summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAnthony G. Basile <blueness@gentoo.org>2012-11-15 10:33:16 -0500
committerAnthony G. Basile <blueness@gentoo.org>2012-11-15 10:33:16 -0500
commit7d4a62f8c1404ed426500b97af03d4ef8d034a71 (patch)
tree2436cd4f0460a3a3d589875d4ffba55556f3c582 /src
parent2944f347d087ff24ec808e4b70fe104a772a97a0 (diff)
Isolation of udev code from remaining systemd
This commit is a first attempt to isolate the udev code from the remaining code base. It intentionally does not modify any files but purely delete files which, on a first examination, appear to not be needed. This is a sweeping commit which may easily have missed needed code. Files can be retrieved by doing a checkout from the previous commit: git checkout 2944f347d0 -- <filename>
Diffstat (limited to 'src')
-rw-r--r--src/.gitignore6
-rw-r--r--src/Makefile28
l---------src/ac-power/Makefile1
-rw-r--r--src/ac-power/ac-power.c111
l---------src/analyze/Makefile1
-rwxr-xr-xsrc/analyze/systemd-analyze294
l---------src/ask-password/Makefile1
-rw-r--r--src/ask-password/ask-password.c184
l---------src/binfmt/Makefile1
-rw-r--r--src/binfmt/binfmt.c170
l---------src/cgls/Makefile1
-rw-r--r--src/cgls/cgls.c182
l---------src/cgroups-agent/Makefile1
-rw-r--r--src/cgroups-agent/cgroups-agent.c101
l---------src/cgtop/Makefile1
-rw-r--r--src/cgtop/cgtop.c793
-rw-r--r--src/core/.gitignore6
l---------src/core/Makefile1
-rw-r--r--src/core/audit-fd.c73
-rw-r--r--src/core/audit-fd.h25
-rw-r--r--src/core/automount.c902
-rw-r--r--src/core/automount.h73
-rw-r--r--src/core/build.h84
-rw-r--r--src/core/bus-errors.h55
-rw-r--r--src/core/cgroup-attr.c102
-rw-r--r--src/core/cgroup-attr.h46
-rw-r--r--src/core/cgroup.c598
-rw-r--r--src/core/cgroup.h91
-rw-r--r--src/core/condition.c370
-rw-r--r--src/core/condition.h69
-rw-r--r--src/core/dbus-automount.c75
-rw-r--r--src/core/dbus-automount.h31
-rw-r--r--src/core/dbus-device.c68
-rw-r--r--src/core/dbus-device.h31
-rw-r--r--src/core/dbus-execute.c439
-rw-r--r--src/core/dbus-execute.h124
-rw-r--r--src/core/dbus-job.c378
-rw-r--r--src/core/dbus-job.h33
-rw-r--r--src/core/dbus-kill.c35
-rw-r--r--src/core/dbus-kill.h39
-rw-r--r--src/core/dbus-manager.c1685
-rw-r--r--src/core/dbus-manager.h28
-rw-r--r--src/core/dbus-mount.c168
-rw-r--r--src/core/dbus-mount.h31
-rw-r--r--src/core/dbus-path.c122
-rw-r--r--src/core/dbus-path.h32
-rw-r--r--src/core/dbus-service.c161
-rw-r--r--src/core/dbus-service.h31
-rw-r--r--src/core/dbus-snapshot.c94
-rw-r--r--src/core/dbus-snapshot.h30
-rw-r--r--src/core/dbus-socket.c151
-rw-r--r--src/core/dbus-socket.h31
-rw-r--r--src/core/dbus-swap.c115
-rw-r--r--src/core/dbus-swap.h32
-rw-r--r--src/core/dbus-target.c58
-rw-r--r--src/core/dbus-target.h30
-rw-r--r--src/core/dbus-timer.c140
-rw-r--r--src/core/dbus-timer.h31
-rw-r--r--src/core/dbus-unit.c887
-rw-r--r--src/core/dbus-unit.h147
-rw-r--r--src/core/dbus.c1479
-rw-r--r--src/core/dbus.h50
-rw-r--r--src/core/device.c644
-rw-r--r--src/core/device.h56
-rw-r--r--src/core/execute.c2132
-rw-r--r--src/core/execute.h209
-rw-r--r--src/core/fdset.c167
-rw-r--r--src/core/fdset.h37
-rw-r--r--src/core/hostname-setup.c182
-rw-r--r--src/core/hostname-setup.h24
-rw-r--r--src/core/ima-setup.c115
-rw-r--r--src/core/ima-setup.h26
-rw-r--r--src/core/initreq.h77
-rw-r--r--src/core/job.c1086
-rw-r--r--src/core/job.h230
-rw-r--r--src/core/kill.c63
-rw-r--r--src/core/kill.h60
-rw-r--r--src/core/killall.c177
-rw-r--r--src/core/killall.h27
-rw-r--r--src/core/kmod-setup.c104
-rw-r--r--src/core/kmod-setup.h24
-rw-r--r--src/core/load-dropin.c150
-rw-r--r--src/core/load-dropin.h28
-rw-r--r--src/core/load-fragment-gperf.gperf.m4255
-rw-r--r--src/core/load-fragment.c2541
-rw-r--r--src/core/load-fragment.h88
-rw-r--r--src/core/locale-setup.c241
-rw-r--r--src/core/locale-setup.h24
-rw-r--r--src/core/loopback-setup.c317
-rw-r--r--src/core/loopback-setup.h24
-rw-r--r--src/core/machine-id-setup.c246
-rw-r--r--src/core/machine-id-setup.h24
-rw-r--r--src/core/macros.systemd.in56
-rw-r--r--src/core/main.c1950
-rw-r--r--src/core/manager.c2309
-rw-r--r--src/core/manager.h293
-rw-r--r--src/core/mount-setup.c441
-rw-r--r--src/core/mount-setup.h33
-rw-r--r--src/core/mount.c1885
-rw-r--r--src/core/mount.h121
-rw-r--r--src/core/namespace.c330
-rw-r--r--src/core/namespace.h31
-rw-r--r--src/core/org.freedesktop.systemd1.conf92
-rw-r--r--src/core/org.freedesktop.systemd1.policy.in.in41
-rw-r--r--src/core/org.freedesktop.systemd1.service11
-rw-r--r--src/core/path.c773
-rw-r--r--src/core/path.h110
-rw-r--r--src/core/securebits.h45
-rw-r--r--src/core/selinux-access.c441
-rw-r--r--src/core/selinux-access.h62
-rw-r--r--src/core/selinux-setup.c123
-rw-r--r--src/core/selinux-setup.h26
-rw-r--r--src/core/service.c3941
-rw-r--r--src/core/service.h225
-rw-r--r--src/core/shutdown.c316
-rw-r--r--src/core/snapshot.c308
-rw-r--r--src/core/snapshot.h50
-rw-r--r--src/core/socket.c2289
-rw-r--r--src/core/socket.h175
-rw-r--r--src/core/special.h113
-rw-r--r--src/core/swap.c1433
-rw-r--r--src/core/swap.h121
-rw-r--r--src/core/switch-root.c142
-rw-r--r--src/core/switch-root.h27
-rw-r--r--src/core/syscall-list.c55
-rw-r--r--src/core/syscall-list.h30
-rw-r--r--src/core/sysfs-show.h24
-rw-r--r--src/core/system.conf43
-rw-r--r--src/core/systemd.pc.in23
-rw-r--r--src/core/target.c239
-rw-r--r--src/core/target.h44
-rw-r--r--src/core/tcpwrap.c68
-rw-r--r--src/core/tcpwrap.h26
-rw-r--r--src/core/timer.c519
-rw-r--r--src/core/timer.h90
-rw-r--r--src/core/transaction.c1087
-rw-r--r--src/core/transaction.h56
-rw-r--r--src/core/umount.c639
-rw-r--r--src/core/umount.h30
-rw-r--r--src/core/unit-printf.c346
-rw-r--r--src/core/unit-printf.h28
-rw-r--r--src/core/unit.c2738
-rw-r--r--src/core/unit.h551
-rw-r--r--src/core/user.conf17
l---------src/cryptsetup/Makefile1
-rw-r--r--src/cryptsetup/cryptsetup-generator.c449
-rw-r--r--src/cryptsetup/cryptsetup.c560
l---------src/delta/Makefile1
-rw-r--r--src/delta/delta.c490
l---------src/detect-virt/Makefile1
-rw-r--r--src/detect-virt/detect-virt.c172
l---------src/fsck/Makefile1
-rw-r--r--src/fsck/fsck.c407
l---------src/fstab-generator/Makefile1
-rw-r--r--src/fstab-generator/fstab-generator.c560
l---------src/getty-generator/Makefile1
-rw-r--r--src/getty-generator/getty-generator.c180
-rw-r--r--src/gudev/.gitignore7
l---------src/gudev/Makefile1
-rw-r--r--src/hostname/.gitignore1
l---------src/hostname/Makefile1
-rw-r--r--src/hostname/hostnamectl.c546
-rw-r--r--src/hostname/hostnamed.c636
-rw-r--r--src/hostname/org.freedesktop.hostname1.conf27
-rw-r--r--src/hostname/org.freedesktop.hostname1.policy.in49
-rw-r--r--src/hostname/org.freedesktop.hostname1.service12
l---------src/initctl/Makefile1
-rw-r--r--src/initctl/initctl.c451
-rw-r--r--src/journal/.gitignore2
l---------src/journal/Makefile1
-rw-r--r--src/journal/browse.html544
-rw-r--r--src/journal/cat.c180
-rw-r--r--src/journal/compress.c208
-rw-r--r--src/journal/compress.h35
-rw-r--r--src/journal/coredump.c278
-rw-r--r--src/journal/coredumpctl.c583
-rw-r--r--src/journal/fsprg.c384
-rw-r--r--src/journal/fsprg.h64
-rw-r--r--src/journal/journal-authenticate.c563
-rw-r--r--src/journal/journal-authenticate.h44
-rw-r--r--src/journal/journal-def.h216
-rw-r--r--src/journal/journal-file.c2872
-rw-r--r--src/journal/journal-file.h193
-rw-r--r--src/journal/journal-gatewayd.c916
-rw-r--r--src/journal/journal-internal.h127
-rw-r--r--src/journal/journal-qrcode.c138
-rw-r--r--src/journal/journal-qrcode.h30
-rw-r--r--src/journal/journal-send.c608
-rw-r--r--src/journal/journal-vacuum.c318
-rw-r--r--src/journal/journal-vacuum.h26
-rw-r--r--src/journal/journal-verify.c1163
-rw-r--r--src/journal/journal-verify.h26
-rw-r--r--src/journal/journalctl.c1060
-rw-r--r--src/journal/journald-console.c86
-rw-r--r--src/journal/journald-console.h26
-rw-r--r--src/journal/journald-gperf.gperf39
-rw-r--r--src/journal/journald-kmsg.c438
-rw-r--r--src/journal/journald-kmsg.h32
-rw-r--r--src/journal/journald-native.c420
-rw-r--r--src/journal/journald-native.h30
-rw-r--r--src/journal/journald-rate-limit.c275
-rw-r--r--src/journal/journald-rate-limit.h31
-rw-r--r--src/journal/journald-server.c1502
-rw-r--r--src/journal/journald-server.h152
-rw-r--r--src/journal/journald-stream.c459
-rw-r--r--src/journal/journald-stream.h30
-rw-r--r--src/journal/journald-syslog.c492
-rw-r--r--src/journal/journald-syslog.h36
-rw-r--r--src/journal/journald.c140
-rw-r--r--src/journal/journald.conf32
-rw-r--r--src/journal/libsystemd-journal.pc.in19
-rw-r--r--src/journal/libsystemd-journal.sym87
-rw-r--r--src/journal/lookup3.c1009
-rw-r--r--src/journal/lookup3.h22
-rw-r--r--src/journal/mmap-cache.c577
-rw-r--r--src/journal/mmap-cache.h36
-rw-r--r--src/journal/sd-journal.c2391
-rw-r--r--src/journal/test-journal-enum.c53
-rw-r--r--src/journal/test-journal-match.c67
-rw-r--r--src/journal/test-journal-send.c78
-rw-r--r--src/journal/test-journal-stream.c185
-rw-r--r--src/journal/test-journal-syslog.c44
-rw-r--r--src/journal/test-journal-verify.c147
-rw-r--r--src/journal/test-journal.c129
-rw-r--r--src/journal/test-mmap-cache.c79
-rw-r--r--src/libsystemd-daemon/.gitignore1
l---------src/libsystemd-daemon/Makefile1
-rw-r--r--src/libsystemd-daemon/libsystemd-daemon.pc.in19
-rw-r--r--src/libsystemd-daemon/libsystemd-daemon.sym27
-rw-r--r--src/libsystemd-daemon/sd-daemon.c536
-rw-r--r--src/libsystemd-id128/.gitignore1
l---------src/libsystemd-id128/Makefile1
-rw-r--r--src/libsystemd-id128/libsystemd-id128.pc.in18
-rw-r--r--src/libsystemd-id128/libsystemd-id128.sym21
-rw-r--r--src/libsystemd-id128/sd-id128.c221
-rw-r--r--src/libudev/.gitignore1
l---------src/libudev/Makefile1
-rw-r--r--src/locale/.gitignore1
l---------src/locale/Makefile1
-rwxr-xr-xsrc/locale/generate-kbd-model-map33
-rw-r--r--src/locale/kbd-model-map72
-rw-r--r--src/locale/localectl.c781
-rw-r--r--src/locale/localed.c1417
-rw-r--r--src/locale/org.freedesktop.locale1.conf27
-rw-r--r--src/locale/org.freedesktop.locale1.policy.in39
-rw-r--r--src/locale/org.freedesktop.locale1.service12
-rw-r--r--src/login/.gitignore5
-rw-r--r--src/login/70-power-switch.rules13
-rw-r--r--src/login/70-uaccess.rules75
-rw-r--r--src/login/71-seat.rules.in48
-rw-r--r--src/login/73-seat-late.rules.in17
l---------src/login/Makefile1
-rw-r--r--src/login/inhibit.c332
-rw-r--r--src/login/libsystemd-login.pc.in18
-rw-r--r--src/login/libsystemd-login.sym55
-rw-r--r--src/login/loginctl.c1611
-rw-r--r--src/login/logind-acl.c248
-rw-r--r--src/login/logind-acl.h57
-rw-r--r--src/login/logind-button.c322
-rw-r--r--src/login/logind-button.h67
-rw-r--r--src/login/logind-dbus.c2389
-rw-r--r--src/login/logind-device.c96
-rw-r--r--src/login/logind-device.h45
-rw-r--r--src/login/logind-gperf.gperf32
-rw-r--r--src/login/logind-inhibit.c468
-rw-r--r--src/login/logind-inhibit.h95
-rw-r--r--src/login/logind-seat-dbus.c444
-rw-r--r--src/login/logind-seat.c543
-rw-r--r--src/login/logind-seat.h83
-rw-r--r--src/login/logind-session-dbus.c590
-rw-r--r--src/login/logind-session.c1010
-rw-r--r--src/login/logind-session.h147
-rw-r--r--src/login/logind-user-dbus.c437
-rw-r--r--src/login/logind-user.c656
-rw-r--r--src/login/logind-user.h84
-rw-r--r--src/login/logind.c1680
-rw-r--r--src/login/logind.conf26
-rw-r--r--src/login/logind.h174
-rw-r--r--src/login/multi-seat-x.c108
-rw-r--r--src/login/org.freedesktop.login1.conf142
-rw-r--r--src/login/org.freedesktop.login1.policy.in259
-rw-r--r--src/login/org.freedesktop.login1.service12
-rw-r--r--src/login/pam-module.c716
-rw-r--r--src/login/sd-login.c794
-rw-r--r--src/login/sysfs-show.c190
-rw-r--r--src/login/test-inhibit.c139
-rw-r--r--src/login/test-login.c201
-rw-r--r--src/login/uaccess.c91
-rw-r--r--src/login/user-sessions.c101
l---------src/machine-id-setup/Makefile1
-rw-r--r--src/machine-id-setup/machine-id-setup-main.c102
l---------src/modules-load/Makefile1
-rw-r--r--src/modules-load/modules-load.c266
l---------src/notify/Makefile1
-rw-r--r--src/notify/notify.c228
l---------src/nspawn/Makefile1
-rw-r--r--src/nspawn/nspawn.c1444
l---------src/python-systemd/Makefile1
-rw-r--r--src/python-systemd/__init__.py18
-rw-r--r--src/python-systemd/_journal.c141
-rw-r--r--src/python-systemd/journal.py201
l---------src/quotacheck/Makefile1
-rw-r--r--src/quotacheck/quotacheck.c120
l---------src/random-seed/Makefile1
-rw-r--r--src/random-seed/random-seed.c149
l---------src/rc-local-generator/Makefile1
-rw-r--r--src/rc-local-generator/rc-local-generator.c115
l---------src/readahead/Makefile1
-rw-r--r--src/readahead/readahead-analyze.c150
-rw-r--r--src/readahead/readahead-collect.c623
-rw-r--r--src/readahead/readahead-common.c359
-rw-r--r--src/readahead/readahead-common.h61
-rw-r--r--src/readahead/readahead-replay.c311
-rw-r--r--src/readahead/readahead.c158
-rw-r--r--src/readahead/sd-readahead.c89
l---------src/remount-fs/Makefile1
-rw-r--r--src/remount-fs/remount-fs.c170
l---------src/reply-password/Makefile1
-rw-r--r--src/reply-password/reply-password.c109
l---------src/shared/Makefile1
-rw-r--r--src/shared/acl-util.c68
-rw-r--r--src/shared/acl-util.h24
-rw-r--r--src/shared/ask-password-api.c576
-rw-r--r--src/shared/ask-password-api.h30
-rw-r--r--src/shared/audit.c118
-rw-r--r--src/shared/audit.h32
-rw-r--r--src/shared/capability.c224
-rw-r--r--src/shared/capability.h33
-rw-r--r--src/shared/cgroup-label.c82
-rw-r--r--src/shared/cgroup-show.c351
-rw-r--r--src/shared/cgroup-show.h34
-rw-r--r--src/shared/cgroup-util.c1256
-rw-r--r--src/shared/cgroup-util.h74
-rw-r--r--src/shared/conf-files.c153
-rw-r--r--src/shared/conf-files.h31
-rw-r--r--src/shared/conf-parser.c1007
-rw-r--r--src/shared/conf-parser.h136
-rw-r--r--src/shared/dbus-common.c1326
-rw-r--r--src/shared/dbus-common.h222
-rw-r--r--src/shared/dbus-loop.c263
-rw-r--r--src/shared/dbus-loop.h27
-rw-r--r--src/shared/def.h35
-rw-r--r--src/shared/dev-setup.c78
-rw-r--r--src/shared/dev-setup.h24
-rw-r--r--src/shared/exit-status.c192
-rw-r--r--src/shared/exit-status.h88
-rw-r--r--src/shared/hashmap.c835
-rw-r--r--src/shared/hashmap.h98
-rw-r--r--src/shared/hwclock.c240
-rw-r--r--src/shared/hwclock.h31
-rw-r--r--src/shared/install.c2059
-rw-r--r--src/shared/install.h87
-rw-r--r--src/shared/ioprio.h57
-rw-r--r--src/shared/label.c382
-rw-r--r--src/shared/label.h47
l---------src/shared/linux/Makefile1
-rw-r--r--src/shared/linux/auto_dev-ioctl.h229
-rw-r--r--src/shared/linux/fanotify.h98
-rw-r--r--src/shared/linux/seccomp-bpf.h76
-rw-r--r--src/shared/linux/seccomp.h47
-rw-r--r--src/shared/list.h125
-rw-r--r--src/shared/log.c885
-rw-r--r--src/shared/log.h139
-rw-r--r--src/shared/logs-show.c904
-rw-r--r--src/shared/logs-show.h74
-rw-r--r--src/shared/macro.h242
-rw-r--r--src/shared/missing.h255
-rw-r--r--src/shared/mkdir.c147
-rw-r--r--src/shared/mkdir.h32
-rw-r--r--src/shared/pager.c143
-rw-r--r--src/shared/pager.h28
-rw-r--r--src/shared/path-lookup.c430
-rw-r--r--src/shared/path-lookup.h45
-rw-r--r--src/shared/path-util.c419
-rw-r--r--src/shared/path-util.h45
-rw-r--r--src/shared/polkit.c163
-rw-r--r--src/shared/polkit.h33
-rw-r--r--src/shared/ratelimit.c57
-rw-r--r--src/shared/ratelimit.h57
-rw-r--r--src/shared/replace-var.c110
-rw-r--r--src/shared/replace-var.h24
-rw-r--r--src/shared/selinux-util.c42
-rw-r--r--src/shared/selinux-util.h27
-rw-r--r--src/shared/set.c130
-rw-r--r--src/shared/set.h71
-rw-r--r--src/shared/socket-label.c143
-rw-r--r--src/shared/socket-util.c544
-rw-r--r--src/shared/socket-util.h99
-rw-r--r--src/shared/sparse-endian.h87
-rw-r--r--src/shared/spawn-ask-password-agent.c67
-rw-r--r--src/shared/spawn-ask-password-agent.h25
-rw-r--r--src/shared/spawn-polkit-agent.c86
-rw-r--r--src/shared/spawn-polkit-agent.h28
-rw-r--r--src/shared/specifier.c111
-rw-r--r--src/shared/specifier.h34
-rw-r--r--src/shared/strbuf.c176
-rw-r--r--src/shared/strbuf.h56
-rw-r--r--src/shared/strv.c750
-rw-r--r--src/shared/strv.h84
-rw-r--r--src/shared/time-dst.c341
-rw-r--r--src/shared/time-dst.h26
-rw-r--r--src/shared/unit-name.c519
-rw-r--r--src/shared/unit-name.h94
-rw-r--r--src/shared/utf8.c286
-rw-r--r--src/shared/utf8.h32
-rw-r--r--src/shared/util.c6215
-rw-r--r--src/shared/util.h615
-rw-r--r--src/shared/utmp-wtmp.c431
-rw-r--r--src/shared/utmp-wtmp.h35
-rw-r--r--src/shared/virt.c259
-rw-r--r--src/shared/virt.h35
-rw-r--r--src/shared/watchdog.c169
-rw-r--r--src/shared/watchdog.h28
l---------src/shutdownd/Makefile1
-rw-r--r--src/shutdownd/shutdownd.c478
l---------src/sleep/Makefile1
-rw-r--r--src/sleep/sleep.c127
l---------src/stdio-bridge/Makefile1
-rw-r--r--src/stdio-bridge/stdio-bridge.c367
l---------src/sysctl/Makefile1
-rw-r--r--src/sysctl/sysctl.c336
l---------src/system-update-generator/Makefile1
-rw-r--r--src/system-update-generator/system-update-generator.c84
l---------src/systemctl/Makefile1
-rw-r--r--src/systemctl/systemctl.c5354
l---------src/systemd/Makefile1
-rw-r--r--src/systemd/sd-daemon.h282
-rw-r--r--src/systemd/sd-id128.h109
-rw-r--r--src/systemd/sd-journal.h149
-rw-r--r--src/systemd/sd-login.h160
-rw-r--r--src/systemd/sd-messages.h69
-rw-r--r--src/systemd/sd-readahead.h73
-rw-r--r--src/systemd/sd-shutdown.h108
l---------src/test/Makefile1
-rw-r--r--src/test/test-cgroup.c105
-rw-r--r--src/test/test-daemon.c37
-rw-r--r--src/test/test-date.c69
-rw-r--r--src/test/test-engine.c99
-rw-r--r--src/test/test-env-replace.c143
-rw-r--r--src/test/test-hostname.c38
-rw-r--r--src/test/test-id128.c52
-rw-r--r--src/test/test-install.c265
-rw-r--r--src/test/test-job-type.c105
-rw-r--r--src/test/test-log.c53
-rw-r--r--src/test/test-loopback.c37
-rw-r--r--src/test/test-ns.c61
-rw-r--r--src/test/test-replace-var.c46
-rw-r--r--src/test/test-sleep.c39
-rw-r--r--src/test/test-strv.c66
-rw-r--r--src/test/test-unit-file.c52
-rw-r--r--src/test/test-unit-name.c177
-rw-r--r--src/test/test-watchdog.c51
-rw-r--r--src/timedate/.gitignore1
l---------src/timedate/Makefile1
-rw-r--r--src/timedate/org.freedesktop.timedate1.conf27
-rw-r--r--src/timedate/org.freedesktop.timedate1.policy.in61
-rw-r--r--src/timedate/org.freedesktop.timedate1.service12
-rw-r--r--src/timedate/timedatectl.c719
-rw-r--r--src/timedate/timedated.c1042
l---------src/timestamp/Makefile1
-rw-r--r--src/timestamp/timestamp.c39
l---------src/tmpfiles/Makefile1
-rw-r--r--src/tmpfiles/tmpfiles.c1418
l---------src/tty-ask-password-agent/Makefile1
-rw-r--r--src/tty-ask-password-agent/tty-ask-password-agent.c764
-rw-r--r--src/udev/.gitignore1
-rw-r--r--src/udev/.vimrc4
l---------src/udev/Makefile1
-rw-r--r--src/udev/keymap/.gitignore5
-rw-r--r--src/udev/scsi_id/.gitignore1
l---------src/update-utmp/Makefile1
-rw-r--r--src/update-utmp/update-utmp.c386
l---------src/vconsole/Makefile1
-rw-r--r--src/vconsole/vconsole-setup.c392
474 files changed, 0 insertions, 133308 deletions
diff --git a/src/.gitignore b/src/.gitignore
deleted file mode 100644
index afabb6a5d2..0000000000
--- a/src/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-load-fragment-gperf-nulstr.c
-load-fragment-gperf.c
-load-fragment-gperf.gperf
-org.freedesktop.systemd1.policy.in
-org.freedesktop.systemd1.policy
-99-systemd.rules
diff --git a/src/Makefile b/src/Makefile
deleted file mode 100644
index 9d07505194..0000000000
--- a/src/Makefile
+++ /dev/null
@@ -1,28 +0,0 @@
-# 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/>.
-
-# This file is a dirty trick to simplify compilation from within
-# emacs. This file is not intended to be distributed. So, don't touch
-# it, even better ignore it!
-
-all:
- $(MAKE) -C ..
-
-clean:
- $(MAKE) -C .. clean
-
-.PHONY: all clean
diff --git a/src/ac-power/Makefile b/src/ac-power/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/ac-power/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/ac-power/ac-power.c b/src/ac-power/ac-power.c
deleted file mode 100644
index 37313cf144..0000000000
--- a/src/ac-power/ac-power.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*-*- 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 <stdlib.h>
-#include <stdbool.h>
-#include <errno.h>
-#include <string.h>
-#include <libudev.h>
-
-#include "util.h"
-
-static int on_ac_power(void) {
- int r;
-
- struct udev *udev;
- struct udev_enumerate *e = NULL;
- struct udev_list_entry *item = NULL, *first = NULL;
- bool found_offline = false, found_online = false;
-
- if (!(udev = udev_new())) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (!(e = udev_enumerate_new(udev))) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (udev_enumerate_add_match_subsystem(e, "power_supply") < 0) {
- r = -EIO;
- goto finish;
- }
-
- if (udev_enumerate_scan_devices(e) < 0) {
- r = -EIO;
- goto finish;
- }
-
- first = udev_enumerate_get_list_entry(e);
- udev_list_entry_foreach(item, first) {
- struct udev_device *d;
- const char *type, *online;
-
- if (!(d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)))) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (!(type = udev_device_get_sysattr_value(d, "type")))
- goto next;
-
- if (!streq(type, "Mains"))
- goto next;
-
- if (!(online = udev_device_get_sysattr_value(d, "online")))
- goto next;
-
- if (streq(online, "1")) {
- found_online = true;
- break;
- } else if (streq(online, "0"))
- found_offline = true;
-
- next:
- udev_device_unref(d);
- }
-
- r = found_online || !found_offline;
-
-finish:
- if (e)
- udev_enumerate_unref(e);
-
- if (udev)
- udev_unref(udev);
-
- return r;
-}
-
-int main(int argc, char *argv[]) {
- int r;
-
- /* This is mostly intended to be used for scripts which want
- * to detect whether AC power is plugged in or not. */
-
- if ((r = on_ac_power()) < 0) {
- log_error("Failed to read AC status: %s", strerror(-r));
- return EXIT_FAILURE;
- }
-
- return r == 0;
-}
diff --git a/src/analyze/Makefile b/src/analyze/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/analyze/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/analyze/systemd-analyze b/src/analyze/systemd-analyze
deleted file mode 100755
index 88699d6728..0000000000
--- a/src/analyze/systemd-analyze
+++ /dev/null
@@ -1,294 +0,0 @@
-#!/usr/bin/python
-
-import sys, os
-import argparse
-from gi.repository import Gio
-try:
- import cairo
-except ImportError:
- cairo = None
-
-def acquire_time_data():
- manager = Gio.DBusProxy.new_for_bus_sync(bus, Gio.DBusProxyFlags.NONE,
- None, 'org.freedesktop.systemd1', '/org/freedesktop/systemd1', 'org.freedesktop.systemd1.Manager', None)
- units = manager.ListUnits()
-
- l = []
-
- for i in units:
- if i[5] != "":
- continue
-
- properties = Gio.DBusProxy.new_for_bus_sync(bus, Gio.DBusProxyFlags.NONE,
- None, 'org.freedesktop.systemd1', i[6], 'org.freedesktop.DBus.Properties', None)
-
- ixt = properties.Get('(ss)', 'org.freedesktop.systemd1.Unit', 'InactiveExitTimestampMonotonic')
- aet = properties.Get('(ss)', 'org.freedesktop.systemd1.Unit', 'ActiveEnterTimestampMonotonic')
- axt = properties.Get('(ss)', 'org.freedesktop.systemd1.Unit', 'ActiveExitTimestampMonotonic')
- iet = properties.Get('(ss)', 'org.freedesktop.systemd1.Unit', 'InactiveEnterTimestampMonotonic')
-
- l.append((str(i[0]), ixt, aet, axt, iet))
-
- return l
-
-def acquire_start_time():
- properties = Gio.DBusProxy.new_for_bus_sync(bus, Gio.DBusProxyFlags.NONE,
- None, 'org.freedesktop.systemd1', '/org/freedesktop/systemd1', 'org.freedesktop.DBus.Properties', None)
-
- initrd_time = properties.Get('(ss)', 'org.freedesktop.systemd1.Manager', 'InitRDTimestampMonotonic')
- userspace_time = properties.Get('(ss)', 'org.freedesktop.systemd1.Manager', 'UserspaceTimestampMonotonic')
- finish_time = properties.Get('(ss)', 'org.freedesktop.systemd1.Manager', 'FinishTimestampMonotonic')
-
- if finish_time == 0:
- sys.stderr.write("Bootup is not yet finished. Please try again later.\n")
- sys.exit(1)
-
- assert initrd_time <= userspace_time
- assert userspace_time <= finish_time
-
- return initrd_time, userspace_time, finish_time
-
-def draw_box(context, j, k, l, m, r = 0, g = 0, b = 0):
- context.save()
- context.set_source_rgb(r, g, b)
- context.rectangle(j, k, l, m)
- context.fill()
- context.restore()
-
-def draw_text(context, x, y, text, size = 12, r = 0, g = 0, b = 0, vcenter = 0.5, hcenter = 0.5):
- context.save()
-
- context.set_source_rgb(r, g, b)
- context.select_font_face("Sans", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
- context.set_font_size(size)
-
- if vcenter or hcenter:
- x_bearing, y_bearing, width, height = context.text_extents(text)[:4]
-
- if hcenter:
- x = x - width*hcenter - x_bearing
-
- if vcenter:
- y = y - height*vcenter - y_bearing
-
- context.move_to(x, y)
- context.show_text(text)
-
- context.restore()
-
-def time():
-
- initrd_time, start_time, finish_time = acquire_start_time()
-
- if initrd_time > 0:
- sys.stdout.write("Startup finished in %lums (kernel) + %lums (initramfs) + %lums (userspace) = %lums\n" % ( \
- initrd_time/1000, \
- (start_time - initrd_time)/1000, \
- (finish_time - start_time)/1000, \
- finish_time/1000))
- else:
- sys.stdout.write("Startup finished in %lums (kernel) + %lums (userspace) = %lums\n" % ( \
- start_time/1000, \
- (finish_time - start_time)/1000, \
- finish_time/1000))
-
-
-def blame():
-
- data = acquire_time_data()
- s = sorted(data, key = lambda i: i[2] - i[1], reverse = True)
-
- for name, ixt, aet, axt, iet in s:
-
- if ixt <= 0 or aet <= 0:
- continue
-
- if aet <= ixt:
- continue
-
- sys.stdout.write("%6lums %s\n" % ((aet - ixt) / 1000, name))
-
-def plot():
- if cairo is None:
- sys.stderr.write("Failed to initilize python-cairo required for 'plot' verb.\n")
- sys.exit(1)
- initrd_time, start_time, finish_time = acquire_start_time()
- data = acquire_time_data()
- s = sorted(data, key = lambda i: i[1])
-
- # Account for kernel and initramfs bars if they exist
- if initrd_time > 0:
- count = 3
- else:
- count = 2
-
- for name, ixt, aet, axt, iet in s:
-
- if (ixt >= start_time and ixt <= finish_time) or \
- (aet >= start_time and aet <= finish_time) or \
- (axt >= start_time and axt <= finish_time):
- count += 1
-
- border = 100
- bar_height = 20
- bar_space = bar_height * 0.1
-
- # 1000px = 10s, 1px = 10ms
- width = finish_time/10000 + border*2
- height = count * (bar_height + bar_space) + border * 2
-
- if width < 1000:
- width = 1000
-
- surface = cairo.SVGSurface(sys.stdout, width, height)
- context = cairo.Context(surface)
-
- draw_box(context, 0, 0, width, height, 1, 1, 1)
-
- context.translate(border + 0.5, border + 0.5)
-
- context.save()
- context.set_line_width(1)
- context.set_source_rgb(0.7, 0.7, 0.7)
-
- for x in range(0, int(finish_time/10000) + 100, 100):
- context.move_to(x, 0)
- context.line_to(x, height-border*2)
-
- context.move_to(0, 0)
- context.line_to(width-border*2, 0)
-
- context.move_to(0, height-border*2)
- context.line_to(width-border*2, height-border*2)
-
- context.stroke()
- context.restore()
-
- osrel = "Linux"
- if os.path.exists("/etc/os-release"):
- for line in open("/etc/os-release"):
- if line.startswith('PRETTY_NAME='):
- osrel = line[12:]
- osrel = osrel.strip('\"\n')
- break
-
- banner = "{} {} ({} {}) {}".format(osrel, *(os.uname()[1:5]))
- draw_text(context, 0, -15, banner, hcenter = 0, vcenter = 1)
-
- for x in range(0, int(finish_time/10000) + 100, 100):
- draw_text(context, x, -5, "%lus" % (x/100), vcenter = 0, hcenter = 0)
-
- y = 0
-
- # draw boxes for kernel and initramfs boot time
- if initrd_time > 0:
- draw_box(context, 0, y, initrd_time/10000, bar_height, 0.7, 0.7, 0.7)
- draw_text(context, 10, y + bar_height/2, "kernel", hcenter = 0)
- y += bar_height + bar_space
-
- draw_box(context, initrd_time/10000, y, start_time/10000-initrd_time/10000, bar_height, 0.7, 0.7, 0.7)
- draw_text(context, initrd_time/10000 + 10, y + bar_height/2, "initramfs", hcenter = 0)
- y += bar_height + bar_space
-
- else:
- draw_box(context, 0, y, start_time/10000, bar_height, 0.6, 0.6, 0.6)
- draw_text(context, 10, y + bar_height/2, "kernel", hcenter = 0)
- y += bar_height + bar_space
-
- draw_box(context, start_time/10000, y, finish_time/10000-start_time/10000, bar_height, 0.7, 0.7, 0.7)
- draw_text(context, start_time/10000 + 10, y + bar_height/2, "userspace", hcenter = 0)
- y += bar_height + bar_space
-
- for name, ixt, aet, axt, iet in s:
-
- drawn = False
- left = -1
-
- if ixt >= start_time and ixt <= finish_time:
-
- # Activating
- a = ixt
- b = min(filter(lambda x: x >= ixt, (aet, axt, iet, finish_time))) - ixt
-
- draw_box(context, a/10000, y, b/10000, bar_height, 1, 0, 0)
- drawn = True
-
- if left < 0:
- left = a
-
- if aet >= start_time and aet <= finish_time:
-
- # Active
- a = aet
- b = min(filter(lambda x: x >= aet, (axt, iet, finish_time))) - aet
-
- draw_box(context, a/10000, y, b/10000, bar_height, .8, .6, .6)
- drawn = True
-
- if left < 0:
- left = a
-
- if axt >= start_time and axt <= finish_time:
-
- # Deactivating
- a = axt
- b = min(filter(lambda x: x >= axt, (iet, finish_time))) - axt
-
- draw_box(context, a/10000, y, b/10000, bar_height, .6, .4, .4)
- drawn = True
-
- if left < 0:
- left = a
-
- if drawn:
- x = left/10000
-
- if x < width/2-border:
- draw_text(context, x + 10, y + bar_height/2, name, hcenter = 0)
- else:
- draw_text(context, x - 10, y + bar_height/2, name, hcenter = 1)
-
- y += bar_height + bar_space
-
- draw_text(context, 0, height-border*2, "Legend: Red = Activating; Pink = Active; Dark Pink = Deactivating", hcenter = 0, vcenter = -1)
-
- if initrd_time > 0:
- draw_text(context, 0, height-border*2 + bar_height, "Startup finished in %lums (kernel) + %lums (initramfs) + %lums (userspace) = %lums" % ( \
- initrd_time/1000, \
- (start_time - initrd_time)/1000, \
- (finish_time - start_time)/1000, \
- finish_time/1000), hcenter = 0, vcenter = -1)
- else:
- draw_text(context, 0, height-border*2 + bar_height, "Startup finished in %lums (kernel) + %lums (userspace) = %lums" % ( \
- start_time/1000, \
- (finish_time - start_time)/1000, \
- finish_time/1000), hcenter = 0, vcenter = -1)
-
- surface.finish()
-
-parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
- description='Process systemd profiling information',
- epilog='''\
-time - print time spent in the kernel before reaching userspace
-blame - print list of running units ordered by time to init
-plot - output SVG graphic showing service initialization
-''')
-
-parser.add_argument('action', choices=('time', 'blame', 'plot'),
- default='time', nargs='?',
- help='action to perform (default: time)')
-parser.add_argument('--user', action='store_true',
- help='use the session bus')
-
-args = parser.parse_args()
-
-if args.user:
- bus = Gio.BusType.SESSION
-else:
- bus = Gio.BusType.SYSTEM
-
-verb = {'time' : time,
- 'blame': blame,
- 'plot' : plot,
- }
-verb.get(args.action)()
diff --git a/src/ask-password/Makefile b/src/ask-password/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/ask-password/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/ask-password/ask-password.c b/src/ask-password/ask-password.c
deleted file mode 100644
index 5f675700f8..0000000000
--- a/src/ask-password/ask-password.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*-*- 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/socket.h>
-#include <sys/poll.h>
-#include <sys/types.h>
-#include <assert.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/un.h>
-#include <sys/stat.h>
-#include <sys/signalfd.h>
-#include <getopt.h>
-#include <termios.h>
-#include <limits.h>
-#include <stddef.h>
-
-#include "log.h"
-#include "macro.h"
-#include "util.h"
-#include "strv.h"
-#include "ask-password-api.h"
-#include "def.h"
-
-static const char *arg_icon = NULL;
-static const char *arg_message = NULL;
-static bool arg_use_tty = true;
-static usec_t arg_timeout = DEFAULT_TIMEOUT_USEC;
-static bool arg_accept_cached = false;
-static bool arg_multiple = false;
-
-static int help(void) {
-
- printf("%s [OPTIONS...] MESSAGE\n\n"
- "Query the user for a system passphrase, via the TTY or an UI agent.\n\n"
- " -h --help Show this help\n"
- " --icon=NAME Icon name\n"
- " --timeout=SEC Timeout in sec\n"
- " --no-tty Ask question via agent even on TTY\n"
- " --accept-cached Accept cached passwords\n"
- " --multiple List multiple passwords if available\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_ICON = 0x100,
- ARG_TIMEOUT,
- ARG_NO_TTY,
- ARG_ACCEPT_CACHED,
- ARG_MULTIPLE
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "icon", required_argument, NULL, ARG_ICON },
- { "timeout", required_argument, NULL, ARG_TIMEOUT },
- { "no-tty", no_argument, NULL, ARG_NO_TTY },
- { "accept-cached", no_argument, NULL, ARG_ACCEPT_CACHED },
- { "multiple", no_argument, NULL, ARG_MULTIPLE },
- { NULL, 0, NULL, 0 }
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_ICON:
- arg_icon = optarg;
- break;
-
- case ARG_TIMEOUT:
- if (parse_usec(optarg, &arg_timeout) < 0) {
- log_error("Failed to parse --timeout parameter %s", optarg);
- return -EINVAL;
- }
- break;
-
- case ARG_NO_TTY:
- arg_use_tty = false;
- break;
-
- case ARG_ACCEPT_CACHED:
- arg_accept_cached = true;
- break;
-
- case ARG_MULTIPLE:
- arg_multiple = true;
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- log_error("Unknown option code %c", c);
- return -EINVAL;
- }
- }
-
- if (optind != argc-1) {
- help();
- return -EINVAL;
- }
-
- arg_message = argv[optind];
- return 1;
-}
-
-int main(int argc, char *argv[]) {
- int r;
- usec_t timeout;
-
- log_parse_environment();
- log_open();
-
- if ((r = parse_argv(argc, argv)) <= 0)
- goto finish;
-
- if (arg_timeout > 0)
- timeout = now(CLOCK_MONOTONIC) + arg_timeout;
- else
- timeout = 0;
-
- if (arg_use_tty && isatty(STDIN_FILENO)) {
- char *password = NULL;
-
- if ((r = ask_password_tty(arg_message, timeout, NULL, &password)) >= 0) {
- puts(password);
- free(password);
- }
-
- } else {
- char **l;
-
- if ((r = ask_password_agent(arg_message, arg_icon, timeout, arg_accept_cached, &l)) >= 0) {
- char **p;
-
- STRV_FOREACH(p, l) {
- puts(*p);
-
- if (!arg_multiple)
- break;
- }
-
- strv_free(l);
- }
- }
-
-finish:
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/binfmt/Makefile b/src/binfmt/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/binfmt/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/binfmt/binfmt.c b/src/binfmt/binfmt.c
deleted file mode 100644
index 788fd4b1a4..0000000000
--- a/src/binfmt/binfmt.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*-*- 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 <stdlib.h>
-#include <stdbool.h>
-#include <errno.h>
-#include <string.h>
-#include <stdio.h>
-#include <limits.h>
-#include <stdarg.h>
-
-#include "log.h"
-#include "hashmap.h"
-#include "strv.h"
-#include "util.h"
-#include "conf-files.h"
-
-static int delete_rule(const char *rule) {
- char *x, *fn = NULL, *e;
- int r;
-
- assert(rule[0]);
-
- if (!(x = strdup(rule)))
- return log_oom();
-
- e = strchrnul(x+1, x[0]);
- *e = 0;
-
- asprintf(&fn, "/proc/sys/fs/binfmt_misc/%s", x+1);
- free(x);
-
- if (!fn)
- return log_oom();
-
- r = write_one_line_file(fn, "-1");
- free(fn);
-
- return r;
-}
-
-static int apply_rule(const char *rule) {
- int r;
-
- delete_rule(rule);
-
- if ((r = write_one_line_file("/proc/sys/fs/binfmt_misc/register", rule)) < 0) {
- log_error("Failed to add binary format: %s", strerror(-r));
- return r;
- }
-
- return 0;
-}
-
-static int apply_file(const char *path, bool ignore_enoent) {
- FILE *f;
- int r = 0;
-
- assert(path);
-
- if (!(f = fopen(path, "re"))) {
- if (ignore_enoent && errno == ENOENT)
- return 0;
-
- log_error("Failed to open file '%s', ignoring: %m", path);
- return -errno;
- }
-
- log_debug("apply: %s\n", path);
- while (!feof(f)) {
- char l[LINE_MAX], *p;
- int k;
-
- if (!fgets(l, sizeof(l), f)) {
- if (feof(f))
- break;
-
- log_error("Failed to read file '%s', ignoring: %m", path);
- r = -errno;
- goto finish;
- }
-
- p = strstrip(l);
-
- if (!*p)
- continue;
-
- if (strchr(COMMENTS, *p))
- continue;
-
- if ((k = apply_rule(p)) < 0 && r == 0)
- r = k;
- }
-
-finish:
- fclose(f);
-
- return r;
-}
-
-int main(int argc, char *argv[]) {
- int r = 0;
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- if (argc > 1) {
- int i;
-
- for (i = 1; i < argc; i++) {
- int k;
-
- k = apply_file(argv[i], false);
- if (k < 0 && r == 0)
- r = k;
- }
- } else {
- char **files, **f;
-
- r = conf_files_list(&files, ".conf",
- "/etc/binfmt.d",
- "/run/binfmt.d",
- "/usr/local/lib/binfmt.d",
- "/usr/lib/binfmt.d",
-#ifdef HAVE_SPLIT_USR
- "/lib/binfmt.d",
-#endif
- NULL);
- if (r < 0) {
- log_error("Failed to enumerate binfmt.d files: %s", strerror(-r));
- goto finish;
- }
-
- /* Flush out all rules */
- write_one_line_file("/proc/sys/fs/binfmt_misc/status", "-1");
-
- STRV_FOREACH(f, files) {
- int k;
-
- k = apply_file(*f, true);
- if (k < 0 && r == 0)
- r = k;
- }
-
- strv_free(files);
- }
-finish:
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/cgls/Makefile b/src/cgls/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/cgls/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c
deleted file mode 100644
index b2cd968e46..0000000000
--- a/src/cgls/cgls.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*-*- 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 <limits.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <getopt.h>
-#include <string.h>
-
-#include "cgroup-show.h"
-#include "cgroup-util.h"
-#include "log.h"
-#include "path-util.h"
-#include "util.h"
-#include "pager.h"
-#include "build.h"
-
-static bool arg_no_pager = false;
-static bool arg_kernel_threads = false;
-static bool arg_all = false;
-
-static void help(void) {
-
- printf("%s [OPTIONS...] [CGROUP...]\n\n"
- "Recursively show control group contents.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --no-pager Do not pipe output into a pager\n"
- " -a --all Show all groups, including empty\n"
- " -k Include kernel threads in output\n",
- program_invocation_short_name);
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_NO_PAGER = 0x100,
- ARG_VERSION
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "no-pager", no_argument, NULL, ARG_NO_PAGER },
- { "all", no_argument, NULL, 'a' },
- { NULL, 0, NULL, 0 }
- };
-
- int c;
-
- assert(argc >= 1);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "hka", options, NULL)) >= 0) {
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(DISTRIBUTION);
- puts(SYSTEMD_FEATURES);
- return 0;
-
- case ARG_NO_PAGER:
- arg_no_pager = true;
- break;
-
- case 'a':
- arg_all = true;
- break;
-
- case 'k':
- arg_kernel_threads = true;
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- log_error("Unknown option code %c", c);
- return -EINVAL;
- }
- }
-
- return 1;
-}
-
-int main(int argc, char *argv[]) {
- int r = 0, retval = EXIT_FAILURE;
-
- log_parse_environment();
- log_open();
-
- r = parse_argv(argc, argv);
- if (r < 0)
- goto finish;
- else if (r == 0) {
- retval = EXIT_SUCCESS;
- goto finish;
- }
-
- if (!arg_no_pager)
- pager_open();
-
- if (optind < argc) {
- unsigned i;
-
- for (i = (unsigned) optind; i < (unsigned) argc; i++) {
- int q;
- printf("%s:\n", argv[i]);
-
- q = show_cgroup_by_path(argv[i], NULL, 0, arg_kernel_threads, arg_all);
- if (q < 0)
- r = q;
- }
-
- } else {
- char *p;
-
- p = get_current_dir_name();
- if (!p) {
- log_error("Cannot determine current working directory: %m");
- goto finish;
- }
-
- if (path_startswith(p, "/sys/fs/cgroup")) {
- printf("Working Directory %s:\n", p);
- r = show_cgroup_by_path(p, NULL, 0, arg_kernel_threads, arg_all);
- } else {
- char *root = NULL;
- const char *t = NULL;
-
- r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &root);
- if (r < 0)
- t = "/";
- else {
- if (endswith(root, "/system"))
- root[strlen(root)-7] = 0;
-
- t = root[0] ? root : "/";
- }
-
- r = show_cgroup(SYSTEMD_CGROUP_CONTROLLER, t, NULL, 0, arg_kernel_threads, arg_all);
- free(root);
- }
-
- free(p);
- }
-
- if (r < 0)
- log_error("Failed to list cgroup tree: %s", strerror(-r));
-
- retval = EXIT_SUCCESS;
-
-finish:
- pager_close();
-
- return retval;
-}
diff --git a/src/cgroups-agent/Makefile b/src/cgroups-agent/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/cgroups-agent/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/cgroups-agent/cgroups-agent.c b/src/cgroups-agent/cgroups-agent.c
deleted file mode 100644
index 7a6173e2a2..0000000000
--- a/src/cgroups-agent/cgroups-agent.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*-*- 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 <dbus/dbus.h>
-
-#include <stdlib.h>
-
-#include "log.h"
-#include "dbus-common.h"
-
-int main(int argc, char *argv[]) {
- DBusError error;
- DBusConnection *bus = NULL;
- DBusMessage *m = NULL;
- int r = EXIT_FAILURE;
-
- dbus_error_init(&error);
-
- if (argc != 2) {
- log_error("Incorrect number of arguments.");
- goto finish;
- }
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- /* We send this event to the private D-Bus socket and then the
- * system instance will forward this to the system bus. We do
- * this to avoid an activation loop when we start dbus when we
- * are called when the dbus service is shut down. */
-
- if (!(bus = dbus_connection_open_private("unix:path=/run/systemd/private", &error))) {
-#ifndef LEGACY
- dbus_error_free(&error);
-
- /* Retry with the pre v21 socket name, to ease upgrades */
- if (!(bus = dbus_connection_open_private("unix:abstract=/org/freedesktop/systemd1/private", &error))) {
-#endif
- log_error("Failed to get D-Bus connection: %s", bus_error_message(&error));
- goto finish;
- }
-#ifndef LEGACY
- }
-#endif
-
- if (bus_check_peercred(bus) < 0) {
- log_error("Bus owner not root.");
- goto finish;
- }
-
- if (!(m = dbus_message_new_signal("/org/freedesktop/systemd1/agent", "org.freedesktop.systemd1.Agent", "Released"))) {
- log_error("Could not allocate signal message.");
- goto finish;
- }
-
- if (!dbus_message_append_args(m,
- DBUS_TYPE_STRING, &argv[1],
- DBUS_TYPE_INVALID)) {
- log_error("Could not attach group information to signal message.");
- goto finish;
- }
-
- if (!dbus_connection_send(bus, m, NULL)) {
- log_error("Failed to send signal message on private connection.");
- goto finish;
- }
-
- r = EXIT_SUCCESS;
-
-finish:
- if (bus) {
- dbus_connection_flush(bus);
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
- }
-
- if (m)
- dbus_message_unref(m);
-
- dbus_error_free(&error);
- return r;
-}
diff --git a/src/cgtop/Makefile b/src/cgtop/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/cgtop/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c
deleted file mode 100644
index f2e62761f1..0000000000
--- a/src/cgtop/cgtop.c
+++ /dev/null
@@ -1,793 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <alloca.h>
-#include <getopt.h>
-
-#include "path-util.h"
-#include "util.h"
-#include "hashmap.h"
-#include "cgroup-util.h"
-#include "build.h"
-
-typedef struct Group {
- char *path;
-
- bool n_tasks_valid:1;
- bool cpu_valid:1;
- bool memory_valid:1;
- bool io_valid:1;
-
- unsigned n_tasks;
-
- unsigned cpu_iteration;
- uint64_t cpu_usage;
- struct timespec cpu_timestamp;
- double cpu_fraction;
-
- uint64_t memory;
-
- unsigned io_iteration;
- uint64_t io_input, io_output;
- struct timespec io_timestamp;
- uint64_t io_input_bps, io_output_bps;
-} Group;
-
-static unsigned arg_depth = 3;
-static unsigned arg_iterations = 0;
-static bool arg_batch = false;
-static usec_t arg_delay = 1*USEC_PER_SEC;
-
-static enum {
- ORDER_PATH,
- ORDER_TASKS,
- ORDER_CPU,
- ORDER_MEMORY,
- ORDER_IO
-} arg_order = ORDER_CPU;
-
-static void group_free(Group *g) {
- assert(g);
-
- free(g->path);
- free(g);
-}
-
-static void group_hashmap_clear(Hashmap *h) {
- Group *g;
-
- while ((g = hashmap_steal_first(h)))
- group_free(g);
-}
-
-static void group_hashmap_free(Hashmap *h) {
- group_hashmap_clear(h);
- hashmap_free(h);
-}
-
-static int process(const char *controller, const char *path, Hashmap *a, Hashmap *b, unsigned iteration) {
- Group *g;
- int r;
- FILE *f;
- pid_t pid;
- unsigned n;
-
- assert(controller);
- assert(path);
- assert(a);
-
- g = hashmap_get(a, path);
- if (!g) {
- g = hashmap_get(b, path);
- if (!g) {
- g = new0(Group, 1);
- if (!g)
- return -ENOMEM;
-
- g->path = strdup(path);
- if (!g->path) {
- group_free(g);
- return -ENOMEM;
- }
-
- r = hashmap_put(a, g->path, g);
- if (r < 0) {
- group_free(g);
- return r;
- }
- } else {
- assert_se(hashmap_move_one(a, b, path) == 0);
- g->cpu_valid = g->memory_valid = g->io_valid = g->n_tasks_valid = false;
- }
- }
-
- /* Regardless which controller, let's find the maximum number
- * of processes in any of it */
-
- r = cg_enumerate_tasks(controller, path, &f);
- if (r < 0)
- return r;
-
- n = 0;
- while (cg_read_pid(f, &pid) > 0)
- n++;
- fclose(f);
-
- if (n > 0) {
- if (g->n_tasks_valid)
- g->n_tasks = MAX(g->n_tasks, n);
- else
- g->n_tasks = n;
-
- g->n_tasks_valid = true;
- }
-
- if (streq(controller, "cpuacct")) {
- uint64_t new_usage;
- char *p, *v;
- struct timespec ts;
-
- r = cg_get_path(controller, path, "cpuacct.usage", &p);
- if (r < 0)
- return r;
-
- r = read_one_line_file(p, &v);
- free(p);
- if (r < 0)
- return r;
-
- r = safe_atou64(v, &new_usage);
- free(v);
- if (r < 0)
- return r;
-
- assert_se(clock_gettime(CLOCK_MONOTONIC, &ts) == 0);
-
- if (g->cpu_iteration == iteration - 1) {
- uint64_t x, y;
-
- x = ((uint64_t) ts.tv_sec * 1000000000ULL + (uint64_t) ts.tv_nsec) -
- ((uint64_t) g->cpu_timestamp.tv_sec * 1000000000ULL + (uint64_t) g->cpu_timestamp.tv_nsec);
-
- y = new_usage - g->cpu_usage;
-
- if (y > 0) {
- g->cpu_fraction = (double) y / (double) x;
- g->cpu_valid = true;
- }
- }
-
- g->cpu_usage = new_usage;
- g->cpu_timestamp = ts;
- g->cpu_iteration = iteration;
-
- } else if (streq(controller, "memory")) {
- char *p, *v;
-
- r = cg_get_path(controller, path, "memory.usage_in_bytes", &p);
- if (r < 0)
- return r;
-
- r = read_one_line_file(p, &v);
- free(p);
- if (r < 0)
- return r;
-
- r = safe_atou64(v, &g->memory);
- free(v);
- if (r < 0)
- return r;
-
- if (g->memory > 0)
- g->memory_valid = true;
-
- } else if (streq(controller, "blkio")) {
- char *p;
- uint64_t wr = 0, rd = 0;
- struct timespec ts;
-
- r = cg_get_path(controller, path, "blkio.io_service_bytes", &p);
- if (r < 0)
- return r;
-
- f = fopen(p, "re");
- free(p);
-
- if (!f)
- return -errno;
-
- for (;;) {
- char line[LINE_MAX], *l;
- uint64_t k, *q;
-
- if (!fgets(line, sizeof(line), f))
- break;
-
- l = strstrip(line);
- l += strcspn(l, WHITESPACE);
- l += strspn(l, WHITESPACE);
-
- if (first_word(l, "Read")) {
- l += 4;
- q = &rd;
- } else if (first_word(l, "Write")) {
- l += 5;
- q = &wr;
- } else
- continue;
-
- l += strspn(l, WHITESPACE);
- r = safe_atou64(l, &k);
- if (r < 0)
- continue;
-
- *q += k;
- }
-
- fclose(f);
-
- assert_se(clock_gettime(CLOCK_MONOTONIC, &ts) == 0);
-
- if (g->io_iteration == iteration - 1) {
- uint64_t x, yr, yw;
-
- x = ((uint64_t) ts.tv_sec * 1000000000ULL + (uint64_t) ts.tv_nsec) -
- ((uint64_t) g->io_timestamp.tv_sec * 1000000000ULL + (uint64_t) g->io_timestamp.tv_nsec);
-
- yr = rd - g->io_input;
- yw = wr - g->io_output;
-
- if (yr > 0 || yw > 0) {
- g->io_input_bps = (yr * 1000000000ULL) / x;
- g->io_output_bps = (yw * 1000000000ULL) / x;
- g->io_valid = true;
-
- }
- }
-
- g->io_input = rd;
- g->io_output = wr;
- g->io_timestamp = ts;
- g->io_iteration = iteration;
- }
-
- return 0;
-}
-
-static int refresh_one(
- const char *controller,
- const char *path,
- Hashmap *a,
- Hashmap *b,
- unsigned iteration,
- unsigned depth) {
-
- DIR *d = NULL;
- int r;
-
- assert(controller);
- assert(path);
- assert(a);
-
- if (depth > arg_depth)
- return 0;
-
- r = process(controller, path, a, b, iteration);
- if (r < 0)
- return r;
-
- r = cg_enumerate_subgroups(controller, path, &d);
- if (r < 0) {
- if (r == -ENOENT)
- return 0;
-
- return r;
- }
-
- for (;;) {
- char *fn, *p;
-
- r = cg_read_subgroup(d, &fn);
- if (r <= 0)
- goto finish;
-
- p = strjoin(path, "/", fn, NULL);
- free(fn);
-
- if (!p) {
- r = -ENOMEM;
- goto finish;
- }
-
- path_kill_slashes(p);
-
- r = refresh_one(controller, p, a, b, iteration, depth + 1);
- free(p);
-
- if (r < 0)
- goto finish;
- }
-
-finish:
- if (d)
- closedir(d);
-
- return r;
-}
-
-static int refresh(Hashmap *a, Hashmap *b, unsigned iteration) {
- int r;
-
- assert(a);
-
- r = refresh_one("name=systemd", "/", a, b, iteration, 0);
- if (r < 0)
- if (r != -ENOENT)
- return r;
- r = refresh_one("cpuacct", "/", a, b, iteration, 0);
- if (r < 0)
- if (r != -ENOENT)
- return r;
- r = refresh_one("memory", "/", a, b, iteration, 0);
- if (r < 0)
- if (r != -ENOENT)
- return r;
-
- r = refresh_one("blkio", "/", a, b, iteration, 0);
- if (r < 0)
- if (r != -ENOENT)
- return r;
- return 0;
-}
-
-static int group_compare(const void*a, const void *b) {
- const Group *x = *(Group**)a, *y = *(Group**)b;
-
- if (path_startswith(y->path, x->path))
- return -1;
- if (path_startswith(x->path, y->path))
- return 1;
-
- if (arg_order == ORDER_CPU) {
- if (x->cpu_valid && y->cpu_valid) {
-
- if (x->cpu_fraction > y->cpu_fraction)
- return -1;
- else if (x->cpu_fraction < y->cpu_fraction)
- return 1;
- } else if (x->cpu_valid)
- return -1;
- else if (y->cpu_valid)
- return 1;
- }
-
- if (arg_order == ORDER_TASKS) {
-
- if (x->n_tasks_valid && y->n_tasks_valid) {
- if (x->n_tasks > y->n_tasks)
- return -1;
- else if (x->n_tasks < y->n_tasks)
- return 1;
- } else if (x->n_tasks_valid)
- return -1;
- else if (y->n_tasks_valid)
- return 1;
- }
-
- if (arg_order == ORDER_MEMORY) {
- if (x->memory_valid && y->memory_valid) {
- if (x->memory > y->memory)
- return -1;
- else if (x->memory < y->memory)
- return 1;
- } else if (x->memory_valid)
- return -1;
- else if (y->memory_valid)
- return 1;
- }
-
- if (arg_order == ORDER_IO) {
- if (x->io_valid && y->io_valid) {
- if (x->io_input_bps + x->io_output_bps > y->io_input_bps + y->io_output_bps)
- return -1;
- else if (x->io_input_bps + x->io_output_bps < y->io_input_bps + y->io_output_bps)
- return 1;
- } else if (x->io_valid)
- return -1;
- else if (y->io_valid)
- return 1;
- }
-
- return strcmp(x->path, y->path);
-}
-
-static int display(Hashmap *a) {
- Iterator i;
- Group *g;
- Group **array;
- unsigned rows, path_columns, n = 0, j;
-
- assert(a);
-
- /* Set cursor to top left corner and clear screen */
- fputs("\033[H"
- "\033[2J", stdout);
-
- array = alloca(sizeof(Group*) * hashmap_size(a));
-
- HASHMAP_FOREACH(g, a, i)
- if (g->n_tasks_valid || g->cpu_valid || g->memory_valid || g->io_valid)
- array[n++] = g;
-
- qsort(array, n, sizeof(Group*), group_compare);
-
- rows = lines();
- if (rows <= 10)
- rows = 10;
-
- path_columns = columns() - 42;
- if (path_columns < 10)
- path_columns = 10;
-
- printf("%s%-*s%s %s%7s%s %s%6s%s %s%8s%s %s%8s%s %s%8s%s\n\n",
- arg_order == ORDER_PATH ? ANSI_HIGHLIGHT_ON : "", path_columns, "Path",
- arg_order == ORDER_PATH ? ANSI_HIGHLIGHT_OFF : "",
- arg_order == ORDER_TASKS ? ANSI_HIGHLIGHT_ON : "", "Tasks",
- arg_order == ORDER_TASKS ? ANSI_HIGHLIGHT_OFF : "",
- arg_order == ORDER_CPU ? ANSI_HIGHLIGHT_ON : "", "%CPU",
- arg_order == ORDER_CPU ? ANSI_HIGHLIGHT_OFF : "",
- arg_order == ORDER_MEMORY ? ANSI_HIGHLIGHT_ON : "", "Memory",
- arg_order == ORDER_MEMORY ? ANSI_HIGHLIGHT_OFF : "",
- arg_order == ORDER_IO ? ANSI_HIGHLIGHT_ON : "", "Input/s",
- arg_order == ORDER_IO ? ANSI_HIGHLIGHT_OFF : "",
- arg_order == ORDER_IO ? ANSI_HIGHLIGHT_ON : "", "Output/s",
- arg_order == ORDER_IO ? ANSI_HIGHLIGHT_OFF : "");
-
- for (j = 0; j < n; j++) {
- char *p;
- char m[FORMAT_BYTES_MAX];
-
- if (j + 5 > rows)
- break;
-
- g = array[j];
-
- p = ellipsize(g->path, path_columns, 33);
- printf("%-*s", path_columns, p ? p : g->path);
- free(p);
-
- if (g->n_tasks_valid)
- printf(" %7u", g->n_tasks);
- else
- fputs(" -", stdout);
-
- if (g->cpu_valid)
- printf(" %6.1f", g->cpu_fraction*100);
- else
- fputs(" -", stdout);
-
- if (g->memory_valid)
- printf(" %8s", format_bytes(m, sizeof(m), g->memory));
- else
- fputs(" -", stdout);
-
- if (g->io_valid) {
- printf(" %8s",
- format_bytes(m, sizeof(m), g->io_input_bps));
- printf(" %8s",
- format_bytes(m, sizeof(m), g->io_output_bps));
- } else
- fputs(" - -", stdout);
-
- putchar('\n');
- }
-
- return 0;
-}
-
-static void help(void) {
-
- printf("%s [OPTIONS...]\n\n"
- "Show top control groups by their resource usage.\n\n"
- " -h --help Show this help\n"
- " --version Print version and exit\n"
- " -p Order by path\n"
- " -t Order by number of tasks\n"
- " -c Order by CPU load\n"
- " -m Order by memory load\n"
- " -i Order by IO load\n"
- " -d --delay=DELAY Specify delay\n"
- " -n --iterations=N Run for N iterations before exiting\n"
- " -b --batch Run in batch mode, accepting no input\n"
- " --depth=DEPTH Maximum traversal depth (default: 2)\n",
- program_invocation_short_name);
-}
-
-static void version(void) {
- puts(PACKAGE_STRING " cgtop");
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100,
- ARG_DEPTH,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "delay", required_argument, NULL, 'd' },
- { "iterations", required_argument, NULL, 'n' },
- { "batch", no_argument, NULL, 'b' },
- { "depth", required_argument, NULL, ARG_DEPTH },
- { NULL, 0, NULL, 0 }
- };
-
- int c;
- int r;
-
- assert(argc >= 1);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "hptcmin:bd:", options, NULL)) >= 0) {
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- version();
- return 0;
-
- case ARG_DEPTH:
- r = safe_atou(optarg, &arg_depth);
- if (r < 0) {
- log_error("Failed to parse depth parameter.");
- return -EINVAL;
- }
-
- break;
-
- case 'd':
- r = parse_usec(optarg, &arg_delay);
- if (r < 0 || arg_delay <= 0) {
- log_error("Failed to parse delay parameter.");
- return -EINVAL;
- }
-
- break;
-
- case 'n':
- r = safe_atou(optarg, &arg_iterations);
- if (r < 0) {
- log_error("Failed to parse iterations parameter.");
- return -EINVAL;
- }
-
- break;
-
- case 'b':
- arg_batch = true;
- break;
-
- case 'p':
- arg_order = ORDER_PATH;
- break;
-
- case 't':
- arg_order = ORDER_TASKS;
- break;
-
- case 'c':
- arg_order = ORDER_CPU;
- break;
-
- case 'm':
- arg_order = ORDER_MEMORY;
- break;
-
- case 'i':
- arg_order = ORDER_IO;
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- log_error("Unknown option code %c", c);
- return -EINVAL;
- }
- }
-
- if (optind < argc) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
- return 1;
-}
-
-int main(int argc, char *argv[]) {
- int r;
- Hashmap *a = NULL, *b = NULL;
- unsigned iteration = 0;
- usec_t last_refresh = 0;
- bool quit = false, immediate_refresh = false;
-
- log_parse_environment();
- log_open();
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- goto finish;
-
- a = hashmap_new(string_hash_func, string_compare_func);
- b = hashmap_new(string_hash_func, string_compare_func);
- if (!a || !b) {
- r = log_oom();
- goto finish;
- }
-
- signal(SIGWINCH, columns_lines_cache_reset);
-
- while (!quit) {
- Hashmap *c;
- usec_t t;
- char key;
- char h[FORMAT_TIMESPAN_MAX];
-
- t = now(CLOCK_MONOTONIC);
-
- if (t >= last_refresh + arg_delay || immediate_refresh) {
-
- r = refresh(a, b, iteration++);
- if (r < 0)
- goto finish;
-
- group_hashmap_clear(b);
-
- c = a;
- a = b;
- b = c;
-
- last_refresh = t;
- immediate_refresh = false;
- }
-
- r = display(b);
- if (r < 0)
- goto finish;
-
- if (arg_iterations && iteration >= arg_iterations)
- break;
-
- if (arg_batch) {
- usleep(last_refresh + arg_delay - t);
- } else {
- r = read_one_char(stdin, &key,
- last_refresh + arg_delay - t, NULL);
- if (r == -ETIMEDOUT)
- continue;
- if (r < 0) {
- log_error("Couldn't read key: %s", strerror(-r));
- goto finish;
- }
- }
-
- fputs("\r \r", stdout);
- fflush(stdout);
-
- if (arg_batch)
- continue;
-
- switch (key) {
-
- case ' ':
- immediate_refresh = true;
- break;
-
- case 'q':
- quit = true;
- break;
-
- case 'p':
- arg_order = ORDER_PATH;
- break;
-
- case 't':
- arg_order = ORDER_TASKS;
- break;
-
- case 'c':
- arg_order = ORDER_CPU;
- break;
-
- case 'm':
- arg_order = ORDER_MEMORY;
- break;
-
- case 'i':
- arg_order = ORDER_IO;
- break;
-
- case '+':
- if (arg_delay < USEC_PER_SEC)
- arg_delay += USEC_PER_MSEC*250;
- else
- arg_delay += USEC_PER_SEC;
-
- fprintf(stdout, "\nIncreased delay to %s.", format_timespan(h, sizeof(h), arg_delay));
- fflush(stdout);
- sleep(1);
- break;
-
- case '-':
- if (arg_delay <= USEC_PER_MSEC*500)
- arg_delay = USEC_PER_MSEC*250;
- else if (arg_delay < USEC_PER_MSEC*1250)
- arg_delay -= USEC_PER_MSEC*250;
- else
- arg_delay -= USEC_PER_SEC;
-
- fprintf(stdout, "\nDecreased delay to %s.", format_timespan(h, sizeof(h), arg_delay));
- fflush(stdout);
- sleep(1);
- break;
-
- case '?':
- case 'h':
- fprintf(stdout,
- "\t<" ANSI_HIGHLIGHT_ON "P" ANSI_HIGHLIGHT_OFF "> By path; <" ANSI_HIGHLIGHT_ON "T" ANSI_HIGHLIGHT_OFF "> By tasks; <" ANSI_HIGHLIGHT_ON "C" ANSI_HIGHLIGHT_OFF "> By CPU; <" ANSI_HIGHLIGHT_ON "M" ANSI_HIGHLIGHT_OFF "> By memory; <" ANSI_HIGHLIGHT_ON "I" ANSI_HIGHLIGHT_OFF "> By I/O\n"
- "\t<" ANSI_HIGHLIGHT_ON "Q" ANSI_HIGHLIGHT_OFF "> Quit; <" ANSI_HIGHLIGHT_ON "+" ANSI_HIGHLIGHT_OFF "> Increase delay; <" ANSI_HIGHLIGHT_ON "-" ANSI_HIGHLIGHT_OFF "> Decrease delay; <" ANSI_HIGHLIGHT_ON "SPACE" ANSI_HIGHLIGHT_OFF "> Refresh");
- fflush(stdout);
- sleep(3);
- break;
-
- default:
- fprintf(stdout, "\nUnknown key '%c'. Ignoring.", key);
- fflush(stdout);
- sleep(1);
- break;
- }
- }
-
- log_info("Exiting.");
-
- r = 0;
-
-finish:
- group_hashmap_free(a);
- group_hashmap_free(b);
-
- if (r < 0) {
- log_error("Exiting with failure: %s", strerror(-r));
- return EXIT_FAILURE;
- }
-
- return EXIT_SUCCESS;
-}
diff --git a/src/core/.gitignore b/src/core/.gitignore
deleted file mode 100644
index a763f72507..0000000000
--- a/src/core/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-/syscall-from-name.gperf
-/syscall-from-name.h
-/syscall-list.txt
-/syscall-to-name.h
-/macros.systemd
-/systemd.pc
diff --git a/src/core/Makefile b/src/core/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/core/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/core/audit-fd.c b/src/core/audit-fd.c
deleted file mode 100644
index 5955bd846e..0000000000
--- a/src/core/audit-fd.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-
-#include <errno.h>
-#include "audit-fd.h"
-
-#ifdef HAVE_AUDIT
-
-#include <stdbool.h>
-#include <libaudit.h>
-
-#include "log.h"
-#include "util.h"
-
-static bool initialized = false;
-static int audit_fd;
-
-int get_audit_fd(void) {
-
- if (!initialized) {
- audit_fd = audit_open();
-
- if (audit_fd < 0) {
- if (errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT)
- log_error("Failed to connect to audit log: %m");
-
- audit_fd = errno ? -errno : -EINVAL;
- }
-
- initialized = true;
- }
-
- return audit_fd;
-}
-
-void close_audit_fd(void) {
-
- if (initialized && audit_fd >= 0)
- close_nointr_nofail(audit_fd);
-
- initialized = true;
- audit_fd = -ECONNRESET;
-}
-
-#else
-
-int get_audit_fd(void) {
- return -EAFNOSUPPORT;
-}
-
-void close_audit_fd(void) {
-}
-
-#endif
diff --git a/src/core/audit-fd.h b/src/core/audit-fd.h
deleted file mode 100644
index 8b58289dc5..0000000000
--- a/src/core/audit-fd.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-int get_audit_fd(void);
-void close_audit_fd(void);
diff --git a/src/core/automount.c b/src/core/automount.c
deleted file mode 100644
index b1619a64e6..0000000000
--- a/src/core/automount.c
+++ /dev/null
@@ -1,902 +0,0 @@
-/*-*- 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 <errno.h>
-#include <limits.h>
-#include <sys/mount.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/epoll.h>
-#include <sys/stat.h>
-#include <linux/auto_fs4.h>
-#include <linux/auto_dev-ioctl.h>
-
-#include "unit.h"
-#include "automount.h"
-#include "load-fragment.h"
-#include "load-dropin.h"
-#include "unit-name.h"
-#include "dbus-automount.h"
-#include "bus-errors.h"
-#include "special.h"
-#include "label.h"
-#include "mkdir.h"
-#include "path-util.h"
-
-static const UnitActiveState state_translation_table[_AUTOMOUNT_STATE_MAX] = {
- [AUTOMOUNT_DEAD] = UNIT_INACTIVE,
- [AUTOMOUNT_WAITING] = UNIT_ACTIVE,
- [AUTOMOUNT_RUNNING] = UNIT_ACTIVE,
- [AUTOMOUNT_FAILED] = UNIT_FAILED
-};
-
-static int open_dev_autofs(Manager *m);
-
-static void automount_init(Unit *u) {
- Automount *a = AUTOMOUNT(u);
-
- assert(u);
- assert(u->load_state == UNIT_STUB);
-
- a->pipe_watch.fd = a->pipe_fd = -1;
- a->pipe_watch.type = WATCH_INVALID;
-
- a->directory_mode = 0755;
-
- UNIT(a)->ignore_on_isolate = true;
-}
-
-static void repeat_unmout(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("Failed to unmount: %m");
-
- break;
- }
-}
-
-static void unmount_autofs(Automount *a) {
- assert(a);
-
- if (a->pipe_fd < 0)
- return;
-
- automount_send_ready(a, -EHOSTDOWN);
-
- unit_unwatch_fd(UNIT(a), &a->pipe_watch);
- close_nointr_nofail(a->pipe_fd);
- a->pipe_fd = -1;
-
- /* If we reload/reexecute things we keep the mount point
- * around */
- if (a->where &&
- (UNIT(a)->manager->exit_code != MANAGER_RELOAD &&
- UNIT(a)->manager->exit_code != MANAGER_REEXECUTE))
- repeat_unmout(a->where);
-}
-
-static void automount_done(Unit *u) {
- Automount *a = AUTOMOUNT(u);
-
- assert(a);
-
- unmount_autofs(a);
- unit_ref_unset(&a->mount);
-
- free(a->where);
- a->where = NULL;
-
- set_free(a->tokens);
- a->tokens = NULL;
-}
-
-int automount_add_one_mount_link(Automount *a, Mount *m) {
- int r;
-
- assert(a);
- assert(m);
-
- if (UNIT(a)->load_state != UNIT_LOADED ||
- UNIT(m)->load_state != UNIT_LOADED)
- return 0;
-
- if (!path_startswith(a->where, m->where))
- return 0;
-
- if (path_equal(a->where, m->where))
- return 0;
-
- if ((r = unit_add_two_dependencies(UNIT(a), UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true)) < 0)
- return r;
-
- return 0;
-}
-
-static int automount_add_mount_links(Automount *a) {
- Unit *other;
- int r;
-
- assert(a);
-
- LIST_FOREACH(units_by_type, other, UNIT(a)->manager->units_by_type[UNIT_MOUNT])
- if ((r = automount_add_one_mount_link(a, MOUNT(other))) < 0)
- return r;
-
- return 0;
-}
-
-static int automount_add_default_dependencies(Automount *a) {
- int r;
-
- assert(a);
-
- if (UNIT(a)->manager->running_as != SYSTEMD_SYSTEM)
- return 0;
-
- r = unit_add_two_dependencies_by_name(UNIT(a), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static int automount_verify(Automount *a) {
- bool b;
- char *e;
- assert(a);
-
- if (UNIT(a)->load_state != UNIT_LOADED)
- return 0;
-
- if (path_equal(a->where, "/")) {
- log_error("Cannot have an automount unit for the root directory. Refusing.");
- return -EINVAL;
- }
-
- if (!(e = unit_name_from_path(a->where, ".automount")))
- return -ENOMEM;
-
- b = unit_has_name(UNIT(a), e);
- free(e);
-
- if (!b) {
- log_error("%s's Where setting doesn't match unit name. Refusing.", UNIT(a)->id);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int automount_load(Unit *u) {
- int r;
- Automount *a = AUTOMOUNT(u);
-
- assert(u);
- assert(u->load_state == UNIT_STUB);
-
- /* Load a .automount file */
- if ((r = unit_load_fragment_and_dropin_optional(u)) < 0)
- return r;
-
- if (u->load_state == UNIT_LOADED) {
- Unit *x;
-
- if (!a->where)
- if (!(a->where = unit_name_to_path(u->id)))
- return -ENOMEM;
-
- path_kill_slashes(a->where);
-
- if ((r = automount_add_mount_links(a)) < 0)
- return r;
-
- r = unit_load_related_unit(u, ".mount", &x);
- if (r < 0)
- return r;
-
- unit_ref_set(&a->mount, x);
-
- r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(a->mount), true);
- if (r < 0)
- return r;
-
- if (UNIT(a)->default_dependencies)
- if ((r = automount_add_default_dependencies(a)) < 0)
- return r;
- }
-
- return automount_verify(a);
-}
-
-static void automount_set_state(Automount *a, AutomountState state) {
- AutomountState old_state;
- assert(a);
-
- old_state = a->state;
- a->state = state;
-
- if (state != AUTOMOUNT_WAITING &&
- state != AUTOMOUNT_RUNNING)
- unmount_autofs(a);
-
- if (state != old_state)
- log_debug("%s changed %s -> %s",
- UNIT(a)->id,
- automount_state_to_string(old_state),
- automount_state_to_string(state));
-
- unit_notify(UNIT(a), state_translation_table[old_state], state_translation_table[state], true);
-}
-
-static int automount_coldplug(Unit *u) {
- Automount *a = AUTOMOUNT(u);
- int r;
-
- assert(a);
- assert(a->state == AUTOMOUNT_DEAD);
-
- if (a->deserialized_state != a->state) {
-
- if ((r = open_dev_autofs(u->manager)) < 0)
- return r;
-
- if (a->deserialized_state == AUTOMOUNT_WAITING ||
- a->deserialized_state == AUTOMOUNT_RUNNING) {
-
- assert(a->pipe_fd >= 0);
-
- if ((r = unit_watch_fd(UNIT(a), a->pipe_fd, EPOLLIN, &a->pipe_watch)) < 0)
- return r;
- }
-
- automount_set_state(a, a->deserialized_state);
- }
-
- return 0;
-}
-
-static void automount_dump(Unit *u, FILE *f, const char *prefix) {
- Automount *a = AUTOMOUNT(u);
-
- assert(a);
-
- fprintf(f,
- "%sAutomount State: %s\n"
- "%sResult: %s\n"
- "%sWhere: %s\n"
- "%sDirectoryMode: %04o\n",
- prefix, automount_state_to_string(a->state),
- prefix, automount_result_to_string(a->result),
- prefix, a->where,
- prefix, a->directory_mode);
-}
-
-static void automount_enter_dead(Automount *a, AutomountResult f) {
- assert(a);
-
- if (f != AUTOMOUNT_SUCCESS)
- a->result = f;
-
- automount_set_state(a, a->result != AUTOMOUNT_SUCCESS ? AUTOMOUNT_FAILED : AUTOMOUNT_DEAD);
-}
-
-static int open_dev_autofs(Manager *m) {
- struct autofs_dev_ioctl param;
-
- assert(m);
-
- if (m->dev_autofs_fd >= 0)
- return m->dev_autofs_fd;
-
- label_fix("/dev/autofs", false, false);
-
- if ((m->dev_autofs_fd = open("/dev/autofs", O_CLOEXEC|O_RDONLY)) < 0) {
- log_error("Failed to open /dev/autofs: %s", strerror(errno));
- return -errno;
- }
-
- init_autofs_dev_ioctl(&param);
- if (ioctl(m->dev_autofs_fd, AUTOFS_DEV_IOCTL_VERSION, &param) < 0) {
- close_nointr_nofail(m->dev_autofs_fd);
- m->dev_autofs_fd = -1;
- return -errno;
- }
-
- log_debug("Autofs kernel version %i.%i", param.ver_major, param.ver_minor);
-
- return m->dev_autofs_fd;
-}
-
-static int open_ioctl_fd(int dev_autofs_fd, const char *where, dev_t devid) {
- struct autofs_dev_ioctl *param;
- size_t l;
- int r;
-
- assert(dev_autofs_fd >= 0);
- assert(where);
-
- l = sizeof(struct autofs_dev_ioctl) + strlen(where) + 1;
-
- if (!(param = malloc(l)))
- return -ENOMEM;
-
- init_autofs_dev_ioctl(param);
- param->size = l;
- param->ioctlfd = -1;
- param->openmount.devid = devid;
- strcpy(param->path, where);
-
- if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_OPENMOUNT, param) < 0) {
- r = -errno;
- goto finish;
- }
-
- if (param->ioctlfd < 0) {
- r = -EIO;
- goto finish;
- }
-
- fd_cloexec(param->ioctlfd, true);
- r = param->ioctlfd;
-
-finish:
- free(param);
- return r;
-}
-
-static int autofs_protocol(int dev_autofs_fd, int ioctl_fd) {
- uint32_t major, minor;
- struct autofs_dev_ioctl param;
-
- assert(dev_autofs_fd >= 0);
- assert(ioctl_fd >= 0);
-
- init_autofs_dev_ioctl(&param);
- param.ioctlfd = ioctl_fd;
-
- if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_PROTOVER, &param) < 0)
- return -errno;
-
- major = param.protover.version;
-
- init_autofs_dev_ioctl(&param);
- param.ioctlfd = ioctl_fd;
-
- if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_PROTOSUBVER, &param) < 0)
- return -errno;
-
- minor = param.protosubver.sub_version;
-
- log_debug("Autofs protocol version %i.%i", major, minor);
- return 0;
-}
-
-static int autofs_set_timeout(int dev_autofs_fd, int ioctl_fd, time_t sec) {
- struct autofs_dev_ioctl param;
-
- assert(dev_autofs_fd >= 0);
- assert(ioctl_fd >= 0);
-
- init_autofs_dev_ioctl(&param);
- param.ioctlfd = ioctl_fd;
- param.timeout.timeout = sec;
-
- if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_TIMEOUT, &param) < 0)
- return -errno;
-
- return 0;
-}
-
-static int autofs_send_ready(int dev_autofs_fd, int ioctl_fd, uint32_t token, int status) {
- struct autofs_dev_ioctl param;
-
- assert(dev_autofs_fd >= 0);
- assert(ioctl_fd >= 0);
-
- init_autofs_dev_ioctl(&param);
- param.ioctlfd = ioctl_fd;
-
- if (status) {
- param.fail.token = token;
- param.fail.status = status;
- } else
- param.ready.token = token;
-
- if (ioctl(dev_autofs_fd, status ? AUTOFS_DEV_IOCTL_FAIL : AUTOFS_DEV_IOCTL_READY, &param) < 0)
- return -errno;
-
- return 0;
-}
-
-int automount_send_ready(Automount *a, int status) {
- int ioctl_fd, r;
- unsigned token;
-
- assert(a);
- assert(status <= 0);
-
- if (set_isempty(a->tokens))
- return 0;
-
- if ((ioctl_fd = open_ioctl_fd(UNIT(a)->manager->dev_autofs_fd, a->where, a->dev_id)) < 0) {
- r = ioctl_fd;
- goto fail;
- }
-
- if (status)
- log_debug("Sending failure: %s", strerror(-status));
- else
- log_debug("Sending success.");
-
- r = 0;
-
- /* Autofs thankfully does not hand out 0 as a token */
- while ((token = PTR_TO_UINT(set_steal_first(a->tokens)))) {
- int k;
-
- /* Autofs fun fact II:
- *
- * if you pass a positive status code here, the kernel will
- * freeze! Yay! */
-
- if ((k = autofs_send_ready(UNIT(a)->manager->dev_autofs_fd,
- ioctl_fd,
- token,
- status)) < 0)
- r = k;
- }
-
-fail:
- if (ioctl_fd >= 0)
- close_nointr_nofail(ioctl_fd);
-
- return r;
-}
-
-static void automount_enter_waiting(Automount *a) {
- int p[2] = { -1, -1 };
- char name[32], options[128];
- bool mounted = false;
- int r, ioctl_fd = -1, dev_autofs_fd;
- struct stat st;
-
- assert(a);
- assert(a->pipe_fd < 0);
- assert(a->where);
-
- if (a->tokens)
- set_clear(a->tokens);
-
- if ((dev_autofs_fd = open_dev_autofs(UNIT(a)->manager)) < 0) {
- r = dev_autofs_fd;
- goto fail;
- }
-
- /* We knowingly ignore the results of this call */
- mkdir_p_label(a->where, 0555);
-
- if (dir_is_empty(a->where) <= 0)
- log_notice("%s: Directory %s to mount over is not empty, mounting anyway. (To see the over-mounted files, please manually mount the underlying file system to a secondary location.)", a->meta.id, a->where);
-
- if (pipe2(p, O_NONBLOCK|O_CLOEXEC) < 0) {
- r = -errno;
- goto fail;
- }
-
- snprintf(options, sizeof(options), "fd=%i,pgrp=%u,minproto=5,maxproto=5,direct", p[1], (unsigned) getpgrp());
- char_array_0(options);
-
- snprintf(name, sizeof(name), "systemd-%u", (unsigned) getpid());
- char_array_0(name);
-
- if (mount(name, a->where, "autofs", 0, options) < 0) {
- r = -errno;
- goto fail;
- }
-
- mounted = true;
-
- close_nointr_nofail(p[1]);
- p[1] = -1;
-
- if (stat(a->where, &st) < 0) {
- r = -errno;
- goto fail;
- }
-
- if ((ioctl_fd = open_ioctl_fd(dev_autofs_fd, a->where, st.st_dev)) < 0) {
- r = ioctl_fd;
- goto fail;
- }
-
- if ((r = autofs_protocol(dev_autofs_fd, ioctl_fd)) < 0)
- goto fail;
-
- if ((r = autofs_set_timeout(dev_autofs_fd, ioctl_fd, 300)) < 0)
- goto fail;
-
- /* Autofs fun fact:
- *
- * Unless we close the ioctl fd here, for some weird reason
- * the direct mount will not receive events from the
- * kernel. */
-
- close_nointr_nofail(ioctl_fd);
- ioctl_fd = -1;
-
- if ((r = unit_watch_fd(UNIT(a), p[0], EPOLLIN, &a->pipe_watch)) < 0)
- goto fail;
-
- a->pipe_fd = p[0];
- a->dev_id = st.st_dev;
-
- automount_set_state(a, AUTOMOUNT_WAITING);
-
- return;
-
-fail:
- assert_se(close_pipe(p) == 0);
-
- if (ioctl_fd >= 0)
- close_nointr_nofail(ioctl_fd);
-
- if (mounted)
- repeat_unmout(a->where);
-
- log_error("Failed to initialize automounter: %s", strerror(-r));
- automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
-}
-
-static void automount_enter_runnning(Automount *a) {
- int r;
- struct stat st;
- DBusError error;
-
- assert(a);
- assert(UNIT_DEREF(a->mount));
-
- dbus_error_init(&error);
-
- /* We don't take mount requests anymore if we are supposed to
- * shut down anyway */
- if (unit_pending_inactive(UNIT(a))) {
- log_debug("Suppressing automount request on %s since unit stop is scheduled.", UNIT(a)->id);
- automount_send_ready(a, -EHOSTDOWN);
- return;
- }
-
- mkdir_p_label(a->where, a->directory_mode);
-
- /* Before we do anything, let's see if somebody is playing games with us? */
- if (lstat(a->where, &st) < 0) {
- log_warning("%s failed to stat automount point: %m", UNIT(a)->id);
- goto fail;
- }
-
- if (!S_ISDIR(st.st_mode) || st.st_dev != a->dev_id)
- log_info("%s's automount point already active?", UNIT(a)->id);
- else if ((r = manager_add_job(UNIT(a)->manager, JOB_START, UNIT_DEREF(a->mount), JOB_REPLACE, true, &error, NULL)) < 0) {
- log_warning("%s failed to queue mount startup job: %s", UNIT(a)->id, bus_error(&error, r));
- goto fail;
- }
-
- automount_set_state(a, AUTOMOUNT_RUNNING);
- return;
-
-fail:
- automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
- dbus_error_free(&error);
-}
-
-static int automount_start(Unit *u) {
- Automount *a = AUTOMOUNT(u);
-
- assert(a);
-
- assert(a->state == AUTOMOUNT_DEAD || a->state == AUTOMOUNT_FAILED);
-
- if (path_is_mount_point(a->where, false)) {
- log_error("Path %s is already a mount point, refusing start for %s", a->where, u->id);
- return -EEXIST;
- }
-
- if (UNIT_DEREF(a->mount)->load_state != UNIT_LOADED)
- return -ENOENT;
-
- a->result = AUTOMOUNT_SUCCESS;
- automount_enter_waiting(a);
- return 0;
-}
-
-static int automount_stop(Unit *u) {
- Automount *a = AUTOMOUNT(u);
-
- assert(a);
-
- assert(a->state == AUTOMOUNT_WAITING || a->state == AUTOMOUNT_RUNNING);
-
- automount_enter_dead(a, AUTOMOUNT_SUCCESS);
- return 0;
-}
-
-static int automount_serialize(Unit *u, FILE *f, FDSet *fds) {
- Automount *a = AUTOMOUNT(u);
- void *p;
- Iterator i;
-
- assert(a);
- assert(f);
- assert(fds);
-
- unit_serialize_item(u, f, "state", automount_state_to_string(a->state));
- unit_serialize_item(u, f, "result", automount_result_to_string(a->result));
- unit_serialize_item_format(u, f, "dev-id", "%u", (unsigned) a->dev_id);
-
- SET_FOREACH(p, a->tokens, i)
- unit_serialize_item_format(u, f, "token", "%u", PTR_TO_UINT(p));
-
- if (a->pipe_fd >= 0) {
- int copy;
-
- if ((copy = fdset_put_dup(fds, a->pipe_fd)) < 0)
- return copy;
-
- unit_serialize_item_format(u, f, "pipe-fd", "%i", copy);
- }
-
- return 0;
-}
-
-static int automount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
- Automount *a = AUTOMOUNT(u);
- int r;
-
- assert(a);
- assert(fds);
-
- if (streq(key, "state")) {
- AutomountState state;
-
- if ((state = automount_state_from_string(value)) < 0)
- log_debug("Failed to parse state value %s", value);
- else
- a->deserialized_state = state;
- } else if (streq(key, "result")) {
- AutomountResult f;
-
- f = automount_result_from_string(value);
- if (f < 0)
- log_debug("Failed to parse result value %s", value);
- else if (f != AUTOMOUNT_SUCCESS)
- a->result = f;
-
- } else if (streq(key, "dev-id")) {
- unsigned d;
-
- if (safe_atou(value, &d) < 0)
- log_debug("Failed to parse dev-id value %s", value);
- else
- a->dev_id = (unsigned) d;
- } else if (streq(key, "token")) {
- unsigned token;
-
- if (safe_atou(value, &token) < 0)
- log_debug("Failed to parse token value %s", value);
- else {
- if (!a->tokens)
- if (!(a->tokens = set_new(trivial_hash_func, trivial_compare_func)))
- return -ENOMEM;
-
- if ((r = set_put(a->tokens, UINT_TO_PTR(token))) < 0)
- return r;
- }
- } else if (streq(key, "pipe-fd")) {
- int fd;
-
- if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
- log_debug("Failed to parse pipe-fd value %s", value);
- else {
- if (a->pipe_fd >= 0)
- close_nointr_nofail(a->pipe_fd);
-
- a->pipe_fd = fdset_remove(fds, fd);
- }
- } else
- log_debug("Unknown serialization key '%s'", key);
-
- return 0;
-}
-
-static UnitActiveState automount_active_state(Unit *u) {
- assert(u);
-
- return state_translation_table[AUTOMOUNT(u)->state];
-}
-
-static const char *automount_sub_state_to_string(Unit *u) {
- assert(u);
-
- return automount_state_to_string(AUTOMOUNT(u)->state);
-}
-
-static bool automount_check_gc(Unit *u) {
- Automount *a = AUTOMOUNT(u);
-
- assert(a);
-
- if (!UNIT_DEREF(a->mount))
- return false;
-
- return UNIT_VTABLE(UNIT_DEREF(a->mount))->check_gc(UNIT_DEREF(a->mount));
-}
-
-static void automount_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
- Automount *a = AUTOMOUNT(u);
- union autofs_v5_packet_union packet;
- ssize_t l;
- int r;
-
- assert(a);
- assert(fd == a->pipe_fd);
-
- if (events != EPOLLIN) {
- log_error("Got invalid poll event on pipe.");
- goto fail;
- }
-
- if ((l = loop_read(a->pipe_fd, &packet, sizeof(packet), true)) != sizeof(packet)) {
- log_error("Invalid read from pipe: %s", l < 0 ? strerror(-l) : "short read");
- goto fail;
- }
-
- switch (packet.hdr.type) {
-
- case autofs_ptype_missing_direct:
-
- if (packet.v5_packet.pid > 0) {
- char *p = NULL;
-
- get_process_comm(packet.v5_packet.pid, &p);
- log_debug("Got direct mount request on %s, triggered by %lu (%s)",
- a->where, (unsigned long) packet.v5_packet.pid, strna(p));
- free(p);
-
- } else
- log_debug("Got direct mount request on %s", a->where);
-
- if (!a->tokens)
- if (!(a->tokens = set_new(trivial_hash_func, trivial_compare_func))) {
- log_error("Failed to allocate token set.");
- goto fail;
- }
-
- if ((r = set_put(a->tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token))) < 0) {
- log_error("Failed to remember token: %s", strerror(-r));
- goto fail;
- }
-
- automount_enter_runnning(a);
- break;
-
- default:
- log_error("Received unknown automount request %i", packet.hdr.type);
- break;
- }
-
- return;
-
-fail:
- automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
-}
-
-static void automount_shutdown(Manager *m) {
- assert(m);
-
- if (m->dev_autofs_fd >= 0)
- close_nointr_nofail(m->dev_autofs_fd);
-}
-
-static void automount_reset_failed(Unit *u) {
- Automount *a = AUTOMOUNT(u);
-
- assert(a);
-
- if (a->state == AUTOMOUNT_FAILED)
- automount_set_state(a, AUTOMOUNT_DEAD);
-
- a->result = AUTOMOUNT_SUCCESS;
-}
-
-static const char* const automount_state_table[_AUTOMOUNT_STATE_MAX] = {
- [AUTOMOUNT_DEAD] = "dead",
- [AUTOMOUNT_WAITING] = "waiting",
- [AUTOMOUNT_RUNNING] = "running",
- [AUTOMOUNT_FAILED] = "failed"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(automount_state, AutomountState);
-
-static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = {
- [AUTOMOUNT_SUCCESS] = "success",
- [AUTOMOUNT_FAILURE_RESOURCES] = "resources"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(automount_result, AutomountResult);
-
-const UnitVTable automount_vtable = {
- .object_size = sizeof(Automount),
- .sections =
- "Unit\0"
- "Automount\0"
- "Install\0",
-
- .no_alias = true,
- .no_instances = true,
-
- .init = automount_init,
- .load = automount_load,
- .done = automount_done,
-
- .coldplug = automount_coldplug,
-
- .dump = automount_dump,
-
- .start = automount_start,
- .stop = automount_stop,
-
- .serialize = automount_serialize,
- .deserialize_item = automount_deserialize_item,
-
- .active_state = automount_active_state,
- .sub_state_to_string = automount_sub_state_to_string,
-
- .check_gc = automount_check_gc,
-
- .fd_event = automount_fd_event,
-
- .reset_failed = automount_reset_failed,
-
- .bus_interface = "org.freedesktop.systemd1.Automount",
- .bus_message_handler = bus_automount_message_handler,
- .bus_invalidating_properties = bus_automount_invalidating_properties,
-
- .shutdown = automount_shutdown,
-
- .status_message_formats = {
- .finished_start_job = {
- [JOB_DONE] = "Set up automount %s.",
- [JOB_FAILED] = "Failed to set up automount %s.",
- [JOB_DEPENDENCY] = "Dependency failed for %s.",
- },
- .finished_stop_job = {
- [JOB_DONE] = "Unset automount %s.",
- [JOB_FAILED] = "Failed to unset automount %s.",
- },
- },
-};
diff --git a/src/core/automount.h b/src/core/automount.h
deleted file mode 100644
index 3d5736d1cb..0000000000
--- a/src/core/automount.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*-*- 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/>.
-***/
-
-typedef struct Automount Automount;
-
-#include "unit.h"
-
-typedef enum AutomountState {
- AUTOMOUNT_DEAD,
- AUTOMOUNT_WAITING,
- AUTOMOUNT_RUNNING,
- AUTOMOUNT_FAILED,
- _AUTOMOUNT_STATE_MAX,
- _AUTOMOUNT_STATE_INVALID = -1
-} AutomountState;
-
-typedef enum AutomountResult {
- AUTOMOUNT_SUCCESS,
- AUTOMOUNT_FAILURE_RESOURCES,
- _AUTOMOUNT_RESULT_MAX,
- _AUTOMOUNT_RESULT_INVALID = -1
-} AutomountResult;
-
-struct Automount {
- Unit meta;
-
- AutomountState state, deserialized_state;
-
- char *where;
-
- UnitRef mount;
-
- int pipe_fd;
- mode_t directory_mode;
- Watch pipe_watch;
- dev_t dev_id;
-
- Set *tokens;
-
- AutomountResult result;
-};
-
-extern const UnitVTable automount_vtable;
-
-int automount_send_ready(Automount *a, int status);
-
-int automount_add_one_mount_link(Automount *a, Mount *m);
-
-const char* automount_state_to_string(AutomountState i);
-AutomountState automount_state_from_string(const char *s);
-
-const char* automount_result_to_string(AutomountResult i);
-AutomountResult automount_result_from_string(const char *s);
diff --git a/src/core/build.h b/src/core/build.h
deleted file mode 100644
index 4513a0bad7..0000000000
--- a/src/core/build.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*-*- 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/>.
-***/
-
-#ifdef HAVE_PAM
-#define _PAM_FEATURE_ "+PAM"
-#else
-#define _PAM_FEATURE_ "-PAM"
-#endif
-
-#ifdef HAVE_LIBWRAP
-#define _LIBWRAP_FEATURE_ "+LIBWRAP"
-#else
-#define _LIBWRAP_FEATURE_ "-LIBWRAP"
-#endif
-
-#ifdef HAVE_AUDIT
-#define _AUDIT_FEATURE_ "+AUDIT"
-#else
-#define _AUDIT_FEATURE_ "-AUDIT"
-#endif
-
-#ifdef HAVE_SELINUX
-#define _SELINUX_FEATURE_ "+SELINUX"
-#else
-#define _SELINUX_FEATURE_ "-SELINUX"
-#endif
-
-#ifdef HAVE_IMA
-#define _IMA_FEATURE_ "+IMA"
-#else
-#define _IMA_FEATURE_ "-IMA"
-#endif
-
-#ifdef HAVE_SYSV_COMPAT
-#define _SYSVINIT_FEATURE_ "+SYSVINIT"
-#else
-#define _SYSVINIT_FEATURE_ "-SYSVINIT"
-#endif
-
-#ifdef HAVE_LIBCRYPTSETUP
-#define _LIBCRYPTSETUP_FEATURE_ "+LIBCRYPTSETUP"
-#else
-#define _LIBCRYPTSETUP_FEATURE_ "-LIBCRYPTSETUP"
-#endif
-
-#ifdef HAVE_GCRYPT
-#define _GCRYPT_FEATURE_ "+GCRYPT"
-#else
-#define _GCRYPT_FEATURE_ "-GCRYPT"
-#endif
-
-#ifdef HAVE_ACL
-#define _ACL_FEATURE_ "+ACL"
-#else
-#define _ACL_FEATURE_ "-ACL"
-#endif
-
-#ifdef HAVE_XZ
-#define _XZ_FEATURE_ "+XZ"
-#else
-#define _XZ_FEATURE_ "-XZ"
-#endif
-
-#define SYSTEMD_FEATURES _PAM_FEATURE_ " " _LIBWRAP_FEATURE_ " " _AUDIT_FEATURE_ " " _SELINUX_FEATURE_ " " _IMA_FEATURE_ " " _SYSVINIT_FEATURE_ " " _LIBCRYPTSETUP_FEATURE_ " " _GCRYPT_FEATURE_ " " _ACL_FEATURE_ " " _XZ_FEATURE_
diff --git a/src/core/bus-errors.h b/src/core/bus-errors.h
deleted file mode 100644
index 04c1b2849d..0000000000
--- a/src/core/bus-errors.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*-*- 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 <dbus/dbus.h>
-
-#define BUS_ERROR_NO_SUCH_UNIT "org.freedesktop.systemd1.NoSuchUnit"
-#define BUS_ERROR_NO_SUCH_JOB "org.freedesktop.systemd1.NoSuchJob"
-#define BUS_ERROR_NOT_SUBSCRIBED "org.freedesktop.systemd1.NotSubscribed"
-#define BUS_ERROR_INVALID_PATH "org.freedesktop.systemd1.InvalidPath"
-#define BUS_ERROR_INVALID_NAME "org.freedesktop.systemd1.InvalidName"
-#define BUS_ERROR_UNIT_TYPE_MISMATCH "org.freedesktop.systemd1.UnitTypeMismatch"
-#define BUS_ERROR_UNIT_EXISTS "org.freedesktop.systemd1.UnitExists"
-#define BUS_ERROR_NOT_SUPPORTED "org.freedesktop.systemd1.NotSupported"
-#define BUS_ERROR_INVALID_JOB_MODE "org.freedesktop.systemd1.InvalidJobMode"
-#define BUS_ERROR_ONLY_BY_DEPENDENCY "org.freedesktop.systemd1.OnlyByDependency"
-#define BUS_ERROR_NO_ISOLATION "org.freedesktop.systemd1.NoIsolation"
-#define BUS_ERROR_LOAD_FAILED "org.freedesktop.systemd1.LoadFailed"
-#define BUS_ERROR_MASKED "org.freedesktop.systemd1.Masked"
-#define BUS_ERROR_JOB_TYPE_NOT_APPLICABLE "org.freedesktop.systemd1.JobTypeNotApplicable"
-#define BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE "org.freedesktop.systemd1.TransactionIsDestructive"
-#define BUS_ERROR_TRANSACTION_JOBS_CONFLICTING "org.freedesktop.systemd1.TransactionJobsConflicting"
-#define BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC "org.freedesktop.systemd1.TransactionOrderIsCyclic"
-#define BUS_ERROR_SHUTTING_DOWN "org.freedesktop.systemd1.ShuttingDown"
-#define BUS_ERROR_NO_SUCH_PROCESS "org.freedesktop.systemd1.NoSuchProcess"
-
-static inline const char *bus_error(const DBusError *e, int r) {
- if (e && e->message)
- return e->message;
-
- if (r >= 0)
- return strerror(r);
-
- return strerror(-r);
-}
diff --git a/src/core/cgroup-attr.c b/src/core/cgroup-attr.c
deleted file mode 100644
index 71af09cf87..0000000000
--- a/src/core/cgroup-attr.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 "cgroup-attr.h"
-#include "cgroup-util.h"
-#include "list.h"
-
-int cgroup_attribute_apply(CGroupAttribute *a, CGroupBonding *b) {
- int r;
- char *path = NULL;
- char *v = NULL;
-
- assert(a);
-
- b = cgroup_bonding_find_list(b, a->controller);
- if (!b)
- return 0;
-
- if (a->map_callback) {
- r = a->map_callback(a->controller, a->name, a->value, &v);
- if (r < 0)
- return r;
- }
-
- r = cg_get_path(a->controller, b->path, a->name, &path);
- if (r < 0) {
- free(v);
- return r;
- }
-
- r = write_one_line_file(path, v ? v : a->value);
- if (r < 0)
- log_warning("Failed to write '%s' to %s: %s", v ? v : a->value, path, strerror(-r));
-
- free(path);
- free(v);
-
- return r;
-}
-
-int cgroup_attribute_apply_list(CGroupAttribute *first, CGroupBonding *b) {
- CGroupAttribute *a;
- int r = 0;
-
- LIST_FOREACH(by_unit, a, first) {
- int k;
-
- k = cgroup_attribute_apply(a, b);
- if (r == 0)
- r = k;
- }
-
- return r;
-}
-
-CGroupAttribute *cgroup_attribute_find_list(CGroupAttribute *first, const char *controller, const char *name) {
- CGroupAttribute *a;
-
- assert(controller);
- assert(name);
-
- LIST_FOREACH(by_unit, a, first)
- if (streq(a->controller, controller) &&
- streq(a->name, name))
- return a;
-
- return NULL;
-}
-
-static void cgroup_attribute_free(CGroupAttribute *a) {
- assert(a);
-
- free(a->controller);
- free(a->name);
- free(a->value);
- free(a);
-}
-
-void cgroup_attribute_free_list(CGroupAttribute *first) {
- CGroupAttribute *a, *n;
-
- LIST_FOREACH_SAFE(by_unit, a, n, first)
- cgroup_attribute_free(a);
-}
diff --git a/src/core/cgroup-attr.h b/src/core/cgroup-attr.h
deleted file mode 100644
index 2b754eac40..0000000000
--- a/src/core/cgroup-attr.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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/>.
-***/
-
-typedef struct CGroupAttribute CGroupAttribute;
-
-typedef int (*CGroupAttributeMapCallback)(const char *controller, const char*name, const char *value, char **ret);
-
-#include "unit.h"
-#include "cgroup.h"
-
-struct CGroupAttribute {
- char *controller;
- char *name;
- char *value;
-
- CGroupAttributeMapCallback map_callback;
-
- LIST_FIELDS(CGroupAttribute, by_unit);
-};
-
-int cgroup_attribute_apply(CGroupAttribute *a, CGroupBonding *b);
-int cgroup_attribute_apply_list(CGroupAttribute *first, CGroupBonding *b);
-
-CGroupAttribute *cgroup_attribute_find_list(CGroupAttribute *first, const char *controller, const char *name);
-
-void cgroup_attribute_free_list(CGroupAttribute *first);
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
deleted file mode 100644
index 8fc1731485..0000000000
--- a/src/core/cgroup.c
+++ /dev/null
@@ -1,598 +0,0 @@
-/*-*- 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 <errno.h>
-#include <assert.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <signal.h>
-#include <sys/mount.h>
-#include <fcntl.h>
-
-#include "cgroup.h"
-#include "cgroup-util.h"
-#include "log.h"
-#include "strv.h"
-#include "path-util.h"
-
-int cgroup_bonding_realize(CGroupBonding *b) {
- int r;
-
- assert(b);
- assert(b->path);
- assert(b->controller);
-
- r = cg_create(b->controller, b->path);
- if (r < 0) {
- log_warning("Failed to create cgroup %s:%s: %s", b->controller, b->path, strerror(-r));
- return r;
- }
-
- b->realized = true;
-
- return 0;
-}
-
-int cgroup_bonding_realize_list(CGroupBonding *first) {
- CGroupBonding *b;
- int r;
-
- LIST_FOREACH(by_unit, b, first)
- if ((r = cgroup_bonding_realize(b)) < 0 && b->essential)
- return r;
-
- return 0;
-}
-
-void cgroup_bonding_free(CGroupBonding *b, bool trim) {
- assert(b);
-
- if (b->unit) {
- CGroupBonding *f;
-
- LIST_REMOVE(CGroupBonding, by_unit, b->unit->cgroup_bondings, b);
-
- if (streq(b->controller, SYSTEMD_CGROUP_CONTROLLER)) {
- assert_se(f = hashmap_get(b->unit->manager->cgroup_bondings, b->path));
- LIST_REMOVE(CGroupBonding, by_path, f, b);
-
- if (f)
- hashmap_replace(b->unit->manager->cgroup_bondings, b->path, f);
- else
- hashmap_remove(b->unit->manager->cgroup_bondings, b->path);
- }
- }
-
- if (b->realized && b->ours && trim)
- cg_trim(b->controller, b->path, false);
-
- free(b->controller);
- free(b->path);
- free(b);
-}
-
-void cgroup_bonding_free_list(CGroupBonding *first, bool remove_or_trim) {
- CGroupBonding *b, *n;
-
- LIST_FOREACH_SAFE(by_unit, b, n, first)
- cgroup_bonding_free(b, remove_or_trim);
-}
-
-void cgroup_bonding_trim(CGroupBonding *b, bool delete_root) {
- assert(b);
-
- if (b->realized && b->ours)
- cg_trim(b->controller, b->path, delete_root);
-}
-
-void cgroup_bonding_trim_list(CGroupBonding *first, bool delete_root) {
- CGroupBonding *b;
-
- LIST_FOREACH(by_unit, b, first)
- cgroup_bonding_trim(b, delete_root);
-}
-
-
-int cgroup_bonding_install(CGroupBonding *b, pid_t pid, const char *cgroup_suffix) {
- char *p = NULL;
- const char *path;
- int r;
-
- assert(b);
- assert(pid >= 0);
-
- if (cgroup_suffix) {
- p = strjoin(b->path, "/", cgroup_suffix, NULL);
- if (!p)
- return -ENOMEM;
-
- path = p;
- } else
- path = b->path;
-
- r = cg_create_and_attach(b->controller, path, pid);
- free(p);
-
- if (r < 0)
- return r;
-
- b->realized = true;
- return 0;
-}
-
-int cgroup_bonding_install_list(CGroupBonding *first, pid_t pid, const char *cgroup_suffix) {
- CGroupBonding *b;
- int r;
-
- LIST_FOREACH(by_unit, b, first) {
- r = cgroup_bonding_install(b, pid, cgroup_suffix);
- if (r < 0 && b->essential)
- return r;
- }
-
- return 0;
-}
-
-int cgroup_bonding_set_group_access(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid) {
- assert(b);
-
- if (!b->realized)
- return -EINVAL;
-
- return cg_set_group_access(b->controller, b->path, mode, uid, gid);
-}
-
-int cgroup_bonding_set_group_access_list(CGroupBonding *first, mode_t mode, uid_t uid, gid_t gid) {
- CGroupBonding *b;
- int r;
-
- LIST_FOREACH(by_unit, b, first) {
- r = cgroup_bonding_set_group_access(b, mode, uid, gid);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-int cgroup_bonding_set_task_access(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid, int sticky) {
- assert(b);
-
- if (!b->realized)
- return -EINVAL;
-
- return cg_set_task_access(b->controller, b->path, mode, uid, gid, sticky);
-}
-
-int cgroup_bonding_set_task_access_list(CGroupBonding *first, mode_t mode, uid_t uid, gid_t gid, int sticky) {
- CGroupBonding *b;
- int r;
-
- LIST_FOREACH(by_unit, b, first) {
- r = cgroup_bonding_set_task_access(b, mode, uid, gid, sticky);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-int cgroup_bonding_kill(CGroupBonding *b, int sig, bool sigcont, bool rem, Set *s, const char *cgroup_suffix) {
- char *p = NULL;
- const char *path;
- int r;
-
- assert(b);
- assert(sig >= 0);
-
- /* Don't kill cgroups that aren't ours */
- if (!b->ours)
- return 0;
-
- if (cgroup_suffix) {
- p = strjoin(b->path, "/", cgroup_suffix, NULL);
- if (!p)
- return -ENOMEM;
-
- path = p;
- } else
- path = b->path;
-
- r = cg_kill_recursive(b->controller, path, sig, sigcont, true, rem, s);
- free(p);
-
- return r;
-}
-
-int cgroup_bonding_kill_list(CGroupBonding *first, int sig, bool sigcont, bool rem, Set *s, const char *cgroup_suffix) {
- CGroupBonding *b;
- Set *allocated_set = NULL;
- int ret = -EAGAIN, r;
-
- if (!first)
- return 0;
-
- if (!s)
- if (!(s = allocated_set = set_new(trivial_hash_func, trivial_compare_func)))
- return -ENOMEM;
-
- LIST_FOREACH(by_unit, b, first) {
- r = cgroup_bonding_kill(b, sig, sigcont, rem, s, cgroup_suffix);
- if (r < 0) {
- if (r == -EAGAIN || r == -ESRCH)
- continue;
-
- ret = r;
- goto finish;
- }
-
- if (ret < 0 || r > 0)
- ret = r;
- }
-
-finish:
- if (allocated_set)
- set_free(allocated_set);
-
- return ret;
-}
-
-/* Returns 1 if the group is empty, 0 if it is not, -EAGAIN if we
- * cannot know */
-int cgroup_bonding_is_empty(CGroupBonding *b) {
- int r;
-
- assert(b);
-
- if ((r = cg_is_empty_recursive(b->controller, b->path, true)) < 0)
- return r;
-
- /* If it is empty it is empty */
- if (r > 0)
- return 1;
-
- /* It's not only us using this cgroup, so we just don't know */
- return b->ours ? 0 : -EAGAIN;
-}
-
-int cgroup_bonding_is_empty_list(CGroupBonding *first) {
- CGroupBonding *b;
-
- LIST_FOREACH(by_unit, b, first) {
- int r;
-
- if ((r = cgroup_bonding_is_empty(b)) < 0) {
- /* If this returned -EAGAIN, then we don't know if the
- * group is empty, so let's see if another group can
- * tell us */
-
- if (r != -EAGAIN)
- return r;
- } else
- return r;
- }
-
- return -EAGAIN;
-}
-
-int manager_setup_cgroup(Manager *m) {
- char *current = NULL, *path = NULL;
- int r;
- char suffix[32];
-
- assert(m);
-
- /* 0. Be nice to Ingo Molnar #628004 */
- if (path_is_mount_point("/sys/fs/cgroup/systemd", false) <= 0) {
- log_warning("No control group support available, not creating root group.");
- return 0;
- }
-
- /* 1. Determine hierarchy */
- r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 0, &current);
- if (r < 0) {
- log_error("Cannot determine cgroup we are running in: %s", strerror(-r));
- goto finish;
- }
-
- if (m->running_as == SYSTEMD_SYSTEM)
- strcpy(suffix, "/system");
- else {
- snprintf(suffix, sizeof(suffix), "/systemd-%lu", (unsigned long) getpid());
- char_array_0(suffix);
- }
-
- free(m->cgroup_hierarchy);
- if (endswith(current, suffix)) {
- /* We probably got reexecuted and can continue to use our root cgroup */
- m->cgroup_hierarchy = current;
- current = NULL;
-
- } else {
- /* We need a new root cgroup */
- m->cgroup_hierarchy = NULL;
- if (asprintf(&m->cgroup_hierarchy, "%s%s", streq(current, "/") ? "" : current, suffix) < 0) {
- r = log_oom();
- goto finish;
- }
- }
-
- /* 2. Show data */
- r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, NULL, &path);
- if (r < 0) {
- log_error("Cannot find cgroup mount point: %s", strerror(-r));
- goto finish;
- }
-
- log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER ". File system hierarchy is at %s.", path);
-
- /* 3. Install agent */
- r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, SYSTEMD_CGROUP_AGENT_PATH);
- if (r < 0)
- log_warning("Failed to install release agent, ignoring: %s", strerror(-r));
- else if (r > 0)
- log_debug("Installed release agent.");
- else
- log_debug("Release agent already installed.");
-
- /* 4. Realize the group */
- r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, 0);
- if (r < 0) {
- log_error("Failed to create root cgroup hierarchy: %s", strerror(-r));
- goto finish;
- }
-
- /* 5. And pin it, so that it cannot be unmounted */
- if (m->pin_cgroupfs_fd >= 0)
- close_nointr_nofail(m->pin_cgroupfs_fd);
-
- m->pin_cgroupfs_fd = open(path, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY|O_NONBLOCK);
- if (r < 0) {
- log_error("Failed to open pin file: %m");
- r = -errno;
- goto finish;
- }
-
- log_debug("Created root group.");
-
- cg_shorten_controllers(m->default_controllers);
-
-finish:
- free(current);
- free(path);
-
- return r;
-}
-
-void manager_shutdown_cgroup(Manager *m, bool delete) {
- assert(m);
-
- if (delete && m->cgroup_hierarchy)
- cg_delete(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy);
-
- if (m->pin_cgroupfs_fd >= 0) {
- close_nointr_nofail(m->pin_cgroupfs_fd);
- m->pin_cgroupfs_fd = -1;
- }
-
- free(m->cgroup_hierarchy);
- m->cgroup_hierarchy = NULL;
-}
-
-int cgroup_bonding_get(Manager *m, const char *cgroup, CGroupBonding **bonding) {
- CGroupBonding *b;
- char *p;
-
- assert(m);
- assert(cgroup);
- assert(bonding);
-
- b = hashmap_get(m->cgroup_bondings, cgroup);
- if (b) {
- *bonding = b;
- return 1;
- }
-
- p = strdup(cgroup);
- if (!p)
- return -ENOMEM;
-
- for (;;) {
- char *e;
-
- e = strrchr(p, '/');
- if (!e || e == p) {
- free(p);
- *bonding = NULL;
- return 0;
- }
-
- *e = 0;
-
- b = hashmap_get(m->cgroup_bondings, p);
- if (b) {
- free(p);
- *bonding = b;
- return 1;
- }
- }
-}
-
-int cgroup_notify_empty(Manager *m, const char *group) {
- CGroupBonding *l, *b;
- int r;
-
- assert(m);
- assert(group);
-
- r = cgroup_bonding_get(m, group, &l);
- if (r <= 0)
- return r;
-
- LIST_FOREACH(by_path, b, l) {
- int t;
-
- if (!b->unit)
- continue;
-
- t = cgroup_bonding_is_empty_list(b);
- if (t < 0) {
-
- /* If we don't know, we don't know */
- if (t != -EAGAIN)
- log_warning("Failed to check whether cgroup is empty: %s", strerror(errno));
-
- continue;
- }
-
- if (t > 0) {
- /* If it is empty, let's delete it */
- cgroup_bonding_trim_list(b->unit->cgroup_bondings, true);
-
- if (UNIT_VTABLE(b->unit)->cgroup_notify_empty)
- UNIT_VTABLE(b->unit)->cgroup_notify_empty(b->unit);
- }
- }
-
- return 0;
-}
-
-Unit* cgroup_unit_by_pid(Manager *m, pid_t pid) {
- CGroupBonding *l, *b;
- char *group = NULL;
-
- assert(m);
-
- if (pid <= 1)
- return NULL;
-
- if (cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &group) < 0)
- return NULL;
-
- l = hashmap_get(m->cgroup_bondings, group);
-
- if (!l) {
- char *slash;
-
- while ((slash = strrchr(group, '/'))) {
- if (slash == group)
- break;
-
- *slash = 0;
-
- if ((l = hashmap_get(m->cgroup_bondings, group)))
- break;
- }
- }
-
- free(group);
-
- LIST_FOREACH(by_path, b, l) {
-
- if (!b->unit)
- continue;
-
- if (b->ours)
- return b->unit;
- }
-
- return NULL;
-}
-
-CGroupBonding *cgroup_bonding_find_list(CGroupBonding *first, const char *controller) {
- CGroupBonding *b;
-
- assert(controller);
-
- LIST_FOREACH(by_unit, b, first)
- if (streq(b->controller, controller))
- return b;
-
- return NULL;
-}
-
-char *cgroup_bonding_to_string(CGroupBonding *b) {
- char *r;
-
- assert(b);
-
- if (asprintf(&r, "%s:%s", b->controller, b->path) < 0)
- return NULL;
-
- return r;
-}
-
-pid_t cgroup_bonding_search_main_pid(CGroupBonding *b) {
- FILE *f;
- pid_t pid = 0, npid, mypid;
-
- assert(b);
-
- if (!b->ours)
- return 0;
-
- if (cg_enumerate_processes(b->controller, b->path, &f) < 0)
- return 0;
-
- mypid = getpid();
-
- while (cg_read_pid(f, &npid) > 0) {
- pid_t ppid;
-
- if (npid == pid)
- continue;
-
- /* Ignore processes that aren't our kids */
- if (get_parent_of_pid(npid, &ppid) >= 0 && ppid != mypid)
- continue;
-
- if (pid != 0) {
- /* Dang, there's more than one daemonized PID
- in this group, so we don't know what process
- is the main process. */
- pid = 0;
- break;
- }
-
- pid = npid;
- }
-
- fclose(f);
-
- return pid;
-}
-
-pid_t cgroup_bonding_search_main_pid_list(CGroupBonding *first) {
- CGroupBonding *b;
- pid_t pid;
-
- /* Try to find a main pid from this cgroup, but checking if
- * there's only one PID in the cgroup and returning it. Later
- * on we might want to add additional, smarter heuristics
- * here. */
-
- LIST_FOREACH(by_unit, b, first)
- if ((pid = cgroup_bonding_search_main_pid(b)) != 0)
- return pid;
-
- return 0;
-
-}
diff --git a/src/core/cgroup.h b/src/core/cgroup.h
deleted file mode 100644
index 229da52ba4..0000000000
--- a/src/core/cgroup.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*-*- 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/>.
-***/
-
-typedef struct CGroupBonding CGroupBonding;
-
-#include "unit.h"
-
-/* Binds a cgroup to a name */
-struct CGroupBonding {
- char *controller;
- char *path;
-
- Unit *unit;
-
- /* For the Unit::cgroup_bondings list */
- LIST_FIELDS(CGroupBonding, by_unit);
-
- /* For the Manager::cgroup_bondings hashmap */
- LIST_FIELDS(CGroupBonding, by_path);
-
- /* When shutting down, remove cgroup? Are our own tasks the
- * only ones in this group?*/
- bool ours:1;
-
- /* If we cannot create this group, or add a process to it, is this fatal? */
- bool essential:1;
-
- /* This cgroup is realized */
- bool realized:1;
-};
-
-int cgroup_bonding_realize(CGroupBonding *b);
-int cgroup_bonding_realize_list(CGroupBonding *first);
-
-void cgroup_bonding_free(CGroupBonding *b, bool trim);
-void cgroup_bonding_free_list(CGroupBonding *first, bool trim);
-
-int cgroup_bonding_install(CGroupBonding *b, pid_t pid, const char *suffix);
-int cgroup_bonding_install_list(CGroupBonding *first, pid_t pid, const char *suffix);
-
-int cgroup_bonding_set_group_access(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid);
-int cgroup_bonding_set_group_access_list(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid);
-
-int cgroup_bonding_set_task_access(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid, int sticky);
-int cgroup_bonding_set_task_access_list(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid, int sticky);
-
-int cgroup_bonding_kill(CGroupBonding *b, int sig, bool sigcont, bool rem, Set *s, const char *suffix);
-int cgroup_bonding_kill_list(CGroupBonding *first, int sig, bool sigcont, bool rem, Set *s, const char *suffix);
-
-void cgroup_bonding_trim(CGroupBonding *first, bool delete_root);
-void cgroup_bonding_trim_list(CGroupBonding *first, bool delete_root);
-
-int cgroup_bonding_is_empty(CGroupBonding *b);
-int cgroup_bonding_is_empty_list(CGroupBonding *first);
-
-CGroupBonding *cgroup_bonding_find_list(CGroupBonding *first, const char *controller);
-
-char *cgroup_bonding_to_string(CGroupBonding *b);
-
-pid_t cgroup_bonding_search_main_pid(CGroupBonding *b);
-pid_t cgroup_bonding_search_main_pid_list(CGroupBonding *b);
-
-#include "manager.h"
-
-int manager_setup_cgroup(Manager *m);
-void manager_shutdown_cgroup(Manager *m, bool delete);
-
-int cgroup_bonding_get(Manager *m, const char *cgroup, CGroupBonding **bonding);
-int cgroup_notify_empty(Manager *m, const char *group);
-
-Unit* cgroup_unit_by_pid(Manager *m, pid_t pid);
diff --git a/src/core/condition.c b/src/core/condition.c
deleted file mode 100644
index 32a37ccad6..0000000000
--- a/src/core/condition.c
+++ /dev/null
@@ -1,370 +0,0 @@
-/*-*- 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 <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/capability.h>
-#include <sys/statvfs.h>
-#include <fnmatch.h>
-
-#ifdef HAVE_SELINUX
-#include <selinux/selinux.h>
-#endif
-
-#include <systemd/sd-id128.h>
-#include "util.h"
-#include "condition.h"
-#include "virt.h"
-#include "path-util.h"
-
-Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate) {
- Condition *c;
-
- assert(type < _CONDITION_TYPE_MAX);
-
- c = new0(Condition, 1);
- if (!c)
- return NULL;
-
- c->type = type;
- c->trigger = trigger;
- c->negate = negate;
-
- if (parameter) {
- c->parameter = strdup(parameter);
- if (!c->parameter) {
- free(c);
- return NULL;
- }
- }
-
- return c;
-}
-
-void condition_free(Condition *c) {
- assert(c);
-
- free(c->parameter);
- free(c);
-}
-
-void condition_free_list(Condition *first) {
- Condition *c, *n;
-
- LIST_FOREACH_SAFE(conditions, c, n, first)
- condition_free(c);
-}
-
-static bool test_kernel_command_line(const char *parameter) {
- char *line, *w, *state, *word = NULL;
- bool equal;
- int r;
- size_t l, pl;
- bool found = false;
-
- assert(parameter);
-
- if (detect_container(NULL) > 0)
- return false;
-
- r = read_one_line_file("/proc/cmdline", &line);
- if (r < 0) {
- log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
- return false;
- }
-
- equal = !!strchr(parameter, '=');
- pl = strlen(parameter);
-
- FOREACH_WORD_QUOTED(w, l, line, state) {
-
- free(word);
- word = strndup(w, l);
- if (!word)
- break;
-
- if (equal) {
- if (streq(word, parameter)) {
- found = true;
- break;
- }
- } else {
- if (startswith(word, parameter) && (word[pl] == '=' || word[pl] == 0)) {
- found = true;
- break;
- }
- }
-
- }
-
- free(word);
- free(line);
-
- return found;
-}
-
-static bool test_virtualization(const char *parameter) {
- int b;
- Virtualization v;
- const char *id;
-
- assert(parameter);
-
- v = detect_virtualization(&id);
- if (v < 0) {
- log_warning("Failed to detect virtualization, ignoring: %s", strerror(-v));
- return false;
- }
-
- /* First, compare with yes/no */
- b = parse_boolean(parameter);
-
- if (v > 0 && b > 0)
- return true;
-
- if (v == 0 && b == 0)
- return true;
-
- /* Then, compare categorization */
- if (v == VIRTUALIZATION_VM && streq(parameter, "vm"))
- return true;
-
- if (v == VIRTUALIZATION_CONTAINER && streq(parameter, "container"))
- return true;
-
- /* Finally compare id */
- return v > 0 && streq(parameter, id);
-}
-
-static bool test_security(const char *parameter) {
-#ifdef HAVE_SELINUX
- if (streq(parameter, "selinux"))
- return is_selinux_enabled() > 0;
-#endif
- return false;
-}
-
-static bool test_capability(const char *parameter) {
- cap_value_t value;
- FILE *f;
- char line[LINE_MAX];
- unsigned long long capabilities = (unsigned long long) -1;
-
- /* If it's an invalid capability, we don't have it */
-
- if (cap_from_name(parameter, &value) < 0)
- return false;
-
- /* If it's a valid capability we default to assume
- * that we have it */
-
- f = fopen("/proc/self/status", "re");
- if (!f)
- return true;
-
- while (fgets(line, sizeof(line), f)) {
- truncate_nl(line);
-
- if (startswith(line, "CapBnd:")) {
- (void) sscanf(line+7, "%llx", &capabilities);
- break;
- }
- }
-
- fclose(f);
-
- return !!(capabilities & (1ULL << value));
-}
-
-static bool test_host(const char *parameter) {
- sd_id128_t x, y;
- char *h;
- int r;
- bool b;
-
- if (sd_id128_from_string(parameter, &x) >= 0) {
-
- r = sd_id128_get_machine(&y);
- if (r < 0)
- return false;
-
- return sd_id128_equal(x, y);
- }
-
- h = gethostname_malloc();
- if (!h)
- return false;
-
- b = fnmatch(parameter, h, FNM_CASEFOLD) == 0;
- free(h);
-
- return b;
-}
-
-bool condition_test(Condition *c) {
- assert(c);
-
- switch(c->type) {
-
- case CONDITION_PATH_EXISTS:
- return (access(c->parameter, F_OK) >= 0) == !c->negate;
-
- case CONDITION_PATH_EXISTS_GLOB:
- return (glob_exists(c->parameter) > 0) == !c->negate;
-
- case CONDITION_PATH_IS_DIRECTORY: {
- struct stat st;
-
- if (stat(c->parameter, &st) < 0)
- return c->negate;
- return S_ISDIR(st.st_mode) == !c->negate;
- }
-
- case CONDITION_PATH_IS_SYMBOLIC_LINK: {
- struct stat st;
-
- if (lstat(c->parameter, &st) < 0)
- return c->negate;
- return S_ISLNK(st.st_mode) == !c->negate;
- }
-
- case CONDITION_PATH_IS_MOUNT_POINT:
- return (path_is_mount_point(c->parameter, true) > 0) == !c->negate;
-
- case CONDITION_PATH_IS_READ_WRITE:
- return (path_is_read_only_fs(c->parameter) > 0) == c->negate;
-
- case CONDITION_DIRECTORY_NOT_EMPTY: {
- int k;
-
- k = dir_is_empty(c->parameter);
- return !(k == -ENOENT || k > 0) == !c->negate;
- }
-
- case CONDITION_FILE_NOT_EMPTY: {
- struct stat st;
-
- if (stat(c->parameter, &st) < 0)
- return c->negate;
-
- return (S_ISREG(st.st_mode) && st.st_size > 0) == !c->negate;
- }
-
- case CONDITION_FILE_IS_EXECUTABLE: {
- struct stat st;
-
- if (stat(c->parameter, &st) < 0)
- return c->negate;
-
- return (S_ISREG(st.st_mode) && (st.st_mode & 0111)) == !c->negate;
- }
-
- case CONDITION_KERNEL_COMMAND_LINE:
- return test_kernel_command_line(c->parameter) == !c->negate;
-
- case CONDITION_VIRTUALIZATION:
- return test_virtualization(c->parameter) == !c->negate;
-
- case CONDITION_SECURITY:
- return test_security(c->parameter) == !c->negate;
-
- case CONDITION_CAPABILITY:
- return test_capability(c->parameter) == !c->negate;
-
- case CONDITION_HOST:
- return test_host(c->parameter) == !c->negate;
-
- case CONDITION_NULL:
- return !c->negate;
-
- default:
- assert_not_reached("Invalid condition type.");
- }
-}
-
-bool condition_test_list(Condition *first) {
- Condition *c;
- int triggered = -1;
-
- /* If the condition list is empty, then it is true */
- if (!first)
- return true;
-
- /* Otherwise, if all of the non-trigger conditions apply and
- * if any of the trigger conditions apply (unless there are
- * none) we return true */
- LIST_FOREACH(conditions, c, first) {
- bool b;
-
- b = condition_test(c);
-
- if (!c->trigger && !b)
- return false;
-
- if (c->trigger && triggered <= 0)
- triggered = b;
- }
-
- return triggered != 0;
-}
-
-void condition_dump(Condition *c, FILE *f, const char *prefix) {
- assert(c);
- assert(f);
-
- if (!prefix)
- prefix = "";
-
- fprintf(f,
- "%s\t%s: %s%s%s\n",
- prefix,
- condition_type_to_string(c->type),
- c->trigger ? "|" : "",
- c->negate ? "!" : "",
- c->parameter);
-}
-
-void condition_dump_list(Condition *first, FILE *f, const char *prefix) {
- Condition *c;
-
- LIST_FOREACH(conditions, c, first)
- condition_dump(c, f, prefix);
-}
-
-static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
- [CONDITION_PATH_EXISTS] = "ConditionPathExists",
- [CONDITION_PATH_EXISTS_GLOB] = "ConditionPathExistsGlob",
- [CONDITION_PATH_IS_DIRECTORY] = "ConditionPathIsDirectory",
- [CONDITION_PATH_IS_SYMBOLIC_LINK] = "ConditionPathIsSymbolicLink",
- [CONDITION_PATH_IS_MOUNT_POINT] = "ConditionPathIsMountPoint",
- [CONDITION_PATH_IS_READ_WRITE] = "ConditionPathIsReadWrite",
- [CONDITION_DIRECTORY_NOT_EMPTY] = "ConditionDirectoryNotEmpty",
- [CONDITION_FILE_NOT_EMPTY] = "ConditionFileNotEmpty",
- [CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine",
- [CONDITION_VIRTUALIZATION] = "ConditionVirtualization",
- [CONDITION_SECURITY] = "ConditionSecurity",
- [CONDITION_HOST] = "ConditionHost",
- [CONDITION_NULL] = "ConditionNull"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType);
diff --git a/src/core/condition.h b/src/core/condition.h
deleted file mode 100644
index 03954e40b3..0000000000
--- a/src/core/condition.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*-*- 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 "list.h"
-
-typedef enum ConditionType {
- CONDITION_PATH_EXISTS,
- CONDITION_PATH_EXISTS_GLOB,
- CONDITION_PATH_IS_DIRECTORY,
- CONDITION_PATH_IS_SYMBOLIC_LINK,
- CONDITION_PATH_IS_MOUNT_POINT,
- CONDITION_PATH_IS_READ_WRITE,
- CONDITION_DIRECTORY_NOT_EMPTY,
- CONDITION_FILE_NOT_EMPTY,
- CONDITION_FILE_IS_EXECUTABLE,
- CONDITION_KERNEL_COMMAND_LINE,
- CONDITION_VIRTUALIZATION,
- CONDITION_SECURITY,
- CONDITION_CAPABILITY,
- CONDITION_HOST,
- CONDITION_NULL,
- _CONDITION_TYPE_MAX,
- _CONDITION_TYPE_INVALID = -1
-} ConditionType;
-
-typedef struct Condition {
- ConditionType type;
- char *parameter;
-
- bool trigger:1;
- bool negate:1;
-
- LIST_FIELDS(struct Condition, conditions);
-} Condition;
-
-Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate);
-void condition_free(Condition *c);
-void condition_free_list(Condition *c);
-
-bool condition_test(Condition *c);
-bool condition_test_list(Condition *c);
-
-void condition_dump(Condition *c, FILE *f, const char *prefix);
-void condition_dump_list(Condition *c, FILE *f, const char *prefix);
-
-const char* condition_type_to_string(ConditionType t);
-int condition_type_from_string(const char *s);
diff --git a/src/core/dbus-automount.c b/src/core/dbus-automount.c
deleted file mode 100644
index 060cbf7707..0000000000
--- a/src/core/dbus-automount.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*-*- 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 <errno.h>
-
-#include "dbus-unit.h"
-#include "dbus-automount.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
-
-#define BUS_AUTOMOUNT_INTERFACE \
- " <interface name=\"org.freedesktop.systemd1.Automount\">\n" \
- " <property name=\"Where\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"Result\" type=\"s\" access=\"read\"/>\n" \
- " </interface>\n"
-
-#define INTROSPECTION \
- DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
- "<node>\n" \
- BUS_UNIT_INTERFACE \
- BUS_AUTOMOUNT_INTERFACE \
- BUS_PROPERTIES_INTERFACE \
- BUS_PEER_INTERFACE \
- BUS_INTROSPECTABLE_INTERFACE \
- "</node>\n"
-
-#define INTERFACES_LIST \
- BUS_UNIT_INTERFACES_LIST \
- "org.freedesktop.systemd1.Automount\0"
-
-const char bus_automount_interface[] _introspect_("Automount") = BUS_AUTOMOUNT_INTERFACE;
-
-const char bus_automount_invalidating_properties[] =
- "Result\0";
-
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_automount_append_automount_result, automount_result, AutomountResult);
-
-static const BusProperty bus_automount_properties[] = {
- { "Where", bus_property_append_string, "s", offsetof(Automount, where), true },
- { "DirectoryMode", bus_property_append_mode, "u", offsetof(Automount, directory_mode) },
- { "Result", bus_automount_append_automount_result, "s", offsetof(Automount, result) },
- { NULL, }
-};
-
-DBusHandlerResult bus_automount_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
- Automount *am = AUTOMOUNT(u);
- const BusBoundProperties bps[] = {
- { "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
- { "org.freedesktop.systemd1.Automount", bus_automount_properties, am },
- { NULL, }
- };
-
- SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
- return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
diff --git a/src/core/dbus-automount.h b/src/core/dbus-automount.h
deleted file mode 100644
index b338e25fc1..0000000000
--- a/src/core/dbus-automount.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*-*- 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 <dbus/dbus.h>
-
-#include "unit.h"
-
-DBusHandlerResult bus_automount_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
-
-extern const char bus_automount_interface[];
-extern const char bus_automount_invalidating_properties[];
diff --git a/src/core/dbus-device.c b/src/core/dbus-device.c
deleted file mode 100644
index dbd91fe3db..0000000000
--- a/src/core/dbus-device.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*-*- 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 "dbus-unit.h"
-#include "dbus-device.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
-
-#define BUS_DEVICE_INTERFACE \
- " <interface name=\"org.freedesktop.systemd1.Device\">\n" \
- " <property name=\"SysFSPath\" type=\"s\" access=\"read\"/>\n" \
- " </interface>\n"
-
-#define INTROSPECTION \
- DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
- "<node>\n" \
- BUS_UNIT_INTERFACE \
- BUS_DEVICE_INTERFACE \
- BUS_PROPERTIES_INTERFACE \
- BUS_PEER_INTERFACE \
- BUS_INTROSPECTABLE_INTERFACE \
- "</node>\n"
-
-#define INTERFACES_LIST \
- BUS_UNIT_INTERFACES_LIST \
- "org.freedesktop.systemd1.Device\0"
-
-const char bus_device_interface[] _introspect_("Device") = BUS_DEVICE_INTERFACE;
-
-const char bus_device_invalidating_properties[] =
- "SysFSPath\0";
-
-static const BusProperty bus_device_properties[] = {
- { "SysFSPath", bus_property_append_string, "s", offsetof(Device, sysfs), true },
- { NULL, }
-};
-
-
-DBusHandlerResult bus_device_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
- Device *d = DEVICE(u);
- const BusBoundProperties bps[] = {
- { "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
- { "org.freedesktop.systemd1.Device", bus_device_properties, d },
- { NULL, }
- };
-
- SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
- return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
diff --git a/src/core/dbus-device.h b/src/core/dbus-device.h
deleted file mode 100644
index 311e0685d1..0000000000
--- a/src/core/dbus-device.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*-*- 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 <dbus/dbus.h>
-
-#include "unit.h"
-
-DBusHandlerResult bus_device_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
-
-extern const char bus_device_interface[];
-extern const char bus_device_invalidating_properties[];
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
deleted file mode 100644
index e815cb58e4..0000000000
--- a/src/core/dbus-execute.c
+++ /dev/null
@@ -1,439 +0,0 @@
-/*-*- 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 <errno.h>
-#include <dbus/dbus.h>
-#include <sys/prctl.h>
-
-#include "dbus-execute.h"
-#include "missing.h"
-#include "ioprio.h"
-#include "strv.h"
-#include "dbus-common.h"
-#include "syscall-list.h"
-
-DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_input, exec_input, ExecInput);
-DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_output, exec_output, ExecOutput);
-
-int bus_execute_append_env_files(DBusMessageIter *i, const char *property, void *data) {
- char **env_files = data, **j;
- DBusMessageIter sub, sub2;
-
- assert(i);
- assert(property);
-
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sb)", &sub))
- return -ENOMEM;
-
- STRV_FOREACH(j, env_files) {
- dbus_bool_t b = false;
- char *fn = *j;
-
- if (fn[0] == '-') {
- b = true;
- fn++;
- }
-
- if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &fn) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_BOOLEAN, &b) ||
- !dbus_message_iter_close_container(&sub, &sub2))
- return -ENOMEM;
- }
-
- if (!dbus_message_iter_close_container(i, &sub))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_execute_append_oom_score_adjust(DBusMessageIter *i, const char *property, void *data) {
- ExecContext *c = data;
- int32_t n;
-
- assert(i);
- assert(property);
- assert(c);
-
- if (c->oom_score_adjust_set)
- n = c->oom_score_adjust;
- else {
- char *t;
-
- n = 0;
- if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0) {
- safe_atoi(t, &n);
- free(t);
- }
- }
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_execute_append_nice(DBusMessageIter *i, const char *property, void *data) {
- ExecContext *c = data;
- int32_t n;
-
- assert(i);
- assert(property);
- assert(c);
-
- if (c->nice_set)
- n = c->nice;
- else
- n = getpriority(PRIO_PROCESS, 0);
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_execute_append_ioprio(DBusMessageIter *i, const char *property, void *data) {
- ExecContext *c = data;
- int32_t n;
-
- assert(i);
- assert(property);
- assert(c);
-
- if (c->ioprio_set)
- n = c->ioprio;
- else
- n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_execute_append_cpu_sched_policy(DBusMessageIter *i, const char *property, void *data) {
- ExecContext *c = data;
- int32_t n;
-
- assert(i);
- assert(property);
- assert(c);
-
- if (c->cpu_sched_set)
- n = c->cpu_sched_policy;
- else
- n = sched_getscheduler(0);
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_execute_append_cpu_sched_priority(DBusMessageIter *i, const char *property, void *data) {
- ExecContext *c = data;
- int32_t n;
-
- assert(i);
- assert(property);
- assert(c);
-
- if (c->cpu_sched_set)
- n = c->cpu_sched_priority;
- else {
- struct sched_param p;
- n = 0;
-
- zero(p);
- if (sched_getparam(0, &p) >= 0)
- n = p.sched_priority;
- }
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_execute_append_affinity(DBusMessageIter *i, const char *property, void *data) {
- ExecContext *c = data;
- dbus_bool_t b;
- DBusMessageIter sub;
-
- assert(i);
- assert(property);
- assert(c);
-
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "y", &sub))
- return -ENOMEM;
-
- if (c->cpuset)
- b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
- else
- b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &c->cpuset, 0);
-
- if (!b)
- return -ENOMEM;
-
- if (!dbus_message_iter_close_container(i, &sub))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_execute_append_timer_slack_nsec(DBusMessageIter *i, const char *property, void *data) {
- ExecContext *c = data;
- uint64_t u;
-
- assert(i);
- assert(property);
- assert(c);
-
- if (c->timer_slack_nsec != (nsec_t) -1)
- u = (uint64_t) c->timer_slack_nsec;
- else
- u = (uint64_t) prctl(PR_GET_TIMERSLACK);
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_execute_append_capability_bs(DBusMessageIter *i, const char *property, void *data) {
- ExecContext *c = data;
- uint64_t normal, inverted;
-
- assert(i);
- assert(property);
- assert(c);
-
- /* We store this negated internally, to match the kernel, but
- * we expose it normalized. */
-
- normal = *(uint64_t*) data;
- inverted = ~normal;
-
- return bus_property_append_uint64(i, property, &inverted);
-}
-
-int bus_execute_append_capabilities(DBusMessageIter *i, const char *property, void *data) {
- ExecContext *c = data;
- char *t = NULL;
- const char *s;
- dbus_bool_t b;
-
- assert(i);
- assert(property);
- assert(c);
-
- if (c->capabilities)
- s = t = cap_to_text(c->capabilities, NULL);
- else
- s = "";
-
- if (!s)
- return -ENOMEM;
-
- b = dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &s);
-
- if (t)
- cap_free(t);
-
- if (!b)
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_execute_append_rlimits(DBusMessageIter *i, const char *property, void *data) {
- ExecContext *c = data;
- int r;
- uint64_t u;
-
- assert(i);
- assert(property);
- assert(c);
-
- assert_se((r = rlimit_from_string(property)) >= 0);
-
- if (c->rlimit[r])
- u = (uint64_t) c->rlimit[r]->rlim_max;
- else {
- struct rlimit rl;
-
- zero(rl);
- getrlimit(r, &rl);
-
- u = (uint64_t) rl.rlim_max;
- }
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_execute_append_command(DBusMessageIter *i, const char *property, void *data) {
- ExecCommand *c = data;
- DBusMessageIter sub, sub2, sub3;
-
- assert(i);
- assert(property);
-
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sasbttttuii)", &sub))
- return -ENOMEM;
-
- LIST_FOREACH(command, c, c) {
- char **l;
- uint32_t pid;
- int32_t code, status;
- dbus_bool_t b;
-
- if (!c->path)
- continue;
-
- if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &c->path) ||
- !dbus_message_iter_open_container(&sub2, DBUS_TYPE_ARRAY, "s", &sub3))
- return -ENOMEM;
-
- STRV_FOREACH(l, c->argv)
- if (!dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, l))
- return -ENOMEM;
-
- pid = (uint32_t) c->exec_status.pid;
- code = (int32_t) c->exec_status.code;
- status = (int32_t) c->exec_status.status;
-
- b = !!c->ignore;
-
- if (!dbus_message_iter_close_container(&sub2, &sub3) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_BOOLEAN, &b) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.realtime) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.monotonic) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.realtime) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.monotonic) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &pid) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_INT32, &code) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_INT32, &status))
- return -ENOMEM;
-
- if (!dbus_message_iter_close_container(&sub, &sub2))
- return -ENOMEM;
- }
-
- if (!dbus_message_iter_close_container(i, &sub))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_execute_append_syscall_filter(DBusMessageIter *i, const char *property, void *data) {
- ExecContext *c = data;
- dbus_bool_t b;
- DBusMessageIter sub;
-
- assert(i);
- assert(property);
- assert(c);
-
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "u", &sub))
- return -ENOMEM;
-
- if (c->syscall_filter)
- b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_UINT32, &c->syscall_filter, (syscall_max() + 31) >> 4);
- else
- b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_UINT32, &c->syscall_filter, 0);
-
- if (!b)
- return -ENOMEM;
-
- if (!dbus_message_iter_close_container(i, &sub))
- return -ENOMEM;
-
- return 0;
-}
-
-const BusProperty bus_exec_context_properties[] = {
- { "Environment", bus_property_append_strv, "as", offsetof(ExecContext, environment), true },
- { "EnvironmentFiles", bus_execute_append_env_files, "a(sb)", offsetof(ExecContext, environment_files), true },
- { "UMask", bus_property_append_mode, "u", offsetof(ExecContext, umask) },
- { "LimitCPU", bus_execute_append_rlimits, "t", 0 },
- { "LimitFSIZE", bus_execute_append_rlimits, "t", 0 },
- { "LimitDATA", bus_execute_append_rlimits, "t", 0 },
- { "LimitSTACK", bus_execute_append_rlimits, "t", 0 },
- { "LimitCORE", bus_execute_append_rlimits, "t", 0 },
- { "LimitRSS", bus_execute_append_rlimits, "t", 0 },
- { "LimitNOFILE", bus_execute_append_rlimits, "t", 0 },
- { "LimitAS", bus_execute_append_rlimits, "t", 0 },
- { "LimitNPROC", bus_execute_append_rlimits, "t", 0 },
- { "LimitMEMLOCK", bus_execute_append_rlimits, "t", 0 },
- { "LimitLOCKS", bus_execute_append_rlimits, "t", 0 },
- { "LimitSIGPENDING", bus_execute_append_rlimits, "t", 0 },
- { "LimitMSGQUEUE", bus_execute_append_rlimits, "t", 0 },
- { "LimitNICE", bus_execute_append_rlimits, "t", 0 },
- { "LimitRTPRIO", bus_execute_append_rlimits, "t", 0 },
- { "LimitRTTIME", bus_execute_append_rlimits, "t", 0 },
- { "WorkingDirectory", bus_property_append_string, "s", offsetof(ExecContext, working_directory), true },
- { "RootDirectory", bus_property_append_string, "s", offsetof(ExecContext, root_directory), true },
- { "OOMScoreAdjust", bus_execute_append_oom_score_adjust, "i", 0 },
- { "Nice", bus_execute_append_nice, "i", 0 },
- { "IOScheduling", bus_execute_append_ioprio, "i", 0 },
- { "CPUSchedulingPolicy", bus_execute_append_cpu_sched_policy, "i", 0 },
- { "CPUSchedulingPriority", bus_execute_append_cpu_sched_priority, "i", 0 },
- { "CPUAffinity", bus_execute_append_affinity, "ay", 0 },
- { "TimerSlackNSec", bus_execute_append_timer_slack_nsec, "t", 0 },
- { "CPUSchedulingResetOnFork", bus_property_append_bool, "b", offsetof(ExecContext, cpu_sched_reset_on_fork) },
- { "NonBlocking", bus_property_append_bool, "b", offsetof(ExecContext, non_blocking) },
- { "StandardInput", bus_execute_append_input, "s", offsetof(ExecContext, std_input) },
- { "StandardOutput", bus_execute_append_output, "s", offsetof(ExecContext, std_output) },
- { "StandardError", bus_execute_append_output, "s", offsetof(ExecContext, std_error) },
- { "TTYPath", bus_property_append_string, "s", offsetof(ExecContext, tty_path), true },
- { "TTYReset", bus_property_append_bool, "b", offsetof(ExecContext, tty_reset) },
- { "TTYVHangup", bus_property_append_bool, "b", offsetof(ExecContext, tty_vhangup) },
- { "TTYVTDisallocate", bus_property_append_bool, "b", offsetof(ExecContext, tty_vt_disallocate) },
- { "SyslogPriority", bus_property_append_int, "i", offsetof(ExecContext, syslog_priority) },
- { "SyslogIdentifier", bus_property_append_string, "s", offsetof(ExecContext, syslog_identifier), true },
- { "SyslogLevelPrefix", bus_property_append_bool, "b", offsetof(ExecContext, syslog_level_prefix) },
- { "Capabilities", bus_execute_append_capabilities, "s", 0 },
- { "SecureBits", bus_property_append_int, "i", offsetof(ExecContext, secure_bits) },
- { "CapabilityBoundingSet", bus_execute_append_capability_bs, "t", offsetof(ExecContext, capability_bounding_set_drop) },
- { "User", bus_property_append_string, "s", offsetof(ExecContext, user), true },
- { "Group", bus_property_append_string, "s", offsetof(ExecContext, group), true },
- { "SupplementaryGroups", bus_property_append_strv, "as", offsetof(ExecContext, supplementary_groups), true },
- { "TCPWrapName", bus_property_append_string, "s", offsetof(ExecContext, tcpwrap_name), true },
- { "PAMName", bus_property_append_string, "s", offsetof(ExecContext, pam_name), true },
- { "ReadWriteDirectories", bus_property_append_strv, "as", offsetof(ExecContext, read_write_dirs), true },
- { "ReadOnlyDirectories", bus_property_append_strv, "as", offsetof(ExecContext, read_only_dirs), true },
- { "InaccessibleDirectories", bus_property_append_strv, "as", offsetof(ExecContext, inaccessible_dirs), true },
- { "MountFlags", bus_property_append_ul, "t", offsetof(ExecContext, mount_flags) },
- { "PrivateTmp", bus_property_append_bool, "b", offsetof(ExecContext, private_tmp) },
- { "PrivateNetwork", bus_property_append_bool, "b", offsetof(ExecContext, private_network) },
- { "SameProcessGroup", bus_property_append_bool, "b", offsetof(ExecContext, same_pgrp) },
- { "UtmpIdentifier", bus_property_append_string, "s", offsetof(ExecContext, utmp_id), true },
- { "ControlGroupModify", bus_property_append_bool, "b", offsetof(ExecContext, control_group_modify) },
- { "ControlGroupPersistent", bus_property_append_tristate_false, "b", offsetof(ExecContext, control_group_persistent) },
- { "IgnoreSIGPIPE", bus_property_append_bool, "b", offsetof(ExecContext, ignore_sigpipe) },
- { "NoNewPrivileges", bus_property_append_bool, "b", offsetof(ExecContext, no_new_privileges) },
- { "SystemCallFilter", bus_execute_append_syscall_filter, "au", 0 },
- { NULL, }
-};
diff --git a/src/core/dbus-execute.h b/src/core/dbus-execute.h
deleted file mode 100644
index eaa1b73e69..0000000000
--- a/src/core/dbus-execute.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*-*- 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 <dbus/dbus.h>
-
-#include "manager.h"
-#include "dbus-common.h"
-
-#define BUS_EXEC_STATUS_INTERFACE(prefix) \
- " <property name=\"" prefix "StartTimestamp\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"" prefix "StartTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"" prefix "ExitTimestamp\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"" prefix "ExitTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"" prefix "PID\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"" prefix "Code\" type=\"i\" access=\"read\"/>\n" \
- " <property name=\"" prefix "Status\" type=\"i\" access=\"read\"/>\n"
-
-#define BUS_EXEC_CONTEXT_INTERFACE \
- " <property name=\"Environment\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"UMask\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"LimitCPU\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"LimitFSIZE\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"LimitDATA\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"LimitSTACK\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"LimitCORE\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"LimitRSS\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"LimitNOFILE\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"LimitAS\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"LimitNPROC\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"LimitMEMLOCK\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"LimitLOCKS\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"LimitSIGPENDING\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"LimitMSGQUEUE\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"LimitNICE\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"LimitRTPRIO\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"LimitRTTIME\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"WorkingDirectory\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"RootDirectory\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"OOMScoreAdjust\" type=\"i\" access=\"read\"/>\n" \
- " <property name=\"Nice\" type=\"i\" access=\"read\"/>\n" \
- " <property name=\"IOScheduling\" type=\"i\" access=\"read\"/>\n" \
- " <property name=\"CPUSchedulingPolicy\" type=\"i\" access=\"read\"/>\n" \
- " <property name=\"CPUSchedulingPriority\" type=\"i\" access=\"read\"/>\n" \
- " <property name=\"CPUAffinity\" type=\"ay\" access=\"read\"/>\n" \
- " <property name=\"TimerSlackNS\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"CPUSchedulingResetOnFork\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"NonBlocking\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"StandardInput\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"StandardOutput\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"StandardError\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"TTYPath\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"TTYReset\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"TTYVHangup\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"TTYVTDisallocate\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"SyslogPriority\" type=\"i\" access=\"read\"/>\n" \
- " <property name=\"SyslogIdentifier\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"SyslogLevelPrefix\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"Capabilities\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"SecureBits\" type=\"i\" access=\"read\"/>\n" \
- " <property name=\"CapabilityBoundingSet\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"User\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Group\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"SupplementaryGroups\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"TCPWrapName\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"PAMName\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"ReadWriteDirectories\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"ReadOnlyDirectories\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"InaccessibleDirectories\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"MountFlags\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"PrivateTmp\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"SameProcessGroup\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"KillMode\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"KillSignal\" type=\"i\" access=\"read\"/>\n" \
- " <property name=\"UtmpIdentifier\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"ControlGroupModify\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"ControlGroupPersistent\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"PrivateNetwork\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"IgnoreSIGPIPE\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"NoNewPrivileges\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"SystemCallFilter\" type=\"au\" access=\"read\"/>\n"
-
-#define BUS_EXEC_COMMAND_INTERFACE(name) \
- " <property name=\"" name "\" type=\"a(sasbttuii)\" access=\"read\"/>\n"
-
-extern const BusProperty bus_exec_context_properties[];
-
-#define BUS_EXEC_COMMAND_PROPERTY(name, command, indirect) \
- { name, bus_execute_append_command, "a(sasbttttuii)", (command), (indirect), NULL }
-
-int bus_execute_append_output(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_input(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_oom_score_adjust(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_nice(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_ioprio(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_cpu_sched_policy(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_cpu_sched_priority(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_affinity(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_timer_slack_nsec(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_capabilities(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_capability_bs(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_rlimits(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_command(DBusMessageIter *u, const char *property, void *data);
-int bus_execute_append_env_files(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_syscall_filter(DBusMessageIter *i, const char *property, void *data);
diff --git a/src/core/dbus-job.c b/src/core/dbus-job.c
deleted file mode 100644
index fdc1dce177..0000000000
--- a/src/core/dbus-job.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/*-*- 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 <errno.h>
-
-#include "dbus.h"
-#include "log.h"
-#include "dbus-job.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
-
-#define BUS_JOB_INTERFACE \
- " <interface name=\"org.freedesktop.systemd1.Job\">\n" \
- " <method name=\"Cancel\"/>\n" \
- " <property name=\"Id\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"Unit\" type=\"(so)\" access=\"read\"/>\n" \
- " <property name=\"JobType\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"State\" type=\"s\" access=\"read\"/>\n" \
- " </interface>\n"
-
-#define INTROSPECTION \
- DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
- "<node>\n" \
- BUS_JOB_INTERFACE \
- BUS_PROPERTIES_INTERFACE \
- BUS_PEER_INTERFACE \
- BUS_INTROSPECTABLE_INTERFACE \
- "</node>\n"
-
-const char bus_job_interface[] _introspect_("Job") = BUS_JOB_INTERFACE;
-
-#define INTERFACES_LIST \
- BUS_GENERIC_INTERFACES_LIST \
- "org.freedesktop.systemd1.Job\0"
-
-#define INVALIDATING_PROPERTIES \
- "State\0"
-
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_job_append_state, job_state, JobState);
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_job_append_type, job_type, JobType);
-
-static int bus_job_append_unit(DBusMessageIter *i, const char *property, void *data) {
- Job *j = data;
- DBusMessageIter sub;
- char *p;
-
- assert(i);
- assert(property);
- assert(j);
-
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub))
- return -ENOMEM;
-
- p = unit_dbus_path(j->unit);
- if (!p)
- return -ENOMEM;
-
- if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &j->unit->id) ||
- !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &p)) {
- free(p);
- return -ENOMEM;
- }
-
- free(p);
-
- if (!dbus_message_iter_close_container(i, &sub))
- return -ENOMEM;
-
- return 0;
-}
-
-static const BusProperty bus_job_properties[] = {
- { "Id", bus_property_append_uint32, "u", offsetof(Job, id) },
- { "State", bus_job_append_state, "s", offsetof(Job, state) },
- { "JobType", bus_job_append_type, "s", offsetof(Job, type) },
- { "Unit", bus_job_append_unit, "(so)", 0 },
- { NULL, }
-};
-
-static DBusHandlerResult bus_job_message_dispatch(Job *j, DBusConnection *connection, DBusMessage *message) {
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
-
- if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Job", "Cancel")) {
-
- SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "stop");
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
- job_finish_and_invalidate(j, JOB_CANCELED, true);
- } else {
- const BusBoundProperties bps[] = {
- { "org.freedesktop.systemd1.Job", bus_job_properties, j },
- { NULL, }
- };
-
- SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "status");
-
- return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps);
- }
-
- if (!dbus_connection_send(connection, reply, NULL))
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
- return DBUS_HANDLER_RESULT_HANDLED;
-}
-
-static DBusHandlerResult bus_job_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
- Manager *m = data;
- Job *j;
- int r;
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
-
- assert(connection);
- assert(message);
- assert(m);
-
- if (streq(dbus_message_get_path(message), "/org/freedesktop/systemd1/job")) {
- /* Be nice to gdbus and return introspection data for our mid-level paths */
-
- if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
- char *introspection = NULL;
- FILE *f;
- Iterator i;
- size_t size;
-
- SELINUX_ACCESS_CHECK(connection, message, "status");
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- /* We roll our own introspection code here, instead of
- * relying on bus_default_message_handler() because we
- * need to generate our introspection string
- * dynamically. */
-
- f = open_memstream(&introspection, &size);
- if (!f)
- goto oom;
-
- fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
- "<node>\n", f);
-
- fputs(BUS_INTROSPECTABLE_INTERFACE, f);
- fputs(BUS_PEER_INTERFACE, f);
-
- HASHMAP_FOREACH(j, m->jobs, i)
- fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
-
- fputs("</node>\n", f);
-
- if (ferror(f)) {
- fclose(f);
- free(introspection);
- goto oom;
- }
-
- fclose(f);
-
- if (!introspection)
- goto oom;
-
- if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
- free(introspection);
- goto oom;
- }
-
- free(introspection);
-
- if (!dbus_connection_send(connection, reply, NULL))
- goto oom;
-
- return DBUS_HANDLER_RESULT_HANDLED;
- }
-
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- }
-
- r = manager_get_job_from_dbus_path(m, dbus_message_get_path(message), &j);
- if (r == -ENOMEM)
- goto oom;
- if (r == -ENOENT) {
- DBusError e;
-
- dbus_error_init(&e);
- dbus_set_error_const(&e, DBUS_ERROR_UNKNOWN_OBJECT, "Unknown job");
- return bus_send_error_reply(connection, message, &e, r);
- }
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- return bus_job_message_dispatch(j, connection, message);
-
-oom:
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-}
-
-const DBusObjectPathVTable bus_job_vtable = {
- .message_function = bus_job_message_handler
-};
-
-static int job_send_message(Job *j, DBusMessage* (*new_message)(Job *j)) {
- DBusMessage *m = NULL;
- int r;
-
- assert(j);
- assert(new_message);
-
- if (bus_has_subscriber(j->manager) || j->forgot_bus_clients) {
- m = new_message(j);
- if (!m)
- goto oom;
- r = bus_broadcast(j->manager, m);
- dbus_message_unref(m);
- if (r < 0)
- return r;
-
- } else {
- /* If nobody is subscribed, we just send the message
- * to the client(s) which created the job */
- JobBusClient *cl;
- assert(j->bus_client_list);
- LIST_FOREACH(client, cl, j->bus_client_list) {
- assert(cl->bus);
-
- m = new_message(j);
- if (!m)
- goto oom;
-
- if (!dbus_message_set_destination(m, cl->name))
- goto oom;
-
- if (!dbus_connection_send(cl->bus, m, NULL))
- goto oom;
-
- dbus_message_unref(m);
- m = NULL;
- }
- }
-
- return 0;
-oom:
- if (m)
- dbus_message_unref(m);
- return -ENOMEM;
-}
-
-static DBusMessage* new_change_signal_message(Job *j) {
- DBusMessage *m = NULL;
- char *p = NULL;
-
- p = job_dbus_path(j);
- if (!p)
- goto oom;
-
- if (j->sent_dbus_new_signal) {
- /* Send a properties changed signal */
- m = bus_properties_changed_new(p, "org.freedesktop.systemd1.Job", INVALIDATING_PROPERTIES);
- if (!m)
- goto oom;
-
- } else {
- /* Send a new signal */
-
- m = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "JobNew");
- if (!m)
- goto oom;
-
- if (!dbus_message_append_args(m,
- DBUS_TYPE_UINT32, &j->id,
- DBUS_TYPE_OBJECT_PATH, &p,
- DBUS_TYPE_STRING, &j->unit->id,
- DBUS_TYPE_INVALID))
- goto oom;
- }
-
- return m;
-
-oom:
- if (m)
- dbus_message_unref(m);
- free(p);
- return NULL;
-}
-
-static DBusMessage* new_removed_signal_message(Job *j) {
- DBusMessage *m = NULL;
- char *p = NULL;
- const char *r;
-
- p = job_dbus_path(j);
- if (!p)
- goto oom;
-
- m = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "JobRemoved");
- if (!m)
- goto oom;
-
- r = job_result_to_string(j->result);
-
- if (!dbus_message_append_args(m,
- DBUS_TYPE_UINT32, &j->id,
- DBUS_TYPE_OBJECT_PATH, &p,
- DBUS_TYPE_STRING, &j->unit->id,
- DBUS_TYPE_STRING, &r,
- DBUS_TYPE_INVALID))
- goto oom;
-
- return m;
-
-oom:
- if (m)
- dbus_message_unref(m);
- free(p);
- return NULL;
-}
-
-void bus_job_send_change_signal(Job *j) {
- assert(j);
-
- if (j->in_dbus_queue) {
- LIST_REMOVE(Job, dbus_queue, j->manager->dbus_job_queue, j);
- j->in_dbus_queue = false;
- }
-
- if (!bus_has_subscriber(j->manager) && !j->bus_client_list && !j->forgot_bus_clients) {
- j->sent_dbus_new_signal = true;
- return;
- }
-
- if (job_send_message(j, new_change_signal_message) < 0)
- goto oom;
-
- j->sent_dbus_new_signal = true;
-
- return;
-
-oom:
- log_error("Failed to allocate job change signal.");
-}
-
-void bus_job_send_removed_signal(Job *j) {
- assert(j);
-
- if (!bus_has_subscriber(j->manager) && !j->bus_client_list && !j->forgot_bus_clients)
- return;
-
- if (!j->sent_dbus_new_signal)
- bus_job_send_change_signal(j);
-
- if (job_send_message(j, new_removed_signal_message) < 0)
- goto oom;
-
- return;
-
-oom:
- log_error("Failed to allocate job remove signal.");
-}
diff --git a/src/core/dbus-job.h b/src/core/dbus-job.h
deleted file mode 100644
index a1b928fb16..0000000000
--- a/src/core/dbus-job.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*-*- 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 <dbus/dbus.h>
-
-#include "job.h"
-
-void bus_job_send_change_signal(Job *j);
-void bus_job_send_removed_signal(Job *j);
-
-extern const DBusObjectPathVTable bus_job_vtable;
-
-extern const char bus_job_interface[];
diff --git a/src/core/dbus-kill.c b/src/core/dbus-kill.c
deleted file mode 100644
index 165f63074b..0000000000
--- a/src/core/dbus-kill.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <dbus/dbus.h>
-
-#include "dbus-kill.h"
-#include "dbus-common.h"
-
-DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_kill_append_mode, kill_mode, KillMode);
-
-const BusProperty bus_kill_context_properties[] = {
- { "KillMode", bus_kill_append_mode, "s", offsetof(KillContext, kill_mode) },
- { "KillSignal", bus_property_append_int, "i", offsetof(KillContext, kill_signal) },
- { "SendSIGKILL", bus_property_append_bool, "b", offsetof(KillContext, send_sigkill) },
- { NULL, }
-};
diff --git a/src/core/dbus-kill.h b/src/core/dbus-kill.h
deleted file mode 100644
index 238fbd36d6..0000000000
--- a/src/core/dbus-kill.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <dbus/dbus.h>
-
-#include "manager.h"
-#include "dbus-common.h"
-
-#define BUS_KILL_CONTEXT_INTERFACE \
- " <property name=\"KillMode\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"KillSignal\" type=\"i\" access=\"read\"/>\n" \
- " <property name=\"SendSIGKILL\" type=\"b\" access=\"read\"/>\n"
-
-#define BUS_KILL_COMMAND_INTERFACE(name) \
- " <property name=\"" name "\" type=\"a(sasbttuii)\" access=\"read\"/>\n"
-
-extern const BusProperty bus_kill_context_properties[];
-
-int bus_kill_append_mode(DBusMessageIter *i, const char *property, void *data);
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
deleted file mode 100644
index 2010241e6a..0000000000
--- a/src/core/dbus-manager.c
+++ /dev/null
@@ -1,1685 +0,0 @@
-/*-*- 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 <errno.h>
-#include <unistd.h>
-
-#include "dbus.h"
-#include "log.h"
-#include "dbus-manager.h"
-#include "strv.h"
-#include "bus-errors.h"
-#include "build.h"
-#include "dbus-common.h"
-#include "install.h"
-#include "selinux-access.h"
-#include "watchdog.h"
-#include "hwclock.h"
-#include "path-util.h"
-#include "dbus-unit.h"
-#include "virt.h"
-
-#define BUS_MANAGER_INTERFACE_BEGIN \
- " <interface name=\"org.freedesktop.systemd1.Manager\">\n"
-
-#define BUS_MANAGER_INTERFACE_METHODS \
- " <method name=\"GetUnit\">\n" \
- " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"GetUnitByPID\">\n" \
- " <arg name=\"pid\" type=\"u\" direction=\"in\"/>\n" \
- " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"LoadUnit\">\n" \
- " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"StartUnit\">\n" \
- " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"StartUnitReplace\">\n" \
- " <arg name=\"old_unit\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"new_unit\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"StopUnit\">\n" \
- " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"ReloadUnit\">\n" \
- " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"RestartUnit\">\n" \
- " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"TryRestartUnit\">\n" \
- " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"ReloadOrRestartUnit\">\n" \
- " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"ReloadOrTryRestartUnit\">\n" \
- " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"KillUnit\">\n" \
- " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"who\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"signal\" type=\"i\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"ResetFailedUnit\">\n" \
- " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"GetJob\">\n" \
- " <arg name=\"id\" type=\"u\" direction=\"in\"/>\n" \
- " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"ClearJobs\"/>\n" \
- " <method name=\"ResetFailed\"/>\n" \
- " <method name=\"ListUnits\">\n" \
- " <arg name=\"units\" type=\"a(ssssssouso)\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"ListJobs\">\n" \
- " <arg name=\"jobs\" type=\"a(usssoo)\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"Subscribe\"/>\n" \
- " <method name=\"Unsubscribe\"/>\n" \
- " <method name=\"Dump\">\n" \
- " <arg name=\"dump\" type=\"s\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"CreateSnapshot\">\n" \
- " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"cleanup\" type=\"b\" direction=\"in\"/>\n" \
- " <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"Reload\"/>\n" \
- " <method name=\"Reexecute\"/>\n" \
- " <method name=\"Exit\"/>\n" \
- " <method name=\"Reboot\"/>\n" \
- " <method name=\"PowerOff\"/>\n" \
- " <method name=\"Halt\"/>\n" \
- " <method name=\"KExec\"/>\n" \
- " <method name=\"SwitchRoot\">\n" \
- " <arg name=\"new_root\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"init\" type=\"s\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"SetEnvironment\">\n" \
- " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"UnsetEnvironment\">\n" \
- " <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"UnsetAndSetEnvironment\">\n" \
- " <arg name=\"unset\" type=\"as\" direction=\"in\"/>\n" \
- " <arg name=\"set\" type=\"as\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"ListUnitFiles\">\n" \
- " <arg name=\"files\" type=\"a(ss)\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"GetUnitFileState\">\n" \
- " <arg name=\"file\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"state\" type=\"s\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"EnableUnitFiles\">\n" \
- " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
- " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
- " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
- " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
- " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"DisableUnitFiles\">\n" \
- " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
- " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
- " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"ReenableUnitFiles\">\n" \
- " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
- " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
- " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
- " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
- " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"LinkUnitFiles\">\n" \
- " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
- " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
- " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
- " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"PresetUnitFiles\">\n" \
- " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
- " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
- " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
- " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
- " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"MaskUnitFiles\">\n" \
- " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
- " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
- " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
- " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"UnmaskUnitFiles\">\n" \
- " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
- " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
- " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
- " </method>\n"
-
-#define BUS_MANAGER_INTERFACE_SIGNALS \
- " <signal name=\"UnitNew\">\n" \
- " <arg name=\"id\" type=\"s\"/>\n" \
- " <arg name=\"unit\" type=\"o\"/>\n" \
- " </signal>\n" \
- " <signal name=\"UnitRemoved\">\n" \
- " <arg name=\"id\" type=\"s\"/>\n" \
- " <arg name=\"unit\" type=\"o\"/>\n" \
- " </signal>\n" \
- " <signal name=\"JobNew\">\n" \
- " <arg name=\"id\" type=\"u\"/>\n" \
- " <arg name=\"job\" type=\"o\"/>\n" \
- " <arg name=\"unit\" type=\"s\"/>\n" \
- " </signal>\n" \
- " <signal name=\"JobRemoved\">\n" \
- " <arg name=\"id\" type=\"u\"/>\n" \
- " <arg name=\"job\" type=\"o\"/>\n" \
- " <arg name=\"unit\" type=\"s\"/>\n" \
- " <arg name=\"result\" type=\"s\"/>\n" \
- " </signal>" \
- " <signal name=\"StartupFinished\">\n" \
- " <arg name=\"firmware\" type=\"t\"/>\n" \
- " <arg name=\"loader\" type=\"t\"/>\n" \
- " <arg name=\"kernel\" type=\"t\"/>\n" \
- " <arg name=\"initrd\" type=\"t\"/>\n" \
- " <arg name=\"userspace\" type=\"t\"/>\n" \
- " <arg name=\"total\" type=\"t\"/>\n" \
- " </signal>" \
- " <signal name=\"UnitFilesChanged\"/>\n"
-
-#define BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
- " <property name=\"Version\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Distribution\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Features\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Tainted\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"FirmwareTimestamp\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"FirmwareTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"LoaderTimestamp\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"LoaderTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"KernelTimestamp\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"KernelTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"InitRDTimestamp\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"InitRDTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"UserspaceTimestamp\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"UserspaceTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"FinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"LogLevel\" type=\"s\" access=\"readwrite\"/>\n" \
- " <property name=\"LogTarget\" type=\"s\" access=\"readwrite\"/>\n" \
- " <property name=\"NNames\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"NJobs\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"NInstalledJobs\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"NFailedJobs\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"Progress\" type=\"d\" access=\"read\"/>\n" \
- " <property name=\"Environment\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"ConfirmSpawn\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"ShowStatus\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"UnitPath\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"DefaultControllers\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"DefaultStandardOutput\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"DefaultStandardError\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"RuntimeWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n" \
- " <property name=\"ShutdownWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n" \
- " <property name=\"Virtualization\" type=\"s\" access=\"read\"/>\n"
-
-#define BUS_MANAGER_INTERFACE_END \
- " </interface>\n"
-
-#define BUS_MANAGER_INTERFACE \
- BUS_MANAGER_INTERFACE_BEGIN \
- BUS_MANAGER_INTERFACE_METHODS \
- BUS_MANAGER_INTERFACE_SIGNALS \
- BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
- BUS_MANAGER_INTERFACE_END
-
-#define INTROSPECTION_BEGIN \
- DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
- "<node>\n" \
- BUS_MANAGER_INTERFACE \
- BUS_PROPERTIES_INTERFACE \
- BUS_PEER_INTERFACE \
- BUS_INTROSPECTABLE_INTERFACE
-
-#define INTROSPECTION_END \
- "</node>\n"
-
-#define INTERFACES_LIST \
- BUS_GENERIC_INTERFACES_LIST \
- "org.freedesktop.systemd1.Manager\0"
-
-const char bus_manager_interface[] _introspect_("Manager") = BUS_MANAGER_INTERFACE;
-
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_exec_output, exec_output, ExecOutput);
-
-static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, void *data) {
- const char *t;
- Manager *m = data;
- char buf[LINE_MAX] = "", *e = buf, *p = NULL;
-
- assert(i);
- assert(property);
- assert(m);
-
- if (m->taint_usr)
- e = stpcpy(e, "split-usr:");
-
- if (readlink_malloc("/etc/mtab", &p) < 0)
- e = stpcpy(e, "mtab-not-symlink:");
- else
- free(p);
-
- if (access("/proc/cgroups", F_OK) < 0)
- e = stpcpy(e, "cgroups-missing:");
-
- if (hwclock_is_localtime() > 0)
- e = stpcpy(e, "local-hwclock:");
-
- /* remove the last ':' */
- if (e != buf)
- e[-1] = 0;
-
- t = buf;
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_manager_append_log_target(DBusMessageIter *i, const char *property, void *data) {
- const char *t;
-
- assert(i);
- assert(property);
-
- t = log_target_to_string(log_get_target());
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_manager_set_log_target(DBusMessageIter *i, const char *property, void *data) {
- const char *t;
-
- assert(i);
- assert(property);
-
- dbus_message_iter_get_basic(i, &t);
-
- return log_set_target_from_string(t);
-}
-
-static int bus_manager_append_log_level(DBusMessageIter *i, const char *property, void *data) {
- char *t;
- int r;
-
- assert(i);
- assert(property);
-
- r = log_level_to_string_alloc(log_get_max_level(), &t);
- if (r < 0)
- return r;
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
- r = -ENOMEM;
-
- free(t);
- return r;
-}
-
-static int bus_manager_set_log_level(DBusMessageIter *i, const char *property, void *data) {
- const char *t;
-
- assert(i);
- assert(property);
-
- dbus_message_iter_get_basic(i, &t);
-
- return log_set_max_level_from_string(t);
-}
-
-static int bus_manager_append_n_names(DBusMessageIter *i, const char *property, void *data) {
- Manager *m = data;
- uint32_t u;
-
- assert(i);
- assert(property);
- assert(m);
-
- u = hashmap_size(m->units);
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_manager_append_n_jobs(DBusMessageIter *i, const char *property, void *data) {
- Manager *m = data;
- uint32_t u;
-
- assert(i);
- assert(property);
- assert(m);
-
- u = hashmap_size(m->jobs);
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_manager_append_progress(DBusMessageIter *i, const char *property, void *data) {
- double d;
- Manager *m = data;
-
- assert(i);
- assert(property);
- assert(m);
-
- if (dual_timestamp_is_set(&m->finish_timestamp))
- d = 1.0;
- else
- d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_DOUBLE, &d))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_manager_append_virt(DBusMessageIter *i, const char *property, void *data) {
- Manager *m = data;
- const char *id = "";
-
- assert(i);
- assert(property);
- assert(m);
-
- detect_virtualization(&id);
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &id))
- return -ENOMEM;
-
- return 0;
-}
-
-static DBusMessage *message_from_file_changes(
- DBusMessage *m,
- UnitFileChange *changes,
- unsigned n_changes,
- int carries_install_info) {
-
- DBusMessageIter iter, sub, sub2;
- DBusMessage *reply;
- unsigned i;
-
- reply = dbus_message_new_method_return(m);
- if (!reply)
- return NULL;
-
- dbus_message_iter_init_append(reply, &iter);
-
- if (carries_install_info >= 0) {
- dbus_bool_t b;
-
- b = !!carries_install_info;
- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b))
- goto oom;
- }
-
- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
- goto oom;
-
- for (i = 0; i < n_changes; i++) {
- const char *type, *path, *source;
-
- type = unit_file_change_type_to_string(changes[i].type);
- path = strempty(changes[i].path);
- source = strempty(changes[i].source);
-
- if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &path) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &source) ||
- !dbus_message_iter_close_container(&sub, &sub2))
- goto oom;
- }
-
- if (!dbus_message_iter_close_container(&iter, &sub))
- goto oom;
-
- return reply;
-
-oom:
- dbus_message_unref(reply);
- return NULL;
-}
-
-static int bus_manager_send_unit_files_changed(Manager *m) {
- DBusMessage *s;
- int r;
-
- s = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
- if (!s)
- return -ENOMEM;
-
- r = bus_broadcast(m, s);
- dbus_message_unref(s);
-
- return r;
-}
-
-static int bus_manager_set_runtime_watchdog_usec(DBusMessageIter *i, const char *property, void *data) {
- uint64_t *t = data;
-
- assert(i);
- assert(property);
-
- dbus_message_iter_get_basic(i, t);
-
- return watchdog_set_timeout(t);
-}
-
-static const char systemd_property_string[] =
- PACKAGE_STRING "\0"
- DISTRIBUTION "\0"
- SYSTEMD_FEATURES;
-
-static const BusProperty bus_systemd_properties[] = {
- { "Version", bus_property_append_string, "s", 0 },
- { "Distribution", bus_property_append_string, "s", sizeof(PACKAGE_STRING) },
- { "Features", bus_property_append_string, "s", sizeof(PACKAGE_STRING) + sizeof(DISTRIBUTION) },
- { NULL, }
-};
-
-static const BusProperty bus_manager_properties[] = {
- { "Tainted", bus_manager_append_tainted, "s", 0 },
- { "FirmwareTimestamp", bus_property_append_uint64, "t", offsetof(Manager, firmware_timestamp.realtime) },
- { "FirmwareTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, firmware_timestamp.monotonic) },
- { "LoaderTimestamp", bus_property_append_uint64, "t", offsetof(Manager, loader_timestamp.realtime) },
- { "LoaderTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, loader_timestamp.monotonic) },
- { "KernelTimestamp", bus_property_append_uint64, "t", offsetof(Manager, kernel_timestamp.realtime) },
- { "KernelTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, kernel_timestamp.monotonic) },
- { "InitRDTimestamp", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.realtime) },
- { "InitRDTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.monotonic) },
- { "UserspaceTimestamp", bus_property_append_uint64, "t", offsetof(Manager, userspace_timestamp.realtime) },
- { "UserspaceTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, userspace_timestamp.monotonic) },
- { "FinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.realtime) },
- { "FinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.monotonic) },
- { "LogLevel", bus_manager_append_log_level, "s", 0, false, bus_manager_set_log_level },
- { "LogTarget", bus_manager_append_log_target, "s", 0, false, bus_manager_set_log_target },
- { "NNames", bus_manager_append_n_names, "u", 0 },
- { "NJobs", bus_manager_append_n_jobs, "u", 0 },
- { "NInstalledJobs", bus_property_append_uint32, "u", offsetof(Manager, n_installed_jobs) },
- { "NFailedJobs", bus_property_append_uint32, "u", offsetof(Manager, n_failed_jobs) },
- { "Progress", bus_manager_append_progress, "d", 0 },
- { "Environment", bus_property_append_strv, "as", offsetof(Manager, environment), true },
- { "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) },
- { "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) },
- { "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true },
- { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_hierarchy), true },
- { "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true },
- { "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) },
- { "DefaultStandardError", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_error) },
- { "RuntimeWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, runtime_watchdog), false, bus_manager_set_runtime_watchdog_usec },
- { "ShutdownWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, shutdown_watchdog), false, bus_property_set_usec },
- { "Virtualization", bus_manager_append_virt, "s", 0, },
- { NULL, }
-};
-
-static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- _cleanup_free_ char * path = NULL;
- Manager *m = data;
- int r;
- DBusError error;
- JobType job_type = _JOB_TYPE_INVALID;
- bool reload_if_possible = false;
- const char *member;
-
- assert(connection);
- assert(message);
- assert(m);
-
- dbus_error_init(&error);
-
- member = dbus_message_get_member(message);
-
- if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
- const char *name;
- Unit *u;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- u = manager_get_unit(m, name);
- if (!u) {
- dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
- return bus_send_error_reply(connection, message, &error, -ENOENT);
- }
-
- SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- path = unit_dbus_path(u);
- if (!path)
- goto oom;
-
- if (!dbus_message_append_args(
- reply,
- DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID))
- goto oom;
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitByPID")) {
- Unit *u;
- uint32_t pid;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_UINT32, &pid,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- u = cgroup_unit_by_pid(m, (pid_t) pid);
- if (!u) {
- dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
- return bus_send_error_reply(connection, message, &error, -ENOENT);
- }
-
- SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- path = unit_dbus_path(u);
- if (!path)
- goto oom;
-
- if (!dbus_message_append_args(
- reply,
- DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID))
- goto oom;
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) {
- const char *name;
- Unit *u;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- r = manager_load_unit(m, name, NULL, &error, &u);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- path = unit_dbus_path(u);
- if (!path)
- goto oom;
-
- if (!dbus_message_append_args(
- reply,
- DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID))
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
- job_type = JOB_START;
- else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
- job_type = JOB_START;
- else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
- job_type = JOB_STOP;
- else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
- job_type = JOB_RELOAD;
- else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RestartUnit"))
- job_type = JOB_RESTART;
- else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "TryRestartUnit"))
- job_type = JOB_TRY_RESTART;
- else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrRestartUnit")) {
- reload_if_possible = true;
- job_type = JOB_RESTART;
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
- reload_if_possible = true;
- job_type = JOB_TRY_RESTART;
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
- const char *name, *swho;
- int32_t signo;
- Unit *u;
- KillWho who;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_STRING, &swho,
- DBUS_TYPE_INT32, &signo,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- if (isempty(swho))
- who = KILL_ALL;
- else {
- who = kill_who_from_string(swho);
- if (who < 0)
- return bus_send_error_reply(connection, message, &error, -EINVAL);
- }
-
- if (signo <= 0 || signo >= _NSIG)
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- u = manager_get_unit(m, name);
- if (!u) {
- dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
- return bus_send_error_reply(connection, message, &error, -ENOENT);
- }
-
- SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
-
- r = unit_kill(u, who, signo, &error);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- if (!(reply = dbus_message_new_method_return(message)))
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
- uint32_t id;
- Job *j;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_UINT32, &id,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- j = manager_get_job(m, id);
- if (!j) {
- dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
- return bus_send_error_reply(connection, message, &error, -ENOENT);
- }
-
- SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "status");
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- path = job_dbus_path(j);
- if (!path)
- goto oom;
-
- if (!dbus_message_append_args(
- reply,
- DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID))
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
-
- SELINUX_ACCESS_CHECK(connection, message, "reboot");
-
- manager_clear_jobs(m);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
-
- SELINUX_ACCESS_CHECK(connection, message, "reload");
-
- manager_reset_failed(m);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
- const char *name;
- Unit *u;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- u = manager_get_unit(m, name);
- if (!u) {
- dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
- return bus_send_error_reply(connection, message, &error, -ENOENT);
- }
-
- SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "reload");
-
- unit_reset_failed(u);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
- DBusMessageIter iter, sub;
- Iterator i;
- Unit *u;
- const char *k;
-
- SELINUX_ACCESS_CHECK(connection, message, "status");
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- dbus_message_iter_init_append(reply, &iter);
-
- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
- goto oom;
-
- HASHMAP_FOREACH_KEY(u, k, m->units, i) {
- char *u_path, *j_path;
- const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
- DBusMessageIter sub2;
- uint32_t job_id;
- Unit *f;
-
- if (k != u->id)
- continue;
-
- if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
- goto oom;
-
- description = unit_description(u);
- load_state = unit_load_state_to_string(u->load_state);
- active_state = unit_active_state_to_string(unit_active_state(u));
- sub_state = unit_sub_state_to_string(u);
-
- f = unit_following(u);
- following = f ? f->id : "";
-
- u_path = unit_dbus_path(u);
- if (!u_path)
- goto oom;
-
- if (u->job) {
- job_id = (uint32_t) u->job->id;
-
- if (!(j_path = job_dbus_path(u->job))) {
- free(u_path);
- goto oom;
- }
-
- sjob_type = job_type_to_string(u->job->type);
- } else {
- job_id = 0;
- j_path = u_path;
- sjob_type = "";
- }
-
- if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
- free(u_path);
- if (u->job)
- free(j_path);
- goto oom;
- }
-
- free(u_path);
- if (u->job)
- free(j_path);
-
- if (!dbus_message_iter_close_container(&sub, &sub2))
- goto oom;
- }
-
- if (!dbus_message_iter_close_container(&iter, &sub))
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
- DBusMessageIter iter, sub;
- Iterator i;
- Job *j;
-
- SELINUX_ACCESS_CHECK(connection, message, "status");
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- dbus_message_iter_init_append(reply, &iter);
-
- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
- goto oom;
-
- HASHMAP_FOREACH(j, m->jobs, i) {
- char *u_path, *j_path;
- const char *state, *type;
- uint32_t id;
- DBusMessageIter sub2;
-
- if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
- goto oom;
-
- id = (uint32_t) j->id;
- state = job_state_to_string(j->state);
- type = job_type_to_string(j->type);
-
- j_path = job_dbus_path(j);
- if (!j_path)
- goto oom;
-
- u_path = unit_dbus_path(j->unit);
- if (!u_path) {
- free(j_path);
- goto oom;
- }
-
- if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
- free(j_path);
- free(u_path);
- goto oom;
- }
-
- free(j_path);
- free(u_path);
-
- if (!dbus_message_iter_close_container(&sub, &sub2))
- goto oom;
- }
-
- if (!dbus_message_iter_close_container(&iter, &sub))
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
- char *client;
- Set *s;
-
- SELINUX_ACCESS_CHECK(connection, message, "status");
-
- s = BUS_CONNECTION_SUBSCRIBED(m, connection);
- if (!s) {
- s = set_new(string_hash_func, string_compare_func);
- if (!s)
- goto oom;
-
- if (!dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL)) {
- set_free(s);
- goto oom;
- }
- }
-
- client = strdup(bus_message_get_sender_with_fallback(message));
- if (!client)
- goto oom;
-
- r = set_put(s, client);
- if (r < 0) {
- free(client);
- return bus_send_error_reply(connection, message, NULL, r);
- }
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
- char *client;
-
- SELINUX_ACCESS_CHECK(connection, message, "status");
-
- client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) bus_message_get_sender_with_fallback(message));
- if (!client) {
- dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
- return bus_send_error_reply(connection, message, &error, -ENOENT);
- }
-
- free(client);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
- FILE *f;
- char *dump = NULL;
- size_t size;
-
- SELINUX_ACCESS_CHECK(connection, message, "status");
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- f = open_memstream(&dump, &size);
- if (!f)
- goto oom;
-
- manager_dump_units(m, f, NULL);
- manager_dump_jobs(m, f, NULL);
-
- if (ferror(f)) {
- fclose(f);
- free(dump);
- goto oom;
- }
-
- fclose(f);
-
- if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
- free(dump);
- goto oom;
- }
-
- free(dump);
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
- const char *name;
- dbus_bool_t cleanup;
- Snapshot *s;
-
- SELINUX_ACCESS_CHECK(connection, message, "start");
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_BOOLEAN, &cleanup,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- if (isempty(name))
- name = NULL;
-
- r = snapshot_create(m, name, cleanup, &error, &s);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- path = unit_dbus_path(UNIT(s));
- if (!path)
- goto oom;
-
- if (!dbus_message_append_args(
- reply,
- DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID))
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
- char *introspection = NULL;
- FILE *f;
- Iterator i;
- Unit *u;
- Job *j;
- const char *k;
- size_t size;
-
- SELINUX_ACCESS_CHECK(connection, message, "status");
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- /* We roll our own introspection code here, instead of
- * relying on bus_default_message_handler() because we
- * need to generate our introspection string
- * dynamically. */
-
- f = open_memstream(&introspection, &size);
- if (!f)
- goto oom;
-
- fputs(INTROSPECTION_BEGIN, f);
-
- HASHMAP_FOREACH_KEY(u, k, m->units, i) {
- char *p;
-
- if (k != u->id)
- continue;
-
- p = bus_path_escape(k);
- if (!p) {
- fclose(f);
- free(introspection);
- goto oom;
- }
-
- fprintf(f, "<node name=\"unit/%s\"/>", p);
- free(p);
- }
-
- HASHMAP_FOREACH(j, m->jobs, i)
- fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
-
- fputs(INTROSPECTION_END, f);
-
- if (ferror(f)) {
- fclose(f);
- free(introspection);
- goto oom;
- }
-
- fclose(f);
-
- if (!introspection)
- goto oom;
-
- if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
- free(introspection);
- goto oom;
- }
-
- free(introspection);
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
-
- SELINUX_ACCESS_CHECK(connection, message, "reload");
-
- assert(!m->queued_message);
-
- /* Instead of sending the reply back right away, we
- * just remember that we need to and then send it
- * after the reload is finished. That way the caller
- * knows when the reload finished. */
-
- m->queued_message = dbus_message_new_method_return(message);
- if (!m->queued_message)
- goto oom;
-
- m->queued_message_connection = connection;
- m->exit_code = MANAGER_RELOAD;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
-
- SELINUX_ACCESS_CHECK(connection, message, "reload");
-
- /* We don't send a reply back here, the client should
- * just wait for us disconnecting. */
-
- m->exit_code = MANAGER_REEXECUTE;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
-
- SELINUX_ACCESS_CHECK(connection, message, "halt");
-
- if (m->running_as == SYSTEMD_SYSTEM) {
- dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
- return bus_send_error_reply(connection, message, &error, -ENOTSUP);
- }
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- m->exit_code = MANAGER_EXIT;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
-
- SELINUX_ACCESS_CHECK(connection, message, "reboot");
-
- if (m->running_as != SYSTEMD_SYSTEM) {
- dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
- return bus_send_error_reply(connection, message, &error, -ENOTSUP);
- }
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- m->exit_code = MANAGER_REBOOT;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
-
- SELINUX_ACCESS_CHECK(connection, message, "halt");
-
- if (m->running_as != SYSTEMD_SYSTEM) {
- dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
- return bus_send_error_reply(connection, message, &error, -ENOTSUP);
- }
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- m->exit_code = MANAGER_POWEROFF;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
-
- SELINUX_ACCESS_CHECK(connection, message, "halt");
-
- if (m->running_as != SYSTEMD_SYSTEM) {
- dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
- return bus_send_error_reply(connection, message, &error, -ENOTSUP);
- }
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- m->exit_code = MANAGER_HALT;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
-
- SELINUX_ACCESS_CHECK(connection, message, "reboot");
-
- if (m->running_as != SYSTEMD_SYSTEM) {
- dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
- return bus_send_error_reply(connection, message, &error, -ENOTSUP);
- }
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- m->exit_code = MANAGER_KEXEC;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SwitchRoot")) {
- const char *switch_root, *switch_root_init;
- char *u, *v;
- int k;
-
- SELINUX_ACCESS_CHECK(connection, message, "reboot");
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &switch_root,
- DBUS_TYPE_STRING, &switch_root_init,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- if (path_equal(switch_root, "/") || !path_is_absolute(switch_root))
- return bus_send_error_reply(connection, message, NULL, -EINVAL);
-
- if (!isempty(switch_root_init) && !path_is_absolute(switch_root_init))
- return bus_send_error_reply(connection, message, NULL, -EINVAL);
-
- if (m->running_as != SYSTEMD_SYSTEM) {
- dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Switching root is only supported for system managers.");
- return bus_send_error_reply(connection, message, &error, -ENOTSUP);
- }
-
- /* Safety check */
- if (isempty(switch_root_init))
- k = access(switch_root, F_OK);
- else {
- char *p;
-
- p = strjoin(switch_root, "/", switch_root_init, NULL);
- if (!p)
- goto oom;
-
- k = access(p, X_OK);
- free(p);
- }
- if (k < 0)
- return bus_send_error_reply(connection, message, NULL, -errno);
-
- u = strdup(switch_root);
- if (!u)
- goto oom;
-
- if (!isempty(switch_root_init)) {
- v = strdup(switch_root_init);
- if (!v) {
- free(u);
- goto oom;
- }
- } else
- v = NULL;
-
- free(m->switch_root);
- free(m->switch_root_init);
- m->switch_root = u;
- m->switch_root_init = v;
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- m->exit_code = MANAGER_SWITCH_ROOT;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
- char **l = NULL, **e = NULL;
-
- SELINUX_ACCESS_CHECK(connection, message, "reboot");
-
- r = bus_parse_strv(message, &l);
- if (r == -ENOMEM)
- goto oom;
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- e = strv_env_merge(2, m->environment, l);
- strv_free(l);
- if (!e)
- goto oom;
-
- reply = dbus_message_new_method_return(message);
- if (!reply) {
- strv_free(e);
- goto oom;
- }
-
- strv_free(m->environment);
- m->environment = e;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
- char **l = NULL, **e = NULL;
-
- SELINUX_ACCESS_CHECK(connection, message, "reboot");
-
- r = bus_parse_strv(message, &l);
- if (r == -ENOMEM)
- goto oom;
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- e = strv_env_delete(m->environment, 1, l);
- strv_free(l);
-
- if (!e)
- goto oom;
-
- if (!(reply = dbus_message_new_method_return(message))) {
- strv_free(e);
- goto oom;
- }
-
- strv_free(m->environment);
- m->environment = e;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
- char **l_set = NULL, **l_unset = NULL, **e = NULL, **f = NULL;
- DBusMessageIter iter;
-
- SELINUX_ACCESS_CHECK(connection, message, "reboot");
-
- if (!dbus_message_iter_init(message, &iter))
- goto oom;
-
- r = bus_parse_strv_iter(&iter, &l_unset);
- if (r == -ENOMEM)
- goto oom;
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- if (!dbus_message_iter_next(&iter)) {
- strv_free(l_unset);
- return bus_send_error_reply(connection, message, NULL, -EINVAL);
- }
-
- r = bus_parse_strv_iter(&iter, &l_set);
- if (r < 0) {
- strv_free(l_unset);
- if (r == -ENOMEM)
- goto oom;
-
- return bus_send_error_reply(connection, message, NULL, r);
- }
-
- e = strv_env_delete(m->environment, 1, l_unset);
- strv_free(l_unset);
-
- if (!e) {
- strv_free(l_set);
- goto oom;
- }
-
- f = strv_env_merge(2, e, l_set);
- strv_free(l_set);
- strv_free(e);
-
- if (!f)
- goto oom;
-
- if (!(reply = dbus_message_new_method_return(message))) {
- strv_free(f);
- goto oom;
- }
-
- strv_free(m->environment);
- m->environment = f;
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
- DBusMessageIter iter, sub, sub2;
- Hashmap *h;
- Iterator i;
- UnitFileList *item;
-
- SELINUX_ACCESS_CHECK(connection, message, "status");
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- h = hashmap_new(string_hash_func, string_compare_func);
- if (!h)
- goto oom;
-
- r = unit_file_get_list(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
- if (r < 0) {
- unit_file_list_free(h);
- dbus_message_unref(reply);
- return bus_send_error_reply(connection, message, NULL, r);
- }
-
- dbus_message_iter_init_append(reply, &iter);
-
- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
- unit_file_list_free(h);
- goto oom;
- }
-
- HASHMAP_FOREACH(item, h, i) {
- const char *state;
-
- state = unit_file_state_to_string(item->state);
- assert(state);
-
- if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
- !dbus_message_iter_close_container(&sub, &sub2)) {
- unit_file_list_free(h);
- goto oom;
- }
- }
-
- unit_file_list_free(h);
-
- if (!dbus_message_iter_close_container(&iter, &sub))
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
- const char *name;
- UnitFileState state;
- const char *s;
-
- SELINUX_ACCESS_CHECK(connection, message, "status");
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- state = unit_file_get_state(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
- if (state < 0)
- return bus_send_error_reply(connection, message, NULL, state);
-
- s = unit_file_state_to_string(state);
- assert(s);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- if (!dbus_message_append_args(
- reply,
- DBUS_TYPE_STRING, &s,
- DBUS_TYPE_INVALID))
- goto oom;
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
- dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
- dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
- dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
- dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles")) {
-
- char **l = NULL;
- DBusMessageIter iter;
- UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
- UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
- dbus_bool_t runtime, force;
- int carries_install_info = -1;
-
- SELINUX_ACCESS_CHECK(connection, message, streq(member, "MaskUnitFiles") ? "disable" : "enable");
-
- if (!dbus_message_iter_init(message, &iter))
- goto oom;
-
- r = bus_parse_strv_iter(&iter, &l);
- if (r < 0) {
- if (r == -ENOMEM)
- goto oom;
-
- return bus_send_error_reply(connection, message, NULL, r);
- }
-
- if (!dbus_message_iter_next(&iter) ||
- bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
- bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
- strv_free(l);
- return bus_send_error_reply(connection, message, NULL, -EIO);
- }
-
- if (streq(member, "EnableUnitFiles")) {
- r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
- carries_install_info = r;
- } else if (streq(member, "ReenableUnitFiles")) {
- r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
- carries_install_info = r;
- } else if (streq(member, "LinkUnitFiles"))
- r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
- else if (streq(member, "PresetUnitFiles")) {
- r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
- carries_install_info = r;
- } else if (streq(member, "MaskUnitFiles"))
- r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
- else
- assert_not_reached("Uh? Wrong method");
-
- strv_free(l);
- bus_manager_send_unit_files_changed(m);
-
- if (r < 0) {
- unit_file_changes_free(changes, n_changes);
- return bus_send_error_reply(connection, message, NULL, r);
- }
-
- reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
- unit_file_changes_free(changes, n_changes);
-
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
- dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
-
- char **l = NULL;
- DBusMessageIter iter;
- UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
- UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
- dbus_bool_t runtime;
-
- SELINUX_ACCESS_CHECK(connection, message, streq(member, "UnmaskUnitFiles") ? "enable" : "disable");
-
- if (!dbus_message_iter_init(message, &iter))
- goto oom;
-
- r = bus_parse_strv_iter(&iter, &l);
- if (r < 0) {
- if (r == -ENOMEM)
- goto oom;
-
- return bus_send_error_reply(connection, message, NULL, r);
- }
-
- if (!dbus_message_iter_next(&iter) ||
- bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
- strv_free(l);
- return bus_send_error_reply(connection, message, NULL, -EIO);
- }
-
- if (streq(member, "DisableUnitFiles"))
- r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
- else if (streq(member, "UnmaskUnitFiles"))
- r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
- else
- assert_not_reached("Uh? Wrong method");
-
- strv_free(l);
- bus_manager_send_unit_files_changed(m);
-
- if (r < 0) {
- unit_file_changes_free(changes, n_changes);
- return bus_send_error_reply(connection, message, NULL, r);
- }
-
- reply = message_from_file_changes(message, changes, n_changes, -1);
- unit_file_changes_free(changes, n_changes);
-
- if (!reply)
- goto oom;
-
- } else {
- const BusBoundProperties bps[] = {
- { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
- { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
- { NULL, }
- };
-
- SELINUX_ACCESS_CHECK(connection, message, "status");
-
- return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
- }
-
- if (job_type != _JOB_TYPE_INVALID) {
- const char *name, *smode, *old_name = NULL;
- JobMode mode;
- Unit *u;
- dbus_bool_t b;
-
- if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
- b = dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &old_name,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_STRING, &smode,
- DBUS_TYPE_INVALID);
- else
- b = dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_STRING, &smode,
- DBUS_TYPE_INVALID);
- if (!b)
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- if (old_name) {
- u = manager_get_unit(m, old_name);
- if (!u || !u->job || u->job->type != JOB_START) {
- dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
- return bus_send_error_reply(connection, message, &error, -ENOENT);
- }
- }
-
- mode = job_mode_from_string(smode);
- if (mode < 0) {
- dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
- return bus_send_error_reply(connection, message, &error, -EINVAL);
- }
-
- r = manager_load_unit(m, name, NULL, &error, &u);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- return bus_unit_queue_job(connection, message, u, job_type, mode, reload_if_possible);
- }
-
- if (reply)
- if (!dbus_connection_send(connection, reply, NULL))
- goto oom;
-
- return DBUS_HANDLER_RESULT_HANDLED;
-
-oom:
- dbus_error_free(&error);
-
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-}
-
-const DBusObjectPathVTable bus_manager_vtable = {
- .message_function = bus_manager_message_handler
-};
diff --git a/src/core/dbus-manager.h b/src/core/dbus-manager.h
deleted file mode 100644
index f0dce5a2e9..0000000000
--- a/src/core/dbus-manager.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*-*- 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 <dbus/dbus.h>
-
-extern const DBusObjectPathVTable bus_manager_vtable;
-
-extern const char bus_manager_interface[];
diff --git a/src/core/dbus-mount.c b/src/core/dbus-mount.c
deleted file mode 100644
index d81edeb807..0000000000
--- a/src/core/dbus-mount.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*-*- 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 <errno.h>
-
-#include "dbus-unit.h"
-#include "dbus-mount.h"
-#include "dbus-kill.h"
-#include "dbus-execute.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
-
-#define BUS_MOUNT_INTERFACE \
- " <interface name=\"org.freedesktop.systemd1.Mount\">\n" \
- " <property name=\"Where\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"What\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Options\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Type\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"TimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
- BUS_EXEC_COMMAND_INTERFACE("ExecMount") \
- BUS_EXEC_COMMAND_INTERFACE("ExecUnmount") \
- BUS_EXEC_COMMAND_INTERFACE("ExecRemount") \
- BUS_EXEC_CONTEXT_INTERFACE \
- BUS_KILL_CONTEXT_INTERFACE \
- " <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"Result\" type=\"s\" access=\"read\"/>\n" \
- " </interface>\n"
-
-#define INTROSPECTION \
- DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
- "<node>\n" \
- BUS_UNIT_INTERFACE \
- BUS_MOUNT_INTERFACE \
- BUS_PROPERTIES_INTERFACE \
- BUS_PEER_INTERFACE \
- BUS_INTROSPECTABLE_INTERFACE \
- "</node>\n"
-
-#define INTERFACES_LIST \
- BUS_UNIT_INTERFACES_LIST \
- "org.freedesktop.systemd1.Mount\0"
-
-const char bus_mount_interface[] _introspect_("Mount") = BUS_MOUNT_INTERFACE;
-
-const char bus_mount_invalidating_properties[] =
- "What\0"
- "Options\0"
- "Type\0"
- "ExecMount\0"
- "ExecUnmount\0"
- "ExecRemount\0"
- "ControlPID\0"
- "Result\0";
-
-static int bus_mount_append_what(DBusMessageIter *i, const char *property, void *data) {
- Mount *m = data;
- const char *d;
-
- assert(i);
- assert(property);
- assert(m);
-
- if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.what)
- d = m->parameters_proc_self_mountinfo.what;
- else if (m->from_fragment && m->parameters_fragment.what)
- d = m->parameters_fragment.what;
- else
- d = "";
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &d))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_mount_append_options(DBusMessageIter *i, const char *property, void *data) {
- Mount *m = data;
- const char *d;
-
- assert(i);
- assert(property);
- assert(m);
-
- if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.options)
- d = m->parameters_proc_self_mountinfo.options;
- else if (m->from_fragment && m->parameters_fragment.options)
- d = m->parameters_fragment.options;
- else
- d = "";
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &d))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_mount_append_type(DBusMessageIter *i, const char *property, void *data) {
- Mount *m = data;
- const char *d;
-
- assert(i);
- assert(property);
- assert(m);
-
- if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.fstype)
- d = m->parameters_proc_self_mountinfo.fstype;
- else if (m->from_fragment && m->parameters_fragment.fstype)
- d = m->parameters_fragment.fstype;
- else
- d = "";
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &d))
- return -ENOMEM;
-
- return 0;
-}
-
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_mount_append_mount_result, mount_result, MountResult);
-
-static const BusProperty bus_mount_properties[] = {
- { "Where", bus_property_append_string, "s", offsetof(Mount, where), true },
- { "What", bus_mount_append_what, "s", 0 },
- { "Options", bus_mount_append_options, "s", 0 },
- { "Type", bus_mount_append_type, "s", 0 },
- { "TimeoutUSec", bus_property_append_usec, "t", offsetof(Mount, timeout_usec) },
- BUS_EXEC_COMMAND_PROPERTY("ExecMount", offsetof(Mount, exec_command[MOUNT_EXEC_MOUNT]), false),
- BUS_EXEC_COMMAND_PROPERTY("ExecUnmount", offsetof(Mount, exec_command[MOUNT_EXEC_UNMOUNT]), false),
- BUS_EXEC_COMMAND_PROPERTY("ExecRemount", offsetof(Mount, exec_command[MOUNT_EXEC_REMOUNT]), false),
- { "ControlPID", bus_property_append_pid, "u", offsetof(Mount, control_pid) },
- { "DirectoryMode", bus_property_append_mode, "u", offsetof(Mount, directory_mode) },
- { "Result", bus_mount_append_mount_result, "s", offsetof(Mount, result) },
- { NULL, }
-};
-
-DBusHandlerResult bus_mount_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
- Mount *m = MOUNT(u);
-
- const BusBoundProperties bps[] = {
- { "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
- { "org.freedesktop.systemd1.Mount", bus_mount_properties, m },
- { "org.freedesktop.systemd1.Mount", bus_exec_context_properties, &m->exec_context },
- { "org.freedesktop.systemd1.Mount", bus_kill_context_properties, &m->kill_context },
- { NULL, }
- };
-
- SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
- return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps );
-}
diff --git a/src/core/dbus-mount.h b/src/core/dbus-mount.h
deleted file mode 100644
index 8597394373..0000000000
--- a/src/core/dbus-mount.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*-*- 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 <dbus/dbus.h>
-
-#include "unit.h"
-
-DBusHandlerResult bus_mount_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
-
-extern const char bus_mount_interface[];
-extern const char bus_mount_invalidating_properties[];
diff --git a/src/core/dbus-path.c b/src/core/dbus-path.c
deleted file mode 100644
index f7fed1754d..0000000000
--- a/src/core/dbus-path.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*-*- 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 <errno.h>
-
-#include "dbus-unit.h"
-#include "dbus-path.h"
-#include "dbus-execute.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
-
-#define BUS_PATH_INTERFACE \
- " <interface name=\"org.freedesktop.systemd1.Path\">\n" \
- " <property name=\"Unit\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Paths\" type=\"a(ss)\" access=\"read\"/>\n" \
- " <property name=\"MakeDirectory\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"Result\" type=\"s\" access=\"read\"/>\n" \
- " </interface>\n"
-
-#define INTROSPECTION \
- DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
- "<node>\n" \
- BUS_UNIT_INTERFACE \
- BUS_PATH_INTERFACE \
- BUS_PROPERTIES_INTERFACE \
- BUS_PEER_INTERFACE \
- BUS_INTROSPECTABLE_INTERFACE \
- "</node>\n"
-
-#define INTERFACES_LIST \
- BUS_UNIT_INTERFACES_LIST \
- "org.freedesktop.systemd1.Path\0"
-
-const char bus_path_interface[] _introspect_("Path") = BUS_PATH_INTERFACE;
-
-const char bus_path_invalidating_properties[] =
- "Result\0";
-
-static int bus_path_append_paths(DBusMessageIter *i, const char *property, void *data) {
- Path *p = data;
- DBusMessageIter sub, sub2;
- PathSpec *k;
-
- assert(i);
- assert(property);
- assert(p);
-
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(ss)", &sub))
- return -ENOMEM;
-
- LIST_FOREACH(spec, k, p->specs) {
- const char *t = path_type_to_string(k->type);
-
- if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &t) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &k->path) ||
- !dbus_message_iter_close_container(&sub, &sub2))
- return -ENOMEM;
- }
-
- if (!dbus_message_iter_close_container(i, &sub))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_path_append_unit(DBusMessageIter *i, const char *property, void *data) {
- Unit *u = data;
- Path *p = PATH(u);
- const char *t;
-
- assert(i);
- assert(property);
- assert(u);
-
- t = UNIT_DEREF(p->unit) ? UNIT_DEREF(p->unit)->id : "";
-
- return dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t) ? 0 : -ENOMEM;
-}
-
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_path_append_path_result, path_result, PathResult);
-
-static const BusProperty bus_path_properties[] = {
- { "Unit", bus_path_append_unit, "s", 0 },
- { "Paths", bus_path_append_paths, "a(ss)", 0 },
- { "MakeDirectory", bus_property_append_bool, "b", offsetof(Path, make_directory) },
- { "DirectoryMode", bus_property_append_mode, "u", offsetof(Path, directory_mode) },
- { "Result", bus_path_append_path_result, "s", offsetof(Path, result) },
- { NULL, }
-};
-
-DBusHandlerResult bus_path_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
- Path *p = PATH(u);
- const BusBoundProperties bps[] = {
- { "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
- { "org.freedesktop.systemd1.Path", bus_path_properties, p },
- { NULL, }
- };
-
- SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
- return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
diff --git a/src/core/dbus-path.h b/src/core/dbus-path.h
deleted file mode 100644
index c945f7d588..0000000000
--- a/src/core/dbus-path.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*-*- 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 <dbus/dbus.h>
-
-#include "unit.h"
-
-DBusHandlerResult bus_path_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
-
-extern const char bus_path_interface[];
-
-extern const char bus_path_invalidating_properties[];
diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c
deleted file mode 100644
index d99058dd46..0000000000
--- a/src/core/dbus-service.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*-*- 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 <errno.h>
-
-#include "dbus-unit.h"
-#include "dbus-execute.h"
-#include "dbus-kill.h"
-#include "dbus-service.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
-
-#define BUS_SERVICE_INTERFACE \
- " <interface name=\"org.freedesktop.systemd1.Service\">\n" \
- " <property name=\"Type\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Restart\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"PIDFile\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"NotifyAccess\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"RestartUSec\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"TimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"WatchdogUSec\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"WatchdogTimestamp\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"WatchdogTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"StartLimitInterval\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"StartLimitBurst\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"StartLimitAction\" type=\"s\" access=\"readwrite\"/>\n" \
- BUS_EXEC_COMMAND_INTERFACE("ExecStartPre") \
- BUS_EXEC_COMMAND_INTERFACE("ExecStart") \
- BUS_EXEC_COMMAND_INTERFACE("ExecStartPost") \
- BUS_EXEC_COMMAND_INTERFACE("ExecReload") \
- BUS_EXEC_COMMAND_INTERFACE("ExecStop") \
- BUS_EXEC_COMMAND_INTERFACE("ExecStopPost") \
- BUS_EXEC_CONTEXT_INTERFACE \
- BUS_KILL_CONTEXT_INTERFACE \
- " <property name=\"PermissionsStartOnly\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"RootDirectoryStartOnly\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"RemainAfterExit\" type=\"b\" access=\"read\"/>\n" \
- BUS_EXEC_STATUS_INTERFACE("ExecMain") \
- " <property name=\"MainPID\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"BusName\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"StatusText\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Result\" type=\"s\" access=\"read\"/>\n" \
- " </interface>\n"
-
-#define INTROSPECTION \
- DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
- "<node>\n" \
- BUS_UNIT_INTERFACE \
- BUS_SERVICE_INTERFACE \
- BUS_PROPERTIES_INTERFACE \
- BUS_PEER_INTERFACE \
- BUS_INTROSPECTABLE_INTERFACE \
- "</node>\n"
-
-#define INTERFACES_LIST \
- BUS_UNIT_INTERFACES_LIST \
- "org.freedesktop.systemd1.Service\0"
-
-const char bus_service_interface[] _introspect_("Service") = BUS_SERVICE_INTERFACE;
-
-const char bus_service_invalidating_properties[] =
- "ExecStartPre\0"
- "ExecStart\0"
- "ExecStartPost\0"
- "ExecReload\0"
- "ExecStop\0"
- "ExecStopPost\0"
- "ExecMain\0"
- "WatchdogTimestamp\0"
- "WatchdogTimestampMonotonic\0"
- "MainPID\0"
- "ControlPID\0"
- "StatusText\0"
- "Result\0";
-
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_type, service_type, ServiceType);
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_restart, service_restart, ServiceRestart);
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_notify_access, notify_access, NotifyAccess);
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_service_result, service_result, ServiceResult);
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_start_limit_action, start_limit_action, StartLimitAction);
-static DEFINE_BUS_PROPERTY_SET_ENUM(bus_service_set_start_limit_action, start_limit_action, StartLimitAction);
-
-static const BusProperty bus_exec_main_status_properties[] = {
- { "ExecMainStartTimestamp", bus_property_append_usec, "t", offsetof(ExecStatus, start_timestamp.realtime) },
- { "ExecMainStartTimestampMonotonic",bus_property_append_usec, "t", offsetof(ExecStatus, start_timestamp.monotonic) },
- { "ExecMainExitTimestamp", bus_property_append_usec, "t", offsetof(ExecStatus, start_timestamp.realtime) },
- { "ExecMainExitTimestampMonotonic", bus_property_append_usec, "t", offsetof(ExecStatus, start_timestamp.monotonic) },
- { "ExecMainPID", bus_property_append_pid, "u", offsetof(ExecStatus, pid) },
- { "ExecMainCode", bus_property_append_int, "i", offsetof(ExecStatus, code) },
- { "ExecMainStatus", bus_property_append_int, "i", offsetof(ExecStatus, status) },
- { NULL, }
-};
-
-static const BusProperty bus_service_properties[] = {
- { "Type", bus_service_append_type, "s", offsetof(Service, type) },
- { "Restart", bus_service_append_restart, "s", offsetof(Service, restart) },
- { "PIDFile", bus_property_append_string, "s", offsetof(Service, pid_file), true },
- { "NotifyAccess", bus_service_append_notify_access, "s", offsetof(Service, notify_access) },
- { "RestartUSec", bus_property_append_usec, "t", offsetof(Service, restart_usec) },
- { "TimeoutUSec", bus_property_append_usec, "t", offsetof(Service, timeout_start_usec) },
- { "TimeoutStartUSec", bus_property_append_usec, "t", offsetof(Service, timeout_start_usec) },
- { "TimeoutStopUSec", bus_property_append_usec, "t", offsetof(Service, timeout_stop_usec) },
- { "WatchdogUSec", bus_property_append_usec, "t", offsetof(Service, watchdog_usec) },
- { "WatchdogTimestamp", bus_property_append_usec, "t", offsetof(Service, watchdog_timestamp.realtime) },
- { "WatchdogTimestampMonotonic",bus_property_append_usec, "t", offsetof(Service, watchdog_timestamp.monotonic) },
- { "StartLimitInterval", bus_property_append_usec, "t", offsetof(Service, start_limit.interval) },
- { "StartLimitBurst", bus_property_append_uint32, "u", offsetof(Service, start_limit.burst) },
- { "StartLimitAction", bus_service_append_start_limit_action,"s", offsetof(Service, start_limit_action), false, bus_service_set_start_limit_action},
- BUS_EXEC_COMMAND_PROPERTY("ExecStartPre", offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]), true ),
- BUS_EXEC_COMMAND_PROPERTY("ExecStart", offsetof(Service, exec_command[SERVICE_EXEC_START]), true ),
- BUS_EXEC_COMMAND_PROPERTY("ExecStartPost", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), true ),
- BUS_EXEC_COMMAND_PROPERTY("ExecReload", offsetof(Service, exec_command[SERVICE_EXEC_RELOAD]), true ),
- BUS_EXEC_COMMAND_PROPERTY("ExecStop", offsetof(Service, exec_command[SERVICE_EXEC_STOP]), true ),
- BUS_EXEC_COMMAND_PROPERTY("ExecStopPost", offsetof(Service, exec_command[SERVICE_EXEC_STOP_POST]), true ),
- { "PermissionsStartOnly", bus_property_append_bool, "b", offsetof(Service, permissions_start_only) },
- { "RootDirectoryStartOnly", bus_property_append_bool, "b", offsetof(Service, root_directory_start_only) },
- { "RemainAfterExit", bus_property_append_bool, "b", offsetof(Service, remain_after_exit) },
- { "GuessMainPID", bus_property_append_bool, "b", offsetof(Service, guess_main_pid) },
- { "MainPID", bus_property_append_pid, "u", offsetof(Service, main_pid) },
- { "ControlPID", bus_property_append_pid, "u", offsetof(Service, control_pid) },
- { "BusName", bus_property_append_string, "s", offsetof(Service, bus_name), true },
- { "StatusText", bus_property_append_string, "s", offsetof(Service, status_text), true },
- { "Result", bus_service_append_service_result,"s", offsetof(Service, result) },
- { NULL, }
-};
-
-DBusHandlerResult bus_service_message_handler(Unit *u, DBusConnection *connection, DBusMessage *message) {
- Service *s = SERVICE(u);
-
- const BusBoundProperties bps[] = {
- { "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
- { "org.freedesktop.systemd1.Service", bus_service_properties, s },
- { "org.freedesktop.systemd1.Service", bus_exec_context_properties, &s->exec_context },
- { "org.freedesktop.systemd1.Service", bus_kill_context_properties, &s->kill_context },
- { "org.freedesktop.systemd1.Service", bus_exec_main_status_properties, &s->main_exec_status },
- { NULL, }
- };
-
- SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
-
- return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
diff --git a/src/core/dbus-service.h b/src/core/dbus-service.h
deleted file mode 100644
index 143aed7ae5..0000000000
--- a/src/core/dbus-service.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*-*- 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 <dbus/dbus.h>
-
-#include "unit.h"
-
-DBusHandlerResult bus_service_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
-
-extern const char bus_service_interface[];
-extern const char bus_service_invalidating_properties[];
diff --git a/src/core/dbus-snapshot.c b/src/core/dbus-snapshot.c
deleted file mode 100644
index 435c6df39c..0000000000
--- a/src/core/dbus-snapshot.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*-*- 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 "dbus-unit.h"
-#include "dbus-snapshot.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
-
-#define BUS_SNAPSHOT_INTERFACE \
- " <interface name=\"org.freedesktop.systemd1.Snapshot\">\n" \
- " <method name=\"Remove\"/>\n" \
- " <property name=\"Cleanup\" type=\"b\" access=\"read\"/>\n" \
- " </interface>\n"
-
-#define INTROSPECTION \
- DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
- "<node>\n" \
- BUS_UNIT_INTERFACE \
- BUS_SNAPSHOT_INTERFACE \
- BUS_PROPERTIES_INTERFACE \
- BUS_PEER_INTERFACE \
- BUS_INTROSPECTABLE_INTERFACE \
- "</node>\n"
-
-#define INTERFACES_LIST \
- BUS_UNIT_INTERFACES_LIST \
- "org.freedesktop.systemd1.Snapshot\0"
-
-const char bus_snapshot_interface[] _introspect_("Snapshot") = BUS_SNAPSHOT_INTERFACE;
-
-static const BusProperty bus_snapshot_properties[] = {
- { "Cleanup", bus_property_append_bool, "b", offsetof(Snapshot, cleanup) },
- { NULL, }
-};
-
-DBusHandlerResult bus_snapshot_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
- Snapshot *s = SNAPSHOT(u);
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- DBusError error;
-
- dbus_error_init(&error);
-
- if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Snapshot", "Remove")) {
-
- SELINUX_UNIT_ACCESS_CHECK(u, c, message, "stop");
-
- snapshot_remove(SNAPSHOT(u));
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else {
- const BusBoundProperties bps[] = {
- { "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
- { "org.freedesktop.systemd1.Snapshot", bus_snapshot_properties, s },
- { NULL, }
- };
-
- SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
- return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
- }
-
- if (reply) {
- if (!dbus_connection_send(c, reply, NULL))
- goto oom;
- }
-
- return DBUS_HANDLER_RESULT_HANDLED;
-
-oom:
- dbus_error_free(&error);
-
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-}
diff --git a/src/core/dbus-snapshot.h b/src/core/dbus-snapshot.h
deleted file mode 100644
index 1208aafff6..0000000000
--- a/src/core/dbus-snapshot.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*-*- 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 <dbus/dbus.h>
-
-#include "unit.h"
-
-DBusHandlerResult bus_snapshot_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
-
-extern const char bus_snapshot_interface[];
diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c
deleted file mode 100644
index 095a031612..0000000000
--- a/src/core/dbus-socket.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*-*- 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 <errno.h>
-
-#include "dbus-unit.h"
-#include "dbus-socket.h"
-#include "dbus-execute.h"
-#include "dbus-kill.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
-
-#define BUS_SOCKET_INTERFACE \
- " <interface name=\"org.freedesktop.systemd1.Socket\">\n" \
- " <property name=\"BindIPv6Only\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"Backlog\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"TimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
- BUS_EXEC_COMMAND_INTERFACE("ExecStartPre") \
- BUS_EXEC_COMMAND_INTERFACE("ExecStartPost") \
- BUS_EXEC_COMMAND_INTERFACE("ExecStopPre") \
- BUS_EXEC_COMMAND_INTERFACE("ExecStopPost") \
- BUS_EXEC_CONTEXT_INTERFACE \
- BUS_KILL_CONTEXT_INTERFACE \
- " <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"BindToDevice\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"SocketMode\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"Accept\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"KeepAlive\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"Priority\" type=\"i\" access=\"read\"/>\n" \
- " <property name=\"ReceiveBuffer\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"SendBuffer\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"IPTOS\" type=\"i\" access=\"read\"/>\n" \
- " <property name=\"IPTTL\" type=\"i\" access=\"read\"/>\n" \
- " <property name=\"PipeSize\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"FreeBind\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"Transparent\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"Broadcast\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"PassCredentials\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"PassSecurity\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"Mark\" type=\"i\" access=\"read\"/>\n" \
- " <property name=\"MaxConnections\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"NAccepted\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"NConnections\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"MessageQueueMaxMessages\" type=\"x\" access=\"read\"/>\n" \
- " <property name=\"MessageQueueMessageSize\" type=\"x\" access=\"read\"/>\n" \
- " <property name=\"Result\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"SmackLabel\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"SmackLabelIPIn\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"SmackLabelIPOut\" type=\"s\" access=\"read\"/>\n" \
- " </interface>\n" \
-
-#define INTROSPECTION \
- DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
- "<node>\n" \
- BUS_UNIT_INTERFACE \
- BUS_SOCKET_INTERFACE \
- BUS_PROPERTIES_INTERFACE \
- BUS_PEER_INTERFACE \
- BUS_INTROSPECTABLE_INTERFACE \
- "</node>\n"
-
-#define INTERFACES_LIST \
- BUS_UNIT_INTERFACES_LIST \
- "org.freedesktop.systemd1.Socket\0"
-
-const char bus_socket_interface[] _introspect_("Socket") = BUS_SOCKET_INTERFACE;
-
-const char bus_socket_invalidating_properties[] =
- "ExecStartPre\0"
- "ExecStartPost\0"
- "ExecStopPre\0"
- "ExecStopPost\0"
- "ControlPID\0"
- "NAccepted\0"
- "NConnections\0"
- "Result\0";
-
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_socket_append_bind_ipv6_only, socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_socket_append_socket_result, socket_result, SocketResult);
-
-static const BusProperty bus_socket_properties[] = {
- { "BindIPv6Only", bus_socket_append_bind_ipv6_only, "s", offsetof(Socket, bind_ipv6_only) },
- { "Backlog", bus_property_append_unsigned, "u", offsetof(Socket, backlog) },
- { "TimeoutUSec", bus_property_append_usec, "t", offsetof(Socket, timeout_usec) },
- BUS_EXEC_COMMAND_PROPERTY("ExecStartPre", offsetof(Socket, exec_command[SOCKET_EXEC_START_PRE]), true ),
- BUS_EXEC_COMMAND_PROPERTY("ExecStartPost", offsetof(Socket, exec_command[SOCKET_EXEC_START_POST]), true ),
- BUS_EXEC_COMMAND_PROPERTY("ExecStopPre", offsetof(Socket, exec_command[SOCKET_EXEC_STOP_PRE]), true ),
- BUS_EXEC_COMMAND_PROPERTY("ExecStopPost", offsetof(Socket, exec_command[SOCKET_EXEC_STOP_POST]), true ),
- { "ControlPID", bus_property_append_pid, "u", offsetof(Socket, control_pid) },
- { "BindToDevice", bus_property_append_string, "s", offsetof(Socket, bind_to_device), true },
- { "DirectoryMode", bus_property_append_mode, "u", offsetof(Socket, directory_mode) },
- { "SocketMode", bus_property_append_mode, "u", offsetof(Socket, socket_mode) },
- { "Accept", bus_property_append_bool, "b", offsetof(Socket, accept) },
- { "KeepAlive", bus_property_append_bool, "b", offsetof(Socket, keep_alive) },
- { "Priority", bus_property_append_int, "i", offsetof(Socket, priority) },
- { "ReceiveBuffer", bus_property_append_size, "t", offsetof(Socket, receive_buffer) },
- { "SendBuffer", bus_property_append_size, "t", offsetof(Socket, send_buffer) },
- { "IPTOS", bus_property_append_int, "i", offsetof(Socket, ip_tos) },
- { "IPTTL", bus_property_append_int, "i", offsetof(Socket, ip_ttl) },
- { "PipeSize", bus_property_append_size, "t", offsetof(Socket, pipe_size) },
- { "FreeBind", bus_property_append_bool, "b", offsetof(Socket, free_bind) },
- { "Transparent", bus_property_append_bool, "b", offsetof(Socket, transparent) },
- { "Broadcast", bus_property_append_bool, "b", offsetof(Socket, broadcast) },
- { "PassCredentials",bus_property_append_bool, "b", offsetof(Socket, pass_cred) },
- { "PassSecurity", bus_property_append_bool, "b", offsetof(Socket, pass_sec) },
- { "Mark", bus_property_append_int, "i", offsetof(Socket, mark) },
- { "MaxConnections", bus_property_append_unsigned, "u", offsetof(Socket, max_connections) },
- { "NConnections", bus_property_append_unsigned, "u", offsetof(Socket, n_connections) },
- { "NAccepted", bus_property_append_unsigned, "u", offsetof(Socket, n_accepted) },
- { "MessageQueueMaxMessages", bus_property_append_long, "x", offsetof(Socket, mq_maxmsg) },
- { "MessageQueueMessageSize", bus_property_append_long, "x", offsetof(Socket, mq_msgsize) },
- { "Result", bus_socket_append_socket_result, "s", offsetof(Socket, result) },
- { "SmackLabel", bus_property_append_string, "s", offsetof(Socket, smack), true },
- { "SmackLabelIPIn", bus_property_append_string, "s", offsetof(Socket, smack_ip_in), true },
- { "SmackLabelIPOut",bus_property_append_string, "s", offsetof(Socket, smack_ip_out), true },
- { NULL, }
-};
-
-DBusHandlerResult bus_socket_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
- Socket *s = SOCKET(u);
- const BusBoundProperties bps[] = {
- { "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
- { "org.freedesktop.systemd1.Socket", bus_socket_properties, s },
- { "org.freedesktop.systemd1.Socket", bus_exec_context_properties, &s->exec_context },
- { "org.freedesktop.systemd1.Socket", bus_kill_context_properties, &s->kill_context },
- { NULL, }
- };
-
- SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
- return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
diff --git a/src/core/dbus-socket.h b/src/core/dbus-socket.h
deleted file mode 100644
index 5369b22e5e..0000000000
--- a/src/core/dbus-socket.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*-*- 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 <dbus/dbus.h>
-
-#include "unit.h"
-
-DBusHandlerResult bus_socket_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
-
-extern const char bus_socket_interface[];
-extern const char bus_socket_invalidating_properties[];
diff --git a/src/core/dbus-swap.c b/src/core/dbus-swap.c
deleted file mode 100644
index 67ea0f24fe..0000000000
--- a/src/core/dbus-swap.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2010 Maarten Lankhorst
-
- 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 <errno.h>
-
-#include "dbus-unit.h"
-#include "dbus-swap.h"
-#include "dbus-execute.h"
-#include "dbus-kill.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
-
-#define BUS_SWAP_INTERFACE \
- " <interface name=\"org.freedesktop.systemd1.Swap\">\n" \
- " <property name=\"What\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Priority\" type=\"i\" access=\"read\"/>\n" \
- " <property name=\"TimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
- BUS_EXEC_COMMAND_INTERFACE("ExecActivate") \
- BUS_EXEC_COMMAND_INTERFACE("ExecDeactivate") \
- BUS_EXEC_CONTEXT_INTERFACE \
- BUS_KILL_CONTEXT_INTERFACE \
- " <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"Result\" type=\"s\" access=\"read\"/>\n" \
- " </interface>\n"
-
-#define INTROSPECTION \
- DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
- "<node>\n" \
- BUS_UNIT_INTERFACE \
- BUS_SWAP_INTERFACE \
- BUS_PROPERTIES_INTERFACE \
- BUS_PEER_INTERFACE \
- BUS_INTROSPECTABLE_INTERFACE \
- "</node>\n"
-
-#define INTERFACES_LIST \
- BUS_UNIT_INTERFACES_LIST \
- "org.freedesktop.systemd1.Swap\0"
-
-const char bus_swap_interface[] _introspect_("Swap") = BUS_SWAP_INTERFACE;
-
-const char bus_swap_invalidating_properties[] =
- "What\0"
- "Priority\0"
- "ExecActivate\0"
- "ExecDeactivate\0"
- "ControlPID\0"
- "Result\0";
-
-static int bus_swap_append_priority(DBusMessageIter *i, const char *property, void *data) {
- Swap *s = data;
- dbus_int32_t j;
-
- assert(i);
- assert(property);
- assert(s);
-
- if (s->from_proc_swaps)
- j = s->parameters_proc_swaps.priority;
- else if (s->from_fragment)
- j = s->parameters_fragment.priority;
- else
- j = -1;
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &j))
- return -ENOMEM;
-
- return 0;
-}
-
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_swap_append_swap_result, swap_result, SwapResult);
-
-static const BusProperty bus_swap_properties[] = {
- { "What", bus_property_append_string, "s", offsetof(Swap, what), true },
- { "Priority", bus_swap_append_priority, "i", 0 },
- BUS_EXEC_COMMAND_PROPERTY("ExecActivate", offsetof(Swap, exec_command[SWAP_EXEC_ACTIVATE]), false),
- BUS_EXEC_COMMAND_PROPERTY("ExecDeactivate", offsetof(Swap, exec_command[SWAP_EXEC_DEACTIVATE]), false),
- { "ControlPID", bus_property_append_pid, "u", offsetof(Swap, control_pid) },
- { "Result", bus_swap_append_swap_result,"s", offsetof(Swap, result) },
- { NULL, }
-};
-
-DBusHandlerResult bus_swap_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
- Swap *s = SWAP(u);
- const BusBoundProperties bps[] = {
- { "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
- { "org.freedesktop.systemd1.Swap", bus_swap_properties, s },
- { "org.freedesktop.systemd1.Swap", bus_exec_context_properties, &s->exec_context },
- { "org.freedesktop.systemd1.Swap", bus_kill_context_properties, &s->kill_context },
- { NULL, }
- };
-
- SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
- return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
diff --git a/src/core/dbus-swap.h b/src/core/dbus-swap.h
deleted file mode 100644
index 41fe4447ff..0000000000
--- a/src/core/dbus-swap.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2010 Maarten Lankhorst
-
- 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 <dbus/dbus.h>
-
-#include "unit.h"
-
-DBusHandlerResult bus_swap_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
-
-extern const char bus_swap_interface[];
-extern const char bus_swap_invalidating_properties[];
diff --git a/src/core/dbus-target.c b/src/core/dbus-target.c
deleted file mode 100644
index 6a775506cc..0000000000
--- a/src/core/dbus-target.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*-*- 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 <errno.h>
-
-#include "dbus-unit.h"
-#include "dbus-target.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
-
-#define BUS_TARGET_INTERFACE \
- " <interface name=\"org.freedesktop.systemd1.Target\">\n" \
- " </interface>\n"
-
-#define INTROSPECTION \
- DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
- "<node>\n" \
- BUS_UNIT_INTERFACE \
- BUS_TARGET_INTERFACE \
- BUS_PROPERTIES_INTERFACE \
- BUS_PEER_INTERFACE \
- BUS_INTROSPECTABLE_INTERFACE \
- "</node>\n"
-
-#define INTERFACES_LIST \
- BUS_UNIT_INTERFACES_LIST \
- "org.freedesktop.systemd1.Target\0"
-
-const char bus_target_interface[] _introspect_("Target") = BUS_TARGET_INTERFACE;
-
-DBusHandlerResult bus_target_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
- const BusBoundProperties bps[] = {
- { "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
- { NULL, }
- };
-
- SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
- return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
diff --git a/src/core/dbus-target.h b/src/core/dbus-target.h
deleted file mode 100644
index a8a0304c75..0000000000
--- a/src/core/dbus-target.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*-*- 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 <dbus/dbus.h>
-
-#include "unit.h"
-
-DBusHandlerResult bus_target_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
-
-extern const char bus_target_interface[];
diff --git a/src/core/dbus-timer.c b/src/core/dbus-timer.c
deleted file mode 100644
index 84b823c9a4..0000000000
--- a/src/core/dbus-timer.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/*-*- 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 <errno.h>
-
-#include "dbus-unit.h"
-#include "dbus-timer.h"
-#include "dbus-execute.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
-
-#define BUS_TIMER_INTERFACE \
- " <interface name=\"org.freedesktop.systemd1.Timer\">\n" \
- " <property name=\"Unit\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Timers\" type=\"a(stt)\" access=\"read\"/>\n" \
- " <property name=\"NextElapseUSec\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"Result\" type=\"s\" access=\"read\"/>\n" \
- " </interface>\n"
-
-#define INTROSPECTION \
- DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
- "<node>\n" \
- BUS_UNIT_INTERFACE \
- BUS_TIMER_INTERFACE \
- BUS_PROPERTIES_INTERFACE \
- BUS_PEER_INTERFACE \
- BUS_INTROSPECTABLE_INTERFACE \
- "</node>\n"
-
-#define INTERFACES_LIST \
- BUS_UNIT_INTERFACES_LIST \
- "org.freedesktop.systemd1.Timer\0"
-
-const char bus_timer_interface[] _introspect_("Timer") = BUS_TIMER_INTERFACE;
-
-const char bus_timer_invalidating_properties[] =
- "Timers\0"
- "NextElapseUSec\0"
- "Result\0";
-
-static int bus_timer_append_timers(DBusMessageIter *i, const char *property, void *data) {
- Timer *p = data;
- DBusMessageIter sub, sub2;
- TimerValue *k;
-
- assert(i);
- assert(property);
- assert(p);
-
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(stt)", &sub))
- return -ENOMEM;
-
- LIST_FOREACH(value, k, p->values) {
- char *buf;
- const char *t;
- size_t l;
- bool b;
-
- t = timer_base_to_string(k->base);
- assert(endswith(t, "Sec"));
-
- /* s/Sec/USec/ */
- l = strlen(t);
- if (!(buf = new(char, l+2)))
- return -ENOMEM;
-
- memcpy(buf, t, l-3);
- memcpy(buf+l-3, "USec", 5);
-
- b = dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) &&
- dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &buf) &&
- dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &k->value) &&
- dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &k->next_elapse) &&
- dbus_message_iter_close_container(&sub, &sub2);
-
- free(buf);
- if (!b)
- return -ENOMEM;
- }
-
- if (!dbus_message_iter_close_container(i, &sub))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_timer_append_unit(DBusMessageIter *i, const char *property, void *data) {
- Unit *u = data;
- Timer *timer = TIMER(u);
- const char *t;
-
- assert(i);
- assert(property);
- assert(u);
-
- t = UNIT_DEREF(timer->unit) ? UNIT_DEREF(timer->unit)->id : "";
-
- return dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t) ? 0 : -ENOMEM;
-}
-
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_timer_append_timer_result, timer_result, TimerResult);
-
-static const BusProperty bus_timer_properties[] = {
- { "Unit", bus_timer_append_unit, "s", 0 },
- { "Timers", bus_timer_append_timers, "a(stt)", 0 },
- { "NextElapseUSec", bus_property_append_usec, "t", offsetof(Timer, next_elapse) },
- { "Result", bus_timer_append_timer_result,"s", offsetof(Timer, result) },
- { NULL, }
-};
-
-DBusHandlerResult bus_timer_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
- Timer *t = TIMER(u);
- const BusBoundProperties bps[] = {
- { "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
- { "org.freedesktop.systemd1.Timer", bus_timer_properties, t },
- { NULL, }
- };
-
- SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
- return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
diff --git a/src/core/dbus-timer.h b/src/core/dbus-timer.h
deleted file mode 100644
index 9ac30501d1..0000000000
--- a/src/core/dbus-timer.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*-*- 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 <dbus/dbus.h>
-
-#include "unit.h"
-
-DBusHandlerResult bus_timer_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
-
-extern const char bus_timer_interface[];
-extern const char bus_timer_invalidating_properties[];
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
deleted file mode 100644
index 83ee018ff3..0000000000
--- a/src/core/dbus-unit.c
+++ /dev/null
@@ -1,887 +0,0 @@
-/*-*- 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 <errno.h>
-
-#include "dbus.h"
-#include "log.h"
-#include "dbus-unit.h"
-#include "bus-errors.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
-
-const char bus_unit_interface[] _introspect_("Unit") = BUS_UNIT_INTERFACE;
-
-#define INVALIDATING_PROPERTIES \
- "LoadState\0" \
- "ActiveState\0" \
- "SubState\0" \
- "InactiveExitTimestamp\0" \
- "ActiveEnterTimestamp\0" \
- "ActiveExitTimestamp\0" \
- "InactiveEnterTimestamp\0" \
- "Job\0" \
- "NeedDaemonReload\0"
-
-static int bus_unit_append_names(DBusMessageIter *i, const char *property, void *data) {
- char *t;
- Iterator j;
- DBusMessageIter sub;
- Unit *u = data;
-
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "s", &sub))
- return -ENOMEM;
-
- SET_FOREACH(t, u->names, j)
- if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &t))
- return -ENOMEM;
-
- if (!dbus_message_iter_close_container(i, &sub))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_unit_append_following(DBusMessageIter *i, const char *property, void *data) {
- Unit *u = data, *f;
- const char *d;
-
- assert(i);
- assert(property);
- assert(u);
-
- f = unit_following(u);
- d = f ? f->id : "";
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &d))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_unit_append_dependencies(DBusMessageIter *i, const char *property, void *data) {
- Unit *u;
- Iterator j;
- DBusMessageIter sub;
- Set *s = data;
-
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "s", &sub))
- return -ENOMEM;
-
- SET_FOREACH(u, s, j)
- if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &u->id))
- return -ENOMEM;
-
- if (!dbus_message_iter_close_container(i, &sub))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_unit_append_description(DBusMessageIter *i, const char *property, void *data) {
- Unit *u = data;
- const char *d;
-
- assert(i);
- assert(property);
- assert(u);
-
- d = unit_description(u);
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &d))
- return -ENOMEM;
-
- return 0;
-}
-
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_unit_append_load_state, unit_load_state, UnitLoadState);
-
-static int bus_unit_append_active_state(DBusMessageIter *i, const char *property, void *data) {
- Unit *u = data;
- const char *state;
-
- assert(i);
- assert(property);
- assert(u);
-
- state = unit_active_state_to_string(unit_active_state(u));
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &state))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_unit_append_sub_state(DBusMessageIter *i, const char *property, void *data) {
- Unit *u = data;
- const char *state;
-
- assert(i);
- assert(property);
- assert(u);
-
- state = unit_sub_state_to_string(u);
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &state))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_unit_append_file_state(DBusMessageIter *i, const char *property, void *data) {
- Unit *u = data;
- const char *state;
-
- assert(i);
- assert(property);
- assert(u);
-
- state = strempty(unit_file_state_to_string(unit_get_unit_file_state(u)));
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &state))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_unit_append_can_start(DBusMessageIter *i, const char *property, void *data) {
- Unit *u = data;
- dbus_bool_t b;
-
- assert(i);
- assert(property);
- assert(u);
-
- b = unit_can_start(u) &&
- !u->refuse_manual_start;
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_unit_append_can_stop(DBusMessageIter *i, const char *property, void *data) {
- Unit *u = data;
- dbus_bool_t b;
-
- assert(i);
- assert(property);
- assert(u);
-
- /* On the lower levels we assume that every unit we can start
- * we can also stop */
-
- b = unit_can_start(u) &&
- !u->refuse_manual_stop;
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_unit_append_can_reload(DBusMessageIter *i, const char *property, void *data) {
- Unit *u = data;
- dbus_bool_t b;
-
- assert(i);
- assert(property);
- assert(u);
-
- b = unit_can_reload(u);
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_unit_append_can_isolate(DBusMessageIter *i, const char *property, void *data) {
- Unit *u = data;
- dbus_bool_t b;
-
- assert(i);
- assert(property);
- assert(u);
-
- b = unit_can_isolate(u) &&
- !u->refuse_manual_start;
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_unit_append_job(DBusMessageIter *i, const char *property, void *data) {
- Unit *u = data;
- DBusMessageIter sub;
- char *p;
-
- assert(i);
- assert(property);
- assert(u);
-
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub))
- return -ENOMEM;
-
- if (u->job) {
-
- if (!(p = job_dbus_path(u->job)))
- return -ENOMEM;
-
- if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT32, &u->job->id) ||
- !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &p)) {
- free(p);
- return -ENOMEM;
- }
- } else {
- uint32_t id = 0;
-
- /* No job, so let's fill in some placeholder
- * data. Since we need to fill in a valid path we
- * simple point to ourselves. */
-
- if (!(p = unit_dbus_path(u)))
- return -ENOMEM;
-
- if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT32, &id) ||
- !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &p)) {
- free(p);
- return -ENOMEM;
- }
- }
-
- free(p);
-
- if (!dbus_message_iter_close_container(i, &sub))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_unit_append_default_cgroup(DBusMessageIter *i, const char *property, void *data) {
- Unit *u = data;
- char *t;
- CGroupBonding *cgb;
- bool success;
-
- assert(i);
- assert(property);
- assert(u);
-
- if ((cgb = unit_get_default_cgroup(u))) {
- if (!(t = cgroup_bonding_to_string(cgb)))
- return -ENOMEM;
- } else
- t = (char*) "";
-
- success = dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t);
-
- if (cgb)
- free(t);
-
- return success ? 0 : -ENOMEM;
-}
-
-static int bus_unit_append_cgroups(DBusMessageIter *i, const char *property, void *data) {
- Unit *u = data;
- CGroupBonding *cgb;
- DBusMessageIter sub;
-
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "s", &sub))
- return -ENOMEM;
-
- LIST_FOREACH(by_unit, cgb, u->cgroup_bondings) {
- char *t;
- bool success;
-
- if (!(t = cgroup_bonding_to_string(cgb)))
- return -ENOMEM;
-
- success = dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &t);
- free(t);
-
- if (!success)
- return -ENOMEM;
- }
-
- if (!dbus_message_iter_close_container(i, &sub))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_unit_append_cgroup_attrs(DBusMessageIter *i, const char *property, void *data) {
- Unit *u = data;
- CGroupAttribute *a;
- DBusMessageIter sub, sub2;
-
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sss)", &sub))
- return -ENOMEM;
-
- LIST_FOREACH(by_unit, a, u->cgroup_attributes) {
- char *v = NULL;
- bool success;
-
- if (a->map_callback)
- a->map_callback(a->controller, a->name, a->value, &v);
-
- success =
- dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) &&
- dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &a->controller) &&
- dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &a->name) &&
- dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, v ? &v : &a->value) &&
- dbus_message_iter_close_container(&sub, &sub2);
-
- free(v);
-
- if (!success)
- return -ENOMEM;
- }
-
- if (!dbus_message_iter_close_container(i, &sub))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_unit_append_need_daemon_reload(DBusMessageIter *i, const char *property, void *data) {
- Unit *u = data;
- dbus_bool_t b;
-
- assert(i);
- assert(property);
- assert(u);
-
- b = unit_need_daemon_reload(u);
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_unit_append_load_error(DBusMessageIter *i, const char *property, void *data) {
- Unit *u = data;
- const char *name, *message;
- DBusMessageIter sub;
-
- assert(i);
- assert(property);
- assert(u);
-
- if (u->load_error != 0) {
- name = bus_errno_to_dbus(u->load_error);
- message = strempty(strerror(-u->load_error));
- } else
- name = message = "";
-
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub) ||
- !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &name) ||
- !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &message) ||
- !dbus_message_iter_close_container(i, &sub))
- return -ENOMEM;
-
- return 0;
-}
-
-static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *connection, DBusMessage *message) {
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- DBusError error;
- JobType job_type = _JOB_TYPE_INVALID;
- bool reload_if_possible = false;
- int r;
-
- dbus_error_init(&error);
-
- if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "Start"))
- job_type = JOB_START;
- else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "Stop"))
- job_type = JOB_STOP;
- else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "Reload"))
- job_type = JOB_RELOAD;
- else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "Restart"))
- job_type = JOB_RESTART;
- else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "TryRestart"))
- job_type = JOB_TRY_RESTART;
- else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "ReloadOrRestart")) {
- reload_if_possible = true;
- job_type = JOB_RESTART;
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "ReloadOrTryRestart")) {
- reload_if_possible = true;
- job_type = JOB_TRY_RESTART;
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "Kill")) {
- const char *swho;
- int32_t signo;
- KillWho who;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &swho,
- DBUS_TYPE_INT32, &signo,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- if (isempty(swho))
- who = KILL_ALL;
- else {
- who = kill_who_from_string(swho);
- if (who < 0)
- return bus_send_error_reply(connection, message, &error, -EINVAL);
- }
-
- if (signo <= 0 || signo >= _NSIG)
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
-
- r = unit_kill(u, who, signo, &error);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "ResetFailed")) {
-
- SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "reload");
-
- unit_reset_failed(u);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (UNIT_VTABLE(u)->bus_message_handler)
- return UNIT_VTABLE(u)->bus_message_handler(u, connection, message);
- else
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
- if (job_type != _JOB_TYPE_INVALID) {
- const char *smode;
- JobMode mode;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &smode,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- mode = job_mode_from_string(smode);
- if (mode < 0) {
- dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
- return bus_send_error_reply(connection, message, &error, -EINVAL);
- }
-
- return bus_unit_queue_job(connection, message, u, job_type, mode, reload_if_possible);
- }
-
- if (reply)
- if (!dbus_connection_send(connection, reply, NULL))
- goto oom;
-
- return DBUS_HANDLER_RESULT_HANDLED;
-
-oom:
- dbus_error_free(&error);
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-}
-
-static DBusHandlerResult bus_unit_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
- Manager *m = data;
- Unit *u;
- int r;
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- DBusError error;
-
- assert(connection);
- assert(message);
- assert(m);
-
- dbus_error_init(&error);
-
- if (streq(dbus_message_get_path(message), "/org/freedesktop/systemd1/unit")) {
- /* Be nice to gdbus and return introspection data for our mid-level paths */
-
- SELINUX_ACCESS_CHECK(connection, message, "status");
-
- if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
- char *introspection = NULL;
- FILE *f;
- Iterator i;
- const char *k;
- size_t size;
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- /* We roll our own introspection code here, instead of
- * relying on bus_default_message_handler() because we
- * need to generate our introspection string
- * dynamically. */
-
- f = open_memstream(&introspection, &size);
- if (!f)
- goto oom;
-
- fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
- "<node>\n", f);
-
- fputs(BUS_INTROSPECTABLE_INTERFACE, f);
- fputs(BUS_PEER_INTERFACE, f);
-
- HASHMAP_FOREACH_KEY(u, k, m->units, i) {
- char *p;
-
- if (k != u->id)
- continue;
-
- p = bus_path_escape(k);
- if (!p) {
- fclose(f);
- free(introspection);
- goto oom;
- }
-
- fprintf(f, "<node name=\"%s\"/>", p);
- free(p);
- }
-
- fputs("</node>\n", f);
-
- if (ferror(f)) {
- fclose(f);
- free(introspection);
- goto oom;
- }
-
- fclose(f);
-
- if (!introspection)
- goto oom;
-
- if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
- free(introspection);
- goto oom;
- }
-
- free(introspection);
-
- if (!dbus_connection_send(connection, reply, NULL))
- goto oom;
-
- return DBUS_HANDLER_RESULT_HANDLED;
- }
-
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- }
-
- r = manager_load_unit_from_dbus_path(m, dbus_message_get_path(message), &error, &u);
- if (r == -ENOMEM)
- goto oom;
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- return bus_unit_message_dispatch(u, connection, message);
-
-oom:
- dbus_error_free(&error);
-
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-}
-
-const DBusObjectPathVTable bus_unit_vtable = {
- .message_function = bus_unit_message_handler
-};
-
-void bus_unit_send_change_signal(Unit *u) {
- char *p = NULL;
- DBusMessage *m = NULL;
-
- assert(u);
-
- if (u->in_dbus_queue) {
- LIST_REMOVE(Unit, dbus_queue, u->manager->dbus_unit_queue, u);
- u->in_dbus_queue = false;
- }
-
- if (!u->id)
- return;
-
- if (!bus_has_subscriber(u->manager)) {
- u->sent_dbus_new_signal = true;
- return;
- }
-
- if (!(p = unit_dbus_path(u)))
- goto oom;
-
- if (u->sent_dbus_new_signal) {
- /* Send a properties changed signal. First for the
- * specific type, then for the generic unit. The
- * clients may rely on this order to get atomic
- * behavior if needed. */
-
- if (UNIT_VTABLE(u)->bus_invalidating_properties) {
-
- if (!(m = bus_properties_changed_new(p,
- UNIT_VTABLE(u)->bus_interface,
- UNIT_VTABLE(u)->bus_invalidating_properties)))
- goto oom;
-
- if (bus_broadcast(u->manager, m) < 0)
- goto oom;
-
- dbus_message_unref(m);
- }
-
- if (!(m = bus_properties_changed_new(p, "org.freedesktop.systemd1.Unit", INVALIDATING_PROPERTIES)))
- goto oom;
-
- } else {
- /* Send a new signal */
-
- if (!(m = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitNew")))
- goto oom;
-
- if (!dbus_message_append_args(m,
- DBUS_TYPE_STRING, &u->id,
- DBUS_TYPE_OBJECT_PATH, &p,
- DBUS_TYPE_INVALID))
- goto oom;
- }
-
- if (bus_broadcast(u->manager, m) < 0)
- goto oom;
-
- free(p);
- dbus_message_unref(m);
-
- u->sent_dbus_new_signal = true;
-
- return;
-
-oom:
- free(p);
-
- if (m)
- dbus_message_unref(m);
-
- log_error("Failed to allocate unit change/new signal.");
-}
-
-void bus_unit_send_removed_signal(Unit *u) {
- char *p = NULL;
- DBusMessage *m = NULL;
-
- assert(u);
-
- if (!bus_has_subscriber(u->manager))
- return;
-
- if (!u->sent_dbus_new_signal)
- bus_unit_send_change_signal(u);
-
- if (!u->id)
- return;
-
- if (!(p = unit_dbus_path(u)))
- goto oom;
-
- if (!(m = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitRemoved")))
- goto oom;
-
- if (!dbus_message_append_args(m,
- DBUS_TYPE_STRING, &u->id,
- DBUS_TYPE_OBJECT_PATH, &p,
- DBUS_TYPE_INVALID))
- goto oom;
-
- if (bus_broadcast(u->manager, m) < 0)
- goto oom;
-
- free(p);
- dbus_message_unref(m);
-
- return;
-
-oom:
- free(p);
-
- if (m)
- dbus_message_unref(m);
-
- log_error("Failed to allocate unit remove signal.");
-}
-
-DBusHandlerResult bus_unit_queue_job(
- DBusConnection *connection,
- DBusMessage *message,
- Unit *u,
- JobType type,
- JobMode mode,
- bool reload_if_possible) {
-
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- _cleanup_free_ char *path = NULL;
- Job *j;
- JobBusClient *cl;
- DBusError error;
- int r;
-
- assert(connection);
- assert(message);
- assert(u);
- assert(type >= 0 && type < _JOB_TYPE_MAX);
- assert(mode >= 0 && mode < _JOB_MODE_MAX);
-
- dbus_error_init(&error);
-
- if (reload_if_possible && unit_can_reload(u)) {
- if (type == JOB_RESTART)
- type = JOB_RELOAD_OR_START;
- else if (type == JOB_TRY_RESTART)
- type = JOB_RELOAD;
- }
-
- SELINUX_UNIT_ACCESS_CHECK(u, connection, message,
- (type == JOB_START || type == JOB_RESTART || type == JOB_TRY_RESTART) ? "start" :
- type == JOB_STOP ? "stop" : "reload");
-
- if (type == JOB_STOP && u->load_state == UNIT_ERROR && unit_active_state(u) == UNIT_INACTIVE) {
- dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
- return bus_send_error_reply(connection, message, &error, -EPERM);
- }
-
- if ((type == JOB_START && u->refuse_manual_start) ||
- (type == JOB_STOP && u->refuse_manual_stop) ||
- ((type == JOB_RESTART || type == JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop))) {
- dbus_set_error(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, unit %s may be requested by dependency only.", u->id);
- return bus_send_error_reply(connection, message, &error, -EPERM);
- }
-
- r = manager_add_job(u->manager, type, u, mode, true, &error, &j);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- cl = job_bus_client_new(connection, bus_message_get_sender_with_fallback(message));
- if (!cl)
- goto oom;
-
- LIST_PREPEND(JobBusClient, client, j->bus_client_list, cl);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- path = job_dbus_path(j);
- if (!path)
- goto oom;
-
- if (!dbus_message_append_args(
- reply,
- DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID))
- goto oom;
-
- if (!dbus_connection_send(connection, reply, NULL))
- goto oom;
-
- return DBUS_HANDLER_RESULT_HANDLED;
-
-oom:
- dbus_error_free(&error);
-
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-}
-
-const BusProperty bus_unit_properties[] = {
- { "Id", bus_property_append_string, "s", offsetof(Unit, id), true },
- { "Names", bus_unit_append_names, "as", 0 },
- { "Following", bus_unit_append_following, "s", 0 },
- { "Requires", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRES]), true },
- { "RequiresOverridable", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRES_OVERRIDABLE]), true },
- { "Requisite", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUISITE]), true },
- { "RequisiteOverridable", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUISITE_OVERRIDABLE]), true },
- { "Wants", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_WANTS]), true },
- { "BindsTo", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BINDS_TO]), true },
- { "PartOf", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PART_OF]), true },
- { "RequiredBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRED_BY]), true },
- { "RequiredByOverridable",bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRED_BY_OVERRIDABLE]), true },
- { "WantedBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_WANTED_BY]), true },
- { "BoundBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BOUND_BY]), true },
- { "ConsistsOf", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_CONSISTS_OF]), true },
- { "Conflicts", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_CONFLICTS]), true },
- { "ConflictedBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_CONFLICTED_BY]), true },
- { "Before", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BEFORE]), true },
- { "After", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_AFTER]), true },
- { "OnFailure", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_ON_FAILURE]), true },
- { "Triggers", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_TRIGGERS]), true },
- { "TriggeredBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]), true },
- { "PropagatesReloadTo", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]), true },
- { "ReloadPropagatedFrom", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]), true },
- { "RequiresMountsFor", bus_property_append_strv, "as", offsetof(Unit, requires_mounts_for), true },
- { "Documentation", bus_property_append_strv, "as", offsetof(Unit, documentation), true },
- { "Description", bus_unit_append_description, "s", 0 },
- { "LoadState", bus_unit_append_load_state, "s", offsetof(Unit, load_state) },
- { "ActiveState", bus_unit_append_active_state, "s", 0 },
- { "SubState", bus_unit_append_sub_state, "s", 0 },
- { "FragmentPath", bus_property_append_string, "s", offsetof(Unit, fragment_path), true },
- { "SourcePath", bus_property_append_string, "s", offsetof(Unit, source_path), true },
- { "UnitFileState", bus_unit_append_file_state, "s", 0 },
- { "InactiveExitTimestamp",bus_property_append_usec, "t", offsetof(Unit, inactive_exit_timestamp.realtime) },
- { "InactiveExitTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, inactive_exit_timestamp.monotonic) },
- { "ActiveEnterTimestamp", bus_property_append_usec, "t", offsetof(Unit, active_enter_timestamp.realtime) },
- { "ActiveEnterTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, active_enter_timestamp.monotonic) },
- { "ActiveExitTimestamp", bus_property_append_usec, "t", offsetof(Unit, active_exit_timestamp.realtime) },
- { "ActiveExitTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, active_exit_timestamp.monotonic) },
- { "InactiveEnterTimestamp", bus_property_append_usec, "t", offsetof(Unit, inactive_enter_timestamp.realtime) },
- { "InactiveEnterTimestampMonotonic",bus_property_append_usec, "t", offsetof(Unit, inactive_enter_timestamp.monotonic) },
- { "CanStart", bus_unit_append_can_start, "b", 0 },
- { "CanStop", bus_unit_append_can_stop, "b", 0 },
- { "CanReload", bus_unit_append_can_reload, "b", 0 },
- { "CanIsolate", bus_unit_append_can_isolate, "b", 0 },
- { "Job", bus_unit_append_job, "(uo)", 0 },
- { "StopWhenUnneeded", bus_property_append_bool, "b", offsetof(Unit, stop_when_unneeded) },
- { "RefuseManualStart", bus_property_append_bool, "b", offsetof(Unit, refuse_manual_start) },
- { "RefuseManualStop", bus_property_append_bool, "b", offsetof(Unit, refuse_manual_stop) },
- { "AllowIsolate", bus_property_append_bool, "b", offsetof(Unit, allow_isolate) },
- { "DefaultDependencies", bus_property_append_bool, "b", offsetof(Unit, default_dependencies) },
- { "OnFailureIsolate", bus_property_append_bool, "b", offsetof(Unit, on_failure_isolate) },
- { "IgnoreOnIsolate", bus_property_append_bool, "b", offsetof(Unit, ignore_on_isolate) },
- { "IgnoreOnSnapshot", bus_property_append_bool, "b", offsetof(Unit, ignore_on_snapshot) },
- { "DefaultControlGroup", bus_unit_append_default_cgroup, "s", 0 },
- { "ControlGroup", bus_unit_append_cgroups, "as", 0 },
- { "ControlGroupAttributes", bus_unit_append_cgroup_attrs,"a(sss)", 0 },
- { "NeedDaemonReload", bus_unit_append_need_daemon_reload, "b", 0 },
- { "JobTimeoutUSec", bus_property_append_usec, "t", offsetof(Unit, job_timeout) },
- { "ConditionTimestamp", bus_property_append_usec, "t", offsetof(Unit, condition_timestamp.realtime) },
- { "ConditionTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, condition_timestamp.monotonic) },
- { "ConditionResult", bus_property_append_bool, "b", offsetof(Unit, condition_result) },
- { "LoadError", bus_unit_append_load_error, "(ss)", 0 },
- { NULL, }
-};
diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h
deleted file mode 100644
index ac6785a949..0000000000
--- a/src/core/dbus-unit.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*-*- 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 <dbus/dbus.h>
-
-#include "manager.h"
-#include "dbus-common.h"
-
-#define BUS_UNIT_INTERFACE \
- " <interface name=\"org.freedesktop.systemd1.Unit\">\n" \
- " <method name=\"Start\">\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"Stop\">\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"Reload\">\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"Restart\">\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"TryRestart\">\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"ReloadOrRestart\">\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"ReloadOrTryRestart\">\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"Kill\">\n" \
- " <arg name=\"who\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"signal\" type=\"i\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"ResetFailed\"/>\n" \
- " <property name=\"Id\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Names\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"Following\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Requires\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"RequiresOverridable\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"Requisite\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"RequisiteOverridable\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"Wants\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"BindsTo\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"RequiredBy\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"RequiredByOverridable\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"WantedBy\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"BoundBy\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"Conflicts\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"ConflictedBy\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"Before\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"After\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"OnFailure\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"Triggers\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"TriggeredBy\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"PropagatesReloadTo\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"ReloadPropagatedFrom\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"RequiresMountsFor\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"Description\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"SourcePath\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Documentation\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"LoadState\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"ActiveState\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"SubState\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"FragmentPath\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"UnitFileState\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"InactiveExitTimestamp\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"InactiveExitTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"ActiveEnterTimestamp\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"ActiveEnterTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"ActiveExitTimestamp\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"ActiveExitTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"InactiveEnterTimestamp\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"InactiveEnterTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"CanStart\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"CanStop\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"CanReload\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"CanIsolate\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"Job\" type=\"(uo)\" access=\"read\"/>\n" \
- " <property name=\"StopWhenUnneeded\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"RefuseManualStart\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"RefuseManualStop\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"AllowIsolate\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"DefaultDependencies\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"OnFailureIsolate\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"IgnoreOnIsolate\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"IgnoreOnSnapshot\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"DefaultControlGroup\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"ControlGroup\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"ControlGroupAttributes\" type=\"a(sss)\" access=\"read\"/>\n" \
- " <property name=\"NeedDaemonReload\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"JobTimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"ConditionTimestamp\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"ConditionTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"ConditionResult\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"LoadError\" type=\"(ss)\" access=\"read\"/>\n" \
- " </interface>\n"
-
-#define BUS_UNIT_INTERFACES_LIST \
- BUS_GENERIC_INTERFACES_LIST \
- "org.freedesktop.systemd1.Unit\0"
-
-extern const BusProperty bus_unit_properties[];
-
-void bus_unit_send_change_signal(Unit *u);
-void bus_unit_send_removed_signal(Unit *u);
-
-
-DBusHandlerResult bus_unit_queue_job(
- DBusConnection *connection,
- DBusMessage *message,
- Unit *u,
- JobType type,
- JobMode mode,
- bool reload_if_possible);
-
-extern const DBusObjectPathVTable bus_unit_vtable;
-
-extern const char bus_unit_interface[];
diff --git a/src/core/dbus.c b/src/core/dbus.c
deleted file mode 100644
index 2a1c66054a..0000000000
--- a/src/core/dbus.c
+++ /dev/null
@@ -1,1479 +0,0 @@
-/*-*- 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/epoll.h>
-#include <sys/timerfd.h>
-#include <errno.h>
-#include <unistd.h>
-#include <dbus/dbus.h>
-
-#include "dbus.h"
-#include "log.h"
-#include "strv.h"
-#include "cgroup.h"
-#include "mkdir.h"
-#include "missing.h"
-#include "dbus-unit.h"
-#include "dbus-job.h"
-#include "dbus-manager.h"
-#include "dbus-service.h"
-#include "dbus-socket.h"
-#include "dbus-target.h"
-#include "dbus-device.h"
-#include "dbus-mount.h"
-#include "dbus-automount.h"
-#include "dbus-snapshot.h"
-#include "dbus-swap.h"
-#include "dbus-timer.h"
-#include "dbus-path.h"
-#include "bus-errors.h"
-#include "special.h"
-#include "dbus-common.h"
-
-#define CONNECTIONS_MAX 52
-
-/* Well-known address (http://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-types) */
-#define DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "unix:path=/var/run/dbus/system_bus_socket"
-/* Only used as a fallback */
-#define DBUS_SESSION_BUS_DEFAULT_ADDRESS "autolaunch:"
-
-static const char bus_properties_interface[] = BUS_PROPERTIES_INTERFACE;
-static const char bus_introspectable_interface[] = BUS_INTROSPECTABLE_INTERFACE;
-
-const char *const bus_interface_table[] = {
- "org.freedesktop.DBus.Properties", bus_properties_interface,
- "org.freedesktop.DBus.Introspectable", bus_introspectable_interface,
- "org.freedesktop.systemd1.Manager", bus_manager_interface,
- "org.freedesktop.systemd1.Job", bus_job_interface,
- "org.freedesktop.systemd1.Unit", bus_unit_interface,
- "org.freedesktop.systemd1.Service", bus_service_interface,
- "org.freedesktop.systemd1.Socket", bus_socket_interface,
- "org.freedesktop.systemd1.Target", bus_target_interface,
- "org.freedesktop.systemd1.Device", bus_device_interface,
- "org.freedesktop.systemd1.Mount", bus_mount_interface,
- "org.freedesktop.systemd1.Automount", bus_automount_interface,
- "org.freedesktop.systemd1.Snapshot", bus_snapshot_interface,
- "org.freedesktop.systemd1.Swap", bus_swap_interface,
- "org.freedesktop.systemd1.Timer", bus_timer_interface,
- "org.freedesktop.systemd1.Path", bus_path_interface,
- NULL
-};
-
-static void bus_done_api(Manager *m);
-static void bus_done_system(Manager *m);
-static void bus_done_private(Manager *m);
-static void shutdown_connection(Manager *m, DBusConnection *c);
-
-static void bus_dispatch_status(DBusConnection *bus, DBusDispatchStatus status, void *data) {
- Manager *m = data;
-
- assert(bus);
- assert(m);
-
- /* We maintain two sets, one for those connections where we
- * requested a dispatch, and another where we didn't. And then,
- * we move the connections between the two sets. */
-
- if (status == DBUS_DISPATCH_COMPLETE)
- set_move_one(m->bus_connections, m->bus_connections_for_dispatch, bus);
- else
- set_move_one(m->bus_connections_for_dispatch, m->bus_connections, bus);
-}
-
-void bus_watch_event(Manager *m, Watch *w, int events) {
- assert(m);
- assert(w);
-
- /* This is called by the event loop whenever there is
- * something happening on D-Bus' file handles. */
-
- if (!dbus_watch_get_enabled(w->data.bus_watch))
- return;
-
- dbus_watch_handle(w->data.bus_watch, bus_events_to_flags(events));
-}
-
-static dbus_bool_t bus_add_watch(DBusWatch *bus_watch, void *data) {
- Manager *m = data;
- Watch *w;
- struct epoll_event ev;
-
- assert(bus_watch);
- assert(m);
-
- if (!(w = new0(Watch, 1)))
- return FALSE;
-
- w->fd = dbus_watch_get_unix_fd(bus_watch);
- w->type = WATCH_DBUS_WATCH;
- w->data.bus_watch = bus_watch;
-
- zero(ev);
- ev.events = bus_flags_to_events(bus_watch);
- ev.data.ptr = w;
-
- if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0) {
-
- if (errno != EEXIST) {
- free(w);
- return FALSE;
- }
-
- /* Hmm, bloody D-Bus creates multiple watches on the
- * same fd. epoll() does not like that. As a dirty
- * hack we simply dup() the fd and hence get a second
- * one we can safely add to the epoll(). */
-
- if ((w->fd = dup(w->fd)) < 0) {
- free(w);
- return FALSE;
- }
-
- if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0) {
- close_nointr_nofail(w->fd);
- free(w);
- return FALSE;
- }
-
- w->fd_is_dupped = true;
- }
-
- dbus_watch_set_data(bus_watch, w, NULL);
-
- return TRUE;
-}
-
-static void bus_remove_watch(DBusWatch *bus_watch, void *data) {
- Manager *m = data;
- Watch *w;
-
- assert(bus_watch);
- assert(m);
-
- w = dbus_watch_get_data(bus_watch);
- if (!w)
- return;
-
- assert(w->type == WATCH_DBUS_WATCH);
- assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
-
- if (w->fd_is_dupped)
- close_nointr_nofail(w->fd);
-
- free(w);
-}
-
-static void bus_toggle_watch(DBusWatch *bus_watch, void *data) {
- Manager *m = data;
- Watch *w;
- struct epoll_event ev;
-
- assert(bus_watch);
- assert(m);
-
- w = dbus_watch_get_data(bus_watch);
- if (!w)
- return;
-
- assert(w->type == WATCH_DBUS_WATCH);
-
- zero(ev);
- ev.events = bus_flags_to_events(bus_watch);
- ev.data.ptr = w;
-
- assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_MOD, w->fd, &ev) == 0);
-}
-
-static int bus_timeout_arm(Manager *m, Watch *w) {
- struct itimerspec its;
-
- assert(m);
- assert(w);
-
- zero(its);
-
- if (dbus_timeout_get_enabled(w->data.bus_timeout)) {
- timespec_store(&its.it_value, dbus_timeout_get_interval(w->data.bus_timeout) * USEC_PER_MSEC);
- its.it_interval = its.it_value;
- }
-
- if (timerfd_settime(w->fd, 0, &its, NULL) < 0)
- return -errno;
-
- return 0;
-}
-
-void bus_timeout_event(Manager *m, Watch *w, int events) {
- assert(m);
- assert(w);
-
- /* This is called by the event loop whenever there is
- * something happening on D-Bus' file handles. */
-
- if (!(dbus_timeout_get_enabled(w->data.bus_timeout)))
- return;
-
- dbus_timeout_handle(w->data.bus_timeout);
-}
-
-static dbus_bool_t bus_add_timeout(DBusTimeout *timeout, void *data) {
- Manager *m = data;
- Watch *w;
- struct epoll_event ev;
-
- assert(timeout);
- assert(m);
-
- if (!(w = new0(Watch, 1)))
- return FALSE;
-
- if ((w->fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0)
- goto fail;
-
- w->type = WATCH_DBUS_TIMEOUT;
- w->data.bus_timeout = timeout;
-
- if (bus_timeout_arm(m, w) < 0)
- goto fail;
-
- zero(ev);
- ev.events = EPOLLIN;
- ev.data.ptr = w;
-
- if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0)
- goto fail;
-
- dbus_timeout_set_data(timeout, w, NULL);
-
- return TRUE;
-
-fail:
- if (w->fd >= 0)
- close_nointr_nofail(w->fd);
-
- free(w);
- return FALSE;
-}
-
-static void bus_remove_timeout(DBusTimeout *timeout, void *data) {
- Manager *m = data;
- Watch *w;
-
- assert(timeout);
- assert(m);
-
- w = dbus_timeout_get_data(timeout);
- if (!w)
- return;
-
- assert(w->type == WATCH_DBUS_TIMEOUT);
-
- assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
- close_nointr_nofail(w->fd);
- free(w);
-}
-
-static void bus_toggle_timeout(DBusTimeout *timeout, void *data) {
- Manager *m = data;
- Watch *w;
- int r;
-
- assert(timeout);
- assert(m);
-
- w = dbus_timeout_get_data(timeout);
- if (!w)
- return;
-
- assert(w->type == WATCH_DBUS_TIMEOUT);
-
- if ((r = bus_timeout_arm(m, w)) < 0)
- log_error("Failed to rearm timer: %s", strerror(-r));
-}
-
-static DBusHandlerResult api_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
- Manager *m = data;
- DBusError error;
- DBusMessage *reply = NULL;
-
- assert(connection);
- assert(message);
- assert(m);
-
- dbus_error_init(&error);
-
- if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
- dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
- log_debug("Got D-Bus request: %s.%s() on %s",
- dbus_message_get_interface(message),
- dbus_message_get_member(message),
- dbus_message_get_path(message));
-
- if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
- log_debug("API D-Bus connection terminated.");
- bus_done_api(m);
-
- } else if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
- const char *name, *old_owner, *new_owner;
-
- if (!dbus_message_get_args(message, &error,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_STRING, &old_owner,
- DBUS_TYPE_STRING, &new_owner,
- DBUS_TYPE_INVALID))
- log_error("Failed to parse NameOwnerChanged message: %s", bus_error_message(&error));
- else {
- if (set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) name))
- log_debug("Subscription client vanished: %s (left: %u)", name, set_size(BUS_CONNECTION_SUBSCRIBED(m, connection)));
-
- if (old_owner[0] == 0)
- old_owner = NULL;
-
- if (new_owner[0] == 0)
- new_owner = NULL;
-
- manager_dispatch_bus_name_owner_changed(m, name, old_owner, new_owner);
- }
- } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Activator", "ActivationRequest")) {
- const char *name;
-
- if (!dbus_message_get_args(message, &error,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_INVALID))
- log_error("Failed to parse ActivationRequest message: %s", bus_error_message(&error));
- else {
- int r;
- Unit *u;
-
- log_debug("Got D-Bus activation request for %s", name);
-
- if (manager_unit_pending_inactive(m, SPECIAL_DBUS_SERVICE) ||
- manager_unit_pending_inactive(m, SPECIAL_DBUS_SOCKET)) {
- r = -EADDRNOTAVAIL;
- dbus_set_error(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
- } else {
- r = manager_load_unit(m, name, NULL, &error, &u);
-
- if (r >= 0 && u->refuse_manual_start)
- r = -EPERM;
-
- if (r >= 0)
- r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
- }
-
- if (r < 0) {
- const char *id, *text;
-
- log_debug("D-Bus activation failed for %s: %s", name, strerror(-r));
-
- if (!(reply = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure")))
- goto oom;
-
- id = error.name ? error.name : bus_errno_to_dbus(r);
- text = bus_error(&error, r);
-
- if (!dbus_message_set_destination(reply, DBUS_SERVICE_DBUS) ||
- !dbus_message_append_args(reply,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_STRING, &id,
- DBUS_TYPE_STRING, &text,
- DBUS_TYPE_INVALID))
- goto oom;
- }
-
- /* On success we don't do anything, the service will be spawned now */
- }
- }
-
- dbus_error_free(&error);
-
- if (reply) {
- if (!dbus_connection_send(connection, reply, NULL))
- goto oom;
-
- dbus_message_unref(reply);
- }
-
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
-oom:
- if (reply)
- dbus_message_unref(reply);
-
- dbus_error_free(&error);
-
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-}
-
-static DBusHandlerResult system_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
- Manager *m = data;
- DBusError error;
-
- assert(connection);
- assert(message);
- assert(m);
-
- dbus_error_init(&error);
-
- if (m->api_bus != m->system_bus &&
- (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
- dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL))
- log_debug("Got D-Bus request on system bus: %s.%s() on %s",
- dbus_message_get_interface(message),
- dbus_message_get_member(message),
- dbus_message_get_path(message));
-
- if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
- log_debug("System D-Bus connection terminated.");
- bus_done_system(m);
-
- } else if (m->running_as != SYSTEMD_SYSTEM &&
- dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
-
- const char *cgroup;
-
- if (!dbus_message_get_args(message, &error,
- DBUS_TYPE_STRING, &cgroup,
- DBUS_TYPE_INVALID))
- log_error("Failed to parse Released message: %s", bus_error_message(&error));
- else
- cgroup_notify_empty(m, cgroup);
- }
-
- dbus_error_free(&error);
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-static DBusHandlerResult private_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
- Manager *m = data;
- DBusError error;
-
- assert(connection);
- assert(message);
- assert(m);
-
- dbus_error_init(&error);
-
- if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
- dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
- log_debug("Got D-Bus request: %s.%s() on %s",
- dbus_message_get_interface(message),
- dbus_message_get_member(message),
- dbus_message_get_path(message));
-
- if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected"))
- shutdown_connection(m, connection);
- else if (m->running_as == SYSTEMD_SYSTEM &&
- dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
-
- const char *cgroup;
-
- if (!dbus_message_get_args(message, &error,
- DBUS_TYPE_STRING, &cgroup,
- DBUS_TYPE_INVALID))
- log_error("Failed to parse Released message: %s", bus_error_message(&error));
- else
- cgroup_notify_empty(m, cgroup);
-
- /* Forward the message to the system bus, so that user
- * instances are notified as well */
-
- if (m->system_bus)
- dbus_connection_send(m->system_bus, message, NULL);
- }
-
- dbus_error_free(&error);
-
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-unsigned bus_dispatch(Manager *m) {
- DBusConnection *c;
-
- assert(m);
-
- if (m->queued_message) {
- /* If we cannot get rid of this message we won't
- * dispatch any D-Bus messages, so that we won't end
- * up wanting to queue another message. */
-
- if (m->queued_message_connection)
- if (!dbus_connection_send(m->queued_message_connection, m->queued_message, NULL))
- return 0;
-
- dbus_message_unref(m->queued_message);
- m->queued_message = NULL;
- m->queued_message_connection = NULL;
- }
-
- if ((c = set_first(m->bus_connections_for_dispatch))) {
- if (dbus_connection_dispatch(c) == DBUS_DISPATCH_COMPLETE)
- set_move_one(m->bus_connections, m->bus_connections_for_dispatch, c);
-
- return 1;
- }
-
- return 0;
-}
-
-static void request_name_pending_cb(DBusPendingCall *pending, void *userdata) {
- DBusMessage *reply;
- DBusError error;
-
- dbus_error_init(&error);
-
- assert_se(reply = dbus_pending_call_steal_reply(pending));
-
- switch (dbus_message_get_type(reply)) {
-
- case DBUS_MESSAGE_TYPE_ERROR:
-
- assert_se(dbus_set_error_from_message(&error, reply));
- log_warning("RequestName() failed: %s", bus_error_message(&error));
- break;
-
- case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
- uint32_t r;
-
- if (!dbus_message_get_args(reply,
- &error,
- DBUS_TYPE_UINT32, &r,
- DBUS_TYPE_INVALID)) {
- log_error("Failed to parse RequestName() reply: %s", bus_error_message(&error));
- break;
- }
-
- if (r == 1)
- log_debug("Successfully acquired name.");
- else
- log_error("Name already owned.");
-
- break;
- }
-
- default:
- assert_not_reached("Invalid reply message");
- }
-
- dbus_message_unref(reply);
- dbus_error_free(&error);
-}
-
-static int request_name(Manager *m) {
- const char *name = "org.freedesktop.systemd1";
- /* Allow replacing of our name, to ease implementation of
- * reexecution, where we keep the old connection open until
- * after the new connection is set up and the name installed
- * to allow clients to synchronously wait for reexecution to
- * finish */
- uint32_t flags = DBUS_NAME_FLAG_ALLOW_REPLACEMENT|DBUS_NAME_FLAG_REPLACE_EXISTING;
- DBusMessage *message = NULL;
- DBusPendingCall *pending = NULL;
-
- if (!(message = dbus_message_new_method_call(
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS,
- "RequestName")))
- goto oom;
-
- if (!dbus_message_append_args(
- message,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_UINT32, &flags,
- DBUS_TYPE_INVALID))
- goto oom;
-
- if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
- goto oom;
-
- if (!dbus_pending_call_set_notify(pending, request_name_pending_cb, m, NULL))
- goto oom;
-
- dbus_message_unref(message);
- dbus_pending_call_unref(pending);
-
- /* We simple ask for the name and don't wait for it. Sooner or
- * later we'll have it. */
-
- return 0;
-
-oom:
- if (pending) {
- dbus_pending_call_cancel(pending);
- dbus_pending_call_unref(pending);
- }
-
- if (message)
- dbus_message_unref(message);
-
- return -ENOMEM;
-}
-
-static void query_name_list_pending_cb(DBusPendingCall *pending, void *userdata) {
- DBusMessage *reply;
- DBusError error;
- Manager *m = userdata;
-
- assert(m);
-
- dbus_error_init(&error);
-
- assert_se(reply = dbus_pending_call_steal_reply(pending));
-
- switch (dbus_message_get_type(reply)) {
-
- case DBUS_MESSAGE_TYPE_ERROR:
-
- assert_se(dbus_set_error_from_message(&error, reply));
- log_warning("ListNames() failed: %s", bus_error_message(&error));
- break;
-
- case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
- int r;
- char **l;
-
- if ((r = bus_parse_strv(reply, &l)) < 0)
- log_warning("Failed to parse ListNames() reply: %s", strerror(-r));
- else {
- char **t;
-
- STRV_FOREACH(t, l)
- /* This is a bit hacky, we say the
- * owner of the name is the name
- * itself, because we don't want the
- * extra traffic to figure out the
- * real owner. */
- manager_dispatch_bus_name_owner_changed(m, *t, NULL, *t);
-
- strv_free(l);
- }
-
- break;
- }
-
- default:
- assert_not_reached("Invalid reply message");
- }
-
- dbus_message_unref(reply);
- dbus_error_free(&error);
-}
-
-static int query_name_list(Manager *m) {
- DBusMessage *message = NULL;
- DBusPendingCall *pending = NULL;
-
- /* Asks for the currently installed bus names */
-
- if (!(message = dbus_message_new_method_call(
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS,
- "ListNames")))
- goto oom;
-
- if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
- goto oom;
-
- if (!dbus_pending_call_set_notify(pending, query_name_list_pending_cb, m, NULL))
- goto oom;
-
- dbus_message_unref(message);
- dbus_pending_call_unref(pending);
-
- /* We simple ask for the list and don't wait for it. Sooner or
- * later we'll get it. */
-
- return 0;
-
-oom:
- if (pending) {
- dbus_pending_call_cancel(pending);
- dbus_pending_call_unref(pending);
- }
-
- if (message)
- dbus_message_unref(message);
-
- return -ENOMEM;
-}
-
-static int bus_setup_loop(Manager *m, DBusConnection *bus) {
- assert(m);
- assert(bus);
-
- dbus_connection_set_exit_on_disconnect(bus, FALSE);
-
- if (!dbus_connection_set_watch_functions(bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) ||
- !dbus_connection_set_timeout_functions(bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL))
- return log_oom();
-
- if (set_put(m->bus_connections_for_dispatch, bus) < 0)
- return log_oom();
-
- dbus_connection_set_dispatch_status_function(bus, bus_dispatch_status, m, NULL);
- return 0;
-}
-
-static dbus_bool_t allow_only_same_user(DBusConnection *connection, unsigned long uid, void *data) {
- return uid == 0 || uid == geteuid();
-}
-
-static void bus_new_connection(
- DBusServer *server,
- DBusConnection *new_connection,
- void *data) {
-
- Manager *m = data;
-
- assert(m);
-
- if (set_size(m->bus_connections) >= CONNECTIONS_MAX) {
- log_error("Too many concurrent connections.");
- return;
- }
-
- dbus_connection_set_unix_user_function(new_connection, allow_only_same_user, NULL, NULL);
-
- if (bus_setup_loop(m, new_connection) < 0)
- return;
-
- if (!dbus_connection_register_object_path(new_connection, "/org/freedesktop/systemd1", &bus_manager_vtable, m) ||
- !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) ||
- !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) ||
- !dbus_connection_add_filter(new_connection, private_bus_message_filter, m, NULL)) {
- log_oom();
- return;
- }
-
- log_debug("Accepted connection on private bus.");
-
- dbus_connection_ref(new_connection);
-}
-
-static int init_registered_system_bus(Manager *m) {
- char *id;
-
- if (!dbus_connection_add_filter(m->system_bus, system_bus_message_filter, m, NULL))
- return log_oom();
-
- if (m->running_as != SYSTEMD_SYSTEM) {
- DBusError error;
-
- dbus_error_init(&error);
-
- dbus_bus_add_match(m->system_bus,
- "type='signal',"
- "interface='org.freedesktop.systemd1.Agent',"
- "member='Released',"
- "path='/org/freedesktop/systemd1/agent'",
- &error);
-
- if (dbus_error_is_set(&error)) {
- log_error("Failed to register match: %s", bus_error_message(&error));
- dbus_error_free(&error);
- return -1;
- }
- }
-
- log_debug("Successfully connected to system D-Bus bus %s as %s",
- strnull((id = dbus_connection_get_server_id(m->system_bus))),
- strnull(dbus_bus_get_unique_name(m->system_bus)));
- dbus_free(id);
-
- return 0;
-}
-
-static int init_registered_api_bus(Manager *m) {
- int r;
-
- if (!dbus_connection_register_object_path(m->api_bus, "/org/freedesktop/systemd1", &bus_manager_vtable, m) ||
- !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) ||
- !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) ||
- !dbus_connection_add_filter(m->api_bus, api_bus_message_filter, m, NULL))
- return log_oom();
-
- /* Get NameOwnerChange messages */
- dbus_bus_add_match(m->api_bus,
- "type='signal',"
- "sender='"DBUS_SERVICE_DBUS"',"
- "interface='"DBUS_INTERFACE_DBUS"',"
- "member='NameOwnerChanged',"
- "path='"DBUS_PATH_DBUS"'",
- NULL);
-
- /* Get activation requests */
- dbus_bus_add_match(m->api_bus,
- "type='signal',"
- "sender='"DBUS_SERVICE_DBUS"',"
- "interface='org.freedesktop.systemd1.Activator',"
- "member='ActivationRequest',"
- "path='"DBUS_PATH_DBUS"'",
- NULL);
-
- r = request_name(m);
- if (r < 0)
- return r;
-
- r = query_name_list(m);
- if (r < 0)
- return r;
-
- if (m->running_as == SYSTEMD_USER) {
- char *id;
- log_debug("Successfully connected to API D-Bus bus %s as %s",
- strnull((id = dbus_connection_get_server_id(m->api_bus))),
- strnull(dbus_bus_get_unique_name(m->api_bus)));
- dbus_free(id);
- } else
- log_debug("Successfully initialized API on the system bus");
-
- return 0;
-}
-
-static void bus_register_cb(DBusPendingCall *pending, void *userdata) {
- Manager *m = userdata;
- DBusConnection **conn;
- DBusMessage *reply;
- DBusError error;
- const char *name;
- int r = 0;
-
- dbus_error_init(&error);
-
- conn = dbus_pending_call_get_data(pending, m->conn_data_slot);
- assert(conn == &m->system_bus || conn == &m->api_bus);
-
- reply = dbus_pending_call_steal_reply(pending);
-
- switch (dbus_message_get_type(reply)) {
- case DBUS_MESSAGE_TYPE_ERROR:
- assert_se(dbus_set_error_from_message(&error, reply));
- log_warning("Failed to register to bus: %s", bus_error_message(&error));
- r = -1;
- break;
- case DBUS_MESSAGE_TYPE_METHOD_RETURN:
- if (!dbus_message_get_args(reply, &error,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_INVALID)) {
- log_error("Failed to parse Hello reply: %s", bus_error_message(&error));
- r = -1;
- break;
- }
-
- log_debug("Received name %s in reply to Hello", name);
- if (!dbus_bus_set_unique_name(*conn, name)) {
- log_error("Failed to set unique name");
- r = -1;
- break;
- }
-
- if (conn == &m->system_bus) {
- r = init_registered_system_bus(m);
- if (r == 0 && m->running_as == SYSTEMD_SYSTEM)
- r = init_registered_api_bus(m);
- } else
- r = init_registered_api_bus(m);
-
- break;
- default:
- assert_not_reached("Invalid reply message");
- }
-
- dbus_message_unref(reply);
- dbus_error_free(&error);
-
- if (r < 0) {
- if (conn == &m->system_bus) {
- log_debug("Failed setting up the system bus");
- bus_done_system(m);
- } else {
- log_debug("Failed setting up the API bus");
- bus_done_api(m);
- }
- }
-}
-
-static int manager_bus_async_register(Manager *m, DBusConnection **conn) {
- DBusMessage *message = NULL;
- DBusPendingCall *pending = NULL;
-
- message = dbus_message_new_method_call(DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS,
- "Hello");
- if (!message)
- goto oom;
-
- if (!dbus_connection_send_with_reply(*conn, message, &pending, -1))
- goto oom;
-
- if (!dbus_pending_call_set_data(pending, m->conn_data_slot, conn, NULL))
- goto oom;
-
- if (!dbus_pending_call_set_notify(pending, bus_register_cb, m, NULL))
- goto oom;
-
- dbus_message_unref(message);
- dbus_pending_call_unref(pending);
-
- return 0;
-oom:
- if (pending) {
- dbus_pending_call_cancel(pending);
- dbus_pending_call_unref(pending);
- }
-
- if (message)
- dbus_message_unref(message);
-
- return -ENOMEM;
-}
-
-static DBusConnection* manager_bus_connect_private(Manager *m, DBusBusType type) {
- const char *address;
- DBusConnection *connection;
- DBusError error;
-
- switch (type) {
- case DBUS_BUS_SYSTEM:
- address = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
- if (!address || !address[0])
- address = DBUS_SYSTEM_BUS_DEFAULT_ADDRESS;
- break;
- case DBUS_BUS_SESSION:
- address = secure_getenv("DBUS_SESSION_BUS_ADDRESS");
- if (!address || !address[0])
- address = DBUS_SESSION_BUS_DEFAULT_ADDRESS;
- break;
- default:
- assert_not_reached("Invalid bus type");
- }
-
- dbus_error_init(&error);
-
- connection = dbus_connection_open_private(address, &error);
- if (!connection) {
- log_warning("Failed to open private bus connection: %s", bus_error_message(&error));
- goto fail;
- }
-
- return connection;
-fail:
- if (connection)
- dbus_connection_close(connection);
- dbus_error_free(&error);
- return NULL;
-}
-
-static int bus_init_system(Manager *m) {
- int r;
-
- if (m->system_bus)
- return 0;
-
- m->system_bus = manager_bus_connect_private(m, DBUS_BUS_SYSTEM);
- if (!m->system_bus) {
- log_debug("Failed to connect to system D-Bus, retrying later");
- r = 0;
- goto fail;
- }
-
- r = bus_setup_loop(m, m->system_bus);
- if (r < 0)
- goto fail;
-
- r = manager_bus_async_register(m, &m->system_bus);
- if (r < 0)
- goto fail;
-
- return 0;
-fail:
- bus_done_system(m);
-
- return r;
-}
-
-static int bus_init_api(Manager *m) {
- int r;
-
- if (m->api_bus)
- return 0;
-
- if (m->running_as == SYSTEMD_SYSTEM) {
- m->api_bus = m->system_bus;
- /* In this mode there is no distinct connection to the API bus,
- * the API is published on the system bus.
- * bus_register_cb() is aware of that and will init the API
- * when the system bus gets registered.
- * No need to setup anything here. */
- return 0;
- }
-
- m->api_bus = manager_bus_connect_private(m, DBUS_BUS_SESSION);
- if (!m->api_bus) {
- log_debug("Failed to connect to API D-Bus, retrying later");
- r = 0;
- goto fail;
- }
-
- r = bus_setup_loop(m, m->api_bus);
- if (r < 0)
- goto fail;
-
- r = manager_bus_async_register(m, &m->api_bus);
- if (r < 0)
- goto fail;
-
- return 0;
-fail:
- bus_done_api(m);
-
- return r;
-}
-
-static int bus_init_private(Manager *m) {
- DBusError error;
- int r;
- const char *const external_only[] = {
- "EXTERNAL",
- NULL
- };
-
- assert(m);
-
- dbus_error_init(&error);
-
- if (m->private_bus)
- return 0;
-
- if (m->running_as == SYSTEMD_SYSTEM) {
-
- /* We want the private bus only when running as init */
- if (getpid() != 1)
- return 0;
-
- unlink("/run/systemd/private");
- m->private_bus = dbus_server_listen("unix:path=/run/systemd/private", &error);
- } else {
- const char *e;
- char *p;
-
- e = secure_getenv("XDG_RUNTIME_DIR");
- if (!e)
- return 0;
-
- if (asprintf(&p, "unix:path=%s/systemd/private", e) < 0) {
- r = log_oom();
- goto fail;
- }
-
- mkdir_parents_label(p+10, 0755);
- unlink(p+10);
- m->private_bus = dbus_server_listen(p, &error);
- free(p);
- }
-
- if (!m->private_bus) {
- log_error("Failed to create private D-Bus server: %s", bus_error_message(&error));
- r = -EIO;
- goto fail;
- }
-
- if (!dbus_server_set_auth_mechanisms(m->private_bus, (const char**) external_only) ||
- !dbus_server_set_watch_functions(m->private_bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) ||
- !dbus_server_set_timeout_functions(m->private_bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL)) {
- r = log_oom();
- goto fail;
- }
-
- dbus_server_set_new_connection_function(m->private_bus, bus_new_connection, m, NULL);
-
- log_debug("Successfully created private D-Bus server.");
-
- return 0;
-
-fail:
- bus_done_private(m);
- dbus_error_free(&error);
-
- return r;
-}
-
-int bus_init(Manager *m, bool try_bus_connect) {
- int r;
-
- if (set_ensure_allocated(&m->bus_connections, trivial_hash_func, trivial_compare_func) < 0 ||
- set_ensure_allocated(&m->bus_connections_for_dispatch, trivial_hash_func, trivial_compare_func) < 0)
- goto oom;
-
- if (m->name_data_slot < 0)
- if (!dbus_pending_call_allocate_data_slot(&m->name_data_slot))
- goto oom;
-
- if (m->conn_data_slot < 0)
- if (!dbus_pending_call_allocate_data_slot(&m->conn_data_slot))
- goto oom;
-
- if (m->subscribed_data_slot < 0)
- if (!dbus_connection_allocate_data_slot(&m->subscribed_data_slot))
- goto oom;
-
- if (try_bus_connect) {
- if ((r = bus_init_system(m)) < 0 ||
- (r = bus_init_api(m)) < 0)
- return r;
- }
-
- if ((r = bus_init_private(m)) < 0)
- return r;
-
- return 0;
-oom:
- return log_oom();
-}
-
-static void shutdown_connection(Manager *m, DBusConnection *c) {
- Set *s;
- Job *j;
- Iterator i;
-
- HASHMAP_FOREACH(j, m->jobs, i) {
- JobBusClient *cl, *nextcl;
- LIST_FOREACH_SAFE(client, cl, nextcl, j->bus_client_list) {
- if (cl->bus == c) {
- LIST_REMOVE(JobBusClient, client, j->bus_client_list, cl);
- free(cl);
- }
- }
- }
-
- set_remove(m->bus_connections, c);
- set_remove(m->bus_connections_for_dispatch, c);
-
- if ((s = BUS_CONNECTION_SUBSCRIBED(m, c))) {
- char *t;
-
- while ((t = set_steal_first(s)))
- free(t);
-
- set_free(s);
- }
-
- if (m->queued_message_connection == c) {
- m->queued_message_connection = NULL;
-
- if (m->queued_message) {
- dbus_message_unref(m->queued_message);
- m->queued_message = NULL;
- }
- }
-
- dbus_connection_set_dispatch_status_function(c, NULL, NULL, NULL);
- /* system manager cannot afford to block on DBus */
- if (m->running_as != SYSTEMD_SYSTEM)
- dbus_connection_flush(c);
- dbus_connection_close(c);
- dbus_connection_unref(c);
-}
-
-static void bus_done_api(Manager *m) {
- if (!m->api_bus)
- return;
-
- if (m->running_as == SYSTEMD_USER)
- shutdown_connection(m, m->api_bus);
-
- m->api_bus = NULL;
-
- if (m->queued_message) {
- dbus_message_unref(m->queued_message);
- m->queued_message = NULL;
- }
-}
-
-static void bus_done_system(Manager *m) {
- if (!m->system_bus)
- return;
-
- if (m->running_as == SYSTEMD_SYSTEM)
- bus_done_api(m);
-
- shutdown_connection(m, m->system_bus);
- m->system_bus = NULL;
-}
-
-static void bus_done_private(Manager *m) {
- if (!m->private_bus)
- return;
-
- dbus_server_disconnect(m->private_bus);
- dbus_server_unref(m->private_bus);
- m->private_bus = NULL;
-}
-
-void bus_done(Manager *m) {
- DBusConnection *c;
-
- bus_done_api(m);
- bus_done_system(m);
- bus_done_private(m);
-
- while ((c = set_steal_first(m->bus_connections)))
- shutdown_connection(m, c);
-
- while ((c = set_steal_first(m->bus_connections_for_dispatch)))
- shutdown_connection(m, c);
-
- set_free(m->bus_connections);
- set_free(m->bus_connections_for_dispatch);
-
- if (m->name_data_slot >= 0)
- dbus_pending_call_free_data_slot(&m->name_data_slot);
-
- if (m->conn_data_slot >= 0)
- dbus_pending_call_free_data_slot(&m->conn_data_slot);
-
- if (m->subscribed_data_slot >= 0)
- dbus_connection_free_data_slot(&m->subscribed_data_slot);
-}
-
-static void query_pid_pending_cb(DBusPendingCall *pending, void *userdata) {
- Manager *m = userdata;
- DBusMessage *reply;
- DBusError error;
- const char *name;
-
- dbus_error_init(&error);
-
- assert_se(name = BUS_PENDING_CALL_NAME(m, pending));
- assert_se(reply = dbus_pending_call_steal_reply(pending));
-
- switch (dbus_message_get_type(reply)) {
-
- case DBUS_MESSAGE_TYPE_ERROR:
-
- assert_se(dbus_set_error_from_message(&error, reply));
- log_warning("GetConnectionUnixProcessID() failed: %s", bus_error_message(&error));
- break;
-
- case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
- uint32_t r;
-
- if (!dbus_message_get_args(reply,
- &error,
- DBUS_TYPE_UINT32, &r,
- DBUS_TYPE_INVALID)) {
- log_error("Failed to parse GetConnectionUnixProcessID() reply: %s", bus_error_message(&error));
- break;
- }
-
- manager_dispatch_bus_query_pid_done(m, name, (pid_t) r);
- break;
- }
-
- default:
- assert_not_reached("Invalid reply message");
- }
-
- dbus_message_unref(reply);
- dbus_error_free(&error);
-}
-
-int bus_query_pid(Manager *m, const char *name) {
- DBusMessage *message = NULL;
- DBusPendingCall *pending = NULL;
- char *n = NULL;
-
- assert(m);
- assert(name);
-
- if (!(message = dbus_message_new_method_call(
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS,
- "GetConnectionUnixProcessID")))
- goto oom;
-
- if (!(dbus_message_append_args(
- message,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_INVALID)))
- goto oom;
-
- if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
- goto oom;
-
- if (!(n = strdup(name)))
- goto oom;
-
- if (!dbus_pending_call_set_data(pending, m->name_data_slot, n, free))
- goto oom;
-
- n = NULL;
-
- if (!dbus_pending_call_set_notify(pending, query_pid_pending_cb, m, NULL))
- goto oom;
-
- dbus_message_unref(message);
- dbus_pending_call_unref(pending);
-
- return 0;
-
-oom:
- free(n);
-
- if (pending) {
- dbus_pending_call_cancel(pending);
- dbus_pending_call_unref(pending);
- }
-
- if (message)
- dbus_message_unref(message);
-
- return -ENOMEM;
-}
-
-int bus_broadcast(Manager *m, DBusMessage *message) {
- bool oom = false;
- Iterator i;
- DBusConnection *c;
-
- assert(m);
- assert(message);
-
- SET_FOREACH(c, m->bus_connections_for_dispatch, i)
- if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM)
- oom = !dbus_connection_send(c, message, NULL);
-
- SET_FOREACH(c, m->bus_connections, i)
- if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM)
- oom = !dbus_connection_send(c, message, NULL);
-
- return oom ? -ENOMEM : 0;
-}
-
-bool bus_has_subscriber(Manager *m) {
- Iterator i;
- DBusConnection *c;
-
- assert(m);
-
- SET_FOREACH(c, m->bus_connections_for_dispatch, i)
- if (bus_connection_has_subscriber(m, c))
- return true;
-
- SET_FOREACH(c, m->bus_connections, i)
- if (bus_connection_has_subscriber(m, c))
- return true;
-
- return false;
-}
-
-bool bus_connection_has_subscriber(Manager *m, DBusConnection *c) {
- assert(m);
- assert(c);
-
- return !set_isempty(BUS_CONNECTION_SUBSCRIBED(m, c));
-}
-
-int bus_fdset_add_all(Manager *m, FDSet *fds) {
- Iterator i;
- DBusConnection *c;
-
- assert(m);
- assert(fds);
-
- /* When we are about to reexecute we add all D-Bus fds to the
- * set to pass over to the newly executed systemd. They won't
- * be used there however, except that they are closed at the
- * very end of deserialization, those making it possible for
- * clients to synchronously wait for systemd to reexec by
- * simply waiting for disconnection */
-
- SET_FOREACH(c, m->bus_connections_for_dispatch, i) {
- int fd;
-
- if (dbus_connection_get_unix_fd(c, &fd)) {
- fd = fdset_put_dup(fds, fd);
-
- if (fd < 0)
- return fd;
- }
- }
-
- SET_FOREACH(c, m->bus_connections, i) {
- int fd;
-
- if (dbus_connection_get_unix_fd(c, &fd)) {
- fd = fdset_put_dup(fds, fd);
-
- if (fd < 0)
- return fd;
- }
- }
-
- return 0;
-}
-
-void bus_broadcast_finished(
- Manager *m,
- usec_t firmware_usec,
- usec_t loader_usec,
- usec_t kernel_usec,
- usec_t initrd_usec,
- usec_t userspace_usec,
- usec_t total_usec) {
-
- DBusMessage *message;
-
- assert(m);
-
- message = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
- if (!message) {
- log_oom();
- return;
- }
-
- assert_cc(sizeof(usec_t) == sizeof(uint64_t));
- if (!dbus_message_append_args(message,
- DBUS_TYPE_UINT64, &firmware_usec,
- DBUS_TYPE_UINT64, &loader_usec,
- DBUS_TYPE_UINT64, &kernel_usec,
- DBUS_TYPE_UINT64, &initrd_usec,
- DBUS_TYPE_UINT64, &userspace_usec,
- DBUS_TYPE_UINT64, &total_usec,
- DBUS_TYPE_INVALID)) {
- log_oom();
- goto finish;
- }
-
-
- if (bus_broadcast(m, message) < 0) {
- log_oom();
- goto finish;
- }
-
-finish:
- if (message)
- dbus_message_unref(message);
-}
diff --git a/src/core/dbus.h b/src/core/dbus.h
deleted file mode 100644
index c7a058e198..0000000000
--- a/src/core/dbus.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*-*- 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 <dbus/dbus.h>
-
-#include "manager.h"
-
-int bus_init(Manager *m, bool try_bus_connect);
-void bus_done(Manager *m);
-
-unsigned bus_dispatch(Manager *m);
-
-void bus_watch_event(Manager *m, Watch *w, int events);
-void bus_timeout_event(Manager *m, Watch *w, int events);
-
-int bus_query_pid(Manager *m, const char *name);
-
-int bus_broadcast(Manager *m, DBusMessage *message);
-
-bool bus_has_subscriber(Manager *m);
-bool bus_connection_has_subscriber(Manager *m, DBusConnection *c);
-
-int bus_fdset_add_all(Manager *m, FDSet *fds);
-
-void bus_broadcast_finished(Manager *m, usec_t firmware_usec, usec_t loader_usec, usec_t kernel_usec, usec_t initrd_usec, usec_t userspace_usec, usec_t total_usec);
-
-#define BUS_CONNECTION_SUBSCRIBED(m, c) dbus_connection_get_data((c), (m)->subscribed_data_slot)
-#define BUS_PENDING_CALL_NAME(m, p) dbus_pending_call_get_data((p), (m)->name_data_slot)
-
-extern const char * const bus_interface_table[];
diff --git a/src/core/device.c b/src/core/device.c
deleted file mode 100644
index be76cafaed..0000000000
--- a/src/core/device.c
+++ /dev/null
@@ -1,644 +0,0 @@
-/*-*- 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 <errno.h>
-#include <sys/epoll.h>
-#include <libudev.h>
-
-#include "unit.h"
-#include "device.h"
-#include "strv.h"
-#include "log.h"
-#include "unit-name.h"
-#include "dbus-device.h"
-#include "def.h"
-#include "path-util.h"
-
-static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = {
- [DEVICE_DEAD] = UNIT_INACTIVE,
- [DEVICE_PLUGGED] = UNIT_ACTIVE
-};
-
-static void device_unset_sysfs(Device *d) {
- Device *first;
-
- assert(d);
-
- if (!d->sysfs)
- return;
-
- /* Remove this unit from the chain of devices which share the
- * same sysfs path. */
- first = hashmap_get(UNIT(d)->manager->devices_by_sysfs, d->sysfs);
- LIST_REMOVE(Device, same_sysfs, first, d);
-
- if (first)
- hashmap_remove_and_replace(UNIT(d)->manager->devices_by_sysfs, d->sysfs, first->sysfs, first);
- else
- hashmap_remove(UNIT(d)->manager->devices_by_sysfs, d->sysfs);
-
- free(d->sysfs);
- d->sysfs = NULL;
-}
-
-static void device_init(Unit *u) {
- Device *d = DEVICE(u);
-
- assert(d);
- assert(UNIT(d)->load_state == UNIT_STUB);
-
- /* In contrast to all other unit types we timeout jobs waiting
- * for devices by default. This is because they otherwise wait
- * indefinitely for plugged in devices, something which cannot
- * happen for the other units since their operations time out
- * anyway. */
- UNIT(d)->job_timeout = DEFAULT_TIMEOUT_USEC;
-
- UNIT(d)->ignore_on_isolate = true;
- UNIT(d)->ignore_on_snapshot = true;
-}
-
-static void device_done(Unit *u) {
- Device *d = DEVICE(u);
-
- assert(d);
-
- device_unset_sysfs(d);
-}
-
-static void device_set_state(Device *d, DeviceState state) {
- DeviceState old_state;
- assert(d);
-
- old_state = d->state;
- d->state = state;
-
- if (state != old_state)
- log_debug("%s changed %s -> %s",
- UNIT(d)->id,
- device_state_to_string(old_state),
- device_state_to_string(state));
-
- unit_notify(UNIT(d), state_translation_table[old_state], state_translation_table[state], true);
-}
-
-static int device_coldplug(Unit *u) {
- Device *d = DEVICE(u);
-
- assert(d);
- assert(d->state == DEVICE_DEAD);
-
- if (d->sysfs)
- device_set_state(d, DEVICE_PLUGGED);
-
- return 0;
-}
-
-static void device_dump(Unit *u, FILE *f, const char *prefix) {
- Device *d = DEVICE(u);
-
- assert(d);
-
- fprintf(f,
- "%sDevice State: %s\n"
- "%sSysfs Path: %s\n",
- prefix, device_state_to_string(d->state),
- prefix, strna(d->sysfs));
-}
-
-static UnitActiveState device_active_state(Unit *u) {
- assert(u);
-
- return state_translation_table[DEVICE(u)->state];
-}
-
-static const char *device_sub_state_to_string(Unit *u) {
- assert(u);
-
- return device_state_to_string(DEVICE(u)->state);
-}
-
-static int device_add_escaped_name(Unit *u, const char *dn) {
- char *e;
- int r;
-
- assert(u);
- assert(dn);
- assert(dn[0] == '/');
-
- e = unit_name_from_path(dn, ".device");
- if (!e)
- return -ENOMEM;
-
- r = unit_add_name(u, e);
- free(e);
-
- if (r < 0 && r != -EEXIST)
- return r;
-
- return 0;
-}
-
-static int device_find_escape_name(Manager *m, const char *dn, Unit **_u) {
- char *e;
- Unit *u;
-
- assert(m);
- assert(dn);
- assert(dn[0] == '/');
- assert(_u);
-
- e = unit_name_from_path(dn, ".device");
- if (!e)
- return -ENOMEM;
-
- u = manager_get_unit(m, e);
- free(e);
-
- if (u) {
- *_u = u;
- return 1;
- }
-
- return 0;
-}
-
-static int device_update_unit(Manager *m, struct udev_device *dev, const char *path, bool main) {
- const char *sysfs, *model;
- Unit *u = NULL;
- int r;
- bool delete;
-
- assert(m);
-
- if (!(sysfs = udev_device_get_syspath(dev)))
- return -ENOMEM;
-
- if ((r = device_find_escape_name(m, path, &u)) < 0)
- return r;
-
- if (u && DEVICE(u)->sysfs && !path_equal(DEVICE(u)->sysfs, sysfs))
- return -EEXIST;
-
- if (!u) {
- delete = true;
-
- u = unit_new(m, sizeof(Device));
- if (!u)
- return -ENOMEM;
-
- r = device_add_escaped_name(u, path);
- if (r < 0)
- goto fail;
-
- unit_add_to_load_queue(u);
- } else
- delete = false;
-
- /* If this was created via some dependency and has not
- * actually been seen yet ->sysfs will not be
- * initialized. Hence initialize it if necessary. */
-
- if (!DEVICE(u)->sysfs) {
- Device *first;
-
- if (!(DEVICE(u)->sysfs = strdup(sysfs))) {
- r = -ENOMEM;
- goto fail;
- }
-
- if (!m->devices_by_sysfs)
- if (!(m->devices_by_sysfs = hashmap_new(string_hash_func, string_compare_func))) {
- r = -ENOMEM;
- goto fail;
- }
-
- first = hashmap_get(m->devices_by_sysfs, sysfs);
- LIST_PREPEND(Device, same_sysfs, first, DEVICE(u));
-
- if ((r = hashmap_replace(m->devices_by_sysfs, DEVICE(u)->sysfs, first)) < 0)
- goto fail;
- }
-
- if ((model = udev_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE")) ||
- (model = udev_device_get_property_value(dev, "ID_MODEL"))) {
- if ((r = unit_set_description(u, model)) < 0)
- goto fail;
- } else
- if ((r = unit_set_description(u, path)) < 0)
- goto fail;
-
- if (main) {
- /* The additional systemd udev properties we only
- * interpret for the main object */
- const char *wants, *alias;
-
- alias = udev_device_get_property_value(dev, "SYSTEMD_ALIAS");
- if (alias) {
- char *state, *w;
- size_t l;
-
- FOREACH_WORD_QUOTED(w, l, alias, state) {
- char *e;
-
- e = strndup(w, l);
- if (!e) {
- r = -ENOMEM;
- goto fail;
- }
-
- if (!is_path(e)) {
- log_warning("SYSTEMD_ALIAS for %s is not a path, ignoring: %s", sysfs, e);
- free(e);
- } else {
- device_update_unit(m, dev, e, false);
- free(e);
- }
- }
- }
-
- wants = udev_device_get_property_value(dev, "SYSTEMD_WANTS");
- if (wants) {
- char *state, *w;
- size_t l;
-
- FOREACH_WORD_QUOTED(w, l, wants, state) {
- char *e;
-
- e = strndup(w, l);
- if (!e) {
- r = -ENOMEM;
- goto fail;
- }
-
- r = unit_add_dependency_by_name(u, UNIT_WANTS, e, NULL, true);
- free(e);
- if (r < 0)
- goto fail;
- }
- }
- }
-
- unit_add_to_dbus_queue(u);
- return 0;
-
-fail:
- log_warning("Failed to load device unit: %s", strerror(-r));
-
- if (delete && u)
- unit_free(u);
-
- return r;
-}
-
-static int device_process_new_device(Manager *m, struct udev_device *dev, bool update_state) {
- const char *sysfs, *dn;
- struct udev_list_entry *item = NULL, *first = NULL;
-
- assert(m);
-
- if (!(sysfs = udev_device_get_syspath(dev)))
- return -ENOMEM;
-
- /* Add the main unit named after the sysfs path */
- device_update_unit(m, dev, sysfs, true);
-
- /* Add an additional unit for the device node */
- if ((dn = udev_device_get_devnode(dev)))
- device_update_unit(m, dev, dn, false);
-
- /* Add additional units for all symlinks */
- first = udev_device_get_devlinks_list_entry(dev);
- udev_list_entry_foreach(item, first) {
- const char *p;
- struct stat st;
-
- /* Don't bother with the /dev/block links */
- p = udev_list_entry_get_name(item);
-
- if (path_startswith(p, "/dev/block/") ||
- path_startswith(p, "/dev/char/"))
- continue;
-
- /* Verify that the symlink in the FS actually belongs
- * to this device. This is useful to deal with
- * conflicting devices, e.g. when two disks want the
- * same /dev/disk/by-label/xxx link because they have
- * the same label. We want to make sure that the same
- * device that won the symlink wins in systemd, so we
- * check the device node major/minor*/
- if (stat(p, &st) >= 0)
- if ((!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) ||
- st.st_rdev != udev_device_get_devnum(dev))
- continue;
-
- device_update_unit(m, dev, p, false);
- }
-
- if (update_state) {
- Device *d, *l;
-
- manager_dispatch_load_queue(m);
-
- l = hashmap_get(m->devices_by_sysfs, sysfs);
- LIST_FOREACH(same_sysfs, d, l)
- device_set_state(d, DEVICE_PLUGGED);
- }
-
- return 0;
-}
-
-static int device_process_path(Manager *m, const char *path, bool update_state) {
- int r;
- struct udev_device *dev;
-
- assert(m);
- assert(path);
-
- if (!(dev = udev_device_new_from_syspath(m->udev, path))) {
- log_warning("Failed to get udev device object from udev for path %s.", path);
- return -ENOMEM;
- }
-
- r = device_process_new_device(m, dev, update_state);
- udev_device_unref(dev);
- return r;
-}
-
-static int device_process_removed_device(Manager *m, struct udev_device *dev) {
- const char *sysfs;
- Device *d;
-
- assert(m);
- assert(dev);
-
- if (!(sysfs = udev_device_get_syspath(dev)))
- return -ENOMEM;
-
- /* Remove all units of this sysfs path */
- while ((d = hashmap_get(m->devices_by_sysfs, sysfs))) {
- device_unset_sysfs(d);
- device_set_state(d, DEVICE_DEAD);
- }
-
- return 0;
-}
-
-static Unit *device_following(Unit *u) {
- Device *d = DEVICE(u);
- Device *other, *first = NULL;
-
- assert(d);
-
- if (startswith(u->id, "sys-"))
- return NULL;
-
- /* Make everybody follow the unit that's named after the sysfs path */
- for (other = d->same_sysfs_next; other; other = other->same_sysfs_next)
- if (startswith(UNIT(other)->id, "sys-"))
- return UNIT(other);
-
- for (other = d->same_sysfs_prev; other; other = other->same_sysfs_prev) {
- if (startswith(UNIT(other)->id, "sys-"))
- return UNIT(other);
-
- first = other;
- }
-
- return UNIT(first);
-}
-
-static int device_following_set(Unit *u, Set **_s) {
- Device *d = DEVICE(u);
- Device *other;
- Set *s;
- int r;
-
- assert(d);
- assert(_s);
-
- if (!d->same_sysfs_prev && !d->same_sysfs_next) {
- *_s = NULL;
- return 0;
- }
-
- if (!(s = set_new(NULL, NULL)))
- return -ENOMEM;
-
- for (other = d->same_sysfs_next; other; other = other->same_sysfs_next)
- if ((r = set_put(s, other)) < 0)
- goto fail;
-
- for (other = d->same_sysfs_prev; other; other = other->same_sysfs_prev)
- if ((r = set_put(s, other)) < 0)
- goto fail;
-
- *_s = s;
- return 1;
-
-fail:
- set_free(s);
- return r;
-}
-
-static void device_shutdown(Manager *m) {
- assert(m);
-
- if (m->udev_monitor) {
- udev_monitor_unref(m->udev_monitor);
- m->udev_monitor = NULL;
- }
-
- if (m->udev) {
- udev_unref(m->udev);
- m->udev = NULL;
- }
-
- hashmap_free(m->devices_by_sysfs);
- m->devices_by_sysfs = NULL;
-}
-
-static int device_enumerate(Manager *m) {
- struct epoll_event ev;
- int r;
- struct udev_enumerate *e = NULL;
- struct udev_list_entry *item = NULL, *first = NULL;
-
- assert(m);
-
- if (!m->udev) {
- if (!(m->udev = udev_new()))
- return -ENOMEM;
-
- if (!(m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev"))) {
- r = -ENOMEM;
- goto fail;
- }
-
- /* This will fail if we are unprivileged, but that
- * should not matter much, as user instances won't run
- * during boot. */
- udev_monitor_set_receive_buffer_size(m->udev_monitor, 128*1024*1024);
-
- if (udev_monitor_filter_add_match_tag(m->udev_monitor, "systemd") < 0) {
- r = -ENOMEM;
- goto fail;
- }
-
- if (udev_monitor_enable_receiving(m->udev_monitor) < 0) {
- r = -EIO;
- goto fail;
- }
-
- m->udev_watch.type = WATCH_UDEV;
- m->udev_watch.fd = udev_monitor_get_fd(m->udev_monitor);
-
- zero(ev);
- ev.events = EPOLLIN;
- ev.data.ptr = &m->udev_watch;
-
- if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_watch.fd, &ev) < 0)
- return -errno;
- }
-
- if (!(e = udev_enumerate_new(m->udev))) {
- r = -ENOMEM;
- goto fail;
- }
- if (udev_enumerate_add_match_tag(e, "systemd") < 0) {
- r = -EIO;
- goto fail;
- }
-
- if (udev_enumerate_scan_devices(e) < 0) {
- r = -EIO;
- goto fail;
- }
-
- first = udev_enumerate_get_list_entry(e);
- udev_list_entry_foreach(item, first)
- device_process_path(m, udev_list_entry_get_name(item), false);
-
- udev_enumerate_unref(e);
- return 0;
-
-fail:
- if (e)
- udev_enumerate_unref(e);
-
- device_shutdown(m);
- return r;
-}
-
-void device_fd_event(Manager *m, int events) {
- struct udev_device *dev;
- int r;
- const char *action, *ready;
-
- assert(m);
-
- if (events != EPOLLIN) {
- static RATELIMIT_DEFINE(limit, 10*USEC_PER_SEC, 5);
-
- if (!ratelimit_test(&limit))
- log_error("Failed to get udev event: %m");
- if (!(events & EPOLLIN))
- return;
- }
-
- if (!(dev = udev_monitor_receive_device(m->udev_monitor))) {
- /*
- * libudev might filter-out devices which pass the bloom filter,
- * so getting NULL here is not necessarily an error
- */
- return;
- }
-
- if (!(action = udev_device_get_action(dev))) {
- log_error("Failed to get udev action string.");
- goto fail;
- }
-
- ready = udev_device_get_property_value(dev, "SYSTEMD_READY");
-
- if (streq(action, "remove") || (ready && parse_boolean(ready) == 0)) {
- if ((r = device_process_removed_device(m, dev)) < 0) {
- log_error("Failed to process udev device event: %s", strerror(-r));
- goto fail;
- }
- } else {
- if ((r = device_process_new_device(m, dev, true)) < 0) {
- log_error("Failed to process udev device event: %s", strerror(-r));
- goto fail;
- }
- }
-
-fail:
- udev_device_unref(dev);
-}
-
-static const char* const device_state_table[_DEVICE_STATE_MAX] = {
- [DEVICE_DEAD] = "dead",
- [DEVICE_PLUGGED] = "plugged"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState);
-
-const UnitVTable device_vtable = {
- .object_size = sizeof(Device),
- .sections =
- "Unit\0"
- "Device\0"
- "Install\0",
-
- .no_instances = true,
-
- .init = device_init,
-
- .load = unit_load_fragment_and_dropin_optional,
- .done = device_done,
- .coldplug = device_coldplug,
-
- .dump = device_dump,
-
- .active_state = device_active_state,
- .sub_state_to_string = device_sub_state_to_string,
-
- .bus_interface = "org.freedesktop.systemd1.Device",
- .bus_message_handler = bus_device_message_handler,
- .bus_invalidating_properties = bus_device_invalidating_properties,
-
- .following = device_following,
- .following_set = device_following_set,
-
- .enumerate = device_enumerate,
- .shutdown = device_shutdown,
-
- .status_message_formats = {
- .starting_stopping = {
- [0] = "Expecting device %s...",
- },
- .finished_start_job = {
- [JOB_DONE] = "Found device %s.",
- [JOB_TIMEOUT] = "Timed out waiting for device %s.",
- },
- },
-};
diff --git a/src/core/device.h b/src/core/device.h
deleted file mode 100644
index 3c4604f60e..0000000000
--- a/src/core/device.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*-*- 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/>.
-***/
-
-typedef struct Device Device;
-
-#include "unit.h"
-
-/* We simply watch devices, we cannot plug/unplug them. That
- * simplifies the state engine greatly */
-typedef enum DeviceState {
- DEVICE_DEAD,
- DEVICE_PLUGGED,
- _DEVICE_STATE_MAX,
- _DEVICE_STATE_INVALID = -1
-} DeviceState;
-
-struct Device {
- Unit meta;
-
- char *sysfs;
-
- /* In order to be able to distinguish dependencies on
- different device nodes we might end up creating multiple
- devices for the same sysfs path. We chain them up here. */
-
- LIST_FIELDS(struct Device, same_sysfs);
-
- DeviceState state;
-};
-
-extern const UnitVTable device_vtable;
-
-void device_fd_event(Manager *m, int events);
-
-const char* device_state_to_string(DeviceState i);
-DeviceState device_state_from_string(const char *s);
diff --git a/src/core/execute.c b/src/core/execute.c
deleted file mode 100644
index e236d38e0f..0000000000
--- a/src/core/execute.c
+++ /dev/null
@@ -1,2132 +0,0 @@
-/*-*- 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 <assert.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/prctl.h>
-#include <linux/sched.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <grp.h>
-#include <pwd.h>
-#include <sys/mount.h>
-#include <linux/fs.h>
-#include <linux/oom.h>
-#include <sys/poll.h>
-#include <linux/seccomp-bpf.h>
-
-#ifdef HAVE_PAM
-#include <security/pam_appl.h>
-#endif
-
-#include "execute.h"
-#include "strv.h"
-#include "macro.h"
-#include "capability.h"
-#include "util.h"
-#include "log.h"
-#include "ioprio.h"
-#include "securebits.h"
-#include "cgroup.h"
-#include "namespace.h"
-#include "tcpwrap.h"
-#include "exit-status.h"
-#include "missing.h"
-#include "utmp-wtmp.h"
-#include "def.h"
-#include "loopback-setup.h"
-#include "path-util.h"
-#include "syscall-list.h"
-#include "sd-id128.h"
-#include "sd-messages.h"
-
-#define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC)
-
-/* This assumes there is a 'tty' group */
-#define TTY_MODE 0620
-
-static int shift_fds(int fds[], unsigned n_fds) {
- int start, restart_from;
-
- if (n_fds <= 0)
- return 0;
-
- /* Modifies the fds array! (sorts it) */
-
- assert(fds);
-
- start = 0;
- for (;;) {
- int i;
-
- restart_from = -1;
-
- for (i = start; i < (int) n_fds; i++) {
- int nfd;
-
- /* Already at right index? */
- if (fds[i] == i+3)
- continue;
-
- if ((nfd = fcntl(fds[i], F_DUPFD, i+3)) < 0)
- return -errno;
-
- close_nointr_nofail(fds[i]);
- fds[i] = nfd;
-
- /* Hmm, the fd we wanted isn't free? Then
- * let's remember that and try again from here*/
- if (nfd != i+3 && restart_from < 0)
- restart_from = i;
- }
-
- if (restart_from < 0)
- break;
-
- start = restart_from;
- }
-
- return 0;
-}
-
-static int flags_fds(const int fds[], unsigned n_fds, bool nonblock) {
- unsigned i;
- int r;
-
- if (n_fds <= 0)
- return 0;
-
- assert(fds);
-
- /* Drops/Sets O_NONBLOCK and FD_CLOEXEC from the file flags */
-
- for (i = 0; i < n_fds; i++) {
-
- if ((r = fd_nonblock(fds[i], nonblock)) < 0)
- return r;
-
- /* We unconditionally drop FD_CLOEXEC from the fds,
- * since after all we want to pass these fds to our
- * children */
-
- if ((r = fd_cloexec(fds[i], false)) < 0)
- return r;
- }
-
- return 0;
-}
-
-static const char *tty_path(const ExecContext *context) {
- assert(context);
-
- if (context->tty_path)
- return context->tty_path;
-
- return "/dev/console";
-}
-
-void exec_context_tty_reset(const ExecContext *context) {
- assert(context);
-
- if (context->tty_vhangup)
- terminal_vhangup(tty_path(context));
-
- if (context->tty_reset)
- reset_terminal(tty_path(context));
-
- if (context->tty_vt_disallocate && context->tty_path)
- vt_disallocate(context->tty_path);
-}
-
-static int open_null_as(int flags, int nfd) {
- int fd, r;
-
- assert(nfd >= 0);
-
- if ((fd = open("/dev/null", flags|O_NOCTTY)) < 0)
- return -errno;
-
- if (fd != nfd) {
- r = dup2(fd, nfd) < 0 ? -errno : nfd;
- close_nointr_nofail(fd);
- } else
- r = nfd;
-
- return r;
-}
-
-static int connect_logger_as(const ExecContext *context, ExecOutput output, const char *ident, const char *unit_id, int nfd) {
- int fd, r;
- union sockaddr_union sa;
-
- assert(context);
- assert(output < _EXEC_OUTPUT_MAX);
- assert(ident);
- assert(nfd >= 0);
-
- fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (fd < 0)
- return -errno;
-
- zero(sa);
- sa.un.sun_family = AF_UNIX;
- strncpy(sa.un.sun_path, "/run/systemd/journal/stdout", sizeof(sa.un.sun_path));
-
- r = connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
- if (r < 0) {
- close_nointr_nofail(fd);
- return -errno;
- }
-
- if (shutdown(fd, SHUT_RD) < 0) {
- close_nointr_nofail(fd);
- return -errno;
- }
-
- dprintf(fd,
- "%s\n"
- "%s\n"
- "%i\n"
- "%i\n"
- "%i\n"
- "%i\n"
- "%i\n",
- context->syslog_identifier ? context->syslog_identifier : ident,
- unit_id,
- context->syslog_priority,
- !!context->syslog_level_prefix,
- output == EXEC_OUTPUT_SYSLOG || output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE,
- output == EXEC_OUTPUT_KMSG || output == EXEC_OUTPUT_KMSG_AND_CONSOLE,
- output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || output == EXEC_OUTPUT_KMSG_AND_CONSOLE || output == EXEC_OUTPUT_JOURNAL_AND_CONSOLE);
-
- if (fd != nfd) {
- r = dup2(fd, nfd) < 0 ? -errno : nfd;
- close_nointr_nofail(fd);
- } else
- r = nfd;
-
- return r;
-}
-static int open_terminal_as(const char *path, mode_t mode, int nfd) {
- int fd, r;
-
- assert(path);
- assert(nfd >= 0);
-
- if ((fd = open_terminal(path, mode | O_NOCTTY)) < 0)
- return fd;
-
- if (fd != nfd) {
- r = dup2(fd, nfd) < 0 ? -errno : nfd;
- close_nointr_nofail(fd);
- } else
- r = nfd;
-
- return r;
-}
-
-static bool is_terminal_input(ExecInput i) {
- return
- i == EXEC_INPUT_TTY ||
- i == EXEC_INPUT_TTY_FORCE ||
- i == EXEC_INPUT_TTY_FAIL;
-}
-
-static int fixup_input(ExecInput std_input, int socket_fd, bool apply_tty_stdin) {
-
- if (is_terminal_input(std_input) && !apply_tty_stdin)
- return EXEC_INPUT_NULL;
-
- if (std_input == EXEC_INPUT_SOCKET && socket_fd < 0)
- return EXEC_INPUT_NULL;
-
- return std_input;
-}
-
-static int fixup_output(ExecOutput std_output, int socket_fd) {
-
- if (std_output == EXEC_OUTPUT_SOCKET && socket_fd < 0)
- return EXEC_OUTPUT_INHERIT;
-
- return std_output;
-}
-
-static int setup_input(const ExecContext *context, int socket_fd, bool apply_tty_stdin) {
- ExecInput i;
-
- assert(context);
-
- i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
-
- switch (i) {
-
- case EXEC_INPUT_NULL:
- return open_null_as(O_RDONLY, STDIN_FILENO);
-
- case EXEC_INPUT_TTY:
- case EXEC_INPUT_TTY_FORCE:
- case EXEC_INPUT_TTY_FAIL: {
- int fd, r;
-
- if ((fd = acquire_terminal(
- tty_path(context),
- i == EXEC_INPUT_TTY_FAIL,
- i == EXEC_INPUT_TTY_FORCE,
- false,
- (usec_t) -1)) < 0)
- return fd;
-
- if (fd != STDIN_FILENO) {
- r = dup2(fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
- close_nointr_nofail(fd);
- } else
- r = STDIN_FILENO;
-
- return r;
- }
-
- case EXEC_INPUT_SOCKET:
- return dup2(socket_fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
-
- default:
- assert_not_reached("Unknown input type");
- }
-}
-
-static int setup_output(const ExecContext *context, int socket_fd, const char *ident, const char *unit_id, bool apply_tty_stdin) {
- ExecOutput o;
- ExecInput i;
-
- assert(context);
- assert(ident);
-
- i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
- o = fixup_output(context->std_output, socket_fd);
-
- /* This expects the input is already set up */
-
- switch (o) {
-
- case EXEC_OUTPUT_INHERIT:
-
- /* If input got downgraded, inherit the original value */
- if (i == EXEC_INPUT_NULL && is_terminal_input(context->std_input))
- return open_terminal_as(tty_path(context), O_WRONLY, STDOUT_FILENO);
-
- /* If the input is connected to anything that's not a /dev/null, inherit that... */
- if (i != EXEC_INPUT_NULL)
- return dup2(STDIN_FILENO, STDOUT_FILENO) < 0 ? -errno : STDOUT_FILENO;
-
- /* If we are not started from PID 1 we just inherit STDOUT from our parent process. */
- if (getppid() != 1)
- return STDOUT_FILENO;
-
- /* We need to open /dev/null here anew, to get the
- * right access mode. So we fall through */
-
- case EXEC_OUTPUT_NULL:
- return open_null_as(O_WRONLY, STDOUT_FILENO);
-
- case EXEC_OUTPUT_TTY:
- if (is_terminal_input(i))
- return dup2(STDIN_FILENO, STDOUT_FILENO) < 0 ? -errno : STDOUT_FILENO;
-
- /* We don't reset the terminal if this is just about output */
- return open_terminal_as(tty_path(context), O_WRONLY, STDOUT_FILENO);
-
- case EXEC_OUTPUT_SYSLOG:
- case EXEC_OUTPUT_SYSLOG_AND_CONSOLE:
- case EXEC_OUTPUT_KMSG:
- case EXEC_OUTPUT_KMSG_AND_CONSOLE:
- case EXEC_OUTPUT_JOURNAL:
- case EXEC_OUTPUT_JOURNAL_AND_CONSOLE:
- return connect_logger_as(context, o, ident, unit_id, STDOUT_FILENO);
-
- case EXEC_OUTPUT_SOCKET:
- assert(socket_fd >= 0);
- return dup2(socket_fd, STDOUT_FILENO) < 0 ? -errno : STDOUT_FILENO;
-
- default:
- assert_not_reached("Unknown output type");
- }
-}
-
-static int setup_error(const ExecContext *context, int socket_fd, const char *ident, const char *unit_id, bool apply_tty_stdin) {
- ExecOutput o, e;
- ExecInput i;
-
- assert(context);
- assert(ident);
-
- i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
- o = fixup_output(context->std_output, socket_fd);
- e = fixup_output(context->std_error, socket_fd);
-
- /* This expects the input and output are already set up */
-
- /* Don't change the stderr file descriptor if we inherit all
- * the way and are not on a tty */
- if (e == EXEC_OUTPUT_INHERIT &&
- o == EXEC_OUTPUT_INHERIT &&
- i == EXEC_INPUT_NULL &&
- !is_terminal_input(context->std_input) &&
- getppid () != 1)
- return STDERR_FILENO;
-
- /* Duplicate from stdout if possible */
- if (e == o || e == EXEC_OUTPUT_INHERIT)
- return dup2(STDOUT_FILENO, STDERR_FILENO) < 0 ? -errno : STDERR_FILENO;
-
- switch (e) {
-
- case EXEC_OUTPUT_NULL:
- return open_null_as(O_WRONLY, STDERR_FILENO);
-
- case EXEC_OUTPUT_TTY:
- if (is_terminal_input(i))
- return dup2(STDIN_FILENO, STDERR_FILENO) < 0 ? -errno : STDERR_FILENO;
-
- /* We don't reset the terminal if this is just about output */
- return open_terminal_as(tty_path(context), O_WRONLY, STDERR_FILENO);
-
- case EXEC_OUTPUT_SYSLOG:
- case EXEC_OUTPUT_SYSLOG_AND_CONSOLE:
- case EXEC_OUTPUT_KMSG:
- case EXEC_OUTPUT_KMSG_AND_CONSOLE:
- case EXEC_OUTPUT_JOURNAL:
- case EXEC_OUTPUT_JOURNAL_AND_CONSOLE:
- return connect_logger_as(context, e, ident, unit_id, STDERR_FILENO);
-
- case EXEC_OUTPUT_SOCKET:
- assert(socket_fd >= 0);
- return dup2(socket_fd, STDERR_FILENO) < 0 ? -errno : STDERR_FILENO;
-
- default:
- assert_not_reached("Unknown error type");
- }
-}
-
-static int chown_terminal(int fd, uid_t uid) {
- struct stat st;
-
- assert(fd >= 0);
-
- /* This might fail. What matters are the results. */
- (void) fchown(fd, uid, -1);
- (void) fchmod(fd, TTY_MODE);
-
- if (fstat(fd, &st) < 0)
- return -errno;
-
- if (st.st_uid != uid || (st.st_mode & 0777) != TTY_MODE)
- return -EPERM;
-
- return 0;
-}
-
-static int setup_confirm_stdio(int *_saved_stdin,
- int *_saved_stdout) {
- int fd = -1, saved_stdin, saved_stdout = -1, r;
-
- assert(_saved_stdin);
- assert(_saved_stdout);
-
- saved_stdin = fcntl(STDIN_FILENO, F_DUPFD, 3);
- if (saved_stdin < 0)
- return -errno;
-
- saved_stdout = fcntl(STDOUT_FILENO, F_DUPFD, 3);
- if (saved_stdout < 0) {
- r = errno;
- goto fail;
- }
-
- fd = acquire_terminal(
- "/dev/console",
- false,
- false,
- false,
- DEFAULT_CONFIRM_USEC);
- if (fd < 0) {
- r = fd;
- goto fail;
- }
-
- r = chown_terminal(fd, getuid());
- if (r < 0)
- goto fail;
-
- if (dup2(fd, STDIN_FILENO) < 0) {
- r = -errno;
- goto fail;
- }
-
- if (dup2(fd, STDOUT_FILENO) < 0) {
- r = -errno;
- goto fail;
- }
-
- if (fd >= 2)
- close_nointr_nofail(fd);
-
- *_saved_stdin = saved_stdin;
- *_saved_stdout = saved_stdout;
-
- return 0;
-
-fail:
- if (saved_stdout >= 0)
- close_nointr_nofail(saved_stdout);
-
- if (saved_stdin >= 0)
- close_nointr_nofail(saved_stdin);
-
- if (fd >= 0)
- close_nointr_nofail(fd);
-
- return r;
-}
-
-static int write_confirm_message(const char *format, ...) {
- int fd;
- va_list ap;
-
- assert(format);
-
- fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return fd;
-
- va_start(ap, format);
- vdprintf(fd, format, ap);
- va_end(ap);
-
- close_nointr_nofail(fd);
-
- return 0;
-}
-
-static int restore_confirm_stdio(int *saved_stdin,
- int *saved_stdout) {
-
- int r = 0;
-
- assert(saved_stdin);
- assert(saved_stdout);
-
- release_terminal();
-
- if (*saved_stdin >= 0)
- if (dup2(*saved_stdin, STDIN_FILENO) < 0)
- r = -errno;
-
- if (*saved_stdout >= 0)
- if (dup2(*saved_stdout, STDOUT_FILENO) < 0)
- r = -errno;
-
- if (*saved_stdin >= 0)
- close_nointr_nofail(*saved_stdin);
-
- if (*saved_stdout >= 0)
- close_nointr_nofail(*saved_stdout);
-
- return r;
-}
-
-static int ask_for_confirmation(char *response, char **argv) {
- int saved_stdout = -1, saved_stdin = -1, r;
- char *line;
-
- r = setup_confirm_stdio(&saved_stdin, &saved_stdout);
- if (r < 0)
- return r;
-
- line = exec_command_line(argv);
- if (!line)
- return -ENOMEM;
-
- r = ask(response, "yns", "Execute %s? [Yes, No, Skip] ", line);
- free(line);
-
- restore_confirm_stdio(&saved_stdin, &saved_stdout);
-
- return r;
-}
-
-static int enforce_groups(const ExecContext *context, const char *username, gid_t gid) {
- bool keep_groups = false;
- int r;
-
- assert(context);
-
- /* Lookup and set GID and supplementary group list. Here too
- * we avoid NSS lookups for gid=0. */
-
- if (context->group || username) {
-
- if (context->group) {
- const char *g = context->group;
-
- if ((r = get_group_creds(&g, &gid)) < 0)
- return r;
- }
-
- /* First step, initialize groups from /etc/groups */
- if (username && gid != 0) {
- if (initgroups(username, gid) < 0)
- return -errno;
-
- keep_groups = true;
- }
-
- /* Second step, set our gids */
- if (setresgid(gid, gid, gid) < 0)
- return -errno;
- }
-
- if (context->supplementary_groups) {
- int ngroups_max, k;
- gid_t *gids;
- char **i;
-
- /* Final step, initialize any manually set supplementary groups */
- assert_se((ngroups_max = (int) sysconf(_SC_NGROUPS_MAX)) > 0);
-
- if (!(gids = new(gid_t, ngroups_max)))
- return -ENOMEM;
-
- if (keep_groups) {
- if ((k = getgroups(ngroups_max, gids)) < 0) {
- free(gids);
- return -errno;
- }
- } else
- k = 0;
-
- STRV_FOREACH(i, context->supplementary_groups) {
- const char *g;
-
- if (k >= ngroups_max) {
- free(gids);
- return -E2BIG;
- }
-
- g = *i;
- r = get_group_creds(&g, gids+k);
- if (r < 0) {
- free(gids);
- return r;
- }
-
- k++;
- }
-
- if (setgroups(k, gids) < 0) {
- free(gids);
- return -errno;
- }
-
- free(gids);
- }
-
- return 0;
-}
-
-static int enforce_user(const ExecContext *context, uid_t uid) {
- int r;
- assert(context);
-
- /* Sets (but doesn't lookup) the uid and make sure we keep the
- * capabilities while doing so. */
-
- if (context->capabilities) {
- cap_t d;
- static const cap_value_t bits[] = {
- CAP_SETUID, /* Necessary so that we can run setresuid() below */
- CAP_SETPCAP /* Necessary so that we can set PR_SET_SECUREBITS later on */
- };
-
- /* First step: If we need to keep capabilities but
- * drop privileges we need to make sure we keep our
- * caps, whiel we drop privileges. */
- if (uid != 0) {
- int sb = context->secure_bits|SECURE_KEEP_CAPS;
-
- if (prctl(PR_GET_SECUREBITS) != sb)
- if (prctl(PR_SET_SECUREBITS, sb) < 0)
- return -errno;
- }
-
- /* Second step: set the capabilities. This will reduce
- * the capabilities to the minimum we need. */
-
- if (!(d = cap_dup(context->capabilities)))
- return -errno;
-
- if (cap_set_flag(d, CAP_EFFECTIVE, ELEMENTSOF(bits), bits, CAP_SET) < 0 ||
- cap_set_flag(d, CAP_PERMITTED, ELEMENTSOF(bits), bits, CAP_SET) < 0) {
- r = -errno;
- cap_free(d);
- return r;
- }
-
- if (cap_set_proc(d) < 0) {
- r = -errno;
- cap_free(d);
- return r;
- }
-
- cap_free(d);
- }
-
- /* Third step: actually set the uids */
- if (setresuid(uid, uid, uid) < 0)
- return -errno;
-
- /* At this point we should have all necessary capabilities but
- are otherwise a normal user. However, the caps might got
- corrupted due to the setresuid() so we need clean them up
- later. This is done outside of this call. */
-
- return 0;
-}
-
-#ifdef HAVE_PAM
-
-static int null_conv(
- int num_msg,
- const struct pam_message **msg,
- struct pam_response **resp,
- void *appdata_ptr) {
-
- /* We don't support conversations */
-
- return PAM_CONV_ERR;
-}
-
-static int setup_pam(
- const char *name,
- const char *user,
- uid_t uid,
- const char *tty,
- char ***pam_env,
- int fds[], unsigned n_fds) {
-
- static const struct pam_conv conv = {
- .conv = null_conv,
- .appdata_ptr = NULL
- };
-
- pam_handle_t *handle = NULL;
- sigset_t ss, old_ss;
- int pam_code = PAM_SUCCESS;
- int err;
- char **e = NULL;
- bool close_session = false;
- pid_t pam_pid = 0, parent_pid;
-
- assert(name);
- assert(user);
- assert(pam_env);
-
- /* We set up PAM in the parent process, then fork. The child
- * will then stay around until killed via PR_GET_PDEATHSIG or
- * systemd via the cgroup logic. It will then remove the PAM
- * session again. The parent process will exec() the actual
- * daemon. We do things this way to ensure that the main PID
- * of the daemon is the one we initially fork()ed. */
-
- if ((pam_code = pam_start(name, user, &conv, &handle)) != PAM_SUCCESS) {
- handle = NULL;
- goto fail;
- }
-
- if (tty)
- if ((pam_code = pam_set_item(handle, PAM_TTY, tty)) != PAM_SUCCESS)
- goto fail;
-
- if ((pam_code = pam_acct_mgmt(handle, PAM_SILENT)) != PAM_SUCCESS)
- goto fail;
-
- if ((pam_code = pam_open_session(handle, PAM_SILENT)) != PAM_SUCCESS)
- goto fail;
-
- close_session = true;
-
- if ((!(e = pam_getenvlist(handle)))) {
- pam_code = PAM_BUF_ERR;
- goto fail;
- }
-
- /* Block SIGTERM, so that we know that it won't get lost in
- * the child */
- if (sigemptyset(&ss) < 0 ||
- sigaddset(&ss, SIGTERM) < 0 ||
- sigprocmask(SIG_BLOCK, &ss, &old_ss) < 0)
- goto fail;
-
- parent_pid = getpid();
-
- if ((pam_pid = fork()) < 0)
- goto fail;
-
- if (pam_pid == 0) {
- int sig;
- int r = EXIT_PAM;
-
- /* The child's job is to reset the PAM session on
- * termination */
-
- /* This string must fit in 10 chars (i.e. the length
- * of "/sbin/init"), to look pretty in /bin/ps */
- rename_process("(sd-pam)");
-
- /* Make sure we don't keep open the passed fds in this
- child. We assume that otherwise only those fds are
- open here that have been opened by PAM. */
- close_many(fds, n_fds);
-
- /* Drop privileges - we don't need any to pam_close_session
- * and this will make PR_SET_PDEATHSIG work in most cases.
- * If this fails, ignore the error - but expect sd-pam threads
- * to fail to exit normally */
- if (setresuid(uid, uid, uid) < 0)
- log_error("Error: Failed to setresuid() in sd-pam: %s", strerror(-r));
-
- /* Wait until our parent died. This will only work if
- * the above setresuid() succeeds, otherwise the kernel
- * will not allow unprivileged parents kill their privileged
- * children this way. We rely on the control groups kill logic
- * to do the rest for us. */
- if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
- goto child_finish;
-
- /* Check if our parent process might already have
- * died? */
- if (getppid() == parent_pid) {
- for (;;) {
- if (sigwait(&ss, &sig) < 0) {
- if (errno == EINTR)
- continue;
-
- goto child_finish;
- }
-
- assert(sig == SIGTERM);
- break;
- }
- }
-
- /* If our parent died we'll end the session */
- if (getppid() != parent_pid)
- if ((pam_code = pam_close_session(handle, PAM_DATA_SILENT)) != PAM_SUCCESS)
- goto child_finish;
-
- r = 0;
-
- child_finish:
- pam_end(handle, pam_code | PAM_DATA_SILENT);
- _exit(r);
- }
-
- /* If the child was forked off successfully it will do all the
- * cleanups, so forget about the handle here. */
- handle = NULL;
-
- /* Unblock SIGTERM again in the parent */
- if (sigprocmask(SIG_SETMASK, &old_ss, NULL) < 0)
- goto fail;
-
- /* We close the log explicitly here, since the PAM modules
- * might have opened it, but we don't want this fd around. */
- closelog();
-
- *pam_env = e;
- e = NULL;
-
- return 0;
-
-fail:
- if (pam_code != PAM_SUCCESS)
- err = -EPERM; /* PAM errors do not map to errno */
- else
- err = -errno;
-
- if (handle) {
- if (close_session)
- pam_code = pam_close_session(handle, PAM_DATA_SILENT);
-
- pam_end(handle, pam_code | PAM_DATA_SILENT);
- }
-
- strv_free(e);
-
- closelog();
-
- if (pam_pid > 1) {
- kill(pam_pid, SIGTERM);
- kill(pam_pid, SIGCONT);
- }
-
- return err;
-}
-#endif
-
-static void rename_process_from_path(const char *path) {
- char process_name[11];
- const char *p;
- size_t l;
-
- /* This resulting string must fit in 10 chars (i.e. the length
- * of "/sbin/init") to look pretty in /bin/ps */
-
- p = path_get_file_name(path);
- if (isempty(p)) {
- rename_process("(...)");
- return;
- }
-
- l = strlen(p);
- if (l > 8) {
- /* The end of the process name is usually more
- * interesting, since the first bit might just be
- * "systemd-" */
- p = p + l - 8;
- l = 8;
- }
-
- process_name[0] = '(';
- memcpy(process_name+1, p, l);
- process_name[1+l] = ')';
- process_name[1+l+1] = 0;
-
- rename_process(process_name);
-}
-
-static int apply_seccomp(uint32_t *syscall_filter) {
- static const struct sock_filter header[] = {
- VALIDATE_ARCHITECTURE,
- EXAMINE_SYSCALL
- };
- static const struct sock_filter footer[] = {
- _KILL_PROCESS
- };
-
- int i;
- unsigned n;
- struct sock_filter *f;
- struct sock_fprog prog;
-
- assert(syscall_filter);
-
- /* First: count the syscalls to check for */
- for (i = 0, n = 0; i < syscall_max(); i++)
- if (syscall_filter[i >> 4] & (1 << (i & 31)))
- n++;
-
- /* Second: build the filter program from a header the syscall
- * matches and the footer */
- f = alloca(sizeof(struct sock_filter) * (ELEMENTSOF(header) + 2*n + ELEMENTSOF(footer)));
- memcpy(f, header, sizeof(header));
-
- for (i = 0, n = 0; i < syscall_max(); i++)
- if (syscall_filter[i >> 4] & (1 << (i & 31))) {
- struct sock_filter item[] = {
- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, i, 0, 1),
- BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
- };
-
- assert_cc(ELEMENTSOF(item) == 2);
-
- f[ELEMENTSOF(header) + 2*n] = item[0];
- f[ELEMENTSOF(header) + 2*n+1] = item[1];
-
- n++;
- }
-
- memcpy(f + (ELEMENTSOF(header) + 2*n), footer, sizeof(footer));
-
- /* Third: install the filter */
- zero(prog);
- prog.len = ELEMENTSOF(header) + ELEMENTSOF(footer) + 2*n;
- prog.filter = f;
- if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) < 0)
- return -errno;
-
- return 0;
-}
-
-int exec_spawn(ExecCommand *command,
- char **argv,
- const ExecContext *context,
- int fds[], unsigned n_fds,
- char **environment,
- bool apply_permissions,
- bool apply_chroot,
- bool apply_tty_stdin,
- bool confirm_spawn,
- CGroupBonding *cgroup_bondings,
- CGroupAttribute *cgroup_attributes,
- const char *cgroup_suffix,
- const char *unit_id,
- int idle_pipe[2],
- pid_t *ret) {
-
- pid_t pid;
- int r;
- char *line;
- int socket_fd;
- char _cleanup_strv_free_ **files_env = NULL;
-
- assert(command);
- assert(context);
- assert(ret);
- assert(fds || n_fds <= 0);
-
- if (context->std_input == EXEC_INPUT_SOCKET ||
- context->std_output == EXEC_OUTPUT_SOCKET ||
- context->std_error == EXEC_OUTPUT_SOCKET) {
-
- if (n_fds != 1)
- return -EINVAL;
-
- socket_fd = fds[0];
-
- fds = NULL;
- n_fds = 0;
- } else
- socket_fd = -1;
-
- r = exec_context_load_environment(context, &files_env);
- if (r < 0) {
- log_struct(LOG_ERR,
- "UNIT=%s", unit_id,
- "MESSAGE=Failed to load environment files: %s", strerror(-r),
- "ERRNO=%d", -r,
- NULL);
- return r;
- }
-
- if (!argv)
- argv = command->argv;
-
- line = exec_command_line(argv);
- if (!line)
- return log_oom();
-
- log_struct(LOG_DEBUG,
- "UNIT=%s", unit_id,
- "MESSAGE=About to execute %s", line,
- NULL);
- free(line);
-
- r = cgroup_bonding_realize_list(cgroup_bondings);
- if (r < 0)
- return r;
-
- cgroup_attribute_apply_list(cgroup_attributes, cgroup_bondings);
-
- pid = fork();
- if (pid < 0)
- return -errno;
-
- if (pid == 0) {
- int i, err;
- sigset_t ss;
- const char *username = NULL, *home = NULL;
- uid_t uid = (uid_t) -1;
- gid_t gid = (gid_t) -1;
- char _cleanup_strv_free_ **our_env = NULL, **pam_env = NULL,
- **final_env = NULL, **final_argv = NULL;
- unsigned n_env = 0;
- bool set_access = false;
-
- /* child */
-
- rename_process_from_path(command->path);
-
- /* We reset exactly these signals, since they are the
- * only ones we set to SIG_IGN in the main daemon. All
- * others we leave untouched because we set them to
- * SIG_DFL or a valid handler initially, both of which
- * will be demoted to SIG_DFL. */
- default_signals(SIGNALS_CRASH_HANDLER,
- SIGNALS_IGNORE, -1);
-
- if (context->ignore_sigpipe)
- ignore_signals(SIGPIPE, -1);
-
- assert_se(sigemptyset(&ss) == 0);
- if (sigprocmask(SIG_SETMASK, &ss, NULL) < 0) {
- err = -errno;
- r = EXIT_SIGNAL_MASK;
- goto fail_child;
- }
-
- if (idle_pipe) {
- if (idle_pipe[1] >= 0)
- close_nointr_nofail(idle_pipe[1]);
- if (idle_pipe[0] >= 0) {
- fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT_USEC);
- close_nointr_nofail(idle_pipe[0]);
- }
- }
-
- /* Close sockets very early to make sure we don't
- * block init reexecution because it cannot bind its
- * sockets */
- log_forget_fds();
- err = close_all_fds(socket_fd >= 0 ? &socket_fd : fds,
- socket_fd >= 0 ? 1 : n_fds);
- if (err < 0) {
- r = EXIT_FDS;
- goto fail_child;
- }
-
- if (!context->same_pgrp)
- if (setsid() < 0) {
- err = -errno;
- r = EXIT_SETSID;
- goto fail_child;
- }
-
- if (context->tcpwrap_name) {
- if (socket_fd >= 0)
- if (!socket_tcpwrap(socket_fd, context->tcpwrap_name)) {
- err = -EACCES;
- r = EXIT_TCPWRAP;
- goto fail_child;
- }
-
- for (i = 0; i < (int) n_fds; i++) {
- if (!socket_tcpwrap(fds[i], context->tcpwrap_name)) {
- err = -EACCES;
- r = EXIT_TCPWRAP;
- goto fail_child;
- }
- }
- }
-
- exec_context_tty_reset(context);
-
- if (confirm_spawn) {
- char response;
-
- err = ask_for_confirmation(&response, argv);
- if (err == -ETIMEDOUT)
- write_confirm_message("Confirmation question timed out, assuming positive response.\n");
- else if (err < 0)
- write_confirm_message("Couldn't ask confirmation question, assuming positive response: %s\n", strerror(-err));
- else if (response == 's') {
- write_confirm_message("Skipping execution.\n");
- err = -ECANCELED;
- r = EXIT_CONFIRM;
- goto fail_child;
- } else if (response == 'n') {
- write_confirm_message("Failing execution.\n");
- err = r = 0;
- goto fail_child;
- }
- }
-
- /* If a socket is connected to STDIN/STDOUT/STDERR, we
- * must sure to drop O_NONBLOCK */
- if (socket_fd >= 0)
- fd_nonblock(socket_fd, false);
-
- err = setup_input(context, socket_fd, apply_tty_stdin);
- if (err < 0) {
- r = EXIT_STDIN;
- goto fail_child;
- }
-
- err = setup_output(context, socket_fd, path_get_file_name(command->path), unit_id, apply_tty_stdin);
- if (err < 0) {
- r = EXIT_STDOUT;
- goto fail_child;
- }
-
- err = setup_error(context, socket_fd, path_get_file_name(command->path), unit_id, apply_tty_stdin);
- if (err < 0) {
- r = EXIT_STDERR;
- goto fail_child;
- }
-
- if (cgroup_bondings) {
- err = cgroup_bonding_install_list(cgroup_bondings, 0, cgroup_suffix);
- if (err < 0) {
- r = EXIT_CGROUP;
- goto fail_child;
- }
- }
-
- if (context->oom_score_adjust_set) {
- char t[16];
-
- snprintf(t, sizeof(t), "%i", context->oom_score_adjust);
- char_array_0(t);
-
- if (write_one_line_file("/proc/self/oom_score_adj", t) < 0) {
- err = -errno;
- r = EXIT_OOM_ADJUST;
- goto fail_child;
- }
- }
-
- if (context->nice_set)
- if (setpriority(PRIO_PROCESS, 0, context->nice) < 0) {
- err = -errno;
- r = EXIT_NICE;
- goto fail_child;
- }
-
- if (context->cpu_sched_set) {
- struct sched_param param;
-
- zero(param);
- param.sched_priority = context->cpu_sched_priority;
-
- if (sched_setscheduler(0, context->cpu_sched_policy |
- (context->cpu_sched_reset_on_fork ? SCHED_RESET_ON_FORK : 0), &param) < 0) {
- err = -errno;
- r = EXIT_SETSCHEDULER;
- goto fail_child;
- }
- }
-
- if (context->cpuset)
- if (sched_setaffinity(0, CPU_ALLOC_SIZE(context->cpuset_ncpus), context->cpuset) < 0) {
- err = -errno;
- r = EXIT_CPUAFFINITY;
- goto fail_child;
- }
-
- if (context->ioprio_set)
- if (ioprio_set(IOPRIO_WHO_PROCESS, 0, context->ioprio) < 0) {
- err = -errno;
- r = EXIT_IOPRIO;
- goto fail_child;
- }
-
- if (context->timer_slack_nsec != (nsec_t) -1)
- if (prctl(PR_SET_TIMERSLACK, context->timer_slack_nsec) < 0) {
- err = -errno;
- r = EXIT_TIMERSLACK;
- goto fail_child;
- }
-
- if (context->utmp_id)
- utmp_put_init_process(context->utmp_id, getpid(), getsid(0), context->tty_path);
-
- if (context->user) {
- username = context->user;
- err = get_user_creds(&username, &uid, &gid, &home, NULL);
- if (err < 0) {
- r = EXIT_USER;
- goto fail_child;
- }
-
- if (is_terminal_input(context->std_input)) {
- err = chown_terminal(STDIN_FILENO, uid);
- if (err < 0) {
- r = EXIT_STDIN;
- goto fail_child;
- }
- }
-
- if (cgroup_bondings && context->control_group_modify) {
- err = cgroup_bonding_set_group_access_list(cgroup_bondings, 0755, uid, gid);
- if (err >= 0)
- err = cgroup_bonding_set_task_access_list(cgroup_bondings, 0644, uid, gid, context->control_group_persistent);
- if (err < 0) {
- r = EXIT_CGROUP;
- goto fail_child;
- }
-
- set_access = true;
- }
- }
-
- if (cgroup_bondings && !set_access && context->control_group_persistent >= 0) {
- err = cgroup_bonding_set_task_access_list(cgroup_bondings, (mode_t) -1, (uid_t) -1, (uid_t) -1, context->control_group_persistent);
- if (err < 0) {
- r = EXIT_CGROUP;
- goto fail_child;
- }
- }
-
- if (apply_permissions) {
- err = enforce_groups(context, username, gid);
- if (err < 0) {
- r = EXIT_GROUP;
- goto fail_child;
- }
- }
-
- umask(context->umask);
-
-#ifdef HAVE_PAM
- if (apply_permissions && context->pam_name && username) {
- err = setup_pam(context->pam_name, username, uid, context->tty_path, &pam_env, fds, n_fds);
- if (err < 0) {
- r = EXIT_PAM;
- goto fail_child;
- }
- }
-#endif
- if (context->private_network) {
- if (unshare(CLONE_NEWNET) < 0) {
- err = -errno;
- r = EXIT_NETWORK;
- goto fail_child;
- }
-
- loopback_setup();
- }
-
- if (strv_length(context->read_write_dirs) > 0 ||
- strv_length(context->read_only_dirs) > 0 ||
- strv_length(context->inaccessible_dirs) > 0 ||
- context->mount_flags != 0 ||
- context->private_tmp) {
- err = setup_namespace(context->read_write_dirs,
- context->read_only_dirs,
- context->inaccessible_dirs,
- context->private_tmp,
- context->mount_flags);
- if (err < 0) {
- r = EXIT_NAMESPACE;
- goto fail_child;
- }
- }
-
- if (apply_chroot) {
- if (context->root_directory)
- if (chroot(context->root_directory) < 0) {
- err = -errno;
- r = EXIT_CHROOT;
- goto fail_child;
- }
-
- if (chdir(context->working_directory ? context->working_directory : "/") < 0) {
- err = -errno;
- r = EXIT_CHDIR;
- goto fail_child;
- }
- } else {
- char _cleanup_free_ *d = NULL;
-
- if (asprintf(&d, "%s/%s",
- context->root_directory ? context->root_directory : "",
- context->working_directory ? context->working_directory : "") < 0) {
- err = -ENOMEM;
- r = EXIT_MEMORY;
- goto fail_child;
- }
-
- if (chdir(d) < 0) {
- err = -errno;
- r = EXIT_CHDIR;
- goto fail_child;
- }
- }
-
- /* We repeat the fd closing here, to make sure that
- * nothing is leaked from the PAM modules */
- err = close_all_fds(fds, n_fds);
- if (err >= 0)
- err = shift_fds(fds, n_fds);
- if (err >= 0)
- err = flags_fds(fds, n_fds, context->non_blocking);
- if (err < 0) {
- r = EXIT_FDS;
- goto fail_child;
- }
-
- if (apply_permissions) {
-
- for (i = 0; i < RLIMIT_NLIMITS; i++) {
- if (!context->rlimit[i])
- continue;
-
- if (setrlimit_closest(i, context->rlimit[i]) < 0) {
- err = -errno;
- r = EXIT_LIMITS;
- goto fail_child;
- }
- }
-
- if (context->capability_bounding_set_drop) {
- err = capability_bounding_set_drop(context->capability_bounding_set_drop, false);
- if (err < 0) {
- r = EXIT_CAPABILITIES;
- goto fail_child;
- }
- }
-
- if (context->user) {
- err = enforce_user(context, uid);
- if (err < 0) {
- r = EXIT_USER;
- goto fail_child;
- }
- }
-
- /* PR_GET_SECUREBITS is not privileged, while
- * PR_SET_SECUREBITS is. So to suppress
- * potential EPERMs we'll try not to call
- * PR_SET_SECUREBITS unless necessary. */
- if (prctl(PR_GET_SECUREBITS) != context->secure_bits)
- if (prctl(PR_SET_SECUREBITS, context->secure_bits) < 0) {
- err = -errno;
- r = EXIT_SECUREBITS;
- goto fail_child;
- }
-
- if (context->capabilities)
- if (cap_set_proc(context->capabilities) < 0) {
- err = -errno;
- r = EXIT_CAPABILITIES;
- goto fail_child;
- }
-
- if (context->no_new_privileges)
- if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
- err = -errno;
- r = EXIT_NO_NEW_PRIVILEGES;
- goto fail_child;
- }
-
- if (context->syscall_filter) {
- err = apply_seccomp(context->syscall_filter);
- if (err < 0) {
- r = EXIT_SECCOMP;
- goto fail_child;
- }
- }
- }
-
- if (!(our_env = new0(char*, 7))) {
- err = -ENOMEM;
- r = EXIT_MEMORY;
- goto fail_child;
- }
-
- if (n_fds > 0)
- if (asprintf(our_env + n_env++, "LISTEN_PID=%lu", (unsigned long) getpid()) < 0 ||
- asprintf(our_env + n_env++, "LISTEN_FDS=%u", n_fds) < 0) {
- err = -ENOMEM;
- r = EXIT_MEMORY;
- goto fail_child;
- }
-
- if (home)
- if (asprintf(our_env + n_env++, "HOME=%s", home) < 0) {
- err = -ENOMEM;
- r = EXIT_MEMORY;
- goto fail_child;
- }
-
- if (username)
- if (asprintf(our_env + n_env++, "LOGNAME=%s", username) < 0 ||
- asprintf(our_env + n_env++, "USER=%s", username) < 0) {
- err = -ENOMEM;
- r = EXIT_MEMORY;
- goto fail_child;
- }
-
- if (is_terminal_input(context->std_input) ||
- context->std_output == EXEC_OUTPUT_TTY ||
- context->std_error == EXEC_OUTPUT_TTY)
- if (!(our_env[n_env++] = strdup(default_term_for_tty(tty_path(context))))) {
- err = -ENOMEM;
- r = EXIT_MEMORY;
- goto fail_child;
- }
-
- assert(n_env <= 7);
-
- if (!(final_env = strv_env_merge(
- 5,
- environment,
- our_env,
- context->environment,
- files_env,
- pam_env,
- NULL))) {
- err = -ENOMEM;
- r = EXIT_MEMORY;
- goto fail_child;
- }
-
- if (!(final_argv = replace_env_argv(argv, final_env))) {
- err = -ENOMEM;
- r = EXIT_MEMORY;
- goto fail_child;
- }
-
- final_env = strv_env_clean(final_env);
-
- execve(command->path, final_argv, final_env);
- err = -errno;
- r = EXIT_EXEC;
-
- fail_child:
- if (r != 0) {
- log_open();
- log_struct(LOG_ERR, MESSAGE_ID(SD_MESSAGE_SPAWN_FAILED),
- "EXECUTABLE=%s", command->path,
- "MESSAGE=Failed at step %s spawning %s: %s",
- exit_status_to_string(r, EXIT_STATUS_SYSTEMD),
- command->path, strerror(-err),
- "ERRNO=%d", -err,
- NULL);
- log_close();
- }
-
- _exit(r);
- }
-
- log_struct(LOG_DEBUG,
- "UNIT=%s", unit_id,
- "MESSAGE=Forked %s as %lu",
- command->path, (unsigned long) pid,
- NULL);
-
- /* We add the new process to the cgroup both in the child (so
- * that we can be sure that no user code is ever executed
- * outside of the cgroup) and in the parent (so that we can be
- * sure that when we kill the cgroup the process will be
- * killed too). */
- if (cgroup_bondings)
- cgroup_bonding_install_list(cgroup_bondings, pid, cgroup_suffix);
-
- exec_status_start(&command->exec_status, pid);
-
- *ret = pid;
- return 0;
-}
-
-void exec_context_init(ExecContext *c) {
- assert(c);
-
- c->umask = 0022;
- c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 0);
- c->cpu_sched_policy = SCHED_OTHER;
- c->syslog_priority = LOG_DAEMON|LOG_INFO;
- c->syslog_level_prefix = true;
- c->control_group_persistent = -1;
- c->ignore_sigpipe = true;
- c->timer_slack_nsec = (nsec_t) -1;
-}
-
-void exec_context_done(ExecContext *c) {
- unsigned l;
-
- assert(c);
-
- strv_free(c->environment);
- c->environment = NULL;
-
- strv_free(c->environment_files);
- c->environment_files = NULL;
-
- for (l = 0; l < ELEMENTSOF(c->rlimit); l++) {
- free(c->rlimit[l]);
- c->rlimit[l] = NULL;
- }
-
- free(c->working_directory);
- c->working_directory = NULL;
- free(c->root_directory);
- c->root_directory = NULL;
-
- free(c->tty_path);
- c->tty_path = NULL;
-
- free(c->tcpwrap_name);
- c->tcpwrap_name = NULL;
-
- free(c->syslog_identifier);
- c->syslog_identifier = NULL;
-
- free(c->user);
- c->user = NULL;
-
- free(c->group);
- c->group = NULL;
-
- strv_free(c->supplementary_groups);
- c->supplementary_groups = NULL;
-
- free(c->pam_name);
- c->pam_name = NULL;
-
- if (c->capabilities) {
- cap_free(c->capabilities);
- c->capabilities = NULL;
- }
-
- strv_free(c->read_only_dirs);
- c->read_only_dirs = NULL;
-
- strv_free(c->read_write_dirs);
- c->read_write_dirs = NULL;
-
- strv_free(c->inaccessible_dirs);
- c->inaccessible_dirs = NULL;
-
- if (c->cpuset)
- CPU_FREE(c->cpuset);
-
- free(c->utmp_id);
- c->utmp_id = NULL;
-
- free(c->syscall_filter);
- c->syscall_filter = NULL;
-}
-
-void exec_command_done(ExecCommand *c) {
- assert(c);
-
- free(c->path);
- c->path = NULL;
-
- strv_free(c->argv);
- c->argv = NULL;
-}
-
-void exec_command_done_array(ExecCommand *c, unsigned n) {
- unsigned i;
-
- for (i = 0; i < n; i++)
- exec_command_done(c+i);
-}
-
-void exec_command_free_list(ExecCommand *c) {
- ExecCommand *i;
-
- while ((i = c)) {
- LIST_REMOVE(ExecCommand, command, c, i);
- exec_command_done(i);
- free(i);
- }
-}
-
-void exec_command_free_array(ExecCommand **c, unsigned n) {
- unsigned i;
-
- for (i = 0; i < n; i++) {
- exec_command_free_list(c[i]);
- c[i] = NULL;
- }
-}
-
-int exec_context_load_environment(const ExecContext *c, char ***l) {
- char **i, **r = NULL;
-
- assert(c);
- assert(l);
-
- STRV_FOREACH(i, c->environment_files) {
- char *fn;
- int k;
- bool ignore = false;
- char **p;
-
- fn = *i;
-
- if (fn[0] == '-') {
- ignore = true;
- fn ++;
- }
-
- if (!path_is_absolute(fn)) {
-
- if (ignore)
- continue;
-
- strv_free(r);
- return -EINVAL;
- }
-
- if ((k = load_env_file(fn, &p)) < 0) {
-
- if (ignore)
- continue;
-
- strv_free(r);
- return k;
- }
-
- if (r == NULL)
- r = p;
- else {
- char **m;
-
- m = strv_env_merge(2, r, p);
- strv_free(r);
- strv_free(p);
-
- if (!m)
- return -ENOMEM;
-
- r = m;
- }
- }
-
- *l = r;
-
- return 0;
-}
-
-static void strv_fprintf(FILE *f, char **l) {
- char **g;
-
- assert(f);
-
- STRV_FOREACH(g, l)
- fprintf(f, " %s", *g);
-}
-
-void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
- char ** e;
- unsigned i;
-
- assert(c);
- assert(f);
-
- if (!prefix)
- prefix = "";
-
- fprintf(f,
- "%sUMask: %04o\n"
- "%sWorkingDirectory: %s\n"
- "%sRootDirectory: %s\n"
- "%sNonBlocking: %s\n"
- "%sPrivateTmp: %s\n"
- "%sControlGroupModify: %s\n"
- "%sControlGroupPersistent: %s\n"
- "%sPrivateNetwork: %s\n"
- "%sIgnoreSIGPIPE: %s\n",
- prefix, c->umask,
- prefix, c->working_directory ? c->working_directory : "/",
- prefix, c->root_directory ? c->root_directory : "/",
- prefix, yes_no(c->non_blocking),
- prefix, yes_no(c->private_tmp),
- prefix, yes_no(c->control_group_modify),
- prefix, yes_no(c->control_group_persistent),
- prefix, yes_no(c->private_network),
- prefix, yes_no(c->ignore_sigpipe));
-
- STRV_FOREACH(e, c->environment)
- fprintf(f, "%sEnvironment: %s\n", prefix, *e);
-
- STRV_FOREACH(e, c->environment_files)
- fprintf(f, "%sEnvironmentFile: %s\n", prefix, *e);
-
- if (c->tcpwrap_name)
- fprintf(f,
- "%sTCPWrapName: %s\n",
- prefix, c->tcpwrap_name);
-
- if (c->nice_set)
- fprintf(f,
- "%sNice: %i\n",
- prefix, c->nice);
-
- if (c->oom_score_adjust_set)
- fprintf(f,
- "%sOOMScoreAdjust: %i\n",
- prefix, c->oom_score_adjust);
-
- for (i = 0; i < RLIM_NLIMITS; i++)
- if (c->rlimit[i])
- fprintf(f, "%s%s: %llu\n", prefix, rlimit_to_string(i), (unsigned long long) c->rlimit[i]->rlim_max);
-
- if (c->ioprio_set) {
- char *class_str;
- int r;
-
- r = ioprio_class_to_string_alloc(IOPRIO_PRIO_CLASS(c->ioprio), &class_str);
- if (r < 0)
- class_str = NULL;
- fprintf(f,
- "%sIOSchedulingClass: %s\n"
- "%sIOPriority: %i\n",
- prefix, strna(class_str),
- prefix, (int) IOPRIO_PRIO_DATA(c->ioprio));
- free(class_str);
- }
-
- if (c->cpu_sched_set) {
- char *policy_str;
- int r;
-
- r = sched_policy_to_string_alloc(c->cpu_sched_policy, &policy_str);
- if (r < 0)
- policy_str = NULL;
- fprintf(f,
- "%sCPUSchedulingPolicy: %s\n"
- "%sCPUSchedulingPriority: %i\n"
- "%sCPUSchedulingResetOnFork: %s\n",
- prefix, strna(policy_str),
- prefix, c->cpu_sched_priority,
- prefix, yes_no(c->cpu_sched_reset_on_fork));
- free(policy_str);
- }
-
- if (c->cpuset) {
- fprintf(f, "%sCPUAffinity:", prefix);
- for (i = 0; i < c->cpuset_ncpus; i++)
- if (CPU_ISSET_S(i, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset))
- fprintf(f, " %i", i);
- fputs("\n", f);
- }
-
- if (c->timer_slack_nsec != (nsec_t) -1)
- fprintf(f, "%sTimerSlackNSec: %lu\n", prefix, (unsigned long)c->timer_slack_nsec);
-
- fprintf(f,
- "%sStandardInput: %s\n"
- "%sStandardOutput: %s\n"
- "%sStandardError: %s\n",
- prefix, exec_input_to_string(c->std_input),
- prefix, exec_output_to_string(c->std_output),
- prefix, exec_output_to_string(c->std_error));
-
- if (c->tty_path)
- fprintf(f,
- "%sTTYPath: %s\n"
- "%sTTYReset: %s\n"
- "%sTTYVHangup: %s\n"
- "%sTTYVTDisallocate: %s\n",
- prefix, c->tty_path,
- prefix, yes_no(c->tty_reset),
- prefix, yes_no(c->tty_vhangup),
- prefix, yes_no(c->tty_vt_disallocate));
-
- if (c->std_output == EXEC_OUTPUT_SYSLOG || c->std_output == EXEC_OUTPUT_KMSG || c->std_output == EXEC_OUTPUT_JOURNAL ||
- c->std_output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || c->std_output == EXEC_OUTPUT_KMSG_AND_CONSOLE || c->std_output == EXEC_OUTPUT_JOURNAL_AND_CONSOLE ||
- c->std_error == EXEC_OUTPUT_SYSLOG || c->std_error == EXEC_OUTPUT_KMSG || c->std_error == EXEC_OUTPUT_JOURNAL ||
- c->std_error == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || c->std_error == EXEC_OUTPUT_KMSG_AND_CONSOLE || c->std_error == EXEC_OUTPUT_JOURNAL_AND_CONSOLE) {
- char *fac_str, *lvl_str;
- int r;
-
- r = log_facility_unshifted_to_string_alloc(c->syslog_priority >> 3, &fac_str);
- if (r < 0)
- fac_str = NULL;
-
- r = log_level_to_string_alloc(LOG_PRI(c->syslog_priority), &lvl_str);
- if (r < 0)
- lvl_str = NULL;
-
- fprintf(f,
- "%sSyslogFacility: %s\n"
- "%sSyslogLevel: %s\n",
- prefix, strna(fac_str),
- prefix, strna(lvl_str));
- free(lvl_str);
- free(fac_str);
- }
-
- if (c->capabilities) {
- char *t;
- if ((t = cap_to_text(c->capabilities, NULL))) {
- fprintf(f, "%sCapabilities: %s\n",
- prefix, t);
- cap_free(t);
- }
- }
-
- if (c->secure_bits)
- fprintf(f, "%sSecure Bits:%s%s%s%s%s%s\n",
- prefix,
- (c->secure_bits & SECURE_KEEP_CAPS) ? " keep-caps" : "",
- (c->secure_bits & SECURE_KEEP_CAPS_LOCKED) ? " keep-caps-locked" : "",
- (c->secure_bits & SECURE_NO_SETUID_FIXUP) ? " no-setuid-fixup" : "",
- (c->secure_bits & SECURE_NO_SETUID_FIXUP_LOCKED) ? " no-setuid-fixup-locked" : "",
- (c->secure_bits & SECURE_NOROOT) ? " noroot" : "",
- (c->secure_bits & SECURE_NOROOT_LOCKED) ? "noroot-locked" : "");
-
- if (c->capability_bounding_set_drop) {
- unsigned long l;
- fprintf(f, "%sCapabilityBoundingSet:", prefix);
-
- for (l = 0; l <= cap_last_cap(); l++)
- if (!(c->capability_bounding_set_drop & ((uint64_t) 1ULL << (uint64_t) l))) {
- char *t;
-
- if ((t = cap_to_name(l))) {
- fprintf(f, " %s", t);
- cap_free(t);
- }
- }
-
- fputs("\n", f);
- }
-
- if (c->user)
- fprintf(f, "%sUser: %s\n", prefix, c->user);
- if (c->group)
- fprintf(f, "%sGroup: %s\n", prefix, c->group);
-
- if (strv_length(c->supplementary_groups) > 0) {
- fprintf(f, "%sSupplementaryGroups:", prefix);
- strv_fprintf(f, c->supplementary_groups);
- fputs("\n", f);
- }
-
- if (c->pam_name)
- fprintf(f, "%sPAMName: %s\n", prefix, c->pam_name);
-
- if (strv_length(c->read_write_dirs) > 0) {
- fprintf(f, "%sReadWriteDirs:", prefix);
- strv_fprintf(f, c->read_write_dirs);
- fputs("\n", f);
- }
-
- if (strv_length(c->read_only_dirs) > 0) {
- fprintf(f, "%sReadOnlyDirs:", prefix);
- strv_fprintf(f, c->read_only_dirs);
- fputs("\n", f);
- }
-
- if (strv_length(c->inaccessible_dirs) > 0) {
- fprintf(f, "%sInaccessibleDirs:", prefix);
- strv_fprintf(f, c->inaccessible_dirs);
- fputs("\n", f);
- }
-
- if (c->utmp_id)
- fprintf(f,
- "%sUtmpIdentifier: %s\n",
- prefix, c->utmp_id);
-}
-
-void exec_status_start(ExecStatus *s, pid_t pid) {
- assert(s);
-
- zero(*s);
- s->pid = pid;
- dual_timestamp_get(&s->start_timestamp);
-}
-
-void exec_status_exit(ExecStatus *s, ExecContext *context, pid_t pid, int code, int status) {
- assert(s);
-
- if (s->pid && s->pid != pid)
- zero(*s);
-
- s->pid = pid;
- dual_timestamp_get(&s->exit_timestamp);
-
- s->code = code;
- s->status = status;
-
- if (context) {
- if (context->utmp_id)
- utmp_put_dead_process(context->utmp_id, pid, code, status);
-
- exec_context_tty_reset(context);
- }
-}
-
-void exec_status_dump(ExecStatus *s, FILE *f, const char *prefix) {
- char buf[FORMAT_TIMESTAMP_MAX];
-
- assert(s);
- assert(f);
-
- if (!prefix)
- prefix = "";
-
- if (s->pid <= 0)
- return;
-
- fprintf(f,
- "%sPID: %lu\n",
- prefix, (unsigned long) s->pid);
-
- if (s->start_timestamp.realtime > 0)
- fprintf(f,
- "%sStart Timestamp: %s\n",
- prefix, format_timestamp(buf, sizeof(buf), s->start_timestamp.realtime));
-
- if (s->exit_timestamp.realtime > 0)
- fprintf(f,
- "%sExit Timestamp: %s\n"
- "%sExit Code: %s\n"
- "%sExit Status: %i\n",
- prefix, format_timestamp(buf, sizeof(buf), s->exit_timestamp.realtime),
- prefix, sigchld_code_to_string(s->code),
- prefix, s->status);
-}
-
-char *exec_command_line(char **argv) {
- size_t k;
- char *n, *p, **a;
- bool first = true;
-
- assert(argv);
-
- k = 1;
- STRV_FOREACH(a, argv)
- k += strlen(*a)+3;
-
- if (!(n = new(char, k)))
- return NULL;
-
- p = n;
- STRV_FOREACH(a, argv) {
-
- if (!first)
- *(p++) = ' ';
- else
- first = false;
-
- if (strpbrk(*a, WHITESPACE)) {
- *(p++) = '\'';
- p = stpcpy(p, *a);
- *(p++) = '\'';
- } else
- p = stpcpy(p, *a);
-
- }
-
- *p = 0;
-
- /* FIXME: this doesn't really handle arguments that have
- * spaces and ticks in them */
-
- return n;
-}
-
-void exec_command_dump(ExecCommand *c, FILE *f, const char *prefix) {
- char *p2;
- const char *prefix2;
-
- char *cmd;
-
- assert(c);
- assert(f);
-
- if (!prefix)
- prefix = "";
- p2 = strappend(prefix, "\t");
- prefix2 = p2 ? p2 : prefix;
-
- cmd = exec_command_line(c->argv);
-
- fprintf(f,
- "%sCommand Line: %s\n",
- prefix, cmd ? cmd : strerror(ENOMEM));
-
- free(cmd);
-
- exec_status_dump(&c->exec_status, f, prefix2);
-
- free(p2);
-}
-
-void exec_command_dump_list(ExecCommand *c, FILE *f, const char *prefix) {
- assert(f);
-
- if (!prefix)
- prefix = "";
-
- LIST_FOREACH(command, c, c)
- exec_command_dump(c, f, prefix);
-}
-
-void exec_command_append_list(ExecCommand **l, ExecCommand *e) {
- ExecCommand *end;
-
- assert(l);
- assert(e);
-
- if (*l) {
- /* It's kind of important, that we keep the order here */
- LIST_FIND_TAIL(ExecCommand, command, *l, end);
- LIST_INSERT_AFTER(ExecCommand, command, *l, end, e);
- } else
- *l = e;
-}
-
-int exec_command_set(ExecCommand *c, const char *path, ...) {
- va_list ap;
- char **l, *p;
-
- assert(c);
- assert(path);
-
- va_start(ap, path);
- l = strv_new_ap(path, ap);
- va_end(ap);
-
- if (!l)
- return -ENOMEM;
-
- if (!(p = strdup(path))) {
- strv_free(l);
- return -ENOMEM;
- }
-
- free(c->path);
- c->path = p;
-
- strv_free(c->argv);
- c->argv = l;
-
- return 0;
-}
-
-static const char* const exec_input_table[_EXEC_INPUT_MAX] = {
- [EXEC_INPUT_NULL] = "null",
- [EXEC_INPUT_TTY] = "tty",
- [EXEC_INPUT_TTY_FORCE] = "tty-force",
- [EXEC_INPUT_TTY_FAIL] = "tty-fail",
- [EXEC_INPUT_SOCKET] = "socket"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(exec_input, ExecInput);
-
-static const char* const exec_output_table[_EXEC_OUTPUT_MAX] = {
- [EXEC_OUTPUT_INHERIT] = "inherit",
- [EXEC_OUTPUT_NULL] = "null",
- [EXEC_OUTPUT_TTY] = "tty",
- [EXEC_OUTPUT_SYSLOG] = "syslog",
- [EXEC_OUTPUT_SYSLOG_AND_CONSOLE] = "syslog+console",
- [EXEC_OUTPUT_KMSG] = "kmsg",
- [EXEC_OUTPUT_KMSG_AND_CONSOLE] = "kmsg+console",
- [EXEC_OUTPUT_JOURNAL] = "journal",
- [EXEC_OUTPUT_JOURNAL_AND_CONSOLE] = "journal+console",
- [EXEC_OUTPUT_SOCKET] = "socket"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(exec_output, ExecOutput);
diff --git a/src/core/execute.h b/src/core/execute.h
deleted file mode 100644
index 2bcd2e1e6c..0000000000
--- a/src/core/execute.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/*-*- 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/>.
-***/
-
-typedef struct ExecStatus ExecStatus;
-typedef struct ExecCommand ExecCommand;
-typedef struct ExecContext ExecContext;
-
-#include <linux/types.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/capability.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <sched.h>
-
-struct CGroupBonding;
-struct CGroupAttribute;
-
-#include "list.h"
-#include "util.h"
-
-typedef enum ExecInput {
- EXEC_INPUT_NULL,
- EXEC_INPUT_TTY,
- EXEC_INPUT_TTY_FORCE,
- EXEC_INPUT_TTY_FAIL,
- EXEC_INPUT_SOCKET,
- _EXEC_INPUT_MAX,
- _EXEC_INPUT_INVALID = -1
-} ExecInput;
-
-typedef enum ExecOutput {
- EXEC_OUTPUT_INHERIT,
- EXEC_OUTPUT_NULL,
- EXEC_OUTPUT_TTY,
- EXEC_OUTPUT_SYSLOG,
- EXEC_OUTPUT_SYSLOG_AND_CONSOLE,
- EXEC_OUTPUT_KMSG,
- EXEC_OUTPUT_KMSG_AND_CONSOLE,
- EXEC_OUTPUT_JOURNAL,
- EXEC_OUTPUT_JOURNAL_AND_CONSOLE,
- EXEC_OUTPUT_SOCKET,
- _EXEC_OUTPUT_MAX,
- _EXEC_OUTPUT_INVALID = -1
-} ExecOutput;
-
-struct ExecStatus {
- dual_timestamp start_timestamp;
- dual_timestamp exit_timestamp;
- pid_t pid;
- int code; /* as in siginfo_t::si_code */
- int status; /* as in sigingo_t::si_status */
-};
-
-struct ExecCommand {
- char *path;
- char **argv;
- ExecStatus exec_status;
- LIST_FIELDS(ExecCommand, command); /* useful for chaining commands */
- bool ignore;
-};
-
-struct ExecContext {
- char **environment;
- char **environment_files;
-
- struct rlimit *rlimit[RLIMIT_NLIMITS];
- char *working_directory, *root_directory;
-
- mode_t umask;
- int oom_score_adjust;
- int nice;
- int ioprio;
- int cpu_sched_policy;
- int cpu_sched_priority;
-
- cpu_set_t *cpuset;
- unsigned cpuset_ncpus;
-
- ExecInput std_input;
- ExecOutput std_output;
- ExecOutput std_error;
-
- nsec_t timer_slack_nsec;
-
- char *tcpwrap_name;
-
- char *tty_path;
-
- bool tty_reset;
- bool tty_vhangup;
- bool tty_vt_disallocate;
-
- bool ignore_sigpipe;
-
- /* Since resolving these names might might involve socket
- * connections and we don't want to deadlock ourselves these
- * names are resolved on execution only and in the child
- * process. */
- char *user;
- char *group;
- char **supplementary_groups;
-
- char *pam_name;
-
- char *utmp_id;
-
- char **read_write_dirs, **read_only_dirs, **inaccessible_dirs;
- unsigned long mount_flags;
-
- uint64_t capability_bounding_set_drop;
-
- cap_t capabilities;
- int secure_bits;
-
- int syslog_priority;
- char *syslog_identifier;
- bool syslog_level_prefix;
-
- bool cpu_sched_reset_on_fork;
- bool non_blocking;
- bool private_tmp;
- bool private_network;
-
- bool no_new_privileges;
-
- bool control_group_modify;
- int control_group_persistent;
-
- /* This is not exposed to the user but available
- * internally. We need it to make sure that whenever we spawn
- * /bin/mount it is run in the same process group as us so
- * that the autofs logic detects that it belongs to us and we
- * don't enter a trigger loop. */
- bool same_pgrp;
-
- uint32_t *syscall_filter;
-
- bool oom_score_adjust_set:1;
- bool nice_set:1;
- bool ioprio_set:1;
- bool cpu_sched_set:1;
-};
-
-int exec_spawn(ExecCommand *command,
- char **argv,
- const ExecContext *context,
- int fds[], unsigned n_fds,
- char **environment,
- bool apply_permissions,
- bool apply_chroot,
- bool apply_tty_stdin,
- bool confirm_spawn,
- struct CGroupBonding *cgroup_bondings,
- struct CGroupAttribute *cgroup_attributes,
- const char *cgroup_suffix,
- const char *unit_id,
- int pipe_fd[2],
- pid_t *ret);
-
-void exec_command_done(ExecCommand *c);
-void exec_command_done_array(ExecCommand *c, unsigned n);
-
-void exec_command_free_list(ExecCommand *c);
-void exec_command_free_array(ExecCommand **c, unsigned n);
-
-char *exec_command_line(char **argv);
-
-void exec_command_dump(ExecCommand *c, FILE *f, const char *prefix);
-void exec_command_dump_list(ExecCommand *c, FILE *f, const char *prefix);
-void exec_command_append_list(ExecCommand **l, ExecCommand *e);
-int exec_command_set(ExecCommand *c, const char *path, ...);
-
-void exec_context_init(ExecContext *c);
-void exec_context_done(ExecContext *c);
-void exec_context_dump(ExecContext *c, FILE* f, const char *prefix);
-void exec_context_tty_reset(const ExecContext *context);
-
-int exec_context_load_environment(const ExecContext *c, char ***l);
-
-void exec_status_start(ExecStatus *s, pid_t pid);
-void exec_status_exit(ExecStatus *s, ExecContext *context, pid_t pid, int code, int status);
-void exec_status_dump(ExecStatus *s, FILE *f, const char *prefix);
-
-const char* exec_output_to_string(ExecOutput i);
-ExecOutput exec_output_from_string(const char *s);
-
-const char* exec_input_to_string(ExecInput i);
-ExecInput exec_input_from_string(const char *s);
diff --git a/src/core/fdset.c b/src/core/fdset.c
deleted file mode 100644
index fe918cd8cc..0000000000
--- a/src/core/fdset.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*-*- 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 <errno.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include "set.h"
-#include "util.h"
-#include "macro.h"
-#include "fdset.h"
-
-#define MAKE_SET(s) ((Set*) s)
-#define MAKE_FDSET(s) ((FDSet*) s)
-
-/* Make sure we can distuingish fd 0 and NULL */
-#define FD_TO_PTR(fd) INT_TO_PTR((fd)+1)
-#define PTR_TO_FD(p) (PTR_TO_INT(p)-1)
-
-FDSet *fdset_new(void) {
- return MAKE_FDSET(set_new(trivial_hash_func, trivial_compare_func));
-}
-
-void fdset_free(FDSet *s) {
- void *p;
-
- while ((p = set_steal_first(MAKE_SET(s)))) {
- /* Valgrind's fd might have ended up in this set here,
- * due to fdset_new_fill(). We'll ignore all failures
- * here, so that the EBADFD that valgrind will return
- * us on close() doesn't influence us */
-
- /* When reloading duplicates of the private bus
- * connection fds and suchlike are closed here, which
- * has no effect at all, since they are only
- * duplicates. So don't be surprised about these log
- * messages. */
-
- log_debug("Closing left-over fd %i", PTR_TO_FD(p));
- close_nointr(PTR_TO_FD(p));
- }
-
- set_free(MAKE_SET(s));
-}
-
-int fdset_put(FDSet *s, int fd) {
- assert(s);
- assert(fd >= 0);
-
- return set_put(MAKE_SET(s), FD_TO_PTR(fd));
-}
-
-int fdset_put_dup(FDSet *s, int fd) {
- int copy, r;
-
- assert(s);
- assert(fd >= 0);
-
- if ((copy = fcntl(fd, F_DUPFD_CLOEXEC, 3)) < 0)
- return -errno;
-
- if ((r = fdset_put(s, copy)) < 0) {
- close_nointr_nofail(copy);
- return r;
- }
-
- return copy;
-}
-
-bool fdset_contains(FDSet *s, int fd) {
- assert(s);
- assert(fd >= 0);
-
- return !!set_get(MAKE_SET(s), FD_TO_PTR(fd));
-}
-
-int fdset_remove(FDSet *s, int fd) {
- assert(s);
- assert(fd >= 0);
-
- return set_remove(MAKE_SET(s), FD_TO_PTR(fd)) ? fd : -ENOENT;
-}
-
-int fdset_new_fill(FDSet **_s) {
- DIR *d;
- struct dirent *de;
- int r = 0;
- FDSet *s;
-
- assert(_s);
-
- /* Creates an fdsets and fills in all currently open file
- * descriptors. */
-
- if (!(d = opendir("/proc/self/fd")))
- return -errno;
-
- if (!(s = fdset_new())) {
- r = -ENOMEM;
- goto finish;
- }
-
- while ((de = readdir(d))) {
- int fd = -1;
-
- if (ignore_file(de->d_name))
- continue;
-
- if ((r = safe_atoi(de->d_name, &fd)) < 0)
- goto finish;
-
- if (fd < 3)
- continue;
-
- if (fd == dirfd(d))
- continue;
-
- if ((r = fdset_put(s, fd)) < 0)
- goto finish;
- }
-
- r = 0;
- *_s = s;
- s = NULL;
-
-finish:
- closedir(d);
-
- /* We won't close the fds here! */
- if (s)
- set_free(MAKE_SET(s));
-
- return r;
-}
-
-int fdset_cloexec(FDSet *fds, bool b) {
- Iterator i;
- void *p;
- int r;
-
- assert(fds);
-
- SET_FOREACH(p, MAKE_SET(fds), i)
- if ((r = fd_cloexec(PTR_TO_FD(p), b)) < 0)
- return r;
-
- return 0;
-}
diff --git a/src/core/fdset.h b/src/core/fdset.h
deleted file mode 100644
index c3e408c8ad..0000000000
--- a/src/core/fdset.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*-*- 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/>.
-***/
-
-typedef struct FDSet FDSet;
-
-FDSet* fdset_new(void);
-void fdset_free(FDSet *s);
-
-int fdset_put(FDSet *s, int fd);
-int fdset_put_dup(FDSet *s, int fd);
-
-bool fdset_contains(FDSet *s, int fd);
-int fdset_remove(FDSet *s, int fd);
-
-int fdset_new_fill(FDSet **_s);
-
-int fdset_cloexec(FDSet *fds, bool b);
diff --git a/src/core/hostname-setup.c b/src/core/hostname-setup.c
deleted file mode 100644
index dbd2227e21..0000000000
--- a/src/core/hostname-setup.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*-*- 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 <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "hostname-setup.h"
-#include "macro.h"
-#include "util.h"
-#include "log.h"
-
-#if defined(TARGET_ALTLINUX) || defined(TARGET_MANDRIVA) || defined(TARGET_MAGEIA)
-#define FILENAME "/etc/sysconfig/network"
-#elif defined(TARGET_SUSE) || defined(TARGET_SLACKWARE)
-#define FILENAME "/etc/HOSTNAME"
-#elif defined(TARGET_GENTOO)
-#define FILENAME "/etc/conf.d/hostname"
-#endif
-
-static int read_and_strip_hostname(const char *path, char **hn) {
- char *s;
- int r;
-
- assert(path);
- assert(hn);
-
- r = read_one_line_file(path, &s);
- if (r < 0)
- return r;
-
- hostname_cleanup(s);
-
- if (isempty(s)) {
- free(s);
- return -ENOENT;
- }
-
- *hn = s;
-
- return 0;
-}
-
-static int read_distro_hostname(char **hn) {
-
-#if defined(TARGET_GENTOO) || defined(TARGET_ALTLINUX) || defined(TARGET_MANDRIVA) || defined(TARGET_MAGEIA)
- int r;
- _cleanup_fclose_ FILE *f = NULL;
-
- assert(hn);
-
- f = fopen(FILENAME, "re");
- if (!f)
- return -errno;
-
- for (;;) {
- char line[LINE_MAX];
- char *s, *k;
-
- if (!fgets(line, sizeof(line), f)) {
- if (feof(f))
- break;
-
- r = -errno;
- goto finish;
- }
-
- s = strstrip(line);
-
- if (!startswith_no_case(s, "HOSTNAME="))
- continue;
-
- k = strdup(s+9);
- if (!k) {
- r = -ENOMEM;
- goto finish;
- }
-
- hostname_cleanup(k);
-
- if (isempty(k)) {
- free(k);
- r = -ENOENT;
- goto finish;
- }
-
- *hn = k;
- r = 0;
- goto finish;
- }
-
- r = -ENOENT;
-
-finish:
- return r;
-
-#elif defined(TARGET_SUSE) || defined(TARGET_SLACKWARE)
- return read_and_strip_hostname(FILENAME, hn);
-#else
- return -ENOENT;
-#endif
-}
-
-static int read_hostname(char **hn) {
- int r;
-
- assert(hn);
-
- /* First, try to load the generic hostname configuration file,
- * that we support on all distributions */
-
- r = read_and_strip_hostname("/etc/hostname", hn);
- if (r < 0) {
- if (r == -ENOENT)
- return read_distro_hostname(hn);
-
- return r;
- }
-
- return 0;
-}
-
-int hostname_setup(void) {
- int r;
- char *b = NULL;
- const char *hn = NULL;
- bool enoent = false;
-
- r = read_hostname(&b);
- if (r < 0) {
- hn = NULL;
-
- if (r == -ENOENT)
- enoent = true;
- else
- log_warning("Failed to read configured hostname: %s", strerror(-r));
- } else
- hn = b;
-
- if (isempty(hn)) {
- /* Don't override the hostname if it is already set
- * and not explicitly configured */
- if (hostname_is_set())
- goto finish;
-
- if (enoent)
- log_info("No hostname configured.");
-
- hn = "localhost";
- }
-
- if (sethostname(hn, strlen(hn)) < 0) {
- log_warning("Failed to set hostname to <%s>: %m", hn);
- r = -errno;
- } else
- log_info("Set hostname to <%s>.", hn);
-
-finish:
- free(b);
-
- return r;
-}
diff --git a/src/core/hostname-setup.h b/src/core/hostname-setup.h
deleted file mode 100644
index 8dc3a9e1d8..0000000000
--- a/src/core/hostname-setup.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*-*- 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 hostname_setup(void);
diff --git a/src/core/ima-setup.c b/src/core/ima-setup.c
deleted file mode 100644
index e8cc1ba8b6..0000000000
--- a/src/core/ima-setup.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright (C) 2012 Roberto Sassu - Politecnico di Torino, Italy
- TORSEC group -- http://security.polito.it
-
- 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 <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-
-#include "ima-setup.h"
-#include "mount-setup.h"
-#include "macro.h"
-#include "util.h"
-#include "log.h"
-#include "label.h"
-
-#define IMA_SECFS_DIR "/sys/kernel/security/ima"
-#define IMA_SECFS_POLICY IMA_SECFS_DIR "/policy"
-#define IMA_POLICY_PATH "/etc/ima/ima-policy"
-
-int ima_setup(void) {
-
-#ifdef HAVE_IMA
- struct stat st;
- ssize_t policy_size = 0, written = 0;
- char *policy;
- int policyfd = -1, imafd = -1;
- int result = 0;
-
-#ifndef HAVE_SELINUX
- /* Mount the securityfs filesystem */
- mount_setup_early();
-#endif
-
- if (stat(IMA_POLICY_PATH, &st) < 0)
- return 0;
-
- policy_size = st.st_size;
- if (stat(IMA_SECFS_DIR, &st) < 0) {
- log_debug("IMA support is disabled in the kernel, ignoring.");
- return 0;
- }
-
- if (stat(IMA_SECFS_POLICY, &st) < 0) {
- log_error("Another IMA custom policy has already been loaded, "
- "ignoring.");
- return 0;
- }
-
- policyfd = open(IMA_POLICY_PATH, O_RDONLY|O_CLOEXEC);
- if (policyfd < 0) {
- log_error("Failed to open the IMA custom policy file %s (%m), "
- "ignoring.", IMA_POLICY_PATH);
- return 0;
- }
-
- imafd = open(IMA_SECFS_POLICY, O_WRONLY|O_CLOEXEC);
- if (imafd < 0) {
- log_error("Failed to open the IMA kernel interface %s (%m), "
- "ignoring.", IMA_SECFS_POLICY);
- goto out;
- }
-
- policy = mmap(NULL, policy_size, PROT_READ, MAP_PRIVATE, policyfd, 0);
- if (policy == MAP_FAILED) {
- log_error("mmap() failed (%m), freezing");
- result = -errno;
- goto out;
- }
-
- written = loop_write(imafd, policy, (size_t)policy_size, false);
- if (written != policy_size) {
- log_error("Failed to load the IMA custom policy file %s (%m), "
- "ignoring.", IMA_POLICY_PATH);
- goto out_mmap;
- }
-
- log_info("Successfully loaded the IMA custom policy %s.",
- IMA_POLICY_PATH);
-out_mmap:
- munmap(policy, policy_size);
-out:
- if (policyfd >= 0)
- close_nointr_nofail(policyfd);
- if (imafd >= 0)
- close_nointr_nofail(imafd);
- if (result)
- return result;
-#endif /* HAVE_IMA */
-
- return 0;
-}
diff --git a/src/core/ima-setup.h b/src/core/ima-setup.h
deleted file mode 100644
index 14b56d1fc2..0000000000
--- a/src/core/ima-setup.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright (C) 2012 Roberto Sassu - Politecnico di Torino, Italy
- TORSEC group -- http://security.polito.it
-
- 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 ima_setup(void);
diff --git a/src/core/initreq.h b/src/core/initreq.h
deleted file mode 100644
index 859042ce42..0000000000
--- a/src/core/initreq.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * initreq.h Interface to talk to init through /dev/initctl.
- *
- * Copyright (C) 1995-2004 Miquel van Smoorenburg
- *
- * This library 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 of the License, or (at your option) any later version.
- *
- * Version: @(#)initreq.h 1.28 31-Mar-2004 MvS
- *
- */
-#ifndef _INITREQ_H
-#define _INITREQ_H
-
-#include <sys/param.h>
-
-#if defined(__FreeBSD_kernel__)
-# define INIT_FIFO "/etc/.initctl"
-#else
-# define INIT_FIFO "/dev/initctl"
-#endif
-
-#define INIT_MAGIC 0x03091969
-#define INIT_CMD_START 0
-#define INIT_CMD_RUNLVL 1
-#define INIT_CMD_POWERFAIL 2
-#define INIT_CMD_POWERFAILNOW 3
-#define INIT_CMD_POWEROK 4
-#define INIT_CMD_BSD 5
-#define INIT_CMD_SETENV 6
-#define INIT_CMD_UNSETENV 7
-
-#define INIT_CMD_CHANGECONS 12345
-
-#ifdef MAXHOSTNAMELEN
-# define INITRQ_HLEN MAXHOSTNAMELEN
-#else
-# define INITRQ_HLEN 64
-#endif
-
-/*
- * This is what BSD 4.4 uses when talking to init.
- * Linux doesn't use this right now.
- */
-struct init_request_bsd {
- char gen_id[8]; /* Beats me.. telnetd uses "fe" */
- char tty_id[16]; /* Tty name minus /dev/tty */
- char host[INITRQ_HLEN]; /* Hostname */
- char term_type[16]; /* Terminal type */
- int signal; /* Signal to send */
- int pid; /* Process to send to */
- char exec_name[128]; /* Program to execute */
- char reserved[128]; /* For future expansion. */
-};
-
-
-/*
- * Because of legacy interfaces, "runlevel" and "sleeptime"
- * aren't in a separate struct in the union.
- *
- * The weird sizes are because init expects the whole
- * struct to be 384 bytes.
- */
-struct init_request {
- int magic; /* Magic number */
- int cmd; /* What kind of request */
- int runlevel; /* Runlevel to change to */
- int sleeptime; /* Time between TERM and KILL */
- union {
- struct init_request_bsd bsd;
- char data[368];
- } i;
-};
-
-#endif
diff --git a/src/core/job.c b/src/core/job.c
deleted file mode 100644
index f08b8cbc7d..0000000000
--- a/src/core/job.c
+++ /dev/null
@@ -1,1086 +0,0 @@
-/*-*- 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 <assert.h>
-#include <errno.h>
-#include <sys/timerfd.h>
-#include <sys/epoll.h>
-
-#include "systemd/sd-id128.h"
-#include "systemd/sd-messages.h"
-#include "set.h"
-#include "unit.h"
-#include "macro.h"
-#include "strv.h"
-#include "load-fragment.h"
-#include "load-dropin.h"
-#include "log.h"
-#include "dbus-job.h"
-
-JobBusClient* job_bus_client_new(DBusConnection *connection, const char *name) {
- JobBusClient *cl;
- size_t name_len;
-
- name_len = strlen(name);
- cl = malloc0(sizeof(JobBusClient) + name_len + 1);
- if (!cl)
- return NULL;
-
- cl->bus = connection;
- memcpy(cl->name, name, name_len + 1);
- return cl;
-}
-
-Job* job_new_raw(Unit *unit) {
- Job *j;
-
- /* used for deserialization */
-
- assert(unit);
-
- j = new0(Job, 1);
- if (!j)
- return NULL;
-
- j->manager = unit->manager;
- j->unit = unit;
- j->type = _JOB_TYPE_INVALID;
- j->timer_watch.type = WATCH_INVALID;
-
- return j;
-}
-
-Job* job_new(Unit *unit, JobType type) {
- Job *j;
-
- assert(type < _JOB_TYPE_MAX);
-
- j = job_new_raw(unit);
- if (!j)
- return NULL;
-
- j->id = j->manager->current_job_id++;
- j->type = type;
-
- /* We don't link it here, that's what job_dependency() is for */
-
- return j;
-}
-
-void job_free(Job *j) {
- JobBusClient *cl;
-
- assert(j);
- assert(!j->installed);
- assert(!j->transaction_prev);
- assert(!j->transaction_next);
- assert(!j->subject_list);
- assert(!j->object_list);
-
- if (j->in_run_queue)
- LIST_REMOVE(Job, run_queue, j->manager->run_queue, j);
-
- if (j->in_dbus_queue)
- LIST_REMOVE(Job, dbus_queue, j->manager->dbus_job_queue, j);
-
- if (j->timer_watch.type != WATCH_INVALID) {
- assert(j->timer_watch.type == WATCH_JOB_TIMER);
- assert(j->timer_watch.data.job == j);
- assert(j->timer_watch.fd >= 0);
-
- assert_se(epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_DEL, j->timer_watch.fd, NULL) >= 0);
- close_nointr_nofail(j->timer_watch.fd);
- }
-
- while ((cl = j->bus_client_list)) {
- LIST_REMOVE(JobBusClient, client, j->bus_client_list, cl);
- free(cl);
- }
- free(j);
-}
-
-void job_uninstall(Job *j) {
- Job **pj;
-
- assert(j->installed);
-
- pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
- assert(*pj == j);
-
- /* Detach from next 'bigger' objects */
-
- /* daemon-reload should be transparent to job observers */
- if (j->manager->n_reloading <= 0)
- bus_job_send_removed_signal(j);
-
- *pj = NULL;
-
- unit_add_to_gc_queue(j->unit);
-
- hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id));
- j->installed = false;
-}
-
-static bool job_type_allows_late_merge(JobType t) {
- /* Tells whether it is OK to merge a job of type 't' with an already
- * running job.
- * Reloads cannot be merged this way. Think of the sequence:
- * 1. Reload of a daemon is in progress; the daemon has already loaded
- * its config file, but hasn't completed the reload operation yet.
- * 2. Edit foo's config file.
- * 3. Trigger another reload to have the daemon use the new config.
- * Should the second reload job be merged into the first one, the daemon
- * would not know about the new config.
- * JOB_RESTART jobs on the other hand can be merged, because they get
- * patched into JOB_START after stopping the unit. So if we see a
- * JOB_RESTART running, it means the unit hasn't stopped yet and at
- * this time the merge is still allowed. */
- return t != JOB_RELOAD;
-}
-
-static void job_merge_into_installed(Job *j, Job *other) {
- assert(j->installed);
- assert(j->unit == other->unit);
-
- if (j->type != JOB_NOP)
- job_type_merge_and_collapse(&j->type, other->type, j->unit);
- else
- assert(other->type == JOB_NOP);
-
- j->override = j->override || other->override;
-}
-
-Job* job_install(Job *j) {
- Job **pj;
- Job *uj;
-
- assert(!j->installed);
- assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
-
- pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
- uj = *pj;
-
- if (uj) {
- if (j->type != JOB_NOP && job_type_is_conflicting(uj->type, j->type))
- job_finish_and_invalidate(uj, JOB_CANCELED, false);
- else {
- /* not conflicting, i.e. mergeable */
-
- if (j->type == JOB_NOP || uj->state == JOB_WAITING ||
- (job_type_allows_late_merge(j->type) && job_type_is_superset(uj->type, j->type))) {
- job_merge_into_installed(uj, j);
- log_debug("Merged into installed job %s/%s as %u",
- uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
- return uj;
- } else {
- /* already running and not safe to merge into */
- /* Patch uj to become a merged job and re-run it. */
- /* XXX It should be safer to queue j to run after uj finishes, but it is
- * not currently possible to have more than one installed job per unit. */
- job_merge_into_installed(uj, j);
- log_debug("Merged into running job, re-running: %s/%s as %u",
- uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
- uj->state = JOB_WAITING;
- return uj;
- }
- }
- }
-
- /* Install the job */
- *pj = j;
- j->installed = true;
- j->manager->n_installed_jobs ++;
- log_debug("Installed new job %s/%s as %u", j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
- return j;
-}
-
-int job_install_deserialized(Job *j) {
- Job **pj;
-
- assert(!j->installed);
-
- if (j->type < 0 || j->type >= _JOB_TYPE_MAX_IN_TRANSACTION) {
- log_debug("Invalid job type %s in deserialization.", strna(job_type_to_string(j->type)));
- return -EINVAL;
- }
-
- pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
-
- if (*pj) {
- log_debug("Unit %s already has a job installed. Not installing deserialized job.", j->unit->id);
- return -EEXIST;
- }
- *pj = j;
- j->installed = true;
- log_debug("Reinstalled deserialized job %s/%s as %u", j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
- return 0;
-}
-
-JobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts) {
- JobDependency *l;
-
- assert(object);
-
- /* Adds a new job link, which encodes that the 'subject' job
- * needs the 'object' job in some way. If 'subject' is NULL
- * this means the 'anchor' job (i.e. the one the user
- * explicitly asked for) is the requester. */
-
- if (!(l = new0(JobDependency, 1)))
- return NULL;
-
- l->subject = subject;
- l->object = object;
- l->matters = matters;
- l->conflicts = conflicts;
-
- if (subject)
- LIST_PREPEND(JobDependency, subject, subject->subject_list, l);
-
- LIST_PREPEND(JobDependency, object, object->object_list, l);
-
- return l;
-}
-
-void job_dependency_free(JobDependency *l) {
- assert(l);
-
- if (l->subject)
- LIST_REMOVE(JobDependency, subject, l->subject->subject_list, l);
-
- LIST_REMOVE(JobDependency, object, l->object->object_list, l);
-
- free(l);
-}
-
-void job_dump(Job *j, FILE*f, const char *prefix) {
- assert(j);
- assert(f);
-
- if (!prefix)
- prefix = "";
-
- fprintf(f,
- "%s-> Job %u:\n"
- "%s\tAction: %s -> %s\n"
- "%s\tState: %s\n"
- "%s\tForced: %s\n",
- prefix, j->id,
- prefix, j->unit->id, job_type_to_string(j->type),
- prefix, job_state_to_string(j->state),
- prefix, yes_no(j->override));
-}
-
-/*
- * Merging is commutative, so imagine the matrix as symmetric. We store only
- * its lower triangle to avoid duplication. We don't store the main diagonal,
- * because A merged with A is simply A.
- *
- * If the resulting type is collapsed immediately afterwards (to get rid of
- * the JOB_RELOAD_OR_START, which lies outside the lookup function's domain),
- * the following properties hold:
- *
- * Merging is associative! A merged with B merged with C is the same as
- * A merged with C merged with B.
- *
- * Mergeability is transitive! If A can be merged with B and B with C then
- * A also with C.
- *
- * Also, if A merged with B cannot be merged with C, then either A or B cannot
- * be merged with C either.
- */
-static const JobType job_merging_table[] = {
-/* What \ With * JOB_START JOB_VERIFY_ACTIVE JOB_STOP JOB_RELOAD */
-/*********************************************************************************/
-/*JOB_START */
-/*JOB_VERIFY_ACTIVE */ JOB_START,
-/*JOB_STOP */ -1, -1,
-/*JOB_RELOAD */ JOB_RELOAD_OR_START, JOB_RELOAD, -1,
-/*JOB_RESTART */ JOB_RESTART, JOB_RESTART, -1, JOB_RESTART,
-};
-
-JobType job_type_lookup_merge(JobType a, JobType b) {
- assert_cc(ELEMENTSOF(job_merging_table) == _JOB_TYPE_MAX_MERGING * (_JOB_TYPE_MAX_MERGING - 1) / 2);
- assert(a >= 0 && a < _JOB_TYPE_MAX_MERGING);
- assert(b >= 0 && b < _JOB_TYPE_MAX_MERGING);
-
- if (a == b)
- return a;
-
- if (a < b) {
- JobType tmp = a;
- a = b;
- b = tmp;
- }
-
- return job_merging_table[(a - 1) * a / 2 + b];
-}
-
-bool job_type_is_redundant(JobType a, UnitActiveState b) {
- switch (a) {
-
- case JOB_START:
- return
- b == UNIT_ACTIVE ||
- b == UNIT_RELOADING;
-
- case JOB_STOP:
- return
- b == UNIT_INACTIVE ||
- b == UNIT_FAILED;
-
- case JOB_VERIFY_ACTIVE:
- return
- b == UNIT_ACTIVE ||
- b == UNIT_RELOADING;
-
- case JOB_RELOAD:
- return
- b == UNIT_RELOADING;
-
- case JOB_RESTART:
- return
- b == UNIT_ACTIVATING;
-
- default:
- assert_not_reached("Invalid job type");
- }
-}
-
-void job_type_collapse(JobType *t, Unit *u) {
- UnitActiveState s;
-
- switch (*t) {
-
- case JOB_TRY_RESTART:
- s = unit_active_state(u);
- if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
- *t = JOB_NOP;
- else
- *t = JOB_RESTART;
- break;
-
- case JOB_RELOAD_OR_START:
- s = unit_active_state(u);
- if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
- *t = JOB_START;
- else
- *t = JOB_RELOAD;
- break;
-
- default:
- ;
- }
-}
-
-int job_type_merge_and_collapse(JobType *a, JobType b, Unit *u) {
- JobType t = job_type_lookup_merge(*a, b);
- if (t < 0)
- return -EEXIST;
- *a = t;
- job_type_collapse(a, u);
- return 0;
-}
-
-bool job_is_runnable(Job *j) {
- Iterator i;
- Unit *other;
-
- assert(j);
- assert(j->installed);
-
- /* Checks whether there is any job running for the units this
- * job needs to be running after (in the case of a 'positive'
- * job type) or before (in the case of a 'negative' job
- * type. */
-
- /* First check if there is an override */
- if (j->ignore_order)
- return true;
-
- if (j->type == JOB_NOP)
- return true;
-
- if (j->type == JOB_START ||
- j->type == JOB_VERIFY_ACTIVE ||
- j->type == JOB_RELOAD) {
-
- /* Immediate result is that the job is or might be
- * started. In this case lets wait for the
- * dependencies, regardless whether they are
- * starting or stopping something. */
-
- SET_FOREACH(other, j->unit->dependencies[UNIT_AFTER], i)
- if (other->job)
- return false;
- }
-
- /* Also, if something else is being stopped and we should
- * change state after it, then lets wait. */
-
- SET_FOREACH(other, j->unit->dependencies[UNIT_BEFORE], i)
- if (other->job &&
- (other->job->type == JOB_STOP ||
- other->job->type == JOB_RESTART))
- return false;
-
- /* This means that for a service a and a service b where b
- * shall be started after a:
- *
- * start a + start b → 1st step start a, 2nd step start b
- * start a + stop b → 1st step stop b, 2nd step start a
- * stop a + start b → 1st step stop a, 2nd step start b
- * stop a + stop b → 1st step stop b, 2nd step stop a
- *
- * This has the side effect that restarts are properly
- * synchronized too. */
-
- return true;
-}
-
-static void job_change_type(Job *j, JobType newtype) {
- log_debug("Converting job %s/%s -> %s/%s",
- j->unit->id, job_type_to_string(j->type),
- j->unit->id, job_type_to_string(newtype));
-
- j->type = newtype;
-}
-
-int job_run_and_invalidate(Job *j) {
- int r;
- uint32_t id;
- Manager *m;
-
- assert(j);
- assert(j->installed);
- assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
- assert(j->in_run_queue);
-
- LIST_REMOVE(Job, run_queue, j->manager->run_queue, j);
- j->in_run_queue = false;
-
- if (j->state != JOB_WAITING)
- return 0;
-
- if (!job_is_runnable(j))
- return -EAGAIN;
-
- j->state = JOB_RUNNING;
- job_add_to_dbus_queue(j);
-
- /* While we execute this operation the job might go away (for
- * example: because it is replaced by a new, conflicting
- * job.) To make sure we don't access a freed job later on we
- * store the id here, so that we can verify the job is still
- * valid. */
- id = j->id;
- m = j->manager;
-
- switch (j->type) {
-
- case JOB_START:
- r = unit_start(j->unit);
-
- /* If this unit cannot be started, then simply wait */
- if (r == -EBADR)
- r = 0;
- break;
-
- case JOB_VERIFY_ACTIVE: {
- UnitActiveState t = unit_active_state(j->unit);
- if (UNIT_IS_ACTIVE_OR_RELOADING(t))
- r = -EALREADY;
- else if (t == UNIT_ACTIVATING)
- r = -EAGAIN;
- else
- r = -ENOEXEC;
- break;
- }
-
- case JOB_STOP:
- case JOB_RESTART:
- r = unit_stop(j->unit);
-
- /* If this unit cannot stopped, then simply wait. */
- if (r == -EBADR)
- r = 0;
- break;
-
- case JOB_RELOAD:
- r = unit_reload(j->unit);
- break;
-
- case JOB_NOP:
- r = -EALREADY;
- break;
-
- default:
- assert_not_reached("Unknown job type");
- }
-
- j = manager_get_job(m, id);
- if (j) {
- if (r == -EALREADY)
- r = job_finish_and_invalidate(j, JOB_DONE, true);
- else if (r == -ENOEXEC)
- r = job_finish_and_invalidate(j, JOB_SKIPPED, true);
- else if (r == -EAGAIN)
- j->state = JOB_WAITING;
- else if (r < 0)
- r = job_finish_and_invalidate(j, JOB_FAILED, true);
- }
-
- return r;
-}
-
-static const char *job_get_status_message_format(Unit *u, JobType t, JobResult result) {
- const UnitStatusMessageFormats *format_table;
-
- assert(u);
- assert(t >= 0);
- assert(t < _JOB_TYPE_MAX);
-
- format_table = &UNIT_VTABLE(u)->status_message_formats;
- if (!format_table)
- return NULL;
-
- if (t == JOB_START)
- return format_table->finished_start_job[result];
- else if (t == JOB_STOP || t == JOB_RESTART)
- return format_table->finished_stop_job[result];
-
- return NULL;
-}
-
-static const char *job_get_status_message_format_try_harder(Unit *u, JobType t, JobResult result) {
- const char *format;
-
- assert(u);
- assert(t >= 0);
- assert(t < _JOB_TYPE_MAX);
-
- format = job_get_status_message_format(u, t, result);
- if (format)
- return format;
-
- /* Return generic strings */
- if (t == JOB_START) {
- if (result == JOB_DONE)
- return "Started %s.";
- else if (result == JOB_FAILED)
- return "Failed to start %s.";
- else if (result == JOB_DEPENDENCY)
- return "Dependency failed for %s.";
- else if (result == JOB_TIMEOUT)
- return "Timed out starting %s.";
- } else if (t == JOB_STOP || t == JOB_RESTART) {
- if (result == JOB_DONE)
- return "Stopped %s.";
- else if (result == JOB_FAILED)
- return "Stopped (with error) %s.";
- else if (result == JOB_TIMEOUT)
- return "Timed out stoppping %s.";
- } else if (t == JOB_RELOAD) {
- if (result == JOB_DONE)
- return "Reloaded %s.";
- else if (result == JOB_FAILED)
- return "Reload failed for %s.";
- else if (result == JOB_TIMEOUT)
- return "Timed out reloading %s.";
- }
-
- return NULL;
-}
-
-static void job_print_status_message(Unit *u, JobType t, JobResult result) {
- const char *format;
-
- assert(u);
- assert(t >= 0);
- assert(t < _JOB_TYPE_MAX);
-
- if (t == JOB_START) {
- format = job_get_status_message_format(u, t, result);
- if (!format)
- return;
-
- switch (result) {
-
- case JOB_DONE:
- if (u->condition_result)
- unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
- break;
-
- case JOB_FAILED:
- unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF, format, unit_description(u));
- unit_status_printf(u, NULL, "See 'systemctl status %s' for details.", u->id);
- break;
-
- case JOB_DEPENDENCY:
- unit_status_printf(u, ANSI_HIGHLIGHT_YELLOW_ON "DEPEND" ANSI_HIGHLIGHT_OFF, format, unit_description(u));
- break;
-
- case JOB_TIMEOUT:
- unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
- break;
-
- default:
- ;
- }
-
- } else if (t == JOB_STOP || t == JOB_RESTART) {
-
- format = job_get_status_message_format(u, t, result);
- if (!format)
- return;
-
- switch (result) {
-
- case JOB_TIMEOUT:
- unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
- break;
-
- case JOB_DONE:
- case JOB_FAILED:
- unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
- break;
-
- default:
- ;
- }
-
- } else if (t == JOB_VERIFY_ACTIVE) {
-
- /* When verify-active detects the unit is inactive, report it.
- * Most likely a DEPEND warning from a requisiting unit will
- * occur next and it's nice to see what was requisited. */
- if (result == JOB_SKIPPED)
- unit_status_printf(u, ANSI_HIGHLIGHT_ON " INFO " ANSI_HIGHLIGHT_OFF, "%s is not active.", unit_description(u));
- }
-}
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wformat-nonliteral"
-static void job_log_status_message(Unit *u, JobType t, JobResult result) {
- const char *format;
- char buf[LINE_MAX];
-
- assert(u);
- assert(t >= 0);
- assert(t < _JOB_TYPE_MAX);
-
- /* Skip this if it goes to the console. since we already print
- * to the console anyway... */
-
- if (log_on_console())
- return;
-
- format = job_get_status_message_format_try_harder(u, t, result);
- if (!format)
- return;
-
- snprintf(buf, sizeof(buf), format, unit_description(u));
- char_array_0(buf);
-
- if (t == JOB_START) {
- sd_id128_t mid;
-
- mid = result == JOB_DONE ? SD_MESSAGE_UNIT_STARTED : SD_MESSAGE_UNIT_FAILED;
- log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
- MESSAGE_ID(mid),
- "UNIT=%s", u->id,
- "RESULT=%s", job_result_to_string(result),
- "MESSAGE=%s", buf,
- NULL);
-
- } else if (t == JOB_STOP)
- log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
- MESSAGE_ID(SD_MESSAGE_UNIT_STOPPED),
- "UNIT=%s", u->id,
- "RESULT=%s", job_result_to_string(result),
- "MESSAGE=%s", buf,
- NULL);
-
- else if (t == JOB_RELOAD)
- log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
- MESSAGE_ID(SD_MESSAGE_UNIT_RELOADED),
- "UNIT=%s", u->id,
- "RESULT=%s", job_result_to_string(result),
- "MESSAGE=%s", buf,
- NULL);
-}
-#pragma GCC diagnostic pop
-
-int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
- Unit *u;
- Unit *other;
- JobType t;
- Iterator i;
-
- assert(j);
- assert(j->installed);
- assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
-
- u = j->unit;
- t = j->type;
-
- j->result = result;
-
- log_debug("Job %s/%s finished, result=%s", u->id, job_type_to_string(t), job_result_to_string(result));
-
- job_print_status_message(u, t, result);
- job_log_status_message(u, t, result);
-
- job_add_to_dbus_queue(j);
-
- /* Patch restart jobs so that they become normal start jobs */
- if (result == JOB_DONE && t == JOB_RESTART) {
-
- job_change_type(j, JOB_START);
- j->state = JOB_WAITING;
-
- job_add_to_run_queue(j);
-
- goto finish;
- }
-
- if (result == JOB_FAILED)
- j->manager->n_failed_jobs ++;
-
- job_uninstall(j);
- job_free(j);
-
- /* Fail depending jobs on failure */
- if (result != JOB_DONE && recursive) {
-
- if (t == JOB_START ||
- t == JOB_VERIFY_ACTIVE) {
-
- SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i)
- if (other->job &&
- (other->job->type == JOB_START ||
- other->job->type == JOB_VERIFY_ACTIVE))
- job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
-
- SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
- if (other->job &&
- (other->job->type == JOB_START ||
- other->job->type == JOB_VERIFY_ACTIVE))
- job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
-
- SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
- if (other->job &&
- !other->job->override &&
- (other->job->type == JOB_START ||
- other->job->type == JOB_VERIFY_ACTIVE))
- job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
-
- } else if (t == JOB_STOP) {
-
- SET_FOREACH(other, u->dependencies[UNIT_CONFLICTED_BY], i)
- if (other->job &&
- (other->job->type == JOB_START ||
- other->job->type == JOB_VERIFY_ACTIVE))
- job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
- }
- }
-
- /* Trigger OnFailure dependencies that are not generated by
- * the unit itself. We don't tread JOB_CANCELED as failure in
- * this context. And JOB_FAILURE is already handled by the
- * unit itself. */
- if (result == JOB_TIMEOUT || result == JOB_DEPENDENCY) {
- log_notice("Job %s/%s failed with result '%s'.",
- u->id,
- job_type_to_string(t),
- job_result_to_string(result));
-
- unit_trigger_on_failure(u);
- }
-
-finish:
- /* Try to start the next jobs that can be started */
- SET_FOREACH(other, u->dependencies[UNIT_AFTER], i)
- if (other->job)
- job_add_to_run_queue(other->job);
- SET_FOREACH(other, u->dependencies[UNIT_BEFORE], i)
- if (other->job)
- job_add_to_run_queue(other->job);
-
- manager_check_finished(u->manager);
-
- return 0;
-}
-
-int job_start_timer(Job *j) {
- struct itimerspec its;
- struct epoll_event ev;
- int fd, r;
- assert(j);
-
- if (j->unit->job_timeout <= 0 ||
- j->timer_watch.type == WATCH_JOB_TIMER)
- return 0;
-
- assert(j->timer_watch.type == WATCH_INVALID);
-
- if ((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0) {
- r = -errno;
- goto fail;
- }
-
- zero(its);
- timespec_store(&its.it_value, j->unit->job_timeout);
-
- if (timerfd_settime(fd, 0, &its, NULL) < 0) {
- r = -errno;
- goto fail;
- }
-
- zero(ev);
- ev.data.ptr = &j->timer_watch;
- ev.events = EPOLLIN;
-
- if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
- r = -errno;
- goto fail;
- }
-
- j->timer_watch.type = WATCH_JOB_TIMER;
- j->timer_watch.fd = fd;
- j->timer_watch.data.job = j;
-
- return 0;
-
-fail:
- if (fd >= 0)
- close_nointr_nofail(fd);
-
- return r;
-}
-
-void job_add_to_run_queue(Job *j) {
- assert(j);
- assert(j->installed);
-
- if (j->in_run_queue)
- return;
-
- LIST_PREPEND(Job, run_queue, j->manager->run_queue, j);
- j->in_run_queue = true;
-}
-
-void job_add_to_dbus_queue(Job *j) {
- assert(j);
- assert(j->installed);
-
- if (j->in_dbus_queue)
- return;
-
- /* We don't check if anybody is subscribed here, since this
- * job might just have been created and not yet assigned to a
- * connection/client. */
-
- LIST_PREPEND(Job, dbus_queue, j->manager->dbus_job_queue, j);
- j->in_dbus_queue = true;
-}
-
-char *job_dbus_path(Job *j) {
- char *p;
-
- assert(j);
-
- if (asprintf(&p, "/org/freedesktop/systemd1/job/%lu", (unsigned long) j->id) < 0)
- return NULL;
-
- return p;
-}
-
-void job_timer_event(Job *j, uint64_t n_elapsed, Watch *w) {
- assert(j);
- assert(w == &j->timer_watch);
-
- log_warning("Job %s/%s timed out.", j->unit->id, job_type_to_string(j->type));
- job_finish_and_invalidate(j, JOB_TIMEOUT, true);
-}
-
-int job_serialize(Job *j, FILE *f, FDSet *fds) {
- fprintf(f, "job-id=%u\n", j->id);
- fprintf(f, "job-type=%s\n", job_type_to_string(j->type));
- fprintf(f, "job-state=%s\n", job_state_to_string(j->state));
- fprintf(f, "job-override=%s\n", yes_no(j->override));
- fprintf(f, "job-sent-dbus-new-signal=%s\n", yes_no(j->sent_dbus_new_signal));
- fprintf(f, "job-ignore-order=%s\n", yes_no(j->ignore_order));
- /* Cannot save bus clients. Just note the fact that we're losing
- * them. job_send_message() will fallback to broadcasting. */
- fprintf(f, "job-forgot-bus-clients=%s\n",
- yes_no(j->forgot_bus_clients || j->bus_client_list));
- if (j->timer_watch.type == WATCH_JOB_TIMER) {
- int copy = fdset_put_dup(fds, j->timer_watch.fd);
- if (copy < 0)
- return copy;
- fprintf(f, "job-timer-watch-fd=%d\n", copy);
- }
-
- /* End marker */
- fputc('\n', f);
- return 0;
-}
-
-int job_deserialize(Job *j, FILE *f, FDSet *fds) {
- for (;;) {
- char line[LINE_MAX], *l, *v;
- size_t k;
-
- if (!fgets(line, sizeof(line), f)) {
- if (feof(f))
- return 0;
- return -errno;
- }
-
- char_array_0(line);
- l = strstrip(line);
-
- /* End marker */
- if (l[0] == 0)
- return 0;
-
- k = strcspn(l, "=");
-
- if (l[k] == '=') {
- l[k] = 0;
- v = l+k+1;
- } else
- v = l+k;
-
- if (streq(l, "job-id")) {
- if (safe_atou32(v, &j->id) < 0)
- log_debug("Failed to parse job id value %s", v);
- } else if (streq(l, "job-type")) {
- JobType t = job_type_from_string(v);
- if (t < 0)
- log_debug("Failed to parse job type %s", v);
- else if (t >= _JOB_TYPE_MAX_IN_TRANSACTION)
- log_debug("Cannot deserialize job of type %s", v);
- else
- j->type = t;
- } else if (streq(l, "job-state")) {
- JobState s = job_state_from_string(v);
- if (s < 0)
- log_debug("Failed to parse job state %s", v);
- else
- j->state = s;
- } else if (streq(l, "job-override")) {
- int b = parse_boolean(v);
- if (b < 0)
- log_debug("Failed to parse job override flag %s", v);
- else
- j->override = j->override || b;
- } else if (streq(l, "job-sent-dbus-new-signal")) {
- int b = parse_boolean(v);
- if (b < 0)
- log_debug("Failed to parse job sent_dbus_new_signal flag %s", v);
- else
- j->sent_dbus_new_signal = j->sent_dbus_new_signal || b;
- } else if (streq(l, "job-ignore-order")) {
- int b = parse_boolean(v);
- if (b < 0)
- log_debug("Failed to parse job ignore_order flag %s", v);
- else
- j->ignore_order = j->ignore_order || b;
- } else if (streq(l, "job-forgot-bus-clients")) {
- int b = parse_boolean(v);
- if (b < 0)
- log_debug("Failed to parse job forgot_bus_clients flag %s", v);
- else
- j->forgot_bus_clients = j->forgot_bus_clients || b;
- } else if (streq(l, "job-timer-watch-fd")) {
- int fd;
- if (safe_atoi(v, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
- log_debug("Failed to parse job-timer-watch-fd value %s", v);
- else {
- if (j->timer_watch.type == WATCH_JOB_TIMER)
- close_nointr_nofail(j->timer_watch.fd);
-
- j->timer_watch.type = WATCH_JOB_TIMER;
- j->timer_watch.fd = fdset_remove(fds, fd);
- j->timer_watch.data.job = j;
- }
- }
- }
-}
-
-int job_coldplug(Job *j) {
- struct epoll_event ev;
-
- if (j->timer_watch.type != WATCH_JOB_TIMER)
- return 0;
-
- zero(ev);
- ev.data.ptr = &j->timer_watch;
- ev.events = EPOLLIN;
-
- if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, j->timer_watch.fd, &ev) < 0)
- return -errno;
-
- return 0;
-}
-
-static const char* const job_state_table[_JOB_STATE_MAX] = {
- [JOB_WAITING] = "waiting",
- [JOB_RUNNING] = "running"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(job_state, JobState);
-
-static const char* const job_type_table[_JOB_TYPE_MAX] = {
- [JOB_START] = "start",
- [JOB_VERIFY_ACTIVE] = "verify-active",
- [JOB_STOP] = "stop",
- [JOB_RELOAD] = "reload",
- [JOB_RELOAD_OR_START] = "reload-or-start",
- [JOB_RESTART] = "restart",
- [JOB_TRY_RESTART] = "try-restart",
- [JOB_NOP] = "nop",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(job_type, JobType);
-
-static const char* const job_mode_table[_JOB_MODE_MAX] = {
- [JOB_FAIL] = "fail",
- [JOB_REPLACE] = "replace",
- [JOB_ISOLATE] = "isolate",
- [JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies",
- [JOB_IGNORE_REQUIREMENTS] = "ignore-requirements"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode);
-
-static const char* const job_result_table[_JOB_RESULT_MAX] = {
- [JOB_DONE] = "done",
- [JOB_CANCELED] = "canceled",
- [JOB_TIMEOUT] = "timeout",
- [JOB_FAILED] = "failed",
- [JOB_DEPENDENCY] = "dependency",
- [JOB_SKIPPED] = "skipped"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(job_result, JobResult);
diff --git a/src/core/job.h b/src/core/job.h
deleted file mode 100644
index 3aa49d4b46..0000000000
--- a/src/core/job.h
+++ /dev/null
@@ -1,230 +0,0 @@
-/*-*- 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 <inttypes.h>
-#include <errno.h>
-
-typedef struct Job Job;
-typedef struct JobDependency JobDependency;
-typedef struct JobBusClient JobBusClient;
-typedef enum JobType JobType;
-typedef enum JobState JobState;
-typedef enum JobMode JobMode;
-typedef enum JobResult JobResult;
-
-/* Be careful when changing the job types! Adjust job_merging_table[] accordingly! */
-enum JobType {
- JOB_START, /* if a unit does not support being started, we'll just wait until it becomes active */
- JOB_VERIFY_ACTIVE,
-
- JOB_STOP,
-
- JOB_RELOAD, /* if running, reload */
-
- /* Note that restarts are first treated like JOB_STOP, but
- * then instead of finishing are patched to become
- * JOB_START. */
- JOB_RESTART, /* If running, stop. Then start unconditionally. */
-
- _JOB_TYPE_MAX_MERGING,
-
- /* JOB_NOP can enter into a transaction, but as it won't pull in
- * any dependencies, it won't have to merge with anything.
- * job_install() avoids the problem of merging JOB_NOP too (it's
- * special-cased, only merges with other JOB_NOPs). */
- JOB_NOP = _JOB_TYPE_MAX_MERGING, /* do nothing */
-
- _JOB_TYPE_MAX_IN_TRANSACTION,
-
- /* JOB_TRY_RESTART can never appear in a transaction, because
- * it always collapses into JOB_RESTART or JOB_NOP before entering.
- * Thus we never need to merge it with anything. */
- JOB_TRY_RESTART = _JOB_TYPE_MAX_IN_TRANSACTION, /* if running, stop and then start */
-
- /* JOB_RELOAD_OR_START won't enter into a transaction and cannot result
- * from transaction merging (there's no way for JOB_RELOAD and
- * JOB_START to meet in one transaction). It can result from a merge
- * during job installation, but then it will immediately collapse into
- * one of the two simpler types. */
- JOB_RELOAD_OR_START, /* if running, reload, otherwise start */
-
- _JOB_TYPE_MAX,
- _JOB_TYPE_INVALID = -1
-};
-
-enum JobState {
- JOB_WAITING,
- JOB_RUNNING,
- _JOB_STATE_MAX,
- _JOB_STATE_INVALID = -1
-};
-
-enum JobMode {
- JOB_FAIL, /* Fail if a conflicting job is already queued */
- JOB_REPLACE, /* Replace an existing conflicting job */
- JOB_ISOLATE, /* Start a unit, and stop all others */
- JOB_IGNORE_DEPENDENCIES, /* Ignore both requirement and ordering dependencies */
- JOB_IGNORE_REQUIREMENTS, /* Ignore requirement dependencies */
- _JOB_MODE_MAX,
- _JOB_MODE_INVALID = -1
-};
-
-enum JobResult {
- JOB_DONE, /* Job completed successfully */
- JOB_CANCELED, /* Job canceled by a conflicting job installation or by explicit cancel request */
- JOB_TIMEOUT, /* JobTimeout elapsed */
- JOB_FAILED, /* Job failed */
- JOB_DEPENDENCY, /* A required dependency job did not result in JOB_DONE */
- JOB_SKIPPED, /* JOB_RELOAD of inactive unit; negative result of JOB_VERIFY_ACTIVE */
- _JOB_RESULT_MAX,
- _JOB_RESULT_INVALID = -1
-};
-
-#include "manager.h"
-#include "unit.h"
-#include "hashmap.h"
-#include "list.h"
-
-struct JobDependency {
- /* Encodes that the 'subject' job needs the 'object' job in
- * some way. This structure is used only while building a transaction. */
- Job *subject;
- Job *object;
-
- LIST_FIELDS(JobDependency, subject);
- LIST_FIELDS(JobDependency, object);
-
- bool matters;
- bool conflicts;
-};
-
-struct JobBusClient {
- LIST_FIELDS(JobBusClient, client);
- /* Note that this bus object is not ref counted here. */
- DBusConnection *bus;
- char name[0];
-};
-
-struct Job {
- Manager *manager;
- Unit *unit;
-
- LIST_FIELDS(Job, transaction);
- LIST_FIELDS(Job, run_queue);
- LIST_FIELDS(Job, dbus_queue);
-
- LIST_HEAD(JobDependency, subject_list);
- LIST_HEAD(JobDependency, object_list);
-
- /* Used for graph algs as a "I have been here" marker */
- Job* marker;
- unsigned generation;
-
- uint32_t id;
-
- JobType type;
- JobState state;
-
- Watch timer_watch;
-
- /* There can be more than one client, because of job merging. */
- LIST_HEAD(JobBusClient, bus_client_list);
-
- JobResult result;
-
- bool installed:1;
- bool in_run_queue:1;
- bool matters_to_anchor:1;
- bool override:1;
- bool in_dbus_queue:1;
- bool sent_dbus_new_signal:1;
- bool ignore_order:1;
- bool forgot_bus_clients:1;
-};
-
-JobBusClient* job_bus_client_new(DBusConnection *connection, const char *name);
-
-Job* job_new(Unit *unit, JobType type);
-Job* job_new_raw(Unit *unit);
-void job_free(Job *job);
-Job* job_install(Job *j);
-int job_install_deserialized(Job *j);
-void job_uninstall(Job *j);
-void job_dump(Job *j, FILE*f, const char *prefix);
-int job_serialize(Job *j, FILE *f, FDSet *fds);
-int job_deserialize(Job *j, FILE *f, FDSet *fds);
-int job_coldplug(Job *j);
-
-JobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts);
-void job_dependency_free(JobDependency *l);
-
-int job_merge(Job *j, Job *other);
-
-JobType job_type_lookup_merge(JobType a, JobType b);
-
-static inline bool job_type_is_mergeable(JobType a, JobType b) {
- return job_type_lookup_merge(a, b) >= 0;
-}
-
-static inline bool job_type_is_conflicting(JobType a, JobType b) {
- return !job_type_is_mergeable(a, b);
-}
-
-static inline bool job_type_is_superset(JobType a, JobType b) {
- /* Checks whether operation a is a "superset" of b in its actions */
- return a == job_type_lookup_merge(a, b);
-}
-
-bool job_type_is_redundant(JobType a, UnitActiveState b);
-
-/* Collapses a state-dependent job type into a simpler type by observing
- * the state of the unit which it is going to be applied to. */
-void job_type_collapse(JobType *t, Unit *u);
-
-int job_type_merge_and_collapse(JobType *a, JobType b, Unit *u);
-
-bool job_is_runnable(Job *j);
-
-void job_add_to_run_queue(Job *j);
-void job_add_to_dbus_queue(Job *j);
-
-int job_start_timer(Job *j);
-void job_timer_event(Job *j, uint64_t n_elapsed, Watch *w);
-
-int job_run_and_invalidate(Job *j);
-int job_finish_and_invalidate(Job *j, JobResult result, bool recursive);
-
-char *job_dbus_path(Job *j);
-
-const char* job_type_to_string(JobType t);
-JobType job_type_from_string(const char *s);
-
-const char* job_state_to_string(JobState t);
-JobState job_state_from_string(const char *s);
-
-const char* job_mode_to_string(JobMode t);
-JobMode job_mode_from_string(const char *s);
-
-const char* job_result_to_string(JobResult t);
-JobResult job_result_from_string(const char *s);
diff --git a/src/core/kill.c b/src/core/kill.c
deleted file mode 100644
index 0775653f73..0000000000
--- a/src/core/kill.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <string.h>
-
-#include "kill.h"
-#include "util.h"
-
-void kill_context_init(KillContext *c) {
- assert(c);
-
- c->kill_signal = SIGTERM;
- c->send_sigkill = true;
-}
-
-void kill_context_dump(KillContext *c, FILE *f, const char *prefix) {
- assert(c);
-
- if (!prefix)
- prefix = "";
-
- fprintf(f,
- "%sKillMode: %s\n"
- "%sKillSignal: SIG%s\n"
- "%sSendSIGKILL: %s\n",
- prefix, kill_mode_to_string(c->kill_mode),
- prefix, signal_to_string(c->kill_signal),
- prefix, yes_no(c->send_sigkill));
-}
-
-static const char* const kill_mode_table[_KILL_MODE_MAX] = {
- [KILL_CONTROL_GROUP] = "control-group",
- [KILL_PROCESS] = "process",
- [KILL_NONE] = "none"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(kill_mode, KillMode);
-
-static const char* const kill_who_table[_KILL_WHO_MAX] = {
- [KILL_MAIN] = "main",
- [KILL_CONTROL] = "control",
- [KILL_ALL] = "all"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);
diff --git a/src/core/kill.h b/src/core/kill.h
deleted file mode 100644
index 3c9b0ab8db..0000000000
--- a/src/core/kill.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-typedef struct KillContext KillContext;
-
-#include <stdbool.h>
-#include <stdio.h>
-
-typedef enum KillMode {
- /* The kill mode is a property of a unit. */
- KILL_CONTROL_GROUP = 0,
- KILL_PROCESS,
- KILL_NONE,
- _KILL_MODE_MAX,
- _KILL_MODE_INVALID = -1
-} KillMode;
-
-struct KillContext {
- KillMode kill_mode;
- int kill_signal;
- bool send_sigkill;
-};
-
-typedef enum KillWho {
- /* Kill who is a property of an operation */
- KILL_MAIN,
- KILL_CONTROL,
- KILL_ALL,
- _KILL_WHO_MAX,
- _KILL_WHO_INVALID = -1
-} KillWho;
-
-void kill_context_init(KillContext *c);
-void kill_context_dump(KillContext *c, FILE *f, const char *prefix);
-
-const char *kill_mode_to_string(KillMode k);
-KillMode kill_mode_from_string(const char *s);
-
-const char *kill_who_to_string(KillWho k);
-KillWho kill_who_from_string(const char *s);
diff --git a/src/core/killall.c b/src/core/killall.c
deleted file mode 100644
index 55200ffa48..0000000000
--- a/src/core/killall.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010 ProFUSION embedded systems
-
- 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/wait.h>
-#include <signal.h>
-#include <errno.h>
-
-#include "util.h"
-#include "def.h"
-#include "killall.h"
-
-#define TIMEOUT_USEC (5 * USEC_PER_SEC)
-
-static bool ignore_proc(pid_t pid) {
- char buf[PATH_MAX];
- FILE *f;
- char c;
- size_t count;
- uid_t uid;
- int r;
-
- /* We are PID 1, let's not commit suicide */
- if (pid == 1)
- return true;
-
- r = get_process_uid(pid, &uid);
- if (r < 0)
- return true; /* not really, but better safe than sorry */
-
- /* Non-root processes otherwise are always subject to be killed */
- if (uid != 0)
- return false;
-
- snprintf(buf, sizeof(buf), "/proc/%lu/cmdline", (unsigned long) pid);
- char_array_0(buf);
-
- f = fopen(buf, "re");
- if (!f)
- return true; /* not really, but has the desired effect */
-
- count = fread(&c, 1, 1, f);
- fclose(f);
-
- /* Kernel threads have an empty cmdline */
- if (count <= 0)
- return true;
-
- /* Processes with argv[0][0] = '@' we ignore from the killing
- * spree.
- *
- * http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons */
- if (count == 1 && c == '@')
- return true;
-
- return false;
-}
-
-static void wait_for_children(int n_processes, sigset_t *mask) {
- usec_t until;
-
- assert(mask);
-
- until = now(CLOCK_MONOTONIC) + TIMEOUT_USEC;
- for (;;) {
- struct timespec ts;
- int k;
- usec_t n;
-
- for (;;) {
- pid_t pid = waitpid(-1, NULL, WNOHANG);
-
- if (pid == 0)
- break;
-
- if (pid < 0 && errno == ECHILD)
- return;
-
- if (n_processes > 0)
- if (--n_processes == 0)
- return;
- }
-
- n = now(CLOCK_MONOTONIC);
- if (n >= until)
- return;
-
- timespec_store(&ts, until - n);
-
- if ((k = sigtimedwait(mask, NULL, &ts)) != SIGCHLD) {
-
- if (k < 0 && errno != EAGAIN) {
- log_error("sigtimedwait() failed: %m");
- return;
- }
-
- if (k >= 0)
- log_warning("sigtimedwait() returned unexpected signal.");
- }
- }
-}
-
-static int killall(int sig) {
- DIR *dir;
- struct dirent *d;
- unsigned int n_processes = 0;
-
- dir = opendir("/proc");
- if (!dir)
- return -errno;
-
- while ((d = readdir(dir))) {
- pid_t pid;
-
- if (d->d_type != DT_DIR &&
- d->d_type != DT_UNKNOWN)
- continue;
-
- if (parse_pid(d->d_name, &pid) < 0)
- continue;
-
- if (ignore_proc(pid))
- continue;
-
- if (kill(pid, sig) >= 0)
- n_processes++;
- else if (errno != ENOENT)
- log_warning("Could not kill %d: %m", pid);
- }
-
- closedir(dir);
-
- return n_processes;
-}
-
-void broadcast_signal(int sig, bool wait_for_exit) {
- sigset_t mask, oldmask;
- int n_processes;
-
- assert_se(sigemptyset(&mask) == 0);
- assert_se(sigaddset(&mask, SIGCHLD) == 0);
- assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) == 0);
-
- if (kill(-1, SIGSTOP) < 0 && errno != ESRCH)
- log_warning("kill(-1, SIGSTOP) failed: %m");
-
- n_processes = killall(sig);
-
- if (kill(-1, SIGCONT) < 0 && errno != ESRCH)
- log_warning("kill(-1, SIGCONT) failed: %m");
-
- if (n_processes <= 0)
- goto finish;
-
- if (wait_for_exit)
- wait_for_children(n_processes, &mask);
-
-finish:
- sigprocmask(SIG_SETMASK, &oldmask, NULL);
-}
diff --git a/src/core/killall.h b/src/core/killall.h
deleted file mode 100644
index d08ac142f0..0000000000
--- a/src/core/killall.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef fookillallhfoo
-#define fookillallhfoo
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-void broadcast_signal(int sig, bool wait);
-
-#endif
diff --git a/src/core/kmod-setup.c b/src/core/kmod-setup.c
deleted file mode 100644
index 20ab232374..0000000000
--- a/src/core/kmod-setup.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*-*- 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/wait.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <libkmod.h>
-
-#include "macro.h"
-#include "execute.h"
-
-#include "kmod-setup.h"
-
-typedef struct Kmodule {
- const char *name;
- const char *directory;
- bool (*condition_fn)(void);
-} KModule;
-
-static const KModule kmod_table[] = {
- { "autofs4", "/sys/class/misc/autofs", NULL } ,
- { "ipv6", "/sys/module/ipv6", NULL },
- { "unix", "/proc/net/unix", NULL } ,
-};
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wformat-nonliteral"
-static void systemd_kmod_log(void *data, int priority, const char *file, int line,
- const char *fn, const char *format, va_list args)
-{
- /* library logging is enabled at debug only */
- log_metav(LOG_DEBUG, file, line, fn, format, args);
-}
-#pragma GCC diagnostic pop
-
-int kmod_setup(void) {
- unsigned i;
- struct kmod_ctx *ctx = NULL;
- struct kmod_module *mod;
- int err;
-
- for (i = 0; i < ELEMENTSOF(kmod_table); i += 2) {
- if (kmod_table[i].condition_fn && !kmod_table[i].condition_fn())
- continue;
-
- if (access(kmod_table[i].directory, F_OK) >= 0)
- continue;
-
- log_debug("Your kernel apparently lacks built-in %s support. Might be a good idea to compile it in. "
- "We'll now try to work around this by loading the module...",
- kmod_table[i].name);
-
- if (!ctx) {
- ctx = kmod_new(NULL, NULL);
- if (!ctx) {
- log_error("Failed to allocate memory for kmod");
- return -ENOMEM;
- }
-
- kmod_set_log_fn(ctx, systemd_kmod_log, NULL);
- kmod_load_resources(ctx);
- }
-
- err = kmod_module_new_from_name(ctx, kmod_table[i].name, &mod);
- if (err < 0) {
- log_error("Failed to lookup module '%s'", kmod_table[i].name);
- continue;
- }
-
- err = kmod_module_probe_insert_module(mod, KMOD_PROBE_APPLY_BLACKLIST, NULL, NULL, NULL, NULL);
- if (err == 0)
- log_info("Inserted module '%s'", kmod_module_get_name(mod));
- else if (err == KMOD_PROBE_APPLY_BLACKLIST)
- log_info("Module '%s' is blacklisted", kmod_module_get_name(mod));
- else
- log_error("Failed to insert module '%s'", kmod_module_get_name(mod));
-
- kmod_module_unref(mod);
- }
-
- if (ctx)
- kmod_unref(ctx);
-
- return 0;
-}
diff --git a/src/core/kmod-setup.h b/src/core/kmod-setup.h
deleted file mode 100644
index 24dcdddfa4..0000000000
--- a/src/core/kmod-setup.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*-*- 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 kmod_setup(void);
diff --git a/src/core/load-dropin.c b/src/core/load-dropin.c
deleted file mode 100644
index 86f81c7484..0000000000
--- a/src/core/load-dropin.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*-*- 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 <dirent.h>
-#include <errno.h>
-
-#include "unit.h"
-#include "load-dropin.h"
-#include "log.h"
-#include "strv.h"
-#include "unit-name.h"
-
-static int iterate_dir(Unit *u, const char *path, UnitDependency dependency) {
- DIR *d;
- struct dirent *de;
- int r;
-
- assert(u);
- assert(path);
-
- d = opendir(path);
- if (!d) {
-
- if (errno == ENOENT)
- return 0;
-
- return -errno;
- }
-
- while ((de = readdir(d))) {
- char *f;
-
- if (ignore_file(de->d_name))
- continue;
-
- f = strjoin(path, "/", de->d_name, NULL);
- if (!f) {
- r = -ENOMEM;
- goto finish;
- }
-
- r = unit_add_dependency_by_name(u, dependency, de->d_name, f, true);
- free(f);
-
- if (r < 0)
- log_error("Cannot add dependency %s to %s, ignoring: %s", de->d_name, u->id, strerror(-r));
- }
-
- r = 0;
-
-finish:
- closedir(d);
- return r;
-}
-
-static int process_dir(Unit *u, const char *unit_path, const char *name, const char *suffix, UnitDependency dependency) {
- int r;
- char *path;
-
- assert(u);
- assert(unit_path);
- assert(name);
- assert(suffix);
-
- path = strjoin(unit_path, "/", name, suffix, NULL);
- if (!path)
- return -ENOMEM;
-
- if (u->manager->unit_path_cache &&
- !set_get(u->manager->unit_path_cache, path))
- r = 0;
- else
- r = iterate_dir(u, path, dependency);
- free(path);
-
- if (r < 0)
- return r;
-
- if (u->instance) {
- char *template;
- /* Also try the template dir */
-
- template = unit_name_template(name);
- if (!template)
- return -ENOMEM;
-
- path = strjoin(unit_path, "/", template, suffix, NULL);
- free(template);
-
- if (!path)
- return -ENOMEM;
-
- if (u->manager->unit_path_cache &&
- !set_get(u->manager->unit_path_cache, path))
- r = 0;
- else
- r = iterate_dir(u, path, dependency);
- free(path);
-
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-int unit_load_dropin(Unit *u) {
- Iterator i;
- char *t;
-
- assert(u);
-
- /* Load dependencies from supplementary drop-in directories */
-
- SET_FOREACH(t, u->names, i) {
- char **p;
-
- STRV_FOREACH(p, u->manager->lookup_paths.unit_path) {
- int r;
-
- r = process_dir(u, *p, t, ".wants", UNIT_WANTS);
- if (r < 0)
- return r;
-
- r = process_dir(u, *p, t, ".requires", UNIT_REQUIRES);
- if (r < 0)
- return r;
- }
- }
-
- return 0;
-}
diff --git a/src/core/load-dropin.h b/src/core/load-dropin.h
deleted file mode 100644
index 1d2fafeee6..0000000000
--- a/src/core/load-dropin.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*-*- 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 "unit.h"
-
-/* Read service data supplementary drop-in directories */
-
-int unit_load_dropin(Unit *u);
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
deleted file mode 100644
index 0c5ccebd73..0000000000
--- a/src/core/load-fragment-gperf.gperf.m4
+++ /dev/null
@@ -1,255 +0,0 @@
-%{
-#include <stddef.h>
-#include "conf-parser.h"
-#include "load-fragment.h"
-#include "missing.h"
-%}
-struct ConfigPerfItem;
-%null_strings
-%language=ANSI-C
-%define slot-name section_and_lvalue
-%define hash-function-name load_fragment_gperf_hash
-%define lookup-function-name load_fragment_gperf_lookup
-%readonly-tables
-%omit-struct-type
-%struct-type
-%includes
-%%
-m4_dnl Define the context options only once
-m4_define(`EXEC_CONTEXT_CONFIG_ITEMS',
-`$1.WorkingDirectory, config_parse_unit_path_printf, 0, offsetof($1, exec_context.working_directory)
-$1.RootDirectory, config_parse_unit_path_printf, 0, offsetof($1, exec_context.root_directory)
-$1.User, config_parse_unit_string_printf, 0, offsetof($1, exec_context.user)
-$1.Group, config_parse_unit_string_printf, 0, offsetof($1, exec_context.group)
-$1.SupplementaryGroups, config_parse_strv, 0, offsetof($1, exec_context.supplementary_groups)
-$1.Nice, config_parse_exec_nice, 0, offsetof($1, exec_context)
-$1.OOMScoreAdjust, config_parse_exec_oom_score_adjust, 0, offsetof($1, exec_context)
-$1.IOSchedulingClass, config_parse_exec_io_class, 0, offsetof($1, exec_context)
-$1.IOSchedulingPriority, config_parse_exec_io_priority, 0, offsetof($1, exec_context)
-$1.CPUSchedulingPolicy, config_parse_exec_cpu_sched_policy, 0, offsetof($1, exec_context)
-$1.CPUSchedulingPriority, config_parse_exec_cpu_sched_prio, 0, offsetof($1, exec_context)
-$1.CPUSchedulingResetOnFork, config_parse_bool, 0, offsetof($1, exec_context.cpu_sched_reset_on_fork)
-$1.CPUAffinity, config_parse_exec_cpu_affinity, 0, offsetof($1, exec_context)
-$1.UMask, config_parse_mode, 0, offsetof($1, exec_context.umask)
-$1.Environment, config_parse_unit_strv_printf, 0, offsetof($1, exec_context.environment)
-$1.EnvironmentFile, config_parse_unit_env_file, 0, offsetof($1, exec_context.environment_files)
-$1.StandardInput, config_parse_input, 0, offsetof($1, exec_context.std_input)
-$1.StandardOutput, config_parse_output, 0, offsetof($1, exec_context.std_output)
-$1.StandardError, config_parse_output, 0, offsetof($1, exec_context.std_error)
-$1.TTYPath, config_parse_unit_path_printf, 0, offsetof($1, exec_context.tty_path)
-$1.TTYReset, config_parse_bool, 0, offsetof($1, exec_context.tty_reset)
-$1.TTYVHangup, config_parse_bool, 0, offsetof($1, exec_context.tty_vhangup)
-$1.TTYVTDisallocate, config_parse_bool, 0, offsetof($1, exec_context.tty_vt_disallocate)
-$1.SyslogIdentifier, config_parse_unit_string_printf, 0, offsetof($1, exec_context.syslog_identifier)
-$1.SyslogFacility, config_parse_facility, 0, offsetof($1, exec_context.syslog_priority)
-$1.SyslogLevel, config_parse_level, 0, offsetof($1, exec_context.syslog_priority)
-$1.SyslogLevelPrefix, config_parse_bool, 0, offsetof($1, exec_context.syslog_level_prefix)
-$1.Capabilities, config_parse_exec_capabilities, 0, offsetof($1, exec_context)
-$1.SecureBits, config_parse_exec_secure_bits, 0, offsetof($1, exec_context)
-$1.CapabilityBoundingSet, config_parse_bounding_set, 0, offsetof($1, exec_context.capability_bounding_set_drop)
-$1.TimerSlackNSec, config_parse_nsec, 0, offsetof($1, exec_context.timer_slack_nsec)
-$1.NoNewPrivileges config_parse_bool, 0, offsetof($1, exec_context.no_new_privileges)
-$1.SystemCallFilter, config_parse_syscall_filter, 0, offsetof($1, exec_context)
-$1.LimitCPU, config_parse_limit, RLIMIT_CPU, offsetof($1, exec_context.rlimit)
-$1.LimitFSIZE, config_parse_limit, RLIMIT_FSIZE, offsetof($1, exec_context.rlimit)
-$1.LimitDATA, config_parse_limit, RLIMIT_DATA, offsetof($1, exec_context.rlimit)
-$1.LimitSTACK, config_parse_limit, RLIMIT_STACK, offsetof($1, exec_context.rlimit)
-$1.LimitCORE, config_parse_limit, RLIMIT_CORE, offsetof($1, exec_context.rlimit)
-$1.LimitRSS, config_parse_limit, RLIMIT_RSS, offsetof($1, exec_context.rlimit)
-$1.LimitNOFILE, config_parse_limit, RLIMIT_NOFILE, offsetof($1, exec_context.rlimit)
-$1.LimitAS, config_parse_limit, RLIMIT_AS, offsetof($1, exec_context.rlimit)
-$1.LimitNPROC, config_parse_limit, RLIMIT_NPROC, offsetof($1, exec_context.rlimit)
-$1.LimitMEMLOCK, config_parse_limit, RLIMIT_MEMLOCK, offsetof($1, exec_context.rlimit)
-$1.LimitLOCKS, config_parse_limit, RLIMIT_LOCKS, offsetof($1, exec_context.rlimit)
-$1.LimitSIGPENDING, config_parse_limit, RLIMIT_SIGPENDING, offsetof($1, exec_context.rlimit)
-$1.LimitMSGQUEUE, config_parse_limit, RLIMIT_MSGQUEUE, offsetof($1, exec_context.rlimit)
-$1.LimitNICE, config_parse_limit, RLIMIT_NICE, offsetof($1, exec_context.rlimit)
-$1.LimitRTPRIO, config_parse_limit, RLIMIT_RTPRIO, offsetof($1, exec_context.rlimit)
-$1.LimitRTTIME, config_parse_limit, RLIMIT_RTTIME, offsetof($1, exec_context.rlimit)
-$1.ControlGroup, config_parse_unit_cgroup, 0, 0
-$1.ControlGroupAttribute, config_parse_unit_cgroup_attr, 0, 0
-$1.CPUShares, config_parse_unit_cpu_shares, 0, 0
-$1.MemoryLimit, config_parse_unit_memory_limit, 0, 0
-$1.MemorySoftLimit, config_parse_unit_memory_limit, 0, 0
-$1.DeviceAllow, config_parse_unit_device_allow, 0, 0
-$1.DeviceDeny, config_parse_unit_device_allow, 0, 0
-$1.BlockIOWeight, config_parse_unit_blkio_weight, 0, 0
-$1.BlockIOReadBandwidth, config_parse_unit_blkio_bandwidth, 0, 0
-$1.BlockIOWriteBandwidth, config_parse_unit_blkio_bandwidth, 0, 0
-$1.ReadWriteDirectories, config_parse_path_strv, 0, offsetof($1, exec_context.read_write_dirs)
-$1.ReadOnlyDirectories, config_parse_path_strv, 0, offsetof($1, exec_context.read_only_dirs)
-$1.InaccessibleDirectories, config_parse_path_strv, 0, offsetof($1, exec_context.inaccessible_dirs)
-$1.PrivateTmp, config_parse_bool, 0, offsetof($1, exec_context.private_tmp)
-$1.PrivateNetwork, config_parse_bool, 0, offsetof($1, exec_context.private_network)
-$1.MountFlags, config_parse_exec_mount_flags, 0, offsetof($1, exec_context)
-$1.TCPWrapName, config_parse_unit_string_printf, 0, offsetof($1, exec_context.tcpwrap_name)
-$1.PAMName, config_parse_unit_string_printf, 0, offsetof($1, exec_context.pam_name)
-$1.IgnoreSIGPIPE, config_parse_bool, 0, offsetof($1, exec_context.ignore_sigpipe)
-$1.UtmpIdentifier, config_parse_unit_string_printf, 0, offsetof($1, exec_context.utmp_id)
-$1.ControlGroupModify, config_parse_bool, 0, offsetof($1, exec_context.control_group_modify)
-$1.ControlGroupPersistent, config_parse_tristate, 0, offsetof($1, exec_context.control_group_persistent)'
-)m4_dnl
-m4_define(`KILL_CONTEXT_CONFIG_ITEMS',
-`$1.SendSIGKILL, config_parse_bool, 0, offsetof($1, kill_context.send_sigkill)
-$1.KillMode, config_parse_kill_mode, 0, offsetof($1, kill_context.kill_mode)
-$1.KillSignal, config_parse_kill_signal, 0, offsetof($1, kill_context.kill_signal)'
-)m4_dnl
-Unit.Description, config_parse_unit_string_printf, 0, offsetof(Unit, description)
-Unit.Documentation, config_parse_documentation, 0, offsetof(Unit, documentation)
-Unit.SourcePath, config_parse_path, 0, offsetof(Unit, source_path)
-Unit.Requires, config_parse_unit_deps, UNIT_REQUIRES, 0
-Unit.RequiresOverridable, config_parse_unit_deps, UNIT_REQUIRES_OVERRIDABLE, 0
-Unit.Requisite, config_parse_unit_deps, UNIT_REQUISITE, 0
-Unit.RequisiteOverridable, config_parse_unit_deps, UNIT_REQUISITE_OVERRIDABLE, 0
-Unit.Wants, config_parse_unit_deps, UNIT_WANTS, 0
-Unit.BindsTo, config_parse_unit_deps, UNIT_BINDS_TO, 0
-Unit.BindTo, config_parse_unit_deps, UNIT_BINDS_TO, 0
-Unit.Conflicts, config_parse_unit_deps, UNIT_CONFLICTS, 0
-Unit.Before, config_parse_unit_deps, UNIT_BEFORE, 0
-Unit.After, config_parse_unit_deps, UNIT_AFTER, 0
-Unit.OnFailure, config_parse_unit_deps, UNIT_ON_FAILURE, 0
-Unit.PropagatesReloadTo, config_parse_unit_deps, UNIT_PROPAGATES_RELOAD_TO, 0
-Unit.PropagateReloadTo, config_parse_unit_deps, UNIT_PROPAGATES_RELOAD_TO, 0
-Unit.ReloadPropagatedFrom, config_parse_unit_deps, UNIT_RELOAD_PROPAGATED_FROM, 0
-Unit.PropagateReloadFrom, config_parse_unit_deps, UNIT_RELOAD_PROPAGATED_FROM, 0
-Unit.PartOf, config_parse_unit_deps, UNIT_PART_OF, 0
-Unit.RequiresMountsFor, config_parse_unit_requires_mounts_for, 0, offsetof(Unit, requires_mounts_for)
-Unit.StopWhenUnneeded, config_parse_bool, 0, offsetof(Unit, stop_when_unneeded)
-Unit.RefuseManualStart, config_parse_bool, 0, offsetof(Unit, refuse_manual_start)
-Unit.RefuseManualStop, config_parse_bool, 0, offsetof(Unit, refuse_manual_stop)
-Unit.AllowIsolate, config_parse_bool, 0, offsetof(Unit, allow_isolate)
-Unit.DefaultDependencies, config_parse_bool, 0, offsetof(Unit, default_dependencies)
-Unit.OnFailureIsolate, config_parse_bool, 0, offsetof(Unit, on_failure_isolate)
-Unit.IgnoreOnIsolate, config_parse_bool, 0, offsetof(Unit, ignore_on_isolate)
-Unit.IgnoreOnSnapshot, config_parse_bool, 0, offsetof(Unit, ignore_on_snapshot)
-Unit.JobTimeoutSec, config_parse_usec, 0, offsetof(Unit, job_timeout)
-Unit.ConditionPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, 0
-Unit.ConditionPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, 0
-Unit.ConditionPathIsDirectory, config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY, 0
-Unit.ConditionPathIsSymbolicLink,config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK,0
-Unit.ConditionPathIsMountPoint, config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT, 0
-Unit.ConditionPathIsReadWrite, config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE, 0
-Unit.ConditionDirectoryNotEmpty, config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY, 0
-Unit.ConditionFileIsExecutable, config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE, 0
-Unit.ConditionKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, 0
-Unit.ConditionVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, 0
-Unit.ConditionSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, 0
-Unit.ConditionCapability, config_parse_unit_condition_string, CONDITION_CAPABILITY, 0
-Unit.ConditionHost, config_parse_unit_condition_string, CONDITION_HOST, 0
-Unit.ConditionNull, config_parse_unit_condition_null, 0, 0
-m4_dnl
-Service.PIDFile, config_parse_unit_path_printf, 0, offsetof(Service, pid_file)
-Service.ExecStartPre, config_parse_exec, SERVICE_EXEC_START_PRE, offsetof(Service, exec_command)
-Service.ExecStart, config_parse_exec, SERVICE_EXEC_START, offsetof(Service, exec_command)
-Service.ExecStartPost, config_parse_exec, SERVICE_EXEC_START_POST, offsetof(Service, exec_command)
-Service.ExecReload, config_parse_exec, SERVICE_EXEC_RELOAD, offsetof(Service, exec_command)
-Service.ExecStop, config_parse_exec, SERVICE_EXEC_STOP, offsetof(Service, exec_command)
-Service.ExecStopPost, config_parse_exec, SERVICE_EXEC_STOP_POST, offsetof(Service, exec_command)
-Service.RestartSec, config_parse_usec, 0, offsetof(Service, restart_usec)
-Service.TimeoutSec, config_parse_service_timeout, 0, offsetof(Service, timeout_start_usec)
-Service.TimeoutStartSec, config_parse_service_timeout, 0, offsetof(Service, timeout_start_usec)
-Service.TimeoutStopSec, config_parse_service_timeout, 0, offsetof(Service, timeout_stop_usec)
-Service.WatchdogSec, config_parse_usec, 0, offsetof(Service, watchdog_usec)
-Service.StartLimitInterval, config_parse_usec, 0, offsetof(Service, start_limit.interval)
-Service.StartLimitBurst, config_parse_unsigned, 0, offsetof(Service, start_limit.burst)
-Service.StartLimitAction, config_parse_start_limit_action, 0, offsetof(Service, start_limit_action)
-Service.Type, config_parse_service_type, 0, offsetof(Service, type)
-Service.Restart, config_parse_service_restart, 0, offsetof(Service, restart)
-Service.PermissionsStartOnly, config_parse_bool, 0, offsetof(Service, permissions_start_only)
-Service.RootDirectoryStartOnly, config_parse_bool, 0, offsetof(Service, root_directory_start_only)
-Service.RemainAfterExit, config_parse_bool, 0, offsetof(Service, remain_after_exit)
-Service.GuessMainPID, config_parse_bool, 0, offsetof(Service, guess_main_pid)
-Service.RestartPreventExitStatus, config_parse_set_status, 0, offsetof(Service, restart_ignore_status)
-Service.SuccessExitStatus, config_parse_set_status, 0, offsetof(Service, success_status)
-m4_ifdef(`HAVE_SYSV_COMPAT',
-`Service.SysVStartPriority, config_parse_sysv_priority, 0, offsetof(Service, sysv_start_priority)',
-`Service.SysVStartPriority, config_parse_warn_compat, 0, 0')
-Service.NonBlocking, config_parse_bool, 0, offsetof(Service, exec_context.non_blocking)
-Service.BusName, config_parse_unit_string_printf, 0, offsetof(Service, bus_name)
-Service.NotifyAccess, config_parse_notify_access, 0, offsetof(Service, notify_access)
-Service.Sockets, config_parse_service_sockets, 0, 0
-Service.FsckPassNo, config_parse_fsck_passno, 0, offsetof(Service, fsck_passno)
-EXEC_CONTEXT_CONFIG_ITEMS(Service)m4_dnl
-KILL_CONTEXT_CONFIG_ITEMS(Service)m4_dnl
-m4_dnl
-Socket.ListenStream, config_parse_socket_listen, 0, 0
-Socket.ListenDatagram, config_parse_socket_listen, 0, 0
-Socket.ListenSequentialPacket, config_parse_socket_listen, 0, 0
-Socket.ListenFIFO, config_parse_socket_listen, 0, 0
-Socket.ListenNetlink, config_parse_socket_listen, 0, 0
-Socket.ListenSpecial, config_parse_socket_listen, 0, 0
-Socket.ListenMessageQueue, config_parse_socket_listen, 0, 0
-Socket.BindIPv6Only, config_parse_socket_bind, 0, 0,
-Socket.Backlog, config_parse_unsigned, 0, offsetof(Socket, backlog)
-Socket.BindToDevice, config_parse_socket_bindtodevice, 0, 0
-Socket.ExecStartPre, config_parse_exec, SOCKET_EXEC_START_PRE, offsetof(Socket, exec_command)
-Socket.ExecStartPost, config_parse_exec, SOCKET_EXEC_START_POST, offsetof(Socket, exec_command)
-Socket.ExecStopPre, config_parse_exec, SOCKET_EXEC_STOP_PRE, offsetof(Socket, exec_command)
-Socket.ExecStopPost, config_parse_exec, SOCKET_EXEC_STOP_POST, offsetof(Socket, exec_command)
-Socket.TimeoutSec, config_parse_usec, 0, offsetof(Socket, timeout_usec)
-Socket.DirectoryMode, config_parse_mode, 0, offsetof(Socket, directory_mode)
-Socket.SocketMode, config_parse_mode, 0, offsetof(Socket, socket_mode)
-Socket.Accept, config_parse_bool, 0, offsetof(Socket, accept)
-Socket.MaxConnections, config_parse_unsigned, 0, offsetof(Socket, max_connections)
-Socket.KeepAlive, config_parse_bool, 0, offsetof(Socket, keep_alive)
-Socket.Priority, config_parse_int, 0, offsetof(Socket, priority)
-Socket.ReceiveBuffer, config_parse_bytes_size, 0, offsetof(Socket, receive_buffer)
-Socket.SendBuffer, config_parse_bytes_size, 0, offsetof(Socket, send_buffer)
-Socket.IPTOS, config_parse_ip_tos, 0, offsetof(Socket, ip_tos)
-Socket.IPTTL, config_parse_int, 0, offsetof(Socket, ip_ttl)
-Socket.Mark, config_parse_int, 0, offsetof(Socket, mark)
-Socket.PipeSize, config_parse_bytes_size, 0, offsetof(Socket, pipe_size)
-Socket.FreeBind, config_parse_bool, 0, offsetof(Socket, free_bind)
-Socket.Transparent, config_parse_bool, 0, offsetof(Socket, transparent)
-Socket.Broadcast, config_parse_bool, 0, offsetof(Socket, broadcast)
-Socket.PassCredentials, config_parse_bool, 0, offsetof(Socket, pass_cred)
-Socket.PassSecurity, config_parse_bool, 0, offsetof(Socket, pass_sec)
-Socket.TCPCongestion, config_parse_string, 0, offsetof(Socket, tcp_congestion)
-Socket.MessageQueueMaxMessages, config_parse_long, 0, offsetof(Socket, mq_maxmsg)
-Socket.MessageQueueMessageSize, config_parse_long, 0, offsetof(Socket, mq_msgsize)
-Socket.Service, config_parse_socket_service, 0, 0
-Socket.SmackLabel, config_parse_string, 0, offsetof(Socket, smack)
-Socket.SmackLabelIPIn, config_parse_string, 0, offsetof(Socket, smack_ip_in)
-Socket.SmackLabelIPOut, config_parse_string, 0, offsetof(Socket, smack_ip_out)
-EXEC_CONTEXT_CONFIG_ITEMS(Socket)m4_dnl
-KILL_CONTEXT_CONFIG_ITEMS(Socket)m4_dnl
-m4_dnl
-Mount.What, config_parse_string, 0, offsetof(Mount, parameters_fragment.what)
-Mount.Where, config_parse_path, 0, offsetof(Mount, where)
-Mount.Options, config_parse_string, 0, offsetof(Mount, parameters_fragment.options)
-Mount.Type, config_parse_string, 0, offsetof(Mount, parameters_fragment.fstype)
-Mount.FsckPassNo, config_parse_fsck_passno, 0, offsetof(Mount, parameters_fragment.passno)
-Mount.TimeoutSec, config_parse_usec, 0, offsetof(Mount, timeout_usec)
-Mount.DirectoryMode, config_parse_mode, 0, offsetof(Mount, directory_mode)
-EXEC_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl
-KILL_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl
-m4_dnl
-Automount.Where, config_parse_path, 0, offsetof(Automount, where)
-Automount.DirectoryMode, config_parse_mode, 0, offsetof(Automount, directory_mode)
-m4_dnl
-Swap.What, config_parse_path, 0, offsetof(Swap, parameters_fragment.what)
-Swap.Priority, config_parse_int, 0, offsetof(Swap, parameters_fragment.priority)
-Swap.TimeoutSec, config_parse_usec, 0, offsetof(Swap, timeout_usec)
-EXEC_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl
-KILL_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl
-m4_dnl
-Timer.OnActiveSec, config_parse_timer, 0, 0
-Timer.OnBootSec, config_parse_timer, 0, 0
-Timer.OnStartupSec, config_parse_timer, 0, 0
-Timer.OnUnitActiveSec, config_parse_timer, 0, 0
-Timer.OnUnitInactiveSec, config_parse_timer, 0, 0
-Timer.Unit, config_parse_timer_unit, 0, 0
-m4_dnl
-Path.PathExists, config_parse_path_spec, 0, 0
-Path.PathExistsGlob, config_parse_path_spec, 0, 0
-Path.PathChanged, config_parse_path_spec, 0, 0
-Path.PathModified, config_parse_path_spec, 0, 0
-Path.DirectoryNotEmpty, config_parse_path_spec, 0, 0
-Path.Unit, config_parse_path_unit, 0, 0
-Path.MakeDirectory, config_parse_bool, 0, offsetof(Path, make_directory)
-Path.DirectoryMode, config_parse_mode, 0, offsetof(Path, directory_mode)
-m4_dnl The [Install] section is ignored here.
-Install.Alias, NULL, 0, 0
-Install.WantedBy, NULL, 0, 0
-Install.RequiredBy, NULL, 0, 0
-Install.Also, NULL, 0, 0
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
deleted file mode 100644
index 5803044178..0000000000
--- a/src/core/load-fragment.c
+++ /dev/null
@@ -1,2541 +0,0 @@
-/*-*- 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 <linux/oom.h>
-#include <assert.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sched.h>
-#include <sys/prctl.h>
-#include <sys/mount.h>
-#include <linux/fs.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-
-#include "unit.h"
-#include "strv.h"
-#include "conf-parser.h"
-#include "load-fragment.h"
-#include "log.h"
-#include "ioprio.h"
-#include "securebits.h"
-#include "missing.h"
-#include "unit-name.h"
-#include "unit-printf.h"
-#include "bus-errors.h"
-#include "utf8.h"
-#include "path-util.h"
-#include "syscall-list.h"
-
-#ifndef HAVE_SYSV_COMPAT
-int config_parse_warn_compat(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- log_debug("[%s:%u] Support for option %s= has been disabled at compile time and is ignored", filename, line, lvalue);
- return 0;
-}
-#endif
-
-int config_parse_unit_deps(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- UnitDependency d = ltype;
- Unit *u = userdata;
- char *w;
- size_t l;
- char *state;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- FOREACH_WORD_QUOTED(w, l, rvalue, state) {
- char *t, *k;
- int r;
-
- t = strndup(w, l);
- if (!t)
- return -ENOMEM;
-
- k = unit_name_printf(u, t);
- free(t);
- if (!k)
- return -ENOMEM;
-
- r = unit_add_dependency_by_name(u, d, k, NULL, true);
- if (r < 0)
- log_error("[%s:%u] Failed to add dependency on %s, ignoring: %s", filename, line, k, strerror(-r));
-
- free(k);
- }
-
- return 0;
-}
-
-int config_parse_unit_string_printf(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Unit *u = userdata;
- char *k;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(u);
-
- k = unit_full_printf(u, rvalue);
- if (!k)
- return -ENOMEM;
-
- r = config_parse_string(filename, line, section, lvalue, ltype, k, data, userdata);
- free (k);
-
- return r;
-}
-
-int config_parse_unit_strv_printf(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Unit *u = userdata;
- char *k;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(u);
-
- k = unit_full_printf(u, rvalue);
- if (!k)
- return -ENOMEM;
-
- r = config_parse_strv(filename, line, section, lvalue, ltype, k, data, userdata);
- free(k);
-
- return r;
-}
-
-int config_parse_unit_path_printf(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Unit *u = userdata;
- char *k;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(u);
-
- k = unit_full_printf(u, rvalue);
- if (!k)
- return log_oom();
-
- r = config_parse_path(filename, line, section, lvalue, ltype, k, data, userdata);
- free(k);
-
- return r;
-}
-
-int config_parse_socket_listen(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- SocketPort *p, *tail;
- Socket *s;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- s = SOCKET(data);
-
- p = new0(SocketPort, 1);
- if (!p)
- return -ENOMEM;
-
- if (streq(lvalue, "ListenFIFO")) {
- p->type = SOCKET_FIFO;
-
- if (!(p->path = unit_full_printf(UNIT(s), rvalue))) {
- free(p);
- return -ENOMEM;
- }
-
- path_kill_slashes(p->path);
-
- } else if (streq(lvalue, "ListenSpecial")) {
- p->type = SOCKET_SPECIAL;
-
- if (!(p->path = unit_full_printf(UNIT(s), rvalue))) {
- free(p);
- return -ENOMEM;
- }
-
- path_kill_slashes(p->path);
-
- } else if (streq(lvalue, "ListenMessageQueue")) {
-
- p->type = SOCKET_MQUEUE;
-
- if (!(p->path = unit_full_printf(UNIT(s), rvalue))) {
- free(p);
- return -ENOMEM;
- }
-
- path_kill_slashes(p->path);
-
- } else if (streq(lvalue, "ListenNetlink")) {
- char *k;
- int r;
-
- p->type = SOCKET_SOCKET;
- k = unit_full_printf(UNIT(s), rvalue);
- r = socket_address_parse_netlink(&p->address, k);
- free(k);
-
- if (r < 0) {
- log_error("[%s:%u] Failed to parse address value, ignoring: %s", filename, line, rvalue);
- free(p);
- return 0;
- }
-
- } else {
- char *k;
- int r;
-
- p->type = SOCKET_SOCKET;
- k = unit_full_printf(UNIT(s), rvalue);
- r = socket_address_parse(&p->address, k);
- free(k);
-
- if (r < 0) {
- log_error("[%s:%u] Failed to parse address value, ignoring: %s", filename, line, rvalue);
- free(p);
- return 0;
- }
-
- if (streq(lvalue, "ListenStream"))
- p->address.type = SOCK_STREAM;
- else if (streq(lvalue, "ListenDatagram"))
- p->address.type = SOCK_DGRAM;
- else {
- assert(streq(lvalue, "ListenSequentialPacket"));
- p->address.type = SOCK_SEQPACKET;
- }
-
- if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET) {
- log_error("[%s:%u] Address family not supported, ignoring: %s", filename, line, rvalue);
- free(p);
- return 0;
- }
- }
-
- p->fd = -1;
-
- if (s->ports) {
- LIST_FIND_TAIL(SocketPort, port, s->ports, tail);
- LIST_INSERT_AFTER(SocketPort, port, s->ports, tail, p);
- } else
- LIST_PREPEND(SocketPort, port, s->ports, p);
-
- return 0;
-}
-
-int config_parse_socket_bind(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Socket *s;
- SocketAddressBindIPv6Only b;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- s = SOCKET(data);
-
- b = socket_address_bind_ipv6_only_from_string(rvalue);
- if (b < 0) {
- int r;
-
- r = parse_boolean(rvalue);
- if (r < 0) {
- log_error("[%s:%u] Failed to parse bind IPv6 only value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- s->bind_ipv6_only = r ? SOCKET_ADDRESS_IPV6_ONLY : SOCKET_ADDRESS_BOTH;
- } else
- s->bind_ipv6_only = b;
-
- return 0;
-}
-
-int config_parse_exec_nice(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ExecContext *c = data;
- int priority;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (safe_atoi(rvalue, &priority) < 0) {
- log_error("[%s:%u] Failed to parse nice priority, ignoring: %s. ", filename, line, rvalue);
- return 0;
- }
-
- if (priority < PRIO_MIN || priority >= PRIO_MAX) {
- log_error("[%s:%u] Nice priority out of range, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- c->nice = priority;
- c->nice_set = true;
-
- return 0;
-}
-
-int config_parse_exec_oom_score_adjust(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ExecContext *c = data;
- int oa;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (safe_atoi(rvalue, &oa) < 0) {
- log_error("[%s:%u] Failed to parse the OOM score adjust value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- if (oa < OOM_SCORE_ADJ_MIN || oa > OOM_SCORE_ADJ_MAX) {
- log_error("[%s:%u] OOM score adjust value out of range, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- c->oom_score_adjust = oa;
- c->oom_score_adjust_set = true;
-
- return 0;
-}
-
-int config_parse_exec(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ExecCommand **e = data, *nce;
- char *path, **n;
- unsigned k;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(e);
-
- /* We accept an absolute path as first argument, or
- * alternatively an absolute prefixed with @ to allow
- * overriding of argv[0]. */
-
- e += ltype;
-
- for (;;) {
- char *w;
- size_t l;
- char *state;
- bool honour_argv0 = false, ignore = false;
-
- path = NULL;
- nce = NULL;
- n = NULL;
-
- rvalue += strspn(rvalue, WHITESPACE);
-
- if (rvalue[0] == 0)
- break;
-
- if (rvalue[0] == '-') {
- ignore = true;
- rvalue ++;
- }
-
- if (rvalue[0] == '@') {
- honour_argv0 = true;
- rvalue ++;
- }
-
- if (*rvalue != '/') {
- log_error("[%s:%u] Invalid executable path in command line, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- k = 0;
- FOREACH_WORD_QUOTED(w, l, rvalue, state) {
- if (strncmp(w, ";", MAX(l, 1U)) == 0)
- break;
-
- k++;
- }
-
- n = new(char*, k + !honour_argv0);
- if (!n)
- return -ENOMEM;
-
- k = 0;
- FOREACH_WORD_QUOTED(w, l, rvalue, state) {
- if (strncmp(w, ";", MAX(l, 1U)) == 0)
- break;
-
- if (honour_argv0 && w == rvalue) {
- assert(!path);
-
- path = strndup(w, l);
- if (!path) {
- r = -ENOMEM;
- goto fail;
- }
-
- if (!utf8_is_valid(path)) {
- log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
- r = 0;
- goto fail;
- }
-
- } else {
- char *c;
-
- c = n[k++] = cunescape_length(w, l);
- if (!c) {
- r = -ENOMEM;
- goto fail;
- }
-
- if (!utf8_is_valid(c)) {
- log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
- r = 0;
- goto fail;
- }
- }
- }
-
- n[k] = NULL;
-
- if (!n[0]) {
- log_error("[%s:%u] Invalid command line, ignoring: %s", filename, line, rvalue);
- r = 0;
- goto fail;
- }
-
- if (!path) {
- path = strdup(n[0]);
- if (!path) {
- r = -ENOMEM;
- goto fail;
- }
- }
-
- assert(path_is_absolute(path));
-
- nce = new0(ExecCommand, 1);
- if (!nce) {
- r = -ENOMEM;
- goto fail;
- }
-
- nce->argv = n;
- nce->path = path;
- nce->ignore = ignore;
-
- path_kill_slashes(nce->path);
-
- exec_command_append_list(e, nce);
-
- rvalue = state;
- }
-
- return 0;
-
-fail:
- n[k] = NULL;
- strv_free(n);
- free(path);
- free(nce);
-
- return r;
-}
-
-DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type");
-DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier");
-
-int config_parse_socket_bindtodevice(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Socket *s = data;
- char *n;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (rvalue[0] && !streq(rvalue, "*")) {
- if (!(n = strdup(rvalue)))
- return -ENOMEM;
- } else
- n = NULL;
-
- free(s->bind_to_device);
- s->bind_to_device = n;
-
- return 0;
-}
-
-DEFINE_CONFIG_PARSE_ENUM(config_parse_output, exec_output, ExecOutput, "Failed to parse output specifier");
-DEFINE_CONFIG_PARSE_ENUM(config_parse_input, exec_input, ExecInput, "Failed to parse input specifier");
-
-int config_parse_exec_io_class(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ExecContext *c = data;
- int x;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- x = ioprio_class_from_string(rvalue);
- if (x < 0) {
- log_error("[%s:%u] Failed to parse IO scheduling class, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- c->ioprio = IOPRIO_PRIO_VALUE(x, IOPRIO_PRIO_DATA(c->ioprio));
- c->ioprio_set = true;
-
- return 0;
-}
-
-int config_parse_exec_io_priority(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ExecContext *c = data;
- int i;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (safe_atoi(rvalue, &i) < 0 || i < 0 || i >= IOPRIO_BE_NR) {
- log_error("[%s:%u] Failed to parse io priority, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), i);
- c->ioprio_set = true;
-
- return 0;
-}
-
-int config_parse_exec_cpu_sched_policy(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
-
- ExecContext *c = data;
- int x;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- x = sched_policy_from_string(rvalue);
- if (x < 0) {
- log_error("[%s:%u] Failed to parse CPU scheduling policy, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- c->cpu_sched_policy = x;
- c->cpu_sched_set = true;
-
- return 0;
-}
-
-int config_parse_exec_cpu_sched_prio(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ExecContext *c = data;
- int i;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- /* On Linux RR/FIFO have the same range */
- if (safe_atoi(rvalue, &i) < 0 || i < sched_get_priority_min(SCHED_RR) || i > sched_get_priority_max(SCHED_RR)) {
- log_error("[%s:%u] Failed to parse CPU scheduling priority, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- c->cpu_sched_priority = i;
- c->cpu_sched_set = true;
-
- return 0;
-}
-
-int config_parse_exec_cpu_affinity(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ExecContext *c = data;
- char *w;
- size_t l;
- char *state;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- FOREACH_WORD_QUOTED(w, l, rvalue, state) {
- char *t;
- int r;
- unsigned cpu;
-
- if (!(t = strndup(w, l)))
- return -ENOMEM;
-
- r = safe_atou(t, &cpu);
- free(t);
-
- if (!(c->cpuset))
- if (!(c->cpuset = cpu_set_malloc(&c->cpuset_ncpus)))
- return -ENOMEM;
-
- if (r < 0 || cpu >= c->cpuset_ncpus) {
- log_error("[%s:%u] Failed to parse CPU affinity, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- CPU_SET_S(cpu, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset);
- }
-
- return 0;
-}
-
-int config_parse_exec_capabilities(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ExecContext *c = data;
- cap_t cap;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (!(cap = cap_from_text(rvalue))) {
- if (errno == ENOMEM)
- return -ENOMEM;
-
- log_error("[%s:%u] Failed to parse capabilities, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- if (c->capabilities)
- cap_free(c->capabilities);
- c->capabilities = cap;
-
- return 0;
-}
-
-int config_parse_exec_secure_bits(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ExecContext *c = data;
- char *w;
- size_t l;
- char *state;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- FOREACH_WORD_QUOTED(w, l, rvalue, state) {
- if (first_word(w, "keep-caps"))
- c->secure_bits |= SECURE_KEEP_CAPS;
- else if (first_word(w, "keep-caps-locked"))
- c->secure_bits |= SECURE_KEEP_CAPS_LOCKED;
- else if (first_word(w, "no-setuid-fixup"))
- c->secure_bits |= SECURE_NO_SETUID_FIXUP;
- else if (first_word(w, "no-setuid-fixup-locked"))
- c->secure_bits |= SECURE_NO_SETUID_FIXUP_LOCKED;
- else if (first_word(w, "noroot"))
- c->secure_bits |= SECURE_NOROOT;
- else if (first_word(w, "noroot-locked"))
- c->secure_bits |= SECURE_NOROOT_LOCKED;
- else {
- log_error("[%s:%u] Failed to parse secure bits, ignoring: %s", filename, line, rvalue);
- return 0;
- }
- }
-
- return 0;
-}
-
-int config_parse_bounding_set(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- uint64_t *capability_bounding_set_drop = data;
- char *w;
- size_t l;
- char *state;
- bool invert = false;
- uint64_t sum = 0;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (rvalue[0] == '~') {
- invert = true;
- rvalue++;
- }
-
- /* Note that we store this inverted internally, since the
- * kernel wants it like this. But we actually expose it
- * non-inverted everywhere to have a fully normalized
- * interface. */
-
- FOREACH_WORD_QUOTED(w, l, rvalue, state) {
- char *t;
- int r;
- cap_value_t cap;
-
- t = strndup(w, l);
- if (!t)
- return -ENOMEM;
-
- r = cap_from_name(t, &cap);
- free(t);
-
- if (r < 0) {
- log_error("[%s:%u] Failed to parse capability bounding set, ignoring: %s", filename, line, rvalue);
- continue;
- }
-
- sum |= ((uint64_t) 1ULL) << (uint64_t) cap;
- }
-
- if (invert)
- *capability_bounding_set_drop |= sum;
- else
- *capability_bounding_set_drop |= ~sum;
-
- return 0;
-}
-
-int config_parse_limit(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- struct rlimit **rl = data;
- unsigned long long u;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- rl += ltype;
-
- if (streq(rvalue, "infinity"))
- u = (unsigned long long) RLIM_INFINITY;
- else if (safe_atollu(rvalue, &u) < 0) {
- log_error("[%s:%u] Failed to parse resource value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- if (!*rl)
- if (!(*rl = new(struct rlimit, 1)))
- return -ENOMEM;
-
- (*rl)->rlim_cur = (*rl)->rlim_max = (rlim_t) u;
- return 0;
-}
-
-int config_parse_unit_cgroup(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Unit *u = userdata;
- char *w;
- size_t l;
- char *state;
-
- FOREACH_WORD_QUOTED(w, l, rvalue, state) {
- char *t, *k;
- int r;
-
- t = strndup(w, l);
- if (!t)
- return -ENOMEM;
-
- k = unit_full_printf(u, t);
- free(t);
-
- if (!k)
- return -ENOMEM;
-
- t = cunescape(k);
- free(k);
-
- if (!t)
- return -ENOMEM;
-
- r = unit_add_cgroup_from_text(u, t);
- free(t);
-
- if (r < 0) {
- log_error("[%s:%u] Failed to parse cgroup value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
- }
-
- return 0;
-}
-
-#ifdef HAVE_SYSV_COMPAT
-int config_parse_sysv_priority(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- int *priority = data;
- int i;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (safe_atoi(rvalue, &i) < 0 || i < 0) {
- log_error("[%s:%u] Failed to parse SysV start priority, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- *priority = (int) i;
- return 0;
-}
-#endif
-
-int config_parse_fsck_passno(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- int *passno = data;
- int i;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (safe_atoi(rvalue, &i) || i < 0) {
- log_error("[%s:%u] Failed to parse fsck pass number, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- *passno = (int) i;
- return 0;
-}
-
-DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode");
-
-int config_parse_kill_signal(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- int *sig = data;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(sig);
-
- if ((r = signal_from_string_try_harder(rvalue)) <= 0) {
- log_error("[%s:%u] Failed to parse kill signal, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- *sig = r;
- return 0;
-}
-
-int config_parse_exec_mount_flags(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ExecContext *c = data;
- char *w;
- size_t l;
- char *state;
- unsigned long flags = 0;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- FOREACH_WORD_QUOTED(w, l, rvalue, state) {
- if (strncmp(w, "shared", MAX(l, 6U)) == 0)
- flags |= MS_SHARED;
- else if (strncmp(w, "slave", MAX(l, 5U)) == 0)
- flags |= MS_SLAVE;
- else if (strncmp(w, "private", MAX(l, 7U)) == 0)
- flags |= MS_PRIVATE;
- else {
- log_error("[%s:%u] Failed to parse mount flags, ignoring: %s", filename, line, rvalue);
- return 0;
- }
- }
-
- c->mount_flags = flags;
- return 0;
-}
-
-int config_parse_timer(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Timer *t = data;
- usec_t u;
- TimerValue *v;
- TimerBase b;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if ((b = timer_base_from_string(lvalue)) < 0) {
- log_error("[%s:%u] Failed to parse timer base, ignoring: %s", filename, line, lvalue);
- return 0;
- }
-
- if (parse_usec(rvalue, &u) < 0) {
- log_error("[%s:%u] Failed to parse timer value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- if (!(v = new0(TimerValue, 1)))
- return -ENOMEM;
-
- v->base = b;
- v->value = u;
-
- LIST_PREPEND(TimerValue, value, t->values, v);
-
- return 0;
-}
-
-int config_parse_timer_unit(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Timer *t = data;
- int r;
- DBusError error;
- Unit *u;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- dbus_error_init(&error);
-
- if (endswith(rvalue, ".timer")) {
- log_error("[%s:%u] Unit cannot be of type timer, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- r = manager_load_unit(UNIT(t)->manager, rvalue, NULL, NULL, &u);
- if (r < 0) {
- log_error("[%s:%u] Failed to load unit %s, ignoring: %s", filename, line, rvalue, bus_error(&error, r));
- dbus_error_free(&error);
- return 0;
- }
-
- unit_ref_set(&t->unit, u);
-
- return 0;
-}
-
-int config_parse_path_spec(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Path *p = data;
- PathSpec *s;
- PathType b;
- char *k;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- b = path_type_from_string(lvalue);
- if (b < 0) {
- log_error("[%s:%u] Failed to parse path type, ignoring: %s", filename, line, lvalue);
- return 0;
- }
-
- k = unit_full_printf(UNIT(p), rvalue);
- if (!k)
- return log_oom();
-
- if (!path_is_absolute(k)) {
- log_error("[%s:%u] Path is not absolute, ignoring: %s", filename, line, k);
- free(k);
- return 0;
- }
-
- s = new0(PathSpec, 1);
- if (!s) {
- free(k);
- return log_oom();
- }
-
- s->path = path_kill_slashes(k);
- s->type = b;
- s->inotify_fd = -1;
-
- LIST_PREPEND(PathSpec, spec, p->specs, s);
-
- return 0;
-}
-
-int config_parse_path_unit(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Path *t = data;
- int r;
- DBusError error;
- Unit *u;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- dbus_error_init(&error);
-
- if (endswith(rvalue, ".path")) {
- log_error("[%s:%u] Unit cannot be of type path, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- if ((r = manager_load_unit(UNIT(t)->manager, rvalue, NULL, &error, &u)) < 0) {
- log_error("[%s:%u] Failed to load unit %s, ignoring: %s", filename, line, rvalue, bus_error(&error, r));
- dbus_error_free(&error);
- return 0;
- }
-
- unit_ref_set(&t->unit, u);
-
- return 0;
-}
-
-int config_parse_socket_service(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Socket *s = data;
- int r;
- DBusError error;
- Unit *x;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- dbus_error_init(&error);
-
- if (!endswith(rvalue, ".service")) {
- log_error("[%s:%u] Unit must be of type service, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- r = manager_load_unit(UNIT(s)->manager, rvalue, NULL, &error, &x);
- if (r < 0) {
- log_error("[%s:%u] Failed to load unit %s, ignoring: %s", filename, line, rvalue, bus_error(&error, r));
- dbus_error_free(&error);
- return 0;
- }
-
- unit_ref_set(&s->service, x);
-
- return 0;
-}
-
-int config_parse_service_sockets(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Service *s = data;
- int r;
- char *state, *w;
- size_t l;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- FOREACH_WORD_QUOTED(w, l, rvalue, state) {
- char *t, *k;
-
- t = strndup(w, l);
- if (!t)
- return -ENOMEM;
-
- k = unit_name_printf(UNIT(s), t);
- free(t);
-
- if (!k)
- return -ENOMEM;
-
- if (!endswith(k, ".socket")) {
- log_error("[%s:%u] Unit must be of type socket, ignoring: %s", filename, line, rvalue);
- free(k);
- continue;
- }
-
- r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k, NULL, true);
- if (r < 0)
- log_error("[%s:%u] Failed to add dependency on %s, ignoring: %s", filename, line, k, strerror(-r));
-
- r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k, NULL, true);
- if (r < 0)
- return r;
-
- free(k);
- }
-
- return 0;
-}
-
-int config_parse_service_timeout(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Service *s = userdata;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(s);
-
- r = config_parse_usec(filename, line, section, lvalue, ltype, rvalue, data, userdata);
-
- if (r)
- return r;
-
- if (streq(lvalue, "TimeoutSec")) {
- s->start_timeout_defined = true;
- s->timeout_stop_usec = s->timeout_start_usec;
- } else if (streq(lvalue, "TimeoutStartSec"))
- s->start_timeout_defined = true;
-
- return 0;
-}
-
-int config_parse_unit_env_file(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- char ***env = data, **k;
- Unit *u = userdata;
- char *s;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- s = unit_full_printf(u, rvalue);
- if (!s)
- return -ENOMEM;
-
- if (!path_is_absolute(s[0] == '-' ? s + 1 : s)) {
- log_error("[%s:%u] Path '%s' is not absolute, ignoring.", filename, line, s);
- free(s);
- return 0;
- }
-
- k = strv_append(*env, s);
- free(s);
- if (!k)
- return -ENOMEM;
-
- strv_free(*env);
- *env = k;
-
- return 0;
-}
-
-int config_parse_ip_tos(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- int *ip_tos = data, x;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- x = ip_tos_from_string(rvalue);
- if (x < 0) {
- log_error("[%s:%u] Failed to parse IP TOS value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- *ip_tos = x;
- return 0;
-}
-
-int config_parse_unit_condition_path(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ConditionType cond = ltype;
- Unit *u = data;
- bool trigger, negate;
- Condition *c;
- _cleanup_free_ char *p = NULL;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- trigger = rvalue[0] == '|';
- if (trigger)
- rvalue++;
-
- negate = rvalue[0] == '!';
- if (negate)
- rvalue++;
-
- p = unit_full_printf(u, rvalue);
- if (!p)
- return -ENOMEM;
-
- if (!path_is_absolute(p)) {
- log_error("[%s:%u] Path in condition not absolute, ignoring: %s", filename, line, p);
- return 0;
- }
-
- c = condition_new(cond, p, trigger, negate);
- if (!c)
- return -ENOMEM;
-
- LIST_PREPEND(Condition, conditions, u->conditions, c);
- return 0;
-}
-
-int config_parse_unit_condition_string(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ConditionType cond = ltype;
- Unit *u = data;
- bool trigger, negate;
- Condition *c;
- _cleanup_free_ char *s = NULL;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- trigger = rvalue[0] == '|';
- if (trigger)
- rvalue++;
-
- negate = rvalue[0] == '!';
- if (negate)
- rvalue++;
-
- s = unit_full_printf(u, rvalue);
- if (!s)
- return -ENOMEM;
-
- c = condition_new(cond, s, trigger, negate);
- if (!c)
- return log_oom();
-
- LIST_PREPEND(Condition, conditions, u->conditions, c);
- return 0;
-}
-
-int config_parse_unit_condition_null(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Unit *u = data;
- Condition *c;
- bool trigger, negate;
- int b;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if ((trigger = rvalue[0] == '|'))
- rvalue++;
-
- if ((negate = rvalue[0] == '!'))
- rvalue++;
-
- if ((b = parse_boolean(rvalue)) < 0) {
- log_error("[%s:%u] Failed to parse boolean value in condition, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- if (!b)
- negate = !negate;
-
- if (!(c = condition_new(CONDITION_NULL, NULL, trigger, negate)))
- return -ENOMEM;
-
- LIST_PREPEND(Condition, conditions, u->conditions, c);
- return 0;
-}
-
-DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
-DEFINE_CONFIG_PARSE_ENUM(config_parse_start_limit_action, start_limit_action, StartLimitAction, "Failed to parse start limit action specifier");
-
-int config_parse_unit_cgroup_attr(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Unit *u = data;
- char **l;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- l = strv_split_quoted(rvalue);
- if (!l)
- return -ENOMEM;
-
- if (strv_length(l) != 2) {
- log_error("[%s:%u] Failed to parse cgroup attribute value, ignoring: %s", filename, line, rvalue);
- strv_free(l);
- return 0;
- }
-
- r = unit_add_cgroup_attribute(u, NULL, l[0], l[1], NULL);
- strv_free(l);
-
- if (r < 0) {
- log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- return 0;
-}
-
-int config_parse_unit_cpu_shares(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) {
- Unit *u = data;
- int r;
- unsigned long ul;
- char *t;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (safe_atolu(rvalue, &ul) < 0 || ul < 1) {
- log_error("[%s:%u] Failed to parse CPU shares value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- if (asprintf(&t, "%lu", ul) < 0)
- return -ENOMEM;
-
- r = unit_add_cgroup_attribute(u, "cpu", "cpu.shares", t, NULL);
- free(t);
-
- if (r < 0) {
- log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- return 0;
-}
-
-int config_parse_unit_memory_limit(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) {
- Unit *u = data;
- int r;
- off_t sz;
- char *t;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (parse_bytes(rvalue, &sz) < 0 || sz <= 0) {
- log_error("[%s:%u] Failed to parse memory limit value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- if (asprintf(&t, "%llu", (unsigned long long) sz) < 0)
- return -ENOMEM;
-
- r = unit_add_cgroup_attribute(u,
- "memory",
- streq(lvalue, "MemorySoftLimit") ? "memory.soft_limit_in_bytes" : "memory.limit_in_bytes",
- t, NULL);
- free(t);
-
- if (r < 0) {
- log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- return 0;
-}
-
-static int device_map(const char *controller, const char *name, const char *value, char **ret) {
- char **l;
-
- assert(controller);
- assert(name);
- assert(value);
- assert(ret);
-
- l = strv_split_quoted(value);
- if (!l)
- return -ENOMEM;
-
- assert(strv_length(l) >= 1);
-
- if (streq(l[0], "*")) {
-
- if (asprintf(ret, "a *:*%s%s",
- isempty(l[1]) ? "" : " ", strempty(l[1])) < 0) {
- strv_free(l);
- return -ENOMEM;
- }
-
- } else {
- struct stat st;
-
- if (stat(l[0], &st) < 0) {
- log_warning("Couldn't stat device %s", l[0]);
- strv_free(l);
- return -errno;
- }
-
- if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
- log_warning("%s is not a device.", l[0]);
- strv_free(l);
- return -ENODEV;
- }
-
- if (asprintf(ret, "%c %u:%u%s%s",
- S_ISCHR(st.st_mode) ? 'c' : 'b',
- major(st.st_rdev), minor(st.st_rdev),
- isempty(l[1]) ? "" : " ", strempty(l[1])) < 0) {
-
- strv_free(l);
- return -ENOMEM;
- }
- }
-
- strv_free(l);
- return 0;
-}
-
-int config_parse_unit_device_allow(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) {
- Unit *u = data;
- char **l;
- int r;
- unsigned k;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- l = strv_split_quoted(rvalue);
- if (!l)
- return -ENOMEM;
-
- k = strv_length(l);
- if (k < 1 || k > 2) {
- log_error("[%s:%u] Failed to parse device value, ignoring: %s", filename, line, rvalue);
- strv_free(l);
- return 0;
- }
-
- if (!streq(l[0], "*") && !path_startswith(l[0], "/dev")) {
- log_error("[%s:%u] Device node path not absolute, ignoring: %s", filename, line, rvalue);
- strv_free(l);
- return 0;
- }
-
- if (!isempty(l[1]) && !in_charset(l[1], "rwm")) {
- log_error("[%s:%u] Device access string invalid, ignoring: %s", filename, line, rvalue);
- strv_free(l);
- return 0;
- }
- strv_free(l);
-
- r = unit_add_cgroup_attribute(u, "devices",
- streq(lvalue, "DeviceAllow") ? "devices.allow" : "devices.deny",
- rvalue, device_map);
-
- if (r < 0) {
- log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- return 0;
-}
-
-static int blkio_map(const char *controller, const char *name, const char *value, char **ret) {
- struct stat st;
- char **l;
- dev_t d;
-
- assert(controller);
- assert(name);
- assert(value);
- assert(ret);
-
- l = strv_split_quoted(value);
- if (!l)
- return -ENOMEM;
-
- assert(strv_length(l) == 2);
-
- if (stat(l[0], &st) < 0) {
- log_warning("Couldn't stat device %s", l[0]);
- strv_free(l);
- return -errno;
- }
-
- if (S_ISBLK(st.st_mode))
- d = st.st_rdev;
- else if (major(st.st_dev) != 0) {
- /* If this is not a device node then find the block
- * device this file is stored on */
- d = st.st_dev;
-
- /* If this is a partition, try to get the originating
- * block device */
- block_get_whole_disk(d, &d);
- } else {
- log_warning("%s is not a block device and file system block device cannot be determined or is not local.", l[0]);
- strv_free(l);
- return -ENODEV;
- }
-
- if (asprintf(ret, "%u:%u %s", major(d), minor(d), l[1]) < 0) {
- strv_free(l);
- return -ENOMEM;
- }
-
- strv_free(l);
- return 0;
-}
-
-int config_parse_unit_blkio_weight(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) {
- Unit *u = data;
- int r;
- unsigned long ul;
- const char *device = NULL, *weight;
- unsigned k;
- char *t, **l;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- l = strv_split_quoted(rvalue);
- if (!l)
- return -ENOMEM;
-
- k = strv_length(l);
- if (k < 1 || k > 2) {
- log_error("[%s:%u] Failed to parse weight value, ignoring: %s", filename, line, rvalue);
- strv_free(l);
- return 0;
- }
-
- if (k == 1)
- weight = l[0];
- else {
- device = l[0];
- weight = l[1];
- }
-
- if (device && !path_is_absolute(device)) {
- log_error("[%s:%u] Failed to parse block device node value, ignoring: %s", filename, line, rvalue);
- strv_free(l);
- return 0;
- }
-
- if (safe_atolu(weight, &ul) < 0 || ul < 10 || ul > 1000) {
- log_error("[%s:%u] Failed to parse block IO weight value, ignoring: %s", filename, line, rvalue);
- strv_free(l);
- return 0;
- }
-
- if (device)
- r = asprintf(&t, "%s %lu", device, ul);
- else
- r = asprintf(&t, "%lu", ul);
- strv_free(l);
-
- if (r < 0)
- return -ENOMEM;
-
- if (device)
- r = unit_add_cgroup_attribute(u, "blkio", "blkio.weight_device", t, blkio_map);
- else
- r = unit_add_cgroup_attribute(u, "blkio", "blkio.weight", t, NULL);
- free(t);
-
- if (r < 0) {
- log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- return 0;
-}
-
-int config_parse_unit_blkio_bandwidth(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) {
- Unit *u = data;
- int r;
- off_t bytes;
- unsigned k;
- char *t, **l;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- l = strv_split_quoted(rvalue);
- if (!l)
- return -ENOMEM;
-
- k = strv_length(l);
- if (k != 2) {
- log_error("[%s:%u] Failed to parse bandwidth value, ignoring: %s", filename, line, rvalue);
- strv_free(l);
- return 0;
- }
-
- if (!path_is_absolute(l[0])) {
- log_error("[%s:%u] Failed to parse block device node value, ignoring: %s", filename, line, rvalue);
- strv_free(l);
- return 0;
- }
-
- if (parse_bytes(l[1], &bytes) < 0 || bytes <= 0) {
- log_error("[%s:%u] Failed to parse block IO bandwidth value, ignoring: %s", filename, line, rvalue);
- strv_free(l);
- return 0;
- }
-
- r = asprintf(&t, "%s %llu", l[0], (unsigned long long) bytes);
- strv_free(l);
-
- if (r < 0)
- return -ENOMEM;
-
- r = unit_add_cgroup_attribute(u, "blkio",
- streq(lvalue, "BlockIOReadBandwidth") ? "blkio.read_bps_device" : "blkio.write_bps_device",
- t, blkio_map);
- free(t);
-
- if (r < 0) {
- log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- return 0;
-}
-
-int config_parse_unit_requires_mounts_for(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Unit *u = userdata;
- int r;
- bool empty_before;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- empty_before = !u->requires_mounts_for;
-
- r = config_parse_path_strv(filename, line, section, lvalue, ltype, rvalue, data, userdata);
-
- /* Make it easy to find units with requires_mounts set */
- if (empty_before && u->requires_mounts_for)
- LIST_PREPEND(Unit, has_requires_mounts_for, u->manager->has_requires_mounts_for, u);
-
- return r;
-}
-
-int config_parse_documentation(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Unit *u = userdata;
- int r;
- char **a, **b;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(u);
-
- r = config_parse_unit_strv_printf(filename, line, section, lvalue, ltype, rvalue, data, userdata);
- if (r < 0)
- return r;
-
- for (a = b = u->documentation; a && *a; a++) {
-
- if (is_valid_documentation_url(*a))
- *(b++) = *a;
- else {
- log_error("[%s:%u] Invalid URL, ignoring: %s", filename, line, *a);
- free(*a);
- }
- }
- *b = NULL;
-
- return r;
-}
-
-static void syscall_set(uint32_t *p, int nr) {
- p[nr >> 4] |= 1 << (nr & 31);
-}
-
-static void syscall_unset(uint32_t *p, int nr) {
- p[nr >> 4] &= ~(1 << (nr & 31));
-}
-
-int config_parse_syscall_filter(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ExecContext *c = data;
- Unit *u = userdata;
- bool invert = false;
- char *w;
- size_t l;
- char *state;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(u);
-
- if (rvalue[0] == '~') {
- invert = true;
- rvalue++;
- }
-
- if (!c->syscall_filter) {
- size_t n;
-
- n = (syscall_max() + 31) >> 4;
- c->syscall_filter = new(uint32_t, n);
- if (!c->syscall_filter)
- return -ENOMEM;
-
- memset(c->syscall_filter, invert ? 0xFF : 0, n * sizeof(uint32_t));
-
- /* Add these by default */
- syscall_set(c->syscall_filter, __NR_execve);
- syscall_set(c->syscall_filter, __NR_rt_sigreturn);
-#ifdef __NR_sigreturn
- syscall_set(c->syscall_filter, __NR_sigreturn);
-#endif
- syscall_set(c->syscall_filter, __NR_exit_group);
- syscall_set(c->syscall_filter, __NR_exit);
- }
-
- FOREACH_WORD_QUOTED(w, l, rvalue, state) {
- int id;
- char *t;
-
- t = strndup(w, l);
- if (!t)
- return -ENOMEM;
-
- id = syscall_from_name(t);
- free(t);
-
- if (id < 0) {
- log_error("[%s:%u] Failed to parse syscall, ignoring: %s", filename, line, rvalue);
- continue;
- }
-
- if (invert)
- syscall_unset(c->syscall_filter, id);
- else
- syscall_set(c->syscall_filter, id);
- }
-
- c->no_new_privileges = true;
-
- return 0;
-}
-
-#define FOLLOW_MAX 8
-
-static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
- unsigned c = 0;
- int fd, r;
- FILE *f;
- char *id = NULL;
-
- assert(filename);
- assert(*filename);
- assert(_f);
- assert(names);
-
- /* This will update the filename pointer if the loaded file is
- * reached by a symlink. The old string will be freed. */
-
- for (;;) {
- char *target, *name;
-
- if (c++ >= FOLLOW_MAX)
- return -ELOOP;
-
- path_kill_slashes(*filename);
-
- /* Add the file name we are currently looking at to
- * the names of this unit, but only if it is a valid
- * unit name. */
- name = path_get_file_name(*filename);
-
- if (unit_name_is_valid(name, true)) {
-
- id = set_get(names, name);
- if (!id) {
- id = strdup(name);
- if (!id)
- return -ENOMEM;
-
- r = set_put(names, id);
- if (r < 0) {
- free(id);
- return r;
- }
- }
- }
-
- /* Try to open the file name, but don't if its a symlink */
- fd = open(*filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
- if (fd >= 0)
- break;
-
- if (errno != ELOOP)
- return -errno;
-
- /* Hmm, so this is a symlink. Let's read the name, and follow it manually */
- r = readlink_and_make_absolute(*filename, &target);
- if (r < 0)
- return r;
-
- free(*filename);
- *filename = target;
- }
-
- f = fdopen(fd, "re");
- if (!f) {
- r = -errno;
- close_nointr_nofail(fd);
- return r;
- }
-
- *_f = f;
- *_final = id;
- return 0;
-}
-
-static int merge_by_names(Unit **u, Set *names, const char *id) {
- char *k;
- int r;
-
- assert(u);
- assert(*u);
- assert(names);
-
- /* Let's try to add in all symlink names we found */
- while ((k = set_steal_first(names))) {
-
- /* First try to merge in the other name into our
- * unit */
- r = unit_merge_by_name(*u, k);
- if (r < 0) {
- Unit *other;
-
- /* Hmm, we couldn't merge the other unit into
- * ours? Then let's try it the other way
- * round */
-
- other = manager_get_unit((*u)->manager, k);
- free(k);
-
- if (other) {
- r = unit_merge(other, *u);
- if (r >= 0) {
- *u = other;
- return merge_by_names(u, names, NULL);
- }
- }
-
- return r;
- }
-
- if (id == k)
- unit_choose_id(*u, id);
-
- free(k);
- }
-
- return 0;
-}
-
-static int load_from_path(Unit *u, const char *path) {
- int r;
- Set *symlink_names;
- FILE *f = NULL;
- char *filename = NULL, *id = NULL;
- Unit *merged;
- struct stat st;
-
- assert(u);
- assert(path);
-
- symlink_names = set_new(string_hash_func, string_compare_func);
- if (!symlink_names)
- return -ENOMEM;
-
- if (path_is_absolute(path)) {
-
- filename = strdup(path);
- if (!filename) {
- r = -ENOMEM;
- goto finish;
- }
-
- r = open_follow(&filename, &f, symlink_names, &id);
- if (r < 0) {
- free(filename);
- filename = NULL;
-
- if (r != -ENOENT)
- goto finish;
- }
-
- } else {
- char **p;
-
- STRV_FOREACH(p, u->manager->lookup_paths.unit_path) {
-
- /* Instead of opening the path right away, we manually
- * follow all symlinks and add their name to our unit
- * name set while doing so */
- filename = path_make_absolute(path, *p);
- if (!filename) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (u->manager->unit_path_cache &&
- !set_get(u->manager->unit_path_cache, filename))
- r = -ENOENT;
- else
- r = open_follow(&filename, &f, symlink_names, &id);
-
- if (r < 0) {
- free(filename);
- filename = NULL;
-
- if (r != -ENOENT)
- goto finish;
-
- /* Empty the symlink names for the next run */
- set_clear_free(symlink_names);
- continue;
- }
-
- break;
- }
- }
-
- if (!filename) {
- /* Hmm, no suitable file found? */
- r = 0;
- goto finish;
- }
-
- merged = u;
- r = merge_by_names(&merged, symlink_names, id);
- if (r < 0)
- goto finish;
-
- if (merged != u) {
- u->load_state = UNIT_MERGED;
- r = 0;
- goto finish;
- }
-
- if (fstat(fileno(f), &st) < 0) {
- r = -errno;
- goto finish;
- }
-
- if (null_or_empty(&st))
- u->load_state = UNIT_MASKED;
- else {
- /* Now, parse the file contents */
- r = config_parse(filename, f, UNIT_VTABLE(u)->sections, config_item_perf_lookup, (void*) load_fragment_gperf_lookup, false, u);
- if (r < 0)
- goto finish;
-
- u->load_state = UNIT_LOADED;
- }
-
- free(u->fragment_path);
- u->fragment_path = filename;
- filename = NULL;
-
- u->fragment_mtime = timespec_load(&st.st_mtim);
-
- if (u->source_path) {
- if (stat(u->source_path, &st) >= 0)
- u->source_mtime = timespec_load(&st.st_mtim);
- else
- u->source_mtime = 0;
- }
-
- r = 0;
-
-finish:
- set_free_free(symlink_names);
- free(filename);
-
- if (f)
- fclose(f);
-
- return r;
-}
-
-int unit_load_fragment(Unit *u) {
- int r;
- Iterator i;
- const char *t;
-
- assert(u);
- assert(u->load_state == UNIT_STUB);
- assert(u->id);
-
- /* First, try to find the unit under its id. We always look
- * for unit files in the default directories, to make it easy
- * to override things by placing things in /etc/systemd/system */
- r = load_from_path(u, u->id);
- if (r < 0)
- return r;
-
- /* Try to find an alias we can load this with */
- if (u->load_state == UNIT_STUB)
- SET_FOREACH(t, u->names, i) {
-
- if (t == u->id)
- continue;
-
- r = load_from_path(u, t);
- if (r < 0)
- return r;
-
- if (u->load_state != UNIT_STUB)
- break;
- }
-
- /* And now, try looking for it under the suggested (originally linked) path */
- if (u->load_state == UNIT_STUB && u->fragment_path) {
-
- r = load_from_path(u, u->fragment_path);
- if (r < 0)
- return r;
-
- if (u->load_state == UNIT_STUB) {
- /* Hmm, this didn't work? Then let's get rid
- * of the fragment path stored for us, so that
- * we don't point to an invalid location. */
- free(u->fragment_path);
- u->fragment_path = NULL;
- }
- }
-
- /* Look for a template */
- if (u->load_state == UNIT_STUB && u->instance) {
- char *k;
-
- k = unit_name_template(u->id);
- if (!k)
- return -ENOMEM;
-
- r = load_from_path(u, k);
- free(k);
-
- if (r < 0)
- return r;
-
- if (u->load_state == UNIT_STUB)
- SET_FOREACH(t, u->names, i) {
-
- if (t == u->id)
- continue;
-
- k = unit_name_template(t);
- if (!k)
- return -ENOMEM;
-
- r = load_from_path(u, k);
- free(k);
-
- if (r < 0)
- return r;
-
- if (u->load_state != UNIT_STUB)
- break;
- }
- }
-
- return 0;
-}
-
-void unit_dump_config_items(FILE *f) {
- static const struct {
- const ConfigParserCallback callback;
- const char *rvalue;
- } table[] = {
- { config_parse_int, "INTEGER" },
- { config_parse_unsigned, "UNSIGNED" },
- { config_parse_bytes_size, "SIZE" },
- { config_parse_bool, "BOOLEAN" },
- { config_parse_string, "STRING" },
- { config_parse_path, "PATH" },
- { config_parse_unit_path_printf, "PATH" },
- { config_parse_strv, "STRING [...]" },
- { config_parse_exec_nice, "NICE" },
- { config_parse_exec_oom_score_adjust, "OOMSCOREADJUST" },
- { config_parse_exec_io_class, "IOCLASS" },
- { config_parse_exec_io_priority, "IOPRIORITY" },
- { config_parse_exec_cpu_sched_policy, "CPUSCHEDPOLICY" },
- { config_parse_exec_cpu_sched_prio, "CPUSCHEDPRIO" },
- { config_parse_exec_cpu_affinity, "CPUAFFINITY" },
- { config_parse_mode, "MODE" },
- { config_parse_unit_env_file, "FILE" },
- { config_parse_output, "OUTPUT" },
- { config_parse_input, "INPUT" },
- { config_parse_facility, "FACILITY" },
- { config_parse_level, "LEVEL" },
- { config_parse_exec_capabilities, "CAPABILITIES" },
- { config_parse_exec_secure_bits, "SECUREBITS" },
- { config_parse_bounding_set, "BOUNDINGSET" },
- { config_parse_limit, "LIMIT" },
- { config_parse_unit_cgroup, "CGROUP [...]" },
- { config_parse_unit_deps, "UNIT [...]" },
- { config_parse_exec, "PATH [ARGUMENT [...]]" },
- { config_parse_service_type, "SERVICETYPE" },
- { config_parse_service_restart, "SERVICERESTART" },
-#ifdef HAVE_SYSV_COMPAT
- { config_parse_sysv_priority, "SYSVPRIORITY" },
-#else
- { config_parse_warn_compat, "NOTSUPPORTED" },
-#endif
- { config_parse_kill_mode, "KILLMODE" },
- { config_parse_kill_signal, "SIGNAL" },
- { config_parse_socket_listen, "SOCKET [...]" },
- { config_parse_socket_bind, "SOCKETBIND" },
- { config_parse_socket_bindtodevice, "NETWORKINTERFACE" },
- { config_parse_usec, "SECONDS" },
- { config_parse_nsec, "NANOSECONDS" },
- { config_parse_path_strv, "PATH [...]" },
- { config_parse_unit_requires_mounts_for, "PATH [...]" },
- { config_parse_exec_mount_flags, "MOUNTFLAG [...]" },
- { config_parse_unit_string_printf, "STRING" },
- { config_parse_timer, "TIMER" },
- { config_parse_timer_unit, "NAME" },
- { config_parse_path_spec, "PATH" },
- { config_parse_path_unit, "UNIT" },
- { config_parse_notify_access, "ACCESS" },
- { config_parse_ip_tos, "TOS" },
- { config_parse_unit_condition_path, "CONDITION" },
- { config_parse_unit_condition_string, "CONDITION" },
- { config_parse_unit_condition_null, "CONDITION" },
- };
-
- const char *prev = NULL;
- const char *i;
-
- assert(f);
-
- NULSTR_FOREACH(i, load_fragment_gperf_nulstr) {
- const char *rvalue = "OTHER", *lvalue;
- unsigned j;
- size_t prefix_len;
- const char *dot;
- const ConfigPerfItem *p;
-
- assert_se(p = load_fragment_gperf_lookup(i, strlen(i)));
-
- dot = strchr(i, '.');
- lvalue = dot ? dot + 1 : i;
- prefix_len = dot-i;
-
- if (dot)
- if (!prev || strncmp(prev, i, prefix_len+1) != 0) {
- if (prev)
- fputc('\n', f);
-
- fprintf(f, "[%.*s]\n", (int) prefix_len, i);
- }
-
- for (j = 0; j < ELEMENTSOF(table); j++)
- if (p->parse == table[j].callback) {
- rvalue = table[j].rvalue;
- break;
- }
-
- fprintf(f, "%s=%s\n", lvalue, rvalue);
- prev = i;
- }
-}
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
deleted file mode 100644
index 24f738464c..0000000000
--- a/src/core/load-fragment.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*-*- 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 "unit.h"
-
-/* Read service data from .desktop file style configuration fragments */
-
-int unit_load_fragment(Unit *u);
-
-void unit_dump_config_items(FILE *f);
-
-int config_parse_warn_compat(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_deps(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_string_printf(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_strv_printf(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_path_printf(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_documentation(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_socket_listen(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_socket_bind(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_nice(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_oom_score_adjust(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_service_timeout(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_service_type(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_service_restart(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_socket_bindtodevice(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_output(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_input(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_io_class(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_io_priority(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_cpu_sched_policy(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_cpu_sched_prio(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_cpu_affinity(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_capabilities(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_secure_bits(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_bounding_set(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_limit(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_cgroup(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_sysv_priority(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_fsck_passno(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_kill_signal(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_mount_flags(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_timer(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_timer_unit(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_path_spec(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_path_unit(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_socket_service(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_service_sockets(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_env_file(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_ip_tos(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_condition_path(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_condition_string(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_condition_null(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_kill_mode(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_notify_access(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_start_limit_action(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_cgroup_attr(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_cpu_shares(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_memory_limit(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_device_allow(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_blkio_weight(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_blkio_bandwidth(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_requires_mounts_for(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_syscall_filter(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-
-/* gperf prototypes */
-const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, unsigned length);
-extern const char load_fragment_gperf_nulstr[];
diff --git a/src/core/locale-setup.c b/src/core/locale-setup.c
deleted file mode 100644
index b9bd3a0748..0000000000
--- a/src/core/locale-setup.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/*-*- 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 <stdlib.h>
-#include <errno.h>
-
-#include "locale-setup.h"
-#include "util.h"
-#include "macro.h"
-#include "virt.h"
-
-enum {
- /* We don't list LC_ALL here on purpose. People should be
- * using LANG instead. */
-
- VARIABLE_LANG,
- VARIABLE_LANGUAGE,
- VARIABLE_LC_CTYPE,
- VARIABLE_LC_NUMERIC,
- VARIABLE_LC_TIME,
- VARIABLE_LC_COLLATE,
- VARIABLE_LC_MONETARY,
- VARIABLE_LC_MESSAGES,
- VARIABLE_LC_PAPER,
- VARIABLE_LC_NAME,
- VARIABLE_LC_ADDRESS,
- VARIABLE_LC_TELEPHONE,
- VARIABLE_LC_MEASUREMENT,
- VARIABLE_LC_IDENTIFICATION,
- _VARIABLE_MAX
-};
-
-static const char * const variable_names[_VARIABLE_MAX] = {
- [VARIABLE_LANG] = "LANG",
- [VARIABLE_LANGUAGE] = "LANGUAGE",
- [VARIABLE_LC_CTYPE] = "LC_CTYPE",
- [VARIABLE_LC_NUMERIC] = "LC_NUMERIC",
- [VARIABLE_LC_TIME] = "LC_TIME",
- [VARIABLE_LC_COLLATE] = "LC_COLLATE",
- [VARIABLE_LC_MONETARY] = "LC_MONETARY",
- [VARIABLE_LC_MESSAGES] = "LC_MESSAGES",
- [VARIABLE_LC_PAPER] = "LC_PAPER",
- [VARIABLE_LC_NAME] = "LC_NAME",
- [VARIABLE_LC_ADDRESS] = "LC_ADDRESS",
- [VARIABLE_LC_TELEPHONE] = "LC_TELEPHONE",
- [VARIABLE_LC_MEASUREMENT] = "LC_MEASUREMENT",
- [VARIABLE_LC_IDENTIFICATION] = "LC_IDENTIFICATION"
-};
-
-int locale_setup(void) {
- char *variables[_VARIABLE_MAX];
- int r = 0, i;
-
- zero(variables);
-
- if (detect_container(NULL) <= 0)
- if ((r = parse_env_file("/proc/cmdline", WHITESPACE,
-#if defined(TARGET_FEDORA)
- "LANG", &variables[VARIABLE_LANG],
-#endif
- "locale.LANG", &variables[VARIABLE_LANG],
- "locale.LANGUAGE", &variables[VARIABLE_LANGUAGE],
- "locale.LC_CTYPE", &variables[VARIABLE_LC_CTYPE],
- "locale.LC_NUMERIC", &variables[VARIABLE_LC_NUMERIC],
- "locale.LC_TIME", &variables[VARIABLE_LC_TIME],
- "locale.LC_COLLATE", &variables[VARIABLE_LC_COLLATE],
- "locale.LC_MONETARY", &variables[VARIABLE_LC_MONETARY],
- "locale.LC_MESSAGES", &variables[VARIABLE_LC_MESSAGES],
- "locale.LC_PAPER", &variables[VARIABLE_LC_PAPER],
- "locale.LC_NAME", &variables[VARIABLE_LC_NAME],
- "locale.LC_ADDRESS", &variables[VARIABLE_LC_ADDRESS],
- "locale.LC_TELEPHONE", &variables[VARIABLE_LC_TELEPHONE],
- "locale.LC_MEASUREMENT", &variables[VARIABLE_LC_MEASUREMENT],
- "locale.LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION],
- NULL)) < 0) {
-
- if (r != -ENOENT)
- log_warning("Failed to read /proc/cmdline: %s", strerror(-r));
- }
-
- /* Hmm, nothing set on the kernel cmd line? Then let's
- * try /etc/locale.conf */
- if (r <= 0 &&
- (r = parse_env_file("/etc/locale.conf", NEWLINE,
- "LANG", &variables[VARIABLE_LANG],
- "LANGUAGE", &variables[VARIABLE_LANGUAGE],
- "LC_CTYPE", &variables[VARIABLE_LC_CTYPE],
- "LC_NUMERIC", &variables[VARIABLE_LC_NUMERIC],
- "LC_TIME", &variables[VARIABLE_LC_TIME],
- "LC_COLLATE", &variables[VARIABLE_LC_COLLATE],
- "LC_MONETARY", &variables[VARIABLE_LC_MONETARY],
- "LC_MESSAGES", &variables[VARIABLE_LC_MESSAGES],
- "LC_PAPER", &variables[VARIABLE_LC_PAPER],
- "LC_NAME", &variables[VARIABLE_LC_NAME],
- "LC_ADDRESS", &variables[VARIABLE_LC_ADDRESS],
- "LC_TELEPHONE", &variables[VARIABLE_LC_TELEPHONE],
- "LC_MEASUREMENT", &variables[VARIABLE_LC_MEASUREMENT],
- "LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION],
- NULL)) < 0) {
-
- if (r != -ENOENT)
- log_warning("Failed to read /etc/locale.conf: %s", strerror(-r));
- }
-
-#if defined(TARGET_ALTLINUX)
- if (r <= 0 &&
- (r = parse_env_file("/etc/sysconfig/i18n", NEWLINE,
- "LANG", &variables[VARIABLE_LANG],
- NULL)) < 0) {
-
- if (r != -ENOENT)
- log_warning("Failed to read /etc/sysconfig/i18n: %s", strerror(-r));
- }
-
-#elif defined(TARGET_SUSE)
- if (r <= 0 &&
- (r = parse_env_file("/etc/sysconfig/language", NEWLINE,
- "RC_LANG", &variables[VARIABLE_LANG],
- NULL)) < 0) {
-
- if (r != -ENOENT)
- log_warning("Failed to read /etc/sysconfig/language: %s", strerror(-r));
- }
-
-#elif defined(TARGET_DEBIAN) || defined(TARGET_UBUNTU) || defined(TARGET_ANGSTROM)
- if (r <= 0 &&
- (r = parse_env_file("/etc/default/locale", NEWLINE,
- "LANG", &variables[VARIABLE_LANG],
- "LC_CTYPE", &variables[VARIABLE_LC_CTYPE],
- "LC_NUMERIC", &variables[VARIABLE_LC_NUMERIC],
- "LC_TIME", &variables[VARIABLE_LC_TIME],
- "LC_COLLATE", &variables[VARIABLE_LC_COLLATE],
- "LC_MONETARY", &variables[VARIABLE_LC_MONETARY],
- "LC_MESSAGES", &variables[VARIABLE_LC_MESSAGES],
- "LC_PAPER", &variables[VARIABLE_LC_PAPER],
- "LC_NAME", &variables[VARIABLE_LC_NAME],
- "LC_ADDRESS", &variables[VARIABLE_LC_ADDRESS],
- "LC_TELEPHONE", &variables[VARIABLE_LC_TELEPHONE],
- "LC_MEASUREMENT", &variables[VARIABLE_LC_MEASUREMENT],
- "LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION],
- NULL)) < 0) {
-
- if (r != -ENOENT)
- log_warning("Failed to read /etc/default/locale: %s", strerror(-r));
- }
-
-#elif defined(TARGET_GENTOO)
- /* Gentoo's openrc expects locale variables in /etc/env.d/
- * These files are later compiled by env-update into shell
- * export commands at /etc/profile.env, with variables being
- * exported by openrc's runscript (so /etc/init.d/)
- */
- if (r <= 0 &&
- (r = parse_env_file("/etc/profile.env", NEWLINE,
- "export LANG", &variables[VARIABLE_LANG],
- "export LC_CTYPE", &variables[VARIABLE_LC_CTYPE],
- "export LC_NUMERIC", &variables[VARIABLE_LC_NUMERIC],
- "export LC_TIME", &variables[VARIABLE_LC_TIME],
- "export LC_COLLATE", &variables[VARIABLE_LC_COLLATE],
- "export LC_MONETARY", &variables[VARIABLE_LC_MONETARY],
- "export LC_MESSAGES", &variables[VARIABLE_LC_MESSAGES],
- "export LC_PAPER", &variables[VARIABLE_LC_PAPER],
- "export LC_NAME", &variables[VARIABLE_LC_NAME],
- "export LC_ADDRESS", &variables[VARIABLE_LC_ADDRESS],
- "export LC_TELEPHONE", &variables[VARIABLE_LC_TELEPHONE],
- "export LC_MEASUREMENT", &variables[VARIABLE_LC_MEASUREMENT],
- "export LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION],
- NULL)) < 0) {
-
- if (r != -ENOENT)
- log_warning("Failed to read /etc/profile.env: %s", strerror(-r));
- }
-#elif defined(TARGET_MANDRIVA) || defined(TARGET_MAGEIA )
- if (r <= 0 &&
- (r = parse_env_file("/etc/sysconfig/i18n", NEWLINE,
- "LANG", &variables[VARIABLE_LANG],
- "LC_CTYPE", &variables[VARIABLE_LC_CTYPE],
- "LC_NUMERIC", &variables[VARIABLE_LC_NUMERIC],
- "LC_TIME", &variables[VARIABLE_LC_TIME],
- "LC_COLLATE", &variables[VARIABLE_LC_COLLATE],
- "LC_MONETARY", &variables[VARIABLE_LC_MONETARY],
- "LC_MESSAGES", &variables[VARIABLE_LC_MESSAGES],
- "LC_PAPER", &variables[VARIABLE_LC_PAPER],
- "LC_NAME", &variables[VARIABLE_LC_NAME],
- "LC_ADDRESS", &variables[VARIABLE_LC_ADDRESS],
- "LC_TELEPHONE", &variables[VARIABLE_LC_TELEPHONE],
- "LC_MEASUREMENT", &variables[VARIABLE_LC_MEASUREMENT],
- "LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION],
- NULL)) < 0) {
-
- if (r != -ENOENT)
- log_warning("Failed to read /etc/sysconfig/i18n: %s", strerror(-r));
- }
-
-#endif
-
- if (!variables[VARIABLE_LANG]) {
- if (!(variables[VARIABLE_LANG] = strdup("C"))) {
- r = -ENOMEM;
- goto finish;
- }
- }
-
- for (i = 0; i < _VARIABLE_MAX; i++) {
-
- if (variables[i]) {
- if (setenv(variable_names[i], variables[i], 1) < 0) {
- r = -errno;
- goto finish;
- }
- } else
- unsetenv(variable_names[i]);
- }
-
- r = 0;
-
-finish:
- for (i = 0; i < _VARIABLE_MAX; i++)
- free(variables[i]);
-
- return r;
-}
diff --git a/src/core/locale-setup.h b/src/core/locale-setup.h
deleted file mode 100644
index 5a0f2f7888..0000000000
--- a/src/core/locale-setup.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*-*- 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 locale_setup(void);
diff --git a/src/core/loopback-setup.c b/src/core/loopback-setup.c
deleted file mode 100644
index 065b75a6e3..0000000000
--- a/src/core/loopback-setup.c
+++ /dev/null
@@ -1,317 +0,0 @@
-/*-*- 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 <errno.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <asm/types.h>
-#include <netinet/in.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-
-#include "util.h"
-#include "macro.h"
-#include "loopback-setup.h"
-#include "socket-util.h"
-
-#define NLMSG_TAIL(nmsg) \
- ((struct rtattr *) (((uint8_t*) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
-
-static int add_rtattr(struct nlmsghdr *n, size_t max_length, int type, const void *data, size_t data_length) {
- size_t length;
- struct rtattr *rta;
-
- length = RTA_LENGTH(data_length);
-
- if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(length) > max_length)
- return -E2BIG;
-
- rta = NLMSG_TAIL(n);
- rta->rta_type = type;
- rta->rta_len = length;
- memcpy(RTA_DATA(rta), data, data_length);
- n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(length);
-
- return 0;
-}
-
-static ssize_t sendto_loop(int fd, const void *buf, size_t buf_len, int flags, const struct sockaddr *sa, socklen_t sa_len) {
-
- for (;;) {
- ssize_t l;
-
- l = sendto(fd, buf, buf_len, flags, sa, sa_len);
- if (l >= 0)
- return l;
-
- if (errno != EINTR)
- return -errno;
- }
-}
-
-static ssize_t recvfrom_loop(int fd, void *buf, size_t buf_len, int flags, struct sockaddr *sa, socklen_t *sa_len) {
-
- for (;;) {
- ssize_t l;
-
- l = recvfrom(fd, buf, buf_len, flags, sa, sa_len);
- if (l >= 0)
- return l;
-
- if (errno != EINTR)
- return -errno;
- }
-}
-
-static int add_adresses(int fd, int if_loopback, unsigned *requests) {
- union {
- struct sockaddr sa;
- struct sockaddr_nl nl;
- } sa;
- union {
- struct nlmsghdr header;
- uint8_t buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
- NLMSG_ALIGN(sizeof(struct ifaddrmsg)) +
- RTA_LENGTH(sizeof(struct in6_addr))];
- } request;
-
- struct ifaddrmsg *ifaddrmsg;
- uint32_t ipv4_address = htonl(INADDR_LOOPBACK);
- int r;
-
- zero(request);
-
- request.header.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
- request.header.nlmsg_type = RTM_NEWADDR;
- request.header.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK;
- request.header.nlmsg_seq = *requests + 1;
-
- ifaddrmsg = NLMSG_DATA(&request.header);
- ifaddrmsg->ifa_family = AF_INET;
- ifaddrmsg->ifa_prefixlen = 8;
- ifaddrmsg->ifa_flags = IFA_F_PERMANENT;
- ifaddrmsg->ifa_scope = RT_SCOPE_HOST;
- ifaddrmsg->ifa_index = if_loopback;
-
- r = add_rtattr(&request.header, sizeof(request), IFA_LOCAL, &ipv4_address, sizeof(ipv4_address));
- if (r < 0)
- return r;
-
- zero(sa);
- sa.nl.nl_family = AF_NETLINK;
-
- if (sendto_loop(fd, &request, request.header.nlmsg_len, 0, &sa.sa, sizeof(sa)) < 0)
- return -errno;
- (*requests)++;
-
- if (!socket_ipv6_is_supported())
- return 0;
-
- request.header.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
- request.header.nlmsg_seq = *requests + 1;
-
- ifaddrmsg->ifa_family = AF_INET6;
- ifaddrmsg->ifa_prefixlen = 128;
-
- r = add_rtattr(&request.header, sizeof(request), IFA_LOCAL, &in6addr_loopback, sizeof(in6addr_loopback));
- if (r < 0)
- return r;
-
- if (sendto_loop(fd, &request, request.header.nlmsg_len, 0, &sa.sa, sizeof(sa)) < 0)
- return -errno;
- (*requests)++;
-
- return 0;
-}
-
-static int start_interface(int fd, int if_loopback, unsigned *requests) {
- union {
- struct sockaddr sa;
- struct sockaddr_nl nl;
- } sa;
- union {
- struct nlmsghdr header;
- uint8_t buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
- NLMSG_ALIGN(sizeof(struct ifinfomsg))];
- } request;
-
- struct ifinfomsg *ifinfomsg;
-
- zero(request);
-
- request.header.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
- request.header.nlmsg_type = RTM_NEWLINK;
- request.header.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
- request.header.nlmsg_seq = *requests + 1;
-
- ifinfomsg = NLMSG_DATA(&request.header);
- ifinfomsg->ifi_family = AF_UNSPEC;
- ifinfomsg->ifi_index = if_loopback;
- ifinfomsg->ifi_flags = IFF_UP;
- ifinfomsg->ifi_change = IFF_UP;
-
- zero(sa);
- sa.nl.nl_family = AF_NETLINK;
-
- if (sendto_loop(fd, &request, request.header.nlmsg_len, 0, &sa.sa, sizeof(sa)) < 0)
- return -errno;
-
- (*requests)++;
-
- return 0;
-}
-
-static int read_response(int fd, unsigned requests_max) {
- union {
- struct sockaddr sa;
- struct sockaddr_nl nl;
- } sa;
- union {
- struct nlmsghdr header;
- uint8_t buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
- NLMSG_ALIGN(sizeof(struct nlmsgerr))];
- } response;
-
- ssize_t l;
- socklen_t sa_len = sizeof(sa);
- struct nlmsgerr *nlmsgerr;
-
- l = recvfrom_loop(fd, &response, sizeof(response), 0, &sa.sa, &sa_len);
- if (l < 0)
- return -errno;
-
- if (sa_len != sizeof(sa.nl) ||
- sa.nl.nl_family != AF_NETLINK)
- return -EIO;
-
- if (sa.nl.nl_pid != 0)
- return 0;
-
- if ((size_t) l < sizeof(struct nlmsghdr))
- return -EIO;
-
- if (response.header.nlmsg_type != NLMSG_ERROR ||
- (pid_t) response.header.nlmsg_pid != getpid() ||
- response.header.nlmsg_seq >= requests_max)
- return 0;
-
- if ((size_t) l < NLMSG_LENGTH(sizeof(struct nlmsgerr)) ||
- response.header.nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
- return -EIO;
-
- nlmsgerr = NLMSG_DATA(&response.header);
-
- if (nlmsgerr->error < 0 && nlmsgerr->error != -EEXIST)
- return nlmsgerr->error;
-
- return response.header.nlmsg_seq;
-}
-
-static int check_loopback(void) {
- int r, fd;
- union {
- struct sockaddr sa;
- struct sockaddr_in in;
- } sa;
-
- /* If we failed to set up the loop back device, check whether
- * it might already be set up */
-
- fd = socket(AF_INET, SOCK_DGRAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0);
- if (fd < 0)
- return -errno;
-
- zero(sa);
- sa.in.sin_family = AF_INET;
- sa.in.sin_addr.s_addr = INADDR_LOOPBACK;
-
- if (bind(fd, &sa.sa, sizeof(sa.in)) >= 0)
- r = 1;
- else
- r = errno == EADDRNOTAVAIL ? 0 : -errno;
-
- close_nointr_nofail(fd);
-
- return r;
-}
-
-int loopback_setup(void) {
- int r, if_loopback;
- union {
- struct sockaddr sa;
- struct sockaddr_nl nl;
- } sa;
- unsigned requests = 0, i;
- int fd;
- bool eperm = false;
-
- errno = 0;
- if_loopback = (int) if_nametoindex("lo");
- if (if_loopback <= 0)
- return errno ? -errno : -ENODEV;
-
- fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (fd < 0)
- return -errno;
-
- zero(sa);
- sa.nl.nl_family = AF_NETLINK;
- if (bind(fd, &sa.sa, sizeof(sa)) < 0) {
- r = -errno;
- goto finish;
- }
-
- r = add_adresses(fd, if_loopback, &requests);
- if (r < 0)
- goto finish;
-
- r = start_interface(fd, if_loopback, &requests);
- if (r < 0)
- goto finish;
-
- for (i = 0; i < requests; i++) {
- r = read_response(fd, requests);
-
- if (r == -EPERM)
- eperm = true;
- else if (r < 0)
- goto finish;
- }
-
- if (eperm && check_loopback() < 0) {
- r = -EPERM;
- goto finish;
- }
-
- r = 0;
-
-finish:
- if (r < 0)
- log_warning("Failed to configure loopback device: %s", strerror(-r));
-
- if (fd >= 0)
- close_nointr_nofail(fd);
-
- return r;
-}
diff --git a/src/core/loopback-setup.h b/src/core/loopback-setup.h
deleted file mode 100644
index dd83cf13a7..0000000000
--- a/src/core/loopback-setup.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*-*- 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 loopback_setup(void);
diff --git a/src/core/machine-id-setup.c b/src/core/machine-id-setup.c
deleted file mode 100644
index 7f4c23b130..0000000000
--- a/src/core/machine-id-setup.c
+++ /dev/null
@@ -1,246 +0,0 @@
-/*-*- 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 <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <sys/mount.h>
-
-#include <systemd/sd-id128.h>
-
-#include "machine-id-setup.h"
-#include "macro.h"
-#include "util.h"
-#include "mkdir.h"
-#include "log.h"
-#include "virt.h"
-
-static int shorten_uuid(char destination[36], const char *source) {
- unsigned i, j;
-
- for (i = 0, j = 0; i < 36 && j < 32; i++) {
- int t;
-
- t = unhexchar(source[i]);
- if (t < 0)
- continue;
-
- destination[j++] = hexchar(t);
- }
-
- if (i == 36 && j == 32) {
- destination[32] = '\n';
- destination[33] = 0;
- return 0;
- }
-
- return -EINVAL;
-}
-
-static int generate(char id[34]) {
- int fd, r;
- unsigned char *p;
- sd_id128_t buf;
- char *q;
- ssize_t k;
- const char *vm_id;
-
- assert(id);
-
- /* First, try reading the D-Bus machine id, unless it is a symlink */
- fd = open("/var/lib/dbus/machine-id", O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
- if (fd >= 0) {
-
- k = loop_read(fd, id, 32, false);
- close_nointr_nofail(fd);
-
- if (k >= 32) {
- id[32] = '\n';
- id[33] = 0;
-
- log_info("Initializing machine ID from D-Bus machine ID.");
- return 0;
- }
- }
-
- /* If that didn't work, see if we are running in qemu/kvm and a
- * machine ID was passed in via -uuid on the qemu/kvm command
- * line */
-
- r = detect_vm(&vm_id);
- if (r > 0 && streq(vm_id, "kvm")) {
- char uuid[37];
-
- fd = open("/sys/class/dmi/id/product_uuid", O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
- if (fd >= 0) {
- k = loop_read(fd, uuid, 36, false);
- close_nointr_nofail(fd);
-
- if (k >= 36) {
- r = shorten_uuid(id, uuid);
- if (r >= 0) {
- log_info("Initializing machine ID from KVM UUID.");
- return 0;
- }
- }
- }
- }
-
- /* If that didn't work either, see if we are running in a
- * container, and a machine ID was passed in via
- * $container_uuid the way libvirt/LXC does it */
- r = detect_container(NULL);
- if (r > 0) {
- char *e;
-
- r = getenv_for_pid(1, "container_uuid", &e);
- if (r > 0) {
- if (strlen(e) >= 36) {
- r = shorten_uuid(id, e);
- if (r >= 0) {
- log_info("Initializing machine ID from container UUID.");
- free(e);
- return 0;
- }
- }
-
- free(e);
- }
- }
-
- /* If that didn't work, generate a random machine id */
- r = sd_id128_randomize(&buf);
- if (r < 0) {
- log_error("Failed to open /dev/urandom: %s", strerror(-r));
- return r;
- }
-
- for (p = buf.bytes, q = id; p < buf.bytes + sizeof(buf); p++, q += 2) {
- q[0] = hexchar(*p >> 4);
- q[1] = hexchar(*p & 15);
- }
-
- id[32] = '\n';
- id[33] = 0;
-
- log_info("Initializing machine ID from random generator.");
-
- return 0;
-}
-
-int machine_id_setup(void) {
- int fd, r;
- bool writable;
- struct stat st;
- char id[34]; /* 32 + \n + \0 */
- mode_t m;
-
- m = umask(0000);
-
- /* We create this 0444, to indicate that this isn't really
- * something you should ever modify. Of course, since the file
- * will be owned by root it doesn't matter much, but maybe
- * people look. */
-
- fd = open("/etc/machine-id", O_RDWR|O_CREAT|O_CLOEXEC|O_NOCTTY, 0444);
- if (fd >= 0)
- writable = true;
- else {
- fd = open("/etc/machine-id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0) {
- umask(m);
- log_error("Cannot open /etc/machine-id: %m");
- return -errno;
- }
-
- writable = false;
- }
-
- umask(m);
-
- if (fstat(fd, &st) < 0) {
- log_error("fstat() failed: %m");
- r = -errno;
- goto finish;
- }
-
- if (S_ISREG(st.st_mode)) {
- if (loop_read(fd, id, 32, false) >= 32) {
- r = 0;
- goto finish;
- }
- }
-
- /* Hmm, so, the id currently stored is not useful, then let's
- * generate one */
-
- r = generate(id);
- if (r < 0)
- goto finish;
-
- if (S_ISREG(st.st_mode) && writable) {
- lseek(fd, 0, SEEK_SET);
-
- if (loop_write(fd, id, 33, false) == 33) {
- r = 0;
- goto finish;
- }
- }
-
- close_nointr_nofail(fd);
- fd = -1;
-
- /* Hmm, we couldn't write it? So let's write it to
- * /run/machine-id as a replacement */
-
- m = umask(0022);
- r = write_one_line_file("/run/machine-id", id);
- umask(m);
-
- if (r < 0) {
- log_error("Cannot write /run/machine-id: %s", strerror(-r));
-
- unlink("/run/machine-id");
- goto finish;
- }
-
- /* And now, let's mount it over */
- r = mount("/run/machine-id", "/etc/machine-id", NULL, MS_BIND, NULL) < 0 ? -errno : 0;
- if (r < 0) {
- unlink("/run/machine-id");
- log_error("Failed to mount /etc/machine-id: %s", strerror(-r));
- } else {
- log_info("Installed transient /etc/machine-id file.");
-
- /* Mark the mount read-only */
- mount(NULL, "/etc/machine-id", NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, NULL);
- }
-
-finish:
-
- if (fd >= 0)
- close_nointr_nofail(fd);
-
- return r;
-}
diff --git a/src/core/machine-id-setup.h b/src/core/machine-id-setup.h
deleted file mode 100644
index b9e6b4d674..0000000000
--- a/src/core/machine-id-setup.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*-*- 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 machine_id_setup(void);
diff --git a/src/core/macros.systemd.in b/src/core/macros.systemd.in
deleted file mode 100644
index e521df337d..0000000000
--- a/src/core/macros.systemd.in
+++ /dev/null
@@ -1,56 +0,0 @@
-# -*- Mode: makefile; indent-tabs-mode: t -*- */
-#
-# This file is part of systemd.
-#
-# Copyright 2012 Lennart Poettering
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-
-# RPM macros for packages installing systemd unit files
-
-%_unitdir @systemunitdir@
-%_presetdir @systempresetdir@
-
-%systemd_requires \
-Requires(post): systemd \
-Requires(preun): systemd \
-Requires(postun): systemd \
-%{nil}
-
-%systemd_post() \
-if [ $1 -eq 1 ] ; then \
- # Initial installation \
- @rootbindir@/systemctl preset %{?*} >/dev/null 2>&1 || : \
-fi \
-%{nil}
-
-%systemd_preun() \
-if [ $1 -eq 0 ] ; then \
- # Package removal, not upgrade \
- @rootbindir@/systemctl --no-reload disable %{?*} > /dev/null 2>&1 || : \
- @rootbindir@/systemctl stop %{?*} > /dev/null 2>&1 || : \
-fi \
-%{nil}
-
-%systemd_postun() \
-@rootbindir@/systemctl daemon-reload >/dev/null 2>&1 || : \
-%{nil}
-
-%systemd_postun_with_restart() \
-@rootbindir@/systemctl daemon-reload >/dev/null 2>&1 || : \
-if [ $1 -ge 1 ] ; then \
- # Package upgrade, not uninstall \
- @rootbindir@/systemctl try-restart %{?*} >/dev/null 2>&1 || : \
-fi \
-%{nil}
diff --git a/src/core/main.c b/src/core/main.c
deleted file mode 100644
index 4da8ecb864..0000000000
--- a/src/core/main.c
+++ /dev/null
@@ -1,1950 +0,0 @@
-/*-*- 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 <dbus/dbus.h>
-
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <getopt.h>
-#include <signal.h>
-#include <sys/wait.h>
-#include <fcntl.h>
-#include <sys/prctl.h>
-#include <sys/mount.h>
-
-#include "manager.h"
-#include "log.h"
-#include "load-fragment.h"
-#include "fdset.h"
-#include "special.h"
-#include "conf-parser.h"
-#include "bus-errors.h"
-#include "missing.h"
-#include "label.h"
-#include "build.h"
-#include "strv.h"
-#include "def.h"
-#include "virt.h"
-#include "watchdog.h"
-#include "path-util.h"
-#include "switch-root.h"
-#include "capability.h"
-#include "killall.h"
-
-#include "mount-setup.h"
-#include "loopback-setup.h"
-#include "kmod-setup.h"
-#include "hostname-setup.h"
-#include "machine-id-setup.h"
-#include "locale-setup.h"
-#include "hwclock.h"
-#include "selinux-setup.h"
-#include "ima-setup.h"
-#include "sd-daemon.h"
-
-static enum {
- ACTION_RUN,
- ACTION_HELP,
- ACTION_VERSION,
- ACTION_TEST,
- ACTION_DUMP_CONFIGURATION_ITEMS,
- ACTION_DONE
-} arg_action = ACTION_RUN;
-
-static char *arg_default_unit = NULL;
-static SystemdRunningAs arg_running_as = _SYSTEMD_RUNNING_AS_INVALID;
-
-static bool arg_dump_core = true;
-static bool arg_crash_shell = false;
-static int arg_crash_chvt = -1;
-static bool arg_confirm_spawn = false;
-static bool arg_show_status = true;
-static bool arg_switched_root = false;
-static char **arg_default_controllers = NULL;
-static char ***arg_join_controllers = NULL;
-static ExecOutput arg_default_std_output = EXEC_OUTPUT_JOURNAL;
-static ExecOutput arg_default_std_error = EXEC_OUTPUT_INHERIT;
-static usec_t arg_runtime_watchdog = 0;
-static usec_t arg_shutdown_watchdog = 10 * USEC_PER_MINUTE;
-static struct rlimit *arg_default_rlimit[RLIMIT_NLIMITS] = {};
-static uint64_t arg_capability_bounding_set_drop = 0;
-static nsec_t arg_timer_slack_nsec = (nsec_t) -1;
-
-static FILE* serialization = NULL;
-
-static void nop_handler(int sig) {
-}
-
-_noreturn_ static void crash(int sig) {
-
- if (!arg_dump_core)
- log_error("Caught <%s>, not dumping core.", signal_to_string(sig));
- else {
- struct sigaction sa;
- pid_t pid;
-
- /* We want to wait for the core process, hence let's enable SIGCHLD */
- zero(sa);
- sa.sa_handler = nop_handler;
- sa.sa_flags = SA_NOCLDSTOP|SA_RESTART;
- assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
-
- if ((pid = fork()) < 0)
- log_error("Caught <%s>, cannot fork for core dump: %s", signal_to_string(sig), strerror(errno));
-
- else if (pid == 0) {
- struct rlimit rl;
-
- /* Enable default signal handler for core dump */
- zero(sa);
- sa.sa_handler = SIG_DFL;
- assert_se(sigaction(sig, &sa, NULL) == 0);
-
- /* Don't limit the core dump size */
- zero(rl);
- rl.rlim_cur = RLIM_INFINITY;
- rl.rlim_max = RLIM_INFINITY;
- setrlimit(RLIMIT_CORE, &rl);
-
- /* Just to be sure... */
- assert_se(chdir("/") == 0);
-
- /* Raise the signal again */
- raise(sig);
-
- assert_not_reached("We shouldn't be here...");
- _exit(1);
-
- } else {
- siginfo_t status;
- int r;
-
- /* Order things nicely. */
- if ((r = wait_for_terminate(pid, &status)) < 0)
- log_error("Caught <%s>, waitpid() failed: %s", signal_to_string(sig), strerror(-r));
- else if (status.si_code != CLD_DUMPED)
- log_error("Caught <%s>, core dump failed.", signal_to_string(sig));
- else
- log_error("Caught <%s>, dumped core as pid %lu.", signal_to_string(sig), (unsigned long) pid);
- }
- }
-
- if (arg_crash_chvt)
- chvt(arg_crash_chvt);
-
- if (arg_crash_shell) {
- struct sigaction sa;
- pid_t pid;
-
- log_info("Executing crash shell in 10s...");
- sleep(10);
-
- /* Let the kernel reap children for us */
- zero(sa);
- sa.sa_handler = SIG_IGN;
- sa.sa_flags = SA_NOCLDSTOP|SA_NOCLDWAIT|SA_RESTART;
- assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
-
- pid = fork();
- if (pid < 0)
- log_error("Failed to fork off crash shell: %m");
- else if (pid == 0) {
- make_console_stdio();
- execl("/bin/sh", "/bin/sh", NULL);
-
- log_error("execl() failed: %m");
- _exit(1);
- }
-
- log_info("Successfully spawned crash shell as pid %lu.", (unsigned long) pid);
- }
-
- log_info("Freezing execution.");
- freeze();
-}
-
-static void install_crash_handler(void) {
- struct sigaction sa;
-
- zero(sa);
-
- sa.sa_handler = crash;
- sa.sa_flags = SA_NODEFER;
-
- sigaction_many(&sa, SIGNALS_CRASH_HANDLER, -1);
-}
-
-static int console_setup(bool do_reset) {
- int tty_fd, r;
-
- /* If we are init, we connect stdin/stdout/stderr to /dev/null
- * and make sure we don't have a controlling tty. */
-
- release_terminal();
-
- if (!do_reset)
- return 0;
-
- tty_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
- if (tty_fd < 0) {
- log_error("Failed to open /dev/console: %s", strerror(-tty_fd));
- return -tty_fd;
- }
-
- /* We don't want to force text mode.
- * plymouth may be showing pictures already from initrd. */
- r = reset_terminal_fd(tty_fd, false);
- if (r < 0)
- log_error("Failed to reset /dev/console: %s", strerror(-r));
-
- close_nointr_nofail(tty_fd);
- return r;
-}
-
-static int set_default_unit(const char *u) {
- char *c;
-
- assert(u);
-
- c = strdup(u);
- if (!c)
- return -ENOMEM;
-
- free(arg_default_unit);
- arg_default_unit = c;
-
- return 0;
-}
-
-static int parse_proc_cmdline_word(const char *word) {
-
- static const char * const rlmap[] = {
- "emergency", SPECIAL_EMERGENCY_TARGET,
- "-b", SPECIAL_EMERGENCY_TARGET,
- "single", SPECIAL_RESCUE_TARGET,
- "-s", SPECIAL_RESCUE_TARGET,
- "s", SPECIAL_RESCUE_TARGET,
- "S", SPECIAL_RESCUE_TARGET,
- "1", SPECIAL_RESCUE_TARGET,
- "2", SPECIAL_RUNLEVEL2_TARGET,
- "3", SPECIAL_RUNLEVEL3_TARGET,
- "4", SPECIAL_RUNLEVEL4_TARGET,
- "5", SPECIAL_RUNLEVEL5_TARGET,
- };
-
- assert(word);
-
- if (startswith(word, "systemd.unit=")) {
-
- if (!in_initrd())
- return set_default_unit(word + 13);
-
- } else if (startswith(word, "rd.systemd.unit=")) {
-
- if (in_initrd())
- return set_default_unit(word + 16);
-
- } else if (startswith(word, "systemd.log_target=")) {
-
- if (log_set_target_from_string(word + 19) < 0)
- log_warning("Failed to parse log target %s. Ignoring.", word + 19);
-
- } else if (startswith(word, "systemd.log_level=")) {
-
- if (log_set_max_level_from_string(word + 18) < 0)
- log_warning("Failed to parse log level %s. Ignoring.", word + 18);
-
- } else if (startswith(word, "systemd.log_color=")) {
-
- if (log_show_color_from_string(word + 18) < 0)
- log_warning("Failed to parse log color setting %s. Ignoring.", word + 18);
-
- } else if (startswith(word, "systemd.log_location=")) {
-
- if (log_show_location_from_string(word + 21) < 0)
- log_warning("Failed to parse log location setting %s. Ignoring.", word + 21);
-
- } else if (startswith(word, "systemd.dump_core=")) {
- int r;
-
- if ((r = parse_boolean(word + 18)) < 0)
- log_warning("Failed to parse dump core switch %s. Ignoring.", word + 18);
- else
- arg_dump_core = r;
-
- } else if (startswith(word, "systemd.crash_shell=")) {
- int r;
-
- if ((r = parse_boolean(word + 20)) < 0)
- log_warning("Failed to parse crash shell switch %s. Ignoring.", word + 20);
- else
- arg_crash_shell = r;
-
- } else if (startswith(word, "systemd.confirm_spawn=")) {
- int r;
-
- if ((r = parse_boolean(word + 22)) < 0)
- log_warning("Failed to parse confirm spawn switch %s. Ignoring.", word + 22);
- else
- arg_confirm_spawn = r;
-
- } else if (startswith(word, "systemd.crash_chvt=")) {
- int k;
-
- if (safe_atoi(word + 19, &k) < 0)
- log_warning("Failed to parse crash chvt switch %s. Ignoring.", word + 19);
- else
- arg_crash_chvt = k;
-
- } else if (startswith(word, "systemd.show_status=")) {
- int r;
-
- if ((r = parse_boolean(word + 20)) < 0)
- log_warning("Failed to parse show status switch %s. Ignoring.", word + 20);
- else
- arg_show_status = r;
- } else if (startswith(word, "systemd.default_standard_output=")) {
- int r;
-
- if ((r = exec_output_from_string(word + 32)) < 0)
- log_warning("Failed to parse default standard output switch %s. Ignoring.", word + 32);
- else
- arg_default_std_output = r;
- } else if (startswith(word, "systemd.default_standard_error=")) {
- int r;
-
- if ((r = exec_output_from_string(word + 31)) < 0)
- log_warning("Failed to parse default standard error switch %s. Ignoring.", word + 31);
- else
- arg_default_std_error = r;
- } else if (startswith(word, "systemd.setenv=")) {
- char *cenv, *eq;
- int r;
-
- cenv = strdup(word + 15);
- if (!cenv)
- return -ENOMEM;
-
- eq = strchr(cenv, '=');
- if (!eq) {
- r = unsetenv(cenv);
- if (r < 0)
- log_warning("unsetenv failed %m. Ignoring.");
- } else {
- *eq = 0;
- r = setenv(cenv, eq + 1, 1);
- if (r < 0)
- log_warning("setenv failed %m. Ignoring.");
- }
- free(cenv);
-
- } else if (startswith(word, "systemd.") ||
- (in_initrd() && startswith(word, "rd.systemd."))) {
-
- log_warning("Unknown kernel switch %s. Ignoring.", word);
-
- log_info("Supported kernel switches:\n"
- "systemd.unit=UNIT Default unit to start\n"
- "rd.systemd.unit=UNIT Default unit to start when run in initrd\n"
- "systemd.dump_core=0|1 Dump core on crash\n"
- "systemd.crash_shell=0|1 Run shell on crash\n"
- "systemd.crash_chvt=N Change to VT #N on crash\n"
- "systemd.confirm_spawn=0|1 Confirm every process spawn\n"
- "systemd.show_status=0|1 Show status updates on the console during bootup\n"
- "systemd.log_target=console|kmsg|journal|journal-or-kmsg|syslog|syslog-or-kmsg|null\n"
- " Log target\n"
- "systemd.log_level=LEVEL Log level\n"
- "systemd.log_color=0|1 Highlight important log messages\n"
- "systemd.log_location=0|1 Include code location in log messages\n"
- "systemd.default_standard_output=null|tty|syslog|syslog+console|kmsg|kmsg+console|journal|journal+console\n"
- " Set default log output for services\n"
- "systemd.default_standard_error=null|tty|syslog|syslog+console|kmsg|kmsg+console|journal|journal+console\n"
- " Set default log error output for services\n"
- "systemd.setenv=ASSIGNMENT Set an environment variable for all spawned processes\n");
-
- } else if (streq(word, "quiet"))
- arg_show_status = false;
- else if (!in_initrd()) {
- unsigned i;
-
- /* SysV compatibility */
- for (i = 0; i < ELEMENTSOF(rlmap); i += 2)
- if (streq(word, rlmap[i]))
- return set_default_unit(rlmap[i+1]);
- }
-
- return 0;
-}
-
-static int config_parse_level2(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- log_set_max_level_from_string(rvalue);
- return 0;
-}
-
-static int config_parse_target(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- log_set_target_from_string(rvalue);
- return 0;
-}
-
-static int config_parse_color(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- log_show_color_from_string(rvalue);
- return 0;
-}
-
-static int config_parse_location(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- log_show_location_from_string(rvalue);
- return 0;
-}
-
-static int config_parse_cpu_affinity2(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- char *w;
- size_t l;
- char *state;
- cpu_set_t *c = NULL;
- unsigned ncpus = 0;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- FOREACH_WORD_QUOTED(w, l, rvalue, state) {
- char *t;
- int r;
- unsigned cpu;
-
- if (!(t = strndup(w, l)))
- return log_oom();
-
- r = safe_atou(t, &cpu);
- free(t);
-
- if (!c)
- if (!(c = cpu_set_malloc(&ncpus)))
- return log_oom();
-
- if (r < 0 || cpu >= ncpus) {
- log_error("[%s:%u] Failed to parse CPU affinity: %s", filename, line, rvalue);
- CPU_FREE(c);
- return -EBADMSG;
- }
-
- CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c);
- }
-
- if (c) {
- if (sched_setaffinity(0, CPU_ALLOC_SIZE(ncpus), c) < 0)
- log_warning("Failed to set CPU affinity: %m");
-
- CPU_FREE(c);
- }
-
- return 0;
-}
-
-static void strv_free_free(char ***l) {
- char ***i;
-
- if (!l)
- return;
-
- for (i = l; *i; i++)
- strv_free(*i);
-
- free(l);
-}
-
-static void free_join_controllers(void) {
- if (!arg_join_controllers)
- return;
-
- strv_free_free(arg_join_controllers);
- arg_join_controllers = NULL;
-}
-
-static int config_parse_join_controllers(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- unsigned n = 0;
- char *state, *w;
- size_t length;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- free_join_controllers();
-
- FOREACH_WORD_QUOTED(w, length, rvalue, state) {
- char *s, **l;
-
- s = strndup(w, length);
- if (!s)
- return log_oom();
-
- l = strv_split(s, ",");
- free(s);
-
- strv_uniq(l);
-
- if (strv_length(l) <= 1) {
- strv_free(l);
- continue;
- }
-
- if (!arg_join_controllers) {
- arg_join_controllers = new(char**, 2);
- if (!arg_join_controllers) {
- strv_free(l);
- return log_oom();
- }
-
- arg_join_controllers[0] = l;
- arg_join_controllers[1] = NULL;
-
- n = 1;
- } else {
- char ***a;
- char ***t;
-
- t = new0(char**, n+2);
- if (!t) {
- strv_free(l);
- return log_oom();
- }
-
- n = 0;
-
- for (a = arg_join_controllers; *a; a++) {
-
- if (strv_overlap(*a, l)) {
- char **c;
-
- c = strv_merge(*a, l);
- if (!c) {
- strv_free(l);
- strv_free_free(t);
- return log_oom();
- }
-
- strv_free(l);
- l = c;
- } else {
- char **c;
-
- c = strv_copy(*a);
- if (!c) {
- strv_free(l);
- strv_free_free(t);
- return log_oom();
- }
-
- t[n++] = c;
- }
- }
-
- t[n++] = strv_uniq(l);
-
- strv_free_free(arg_join_controllers);
- arg_join_controllers = t;
- }
- }
-
- return 0;
-}
-
-static int parse_config_file(void) {
-
- const ConfigTableItem items[] = {
- { "Manager", "LogLevel", config_parse_level2, 0, NULL },
- { "Manager", "LogTarget", config_parse_target, 0, NULL },
- { "Manager", "LogColor", config_parse_color, 0, NULL },
- { "Manager", "LogLocation", config_parse_location, 0, NULL },
- { "Manager", "DumpCore", config_parse_bool, 0, &arg_dump_core },
- { "Manager", "CrashShell", config_parse_bool, 0, &arg_crash_shell },
- { "Manager", "ShowStatus", config_parse_bool, 0, &arg_show_status },
- { "Manager", "CrashChVT", config_parse_int, 0, &arg_crash_chvt },
- { "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, NULL },
- { "Manager", "DefaultControllers", config_parse_strv, 0, &arg_default_controllers },
- { "Manager", "DefaultStandardOutput", config_parse_output, 0, &arg_default_std_output },
- { "Manager", "DefaultStandardError", config_parse_output, 0, &arg_default_std_error },
- { "Manager", "JoinControllers", config_parse_join_controllers, 0, &arg_join_controllers },
- { "Manager", "RuntimeWatchdogSec", config_parse_usec, 0, &arg_runtime_watchdog },
- { "Manager", "ShutdownWatchdogSec", config_parse_usec, 0, &arg_shutdown_watchdog },
- { "Manager", "CapabilityBoundingSet", config_parse_bounding_set, 0, &arg_capability_bounding_set_drop },
- { "Manager", "TimerSlackNSec", config_parse_nsec, 0, &arg_timer_slack_nsec },
- { "Manager", "DefaultLimitCPU", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_CPU]},
- { "Manager", "DefaultLimitFSIZE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_FSIZE]},
- { "Manager", "DefaultLimitDATA", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_DATA]},
- { "Manager", "DefaultLimitSTACK", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_STACK]},
- { "Manager", "DefaultLimitCORE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_CORE]},
- { "Manager", "DefaultLimitRSS", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_RSS]},
- { "Manager", "DefaultLimitNOFILE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_NOFILE]},
- { "Manager", "DefaultLimitAS", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_AS]},
- { "Manager", "DefaultLimitNPROC", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_NPROC]},
- { "Manager", "DefaultLimitMEMLOCK", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_MEMLOCK]},
- { "Manager", "DefaultLimitLOCKS", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_LOCKS]},
- { "Manager", "DefaultLimitSIGPENDING",config_parse_limit, 0, &arg_default_rlimit[RLIMIT_SIGPENDING]},
- { "Manager", "DefaultLimitMSGQUEUE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_MSGQUEUE]},
- { "Manager", "DefaultLimitNICE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_NICE]},
- { "Manager", "DefaultLimitRTPRIO", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_RTPRIO]},
- { "Manager", "DefaultLimitRTTIME", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_RTTIME]},
- { NULL, NULL, NULL, 0, NULL }
- };
-
- FILE *f;
- const char *fn;
- int r;
-
- fn = arg_running_as == SYSTEMD_SYSTEM ? SYSTEM_CONFIG_FILE : USER_CONFIG_FILE;
- f = fopen(fn, "re");
- if (!f) {
- if (errno == ENOENT)
- return 0;
-
- log_warning("Failed to open configuration file '%s': %m", fn);
- return 0;
- }
-
- r = config_parse(fn, f, "Manager\0", config_item_table_lookup, (void*) items, false, NULL);
- if (r < 0)
- log_warning("Failed to parse configuration file: %s", strerror(-r));
-
- fclose(f);
-
- return 0;
-}
-
-static int parse_proc_cmdline(void) {
- char *line, *w, *state;
- int r;
- size_t l;
-
- /* Don't read /proc/cmdline if we are in a container, since
- * that is only relevant for the host system */
- if (detect_container(NULL) > 0)
- return 0;
-
- if ((r = read_one_line_file("/proc/cmdline", &line)) < 0) {
- log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
- return 0;
- }
-
- FOREACH_WORD_QUOTED(w, l, line, state) {
- char *word;
-
- if (!(word = strndup(w, l))) {
- r = -ENOMEM;
- goto finish;
- }
-
- r = parse_proc_cmdline_word(word);
- if (r < 0) {
- log_error("Failed on cmdline argument %s: %s", word, strerror(-r));
- free(word);
- goto finish;
- }
-
- free(word);
- }
-
- r = 0;
-
-finish:
- free(line);
- return r;
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_LOG_LEVEL = 0x100,
- ARG_LOG_TARGET,
- ARG_LOG_COLOR,
- ARG_LOG_LOCATION,
- ARG_UNIT,
- ARG_SYSTEM,
- ARG_USER,
- ARG_TEST,
- ARG_VERSION,
- ARG_DUMP_CONFIGURATION_ITEMS,
- ARG_DUMP_CORE,
- ARG_CRASH_SHELL,
- ARG_CONFIRM_SPAWN,
- ARG_SHOW_STATUS,
- ARG_DESERIALIZE,
- ARG_SWITCHED_ROOT,
- ARG_INTROSPECT,
- ARG_DEFAULT_STD_OUTPUT,
- ARG_DEFAULT_STD_ERROR
- };
-
- static const struct option options[] = {
- { "log-level", required_argument, NULL, ARG_LOG_LEVEL },
- { "log-target", required_argument, NULL, ARG_LOG_TARGET },
- { "log-color", optional_argument, NULL, ARG_LOG_COLOR },
- { "log-location", optional_argument, NULL, ARG_LOG_LOCATION },
- { "unit", required_argument, NULL, ARG_UNIT },
- { "system", no_argument, NULL, ARG_SYSTEM },
- { "user", no_argument, NULL, ARG_USER },
- { "test", no_argument, NULL, ARG_TEST },
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "dump-configuration-items", no_argument, NULL, ARG_DUMP_CONFIGURATION_ITEMS },
- { "dump-core", optional_argument, NULL, ARG_DUMP_CORE },
- { "crash-shell", optional_argument, NULL, ARG_CRASH_SHELL },
- { "confirm-spawn", optional_argument, NULL, ARG_CONFIRM_SPAWN },
- { "show-status", optional_argument, NULL, ARG_SHOW_STATUS },
- { "deserialize", required_argument, NULL, ARG_DESERIALIZE },
- { "switched-root", no_argument, NULL, ARG_SWITCHED_ROOT },
- { "introspect", optional_argument, NULL, ARG_INTROSPECT },
- { "default-standard-output", required_argument, NULL, ARG_DEFAULT_STD_OUTPUT, },
- { "default-standard-error", required_argument, NULL, ARG_DEFAULT_STD_ERROR, },
- { NULL, 0, NULL, 0 }
- };
-
- int c, r;
-
- assert(argc >= 1);
- assert(argv);
-
- if (getpid() == 1)
- opterr = 0;
-
- while ((c = getopt_long(argc, argv, "hDbsz:", options, NULL)) >= 0)
-
- switch (c) {
-
- case ARG_LOG_LEVEL:
- if ((r = log_set_max_level_from_string(optarg)) < 0) {
- log_error("Failed to parse log level %s.", optarg);
- return r;
- }
-
- break;
-
- case ARG_LOG_TARGET:
-
- if ((r = log_set_target_from_string(optarg)) < 0) {
- log_error("Failed to parse log target %s.", optarg);
- return r;
- }
-
- break;
-
- case ARG_LOG_COLOR:
-
- if (optarg) {
- if ((r = log_show_color_from_string(optarg)) < 0) {
- log_error("Failed to parse log color setting %s.", optarg);
- return r;
- }
- } else
- log_show_color(true);
-
- break;
-
- case ARG_LOG_LOCATION:
-
- if (optarg) {
- if ((r = log_show_location_from_string(optarg)) < 0) {
- log_error("Failed to parse log location setting %s.", optarg);
- return r;
- }
- } else
- log_show_location(true);
-
- break;
-
- case ARG_DEFAULT_STD_OUTPUT:
-
- if ((r = exec_output_from_string(optarg)) < 0) {
- log_error("Failed to parse default standard output setting %s.", optarg);
- return r;
- } else
- arg_default_std_output = r;
- break;
-
- case ARG_DEFAULT_STD_ERROR:
-
- if ((r = exec_output_from_string(optarg)) < 0) {
- log_error("Failed to parse default standard error output setting %s.", optarg);
- return r;
- } else
- arg_default_std_error = r;
- break;
-
- case ARG_UNIT:
-
- if ((r = set_default_unit(optarg)) < 0) {
- log_error("Failed to set default unit %s: %s", optarg, strerror(-r));
- return r;
- }
-
- break;
-
- case ARG_SYSTEM:
- arg_running_as = SYSTEMD_SYSTEM;
- break;
-
- case ARG_USER:
- arg_running_as = SYSTEMD_USER;
- break;
-
- case ARG_TEST:
- arg_action = ACTION_TEST;
- break;
-
- case ARG_VERSION:
- arg_action = ACTION_VERSION;
- break;
-
- case ARG_DUMP_CONFIGURATION_ITEMS:
- arg_action = ACTION_DUMP_CONFIGURATION_ITEMS;
- break;
-
- case ARG_DUMP_CORE:
- r = optarg ? parse_boolean(optarg) : 1;
- if (r < 0) {
- log_error("Failed to parse dump core boolean %s.", optarg);
- return r;
- }
- arg_dump_core = r;
- break;
-
- case ARG_CRASH_SHELL:
- r = optarg ? parse_boolean(optarg) : 1;
- if (r < 0) {
- log_error("Failed to parse crash shell boolean %s.", optarg);
- return r;
- }
- arg_crash_shell = r;
- break;
-
- case ARG_CONFIRM_SPAWN:
- r = optarg ? parse_boolean(optarg) : 1;
- if (r < 0) {
- log_error("Failed to parse confirm spawn boolean %s.", optarg);
- return r;
- }
- arg_confirm_spawn = r;
- break;
-
- case ARG_SHOW_STATUS:
- r = optarg ? parse_boolean(optarg) : 1;
- if (r < 0) {
- log_error("Failed to parse show status boolean %s.", optarg);
- return r;
- }
- arg_show_status = r;
- break;
-
- case ARG_DESERIALIZE: {
- int fd;
- FILE *f;
-
- if ((r = safe_atoi(optarg, &fd)) < 0 || fd < 0) {
- log_error("Failed to parse deserialize option %s.", optarg);
- return r;
- }
-
- if (!(f = fdopen(fd, "r"))) {
- log_error("Failed to open serialization fd: %m");
- return r;
- }
-
- if (serialization)
- fclose(serialization);
-
- serialization = f;
-
- break;
- }
-
- case ARG_SWITCHED_ROOT:
- arg_switched_root = true;
- break;
-
- case ARG_INTROSPECT: {
- const char * const * i = NULL;
-
- for (i = bus_interface_table; *i; i += 2)
- if (!optarg || streq(i[0], optarg)) {
- fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
- "<node>\n", stdout);
- fputs(i[1], stdout);
- fputs("</node>\n", stdout);
-
- if (optarg)
- break;
- }
-
- if (!i[0] && optarg)
- log_error("Unknown interface %s.", optarg);
-
- arg_action = ACTION_DONE;
- break;
- }
-
- case 'h':
- arg_action = ACTION_HELP;
- break;
-
- case 'D':
- log_set_max_level(LOG_DEBUG);
- break;
-
- case 'b':
- case 's':
- case 'z':
- /* Just to eat away the sysvinit kernel
- * cmdline args without getopt() error
- * messages that we'll parse in
- * parse_proc_cmdline_word() or ignore. */
-
- case '?':
- default:
- if (getpid() != 1) {
- log_error("Unknown option code %c", c);
- return -EINVAL;
- }
-
- break;
- }
-
- if (optind < argc && getpid() != 1) {
- /* Hmm, when we aren't run as init system
- * let's complain about excess arguments */
-
- log_error("Excess arguments.");
- return -EINVAL;
- }
-
- if (detect_container(NULL) > 0) {
- char **a;
-
- /* All /proc/cmdline arguments the kernel didn't
- * understand it passed to us. We're not really
- * interested in that usually since /proc/cmdline is
- * more interesting and complete. With one exception:
- * if we are run in a container /proc/cmdline is not
- * relevant for the container, hence we rely on argv[]
- * instead. */
-
- for (a = argv; a < argv + argc; a++)
- if ((r = parse_proc_cmdline_word(*a)) < 0) {
- log_error("Failed on cmdline argument %s: %s", *a, strerror(-r));
- return r;
- }
- }
-
- return 0;
-}
-
-static int help(void) {
-
- printf("%s [OPTIONS...]\n\n"
- "Starts up and maintains the system or user services.\n\n"
- " -h --help Show this help\n"
- " --test Determine startup sequence, dump it and exit\n"
- " --dump-configuration-items Dump understood unit configuration items\n"
- " --introspect[=INTERFACE] Extract D-Bus interface data\n"
- " --unit=UNIT Set default unit\n"
- " --system Run a system instance, even if PID != 1\n"
- " --user Run a user instance\n"
- " --dump-core[=0|1] Dump core on crash\n"
- " --crash-shell[=0|1] Run shell on crash\n"
- " --confirm-spawn[=0|1] Ask for confirmation when spawning processes\n"
- " --show-status[=0|1] Show status updates on the console during bootup\n"
- " --log-target=TARGET Set log target (console, journal, syslog, kmsg, journal-or-kmsg, syslog-or-kmsg, null)\n"
- " --log-level=LEVEL Set log level (debug, info, notice, warning, err, crit, alert, emerg)\n"
- " --log-color[=0|1] Highlight important log messages\n"
- " --log-location[=0|1] Include code location in log messages\n"
- " --default-standard-output= Set default standard output for services\n"
- " --default-standard-error= Set default standard error output for services\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static int version(void) {
- puts(PACKAGE_STRING);
- puts(DISTRIBUTION);
- puts(SYSTEMD_FEATURES);
-
- return 0;
-}
-
-static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool serialize_jobs) {
- FILE *f = NULL;
- FDSet *fds = NULL;
- int r;
-
- assert(m);
- assert(_f);
- assert(_fds);
-
- /* Make sure nothing is really destructed when we shut down */
- m->n_reloading ++;
-
- r = manager_open_serialization(m, &f);
- if (r < 0) {
- log_error("Failed to create serialization file: %s", strerror(-r));
- goto fail;
- }
-
- fds = fdset_new();
- if (!fds) {
- r = -ENOMEM;
- log_error("Failed to allocate fd set: %s", strerror(-r));
- goto fail;
- }
-
- r = manager_serialize(m, f, fds, serialize_jobs);
- if (r < 0) {
- log_error("Failed to serialize state: %s", strerror(-r));
- goto fail;
- }
-
- if (fseeko(f, 0, SEEK_SET) < 0) {
- log_error("Failed to rewind serialization fd: %m");
- goto fail;
- }
-
- r = fd_cloexec(fileno(f), false);
- if (r < 0) {
- log_error("Failed to disable O_CLOEXEC for serialization: %s", strerror(-r));
- goto fail;
- }
-
- r = fdset_cloexec(fds, false);
- if (r < 0) {
- log_error("Failed to disable O_CLOEXEC for serialization fds: %s", strerror(-r));
- goto fail;
- }
-
- *_f = f;
- *_fds = fds;
-
- return 0;
-
-fail:
- fdset_free(fds);
-
- if (f)
- fclose(f);
-
- return r;
-}
-
-static int bump_rlimit_nofile(struct rlimit *saved_rlimit) {
- struct rlimit nl;
- int r;
-
- assert(saved_rlimit);
-
- /* Save the original RLIMIT_NOFILE so that we can reset it
- * later when transitioning from the initrd to the main
- * systemd or suchlike. */
- if (getrlimit(RLIMIT_NOFILE, saved_rlimit) < 0) {
- log_error("Reading RLIMIT_NOFILE failed: %m");
- return -errno;
- }
-
- /* Make sure forked processes get the default kernel setting */
- if (!arg_default_rlimit[RLIMIT_NOFILE]) {
- struct rlimit *rl;
-
- rl = newdup(struct rlimit, saved_rlimit, 1);
- if (!rl)
- return log_oom();
-
- arg_default_rlimit[RLIMIT_NOFILE] = rl;
- }
-
- /* Bump up the resource limit for ourselves substantially */
- nl.rlim_cur = nl.rlim_max = 64*1024;
- r = setrlimit_closest(RLIMIT_NOFILE, &nl);
- if (r < 0) {
- log_error("Setting RLIMIT_NOFILE failed: %s", strerror(-r));
- return r;
- }
-
- return 0;
-}
-
-static struct dual_timestamp* parse_initrd_timestamp(struct dual_timestamp *t) {
- const char *e;
- unsigned long long a, b;
-
- assert(t);
-
- e = getenv("RD_TIMESTAMP");
- if (!e)
- return NULL;
-
- if (sscanf(e, "%llu %llu", &a, &b) != 2)
- return NULL;
-
- t->realtime = (usec_t) a;
- t->monotonic = (usec_t) b;
-
- return t;
-}
-
-static void test_mtab(void) {
- char *p;
-
- /* Check that /etc/mtab is a symlink */
-
- if (readlink_malloc("/etc/mtab", &p) >= 0) {
- bool b;
-
- b = streq(p, "/proc/self/mounts") || streq(p, "/proc/mounts");
- free(p);
-
- if (b)
- return;
- }
-
- log_warning("/etc/mtab is not a symlink or not pointing to /proc/self/mounts. "
- "This is not supported anymore. "
- "Please make sure to replace this file by a symlink to avoid incorrect or misleading mount(8) output.");
-}
-
-static void test_usr(void) {
-
- /* Check that /usr is not a separate fs */
-
- if (dir_is_empty("/usr") <= 0)
- return;
-
- log_warning("/usr appears to be on its own filesytem and is not already mounted. This is not a supported setup. "
- "Some things will probably break (sometimes even silently) in mysterious ways. "
- "Consult http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken for more information.");
-}
-
-static void test_cgroups(void) {
-
- if (access("/proc/cgroups", F_OK) >= 0)
- return;
-
- log_warning("CONFIG_CGROUPS was not set when your kernel was compiled. "
- "Systems without control groups are not supported. "
- "We will now sleep for 10s, and then continue boot-up. "
- "Expect breakage and please do not file bugs. "
- "Instead fix your kernel and enable CONFIG_CGROUPS. "
- "Consult http://0pointer.de/blog/projects/cgroups-vs-cgroups.html for more information.");
-
- sleep(10);
-}
-
-static int initialize_join_controllers(void) {
- /* By default, mount "cpu" + "cpuacct" together, and "net_cls"
- * + "net_prio". We'd like to add "cpuset" to the mix, but
- * "cpuset" does't really work for groups with no initialized
- * attributes. */
-
- arg_join_controllers = new(char**, 3);
- if (!arg_join_controllers)
- return -ENOMEM;
-
- arg_join_controllers[0] = strv_new("cpu", "cpuacct", NULL);
- if (!arg_join_controllers[0])
- return -ENOMEM;
-
- arg_join_controllers[1] = strv_new("net_cls", "net_prio", NULL);
- if (!arg_join_controllers[1])
- return -ENOMEM;
-
- arg_join_controllers[2] = NULL;
- return 0;
-}
-
-int main(int argc, char *argv[]) {
- Manager *m = NULL;
- int r, retval = EXIT_FAILURE;
- usec_t before_startup, after_startup;
- char timespan[FORMAT_TIMESPAN_MAX];
- FDSet *fds = NULL;
- bool reexecute = false;
- const char *shutdown_verb = NULL;
- dual_timestamp initrd_timestamp = { 0ULL, 0ULL };
- static char systemd[] = "systemd";
- bool skip_setup = false;
- int j;
- bool loaded_policy = false;
- bool arm_reboot_watchdog = false;
- bool queue_default_job = false;
- char *switch_root_dir = NULL, *switch_root_init = NULL;
- static struct rlimit saved_rlimit_nofile = { 0, 0 };
-
-#ifdef HAVE_SYSV_COMPAT
- if (getpid() != 1 && strstr(program_invocation_short_name, "init")) {
- /* This is compatibility support for SysV, where
- * calling init as a user is identical to telinit. */
-
- errno = -ENOENT;
- execv(SYSTEMCTL_BINARY_PATH, argv);
- log_error("Failed to exec " SYSTEMCTL_BINARY_PATH ": %m");
- return 1;
- }
-#endif
-
- /* Determine if this is a reexecution or normal bootup. We do
- * the full command line parsing much later, so let's just
- * have a quick peek here. */
- for (j = 1; j < argc; j++)
- if (streq(argv[j], "--deserialize")) {
- skip_setup = true;
- break;
- }
-
- /* If we have switched root, do all the special setup
- * things */
- for (j = 1; j < argc; j++)
- if (streq(argv[j], "--switched-root")) {
- skip_setup = false;
- break;
- }
-
- /* If we get started via the /sbin/init symlink then we are
- called 'init'. After a subsequent reexecution we are then
- called 'systemd'. That is confusing, hence let's call us
- systemd right-away. */
- program_invocation_short_name = systemd;
- prctl(PR_SET_NAME, systemd);
-
- saved_argv = argv;
- saved_argc = argc;
-
- log_show_color(isatty(STDERR_FILENO) > 0);
-
- if (getpid() == 1 && detect_container(NULL) <= 0) {
-
- /* Running outside of a container as PID 1 */
- arg_running_as = SYSTEMD_SYSTEM;
- make_null_stdio();
- log_set_target(LOG_TARGET_KMSG);
- log_open();
-
- if (in_initrd()) {
- char *rd_timestamp = NULL;
-
- dual_timestamp_get(&initrd_timestamp);
- asprintf(&rd_timestamp, "%llu %llu",
- (unsigned long long) initrd_timestamp.realtime,
- (unsigned long long) initrd_timestamp.monotonic);
- if (rd_timestamp) {
- setenv("RD_TIMESTAMP", rd_timestamp, 1);
- free(rd_timestamp);
- }
- }
-
- if (!skip_setup) {
- if (selinux_setup(&loaded_policy) < 0)
- goto finish;
- if (ima_setup() < 0)
- goto finish;
- }
-
- if (label_init(NULL) < 0)
- goto finish;
-
- if (!skip_setup) {
- if (hwclock_is_localtime() > 0) {
- int min;
-
- /* The first-time call to settimeofday() does a time warp in the kernel */
- r = hwclock_set_timezone(&min);
- if (r < 0)
- log_error("Failed to apply local time delta, ignoring: %s", strerror(-r));
- else
- log_info("RTC configured in localtime, applying delta of %i minutes to system time.", min);
- } else if (!in_initrd()) {
- /*
- * Do dummy first-time call to seal the kernel's time warp magic
- *
- * Do not call this this from inside the initrd. The initrd might not
- * carry /etc/adjtime with LOCAL, but the real system could be set up
- * that way. In such case, we need to delay the time-warp or the sealing
- * until we reach the real system.
- */
- hwclock_reset_timezone();
-
- /* Tell the kernel our time zone */
- r = hwclock_set_timezone(NULL);
- if (r < 0)
- log_error("Failed to set the kernel's time zone, ignoring: %s", strerror(-r));
- }
- }
-
- /* Set the default for later on, but don't actually
- * open the logs like this for now. Note that if we
- * are transitioning from the initrd there might still
- * be journal fd open, and we shouldn't attempt
- * opening that before we parsed /proc/cmdline which
- * might redirect output elsewhere. */
- log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
-
- } else if (getpid() == 1) {
-
- /* Running inside a container, as PID 1 */
- arg_running_as = SYSTEMD_SYSTEM;
- log_set_target(LOG_TARGET_CONSOLE);
- log_open();
-
- /* For the later on, see above... */
- log_set_target(LOG_TARGET_JOURNAL);
-
- } else {
-
- /* Running as user instance */
- arg_running_as = SYSTEMD_USER;
- log_set_target(LOG_TARGET_AUTO);
- log_open();
- }
-
- /* Initialize default unit */
- r = set_default_unit(SPECIAL_DEFAULT_TARGET);
- if (r < 0) {
- log_error("Failed to set default unit %s: %s", SPECIAL_DEFAULT_TARGET, strerror(-r));
- goto finish;
- }
-
- r = initialize_join_controllers();
- if (r < 0)
- goto finish;
-
- /* Mount /proc, /sys and friends, so that /proc/cmdline and
- * /proc/$PID/fd is available. */
- if (geteuid() == 0 && !getenv("SYSTEMD_SKIP_API_MOUNTS")) {
- r = mount_setup(loaded_policy);
- if (r < 0)
- goto finish;
- }
-
- /* Reset all signal handlers. */
- assert_se(reset_all_signal_handlers() == 0);
-
- /* If we are init, we can block sigkill. Yay. */
- ignore_signals(SIGNALS_IGNORE, -1);
-
- if (parse_config_file() < 0)
- goto finish;
-
- if (arg_running_as == SYSTEMD_SYSTEM)
- if (parse_proc_cmdline() < 0)
- goto finish;
-
- log_parse_environment();
-
- if (parse_argv(argc, argv) < 0)
- goto finish;
-
- if (arg_action == ACTION_TEST &&
- geteuid() == 0) {
- log_error("Don't run test mode as root.");
- goto finish;
- }
-
- if (arg_running_as == SYSTEMD_USER &&
- arg_action == ACTION_RUN &&
- sd_booted() <= 0) {
- log_error("Trying to run as user instance, but the system has not been booted with systemd.");
- goto finish;
- }
-
- if (arg_running_as == SYSTEMD_SYSTEM &&
- arg_action == ACTION_RUN &&
- running_in_chroot() > 0) {
- log_error("Cannot be run in a chroot() environment.");
- goto finish;
- }
-
- if (arg_action == ACTION_HELP) {
- retval = help();
- goto finish;
- } else if (arg_action == ACTION_VERSION) {
- retval = version();
- goto finish;
- } else if (arg_action == ACTION_DUMP_CONFIGURATION_ITEMS) {
- unit_dump_config_items(stdout);
- retval = EXIT_SUCCESS;
- goto finish;
- } else if (arg_action == ACTION_DONE) {
- retval = EXIT_SUCCESS;
- goto finish;
- }
-
- assert_se(arg_action == ACTION_RUN || arg_action == ACTION_TEST);
-
- /* Close logging fds, in order not to confuse fdset below */
- log_close();
-
- /* Remember open file descriptors for later deserialization */
- if (serialization) {
- r = fdset_new_fill(&fds);
- if (r < 0) {
- log_error("Failed to allocate fd set: %s", strerror(-r));
- goto finish;
- }
-
- assert_se(fdset_remove(fds, fileno(serialization)) >= 0);
- } else
- close_all_fds(NULL, 0);
-
- /* Set up PATH unless it is already set */
- setenv("PATH",
-#ifdef HAVE_SPLIT_USR
- "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
-#else
- "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin",
-#endif
- arg_running_as == SYSTEMD_SYSTEM);
-
- if (arg_running_as == SYSTEMD_SYSTEM) {
- /* Parse the data passed to us. We leave this
- * variables set, but the manager later on will not
- * pass them on to our children. */
- if (!in_initrd())
- parse_initrd_timestamp(&initrd_timestamp);
-
- /* Unset some environment variables passed in from the
- * kernel that don't really make sense for us. */
- unsetenv("HOME");
- unsetenv("TERM");
-
- /* When we are invoked by a shell, these might be set,
- * but make little sense to pass on */
- unsetenv("PWD");
- unsetenv("SHLVL");
- unsetenv("_");
-
- /* When we are invoked by a chroot-like tool such as
- * nspawn, these might be set, but make little sense
- * to pass on */
- unsetenv("USER");
- unsetenv("LOGNAME");
-
- /* All other variables are left as is, so that clients
- * can still read them via /proc/1/environ */
- }
-
- /* Move out of the way, so that we won't block unmounts */
- assert_se(chdir("/") == 0);
-
- if (arg_running_as == SYSTEMD_SYSTEM) {
- /* Become a session leader if we aren't one yet. */
- setsid();
-
- /* Disable the umask logic */
- umask(0);
- }
-
- /* Make sure D-Bus doesn't fiddle with the SIGPIPE handlers */
- dbus_connection_set_change_sigpipe(FALSE);
-
- /* Reset the console, but only if this is really init and we
- * are freshly booted */
- if (arg_running_as == SYSTEMD_SYSTEM && arg_action == ACTION_RUN)
- console_setup(getpid() == 1 && !skip_setup);
-
- /* Open the logging devices, if possible and necessary */
- log_open();
-
- /* Make sure we leave a core dump without panicing the
- * kernel. */
- if (getpid() == 1)
- install_crash_handler();
-
- if (geteuid() == 0 && !getenv("SYSTEMD_SKIP_API_MOUNTS")) {
- r = mount_cgroup_controllers(arg_join_controllers);
- if (r < 0)
- goto finish;
- }
-
- if (arg_running_as == SYSTEMD_SYSTEM) {
- const char *virtualization = NULL;
-
- log_info(PACKAGE_STRING " running in system mode. (" SYSTEMD_FEATURES "; " DISTRIBUTION ")");
-
- detect_virtualization(&virtualization);
- if (virtualization)
- log_info("Detected virtualization '%s'.", virtualization);
-
- if (in_initrd())
- log_info("Running in initial RAM disk.");
-
- } else
- log_debug(PACKAGE_STRING " running in user mode. (" SYSTEMD_FEATURES "; " DISTRIBUTION ")");
-
- if (arg_running_as == SYSTEMD_SYSTEM && !skip_setup) {
- locale_setup();
-
- if (arg_show_status || plymouth_running())
- status_welcome();
-
- kmod_setup();
- hostname_setup();
- machine_id_setup();
- loopback_setup();
-
- test_mtab();
- test_usr();
- test_cgroups();
- }
-
- if (arg_running_as == SYSTEMD_SYSTEM && arg_runtime_watchdog > 0)
- watchdog_set_timeout(&arg_runtime_watchdog);
-
- if (arg_timer_slack_nsec != (nsec_t) -1)
- if (prctl(PR_SET_TIMERSLACK, arg_timer_slack_nsec) < 0)
- log_error("Failed to adjust timer slack: %m");
-
- if (arg_capability_bounding_set_drop) {
- r = capability_bounding_set_drop(arg_capability_bounding_set_drop, true);
- if (r < 0) {
- log_error("Failed to drop capability bounding set: %s", strerror(-r));
- goto finish;
- }
- r = capability_bounding_set_drop_usermode(arg_capability_bounding_set_drop);
- if (r < 0) {
- log_error("Failed to drop capability bounding set of usermode helpers: %s", strerror(-r));
- goto finish;
- }
- }
-
- if (arg_running_as == SYSTEMD_USER) {
- /* Become reaper of our children */
- if (prctl(PR_SET_CHILD_SUBREAPER, 1) < 0) {
- log_warning("Failed to make us a subreaper: %m");
- if (errno == EINVAL)
- log_info("Perhaps the kernel version is too old (< 3.4?)");
- }
- }
-
- if (arg_running_as == SYSTEMD_SYSTEM)
- bump_rlimit_nofile(&saved_rlimit_nofile);
-
- r = manager_new(arg_running_as, &m);
- if (r < 0) {
- log_error("Failed to allocate manager object: %s", strerror(-r));
- goto finish;
- }
-
- m->confirm_spawn = arg_confirm_spawn;
- m->default_std_output = arg_default_std_output;
- m->default_std_error = arg_default_std_error;
- m->runtime_watchdog = arg_runtime_watchdog;
- m->shutdown_watchdog = arg_shutdown_watchdog;
-
- manager_set_default_rlimits(m, arg_default_rlimit);
-
- if (dual_timestamp_is_set(&initrd_timestamp))
- m->initrd_timestamp = initrd_timestamp;
-
- if (arg_default_controllers)
- manager_set_default_controllers(m, arg_default_controllers);
-
- manager_set_show_status(m, arg_show_status);
-
- /* Remember whether we should queue the default job */
- queue_default_job = !serialization || arg_switched_root;
-
- before_startup = now(CLOCK_MONOTONIC);
-
- r = manager_startup(m, serialization, fds);
- if (r < 0)
- log_error("Failed to fully start up daemon: %s", strerror(-r));
-
- /* This will close all file descriptors that were opened, but
- * not claimed by any unit. */
- if (fds) {
- fdset_free(fds);
- fds = NULL;
- }
-
- if (serialization) {
- fclose(serialization);
- serialization = NULL;
- }
-
- if (queue_default_job) {
- DBusError error;
- Unit *target = NULL;
- Job *default_unit_job;
-
- dbus_error_init(&error);
-
- log_debug("Activating default unit: %s", arg_default_unit);
-
- r = manager_load_unit(m, arg_default_unit, NULL, &error, &target);
- if (r < 0) {
- log_error("Failed to load default target: %s", bus_error(&error, r));
- dbus_error_free(&error);
- } else if (target->load_state == UNIT_ERROR)
- log_error("Failed to load default target: %s", strerror(-target->load_error));
- else if (target->load_state == UNIT_MASKED)
- log_error("Default target masked.");
-
- if (!target || target->load_state != UNIT_LOADED) {
- log_info("Trying to load rescue target...");
-
- r = manager_load_unit(m, SPECIAL_RESCUE_TARGET, NULL, &error, &target);
- if (r < 0) {
- log_error("Failed to load rescue target: %s", bus_error(&error, r));
- dbus_error_free(&error);
- goto finish;
- } else if (target->load_state == UNIT_ERROR) {
- log_error("Failed to load rescue target: %s", strerror(-target->load_error));
- goto finish;
- } else if (target->load_state == UNIT_MASKED) {
- log_error("Rescue target masked.");
- goto finish;
- }
- }
-
- assert(target->load_state == UNIT_LOADED);
-
- if (arg_action == ACTION_TEST) {
- printf("-> By units:\n");
- manager_dump_units(m, stdout, "\t");
- }
-
- r = manager_add_job(m, JOB_START, target, JOB_REPLACE, false, &error, &default_unit_job);
- if (r < 0) {
- log_error("Failed to start default target: %s", bus_error(&error, r));
- dbus_error_free(&error);
- goto finish;
- }
- m->default_unit_job_id = default_unit_job->id;
-
- after_startup = now(CLOCK_MONOTONIC);
- log_full(arg_action == ACTION_TEST ? LOG_INFO : LOG_DEBUG,
- "Loaded units and determined initial transaction in %s.",
- format_timespan(timespan, sizeof(timespan), after_startup - before_startup));
-
- if (arg_action == ACTION_TEST) {
- printf("-> By jobs:\n");
- manager_dump_jobs(m, stdout, "\t");
- retval = EXIT_SUCCESS;
- goto finish;
- }
- }
-
- for (;;) {
- r = manager_loop(m);
- if (r < 0) {
- log_error("Failed to run mainloop: %s", strerror(-r));
- goto finish;
- }
-
- switch (m->exit_code) {
-
- case MANAGER_EXIT:
- retval = EXIT_SUCCESS;
- log_debug("Exit.");
- goto finish;
-
- case MANAGER_RELOAD:
- log_info("Reloading.");
- r = manager_reload(m);
- if (r < 0)
- log_error("Failed to reload: %s", strerror(-r));
- break;
-
- case MANAGER_REEXECUTE:
-
- if (prepare_reexecute(m, &serialization, &fds, true) < 0)
- goto finish;
-
- reexecute = true;
- log_notice("Reexecuting.");
- goto finish;
-
- case MANAGER_SWITCH_ROOT:
- /* Steal the switch root parameters */
- switch_root_dir = m->switch_root;
- switch_root_init = m->switch_root_init;
- m->switch_root = m->switch_root_init = NULL;
-
- if (!switch_root_init)
- if (prepare_reexecute(m, &serialization, &fds, false) < 0)
- goto finish;
-
- reexecute = true;
- log_notice("Switching root.");
- goto finish;
-
- case MANAGER_REBOOT:
- case MANAGER_POWEROFF:
- case MANAGER_HALT:
- case MANAGER_KEXEC: {
- static const char * const table[_MANAGER_EXIT_CODE_MAX] = {
- [MANAGER_REBOOT] = "reboot",
- [MANAGER_POWEROFF] = "poweroff",
- [MANAGER_HALT] = "halt",
- [MANAGER_KEXEC] = "kexec"
- };
-
- assert_se(shutdown_verb = table[m->exit_code]);
- arm_reboot_watchdog = m->exit_code == MANAGER_REBOOT;
-
- log_notice("Shutting down.");
- goto finish;
- }
-
- default:
- assert_not_reached("Unknown exit code.");
- }
- }
-
-finish:
- if (m)
- manager_free(m);
-
- for (j = 0; j < RLIMIT_NLIMITS; j++)
- free(arg_default_rlimit[j]);
-
- free(arg_default_unit);
- strv_free(arg_default_controllers);
- free_join_controllers();
-
- dbus_shutdown();
- label_finish();
-
- if (reexecute) {
- const char **args;
- unsigned i, args_size;
-
- /* Close and disarm the watchdog, so that the new
- * instance can reinitialize it, but doesn't get
- * rebooted while we do that */
- watchdog_close(true);
-
- /* Reset the RLIMIT_NOFILE to the kernel default, so
- * that the new systemd can pass the kernel default to
- * its child processes */
- if (saved_rlimit_nofile.rlim_cur > 0)
- setrlimit(RLIMIT_NOFILE, &saved_rlimit_nofile);
-
- if (switch_root_dir) {
- /* Kill all remaining processes from the
- * initrd, but don't wait for them, so that we
- * can handle the SIGCHLD for them after
- * deserializing. */
- broadcast_signal(SIGTERM, false);
-
- /* And switch root */
- r = switch_root(switch_root_dir);
- if (r < 0)
- log_error("Failed to switch root, ignoring: %s", strerror(-r));
- }
-
- args_size = MAX(6, argc+1);
- args = newa(const char*, args_size);
-
- if (!switch_root_init) {
- char sfd[16];
-
- /* First try to spawn ourselves with the right
- * path, and with full serialization. We do
- * this only if the user didn't specify an
- * explicit init to spawn. */
-
- assert(serialization);
- assert(fds);
-
- snprintf(sfd, sizeof(sfd), "%i", fileno(serialization));
- char_array_0(sfd);
-
- i = 0;
- args[i++] = SYSTEMD_BINARY_PATH;
- if (switch_root_dir)
- args[i++] = "--switched-root";
- args[i++] = arg_running_as == SYSTEMD_SYSTEM ? "--system" : "--user";
- args[i++] = "--deserialize";
- args[i++] = sfd;
- args[i++] = NULL;
-
- assert(i <= args_size);
- execv(args[0], (char* const*) args);
- }
-
- /* Try the fallback, if there is any, without any
- * serialization. We pass the original argv[] and
- * envp[]. (Well, modulo the ordering changes due to
- * getopt() in argv[], and some cleanups in envp[],
- * but let's hope that doesn't matter.) */
-
- if (serialization) {
- fclose(serialization);
- serialization = NULL;
- }
-
- if (fds) {
- fdset_free(fds);
- fds = NULL;
- }
-
- /* Reopen the console */
- make_console_stdio();
-
- for (j = 1, i = 1; j < argc; j++)
- args[i++] = argv[j];
- args[i++] = NULL;
- assert(i <= args_size);
-
- if (switch_root_init) {
- args[0] = switch_root_init;
- execv(args[0], (char* const*) args);
- log_warning("Failed to execute configured init, trying fallback: %m");
- }
-
- args[0] = "/sbin/init";
- execv(args[0], (char* const*) args);
-
- if (errno == ENOENT) {
- log_warning("No /sbin/init, trying fallback");
-
- args[0] = "/bin/sh";
- args[1] = NULL;
- execv(args[0], (char* const*) args);
- log_error("Failed to execute /bin/sh, giving up: %m");
- } else
- log_warning("Failed to execute /sbin/init, giving up: %m");
- }
-
- if (serialization)
- fclose(serialization);
-
- if (fds)
- fdset_free(fds);
-
- if (shutdown_verb) {
- const char * command_line[] = {
- SYSTEMD_SHUTDOWN_BINARY_PATH,
- shutdown_verb,
- NULL
- };
- char **env_block;
-
- if (arm_reboot_watchdog && arg_shutdown_watchdog > 0) {
- char e[32];
-
- /* If we reboot let's set the shutdown
- * watchdog and tell the shutdown binary to
- * repeatedly ping it */
- watchdog_set_timeout(&arg_shutdown_watchdog);
- watchdog_close(false);
-
- /* Tell the binary how often to ping */
- snprintf(e, sizeof(e), "WATCHDOG_USEC=%llu", (unsigned long long) arg_shutdown_watchdog);
- char_array_0(e);
-
- env_block = strv_append(environ, e);
- } else {
- env_block = strv_copy(environ);
- watchdog_close(true);
- }
-
- execve(SYSTEMD_SHUTDOWN_BINARY_PATH, (char **) command_line, env_block);
- free(env_block);
- log_error("Failed to execute shutdown binary, freezing: %m");
- }
-
- if (getpid() == 1)
- freeze();
-
- return retval;
-}
diff --git a/src/core/manager.c b/src/core/manager.c
deleted file mode 100644
index f932c79a1b..0000000000
--- a/src/core/manager.c
+++ /dev/null
@@ -1,2309 +0,0 @@
-/*-*- 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 <assert.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/epoll.h>
-#include <signal.h>
-#include <sys/signalfd.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <sys/poll.h>
-#include <sys/reboot.h>
-#include <sys/ioctl.h>
-#include <linux/kd.h>
-#include <termios.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <dirent.h>
-
-#ifdef HAVE_AUDIT
-#include <libaudit.h>
-#endif
-
-#include "systemd/sd-daemon.h"
-#include "systemd/sd-id128.h"
-#include "systemd/sd-messages.h"
-
-#include "manager.h"
-#include "transaction.h"
-#include "hashmap.h"
-#include "macro.h"
-#include "strv.h"
-#include "log.h"
-#include "util.h"
-#include "mkdir.h"
-#include "ratelimit.h"
-#include "cgroup.h"
-#include "mount-setup.h"
-#include "unit-name.h"
-#include "dbus-unit.h"
-#include "dbus-job.h"
-#include "missing.h"
-#include "path-lookup.h"
-#include "special.h"
-#include "bus-errors.h"
-#include "exit-status.h"
-#include "virt.h"
-#include "watchdog.h"
-#include "cgroup-util.h"
-#include "path-util.h"
-#include "audit-fd.h"
-
-/* As soon as 16 units are in our GC queue, make sure to run a gc sweep */
-#define GC_QUEUE_ENTRIES_MAX 16
-
-/* As soon as 5s passed since a unit was added to our GC queue, make sure to run a gc sweep */
-#define GC_QUEUE_USEC_MAX (10*USEC_PER_SEC)
-
-/* Where clients shall send notification messages to */
-#define NOTIFY_SOCKET "@/org/freedesktop/systemd1/notify"
-
-static int manager_setup_notify(Manager *m) {
- union {
- struct sockaddr sa;
- struct sockaddr_un un;
- } sa;
- struct epoll_event ev;
- int one = 1;
-
- assert(m);
-
- m->notify_watch.type = WATCH_NOTIFY;
- m->notify_watch.fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (m->notify_watch.fd < 0) {
- log_error("Failed to allocate notification socket: %m");
- return -errno;
- }
-
- zero(sa);
- sa.sa.sa_family = AF_UNIX;
-
- if (getpid() != 1 || detect_container(NULL) > 0)
- snprintf(sa.un.sun_path, sizeof(sa.un.sun_path), NOTIFY_SOCKET "/%llu", random_ull());
- else
- strncpy(sa.un.sun_path, NOTIFY_SOCKET, sizeof(sa.un.sun_path));
-
- sa.un.sun_path[0] = 0;
-
- if (bind(m->notify_watch.fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) {
- log_error("bind() failed: %m");
- return -errno;
- }
-
- if (setsockopt(m->notify_watch.fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) {
- log_error("SO_PASSCRED failed: %m");
- return -errno;
- }
-
- zero(ev);
- ev.events = EPOLLIN;
- ev.data.ptr = &m->notify_watch;
-
- if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->notify_watch.fd, &ev) < 0)
- return -errno;
-
- sa.un.sun_path[0] = '@';
- m->notify_socket = strdup(sa.un.sun_path);
- if (!m->notify_socket)
- return -ENOMEM;
-
- log_debug("Using notification socket %s", m->notify_socket);
-
- return 0;
-}
-
-static int enable_special_signals(Manager *m) {
- int fd;
-
- assert(m);
-
- /* Enable that we get SIGINT on control-alt-del. In containers
- * this will fail with EPERM (older) or EINVAL (newer), so
- * ignore that. */
- if (reboot(RB_DISABLE_CAD) < 0 && errno != EPERM && errno != EINVAL)
- log_warning("Failed to enable ctrl-alt-del handling: %m");
-
- fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0) {
- /* Support systems without virtual console */
- if (fd != -ENOENT)
- log_warning("Failed to open /dev/tty0: %m");
- } else {
- /* Enable that we get SIGWINCH on kbrequest */
- if (ioctl(fd, KDSIGACCEPT, SIGWINCH) < 0)
- log_warning("Failed to enable kbrequest handling: %s", strerror(errno));
-
- close_nointr_nofail(fd);
- }
-
- return 0;
-}
-
-static int manager_setup_signals(Manager *m) {
- sigset_t mask;
- struct epoll_event ev;
- struct sigaction sa;
-
- assert(m);
-
- /* We are not interested in SIGSTOP and friends. */
- zero(sa);
- sa.sa_handler = SIG_DFL;
- sa.sa_flags = SA_NOCLDSTOP|SA_RESTART;
- assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
-
- assert_se(sigemptyset(&mask) == 0);
-
- sigset_add_many(&mask,
- SIGCHLD, /* Child died */
- SIGTERM, /* Reexecute daemon */
- SIGHUP, /* Reload configuration */
- SIGUSR1, /* systemd/upstart: reconnect to D-Bus */
- SIGUSR2, /* systemd: dump status */
- SIGINT, /* Kernel sends us this on control-alt-del */
- SIGWINCH, /* Kernel sends us this on kbrequest (alt-arrowup) */
- SIGPWR, /* Some kernel drivers and upsd send us this on power failure */
- SIGRTMIN+0, /* systemd: start default.target */
- SIGRTMIN+1, /* systemd: isolate rescue.target */
- SIGRTMIN+2, /* systemd: isolate emergency.target */
- SIGRTMIN+3, /* systemd: start halt.target */
- SIGRTMIN+4, /* systemd: start poweroff.target */
- SIGRTMIN+5, /* systemd: start reboot.target */
- SIGRTMIN+6, /* systemd: start kexec.target */
- SIGRTMIN+13, /* systemd: Immediate halt */
- SIGRTMIN+14, /* systemd: Immediate poweroff */
- SIGRTMIN+15, /* systemd: Immediate reboot */
- SIGRTMIN+16, /* systemd: Immediate kexec */
- SIGRTMIN+20, /* systemd: enable status messages */
- SIGRTMIN+21, /* systemd: disable status messages */
- SIGRTMIN+22, /* systemd: set log level to LOG_DEBUG */
- SIGRTMIN+23, /* systemd: set log level to LOG_INFO */
- SIGRTMIN+24, /* systemd: Immediate exit (--user only) */
- SIGRTMIN+26, /* systemd: set log target to journal-or-kmsg */
- SIGRTMIN+27, /* systemd: set log target to console */
- SIGRTMIN+28, /* systemd: set log target to kmsg */
- SIGRTMIN+29, /* systemd: set log target to syslog-or-kmsg */
- -1);
- assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
-
- m->signal_watch.type = WATCH_SIGNAL;
- if ((m->signal_watch.fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC)) < 0)
- return -errno;
-
- zero(ev);
- ev.events = EPOLLIN;
- ev.data.ptr = &m->signal_watch;
-
- if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->signal_watch.fd, &ev) < 0)
- return -errno;
-
- if (m->running_as == SYSTEMD_SYSTEM)
- return enable_special_signals(m);
-
- return 0;
-}
-
-static void manager_strip_environment(Manager *m) {
- assert(m);
-
- /* Remove variables from the inherited set that are part of
- * the container interface:
- * http://www.freedesktop.org/wiki/Software/systemd/ContainerInterface */
- strv_remove_prefix(m->environment, "container=");
- strv_remove_prefix(m->environment, "container_");
-
- /* Remove variables from the inherited set that are part of
- * the initrd interface:
- * http://www.freedesktop.org/wiki/Software/systemd/InitrdInterface */
- strv_remove_prefix(m->environment, "RD_");
-}
-
-int manager_new(SystemdRunningAs running_as, Manager **_m) {
- Manager *m;
- int r = -ENOMEM;
-
- assert(_m);
- assert(running_as >= 0);
- assert(running_as < _SYSTEMD_RUNNING_AS_MAX);
-
- m = new0(Manager, 1);
- if (!m)
- return -ENOMEM;
-
- dual_timestamp_get(&m->userspace_timestamp);
-
- m->running_as = running_as;
- m->name_data_slot = m->conn_data_slot = m->subscribed_data_slot = -1;
- m->exit_code = _MANAGER_EXIT_CODE_INVALID;
- m->pin_cgroupfs_fd = -1;
- m->idle_pipe[0] = m->idle_pipe[1] = -1;
-
- m->signal_watch.fd = m->mount_watch.fd = m->udev_watch.fd = m->epoll_fd = m->dev_autofs_fd = m->swap_watch.fd = -1;
- m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */
-
- m->environment = strv_copy(environ);
- if (!m->environment)
- goto fail;
-
- manager_strip_environment(m);
-
- if (running_as == SYSTEMD_SYSTEM) {
- m->default_controllers = strv_new("cpu", NULL);
- if (!m->default_controllers)
- goto fail;
- }
-
- if (!(m->units = hashmap_new(string_hash_func, string_compare_func)))
- goto fail;
-
- if (!(m->jobs = hashmap_new(trivial_hash_func, trivial_compare_func)))
- goto fail;
-
- if (!(m->watch_pids = hashmap_new(trivial_hash_func, trivial_compare_func)))
- goto fail;
-
- if (!(m->cgroup_bondings = hashmap_new(string_hash_func, string_compare_func)))
- goto fail;
-
- if (!(m->watch_bus = hashmap_new(string_hash_func, string_compare_func)))
- goto fail;
-
- if ((m->epoll_fd = epoll_create1(EPOLL_CLOEXEC)) < 0)
- goto fail;
-
- if ((r = manager_setup_signals(m)) < 0)
- goto fail;
-
- if ((r = manager_setup_cgroup(m)) < 0)
- goto fail;
-
- if ((r = manager_setup_notify(m)) < 0)
- goto fail;
-
- /* Try to connect to the busses, if possible. */
- if ((r = bus_init(m, running_as != SYSTEMD_SYSTEM)) < 0)
- goto fail;
-
- m->taint_usr = dir_is_empty("/usr") > 0;
-
- *_m = m;
- return 0;
-
-fail:
- manager_free(m);
- return r;
-}
-
-static unsigned manager_dispatch_cleanup_queue(Manager *m) {
- Unit *u;
- unsigned n = 0;
-
- assert(m);
-
- while ((u = m->cleanup_queue)) {
- assert(u->in_cleanup_queue);
-
- unit_free(u);
- n++;
- }
-
- return n;
-}
-
-enum {
- GC_OFFSET_IN_PATH, /* This one is on the path we were traveling */
- GC_OFFSET_UNSURE, /* No clue */
- GC_OFFSET_GOOD, /* We still need this unit */
- GC_OFFSET_BAD, /* We don't need this unit anymore */
- _GC_OFFSET_MAX
-};
-
-static void unit_gc_sweep(Unit *u, unsigned gc_marker) {
- Iterator i;
- Unit *other;
- bool is_bad;
-
- assert(u);
-
- if (u->gc_marker == gc_marker + GC_OFFSET_GOOD ||
- u->gc_marker == gc_marker + GC_OFFSET_BAD ||
- u->gc_marker == gc_marker + GC_OFFSET_IN_PATH)
- return;
-
- if (u->in_cleanup_queue)
- goto bad;
-
- if (unit_check_gc(u))
- goto good;
-
- u->gc_marker = gc_marker + GC_OFFSET_IN_PATH;
-
- is_bad = true;
-
- SET_FOREACH(other, u->dependencies[UNIT_REFERENCED_BY], i) {
- unit_gc_sweep(other, gc_marker);
-
- if (other->gc_marker == gc_marker + GC_OFFSET_GOOD)
- goto good;
-
- if (other->gc_marker != gc_marker + GC_OFFSET_BAD)
- is_bad = false;
- }
-
- if (is_bad)
- goto bad;
-
- /* We were unable to find anything out about this entry, so
- * let's investigate it later */
- u->gc_marker = gc_marker + GC_OFFSET_UNSURE;
- unit_add_to_gc_queue(u);
- return;
-
-bad:
- /* We definitely know that this one is not useful anymore, so
- * let's mark it for deletion */
- u->gc_marker = gc_marker + GC_OFFSET_BAD;
- unit_add_to_cleanup_queue(u);
- return;
-
-good:
- u->gc_marker = gc_marker + GC_OFFSET_GOOD;
-}
-
-static unsigned manager_dispatch_gc_queue(Manager *m) {
- Unit *u;
- unsigned n = 0;
- unsigned gc_marker;
-
- assert(m);
-
- if ((m->n_in_gc_queue < GC_QUEUE_ENTRIES_MAX) &&
- (m->gc_queue_timestamp <= 0 ||
- (m->gc_queue_timestamp + GC_QUEUE_USEC_MAX) > now(CLOCK_MONOTONIC)))
- return 0;
-
- log_debug("Running GC...");
-
- m->gc_marker += _GC_OFFSET_MAX;
- if (m->gc_marker + _GC_OFFSET_MAX <= _GC_OFFSET_MAX)
- m->gc_marker = 1;
-
- gc_marker = m->gc_marker;
-
- while ((u = m->gc_queue)) {
- assert(u->in_gc_queue);
-
- unit_gc_sweep(u, gc_marker);
-
- LIST_REMOVE(Unit, gc_queue, m->gc_queue, u);
- u->in_gc_queue = false;
-
- n++;
-
- if (u->gc_marker == gc_marker + GC_OFFSET_BAD ||
- u->gc_marker == gc_marker + GC_OFFSET_UNSURE) {
- log_debug("Collecting %s", u->id);
- u->gc_marker = gc_marker + GC_OFFSET_BAD;
- unit_add_to_cleanup_queue(u);
- }
- }
-
- m->n_in_gc_queue = 0;
- m->gc_queue_timestamp = 0;
-
- return n;
-}
-
-static void manager_clear_jobs_and_units(Manager *m) {
- Unit *u;
-
- assert(m);
-
- while ((u = hashmap_first(m->units)))
- unit_free(u);
-
- manager_dispatch_cleanup_queue(m);
-
- assert(!m->load_queue);
- assert(!m->run_queue);
- assert(!m->dbus_unit_queue);
- assert(!m->dbus_job_queue);
- assert(!m->cleanup_queue);
- assert(!m->gc_queue);
-
- assert(hashmap_isempty(m->jobs));
- assert(hashmap_isempty(m->units));
-}
-
-void manager_free(Manager *m) {
- UnitType c;
- int i;
-
- assert(m);
-
- manager_clear_jobs_and_units(m);
-
- for (c = 0; c < _UNIT_TYPE_MAX; c++)
- if (unit_vtable[c]->shutdown)
- unit_vtable[c]->shutdown(m);
-
- /* If we reexecute ourselves, we keep the root cgroup
- * around */
- manager_shutdown_cgroup(m, m->exit_code != MANAGER_REEXECUTE);
-
- manager_undo_generators(m);
-
- bus_done(m);
-
- hashmap_free(m->units);
- hashmap_free(m->jobs);
- hashmap_free(m->watch_pids);
- hashmap_free(m->watch_bus);
-
- if (m->epoll_fd >= 0)
- close_nointr_nofail(m->epoll_fd);
- if (m->signal_watch.fd >= 0)
- close_nointr_nofail(m->signal_watch.fd);
- if (m->notify_watch.fd >= 0)
- close_nointr_nofail(m->notify_watch.fd);
-
- free(m->notify_socket);
-
- lookup_paths_free(&m->lookup_paths);
- strv_free(m->environment);
-
- strv_free(m->default_controllers);
-
- hashmap_free(m->cgroup_bondings);
- set_free_free(m->unit_path_cache);
-
- close_pipe(m->idle_pipe);
-
- free(m->switch_root);
- free(m->switch_root_init);
-
- for (i = 0; i < RLIMIT_NLIMITS; i++)
- free(m->rlimit[i]);
-
- free(m);
-}
-
-int manager_enumerate(Manager *m) {
- int r = 0, q;
- UnitType c;
-
- assert(m);
-
- /* Let's ask every type to load all units from disk/kernel
- * that it might know */
- for (c = 0; c < _UNIT_TYPE_MAX; c++)
- if (unit_vtable[c]->enumerate)
- if ((q = unit_vtable[c]->enumerate(m)) < 0)
- r = q;
-
- manager_dispatch_load_queue(m);
- return r;
-}
-
-int manager_coldplug(Manager *m) {
- int r = 0, q;
- Iterator i;
- Unit *u;
- char *k;
-
- assert(m);
-
- /* Then, let's set up their initial state. */
- HASHMAP_FOREACH_KEY(u, k, m->units, i) {
-
- /* ignore aliases */
- if (u->id != k)
- continue;
-
- if ((q = unit_coldplug(u)) < 0)
- r = q;
- }
-
- return r;
-}
-
-static void manager_build_unit_path_cache(Manager *m) {
- char **i;
- DIR *d = NULL;
- int r;
-
- assert(m);
-
- set_free_free(m->unit_path_cache);
-
- if (!(m->unit_path_cache = set_new(string_hash_func, string_compare_func))) {
- log_error("Failed to allocate unit path cache.");
- return;
- }
-
- /* This simply builds a list of files we know exist, so that
- * we don't always have to go to disk */
-
- STRV_FOREACH(i, m->lookup_paths.unit_path) {
- struct dirent *de;
-
- if (!(d = opendir(*i))) {
- log_error("Failed to open directory: %m");
- continue;
- }
-
- while ((de = readdir(d))) {
- char *p;
-
- if (ignore_file(de->d_name))
- continue;
-
- p = strjoin(streq(*i, "/") ? "" : *i, "/", de->d_name, NULL);
- if (!p) {
- r = -ENOMEM;
- goto fail;
- }
-
- if ((r = set_put(m->unit_path_cache, p)) < 0) {
- free(p);
- goto fail;
- }
- }
-
- closedir(d);
- d = NULL;
- }
-
- return;
-
-fail:
- log_error("Failed to build unit path cache: %s", strerror(-r));
-
- set_free_free(m->unit_path_cache);
- m->unit_path_cache = NULL;
-
- if (d)
- closedir(d);
-}
-
-int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
- int r, q;
-
- assert(m);
-
- manager_run_generators(m);
-
- r = lookup_paths_init(
- &m->lookup_paths, m->running_as, true,
- m->generator_unit_path,
- m->generator_unit_path_early,
- m->generator_unit_path_late);
- if (r < 0)
- return r;
-
- manager_build_unit_path_cache(m);
-
- /* If we will deserialize make sure that during enumeration
- * this is already known, so we increase the counter here
- * already */
- if (serialization)
- m->n_reloading ++;
-
- /* First, enumerate what we can from all config files */
- r = manager_enumerate(m);
-
- /* Second, deserialize if there is something to deserialize */
- if (serialization) {
- q = manager_deserialize(m, serialization, fds);
- if (q < 0)
- r = q;
- }
-
- /* Third, fire things up! */
- q = manager_coldplug(m);
- if (q < 0)
- r = q;
-
- if (serialization) {
- assert(m->n_reloading > 0);
- m->n_reloading --;
- }
-
- return r;
-}
-
-int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool override, DBusError *e, Job **_ret) {
- int r;
- Transaction *tr;
-
- assert(m);
- assert(type < _JOB_TYPE_MAX);
- assert(unit);
- assert(mode < _JOB_MODE_MAX);
-
- if (mode == JOB_ISOLATE && type != JOB_START) {
- dbus_set_error(e, BUS_ERROR_INVALID_JOB_MODE, "Isolate is only valid for start.");
- return -EINVAL;
- }
-
- if (mode == JOB_ISOLATE && !unit->allow_isolate) {
- dbus_set_error(e, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated.");
- return -EPERM;
- }
-
- log_debug("Trying to enqueue job %s/%s/%s", unit->id, job_type_to_string(type), job_mode_to_string(mode));
-
- job_type_collapse(&type, unit);
-
- tr = transaction_new();
- if (!tr)
- return -ENOMEM;
-
- r = transaction_add_job_and_dependencies(tr, type, unit, NULL, true, override, false,
- mode == JOB_IGNORE_DEPENDENCIES || mode == JOB_IGNORE_REQUIREMENTS,
- mode == JOB_IGNORE_DEPENDENCIES, e);
- if (r < 0)
- goto tr_abort;
-
- if (mode == JOB_ISOLATE) {
- r = transaction_add_isolate_jobs(tr, m);
- if (r < 0)
- goto tr_abort;
- }
-
- r = transaction_activate(tr, m, mode, e);
- if (r < 0)
- goto tr_abort;
-
- log_debug("Enqueued job %s/%s as %u", unit->id, job_type_to_string(type), (unsigned) tr->anchor_job->id);
-
- if (_ret)
- *_ret = tr->anchor_job;
-
- transaction_free(tr);
- return 0;
-
-tr_abort:
- transaction_abort(tr);
- transaction_free(tr);
- return r;
-}
-
-int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, bool override, DBusError *e, Job **_ret) {
- Unit *unit;
- int r;
-
- assert(m);
- assert(type < _JOB_TYPE_MAX);
- assert(name);
- assert(mode < _JOB_MODE_MAX);
-
- r = manager_load_unit(m, name, NULL, NULL, &unit);
- if (r < 0)
- return r;
-
- return manager_add_job(m, type, unit, mode, override, e, _ret);
-}
-
-Job *manager_get_job(Manager *m, uint32_t id) {
- assert(m);
-
- return hashmap_get(m->jobs, UINT32_TO_PTR(id));
-}
-
-Unit *manager_get_unit(Manager *m, const char *name) {
- assert(m);
- assert(name);
-
- return hashmap_get(m->units, name);
-}
-
-unsigned manager_dispatch_load_queue(Manager *m) {
- Unit *u;
- unsigned n = 0;
-
- assert(m);
-
- /* Make sure we are not run recursively */
- if (m->dispatching_load_queue)
- return 0;
-
- m->dispatching_load_queue = true;
-
- /* Dispatches the load queue. Takes a unit from the queue and
- * tries to load its data until the queue is empty */
-
- while ((u = m->load_queue)) {
- assert(u->in_load_queue);
-
- unit_load(u);
- n++;
- }
-
- m->dispatching_load_queue = false;
- return n;
-}
-
-int manager_load_unit_prepare(Manager *m, const char *name, const char *path, DBusError *e, Unit **_ret) {
- Unit *ret;
- UnitType t;
- int r;
-
- assert(m);
- assert(name || path);
-
- /* This will prepare the unit for loading, but not actually
- * load anything from disk. */
-
- if (path && !is_path(path)) {
- dbus_set_error(e, BUS_ERROR_INVALID_PATH, "Path %s is not absolute.", path);
- return -EINVAL;
- }
-
- if (!name)
- name = path_get_file_name(path);
-
- t = unit_name_to_type(name);
-
- if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid(name, false)) {
- dbus_set_error(e, BUS_ERROR_INVALID_NAME, "Unit name %s is not valid.", name);
- return -EINVAL;
- }
-
- ret = manager_get_unit(m, name);
- if (ret) {
- *_ret = ret;
- return 1;
- }
-
- ret = unit_new(m, unit_vtable[t]->object_size);
- if (!ret)
- return -ENOMEM;
-
- if (path) {
- ret->fragment_path = strdup(path);
- if (!ret->fragment_path) {
- unit_free(ret);
- return -ENOMEM;
- }
- }
-
- if ((r = unit_add_name(ret, name)) < 0) {
- unit_free(ret);
- return r;
- }
-
- unit_add_to_load_queue(ret);
- unit_add_to_dbus_queue(ret);
- unit_add_to_gc_queue(ret);
-
- if (_ret)
- *_ret = ret;
-
- return 0;
-}
-
-int manager_load_unit(Manager *m, const char *name, const char *path, DBusError *e, Unit **_ret) {
- int r;
-
- assert(m);
-
- /* This will load the service information files, but not actually
- * start any services or anything. */
-
- r = manager_load_unit_prepare(m, name, path, e, _ret);
- if (r != 0)
- return r;
-
- manager_dispatch_load_queue(m);
-
- if (_ret)
- *_ret = unit_follow_merge(*_ret);
-
- return 0;
-}
-
-void manager_dump_jobs(Manager *s, FILE *f, const char *prefix) {
- Iterator i;
- Job *j;
-
- assert(s);
- assert(f);
-
- HASHMAP_FOREACH(j, s->jobs, i)
- job_dump(j, f, prefix);
-}
-
-void manager_dump_units(Manager *s, FILE *f, const char *prefix) {
- Iterator i;
- Unit *u;
- const char *t;
-
- assert(s);
- assert(f);
-
- HASHMAP_FOREACH_KEY(u, t, s->units, i)
- if (u->id == t)
- unit_dump(u, f, prefix);
-}
-
-void manager_clear_jobs(Manager *m) {
- Job *j;
-
- assert(m);
-
- while ((j = hashmap_first(m->jobs)))
- /* No need to recurse. We're cancelling all jobs. */
- job_finish_and_invalidate(j, JOB_CANCELED, false);
-}
-
-unsigned manager_dispatch_run_queue(Manager *m) {
- Job *j;
- unsigned n = 0;
-
- if (m->dispatching_run_queue)
- return 0;
-
- m->dispatching_run_queue = true;
-
- while ((j = m->run_queue)) {
- assert(j->installed);
- assert(j->in_run_queue);
-
- job_run_and_invalidate(j);
- n++;
- }
-
- m->dispatching_run_queue = false;
- return n;
-}
-
-unsigned manager_dispatch_dbus_queue(Manager *m) {
- Job *j;
- Unit *u;
- unsigned n = 0;
-
- assert(m);
-
- if (m->dispatching_dbus_queue)
- return 0;
-
- m->dispatching_dbus_queue = true;
-
- while ((u = m->dbus_unit_queue)) {
- assert(u->in_dbus_queue);
-
- bus_unit_send_change_signal(u);
- n++;
- }
-
- while ((j = m->dbus_job_queue)) {
- assert(j->in_dbus_queue);
-
- bus_job_send_change_signal(j);
- n++;
- }
-
- m->dispatching_dbus_queue = false;
- return n;
-}
-
-static int manager_process_notify_fd(Manager *m) {
- ssize_t n;
-
- assert(m);
-
- for (;;) {
- char buf[4096];
- struct msghdr msghdr;
- struct iovec iovec;
- struct ucred *ucred;
- union {
- struct cmsghdr cmsghdr;
- uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
- } control;
- Unit *u;
- char **tags;
-
- zero(iovec);
- iovec.iov_base = buf;
- iovec.iov_len = sizeof(buf)-1;
-
- zero(control);
- zero(msghdr);
- msghdr.msg_iov = &iovec;
- msghdr.msg_iovlen = 1;
- msghdr.msg_control = &control;
- msghdr.msg_controllen = sizeof(control);
-
- if ((n = recvmsg(m->notify_watch.fd, &msghdr, MSG_DONTWAIT)) <= 0) {
- if (n >= 0)
- return -EIO;
-
- if (errno == EAGAIN || errno == EINTR)
- break;
-
- return -errno;
- }
-
- if (msghdr.msg_controllen < CMSG_LEN(sizeof(struct ucred)) ||
- control.cmsghdr.cmsg_level != SOL_SOCKET ||
- control.cmsghdr.cmsg_type != SCM_CREDENTIALS ||
- control.cmsghdr.cmsg_len != CMSG_LEN(sizeof(struct ucred))) {
- log_warning("Received notify message without credentials. Ignoring.");
- continue;
- }
-
- ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr);
-
- if (!(u = hashmap_get(m->watch_pids, LONG_TO_PTR(ucred->pid))))
- if (!(u = cgroup_unit_by_pid(m, ucred->pid))) {
- log_warning("Cannot find unit for notify message of PID %lu.", (unsigned long) ucred->pid);
- continue;
- }
-
- assert((size_t) n < sizeof(buf));
- buf[n] = 0;
- if (!(tags = strv_split(buf, "\n\r")))
- return -ENOMEM;
-
- log_debug("Got notification message for unit %s", u->id);
-
- if (UNIT_VTABLE(u)->notify_message)
- UNIT_VTABLE(u)->notify_message(u, ucred->pid, tags);
-
- strv_free(tags);
- }
-
- return 0;
-}
-
-static int manager_dispatch_sigchld(Manager *m) {
- assert(m);
-
- for (;;) {
- siginfo_t si;
- Unit *u;
- int r;
-
- zero(si);
-
- /* First we call waitd() for a PID and do not reap the
- * zombie. That way we can still access /proc/$PID for
- * it while it is a zombie. */
- if (waitid(P_ALL, 0, &si, WEXITED|WNOHANG|WNOWAIT) < 0) {
-
- if (errno == ECHILD)
- break;
-
- if (errno == EINTR)
- continue;
-
- return -errno;
- }
-
- if (si.si_pid <= 0)
- break;
-
- if (si.si_code == CLD_EXITED || si.si_code == CLD_KILLED || si.si_code == CLD_DUMPED) {
- char *name = NULL;
-
- get_process_comm(si.si_pid, &name);
- log_debug("Got SIGCHLD for process %lu (%s)", (unsigned long) si.si_pid, strna(name));
- free(name);
- }
-
- /* Let's flush any message the dying child might still
- * have queued for us. This ensures that the process
- * still exists in /proc so that we can figure out
- * which cgroup and hence unit it belongs to. */
- if ((r = manager_process_notify_fd(m)) < 0)
- return r;
-
- /* And now figure out the unit this belongs to */
- if (!(u = hashmap_get(m->watch_pids, LONG_TO_PTR(si.si_pid))))
- u = cgroup_unit_by_pid(m, si.si_pid);
-
- /* And now, we actually reap the zombie. */
- if (waitid(P_PID, si.si_pid, &si, WEXITED) < 0) {
- if (errno == EINTR)
- continue;
-
- return -errno;
- }
-
- if (si.si_code != CLD_EXITED && si.si_code != CLD_KILLED && si.si_code != CLD_DUMPED)
- continue;
-
- log_debug("Child %lu died (code=%s, status=%i/%s)",
- (long unsigned) si.si_pid,
- sigchld_code_to_string(si.si_code),
- si.si_status,
- strna(si.si_code == CLD_EXITED
- ? exit_status_to_string(si.si_status, EXIT_STATUS_FULL)
- : signal_to_string(si.si_status)));
-
- if (!u)
- continue;
-
- log_debug("Child %lu belongs to %s", (long unsigned) si.si_pid, u->id);
-
- hashmap_remove(m->watch_pids, LONG_TO_PTR(si.si_pid));
- UNIT_VTABLE(u)->sigchld_event(u, si.si_pid, si.si_code, si.si_status);
- }
-
- return 0;
-}
-
-static int manager_start_target(Manager *m, const char *name, JobMode mode) {
- int r;
- DBusError error;
-
- dbus_error_init(&error);
-
- log_debug("Activating special unit %s", name);
-
- if ((r = manager_add_job_by_name(m, JOB_START, name, mode, true, &error, NULL)) < 0)
- log_error("Failed to enqueue %s job: %s", name, bus_error(&error, r));
-
- dbus_error_free(&error);
-
- return r;
-}
-
-static int manager_process_signal_fd(Manager *m) {
- ssize_t n;
- struct signalfd_siginfo sfsi;
- bool sigchld = false;
-
- assert(m);
-
- for (;;) {
- if ((n = read(m->signal_watch.fd, &sfsi, sizeof(sfsi))) != sizeof(sfsi)) {
-
- if (n >= 0)
- return -EIO;
-
- if (errno == EINTR || errno == EAGAIN)
- break;
-
- return -errno;
- }
-
- if (sfsi.ssi_pid > 0) {
- char *p = NULL;
-
- get_process_comm(sfsi.ssi_pid, &p);
-
- log_debug("Received SIG%s from PID %lu (%s).",
- signal_to_string(sfsi.ssi_signo),
- (unsigned long) sfsi.ssi_pid, strna(p));
- free(p);
- } else
- log_debug("Received SIG%s.", signal_to_string(sfsi.ssi_signo));
-
- switch (sfsi.ssi_signo) {
-
- case SIGCHLD:
- sigchld = true;
- break;
-
- case SIGTERM:
- if (m->running_as == SYSTEMD_SYSTEM) {
- /* This is for compatibility with the
- * original sysvinit */
- m->exit_code = MANAGER_REEXECUTE;
- break;
- }
-
- /* Fall through */
-
- case SIGINT:
- if (m->running_as == SYSTEMD_SYSTEM) {
- manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE);
- break;
- }
-
- /* Run the exit target if there is one, if not, just exit. */
- if (manager_start_target(m, SPECIAL_EXIT_TARGET, JOB_REPLACE) < 0) {
- m->exit_code = MANAGER_EXIT;
- return 0;
- }
-
- break;
-
- case SIGWINCH:
- if (m->running_as == SYSTEMD_SYSTEM)
- manager_start_target(m, SPECIAL_KBREQUEST_TARGET, JOB_REPLACE);
-
- /* This is a nop on non-init */
- break;
-
- case SIGPWR:
- if (m->running_as == SYSTEMD_SYSTEM)
- manager_start_target(m, SPECIAL_SIGPWR_TARGET, JOB_REPLACE);
-
- /* This is a nop on non-init */
- break;
-
- case SIGUSR1: {
- Unit *u;
-
- u = manager_get_unit(m, SPECIAL_DBUS_SERVICE);
-
- if (!u || UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) {
- log_info("Trying to reconnect to bus...");
- bus_init(m, true);
- }
-
- if (!u || !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u))) {
- log_info("Loading D-Bus service...");
- manager_start_target(m, SPECIAL_DBUS_SERVICE, JOB_REPLACE);
- }
-
- break;
- }
-
- case SIGUSR2: {
- FILE *f;
- char *dump = NULL;
- size_t size;
-
- if (!(f = open_memstream(&dump, &size))) {
- log_warning("Failed to allocate memory stream.");
- break;
- }
-
- manager_dump_units(m, f, "\t");
- manager_dump_jobs(m, f, "\t");
-
- if (ferror(f)) {
- fclose(f);
- free(dump);
- log_warning("Failed to write status stream");
- break;
- }
-
- fclose(f);
- log_dump(LOG_INFO, dump);
- free(dump);
-
- break;
- }
-
- case SIGHUP:
- m->exit_code = MANAGER_RELOAD;
- break;
-
- default: {
-
- /* Starting SIGRTMIN+0 */
- static const char * const target_table[] = {
- [0] = SPECIAL_DEFAULT_TARGET,
- [1] = SPECIAL_RESCUE_TARGET,
- [2] = SPECIAL_EMERGENCY_TARGET,
- [3] = SPECIAL_HALT_TARGET,
- [4] = SPECIAL_POWEROFF_TARGET,
- [5] = SPECIAL_REBOOT_TARGET,
- [6] = SPECIAL_KEXEC_TARGET
- };
-
- /* Starting SIGRTMIN+13, so that target halt and system halt are 10 apart */
- static const ManagerExitCode code_table[] = {
- [0] = MANAGER_HALT,
- [1] = MANAGER_POWEROFF,
- [2] = MANAGER_REBOOT,
- [3] = MANAGER_KEXEC
- };
-
- if ((int) sfsi.ssi_signo >= SIGRTMIN+0 &&
- (int) sfsi.ssi_signo < SIGRTMIN+(int) ELEMENTSOF(target_table)) {
- int idx = (int) sfsi.ssi_signo - SIGRTMIN;
- manager_start_target(m, target_table[idx],
- (idx == 1 || idx == 2) ? JOB_ISOLATE : JOB_REPLACE);
- break;
- }
-
- if ((int) sfsi.ssi_signo >= SIGRTMIN+13 &&
- (int) sfsi.ssi_signo < SIGRTMIN+13+(int) ELEMENTSOF(code_table)) {
- m->exit_code = code_table[sfsi.ssi_signo - SIGRTMIN - 13];
- break;
- }
-
- switch (sfsi.ssi_signo - SIGRTMIN) {
-
- case 20:
- log_debug("Enabling showing of status.");
- manager_set_show_status(m, true);
- break;
-
- case 21:
- log_debug("Disabling showing of status.");
- manager_set_show_status(m, false);
- break;
-
- case 22:
- log_set_max_level(LOG_DEBUG);
- log_notice("Setting log level to debug.");
- break;
-
- case 23:
- log_set_max_level(LOG_INFO);
- log_notice("Setting log level to info.");
- break;
-
- case 24:
- if (m->running_as == SYSTEMD_USER) {
- m->exit_code = MANAGER_EXIT;
- return 0;
- }
-
- /* This is a nop on init */
- break;
-
- case 26:
- log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
- log_notice("Setting log target to journal-or-kmsg.");
- break;
-
- case 27:
- log_set_target(LOG_TARGET_CONSOLE);
- log_notice("Setting log target to console.");
- break;
-
- case 28:
- log_set_target(LOG_TARGET_KMSG);
- log_notice("Setting log target to kmsg.");
- break;
-
- case 29:
- log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
- log_notice("Setting log target to syslog-or-kmsg.");
- break;
-
- default:
- log_warning("Got unhandled signal <%s>.", signal_to_string(sfsi.ssi_signo));
- }
- }
- }
- }
-
- if (sigchld)
- return manager_dispatch_sigchld(m);
-
- return 0;
-}
-
-static int process_event(Manager *m, struct epoll_event *ev) {
- int r;
- Watch *w;
-
- assert(m);
- assert(ev);
-
- assert_se(w = ev->data.ptr);
-
- if (w->type == WATCH_INVALID)
- return 0;
-
- switch (w->type) {
-
- case WATCH_SIGNAL:
-
- /* An incoming signal? */
- if (ev->events != EPOLLIN)
- return -EINVAL;
-
- if ((r = manager_process_signal_fd(m)) < 0)
- return r;
-
- break;
-
- case WATCH_NOTIFY:
-
- /* An incoming daemon notification event? */
- if (ev->events != EPOLLIN)
- return -EINVAL;
-
- if ((r = manager_process_notify_fd(m)) < 0)
- return r;
-
- break;
-
- case WATCH_FD:
-
- /* Some fd event, to be dispatched to the units */
- UNIT_VTABLE(w->data.unit)->fd_event(w->data.unit, w->fd, ev->events, w);
- break;
-
- case WATCH_UNIT_TIMER:
- case WATCH_JOB_TIMER: {
- uint64_t v;
- ssize_t k;
-
- /* Some timer event, to be dispatched to the units */
- if ((k = read(w->fd, &v, sizeof(v))) != sizeof(v)) {
-
- if (k < 0 && (errno == EINTR || errno == EAGAIN))
- break;
-
- return k < 0 ? -errno : -EIO;
- }
-
- if (w->type == WATCH_UNIT_TIMER)
- UNIT_VTABLE(w->data.unit)->timer_event(w->data.unit, v, w);
- else
- job_timer_event(w->data.job, v, w);
- break;
- }
-
- case WATCH_MOUNT:
- /* Some mount table change, intended for the mount subsystem */
- mount_fd_event(m, ev->events);
- break;
-
- case WATCH_SWAP:
- /* Some swap table change, intended for the swap subsystem */
- swap_fd_event(m, ev->events);
- break;
-
- case WATCH_UDEV:
- /* Some notification from udev, intended for the device subsystem */
- device_fd_event(m, ev->events);
- break;
-
- case WATCH_DBUS_WATCH:
- bus_watch_event(m, w, ev->events);
- break;
-
- case WATCH_DBUS_TIMEOUT:
- bus_timeout_event(m, w, ev->events);
- break;
-
- default:
- log_error("event type=%i", w->type);
- assert_not_reached("Unknown epoll event type.");
- }
-
- return 0;
-}
-
-int manager_loop(Manager *m) {
- int r;
-
- RATELIMIT_DEFINE(rl, 1*USEC_PER_SEC, 50000);
-
- assert(m);
- m->exit_code = MANAGER_RUNNING;
-
- /* Release the path cache */
- set_free_free(m->unit_path_cache);
- m->unit_path_cache = NULL;
-
- manager_check_finished(m);
-
- /* There might still be some zombies hanging around from
- * before we were exec()'ed. Leat's reap them */
- r = manager_dispatch_sigchld(m);
- if (r < 0)
- return r;
-
- while (m->exit_code == MANAGER_RUNNING) {
- struct epoll_event event;
- int n;
- int wait_msec = -1;
-
- if (m->runtime_watchdog > 0 && m->running_as == SYSTEMD_SYSTEM)
- watchdog_ping();
-
- if (!ratelimit_test(&rl)) {
- /* Yay, something is going seriously wrong, pause a little */
- log_warning("Looping too fast. Throttling execution a little.");
- sleep(1);
- continue;
- }
-
- if (manager_dispatch_load_queue(m) > 0)
- continue;
-
- if (manager_dispatch_run_queue(m) > 0)
- continue;
-
- if (bus_dispatch(m) > 0)
- continue;
-
- if (manager_dispatch_cleanup_queue(m) > 0)
- continue;
-
- if (manager_dispatch_gc_queue(m) > 0)
- continue;
-
- if (manager_dispatch_dbus_queue(m) > 0)
- continue;
-
- if (swap_dispatch_reload(m) > 0)
- continue;
-
- /* Sleep for half the watchdog time */
- if (m->runtime_watchdog > 0 && m->running_as == SYSTEMD_SYSTEM) {
- wait_msec = (int) (m->runtime_watchdog / 2 / USEC_PER_MSEC);
- if (wait_msec <= 0)
- wait_msec = 1;
- } else
- wait_msec = -1;
-
- n = epoll_wait(m->epoll_fd, &event, 1, wait_msec);
- if (n < 0) {
-
- if (errno == EINTR)
- continue;
-
- return -errno;
- } else if (n == 0)
- continue;
-
- assert(n == 1);
-
- r = process_event(m, &event);
- if (r < 0)
- return r;
- }
-
- return m->exit_code;
-}
-
-int manager_load_unit_from_dbus_path(Manager *m, const char *s, DBusError *e, Unit **_u) {
- char *n;
- Unit *u;
- int r;
-
- assert(m);
- assert(s);
- assert(_u);
-
- if (!startswith(s, "/org/freedesktop/systemd1/unit/"))
- return -EINVAL;
-
- n = bus_path_unescape(s+31);
- if (!n)
- return -ENOMEM;
-
- r = manager_load_unit(m, n, NULL, e, &u);
- free(n);
-
- if (r < 0)
- return r;
-
- *_u = u;
-
- return 0;
-}
-
-int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j) {
- Job *j;
- unsigned id;
- int r;
-
- assert(m);
- assert(s);
- assert(_j);
-
- if (!startswith(s, "/org/freedesktop/systemd1/job/"))
- return -EINVAL;
-
- if ((r = safe_atou(s + 30, &id)) < 0)
- return r;
-
- if (!(j = manager_get_job(m, id)))
- return -ENOENT;
-
- *_j = j;
-
- return 0;
-}
-
-void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) {
-
-#ifdef HAVE_AUDIT
- char *p;
- int audit_fd;
-
- audit_fd = get_audit_fd();
- if (audit_fd < 0)
- return;
-
- /* Don't generate audit events if the service was already
- * started and we're just deserializing */
- if (m->n_reloading > 0)
- return;
-
- if (m->running_as != SYSTEMD_SYSTEM)
- return;
-
- if (u->type != UNIT_SERVICE)
- return;
-
- if (!(p = unit_name_to_prefix_and_instance(u->id))) {
- log_error("Failed to allocate unit name for audit message: %s", strerror(ENOMEM));
- return;
- }
-
- if (audit_log_user_comm_message(audit_fd, type, "", p, NULL, NULL, NULL, success) < 0) {
- if (errno == EPERM) {
- /* We aren't allowed to send audit messages?
- * Then let's not retry again. */
- close_audit_fd();
- } else
- log_warning("Failed to send audit message: %m");
- }
-
- free(p);
-#endif
-
-}
-
-void manager_send_unit_plymouth(Manager *m, Unit *u) {
- int fd = -1;
- union sockaddr_union sa;
- int n = 0;
- char *message = NULL;
-
- /* Don't generate plymouth events if the service was already
- * started and we're just deserializing */
- if (m->n_reloading > 0)
- return;
-
- if (m->running_as != SYSTEMD_SYSTEM)
- return;
-
- if (u->type != UNIT_SERVICE &&
- u->type != UNIT_MOUNT &&
- u->type != UNIT_SWAP)
- return;
-
- /* We set SOCK_NONBLOCK here so that we rather drop the
- * message then wait for plymouth */
- if ((fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0)) < 0) {
- log_error("socket() failed: %m");
- return;
- }
-
- zero(sa);
- sa.sa.sa_family = AF_UNIX;
- strncpy(sa.un.sun_path+1, "/org/freedesktop/plymouthd", sizeof(sa.un.sun_path)-1);
- if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) {
-
- if (errno != EPIPE &&
- errno != EAGAIN &&
- errno != ENOENT &&
- errno != ECONNREFUSED &&
- errno != ECONNRESET &&
- errno != ECONNABORTED)
- log_error("connect() failed: %m");
-
- goto finish;
- }
-
- if (asprintf(&message, "U\002%c%s%n", (int) (strlen(u->id) + 1), u->id, &n) < 0) {
- log_oom();
- goto finish;
- }
-
- errno = 0;
- if (write(fd, message, n + 1) != n + 1) {
-
- if (errno != EPIPE &&
- errno != EAGAIN &&
- errno != ENOENT &&
- errno != ECONNREFUSED &&
- errno != ECONNRESET &&
- errno != ECONNABORTED)
- log_error("Failed to write Plymouth message: %m");
-
- goto finish;
- }
-
-finish:
- if (fd >= 0)
- close_nointr_nofail(fd);
-
- free(message);
-}
-
-void manager_dispatch_bus_name_owner_changed(
- Manager *m,
- const char *name,
- const char* old_owner,
- const char *new_owner) {
-
- Unit *u;
-
- assert(m);
- assert(name);
-
- if (!(u = hashmap_get(m->watch_bus, name)))
- return;
-
- UNIT_VTABLE(u)->bus_name_owner_change(u, name, old_owner, new_owner);
-}
-
-void manager_dispatch_bus_query_pid_done(
- Manager *m,
- const char *name,
- pid_t pid) {
-
- Unit *u;
-
- assert(m);
- assert(name);
- assert(pid >= 1);
-
- if (!(u = hashmap_get(m->watch_bus, name)))
- return;
-
- UNIT_VTABLE(u)->bus_query_pid_done(u, name, pid);
-}
-
-int manager_open_serialization(Manager *m, FILE **_f) {
- char *path = NULL;
- mode_t saved_umask;
- int fd;
- FILE *f;
-
- assert(_f);
-
- if (m->running_as == SYSTEMD_SYSTEM)
- asprintf(&path, "/run/systemd/dump-%lu-XXXXXX", (unsigned long) getpid());
- else
- asprintf(&path, "/tmp/systemd-dump-%lu-XXXXXX", (unsigned long) getpid());
-
- if (!path)
- return -ENOMEM;
-
- saved_umask = umask(0077);
- fd = mkostemp(path, O_RDWR|O_CLOEXEC);
- umask(saved_umask);
-
- if (fd < 0) {
- free(path);
- return -errno;
- }
-
- unlink(path);
-
- log_debug("Serializing state to %s", path);
- free(path);
-
- if (!(f = fdopen(fd, "w+")))
- return -errno;
-
- *_f = f;
-
- return 0;
-}
-
-int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool serialize_jobs) {
- Iterator i;
- Unit *u;
- const char *t;
- int r;
-
- assert(m);
- assert(f);
- assert(fds);
-
- m->n_reloading ++;
-
- fprintf(f, "current-job-id=%i\n", m->current_job_id);
- fprintf(f, "taint-usr=%s\n", yes_no(m->taint_usr));
- fprintf(f, "n-installed-jobs=%u\n", m->n_installed_jobs);
- fprintf(f, "n-failed-jobs=%u\n", m->n_failed_jobs);
-
- dual_timestamp_serialize(f, "firmware-timestamp", &m->firmware_timestamp);
- dual_timestamp_serialize(f, "kernel-timestamp", &m->kernel_timestamp);
- dual_timestamp_serialize(f, "loader-timestamp", &m->loader_timestamp);
- dual_timestamp_serialize(f, "initrd-timestamp", &m->initrd_timestamp);
-
- if (!in_initrd()) {
- dual_timestamp_serialize(f, "userspace-timestamp", &m->userspace_timestamp);
- dual_timestamp_serialize(f, "finish-timestamp", &m->finish_timestamp);
- }
-
- fputc('\n', f);
-
- HASHMAP_FOREACH_KEY(u, t, m->units, i) {
- if (u->id != t)
- continue;
-
- if (!unit_can_serialize(u))
- continue;
-
- /* Start marker */
- fputs(u->id, f);
- fputc('\n', f);
-
- if ((r = unit_serialize(u, f, fds, serialize_jobs)) < 0) {
- m->n_reloading --;
- return r;
- }
- }
-
- assert(m->n_reloading > 0);
- m->n_reloading --;
-
- if (ferror(f))
- return -EIO;
-
- r = bus_fdset_add_all(m, fds);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
- int r = 0;
-
- assert(m);
- assert(f);
-
- log_debug("Deserializing state...");
-
- m->n_reloading ++;
-
- for (;;) {
- char line[LINE_MAX], *l;
-
- if (!fgets(line, sizeof(line), f)) {
- if (feof(f))
- r = 0;
- else
- r = -errno;
-
- goto finish;
- }
-
- char_array_0(line);
- l = strstrip(line);
-
- if (l[0] == 0)
- break;
-
- if (startswith(l, "current-job-id=")) {
- uint32_t id;
-
- if (safe_atou32(l+15, &id) < 0)
- log_debug("Failed to parse current job id value %s", l+15);
- else
- m->current_job_id = MAX(m->current_job_id, id);
- } else if (startswith(l, "n-installed-jobs=")) {
- uint32_t n;
-
- if (safe_atou32(l+17, &n) < 0)
- log_debug("Failed to parse installed jobs counter %s", l+17);
- else
- m->n_installed_jobs += n;
- } else if (startswith(l, "n-failed-jobs=")) {
- uint32_t n;
-
- if (safe_atou32(l+14, &n) < 0)
- log_debug("Failed to parse failed jobs counter %s", l+14);
- else
- m->n_failed_jobs += n;
- } else if (startswith(l, "taint-usr=")) {
- int b;
-
- if ((b = parse_boolean(l+10)) < 0)
- log_debug("Failed to parse taint /usr flag %s", l+10);
- else
- m->taint_usr = m->taint_usr || b;
- } else if (startswith(l, "firmware-timestamp="))
- dual_timestamp_deserialize(l+19, &m->firmware_timestamp);
- else if (startswith(l, "loader-timestamp="))
- dual_timestamp_deserialize(l+17, &m->loader_timestamp);
- else if (startswith(l, "kernel-timestamp="))
- dual_timestamp_deserialize(l+17, &m->kernel_timestamp);
- else if (startswith(l, "initrd-timestamp="))
- dual_timestamp_deserialize(l+17, &m->initrd_timestamp);
- else if (startswith(l, "userspace-timestamp="))
- dual_timestamp_deserialize(l+20, &m->userspace_timestamp);
- else if (startswith(l, "finish-timestamp="))
- dual_timestamp_deserialize(l+17, &m->finish_timestamp);
- else
- log_debug("Unknown serialization item '%s'", l);
- }
-
- for (;;) {
- Unit *u;
- char name[UNIT_NAME_MAX+2];
-
- /* Start marker */
- if (!fgets(name, sizeof(name), f)) {
- if (feof(f))
- r = 0;
- else
- r = -errno;
-
- goto finish;
- }
-
- char_array_0(name);
-
- if ((r = manager_load_unit(m, strstrip(name), NULL, NULL, &u)) < 0)
- goto finish;
-
- if ((r = unit_deserialize(u, f, fds)) < 0)
- goto finish;
- }
-
-finish:
- if (ferror(f)) {
- r = -EIO;
- goto finish;
- }
-
- assert(m->n_reloading > 0);
- m->n_reloading --;
-
- return r;
-}
-
-int manager_reload(Manager *m) {
- int r, q;
- FILE *f;
- FDSet *fds;
-
- assert(m);
-
- r = manager_open_serialization(m, &f);
- if (r < 0)
- return r;
-
- m->n_reloading ++;
-
- fds = fdset_new();
- if (!fds) {
- m->n_reloading --;
- r = -ENOMEM;
- goto finish;
- }
-
- r = manager_serialize(m, f, fds, true);
- if (r < 0) {
- m->n_reloading --;
- goto finish;
- }
-
- if (fseeko(f, 0, SEEK_SET) < 0) {
- m->n_reloading --;
- r = -errno;
- goto finish;
- }
-
- /* From here on there is no way back. */
- manager_clear_jobs_and_units(m);
- manager_undo_generators(m);
- lookup_paths_free(&m->lookup_paths);
-
- /* Find new unit paths */
- manager_run_generators(m);
-
- q = lookup_paths_init(
- &m->lookup_paths, m->running_as, true,
- m->generator_unit_path,
- m->generator_unit_path_early,
- m->generator_unit_path_late);
- if (q < 0)
- r = q;
-
- manager_build_unit_path_cache(m);
-
- /* First, enumerate what we can from all config files */
- q = manager_enumerate(m);
- if (q < 0)
- r = q;
-
- /* Second, deserialize our stored data */
- q = manager_deserialize(m, f, fds);
- if (q < 0)
- r = q;
-
- fclose(f);
- f = NULL;
-
- /* Third, fire things up! */
- q = manager_coldplug(m);
- if (q < 0)
- r = q;
-
- assert(m->n_reloading > 0);
- m->n_reloading--;
-
-finish:
- if (f)
- fclose(f);
-
- if (fds)
- fdset_free(fds);
-
- return r;
-}
-
-bool manager_is_booting_or_shutting_down(Manager *m) {
- Unit *u;
-
- assert(m);
-
- /* Is the initial job still around? */
- if (manager_get_job(m, m->default_unit_job_id))
- return true;
-
- /* Is there a job for the shutdown target? */
- u = manager_get_unit(m, SPECIAL_SHUTDOWN_TARGET);
- if (u)
- return !!u->job;
-
- return false;
-}
-
-void manager_reset_failed(Manager *m) {
- Unit *u;
- Iterator i;
-
- assert(m);
-
- HASHMAP_FOREACH(u, m->units, i)
- unit_reset_failed(u);
-}
-
-bool manager_unit_pending_inactive(Manager *m, const char *name) {
- Unit *u;
-
- assert(m);
- assert(name);
-
- /* Returns true if the unit is inactive or going down */
- if (!(u = manager_get_unit(m, name)))
- return true;
-
- return unit_pending_inactive(u);
-}
-
-void manager_check_finished(Manager *m) {
- char userspace[FORMAT_TIMESPAN_MAX], initrd[FORMAT_TIMESPAN_MAX], kernel[FORMAT_TIMESPAN_MAX], sum[FORMAT_TIMESPAN_MAX];
- usec_t firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec;
-
- assert(m);
-
- if (hashmap_size(m->jobs) > 0)
- return;
-
- /* Notify Type=idle units that we are done now */
- close_pipe(m->idle_pipe);
-
- /* Turn off confirm spawn now */
- m->confirm_spawn = false;
-
- if (dual_timestamp_is_set(&m->finish_timestamp))
- return;
-
- dual_timestamp_get(&m->finish_timestamp);
-
- if (m->running_as == SYSTEMD_SYSTEM && detect_container(NULL) <= 0) {
-
- /* Note that m->kernel_usec.monotonic is always at 0,
- * and m->firmware_usec.monotonic and
- * m->loader_usec.monotonic should be considered
- * negative values. */
-
- firmware_usec = m->firmware_timestamp.monotonic - m->loader_timestamp.monotonic;
- loader_usec = m->loader_timestamp.monotonic - m->kernel_timestamp.monotonic;
- userspace_usec = m->finish_timestamp.monotonic - m->userspace_timestamp.monotonic;
- total_usec = m->firmware_timestamp.monotonic + m->finish_timestamp.monotonic;
-
- if (dual_timestamp_is_set(&m->initrd_timestamp)) {
-
- kernel_usec = m->initrd_timestamp.monotonic - m->kernel_timestamp.monotonic;
- initrd_usec = m->userspace_timestamp.monotonic - m->initrd_timestamp.monotonic;
-
- if (!log_on_console())
- log_struct(LOG_INFO,
- MESSAGE_ID(SD_MESSAGE_STARTUP_FINISHED),
- "KERNEL_USEC=%llu", (unsigned long long) kernel_usec,
- "INITRD_USEC=%llu", (unsigned long long) initrd_usec,
- "USERSPACE_USEC=%llu", (unsigned long long) userspace_usec,
- "MESSAGE=Startup finished in %s (kernel) + %s (initrd) + %s (userspace) = %s.",
- format_timespan(kernel, sizeof(kernel), kernel_usec),
- format_timespan(initrd, sizeof(initrd), initrd_usec),
- format_timespan(userspace, sizeof(userspace), userspace_usec),
- format_timespan(sum, sizeof(sum), total_usec),
- NULL);
- } else {
- kernel_usec = m->userspace_timestamp.monotonic - m->kernel_timestamp.monotonic;
- initrd_usec = 0;
-
- if (!log_on_console())
- log_struct(LOG_INFO,
- MESSAGE_ID(SD_MESSAGE_STARTUP_FINISHED),
- "KERNEL_USEC=%llu", (unsigned long long) kernel_usec,
- "USERSPACE_USEC=%llu", (unsigned long long) userspace_usec,
- "MESSAGE=Startup finished in %s (kernel) + %s (userspace) = %s.",
- format_timespan(kernel, sizeof(kernel), kernel_usec),
- format_timespan(userspace, sizeof(userspace), userspace_usec),
- format_timespan(sum, sizeof(sum), total_usec),
- NULL);
- }
- } else {
- firmware_usec = loader_usec = initrd_usec = kernel_usec = 0;
- total_usec = userspace_usec = m->finish_timestamp.monotonic - m->userspace_timestamp.monotonic;
-
- if (!log_on_console())
- log_struct(LOG_INFO,
- MESSAGE_ID(SD_MESSAGE_STARTUP_FINISHED),
- "USERSPACE_USEC=%llu", (unsigned long long) userspace_usec,
- "MESSAGE=Startup finished in %s.",
- format_timespan(sum, sizeof(sum), total_usec),
- NULL);
- }
-
- bus_broadcast_finished(m, firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec);
-
- sd_notifyf(false,
- "READY=1\nSTATUS=Startup finished in %s.",
- format_timespan(sum, sizeof(sum), total_usec));
-}
-
-static int create_generator_dir(Manager *m, char **generator, const char *name) {
- char *p;
- int r;
-
- assert(m);
- assert(generator);
- assert(name);
-
- if (*generator)
- return 0;
-
- if (m->running_as == SYSTEMD_SYSTEM && getpid() == 1) {
-
- p = strappend("/run/systemd/", name);
- if (!p)
- return log_oom();
-
- r = mkdir_p_label(p, 0755);
- if (r < 0) {
- log_error("Failed to create generator directory: %s", strerror(-r));
- free(p);
- return r;
- }
- } else {
- p = strjoin("/tmp/systemd-", name, ".XXXXXX", NULL);
- if (!p)
- return log_oom();
-
- if (!mkdtemp(p)) {
- free(p);
- log_error("Failed to create generator directory: %m");
- return -errno;
- }
- }
-
- *generator = p;
- return 0;
-}
-
-static void trim_generator_dir(Manager *m, char **generator) {
- assert(m);
- assert(generator);
-
- if (!*generator)
- return;
-
- if (rmdir(*generator) >= 0) {
- free(*generator);
- *generator = NULL;
- }
-
- return;
-}
-
-void manager_run_generators(Manager *m) {
- DIR *d = NULL;
- const char *generator_path;
- const char *argv[5];
- mode_t u;
- int r;
-
- assert(m);
-
- generator_path = m->running_as == SYSTEMD_SYSTEM ? SYSTEM_GENERATOR_PATH : USER_GENERATOR_PATH;
- d = opendir(generator_path);
- if (!d) {
- if (errno == ENOENT)
- return;
-
- log_error("Failed to enumerate generator directory: %m");
- return;
- }
-
- r = create_generator_dir(m, &m->generator_unit_path, "generator");
- if (r < 0)
- goto finish;
-
- r = create_generator_dir(m, &m->generator_unit_path_early, "generator.early");
- if (r < 0)
- goto finish;
-
- r = create_generator_dir(m, &m->generator_unit_path_late, "generator.late");
- if (r < 0)
- goto finish;
-
- argv[0] = NULL; /* Leave this empty, execute_directory() will fill something in */
- argv[1] = m->generator_unit_path;
- argv[2] = m->generator_unit_path_early;
- argv[3] = m->generator_unit_path_late;
- argv[4] = NULL;
-
- u = umask(0022);
- execute_directory(generator_path, d, (char**) argv);
- umask(u);
-
- trim_generator_dir(m, &m->generator_unit_path);
- trim_generator_dir(m, &m->generator_unit_path_early);
- trim_generator_dir(m, &m->generator_unit_path_late);
-
-finish:
- if (d)
- closedir(d);
-}
-
-static void remove_generator_dir(Manager *m, char **generator) {
- assert(m);
- assert(generator);
-
- if (!*generator)
- return;
-
- strv_remove(m->lookup_paths.unit_path, *generator);
- rm_rf(*generator, false, true, false);
-
- free(*generator);
- *generator = NULL;
-}
-
-void manager_undo_generators(Manager *m) {
- assert(m);
-
- remove_generator_dir(m, &m->generator_unit_path);
- remove_generator_dir(m, &m->generator_unit_path_early);
- remove_generator_dir(m, &m->generator_unit_path_late);
-}
-
-int manager_set_default_controllers(Manager *m, char **controllers) {
- char **l;
-
- assert(m);
-
- l = strv_copy(controllers);
- if (!l)
- return -ENOMEM;
-
- strv_free(m->default_controllers);
- m->default_controllers = l;
-
- cg_shorten_controllers(m->default_controllers);
-
- return 0;
-}
-
-int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit) {
- int i;
-
- assert(m);
-
- for (i = 0; i < RLIMIT_NLIMITS; i++) {
- if (!default_rlimit[i])
- continue;
-
- m->rlimit[i] = newdup(struct rlimit, default_rlimit[i], 1);
- if (!m->rlimit[i])
- return -ENOMEM;
- }
-
- return 0;
-}
-
-void manager_recheck_journal(Manager *m) {
- Unit *u;
-
- assert(m);
-
- if (m->running_as != SYSTEMD_SYSTEM)
- return;
-
- u = manager_get_unit(m, SPECIAL_JOURNALD_SOCKET);
- if (u && SOCKET(u)->state != SOCKET_RUNNING) {
- log_close_journal();
- return;
- }
-
- u = manager_get_unit(m, SPECIAL_JOURNALD_SERVICE);
- if (u && SERVICE(u)->state != SERVICE_RUNNING) {
- log_close_journal();
- return;
- }
-
- /* Hmm, OK, so the socket is fully up and the service is up
- * too, then let's make use of the thing. */
- log_open();
-}
-
-void manager_set_show_status(Manager *m, bool b) {
- assert(m);
-
- if (m->running_as != SYSTEMD_SYSTEM)
- return;
-
- m->show_status = b;
-
- if (b)
- touch("/run/systemd/show-status");
- else
- unlink("/run/systemd/show-status");
-}
-
-bool manager_get_show_status(Manager *m) {
- assert(m);
-
- if (m->running_as != SYSTEMD_SYSTEM)
- return false;
-
- if (m->show_status)
- return true;
-
- /* If Plymouth is running make sure we show the status, so
- * that there's something nice to see when people press Esc */
-
- return plymouth_running();
-}
diff --git a/src/core/manager.h b/src/core/manager.h
deleted file mode 100644
index 22145024f1..0000000000
--- a/src/core/manager.h
+++ /dev/null
@@ -1,293 +0,0 @@
-/*-*- 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 <inttypes.h>
-#include <stdio.h>
-#include <dbus/dbus.h>
-
-#include "fdset.h"
-
-/* Enforce upper limit how many names we allow */
-#define MANAGER_MAX_NAMES 131072 /* 128K */
-
-typedef struct Manager Manager;
-typedef enum WatchType WatchType;
-typedef struct Watch Watch;
-
-typedef enum ManagerExitCode {
- MANAGER_RUNNING,
- MANAGER_EXIT,
- MANAGER_RELOAD,
- MANAGER_REEXECUTE,
- MANAGER_REBOOT,
- MANAGER_POWEROFF,
- MANAGER_HALT,
- MANAGER_KEXEC,
- MANAGER_SWITCH_ROOT,
- _MANAGER_EXIT_CODE_MAX,
- _MANAGER_EXIT_CODE_INVALID = -1
-} ManagerExitCode;
-
-enum WatchType {
- WATCH_INVALID,
- WATCH_SIGNAL,
- WATCH_NOTIFY,
- WATCH_FD,
- WATCH_UNIT_TIMER,
- WATCH_JOB_TIMER,
- WATCH_MOUNT,
- WATCH_SWAP,
- WATCH_UDEV,
- WATCH_DBUS_WATCH,
- WATCH_DBUS_TIMEOUT
-};
-
-struct Watch {
- int fd;
- WatchType type;
- union {
- struct Unit *unit;
- struct Job *job;
- DBusWatch *bus_watch;
- DBusTimeout *bus_timeout;
- } data;
- bool fd_is_dupped:1;
- bool socket_accept:1;
-};
-
-#include "unit.h"
-#include "job.h"
-#include "hashmap.h"
-#include "list.h"
-#include "set.h"
-#include "dbus.h"
-#include "path-lookup.h"
-
-struct Manager {
- /* Note that the set of units we know of is allowed to be
- * inconsistent. However the subset of it that is loaded may
- * not, and the list of jobs may neither. */
-
- /* Active jobs and units */
- Hashmap *units; /* name string => Unit object n:1 */
- Hashmap *jobs; /* job id => Job object 1:1 */
-
- /* To make it easy to iterate through the units of a specific
- * type we maintain a per type linked list */
- LIST_HEAD(Unit, units_by_type[_UNIT_TYPE_MAX]);
-
- /* To optimize iteration of units that have requires_mounts_for set */
- LIST_HEAD(Unit, has_requires_mounts_for);
-
- /* Units that need to be loaded */
- LIST_HEAD(Unit, load_queue); /* this is actually more a stack than a queue, but uh. */
-
- /* Jobs that need to be run */
- LIST_HEAD(Job, run_queue); /* more a stack than a queue, too */
-
- /* Units and jobs that have not yet been announced via
- * D-Bus. When something about a job changes it is added here
- * if it is not in there yet. This allows easy coalescing of
- * D-Bus change signals. */
- LIST_HEAD(Unit, dbus_unit_queue);
- LIST_HEAD(Job, dbus_job_queue);
-
- /* Units to remove */
- LIST_HEAD(Unit, cleanup_queue);
-
- /* Units to check when doing GC */
- LIST_HEAD(Unit, gc_queue);
-
- Hashmap *watch_pids; /* pid => Unit object n:1 */
-
- char *notify_socket;
-
- Watch notify_watch;
- Watch signal_watch;
-
- int epoll_fd;
-
- unsigned n_snapshots;
-
- LookupPaths lookup_paths;
- Set *unit_path_cache;
-
- char **environment;
- char **default_controllers;
-
- usec_t runtime_watchdog;
- usec_t shutdown_watchdog;
-
- dual_timestamp firmware_timestamp;
- dual_timestamp loader_timestamp;
- dual_timestamp kernel_timestamp;
- dual_timestamp initrd_timestamp;
- dual_timestamp userspace_timestamp;
- dual_timestamp finish_timestamp;
-
- char *generator_unit_path;
- char *generator_unit_path_early;
- char *generator_unit_path_late;
-
- /* Data specific to the device subsystem */
- struct udev* udev;
- struct udev_monitor* udev_monitor;
- Watch udev_watch;
- Hashmap *devices_by_sysfs;
-
- /* Data specific to the mount subsystem */
- FILE *proc_self_mountinfo;
- Watch mount_watch;
-
- /* Data specific to the swap filesystem */
- FILE *proc_swaps;
- Hashmap *swaps_by_proc_swaps;
- bool request_reload;
- Watch swap_watch;
-
- /* Data specific to the D-Bus subsystem */
- DBusConnection *api_bus, *system_bus;
- DBusServer *private_bus;
- Set *bus_connections, *bus_connections_for_dispatch;
-
- DBusMessage *queued_message; /* This is used during reloading:
- * before the reload we queue the
- * reply message here, and
- * afterwards we send it */
- DBusConnection *queued_message_connection; /* The connection to send the queued message on */
-
- Hashmap *watch_bus; /* D-Bus names => Unit object n:1 */
- int32_t name_data_slot;
- int32_t conn_data_slot;
- int32_t subscribed_data_slot;
-
- uint32_t current_job_id;
- uint32_t default_unit_job_id;
-
- /* Data specific to the Automount subsystem */
- int dev_autofs_fd;
-
- /* Data specific to the cgroup subsystem */
- Hashmap *cgroup_bondings; /* path string => CGroupBonding object 1:n */
- char *cgroup_hierarchy;
-
- usec_t gc_queue_timestamp;
- int gc_marker;
- unsigned n_in_gc_queue;
-
- /* Make sure the user cannot accidentally unmount our cgroup
- * file system */
- int pin_cgroupfs_fd;
-
- /* Flags */
- SystemdRunningAs running_as;
- ManagerExitCode exit_code:5;
-
- bool dispatching_load_queue:1;
- bool dispatching_run_queue:1;
- bool dispatching_dbus_queue:1;
-
- bool taint_usr:1;
-
- bool show_status;
- bool confirm_spawn;
-
- ExecOutput default_std_output, default_std_error;
-
- struct rlimit *rlimit[RLIMIT_NLIMITS];
-
- /* non-zero if we are reloading or reexecuting, */
- int n_reloading;
-
- unsigned n_installed_jobs;
- unsigned n_failed_jobs;
-
- /* Type=idle pipes */
- int idle_pipe[2];
-
- char *switch_root;
- char *switch_root_init;
-};
-
-int manager_new(SystemdRunningAs running_as, Manager **m);
-void manager_free(Manager *m);
-
-int manager_enumerate(Manager *m);
-int manager_coldplug(Manager *m);
-int manager_startup(Manager *m, FILE *serialization, FDSet *fds);
-
-Job *manager_get_job(Manager *m, uint32_t id);
-Unit *manager_get_unit(Manager *m, const char *name);
-
-int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j);
-
-int manager_load_unit_prepare(Manager *m, const char *name, const char *path, DBusError *e, Unit **_ret);
-int manager_load_unit(Manager *m, const char *name, const char *path, DBusError *e, Unit **_ret);
-int manager_load_unit_from_dbus_path(Manager *m, const char *s, DBusError *e, Unit **_u);
-
-int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool force, DBusError *e, Job **_ret);
-int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, bool force, DBusError *e, Job **_ret);
-
-void manager_dump_units(Manager *s, FILE *f, const char *prefix);
-void manager_dump_jobs(Manager *s, FILE *f, const char *prefix);
-
-void manager_clear_jobs(Manager *m);
-
-unsigned manager_dispatch_load_queue(Manager *m);
-unsigned manager_dispatch_run_queue(Manager *m);
-unsigned manager_dispatch_dbus_queue(Manager *m);
-
-int manager_set_default_controllers(Manager *m, char **controllers);
-int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit);
-
-int manager_loop(Manager *m);
-
-void manager_dispatch_bus_name_owner_changed(Manager *m, const char *name, const char* old_owner, const char *new_owner);
-void manager_dispatch_bus_query_pid_done(Manager *m, const char *name, pid_t pid);
-
-int manager_open_serialization(Manager *m, FILE **_f);
-
-int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool serialize_jobs);
-int manager_deserialize(Manager *m, FILE *f, FDSet *fds);
-
-int manager_reload(Manager *m);
-
-bool manager_is_booting_or_shutting_down(Manager *m);
-
-void manager_reset_failed(Manager *m);
-
-void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success);
-void manager_send_unit_plymouth(Manager *m, Unit *u);
-
-bool manager_unit_pending_inactive(Manager *m, const char *name);
-
-void manager_check_finished(Manager *m);
-
-void manager_run_generators(Manager *m);
-void manager_undo_generators(Manager *m);
-
-void manager_recheck_journal(Manager *m);
-
-void manager_set_show_status(Manager *m, bool b);
-bool manager_get_show_status(Manager *m);
diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c
deleted file mode 100644
index 98614d0c3e..0000000000
--- a/src/core/mount-setup.c
+++ /dev/null
@@ -1,441 +0,0 @@
-/*-*- 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/mount.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <string.h>
-#include <libgen.h>
-#include <assert.h>
-#include <unistd.h>
-#include <ftw.h>
-
-#include "mount-setup.h"
-#include "dev-setup.h"
-#include "log.h"
-#include "macro.h"
-#include "util.h"
-#include "label.h"
-#include "set.h"
-#include "strv.h"
-#include "mkdir.h"
-#include "path-util.h"
-#include "missing.h"
-#include "virt.h"
-
-#ifndef TTY_GID
-#define TTY_GID 5
-#endif
-
-typedef enum MountMode {
- MNT_NONE = 0,
- MNT_FATAL = 1 << 0,
- MNT_IN_CONTAINER = 1 << 1,
-} MountMode;
-
-typedef struct MountPoint {
- const char *what;
- const char *where;
- const char *type;
- const char *options;
- unsigned long flags;
- bool (*condition_fn)(void);
- MountMode mode;
-} MountPoint;
-
-/* The first three entries we might need before SELinux is up. The
- * fourth (securityfs) is needed by IMA to load a custom policy. The
- * other ones we can delay until SELinux and IMA are loaded. */
-#define N_EARLY_MOUNT 4
-
-static const MountPoint mount_table[] = {
- { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
- NULL, MNT_FATAL|MNT_IN_CONTAINER },
- { "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
- NULL, MNT_FATAL|MNT_IN_CONTAINER },
- { "devtmpfs", "/dev", "devtmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME,
- NULL, MNT_FATAL|MNT_IN_CONTAINER },
- { "securityfs", "/sys/kernel/security", "securityfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
- NULL, MNT_NONE },
- { "efivarfs", "/sys/firmware/efi/efivars", "efivarfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
- is_efiboot, MNT_NONE },
- { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME,
- NULL, MNT_FATAL|MNT_IN_CONTAINER },
- { "devpts", "/dev/pts", "devpts", "mode=620,gid=" STRINGIFY(TTY_GID), MS_NOSUID|MS_NOEXEC,
- NULL, MNT_IN_CONTAINER },
- { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME,
- NULL, MNT_FATAL|MNT_IN_CONTAINER },
- { "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME,
- NULL, MNT_IN_CONTAINER },
- { "cgroup", "/sys/fs/cgroup/systemd", "cgroup", "none,name=systemd", MS_NOSUID|MS_NOEXEC|MS_NODEV,
- NULL, MNT_IN_CONTAINER },
-};
-
-/* These are API file systems that might be mounted by other software,
- * we just list them here so that we know that we should ignore them */
-
-static const char ignore_paths[] =
- /* SELinux file systems */
- "/sys/fs/selinux\0"
- "/selinux\0"
- /* Legacy cgroup mount points */
- "/dev/cgroup\0"
- "/cgroup\0"
- /* Legacy kernel file system */
- "/proc/bus/usb\0"
- /* Container bind mounts */
- "/proc/sys\0"
- "/dev/console\0"
- "/proc/kmsg\0";
-
-bool mount_point_is_api(const char *path) {
- unsigned i;
-
- /* Checks if this mount point is considered "API", and hence
- * should be ignored */
-
- for (i = 0; i < ELEMENTSOF(mount_table); i ++)
- if (path_equal(path, mount_table[i].where))
- return true;
-
- return path_startswith(path, "/sys/fs/cgroup/");
-}
-
-bool mount_point_ignore(const char *path) {
- const char *i;
-
- NULSTR_FOREACH(i, ignore_paths)
- if (path_equal(path, i))
- return true;
-
- return false;
-}
-
-static int mount_one(const MountPoint *p, bool relabel) {
- int r;
-
- assert(p);
-
- if (p->condition_fn && !p->condition_fn())
- return 0;
-
- /* Relabel first, just in case */
- if (relabel)
- label_fix(p->where, true, true);
-
- r = path_is_mount_point(p->where, true);
- if (r < 0)
- return r;
-
- if (r > 0)
- return 0;
-
- /* Skip securityfs in a container */
- if (!(p->mode & MNT_IN_CONTAINER) && detect_container(NULL) > 0)
- return 0;
-
- /* The access mode here doesn't really matter too much, since
- * the mounted file system will take precedence anyway. */
- mkdir_p_label(p->where, 0755);
-
- log_debug("Mounting %s to %s of type %s with options %s.",
- p->what,
- p->where,
- p->type,
- strna(p->options));
-
- if (mount(p->what,
- p->where,
- p->type,
- p->flags,
- p->options) < 0) {
- log_full((p->mode & MNT_FATAL) ? LOG_ERR : LOG_DEBUG, "Failed to mount %s: %s", p->where, strerror(errno));
- return (p->mode & MNT_FATAL) ? -errno : 0;
- }
-
- /* Relabel again, since we now mounted something fresh here */
- if (relabel)
- label_fix(p->where, false, false);
-
- return 1;
-}
-
-int mount_setup_early(void) {
- unsigned i;
- int r = 0;
-
- assert_cc(N_EARLY_MOUNT <= ELEMENTSOF(mount_table));
-
- /* Do a minimal mount of /proc and friends to enable the most
- * basic stuff, such as SELinux */
- for (i = 0; i < N_EARLY_MOUNT; i ++) {
- int j;
-
- j = mount_one(mount_table + i, false);
- if (r == 0)
- r = j;
- }
-
- return r;
-}
-
-int mount_cgroup_controllers(char ***join_controllers) {
- int r;
- FILE *f;
- char buf[LINE_MAX];
- Set *controllers;
-
- /* Mount all available cgroup controllers that are built into the kernel. */
-
- f = fopen("/proc/cgroups", "re");
- if (!f) {
- log_error("Failed to enumerate cgroup controllers: %m");
- return 0;
- }
-
- controllers = set_new(string_hash_func, string_compare_func);
- if (!controllers) {
- r = log_oom();
- goto finish;
- }
-
- /* Ignore the header line */
- (void) fgets(buf, sizeof(buf), f);
-
- for (;;) {
- char *controller;
- int enabled = 0;
-
- if (fscanf(f, "%ms %*i %*i %i", &controller, &enabled) != 2) {
-
- if (feof(f))
- break;
-
- log_error("Failed to parse /proc/cgroups.");
- r = -EIO;
- goto finish;
- }
-
- if (!enabled) {
- free(controller);
- continue;
- }
-
- r = set_put(controllers, controller);
- if (r < 0) {
- log_error("Failed to add controller to set.");
- free(controller);
- goto finish;
- }
- }
-
- for (;;) {
- MountPoint p;
- char *controller, *where, *options;
- char ***k = NULL;
-
- controller = set_steal_first(controllers);
- if (!controller)
- break;
-
- if (join_controllers)
- for (k = join_controllers; *k; k++)
- if (strv_find(*k, controller))
- break;
-
- if (k && *k) {
- char **i, **j;
-
- for (i = *k, j = *k; *i; i++) {
-
- if (!streq(*i, controller)) {
- char *t;
-
- t = set_remove(controllers, *i);
- if (!t) {
- free(*i);
- continue;
- }
- free(t);
- }
-
- *(j++) = *i;
- }
-
- *j = NULL;
-
- options = strv_join(*k, ",");
- if (!options) {
- free(controller);
- r = log_oom();
- goto finish;
- }
-
- } else {
- options = controller;
- controller = NULL;
- }
-
- where = strappend("/sys/fs/cgroup/", options);
- if (!where) {
- free(options);
- r = log_oom();
- goto finish;
- }
-
- zero(p);
- p.what = "cgroup";
- p.where = where;
- p.type = "cgroup";
- p.options = options;
- p.flags = MS_NOSUID|MS_NOEXEC|MS_NODEV;
-
- r = mount_one(&p, true);
- free(controller);
- free(where);
-
- if (r < 0) {
- free(options);
- goto finish;
- }
-
- if (r > 0 && k && *k) {
- char **i;
-
- for (i = *k; *i; i++) {
- char *t;
-
- t = strappend("/sys/fs/cgroup/", *i);
- if (!t) {
- r = log_oom();
- free(options);
- goto finish;
- }
-
- r = symlink(options, t);
- free(t);
-
- if (r < 0 && errno != EEXIST) {
- log_error("Failed to create symlink: %m");
- r = -errno;
- free(options);
- goto finish;
- }
- }
- }
-
- free(options);
- }
-
- r = 0;
-
-finish:
- set_free_free(controllers);
-
- fclose(f);
-
- return r;
-}
-
-static int nftw_cb(
- const char *fpath,
- const struct stat *sb,
- int tflag,
- struct FTW *ftwbuf) {
-
- /* No need to label /dev twice in a row... */
- if (_unlikely_(ftwbuf->level == 0))
- return FTW_CONTINUE;
-
- label_fix(fpath, false, false);
-
- /* /run/initramfs is static data and big, no need to
- * dynamically relabel its contents at boot... */
- if (_unlikely_(ftwbuf->level == 1 &&
- tflag == FTW_D &&
- streq(fpath, "/run/initramfs")))
- return FTW_SKIP_SUBTREE;
-
- return FTW_CONTINUE;
-};
-
-int mount_setup(bool loaded_policy) {
-
- static const char relabel[] =
- "/run/initramfs/root-fsck\0"
- "/run/initramfs/shutdown\0";
-
- int r;
- unsigned i;
- const char *j;
-
- for (i = 0; i < ELEMENTSOF(mount_table); i ++) {
- r = mount_one(mount_table + i, true);
-
- if (r < 0)
- return r;
- }
-
- /* Nodes in devtmpfs and /run need to be manually updated for
- * the appropriate labels, after mounting. The other virtual
- * API file systems like /sys and /proc do not need that, they
- * use the same label for all their files. */
- if (loaded_policy) {
- usec_t before_relabel, after_relabel;
- char timespan[FORMAT_TIMESPAN_MAX];
-
- before_relabel = now(CLOCK_MONOTONIC);
-
- nftw("/dev", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
- nftw("/run", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
-
- /* Explicitly relabel these */
- NULSTR_FOREACH(j, relabel)
- label_fix(j, true, false);
-
- after_relabel = now(CLOCK_MONOTONIC);
-
- log_info("Relabelled /dev and /run in %s.",
- format_timespan(timespan, sizeof(timespan), after_relabel - before_relabel));
- }
-
- /* Create a few default symlinks, which are normally created
- * by udevd, but some scripts might need them before we start
- * udevd. */
- dev_setup(NULL);
-
- /* Mark the root directory as shared in regards to mount
- * propagation. The kernel defaults to "private", but we think
- * it makes more sense to have a default of "shared" so that
- * nspawn and the container tools work out of the box. If
- * specific setups need other settings they can reset the
- * propagation mode to private if needed. */
- if (detect_container(NULL) <= 0)
- if (mount(NULL, "/", NULL, MS_REC|MS_SHARED, NULL) < 0)
- log_warning("Failed to set up the root directory for shared mount propagation: %m");
-
- /* Create a few directories we always want around */
- mkdir_label("/run/systemd", 0755);
- mkdir_label("/run/systemd/system", 0755);
-
- return 0;
-}
diff --git a/src/core/mount-setup.h b/src/core/mount-setup.h
deleted file mode 100644
index 4b521ad0e1..0000000000
--- a/src/core/mount-setup.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*-*- 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 mount_setup_early(void);
-
-int mount_setup(bool loaded_policy);
-
-int mount_cgroup_controllers(char ***join_controllers);
-
-bool mount_point_is_api(const char *path);
-bool mount_point_ignore(const char *path);
diff --git a/src/core/mount.c b/src/core/mount.c
deleted file mode 100644
index 14f4863dc6..0000000000
--- a/src/core/mount.c
+++ /dev/null
@@ -1,1885 +0,0 @@
-/*-*- 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 <errno.h>
-#include <stdio.h>
-#include <mntent.h>
-#include <sys/epoll.h>
-#include <signal.h>
-
-#include "unit.h"
-#include "mount.h"
-#include "load-fragment.h"
-#include "load-dropin.h"
-#include "log.h"
-#include "strv.h"
-#include "mkdir.h"
-#include "path-util.h"
-#include "mount-setup.h"
-#include "unit-name.h"
-#include "dbus-mount.h"
-#include "special.h"
-#include "bus-errors.h"
-#include "exit-status.h"
-#include "def.h"
-
-static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
- [MOUNT_DEAD] = UNIT_INACTIVE,
- [MOUNT_MOUNTING] = UNIT_ACTIVATING,
- [MOUNT_MOUNTING_DONE] = UNIT_ACTIVE,
- [MOUNT_MOUNTED] = UNIT_ACTIVE,
- [MOUNT_REMOUNTING] = UNIT_RELOADING,
- [MOUNT_UNMOUNTING] = UNIT_DEACTIVATING,
- [MOUNT_MOUNTING_SIGTERM] = UNIT_DEACTIVATING,
- [MOUNT_MOUNTING_SIGKILL] = UNIT_DEACTIVATING,
- [MOUNT_REMOUNTING_SIGTERM] = UNIT_RELOADING,
- [MOUNT_REMOUNTING_SIGKILL] = UNIT_RELOADING,
- [MOUNT_UNMOUNTING_SIGTERM] = UNIT_DEACTIVATING,
- [MOUNT_UNMOUNTING_SIGKILL] = UNIT_DEACTIVATING,
- [MOUNT_FAILED] = UNIT_FAILED
-};
-
-static void mount_init(Unit *u) {
- Mount *m = MOUNT(u);
-
- assert(u);
- assert(u->load_state == UNIT_STUB);
-
- m->timeout_usec = DEFAULT_TIMEOUT_USEC;
- m->directory_mode = 0755;
-
- exec_context_init(&m->exec_context);
-
- if (unit_has_name(u, "-.mount")) {
- /* Don't allow start/stop for root directory */
- UNIT(m)->refuse_manual_start = true;
- UNIT(m)->refuse_manual_stop = true;
- } else {
- /* The stdio/kmsg bridge socket is on /, in order to avoid a
- * dep loop, don't use kmsg logging for -.mount */
- m->exec_context.std_output = u->manager->default_std_output;
- m->exec_context.std_error = u->manager->default_std_error;
- }
-
- kill_context_init(&m->kill_context);
-
- /* We need to make sure that /bin/mount is always called in
- * the same process group as us, so that the autofs kernel
- * side doesn't send us another mount request while we are
- * already trying to comply its last one. */
- m->exec_context.same_pgrp = true;
-
- m->timer_watch.type = WATCH_INVALID;
-
- m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
-
- UNIT(m)->ignore_on_isolate = true;
-}
-
-static void mount_unwatch_control_pid(Mount *m) {
- assert(m);
-
- if (m->control_pid <= 0)
- return;
-
- unit_unwatch_pid(UNIT(m), m->control_pid);
- m->control_pid = 0;
-}
-
-static void mount_parameters_done(MountParameters *p) {
- assert(p);
-
- free(p->what);
- free(p->options);
- free(p->fstype);
-
- p->what = p->options = p->fstype = NULL;
-}
-
-static void mount_done(Unit *u) {
- Mount *m = MOUNT(u);
-
- assert(m);
-
- free(m->where);
- m->where = NULL;
-
- mount_parameters_done(&m->parameters_proc_self_mountinfo);
- mount_parameters_done(&m->parameters_fragment);
-
- exec_context_done(&m->exec_context);
- exec_command_done_array(m->exec_command, _MOUNT_EXEC_COMMAND_MAX);
- m->control_command = NULL;
-
- mount_unwatch_control_pid(m);
-
- unit_unwatch_timer(u, &m->timer_watch);
-}
-
-static MountParameters* get_mount_parameters_fragment(Mount *m) {
- assert(m);
-
- if (m->from_fragment)
- return &m->parameters_fragment;
-
- return NULL;
-}
-
-static MountParameters* get_mount_parameters(Mount *m) {
- assert(m);
-
- if (m->from_proc_self_mountinfo)
- return &m->parameters_proc_self_mountinfo;
-
- return get_mount_parameters_fragment(m);
-}
-
-static int mount_add_mount_links(Mount *m) {
- Unit *other;
- int r;
- MountParameters *pm;
-
- assert(m);
-
- pm = get_mount_parameters_fragment(m);
-
- /* Adds in links to other mount points that might lie below or
- * above us in the hierarchy */
-
- LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_MOUNT]) {
- Mount *n = MOUNT(other);
- MountParameters *pn;
-
- if (n == m)
- continue;
-
- if (UNIT(n)->load_state != UNIT_LOADED)
- continue;
-
- pn = get_mount_parameters_fragment(n);
-
- if (path_startswith(m->where, n->where)) {
-
- if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, UNIT(n), true)) < 0)
- return r;
-
- if (pn)
- if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, UNIT(n), true)) < 0)
- return r;
-
- } else if (path_startswith(n->where, m->where)) {
-
- if ((r = unit_add_dependency(UNIT(n), UNIT_AFTER, UNIT(m), true)) < 0)
- return r;
-
- if (pm)
- if ((r = unit_add_dependency(UNIT(n), UNIT_REQUIRES, UNIT(m), true)) < 0)
- return r;
-
- } else if (pm && pm->what && path_startswith(pm->what, n->where)) {
-
- if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, UNIT(n), true)) < 0)
- return r;
-
- if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, UNIT(n), true)) < 0)
- return r;
-
- } else if (pn && pn->what && path_startswith(pn->what, m->where)) {
-
- if ((r = unit_add_dependency(UNIT(n), UNIT_AFTER, UNIT(m), true)) < 0)
- return r;
-
- if ((r = unit_add_dependency(UNIT(n), UNIT_REQUIRES, UNIT(m), true)) < 0)
- return r;
- }
- }
-
- return 0;
-}
-
-static int mount_add_swap_links(Mount *m) {
- Unit *other;
- int r;
-
- assert(m);
-
- LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_SWAP])
- if ((r = swap_add_one_mount_link(SWAP(other), m)) < 0)
- return r;
-
- return 0;
-}
-
-static int mount_add_path_links(Mount *m) {
- Unit *other;
- int r;
-
- assert(m);
-
- LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_PATH])
- if ((r = path_add_one_mount_link(PATH(other), m)) < 0)
- return r;
-
- return 0;
-}
-
-static int mount_add_automount_links(Mount *m) {
- Unit *other;
- int r;
-
- assert(m);
-
- LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_AUTOMOUNT])
- if ((r = automount_add_one_mount_link(AUTOMOUNT(other), m)) < 0)
- return r;
-
- return 0;
-}
-
-static int mount_add_socket_links(Mount *m) {
- Unit *other;
- int r;
-
- assert(m);
-
- LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_SOCKET])
- if ((r = socket_add_one_mount_link(SOCKET(other), m)) < 0)
- return r;
-
- return 0;
-}
-
-static int mount_add_requires_mounts_links(Mount *m) {
- Unit *other;
- int r;
-
- assert(m);
-
- LIST_FOREACH(has_requires_mounts_for, other, UNIT(m)->manager->has_requires_mounts_for) {
- r = unit_add_one_mount_link(other, m);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-static char* mount_test_option(const char *haystack, const char *needle) {
- struct mntent me;
-
- assert(needle);
-
- /* Like glibc's hasmntopt(), but works on a string, not a
- * struct mntent */
-
- if (!haystack)
- return NULL;
-
- zero(me);
- me.mnt_opts = (char*) haystack;
-
- return hasmntopt(&me, needle);
-}
-
-static bool mount_is_network(MountParameters *p) {
- assert(p);
-
- if (mount_test_option(p->options, "_netdev"))
- return true;
-
- if (p->fstype && fstype_is_network(p->fstype))
- return true;
-
- return false;
-}
-
-static bool mount_is_bind(MountParameters *p) {
- assert(p);
-
- if (mount_test_option(p->options, "bind"))
- return true;
-
- if (p->fstype && streq(p->fstype, "bind"))
- return true;
-
- return false;
-}
-
-static bool needs_quota(MountParameters *p) {
- assert(p);
-
- if (mount_is_network(p))
- return false;
-
- if (mount_is_bind(p))
- return false;
-
- return mount_test_option(p->options, "usrquota") ||
- mount_test_option(p->options, "grpquota") ||
- mount_test_option(p->options, "quota") ||
- mount_test_option(p->options, "usrjquota") ||
- mount_test_option(p->options, "grpjquota");
-}
-
-static int mount_add_device_links(Mount *m) {
- MountParameters *p;
- int r;
-
- assert(m);
-
- p = get_mount_parameters_fragment(m);
- if (!p)
- return 0;
-
- if (!p->what)
- return 0;
-
- if (mount_is_bind(p))
- return 0;
-
- if (!is_device_path(p->what))
- return 0;
-
- if (path_equal(m->where, "/"))
- return 0;
-
- r = unit_add_node_link(UNIT(m), p->what, false);
- if (r < 0)
- return r;
-
- if (p->passno > 0 &&
- UNIT(m)->manager->running_as == SYSTEMD_SYSTEM) {
- char *name;
- Unit *fsck;
- /* Let's add in the fsck service */
-
- /* aka SPECIAL_FSCK_SERVICE */
- name = unit_name_from_path_instance("systemd-fsck", p->what, ".service");
- if (!name)
- return -ENOMEM;
-
- r = manager_load_unit_prepare(UNIT(m)->manager, name, NULL, NULL, &fsck);
- if (r < 0) {
- log_warning("Failed to prepare unit %s: %s", name, strerror(-r));
- free(name);
- return r;
- }
- free(name);
-
- SERVICE(fsck)->fsck_passno = p->passno;
-
- r = unit_add_two_dependencies(UNIT(m), UNIT_AFTER, UNIT_REQUIRES, fsck, true);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-static int mount_add_quota_links(Mount *m) {
- int r;
- MountParameters *p;
-
- assert(m);
-
- if (UNIT(m)->manager->running_as != SYSTEMD_SYSTEM)
- return 0;
-
- p = get_mount_parameters_fragment(m);
- if (!p)
- return 0;
-
- if (!needs_quota(p))
- return 0;
-
- r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTACHECK_SERVICE, NULL, true);
- if (r < 0)
- return r;
-
- r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTAON_SERVICE, NULL, true);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static int mount_add_default_dependencies(Mount *m) {
- int r;
- MountParameters *p;
- const char *after;
-
- assert(m);
-
- if (UNIT(m)->manager->running_as != SYSTEMD_SYSTEM)
- return 0;
-
- p = get_mount_parameters_fragment(m);
- if (!p)
- return 0;
-
- if (path_equal(m->where, "/"))
- return 0;
-
- if (mount_is_network(p))
- after = SPECIAL_REMOTE_FS_PRE_TARGET;
- else
- after = SPECIAL_LOCAL_FS_PRE_TARGET;
-
- r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_WANTS, UNIT_AFTER, after, NULL, true);
- if (r < 0)
- return r;
-
- r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static int mount_fix_timeouts(Mount *m) {
- MountParameters *p;
- const char *timeout = NULL;
- Unit *other;
- Iterator i;
- usec_t u;
- char *t;
- int r;
-
- assert(m);
-
- p = get_mount_parameters_fragment(m);
- if (!p)
- return 0;
-
- /* Allow configuration how long we wait for a device that
- * backs a mount point to show up. This is useful to support
- * endless device timeouts for devices that show up only after
- * user input, like crypto devices. */
-
- if ((timeout = mount_test_option(p->options, "comment=systemd.device-timeout")))
- timeout += 31;
- else if ((timeout = mount_test_option(p->options, "x-systemd.device-timeout")))
- timeout += 25;
- else
- return 0;
-
- t = strndup(timeout, strcspn(timeout, ",;" WHITESPACE));
- if (!t)
- return -ENOMEM;
-
- r = parse_usec(t, &u);
- free(t);
-
- if (r < 0) {
- log_warning("Failed to parse timeout for %s, ignoring: %s", m->where, timeout);
- return r;
- }
-
- SET_FOREACH(other, UNIT(m)->dependencies[UNIT_AFTER], i) {
- if (other->type != UNIT_DEVICE)
- continue;
-
- other->job_timeout = u;
- }
-
- return 0;
-}
-
-static int mount_verify(Mount *m) {
- bool b;
- char *e;
- assert(m);
-
- if (UNIT(m)->load_state != UNIT_LOADED)
- return 0;
-
- if (!m->from_fragment && !m->from_proc_self_mountinfo)
- return -ENOENT;
-
- if (!(e = unit_name_from_path(m->where, ".mount")))
- return -ENOMEM;
-
- b = unit_has_name(UNIT(m), e);
- free(e);
-
- if (!b) {
- log_error("%s's Where setting doesn't match unit name. Refusing.", UNIT(m)->id);
- return -EINVAL;
- }
-
- if (mount_point_is_api(m->where) || mount_point_ignore(m->where)) {
- log_error("Cannot create mount unit for API file system %s. Refusing.", m->where);
- return -EINVAL;
- }
-
- if (UNIT(m)->fragment_path && !m->parameters_fragment.what) {
- log_error("%s's What setting is missing. Refusing.", UNIT(m)->id);
- return -EBADMSG;
- }
-
- if (m->exec_context.pam_name && m->kill_context.kill_mode != KILL_CONTROL_GROUP) {
- log_error("%s has PAM enabled. Kill mode must be set to 'control-group'. Refusing.", UNIT(m)->id);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int mount_add_extras(Mount *m) {
- Unit *u = UNIT(m);
- int r;
-
- if (UNIT(m)->fragment_path)
- m->from_fragment = true;
-
- if (!m->where) {
- m->where = unit_name_to_path(u->id);
- if (!m->where)
- return -ENOMEM;
- }
-
- path_kill_slashes(m->where);
-
- r = unit_add_exec_dependencies(u, &m->exec_context);
- if (r < 0)
- return r;
-
- if (!UNIT(m)->description) {
- r = unit_set_description(u, m->where);
- if (r < 0)
- return r;
- }
-
- r = mount_add_device_links(m);
- if (r < 0)
- return r;
-
- r = mount_add_mount_links(m);
- if (r < 0)
- return r;
-
- r = mount_add_socket_links(m);
- if (r < 0)
- return r;
-
- r = mount_add_swap_links(m);
- if (r < 0)
- return r;
-
- r = mount_add_path_links(m);
- if (r < 0)
- return r;
-
- r = mount_add_requires_mounts_links(m);
- if (r < 0)
- return r;
-
- r = mount_add_automount_links(m);
- if (r < 0)
- return r;
-
- r = mount_add_quota_links(m);
- if (r < 0)
- return r;
-
- if (UNIT(m)->default_dependencies) {
- r = mount_add_default_dependencies(m);
- if (r < 0)
- return r;
- }
-
- r = unit_add_default_cgroups(u);
- if (r < 0)
- return r;
-
- r = mount_fix_timeouts(m);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static int mount_load(Unit *u) {
- Mount *m = MOUNT(u);
- int r;
-
- assert(u);
- assert(u->load_state == UNIT_STUB);
-
- if (m->from_proc_self_mountinfo)
- r = unit_load_fragment_and_dropin_optional(u);
- else
- r = unit_load_fragment_and_dropin(u);
-
- if (r < 0)
- return r;
-
- /* This is a new unit? Then let's add in some extras */
- if (u->load_state == UNIT_LOADED) {
- r = mount_add_extras(m);
- if (r < 0)
- return r;
-
- r = unit_exec_context_defaults(u, &m->exec_context);
- if (r < 0)
- return r;
- }
-
- return mount_verify(m);
-}
-
-static int mount_notify_automount(Mount *m, int status) {
- Unit *p;
- int r;
- Iterator i;
-
- assert(m);
-
- SET_FOREACH(p, UNIT(m)->dependencies[UNIT_TRIGGERED_BY], i)
- if (p->type == UNIT_AUTOMOUNT) {
- r = automount_send_ready(AUTOMOUNT(p), status);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-static void mount_set_state(Mount *m, MountState state) {
- MountState old_state;
- assert(m);
-
- old_state = m->state;
- m->state = state;
-
- if (state != MOUNT_MOUNTING &&
- state != MOUNT_MOUNTING_DONE &&
- state != MOUNT_REMOUNTING &&
- state != MOUNT_UNMOUNTING &&
- state != MOUNT_MOUNTING_SIGTERM &&
- state != MOUNT_MOUNTING_SIGKILL &&
- state != MOUNT_UNMOUNTING_SIGTERM &&
- state != MOUNT_UNMOUNTING_SIGKILL &&
- state != MOUNT_REMOUNTING_SIGTERM &&
- state != MOUNT_REMOUNTING_SIGKILL) {
- unit_unwatch_timer(UNIT(m), &m->timer_watch);
- mount_unwatch_control_pid(m);
- m->control_command = NULL;
- m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
- }
-
- if (state == MOUNT_MOUNTED ||
- state == MOUNT_REMOUNTING)
- mount_notify_automount(m, 0);
- else if (state == MOUNT_DEAD ||
- state == MOUNT_UNMOUNTING ||
- state == MOUNT_MOUNTING_SIGTERM ||
- state == MOUNT_MOUNTING_SIGKILL ||
- state == MOUNT_REMOUNTING_SIGTERM ||
- state == MOUNT_REMOUNTING_SIGKILL ||
- state == MOUNT_UNMOUNTING_SIGTERM ||
- state == MOUNT_UNMOUNTING_SIGKILL ||
- state == MOUNT_FAILED) {
- if (state != old_state)
- mount_notify_automount(m, -ENODEV);
- }
-
- if (state != old_state)
- log_debug("%s changed %s -> %s",
- UNIT(m)->id,
- mount_state_to_string(old_state),
- mount_state_to_string(state));
-
- unit_notify(UNIT(m), state_translation_table[old_state], state_translation_table[state], m->reload_result == MOUNT_SUCCESS);
- m->reload_result = MOUNT_SUCCESS;
-}
-
-static int mount_coldplug(Unit *u) {
- Mount *m = MOUNT(u);
- MountState new_state = MOUNT_DEAD;
- int r;
-
- assert(m);
- assert(m->state == MOUNT_DEAD);
-
- if (m->deserialized_state != m->state)
- new_state = m->deserialized_state;
- else if (m->from_proc_self_mountinfo)
- new_state = MOUNT_MOUNTED;
-
- if (new_state != m->state) {
-
- 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 ((r = unit_watch_pid(UNIT(m), m->control_pid)) < 0)
- return r;
-
- if ((r = unit_watch_timer(UNIT(m), m->timeout_usec, &m->timer_watch)) < 0)
- return r;
- }
-
- mount_set_state(m, new_state);
- }
-
- return 0;
-}
-
-static void mount_dump(Unit *u, FILE *f, const char *prefix) {
- Mount *m = MOUNT(u);
- MountParameters *p;
-
- assert(m);
- assert(f);
-
- p = get_mount_parameters(m);
-
- fprintf(f,
- "%sMount State: %s\n"
- "%sResult: %s\n"
- "%sWhere: %s\n"
- "%sWhat: %s\n"
- "%sFile System Type: %s\n"
- "%sOptions: %s\n"
- "%sFrom /proc/self/mountinfo: %s\n"
- "%sFrom fragment: %s\n"
- "%sDirectoryMode: %04o\n",
- prefix, mount_state_to_string(m->state),
- prefix, mount_result_to_string(m->result),
- prefix, m->where,
- prefix, strna(p->what),
- prefix, strna(p->fstype),
- prefix, strna(p->options),
- prefix, yes_no(m->from_proc_self_mountinfo),
- prefix, yes_no(m->from_fragment),
- prefix, m->directory_mode);
-
- if (m->control_pid > 0)
- fprintf(f,
- "%sControl PID: %lu\n",
- prefix, (unsigned long) m->control_pid);
-
- exec_context_dump(&m->exec_context, f, prefix);
- kill_context_dump(&m->kill_context, f, prefix);
-}
-
-static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
- pid_t pid;
- int r;
-
- assert(m);
- assert(c);
- assert(_pid);
-
- if ((r = unit_watch_timer(UNIT(m), m->timeout_usec, &m->timer_watch)) < 0)
- goto fail;
-
- if ((r = exec_spawn(c,
- NULL,
- &m->exec_context,
- NULL, 0,
- UNIT(m)->manager->environment,
- true,
- true,
- true,
- UNIT(m)->manager->confirm_spawn,
- UNIT(m)->cgroup_bondings,
- UNIT(m)->cgroup_attributes,
- NULL,
- UNIT(m)->id,
- NULL,
- &pid)) < 0)
- goto fail;
-
- if ((r = unit_watch_pid(UNIT(m), pid)) < 0)
- /* FIXME: we need to do something here */
- goto fail;
-
- *_pid = pid;
-
- return 0;
-
-fail:
- unit_unwatch_timer(UNIT(m), &m->timer_watch);
-
- return r;
-}
-
-static void mount_enter_dead(Mount *m, MountResult f) {
- assert(m);
-
- if (f != MOUNT_SUCCESS)
- m->result = f;
-
- mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD);
-}
-
-static void mount_enter_mounted(Mount *m, MountResult f) {
- assert(m);
-
- if (f != MOUNT_SUCCESS)
- m->result = f;
-
- mount_set_state(m, MOUNT_MOUNTED);
-}
-
-static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
- int r;
- Set *pid_set = NULL;
- bool wait_for_exit = false;
-
- assert(m);
-
- if (f != MOUNT_SUCCESS)
- m->result = f;
-
- if (m->kill_context.kill_mode != KILL_NONE) {
- int sig = (state == MOUNT_MOUNTING_SIGTERM ||
- state == MOUNT_UNMOUNTING_SIGTERM ||
- state == MOUNT_REMOUNTING_SIGTERM) ? m->kill_context.kill_signal : SIGKILL;
-
- if (m->control_pid > 0) {
- if (kill_and_sigcont(m->control_pid, sig) < 0 && errno != ESRCH)
-
- log_warning("Failed to kill control process %li: %m", (long) m->control_pid);
- else
- wait_for_exit = true;
- }
-
- if (m->kill_context.kill_mode == KILL_CONTROL_GROUP) {
-
- if (!(pid_set = set_new(trivial_hash_func, trivial_compare_func))) {
- r = -ENOMEM;
- goto fail;
- }
-
- /* Exclude the control pid from being killed via the cgroup */
- if (m->control_pid > 0)
- if ((r = set_put(pid_set, LONG_TO_PTR(m->control_pid))) < 0)
- goto fail;
-
- r = cgroup_bonding_kill_list(UNIT(m)->cgroup_bondings, sig, true, false, pid_set, NULL);
- if (r < 0) {
- if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
- log_warning("Failed to kill control group: %s", strerror(-r));
- } else if (r > 0)
- wait_for_exit = true;
-
- set_free(pid_set);
- pid_set = NULL;
- }
- }
-
- if (wait_for_exit) {
- if ((r = unit_watch_timer(UNIT(m), m->timeout_usec, &m->timer_watch)) < 0)
- goto fail;
-
- mount_set_state(m, state);
- } else if (state == MOUNT_REMOUNTING_SIGTERM || state == MOUNT_REMOUNTING_SIGKILL)
- mount_enter_mounted(m, MOUNT_SUCCESS);
- else
- mount_enter_dead(m, MOUNT_SUCCESS);
-
- return;
-
-fail:
- log_warning("%s failed to kill processes: %s", UNIT(m)->id, strerror(-r));
-
- if (state == MOUNT_REMOUNTING_SIGTERM || state == MOUNT_REMOUNTING_SIGKILL)
- mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES);
- else
- mount_enter_dead(m, MOUNT_FAILURE_RESOURCES);
-
- if (pid_set)
- set_free(pid_set);
-}
-
-static void mount_enter_unmounting(Mount *m) {
- int r;
-
- assert(m);
-
- m->control_command_id = MOUNT_EXEC_UNMOUNT;
- m->control_command = m->exec_command + MOUNT_EXEC_UNMOUNT;
-
- if ((r = exec_command_set(
- m->control_command,
- "/bin/umount",
- m->where,
- NULL)) < 0)
- goto fail;
-
- mount_unwatch_control_pid(m);
-
- if ((r = mount_spawn(m, m->control_command, &m->control_pid)) < 0)
- goto fail;
-
- mount_set_state(m, MOUNT_UNMOUNTING);
-
- return;
-
-fail:
- log_warning("%s failed to run 'umount' task: %s", UNIT(m)->id, strerror(-r));
- mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES);
-}
-
-static void mount_enter_mounting(Mount *m) {
- int r;
- MountParameters *p;
-
- assert(m);
-
- m->control_command_id = MOUNT_EXEC_MOUNT;
- m->control_command = m->exec_command + MOUNT_EXEC_MOUNT;
-
- mkdir_p_label(m->where, m->directory_mode);
-
- if (dir_is_empty(m->where) <= 0)
- log_notice("%s: Directory %s to mount over is not empty, mounting anyway. (To see the over-mounted files, please manually mount the underlying file system to a secondary location.)", m->meta.id, m->where);
-
- /* Create the source directory for bind-mounts if needed */
- p = get_mount_parameters_fragment(m);
- if (p && mount_is_bind(p))
- mkdir_p_label(p->what, m->directory_mode);
-
- if (m->from_fragment)
- r = exec_command_set(
- m->control_command,
- "/bin/mount",
- m->parameters_fragment.what,
- m->where,
- "-t", m->parameters_fragment.fstype ? m->parameters_fragment.fstype : "auto",
- m->parameters_fragment.options ? "-o" : NULL, m->parameters_fragment.options,
- NULL);
- else
- r = -ENOENT;
-
- if (r < 0)
- goto fail;
-
- mount_unwatch_control_pid(m);
-
- r = mount_spawn(m, m->control_command, &m->control_pid);
- if (r < 0)
- goto fail;
-
- mount_set_state(m, MOUNT_MOUNTING);
-
- return;
-
-fail:
- log_warning("%s failed to run 'mount' task: %s", UNIT(m)->id, strerror(-r));
- mount_enter_dead(m, MOUNT_FAILURE_RESOURCES);
-}
-
-static void mount_enter_mounting_done(Mount *m) {
- assert(m);
-
- mount_set_state(m, MOUNT_MOUNTING_DONE);
-}
-
-static void mount_enter_remounting(Mount *m) {
- int r;
-
- assert(m);
-
- m->control_command_id = MOUNT_EXEC_REMOUNT;
- m->control_command = m->exec_command + MOUNT_EXEC_REMOUNT;
-
- if (m->from_fragment) {
- char *buf = NULL;
- const char *o;
-
- if (m->parameters_fragment.options) {
- if (!(buf = strappend("remount,", m->parameters_fragment.options))) {
- r = -ENOMEM;
- goto fail;
- }
-
- o = buf;
- } else
- o = "remount";
-
- r = exec_command_set(
- m->control_command,
- "/bin/mount",
- m->parameters_fragment.what,
- m->where,
- "-t", m->parameters_fragment.fstype ? m->parameters_fragment.fstype : "auto",
- "-o", o,
- NULL);
-
- free(buf);
- } else
- r = -ENOENT;
-
- if (r < 0)
- goto fail;
-
- mount_unwatch_control_pid(m);
-
- if ((r = mount_spawn(m, m->control_command, &m->control_pid)) < 0)
- goto fail;
-
- mount_set_state(m, MOUNT_REMOUNTING);
-
- return;
-
-fail:
- log_warning("%s failed to run 'remount' task: %s", UNIT(m)->id, strerror(-r));
- m->reload_result = MOUNT_FAILURE_RESOURCES;
- mount_enter_mounted(m, MOUNT_SUCCESS);
-}
-
-static int mount_start(Unit *u) {
- Mount *m = MOUNT(u);
-
- assert(m);
-
- /* We cannot fulfill this request right now, try again later
- * please! */
- if (m->state == MOUNT_UNMOUNTING ||
- m->state == MOUNT_UNMOUNTING_SIGTERM ||
- m->state == MOUNT_UNMOUNTING_SIGKILL ||
- m->state == MOUNT_MOUNTING_SIGTERM ||
- m->state == MOUNT_MOUNTING_SIGKILL)
- return -EAGAIN;
-
- /* Already on it! */
- if (m->state == MOUNT_MOUNTING)
- return 0;
-
- assert(m->state == MOUNT_DEAD || m->state == MOUNT_FAILED);
-
- m->result = MOUNT_SUCCESS;
- m->reload_result = MOUNT_SUCCESS;
-
- mount_enter_mounting(m);
- return 0;
-}
-
-static int mount_stop(Unit *u) {
- Mount *m = MOUNT(u);
-
- assert(m);
-
- /* Already on it */
- if (m->state == MOUNT_UNMOUNTING ||
- m->state == MOUNT_UNMOUNTING_SIGKILL ||
- m->state == MOUNT_UNMOUNTING_SIGTERM ||
- m->state == MOUNT_MOUNTING_SIGTERM ||
- m->state == MOUNT_MOUNTING_SIGKILL)
- return 0;
-
- assert(m->state == MOUNT_MOUNTING ||
- m->state == MOUNT_MOUNTING_DONE ||
- m->state == MOUNT_MOUNTED ||
- m->state == MOUNT_REMOUNTING ||
- m->state == MOUNT_REMOUNTING_SIGTERM ||
- m->state == MOUNT_REMOUNTING_SIGKILL);
-
- mount_enter_unmounting(m);
- return 0;
-}
-
-static int mount_reload(Unit *u) {
- Mount *m = MOUNT(u);
-
- assert(m);
-
- if (m->state == MOUNT_MOUNTING_DONE)
- return -EAGAIN;
-
- assert(m->state == MOUNT_MOUNTED);
-
- mount_enter_remounting(m);
- return 0;
-}
-
-static int mount_serialize(Unit *u, FILE *f, FDSet *fds) {
- Mount *m = MOUNT(u);
-
- assert(m);
- assert(f);
- assert(fds);
-
- unit_serialize_item(u, f, "state", mount_state_to_string(m->state));
- unit_serialize_item(u, f, "result", mount_result_to_string(m->result));
- unit_serialize_item(u, f, "reload-result", mount_result_to_string(m->reload_result));
-
- if (m->control_pid > 0)
- unit_serialize_item_format(u, f, "control-pid", "%lu", (unsigned long) m->control_pid);
-
- if (m->control_command_id >= 0)
- unit_serialize_item(u, f, "control-command", mount_exec_command_to_string(m->control_command_id));
-
- return 0;
-}
-
-static int mount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
- Mount *m = MOUNT(u);
-
- assert(u);
- assert(key);
- assert(value);
- assert(fds);
-
- if (streq(key, "state")) {
- MountState state;
-
- if ((state = mount_state_from_string(value)) < 0)
- log_debug("Failed to parse state value %s", value);
- else
- m->deserialized_state = state;
- } else if (streq(key, "result")) {
- MountResult f;
-
- f = mount_result_from_string(value);
- if (f < 0)
- log_debug("Failed to parse result value %s", value);
- else if (f != MOUNT_SUCCESS)
- m->result = f;
-
- } else if (streq(key, "reload-result")) {
- MountResult f;
-
- f = mount_result_from_string(value);
- if (f < 0)
- log_debug("Failed to parse reload result value %s", value);
- else if (f != MOUNT_SUCCESS)
- m->reload_result = f;
-
- } else if (streq(key, "control-pid")) {
- pid_t pid;
-
- if (parse_pid(value, &pid) < 0)
- log_debug("Failed to parse control-pid value %s", value);
- else
- m->control_pid = pid;
- } else if (streq(key, "control-command")) {
- MountExecCommand id;
-
- if ((id = mount_exec_command_from_string(value)) < 0)
- log_debug("Failed to parse exec-command value %s", value);
- else {
- m->control_command_id = id;
- m->control_command = m->exec_command + id;
- }
-
- } else
- log_debug("Unknown serialization key '%s'", key);
-
- return 0;
-}
-
-static UnitActiveState mount_active_state(Unit *u) {
- assert(u);
-
- return state_translation_table[MOUNT(u)->state];
-}
-
-static const char *mount_sub_state_to_string(Unit *u) {
- assert(u);
-
- return mount_state_to_string(MOUNT(u)->state);
-}
-
-static bool mount_check_gc(Unit *u) {
- Mount *m = MOUNT(u);
-
- assert(m);
-
- return m->from_proc_self_mountinfo;
-}
-
-static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
- Mount *m = MOUNT(u);
- MountResult f;
-
- assert(m);
- assert(pid >= 0);
-
- if (pid != m->control_pid)
- return;
-
- m->control_pid = 0;
-
- if (is_clean_exit(code, status, NULL))
- f = MOUNT_SUCCESS;
- else if (code == CLD_EXITED)
- f = MOUNT_FAILURE_EXIT_CODE;
- else if (code == CLD_KILLED)
- f = MOUNT_FAILURE_SIGNAL;
- else if (code == CLD_DUMPED)
- f = MOUNT_FAILURE_CORE_DUMP;
- else
- assert_not_reached("Unknown code");
-
- if (f != MOUNT_SUCCESS)
- m->result = f;
-
- if (m->control_command) {
- exec_status_exit(&m->control_command->exec_status, &m->exec_context, pid, code, status);
-
- m->control_command = NULL;
- m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
- }
-
- log_full(f == MOUNT_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
- "%s mount process exited, code=%s status=%i", u->id, sigchld_code_to_string(code), status);
-
- /* Note that mount(8) returning and the kernel sending us a
- * mount table change event might happen out-of-order. If an
- * operation succeed we assume the kernel will follow soon too
- * and already change into the resulting state. If it fails
- * we check if the kernel still knows about the mount. and
- * change state accordingly. */
-
- switch (m->state) {
-
- case MOUNT_MOUNTING:
- case MOUNT_MOUNTING_DONE:
- case MOUNT_MOUNTING_SIGKILL:
- case MOUNT_MOUNTING_SIGTERM:
-
- if (f == MOUNT_SUCCESS)
- mount_enter_mounted(m, f);
- else if (m->from_proc_self_mountinfo)
- mount_enter_mounted(m, f);
- else
- mount_enter_dead(m, f);
- break;
-
- case MOUNT_REMOUNTING:
- case MOUNT_REMOUNTING_SIGKILL:
- case MOUNT_REMOUNTING_SIGTERM:
-
- m->reload_result = f;
- if (m->from_proc_self_mountinfo)
- mount_enter_mounted(m, MOUNT_SUCCESS);
- else
- mount_enter_dead(m, MOUNT_SUCCESS);
-
- break;
-
- case MOUNT_UNMOUNTING:
- case MOUNT_UNMOUNTING_SIGKILL:
- case MOUNT_UNMOUNTING_SIGTERM:
-
- if (f == MOUNT_SUCCESS)
- mount_enter_dead(m, f);
- else if (m->from_proc_self_mountinfo)
- mount_enter_mounted(m, f);
- else
- mount_enter_dead(m, f);
- break;
-
- default:
- assert_not_reached("Uh, control process died at wrong time.");
- }
-
- /* Notify clients about changed exit status */
- unit_add_to_dbus_queue(u);
-}
-
-static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
- Mount *m = MOUNT(u);
-
- assert(m);
- assert(elapsed == 1);
- assert(w == &m->timer_watch);
-
- switch (m->state) {
-
- case MOUNT_MOUNTING:
- case MOUNT_MOUNTING_DONE:
- log_warning("%s mounting timed out. Stopping.", u->id);
- mount_enter_signal(m, MOUNT_MOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
- break;
-
- case MOUNT_REMOUNTING:
- log_warning("%s remounting timed out. Stopping.", u->id);
- m->reload_result = MOUNT_FAILURE_TIMEOUT;
- mount_enter_mounted(m, MOUNT_SUCCESS);
- break;
-
- case MOUNT_UNMOUNTING:
- log_warning("%s unmounting timed out. Stopping.", u->id);
- mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
- break;
-
- case MOUNT_MOUNTING_SIGTERM:
- if (m->kill_context.send_sigkill) {
- log_warning("%s mounting timed out. Killing.", u->id);
- mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
- } else {
- log_warning("%s mounting timed out. Skipping SIGKILL. Ignoring.", u->id);
-
- if (m->from_proc_self_mountinfo)
- mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
- else
- mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
- }
- break;
-
- case MOUNT_REMOUNTING_SIGTERM:
- if (m->kill_context.send_sigkill) {
- log_warning("%s remounting timed out. Killing.", u->id);
- mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
- } else {
- log_warning("%s remounting timed out. Skipping SIGKILL. Ignoring.", u->id);
-
- if (m->from_proc_self_mountinfo)
- mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
- else
- mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
- }
- break;
-
- case MOUNT_UNMOUNTING_SIGTERM:
- if (m->kill_context.send_sigkill) {
- log_warning("%s unmounting timed out. Killing.", u->id);
- mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
- } else {
- log_warning("%s unmounting timed out. Skipping SIGKILL. Ignoring.", u->id);
-
- if (m->from_proc_self_mountinfo)
- mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
- else
- mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
- }
- break;
-
- case MOUNT_MOUNTING_SIGKILL:
- case MOUNT_REMOUNTING_SIGKILL:
- case MOUNT_UNMOUNTING_SIGKILL:
- log_warning("%s mount process still around after SIGKILL. Ignoring.", u->id);
-
- if (m->from_proc_self_mountinfo)
- mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
- else
- mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
- break;
-
- default:
- assert_not_reached("Timeout at wrong time.");
- }
-}
-
-static int mount_add_one(
- Manager *m,
- const char *what,
- const char *where,
- const char *options,
- const char *fstype,
- int passno,
- bool set_flags) {
- int r;
- Unit *u;
- bool delete;
- char *e, *w = NULL, *o = NULL, *f = NULL;
- MountParameters *p;
- bool load_extras = false;
-
- assert(m);
- assert(what);
- assert(where);
- assert(options);
- assert(fstype);
-
- /* Ignore API mount points. They should never be referenced in
- * dependencies ever. */
- if (mount_point_is_api(where) || mount_point_ignore(where))
- return 0;
-
- if (streq(fstype, "autofs"))
- return 0;
-
- /* probably some kind of swap, ignore */
- if (!is_path(where))
- return 0;
-
- e = unit_name_from_path(where, ".mount");
- if (!e)
- return -ENOMEM;
-
- u = manager_get_unit(m, e);
- if (!u) {
- delete = true;
-
- u = unit_new(m, sizeof(Mount));
- if (!u) {
- free(e);
- return -ENOMEM;
- }
-
- r = unit_add_name(u, e);
- free(e);
-
- if (r < 0)
- goto fail;
-
- MOUNT(u)->where = strdup(where);
- if (!MOUNT(u)->where) {
- r = -ENOMEM;
- goto fail;
- }
-
- unit_add_to_load_queue(u);
- } else {
- delete = false;
- free(e);
-
- if (!MOUNT(u)->where) {
- MOUNT(u)->where = strdup(where);
- if (!MOUNT(u)->where) {
- r = -ENOMEM;
- goto fail;
- }
- }
-
- if (u->load_state == UNIT_ERROR) {
- u->load_state = UNIT_LOADED;
- u->load_error = 0;
-
- /* Load in the extras later on, after we
- * finished initialization of the unit */
- load_extras = true;
- }
- }
-
- if (!(w = strdup(what)) ||
- !(o = strdup(options)) ||
- !(f = strdup(fstype))) {
- r = -ENOMEM;
- goto fail;
- }
-
- p = &MOUNT(u)->parameters_proc_self_mountinfo;
- if (set_flags) {
- MOUNT(u)->is_mounted = true;
- MOUNT(u)->just_mounted = !MOUNT(u)->from_proc_self_mountinfo;
- MOUNT(u)->just_changed = !streq_ptr(p->options, o);
- }
-
- MOUNT(u)->from_proc_self_mountinfo = true;
-
- free(p->what);
- p->what = w;
-
- free(p->options);
- p->options = o;
-
- free(p->fstype);
- p->fstype = f;
-
- p->passno = passno;
-
- if (load_extras) {
- r = mount_add_extras(MOUNT(u));
- if (r < 0)
- goto fail;
- }
-
- unit_add_to_dbus_queue(u);
-
- return 0;
-
-fail:
- free(w);
- free(o);
- free(f);
-
- if (delete && u)
- unit_free(u);
-
- return r;
-}
-
-static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
- int r = 0;
- unsigned i;
- char *device, *path, *options, *options2, *fstype, *d, *p, *o;
-
- assert(m);
-
- rewind(m->proc_self_mountinfo);
-
- for (i = 1;; i++) {
- int k;
-
- device = path = options = options2 = fstype = d = p = o = NULL;
-
- if ((k = fscanf(m->proc_self_mountinfo,
- "%*s " /* (1) mount id */
- "%*s " /* (2) parent id */
- "%*s " /* (3) major:minor */
- "%*s " /* (4) root */
- "%ms " /* (5) mount point */
- "%ms" /* (6) mount options */
- "%*[^-]" /* (7) optional fields */
- "- " /* (8) separator */
- "%ms " /* (9) file system type */
- "%ms" /* (10) mount source */
- "%ms" /* (11) mount options 2 */
- "%*[^\n]", /* some rubbish at the end */
- &path,
- &options,
- &fstype,
- &device,
- &options2)) != 5) {
-
- if (k == EOF)
- break;
-
- log_warning("Failed to parse /proc/self/mountinfo:%u.", i);
- goto clean_up;
- }
-
- o = strjoin(options, ",", options2, NULL);
- if (!o) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (!(d = cunescape(device)) ||
- !(p = cunescape(path))) {
- r = -ENOMEM;
- goto finish;
- }
-
- if ((k = mount_add_one(m, d, p, o, fstype, 0, set_flags)) < 0)
- r = k;
-
-clean_up:
- free(device);
- free(path);
- free(options);
- free(options2);
- free(fstype);
- free(d);
- free(p);
- free(o);
- }
-
-finish:
- free(device);
- free(path);
- free(options);
- free(options2);
- free(fstype);
- free(d);
- free(p);
- free(o);
-
- return r;
-}
-
-static void mount_shutdown(Manager *m) {
- assert(m);
-
- if (m->proc_self_mountinfo) {
- fclose(m->proc_self_mountinfo);
- m->proc_self_mountinfo = NULL;
- }
-}
-
-static int mount_enumerate(Manager *m) {
- int r;
- struct epoll_event ev;
- assert(m);
-
- if (!m->proc_self_mountinfo) {
- if (!(m->proc_self_mountinfo = fopen("/proc/self/mountinfo", "re")))
- return -errno;
-
- m->mount_watch.type = WATCH_MOUNT;
- m->mount_watch.fd = fileno(m->proc_self_mountinfo);
-
- zero(ev);
- ev.events = EPOLLPRI;
- ev.data.ptr = &m->mount_watch;
-
- if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->mount_watch.fd, &ev) < 0)
- return -errno;
- }
-
- if ((r = mount_load_proc_self_mountinfo(m, false)) < 0)
- goto fail;
-
- return 0;
-
-fail:
- mount_shutdown(m);
- return r;
-}
-
-void mount_fd_event(Manager *m, int events) {
- Unit *u;
- int r;
-
- assert(m);
- assert(events & EPOLLPRI);
-
- /* The manager calls this for every fd event happening on the
- * /proc/self/mountinfo file, which informs us about mounting
- * table changes */
-
- if ((r = mount_load_proc_self_mountinfo(m, true)) < 0) {
- log_error("Failed to reread /proc/self/mountinfo: %s", strerror(-r));
-
- /* Reset flags, just in case, for later calls */
- LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) {
- Mount *mount = MOUNT(u);
-
- mount->is_mounted = mount->just_mounted = mount->just_changed = false;
- }
-
- return;
- }
-
- manager_dispatch_load_queue(m);
-
- LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) {
- Mount *mount = MOUNT(u);
-
- if (!mount->is_mounted) {
- /* This has just been unmounted. */
-
- mount->from_proc_self_mountinfo = false;
-
- switch (mount->state) {
-
- case MOUNT_MOUNTED:
- mount_enter_dead(mount, MOUNT_SUCCESS);
- break;
-
- default:
- mount_set_state(mount, mount->state);
- break;
-
- }
-
- } else if (mount->just_mounted || mount->just_changed) {
-
- /* New or changed mount entry */
-
- switch (mount->state) {
-
- case MOUNT_DEAD:
- case MOUNT_FAILED:
- mount_enter_mounted(mount, MOUNT_SUCCESS);
- break;
-
- case MOUNT_MOUNTING:
- mount_enter_mounting_done(mount);
- break;
-
- default:
- /* Nothing really changed, but let's
- * issue an notification call
- * nonetheless, in case somebody is
- * waiting for this. (e.g. file system
- * ro/rw remounts.) */
- mount_set_state(mount, mount->state);
- break;
- }
- }
-
- /* Reset the flags for later calls */
- mount->is_mounted = mount->just_mounted = mount->just_changed = false;
- }
-}
-
-static void mount_reset_failed(Unit *u) {
- Mount *m = MOUNT(u);
-
- assert(m);
-
- if (m->state == MOUNT_FAILED)
- mount_set_state(m, MOUNT_DEAD);
-
- m->result = MOUNT_SUCCESS;
- m->reload_result = MOUNT_SUCCESS;
-}
-
-static int mount_kill(Unit *u, KillWho who, int signo, DBusError *error) {
- Mount *m = MOUNT(u);
- int r = 0;
- Set *pid_set = NULL;
-
- assert(m);
-
- if (who == KILL_MAIN) {
- dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "Mount units have no main processes");
- return -ESRCH;
- }
-
- if (m->control_pid <= 0 && who == KILL_CONTROL) {
- dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
- return -ESRCH;
- }
-
- if (who == KILL_CONTROL || who == KILL_ALL)
- if (m->control_pid > 0)
- if (kill(m->control_pid, signo) < 0)
- r = -errno;
-
- if (who == KILL_ALL) {
- int q;
-
- pid_set = set_new(trivial_hash_func, trivial_compare_func);
- if (!pid_set)
- return -ENOMEM;
-
- /* Exclude the control pid from being killed via the cgroup */
- if (m->control_pid > 0) {
- q = set_put(pid_set, LONG_TO_PTR(m->control_pid));
- if (q < 0) {
- r = q;
- goto finish;
- }
- }
-
- q = cgroup_bonding_kill_list(UNIT(m)->cgroup_bondings, signo, false, false, pid_set, NULL);
- if (q < 0 && q != -EAGAIN && q != -ESRCH && q != -ENOENT)
- r = q;
- }
-
-finish:
- if (pid_set)
- set_free(pid_set);
-
- return r;
-}
-
-static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
- [MOUNT_DEAD] = "dead",
- [MOUNT_MOUNTING] = "mounting",
- [MOUNT_MOUNTING_DONE] = "mounting-done",
- [MOUNT_MOUNTED] = "mounted",
- [MOUNT_REMOUNTING] = "remounting",
- [MOUNT_UNMOUNTING] = "unmounting",
- [MOUNT_MOUNTING_SIGTERM] = "mounting-sigterm",
- [MOUNT_MOUNTING_SIGKILL] = "mounting-sigkill",
- [MOUNT_REMOUNTING_SIGTERM] = "remounting-sigterm",
- [MOUNT_REMOUNTING_SIGKILL] = "remounting-sigkill",
- [MOUNT_UNMOUNTING_SIGTERM] = "unmounting-sigterm",
- [MOUNT_UNMOUNTING_SIGKILL] = "unmounting-sigkill",
- [MOUNT_FAILED] = "failed"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState);
-
-static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = {
- [MOUNT_EXEC_MOUNT] = "ExecMount",
- [MOUNT_EXEC_UNMOUNT] = "ExecUnmount",
- [MOUNT_EXEC_REMOUNT] = "ExecRemount",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(mount_exec_command, MountExecCommand);
-
-static const char* const mount_result_table[_MOUNT_RESULT_MAX] = {
- [MOUNT_SUCCESS] = "success",
- [MOUNT_FAILURE_RESOURCES] = "resources",
- [MOUNT_FAILURE_TIMEOUT] = "timeout",
- [MOUNT_FAILURE_EXIT_CODE] = "exit-code",
- [MOUNT_FAILURE_SIGNAL] = "signal",
- [MOUNT_FAILURE_CORE_DUMP] = "core-dump"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(mount_result, MountResult);
-
-const UnitVTable mount_vtable = {
- .object_size = sizeof(Mount),
- .exec_context_offset = offsetof(Mount, exec_context),
-
- .sections =
- "Unit\0"
- "Mount\0"
- "Install\0",
-
- .no_alias = true,
- .no_instances = true,
-
- .init = mount_init,
- .load = mount_load,
- .done = mount_done,
-
- .coldplug = mount_coldplug,
-
- .dump = mount_dump,
-
- .start = mount_start,
- .stop = mount_stop,
- .reload = mount_reload,
-
- .kill = mount_kill,
-
- .serialize = mount_serialize,
- .deserialize_item = mount_deserialize_item,
-
- .active_state = mount_active_state,
- .sub_state_to_string = mount_sub_state_to_string,
-
- .check_gc = mount_check_gc,
-
- .sigchld_event = mount_sigchld_event,
- .timer_event = mount_timer_event,
-
- .reset_failed = mount_reset_failed,
-
- .bus_interface = "org.freedesktop.systemd1.Mount",
- .bus_message_handler = bus_mount_message_handler,
- .bus_invalidating_properties = bus_mount_invalidating_properties,
-
- .enumerate = mount_enumerate,
- .shutdown = mount_shutdown,
-
- .status_message_formats = {
- .starting_stopping = {
- [0] = "Mounting %s...",
- [1] = "Unmounting %s...",
- },
- .finished_start_job = {
- [JOB_DONE] = "Mounted %s.",
- [JOB_FAILED] = "Failed to mount %s.",
- [JOB_DEPENDENCY] = "Dependency failed for %s.",
- [JOB_TIMEOUT] = "Timed out mounting %s.",
- },
- .finished_stop_job = {
- [JOB_DONE] = "Unmounted %s.",
- [JOB_FAILED] = "Failed unmounting %s.",
- [JOB_TIMEOUT] = "Timed out unmounting %s.",
- },
- },
-};
diff --git a/src/core/mount.h b/src/core/mount.h
deleted file mode 100644
index 67d6132a5d..0000000000
--- a/src/core/mount.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*-*- 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/>.
-***/
-
-typedef struct Mount Mount;
-
-#include "unit.h"
-#include "kill.h"
-
-typedef enum MountState {
- MOUNT_DEAD,
- MOUNT_MOUNTING, /* /bin/mount is running, but the mount is not done yet. */
- MOUNT_MOUNTING_DONE, /* /bin/mount is running, and the mount is done. */
- MOUNT_MOUNTED,
- MOUNT_REMOUNTING,
- MOUNT_UNMOUNTING,
- MOUNT_MOUNTING_SIGTERM,
- MOUNT_MOUNTING_SIGKILL,
- MOUNT_REMOUNTING_SIGTERM,
- MOUNT_REMOUNTING_SIGKILL,
- MOUNT_UNMOUNTING_SIGTERM,
- MOUNT_UNMOUNTING_SIGKILL,
- MOUNT_FAILED,
- _MOUNT_STATE_MAX,
- _MOUNT_STATE_INVALID = -1
-} MountState;
-
-typedef enum MountExecCommand {
- MOUNT_EXEC_MOUNT,
- MOUNT_EXEC_UNMOUNT,
- MOUNT_EXEC_REMOUNT,
- _MOUNT_EXEC_COMMAND_MAX,
- _MOUNT_EXEC_COMMAND_INVALID = -1
-} MountExecCommand;
-
-typedef struct MountParameters {
- char *what;
- char *options;
- char *fstype;
- int passno;
-} MountParameters;
-
-typedef enum MountResult {
- MOUNT_SUCCESS,
- MOUNT_FAILURE_RESOURCES,
- MOUNT_FAILURE_TIMEOUT,
- MOUNT_FAILURE_EXIT_CODE,
- MOUNT_FAILURE_SIGNAL,
- MOUNT_FAILURE_CORE_DUMP,
- _MOUNT_RESULT_MAX,
- _MOUNT_RESULT_INVALID = -1
-} MountResult;
-
-struct Mount {
- Unit meta;
-
- char *where;
-
- MountParameters parameters_proc_self_mountinfo;
- MountParameters parameters_fragment;
-
- bool from_proc_self_mountinfo:1;
- bool from_fragment:1;
-
- /* Used while looking for mount points that vanished or got
- * added from/to /proc/self/mountinfo */
- bool is_mounted:1;
- bool just_mounted:1;
- bool just_changed:1;
-
- MountResult result;
- MountResult reload_result;
-
- mode_t directory_mode;
-
- usec_t timeout_usec;
-
- ExecCommand exec_command[_MOUNT_EXEC_COMMAND_MAX];
- ExecContext exec_context;
- KillContext kill_context;
-
- MountState state, deserialized_state;
-
- ExecCommand* control_command;
- MountExecCommand control_command_id;
- pid_t control_pid;
-
- Watch timer_watch;
-};
-
-extern const UnitVTable mount_vtable;
-
-void mount_fd_event(Manager *m, int events);
-
-const char* mount_state_to_string(MountState i);
-MountState mount_state_from_string(const char *s);
-
-const char* mount_exec_command_to_string(MountExecCommand i);
-MountExecCommand mount_exec_command_from_string(const char *s);
-
-const char* mount_result_to_string(MountResult i);
-MountResult mount_result_from_string(const char *s);
diff --git a/src/core/namespace.c b/src/core/namespace.c
deleted file mode 100644
index ba18ddc5b0..0000000000
--- a/src/core/namespace.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/*-*- 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 <errno.h>
-#include <sys/mount.h>
-#include <string.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sched.h>
-#include <sys/syscall.h>
-#include <limits.h>
-#include <linux/fs.h>
-
-#include "strv.h"
-#include "util.h"
-#include "path-util.h"
-#include "namespace.h"
-#include "missing.h"
-
-typedef enum PathMode {
- /* This is ordered by priority! */
- INACCESSIBLE,
- READONLY,
- PRIVATE_TMP,
- PRIVATE_VAR_TMP,
- READWRITE
-} PathMode;
-
-typedef struct Path {
- const char *path;
- PathMode mode;
- bool done;
-} Path;
-
-static int append_paths(Path **p, char **strv, PathMode mode) {
- char **i;
-
- STRV_FOREACH(i, strv) {
-
- if (!path_is_absolute(*i))
- return -EINVAL;
-
- (*p)->path = *i;
- (*p)->mode = mode;
- (*p)++;
- }
-
- return 0;
-}
-
-static int path_compare(const void *a, const void *b) {
- const Path *p = a, *q = b;
-
- if (path_equal(p->path, q->path)) {
-
- /* If the paths are equal, check the mode */
- if (p->mode < q->mode)
- return -1;
-
- if (p->mode > q->mode)
- return 1;
-
- return 0;
- }
-
- /* If the paths are not equal, then order prefixes first */
- if (path_startswith(p->path, q->path))
- return 1;
-
- if (path_startswith(q->path, p->path))
- return -1;
-
- return 0;
-}
-
-static void drop_duplicates(Path *p, unsigned *n, bool *need_inaccessible) {
- Path *f, *t, *previous;
-
- assert(p);
- assert(n);
- assert(need_inaccessible);
-
- for (f = p, t = p, previous = NULL; f < p+*n; f++) {
-
- /* The first one wins */
- if (previous && path_equal(f->path, previous->path))
- continue;
-
- t->path = f->path;
- t->mode = f->mode;
-
- if (t->mode == INACCESSIBLE)
- *need_inaccessible = true;
-
- previous = t;
-
- t++;
- }
-
- *n = t - p;
-}
-
-static int apply_mount(
- Path *p,
- const char *tmp_dir,
- const char *var_tmp_dir,
- const char *inaccessible_dir) {
-
- const char *what;
- int r;
-
- assert(p);
-
- switch (p->mode) {
-
- case INACCESSIBLE:
- what = inaccessible_dir;
- break;
-
- case READONLY:
- case READWRITE:
- what = p->path;
- break;
-
- case PRIVATE_TMP:
- what = tmp_dir;
- break;
-
- case PRIVATE_VAR_TMP:
- what = var_tmp_dir;
- break;
-
- default:
- assert_not_reached("Unknown mode");
- }
-
- assert(what);
-
- r = mount(what, p->path, NULL, MS_BIND|MS_REC, NULL);
- if (r >= 0)
- log_debug("Successfully mounted %s to %s", what, p->path);
-
- return r;
-}
-
-static int make_read_only(Path *p) {
- int r;
-
- assert(p);
-
- if (p->mode != INACCESSIBLE && p->mode != READONLY)
- return 0;
-
- r = mount(NULL, p->path, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_REC, NULL);
- if (r < 0)
- return -errno;
-
- return 0;
-}
-
-int setup_namespace(
- char **writable,
- char **readable,
- char **inaccessible,
- bool private_tmp,
- unsigned long flags) {
-
- char
- tmp_dir[] = "/tmp/systemd-private-XXXXXX",
- var_tmp_dir[] = "/var/tmp/systemd-private-XXXXXX",
- inaccessible_dir[] = "/tmp/systemd-inaccessible-XXXXXX";
-
- Path *paths, *p;
- unsigned n;
- bool need_inaccessible = false;
- bool remove_tmp = false, remove_var_tmp = false, remove_inaccessible = false;
- int r;
-
- if (!flags)
- flags = MS_SHARED;
-
- n =
- strv_length(writable) +
- strv_length(readable) +
- strv_length(inaccessible) +
- (private_tmp ? 2 : 0);
-
- p = paths = alloca(sizeof(Path) * n);
- if ((r = append_paths(&p, writable, READWRITE)) < 0 ||
- (r = append_paths(&p, readable, READONLY)) < 0 ||
- (r = append_paths(&p, inaccessible, INACCESSIBLE)) < 0)
- goto fail;
-
- if (private_tmp) {
- p->path = "/tmp";
- p->mode = PRIVATE_TMP;
- p++;
-
- p->path = "/var/tmp";
- p->mode = PRIVATE_VAR_TMP;
- p++;
- }
-
- assert(paths + n == p);
-
- qsort(paths, n, sizeof(Path), path_compare);
- drop_duplicates(paths, &n, &need_inaccessible);
-
- if (need_inaccessible) {
- mode_t u;
- char *d;
-
- u = umask(0777);
- d = mkdtemp(inaccessible_dir);
- umask(u);
-
- if (!d) {
- r = -errno;
- goto fail;
- }
-
- remove_inaccessible = true;
- }
-
- if (private_tmp) {
- mode_t u;
- char *d;
-
- u = umask(0000);
- d = mkdtemp(tmp_dir);
- umask(u);
-
- if (!d) {
- r = -errno;
- goto fail;
- }
-
- remove_tmp = true;
-
- u = umask(0000);
- d = mkdtemp(var_tmp_dir);
- umask(u);
-
- if (!d) {
- r = -errno;
- goto fail;
- }
-
- remove_var_tmp = true;
-
- if (chmod(tmp_dir, 0777 + S_ISVTX) < 0) {
- r = -errno;
- goto fail;
- }
-
- if (chmod(var_tmp_dir, 0777 + S_ISVTX) < 0) {
- r = -errno;
- goto fail;
- }
- }
-
- if (unshare(CLONE_NEWNS) < 0) {
- r = -errno;
- goto fail;
- }
-
- /* Remount / as SLAVE so that nothing now mounted in the namespace
- shows up in the parent */
- if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) {
- r = -errno;
- goto fail;
- }
-
- for (p = paths; p < paths + n; p++) {
- r = apply_mount(p, tmp_dir, var_tmp_dir, inaccessible_dir);
- if (r < 0)
- goto undo_mounts;
- }
-
- for (p = paths; p < paths + n; p++) {
- r = make_read_only(p);
- if (r < 0)
- goto undo_mounts;
- }
-
- /* Remount / as the desired mode */
- if (mount(NULL, "/", NULL, flags|MS_REC, NULL) < 0) {
- r = -errno;
- goto undo_mounts;
- }
-
- return 0;
-
-undo_mounts:
- for (p = paths; p < paths + n; p++)
- if (p->done)
- umount2(p->path, MNT_DETACH);
-
-fail:
- if (remove_inaccessible)
- rmdir(inaccessible_dir);
-
- if (remove_tmp)
- rmdir(tmp_dir);
-
- if (remove_var_tmp)
- rmdir(var_tmp_dir);
-
- return r;
-}
diff --git a/src/core/namespace.h b/src/core/namespace.h
deleted file mode 100644
index 5d72ed91fb..0000000000
--- a/src/core/namespace.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*-*- 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 setup_namespace(
- char **writable,
- char **readable,
- char **inaccessible,
- bool private_tmp,
- unsigned long flags);
diff --git a/src/core/org.freedesktop.systemd1.conf b/src/core/org.freedesktop.systemd1.conf
deleted file mode 100644
index a07a8e1ce3..0000000000
--- a/src/core/org.freedesktop.systemd1.conf
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0"?> <!--*-nxml-*-->
-<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
-
-<!--
- This file is part of systemd.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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.
--->
-
-<busconfig>
-
- <policy user="root">
- <allow own="org.freedesktop.systemd1"/>
-
- <!-- Root clients can do everything -->
- <allow send_destination="org.freedesktop.systemd1"/>
- <allow receive_sender="org.freedesktop.systemd1"/>
-
- <!-- systemd may receive activator requests -->
- <allow receive_interface="org.freedesktop.systemd1.Activator"
- receive_member="ActivationRequest"/>
- </policy>
-
- <policy context="default">
- <deny send_destination="org.freedesktop.systemd1"/>
-
- <allow send_destination="org.freedesktop.systemd1"
- send_interface="org.freedesktop.DBus.Introspectable"/>
-
- <allow send_destination="org.freedesktop.systemd1"
- send_interface="org.freedesktop.DBus.Peer"/>
-
- <allow send_destination="org.freedesktop.systemd1"
- send_interface="org.freedesktop.DBus.Properties"
- send_member="Get"/>
-
- <allow send_destination="org.freedesktop.systemd1"
- send_interface="org.freedesktop.DBus.Properties"
- send_member="GetAll"/>
-
- <allow send_destination="org.freedesktop.systemd1"
- send_interface="org.freedesktop.systemd1.Manager"
- send_member="GetUnit"/>
-
- <allow send_destination="org.freedesktop.systemd1"
- send_interface="org.freedesktop.systemd1.Manager"
- send_member="GetUnitByPID"/>
-
- <allow send_destination="org.freedesktop.systemd1"
- send_interface="org.freedesktop.systemd1.Manager"
- send_member="LoadUnit"/>
-
- <allow send_destination="org.freedesktop.systemd1"
- send_interface="org.freedesktop.systemd1.Manager"
- send_member="GetJob"/>
-
- <allow send_destination="org.freedesktop.systemd1"
- send_interface="org.freedesktop.systemd1.Manager"
- send_member="ListUnits"/>
-
- <allow send_destination="org.freedesktop.systemd1"
- send_interface="org.freedesktop.systemd1.Manager"
- send_member="ListUnitFiles"/>
-
- <allow send_destination="org.freedesktop.systemd1"
- send_interface="org.freedesktop.systemd1.Manager"
- send_member="GetUnitFileState"/>
-
- <allow send_destination="org.freedesktop.systemd1"
- send_interface="org.freedesktop.systemd1.Manager"
- send_member="ListJobs"/>
-
- <allow send_destination="org.freedesktop.systemd1"
- send_interface="org.freedesktop.systemd1.Manager"
- send_member="Subscribe"/>
-
- <allow send_destination="org.freedesktop.systemd1"
- send_interface="org.freedesktop.systemd1.Manager"
- send_member="Unsubscribe"/>
-
- <allow send_destination="org.freedesktop.systemd1"
- send_interface="org.freedesktop.systemd1.Manager"
- send_member="Dump"/>
-
- <allow receive_sender="org.freedesktop.systemd1"/>
- </policy>
-
-</busconfig>
diff --git a/src/core/org.freedesktop.systemd1.policy.in.in b/src/core/org.freedesktop.systemd1.policy.in.in
deleted file mode 100644
index 51bdafac45..0000000000
--- a/src/core/org.freedesktop.systemd1.policy.in.in
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?> <!--*-nxml-*-->
-<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
-
-<!--
- This file is part of systemd.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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.
--->
-
-<policyconfig>
-
- <vendor>The systemd Project</vendor>
- <vendor_url>http://www.freedesktop.org/wiki/Software/systemd</vendor_url>
-
- <action id="org.freedesktop.systemd1.reply-password">
- <_description>Send passphrase back to system</_description>
- <_message>Authentication is required to send the entered passphrase back to the system.</_message>
- <defaults>
- <allow_any>no</allow_any>
- <allow_inactive>no</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
- </defaults>
- <annotate key="org.freedesktop.policykit.exec.path">@rootlibexecdir@/systemd-reply-password</annotate>
- </action>
-
- <action id="org.freedesktop.systemd1.bus-access">
- <_description>Privileged system and service manager access</_description>
- <_message>Authentication is required to access the system and service manager.</_message>
- <defaults>
- <allow_any>no</allow_any>
- <allow_inactive>no</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
- </defaults>
- <annotate key="org.freedesktop.policykit.exec.path">@bindir@/systemd-stdio-bridge</annotate>
- </action>
-
-</policyconfig>
diff --git a/src/core/org.freedesktop.systemd1.service b/src/core/org.freedesktop.systemd1.service
deleted file mode 100644
index d4df3e93a2..0000000000
--- a/src/core/org.freedesktop.systemd1.service
+++ /dev/null
@@ -1,11 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-
-[D-BUS Service]
-Name=org.freedesktop.systemd1
-Exec=/bin/false
-User=root
diff --git a/src/core/path.c b/src/core/path.c
deleted file mode 100644
index 3936971b41..0000000000
--- a/src/core/path.c
+++ /dev/null
@@ -1,773 +0,0 @@
-/*-*- 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/inotify.h>
-#include <sys/epoll.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include "unit.h"
-#include "unit-name.h"
-#include "path.h"
-#include "mkdir.h"
-#include "dbus-path.h"
-#include "special.h"
-#include "bus-errors.h"
-#include "path-util.h"
-
-static const UnitActiveState state_translation_table[_PATH_STATE_MAX] = {
- [PATH_DEAD] = UNIT_INACTIVE,
- [PATH_WAITING] = UNIT_ACTIVE,
- [PATH_RUNNING] = UNIT_ACTIVE,
- [PATH_FAILED] = UNIT_FAILED
-};
-
-int path_spec_watch(PathSpec *s, Unit *u) {
-
- static const int flags_table[_PATH_TYPE_MAX] = {
- [PATH_EXISTS] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB,
- [PATH_EXISTS_GLOB] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB,
- [PATH_CHANGED] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO,
- [PATH_MODIFIED] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO|IN_MODIFY,
- [PATH_DIRECTORY_NOT_EMPTY] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CREATE|IN_MOVED_TO
- };
-
- bool exists = false;
- char *k, *slash;
- int r;
-
- assert(u);
- assert(s);
-
- path_spec_unwatch(s, u);
-
- if (!(k = strdup(s->path)))
- return -ENOMEM;
-
- if ((s->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC)) < 0) {
- r = -errno;
- goto fail;
- }
-
- if (unit_watch_fd(u, s->inotify_fd, EPOLLIN, &s->watch) < 0) {
- r = -errno;
- goto fail;
- }
-
- s->primary_wd = inotify_add_watch(s->inotify_fd, k, flags_table[s->type]);
- if (s->primary_wd >= 0)
- exists = true;
-
- do {
- int flags;
-
- /* This assumes the path was passed through path_kill_slashes()! */
- slash = strrchr(k, '/');
- if (!slash)
- break;
-
- /* Trim the path at the last slash. Keep the slash if it's the root dir. */
- slash[slash == k] = 0;
-
- flags = IN_MOVE_SELF;
- if (!exists)
- flags |= IN_DELETE_SELF | IN_ATTRIB | IN_CREATE | IN_MOVED_TO;
-
- if (inotify_add_watch(s->inotify_fd, k, flags) >= 0)
- exists = true;
- } while (slash != k);
-
- return 0;
-
-fail:
- free(k);
-
- path_spec_unwatch(s, u);
- return r;
-}
-
-void path_spec_unwatch(PathSpec *s, Unit *u) {
-
- if (s->inotify_fd < 0)
- return;
-
- unit_unwatch_fd(u, &s->watch);
-
- close_nointr_nofail(s->inotify_fd);
- s->inotify_fd = -1;
-}
-
-int path_spec_fd_event(PathSpec *s, uint32_t events) {
- uint8_t *buf = NULL;
- struct inotify_event *e;
- ssize_t k;
- int l;
- int r = 0;
-
- if (events != EPOLLIN) {
- log_error("Got Invalid poll event on inotify.");
- r = -EINVAL;
- goto out;
- }
-
- if (ioctl(s->inotify_fd, FIONREAD, &l) < 0) {
- log_error("FIONREAD failed: %m");
- r = -errno;
- goto out;
- }
-
- assert(l > 0);
-
- if (!(buf = malloc(l))) {
- log_error("Failed to allocate buffer: %m");
- r = -errno;
- goto out;
- }
-
- if ((k = read(s->inotify_fd, buf, l)) < 0) {
- log_error("Failed to read inotify event: %m");
- r = -errno;
- goto out;
- }
-
- e = (struct inotify_event*) buf;
-
- while (k > 0) {
- size_t step;
-
- if ((s->type == PATH_CHANGED || s->type == PATH_MODIFIED) &&
- s->primary_wd == e->wd)
- r = 1;
-
- step = sizeof(struct inotify_event) + e->len;
- assert(step <= (size_t) k);
-
- e = (struct inotify_event*) ((uint8_t*) e + step);
- k -= step;
- }
-out:
- free(buf);
- return r;
-}
-
-static bool path_spec_check_good(PathSpec *s, bool initial) {
- bool good = false;
-
- switch (s->type) {
-
- case PATH_EXISTS:
- good = access(s->path, F_OK) >= 0;
- break;
-
- case PATH_EXISTS_GLOB:
- good = glob_exists(s->path) > 0;
- break;
-
- case PATH_DIRECTORY_NOT_EMPTY: {
- int k;
-
- k = dir_is_empty(s->path);
- good = !(k == -ENOENT || k > 0);
- break;
- }
-
- case PATH_CHANGED:
- case PATH_MODIFIED: {
- bool b;
-
- b = access(s->path, F_OK) >= 0;
- good = !initial && b != s->previous_exists;
- s->previous_exists = b;
- break;
- }
-
- default:
- ;
- }
-
- return good;
-}
-
-static bool path_spec_startswith(PathSpec *s, const char *what) {
- return path_startswith(s->path, what);
-}
-
-static void path_spec_mkdir(PathSpec *s, mode_t mode) {
- int r;
-
- if (s->type == PATH_EXISTS || s->type == PATH_EXISTS_GLOB)
- return;
-
- if ((r = mkdir_p_label(s->path, mode)) < 0)
- log_warning("mkdir(%s) failed: %s", s->path, strerror(-r));
-}
-
-static void path_spec_dump(PathSpec *s, FILE *f, const char *prefix) {
- fprintf(f,
- "%s%s: %s\n",
- prefix,
- path_type_to_string(s->type),
- s->path);
-}
-
-void path_spec_done(PathSpec *s) {
- assert(s);
- assert(s->inotify_fd == -1);
-
- free(s->path);
-}
-
-static void path_init(Unit *u) {
- Path *p = PATH(u);
-
- assert(u);
- assert(u->load_state == UNIT_STUB);
-
- p->directory_mode = 0755;
-}
-
-static void path_done(Unit *u) {
- Path *p = PATH(u);
- PathSpec *s;
-
- assert(p);
-
- unit_ref_unset(&p->unit);
-
- while ((s = p->specs)) {
- path_spec_unwatch(s, u);
- LIST_REMOVE(PathSpec, spec, p->specs, s);
- path_spec_done(s);
- free(s);
- }
-}
-
-int path_add_one_mount_link(Path *p, Mount *m) {
- PathSpec *s;
- int r;
-
- assert(p);
- assert(m);
-
- if (UNIT(p)->load_state != UNIT_LOADED ||
- UNIT(m)->load_state != UNIT_LOADED)
- return 0;
-
- LIST_FOREACH(spec, s, p->specs) {
-
- if (!path_spec_startswith(s, m->where))
- continue;
-
- if ((r = unit_add_two_dependencies(UNIT(p), UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true)) < 0)
- return r;
- }
-
- return 0;
-}
-
-static int path_add_mount_links(Path *p) {
- Unit *other;
- int r;
-
- assert(p);
-
- LIST_FOREACH(units_by_type, other, UNIT(p)->manager->units_by_type[UNIT_MOUNT])
- if ((r = path_add_one_mount_link(p, MOUNT(other))) < 0)
- return r;
-
- return 0;
-}
-
-static int path_verify(Path *p) {
- assert(p);
-
- if (UNIT(p)->load_state != UNIT_LOADED)
- return 0;
-
- if (!p->specs) {
- log_error("%s lacks path setting. Refusing.", UNIT(p)->id);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int path_add_default_dependencies(Path *p) {
- int r;
-
- assert(p);
-
- if (UNIT(p)->manager->running_as == SYSTEMD_SYSTEM) {
- if ((r = unit_add_dependency_by_name(UNIT(p), UNIT_BEFORE, SPECIAL_BASIC_TARGET, NULL, true)) < 0)
- return r;
-
- if ((r = unit_add_two_dependencies_by_name(UNIT(p), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true)) < 0)
- return r;
- }
-
- return unit_add_two_dependencies_by_name(UNIT(p), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
-}
-
-static int path_load(Unit *u) {
- Path *p = PATH(u);
- int r;
-
- assert(u);
- assert(u->load_state == UNIT_STUB);
-
- if ((r = unit_load_fragment_and_dropin(u)) < 0)
- return r;
-
- if (u->load_state == UNIT_LOADED) {
-
- if (!UNIT_DEREF(p->unit)) {
- Unit *x;
-
- r = unit_load_related_unit(u, ".service", &x);
- if (r < 0)
- return r;
-
- unit_ref_set(&p->unit, x);
- }
-
- r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(p->unit), true);
- if (r < 0)
- return r;
-
- if ((r = path_add_mount_links(p)) < 0)
- return r;
-
- if (UNIT(p)->default_dependencies)
- if ((r = path_add_default_dependencies(p)) < 0)
- return r;
- }
-
- return path_verify(p);
-}
-
-static void path_dump(Unit *u, FILE *f, const char *prefix) {
- Path *p = PATH(u);
- PathSpec *s;
-
- assert(p);
- assert(f);
-
- fprintf(f,
- "%sPath State: %s\n"
- "%sResult: %s\n"
- "%sUnit: %s\n"
- "%sMakeDirectory: %s\n"
- "%sDirectoryMode: %04o\n",
- prefix, path_state_to_string(p->state),
- prefix, path_result_to_string(p->result),
- prefix, UNIT_DEREF(p->unit)->id,
- prefix, yes_no(p->make_directory),
- prefix, p->directory_mode);
-
- LIST_FOREACH(spec, s, p->specs)
- path_spec_dump(s, f, prefix);
-}
-
-static void path_unwatch(Path *p) {
- PathSpec *s;
-
- assert(p);
-
- LIST_FOREACH(spec, s, p->specs)
- path_spec_unwatch(s, UNIT(p));
-}
-
-static int path_watch(Path *p) {
- int r;
- PathSpec *s;
-
- assert(p);
-
- LIST_FOREACH(spec, s, p->specs)
- if ((r = path_spec_watch(s, UNIT(p))) < 0)
- return r;
-
- return 0;
-}
-
-static void path_set_state(Path *p, PathState state) {
- PathState old_state;
- assert(p);
-
- old_state = p->state;
- p->state = state;
-
- if (state != PATH_WAITING &&
- (state != PATH_RUNNING || p->inotify_triggered))
- path_unwatch(p);
-
- if (state != old_state)
- log_debug("%s changed %s -> %s",
- UNIT(p)->id,
- path_state_to_string(old_state),
- path_state_to_string(state));
-
- unit_notify(UNIT(p), state_translation_table[old_state], state_translation_table[state], true);
-}
-
-static void path_enter_waiting(Path *p, bool initial, bool recheck);
-
-static int path_coldplug(Unit *u) {
- Path *p = PATH(u);
-
- assert(p);
- assert(p->state == PATH_DEAD);
-
- if (p->deserialized_state != p->state) {
-
- if (p->deserialized_state == PATH_WAITING ||
- p->deserialized_state == PATH_RUNNING)
- path_enter_waiting(p, true, true);
- else
- path_set_state(p, p->deserialized_state);
- }
-
- return 0;
-}
-
-static void path_enter_dead(Path *p, PathResult f) {
- assert(p);
-
- if (f != PATH_SUCCESS)
- p->result = f;
-
- path_set_state(p, p->result != PATH_SUCCESS ? PATH_FAILED : PATH_DEAD);
-}
-
-static void path_enter_running(Path *p) {
- int r;
- DBusError error;
-
- assert(p);
- dbus_error_init(&error);
-
- /* Don't start job if we are supposed to go down */
- if (UNIT(p)->job && UNIT(p)->job->type == JOB_STOP)
- return;
-
- if ((r = manager_add_job(UNIT(p)->manager, JOB_START, UNIT_DEREF(p->unit), JOB_REPLACE, true, &error, NULL)) < 0)
- goto fail;
-
- p->inotify_triggered = false;
-
- if ((r = path_watch(p)) < 0)
- goto fail;
-
- path_set_state(p, PATH_RUNNING);
- return;
-
-fail:
- log_warning("%s failed to queue unit startup job: %s", UNIT(p)->id, bus_error(&error, r));
- path_enter_dead(p, PATH_FAILURE_RESOURCES);
-
- dbus_error_free(&error);
-}
-
-static bool path_check_good(Path *p, bool initial) {
- PathSpec *s;
- bool good = false;
-
- assert(p);
-
- LIST_FOREACH(spec, s, p->specs) {
- good = path_spec_check_good(s, initial);
-
- if (good)
- break;
- }
-
- return good;
-}
-
-static void path_enter_waiting(Path *p, bool initial, bool recheck) {
- int r;
-
- if (recheck)
- if (path_check_good(p, initial)) {
- log_debug("%s got triggered.", UNIT(p)->id);
- path_enter_running(p);
- return;
- }
-
- if ((r = path_watch(p)) < 0)
- goto fail;
-
- /* Hmm, so now we have created inotify watches, but the file
- * might have appeared/been removed by now, so we must
- * recheck */
-
- if (recheck)
- if (path_check_good(p, false)) {
- log_debug("%s got triggered.", UNIT(p)->id);
- path_enter_running(p);
- return;
- }
-
- path_set_state(p, PATH_WAITING);
- return;
-
-fail:
- log_warning("%s failed to enter waiting state: %s", UNIT(p)->id, strerror(-r));
- path_enter_dead(p, PATH_FAILURE_RESOURCES);
-}
-
-static void path_mkdir(Path *p) {
- PathSpec *s;
-
- assert(p);
-
- if (!p->make_directory)
- return;
-
- LIST_FOREACH(spec, s, p->specs)
- path_spec_mkdir(s, p->directory_mode);
-}
-
-static int path_start(Unit *u) {
- Path *p = PATH(u);
-
- assert(p);
- assert(p->state == PATH_DEAD || p->state == PATH_FAILED);
-
- if (UNIT_DEREF(p->unit)->load_state != UNIT_LOADED)
- return -ENOENT;
-
- path_mkdir(p);
-
- p->result = PATH_SUCCESS;
- path_enter_waiting(p, true, true);
-
- return 0;
-}
-
-static int path_stop(Unit *u) {
- Path *p = PATH(u);
-
- assert(p);
- assert(p->state == PATH_WAITING || p->state == PATH_RUNNING);
-
- path_enter_dead(p, PATH_SUCCESS);
- return 0;
-}
-
-static int path_serialize(Unit *u, FILE *f, FDSet *fds) {
- Path *p = PATH(u);
-
- assert(u);
- assert(f);
- assert(fds);
-
- unit_serialize_item(u, f, "state", path_state_to_string(p->state));
- unit_serialize_item(u, f, "result", path_result_to_string(p->result));
-
- return 0;
-}
-
-static int path_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
- Path *p = PATH(u);
-
- assert(u);
- assert(key);
- assert(value);
- assert(fds);
-
- if (streq(key, "state")) {
- PathState state;
-
- if ((state = path_state_from_string(value)) < 0)
- log_debug("Failed to parse state value %s", value);
- else
- p->deserialized_state = state;
-
- } else if (streq(key, "result")) {
- PathResult f;
-
- f = path_result_from_string(value);
- if (f < 0)
- log_debug("Failed to parse result value %s", value);
- else if (f != PATH_SUCCESS)
- p->result = f;
-
- } else
- log_debug("Unknown serialization key '%s'", key);
-
- return 0;
-}
-
-static UnitActiveState path_active_state(Unit *u) {
- assert(u);
-
- return state_translation_table[PATH(u)->state];
-}
-
-static const char *path_sub_state_to_string(Unit *u) {
- assert(u);
-
- return path_state_to_string(PATH(u)->state);
-}
-
-static void path_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
- Path *p = PATH(u);
- PathSpec *s;
- int changed;
-
- assert(p);
- assert(fd >= 0);
-
- if (p->state != PATH_WAITING &&
- p->state != PATH_RUNNING)
- return;
-
- /* log_debug("inotify wakeup on %s.", u->id); */
-
- LIST_FOREACH(spec, s, p->specs)
- if (path_spec_owns_inotify_fd(s, fd))
- break;
-
- if (!s) {
- log_error("Got event on unknown fd.");
- goto fail;
- }
-
- changed = path_spec_fd_event(s, events);
- if (changed < 0)
- goto fail;
-
- /* If we are already running, then remember that one event was
- * dispatched so that we restart the service only if something
- * actually changed on disk */
- p->inotify_triggered = true;
-
- if (changed)
- path_enter_running(p);
- else
- path_enter_waiting(p, false, true);
-
- return;
-
-fail:
- path_enter_dead(p, PATH_FAILURE_RESOURCES);
-}
-
-void path_unit_notify(Unit *u, UnitActiveState new_state) {
- Iterator i;
- Unit *k;
-
- if (u->type == UNIT_PATH)
- return;
-
- SET_FOREACH(k, u->dependencies[UNIT_TRIGGERED_BY], i) {
- Path *p;
-
- if (k->type != UNIT_PATH)
- continue;
-
- if (k->load_state != UNIT_LOADED)
- continue;
-
- p = PATH(k);
-
- if (p->state == PATH_RUNNING && new_state == UNIT_INACTIVE) {
- log_debug("%s got notified about unit deactivation.", UNIT(p)->id);
-
- /* Hmm, so inotify was triggered since the
- * last activation, so I guess we need to
- * recheck what is going on. */
- path_enter_waiting(p, false, p->inotify_triggered);
- }
- }
-}
-
-static void path_reset_failed(Unit *u) {
- Path *p = PATH(u);
-
- assert(p);
-
- if (p->state == PATH_FAILED)
- path_set_state(p, PATH_DEAD);
-
- p->result = PATH_SUCCESS;
-}
-
-static const char* const path_state_table[_PATH_STATE_MAX] = {
- [PATH_DEAD] = "dead",
- [PATH_WAITING] = "waiting",
- [PATH_RUNNING] = "running",
- [PATH_FAILED] = "failed"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(path_state, PathState);
-
-static const char* const path_type_table[_PATH_TYPE_MAX] = {
- [PATH_EXISTS] = "PathExists",
- [PATH_EXISTS_GLOB] = "PathExistsGlob",
- [PATH_CHANGED] = "PathChanged",
- [PATH_MODIFIED] = "PathModified",
- [PATH_DIRECTORY_NOT_EMPTY] = "DirectoryNotEmpty"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(path_type, PathType);
-
-static const char* const path_result_table[_PATH_RESULT_MAX] = {
- [PATH_SUCCESS] = "success",
- [PATH_FAILURE_RESOURCES] = "resources"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult);
-
-const UnitVTable path_vtable = {
- .object_size = sizeof(Path),
- .sections =
- "Unit\0"
- "Path\0"
- "Install\0",
-
- .init = path_init,
- .done = path_done,
- .load = path_load,
-
- .coldplug = path_coldplug,
-
- .dump = path_dump,
-
- .start = path_start,
- .stop = path_stop,
-
- .serialize = path_serialize,
- .deserialize_item = path_deserialize_item,
-
- .active_state = path_active_state,
- .sub_state_to_string = path_sub_state_to_string,
-
- .fd_event = path_fd_event,
-
- .reset_failed = path_reset_failed,
-
- .bus_interface = "org.freedesktop.systemd1.Path",
- .bus_message_handler = bus_path_message_handler,
- .bus_invalidating_properties = bus_path_invalidating_properties
-};
diff --git a/src/core/path.h b/src/core/path.h
deleted file mode 100644
index 77926888ae..0000000000
--- a/src/core/path.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*-*- 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/>.
-***/
-
-typedef struct Path Path;
-
-#include "unit.h"
-#include "mount.h"
-
-typedef enum PathState {
- PATH_DEAD,
- PATH_WAITING,
- PATH_RUNNING,
- PATH_FAILED,
- _PATH_STATE_MAX,
- _PATH_STATE_INVALID = -1
-} PathState;
-
-typedef enum PathType {
- PATH_EXISTS,
- PATH_EXISTS_GLOB,
- PATH_DIRECTORY_NOT_EMPTY,
- PATH_CHANGED,
- PATH_MODIFIED,
- _PATH_TYPE_MAX,
- _PATH_TYPE_INVALID = -1
-} PathType;
-
-typedef struct PathSpec {
- char *path;
-
- Watch watch;
-
- LIST_FIELDS(struct PathSpec, spec);
-
- PathType type;
- int inotify_fd;
- int primary_wd;
-
- bool previous_exists;
-} PathSpec;
-
-int path_spec_watch(PathSpec *s, Unit *u);
-void path_spec_unwatch(PathSpec *s, Unit *u);
-int path_spec_fd_event(PathSpec *s, uint32_t events);
-void path_spec_done(PathSpec *s);
-
-static inline bool path_spec_owns_inotify_fd(PathSpec *s, int fd) {
- return s->inotify_fd == fd;
-}
-
-typedef enum PathResult {
- PATH_SUCCESS,
- PATH_FAILURE_RESOURCES,
- _PATH_RESULT_MAX,
- _PATH_RESULT_INVALID = -1
-} PathResult;
-
-struct Path {
- Unit meta;
-
- LIST_HEAD(PathSpec, specs);
-
- UnitRef unit;
-
- PathState state, deserialized_state;
-
- bool inotify_triggered;
-
- bool make_directory;
- mode_t directory_mode;
-
- PathResult result;
-};
-
-void path_unit_notify(Unit *u, UnitActiveState new_state);
-
-/* Called from the mount code figure out if a mount is a dependency of
- * any of the paths of this path object */
-int path_add_one_mount_link(Path *p, Mount *m);
-
-extern const UnitVTable path_vtable;
-
-const char* path_state_to_string(PathState i);
-PathState path_state_from_string(const char *s);
-
-const char* path_type_to_string(PathType i);
-PathType path_type_from_string(const char *s);
-
-const char* path_result_to_string(PathResult i);
-PathResult path_result_from_string(const char *s);
diff --git a/src/core/securebits.h b/src/core/securebits.h
deleted file mode 100644
index ba0bba5353..0000000000
--- a/src/core/securebits.h
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef _LINUX_SECUREBITS_H
-#define _LINUX_SECUREBITS_H 1
-
-/* This is minimal version of Linux' linux/securebits.h header file,
- * which is licensed GPL2 */
-
-#define SECUREBITS_DEFAULT 0x00000000
-
-/* When set UID 0 has no special privileges. When unset, we support
- inheritance of root-permissions and suid-root executable under
- compatibility mode. We raise the effective and inheritable bitmasks
- *of the executable file* if the effective uid of the new process is
- 0. If the real uid is 0, we raise the effective (legacy) bit of the
- executable file. */
-#define SECURE_NOROOT 0
-#define SECURE_NOROOT_LOCKED 1 /* make bit-0 immutable */
-
-/* When set, setuid to/from uid 0 does not trigger capability-"fixup".
- When unset, to provide compatibility with old programs relying on
- set*uid to gain/lose privilege, transitions to/from uid 0 cause
- capabilities to be gained/lost. */
-#define SECURE_NO_SETUID_FIXUP 2
-#define SECURE_NO_SETUID_FIXUP_LOCKED 3 /* make bit-2 immutable */
-
-/* When set, a process can retain its capabilities even after
- transitioning to a non-root user (the set-uid fixup suppressed by
- bit 2). Bit-4 is cleared when a process calls exec(); setting both
- bit 4 and 5 will create a barrier through exec that no exec()'d
- child can use this feature again. */
-#define SECURE_KEEP_CAPS 4
-#define SECURE_KEEP_CAPS_LOCKED 5 /* make bit-4 immutable */
-
-/* Each securesetting is implemented using two bits. One bit specifies
- whether the setting is on or off. The other bit specify whether the
- setting is locked or not. A setting which is locked cannot be
- changed from user-level. */
-#define issecure_mask(X) (1 << (X))
-#define issecure(X) (issecure_mask(X) & current_cred_xxx(securebits))
-
-#define SECURE_ALL_BITS (issecure_mask(SECURE_NOROOT) | \
- issecure_mask(SECURE_NO_SETUID_FIXUP) | \
- issecure_mask(SECURE_KEEP_CAPS))
-#define SECURE_ALL_LOCKS (SECURE_ALL_BITS << 1)
-
-#endif /* !_LINUX_SECUREBITS_H */
diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c
deleted file mode 100644
index 6dfe8b45f3..0000000000
--- a/src/core/selinux-access.c
+++ /dev/null
@@ -1,441 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Dan Walsh
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "selinux-access.h"
-
-#ifdef HAVE_SELINUX
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <limits.h>
-#include <selinux/selinux.h>
-#include <selinux/avc.h>
-#ifdef HAVE_AUDIT
-#include <libaudit.h>
-#endif
-#include <dbus.h>
-
-#include "util.h"
-#include "log.h"
-#include "bus-errors.h"
-#include "dbus-common.h"
-#include "audit.h"
-#include "selinux-util.h"
-#include "audit-fd.h"
-
-static bool initialized = false;
-
-struct auditstruct {
- const char *path;
- char *cmdline;
- uid_t loginuid;
- uid_t uid;
- gid_t gid;
-};
-
-static int bus_get_selinux_security_context(
- DBusConnection *connection,
- const char *name,
- char **scon,
- DBusError *error) {
-
- _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
- DBusMessageIter iter, sub;
- const char *bytes;
- char *b;
- int nbytes;
-
- m = dbus_message_new_method_call(
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS,
- "GetConnectionSELinuxSecurityContext");
- if (!m) {
- dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
- return -ENOMEM;
- }
-
- if (!dbus_message_append_args(
- m,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_INVALID)) {
- dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
- return -ENOMEM;
- }
-
- reply = dbus_connection_send_with_reply_and_block(connection, m, -1, error);
- if (!reply)
- return -EIO;
-
- if (dbus_set_error_from_message(error, reply))
- return -EIO;
-
- if (!dbus_message_iter_init(reply, &iter))
- return -EIO;
-
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
- return -EIO;
-
- dbus_message_iter_recurse(&iter, &sub);
- dbus_message_iter_get_fixed_array(&sub, &bytes, &nbytes);
-
- b = strndup(bytes, nbytes);
- if (!b)
- return -ENOMEM;
-
- *scon = b;
-
- log_debug("GetConnectionSELinuxSecurityContext %s (pid %ld)", *scon, (long) bus_get_unix_process_id(connection, name, error));
-
- return 0;
-}
-
-static int bus_get_audit_data(
- DBusConnection *connection,
- const char *name,
- struct auditstruct *audit,
- DBusError *error) {
-
- pid_t pid;
- int r;
-
- pid = bus_get_unix_process_id(connection, name, error);
- if (pid <= 0)
- return -EIO;
-
- r = audit_loginuid_from_pid(pid, &audit->loginuid);
- if (r < 0)
- return r;
-
- r = get_process_uid(pid, &audit->uid);
- if (r < 0)
- return r;
-
- r = get_process_gid(pid, &audit->gid);
- if (r < 0)
- return r;
-
- r = get_process_cmdline(pid, LINE_MAX, true, &audit->cmdline);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-/*
- Any time an access gets denied this callback will be called
- with the aduit data. We then need to just copy the audit data into the msgbuf.
-*/
-static int audit_callback(
- void *auditdata,
- security_class_t cls,
- char *msgbuf,
- size_t msgbufsize) {
-
- struct auditstruct *audit = (struct auditstruct *) auditdata;
-
- snprintf(msgbuf, msgbufsize,
- "auid=%d uid=%d gid=%d%s%s%s%s%s%s",
- audit->loginuid,
- audit->uid,
- audit->gid,
- (audit->path ? " path=\"" : ""),
- strempty(audit->path),
- (audit->path ? "\"" : ""),
- (audit->cmdline ? " cmdline=\"" : ""),
- strempty(audit->cmdline),
- (audit->cmdline ? "\"" : ""));
-
- msgbuf[msgbufsize-1] = 0;
-
- return 0;
-}
-
-/*
- Any time an access gets denied this callback will be called
- code copied from dbus. If audit is turned on the messages will go as
- user_avc's into the /var/log/audit/audit.log, otherwise they will be
- sent to syslog.
-*/
-static int log_callback(int type, const char *fmt, ...) {
- va_list ap;
-
- va_start(ap, fmt);
-
-#ifdef HAVE_AUDIT
- if (get_audit_fd() >= 0) {
- char buf[LINE_MAX];
-
- vsnprintf(buf, sizeof(buf), fmt, ap);
- audit_log_user_avc_message(get_audit_fd(), AUDIT_USER_AVC, buf, NULL, NULL, NULL, 0);
- va_end(ap);
-
- return 0;
- }
-#endif
- log_metav(LOG_USER | LOG_INFO, __FILE__, __LINE__, __FUNCTION__, fmt, ap);
- va_end(ap);
-
- return 0;
-}
-
-/*
- Function must be called once to initialize the SELinux AVC environment.
- Sets up callbacks.
- If you want to cleanup memory you should need to call selinux_access_finish.
-*/
-static int access_init(void) {
- int r;
-
- if (avc_open(NULL, 0)) {
- log_error("avc_open() failed: %m");
- return -errno;
- }
-
- selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback) audit_callback);
- selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) log_callback);
-
- if (security_getenforce() >= 0)
- return 0;
-
- r = -errno;
- avc_destroy();
-
- return r;
-}
-
-static int selinux_access_init(DBusError *error) {
- int r;
-
- if (initialized)
- return 0;
-
- if (use_selinux()) {
- r = access_init();
- if (r < 0) {
- dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "Failed to initialize SELinux.");
- return r;
- }
- }
-
- initialized = true;
- return 0;
-}
-
-void selinux_access_free(void) {
- if (!initialized)
- return;
-
- avc_destroy();
- initialized = false;
-}
-
-static int get_audit_data(
- DBusConnection *connection,
- DBusMessage *message,
- struct auditstruct *audit,
- DBusError *error) {
-
- const char *sender;
- int r, fd;
- struct ucred ucred;
- socklen_t len;
-
- sender = dbus_message_get_sender(message);
- if (sender)
- return bus_get_audit_data(connection, sender, audit, error);
-
- if (!dbus_connection_get_unix_fd(connection, &fd))
- return -EINVAL;
-
- r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len);
- if (r < 0) {
- log_error("Failed to determine peer credentials: %m");
- return -errno;
- }
-
- audit->uid = ucred.uid;
- audit->gid = ucred.gid;
-
- r = audit_loginuid_from_pid(ucred.pid, &audit->loginuid);
- if (r < 0)
- return r;
-
- r = get_process_cmdline(ucred.pid, LINE_MAX, true, &audit->cmdline);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-/*
- This function returns the security context of the remote end of the dbus
- connections. Whether it is on the bus or a local connection.
-*/
-static int get_calling_context(
- DBusConnection *connection,
- DBusMessage *message,
- security_context_t *scon,
- DBusError *error) {
-
- const char *sender;
- int r;
- int fd;
-
- /*
- If sender exists then
- if sender is NULL this indicates a local connection. Grab the fd
- from dbus and do an getpeercon to peers process context
- */
- sender = dbus_message_get_sender(message);
- if (sender) {
- log_error("SELinux Got Sender %s", sender);
-
- r = bus_get_selinux_security_context(connection, sender, scon, error);
- if (r >= 0)
- return r;
-
- log_error("bus_get_selinux_security_context failed: %m");
- return r;
- }
-
- log_debug("SELinux No Sender");
- if (!dbus_connection_get_unix_fd(connection, &fd)) {
- log_error("bus_connection_get_unix_fd failed %m");
- return -EINVAL;
- }
-
- r = getpeercon(fd, scon);
- if (r < 0) {
- log_error("getpeercon failed %m");
- return -errno;
- }
-
- return 0;
-}
-
-/*
- This function communicates with the kernel to check whether or not it should
- allow the access.
- If the machine is in permissive mode it will return ok. Audit messages will
- still be generated if the access would be denied in enforcing mode.
-*/
-int selinux_access_check(
- DBusConnection *connection,
- DBusMessage *message,
- const char *path,
- const char *permission,
- DBusError *error) {
-
- security_context_t scon = NULL, fcon = NULL;
- int r = 0;
- const char *tclass = NULL;
- struct auditstruct audit;
-
- assert(connection);
- assert(message);
- assert(permission);
- assert(error);
-
- if (!use_selinux())
- return 0;
-
- r = selinux_access_init(error);
- if (r < 0)
- return r;
-
- log_debug("SELinux access check for path=%s permission=%s", strna(path), permission);
-
- audit.uid = audit.loginuid = (uid_t) -1;
- audit.gid = (gid_t) -1;
- audit.cmdline = NULL;
- audit.path = path;
-
- r = get_calling_context(connection, message, &scon, error);
- if (r < 0) {
- log_error("Failed to get caller's security context on: %m");
- goto finish;
- }
-
- if (path) {
- tclass = "service";
- /* get the file context of the unit file */
- r = getfilecon(path, &fcon);
- if (r < 0) {
- dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "Failed to get file context on %s.", path);
- r = -errno;
- log_error("Failed to get security context on %s: %m",path);
- goto finish;
- }
-
- } else {
- tclass = "system";
- r = getcon(&fcon);
- if (r < 0) {
- dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "Failed to get current context.");
- r = -errno;
- log_error("Failed to get current process context on: %m");
- goto finish;
- }
- }
-
- (void) get_audit_data(connection, message, &audit, error);
-
- errno = 0;
- r = selinux_check_access(scon, fcon, tclass, permission, &audit);
- if (r < 0) {
- dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "SELinux policy denies access.");
- r = -errno;
- log_error("SELinux policy denies access.");
- }
-
- log_debug("SELinux access check scon=%s tcon=%s tclass=%s perm=%s path=%s cmdline=%s: %i", scon, fcon, tclass, permission, path, audit.cmdline, r);
-
-finish:
- free(audit.cmdline);
- freecon(scon);
- freecon(fcon);
-
- if (r && security_getenforce() != 1) {
- dbus_error_init(error);
- r = 0;
- }
-
- return r;
-}
-
-#else
-
-int selinux_access_check(
- DBusConnection *connection,
- DBusMessage *message,
- const char *path,
- const char *permission,
- DBusError *error) {
-
- return 0;
-}
-
-void selinux_access_free(void) {
-}
-
-#endif
diff --git a/src/core/selinux-access.h b/src/core/selinux-access.h
deleted file mode 100644
index 9183cbc9a6..0000000000
--- a/src/core/selinux-access.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Dan Walsh
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <dbus.h>
-
-void selinux_access_free(void);
-
-int selinux_access_check(DBusConnection *connection, DBusMessage *message, const char *path, const char *permission, DBusError *error);
-
-#ifdef HAVE_SELINUX
-
-#define SELINUX_ACCESS_CHECK(connection, message, permission) \
- do { \
- DBusError _error; \
- int _r; \
- DBusConnection *_c = (connection); \
- DBusMessage *_m = (message); \
- dbus_error_init(&_error); \
- _r = selinux_access_check(_c, _m, NULL, (permission), &_error); \
- if (_r < 0) \
- return bus_send_error_reply(_c, _m, &_error, _r); \
- } while (false)
-
-#define SELINUX_UNIT_ACCESS_CHECK(unit, connection, message, permission) \
- do { \
- DBusError _error; \
- int _r; \
- DBusConnection *_c = (connection); \
- DBusMessage *_m = (message); \
- Unit *_u = (unit); \
- dbus_error_init(&_error); \
- _r = selinux_access_check(_c, _m, _u->source_path ?: _u->fragment_path, (permission), &_error); \
- if (_r < 0) \
- return bus_send_error_reply(_c, _m, &_error, _r); \
- } while (false)
-
-#else
-
-#define SELINUX_ACCESS_CHECK(connection, message, permission) do { } while (false)
-#define SELINUX_UNIT_ACCESS_CHECK(unit, connection, message, permission) do { } while (false)
-
-#endif
diff --git a/src/core/selinux-setup.c b/src/core/selinux-setup.c
deleted file mode 100644
index e9c0de92f1..0000000000
--- a/src/core/selinux-setup.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*-*- 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 <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-
-#ifdef HAVE_SELINUX
-#include <selinux/selinux.h>
-#endif
-
-#include "selinux-setup.h"
-#include "selinux-util.h"
-#include "label.h"
-#include "mount-setup.h"
-#include "macro.h"
-#include "util.h"
-#include "log.h"
-
-#ifdef HAVE_SELINUX
-static int null_log(int type, const char *fmt, ...) {
- return 0;
-}
-#endif
-
-int selinux_setup(bool *loaded_policy) {
-
-#ifdef HAVE_SELINUX
- int enforce = 0;
- usec_t before_load, after_load;
- security_context_t con;
- int r;
- union selinux_callback cb;
-
- assert(loaded_policy);
-
- /* Turn off all of SELinux' own logging, we want to do that */
- cb.func_log = null_log;
- selinux_set_callback(SELINUX_CB_LOG, cb);
-
- /* Make sure getcon() works, which needs /proc and /sys */
- mount_setup_early();
-
- /* Already initialized by somebody else? */
- r = getcon_raw(&con);
- if (r == 0) {
- bool initialized;
-
- initialized = !streq(con, "kernel");
- freecon(con);
-
- if (initialized)
- return 0;
- }
-
- /* Make sure we have no fds open while loading the policy and
- * transitioning */
- log_close();
-
- /* Now load the policy */
- before_load = now(CLOCK_MONOTONIC);
- r = selinux_init_load_policy(&enforce);
- if (r == 0) {
- char timespan[FORMAT_TIMESPAN_MAX];
- char *label;
-
- retest_selinux();
-
- /* Transition to the new context */
- r = label_get_create_label_from_exe(SYSTEMD_BINARY_PATH, &label);
- if (r < 0 || label == NULL) {
- log_open();
- log_error("Failed to compute init label, ignoring.");
- } else {
- r = setcon(label);
-
- log_open();
- if (r < 0)
- log_error("Failed to transition into init label '%s', ignoring.", label);
-
- label_free(label);
- }
-
- after_load = now(CLOCK_MONOTONIC);
-
- log_info("Successfully loaded SELinux policy in %s.",
- format_timespan(timespan, sizeof(timespan), after_load - before_load));
-
- *loaded_policy = true;
-
- } else {
- log_open();
-
- if (enforce > 0) {
- log_error("Failed to load SELinux policy. Freezing.");
- return -EIO;
- } else
- log_debug("Unable to load SELinux policy. Ignoring.");
- }
-#endif
-
- return 0;
-}
diff --git a/src/core/selinux-setup.h b/src/core/selinux-setup.h
deleted file mode 100644
index 39e2bc25bb..0000000000
--- a/src/core/selinux-setup.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*-*- 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 selinux_setup(bool *loaded_policy);
diff --git a/src/core/service.c b/src/core/service.c
deleted file mode 100644
index cf08485374..0000000000
--- a/src/core/service.c
+++ /dev/null
@@ -1,3941 +0,0 @@
-/*-*- 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 <errno.h>
-#include <signal.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <sys/reboot.h>
-
-#include "manager.h"
-#include "unit.h"
-#include "service.h"
-#include "load-fragment.h"
-#include "load-dropin.h"
-#include "log.h"
-#include "strv.h"
-#include "unit-name.h"
-#include "unit-printf.h"
-#include "dbus-service.h"
-#include "special.h"
-#include "bus-errors.h"
-#include "exit-status.h"
-#include "def.h"
-#include "path-util.h"
-#include "util.h"
-#include "utf8.h"
-
-#ifdef HAVE_SYSV_COMPAT
-
-#define DEFAULT_SYSV_TIMEOUT_USEC (5*USEC_PER_MINUTE)
-
-typedef enum RunlevelType {
- RUNLEVEL_UP,
- RUNLEVEL_DOWN,
- RUNLEVEL_SYSINIT
-} RunlevelType;
-
-static const struct {
- const char *path;
- const char *target;
- const RunlevelType type;
-} rcnd_table[] = {
- /* Standard SysV runlevels for start-up */
- { "rc1.d", SPECIAL_RESCUE_TARGET, RUNLEVEL_UP },
- { "rc2.d", SPECIAL_RUNLEVEL2_TARGET, RUNLEVEL_UP },
- { "rc3.d", SPECIAL_RUNLEVEL3_TARGET, RUNLEVEL_UP },
- { "rc4.d", SPECIAL_RUNLEVEL4_TARGET, RUNLEVEL_UP },
- { "rc5.d", SPECIAL_RUNLEVEL5_TARGET, RUNLEVEL_UP },
-
-#ifdef TARGET_SUSE
- /* SUSE style boot.d */
- { "boot.d", SPECIAL_SYSINIT_TARGET, RUNLEVEL_SYSINIT },
-#endif
-
-#if defined(TARGET_DEBIAN) || defined(TARGET_UBUNTU) || defined(TARGET_ANGSTROM)
- /* Debian style rcS.d */
- { "rcS.d", SPECIAL_SYSINIT_TARGET, RUNLEVEL_SYSINIT },
-#endif
-
- /* Standard SysV runlevels for shutdown */
- { "rc0.d", SPECIAL_POWEROFF_TARGET, RUNLEVEL_DOWN },
- { "rc6.d", SPECIAL_REBOOT_TARGET, RUNLEVEL_DOWN }
-
- /* Note that the order here matters, as we read the
- directories in this order, and we want to make sure that
- sysv_start_priority is known when we first load the
- unit. And that value we only know from S links. Hence
- UP/SYSINIT must be read before DOWN */
-};
-
-#define RUNLEVELS_UP "12345"
-/* #define RUNLEVELS_DOWN "06" */
-#define RUNLEVELS_BOOT "bBsS"
-#endif
-
-static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = {
- [SERVICE_DEAD] = UNIT_INACTIVE,
- [SERVICE_START_PRE] = UNIT_ACTIVATING,
- [SERVICE_START] = UNIT_ACTIVATING,
- [SERVICE_START_POST] = UNIT_ACTIVATING,
- [SERVICE_RUNNING] = UNIT_ACTIVE,
- [SERVICE_EXITED] = UNIT_ACTIVE,
- [SERVICE_RELOAD] = UNIT_RELOADING,
- [SERVICE_STOP] = UNIT_DEACTIVATING,
- [SERVICE_STOP_SIGTERM] = UNIT_DEACTIVATING,
- [SERVICE_STOP_SIGKILL] = UNIT_DEACTIVATING,
- [SERVICE_STOP_POST] = UNIT_DEACTIVATING,
- [SERVICE_FINAL_SIGTERM] = UNIT_DEACTIVATING,
- [SERVICE_FINAL_SIGKILL] = UNIT_DEACTIVATING,
- [SERVICE_FAILED] = UNIT_FAILED,
- [SERVICE_AUTO_RESTART] = UNIT_ACTIVATING
-};
-
-/* For Type=idle we never want to delay any other jobs, hence we
- * consider idle jobs active as soon as we start working on them */
-static const UnitActiveState state_translation_table_idle[_SERVICE_STATE_MAX] = {
- [SERVICE_DEAD] = UNIT_INACTIVE,
- [SERVICE_START_PRE] = UNIT_ACTIVE,
- [SERVICE_START] = UNIT_ACTIVE,
- [SERVICE_START_POST] = UNIT_ACTIVE,
- [SERVICE_RUNNING] = UNIT_ACTIVE,
- [SERVICE_EXITED] = UNIT_ACTIVE,
- [SERVICE_RELOAD] = UNIT_RELOADING,
- [SERVICE_STOP] = UNIT_DEACTIVATING,
- [SERVICE_STOP_SIGTERM] = UNIT_DEACTIVATING,
- [SERVICE_STOP_SIGKILL] = UNIT_DEACTIVATING,
- [SERVICE_STOP_POST] = UNIT_DEACTIVATING,
- [SERVICE_FINAL_SIGTERM] = UNIT_DEACTIVATING,
- [SERVICE_FINAL_SIGKILL] = UNIT_DEACTIVATING,
- [SERVICE_FAILED] = UNIT_FAILED,
- [SERVICE_AUTO_RESTART] = UNIT_ACTIVATING
-};
-
-static void service_init(Unit *u) {
- Service *s = SERVICE(u);
-
- assert(u);
- assert(u->load_state == UNIT_STUB);
-
- s->timeout_start_usec = DEFAULT_TIMEOUT_USEC;
- s->timeout_stop_usec = DEFAULT_TIMEOUT_USEC;
- s->restart_usec = DEFAULT_RESTART_USEC;
- s->type = _SERVICE_TYPE_INVALID;
-
- s->watchdog_watch.type = WATCH_INVALID;
-
- s->timer_watch.type = WATCH_INVALID;
-#ifdef HAVE_SYSV_COMPAT
- s->sysv_start_priority = -1;
- s->sysv_start_priority_from_rcnd = -1;
-#endif
- s->socket_fd = -1;
- s->guess_main_pid = true;
-
- exec_context_init(&s->exec_context);
- kill_context_init(&s->kill_context);
-
- RATELIMIT_INIT(s->start_limit, 10*USEC_PER_SEC, 5);
-
- s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID;
-}
-
-static void service_unwatch_control_pid(Service *s) {
- assert(s);
-
- if (s->control_pid <= 0)
- return;
-
- unit_unwatch_pid(UNIT(s), s->control_pid);
- s->control_pid = 0;
-}
-
-static void service_unwatch_main_pid(Service *s) {
- assert(s);
-
- if (s->main_pid <= 0)
- return;
-
- unit_unwatch_pid(UNIT(s), s->main_pid);
- s->main_pid = 0;
-}
-
-static void service_unwatch_pid_file(Service *s) {
- if (!s->pid_file_pathspec)
- return;
-
- log_debug("Stopping watch for %s's PID file %s", UNIT(s)->id, s->pid_file_pathspec->path);
- path_spec_unwatch(s->pid_file_pathspec, UNIT(s));
- path_spec_done(s->pid_file_pathspec);
- free(s->pid_file_pathspec);
- s->pid_file_pathspec = NULL;
-}
-
-static int service_set_main_pid(Service *s, pid_t pid) {
- pid_t ppid;
-
- assert(s);
-
- if (pid <= 1)
- return -EINVAL;
-
- if (pid == getpid())
- return -EINVAL;
-
- s->main_pid = pid;
- s->main_pid_known = true;
-
- if (get_parent_of_pid(pid, &ppid) >= 0 && ppid != getpid()) {
- log_warning("%s: Supervising process %lu which is not our child. We'll most likely not notice when it exits.",
- UNIT(s)->id, (unsigned long) pid);
-
- s->main_pid_alien = true;
- } else
- s->main_pid_alien = false;
-
- exec_status_start(&s->main_exec_status, pid);
-
- return 0;
-}
-
-static void service_close_socket_fd(Service *s) {
- assert(s);
-
- if (s->socket_fd < 0)
- return;
-
- close_nointr_nofail(s->socket_fd);
- s->socket_fd = -1;
-}
-
-static void service_connection_unref(Service *s) {
- assert(s);
-
- if (!UNIT_DEREF(s->accept_socket))
- return;
-
- socket_connection_unref(SOCKET(UNIT_DEREF(s->accept_socket)));
- unit_ref_unset(&s->accept_socket);
-}
-
-static void service_stop_watchdog(Service *s) {
- assert(s);
-
- unit_unwatch_timer(UNIT(s), &s->watchdog_watch);
- s->watchdog_timestamp.realtime = 0;
- s->watchdog_timestamp.monotonic = 0;
-}
-
-static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart);
-
-static void service_handle_watchdog(Service *s) {
- usec_t offset;
- int r;
-
- assert(s);
-
- if (s->watchdog_usec == 0)
- return;
-
- offset = now(CLOCK_MONOTONIC) - s->watchdog_timestamp.monotonic;
- if (offset >= s->watchdog_usec) {
- log_error("%s watchdog timeout!", UNIT(s)->id);
- service_enter_dead(s, SERVICE_FAILURE_WATCHDOG, true);
- return;
- }
-
- r = unit_watch_timer(UNIT(s), s->watchdog_usec - offset, &s->watchdog_watch);
- if (r < 0)
- log_warning("%s failed to install watchdog timer: %s", UNIT(s)->id, strerror(-r));
-}
-
-static void service_reset_watchdog(Service *s) {
- assert(s);
-
- dual_timestamp_get(&s->watchdog_timestamp);
- service_handle_watchdog(s);
-}
-
-static void service_done(Unit *u) {
- Service *s = SERVICE(u);
-
- assert(s);
-
- free(s->pid_file);
- s->pid_file = NULL;
-
-#ifdef HAVE_SYSV_COMPAT
- free(s->sysv_runlevels);
- s->sysv_runlevels = NULL;
-#endif
-
- free(s->status_text);
- s->status_text = NULL;
-
- exec_context_done(&s->exec_context);
- exec_command_free_array(s->exec_command, _SERVICE_EXEC_COMMAND_MAX);
- s->control_command = NULL;
- s->main_command = NULL;
-
- set_free(s->restart_ignore_status.code);
- s->restart_ignore_status.code = NULL;
- set_free(s->restart_ignore_status.signal);
- s->restart_ignore_status.signal = NULL;
-
- set_free(s->success_status.code);
- s->success_status.code = NULL;
- set_free(s->success_status.signal);
- s->success_status.signal = NULL;
-
- /* This will leak a process, but at least no memory or any of
- * our resources */
- service_unwatch_main_pid(s);
- service_unwatch_control_pid(s);
- service_unwatch_pid_file(s);
-
- if (s->bus_name) {
- unit_unwatch_bus_name(u, s->bus_name);
- free(s->bus_name);
- s->bus_name = NULL;
- }
-
- service_close_socket_fd(s);
- service_connection_unref(s);
-
- unit_ref_unset(&s->accept_socket);
-
- service_stop_watchdog(s);
-
- unit_unwatch_timer(u, &s->timer_watch);
-}
-
-#ifdef HAVE_SYSV_COMPAT
-static char *sysv_translate_name(const char *name) {
- char *r;
-
- if (!(r = new(char, strlen(name) + sizeof(".service"))))
- return NULL;
-
-#if defined(TARGET_DEBIAN) || defined(TARGET_UBUNTU) || defined(TARGET_ANGSTROM)
- if (endswith(name, ".sh"))
- /* Drop Debian-style .sh suffix */
- strcpy(stpcpy(r, name) - 3, ".service");
-#endif
-#ifdef TARGET_SUSE
- if (startswith(name, "boot."))
- /* Drop SuSE-style boot. prefix */
- strcpy(stpcpy(r, name + 5), ".service");
-#endif
-#ifdef TARGET_FRUGALWARE
- if (startswith(name, "rc."))
- /* Drop Frugalware-style rc. prefix */
- strcpy(stpcpy(r, name + 3), ".service");
-#endif
- else
- /* Normal init scripts */
- strcpy(stpcpy(r, name), ".service");
-
- return r;
-}
-
-static int sysv_translate_facility(const char *name, const char *filename, char **_r) {
-
- /* We silently ignore the $ prefix here. According to the LSB
- * spec it simply indicates whether something is a
- * standardized name or a distribution-specific one. Since we
- * just follow what already exists and do not introduce new
- * uses or names we don't care who introduced a new name. */
-
- static const char * const table[] = {
- /* LSB defined facilities */
- "local_fs", SPECIAL_LOCAL_FS_TARGET,
-#if defined(TARGET_MANDRIVA) || defined(TARGET_MAGEIA)
-#else
- /* Due to unfortunate name selection in Mandriva,
- * $network is provided by network-up which is ordered
- * after network which actually starts interfaces.
- * To break the loop, just ignore it */
- "network", SPECIAL_NETWORK_TARGET,
-#endif
- "named", SPECIAL_NSS_LOOKUP_TARGET,
- "portmap", SPECIAL_RPCBIND_TARGET,
- "remote_fs", SPECIAL_REMOTE_FS_TARGET,
- "syslog", SPECIAL_SYSLOG_TARGET,
- "time", SPECIAL_TIME_SYNC_TARGET,
-
- /* common extensions */
- "mail-transfer-agent", SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
- "x-display-manager", SPECIAL_DISPLAY_MANAGER_SERVICE,
- "null", NULL,
-
-#if defined(TARGET_DEBIAN) || defined(TARGET_UBUNTU) || defined(TARGET_ANGSTROM)
- "mail-transport-agent", SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
-#endif
-
-#ifdef TARGET_SUSE
- "smtp", SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
-#endif
- };
-
- unsigned i;
- char *r;
- const char *n;
-
- assert(name);
- assert(_r);
-
- 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;
-
- if (!(r = strdup(table[i+1])))
- return -ENOMEM;
-
- goto finish;
- }
-
- /* If we don't know this name, fallback heuristics to figure
- * out whether something is a target or a service alias. */
-
- if (*name == '$') {
- if (!unit_prefix_is_valid(n))
- return -EINVAL;
-
- /* Facilities starting with $ are most likely targets */
- r = unit_name_build(n, NULL, ".target");
- } else if (filename && streq(name, filename))
- /* Names equaling the file name of the services are redundant */
- return 0;
- else
- /* Everything else we assume to be normal service names */
- r = sysv_translate_name(n);
-
- if (!r)
- return -ENOMEM;
-
-finish:
- *_r = r;
-
- return 1;
-}
-
-static int sysv_fix_order(Service *s) {
- Unit *other;
- int r;
-
- assert(s);
-
- if (s->sysv_start_priority < 0)
- return 0;
-
- /* For each pair of services where at least one lacks a LSB
- * header, we use the start priority value to order things. */
-
- LIST_FOREACH(units_by_type, other, UNIT(s)->manager->units_by_type[UNIT_SERVICE]) {
- Service *t;
- UnitDependency d;
- bool special_s, special_t;
-
- t = SERVICE(other);
-
- if (s == t)
- continue;
-
- if (UNIT(t)->load_state != UNIT_LOADED)
- continue;
-
- if (t->sysv_start_priority < 0)
- continue;
-
- /* If both units have modern headers we don't care
- * about the priorities */
- if ((UNIT(s)->fragment_path || s->sysv_has_lsb) &&
- (UNIT(t)->fragment_path || t->sysv_has_lsb))
- continue;
-
- special_s = s->sysv_runlevels && !chars_intersect(RUNLEVELS_UP, s->sysv_runlevels);
- special_t = t->sysv_runlevels && !chars_intersect(RUNLEVELS_UP, t->sysv_runlevels);
-
- if (special_t && !special_s)
- d = UNIT_AFTER;
- else if (special_s && !special_t)
- d = UNIT_BEFORE;
- else if (t->sysv_start_priority < s->sysv_start_priority)
- d = UNIT_AFTER;
- else if (t->sysv_start_priority > s->sysv_start_priority)
- d = UNIT_BEFORE;
- else
- continue;
-
- /* FIXME: Maybe we should compare the name here lexicographically? */
-
- if ((r = unit_add_dependency(UNIT(s), d, UNIT(t), true)) < 0)
- return r;
- }
-
- return 0;
-}
-
-static ExecCommand *exec_command_new(const char *path, const char *arg1) {
- ExecCommand *c;
-
- if (!(c = new0(ExecCommand, 1)))
- return NULL;
-
- if (!(c->path = strdup(path))) {
- free(c);
- return NULL;
- }
-
- if (!(c->argv = strv_new(path, arg1, NULL))) {
- free(c->path);
- free(c);
- return NULL;
- }
-
- return c;
-}
-
-static int sysv_exec_commands(Service *s, const bool supports_reload) {
- ExecCommand *c;
-
- assert(s);
- assert(s->is_sysv);
- assert(UNIT(s)->source_path);
-
- c = exec_command_new(UNIT(s)->source_path, "start");
- if (!c)
- return -ENOMEM;
- exec_command_append_list(s->exec_command+SERVICE_EXEC_START, c);
-
- c = exec_command_new(UNIT(s)->source_path, "stop");
- if (!c)
- return -ENOMEM;
- exec_command_append_list(s->exec_command+SERVICE_EXEC_STOP, c);
-
- if (supports_reload) {
- c = exec_command_new(UNIT(s)->source_path, "reload");
- if (!c)
- return -ENOMEM;
- exec_command_append_list(s->exec_command+SERVICE_EXEC_RELOAD, c);
- }
-
- return 0;
-}
-
-static bool usage_contains_reload(const char *line) {
- return (strcasestr(line, "{reload|") ||
- strcasestr(line, "{reload}") ||
- strcasestr(line, "{reload\"") ||
- strcasestr(line, "|reload|") ||
- strcasestr(line, "|reload}") ||
- strcasestr(line, "|reload\""));
-}
-
-static int service_load_sysv_path(Service *s, const char *path) {
- FILE *f;
- Unit *u;
- unsigned line = 0;
- int r;
- enum {
- NORMAL,
- DESCRIPTION,
- LSB,
- LSB_DESCRIPTION,
- USAGE_CONTINUATION
- } state = NORMAL;
- char *short_description = NULL, *long_description = NULL, *chkconfig_description = NULL, *description;
- struct stat st;
- bool supports_reload = false;
-
- assert(s);
- assert(path);
-
- u = UNIT(s);
-
- f = fopen(path, "re");
- if (!f) {
- r = errno == ENOENT ? 0 : -errno;
- goto finish;
- }
-
- if (fstat(fileno(f), &st) < 0) {
- r = -errno;
- goto finish;
- }
-
- free(u->source_path);
- u->source_path = strdup(path);
- if (!u->source_path) {
- r = -ENOMEM;
- goto finish;
- }
- u->source_mtime = timespec_load(&st.st_mtim);
-
- if (null_or_empty(&st)) {
- u->load_state = UNIT_MASKED;
- r = 0;
- goto finish;
- }
-
- s->is_sysv = true;
-
- while (!feof(f)) {
- char l[LINE_MAX], *t;
-
- if (!fgets(l, sizeof(l), f)) {
- if (feof(f))
- break;
-
- r = -errno;
- log_error("Failed to read configuration file '%s': %s", path, strerror(-r));
- goto finish;
- }
-
- line++;
-
- t = strstrip(l);
- if (*t != '#') {
- /* Try to figure out whether this init script supports
- * the reload operation. This heuristic looks for
- * "Usage" lines which include the reload option. */
- if ( state == USAGE_CONTINUATION ||
- (state == NORMAL && strcasestr(t, "usage"))) {
- if (usage_contains_reload(t)) {
- supports_reload = true;
- state = NORMAL;
- } else if (t[strlen(t)-1] == '\\')
- state = USAGE_CONTINUATION;
- else
- state = NORMAL;
- }
-
- continue;
- }
-
- if (state == NORMAL && streq(t, "### BEGIN INIT INFO")) {
- state = LSB;
- s->sysv_has_lsb = true;
- continue;
- }
-
- if ((state == LSB_DESCRIPTION || state == LSB) && streq(t, "### END INIT INFO")) {
- state = NORMAL;
- continue;
- }
-
- t++;
- t += strspn(t, WHITESPACE);
-
- if (state == NORMAL) {
-
- /* Try to parse Red Hat style chkconfig headers */
-
- if (startswith_no_case(t, "chkconfig:")) {
- int start_priority;
- char runlevels[16], *k;
-
- state = NORMAL;
-
- if (sscanf(t+10, "%15s %i %*i",
- runlevels,
- &start_priority) != 2) {
-
- log_warning("[%s:%u] Failed to parse chkconfig line. Ignoring.", path, line);
- continue;
- }
-
- /* A start priority gathered from the
- * symlink farms is preferred over the
- * data from the LSB header. */
- if (start_priority < 0 || start_priority > 99)
- log_warning("[%s:%u] Start priority out of range. Ignoring.", path, line);
- else
- s->sysv_start_priority = start_priority;
-
- char_array_0(runlevels);
- k = delete_chars(runlevels, WHITESPACE "-");
-
- if (k[0]) {
- char *d;
-
- if (!(d = strdup(k))) {
- r = -ENOMEM;
- goto finish;
- }
-
- free(s->sysv_runlevels);
- s->sysv_runlevels = d;
- }
-
- } else if (startswith_no_case(t, "description:")) {
-
- size_t k = strlen(t);
- char *d;
- const char *j;
-
- if (t[k-1] == '\\') {
- state = DESCRIPTION;
- t[k-1] = 0;
- }
-
- if ((j = strstrip(t+12)) && *j) {
- if (!(d = strdup(j))) {
- r = -ENOMEM;
- goto finish;
- }
- } else
- d = NULL;
-
- free(chkconfig_description);
- chkconfig_description = d;
-
- } else if (startswith_no_case(t, "pidfile:")) {
-
- char *fn;
-
- state = NORMAL;
-
- fn = strstrip(t+8);
- if (!path_is_absolute(fn)) {
- log_warning("[%s:%u] PID file not absolute. Ignoring.", path, line);
- continue;
- }
-
- if (!(fn = strdup(fn))) {
- r = -ENOMEM;
- goto finish;
- }
-
- free(s->pid_file);
- s->pid_file = fn;
- }
-
- } else if (state == DESCRIPTION) {
-
- /* Try to parse Red Hat style description
- * continuation */
-
- size_t k = strlen(t);
- char *j;
-
- if (t[k-1] == '\\')
- t[k-1] = 0;
- else
- state = NORMAL;
-
- if ((j = strstrip(t)) && *j) {
- char *d = NULL;
-
- if (chkconfig_description)
- d = strjoin(chkconfig_description, " ", j, NULL);
- else
- d = strdup(j);
-
- if (!d) {
- r = -ENOMEM;
- goto finish;
- }
-
- free(chkconfig_description);
- chkconfig_description = d;
- }
-
- } else if (state == LSB || state == LSB_DESCRIPTION) {
-
- if (startswith_no_case(t, "Provides:")) {
- char *i, *w;
- size_t z;
-
- state = LSB;
-
- FOREACH_WORD_QUOTED(w, z, t+9, i) {
- char *n, *m;
-
- if (!(n = strndup(w, z))) {
- r = -ENOMEM;
- goto finish;
- }
-
- r = sysv_translate_facility(n, path_get_file_name(path), &m);
- free(n);
-
- if (r < 0)
- goto finish;
-
- if (r == 0)
- continue;
-
- if (unit_name_to_type(m) == UNIT_SERVICE)
- r = unit_add_name(u, m);
- else
- /* 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 the SysV
- * services! */
- r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_WANTS, m, NULL, true);
-
- if (r < 0)
- log_error("[%s:%u] Failed to add LSB Provides name %s, ignoring: %s", path, line, m, strerror(-r));
-
- free(m);
- }
-
- } else if (startswith_no_case(t, "Required-Start:") ||
- startswith_no_case(t, "Should-Start:") ||
- startswith_no_case(t, "X-Start-Before:") ||
- startswith_no_case(t, "X-Start-After:")) {
- char *i, *w;
- size_t z;
-
- state = LSB;
-
- FOREACH_WORD_QUOTED(w, z, strchr(t, ':')+1, i) {
- char *n, *m;
-
- if (!(n = strndup(w, z))) {
- r = -ENOMEM;
- goto finish;
- }
-
- r = sysv_translate_facility(n, path_get_file_name(path), &m);
-
- if (r < 0) {
- log_error("[%s:%u] Failed to translate LSB dependency %s, ignoring: %s", path, line, n, strerror(-r));
- free(n);
- continue;
- }
-
- free(n);
-
- if (r == 0)
- continue;
-
- r = unit_add_dependency_by_name(u, startswith_no_case(t, "X-Start-Before:") ? UNIT_BEFORE : UNIT_AFTER, m, NULL, true);
-
- if (r < 0)
- log_error("[%s:%u] Failed to add dependency on %s, ignoring: %s", path, line, m, strerror(-r));
-
- free(m);
- }
- } else if (startswith_no_case(t, "Default-Start:")) {
- char *k, *d;
-
- state = LSB;
-
- k = delete_chars(t+14, WHITESPACE "-");
-
- if (k[0] != 0) {
- if (!(d = strdup(k))) {
- r = -ENOMEM;
- goto finish;
- }
-
- free(s->sysv_runlevels);
- s->sysv_runlevels = d;
- }
-
- } else if (startswith_no_case(t, "Description:")) {
- char *d, *j;
-
- state = LSB_DESCRIPTION;
-
- if ((j = strstrip(t+12)) && *j) {
- if (!(d = strdup(j))) {
- r = -ENOMEM;
- goto finish;
- }
- } else
- d = NULL;
-
- free(long_description);
- long_description = d;
-
- } else if (startswith_no_case(t, "Short-Description:")) {
- char *d, *j;
-
- state = LSB;
-
- if ((j = strstrip(t+18)) && *j) {
- if (!(d = strdup(j))) {
- r = -ENOMEM;
- goto finish;
- }
- } else
- d = NULL;
-
- free(short_description);
- short_description = d;
-
- } else if (state == LSB_DESCRIPTION) {
-
- if (startswith(l, "#\t") || startswith(l, "# ")) {
- char *j;
-
- if ((j = strstrip(t)) && *j) {
- char *d = NULL;
-
- if (long_description)
- d = strjoin(long_description, " ", t, NULL);
- else
- d = strdup(j);
-
- if (!d) {
- r = -ENOMEM;
- goto finish;
- }
-
- free(long_description);
- long_description = d;
- }
-
- } else
- state = LSB;
- }
- }
- }
-
- if ((r = sysv_exec_commands(s, supports_reload)) < 0)
- goto finish;
- if (s->sysv_runlevels &&
- chars_intersect(RUNLEVELS_BOOT, s->sysv_runlevels) &&
- chars_intersect(RUNLEVELS_UP, s->sysv_runlevels)) {
- /* Service has both boot and "up" runlevels
- configured. Kill the "up" ones. */
- delete_chars(s->sysv_runlevels, RUNLEVELS_UP);
- }
-
- if (s->sysv_runlevels && !chars_intersect(RUNLEVELS_UP, s->sysv_runlevels)) {
- /* If there a runlevels configured for this service
- * but none of the standard ones, then we assume this
- * is some special kind of service (which might be
- * needed for early boot) and don't create any links
- * to it. */
-
- UNIT(s)->default_dependencies = false;
-
- /* Don't timeout special services during boot (like fsck) */
- s->timeout_start_usec = 0;
- s->timeout_stop_usec = 0;
- } else {
- s->timeout_start_usec = DEFAULT_SYSV_TIMEOUT_USEC;
- s->timeout_stop_usec = DEFAULT_SYSV_TIMEOUT_USEC;
- }
-
- /* Special setting for all SysV services */
- s->type = SERVICE_FORKING;
- s->remain_after_exit = !s->pid_file;
- s->guess_main_pid = false;
- s->restart = SERVICE_RESTART_NO;
- s->exec_context.ignore_sigpipe = false;
- s->kill_context.kill_mode = KILL_PROCESS;
-
- /* We use the long description only if
- * no short description is set. */
-
- if (short_description)
- description = short_description;
- else if (chkconfig_description)
- description = chkconfig_description;
- else if (long_description)
- description = long_description;
- else
- description = NULL;
-
- if (description) {
- char *d;
-
- if (!(d = strappend(s->sysv_has_lsb ? "LSB: " : "SYSV: ", description))) {
- r = -ENOMEM;
- goto finish;
- }
-
- u->description = d;
- }
-
- /* The priority that has been set in /etc/rcN.d/ hierarchies
- * takes precedence over what is stored as default in the LSB
- * header */
- if (s->sysv_start_priority_from_rcnd >= 0)
- s->sysv_start_priority = s->sysv_start_priority_from_rcnd;
-
- u->load_state = UNIT_LOADED;
- r = 0;
-
-finish:
-
- if (f)
- fclose(f);
-
- free(short_description);
- free(long_description);
- free(chkconfig_description);
-
- return r;
-}
-
-static int service_load_sysv_name(Service *s, const char *name) {
- char **p;
-
- assert(s);
- assert(name);
-
- /* For SysV services we strip the boot.*, rc.* and *.sh
- * prefixes/suffixes. */
-#if defined(TARGET_DEBIAN) || defined(TARGET_UBUNTU) || defined(TARGET_ANGSTROM)
- if (endswith(name, ".sh.service"))
- return -ENOENT;
-#endif
-
-#ifdef TARGET_SUSE
- if (startswith(name, "boot."))
- return -ENOENT;
-#endif
-
-#ifdef TARGET_FRUGALWARE
- if (startswith(name, "rc."))
- return -ENOENT;
-#endif
-
- STRV_FOREACH(p, UNIT(s)->manager->lookup_paths.sysvinit_path) {
- char *path;
- int r;
-
- path = strjoin(*p, "/", name, NULL);
- if (!path)
- return -ENOMEM;
-
- assert(endswith(path, ".service"));
- path[strlen(path)-8] = 0;
-
- r = service_load_sysv_path(s, path);
-
-#if defined(TARGET_DEBIAN) || defined(TARGET_UBUNTU) || defined(TARGET_ANGSTROM)
- if (r >= 0 && UNIT(s)->load_state == UNIT_STUB) {
- /* Try Debian style *.sh source'able init scripts */
- strcat(path, ".sh");
- r = service_load_sysv_path(s, path);
- }
-#endif
- free(path);
-
-#ifdef TARGET_SUSE
- if (r >= 0 && UNIT(s)->load_state == UNIT_STUB) {
- /* Try SUSE style boot.* init scripts */
-
- path = strjoin(*p, "/boot.", name, NULL);
- if (!path)
- return -ENOMEM;
-
- /* Drop .service suffix */
- path[strlen(path)-8] = 0;
- r = service_load_sysv_path(s, path);
- free(path);
- }
-#endif
-
-#ifdef TARGET_FRUGALWARE
- if (r >= 0 && UNIT(s)->load_state == UNIT_STUB) {
- /* Try Frugalware style rc.* init scripts */
-
- path = strjoin(*p, "/rc.", name, NULL);
- if (!path)
- return -ENOMEM;
-
- /* Drop .service suffix */
- path[strlen(path)-8] = 0;
- r = service_load_sysv_path(s, path);
- free(path);
- }
-#endif
-
- if (r < 0)
- return r;
-
- if ((UNIT(s)->load_state != UNIT_STUB))
- break;
- }
-
- return 0;
-}
-
-static int service_load_sysv(Service *s) {
- const char *t;
- Iterator i;
- int r;
-
- assert(s);
-
- /* Load service data from SysV init scripts, preferably with
- * LSB headers ... */
-
- if (strv_isempty(UNIT(s)->manager->lookup_paths.sysvinit_path))
- return 0;
-
- if ((t = UNIT(s)->id))
- if ((r = service_load_sysv_name(s, t)) < 0)
- return r;
-
- if (UNIT(s)->load_state == UNIT_STUB)
- SET_FOREACH(t, UNIT(s)->names, i) {
- if (t == UNIT(s)->id)
- continue;
-
- if ((r = service_load_sysv_name(s, t)) < 0)
- return r;
-
- if (UNIT(s)->load_state != UNIT_STUB)
- break;
- }
-
- return 0;
-}
-#endif
-
-static int fsck_fix_order(Service *s) {
- Unit *other;
- int r;
-
- assert(s);
-
- if (s->fsck_passno <= 0)
- return 0;
-
- /* For each pair of services where both have an fsck priority
- * we order things based on it. */
-
- LIST_FOREACH(units_by_type, other, UNIT(s)->manager->units_by_type[UNIT_SERVICE]) {
- Service *t;
- UnitDependency d;
-
- t = SERVICE(other);
-
- if (s == t)
- continue;
-
- if (UNIT(t)->load_state != UNIT_LOADED)
- continue;
-
- if (t->fsck_passno <= 0)
- continue;
-
- if (t->fsck_passno < s->fsck_passno)
- d = UNIT_AFTER;
- else if (t->fsck_passno > s->fsck_passno)
- d = UNIT_BEFORE;
- else
- continue;
-
- if ((r = unit_add_dependency(UNIT(s), d, UNIT(t), true)) < 0)
- return r;
- }
-
- return 0;
-}
-
-static int service_verify(Service *s) {
- assert(s);
-
- if (UNIT(s)->load_state != UNIT_LOADED)
- return 0;
-
- if (!s->exec_command[SERVICE_EXEC_START]) {
- log_error("%s lacks ExecStart setting. Refusing.", UNIT(s)->id);
- return -EINVAL;
- }
-
- if (s->type != SERVICE_ONESHOT &&
- s->exec_command[SERVICE_EXEC_START]->command_next) {
- log_error("%s has more than one ExecStart setting, which is only allowed for Type=oneshot services. Refusing.", UNIT(s)->id);
- return -EINVAL;
- }
-
- if (s->type == SERVICE_DBUS && !s->bus_name) {
- log_error("%s is of type D-Bus but no D-Bus service name has been specified. Refusing.", UNIT(s)->id);
- return -EINVAL;
- }
-
- if (s->bus_name && s->type != SERVICE_DBUS)
- log_warning("%s has a D-Bus service name specified, but is not of type dbus. Ignoring.", UNIT(s)->id);
-
- if (s->exec_context.pam_name && s->kill_context.kill_mode != KILL_CONTROL_GROUP) {
- log_error("%s has PAM enabled. Kill mode must be set to 'control-group'. Refusing.", UNIT(s)->id);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int service_add_default_dependencies(Service *s) {
- int r;
-
- assert(s);
-
- /* Add a number of automatic dependencies useful for the
- * majority of services. */
-
- /* First, pull in base system */
- if (UNIT(s)->manager->running_as == SYSTEMD_SYSTEM) {
-
- if ((r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_BASIC_TARGET, NULL, true)) < 0)
- return r;
-
- } else if (UNIT(s)->manager->running_as == SYSTEMD_USER) {
-
- if ((r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SOCKETS_TARGET, NULL, true)) < 0)
- return r;
- }
-
- /* Second, activate normal shutdown */
- return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
-}
-
-static void service_fix_output(Service *s) {
- assert(s);
-
- /* If nothing has been explicitly configured, patch default
- * output in. If input is socket/tty we avoid this however,
- * since in that case we want output to default to the same
- * place as we read input from. */
-
- if (s->exec_context.std_error == EXEC_OUTPUT_INHERIT &&
- s->exec_context.std_output == EXEC_OUTPUT_INHERIT &&
- s->exec_context.std_input == EXEC_INPUT_NULL)
- s->exec_context.std_error = UNIT(s)->manager->default_std_error;
-
- if (s->exec_context.std_output == EXEC_OUTPUT_INHERIT &&
- s->exec_context.std_input == EXEC_INPUT_NULL)
- s->exec_context.std_output = UNIT(s)->manager->default_std_output;
-}
-
-static int service_load(Unit *u) {
- int r;
- Service *s = SERVICE(u);
-
- assert(s);
-
- /* Load a .service file */
- if ((r = unit_load_fragment(u)) < 0)
- return r;
-
-#ifdef HAVE_SYSV_COMPAT
- /* Load a classic init script as a fallback, if we couldn't find anything */
- if (u->load_state == UNIT_STUB)
- if ((r = service_load_sysv(s)) < 0)
- return r;
-#endif
-
- /* Still nothing found? Then let's give up */
- if (u->load_state == UNIT_STUB)
- return -ENOENT;
-
- /* We were able to load something, then let's add in the
- * dropin directories. */
- if ((r = unit_load_dropin(unit_follow_merge(u))) < 0)
- return r;
-
- /* This is a new unit? Then let's add in some extras */
- if (u->load_state == UNIT_LOADED) {
- if (s->type == _SERVICE_TYPE_INVALID)
- s->type = s->bus_name ? SERVICE_DBUS : SERVICE_SIMPLE;
-
- /* Oneshot services have disabled start timeout by default */
- if (s->type == SERVICE_ONESHOT && !s->start_timeout_defined)
- s->timeout_start_usec = 0;
-
- service_fix_output(s);
-
- if ((r = unit_add_exec_dependencies(u, &s->exec_context)) < 0)
- return r;
-
- if ((r = unit_add_default_cgroups(u)) < 0)
- return r;
-
-#ifdef HAVE_SYSV_COMPAT
- if ((r = sysv_fix_order(s)) < 0)
- return r;
-#endif
-
- if ((r = fsck_fix_order(s)) < 0)
- return r;
-
- if (s->bus_name)
- if ((r = unit_watch_bus_name(u, s->bus_name)) < 0)
- return r;
-
- if (s->type == SERVICE_NOTIFY && s->notify_access == NOTIFY_NONE)
- s->notify_access = NOTIFY_MAIN;
-
- if (s->watchdog_usec > 0 && s->notify_access == NOTIFY_NONE)
- s->notify_access = NOTIFY_MAIN;
-
- if (s->type == SERVICE_DBUS || s->bus_name)
- if ((r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_REQUIRES, SPECIAL_DBUS_SOCKET, NULL, true)) < 0)
- return r;
-
- if (UNIT(s)->default_dependencies)
- if ((r = service_add_default_dependencies(s)) < 0)
- return r;
-
- r = unit_exec_context_defaults(u, &s->exec_context);
- if (r < 0)
- return r;
- }
-
- return service_verify(s);
-}
-
-static void service_dump(Unit *u, FILE *f, const char *prefix) {
-
- ServiceExecCommand c;
- Service *s = SERVICE(u);
- const char *prefix2;
- char *p2;
-
- assert(s);
-
- p2 = strappend(prefix, "\t");
- prefix2 = p2 ? p2 : prefix;
-
- fprintf(f,
- "%sService State: %s\n"
- "%sResult: %s\n"
- "%sReload Result: %s\n"
- "%sPermissionsStartOnly: %s\n"
- "%sRootDirectoryStartOnly: %s\n"
- "%sRemainAfterExit: %s\n"
- "%sGuessMainPID: %s\n"
- "%sType: %s\n"
- "%sRestart: %s\n"
- "%sNotifyAccess: %s\n",
- prefix, service_state_to_string(s->state),
- prefix, service_result_to_string(s->result),
- prefix, service_result_to_string(s->reload_result),
- prefix, yes_no(s->permissions_start_only),
- prefix, yes_no(s->root_directory_start_only),
- prefix, yes_no(s->remain_after_exit),
- prefix, yes_no(s->guess_main_pid),
- prefix, service_type_to_string(s->type),
- prefix, service_restart_to_string(s->restart),
- prefix, notify_access_to_string(s->notify_access));
-
- if (s->control_pid > 0)
- fprintf(f,
- "%sControl PID: %lu\n",
- prefix, (unsigned long) s->control_pid);
-
- if (s->main_pid > 0)
- fprintf(f,
- "%sMain PID: %lu\n"
- "%sMain PID Known: %s\n"
- "%sMain PID Alien: %s\n",
- prefix, (unsigned long) s->main_pid,
- prefix, yes_no(s->main_pid_known),
- prefix, yes_no(s->main_pid_alien));
-
- if (s->pid_file)
- fprintf(f,
- "%sPIDFile: %s\n",
- prefix, s->pid_file);
-
- if (s->bus_name)
- fprintf(f,
- "%sBusName: %s\n"
- "%sBus Name Good: %s\n",
- prefix, s->bus_name,
- prefix, yes_no(s->bus_name_good));
-
- kill_context_dump(&s->kill_context, f, prefix);
- exec_context_dump(&s->exec_context, f, prefix);
-
- for (c = 0; c < _SERVICE_EXEC_COMMAND_MAX; c++) {
-
- if (!s->exec_command[c])
- continue;
-
- fprintf(f, "%s-> %s:\n",
- prefix, service_exec_command_to_string(c));
-
- exec_command_dump_list(s->exec_command[c], f, prefix2);
- }
-
-#ifdef HAVE_SYSV_COMPAT
- if (s->is_sysv)
- fprintf(f,
- "%sSysV Init Script has LSB Header: %s\n"
- "%sSysVEnabled: %s\n",
- prefix, yes_no(s->sysv_has_lsb),
- prefix, yes_no(s->sysv_enabled));
-
- if (s->sysv_start_priority >= 0)
- fprintf(f,
- "%sSysVStartPriority: %i\n",
- prefix, s->sysv_start_priority);
-
- if (s->sysv_runlevels)
- fprintf(f, "%sSysVRunLevels: %s\n",
- prefix, s->sysv_runlevels);
-#endif
-
- if (s->fsck_passno > 0)
- fprintf(f,
- "%sFsckPassNo: %i\n",
- prefix, s->fsck_passno);
-
- if (s->status_text)
- fprintf(f, "%sStatus Text: %s\n",
- prefix, s->status_text);
-
- free(p2);
-}
-
-static int service_load_pid_file(Service *s, bool may_warn) {
- char *k;
- int r;
- pid_t pid;
-
- assert(s);
-
- if (!s->pid_file)
- return -ENOENT;
-
- if ((r = read_one_line_file(s->pid_file, &k)) < 0) {
- if (may_warn)
- log_info("PID file %s not readable (yet?) after %s.",
- s->pid_file, service_state_to_string(s->state));
- return r;
- }
-
- r = parse_pid(k, &pid);
- free(k);
-
- if (r < 0)
- return r;
-
- if (kill(pid, 0) < 0 && errno != EPERM) {
- if (may_warn)
- log_info("PID %lu read from file %s does not exist.",
- (unsigned long) pid, s->pid_file);
- return -ESRCH;
- }
-
- if (s->main_pid_known) {
- if (pid == s->main_pid)
- return 0;
-
- log_debug("Main PID changing: %lu -> %lu",
- (unsigned long) s->main_pid, (unsigned long) pid);
- service_unwatch_main_pid(s);
- s->main_pid_known = false;
- } else
- log_debug("Main PID loaded: %lu", (unsigned long) pid);
-
- if ((r = service_set_main_pid(s, pid)) < 0)
- return r;
-
- if ((r = unit_watch_pid(UNIT(s), pid)) < 0)
- /* FIXME: we need to do something here */
- return r;
-
- return 0;
-}
-
-static int service_search_main_pid(Service *s) {
- pid_t pid;
- int r;
-
- assert(s);
-
- /* If we know it anyway, don't ever fallback to unreliable
- * heuristics */
- if (s->main_pid_known)
- return 0;
-
- if (!s->guess_main_pid)
- return 0;
-
- assert(s->main_pid <= 0);
-
- if ((pid = cgroup_bonding_search_main_pid_list(UNIT(s)->cgroup_bondings)) <= 0)
- return -ENOENT;
-
- log_debug("Main PID guessed: %lu", (unsigned long) pid);
- if ((r = service_set_main_pid(s, pid)) < 0)
- return r;
-
- if ((r = unit_watch_pid(UNIT(s), pid)) < 0)
- /* FIXME: we need to do something here */
- return r;
-
- return 0;
-}
-
-static void service_notify_sockets_dead(Service *s, bool failed_permanent) {
- Iterator i;
- Unit *u;
-
- assert(s);
-
- /* Notifies all our sockets when we die */
-
- if (s->socket_fd >= 0)
- return;
-
- SET_FOREACH(u, UNIT(s)->dependencies[UNIT_TRIGGERED_BY], i)
- if (u->type == UNIT_SOCKET)
- socket_notify_service_dead(SOCKET(u), failed_permanent);
-
- return;
-}
-
-static void service_set_state(Service *s, ServiceState state) {
- ServiceState old_state;
- const UnitActiveState *table;
- assert(s);
-
- table = s->type == SERVICE_IDLE ? state_translation_table_idle : state_translation_table;
-
- old_state = s->state;
- s->state = state;
-
- service_unwatch_pid_file(s);
-
- if (state != SERVICE_START_PRE &&
- state != SERVICE_START &&
- state != SERVICE_START_POST &&
- state != SERVICE_RELOAD &&
- state != SERVICE_STOP &&
- state != SERVICE_STOP_SIGTERM &&
- state != SERVICE_STOP_SIGKILL &&
- state != SERVICE_STOP_POST &&
- state != SERVICE_FINAL_SIGTERM &&
- state != SERVICE_FINAL_SIGKILL &&
- state != SERVICE_AUTO_RESTART)
- unit_unwatch_timer(UNIT(s), &s->timer_watch);
-
- if (state != SERVICE_START &&
- state != SERVICE_START_POST &&
- state != SERVICE_RUNNING &&
- state != SERVICE_RELOAD &&
- state != SERVICE_STOP &&
- state != SERVICE_STOP_SIGTERM &&
- state != SERVICE_STOP_SIGKILL) {
- service_unwatch_main_pid(s);
- s->main_command = NULL;
- }
-
- if (state != SERVICE_START_PRE &&
- state != SERVICE_START &&
- state != SERVICE_START_POST &&
- state != SERVICE_RELOAD &&
- state != SERVICE_STOP &&
- state != SERVICE_STOP_SIGTERM &&
- state != SERVICE_STOP_SIGKILL &&
- state != SERVICE_STOP_POST &&
- state != SERVICE_FINAL_SIGTERM &&
- state != SERVICE_FINAL_SIGKILL) {
- service_unwatch_control_pid(s);
- s->control_command = NULL;
- s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID;
- }
-
- if (state == SERVICE_DEAD ||
- state == SERVICE_STOP ||
- state == SERVICE_STOP_SIGTERM ||
- state == SERVICE_STOP_SIGKILL ||
- state == SERVICE_STOP_POST ||
- state == SERVICE_FINAL_SIGTERM ||
- state == SERVICE_FINAL_SIGKILL ||
- state == SERVICE_FAILED ||
- state == SERVICE_AUTO_RESTART)
- service_notify_sockets_dead(s, false);
-
- if (state != SERVICE_START_PRE &&
- state != SERVICE_START &&
- state != SERVICE_START_POST &&
- state != SERVICE_RUNNING &&
- state != SERVICE_RELOAD &&
- state != SERVICE_STOP &&
- state != SERVICE_STOP_SIGTERM &&
- state != SERVICE_STOP_SIGKILL &&
- state != SERVICE_STOP_POST &&
- state != SERVICE_FINAL_SIGTERM &&
- state != SERVICE_FINAL_SIGKILL &&
- !(state == SERVICE_DEAD && UNIT(s)->job)) {
- service_close_socket_fd(s);
- service_connection_unref(s);
- }
-
- if (state == SERVICE_STOP)
- service_stop_watchdog(s);
-
- /* For the inactive states unit_notify() will trim the cgroup,
- * but for exit we have to do that ourselves... */
- if (state == SERVICE_EXITED && UNIT(s)->manager->n_reloading <= 0)
- cgroup_bonding_trim_list(UNIT(s)->cgroup_bondings, true);
-
- if (old_state != state)
- log_struct(LOG_DEBUG,
- "UNIT=%s", UNIT(s)->id,
- "MESSAGE=%s changed %s -> %s", UNIT(s)->id,
- service_state_to_string(old_state),
- service_state_to_string(state),
- NULL);
-
- unit_notify(UNIT(s), table[old_state], table[state], s->reload_result == SERVICE_SUCCESS);
- s->reload_result = SERVICE_SUCCESS;
-}
-
-static int service_coldplug(Unit *u) {
- Service *s = SERVICE(u);
- int r;
-
- assert(s);
- assert(s->state == SERVICE_DEAD);
-
- if (s->deserialized_state != s->state) {
-
- if (s->deserialized_state == SERVICE_START_PRE ||
- s->deserialized_state == SERVICE_START ||
- s->deserialized_state == SERVICE_START_POST ||
- s->deserialized_state == SERVICE_RELOAD ||
- s->deserialized_state == SERVICE_STOP ||
- s->deserialized_state == SERVICE_STOP_SIGTERM ||
- s->deserialized_state == SERVICE_STOP_SIGKILL ||
- s->deserialized_state == SERVICE_STOP_POST ||
- s->deserialized_state == SERVICE_FINAL_SIGTERM ||
- s->deserialized_state == SERVICE_FINAL_SIGKILL ||
- s->deserialized_state == SERVICE_AUTO_RESTART) {
- if (s->deserialized_state == SERVICE_AUTO_RESTART || s->timeout_start_usec > 0) {
- usec_t k;
-
- k = s->deserialized_state == SERVICE_AUTO_RESTART ? s->restart_usec : s->timeout_start_usec;
-
- if ((r = unit_watch_timer(UNIT(s), k, &s->timer_watch)) < 0)
- return r;
- }
- }
-
- if ((s->deserialized_state == SERVICE_START &&
- (s->type == SERVICE_FORKING ||
- s->type == SERVICE_DBUS ||
- s->type == SERVICE_ONESHOT ||
- s->type == SERVICE_NOTIFY)) ||
- s->deserialized_state == SERVICE_START_POST ||
- s->deserialized_state == SERVICE_RUNNING ||
- s->deserialized_state == SERVICE_RELOAD ||
- s->deserialized_state == SERVICE_STOP ||
- s->deserialized_state == SERVICE_STOP_SIGTERM ||
- s->deserialized_state == SERVICE_STOP_SIGKILL)
- if (s->main_pid > 0)
- if ((r = unit_watch_pid(UNIT(s), s->main_pid)) < 0)
- return r;
-
- if (s->deserialized_state == SERVICE_START_PRE ||
- s->deserialized_state == SERVICE_START ||
- s->deserialized_state == SERVICE_START_POST ||
- s->deserialized_state == SERVICE_RELOAD ||
- s->deserialized_state == SERVICE_STOP ||
- s->deserialized_state == SERVICE_STOP_SIGTERM ||
- s->deserialized_state == SERVICE_STOP_SIGKILL ||
- s->deserialized_state == SERVICE_STOP_POST ||
- s->deserialized_state == SERVICE_FINAL_SIGTERM ||
- s->deserialized_state == SERVICE_FINAL_SIGKILL)
- if (s->control_pid > 0)
- if ((r = unit_watch_pid(UNIT(s), s->control_pid)) < 0)
- return r;
-
- if (s->deserialized_state == SERVICE_START_POST ||
- s->deserialized_state == SERVICE_RUNNING)
- service_handle_watchdog(s);
-
- service_set_state(s, s->deserialized_state);
- }
- return 0;
-}
-
-static int service_collect_fds(Service *s, int **fds, unsigned *n_fds) {
- Iterator i;
- int r;
- int *rfds = NULL;
- unsigned rn_fds = 0;
- Unit *u;
-
- assert(s);
- assert(fds);
- assert(n_fds);
-
- if (s->socket_fd >= 0)
- return 0;
-
- SET_FOREACH(u, UNIT(s)->dependencies[UNIT_TRIGGERED_BY], i) {
- int *cfds;
- unsigned cn_fds;
- Socket *sock;
-
- if (u->type != UNIT_SOCKET)
- continue;
-
- sock = SOCKET(u);
-
- if ((r = socket_collect_fds(sock, &cfds, &cn_fds)) < 0)
- goto fail;
-
- if (!cfds)
- continue;
-
- if (!rfds) {
- rfds = cfds;
- rn_fds = cn_fds;
- } else {
- int *t;
-
- if (!(t = new(int, rn_fds+cn_fds))) {
- free(cfds);
- r = -ENOMEM;
- goto fail;
- }
-
- memcpy(t, rfds, rn_fds * sizeof(int));
- memcpy(t+rn_fds, cfds, cn_fds * sizeof(int));
- free(rfds);
- free(cfds);
-
- rfds = t;
- rn_fds = rn_fds+cn_fds;
- }
- }
-
- *fds = rfds;
- *n_fds = rn_fds;
-
- return 0;
-
-fail:
- free(rfds);
-
- return r;
-}
-
-static int service_spawn(
- Service *s,
- ExecCommand *c,
- bool timeout,
- bool pass_fds,
- bool apply_permissions,
- bool apply_chroot,
- bool apply_tty_stdin,
- bool set_notify_socket,
- bool is_control,
- pid_t *_pid) {
-
- pid_t pid;
- int r;
- int *fds = NULL, *fdsbuf = NULL;
- unsigned n_fds = 0, n_env = 0;
- char **argv = NULL, **final_env = NULL, **our_env = NULL;
-
- assert(s);
- assert(c);
- assert(_pid);
-
- if (pass_fds ||
- s->exec_context.std_input == EXEC_INPUT_SOCKET ||
- s->exec_context.std_output == EXEC_OUTPUT_SOCKET ||
- s->exec_context.std_error == EXEC_OUTPUT_SOCKET) {
-
- if (s->socket_fd >= 0) {
- fds = &s->socket_fd;
- n_fds = 1;
- } else {
- if ((r = service_collect_fds(s, &fdsbuf, &n_fds)) < 0)
- goto fail;
-
- fds = fdsbuf;
- }
- }
-
- if (timeout && s->timeout_start_usec) {
- r = unit_watch_timer(UNIT(s), s->timeout_start_usec, &s->timer_watch);
- if (r < 0)
- goto fail;
- } else
- unit_unwatch_timer(UNIT(s), &s->timer_watch);
-
- if (!(argv = unit_full_printf_strv(UNIT(s), c->argv))) {
- r = -ENOMEM;
- goto fail;
- }
-
- our_env = new0(char*, 5);
- if (!our_env) {
- r = -ENOMEM;
- goto fail;
- }
-
- if (set_notify_socket)
- if (asprintf(our_env + n_env++, "NOTIFY_SOCKET=%s", UNIT(s)->manager->notify_socket) < 0) {
- r = -ENOMEM;
- goto fail;
- }
-
- if (s->main_pid > 0)
- if (asprintf(our_env + n_env++, "MAINPID=%lu", (unsigned long) s->main_pid) < 0) {
- r = -ENOMEM;
- goto fail;
- }
-
- if (s->watchdog_usec > 0)
- if (asprintf(our_env + n_env++, "WATCHDOG_USEC=%llu", (unsigned long long) s->watchdog_usec) < 0) {
- r = -ENOMEM;
- goto fail;
- }
-
- if (s->meta.manager->running_as != SYSTEMD_SYSTEM)
- if (asprintf(our_env + n_env++, "MANAGERPID=%lu", (unsigned long) getpid()) < 0) {
- r = -ENOMEM;
- goto fail;
- }
-
- final_env = strv_env_merge(2, UNIT(s)->manager->environment, our_env, NULL);
- if (!final_env) {
- r = -ENOMEM;
- goto fail;
- }
-
- r = exec_spawn(c,
- argv,
- &s->exec_context,
- fds, n_fds,
- final_env,
- apply_permissions,
- apply_chroot,
- apply_tty_stdin,
- UNIT(s)->manager->confirm_spawn,
- UNIT(s)->cgroup_bondings,
- UNIT(s)->cgroup_attributes,
- is_control ? "control" : NULL,
- UNIT(s)->id,
- s->type == SERVICE_IDLE ? UNIT(s)->manager->idle_pipe : NULL,
- &pid);
-
- if (r < 0)
- goto fail;
-
- if ((r = unit_watch_pid(UNIT(s), pid)) < 0)
- /* FIXME: we need to do something here */
- goto fail;
-
- free(fdsbuf);
- strv_free(argv);
- strv_free(our_env);
- strv_free(final_env);
-
- *_pid = pid;
-
- return 0;
-
-fail:
- free(fdsbuf);
- strv_free(argv);
- strv_free(our_env);
- strv_free(final_env);
-
- if (timeout)
- unit_unwatch_timer(UNIT(s), &s->timer_watch);
-
- return r;
-}
-
-static int main_pid_good(Service *s) {
- assert(s);
-
- /* Returns 0 if the pid is dead, 1 if it is good, -1 if we
- * don't know */
-
- /* If we know the pid file, then lets just check if it is
- * still valid */
- if (s->main_pid_known) {
-
- /* If it's an alien child let's check if it is still
- * alive ... */
- if (s->main_pid_alien)
- return kill(s->main_pid, 0) >= 0 || errno != ESRCH;
-
- /* .. otherwise assume we'll get a SIGCHLD for it,
- * which we really should wait for to collect exit
- * status and code */
- return s->main_pid > 0;
- }
-
- /* We don't know the pid */
- return -EAGAIN;
-}
-
-static int control_pid_good(Service *s) {
- assert(s);
-
- return s->control_pid > 0;
-}
-
-static int cgroup_good(Service *s) {
- int r;
-
- assert(s);
-
- if ((r = cgroup_bonding_is_empty_list(UNIT(s)->cgroup_bondings)) < 0)
- return r;
-
- return !r;
-}
-
-static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) {
- int r;
- assert(s);
-
- if (f != SERVICE_SUCCESS)
- s->result = f;
-
- service_set_state(s, s->result != SERVICE_SUCCESS ? SERVICE_FAILED : SERVICE_DEAD);
-
- if (allow_restart &&
- !s->forbid_restart &&
- (s->restart == SERVICE_RESTART_ALWAYS ||
- (s->restart == SERVICE_RESTART_ON_SUCCESS && s->result == SERVICE_SUCCESS) ||
- (s->restart == SERVICE_RESTART_ON_FAILURE && s->result != SERVICE_SUCCESS) ||
- (s->restart == SERVICE_RESTART_ON_ABORT && (s->result == SERVICE_FAILURE_SIGNAL ||
- s->result == SERVICE_FAILURE_CORE_DUMP))) &&
- (s->result != SERVICE_FAILURE_EXIT_CODE ||
- !set_contains(s->restart_ignore_status.code, INT_TO_PTR(s->main_exec_status.status))) &&
- (s->result != SERVICE_FAILURE_SIGNAL ||
- !set_contains(s->restart_ignore_status.signal, INT_TO_PTR(s->main_exec_status.status)))
- ) {
-
- r = unit_watch_timer(UNIT(s), s->restart_usec, &s->timer_watch);
- if (r < 0)
- goto fail;
-
- service_set_state(s, SERVICE_AUTO_RESTART);
- }
-
- s->forbid_restart = false;
-
- return;
-
-fail:
- log_warning("%s failed to run install restart timer: %s", UNIT(s)->id, strerror(-r));
- service_enter_dead(s, SERVICE_FAILURE_RESOURCES, false);
-}
-
-static void service_enter_signal(Service *s, ServiceState state, ServiceResult f);
-
-static void service_enter_stop_post(Service *s, ServiceResult f) {
- int r;
- assert(s);
-
- if (f != SERVICE_SUCCESS)
- s->result = f;
-
- service_unwatch_control_pid(s);
-
- if ((s->control_command = s->exec_command[SERVICE_EXEC_STOP_POST])) {
- s->control_command_id = SERVICE_EXEC_STOP_POST;
-
- r = service_spawn(s,
- s->control_command,
- true,
- false,
- !s->permissions_start_only,
- !s->root_directory_start_only,
- true,
- false,
- true,
- &s->control_pid);
- if (r < 0)
- goto fail;
-
-
- service_set_state(s, SERVICE_STOP_POST);
- } else
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_SUCCESS);
-
- return;
-
-fail:
- log_warning("%s failed to run 'stop-post' task: %s", UNIT(s)->id, strerror(-r));
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES);
-}
-
-static void service_enter_signal(Service *s, ServiceState state, ServiceResult f) {
- int r;
- Set *pid_set = NULL;
- bool wait_for_exit = false;
-
- assert(s);
-
- if (f != SERVICE_SUCCESS)
- s->result = f;
-
- if (s->kill_context.kill_mode != KILL_NONE) {
- int sig = (state == SERVICE_STOP_SIGTERM || state == SERVICE_FINAL_SIGTERM) ? s->kill_context.kill_signal : SIGKILL;
-
- if (s->main_pid > 0) {
- if (kill_and_sigcont(s->main_pid, sig) < 0 && errno != ESRCH)
- log_warning("Failed to kill main process %li: %m", (long) s->main_pid);
- else
- wait_for_exit = !s->main_pid_alien;
- }
-
- if (s->control_pid > 0) {
- if (kill_and_sigcont(s->control_pid, sig) < 0 && errno != ESRCH)
- log_warning("Failed to kill control process %li: %m", (long) s->control_pid);
- else
- wait_for_exit = true;
- }
-
- if (s->kill_context.kill_mode == KILL_CONTROL_GROUP) {
-
- pid_set = set_new(trivial_hash_func, trivial_compare_func);
- if (!pid_set) {
- r = -ENOMEM;
- goto fail;
- }
-
- /* Exclude the main/control pids from being killed via the cgroup */
- if (s->main_pid > 0)
- if ((r = set_put(pid_set, LONG_TO_PTR(s->main_pid))) < 0)
- goto fail;
-
- if (s->control_pid > 0)
- if ((r = set_put(pid_set, LONG_TO_PTR(s->control_pid))) < 0)
- goto fail;
-
- r = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, sig, true, false, pid_set, NULL);
- if (r < 0) {
- if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
- log_warning("Failed to kill control group: %s", strerror(-r));
- } else if (r > 0)
- wait_for_exit = true;
-
- set_free(pid_set);
- pid_set = NULL;
- }
- }
-
- if (wait_for_exit) {
- if (s->timeout_stop_usec > 0) {
- r = unit_watch_timer(UNIT(s), s->timeout_stop_usec, &s->timer_watch);
- if (r < 0)
- goto fail;
- }
-
- service_set_state(s, state);
- } else if (state == SERVICE_STOP_SIGTERM || state == SERVICE_STOP_SIGKILL)
- service_enter_stop_post(s, SERVICE_SUCCESS);
- else
- service_enter_dead(s, SERVICE_SUCCESS, true);
-
- return;
-
-fail:
- log_warning("%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));
-
- if (state == SERVICE_STOP_SIGTERM || state == SERVICE_STOP_SIGKILL)
- service_enter_stop_post(s, SERVICE_FAILURE_RESOURCES);
- else
- service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true);
-
- if (pid_set)
- set_free(pid_set);
-}
-
-static void service_enter_stop(Service *s, ServiceResult f) {
- int r;
-
- assert(s);
-
- if (f != SERVICE_SUCCESS)
- s->result = f;
-
- service_unwatch_control_pid(s);
-
- if ((s->control_command = s->exec_command[SERVICE_EXEC_STOP])) {
- s->control_command_id = SERVICE_EXEC_STOP;
-
- r = service_spawn(s,
- s->control_command,
- true,
- false,
- !s->permissions_start_only,
- !s->root_directory_start_only,
- false,
- false,
- true,
- &s->control_pid);
- if (r < 0)
- goto fail;
-
- service_set_state(s, SERVICE_STOP);
- } else
- service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_SUCCESS);
-
- return;
-
-fail:
- log_warning("%s failed to run 'stop' task: %s", UNIT(s)->id, strerror(-r));
- service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES);
-}
-
-static void service_enter_running(Service *s, ServiceResult f) {
- int main_pid_ok, cgroup_ok;
- assert(s);
-
- if (f != SERVICE_SUCCESS)
- s->result = f;
-
- main_pid_ok = main_pid_good(s);
- cgroup_ok = cgroup_good(s);
-
- if ((main_pid_ok > 0 || (main_pid_ok < 0 && cgroup_ok != 0)) &&
- (s->bus_name_good || s->type != SERVICE_DBUS))
- service_set_state(s, SERVICE_RUNNING);
- else if (s->remain_after_exit)
- service_set_state(s, SERVICE_EXITED);
- else
- service_enter_stop(s, SERVICE_SUCCESS);
-}
-
-static void service_enter_start_post(Service *s) {
- int r;
- assert(s);
-
- service_unwatch_control_pid(s);
-
- if (s->watchdog_usec > 0)
- service_reset_watchdog(s);
-
- if ((s->control_command = s->exec_command[SERVICE_EXEC_START_POST])) {
- s->control_command_id = SERVICE_EXEC_START_POST;
-
- r = service_spawn(s,
- s->control_command,
- true,
- false,
- !s->permissions_start_only,
- !s->root_directory_start_only,
- false,
- false,
- true,
- &s->control_pid);
- if (r < 0)
- goto fail;
-
- service_set_state(s, SERVICE_START_POST);
- } else
- service_enter_running(s, SERVICE_SUCCESS);
-
- return;
-
-fail:
- log_warning("%s failed to run 'start-post' task: %s", UNIT(s)->id, strerror(-r));
- service_enter_stop(s, SERVICE_FAILURE_RESOURCES);
-}
-
-static void service_enter_start(Service *s) {
- pid_t pid;
- int r;
- ExecCommand *c;
-
- assert(s);
-
- assert(s->exec_command[SERVICE_EXEC_START]);
- assert(!s->exec_command[SERVICE_EXEC_START]->command_next || s->type == SERVICE_ONESHOT);
-
- if (s->type == SERVICE_FORKING)
- service_unwatch_control_pid(s);
- else
- service_unwatch_main_pid(s);
-
- /* We want to ensure that nobody leaks processes from
- * START_PRE here, so let's go on a killing spree, People
- * should not spawn long running processes from START_PRE. */
- cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, SIGKILL, true, true, NULL, "control");
-
- if (s->type == SERVICE_FORKING) {
- s->control_command_id = SERVICE_EXEC_START;
- c = s->control_command = s->exec_command[SERVICE_EXEC_START];
-
- s->main_command = NULL;
- } else {
- s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID;
- s->control_command = NULL;
-
- c = s->main_command = s->exec_command[SERVICE_EXEC_START];
- }
-
- r = service_spawn(s,
- c,
- s->type == SERVICE_FORKING || s->type == SERVICE_DBUS || s->type == SERVICE_NOTIFY || s->type == SERVICE_ONESHOT,
- true,
- true,
- true,
- true,
- s->notify_access != NOTIFY_NONE,
- false,
- &pid);
- if (r < 0)
- goto fail;
-
- if (s->type == SERVICE_SIMPLE || s->type == SERVICE_IDLE) {
- /* For simple services we immediately start
- * the START_POST binaries. */
-
- service_set_main_pid(s, pid);
- service_enter_start_post(s);
-
- } else if (s->type == SERVICE_FORKING) {
-
- /* For forking services we wait until the start
- * process exited. */
-
- s->control_pid = pid;
- service_set_state(s, SERVICE_START);
-
- } else if (s->type == SERVICE_ONESHOT ||
- s->type == SERVICE_DBUS ||
- s->type == SERVICE_NOTIFY) {
-
- /* For oneshot services we wait until the start
- * process exited, too, but it is our main process. */
-
- /* For D-Bus services we know the main pid right away,
- * but wait for the bus name to appear on the
- * bus. Notify services are similar. */
-
- service_set_main_pid(s, pid);
- service_set_state(s, SERVICE_START);
- } else
- assert_not_reached("Unknown service type");
-
- return;
-
-fail:
- log_warning("%s failed to run 'start' task: %s", UNIT(s)->id, strerror(-r));
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES);
-}
-
-static void service_enter_start_pre(Service *s) {
- int r;
-
- assert(s);
-
- service_unwatch_control_pid(s);
-
- if ((s->control_command = s->exec_command[SERVICE_EXEC_START_PRE])) {
-
- /* Before we start anything, let's clear up what might
- * be left from previous runs. */
- cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, SIGKILL, true, true, NULL, "control");
-
- s->control_command_id = SERVICE_EXEC_START_PRE;
-
- r = service_spawn(s,
- s->control_command,
- true,
- false,
- !s->permissions_start_only,
- !s->root_directory_start_only,
- true,
- false,
- true,
- &s->control_pid);
- if (r < 0)
- goto fail;
-
- service_set_state(s, SERVICE_START_PRE);
- } else
- service_enter_start(s);
-
- return;
-
-fail:
- log_warning("%s failed to run 'start-pre' task: %s", UNIT(s)->id, strerror(-r));
- service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true);
-}
-
-static void service_enter_restart(Service *s) {
- int r;
- DBusError error;
-
- assert(s);
- dbus_error_init(&error);
-
- if (UNIT(s)->job && UNIT(s)->job->type == JOB_STOP) {
- /* Don't restart things if we are going down anyway */
- log_info("Stop job pending for unit, delaying automatic restart.");
-
- r = unit_watch_timer(UNIT(s), s->restart_usec, &s->timer_watch);
- if (r < 0)
- goto fail;
-
- return;
- }
-
- /* Any units that are bound to this service must also be
- * restarted. We use JOB_RESTART (instead of the more obvious
- * JOB_START) here so that those dependency jobs will be added
- * as well. */
- r = manager_add_job(UNIT(s)->manager, JOB_RESTART, UNIT(s), JOB_FAIL, false, &error, NULL);
- if (r < 0)
- goto fail;
-
- /* Note that we stay in the SERVICE_AUTO_RESTART state here,
- * it will be canceled as part of the service_stop() call that
- * is executed as part of JOB_RESTART. */
-
- log_debug("%s scheduled restart job.", UNIT(s)->id);
- return;
-
-fail:
- log_warning("%s failed to schedule restart job: %s", UNIT(s)->id, bus_error(&error, -r));
- service_enter_dead(s, SERVICE_FAILURE_RESOURCES, false);
-
- dbus_error_free(&error);
-}
-
-static void service_enter_reload(Service *s) {
- int r;
-
- assert(s);
-
- service_unwatch_control_pid(s);
-
- if ((s->control_command = s->exec_command[SERVICE_EXEC_RELOAD])) {
- s->control_command_id = SERVICE_EXEC_RELOAD;
-
- r = service_spawn(s,
- s->control_command,
- true,
- false,
- !s->permissions_start_only,
- !s->root_directory_start_only,
- false,
- false,
- true,
- &s->control_pid);
- if (r < 0)
- goto fail;
-
- service_set_state(s, SERVICE_RELOAD);
- } else
- service_enter_running(s, SERVICE_SUCCESS);
-
- return;
-
-fail:
- log_warning("%s failed to run 'reload' task: %s", UNIT(s)->id, strerror(-r));
- s->reload_result = SERVICE_FAILURE_RESOURCES;
- service_enter_running(s, SERVICE_SUCCESS);
-}
-
-static void service_run_next_control(Service *s) {
- int r;
-
- assert(s);
- assert(s->control_command);
- assert(s->control_command->command_next);
-
- assert(s->control_command_id != SERVICE_EXEC_START);
-
- s->control_command = s->control_command->command_next;
- service_unwatch_control_pid(s);
-
- r = service_spawn(s,
- s->control_command,
- true,
- false,
- !s->permissions_start_only,
- !s->root_directory_start_only,
- s->control_command_id == SERVICE_EXEC_START_PRE ||
- s->control_command_id == SERVICE_EXEC_STOP_POST,
- false,
- true,
- &s->control_pid);
- if (r < 0)
- goto fail;
-
- return;
-
-fail:
- log_warning("%s failed to run next control task: %s", UNIT(s)->id, strerror(-r));
-
- if (s->state == SERVICE_START_PRE)
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES);
- else if (s->state == SERVICE_STOP)
- service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES);
- else if (s->state == SERVICE_STOP_POST)
- service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true);
- else if (s->state == SERVICE_RELOAD) {
- s->reload_result = SERVICE_FAILURE_RESOURCES;
- service_enter_running(s, SERVICE_SUCCESS);
- } else
- service_enter_stop(s, SERVICE_FAILURE_RESOURCES);
-}
-
-static void service_run_next_main(Service *s) {
- pid_t pid;
- int r;
-
- assert(s);
- assert(s->main_command);
- assert(s->main_command->command_next);
- assert(s->type == SERVICE_ONESHOT);
-
- s->main_command = s->main_command->command_next;
- service_unwatch_main_pid(s);
-
- r = service_spawn(s,
- s->main_command,
- true,
- true,
- true,
- true,
- true,
- s->notify_access != NOTIFY_NONE,
- false,
- &pid);
- if (r < 0)
- goto fail;
-
- service_set_main_pid(s, pid);
-
- return;
-
-fail:
- log_warning("%s failed to run next main task: %s", UNIT(s)->id, strerror(-r));
- service_enter_stop(s, SERVICE_FAILURE_RESOURCES);
-}
-
-static int service_start_limit_test(Service *s) {
- assert(s);
-
- if (ratelimit_test(&s->start_limit))
- return 0;
-
- switch (s->start_limit_action) {
-
- case SERVICE_START_LIMIT_NONE:
- log_warning("%s start request repeated too quickly, refusing to start.", UNIT(s)->id);
- break;
-
- case SERVICE_START_LIMIT_REBOOT: {
- DBusError error;
- int r;
-
- dbus_error_init(&error);
-
- log_warning("%s start request repeated too quickly, rebooting.", UNIT(s)->id);
-
- r = manager_add_job_by_name(UNIT(s)->manager, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE, true, &error, NULL);
- if (r < 0) {
- log_error("Failed to reboot: %s.", bus_error(&error, r));
- dbus_error_free(&error);
- }
-
- break;
- }
-
- case SERVICE_START_LIMIT_REBOOT_FORCE:
- log_warning("%s start request repeated too quickly, forcibly rebooting.", UNIT(s)->id);
- UNIT(s)->manager->exit_code = MANAGER_REBOOT;
- break;
-
- case SERVICE_START_LIMIT_REBOOT_IMMEDIATE:
- log_warning("%s start request repeated too quickly, rebooting immediately.", UNIT(s)->id);
- reboot(RB_AUTOBOOT);
- break;
-
- default:
- log_error("start limit action=%i", s->start_limit_action);
- assert_not_reached("Unknown StartLimitAction.");
- }
-
- return -ECANCELED;
-}
-
-static int service_start(Unit *u) {
- Service *s = SERVICE(u);
- int r;
-
- assert(s);
-
- /* We cannot fulfill this request right now, try again later
- * please! */
- if (s->state == SERVICE_STOP ||
- s->state == SERVICE_STOP_SIGTERM ||
- s->state == SERVICE_STOP_SIGKILL ||
- s->state == SERVICE_STOP_POST ||
- s->state == SERVICE_FINAL_SIGTERM ||
- s->state == SERVICE_FINAL_SIGKILL)
- return -EAGAIN;
-
- /* Already on it! */
- if (s->state == SERVICE_START_PRE ||
- s->state == SERVICE_START ||
- s->state == SERVICE_START_POST)
- return 0;
-
- /* A service that will be restarted must be stopped first to
- * trigger BindsTo and/or OnFailure dependencies. If a user
- * does not want to wait for the holdoff time to elapse, the
- * service should be manually restarted, not started. We
- * simply return EAGAIN here, so that any start jobs stay
- * queued, and assume that the auto restart timer will
- * eventually trigger the restart. */
- if (s->state == SERVICE_AUTO_RESTART)
- return -EAGAIN;
-
- assert(s->state == SERVICE_DEAD || s->state == SERVICE_FAILED);
-
- /* Make sure we don't enter a busy loop of some kind. */
- r = service_start_limit_test(s);
- if (r < 0) {
- service_enter_dead(s, SERVICE_FAILURE_START_LIMIT, false);
- return r;
- }
-
- s->result = SERVICE_SUCCESS;
- s->reload_result = SERVICE_SUCCESS;
- s->main_pid_known = false;
- s->main_pid_alien = false;
- s->forbid_restart = false;
-
- service_enter_start_pre(s);
- return 0;
-}
-
-static int service_stop(Unit *u) {
- Service *s = SERVICE(u);
-
- assert(s);
-
- /* Don't create restart jobs from here. */
- s->forbid_restart = true;
-
- /* Already on it */
- if (s->state == SERVICE_STOP ||
- s->state == SERVICE_STOP_SIGTERM ||
- s->state == SERVICE_STOP_SIGKILL ||
- s->state == SERVICE_STOP_POST ||
- s->state == SERVICE_FINAL_SIGTERM ||
- s->state == SERVICE_FINAL_SIGKILL)
- return 0;
-
- /* A restart will be scheduled or is in progress. */
- if (s->state == SERVICE_AUTO_RESTART) {
- service_set_state(s, SERVICE_DEAD);
- return 0;
- }
-
- /* If there's already something running we go directly into
- * kill mode. */
- if (s->state == SERVICE_START_PRE ||
- s->state == SERVICE_START ||
- s->state == SERVICE_START_POST ||
- s->state == SERVICE_RELOAD) {
- service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_SUCCESS);
- return 0;
- }
-
- assert(s->state == SERVICE_RUNNING ||
- s->state == SERVICE_EXITED);
-
- service_enter_stop(s, SERVICE_SUCCESS);
- return 0;
-}
-
-static int service_reload(Unit *u) {
- Service *s = SERVICE(u);
-
- assert(s);
-
- assert(s->state == SERVICE_RUNNING || s->state == SERVICE_EXITED);
-
- service_enter_reload(s);
- return 0;
-}
-
-static bool service_can_reload(Unit *u) {
- Service *s = SERVICE(u);
-
- assert(s);
-
- return !!s->exec_command[SERVICE_EXEC_RELOAD];
-}
-
-static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
- Service *s = SERVICE(u);
-
- assert(u);
- assert(f);
- assert(fds);
-
- unit_serialize_item(u, f, "state", service_state_to_string(s->state));
- unit_serialize_item(u, f, "result", service_result_to_string(s->result));
- unit_serialize_item(u, f, "reload-result", service_result_to_string(s->reload_result));
-
- if (s->control_pid > 0)
- unit_serialize_item_format(u, f, "control-pid", "%lu", (unsigned long) s->control_pid);
-
- if (s->main_pid_known && s->main_pid > 0)
- unit_serialize_item_format(u, f, "main-pid", "%lu", (unsigned long) s->main_pid);
-
- unit_serialize_item(u, f, "main-pid-known", yes_no(s->main_pid_known));
-
- if (s->status_text)
- unit_serialize_item(u, f, "status-text", s->status_text);
-
- /* FIXME: There's a minor uncleanliness here: if there are
- * multiple commands attached here, we will start from the
- * first one again */
- if (s->control_command_id >= 0)
- unit_serialize_item(u, f, "control-command", service_exec_command_to_string(s->control_command_id));
-
- if (s->socket_fd >= 0) {
- int copy;
-
- if ((copy = fdset_put_dup(fds, s->socket_fd)) < 0)
- return copy;
-
- unit_serialize_item_format(u, f, "socket-fd", "%i", copy);
- }
-
- if (s->main_exec_status.pid > 0) {
- unit_serialize_item_format(u, f, "main-exec-status-pid", "%lu", (unsigned long) s->main_exec_status.pid);
- dual_timestamp_serialize(f, "main-exec-status-start", &s->main_exec_status.start_timestamp);
- dual_timestamp_serialize(f, "main-exec-status-exit", &s->main_exec_status.exit_timestamp);
-
- if (dual_timestamp_is_set(&s->main_exec_status.exit_timestamp)) {
- unit_serialize_item_format(u, f, "main-exec-status-code", "%i", s->main_exec_status.code);
- unit_serialize_item_format(u, f, "main-exec-status-status", "%i", s->main_exec_status.status);
- }
- }
- if (dual_timestamp_is_set(&s->watchdog_timestamp))
- dual_timestamp_serialize(f, "watchdog-timestamp", &s->watchdog_timestamp);
-
- return 0;
-}
-
-static int service_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
- Service *s = SERVICE(u);
-
- assert(u);
- assert(key);
- assert(value);
- assert(fds);
-
- if (streq(key, "state")) {
- ServiceState state;
-
- if ((state = service_state_from_string(value)) < 0)
- log_debug("Failed to parse state value %s", value);
- else
- s->deserialized_state = state;
- } else if (streq(key, "result")) {
- ServiceResult f;
-
- f = service_result_from_string(value);
- if (f < 0)
- log_debug("Failed to parse result value %s", value);
- else if (f != SERVICE_SUCCESS)
- s->result = f;
-
- } else if (streq(key, "reload-result")) {
- ServiceResult f;
-
- f = service_result_from_string(value);
- if (f < 0)
- log_debug("Failed to parse reload result value %s", value);
- else if (f != SERVICE_SUCCESS)
- s->reload_result = f;
-
- } else if (streq(key, "control-pid")) {
- pid_t pid;
-
- if (parse_pid(value, &pid) < 0)
- log_debug("Failed to parse control-pid value %s", value);
- else
- s->control_pid = pid;
- } else if (streq(key, "main-pid")) {
- pid_t pid;
-
- if (parse_pid(value, &pid) < 0)
- log_debug("Failed to parse main-pid value %s", value);
- else
- service_set_main_pid(s, (pid_t) pid);
- } else if (streq(key, "main-pid-known")) {
- int b;
-
- if ((b = parse_boolean(value)) < 0)
- log_debug("Failed to parse main-pid-known value %s", value);
- else
- s->main_pid_known = b;
- } else if (streq(key, "status-text")) {
- char *t;
-
- if ((t = strdup(value))) {
- free(s->status_text);
- s->status_text = t;
- }
-
- } else if (streq(key, "control-command")) {
- ServiceExecCommand id;
-
- if ((id = service_exec_command_from_string(value)) < 0)
- log_debug("Failed to parse exec-command value %s", value);
- else {
- s->control_command_id = id;
- s->control_command = s->exec_command[id];
- }
- } else if (streq(key, "socket-fd")) {
- int fd;
-
- if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
- log_debug("Failed to parse socket-fd value %s", value);
- else {
-
- if (s->socket_fd >= 0)
- close_nointr_nofail(s->socket_fd);
- s->socket_fd = fdset_remove(fds, fd);
- }
- } else if (streq(key, "main-exec-status-pid")) {
- pid_t pid;
-
- if (parse_pid(value, &pid) < 0)
- log_debug("Failed to parse main-exec-status-pid value %s", value);
- else
- s->main_exec_status.pid = pid;
- } else if (streq(key, "main-exec-status-code")) {
- int i;
-
- if (safe_atoi(value, &i) < 0)
- log_debug("Failed to parse main-exec-status-code value %s", value);
- else
- s->main_exec_status.code = i;
- } else if (streq(key, "main-exec-status-status")) {
- int i;
-
- if (safe_atoi(value, &i) < 0)
- log_debug("Failed to parse main-exec-status-status value %s", value);
- else
- s->main_exec_status.status = i;
- } else if (streq(key, "main-exec-status-start"))
- dual_timestamp_deserialize(value, &s->main_exec_status.start_timestamp);
- else if (streq(key, "main-exec-status-exit"))
- dual_timestamp_deserialize(value, &s->main_exec_status.exit_timestamp);
- else if (streq(key, "watchdog-timestamp"))
- dual_timestamp_deserialize(value, &s->watchdog_timestamp);
- else
- log_debug("Unknown serialization key '%s'", key);
-
- return 0;
-}
-
-static UnitActiveState service_active_state(Unit *u) {
- const UnitActiveState *table;
-
- assert(u);
-
- table = SERVICE(u)->type == SERVICE_IDLE ? state_translation_table_idle : state_translation_table;
-
- return table[SERVICE(u)->state];
-}
-
-static const char *service_sub_state_to_string(Unit *u) {
- assert(u);
-
- return service_state_to_string(SERVICE(u)->state);
-}
-
-static bool service_check_gc(Unit *u) {
- Service *s = SERVICE(u);
-
- assert(s);
-
- /* Never clean up services that still have a process around,
- * even if the service is formally dead. */
- if (cgroup_good(s) > 0 ||
- main_pid_good(s) > 0 ||
- control_pid_good(s) > 0)
- return true;
-
-#ifdef HAVE_SYSV_COMPAT
- if (s->is_sysv)
- return true;
-#endif
-
- return false;
-}
-
-static bool service_check_snapshot(Unit *u) {
- Service *s = SERVICE(u);
-
- assert(s);
-
- return !s->got_socket_fd;
-}
-
-static int service_retry_pid_file(Service *s) {
- int r;
-
- assert(s->pid_file);
- assert(s->state == SERVICE_START || s->state == SERVICE_START_POST);
-
- r = service_load_pid_file(s, false);
- if (r < 0)
- return r;
-
- service_unwatch_pid_file(s);
-
- service_enter_running(s, SERVICE_SUCCESS);
- return 0;
-}
-
-static int service_watch_pid_file(Service *s) {
- int r;
-
- log_debug("Setting watch for %s's PID file %s", UNIT(s)->id, s->pid_file_pathspec->path);
- r = path_spec_watch(s->pid_file_pathspec, UNIT(s));
- if (r < 0)
- goto fail;
-
- /* the pidfile might have appeared just before we set the watch */
- service_retry_pid_file(s);
-
- return 0;
-fail:
- log_error("Failed to set a watch for %s's PID file %s: %s",
- UNIT(s)->id, s->pid_file_pathspec->path, strerror(-r));
- service_unwatch_pid_file(s);
- return r;
-}
-
-static int service_demand_pid_file(Service *s) {
- PathSpec *ps;
-
- assert(s->pid_file);
- assert(!s->pid_file_pathspec);
-
- ps = new0(PathSpec, 1);
- if (!ps)
- return -ENOMEM;
-
- ps->path = strdup(s->pid_file);
- if (!ps->path) {
- free(ps);
- return -ENOMEM;
- }
-
- path_kill_slashes(ps->path);
-
- /* PATH_CHANGED would not be enough. There are daemons (sendmail) that
- * keep their PID file open all the time. */
- ps->type = PATH_MODIFIED;
- ps->inotify_fd = -1;
-
- s->pid_file_pathspec = ps;
-
- return service_watch_pid_file(s);
-}
-
-static void service_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
- Service *s = SERVICE(u);
-
- assert(s);
- assert(fd >= 0);
- assert(s->state == SERVICE_START || s->state == SERVICE_START_POST);
- assert(s->pid_file_pathspec);
- assert(path_spec_owns_inotify_fd(s->pid_file_pathspec, fd));
-
- log_debug("inotify event for %s", u->id);
-
- if (path_spec_fd_event(s->pid_file_pathspec, events) < 0)
- goto fail;
-
- if (service_retry_pid_file(s) == 0)
- return;
-
- if (service_watch_pid_file(s) < 0)
- goto fail;
-
- return;
-fail:
- service_unwatch_pid_file(s);
- service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES);
-}
-
-static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
- Service *s = SERVICE(u);
- ServiceResult f;
-
- assert(s);
- assert(pid >= 0);
-
- if (UNIT(s)->fragment_path ? is_clean_exit(code, status, &s->success_status) :
- is_clean_exit_lsb(code, status, &s->success_status))
- f = SERVICE_SUCCESS;
- else if (code == CLD_EXITED)
- f = SERVICE_FAILURE_EXIT_CODE;
- else if (code == CLD_KILLED)
- f = SERVICE_FAILURE_SIGNAL;
- else if (code == CLD_DUMPED)
- f = SERVICE_FAILURE_CORE_DUMP;
- else
- assert_not_reached("Unknown code");
-
- if (s->main_pid == pid) {
- /* Forking services may occasionally move to a new PID.
- * As long as they update the PID file before exiting the old
- * PID, they're fine. */
- if (service_load_pid_file(s, false) == 0)
- return;
-
- s->main_pid = 0;
- exec_status_exit(&s->main_exec_status, &s->exec_context, pid, code, status);
-
- /* If this is not a forking service than the main
- * process got started and hence we copy the exit
- * status so that it is recorded both as main and as
- * control process exit status */
- if (s->main_command) {
- s->main_command->exec_status = s->main_exec_status;
-
- if (s->main_command->ignore)
- f = SERVICE_SUCCESS;
- }
-
- log_struct(f == SERVICE_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
- "MESSAGE=%s: main process exited, code=%s, status=%i/%s",
- u->id, sigchld_code_to_string(code), status,
- strna(code == CLD_EXITED
- ? exit_status_to_string(status, EXIT_STATUS_FULL)
- : signal_to_string(status)),
- "UNIT=%s", u->id,
- "EXIT_CODE=%s", sigchld_code_to_string(code),
- "EXIT_STATUS=%i", status,
- NULL);
-
- if (f != SERVICE_SUCCESS)
- s->result = f;
-
- if (s->main_command &&
- s->main_command->command_next &&
- f == SERVICE_SUCCESS) {
-
- /* There is another command to *
- * execute, so let's do that. */
-
- log_debug("%s running next main command for state %s", u->id, service_state_to_string(s->state));
- service_run_next_main(s);
-
- } else {
-
- /* The service exited, so the service is officially
- * gone. */
- s->main_command = NULL;
-
- switch (s->state) {
-
- case SERVICE_START_POST:
- case SERVICE_RELOAD:
- case SERVICE_STOP:
- /* Need to wait until the operation is
- * done */
- break;
-
- case SERVICE_START:
- if (s->type == SERVICE_ONESHOT) {
- /* This was our main goal, so let's go on */
- if (f == SERVICE_SUCCESS)
- service_enter_start_post(s);
- else
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
- break;
- }
-
- /* Fall through */
-
- case SERVICE_RUNNING:
- service_enter_running(s, f);
- break;
-
- case SERVICE_STOP_SIGTERM:
- case SERVICE_STOP_SIGKILL:
-
- if (!control_pid_good(s))
- service_enter_stop_post(s, f);
-
- /* If there is still a control process, wait for that first */
- break;
-
- default:
- assert_not_reached("Uh, main process died at wrong time.");
- }
- }
-
- } else if (s->control_pid == pid) {
-
- s->control_pid = 0;
-
- if (s->control_command) {
- exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status);
-
- if (s->control_command->ignore)
- f = SERVICE_SUCCESS;
- }
-
- log_full(f == SERVICE_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
- "%s: control process exited, code=%s status=%i", u->id, sigchld_code_to_string(code), status);
-
- if (f != SERVICE_SUCCESS)
- s->result = f;
-
- /* Immediately get rid of the cgroup, so that the
- * kernel doesn't delay the cgroup empty messages for
- * the service cgroup any longer than necessary */
- cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, SIGKILL, true, true, NULL, "control");
-
- if (s->control_command &&
- s->control_command->command_next &&
- f == SERVICE_SUCCESS) {
-
- /* There is another command to *
- * execute, so let's do that. */
-
- log_debug("%s running next control command for state %s", u->id, service_state_to_string(s->state));
- service_run_next_control(s);
-
- } else {
- /* No further commands for this step, so let's
- * figure out what to do next */
-
- s->control_command = NULL;
- s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID;
-
- log_debug("%s got final SIGCHLD for state %s", u->id, service_state_to_string(s->state));
-
- switch (s->state) {
-
- case SERVICE_START_PRE:
- if (f == SERVICE_SUCCESS)
- service_enter_start(s);
- else
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
- break;
-
- case SERVICE_START:
- if (s->type != SERVICE_FORKING)
- /* Maybe spurious event due to a reload that changed the type? */
- break;
-
- if (f != SERVICE_SUCCESS) {
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
- break;
- }
-
- if (s->pid_file) {
- bool has_start_post;
- int r;
-
- /* Let's try to load the pid file here if we can.
- * The PID file might actually be created by a START_POST
- * script. In that case don't worry if the loading fails. */
-
- has_start_post = !!s->exec_command[SERVICE_EXEC_START_POST];
- r = service_load_pid_file(s, !has_start_post);
- if (!has_start_post && r < 0) {
- r = service_demand_pid_file(s);
- if (r < 0 || !cgroup_good(s))
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES);
- break;
- }
- } else
- service_search_main_pid(s);
-
- service_enter_start_post(s);
- break;
-
- case SERVICE_START_POST:
- if (f != SERVICE_SUCCESS) {
- service_enter_stop(s, f);
- break;
- }
-
- if (s->pid_file) {
- int r;
-
- r = service_load_pid_file(s, true);
- if (r < 0) {
- r = service_demand_pid_file(s);
- if (r < 0 || !cgroup_good(s))
- service_enter_stop(s, SERVICE_FAILURE_RESOURCES);
- break;
- }
- } else
- service_search_main_pid(s);
-
- service_enter_running(s, SERVICE_SUCCESS);
- break;
-
- case SERVICE_RELOAD:
- if (f == SERVICE_SUCCESS) {
- service_load_pid_file(s, true);
- service_search_main_pid(s);
- }
-
- s->reload_result = f;
- service_enter_running(s, SERVICE_SUCCESS);
- break;
-
- case SERVICE_STOP:
- service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
- break;
-
- case SERVICE_STOP_SIGTERM:
- case SERVICE_STOP_SIGKILL:
- if (main_pid_good(s) <= 0)
- service_enter_stop_post(s, f);
-
- /* If there is still a service
- * process around, wait until
- * that one quit, too */
- break;
-
- case SERVICE_STOP_POST:
- case SERVICE_FINAL_SIGTERM:
- case SERVICE_FINAL_SIGKILL:
- service_enter_dead(s, f, true);
- break;
-
- default:
- assert_not_reached("Uh, control process died at wrong time.");
- }
- }
- }
-
- /* Notify clients about changed exit status */
- unit_add_to_dbus_queue(u);
-}
-
-static void service_timer_event(Unit *u, uint64_t elapsed, Watch* w) {
- Service *s = SERVICE(u);
-
- assert(s);
- assert(elapsed == 1);
-
- if (w == &s->watchdog_watch) {
- service_handle_watchdog(s);
- return;
- }
-
- assert(w == &s->timer_watch);
-
- switch (s->state) {
-
- case SERVICE_START_PRE:
- case SERVICE_START:
- log_warning("%s operation timed out. Terminating.", u->id);
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_TIMEOUT);
- break;
-
- case SERVICE_START_POST:
- log_warning("%s operation timed out. Stopping.", u->id);
- service_enter_stop(s, SERVICE_FAILURE_TIMEOUT);
- break;
-
- case SERVICE_RELOAD:
- log_warning("%s operation timed out. Stopping.", u->id);
- s->reload_result = SERVICE_FAILURE_TIMEOUT;
- service_enter_running(s, SERVICE_SUCCESS);
- break;
-
- case SERVICE_STOP:
- log_warning("%s stopping timed out. Terminating.", u->id);
- service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT);
- break;
-
- case SERVICE_STOP_SIGTERM:
- if (s->kill_context.send_sigkill) {
- log_warning("%s stopping timed out. Killing.", u->id);
- service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_FAILURE_TIMEOUT);
- } else {
- log_warning("%s stopping timed out. Skipping SIGKILL.", u->id);
- service_enter_stop_post(s, SERVICE_FAILURE_TIMEOUT);
- }
-
- break;
-
- case SERVICE_STOP_SIGKILL:
- /* Uh, we sent a SIGKILL and it is still not gone?
- * Must be something we cannot kill, so let's just be
- * weirded out and continue */
-
- log_warning("%s still around after SIGKILL. Ignoring.", u->id);
- service_enter_stop_post(s, SERVICE_FAILURE_TIMEOUT);
- break;
-
- case SERVICE_STOP_POST:
- log_warning("%s stopping timed out (2). Terminating.", u->id);
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_TIMEOUT);
- break;
-
- case SERVICE_FINAL_SIGTERM:
- if (s->kill_context.send_sigkill) {
- log_warning("%s stopping timed out (2). Killing.", u->id);
- service_enter_signal(s, SERVICE_FINAL_SIGKILL, SERVICE_FAILURE_TIMEOUT);
- } else {
- log_warning("%s stopping timed out (2). Skipping SIGKILL. Entering failed mode.", u->id);
- service_enter_dead(s, SERVICE_FAILURE_TIMEOUT, false);
- }
-
- break;
-
- case SERVICE_FINAL_SIGKILL:
- log_warning("%s still around after SIGKILL (2). Entering failed mode.", u->id);
- service_enter_dead(s, SERVICE_FAILURE_TIMEOUT, true);
- break;
-
- case SERVICE_AUTO_RESTART:
- log_info("%s holdoff time over, scheduling restart.", u->id);
- service_enter_restart(s);
- break;
-
- default:
- assert_not_reached("Timeout at wrong time.");
- }
-}
-
-static void service_cgroup_notify_event(Unit *u) {
- Service *s = SERVICE(u);
-
- assert(u);
-
- log_debug("%s: cgroup is empty", u->id);
-
- switch (s->state) {
-
- /* Waiting for SIGCHLD is usually more interesting,
- * because it includes return codes/signals. Which is
- * why we ignore the cgroup events for most cases,
- * except when we don't know pid which to expect the
- * SIGCHLD for. */
-
- case SERVICE_START:
- case SERVICE_START_POST:
- /* If we were hoping for the daemon to write its PID file,
- * we can give up now. */
- if (s->pid_file_pathspec) {
- log_warning("%s never wrote its PID file. Failing.", UNIT(s)->id);
- service_unwatch_pid_file(s);
- if (s->state == SERVICE_START)
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES);
- else
- service_enter_stop(s, SERVICE_FAILURE_RESOURCES);
- }
- break;
-
- case SERVICE_RUNNING:
- /* service_enter_running() will figure out what to do */
- service_enter_running(s, SERVICE_SUCCESS);
- break;
-
- case SERVICE_STOP_SIGTERM:
- case SERVICE_STOP_SIGKILL:
-
- if (main_pid_good(s) <= 0 && !control_pid_good(s))
- service_enter_stop_post(s, SERVICE_SUCCESS);
-
- break;
-
- case SERVICE_FINAL_SIGTERM:
- case SERVICE_FINAL_SIGKILL:
- if (main_pid_good(s) <= 0 && !control_pid_good(s))
- service_enter_dead(s, SERVICE_SUCCESS, true);
-
- break;
-
- default:
- ;
- }
-}
-
-static void service_notify_message(Unit *u, pid_t pid, char **tags) {
- Service *s = SERVICE(u);
- const char *e;
-
- assert(u);
-
- if (s->notify_access == NOTIFY_NONE) {
- log_warning("%s: Got notification message from PID %lu, but reception is disabled.",
- u->id, (unsigned long) pid);
- return;
- }
-
- if (s->notify_access == NOTIFY_MAIN && pid != s->main_pid) {
- log_warning("%s: Got notification message from PID %lu, but reception only permitted for PID %lu",
- u->id, (unsigned long) pid, (unsigned long) s->main_pid);
- return;
- }
-
- log_debug("%s: Got message", u->id);
-
- /* Interpret MAINPID= */
- if ((e = strv_find_prefix(tags, "MAINPID=")) &&
- (s->state == SERVICE_START ||
- s->state == SERVICE_START_POST ||
- s->state == SERVICE_RUNNING ||
- s->state == SERVICE_RELOAD)) {
-
- if (parse_pid(e + 8, &pid) < 0)
- log_warning("Failed to parse notification message %s", e);
- else {
- log_debug("%s: got %s", u->id, e);
- service_set_main_pid(s, pid);
- }
- }
-
- /* Interpret READY= */
- if (s->type == SERVICE_NOTIFY &&
- s->state == SERVICE_START &&
- strv_find(tags, "READY=1")) {
- log_debug("%s: got READY=1", u->id);
-
- service_enter_start_post(s);
- }
-
- /* Interpret STATUS= */
- e = strv_find_prefix(tags, "STATUS=");
- if (e) {
- char *t;
-
- if (e[7]) {
-
- if (!utf8_is_valid(e+7)) {
- log_warning("Status message in notification is not UTF-8 clean.");
- return;
- }
-
- t = strdup(e+7);
- if (!t) {
- log_error("Failed to allocate string.");
- return;
- }
-
- log_debug("%s: got %s", u->id, e);
-
- free(s->status_text);
- s->status_text = t;
- } else {
- free(s->status_text);
- s->status_text = NULL;
- }
-
- }
- if (strv_find(tags, "WATCHDOG=1")) {
- log_debug("%s: got WATCHDOG=1", u->id);
- service_reset_watchdog(s);
- }
-
- /* Notify clients about changed status or main pid */
- unit_add_to_dbus_queue(u);
-}
-
-#ifdef HAVE_SYSV_COMPAT
-
-#ifdef TARGET_SUSE
-static void sysv_facility_in_insserv_conf(Manager *mgr) {
- FILE *f=NULL;
- int r;
-
- if (!(f = fopen("/etc/insserv.conf", "re"))) {
- r = errno == ENOENT ? 0 : -errno;
- goto finish;
- }
-
- while (!feof(f)) {
- char l[LINE_MAX], *t;
- char **parsed = NULL;
-
- if (!fgets(l, sizeof(l), f)) {
- if (feof(f))
- break;
-
- r = -errno;
- log_error("Failed to read configuration file '/etc/insserv.conf': %s", strerror(-r));
- goto finish;
- }
-
- t = strstrip(l);
- if (*t != '$' && *t != '<')
- continue;
-
- parsed = strv_split(t,WHITESPACE);
- /* we ignore <interactive>, not used, equivalent to X-Interactive */
- if (parsed && !startswith_no_case (parsed[0], "<interactive>")) {
- char *facility;
- Unit *u;
- if (sysv_translate_facility(parsed[0], NULL, &facility) < 0)
- continue;
- if ((u = manager_get_unit(mgr, facility)) && (u->type == UNIT_TARGET)) {
- UnitDependency e;
- char *dep = NULL, *name, **j;
-
- STRV_FOREACH (j, parsed+1) {
- if (*j[0]=='+') {
- e = UNIT_WANTS;
- name = *j+1;
- }
- else {
- e = UNIT_REQUIRES;
- name = *j;
- }
- if (sysv_translate_facility(name, NULL, &dep) < 0)
- continue;
-
- r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, e, dep, NULL, true);
- free(dep);
- }
- }
- free(facility);
- }
- strv_free(parsed);
- }
-finish:
- if (f)
- fclose(f);
-
-}
-#endif
-
-static int service_enumerate(Manager *m) {
- char **p;
- unsigned i;
- DIR *d = NULL;
- char *path = NULL, *fpath = NULL, *name = NULL;
- Set *runlevel_services[ELEMENTSOF(rcnd_table)], *shutdown_services = NULL;
- Unit *service;
- Iterator j;
- int r;
-
- assert(m);
-
- if (m->running_as != SYSTEMD_SYSTEM)
- return 0;
-
- zero(runlevel_services);
-
- STRV_FOREACH(p, m->lookup_paths.sysvrcnd_path)
- for (i = 0; i < ELEMENTSOF(rcnd_table); i ++) {
- struct dirent *de;
-
- free(path);
- path = strjoin(*p, "/", rcnd_table[i].path, NULL);
- if (!path) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (d)
- closedir(d);
-
- if (!(d = opendir(path))) {
- if (errno != ENOENT)
- log_warning("opendir() failed on %s: %s", path, strerror(errno));
-
- continue;
- }
-
- while ((de = readdir(d))) {
- int a, b;
-
- if (ignore_file(de->d_name))
- continue;
-
- if (de->d_name[0] != 'S' && de->d_name[0] != 'K')
- continue;
-
- if (strlen(de->d_name) < 4)
- continue;
-
- a = undecchar(de->d_name[1]);
- b = undecchar(de->d_name[2]);
-
- if (a < 0 || b < 0)
- continue;
-
- free(fpath);
- fpath = strjoin(path, "/", de->d_name, NULL);
- if (!fpath) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (access(fpath, X_OK) < 0) {
-
- if (errno != ENOENT)
- log_warning("access() failed on %s: %s", fpath, strerror(errno));
-
- continue;
- }
-
- free(name);
- if (!(name = sysv_translate_name(de->d_name + 3))) {
- r = -ENOMEM;
- goto finish;
- }
-
- if ((r = manager_load_unit_prepare(m, name, NULL, NULL, &service)) < 0) {
- log_warning("Failed to prepare unit %s: %s", name, strerror(-r));
- continue;
- }
-
- if (de->d_name[0] == 'S') {
-
- if (rcnd_table[i].type == RUNLEVEL_UP || rcnd_table[i].type == RUNLEVEL_SYSINIT) {
- SERVICE(service)->sysv_start_priority_from_rcnd =
- MAX(a*10 + b, SERVICE(service)->sysv_start_priority_from_rcnd);
-
- SERVICE(service)->sysv_enabled = true;
- }
-
- if ((r = set_ensure_allocated(&runlevel_services[i], trivial_hash_func, trivial_compare_func)) < 0)
- goto finish;
-
- if ((r = set_put(runlevel_services[i], service)) < 0)
- goto finish;
-
- } else if (de->d_name[0] == 'K' &&
- (rcnd_table[i].type == RUNLEVEL_DOWN ||
- rcnd_table[i].type == RUNLEVEL_SYSINIT)) {
-
- if ((r = set_ensure_allocated(&shutdown_services, trivial_hash_func, trivial_compare_func)) < 0)
- goto finish;
-
- if ((r = set_put(shutdown_services, service)) < 0)
- goto finish;
- }
- }
- }
-
- /* Now we loaded all stubs and are aware of the lowest
- start-up priority for all services, not let's actually load
- the services, this will also tell us which services are
- actually native now */
- manager_dispatch_load_queue(m);
-
- /* If this is a native service, rely on native ways to pull in
- * a service, don't pull it in via sysv rcN.d links. */
- for (i = 0; i < ELEMENTSOF(rcnd_table); i ++)
- SET_FOREACH(service, runlevel_services[i], j) {
- service = unit_follow_merge(service);
-
- if (service->fragment_path)
- continue;
-
- if ((r = unit_add_two_dependencies_by_name_inverse(service, UNIT_AFTER, UNIT_WANTS, rcnd_table[i].target, NULL, true)) < 0)
- goto finish;
- }
-
- /* We honour K links only for halt/reboot. For the normal
- * runlevels we assume the stop jobs will be implicitly added
- * by the core logic. Also, we don't really distinguish here
- * between the runlevels 0 and 6 and just add them to the
- * special shutdown target. On SUSE the boot.d/ runlevel is
- * also used for shutdown, so we add links for that too to the
- * shutdown target.*/
- SET_FOREACH(service, shutdown_services, j) {
- service = unit_follow_merge(service);
-
- if (service->fragment_path)
- continue;
-
- if ((r = unit_add_two_dependencies_by_name(service, UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true)) < 0)
- goto finish;
- }
-
- r = 0;
-
-#ifdef TARGET_SUSE
- sysv_facility_in_insserv_conf (m);
-#endif
-
-finish:
- free(path);
- free(fpath);
- free(name);
-
- for (i = 0; i < ELEMENTSOF(rcnd_table); i++)
- set_free(runlevel_services[i]);
- set_free(shutdown_services);
-
- if (d)
- closedir(d);
-
- return r;
-}
-#endif
-
-static void service_bus_name_owner_change(
- Unit *u,
- const char *name,
- const char *old_owner,
- const char *new_owner) {
-
- Service *s = SERVICE(u);
-
- assert(s);
- assert(name);
-
- assert(streq(s->bus_name, name));
- assert(old_owner || new_owner);
-
- if (old_owner && new_owner)
- log_debug("%s's D-Bus name %s changed owner from %s to %s", u->id, name, old_owner, new_owner);
- else if (old_owner)
- log_debug("%s's D-Bus name %s no longer registered by %s", u->id, name, old_owner);
- else
- log_debug("%s's D-Bus name %s now registered by %s", u->id, name, new_owner);
-
- s->bus_name_good = !!new_owner;
-
- if (s->type == SERVICE_DBUS) {
-
- /* service_enter_running() will figure out what to
- * do */
- if (s->state == SERVICE_RUNNING)
- service_enter_running(s, SERVICE_SUCCESS);
- else if (s->state == SERVICE_START && new_owner)
- service_enter_start_post(s);
-
- } else if (new_owner &&
- s->main_pid <= 0 &&
- (s->state == SERVICE_START ||
- s->state == SERVICE_START_POST ||
- s->state == SERVICE_RUNNING ||
- s->state == SERVICE_RELOAD)) {
-
- /* Try to acquire PID from bus service */
- log_debug("Trying to acquire PID from D-Bus name...");
-
- bus_query_pid(u->manager, name);
- }
-}
-
-static void service_bus_query_pid_done(
- Unit *u,
- const char *name,
- pid_t pid) {
-
- Service *s = SERVICE(u);
-
- assert(s);
- assert(name);
-
- log_debug("%s's D-Bus name %s is now owned by process %u", u->id, name, (unsigned) pid);
-
- if (s->main_pid <= 0 &&
- (s->state == SERVICE_START ||
- s->state == SERVICE_START_POST ||
- s->state == SERVICE_RUNNING ||
- s->state == SERVICE_RELOAD))
- service_set_main_pid(s, pid);
-}
-
-int service_set_socket_fd(Service *s, int fd, Socket *sock) {
-
- assert(s);
- assert(fd >= 0);
-
- /* This is called by the socket code when instantiating a new
- * service for a stream socket and the socket needs to be
- * configured. */
-
- if (UNIT(s)->load_state != UNIT_LOADED)
- return -EINVAL;
-
- if (s->socket_fd >= 0)
- return -EBUSY;
-
- if (s->state != SERVICE_DEAD)
- return -EAGAIN;
-
- s->socket_fd = fd;
- s->got_socket_fd = true;
-
- unit_ref_set(&s->accept_socket, UNIT(sock));
-
- return unit_add_two_dependencies(UNIT(sock), UNIT_BEFORE, UNIT_TRIGGERS, UNIT(s), false);
-}
-
-static void service_reset_failed(Unit *u) {
- Service *s = SERVICE(u);
-
- assert(s);
-
- if (s->state == SERVICE_FAILED)
- service_set_state(s, SERVICE_DEAD);
-
- s->result = SERVICE_SUCCESS;
- s->reload_result = SERVICE_SUCCESS;
-
- RATELIMIT_RESET(s->start_limit);
-}
-
-static int service_kill(Unit *u, KillWho who, int signo, DBusError *error) {
- Service *s = SERVICE(u);
- int r = 0;
- Set *pid_set = NULL;
-
- assert(s);
-
- if (s->main_pid <= 0 && who == KILL_MAIN) {
- dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No main process to kill");
- return -ESRCH;
- }
-
- if (s->control_pid <= 0 && who == KILL_CONTROL) {
- dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
- return -ESRCH;
- }
-
- if (who == KILL_CONTROL || who == KILL_ALL)
- if (s->control_pid > 0)
- if (kill(s->control_pid, signo) < 0)
- r = -errno;
-
- if (who == KILL_MAIN || who == KILL_ALL)
- if (s->main_pid > 0)
- if (kill(s->main_pid, signo) < 0)
- r = -errno;
-
- if (who == KILL_ALL) {
- int q;
-
- pid_set = set_new(trivial_hash_func, trivial_compare_func);
- if (!pid_set)
- return -ENOMEM;
-
- /* Exclude the control/main pid from being killed via the cgroup */
- if (s->control_pid > 0) {
- q = set_put(pid_set, LONG_TO_PTR(s->control_pid));
- if (q < 0) {
- r = q;
- goto finish;
- }
- }
-
- if (s->main_pid > 0) {
- q = set_put(pid_set, LONG_TO_PTR(s->main_pid));
- if (q < 0) {
- r = q;
- goto finish;
- }
- }
-
- q = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, signo, false, false, pid_set, NULL);
- if (q < 0 && q != -EAGAIN && q != -ESRCH && q != -ENOENT)
- r = q;
- }
-
-finish:
- if (pid_set)
- set_free(pid_set);
-
- return r;
-}
-
-static const char* const service_state_table[_SERVICE_STATE_MAX] = {
- [SERVICE_DEAD] = "dead",
- [SERVICE_START_PRE] = "start-pre",
- [SERVICE_START] = "start",
- [SERVICE_START_POST] = "start-post",
- [SERVICE_RUNNING] = "running",
- [SERVICE_EXITED] = "exited",
- [SERVICE_RELOAD] = "reload",
- [SERVICE_STOP] = "stop",
- [SERVICE_STOP_SIGTERM] = "stop-sigterm",
- [SERVICE_STOP_SIGKILL] = "stop-sigkill",
- [SERVICE_STOP_POST] = "stop-post",
- [SERVICE_FINAL_SIGTERM] = "final-sigterm",
- [SERVICE_FINAL_SIGKILL] = "final-sigkill",
- [SERVICE_FAILED] = "failed",
- [SERVICE_AUTO_RESTART] = "auto-restart",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(service_state, ServiceState);
-
-static const char* const service_restart_table[_SERVICE_RESTART_MAX] = {
- [SERVICE_RESTART_NO] = "no",
- [SERVICE_RESTART_ON_SUCCESS] = "on-success",
- [SERVICE_RESTART_ON_FAILURE] = "on-failure",
- [SERVICE_RESTART_ON_ABORT] = "on-abort",
- [SERVICE_RESTART_ALWAYS] = "always"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(service_restart, ServiceRestart);
-
-static const char* const service_type_table[_SERVICE_TYPE_MAX] = {
- [SERVICE_SIMPLE] = "simple",
- [SERVICE_FORKING] = "forking",
- [SERVICE_ONESHOT] = "oneshot",
- [SERVICE_DBUS] = "dbus",
- [SERVICE_NOTIFY] = "notify",
- [SERVICE_IDLE] = "idle"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(service_type, ServiceType);
-
-static const char* const service_exec_command_table[_SERVICE_EXEC_COMMAND_MAX] = {
- [SERVICE_EXEC_START_PRE] = "ExecStartPre",
- [SERVICE_EXEC_START] = "ExecStart",
- [SERVICE_EXEC_START_POST] = "ExecStartPost",
- [SERVICE_EXEC_RELOAD] = "ExecReload",
- [SERVICE_EXEC_STOP] = "ExecStop",
- [SERVICE_EXEC_STOP_POST] = "ExecStopPost",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(service_exec_command, ServiceExecCommand);
-
-static const char* const notify_access_table[_NOTIFY_ACCESS_MAX] = {
- [NOTIFY_NONE] = "none",
- [NOTIFY_MAIN] = "main",
- [NOTIFY_ALL] = "all"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(notify_access, NotifyAccess);
-
-static const char* const service_result_table[_SERVICE_RESULT_MAX] = {
- [SERVICE_SUCCESS] = "success",
- [SERVICE_FAILURE_RESOURCES] = "resources",
- [SERVICE_FAILURE_TIMEOUT] = "timeout",
- [SERVICE_FAILURE_EXIT_CODE] = "exit-code",
- [SERVICE_FAILURE_SIGNAL] = "signal",
- [SERVICE_FAILURE_CORE_DUMP] = "core-dump",
- [SERVICE_FAILURE_WATCHDOG] = "watchdog",
- [SERVICE_FAILURE_START_LIMIT] = "start-limit"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(service_result, ServiceResult);
-
-static const char* const start_limit_action_table[_SERVICE_START_LIMIT_MAX] = {
- [SERVICE_START_LIMIT_NONE] = "none",
- [SERVICE_START_LIMIT_REBOOT] = "reboot",
- [SERVICE_START_LIMIT_REBOOT_FORCE] = "reboot-force",
- [SERVICE_START_LIMIT_REBOOT_IMMEDIATE] = "reboot-immediate"
-};
-DEFINE_STRING_TABLE_LOOKUP(start_limit_action, StartLimitAction);
-
-const UnitVTable service_vtable = {
- .object_size = sizeof(Service),
- .exec_context_offset = offsetof(Service, exec_context),
-
- .sections =
- "Unit\0"
- "Service\0"
- "Install\0",
-
- .init = service_init,
- .done = service_done,
- .load = service_load,
-
- .coldplug = service_coldplug,
-
- .dump = service_dump,
-
- .start = service_start,
- .stop = service_stop,
- .reload = service_reload,
-
- .can_reload = service_can_reload,
-
- .kill = service_kill,
-
- .serialize = service_serialize,
- .deserialize_item = service_deserialize_item,
-
- .active_state = service_active_state,
- .sub_state_to_string = service_sub_state_to_string,
-
- .check_gc = service_check_gc,
- .check_snapshot = service_check_snapshot,
-
- .sigchld_event = service_sigchld_event,
- .timer_event = service_timer_event,
- .fd_event = service_fd_event,
-
- .reset_failed = service_reset_failed,
-
- .cgroup_notify_empty = service_cgroup_notify_event,
- .notify_message = service_notify_message,
-
- .bus_name_owner_change = service_bus_name_owner_change,
- .bus_query_pid_done = service_bus_query_pid_done,
-
- .bus_interface = "org.freedesktop.systemd1.Service",
- .bus_message_handler = bus_service_message_handler,
- .bus_invalidating_properties = bus_service_invalidating_properties,
-
-#ifdef HAVE_SYSV_COMPAT
- .enumerate = service_enumerate,
-#endif
- .status_message_formats = {
- .starting_stopping = {
- [0] = "Starting %s...",
- [1] = "Stopping %s...",
- },
- .finished_start_job = {
- [JOB_DONE] = "Started %s.",
- [JOB_FAILED] = "Failed to start %s.",
- [JOB_DEPENDENCY] = "Dependency failed for %s.",
- [JOB_TIMEOUT] = "Timed out starting %s.",
- },
- .finished_stop_job = {
- [JOB_DONE] = "Stopped %s.",
- [JOB_FAILED] = "Stopped (with error) %s.",
- [JOB_TIMEOUT] = "Timed out stopping %s.",
- },
- },
-};
diff --git a/src/core/service.h b/src/core/service.h
deleted file mode 100644
index d1e53bf727..0000000000
--- a/src/core/service.h
+++ /dev/null
@@ -1,225 +0,0 @@
-/*-*- 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/>.
-***/
-
-typedef struct Service Service;
-
-#include "unit.h"
-#include "path.h"
-#include "ratelimit.h"
-#include "service.h"
-#include "kill.h"
-#include "exit-status.h"
-
-typedef enum ServiceState {
- SERVICE_DEAD,
- SERVICE_START_PRE,
- SERVICE_START,
- SERVICE_START_POST,
- SERVICE_RUNNING,
- SERVICE_EXITED, /* Nothing is running anymore, but RemainAfterExit is true hence this is OK */
- SERVICE_RELOAD,
- SERVICE_STOP, /* No STOP_PRE state, instead just register multiple STOP executables */
- SERVICE_STOP_SIGTERM,
- SERVICE_STOP_SIGKILL,
- SERVICE_STOP_POST,
- SERVICE_FINAL_SIGTERM, /* In case the STOP_POST executable hangs, we shoot that down, too */
- SERVICE_FINAL_SIGKILL,
- SERVICE_FAILED,
- SERVICE_AUTO_RESTART,
- _SERVICE_STATE_MAX,
- _SERVICE_STATE_INVALID = -1
-} ServiceState;
-
-typedef enum ServiceRestart {
- SERVICE_RESTART_NO,
- SERVICE_RESTART_ON_SUCCESS,
- SERVICE_RESTART_ON_FAILURE,
- SERVICE_RESTART_ON_ABORT,
- SERVICE_RESTART_ALWAYS,
- _SERVICE_RESTART_MAX,
- _SERVICE_RESTART_INVALID = -1
-} ServiceRestart;
-
-typedef enum ServiceType {
- SERVICE_SIMPLE, /* we fork and go on right-away (i.e. modern socket activated daemons) */
- SERVICE_FORKING, /* forks by itself (i.e. traditional daemons) */
- SERVICE_ONESHOT, /* we fork and wait until the program finishes (i.e. programs like fsck which run and need to finish before we continue) */
- SERVICE_DBUS, /* we fork and wait until a specific D-Bus name appears on the bus */
- SERVICE_NOTIFY, /* we fork and wait until a daemon sends us a ready message with sd_notify() */
- SERVICE_IDLE, /* much like simple, but delay exec() until all jobs are dispatched. */
- _SERVICE_TYPE_MAX,
- _SERVICE_TYPE_INVALID = -1
-} ServiceType;
-
-typedef enum ServiceExecCommand {
- SERVICE_EXEC_START_PRE,
- SERVICE_EXEC_START,
- SERVICE_EXEC_START_POST,
- SERVICE_EXEC_RELOAD,
- SERVICE_EXEC_STOP,
- SERVICE_EXEC_STOP_POST,
- _SERVICE_EXEC_COMMAND_MAX,
- _SERVICE_EXEC_COMMAND_INVALID = -1
-} ServiceExecCommand;
-
-typedef enum NotifyAccess {
- NOTIFY_NONE,
- NOTIFY_ALL,
- NOTIFY_MAIN,
- _NOTIFY_ACCESS_MAX,
- _NOTIFY_ACCESS_INVALID = -1
-} NotifyAccess;
-
-typedef enum ServiceResult {
- SERVICE_SUCCESS,
- SERVICE_FAILURE_RESOURCES,
- SERVICE_FAILURE_TIMEOUT,
- SERVICE_FAILURE_EXIT_CODE,
- SERVICE_FAILURE_SIGNAL,
- SERVICE_FAILURE_CORE_DUMP,
- SERVICE_FAILURE_WATCHDOG,
- SERVICE_FAILURE_START_LIMIT,
- _SERVICE_RESULT_MAX,
- _SERVICE_RESULT_INVALID = -1
-} ServiceResult;
-
-typedef enum StartLimitAction {
- SERVICE_START_LIMIT_NONE,
- SERVICE_START_LIMIT_REBOOT,
- SERVICE_START_LIMIT_REBOOT_FORCE,
- SERVICE_START_LIMIT_REBOOT_IMMEDIATE,
- _SERVICE_START_LIMIT_MAX,
- _SERVICE_START_LIMIT_INVALID = -1
-} StartLimitAction;
-
-struct Service {
- Unit meta;
-
- ServiceType type;
- ServiceRestart restart;
- ExitStatusSet restart_ignore_status;
- ExitStatusSet success_status;
-
- /* If set we'll read the main daemon PID from this file */
- char *pid_file;
-
- usec_t restart_usec;
- usec_t timeout_start_usec;
- usec_t timeout_stop_usec;
-
- dual_timestamp watchdog_timestamp;
- usec_t watchdog_usec;
- Watch watchdog_watch;
-
- ExecCommand* exec_command[_SERVICE_EXEC_COMMAND_MAX];
-
- ExecContext exec_context;
- KillContext kill_context;
-
- ServiceState state, deserialized_state;
-
- /* The exit status of the real main process */
- ExecStatus main_exec_status;
-
- /* The currently executed control process */
- ExecCommand *control_command;
-
- /* The currently executed main process, which may be NULL if
- * the main process got started via forking mode and not by
- * us */
- ExecCommand *main_command;
-
- /* The ID of the control command currently being executed */
- ServiceExecCommand control_command_id;
-
- pid_t main_pid, control_pid;
- int socket_fd;
-
- int fsck_passno;
-
- bool permissions_start_only;
- bool root_directory_start_only;
- bool remain_after_exit;
- bool guess_main_pid;
-
- /* If we shut down, remember why */
- ServiceResult result;
- ServiceResult reload_result;
-
- bool main_pid_known:1;
- bool main_pid_alien:1;
- bool bus_name_good:1;
- bool forbid_restart:1;
- bool got_socket_fd:1;
- bool start_timeout_defined:1;
-#ifdef HAVE_SYSV_COMPAT
- bool is_sysv:1;
- bool sysv_has_lsb:1;
- bool sysv_enabled:1;
- int sysv_start_priority_from_rcnd;
- int sysv_start_priority;
-
- char *sysv_runlevels;
-#endif
-
- char *bus_name;
-
- char *status_text;
-
- RateLimit start_limit;
- StartLimitAction start_limit_action;
-
- UnitRef accept_socket;
-
- Watch timer_watch;
- PathSpec *pid_file_pathspec;
-
- NotifyAccess notify_access;
-};
-
-extern const UnitVTable service_vtable;
-
-struct Socket;
-
-int service_set_socket_fd(Service *s, int fd, struct Socket *socket);
-
-const char* service_state_to_string(ServiceState i);
-ServiceState service_state_from_string(const char *s);
-
-const char* service_restart_to_string(ServiceRestart i);
-ServiceRestart service_restart_from_string(const char *s);
-
-const char* service_type_to_string(ServiceType i);
-ServiceType service_type_from_string(const char *s);
-
-const char* service_exec_command_to_string(ServiceExecCommand i);
-ServiceExecCommand service_exec_command_from_string(const char *s);
-
-const char* notify_access_to_string(NotifyAccess i);
-NotifyAccess notify_access_from_string(const char *s);
-
-const char* service_result_to_string(ServiceResult i);
-ServiceResult service_result_from_string(const char *s);
-
-const char* start_limit_action_to_string(StartLimitAction i);
-StartLimitAction start_limit_action_from_string(const char *s);
diff --git a/src/core/shutdown.c b/src/core/shutdown.c
deleted file mode 100644
index cc8c57bd2d..0000000000
--- a/src/core/shutdown.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010 ProFUSION embedded systems
-
- 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/mman.h>
-#include <sys/types.h>
-#include <sys/reboot.h>
-#include <linux/reboot.h>
-#include <sys/wait.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mount.h>
-#include <sys/syscall.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <errno.h>
-#include <unistd.h>
-#include <signal.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "missing.h"
-#include "log.h"
-#include "umount.h"
-#include "util.h"
-#include "mkdir.h"
-#include "virt.h"
-#include "watchdog.h"
-#include "killall.h"
-
-#define FINALIZE_ATTEMPTS 50
-
-static int prepare_new_root(void) {
- static const char dirs[] =
- "/run/initramfs/oldroot\0"
- "/run/initramfs/proc\0"
- "/run/initramfs/sys\0"
- "/run/initramfs/dev\0"
- "/run/initramfs/run\0";
-
- const char *dir;
-
- if (mount("/run/initramfs", "/run/initramfs", NULL, MS_BIND, NULL) < 0) {
- log_error("Failed to mount bind /run/initramfs on /run/initramfs: %m");
- return -errno;
- }
-
- if (mount(NULL, "/run/initramfs", NULL, MS_PRIVATE, NULL) < 0) {
- log_error("Failed to make /run/initramfs private mount: %m");
- return -errno;
- }
-
- NULSTR_FOREACH(dir, dirs)
- if (mkdir_p_label(dir, 0755) < 0 && errno != EEXIST) {
- log_error("Failed to mkdir %s: %m", dir);
- return -errno;
- }
-
- if (mount("/sys", "/run/initramfs/sys", NULL, MS_BIND, NULL) < 0) {
- log_error("Failed to mount bind /sys on /run/initramfs/sys: %m");
- return -errno;
- }
-
- if (mount("/proc", "/run/initramfs/proc", NULL, MS_BIND, NULL) < 0) {
- log_error("Failed to mount bind /proc on /run/initramfs/proc: %m");
- return -errno;
- }
-
- if (mount("/dev", "/run/initramfs/dev", NULL, MS_BIND, NULL) < 0) {
- log_error("Failed to mount bind /dev on /run/initramfs/dev: %m");
- return -errno;
- }
-
- if (mount("/run", "/run/initramfs/run", NULL, MS_BIND, NULL) < 0) {
- log_error("Failed to mount bind /run on /run/initramfs/run: %m");
- return -errno;
- }
-
- return 0;
-}
-
-static int pivot_to_new_root(void) {
-
- if (chdir("/run/initramfs") < 0) {
- log_error("Failed to change directory to /run/initramfs: %m");
- return -errno;
- }
-
- /* Work-around for a kernel bug: for some reason the kernel
- * refuses switching root if any file systems are mounted
- * MS_SHARED. Hence remount them MS_PRIVATE here as a
- * work-around.
- *
- * https://bugzilla.redhat.com/show_bug.cgi?id=847418 */
- if (mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL) < 0)
- log_warning("Failed to make \"/\" private mount: %m");
-
- if (pivot_root(".", "oldroot") < 0) {
- log_error("pivot failed: %m");
- /* only chroot if pivot root succeeded */
- return -errno;
- }
-
- chroot(".");
-
- setsid();
- make_console_stdio();
-
- log_info("Successfully changed into root pivot.");
-
- return 0;
-}
-
-int main(int argc, char *argv[]) {
- int cmd, r;
- unsigned retries;
- bool need_umount = true, need_swapoff = true, need_loop_detach = true, need_dm_detach = true;
- bool in_container, use_watchdog = false;
- char *arguments[3];
-
- log_parse_environment();
- log_set_target(LOG_TARGET_CONSOLE); /* syslog will die if not gone yet */
- log_open();
-
- umask(0022);
-
- if (getpid() != 1) {
- log_error("Not executed by init (pid 1).");
- r = -EPERM;
- goto error;
- }
-
- if (argc != 2) {
- log_error("Invalid number of arguments.");
- r = -EINVAL;
- goto error;
- }
-
- in_container = detect_container(NULL) > 0;
-
- if (streq(argv[1], "reboot"))
- cmd = RB_AUTOBOOT;
- else if (streq(argv[1], "poweroff"))
- cmd = RB_POWER_OFF;
- else if (streq(argv[1], "halt"))
- cmd = RB_HALT_SYSTEM;
- else if (streq(argv[1], "kexec"))
- cmd = LINUX_REBOOT_CMD_KEXEC;
- else {
- log_error("Unknown action '%s'.", argv[1]);
- r = -EINVAL;
- goto error;
- }
-
- use_watchdog = !!getenv("WATCHDOG_USEC");
-
- /* lock us into memory */
- mlockall(MCL_CURRENT|MCL_FUTURE);
-
- log_info("Sending SIGTERM to remaining processes...");
- broadcast_signal(SIGTERM, true);
-
- log_info("Sending SIGKILL to remaining processes...");
- broadcast_signal(SIGKILL, true);
-
- if (in_container) {
- need_swapoff = false;
- need_dm_detach = false;
- need_loop_detach = false;
- }
-
- /* Unmount all mountpoints, swaps, and loopback devices */
- for (retries = 0; retries < FINALIZE_ATTEMPTS; retries++) {
- bool changed = false;
-
- if (use_watchdog)
- watchdog_ping();
-
- if (need_umount) {
- log_info("Unmounting file systems.");
- r = umount_all(&changed);
- if (r == 0)
- need_umount = false;
- else if (r > 0)
- log_info("Not all file systems unmounted, %d left.", r);
- else
- log_error("Failed to unmount file systems: %s", strerror(-r));
- }
-
- if (need_swapoff) {
- log_info("Disabling swaps.");
- r = swapoff_all(&changed);
- if (r == 0)
- need_swapoff = false;
- else if (r > 0)
- log_info("Not all swaps are turned off, %d left.", r);
- else
- log_error("Failed to turn off swaps: %s", strerror(-r));
- }
-
- if (need_loop_detach) {
- log_info("Detaching loop devices.");
- r = loopback_detach_all(&changed);
- if (r == 0)
- need_loop_detach = false;
- else if (r > 0)
- log_info("Not all loop devices detached, %d left.", r);
- else
- log_error("Failed to detach loop devices: %s", strerror(-r));
- }
-
- if (need_dm_detach) {
- log_info("Detaching DM devices.");
- r = dm_detach_all(&changed);
- if (r == 0)
- need_dm_detach = false;
- else if (r > 0)
- log_warning("Not all DM devices detached, %d left.", r);
- else
- log_error("Failed to detach DM devices: %s", strerror(-r));
- }
-
- if (!need_umount && !need_swapoff && !need_loop_detach && !need_dm_detach) {
- if (retries > 0)
- log_info("All filesystems, swaps, loop devices, DM devices detached.");
- /* Yay, done */
- break;
- }
-
- /* If in this iteration we didn't manage to
- * unmount/deactivate anything, we simply give up */
- if (!changed) {
- log_error("Cannot finalize remaining file systems and devices, giving up.");
- break;
- }
-
- log_debug("Couldn't finalize remaining file systems and devices after %u retries, trying again.", retries+1);
- }
-
- if (retries >= FINALIZE_ATTEMPTS)
- log_error("Too many iterations, giving up.");
-
- arguments[0] = NULL;
- arguments[1] = argv[1];
- arguments[2] = NULL;
- execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, arguments);
-
- if (!in_container &&
- access("/run/initramfs/shutdown", X_OK) == 0) {
-
- if (prepare_new_root() >= 0 &&
- pivot_to_new_root() >= 0) {
- execv("/shutdown", argv);
- log_error("Failed to execute shutdown binary: %m");
- }
- }
-
- if (cmd == LINUX_REBOOT_CMD_KEXEC) {
-
- if (!in_container) {
- /* We cheat and exec kexec to avoid doing all its work */
- pid_t pid = fork();
-
- if (pid < 0)
- log_error("Could not fork: %m. Falling back to normal reboot.");
- else if (pid > 0) {
- wait_for_terminate_and_warn("kexec", pid);
- log_warning("kexec failed. Falling back to normal reboot.");
- } else {
- /* Child */
- const char *args[3] = { "/sbin/kexec", "-e", NULL };
- execv(args[0], (char * const *) args);
- return EXIT_FAILURE;
- }
- }
-
- cmd = RB_AUTOBOOT;
- }
-
- reboot(cmd);
-
- if (errno == EPERM && in_container) {
- /* If we are in a container, and we lacked
- * CAP_SYS_BOOT just exit, this will kill our
- * container for good. */
- log_error("Exiting container.");
- exit(0);
- }
-
- log_error("Failed to invoke reboot(): %m");
- r = -errno;
-
- error:
- log_error("Critical error while doing system shutdown: %s", strerror(-r));
-
- freeze();
- return EXIT_FAILURE;
-}
diff --git a/src/core/snapshot.c b/src/core/snapshot.c
deleted file mode 100644
index 5c2a319cb6..0000000000
--- a/src/core/snapshot.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/*-*- 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 <errno.h>
-
-#include "unit.h"
-#include "snapshot.h"
-#include "unit-name.h"
-#include "dbus-snapshot.h"
-#include "bus-errors.h"
-
-static const UnitActiveState state_translation_table[_SNAPSHOT_STATE_MAX] = {
- [SNAPSHOT_DEAD] = UNIT_INACTIVE,
- [SNAPSHOT_ACTIVE] = UNIT_ACTIVE
-};
-
-static void snapshot_init(Unit *u) {
- Snapshot *s = SNAPSHOT(u);
-
- assert(s);
- assert(UNIT(s)->load_state == UNIT_STUB);
-
- UNIT(s)->ignore_on_isolate = true;
- UNIT(s)->ignore_on_snapshot = true;
-}
-
-static void snapshot_set_state(Snapshot *s, SnapshotState state) {
- SnapshotState old_state;
- assert(s);
-
- old_state = s->state;
- s->state = state;
-
- if (state != old_state)
- log_debug("%s changed %s -> %s",
- UNIT(s)->id,
- snapshot_state_to_string(old_state),
- snapshot_state_to_string(state));
-
- unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true);
-}
-
-static int snapshot_load(Unit *u) {
- Snapshot *s = SNAPSHOT(u);
-
- assert(u);
- assert(u->load_state == UNIT_STUB);
-
- /* Make sure that only snapshots created via snapshot_create()
- * can be loaded */
- if (!s->by_snapshot_create && UNIT(s)->manager->n_reloading <= 0)
- return -ENOENT;
-
- u->load_state = UNIT_LOADED;
- return 0;
-}
-
-static int snapshot_coldplug(Unit *u) {
- Snapshot *s = SNAPSHOT(u);
-
- assert(s);
- assert(s->state == SNAPSHOT_DEAD);
-
- if (s->deserialized_state != s->state)
- snapshot_set_state(s, s->deserialized_state);
-
- return 0;
-}
-
-static void snapshot_dump(Unit *u, FILE *f, const char *prefix) {
- Snapshot *s = SNAPSHOT(u);
-
- assert(s);
- assert(f);
-
- fprintf(f,
- "%sSnapshot State: %s\n"
- "%sClean Up: %s\n",
- prefix, snapshot_state_to_string(s->state),
- prefix, yes_no(s->cleanup));
-}
-
-static int snapshot_start(Unit *u) {
- Snapshot *s = SNAPSHOT(u);
-
- assert(s);
- assert(s->state == SNAPSHOT_DEAD);
-
- snapshot_set_state(s, SNAPSHOT_ACTIVE);
-
- if (s->cleanup)
- unit_add_to_cleanup_queue(u);
-
- return 0;
-}
-
-static int snapshot_stop(Unit *u) {
- Snapshot *s = SNAPSHOT(u);
-
- assert(s);
- assert(s->state == SNAPSHOT_ACTIVE);
-
- snapshot_set_state(s, SNAPSHOT_DEAD);
- return 0;
-}
-
-static int snapshot_serialize(Unit *u, FILE *f, FDSet *fds) {
- Snapshot *s = SNAPSHOT(u);
- Unit *other;
- Iterator i;
-
- assert(s);
- assert(f);
- assert(fds);
-
- unit_serialize_item(u, f, "state", snapshot_state_to_string(s->state));
- unit_serialize_item(u, f, "cleanup", yes_no(s->cleanup));
- SET_FOREACH(other, u->dependencies[UNIT_WANTS], i)
- unit_serialize_item(u, f, "wants", other->id);
-
- return 0;
-}
-
-static int snapshot_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
- Snapshot *s = SNAPSHOT(u);
- int r;
-
- assert(u);
- assert(key);
- assert(value);
- assert(fds);
-
- if (streq(key, "state")) {
- SnapshotState state;
-
- if ((state = snapshot_state_from_string(value)) < 0)
- log_debug("Failed to parse state value %s", value);
- else
- s->deserialized_state = state;
-
- } else if (streq(key, "cleanup")) {
-
- if ((r = parse_boolean(value)) < 0)
- log_debug("Failed to parse cleanup value %s", value);
- else
- s->cleanup = r;
-
- } else if (streq(key, "wants")) {
-
- if ((r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_WANTS, value, NULL, true)) < 0)
- return r;
- } else
- log_debug("Unknown serialization key '%s'", key);
-
- return 0;
-}
-
-static UnitActiveState snapshot_active_state(Unit *u) {
- assert(u);
-
- return state_translation_table[SNAPSHOT(u)->state];
-}
-
-static const char *snapshot_sub_state_to_string(Unit *u) {
- assert(u);
-
- return snapshot_state_to_string(SNAPSHOT(u)->state);
-}
-
-int snapshot_create(Manager *m, const char *name, bool cleanup, DBusError *e, Snapshot **_s) {
- Iterator i;
- Unit *other, *u = NULL;
- char *n = NULL;
- int r;
- const char *k;
-
- assert(m);
- assert(_s);
-
- if (name) {
- if (!unit_name_is_valid(name, false)) {
- dbus_set_error(e, BUS_ERROR_INVALID_NAME, "Unit name %s is not valid.", name);
- return -EINVAL;
- }
-
- if (unit_name_to_type(name) != UNIT_SNAPSHOT) {
- dbus_set_error(e, BUS_ERROR_UNIT_TYPE_MISMATCH, "Unit name %s lacks snapshot suffix.", name);
- return -EINVAL;
- }
-
- if (manager_get_unit(m, name)) {
- dbus_set_error(e, BUS_ERROR_UNIT_EXISTS, "Snapshot %s exists already.", name);
- return -EEXIST;
- }
-
- } else {
-
- for (;;) {
- if (asprintf(&n, "snapshot-%u.snapshot", ++ m->n_snapshots) < 0)
- return -ENOMEM;
-
- if (!manager_get_unit(m, n))
- break;
-
- free(n);
- }
-
- name = n;
- }
-
- r = manager_load_unit_prepare(m, name, NULL, e, &u);
- free(n);
-
- if (r < 0)
- goto fail;
-
- SNAPSHOT(u)->by_snapshot_create = true;
- manager_dispatch_load_queue(m);
- assert(u->load_state == UNIT_LOADED);
-
- HASHMAP_FOREACH_KEY(other, k, m->units, i) {
-
- if (other->ignore_on_snapshot)
- continue;
-
- if (k != other->id)
- continue;
-
- if (UNIT_VTABLE(other)->check_snapshot)
- if (!UNIT_VTABLE(other)->check_snapshot(other))
- continue;
-
- if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
- continue;
-
- if ((r = unit_add_two_dependencies(u, UNIT_AFTER, UNIT_WANTS, other, true)) < 0)
- goto fail;
- }
-
- SNAPSHOT(u)->cleanup = cleanup;
- *_s = SNAPSHOT(u);
-
- return 0;
-
-fail:
- if (u)
- unit_add_to_cleanup_queue(u);
-
- return r;
-}
-
-void snapshot_remove(Snapshot *s) {
- assert(s);
-
- unit_add_to_cleanup_queue(UNIT(s));
-}
-
-static const char* const snapshot_state_table[_SNAPSHOT_STATE_MAX] = {
- [SNAPSHOT_DEAD] = "dead",
- [SNAPSHOT_ACTIVE] = "active"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(snapshot_state, SnapshotState);
-
-const UnitVTable snapshot_vtable = {
- .object_size = sizeof(Snapshot),
-
- .no_alias = true,
- .no_instances = true,
- .no_gc = true,
-
- .init = snapshot_init,
-
- .load = snapshot_load,
- .coldplug = snapshot_coldplug,
-
- .dump = snapshot_dump,
-
- .start = snapshot_start,
- .stop = snapshot_stop,
-
- .serialize = snapshot_serialize,
- .deserialize_item = snapshot_deserialize_item,
-
- .active_state = snapshot_active_state,
- .sub_state_to_string = snapshot_sub_state_to_string,
-
- .bus_interface = "org.freedesktop.systemd1.Snapshot",
- .bus_message_handler = bus_snapshot_message_handler
-};
diff --git a/src/core/snapshot.h b/src/core/snapshot.h
deleted file mode 100644
index 9662d93164..0000000000
--- a/src/core/snapshot.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*-*- 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/>.
-***/
-
-typedef struct Snapshot Snapshot;
-
-#include "unit.h"
-
-typedef enum SnapshotState {
- SNAPSHOT_DEAD,
- SNAPSHOT_ACTIVE,
- _SNAPSHOT_STATE_MAX,
- _SNAPSHOT_STATE_INVALID = -1
-} SnapshotState;
-
-struct Snapshot {
- Unit meta;
-
- SnapshotState state, deserialized_state;
-
- bool cleanup;
- bool by_snapshot_create:1;
-};
-
-extern const UnitVTable snapshot_vtable;
-
-int snapshot_create(Manager *m, const char *name, bool cleanup, DBusError *e, Snapshot **s);
-void snapshot_remove(Snapshot *s);
-
-const char* snapshot_state_to_string(SnapshotState i);
-SnapshotState snapshot_state_from_string(const char *s);
diff --git a/src/core/socket.c b/src/core/socket.c
deleted file mode 100644
index c0959815c1..0000000000
--- a/src/core/socket.c
+++ /dev/null
@@ -1,2289 +0,0 @@
-/*-*- 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/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/epoll.h>
-#include <signal.h>
-#include <arpa/inet.h>
-#include <mqueue.h>
-#include <attr/xattr.h>
-
-#include "unit.h"
-#include "socket.h"
-#include "netinet/tcp.h"
-#include "log.h"
-#include "load-dropin.h"
-#include "load-fragment.h"
-#include "strv.h"
-#include "mkdir.h"
-#include "path-util.h"
-#include "unit-name.h"
-#include "unit-printf.h"
-#include "dbus-socket.h"
-#include "missing.h"
-#include "special.h"
-#include "bus-errors.h"
-#include "label.h"
-#include "exit-status.h"
-#include "def.h"
-
-static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
- [SOCKET_DEAD] = UNIT_INACTIVE,
- [SOCKET_START_PRE] = UNIT_ACTIVATING,
- [SOCKET_START_POST] = UNIT_ACTIVATING,
- [SOCKET_LISTENING] = UNIT_ACTIVE,
- [SOCKET_RUNNING] = UNIT_ACTIVE,
- [SOCKET_STOP_PRE] = UNIT_DEACTIVATING,
- [SOCKET_STOP_PRE_SIGTERM] = UNIT_DEACTIVATING,
- [SOCKET_STOP_PRE_SIGKILL] = UNIT_DEACTIVATING,
- [SOCKET_STOP_POST] = UNIT_DEACTIVATING,
- [SOCKET_FINAL_SIGTERM] = UNIT_DEACTIVATING,
- [SOCKET_FINAL_SIGKILL] = UNIT_DEACTIVATING,
- [SOCKET_FAILED] = UNIT_FAILED
-};
-
-static void socket_init(Unit *u) {
- Socket *s = SOCKET(u);
-
- assert(u);
- assert(u->load_state == UNIT_STUB);
-
- s->backlog = SOMAXCONN;
- s->timeout_usec = DEFAULT_TIMEOUT_USEC;
- s->directory_mode = 0755;
- s->socket_mode = 0666;
-
- s->max_connections = 64;
-
- s->priority = -1;
- s->ip_tos = -1;
- s->ip_ttl = -1;
- s->mark = -1;
-
- exec_context_init(&s->exec_context);
- s->exec_context.std_output = u->manager->default_std_output;
- s->exec_context.std_error = u->manager->default_std_error;
- kill_context_init(&s->kill_context);
-
- s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID;
-}
-
-static void socket_unwatch_control_pid(Socket *s) {
- assert(s);
-
- if (s->control_pid <= 0)
- return;
-
- unit_unwatch_pid(UNIT(s), s->control_pid);
- s->control_pid = 0;
-}
-
-static void socket_done(Unit *u) {
- Socket *s = SOCKET(u);
- SocketPort *p;
-
- assert(s);
-
- while ((p = s->ports)) {
- LIST_REMOVE(SocketPort, port, s->ports, p);
-
- if (p->fd >= 0) {
- unit_unwatch_fd(UNIT(s), &p->fd_watch);
- close_nointr_nofail(p->fd);
- }
-
- free(p->path);
- free(p);
- }
-
- exec_context_done(&s->exec_context);
- exec_command_free_array(s->exec_command, _SOCKET_EXEC_COMMAND_MAX);
- s->control_command = NULL;
-
- socket_unwatch_control_pid(s);
-
- unit_ref_unset(&s->service);
-
- free(s->tcp_congestion);
- s->tcp_congestion = NULL;
-
- free(s->bind_to_device);
- s->bind_to_device = NULL;
-
- free(s->smack);
- free(s->smack_ip_in);
- free(s->smack_ip_out);
-
- unit_unwatch_timer(u, &s->timer_watch);
-}
-
-static int socket_instantiate_service(Socket *s) {
- char *prefix, *name;
- int r;
- Unit *u;
-
- assert(s);
-
- /* This fills in s->service if it isn't filled in yet. For
- * Accept=yes sockets we create the next connection service
- * here. For Accept=no this is mostly a NOP since the service
- * is figured out at load time anyway. */
-
- if (UNIT_DEREF(s->service))
- return 0;
-
- assert(s->accept);
-
- if (!(prefix = unit_name_to_prefix(UNIT(s)->id)))
- return -ENOMEM;
-
- r = asprintf(&name, "%s@%u.service", prefix, s->n_accepted);
- free(prefix);
-
- if (r < 0)
- return -ENOMEM;
-
- r = manager_load_unit(UNIT(s)->manager, name, NULL, NULL, &u);
- free(name);
-
- if (r < 0)
- return r;
-
-#ifdef HAVE_SYSV_COMPAT
- if (SERVICE(u)->is_sysv) {
- log_error("Using SysV services for socket activation is not supported. Refusing.");
- return -ENOENT;
- }
-#endif
-
- u->no_gc = true;
- unit_ref_set(&s->service, u);
-
- return unit_add_two_dependencies(UNIT(s), UNIT_BEFORE, UNIT_TRIGGERS, u, false);
-}
-
-static bool have_non_accept_socket(Socket *s) {
- SocketPort *p;
-
- assert(s);
-
- if (!s->accept)
- return true;
-
- LIST_FOREACH(port, p, s->ports) {
-
- if (p->type != SOCKET_SOCKET)
- return true;
-
- if (!socket_address_can_accept(&p->address))
- return true;
- }
-
- return false;
-}
-
-static int socket_verify(Socket *s) {
- assert(s);
-
- if (UNIT(s)->load_state != UNIT_LOADED)
- return 0;
-
- if (!s->ports) {
- log_error("%s lacks Listen setting. Refusing.", UNIT(s)->id);
- return -EINVAL;
- }
-
- if (s->accept && have_non_accept_socket(s)) {
- log_error("%s configured for accepting sockets, but sockets are non-accepting. Refusing.", UNIT(s)->id);
- return -EINVAL;
- }
-
- if (s->accept && s->max_connections <= 0) {
- log_error("%s's MaxConnection setting too small. Refusing.", UNIT(s)->id);
- return -EINVAL;
- }
-
- if (s->accept && UNIT_DEREF(s->service)) {
- log_error("Explicit service configuration for accepting sockets not supported on %s. Refusing.", UNIT(s)->id);
- return -EINVAL;
- }
-
- if (s->exec_context.pam_name && s->kill_context.kill_mode != KILL_CONTROL_GROUP) {
- log_error("%s has PAM enabled. Kill mode must be set to 'control-group'. Refusing.", UNIT(s)->id);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static bool socket_needs_mount(Socket *s, const char *prefix) {
- SocketPort *p;
-
- assert(s);
-
- LIST_FOREACH(port, p, s->ports) {
-
- if (p->type == SOCKET_SOCKET) {
- if (socket_address_needs_mount(&p->address, prefix))
- return true;
- } else if (p->type == SOCKET_FIFO || p->type == SOCKET_SPECIAL) {
- if (path_startswith(p->path, prefix))
- return true;
- }
- }
-
- return false;
-}
-
-int socket_add_one_mount_link(Socket *s, Mount *m) {
- int r;
-
- assert(s);
- assert(m);
-
- if (UNIT(s)->load_state != UNIT_LOADED ||
- UNIT(m)->load_state != UNIT_LOADED)
- return 0;
-
- if (!socket_needs_mount(s, m->where))
- return 0;
-
- r = unit_add_two_dependencies(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static int socket_add_mount_links(Socket *s) {
- Unit *other;
- int r;
-
- assert(s);
-
- LIST_FOREACH(units_by_type, other, UNIT(s)->manager->units_by_type[UNIT_MOUNT]) {
- r = socket_add_one_mount_link(s, MOUNT(other));
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-static int socket_add_device_link(Socket *s) {
- char *t;
- int r;
-
- assert(s);
-
- if (!s->bind_to_device)
- return 0;
-
- if (asprintf(&t, "/sys/subsystem/net/devices/%s", s->bind_to_device) < 0)
- return -ENOMEM;
-
- r = unit_add_node_link(UNIT(s), t, false);
- free(t);
-
- return r;
-}
-
-static int socket_add_default_dependencies(Socket *s) {
- int r;
- assert(s);
-
- if (UNIT(s)->manager->running_as == SYSTEMD_SYSTEM) {
- if ((r = unit_add_dependency_by_name(UNIT(s), UNIT_BEFORE, SPECIAL_SOCKETS_TARGET, NULL, true)) < 0)
- return r;
-
- if ((r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true)) < 0)
- return r;
- }
-
- return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
-}
-
-static bool socket_has_exec(Socket *s) {
- unsigned i;
- assert(s);
-
- for (i = 0; i < _SOCKET_EXEC_COMMAND_MAX; i++)
- if (s->exec_command[i])
- return true;
-
- return false;
-}
-
-static int socket_load(Unit *u) {
- Socket *s = SOCKET(u);
- int r;
-
- assert(u);
- assert(u->load_state == UNIT_STUB);
-
- if ((r = unit_load_fragment_and_dropin(u)) < 0)
- return r;
-
- /* This is a new unit? Then let's add in some extras */
- if (u->load_state == UNIT_LOADED) {
-
- if (have_non_accept_socket(s)) {
-
- if (!UNIT_DEREF(s->service)) {
- Unit *x;
-
- r = unit_load_related_unit(u, ".service", &x);
- if (r < 0)
- return r;
-
- unit_ref_set(&s->service, x);
- }
-
- r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(s->service), true);
- if (r < 0)
- return r;
- }
-
- if ((r = socket_add_mount_links(s)) < 0)
- return r;
-
- if ((r = socket_add_device_link(s)) < 0)
- return r;
-
- if (socket_has_exec(s))
- if ((r = unit_add_exec_dependencies(u, &s->exec_context)) < 0)
- return r;
-
- if ((r = unit_add_default_cgroups(u)) < 0)
- return r;
-
- if (UNIT(s)->default_dependencies)
- if ((r = socket_add_default_dependencies(s)) < 0)
- return r;
-
- r = unit_exec_context_defaults(u, &s->exec_context);
- if (r < 0)
- return r;
- }
-
- return socket_verify(s);
-}
-
-static const char* listen_lookup(int family, int type) {
-
- if (family == AF_NETLINK)
- return "ListenNetlink";
-
- if (type == SOCK_STREAM)
- return "ListenStream";
- else if (type == SOCK_DGRAM)
- return "ListenDatagram";
- else if (type == SOCK_SEQPACKET)
- return "ListenSequentialPacket";
-
- assert_not_reached("Unknown socket type");
- return NULL;
-}
-
-static void socket_dump(Unit *u, FILE *f, const char *prefix) {
-
- SocketExecCommand c;
- Socket *s = SOCKET(u);
- SocketPort *p;
- const char *prefix2;
- char *p2;
-
- assert(s);
- assert(f);
-
- p2 = strappend(prefix, "\t");
- prefix2 = p2 ? p2 : prefix;
-
- fprintf(f,
- "%sSocket State: %s\n"
- "%sResult: %s\n"
- "%sBindIPv6Only: %s\n"
- "%sBacklog: %u\n"
- "%sSocketMode: %04o\n"
- "%sDirectoryMode: %04o\n"
- "%sKeepAlive: %s\n"
- "%sFreeBind: %s\n"
- "%sTransparent: %s\n"
- "%sBroadcast: %s\n"
- "%sPassCredentials: %s\n"
- "%sPassSecurity: %s\n"
- "%sTCPCongestion: %s\n",
- prefix, socket_state_to_string(s->state),
- prefix, socket_result_to_string(s->result),
- prefix, socket_address_bind_ipv6_only_to_string(s->bind_ipv6_only),
- prefix, s->backlog,
- prefix, s->socket_mode,
- prefix, s->directory_mode,
- prefix, yes_no(s->keep_alive),
- prefix, yes_no(s->free_bind),
- prefix, yes_no(s->transparent),
- prefix, yes_no(s->broadcast),
- prefix, yes_no(s->pass_cred),
- prefix, yes_no(s->pass_sec),
- prefix, strna(s->tcp_congestion));
-
- if (s->control_pid > 0)
- fprintf(f,
- "%sControl PID: %lu\n",
- prefix, (unsigned long) s->control_pid);
-
- if (s->bind_to_device)
- fprintf(f,
- "%sBindToDevice: %s\n",
- prefix, s->bind_to_device);
-
- if (s->accept)
- fprintf(f,
- "%sAccepted: %u\n"
- "%sNConnections: %u\n"
- "%sMaxConnections: %u\n",
- prefix, s->n_accepted,
- prefix, s->n_connections,
- prefix, s->max_connections);
-
- if (s->priority >= 0)
- fprintf(f,
- "%sPriority: %i\n",
- prefix, s->priority);
-
- if (s->receive_buffer > 0)
- fprintf(f,
- "%sReceiveBuffer: %zu\n",
- prefix, s->receive_buffer);
-
- if (s->send_buffer > 0)
- fprintf(f,
- "%sSendBuffer: %zu\n",
- prefix, s->send_buffer);
-
- if (s->ip_tos >= 0)
- fprintf(f,
- "%sIPTOS: %i\n",
- prefix, s->ip_tos);
-
- if (s->ip_ttl >= 0)
- fprintf(f,
- "%sIPTTL: %i\n",
- prefix, s->ip_ttl);
-
- if (s->pipe_size > 0)
- fprintf(f,
- "%sPipeSize: %zu\n",
- prefix, s->pipe_size);
-
- if (s->mark >= 0)
- fprintf(f,
- "%sMark: %i\n",
- prefix, s->mark);
-
- if (s->mq_maxmsg > 0)
- fprintf(f,
- "%sMessageQueueMaxMessages: %li\n",
- prefix, s->mq_maxmsg);
-
- if (s->mq_msgsize > 0)
- fprintf(f,
- "%sMessageQueueMessageSize: %li\n",
- prefix, s->mq_msgsize);
-
- if (s->smack)
- fprintf(f,
- "%sSmackLabel: %s\n",
- prefix, s->smack);
-
- if (s->smack_ip_in)
- fprintf(f,
- "%sSmackLabelIPIn: %s\n",
- prefix, s->smack_ip_in);
-
- if (s->smack_ip_out)
- fprintf(f,
- "%sSmackLabelIPOut: %s\n",
- prefix, s->smack_ip_out);
-
- LIST_FOREACH(port, p, s->ports) {
-
- if (p->type == SOCKET_SOCKET) {
- const char *t;
- int r;
- char *k = NULL;
-
- if ((r = socket_address_print(&p->address, &k)) < 0)
- t = strerror(-r);
- else
- t = k;
-
- fprintf(f, "%s%s: %s\n", prefix, listen_lookup(socket_address_family(&p->address), p->address.type), t);
- free(k);
- } else if (p->type == SOCKET_SPECIAL)
- fprintf(f, "%sListenSpecial: %s\n", prefix, p->path);
- else if (p->type == SOCKET_MQUEUE)
- fprintf(f, "%sListenMessageQueue: %s\n", prefix, p->path);
- else
- fprintf(f, "%sListenFIFO: %s\n", prefix, p->path);
- }
-
- exec_context_dump(&s->exec_context, f, prefix);
- kill_context_dump(&s->kill_context, f, prefix);
-
- for (c = 0; c < _SOCKET_EXEC_COMMAND_MAX; c++) {
- if (!s->exec_command[c])
- continue;
-
- fprintf(f, "%s-> %s:\n",
- prefix, socket_exec_command_to_string(c));
-
- exec_command_dump_list(s->exec_command[c], f, prefix2);
- }
-
- free(p2);
-}
-
-static int instance_from_socket(int fd, unsigned nr, char **instance) {
- socklen_t l;
- char *r;
- union {
- struct sockaddr sa;
- struct sockaddr_un un;
- struct sockaddr_in in;
- struct sockaddr_in6 in6;
- struct sockaddr_storage storage;
- } local, remote;
-
- assert(fd >= 0);
- assert(instance);
-
- l = sizeof(local);
- if (getsockname(fd, &local.sa, &l) < 0)
- return -errno;
-
- l = sizeof(remote);
- if (getpeername(fd, &remote.sa, &l) < 0)
- return -errno;
-
- switch (local.sa.sa_family) {
-
- case AF_INET: {
- uint32_t
- a = ntohl(local.in.sin_addr.s_addr),
- b = ntohl(remote.in.sin_addr.s_addr);
-
- if (asprintf(&r,
- "%u-%u.%u.%u.%u:%u-%u.%u.%u.%u:%u",
- nr,
- a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF,
- ntohs(local.in.sin_port),
- b >> 24, (b >> 16) & 0xFF, (b >> 8) & 0xFF, b & 0xFF,
- ntohs(remote.in.sin_port)) < 0)
- return -ENOMEM;
-
- break;
- }
-
- case AF_INET6: {
- static const unsigned char ipv4_prefix[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF
- };
-
- if (memcmp(&local.in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0 &&
- memcmp(&remote.in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0) {
- const uint8_t
- *a = local.in6.sin6_addr.s6_addr+12,
- *b = remote.in6.sin6_addr.s6_addr+12;
-
- if (asprintf(&r,
- "%u-%u.%u.%u.%u:%u-%u.%u.%u.%u:%u",
- nr,
- a[0], a[1], a[2], a[3],
- ntohs(local.in6.sin6_port),
- b[0], b[1], b[2], b[3],
- ntohs(remote.in6.sin6_port)) < 0)
- return -ENOMEM;
- } else {
- char a[INET6_ADDRSTRLEN], b[INET6_ADDRSTRLEN];
-
- if (asprintf(&r,
- "%u-%s:%u-%s:%u",
- nr,
- inet_ntop(AF_INET6, &local.in6.sin6_addr, a, sizeof(a)),
- ntohs(local.in6.sin6_port),
- inet_ntop(AF_INET6, &remote.in6.sin6_addr, b, sizeof(b)),
- ntohs(remote.in6.sin6_port)) < 0)
- return -ENOMEM;
- }
-
- break;
- }
-
- case AF_UNIX: {
- struct ucred ucred;
-
- l = sizeof(ucred);
- if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
- return -errno;
-
- if (asprintf(&r,
- "%u-%lu-%lu",
- nr,
- (unsigned long) ucred.pid,
- (unsigned long) ucred.uid) < 0)
- return -ENOMEM;
-
- break;
- }
-
- default:
- assert_not_reached("Unhandled socket type.");
- }
-
- *instance = r;
- return 0;
-}
-
-static void socket_close_fds(Socket *s) {
- SocketPort *p;
-
- assert(s);
-
- LIST_FOREACH(port, p, s->ports) {
- if (p->fd < 0)
- continue;
-
- unit_unwatch_fd(UNIT(s), &p->fd_watch);
- close_nointr_nofail(p->fd);
-
- /* One little note: we should never delete any sockets
- * in the file system here! After all some other
- * process we spawned might still have a reference of
- * this fd and wants to continue to use it. Therefore
- * we delete sockets in the file system before we
- * create a new one, not after we stopped using
- * one! */
-
- p->fd = -1;
- }
-}
-
-static void socket_apply_socket_options(Socket *s, int fd) {
- assert(s);
- assert(fd >= 0);
-
- if (s->keep_alive) {
- int b = s->keep_alive;
- if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &b, sizeof(b)) < 0)
- log_warning("SO_KEEPALIVE failed: %m");
- }
-
- if (s->broadcast) {
- int one = 1;
- if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one)) < 0)
- log_warning("SO_BROADCAST failed: %m");
- }
-
- if (s->pass_cred) {
- int one = 1;
- if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0)
- log_warning("SO_PASSCRED failed: %m");
- }
-
- if (s->pass_sec) {
- int one = 1;
- if (setsockopt(fd, SOL_SOCKET, SO_PASSSEC, &one, sizeof(one)) < 0)
- log_warning("SO_PASSSEC failed: %m");
- }
-
- if (s->priority >= 0)
- if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &s->priority, sizeof(s->priority)) < 0)
- log_warning("SO_PRIORITY failed: %m");
-
- if (s->receive_buffer > 0) {
- int value = (int) s->receive_buffer;
-
- /* We first try with SO_RCVBUFFORCE, in case we have the perms for that */
-
- if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0)
- if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
- log_warning("SO_RCVBUF failed: %m");
- }
-
- if (s->send_buffer > 0) {
- int value = (int) s->send_buffer;
- if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0)
- if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0)
- log_warning("SO_SNDBUF failed: %m");
- }
-
- if (s->mark >= 0)
- if (setsockopt(fd, SOL_SOCKET, SO_MARK, &s->mark, sizeof(s->mark)) < 0)
- log_warning("SO_MARK failed: %m");
-
- if (s->ip_tos >= 0)
- if (setsockopt(fd, IPPROTO_IP, IP_TOS, &s->ip_tos, sizeof(s->ip_tos)) < 0)
- log_warning("IP_TOS failed: %m");
-
- if (s->ip_ttl >= 0) {
- int r, x;
-
- r = setsockopt(fd, IPPROTO_IP, IP_TTL, &s->ip_ttl, sizeof(s->ip_ttl));
-
- if (socket_ipv6_is_supported())
- x = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &s->ip_ttl, sizeof(s->ip_ttl));
- else {
- x = -1;
- errno = EAFNOSUPPORT;
- }
-
- if (r < 0 && x < 0)
- log_warning("IP_TTL/IPV6_UNICAST_HOPS failed: %m");
- }
-
- if (s->tcp_congestion)
- if (setsockopt(fd, SOL_TCP, TCP_CONGESTION, s->tcp_congestion, strlen(s->tcp_congestion)+1) < 0)
- log_warning("TCP_CONGESTION failed: %m");
-
- if (s->smack_ip_in)
- if (fsetxattr(fd, "security.SMACK64IPIN", s->smack_ip_in, strlen(s->smack_ip_in), 0) < 0)
- log_error("fsetxattr(\"security.SMACK64IPIN\"): %m");
-
- if (s->smack_ip_out)
- if (fsetxattr(fd, "security.SMACK64IPOUT", s->smack_ip_out, strlen(s->smack_ip_out), 0) < 0)
- log_error("fsetxattr(\"security.SMACK64IPOUT\"): %m");
-}
-
-static void socket_apply_fifo_options(Socket *s, int fd) {
- assert(s);
- assert(fd >= 0);
-
- if (s->pipe_size > 0)
- if (fcntl(fd, F_SETPIPE_SZ, s->pipe_size) < 0)
- log_warning("F_SETPIPE_SZ: %m");
-
- if (s->smack)
- if (fsetxattr(fd, "security.SMACK64", s->smack, strlen(s->smack), 0) < 0)
- log_error("fsetxattr(\"security.SMACK64\"): %m");
-}
-
-static int fifo_address_create(
- const char *path,
- mode_t directory_mode,
- mode_t socket_mode,
- int *_fd) {
-
- int fd = -1, r = 0;
- struct stat st;
- mode_t old_mask;
-
- assert(path);
- assert(_fd);
-
- mkdir_parents_label(path, directory_mode);
-
- r = label_context_set(path, S_IFIFO);
- if (r < 0)
- goto fail;
-
- /* Enforce the right access mode for the fifo */
- old_mask = umask(~ socket_mode);
-
- /* Include the original umask in our mask */
- umask(~socket_mode | old_mask);
-
- r = mkfifo(path, socket_mode);
- umask(old_mask);
-
- if (r < 0 && errno != EEXIST) {
- r = -errno;
- goto fail;
- }
-
- if ((fd = open(path, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW)) < 0) {
- r = -errno;
- goto fail;
- }
-
- label_context_clear();
-
- if (fstat(fd, &st) < 0) {
- r = -errno;
- goto fail;
- }
-
- if (!S_ISFIFO(st.st_mode) ||
- (st.st_mode & 0777) != (socket_mode & ~old_mask) ||
- st.st_uid != getuid() ||
- st.st_gid != getgid()) {
-
- r = -EEXIST;
- goto fail;
- }
-
- *_fd = fd;
- return 0;
-
-fail:
- label_context_clear();
-
- if (fd >= 0)
- close_nointr_nofail(fd);
-
- return r;
-}
-
-static int special_address_create(
- const char *path,
- int *_fd) {
-
- int fd = -1, r = 0;
- struct stat st;
-
- assert(path);
- assert(_fd);
-
- if ((fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW)) < 0) {
- r = -errno;
- goto fail;
- }
-
- if (fstat(fd, &st) < 0) {
- r = -errno;
- goto fail;
- }
-
- /* Check whether this is a /proc, /sys or /dev file or char device */
- if (!S_ISREG(st.st_mode) && !S_ISCHR(st.st_mode)) {
- r = -EEXIST;
- goto fail;
- }
-
- *_fd = fd;
- return 0;
-
-fail:
- if (fd >= 0)
- close_nointr_nofail(fd);
-
- return r;
-}
-
-static int mq_address_create(
- const char *path,
- mode_t mq_mode,
- long maxmsg,
- long msgsize,
- int *_fd) {
-
- int fd = -1, r = 0;
- struct stat st;
- mode_t old_mask;
- struct mq_attr _attr, *attr = NULL;
-
- assert(path);
- assert(_fd);
-
- if (maxmsg > 0 && msgsize > 0) {
- zero(_attr);
- _attr.mq_flags = O_NONBLOCK;
- _attr.mq_maxmsg = maxmsg;
- _attr.mq_msgsize = msgsize;
- attr = &_attr;
- }
-
- /* Enforce the right access mode for the mq */
- old_mask = umask(~ mq_mode);
-
- /* Include the original umask in our mask */
- umask(~mq_mode | old_mask);
-
- fd = mq_open(path, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_CREAT, mq_mode, attr);
- umask(old_mask);
-
- if (fd < 0) {
- r = -errno;
- goto fail;
- }
-
- if (fstat(fd, &st) < 0) {
- r = -errno;
- goto fail;
- }
-
- if ((st.st_mode & 0777) != (mq_mode & ~old_mask) ||
- st.st_uid != getuid() ||
- st.st_gid != getgid()) {
-
- r = -EEXIST;
- goto fail;
- }
-
- *_fd = fd;
- return 0;
-
-fail:
- if (fd >= 0)
- close_nointr_nofail(fd);
-
- return r;
-}
-
-static int socket_open_fds(Socket *s) {
- SocketPort *p;
- int r;
- char *label = NULL;
- bool know_label = false;
-
- assert(s);
-
- LIST_FOREACH(port, p, s->ports) {
-
- if (p->fd >= 0)
- continue;
-
- if (p->type == SOCKET_SOCKET) {
-
- if (!know_label) {
-
- if ((r = socket_instantiate_service(s)) < 0)
- return r;
-
- if (UNIT_DEREF(s->service) &&
- SERVICE(UNIT_DEREF(s->service))->exec_command[SERVICE_EXEC_START]) {
- r = label_get_create_label_from_exe(SERVICE(UNIT_DEREF(s->service))->exec_command[SERVICE_EXEC_START]->path, &label);
-
- if (r < 0) {
- if (r != -EPERM)
- return r;
- }
- }
-
- know_label = true;
- }
-
- if ((r = socket_address_listen(
- &p->address,
- s->backlog,
- s->bind_ipv6_only,
- s->bind_to_device,
- s->free_bind,
- s->transparent,
- s->directory_mode,
- s->socket_mode,
- label,
- &p->fd)) < 0)
- goto rollback;
-
- socket_apply_socket_options(s, p->fd);
-
- } else if (p->type == SOCKET_SPECIAL) {
-
- if ((r = special_address_create(
- p->path,
- &p->fd)) < 0)
- goto rollback;
-
- } else if (p->type == SOCKET_FIFO) {
-
- if ((r = fifo_address_create(
- p->path,
- s->directory_mode,
- s->socket_mode,
- &p->fd)) < 0)
- goto rollback;
-
- socket_apply_fifo_options(s, p->fd);
- } else if (p->type == SOCKET_MQUEUE) {
-
- if ((r = mq_address_create(
- p->path,
- s->socket_mode,
- s->mq_maxmsg,
- s->mq_msgsize,
- &p->fd)) < 0)
- goto rollback;
- } else
- assert_not_reached("Unknown port type");
- }
-
- label_free(label);
- return 0;
-
-rollback:
- socket_close_fds(s);
- label_free(label);
- return r;
-}
-
-static void socket_unwatch_fds(Socket *s) {
- SocketPort *p;
-
- assert(s);
-
- LIST_FOREACH(port, p, s->ports) {
- if (p->fd < 0)
- continue;
-
- unit_unwatch_fd(UNIT(s), &p->fd_watch);
- }
-}
-
-static int socket_watch_fds(Socket *s) {
- SocketPort *p;
- int r;
-
- assert(s);
-
- LIST_FOREACH(port, p, s->ports) {
- if (p->fd < 0)
- continue;
-
- p->fd_watch.socket_accept =
- s->accept &&
- p->type == SOCKET_SOCKET &&
- socket_address_can_accept(&p->address);
-
- if ((r = unit_watch_fd(UNIT(s), p->fd, EPOLLIN, &p->fd_watch)) < 0)
- goto fail;
- }
-
- return 0;
-
-fail:
- socket_unwatch_fds(s);
- return r;
-}
-
-static void socket_set_state(Socket *s, SocketState state) {
- SocketState old_state;
- assert(s);
-
- old_state = s->state;
- s->state = state;
-
- if (state != SOCKET_START_PRE &&
- state != SOCKET_START_POST &&
- state != SOCKET_STOP_PRE &&
- state != SOCKET_STOP_PRE_SIGTERM &&
- state != SOCKET_STOP_PRE_SIGKILL &&
- state != SOCKET_STOP_POST &&
- state != SOCKET_FINAL_SIGTERM &&
- state != SOCKET_FINAL_SIGKILL) {
- unit_unwatch_timer(UNIT(s), &s->timer_watch);
- socket_unwatch_control_pid(s);
- s->control_command = NULL;
- s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID;
- }
-
- if (state != SOCKET_LISTENING)
- socket_unwatch_fds(s);
-
- if (state != SOCKET_START_POST &&
- state != SOCKET_LISTENING &&
- state != SOCKET_RUNNING &&
- state != SOCKET_STOP_PRE &&
- state != SOCKET_STOP_PRE_SIGTERM &&
- state != SOCKET_STOP_PRE_SIGKILL)
- socket_close_fds(s);
-
- if (state != old_state)
- log_debug("%s changed %s -> %s",
- UNIT(s)->id,
- socket_state_to_string(old_state),
- socket_state_to_string(state));
-
- unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true);
-}
-
-static int socket_coldplug(Unit *u) {
- Socket *s = SOCKET(u);
- int r;
-
- assert(s);
- assert(s->state == SOCKET_DEAD);
-
- if (s->deserialized_state != s->state) {
-
- if (s->deserialized_state == SOCKET_START_PRE ||
- s->deserialized_state == SOCKET_START_POST ||
- s->deserialized_state == SOCKET_STOP_PRE ||
- s->deserialized_state == SOCKET_STOP_PRE_SIGTERM ||
- s->deserialized_state == SOCKET_STOP_PRE_SIGKILL ||
- s->deserialized_state == SOCKET_STOP_POST ||
- s->deserialized_state == SOCKET_FINAL_SIGTERM ||
- s->deserialized_state == SOCKET_FINAL_SIGKILL) {
-
- if (s->control_pid <= 0)
- return -EBADMSG;
-
- if ((r = unit_watch_pid(UNIT(s), s->control_pid)) < 0)
- return r;
-
- if ((r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch)) < 0)
- return r;
- }
-
- if (s->deserialized_state == SOCKET_START_POST ||
- s->deserialized_state == SOCKET_LISTENING ||
- s->deserialized_state == SOCKET_RUNNING ||
- s->deserialized_state == SOCKET_STOP_PRE ||
- s->deserialized_state == SOCKET_STOP_PRE_SIGTERM ||
- s->deserialized_state == SOCKET_STOP_PRE_SIGKILL)
- if ((r = socket_open_fds(s)) < 0)
- return r;
-
- if (s->deserialized_state == SOCKET_LISTENING)
- if ((r = socket_watch_fds(s)) < 0)
- return r;
-
- socket_set_state(s, s->deserialized_state);
- }
-
- return 0;
-}
-
-static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
- pid_t pid;
- int r;
- char **argv;
-
- assert(s);
- assert(c);
- assert(_pid);
-
- if ((r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch)) < 0)
- goto fail;
-
- if (!(argv = unit_full_printf_strv(UNIT(s), c->argv))) {
- r = -ENOMEM;
- goto fail;
- }
-
- r = exec_spawn(c,
- argv,
- &s->exec_context,
- NULL, 0,
- UNIT(s)->manager->environment,
- true,
- true,
- true,
- UNIT(s)->manager->confirm_spawn,
- UNIT(s)->cgroup_bondings,
- UNIT(s)->cgroup_attributes,
- NULL,
- UNIT(s)->id,
- NULL,
- &pid);
-
- strv_free(argv);
- if (r < 0)
- goto fail;
-
- if ((r = unit_watch_pid(UNIT(s), pid)) < 0)
- /* FIXME: we need to do something here */
- goto fail;
-
- *_pid = pid;
-
- return 0;
-
-fail:
- unit_unwatch_timer(UNIT(s), &s->timer_watch);
-
- return r;
-}
-
-static void socket_enter_dead(Socket *s, SocketResult f) {
- assert(s);
-
- if (f != SOCKET_SUCCESS)
- s->result = f;
-
- socket_set_state(s, s->result != SOCKET_SUCCESS ? SOCKET_FAILED : SOCKET_DEAD);
-}
-
-static void socket_enter_signal(Socket *s, SocketState state, SocketResult f);
-
-static void socket_enter_stop_post(Socket *s, SocketResult f) {
- int r;
- assert(s);
-
- if (f != SOCKET_SUCCESS)
- s->result = f;
-
- socket_unwatch_control_pid(s);
-
- s->control_command_id = SOCKET_EXEC_STOP_POST;
-
- if ((s->control_command = s->exec_command[SOCKET_EXEC_STOP_POST])) {
- if ((r = socket_spawn(s, s->control_command, &s->control_pid)) < 0)
- goto fail;
-
- socket_set_state(s, SOCKET_STOP_POST);
- } else
- socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_SUCCESS);
-
- return;
-
-fail:
- log_warning("%s failed to run 'stop-post' task: %s", UNIT(s)->id, strerror(-r));
- socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_RESOURCES);
-}
-
-static void socket_enter_signal(Socket *s, SocketState state, SocketResult f) {
- int r;
- Set *pid_set = NULL;
- bool wait_for_exit = false;
-
- assert(s);
-
- if (f != SOCKET_SUCCESS)
- s->result = f;
-
- if (s->kill_context.kill_mode != KILL_NONE) {
- int sig = (state == SOCKET_STOP_PRE_SIGTERM || state == SOCKET_FINAL_SIGTERM) ? s->kill_context.kill_signal : SIGKILL;
-
- if (s->control_pid > 0) {
- if (kill_and_sigcont(s->control_pid, sig) < 0 && errno != ESRCH)
-
- log_warning("Failed to kill control process %li: %m", (long) s->control_pid);
- else
- wait_for_exit = true;
- }
-
- if (s->kill_context.kill_mode == KILL_CONTROL_GROUP) {
-
- if (!(pid_set = set_new(trivial_hash_func, trivial_compare_func))) {
- r = -ENOMEM;
- goto fail;
- }
-
- /* Exclude the control pid from being killed via the cgroup */
- if (s->control_pid > 0)
- if ((r = set_put(pid_set, LONG_TO_PTR(s->control_pid))) < 0)
- goto fail;
-
- r = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, sig, true, false, pid_set, NULL);
- if (r < 0) {
- if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
- log_warning("Failed to kill control group: %s", strerror(-r));
- } else if (r > 0)
- wait_for_exit = true;
-
- set_free(pid_set);
- pid_set = NULL;
- }
- }
-
- if (wait_for_exit) {
- if ((r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch)) < 0)
- goto fail;
-
- socket_set_state(s, state);
- } else if (state == SOCKET_STOP_PRE_SIGTERM || state == SOCKET_STOP_PRE_SIGKILL)
- socket_enter_stop_post(s, SOCKET_SUCCESS);
- else
- socket_enter_dead(s, SOCKET_SUCCESS);
-
- return;
-
-fail:
- log_warning("%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));
-
- if (state == SOCKET_STOP_PRE_SIGTERM || state == SOCKET_STOP_PRE_SIGKILL)
- socket_enter_stop_post(s, SOCKET_FAILURE_RESOURCES);
- else
- socket_enter_dead(s, SOCKET_FAILURE_RESOURCES);
-
- if (pid_set)
- set_free(pid_set);
-}
-
-static void socket_enter_stop_pre(Socket *s, SocketResult f) {
- int r;
- assert(s);
-
- if (f != SOCKET_SUCCESS)
- s->result = f;
-
- socket_unwatch_control_pid(s);
-
- s->control_command_id = SOCKET_EXEC_STOP_PRE;
-
- if ((s->control_command = s->exec_command[SOCKET_EXEC_STOP_PRE])) {
- if ((r = socket_spawn(s, s->control_command, &s->control_pid)) < 0)
- goto fail;
-
- socket_set_state(s, SOCKET_STOP_PRE);
- } else
- socket_enter_stop_post(s, SOCKET_SUCCESS);
-
- return;
-
-fail:
- log_warning("%s failed to run 'stop-pre' task: %s", UNIT(s)->id, strerror(-r));
- socket_enter_stop_post(s, SOCKET_FAILURE_RESOURCES);
-}
-
-static void socket_enter_listening(Socket *s) {
- int r;
- assert(s);
-
- r = socket_watch_fds(s);
- if (r < 0) {
- log_warning("%s failed to watch sockets: %s", UNIT(s)->id, strerror(-r));
- goto fail;
- }
-
- socket_set_state(s, SOCKET_LISTENING);
- return;
-
-fail:
- socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES);
-}
-
-static void socket_enter_start_post(Socket *s) {
- int r;
- assert(s);
-
- r = socket_open_fds(s);
- if (r < 0) {
- log_warning("%s failed to listen on sockets: %s", UNIT(s)->id, strerror(-r));
- goto fail;
- }
-
- socket_unwatch_control_pid(s);
-
- s->control_command_id = SOCKET_EXEC_START_POST;
-
- if ((s->control_command = s->exec_command[SOCKET_EXEC_START_POST])) {
- r = socket_spawn(s, s->control_command, &s->control_pid);
- if (r < 0) {
- log_warning("%s failed to run 'start-post' task: %s", UNIT(s)->id, strerror(-r));
- goto fail;
- }
-
- socket_set_state(s, SOCKET_START_POST);
- } else
- socket_enter_listening(s);
-
- return;
-
-fail:
- socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES);
-}
-
-static void socket_enter_start_pre(Socket *s) {
- int r;
- assert(s);
-
- socket_unwatch_control_pid(s);
-
- s->control_command_id = SOCKET_EXEC_START_PRE;
-
- if ((s->control_command = s->exec_command[SOCKET_EXEC_START_PRE])) {
- if ((r = socket_spawn(s, s->control_command, &s->control_pid)) < 0)
- goto fail;
-
- socket_set_state(s, SOCKET_START_PRE);
- } else
- socket_enter_start_post(s);
-
- return;
-
-fail:
- log_warning("%s failed to run 'start-pre' task: %s", UNIT(s)->id, strerror(-r));
- socket_enter_dead(s, SOCKET_FAILURE_RESOURCES);
-}
-
-static void socket_enter_running(Socket *s, int cfd) {
- int r;
- DBusError error;
-
- assert(s);
- dbus_error_init(&error);
-
- /* We don't take connections anymore if we are supposed to
- * shut down anyway */
- if (unit_pending_inactive(UNIT(s))) {
- log_debug("Suppressing connection request on %s since unit stop is scheduled.", UNIT(s)->id);
-
- if (cfd >= 0)
- close_nointr_nofail(cfd);
- else {
- /* Flush all sockets by closing and reopening them */
- socket_close_fds(s);
-
- r = socket_watch_fds(s);
- if (r < 0) {
- log_warning("%s failed to watch sockets: %s", UNIT(s)->id, strerror(-r));
- socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES);
- }
- }
-
- return;
- }
-
- if (cfd < 0) {
- Iterator i;
- Unit *u;
- bool pending = false;
-
- /* If there's already a start pending don't bother to
- * do anything */
- SET_FOREACH(u, UNIT(s)->dependencies[UNIT_TRIGGERS], i)
- if (unit_pending_active(u)) {
- pending = true;
- break;
- }
-
- if (!pending) {
- r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT_DEREF(s->service), JOB_REPLACE, true, &error, NULL);
- if (r < 0)
- goto fail;
- }
-
- socket_set_state(s, SOCKET_RUNNING);
- } else {
- char *prefix, *instance = NULL, *name;
- Service *service;
-
- if (s->n_connections >= s->max_connections) {
- log_warning("Too many incoming connections (%u)", s->n_connections);
- close_nointr_nofail(cfd);
- return;
- }
-
- r = socket_instantiate_service(s);
- if (r < 0)
- goto fail;
-
- r = instance_from_socket(cfd, s->n_accepted, &instance);
- if (r < 0) {
- if (r != -ENOTCONN)
- goto fail;
-
- /* ENOTCONN is legitimate if TCP RST was received.
- * This connection is over, but the socket unit lives on. */
- close_nointr_nofail(cfd);
- return;
- }
-
- prefix = unit_name_to_prefix(UNIT(s)->id);
- if (!prefix) {
- free(instance);
- r = -ENOMEM;
- goto fail;
- }
-
- name = unit_name_build(prefix, instance, ".service");
- free(prefix);
- free(instance);
-
- if (!name) {
- r = -ENOMEM;
- goto fail;
- }
-
- r = unit_add_name(UNIT_DEREF(s->service), name);
- if (r < 0) {
- free(name);
- goto fail;
- }
-
- service = SERVICE(UNIT_DEREF(s->service));
- unit_ref_unset(&s->service);
- s->n_accepted ++;
-
- UNIT(service)->no_gc = false;
-
- unit_choose_id(UNIT(service), name);
- free(name);
-
- r = service_set_socket_fd(service, cfd, s);
- if (r < 0)
- goto fail;
-
- cfd = -1;
- s->n_connections ++;
-
- r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT(service), JOB_REPLACE, true, &error, NULL);
- if (r < 0)
- goto fail;
-
- /* Notify clients about changed counters */
- unit_add_to_dbus_queue(UNIT(s));
- }
-
- return;
-
-fail:
- log_warning("%s failed to queue socket startup job: %s", UNIT(s)->id, bus_error(&error, r));
- socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES);
-
- if (cfd >= 0)
- close_nointr_nofail(cfd);
-
- dbus_error_free(&error);
-}
-
-static void socket_run_next(Socket *s) {
- int r;
-
- assert(s);
- assert(s->control_command);
- assert(s->control_command->command_next);
-
- socket_unwatch_control_pid(s);
-
- s->control_command = s->control_command->command_next;
-
- if ((r = socket_spawn(s, s->control_command, &s->control_pid)) < 0)
- goto fail;
-
- return;
-
-fail:
- log_warning("%s failed to run next task: %s", UNIT(s)->id, strerror(-r));
-
- if (s->state == SOCKET_START_POST)
- socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES);
- else if (s->state == SOCKET_STOP_POST)
- socket_enter_dead(s, SOCKET_FAILURE_RESOURCES);
- else
- socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_RESOURCES);
-}
-
-static int socket_start(Unit *u) {
- Socket *s = SOCKET(u);
-
- assert(s);
-
- /* We cannot fulfill this request right now, try again later
- * please! */
- if (s->state == SOCKET_STOP_PRE ||
- s->state == SOCKET_STOP_PRE_SIGKILL ||
- s->state == SOCKET_STOP_PRE_SIGTERM ||
- s->state == SOCKET_STOP_POST ||
- s->state == SOCKET_FINAL_SIGTERM ||
- s->state == SOCKET_FINAL_SIGKILL)
- return -EAGAIN;
-
- if (s->state == SOCKET_START_PRE ||
- s->state == SOCKET_START_POST)
- return 0;
-
- /* Cannot run this without the service being around */
- if (UNIT_DEREF(s->service)) {
- Service *service;
-
- service = SERVICE(UNIT_DEREF(s->service));
-
- if (UNIT(service)->load_state != UNIT_LOADED) {
- log_error("Socket service %s not loaded, refusing.", UNIT(service)->id);
- return -ENOENT;
- }
-
- /* If the service is already active we cannot start the
- * socket */
- if (service->state != SERVICE_DEAD &&
- service->state != SERVICE_FAILED &&
- service->state != SERVICE_AUTO_RESTART) {
- log_error("Socket service %s already active, refusing.", UNIT(service)->id);
- return -EBUSY;
- }
-
-#ifdef HAVE_SYSV_COMPAT
- if (service->is_sysv) {
- log_error("Using SysV services for socket activation is not supported. Refusing.");
- return -ENOENT;
- }
-#endif
- }
-
- assert(s->state == SOCKET_DEAD || s->state == SOCKET_FAILED);
-
- s->result = SOCKET_SUCCESS;
- socket_enter_start_pre(s);
- return 0;
-}
-
-static int socket_stop(Unit *u) {
- Socket *s = SOCKET(u);
-
- assert(s);
-
- /* Already on it */
- if (s->state == SOCKET_STOP_PRE ||
- s->state == SOCKET_STOP_PRE_SIGTERM ||
- s->state == SOCKET_STOP_PRE_SIGKILL ||
- s->state == SOCKET_STOP_POST ||
- s->state == SOCKET_FINAL_SIGTERM ||
- s->state == SOCKET_FINAL_SIGKILL)
- return 0;
-
- /* If there's already something running we go directly into
- * kill mode. */
- if (s->state == SOCKET_START_PRE ||
- s->state == SOCKET_START_POST) {
- socket_enter_signal(s, SOCKET_STOP_PRE_SIGTERM, SOCKET_SUCCESS);
- return -EAGAIN;
- }
-
- assert(s->state == SOCKET_LISTENING || s->state == SOCKET_RUNNING);
-
- socket_enter_stop_pre(s, SOCKET_SUCCESS);
- return 0;
-}
-
-static int socket_serialize(Unit *u, FILE *f, FDSet *fds) {
- Socket *s = SOCKET(u);
- SocketPort *p;
- int r;
-
- assert(u);
- assert(f);
- assert(fds);
-
- unit_serialize_item(u, f, "state", socket_state_to_string(s->state));
- unit_serialize_item(u, f, "result", socket_result_to_string(s->result));
- unit_serialize_item_format(u, f, "n-accepted", "%u", s->n_accepted);
-
- if (s->control_pid > 0)
- unit_serialize_item_format(u, f, "control-pid", "%lu", (unsigned long) s->control_pid);
-
- if (s->control_command_id >= 0)
- unit_serialize_item(u, f, "control-command", socket_exec_command_to_string(s->control_command_id));
-
- LIST_FOREACH(port, p, s->ports) {
- int copy;
-
- if (p->fd < 0)
- continue;
-
- if ((copy = fdset_put_dup(fds, p->fd)) < 0)
- return copy;
-
- if (p->type == SOCKET_SOCKET) {
- char *t;
-
- if ((r = socket_address_print(&p->address, &t)) < 0)
- return r;
-
- if (socket_address_family(&p->address) == AF_NETLINK)
- unit_serialize_item_format(u, f, "netlink", "%i %s", copy, t);
- else
- unit_serialize_item_format(u, f, "socket", "%i %i %s", copy, p->address.type, t);
- free(t);
- } else if (p->type == SOCKET_SPECIAL)
- unit_serialize_item_format(u, f, "special", "%i %s", copy, p->path);
- else {
- assert(p->type == SOCKET_FIFO);
- unit_serialize_item_format(u, f, "fifo", "%i %s", copy, p->path);
- }
- }
-
- return 0;
-}
-
-static int socket_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
- Socket *s = SOCKET(u);
-
- assert(u);
- assert(key);
- assert(value);
- assert(fds);
-
- if (streq(key, "state")) {
- SocketState state;
-
- if ((state = socket_state_from_string(value)) < 0)
- log_debug("Failed to parse state value %s", value);
- else
- s->deserialized_state = state;
- } else if (streq(key, "result")) {
- SocketResult f;
-
- f = socket_result_from_string(value);
- if (f < 0)
- log_debug("Failed to parse result value %s", value);
- else if (f != SOCKET_SUCCESS)
- s->result = f;
-
- } else if (streq(key, "n-accepted")) {
- unsigned k;
-
- if (safe_atou(value, &k) < 0)
- log_debug("Failed to parse n-accepted value %s", value);
- else
- s->n_accepted += k;
- } else if (streq(key, "control-pid")) {
- pid_t pid;
-
- if (parse_pid(value, &pid) < 0)
- log_debug("Failed to parse control-pid value %s", value);
- else
- s->control_pid = pid;
- } else if (streq(key, "control-command")) {
- SocketExecCommand id;
-
- if ((id = socket_exec_command_from_string(value)) < 0)
- log_debug("Failed to parse exec-command value %s", value);
- else {
- s->control_command_id = id;
- s->control_command = s->exec_command[id];
- }
- } else if (streq(key, "fifo")) {
- int fd, skip = 0;
- SocketPort *p;
-
- if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
- log_debug("Failed to parse fifo value %s", value);
- else {
-
- LIST_FOREACH(port, p, s->ports)
- if (p->type == SOCKET_FIFO &&
- streq_ptr(p->path, value+skip))
- break;
-
- if (p) {
- if (p->fd >= 0)
- close_nointr_nofail(p->fd);
- p->fd = fdset_remove(fds, fd);
- }
- }
-
- } else if (streq(key, "special")) {
- int fd, skip = 0;
- SocketPort *p;
-
- if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
- log_debug("Failed to parse special value %s", value);
- else {
-
- LIST_FOREACH(port, p, s->ports)
- if (p->type == SOCKET_SPECIAL &&
- streq_ptr(p->path, value+skip))
- break;
-
- if (p) {
- if (p->fd >= 0)
- close_nointr_nofail(p->fd);
- p->fd = fdset_remove(fds, fd);
- }
- }
-
- } else if (streq(key, "socket")) {
- int fd, type, skip = 0;
- SocketPort *p;
-
- if (sscanf(value, "%i %i %n", &fd, &type, &skip) < 2 || fd < 0 || type < 0 || !fdset_contains(fds, fd))
- log_debug("Failed to parse socket value %s", value);
- else {
-
- LIST_FOREACH(port, p, s->ports)
- if (socket_address_is(&p->address, value+skip, type))
- break;
-
- if (p) {
- if (p->fd >= 0)
- close_nointr_nofail(p->fd);
- p->fd = fdset_remove(fds, fd);
- }
- }
-
- } else if (streq(key, "netlink")) {
- int fd, skip = 0;
- SocketPort *p;
-
- if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
- log_debug("Failed to parse socket value %s", value);
- else {
-
- LIST_FOREACH(port, p, s->ports)
- if (socket_address_is_netlink(&p->address, value+skip))
- break;
-
- if (p) {
- if (p->fd >= 0)
- close_nointr_nofail(p->fd);
- p->fd = fdset_remove(fds, fd);
- }
- }
-
- } else
- log_debug("Unknown serialization key '%s'", key);
-
- return 0;
-}
-
-static UnitActiveState socket_active_state(Unit *u) {
- assert(u);
-
- return state_translation_table[SOCKET(u)->state];
-}
-
-static const char *socket_sub_state_to_string(Unit *u) {
- assert(u);
-
- return socket_state_to_string(SOCKET(u)->state);
-}
-
-static bool socket_check_gc(Unit *u) {
- Socket *s = SOCKET(u);
-
- assert(u);
-
- return s->n_connections > 0;
-}
-
-static void socket_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
- Socket *s = SOCKET(u);
- int cfd = -1;
-
- assert(s);
- assert(fd >= 0);
-
- if (s->state != SOCKET_LISTENING)
- return;
-
- log_debug("Incoming traffic on %s", u->id);
-
- if (events != EPOLLIN) {
-
- if (events & EPOLLHUP)
- log_error("%s: Got POLLHUP on a listening socket. The service probably invoked shutdown() on it, and should better not do that.", u->id);
- else
- log_error("%s: Got unexpected poll event (0x%x) on socket.", u->id, events);
-
- goto fail;
- }
-
- if (w->socket_accept) {
- for (;;) {
-
- cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK);
- if (cfd < 0) {
-
- if (errno == EINTR)
- continue;
-
- log_error("Failed to accept socket: %m");
- goto fail;
- }
-
- break;
- }
-
- socket_apply_socket_options(s, cfd);
- }
-
- socket_enter_running(s, cfd);
- return;
-
-fail:
- socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES);
-}
-
-static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) {
- Socket *s = SOCKET(u);
- SocketResult f;
-
- assert(s);
- assert(pid >= 0);
-
- if (pid != s->control_pid)
- return;
-
- s->control_pid = 0;
-
- if (is_clean_exit(code, status, NULL))
- f = SOCKET_SUCCESS;
- else if (code == CLD_EXITED)
- f = SOCKET_FAILURE_EXIT_CODE;
- else if (code == CLD_KILLED)
- f = SOCKET_FAILURE_SIGNAL;
- else if (code == CLD_DUMPED)
- f = SOCKET_FAILURE_CORE_DUMP;
- else
- assert_not_reached("Unknown code");
-
- if (s->control_command) {
- exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status);
-
- if (s->control_command->ignore)
- f = SOCKET_SUCCESS;
- }
-
- log_full(f == SOCKET_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
- "%s control process exited, code=%s status=%i", u->id, sigchld_code_to_string(code), status);
-
- if (f != SOCKET_SUCCESS)
- s->result = f;
-
- if (s->control_command &&
- s->control_command->command_next &&
- f == SOCKET_SUCCESS) {
-
- log_debug("%s running next command for state %s", u->id, socket_state_to_string(s->state));
- socket_run_next(s);
- } else {
- s->control_command = NULL;
- s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID;
-
- /* No further commands for this step, so let's figure
- * out what to do next */
-
- log_debug("%s got final SIGCHLD for state %s", u->id, socket_state_to_string(s->state));
-
- switch (s->state) {
-
- case SOCKET_START_PRE:
- if (f == SOCKET_SUCCESS)
- socket_enter_start_post(s);
- else
- socket_enter_signal(s, SOCKET_FINAL_SIGTERM, f);
- break;
-
- case SOCKET_START_POST:
- if (f == SOCKET_SUCCESS)
- socket_enter_listening(s);
- else
- socket_enter_stop_pre(s, f);
- break;
-
- case SOCKET_STOP_PRE:
- case SOCKET_STOP_PRE_SIGTERM:
- case SOCKET_STOP_PRE_SIGKILL:
- socket_enter_stop_post(s, f);
- break;
-
- case SOCKET_STOP_POST:
- case SOCKET_FINAL_SIGTERM:
- case SOCKET_FINAL_SIGKILL:
- socket_enter_dead(s, f);
- break;
-
- default:
- assert_not_reached("Uh, control process died at wrong time.");
- }
- }
-
- /* Notify clients about changed exit status */
- unit_add_to_dbus_queue(u);
-}
-
-static void socket_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
- Socket *s = SOCKET(u);
-
- assert(s);
- assert(elapsed == 1);
- assert(w == &s->timer_watch);
-
- switch (s->state) {
-
- case SOCKET_START_PRE:
- log_warning("%s starting timed out. Terminating.", u->id);
- socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_TIMEOUT);
- break;
-
- case SOCKET_START_POST:
- log_warning("%s starting timed out. Stopping.", u->id);
- socket_enter_stop_pre(s, SOCKET_FAILURE_TIMEOUT);
- break;
-
- case SOCKET_STOP_PRE:
- log_warning("%s stopping timed out. Terminating.", u->id);
- socket_enter_signal(s, SOCKET_STOP_PRE_SIGTERM, SOCKET_FAILURE_TIMEOUT);
- break;
-
- case SOCKET_STOP_PRE_SIGTERM:
- if (s->kill_context.send_sigkill) {
- log_warning("%s stopping timed out. Killing.", u->id);
- socket_enter_signal(s, SOCKET_STOP_PRE_SIGKILL, SOCKET_FAILURE_TIMEOUT);
- } else {
- log_warning("%s stopping timed out. Skipping SIGKILL. Ignoring.", u->id);
- socket_enter_stop_post(s, SOCKET_FAILURE_TIMEOUT);
- }
- break;
-
- case SOCKET_STOP_PRE_SIGKILL:
- log_warning("%s still around after SIGKILL. Ignoring.", u->id);
- socket_enter_stop_post(s, SOCKET_FAILURE_TIMEOUT);
- break;
-
- case SOCKET_STOP_POST:
- log_warning("%s stopping timed out (2). Terminating.", u->id);
- socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_TIMEOUT);
- break;
-
- case SOCKET_FINAL_SIGTERM:
- if (s->kill_context.send_sigkill) {
- log_warning("%s stopping timed out (2). Killing.", u->id);
- socket_enter_signal(s, SOCKET_FINAL_SIGKILL, SOCKET_FAILURE_TIMEOUT);
- } else {
- log_warning("%s stopping timed out (2). Skipping SIGKILL. Ignoring.", u->id);
- socket_enter_dead(s, SOCKET_FAILURE_TIMEOUT);
- }
- break;
-
- case SOCKET_FINAL_SIGKILL:
- log_warning("%s still around after SIGKILL (2). Entering failed mode.", u->id);
- socket_enter_dead(s, SOCKET_FAILURE_TIMEOUT);
- break;
-
- default:
- assert_not_reached("Timeout at wrong time.");
- }
-}
-
-int socket_collect_fds(Socket *s, int **fds, unsigned *n_fds) {
- int *rfds;
- unsigned rn_fds, k;
- SocketPort *p;
-
- assert(s);
- assert(fds);
- assert(n_fds);
-
- /* Called from the service code for requesting our fds */
-
- rn_fds = 0;
- LIST_FOREACH(port, p, s->ports)
- if (p->fd >= 0)
- rn_fds++;
-
- if (rn_fds <= 0) {
- *fds = NULL;
- *n_fds = 0;
- return 0;
- }
-
- if (!(rfds = new(int, rn_fds)))
- return -ENOMEM;
-
- k = 0;
- LIST_FOREACH(port, p, s->ports)
- if (p->fd >= 0)
- rfds[k++] = p->fd;
-
- assert(k == rn_fds);
-
- *fds = rfds;
- *n_fds = rn_fds;
-
- return 0;
-}
-
-void socket_notify_service_dead(Socket *s, bool failed_permanent) {
- assert(s);
-
- /* The service is dead. Dang!
- *
- * This is strictly for one-instance-for-all-connections
- * services. */
-
- if (s->state == SOCKET_RUNNING) {
- log_debug("%s got notified about service death (failed permanently: %s)", UNIT(s)->id, yes_no(failed_permanent));
- if (failed_permanent)
- socket_enter_stop_pre(s, SOCKET_FAILURE_SERVICE_FAILED_PERMANENT);
- else
- socket_enter_listening(s);
- }
-}
-
-void socket_connection_unref(Socket *s) {
- assert(s);
-
- /* The service is dead. Yay!
- *
- * This is strictly for one-instance-per-connection
- * services. */
-
- assert(s->n_connections > 0);
- s->n_connections--;
-
- log_debug("%s: One connection closed, %u left.", UNIT(s)->id, s->n_connections);
-}
-
-static void socket_reset_failed(Unit *u) {
- Socket *s = SOCKET(u);
-
- assert(s);
-
- if (s->state == SOCKET_FAILED)
- socket_set_state(s, SOCKET_DEAD);
-
- s->result = SOCKET_SUCCESS;
-}
-
-static int socket_kill(Unit *u, KillWho who, int signo, DBusError *error) {
- Socket *s = SOCKET(u);
- int r = 0;
- Set *pid_set = NULL;
-
- assert(s);
-
- if (who == KILL_MAIN) {
- dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "Socket units have no main processes");
- return -ESRCH;
- }
-
- if (s->control_pid <= 0 && who == KILL_CONTROL) {
- dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
- return -ESRCH;
- }
-
- if (who == KILL_CONTROL || who == KILL_ALL)
- if (s->control_pid > 0)
- if (kill(s->control_pid, signo) < 0)
- r = -errno;
-
- if (who == KILL_ALL) {
- int q;
-
- pid_set = set_new(trivial_hash_func, trivial_compare_func);
- if (!pid_set)
- return -ENOMEM;
-
- /* Exclude the control pid from being killed via the cgroup */
- if (s->control_pid > 0) {
- q = set_put(pid_set, LONG_TO_PTR(s->control_pid));
- if (q < 0) {
- r = q;
- goto finish;
- }
- }
-
- q = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, signo, false, false, pid_set, NULL);
- if (q < 0 && q != -EAGAIN && q != -ESRCH && q != -ENOENT)
- r = q;
- }
-
-finish:
- if (pid_set)
- set_free(pid_set);
-
- return r;
-}
-
-static const char* const socket_state_table[_SOCKET_STATE_MAX] = {
- [SOCKET_DEAD] = "dead",
- [SOCKET_START_PRE] = "start-pre",
- [SOCKET_START_POST] = "start-post",
- [SOCKET_LISTENING] = "listening",
- [SOCKET_RUNNING] = "running",
- [SOCKET_STOP_PRE] = "stop-pre",
- [SOCKET_STOP_PRE_SIGTERM] = "stop-pre-sigterm",
- [SOCKET_STOP_PRE_SIGKILL] = "stop-pre-sigkill",
- [SOCKET_STOP_POST] = "stop-post",
- [SOCKET_FINAL_SIGTERM] = "final-sigterm",
- [SOCKET_FINAL_SIGKILL] = "final-sigkill",
- [SOCKET_FAILED] = "failed"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(socket_state, SocketState);
-
-static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = {
- [SOCKET_EXEC_START_PRE] = "StartPre",
- [SOCKET_EXEC_START_POST] = "StartPost",
- [SOCKET_EXEC_STOP_PRE] = "StopPre",
- [SOCKET_EXEC_STOP_POST] = "StopPost"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(socket_exec_command, SocketExecCommand);
-
-static const char* const socket_result_table[_SOCKET_RESULT_MAX] = {
- [SOCKET_SUCCESS] = "success",
- [SOCKET_FAILURE_RESOURCES] = "resources",
- [SOCKET_FAILURE_TIMEOUT] = "timeout",
- [SOCKET_FAILURE_EXIT_CODE] = "exit-code",
- [SOCKET_FAILURE_SIGNAL] = "signal",
- [SOCKET_FAILURE_CORE_DUMP] = "core-dump",
- [SOCKET_FAILURE_SERVICE_FAILED_PERMANENT] = "service-failed-permanent"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(socket_result, SocketResult);
-
-const UnitVTable socket_vtable = {
- .object_size = sizeof(Socket),
- .exec_context_offset = offsetof(Socket, exec_context),
-
- .sections =
- "Unit\0"
- "Socket\0"
- "Install\0",
-
- .init = socket_init,
- .done = socket_done,
- .load = socket_load,
-
- .kill = socket_kill,
-
- .coldplug = socket_coldplug,
-
- .dump = socket_dump,
-
- .start = socket_start,
- .stop = socket_stop,
-
- .serialize = socket_serialize,
- .deserialize_item = socket_deserialize_item,
-
- .active_state = socket_active_state,
- .sub_state_to_string = socket_sub_state_to_string,
-
- .check_gc = socket_check_gc,
-
- .fd_event = socket_fd_event,
- .sigchld_event = socket_sigchld_event,
- .timer_event = socket_timer_event,
-
- .reset_failed = socket_reset_failed,
-
- .bus_interface = "org.freedesktop.systemd1.Socket",
- .bus_message_handler = bus_socket_message_handler,
- .bus_invalidating_properties = bus_socket_invalidating_properties,
-
- .status_message_formats = {
- /*.starting_stopping = {
- [0] = "Starting socket %s...",
- [1] = "Stopping socket %s...",
- },*/
- .finished_start_job = {
- [JOB_DONE] = "Listening on %s.",
- [JOB_FAILED] = "Failed to listen on %s.",
- [JOB_DEPENDENCY] = "Dependency failed for %s.",
- [JOB_TIMEOUT] = "Timed out starting %s.",
- },
- .finished_stop_job = {
- [JOB_DONE] = "Closed %s.",
- [JOB_FAILED] = "Failed stopping %s.",
- [JOB_TIMEOUT] = "Timed out stopping %s.",
- },
- },
-};
diff --git a/src/core/socket.h b/src/core/socket.h
deleted file mode 100644
index f099520dce..0000000000
--- a/src/core/socket.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/*-*- 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/>.
-***/
-
-typedef struct Socket Socket;
-
-#include "manager.h"
-#include "unit.h"
-#include "socket-util.h"
-#include "mount.h"
-#include "service.h"
-
-typedef enum SocketState {
- SOCKET_DEAD,
- SOCKET_START_PRE,
- SOCKET_START_POST,
- SOCKET_LISTENING,
- SOCKET_RUNNING,
- SOCKET_STOP_PRE,
- SOCKET_STOP_PRE_SIGTERM,
- SOCKET_STOP_PRE_SIGKILL,
- SOCKET_STOP_POST,
- SOCKET_FINAL_SIGTERM,
- SOCKET_FINAL_SIGKILL,
- SOCKET_FAILED,
- _SOCKET_STATE_MAX,
- _SOCKET_STATE_INVALID = -1
-} SocketState;
-
-typedef enum SocketExecCommand {
- SOCKET_EXEC_START_PRE,
- SOCKET_EXEC_START_POST,
- SOCKET_EXEC_STOP_PRE,
- SOCKET_EXEC_STOP_POST,
- _SOCKET_EXEC_COMMAND_MAX,
- _SOCKET_EXEC_COMMAND_INVALID = -1
-} SocketExecCommand;
-
-typedef enum SocketType {
- SOCKET_SOCKET,
- SOCKET_FIFO,
- SOCKET_SPECIAL,
- SOCKET_MQUEUE,
- _SOCKET_FIFO_MAX,
- _SOCKET_FIFO_INVALID = -1
-} SocketType;
-
-typedef enum SocketResult {
- SOCKET_SUCCESS,
- SOCKET_FAILURE_RESOURCES,
- SOCKET_FAILURE_TIMEOUT,
- SOCKET_FAILURE_EXIT_CODE,
- SOCKET_FAILURE_SIGNAL,
- SOCKET_FAILURE_CORE_DUMP,
- SOCKET_FAILURE_SERVICE_FAILED_PERMANENT,
- _SOCKET_RESULT_MAX,
- _SOCKET_RESULT_INVALID = -1
-} SocketResult;
-
-typedef struct SocketPort {
- SocketType type;
- int fd;
-
- SocketAddress address;
- char *path;
- Watch fd_watch;
-
- LIST_FIELDS(struct SocketPort, port);
-} SocketPort;
-
-struct Socket {
- Unit meta;
-
- LIST_HEAD(SocketPort, ports);
-
- unsigned n_accepted;
- unsigned n_connections;
- unsigned max_connections;
-
- unsigned backlog;
- usec_t timeout_usec;
-
- ExecCommand* exec_command[_SOCKET_EXEC_COMMAND_MAX];
- ExecContext exec_context;
- KillContext kill_context;
-
- /* For Accept=no sockets refers to the one service we'll
- activate. For Accept=yes sockets is either NULL, or filled
- when the next service we spawn. */
- UnitRef service;
-
- SocketState state, deserialized_state;
-
- Watch timer_watch;
-
- ExecCommand* control_command;
- SocketExecCommand control_command_id;
- pid_t control_pid;
-
- mode_t directory_mode;
- mode_t socket_mode;
-
- SocketResult result;
-
- bool accept;
-
- /* Socket options */
- bool keep_alive;
- bool free_bind;
- bool transparent;
- bool broadcast;
- bool pass_cred;
- bool pass_sec;
- int priority;
- int mark;
- size_t receive_buffer;
- size_t send_buffer;
- int ip_tos;
- int ip_ttl;
- size_t pipe_size;
- char *bind_to_device;
- char *tcp_congestion;
- long mq_maxmsg;
- long mq_msgsize;
-
- /* Only for INET6 sockets: issue IPV6_V6ONLY sockopt */
- SocketAddressBindIPv6Only bind_ipv6_only;
-
- char *smack;
- char *smack_ip_in;
- char *smack_ip_out;
-};
-
-/* Called from the service code when collecting fds */
-int socket_collect_fds(Socket *s, int **fds, unsigned *n_fds);
-
-/* Called from the service when it shut down */
-void socket_notify_service_dead(Socket *s, bool failed_permanent);
-
-/* Called from the mount code figure out if a mount is a dependency of
- * any of the sockets of this socket */
-int socket_add_one_mount_link(Socket *s, Mount *m);
-
-/* Called from the service code when a per-connection service ended */
-void socket_connection_unref(Socket *s);
-
-extern const UnitVTable socket_vtable;
-
-const char* socket_state_to_string(SocketState i);
-SocketState socket_state_from_string(const char *s);
-
-const char* socket_exec_command_to_string(SocketExecCommand i);
-SocketExecCommand socket_exec_command_from_string(const char *s);
-
-const char* socket_result_to_string(SocketResult i);
-SocketResult socket_result_from_string(const char *s);
diff --git a/src/core/special.h b/src/core/special.h
deleted file mode 100644
index ef72260ecd..0000000000
--- a/src/core/special.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*-*- 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/>.
-***/
-
-#define SPECIAL_DEFAULT_TARGET "default.target"
-
-/* Shutdown targets */
-#define SPECIAL_UMOUNT_TARGET "umount.target"
-/* This is not really intended to be started by directly. This is
- * mostly so that other targets (reboot/halt/poweroff) can depend on
- * it to bring all services down that want to be brought down on
- * system shutdown. */
-#define SPECIAL_SHUTDOWN_TARGET "shutdown.target"
-#define SPECIAL_HALT_TARGET "halt.target"
-#define SPECIAL_POWEROFF_TARGET "poweroff.target"
-#define SPECIAL_REBOOT_TARGET "reboot.target"
-#define SPECIAL_KEXEC_TARGET "kexec.target"
-#define SPECIAL_EXIT_TARGET "exit.target"
-#define SPECIAL_SUSPEND_TARGET "suspend.target"
-#define SPECIAL_HIBERNATE_TARGET "hibernate.target"
-#define SPECIAL_HYBRID_SLEEP_TARGET "hybrid-sleep.target"
-
-/* Special boot targets */
-#define SPECIAL_RESCUE_TARGET "rescue.target"
-#define SPECIAL_EMERGENCY_TARGET "emergency.target"
-
-/* Early boot targets */
-#define SPECIAL_SYSINIT_TARGET "sysinit.target"
-#define SPECIAL_SOCKETS_TARGET "sockets.target"
-#define SPECIAL_LOCAL_FS_TARGET "local-fs.target" /* LSB's $local_fs */
-#define SPECIAL_LOCAL_FS_PRE_TARGET "local-fs-pre.target"
-#define SPECIAL_REMOTE_FS_TARGET "remote-fs.target" /* LSB's $remote_fs */
-#define SPECIAL_REMOTE_FS_PRE_TARGET "remote-fs-pre.target"
-#define SPECIAL_SWAP_TARGET "swap.target"
-#define SPECIAL_BASIC_TARGET "basic.target"
-
-/* LSB compatibility */
-#define SPECIAL_NETWORK_TARGET "network.target" /* LSB's $network */
-#define SPECIAL_NSS_LOOKUP_TARGET "nss-lookup.target" /* LSB's $named */
-#define SPECIAL_RPCBIND_TARGET "rpcbind.target" /* LSB's $portmap */
-#define SPECIAL_SYSLOG_TARGET "syslog.target" /* LSB's $syslog */
-#define SPECIAL_TIME_SYNC_TARGET "time-sync.target" /* LSB's $time */
-#define SPECIAL_DISPLAY_MANAGER_SERVICE "display-manager.service" /* Common extension of LSB */
-#define SPECIAL_MAIL_TRANSFER_AGENT_TARGET "mail-transfer-agent.target" /* Common extension of LSB */
-
-/*
- * Rules regarding adding further high level targets like the above:
- *
- * - Be conservative, only add more of these when we really need
- * them. We need strong usecases for further additions.
- *
- * - When there can be multiple implementations running side-by-side,
- * it needs to be a .target unit which can pull in all
- * implementations.
- *
- * - If something can be implemented with socket activation, and
- * without, it needs to be a .target unit, so that it can pull in
- * the appropriate unit.
- *
- * - Otherwise, it should be a .service unit.
- *
- * - In some cases it is OK to have both a .service and a .target
- * unit, i.e. if there can be multiple parallel implementations, but
- * only one is the "system" one. Example: syslog.
- *
- * Or to put this in other words: .service symlinks can be used to
- * arbitrate between multiple implementations if there can be only one
- * of a kind. .target units can be used to support multiple
- * implementations that can run side-by-side.
- */
-
-/* Magic early boot services */
-#define SPECIAL_FSCK_SERVICE "systemd-fsck@.service"
-#define SPECIAL_QUOTACHECK_SERVICE "systemd-quotacheck.service"
-#define SPECIAL_QUOTAON_SERVICE "quotaon.service"
-#define SPECIAL_REMOUNT_FS_SERVICE "systemd-remount-fs.service"
-
-/* Services systemd relies on */
-#define SPECIAL_DBUS_SERVICE "dbus.service"
-#define SPECIAL_DBUS_SOCKET "dbus.socket"
-#define SPECIAL_JOURNALD_SOCKET "systemd-journald.socket"
-#define SPECIAL_JOURNALD_SERVICE "systemd-journald.service"
-
-/* Magic init signals */
-#define SPECIAL_KBREQUEST_TARGET "kbrequest.target"
-#define SPECIAL_SIGPWR_TARGET "sigpwr.target"
-#define SPECIAL_CTRL_ALT_DEL_TARGET "ctrl-alt-del.target"
-
-/* For SysV compatibility. Usually an alias for a saner target. On
- * SysV-free systems this doesn't exist. */
-#define SPECIAL_RUNLEVEL2_TARGET "runlevel2.target"
-#define SPECIAL_RUNLEVEL3_TARGET "runlevel3.target"
-#define SPECIAL_RUNLEVEL4_TARGET "runlevel4.target"
-#define SPECIAL_RUNLEVEL5_TARGET "runlevel5.target"
diff --git a/src/core/swap.c b/src/core/swap.c
deleted file mode 100644
index 97145a9974..0000000000
--- a/src/core/swap.c
+++ /dev/null
@@ -1,1433 +0,0 @@
-/*-*- 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 <errno.h>
-#include <limits.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/epoll.h>
-#include <sys/stat.h>
-#include <sys/swap.h>
-#include <libudev.h>
-
-#include "unit.h"
-#include "swap.h"
-#include "load-fragment.h"
-#include "load-dropin.h"
-#include "unit-name.h"
-#include "dbus-swap.h"
-#include "special.h"
-#include "bus-errors.h"
-#include "exit-status.h"
-#include "def.h"
-#include "path-util.h"
-#include "virt.h"
-
-static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = {
- [SWAP_DEAD] = UNIT_INACTIVE,
- [SWAP_ACTIVATING] = UNIT_ACTIVATING,
- [SWAP_ACTIVE] = UNIT_ACTIVE,
- [SWAP_DEACTIVATING] = UNIT_DEACTIVATING,
- [SWAP_ACTIVATING_SIGTERM] = UNIT_DEACTIVATING,
- [SWAP_ACTIVATING_SIGKILL] = UNIT_DEACTIVATING,
- [SWAP_DEACTIVATING_SIGTERM] = UNIT_DEACTIVATING,
- [SWAP_DEACTIVATING_SIGKILL] = UNIT_DEACTIVATING,
- [SWAP_FAILED] = UNIT_FAILED
-};
-
-static void swap_unset_proc_swaps(Swap *s) {
- Swap *first;
- Hashmap *swaps;
-
- assert(s);
-
- if (!s->parameters_proc_swaps.what)
- return;
-
- /* Remove this unit from the chain of swaps which share the
- * same kernel swap device. */
- swaps = UNIT(s)->manager->swaps_by_proc_swaps;
- first = hashmap_get(swaps, s->parameters_proc_swaps.what);
- LIST_REMOVE(Swap, same_proc_swaps, first, s);
-
- if (first)
- hashmap_remove_and_replace(swaps,
- s->parameters_proc_swaps.what,
- first->parameters_proc_swaps.what,
- first);
- else
- hashmap_remove(swaps, s->parameters_proc_swaps.what);
-
- free(s->parameters_proc_swaps.what);
- s->parameters_proc_swaps.what = NULL;
-}
-
-static void swap_init(Unit *u) {
- Swap *s = SWAP(u);
-
- assert(s);
- assert(UNIT(s)->load_state == UNIT_STUB);
-
- s->timeout_usec = DEFAULT_TIMEOUT_USEC;
-
- exec_context_init(&s->exec_context);
- s->exec_context.std_output = u->manager->default_std_output;
- s->exec_context.std_error = u->manager->default_std_error;
- kill_context_init(&s->kill_context);
-
- s->parameters_proc_swaps.priority = s->parameters_fragment.priority = -1;
-
- s->timer_watch.type = WATCH_INVALID;
-
- s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
-
- UNIT(s)->ignore_on_isolate = true;
-}
-
-static void swap_unwatch_control_pid(Swap *s) {
- assert(s);
-
- if (s->control_pid <= 0)
- return;
-
- unit_unwatch_pid(UNIT(s), s->control_pid);
- s->control_pid = 0;
-}
-
-static void swap_done(Unit *u) {
- Swap *s = SWAP(u);
-
- assert(s);
-
- swap_unset_proc_swaps(s);
-
- free(s->what);
- s->what = NULL;
-
- free(s->parameters_fragment.what);
- s->parameters_fragment.what = NULL;
-
- exec_context_done(&s->exec_context);
- exec_command_done_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX);
- s->control_command = NULL;
-
- swap_unwatch_control_pid(s);
-
- unit_unwatch_timer(u, &s->timer_watch);
-}
-
-int swap_add_one_mount_link(Swap *s, Mount *m) {
- int r;
-
- assert(s);
- assert(m);
-
- if (UNIT(s)->load_state != UNIT_LOADED ||
- UNIT(m)->load_state != UNIT_LOADED)
- return 0;
-
- if (is_device_path(s->what))
- return 0;
-
- if (!path_startswith(s->what, m->where))
- return 0;
-
- r = unit_add_two_dependencies(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static int swap_add_mount_links(Swap *s) {
- Unit *other;
- int r;
-
- assert(s);
-
- LIST_FOREACH(units_by_type, other, UNIT(s)->manager->units_by_type[UNIT_MOUNT])
- if ((r = swap_add_one_mount_link(s, MOUNT(other))) < 0)
- return r;
-
- return 0;
-}
-
-static int swap_add_device_links(Swap *s) {
- SwapParameters *p;
-
- assert(s);
-
- if (!s->what)
- return 0;
-
- if (s->from_fragment)
- p = &s->parameters_fragment;
- else
- return 0;
-
- if (is_device_path(s->what))
- return unit_add_node_link(UNIT(s), s->what,
- !p->noauto && p->nofail &&
- UNIT(s)->manager->running_as == SYSTEMD_SYSTEM);
- else
- /* File based swap devices need to be ordered after
- * systemd-remount-fs.service, since they might need a
- * writable file system. */
- return unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_REMOUNT_FS_SERVICE, NULL, true);
-}
-
-static int swap_add_default_dependencies(Swap *s) {
- int r;
-
- assert(s);
-
- if (UNIT(s)->manager->running_as != SYSTEMD_SYSTEM)
- return 0;
-
- if (detect_container(NULL) > 0)
- return 0;
-
- r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static int swap_verify(Swap *s) {
- bool b;
- char _cleanup_free_ *e = NULL;
-
- if (UNIT(s)->load_state != UNIT_LOADED)
- return 0;
-
- e = unit_name_from_path(s->what, ".swap");
- if (e == NULL)
- return log_oom();
-
- b = unit_has_name(UNIT(s), e);
- if (!b) {
- log_error("%s: Value of \"What\" and unit name do not match, not loading.", UNIT(s)->id);
- return -EINVAL;
- }
-
- if (s->exec_context.pam_name && s->kill_context.kill_mode != KILL_CONTROL_GROUP) {
- log_error("%s has PAM enabled. Kill mode must be set to 'control-group'. Refusing to load.", UNIT(s)->id);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int swap_load(Unit *u) {
- int r;
- Swap *s = SWAP(u);
-
- assert(s);
- assert(u->load_state == UNIT_STUB);
-
- /* Load a .swap file */
- r = unit_load_fragment_and_dropin_optional(u);
- if (r < 0)
- return r;
-
- if (u->load_state == UNIT_LOADED) {
- r = unit_add_exec_dependencies(u, &s->exec_context);
- if (r < 0)
- return r;
-
- if (UNIT(s)->fragment_path)
- s->from_fragment = true;
-
- if (!s->what) {
- if (s->parameters_fragment.what)
- s->what = strdup(s->parameters_fragment.what);
- else if (s->parameters_proc_swaps.what)
- s->what = strdup(s->parameters_proc_swaps.what);
- else
- s->what = unit_name_to_path(u->id);
-
- if (!s->what)
- return -ENOMEM;
- }
-
- path_kill_slashes(s->what);
-
- if (!UNIT(s)->description)
- if ((r = unit_set_description(u, s->what)) < 0)
- return r;
-
- r = swap_add_device_links(s);
- if (r < 0)
- return r;
-
- r = swap_add_mount_links(s);
- if (r < 0)
- return r;
-
- r = unit_add_default_cgroups(u);
- if (r < 0)
- return r;
-
- if (UNIT(s)->default_dependencies) {
- r = swap_add_default_dependencies(s);
- if (r < 0)
- return r;
- }
-
- r = unit_exec_context_defaults(u, &s->exec_context);
- if (r < 0)
- return r;
- }
-
- return swap_verify(s);
-}
-
-static int swap_add_one(
- Manager *m,
- const char *what,
- const char *what_proc_swaps,
- int priority,
- bool noauto,
- bool nofail,
- bool set_flags) {
-
- Unit *u = NULL;
- char _cleanup_free_ *e = NULL;
- char *wp = NULL;
- bool delete = false;
- int r;
- SwapParameters *p;
- Swap *first;
-
- assert(m);
- assert(what);
- assert(what_proc_swaps);
-
- e = unit_name_from_path(what, ".swap");
- if (!e)
- return log_oom();
-
- u = manager_get_unit(m, e);
-
- if (u &&
- SWAP(u)->from_proc_swaps &&
- !path_equal(SWAP(u)->parameters_proc_swaps.what, what_proc_swaps))
- return -EEXIST;
-
- if (!u) {
- delete = true;
-
- u = unit_new(m, sizeof(Swap));
- if (!u)
- return log_oom();
-
- r = unit_add_name(u, e);
- if (r < 0)
- goto fail;
-
- SWAP(u)->what = strdup(what);
- if (!SWAP(u)->what) {
- r = log_oom();
- goto fail;
- }
-
- unit_add_to_load_queue(u);
- } else
- delete = false;
-
- p = &SWAP(u)->parameters_proc_swaps;
-
- if (!p->what) {
- wp = strdup(what_proc_swaps);
- if (!wp) {
- r = log_oom();
- goto fail;
- }
-
- if (!m->swaps_by_proc_swaps) {
- m->swaps_by_proc_swaps = hashmap_new(string_hash_func, string_compare_func);
- if (!m->swaps_by_proc_swaps) {
- r = log_oom();
- goto fail;
- }
- }
-
- free(p->what);
- p->what = wp;
-
- first = hashmap_get(m->swaps_by_proc_swaps, wp);
- LIST_PREPEND(Swap, same_proc_swaps, first, SWAP(u));
-
- r = hashmap_replace(m->swaps_by_proc_swaps, wp, first);
- if (r < 0)
- goto fail;
- }
-
- if (set_flags) {
- SWAP(u)->is_active = true;
- SWAP(u)->just_activated = !SWAP(u)->from_proc_swaps;
- }
-
- SWAP(u)->from_proc_swaps = true;
-
- p->priority = priority;
- p->noauto = noauto;
- p->nofail = nofail;
-
- unit_add_to_dbus_queue(u);
-
- return 0;
-
-fail:
- log_warning("Failed to load swap unit: %s", strerror(-r));
-
- free(wp);
-
- if (delete && u)
- unit_free(u);
-
- return r;
-}
-
-static int swap_process_new_swap(Manager *m, const char *device, int prio, bool set_flags) {
- struct stat st;
- int r = 0, k;
-
- assert(m);
-
- if (stat(device, &st) >= 0 && S_ISBLK(st.st_mode)) {
- struct udev_device *d;
- const char *dn;
- struct udev_list_entry *item = NULL, *first = NULL;
-
- /* So this is a proper swap device. Create swap units
- * for all names this swap device is known under */
-
- d = udev_device_new_from_devnum(m->udev, 'b', st.st_rdev);
- if (!d)
- return log_oom();
-
- dn = udev_device_get_devnode(d);
- /* Skip dn==device, since that case will be handled below */
- if (dn && !streq(dn, device))
- r = swap_add_one(m, dn, device, prio, false, false, set_flags);
-
- /* Add additional units for all symlinks */
- first = udev_device_get_devlinks_list_entry(d);
- udev_list_entry_foreach(item, first) {
- const char *p;
-
- /* Don't bother with the /dev/block links */
- p = udev_list_entry_get_name(item);
-
- if (path_startswith(p, "/dev/block/"))
- continue;
-
- if (stat(p, &st) >= 0)
- if ((!S_ISBLK(st.st_mode)) ||
- st.st_rdev != udev_device_get_devnum(d))
- continue;
-
- k = swap_add_one(m, p, device, prio, false, false, set_flags);
- if (k < 0)
- r = k;
- }
-
- udev_device_unref(d);
- }
-
- k = swap_add_one(m, device, device, prio, false, false, set_flags);
- if (k < 0)
- r = k;
-
- return r;
-}
-
-static void swap_set_state(Swap *s, SwapState state) {
- SwapState old_state;
-
- assert(s);
-
- old_state = s->state;
- s->state = state;
-
- if (state != SWAP_ACTIVATING &&
- state != SWAP_ACTIVATING_SIGTERM &&
- state != SWAP_ACTIVATING_SIGKILL &&
- state != SWAP_DEACTIVATING &&
- state != SWAP_DEACTIVATING_SIGTERM &&
- state != SWAP_DEACTIVATING_SIGKILL) {
- unit_unwatch_timer(UNIT(s), &s->timer_watch);
- swap_unwatch_control_pid(s);
- s->control_command = NULL;
- s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
- }
-
- if (state != old_state)
- log_debug("%s changed %s -> %s",
- UNIT(s)->id,
- swap_state_to_string(old_state),
- swap_state_to_string(state));
-
- unit_notify(UNIT(s), state_translation_table[old_state],
- state_translation_table[state], true);
-}
-
-static int swap_coldplug(Unit *u) {
- Swap *s = SWAP(u);
- SwapState new_state = SWAP_DEAD;
- int r;
-
- assert(s);
- assert(s->state == SWAP_DEAD);
-
- if (s->deserialized_state != s->state)
- new_state = s->deserialized_state;
- else if (s->from_proc_swaps)
- new_state = SWAP_ACTIVE;
-
- if (new_state != s->state) {
-
- if (new_state == SWAP_ACTIVATING ||
- new_state == SWAP_ACTIVATING_SIGTERM ||
- new_state == SWAP_ACTIVATING_SIGKILL ||
- new_state == SWAP_DEACTIVATING ||
- new_state == SWAP_DEACTIVATING_SIGTERM ||
- new_state == SWAP_DEACTIVATING_SIGKILL) {
-
- if (s->control_pid <= 0)
- return -EBADMSG;
-
- r = unit_watch_pid(UNIT(s), s->control_pid);
- if (r < 0)
- return r;
-
- r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch);
- if (r < 0)
- return r;
- }
-
- swap_set_state(s, new_state);
- }
-
- return 0;
-}
-
-static void swap_dump(Unit *u, FILE *f, const char *prefix) {
- Swap *s = SWAP(u);
- SwapParameters *p;
-
- assert(s);
- assert(f);
-
- if (s->from_proc_swaps)
- p = &s->parameters_proc_swaps;
- else if (s->from_fragment)
- p = &s->parameters_fragment;
- else
- p = NULL;
-
- fprintf(f,
- "%sSwap State: %s\n"
- "%sResult: %s\n"
- "%sWhat: %s\n"
- "%sFrom /proc/swaps: %s\n"
- "%sFrom fragment: %s\n",
- prefix, swap_state_to_string(s->state),
- prefix, swap_result_to_string(s->result),
- prefix, s->what,
- prefix, yes_no(s->from_proc_swaps),
- prefix, yes_no(s->from_fragment));
-
- if (p)
- fprintf(f,
- "%sPriority: %i\n"
- "%sNoAuto: %s\n"
- "%sNoFail: %s\n",
- prefix, p->priority,
- prefix, yes_no(p->noauto),
- prefix, yes_no(p->nofail));
-
- if (s->control_pid > 0)
- fprintf(f,
- "%sControl PID: %lu\n",
- prefix, (unsigned long) s->control_pid);
-
- exec_context_dump(&s->exec_context, f, prefix);
- kill_context_dump(&s->kill_context, f, prefix);
-}
-
-static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
- pid_t pid;
- int r;
-
- assert(s);
- assert(c);
- assert(_pid);
-
- r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch);
- if (r < 0)
- goto fail;
-
- r = exec_spawn(c,
- NULL,
- &s->exec_context,
- NULL, 0,
- UNIT(s)->manager->environment,
- true,
- true,
- true,
- UNIT(s)->manager->confirm_spawn,
- UNIT(s)->cgroup_bondings,
- UNIT(s)->cgroup_attributes,
- NULL,
- UNIT(s)->id,
- NULL,
- &pid);
- if (r < 0)
- goto fail;
-
- r = unit_watch_pid(UNIT(s), pid);
- if (r < 0)
- /* FIXME: we need to do something here */
- goto fail;
-
- *_pid = pid;
-
- return 0;
-
-fail:
- unit_unwatch_timer(UNIT(s), &s->timer_watch);
-
- return r;
-}
-
-static void swap_enter_dead(Swap *s, SwapResult f) {
- assert(s);
-
- if (f != SWAP_SUCCESS)
- s->result = f;
-
- swap_set_state(s, s->result != SWAP_SUCCESS ? SWAP_FAILED : SWAP_DEAD);
-}
-
-static void swap_enter_active(Swap *s, SwapResult f) {
- assert(s);
-
- if (f != SWAP_SUCCESS)
- s->result = f;
-
- swap_set_state(s, SWAP_ACTIVE);
-}
-
-static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
- int r;
- Set *pid_set = NULL;
- bool wait_for_exit = false;
-
- assert(s);
-
- if (f != SWAP_SUCCESS)
- s->result = f;
-
- if (s->kill_context.kill_mode != KILL_NONE) {
- int sig = (state == SWAP_ACTIVATING_SIGTERM ||
- state == SWAP_DEACTIVATING_SIGTERM) ? s->kill_context.kill_signal : SIGKILL;
-
- if (s->control_pid > 0) {
- if (kill_and_sigcont(s->control_pid, sig) < 0 && errno != ESRCH)
-
- log_warning("Failed to kill control process %li: %m", (long) s->control_pid);
- else
- wait_for_exit = true;
- }
-
- if (s->kill_context.kill_mode == KILL_CONTROL_GROUP) {
-
- pid_set = set_new(trivial_hash_func, trivial_compare_func);
- if (!pid_set) {
- r = log_oom();
- goto fail;
- }
-
- /* Exclude the control pid from being killed via the cgroup */
- if (s->control_pid > 0) {
- r = set_put(pid_set, LONG_TO_PTR(s->control_pid));
- if (r < 0)
- goto fail;
- }
-
- r = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, sig, true, false, pid_set, NULL);
- if (r < 0) {
- if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
- log_warning("Failed to kill control group: %s", strerror(-r));
- } else if (r > 0)
- wait_for_exit = true;
-
- set_free(pid_set);
- pid_set = NULL;
- }
- }
-
- if (wait_for_exit) {
- r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch);
- if (r < 0)
- goto fail;
-
- swap_set_state(s, state);
- } else
- swap_enter_dead(s, SWAP_SUCCESS);
-
- return;
-
-fail:
- log_warning("%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));
-
- swap_enter_dead(s, SWAP_FAILURE_RESOURCES);
-
- if (pid_set)
- set_free(pid_set);
-}
-
-static void swap_enter_activating(Swap *s) {
- int r, priority;
-
- assert(s);
-
- s->control_command_id = SWAP_EXEC_ACTIVATE;
- s->control_command = s->exec_command + SWAP_EXEC_ACTIVATE;
-
- if (s->from_fragment)
- priority = s->parameters_fragment.priority;
- else
- priority = -1;
-
- if (priority >= 0) {
- char p[LINE_MAX];
-
- snprintf(p, sizeof(p), "%i", priority);
- char_array_0(p);
-
- r = exec_command_set(
- s->control_command,
- "/sbin/swapon",
- "-p",
- p,
- s->what,
- NULL);
- } else
- r = exec_command_set(
- s->control_command,
- "/sbin/swapon",
- s->what,
- NULL);
-
- if (r < 0)
- goto fail;
-
- swap_unwatch_control_pid(s);
-
- r = swap_spawn(s, s->control_command, &s->control_pid);
- if (r < 0)
- goto fail;
-
- swap_set_state(s, SWAP_ACTIVATING);
-
- return;
-
-fail:
- log_warning("%s failed to run 'swapon' task: %s", UNIT(s)->id, strerror(-r));
- swap_enter_dead(s, SWAP_FAILURE_RESOURCES);
-}
-
-static void swap_enter_deactivating(Swap *s) {
- int r;
-
- assert(s);
-
- s->control_command_id = SWAP_EXEC_DEACTIVATE;
- s->control_command = s->exec_command + SWAP_EXEC_DEACTIVATE;
-
- r = exec_command_set(s->control_command,
- "/sbin/swapoff",
- s->what,
- NULL);
- if (r < 0)
- goto fail;
-
- swap_unwatch_control_pid(s);
-
- r = swap_spawn(s, s->control_command, &s->control_pid);
- if (r < 0)
- goto fail;
-
- swap_set_state(s, SWAP_DEACTIVATING);
-
- return;
-
-fail:
- log_warning("%s failed to run 'swapoff' task: %s", UNIT(s)->id, strerror(-r));
- swap_enter_active(s, SWAP_FAILURE_RESOURCES);
-}
-
-static int swap_start(Unit *u) {
- Swap *s = SWAP(u);
-
- assert(s);
-
- /* We cannot fulfill this request right now, try again later
- * please! */
-
- if (s->state == SWAP_DEACTIVATING ||
- s->state == SWAP_DEACTIVATING_SIGTERM ||
- s->state == SWAP_DEACTIVATING_SIGKILL ||
- s->state == SWAP_ACTIVATING_SIGTERM ||
- s->state == SWAP_ACTIVATING_SIGKILL)
- return -EAGAIN;
-
- if (s->state == SWAP_ACTIVATING)
- return 0;
-
- assert(s->state == SWAP_DEAD || s->state == SWAP_FAILED);
-
- if (detect_container(NULL) > 0)
- return -EPERM;
-
- s->result = SWAP_SUCCESS;
- swap_enter_activating(s);
- return 0;
-}
-
-static int swap_stop(Unit *u) {
- Swap *s = SWAP(u);
-
- assert(s);
-
- if (s->state == SWAP_DEACTIVATING ||
- s->state == SWAP_DEACTIVATING_SIGTERM ||
- s->state == SWAP_DEACTIVATING_SIGKILL ||
- s->state == SWAP_ACTIVATING_SIGTERM ||
- s->state == SWAP_ACTIVATING_SIGKILL)
- return 0;
-
- assert(s->state == SWAP_ACTIVATING ||
- s->state == SWAP_ACTIVE);
-
- if (detect_container(NULL) > 0)
- return -EPERM;
-
- swap_enter_deactivating(s);
- return 0;
-}
-
-static int swap_serialize(Unit *u, FILE *f, FDSet *fds) {
- Swap *s = SWAP(u);
-
- assert(s);
- assert(f);
- assert(fds);
-
- unit_serialize_item(u, f, "state", swap_state_to_string(s->state));
- unit_serialize_item(u, f, "result", swap_result_to_string(s->result));
-
- if (s->control_pid > 0)
- unit_serialize_item_format(u, f, "control-pid", "%lu", (unsigned long) s->control_pid);
-
- if (s->control_command_id >= 0)
- unit_serialize_item(u, f, "control-command", swap_exec_command_to_string(s->control_command_id));
-
- return 0;
-}
-
-static int swap_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
- Swap *s = SWAP(u);
-
- assert(s);
- assert(fds);
-
- if (streq(key, "state")) {
- SwapState state;
-
- state = swap_state_from_string(value);
- if (state < 0)
- log_debug("Failed to parse state value %s", value);
- else
- s->deserialized_state = state;
- } else if (streq(key, "result")) {
- SwapResult f;
-
- f = swap_result_from_string(value);
- if (f < 0)
- log_debug("Failed to parse result value %s", value);
- else if (f != SWAP_SUCCESS)
- s->result = f;
- } else if (streq(key, "control-pid")) {
- pid_t pid;
-
- if (parse_pid(value, &pid) < 0)
- log_debug("Failed to parse control-pid value %s", value);
- else
- s->control_pid = pid;
-
- } else if (streq(key, "control-command")) {
- SwapExecCommand id;
-
- id = swap_exec_command_from_string(value);
- if (id < 0)
- log_debug("Failed to parse exec-command value %s", value);
- else {
- s->control_command_id = id;
- s->control_command = s->exec_command + id;
- }
-
- } else
- log_debug("Unknown serialization key '%s'", key);
-
- return 0;
-}
-
-static UnitActiveState swap_active_state(Unit *u) {
- assert(u);
-
- return state_translation_table[SWAP(u)->state];
-}
-
-static const char *swap_sub_state_to_string(Unit *u) {
- assert(u);
-
- return swap_state_to_string(SWAP(u)->state);
-}
-
-static bool swap_check_gc(Unit *u) {
- Swap *s = SWAP(u);
-
- assert(s);
-
- return s->from_proc_swaps;
-}
-
-static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
- Swap *s = SWAP(u);
- SwapResult f;
-
- assert(s);
- assert(pid >= 0);
-
- if (pid != s->control_pid)
- return;
-
- s->control_pid = 0;
-
- if (is_clean_exit(code, status, NULL))
- f = SWAP_SUCCESS;
- else if (code == CLD_EXITED)
- f = SWAP_FAILURE_EXIT_CODE;
- else if (code == CLD_KILLED)
- f = SWAP_FAILURE_SIGNAL;
- else if (code == CLD_DUMPED)
- f = SWAP_FAILURE_CORE_DUMP;
- else
- assert_not_reached("Unknown code");
-
- if (f != SWAP_SUCCESS)
- s->result = f;
-
- if (s->control_command) {
- exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status);
-
- s->control_command = NULL;
- s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
- }
-
- log_full(f == SWAP_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
- "%s swap process exited, code=%s status=%i", u->id, sigchld_code_to_string(code), status);
-
- switch (s->state) {
-
- case SWAP_ACTIVATING:
- case SWAP_ACTIVATING_SIGTERM:
- case SWAP_ACTIVATING_SIGKILL:
-
- if (f == SWAP_SUCCESS)
- swap_enter_active(s, f);
- else
- swap_enter_dead(s, f);
- break;
-
- case SWAP_DEACTIVATING:
- case SWAP_DEACTIVATING_SIGKILL:
- case SWAP_DEACTIVATING_SIGTERM:
-
- if (f == SWAP_SUCCESS)
- swap_enter_dead(s, f);
- else
- swap_enter_dead(s, f);
- break;
-
- default:
- assert_not_reached("Uh, control process died at wrong time.");
- }
-
- /* Notify clients about changed exit status */
- unit_add_to_dbus_queue(u);
-
- /* Request a reload of /proc/swaps, so that following units
- * can follow our state change */
- u->manager->request_reload = true;
-}
-
-static void swap_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
- Swap *s = SWAP(u);
-
- assert(s);
- assert(elapsed == 1);
- assert(w == &s->timer_watch);
-
- switch (s->state) {
-
- case SWAP_ACTIVATING:
- log_warning("%s activation timed out. Stopping.", u->id);
- swap_enter_signal(s, SWAP_ACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
- break;
-
- case SWAP_DEACTIVATING:
- log_warning("%s deactivation timed out. Stopping.", u->id);
- swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
- break;
-
- case SWAP_ACTIVATING_SIGTERM:
- if (s->kill_context.send_sigkill) {
- log_warning("%s activation timed out. Killing.", u->id);
- swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
- } else {
- log_warning("%s activation timed out. Skipping SIGKILL. Ignoring.", u->id);
- swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
- }
- break;
-
- case SWAP_DEACTIVATING_SIGTERM:
- if (s->kill_context.send_sigkill) {
- log_warning("%s deactivation timed out. Killing.", u->id);
- swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
- } else {
- log_warning("%s deactivation timed out. Skipping SIGKILL. Ignoring.", u->id);
- swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
- }
- break;
-
- case SWAP_ACTIVATING_SIGKILL:
- case SWAP_DEACTIVATING_SIGKILL:
- log_warning("%s swap process still around after SIGKILL. Ignoring.", u->id);
- swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
- break;
-
- default:
- assert_not_reached("Timeout at wrong time.");
- }
-}
-
-static int swap_load_proc_swaps(Manager *m, bool set_flags) {
- unsigned i;
- int r = 0;
-
- assert(m);
-
- rewind(m->proc_swaps);
-
- (void) fscanf(m->proc_swaps, "%*s %*s %*s %*s %*s\n");
-
- for (i = 1;; i++) {
- char *dev = NULL, *d;
- int prio = 0, k;
-
- k = fscanf(m->proc_swaps,
- "%ms " /* device/file */
- "%*s " /* type of swap */
- "%*s " /* swap size */
- "%*s " /* used */
- "%i\n", /* priority */
- &dev, &prio);
- if (k != 2) {
- if (k == EOF)
- break;
-
- log_warning("Failed to parse /proc/swaps:%u", i);
- free(dev);
- continue;
- }
-
- d = cunescape(dev);
- free(dev);
-
- if (!d)
- return -ENOMEM;
-
- k = swap_process_new_swap(m, d, prio, set_flags);
- free(d);
-
- if (k < 0)
- r = k;
- }
-
- return r;
-}
-
-int swap_dispatch_reload(Manager *m) {
- /* This function should go as soon as the kernel properly notifies us */
-
- if (_likely_(!m->request_reload))
- return 0;
-
- m->request_reload = false;
-
- return swap_fd_event(m, EPOLLPRI);
-}
-
-int swap_fd_event(Manager *m, int events) {
- Unit *u;
- int r;
-
- assert(m);
- assert(events & EPOLLPRI);
-
- r = swap_load_proc_swaps(m, true);
- if (r < 0) {
- log_error("Failed to reread /proc/swaps: %s", strerror(-r));
-
- /* Reset flags, just in case, for late calls */
- LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_SWAP]) {
- Swap *swap = SWAP(u);
-
- swap->is_active = swap->just_activated = false;
- }
-
- return 0;
- }
-
- manager_dispatch_load_queue(m);
-
- LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_SWAP]) {
- Swap *swap = SWAP(u);
-
- if (!swap->is_active) {
- /* This has just been deactivated */
-
- swap->from_proc_swaps = false;
- swap_unset_proc_swaps(swap);
-
- switch (swap->state) {
-
- case SWAP_ACTIVE:
- swap_enter_dead(swap, SWAP_SUCCESS);
- break;
-
- default:
- swap_set_state(swap, swap->state);
- break;
- }
-
- } else if (swap->just_activated) {
-
- /* New swap entry */
-
- switch (swap->state) {
-
- case SWAP_DEAD:
- case SWAP_FAILED:
- swap_enter_active(swap, SWAP_SUCCESS);
- break;
-
- default:
- /* Nothing really changed, but let's
- * issue an notification call
- * nonetheless, in case somebody is
- * waiting for this. */
- swap_set_state(swap, swap->state);
- break;
- }
- }
-
- /* Reset the flags for later calls */
- swap->is_active = swap->just_activated = false;
- }
-
- return 1;
-}
-
-static Unit *swap_following(Unit *u) {
- Swap *s = SWAP(u);
- Swap *other, *first = NULL;
-
- assert(s);
-
- if (streq_ptr(s->what, s->parameters_proc_swaps.what))
- return NULL;
-
- /* Make everybody follow the unit that's named after the swap
- * device in the kernel */
-
- LIST_FOREACH_AFTER(same_proc_swaps, other, s)
- if (streq_ptr(other->what, other->parameters_proc_swaps.what))
- return UNIT(other);
-
- LIST_FOREACH_BEFORE(same_proc_swaps, other, s) {
- if (streq_ptr(other->what, other->parameters_proc_swaps.what))
- return UNIT(other);
-
- first = other;
- }
-
- return UNIT(first);
-}
-
-static int swap_following_set(Unit *u, Set **_set) {
- Swap *s = SWAP(u);
- Swap *other;
- Set *set;
- int r;
-
- assert(s);
- assert(_set);
-
- if (LIST_JUST_US(same_proc_swaps, s)) {
- *_set = NULL;
- return 0;
- }
-
- if (!(set = set_new(NULL, NULL)))
- return -ENOMEM;
-
- LIST_FOREACH_AFTER(same_proc_swaps, other, s)
- if ((r = set_put(set, other)) < 0)
- goto fail;
-
- LIST_FOREACH_BEFORE(same_proc_swaps, other, s)
- if ((r = set_put(set, other)) < 0)
- goto fail;
-
- *_set = set;
- return 1;
-
-fail:
- set_free(set);
- return r;
-}
-
-static void swap_shutdown(Manager *m) {
- assert(m);
-
- if (m->proc_swaps) {
- fclose(m->proc_swaps);
- m->proc_swaps = NULL;
- }
-
- hashmap_free(m->swaps_by_proc_swaps);
- m->swaps_by_proc_swaps = NULL;
-}
-
-static int swap_enumerate(Manager *m) {
- int r;
- struct epoll_event ev;
- assert(m);
-
- if (!m->proc_swaps) {
- m->proc_swaps = fopen("/proc/swaps", "re");
- if (!m->proc_swaps)
- return (errno == ENOENT) ? 0 : -errno;
-
- m->swap_watch.type = WATCH_SWAP;
- m->swap_watch.fd = fileno(m->proc_swaps);
-
- zero(ev);
- ev.events = EPOLLPRI;
- ev.data.ptr = &m->swap_watch;
-
- if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->swap_watch.fd, &ev) < 0)
- return -errno;
- }
-
- r = swap_load_proc_swaps(m, false);
- if (r < 0)
- swap_shutdown(m);
-
- return r;
-}
-
-static void swap_reset_failed(Unit *u) {
- Swap *s = SWAP(u);
-
- assert(s);
-
- if (s->state == SWAP_FAILED)
- swap_set_state(s, SWAP_DEAD);
-
- s->result = SWAP_SUCCESS;
-}
-
-static int swap_kill(Unit *u, KillWho who, int signo, DBusError *error) {
- Swap *s = SWAP(u);
- int r = 0;
- Set *pid_set = NULL;
-
- assert(s);
-
- if (who == KILL_MAIN) {
- dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "Swap units have no main processes");
- return -ESRCH;
- }
-
- if (s->control_pid <= 0 && who == KILL_CONTROL) {
- dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
- return -ESRCH;
- }
-
- if (who == KILL_CONTROL || who == KILL_ALL)
- if (s->control_pid > 0)
- if (kill(s->control_pid, signo) < 0)
- r = -errno;
-
- if (who == KILL_ALL) {
- int q;
-
- pid_set = set_new(trivial_hash_func, trivial_compare_func);
- if (!pid_set)
- return -ENOMEM;
-
- /* Exclude the control pid from being killed via the cgroup */
- if (s->control_pid > 0) {
- q = set_put(pid_set, LONG_TO_PTR(s->control_pid));
- if (q < 0) {
- r = q;
- goto finish;
- }
- }
-
- q = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, signo, false, false, pid_set, NULL);
- if (q < 0 && q != -EAGAIN && q != -ESRCH && q != -ENOENT)
- r = q;
- }
-
-finish:
- if (pid_set)
- set_free(pid_set);
-
- return r;
-}
-
-static const char* const swap_state_table[_SWAP_STATE_MAX] = {
- [SWAP_DEAD] = "dead",
- [SWAP_ACTIVATING] = "activating",
- [SWAP_ACTIVE] = "active",
- [SWAP_DEACTIVATING] = "deactivating",
- [SWAP_ACTIVATING_SIGTERM] = "activating-sigterm",
- [SWAP_ACTIVATING_SIGKILL] = "activating-sigkill",
- [SWAP_DEACTIVATING_SIGTERM] = "deactivating-sigterm",
- [SWAP_DEACTIVATING_SIGKILL] = "deactivating-sigkill",
- [SWAP_FAILED] = "failed"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
-
-static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = {
- [SWAP_EXEC_ACTIVATE] = "ExecActivate",
- [SWAP_EXEC_DEACTIVATE] = "ExecDeactivate",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(swap_exec_command, SwapExecCommand);
-
-static const char* const swap_result_table[_SWAP_RESULT_MAX] = {
- [SWAP_SUCCESS] = "success",
- [SWAP_FAILURE_RESOURCES] = "resources",
- [SWAP_FAILURE_TIMEOUT] = "timeout",
- [SWAP_FAILURE_EXIT_CODE] = "exit-code",
- [SWAP_FAILURE_SIGNAL] = "signal",
- [SWAP_FAILURE_CORE_DUMP] = "core-dump"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(swap_result, SwapResult);
-
-const UnitVTable swap_vtable = {
- .object_size = sizeof(Swap),
- .exec_context_offset = offsetof(Swap, exec_context),
-
- .sections =
- "Unit\0"
- "Swap\0"
- "Install\0",
-
- .no_alias = true,
- .no_instances = true,
-
- .init = swap_init,
- .load = swap_load,
- .done = swap_done,
-
- .coldplug = swap_coldplug,
-
- .dump = swap_dump,
-
- .start = swap_start,
- .stop = swap_stop,
-
- .kill = swap_kill,
-
- .serialize = swap_serialize,
- .deserialize_item = swap_deserialize_item,
-
- .active_state = swap_active_state,
- .sub_state_to_string = swap_sub_state_to_string,
-
- .check_gc = swap_check_gc,
-
- .sigchld_event = swap_sigchld_event,
- .timer_event = swap_timer_event,
-
- .reset_failed = swap_reset_failed,
-
- .bus_interface = "org.freedesktop.systemd1.Swap",
- .bus_message_handler = bus_swap_message_handler,
- .bus_invalidating_properties = bus_swap_invalidating_properties,
-
- .following = swap_following,
- .following_set = swap_following_set,
-
- .enumerate = swap_enumerate,
- .shutdown = swap_shutdown,
-
- .status_message_formats = {
- .starting_stopping = {
- [0] = "Activating swap %s...",
- [1] = "Deactivating swap %s...",
- },
- .finished_start_job = {
- [JOB_DONE] = "Activated swap %s.",
- [JOB_FAILED] = "Failed to activate swap %s.",
- [JOB_DEPENDENCY] = "Dependency failed for %s.",
- [JOB_TIMEOUT] = "Timed out activating swap %s.",
- },
- .finished_stop_job = {
- [JOB_DONE] = "Deactivated swap %s.",
- [JOB_FAILED] = "Failed deactivating swap %s.",
- [JOB_TIMEOUT] = "Timed out deactivating swap %s.",
- },
- },
-};
diff --git a/src/core/swap.h b/src/core/swap.h
deleted file mode 100644
index 35d47fd46f..0000000000
--- a/src/core/swap.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2010 Maarten Lankhorst
-
- 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/>.
-***/
-
-typedef struct Swap Swap;
-
-#include "unit.h"
-
-typedef enum SwapState {
- SWAP_DEAD,
- SWAP_ACTIVATING,
- SWAP_ACTIVE,
- SWAP_DEACTIVATING,
- SWAP_ACTIVATING_SIGTERM,
- SWAP_ACTIVATING_SIGKILL,
- SWAP_DEACTIVATING_SIGTERM,
- SWAP_DEACTIVATING_SIGKILL,
- SWAP_FAILED,
- _SWAP_STATE_MAX,
- _SWAP_STATE_INVALID = -1
-} SwapState;
-
-typedef enum SwapExecCommand {
- SWAP_EXEC_ACTIVATE,
- SWAP_EXEC_DEACTIVATE,
- _SWAP_EXEC_COMMAND_MAX,
- _SWAP_EXEC_COMMAND_INVALID = -1
-} SwapExecCommand;
-
-typedef struct SwapParameters {
- char *what;
- int priority;
- bool noauto:1;
- bool nofail:1;
-} SwapParameters;
-
-typedef enum SwapResult {
- SWAP_SUCCESS,
- SWAP_FAILURE_RESOURCES,
- SWAP_FAILURE_TIMEOUT,
- SWAP_FAILURE_EXIT_CODE,
- SWAP_FAILURE_SIGNAL,
- SWAP_FAILURE_CORE_DUMP,
- _SWAP_RESULT_MAX,
- _SWAP_RESULT_INVALID = -1
-} SwapResult;
-
-struct Swap {
- Unit meta;
-
- char *what;
-
- SwapParameters parameters_proc_swaps;
- SwapParameters parameters_fragment;
-
- bool from_proc_swaps:1;
- bool from_fragment:1;
-
- /* Used while looking for swaps that vanished or got added
- * from/to /proc/swaps */
- bool is_active:1;
- bool just_activated:1;
-
- SwapResult result;
-
- usec_t timeout_usec;
-
- ExecCommand exec_command[_SWAP_EXEC_COMMAND_MAX];
- ExecContext exec_context;
- KillContext kill_context;
-
- SwapState state, deserialized_state;
-
- ExecCommand* control_command;
- SwapExecCommand control_command_id;
- pid_t control_pid;
-
- Watch timer_watch;
-
- /* In order to be able to distinguish dependencies on
- different device nodes we might end up creating multiple
- devices for the same swap. We chain them up here. */
-
- LIST_FIELDS(struct Swap, same_proc_swaps);
-};
-
-extern const UnitVTable swap_vtable;
-
-int swap_add_one_mount_link(Swap *s, Mount *m);
-
-int swap_dispatch_reload(Manager *m);
-int swap_fd_event(Manager *m, int events);
-
-const char* swap_state_to_string(SwapState i);
-SwapState swap_state_from_string(const char *s);
-
-const char* swap_exec_command_to_string(SwapExecCommand i);
-SwapExecCommand swap_exec_command_from_string(const char *s);
-
-const char* swap_result_to_string(SwapResult i);
-SwapResult swap_result_from_string(const char *s);
diff --git a/src/core/switch-root.c b/src/core/switch-root.c
deleted file mode 100644
index 150332a858..0000000000
--- a/src/core/switch-root.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Harald Hoyer, 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/stat.h>
-#include <stdbool.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/mount.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "util.h"
-#include "path-util.h"
-#include "switch-root.h"
-
-int switch_root(const char *new_root) {
-
- /* Don't try to unmount/move the old "/", there's no way to do it. */
- static const char move_mounts[] =
- "/dev\0"
- "/proc\0"
- "/sys\0"
- "/run\0";
-
- int r, old_root_fd = -1;
- struct stat new_root_stat;
- bool old_root_remove;
- const char *i;
-
- if (path_equal(new_root, "/"))
- return 0;
-
- old_root_remove = in_initrd();
-
- if (stat(new_root, &new_root_stat) < 0) {
- r = -errno;
- log_error("Failed to stat directory %s: %m", new_root);
- goto fail;
- }
-
- /* Work-around for a kernel bug: for some reason the kernel
- * refuses switching root if any file systems are mounted
- * MS_SHARED. Hence remount them MS_PRIVATE here as a
- * work-around.
- *
- * https://bugzilla.redhat.com/show_bug.cgi?id=847418 */
- if (mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL) < 0)
- log_warning("Failed to make \"/\" private mount: %m");
-
- NULSTR_FOREACH(i, move_mounts) {
- char new_mount[PATH_MAX];
- struct stat sb;
-
- snprintf(new_mount, sizeof(new_mount), "%s%s", new_root, i);
- char_array_0(new_mount);
-
- if ((stat(new_mount, &sb) < 0) ||
- sb.st_dev != new_root_stat.st_dev) {
-
- /* Mount point seems to be mounted already or
- * stat failed. Unmount the old mount
- * point. */
- if (umount2(i, MNT_DETACH) < 0)
- log_warning("Failed to unmount %s: %m", i);
- continue;
- }
-
- if (mount(i, new_mount, NULL, MS_MOVE, NULL) < 0) {
- log_error("Failed to move mount %s to %s, forcing unmount: %m", i, new_mount);
-
- if (umount2(i, MNT_FORCE) < 0)
- log_warning("Failed to unmount %s: %m", i);
- }
- }
-
- if (chdir(new_root) < 0) {
- r = -errno;
- log_error("Failed to change directory to %s: %m", new_root);
- goto fail;
- }
-
- if (old_root_remove) {
- old_root_fd = open("/", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY|O_DIRECTORY);
- if (old_root_fd < 0)
- log_warning("Failed to open root directory: %m");
- }
-
- if (mount(new_root, "/", NULL, MS_MOVE, NULL) < 0) {
- r = -errno;
- log_error("Failed to mount moving %s to /: %m", new_root);
- goto fail;
- }
-
- if (chroot(".") < 0) {
- r = -errno;
- log_error("Failed to change root: %m");
- goto fail;
- }
-
- if (chdir("/") < 0) {
- r = -errno;
- log_error("Failed to change directory: %m");
- goto fail;
- }
-
- if (old_root_fd >= 0) {
- struct stat rb;
-
- if (fstat(old_root_fd, &rb) < 0)
- log_warning("Failed to stat old root directory, leaving: %m");
- else {
- rm_rf_children(old_root_fd, false, false, &rb);
- old_root_fd = -1;
- }
- }
-
- r = 0;
-
-fail:
- if (old_root_fd >= 0)
- close_nointr_nofail(old_root_fd);
-
- return r;
-}
diff --git a/src/core/switch-root.h b/src/core/switch-root.h
deleted file mode 100644
index 0c4cd1e403..0000000000
--- a/src/core/switch-root.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef fooswitchroothfoo
-#define fooswitchroothfoo
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Harald Hoyer, 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 switch_root(const char *switch_root);
-
-#endif
diff --git a/src/core/syscall-list.c b/src/core/syscall-list.c
deleted file mode 100644
index 05fad3e158..0000000000
--- a/src/core/syscall-list.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <sys/syscall.h>
-#include <string.h>
-
-#include "util.h"
-
-#include "syscall-list.h"
-
-const struct syscall_name *lookup_syscall(register const char *str, register unsigned int len);
-
-#include "syscall-to-name.h"
-#include "syscall-from-name.h"
-
-const char *syscall_to_name(int id) {
- if (id < 0 || id >= (int) ELEMENTSOF(syscall_names))
- return NULL;
-
- return syscall_names[id];
-}
-
-int syscall_from_name(const char *name) {
- const struct syscall_name *sc;
-
- assert(name);
-
- sc = lookup_syscall(name, strlen(name));
- if (!sc)
- return -1;
-
- return sc->id;
-}
-
-int syscall_max(void) {
- return ELEMENTSOF(syscall_names);
-}
diff --git a/src/core/syscall-list.h b/src/core/syscall-list.h
deleted file mode 100644
index 0fc6859605..0000000000
--- a/src/core/syscall-list.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef foosyscalllisthfoo
-#define foosyscalllisthfoo
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-const char *syscall_to_name(int id);
-int syscall_from_name(const char *name);
-
-int syscall_max(void);
-
-#endif
diff --git a/src/core/sysfs-show.h b/src/core/sysfs-show.h
deleted file mode 100644
index 9ffd129c48..0000000000
--- a/src/core/sysfs-show.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 show_sysfs(const char *seat, const char *prefix, unsigned columns);
diff --git a/src/core/system.conf b/src/core/system.conf
deleted file mode 100644
index 68076d9735..0000000000
--- a/src/core/system.conf
+++ /dev/null
@@ -1,43 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# See systemd.conf(5) for details
-
-[Manager]
-#LogLevel=info
-#LogTarget=journal-or-kmsg
-#LogColor=yes
-#LogLocation=no
-#DumpCore=yes
-#CrashShell=no
-#ShowStatus=yes
-#CrashChVT=1
-#CPUAffinity=1 2
-#DefaultControllers=cpu
-#DefaultStandardOutput=journal
-#DefaultStandardError=inherit
-#JoinControllers=cpu,cpuacct,cpuset net_cls,net_prio
-#RuntimeWatchdogSec=0
-#ShutdownWatchdogSec=10min
-#CapabilityBoundingSet=
-#TimerSlackNSec=
-#DefaultLimitCPU=
-#DefaultLimitFSIZE=
-#DefaultLimitDATA=
-#DefaultLimitSTACK=
-#DefaultLimitCORE=
-#DefaultLimitRSS=
-#DefaultLimitNOFILE=
-#DefaultLimitAS=
-#DefaultLimitNPROC=
-#DefaultLimitMEMLOCK=
-#DefaultLimitLOCKS=
-#DefaultLimitSIGPENDING=
-#DefaultLimitMSGQUEUE=
-#DefaultLimitNICE=
-#DefaultLimitRTPRIO=
-#DefaultLimitRTTIME=
diff --git a/src/core/systemd.pc.in b/src/core/systemd.pc.in
deleted file mode 100644
index 2f49d5df52..0000000000
--- a/src/core/systemd.pc.in
+++ /dev/null
@@ -1,23 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-systemdutildir=@rootlibexecdir@
-systemdsystemunitdir=@systemunitdir@
-systemdsystempresetdir=@systempresetdir@
-systemduserunitdir=@userunitdir@
-systemduserpresetdir=@userpresetdir@
-systemdsystemconfdir=@pkgsysconfdir@/system
-systemduserconfdir=@pkgsysconfdir@/user
-systemdsystemunitpath=${systemdsystemconfdir}:/etc/systemd/system:/run/systemd/system:/usr/local/lib/systemd/system:${systemdsystemunitdir}:/usr/lib/systemd/system:/lib/systemd/system
-systemduserunitpath=${systemduserconfdir}:/etc/systemd/user:/run/systemd/user:/usr/local/lib/systemd/user:/usr/local/share/systemd/user:${systemduserunitdir}:/usr/lib/systemd/user:/usr/share/systemd/user
-
-Name: systemd
-Description: systemd System and Service Manager
-URL: @PACKAGE_URL@
-Version: @PACKAGE_VERSION@
diff --git a/src/core/target.c b/src/core/target.c
deleted file mode 100644
index 981424132b..0000000000
--- a/src/core/target.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/*-*- 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 <errno.h>
-#include <signal.h>
-#include <unistd.h>
-
-#include "unit.h"
-#include "target.h"
-#include "load-fragment.h"
-#include "log.h"
-#include "dbus-target.h"
-#include "special.h"
-#include "unit-name.h"
-
-static const UnitActiveState state_translation_table[_TARGET_STATE_MAX] = {
- [TARGET_DEAD] = UNIT_INACTIVE,
- [TARGET_ACTIVE] = UNIT_ACTIVE
-};
-
-static void target_set_state(Target *t, TargetState state) {
- TargetState old_state;
- assert(t);
-
- old_state = t->state;
- t->state = state;
-
- if (state != old_state)
- log_debug("%s changed %s -> %s",
- UNIT(t)->id,
- target_state_to_string(old_state),
- target_state_to_string(state));
-
- unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], true);
-}
-
-static int target_add_default_dependencies(Target *t) {
-
- static const UnitDependency deps[] = {
- UNIT_REQUIRES,
- UNIT_REQUIRES_OVERRIDABLE,
- UNIT_REQUISITE,
- UNIT_REQUISITE_OVERRIDABLE,
- UNIT_WANTS,
- UNIT_BINDS_TO,
- UNIT_PART_OF
- };
-
- Iterator i;
- Unit *other;
- int r;
- unsigned k;
-
- assert(t);
-
- /* Imply ordering for requirement dependencies on target
- * units. Note that when the user created a contradicting
- * ordering manually we won't add anything in here to make
- * sure we don't create a loop. */
-
- for (k = 0; k < ELEMENTSOF(deps); k++)
- SET_FOREACH(other, UNIT(t)->dependencies[deps[k]], i) {
- r = unit_add_default_target_dependency(other, UNIT(t));
- if (r < 0)
- return r;
- }
-
- /* Make sure targets are unloaded on shutdown */
- return unit_add_dependency_by_name(UNIT(t), UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
-}
-
-static int target_load(Unit *u) {
- Target *t = TARGET(u);
- int r;
-
- assert(t);
-
- r = unit_load_fragment_and_dropin(u);
- if (r < 0)
- return r;
-
- /* This is a new unit? Then let's add in some extras */
- if (u->load_state == UNIT_LOADED && u->default_dependencies) {
- r = target_add_default_dependencies(t);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-static int target_coldplug(Unit *u) {
- Target *t = TARGET(u);
-
- assert(t);
- assert(t->state == TARGET_DEAD);
-
- if (t->deserialized_state != t->state)
- target_set_state(t, t->deserialized_state);
-
- return 0;
-}
-
-static void target_dump(Unit *u, FILE *f, const char *prefix) {
- Target *t = TARGET(u);
-
- assert(t);
- assert(f);
-
- fprintf(f,
- "%sTarget State: %s\n",
- prefix, target_state_to_string(t->state));
-}
-
-static int target_start(Unit *u) {
- Target *t = TARGET(u);
-
- assert(t);
- assert(t->state == TARGET_DEAD);
-
- target_set_state(t, TARGET_ACTIVE);
- return 0;
-}
-
-static int target_stop(Unit *u) {
- Target *t = TARGET(u);
-
- assert(t);
- assert(t->state == TARGET_ACTIVE);
-
- target_set_state(t, TARGET_DEAD);
- return 0;
-}
-
-static int target_serialize(Unit *u, FILE *f, FDSet *fds) {
- Target *s = TARGET(u);
-
- assert(s);
- assert(f);
- assert(fds);
-
- unit_serialize_item(u, f, "state", target_state_to_string(s->state));
- return 0;
-}
-
-static int target_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
- Target *s = TARGET(u);
-
- assert(u);
- assert(key);
- assert(value);
- assert(fds);
-
- if (streq(key, "state")) {
- TargetState state;
-
- state = target_state_from_string(value);
- if (state < 0)
- log_debug("Failed to parse state value %s", value);
- else
- s->deserialized_state = state;
-
- } else
- log_debug("Unknown serialization key '%s'", key);
-
- return 0;
-}
-
-static UnitActiveState target_active_state(Unit *u) {
- assert(u);
-
- return state_translation_table[TARGET(u)->state];
-}
-
-static const char *target_sub_state_to_string(Unit *u) {
- assert(u);
-
- return target_state_to_string(TARGET(u)->state);
-}
-
-static const char* const target_state_table[_TARGET_STATE_MAX] = {
- [TARGET_DEAD] = "dead",
- [TARGET_ACTIVE] = "active"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(target_state, TargetState);
-
-const UnitVTable target_vtable = {
- .object_size = sizeof(Target),
- .sections =
- "Unit\0"
- "Target\0"
- "Install\0",
-
- .load = target_load,
- .coldplug = target_coldplug,
-
- .dump = target_dump,
-
- .start = target_start,
- .stop = target_stop,
-
- .serialize = target_serialize,
- .deserialize_item = target_deserialize_item,
-
- .active_state = target_active_state,
- .sub_state_to_string = target_sub_state_to_string,
-
- .bus_interface = "org.freedesktop.systemd1.Target",
- .bus_message_handler = bus_target_message_handler,
-
- .status_message_formats = {
- .finished_start_job = {
- [JOB_DONE] = "Reached target %s.",
- [JOB_DEPENDENCY] = "Dependency failed for %s.",
- },
- .finished_stop_job = {
- [JOB_DONE] = "Stopped target %s.",
- },
- },
-};
diff --git a/src/core/target.h b/src/core/target.h
deleted file mode 100644
index 1676553add..0000000000
--- a/src/core/target.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*-*- 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/>.
-***/
-
-typedef struct Target Target;
-
-#include "unit.h"
-
-typedef enum TargetState {
- TARGET_DEAD,
- TARGET_ACTIVE,
- _TARGET_STATE_MAX,
- _TARGET_STATE_INVALID = -1
-} TargetState;
-
-struct Target {
- Unit meta;
-
- TargetState state, deserialized_state;
-};
-
-extern const UnitVTable target_vtable;
-
-const char* target_state_to_string(TargetState i);
-TargetState target_state_from_string(const char *s);
diff --git a/src/core/tcpwrap.c b/src/core/tcpwrap.c
deleted file mode 100644
index 6c630fac60..0000000000
--- a/src/core/tcpwrap.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*-*- 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/socket.h>
-#include <sys/un.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-
-#ifdef HAVE_LIBWRAP
-#include <tcpd.h>
-#endif
-
-#include "tcpwrap.h"
-#include "log.h"
-
-bool socket_tcpwrap(int fd, const char *name) {
-#ifdef HAVE_LIBWRAP
- struct request_info req;
- union {
- struct sockaddr sa;
- struct sockaddr_in in;
- struct sockaddr_in6 in6;
- struct sockaddr_un un;
- struct sockaddr_storage storage;
- } sa_union;
- socklen_t l = sizeof(sa_union);
-
- if (getsockname(fd, &sa_union.sa, &l) < 0)
- return true;
-
- if (sa_union.sa.sa_family != AF_INET &&
- sa_union.sa.sa_family != AF_INET6)
- return true;
-
- request_init(&req,
- RQ_DAEMON, name,
- RQ_FILE, fd,
- NULL);
-
- fromhost(&req);
-
- if (!hosts_access(&req)) {
- log_warning("Connection refused by tcpwrap.");
- return false;
- }
-
- log_debug("Connection accepted by tcpwrap.");
-#endif
- return true;
-}
diff --git a/src/core/tcpwrap.h b/src/core/tcpwrap.h
deleted file mode 100644
index 3353b6596e..0000000000
--- a/src/core/tcpwrap.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*-*- 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>
-
-bool socket_tcpwrap(int fd, const char *name);
diff --git a/src/core/timer.c b/src/core/timer.c
deleted file mode 100644
index 7080b32c6b..0000000000
--- a/src/core/timer.c
+++ /dev/null
@@ -1,519 +0,0 @@
-/*-*- 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 <errno.h>
-
-#include "unit.h"
-#include "unit-name.h"
-#include "timer.h"
-#include "dbus-timer.h"
-#include "special.h"
-#include "bus-errors.h"
-
-static const UnitActiveState state_translation_table[_TIMER_STATE_MAX] = {
- [TIMER_DEAD] = UNIT_INACTIVE,
- [TIMER_WAITING] = UNIT_ACTIVE,
- [TIMER_RUNNING] = UNIT_ACTIVE,
- [TIMER_ELAPSED] = UNIT_ACTIVE,
- [TIMER_FAILED] = UNIT_FAILED
-};
-
-static void timer_init(Unit *u) {
- Timer *t = TIMER(u);
-
- assert(u);
- assert(u->load_state == UNIT_STUB);
-
- t->next_elapse = (usec_t) -1;
-}
-
-static void timer_done(Unit *u) {
- Timer *t = TIMER(u);
- TimerValue *v;
-
- assert(t);
-
- while ((v = t->values)) {
- LIST_REMOVE(TimerValue, value, t->values, v);
- free(v);
- }
-
- unit_unwatch_timer(u, &t->timer_watch);
-
- unit_ref_unset(&t->unit);
-}
-
-static int timer_verify(Timer *t) {
- assert(t);
-
- if (UNIT(t)->load_state != UNIT_LOADED)
- return 0;
-
- if (!t->values) {
- log_error("%s lacks value setting. Refusing.", UNIT(t)->id);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int timer_add_default_dependencies(Timer *t) {
- int r;
-
- assert(t);
-
- if (UNIT(t)->manager->running_as == SYSTEMD_SYSTEM) {
- if ((r = unit_add_dependency_by_name(UNIT(t), UNIT_BEFORE, SPECIAL_BASIC_TARGET, NULL, true)) < 0)
- return r;
-
- if ((r = unit_add_two_dependencies_by_name(UNIT(t), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true)) < 0)
- return r;
- }
-
- return unit_add_two_dependencies_by_name(UNIT(t), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
-}
-
-static int timer_load(Unit *u) {
- Timer *t = TIMER(u);
- int r;
-
- assert(u);
- assert(u->load_state == UNIT_STUB);
-
- if ((r = unit_load_fragment_and_dropin(u)) < 0)
- return r;
-
- if (u->load_state == UNIT_LOADED) {
-
- if (!UNIT_DEREF(t->unit)) {
- Unit *x;
-
- r = unit_load_related_unit(u, ".service", &x);
- if (r < 0)
- return r;
-
- unit_ref_set(&t->unit, x);
- }
-
- r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(t->unit), true);
- if (r < 0)
- return r;
-
- if (UNIT(t)->default_dependencies)
- if ((r = timer_add_default_dependencies(t)) < 0)
- return r;
- }
-
- return timer_verify(t);
-}
-
-static void timer_dump(Unit *u, FILE *f, const char *prefix) {
- Timer *t = TIMER(u);
- TimerValue *v;
- char
- timespan1[FORMAT_TIMESPAN_MAX];
-
- fprintf(f,
- "%sTimer State: %s\n"
- "%sResult: %s\n"
- "%sUnit: %s\n",
- prefix, timer_state_to_string(t->state),
- prefix, timer_result_to_string(t->result),
- prefix, UNIT_DEREF(t->unit)->id);
-
- LIST_FOREACH(value, v, t->values)
- fprintf(f,
- "%s%s: %s\n",
- prefix,
- timer_base_to_string(v->base),
- strna(format_timespan(timespan1, sizeof(timespan1), v->value)));
-}
-
-static void timer_set_state(Timer *t, TimerState state) {
- TimerState old_state;
- assert(t);
-
- old_state = t->state;
- t->state = state;
-
- if (state != TIMER_WAITING)
- unit_unwatch_timer(UNIT(t), &t->timer_watch);
-
- if (state != old_state)
- log_debug("%s changed %s -> %s",
- UNIT(t)->id,
- timer_state_to_string(old_state),
- timer_state_to_string(state));
-
- unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], true);
-}
-
-static void timer_enter_waiting(Timer *t, bool initial);
-
-static int timer_coldplug(Unit *u) {
- Timer *t = TIMER(u);
-
- assert(t);
- assert(t->state == TIMER_DEAD);
-
- if (t->deserialized_state != t->state) {
-
- if (t->deserialized_state == TIMER_WAITING)
- timer_enter_waiting(t, false);
- else
- timer_set_state(t, t->deserialized_state);
- }
-
- return 0;
-}
-
-static void timer_enter_dead(Timer *t, TimerResult f) {
- assert(t);
-
- if (f != TIMER_SUCCESS)
- t->result = f;
-
- timer_set_state(t, t->result != TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD);
-}
-
-static void timer_enter_waiting(Timer *t, bool initial) {
- TimerValue *v;
- usec_t base = 0, delay, n;
- bool found = false;
- int r;
-
- n = now(CLOCK_MONOTONIC);
-
- LIST_FOREACH(value, v, t->values) {
-
- if (v->disabled)
- continue;
-
- switch (v->base) {
-
- case TIMER_ACTIVE:
- if (state_translation_table[t->state] == UNIT_ACTIVE)
- base = UNIT(t)->inactive_exit_timestamp.monotonic;
- else
- base = n;
- break;
-
- case TIMER_BOOT:
- /* CLOCK_MONOTONIC equals the uptime on Linux */
- base = 0;
- break;
-
- case TIMER_STARTUP:
- base = UNIT(t)->manager->userspace_timestamp.monotonic;
- break;
-
- case TIMER_UNIT_ACTIVE:
-
- if (UNIT_DEREF(t->unit)->inactive_exit_timestamp.monotonic <= 0)
- continue;
-
- base = UNIT_DEREF(t->unit)->inactive_exit_timestamp.monotonic;
- break;
-
- case TIMER_UNIT_INACTIVE:
-
- if (UNIT_DEREF(t->unit)->inactive_enter_timestamp.monotonic <= 0)
- continue;
-
- base = UNIT_DEREF(t->unit)->inactive_enter_timestamp.monotonic;
- break;
-
- default:
- assert_not_reached("Unknown timer base");
- }
-
- v->next_elapse = base + v->value;
-
- if (!initial && v->next_elapse < n) {
- v->disabled = true;
- continue;
- }
-
- if (!found)
- t->next_elapse = v->next_elapse;
- else
- t->next_elapse = MIN(t->next_elapse, v->next_elapse);
-
- found = true;
- }
-
- if (!found) {
- timer_set_state(t, TIMER_ELAPSED);
- return;
- }
-
- delay = n < t->next_elapse ? t->next_elapse - n : 0;
-
- if ((r = unit_watch_timer(UNIT(t), delay, &t->timer_watch)) < 0)
- goto fail;
-
- timer_set_state(t, TIMER_WAITING);
- return;
-
-fail:
- log_warning("%s failed to enter waiting state: %s", UNIT(t)->id, strerror(-r));
- timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
-}
-
-static void timer_enter_running(Timer *t) {
- DBusError error;
- int r;
-
- assert(t);
- dbus_error_init(&error);
-
- /* Don't start job if we are supposed to go down */
- if (UNIT(t)->job && UNIT(t)->job->type == JOB_STOP)
- return;
-
- if ((r = manager_add_job(UNIT(t)->manager, JOB_START, UNIT_DEREF(t->unit), JOB_REPLACE, true, &error, NULL)) < 0)
- goto fail;
-
- timer_set_state(t, TIMER_RUNNING);
- return;
-
-fail:
- log_warning("%s failed to queue unit startup job: %s", UNIT(t)->id, bus_error(&error, r));
- timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
-
- dbus_error_free(&error);
-}
-
-static int timer_start(Unit *u) {
- Timer *t = TIMER(u);
-
- assert(t);
- assert(t->state == TIMER_DEAD || t->state == TIMER_FAILED);
-
- if (UNIT_DEREF(t->unit)->load_state != UNIT_LOADED)
- return -ENOENT;
-
- t->result = TIMER_SUCCESS;
- timer_enter_waiting(t, true);
- return 0;
-}
-
-static int timer_stop(Unit *u) {
- Timer *t = TIMER(u);
-
- assert(t);
- assert(t->state == TIMER_WAITING || t->state == TIMER_RUNNING || t->state == TIMER_ELAPSED);
-
- timer_enter_dead(t, TIMER_SUCCESS);
- return 0;
-}
-
-static int timer_serialize(Unit *u, FILE *f, FDSet *fds) {
- Timer *t = TIMER(u);
-
- assert(u);
- assert(f);
- assert(fds);
-
- unit_serialize_item(u, f, "state", timer_state_to_string(t->state));
- unit_serialize_item(u, f, "result", timer_result_to_string(t->result));
-
- return 0;
-}
-
-static int timer_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
- Timer *t = TIMER(u);
-
- assert(u);
- assert(key);
- assert(value);
- assert(fds);
-
- if (streq(key, "state")) {
- TimerState state;
-
- if ((state = timer_state_from_string(value)) < 0)
- log_debug("Failed to parse state value %s", value);
- else
- t->deserialized_state = state;
- } else if (streq(key, "result")) {
- TimerResult f;
-
- f = timer_result_from_string(value);
- if (f < 0)
- log_debug("Failed to parse result value %s", value);
- else if (f != TIMER_SUCCESS)
- t->result = f;
-
- } else
- log_debug("Unknown serialization key '%s'", key);
-
- return 0;
-}
-
-static UnitActiveState timer_active_state(Unit *u) {
- assert(u);
-
- return state_translation_table[TIMER(u)->state];
-}
-
-static const char *timer_sub_state_to_string(Unit *u) {
- assert(u);
-
- return timer_state_to_string(TIMER(u)->state);
-}
-
-static void timer_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
- Timer *t = TIMER(u);
-
- assert(t);
- assert(elapsed == 1);
-
- if (t->state != TIMER_WAITING)
- return;
-
- log_debug("Timer elapsed on %s", u->id);
- timer_enter_running(t);
-}
-
-void timer_unit_notify(Unit *u, UnitActiveState new_state) {
- Iterator i;
- Unit *k;
-
- if (u->type == UNIT_TIMER)
- return;
-
- SET_FOREACH(k, u->dependencies[UNIT_TRIGGERED_BY], i) {
- Timer *t;
- TimerValue *v;
-
- if (k->type != UNIT_TIMER)
- continue;
-
- if (k->load_state != UNIT_LOADED)
- continue;
-
- t = TIMER(k);
-
- /* Reenable all timers that depend on unit state */
- LIST_FOREACH(value, v, t->values)
- if (v->base == TIMER_UNIT_ACTIVE ||
- v->base == TIMER_UNIT_INACTIVE)
- v->disabled = false;
-
- switch (t->state) {
-
- case TIMER_WAITING:
- case TIMER_ELAPSED:
-
- /* Recalculate sleep time */
- timer_enter_waiting(t, false);
- break;
-
- case TIMER_RUNNING:
-
- if (UNIT_IS_INACTIVE_OR_FAILED(new_state)) {
- log_debug("%s got notified about unit deactivation.", UNIT(t)->id);
- timer_enter_waiting(t, false);
- }
-
- break;
-
- case TIMER_DEAD:
- case TIMER_FAILED:
- break;
-
- default:
- assert_not_reached("Unknown timer state");
- }
- }
-}
-
-static void timer_reset_failed(Unit *u) {
- Timer *t = TIMER(u);
-
- assert(t);
-
- if (t->state == TIMER_FAILED)
- timer_set_state(t, TIMER_DEAD);
-
- t->result = TIMER_SUCCESS;
-}
-
-static const char* const timer_state_table[_TIMER_STATE_MAX] = {
- [TIMER_DEAD] = "dead",
- [TIMER_WAITING] = "waiting",
- [TIMER_RUNNING] = "running",
- [TIMER_ELAPSED] = "elapsed",
- [TIMER_FAILED] = "failed"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(timer_state, TimerState);
-
-static const char* const timer_base_table[_TIMER_BASE_MAX] = {
- [TIMER_ACTIVE] = "OnActiveSec",
- [TIMER_BOOT] = "OnBootSec",
- [TIMER_STARTUP] = "OnStartupSec",
- [TIMER_UNIT_ACTIVE] = "OnUnitActiveSec",
- [TIMER_UNIT_INACTIVE] = "OnUnitInactiveSec"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase);
-
-static const char* const timer_result_table[_TIMER_RESULT_MAX] = {
- [TIMER_SUCCESS] = "success",
- [TIMER_FAILURE_RESOURCES] = "resources"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);
-
-const UnitVTable timer_vtable = {
- .object_size = sizeof(Timer),
- .sections =
- "Unit\0"
- "Timer\0"
- "Install\0",
-
- .init = timer_init,
- .done = timer_done,
- .load = timer_load,
-
- .coldplug = timer_coldplug,
-
- .dump = timer_dump,
-
- .start = timer_start,
- .stop = timer_stop,
-
- .serialize = timer_serialize,
- .deserialize_item = timer_deserialize_item,
-
- .active_state = timer_active_state,
- .sub_state_to_string = timer_sub_state_to_string,
-
- .timer_event = timer_timer_event,
-
- .reset_failed = timer_reset_failed,
-
- .bus_interface = "org.freedesktop.systemd1.Timer",
- .bus_message_handler = bus_timer_message_handler,
- .bus_invalidating_properties = bus_timer_invalidating_properties
-};
diff --git a/src/core/timer.h b/src/core/timer.h
deleted file mode 100644
index c6d1d42e44..0000000000
--- a/src/core/timer.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*-*- 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/>.
-***/
-
-typedef struct Timer Timer;
-
-#include "unit.h"
-
-typedef enum TimerState {
- TIMER_DEAD,
- TIMER_WAITING,
- TIMER_RUNNING,
- TIMER_ELAPSED,
- TIMER_FAILED,
- _TIMER_STATE_MAX,
- _TIMER_STATE_INVALID = -1
-} TimerState;
-
-typedef enum TimerBase {
- TIMER_ACTIVE,
- TIMER_BOOT,
- TIMER_STARTUP,
- TIMER_UNIT_ACTIVE,
- TIMER_UNIT_INACTIVE,
- _TIMER_BASE_MAX,
- _TIMER_BASE_INVALID = -1
-} TimerBase;
-
-typedef struct TimerValue {
- usec_t value;
- usec_t next_elapse;
-
- LIST_FIELDS(struct TimerValue, value);
-
- TimerBase base;
- bool disabled;
-} TimerValue;
-
-typedef enum TimerResult {
- TIMER_SUCCESS,
- TIMER_FAILURE_RESOURCES,
- _TIMER_RESULT_MAX,
- _TIMER_RESULT_INVALID = -1
-} TimerResult;
-
-struct Timer {
- Unit meta;
-
- LIST_HEAD(TimerValue, values);
- usec_t next_elapse;
-
- TimerState state, deserialized_state;
- UnitRef unit;
-
- Watch timer_watch;
-
- TimerResult result;
-};
-
-void timer_unit_notify(Unit *u, UnitActiveState new_state);
-
-extern const UnitVTable timer_vtable;
-
-const char *timer_state_to_string(TimerState i);
-TimerState timer_state_from_string(const char *s);
-
-const char *timer_base_to_string(TimerBase i);
-TimerBase timer_base_from_string(const char *s);
-
-const char* timer_result_to_string(TimerResult i);
-TimerResult timer_result_from_string(const char *s);
diff --git a/src/core/transaction.c b/src/core/transaction.c
deleted file mode 100644
index 4bce942012..0000000000
--- a/src/core/transaction.c
+++ /dev/null
@@ -1,1087 +0,0 @@
-/*-*- 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 <unistd.h>
-#include <fcntl.h>
-
-#include "transaction.h"
-#include "bus-errors.h"
-
-static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies);
-
-static void transaction_delete_job(Transaction *tr, Job *j, bool delete_dependencies) {
- assert(tr);
- assert(j);
-
- /* Deletes one job from the transaction */
-
- transaction_unlink_job(tr, j, delete_dependencies);
-
- job_free(j);
-}
-
-static void transaction_delete_unit(Transaction *tr, Unit *u) {
- Job *j;
-
- /* Deletes all jobs associated with a certain unit from the
- * transaction */
-
- while ((j = hashmap_get(tr->jobs, u)))
- transaction_delete_job(tr, j, true);
-}
-
-void transaction_abort(Transaction *tr) {
- Job *j;
-
- assert(tr);
-
- while ((j = hashmap_first(tr->jobs)))
- transaction_delete_job(tr, j, false);
-
- assert(hashmap_isempty(tr->jobs));
-}
-
-static void transaction_find_jobs_that_matter_to_anchor(Job *j, unsigned generation) {
- JobDependency *l;
-
- /* A recursive sweep through the graph that marks all units
- * that matter to the anchor job, i.e. are directly or
- * indirectly a dependency of the anchor job via paths that
- * are fully marked as mattering. */
-
- j->matters_to_anchor = true;
- j->generation = generation;
-
- LIST_FOREACH(subject, l, j->subject_list) {
-
- /* This link does not matter */
- if (!l->matters)
- continue;
-
- /* This unit has already been marked */
- if (l->object->generation == generation)
- continue;
-
- transaction_find_jobs_that_matter_to_anchor(l->object, generation);
- }
-}
-
-static void transaction_merge_and_delete_job(Transaction *tr, Job *j, Job *other, JobType t) {
- JobDependency *l, *last;
-
- assert(j);
- assert(other);
- assert(j->unit == other->unit);
- assert(!j->installed);
-
- /* Merges 'other' into 'j' and then deletes 'other'. */
-
- j->type = t;
- j->state = JOB_WAITING;
- j->override = j->override || other->override;
-
- j->matters_to_anchor = j->matters_to_anchor || other->matters_to_anchor;
-
- /* Patch us in as new owner of the JobDependency objects */
- last = NULL;
- LIST_FOREACH(subject, l, other->subject_list) {
- assert(l->subject == other);
- l->subject = j;
- last = l;
- }
-
- /* Merge both lists */
- if (last) {
- last->subject_next = j->subject_list;
- if (j->subject_list)
- j->subject_list->subject_prev = last;
- j->subject_list = other->subject_list;
- }
-
- /* Patch us in as new owner of the JobDependency objects */
- last = NULL;
- LIST_FOREACH(object, l, other->object_list) {
- assert(l->object == other);
- l->object = j;
- last = l;
- }
-
- /* Merge both lists */
- if (last) {
- last->object_next = j->object_list;
- if (j->object_list)
- j->object_list->object_prev = last;
- j->object_list = other->object_list;
- }
-
- /* Kill the other job */
- other->subject_list = NULL;
- other->object_list = NULL;
- transaction_delete_job(tr, other, true);
-}
-
-static bool job_is_conflicted_by(Job *j) {
- JobDependency *l;
-
- assert(j);
-
- /* Returns true if this job is pulled in by a least one
- * ConflictedBy dependency. */
-
- LIST_FOREACH(object, l, j->object_list)
- if (l->conflicts)
- return true;
-
- return false;
-}
-
-static int delete_one_unmergeable_job(Transaction *tr, Job *j) {
- Job *k;
-
- assert(j);
-
- /* Tries to delete one item in the linked list
- * j->transaction_next->transaction_next->... that conflicts
- * with another one, in an attempt to make an inconsistent
- * transaction work. */
-
- /* We rely here on the fact that if a merged with b does not
- * merge with c, either a or b merge with c neither */
- LIST_FOREACH(transaction, j, j)
- LIST_FOREACH(transaction, k, j->transaction_next) {
- Job *d;
-
- /* Is this one mergeable? Then skip it */
- if (job_type_is_mergeable(j->type, k->type))
- continue;
-
- /* Ok, we found two that conflict, let's see if we can
- * drop one of them */
- if (!j->matters_to_anchor && !k->matters_to_anchor) {
-
- /* Both jobs don't matter, so let's
- * find the one that is smarter to
- * remove. Let's think positive and
- * rather remove stops then starts --
- * except if something is being
- * stopped because it is conflicted by
- * another unit in which case we
- * rather remove the start. */
-
- log_debug("Looking at job %s/%s conflicted_by=%s", j->unit->id, job_type_to_string(j->type), yes_no(j->type == JOB_STOP && job_is_conflicted_by(j)));
- log_debug("Looking at job %s/%s conflicted_by=%s", k->unit->id, job_type_to_string(k->type), yes_no(k->type == JOB_STOP && job_is_conflicted_by(k)));
-
- if (j->type == JOB_STOP) {
-
- if (job_is_conflicted_by(j))
- d = k;
- else
- d = j;
-
- } else if (k->type == JOB_STOP) {
-
- if (job_is_conflicted_by(k))
- d = j;
- else
- d = k;
- } else
- d = j;
-
- } else if (!j->matters_to_anchor)
- d = j;
- else if (!k->matters_to_anchor)
- d = k;
- else
- return -ENOEXEC;
-
- /* Ok, we can drop one, so let's do so. */
- log_debug("Fixing conflicting jobs by deleting job %s/%s", d->unit->id, job_type_to_string(d->type));
- transaction_delete_job(tr, d, true);
- return 0;
- }
-
- return -EINVAL;
-}
-
-static int transaction_merge_jobs(Transaction *tr, DBusError *e) {
- Job *j;
- Iterator i;
- int r;
-
- assert(tr);
-
- /* First step, check whether any of the jobs for one specific
- * task conflict. If so, try to drop one of them. */
- HASHMAP_FOREACH(j, tr->jobs, i) {
- JobType t;
- Job *k;
-
- t = j->type;
- LIST_FOREACH(transaction, k, j->transaction_next) {
- if (job_type_merge_and_collapse(&t, k->type, j->unit) >= 0)
- continue;
-
- /* OK, we could not merge all jobs for this
- * action. Let's see if we can get rid of one
- * of them */
-
- r = delete_one_unmergeable_job(tr, j);
- if (r >= 0)
- /* Ok, we managed to drop one, now
- * let's ask our callers to call us
- * again after garbage collecting */
- return -EAGAIN;
-
- /* We couldn't merge anything. Failure */
- dbus_set_error(e, BUS_ERROR_TRANSACTION_JOBS_CONFLICTING, "Transaction contains conflicting jobs '%s' and '%s' for %s. Probably contradicting requirement dependencies configured.",
- job_type_to_string(t), job_type_to_string(k->type), k->unit->id);
- return r;
- }
- }
-
- /* Second step, merge the jobs. */
- HASHMAP_FOREACH(j, tr->jobs, i) {
- JobType t = j->type;
- Job *k;
-
- /* Merge all transaction jobs for j->unit */
- LIST_FOREACH(transaction, k, j->transaction_next)
- assert_se(job_type_merge_and_collapse(&t, k->type, j->unit) == 0);
-
- while ((k = j->transaction_next)) {
- if (tr->anchor_job == k) {
- transaction_merge_and_delete_job(tr, k, j, t);
- j = k;
- } else
- transaction_merge_and_delete_job(tr, j, k, t);
- }
-
- assert(!j->transaction_next);
- assert(!j->transaction_prev);
- }
-
- return 0;
-}
-
-static void transaction_drop_redundant(Transaction *tr) {
- Job *j;
- Iterator i;
-
- /* Goes through the transaction and removes all jobs of the units
- * whose jobs are all noops. If not all of a unit's jobs are
- * redundant, they are kept. */
-
- assert(tr);
-
-rescan:
- HASHMAP_FOREACH(j, tr->jobs, i) {
- Job *k;
-
- LIST_FOREACH(transaction, k, j) {
-
- if (tr->anchor_job == k ||
- !job_type_is_redundant(k->type, unit_active_state(k->unit)) ||
- (k->unit->job && job_type_is_conflicting(k->type, k->unit->job->type)))
- goto next_unit;
- }
-
- /* log_debug("Found redundant job %s/%s, dropping.", j->unit->id, job_type_to_string(j->type)); */
- transaction_delete_job(tr, j, false);
- goto rescan;
- next_unit:;
- }
-}
-
-static bool unit_matters_to_anchor(Unit *u, Job *j) {
- assert(u);
- assert(!j->transaction_prev);
-
- /* Checks whether at least one of the jobs for this unit
- * matters to the anchor. */
-
- LIST_FOREACH(transaction, j, j)
- if (j->matters_to_anchor)
- return true;
-
- return false;
-}
-
-static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsigned generation, DBusError *e) {
- Iterator i;
- Unit *u;
- int r;
-
- assert(tr);
- assert(j);
- assert(!j->transaction_prev);
-
- /* Does a recursive sweep through the ordering graph, looking
- * for a cycle. If we find cycle we try to break it. */
-
- /* Have we seen this before? */
- if (j->generation == generation) {
- Job *k, *delete;
-
- /* If the marker is NULL we have been here already and
- * decided the job was loop-free from here. Hence
- * shortcut things and return right-away. */
- if (!j->marker)
- return 0;
-
- /* So, the marker is not NULL and we already have been
- * here. We have a cycle. Let's try to break it. We go
- * backwards in our path and try to find a suitable
- * job to remove. We use the marker to find our way
- * back, since smart how we are we stored our way back
- * in there. */
- log_warning("Found ordering cycle on %s/%s", j->unit->id, job_type_to_string(j->type));
-
- delete = NULL;
- for (k = from; k; k = ((k->generation == generation && k->marker != k) ? k->marker : NULL)) {
-
- log_info("Walked on cycle path to %s/%s", k->unit->id, job_type_to_string(k->type));
-
- if (!delete &&
- !unit_matters_to_anchor(k->unit, k)) {
- /* Ok, we can drop this one, so let's
- * do so. */
- delete = k;
- }
-
- /* Check if this in fact was the beginning of
- * the cycle */
- if (k == j)
- break;
- }
-
-
- if (delete) {
- log_warning("Breaking ordering cycle by deleting job %s/%s", delete->unit->id, job_type_to_string(delete->type));
- transaction_delete_unit(tr, delete->unit);
- return -EAGAIN;
- }
-
- log_error("Unable to break cycle");
-
- dbus_set_error(e, BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC, "Transaction order is cyclic. See system logs for details.");
- return -ENOEXEC;
- }
-
- /* Make the marker point to where we come from, so that we can
- * find our way backwards if we want to break a cycle. We use
- * a special marker for the beginning: we point to
- * ourselves. */
- j->marker = from ? from : j;
- j->generation = generation;
-
- /* We assume that the dependencies are bidirectional, and
- * hence can ignore UNIT_AFTER */
- SET_FOREACH(u, j->unit->dependencies[UNIT_BEFORE], i) {
- Job *o;
-
- /* Is there a job for this unit? */
- o = hashmap_get(tr->jobs, u);
- if (!o) {
- /* Ok, there is no job for this in the
- * transaction, but maybe there is already one
- * running? */
- o = u->job;
- if (!o)
- continue;
- }
-
- r = transaction_verify_order_one(tr, o, j, generation, e);
- if (r < 0)
- return r;
- }
-
- /* Ok, let's backtrack, and remember that this entry is not on
- * our path anymore. */
- j->marker = NULL;
-
- return 0;
-}
-
-static int transaction_verify_order(Transaction *tr, unsigned *generation, DBusError *e) {
- Job *j;
- int r;
- Iterator i;
- unsigned g;
-
- assert(tr);
- assert(generation);
-
- /* Check if the ordering graph is cyclic. If it is, try to fix
- * that up by dropping one of the jobs. */
-
- g = (*generation)++;
-
- HASHMAP_FOREACH(j, tr->jobs, i)
- if ((r = transaction_verify_order_one(tr, j, NULL, g, e)) < 0)
- return r;
-
- return 0;
-}
-
-static void transaction_collect_garbage(Transaction *tr) {
- Iterator i;
- Job *j;
-
- assert(tr);
-
- /* Drop jobs that are not required by any other job */
-
-rescan:
- HASHMAP_FOREACH(j, tr->jobs, i) {
- if (tr->anchor_job == j || j->object_list) {
- /* log_debug("Keeping job %s/%s because of %s/%s", */
- /* j->unit->id, job_type_to_string(j->type), */
- /* j->object_list->subject ? j->object_list->subject->unit->id : "root", */
- /* j->object_list->subject ? job_type_to_string(j->object_list->subject->type) : "root"); */
- continue;
- }
-
- /* log_debug("Garbage collecting job %s/%s", j->unit->id, job_type_to_string(j->type)); */
- transaction_delete_job(tr, j, true);
- goto rescan;
- }
-}
-
-static int transaction_is_destructive(Transaction *tr, DBusError *e) {
- Iterator i;
- Job *j;
-
- assert(tr);
-
- /* Checks whether applying this transaction means that
- * existing jobs would be replaced */
-
- HASHMAP_FOREACH(j, tr->jobs, i) {
-
- /* Assume merged */
- assert(!j->transaction_prev);
- assert(!j->transaction_next);
-
- if (j->unit->job &&
- !job_type_is_superset(j->type, j->unit->job->type)) {
-
- dbus_set_error(e, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE, "Transaction is destructive.");
- return -EEXIST;
- }
- }
-
- return 0;
-}
-
-static void transaction_minimize_impact(Transaction *tr) {
- Job *j;
- Iterator i;
-
- assert(tr);
-
- /* Drops all unnecessary jobs that reverse already active jobs
- * or that stop a running service. */
-
-rescan:
- HASHMAP_FOREACH(j, tr->jobs, i) {
- LIST_FOREACH(transaction, j, j) {
- bool stops_running_service, changes_existing_job;
-
- /* If it matters, we shouldn't drop it */
- if (j->matters_to_anchor)
- continue;
-
- /* Would this stop a running service?
- * Would this change an existing job?
- * If so, let's drop this entry */
-
- stops_running_service =
- j->type == JOB_STOP && UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(j->unit));
-
- changes_existing_job =
- j->unit->job &&
- job_type_is_conflicting(j->type, j->unit->job->type);
-
- if (!stops_running_service && !changes_existing_job)
- continue;
-
- if (stops_running_service)
- log_debug("%s/%s would stop a running service.", j->unit->id, job_type_to_string(j->type));
-
- if (changes_existing_job)
- log_debug("%s/%s would change existing job.", j->unit->id, job_type_to_string(j->type));
-
- /* Ok, let's get rid of this */
- log_debug("Deleting %s/%s to minimize impact.", j->unit->id, job_type_to_string(j->type));
-
- transaction_delete_job(tr, j, true);
- goto rescan;
- }
- }
-}
-
-static int transaction_apply(Transaction *tr, Manager *m, JobMode mode) {
- Iterator i;
- Job *j;
- int r;
-
- /* Moves the transaction jobs to the set of active jobs */
-
- if (mode == JOB_ISOLATE) {
-
- /* When isolating first kill all installed jobs which
- * aren't part of the new transaction */
- HASHMAP_FOREACH(j, m->jobs, i) {
- assert(j->installed);
-
- if (hashmap_get(tr->jobs, j->unit))
- continue;
-
- /* Not invalidating recursively. Avoids triggering
- * OnFailure= actions of dependent jobs. Also avoids
- * invalidating our iterator. */
- job_finish_and_invalidate(j, JOB_CANCELED, false);
- }
- }
-
- HASHMAP_FOREACH(j, tr->jobs, i) {
- /* Assume merged */
- assert(!j->transaction_prev);
- assert(!j->transaction_next);
-
- r = hashmap_put(m->jobs, UINT32_TO_PTR(j->id), j);
- if (r < 0)
- goto rollback;
- }
-
- while ((j = hashmap_steal_first(tr->jobs))) {
- Job *installed_job;
-
- /* Clean the job dependencies */
- transaction_unlink_job(tr, j, false);
-
- installed_job = job_install(j);
- if (installed_job != j) {
- /* j has been merged into a previously installed job */
- if (tr->anchor_job == j)
- tr->anchor_job = installed_job;
- hashmap_remove(m->jobs, UINT32_TO_PTR(j->id));
- job_free(j);
- j = installed_job;
- }
-
- job_add_to_run_queue(j);
- job_add_to_dbus_queue(j);
- job_start_timer(j);
- }
-
- return 0;
-
-rollback:
-
- HASHMAP_FOREACH(j, tr->jobs, i)
- hashmap_remove(m->jobs, UINT32_TO_PTR(j->id));
-
- return r;
-}
-
-int transaction_activate(Transaction *tr, Manager *m, JobMode mode, DBusError *e) {
- Iterator i;
- Job *j;
- int r;
- unsigned generation = 1;
-
- assert(tr);
-
- /* This applies the changes recorded in tr->jobs to
- * the actual list of jobs, if possible. */
-
- /* Reset the generation counter of all installed jobs. The detection of cycles
- * looks at installed jobs. If they had a non-zero generation from some previous
- * walk of the graph, the algorithm would break. */
- HASHMAP_FOREACH(j, m->jobs, i)
- j->generation = 0;
-
- /* First step: figure out which jobs matter */
- transaction_find_jobs_that_matter_to_anchor(tr->anchor_job, generation++);
-
- /* Second step: Try not to stop any running services if
- * we don't have to. Don't try to reverse running
- * jobs if we don't have to. */
- if (mode == JOB_FAIL)
- transaction_minimize_impact(tr);
-
- /* Third step: Drop redundant jobs */
- transaction_drop_redundant(tr);
-
- for (;;) {
- /* Fourth step: Let's remove unneeded jobs that might
- * be lurking. */
- if (mode != JOB_ISOLATE)
- transaction_collect_garbage(tr);
-
- /* Fifth step: verify order makes sense and correct
- * cycles if necessary and possible */
- r = transaction_verify_order(tr, &generation, e);
- if (r >= 0)
- break;
-
- if (r != -EAGAIN) {
- log_warning("Requested transaction contains an unfixable cyclic ordering dependency: %s", bus_error(e, r));
- return r;
- }
-
- /* Let's see if the resulting transaction ordering
- * graph is still cyclic... */
- }
-
- for (;;) {
- /* Sixth step: let's drop unmergeable entries if
- * necessary and possible, merge entries we can
- * merge */
- r = transaction_merge_jobs(tr, e);
- if (r >= 0)
- break;
-
- if (r != -EAGAIN) {
- log_warning("Requested transaction contains unmergeable jobs: %s", bus_error(e, r));
- return r;
- }
-
- /* Seventh step: an entry got dropped, let's garbage
- * collect its dependencies. */
- if (mode != JOB_ISOLATE)
- transaction_collect_garbage(tr);
-
- /* Let's see if the resulting transaction still has
- * unmergeable entries ... */
- }
-
- /* Eights step: Drop redundant jobs again, if the merging now allows us to drop more. */
- transaction_drop_redundant(tr);
-
- /* Ninth step: check whether we can actually apply this */
- if (mode == JOB_FAIL) {
- r = transaction_is_destructive(tr, e);
- if (r < 0) {
- log_notice("Requested transaction contradicts existing jobs: %s", bus_error(e, r));
- return r;
- }
- }
-
- /* Tenth step: apply changes */
- r = transaction_apply(tr, m, mode);
- if (r < 0) {
- log_warning("Failed to apply transaction: %s", strerror(-r));
- return r;
- }
-
- assert(hashmap_isempty(tr->jobs));
-
- if (!hashmap_isempty(m->jobs)) {
- /* Are there any jobs now? Then make sure we have the
- * idle pipe around. We don't really care too much
- * whether this works or not, as the idle pipe is a
- * feature for cosmetics, not actually useful for
- * anything beyond that. */
-
- if (m->idle_pipe[0] < 0 && m->idle_pipe[1] < 0)
- pipe2(m->idle_pipe, O_NONBLOCK|O_CLOEXEC);
- }
-
- return 0;
-}
-
-static Job* transaction_add_one_job(Transaction *tr, JobType type, Unit *unit, bool override, bool *is_new) {
- Job *j, *f;
-
- assert(tr);
- assert(unit);
-
- /* Looks for an existing prospective job and returns that. If
- * it doesn't exist it is created and added to the prospective
- * jobs list. */
-
- f = hashmap_get(tr->jobs, unit);
-
- LIST_FOREACH(transaction, j, f) {
- assert(j->unit == unit);
-
- if (j->type == type) {
- if (is_new)
- *is_new = false;
- return j;
- }
- }
-
- j = job_new(unit, type);
- if (!j)
- return NULL;
-
- j->generation = 0;
- j->marker = NULL;
- j->matters_to_anchor = false;
- j->override = override;
-
- LIST_PREPEND(Job, transaction, f, j);
-
- if (hashmap_replace(tr->jobs, unit, f) < 0) {
- LIST_REMOVE(Job, transaction, f, j);
- job_free(j);
- return NULL;
- }
-
- if (is_new)
- *is_new = true;
-
- /* log_debug("Added job %s/%s to transaction.", unit->id, job_type_to_string(type)); */
-
- return j;
-}
-
-static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies) {
- assert(tr);
- assert(j);
-
- if (j->transaction_prev)
- j->transaction_prev->transaction_next = j->transaction_next;
- else if (j->transaction_next)
- hashmap_replace(tr->jobs, j->unit, j->transaction_next);
- else
- hashmap_remove_value(tr->jobs, j->unit, j);
-
- if (j->transaction_next)
- j->transaction_next->transaction_prev = j->transaction_prev;
-
- j->transaction_prev = j->transaction_next = NULL;
-
- while (j->subject_list)
- job_dependency_free(j->subject_list);
-
- while (j->object_list) {
- Job *other = j->object_list->matters ? j->object_list->subject : NULL;
-
- job_dependency_free(j->object_list);
-
- if (other && delete_dependencies) {
- log_debug("Deleting job %s/%s as dependency of job %s/%s",
- other->unit->id, job_type_to_string(other->type),
- j->unit->id, job_type_to_string(j->type));
- transaction_delete_job(tr, other, delete_dependencies);
- }
- }
-}
-
-int transaction_add_job_and_dependencies(
- Transaction *tr,
- JobType type,
- Unit *unit,
- Job *by,
- bool matters,
- bool override,
- bool conflicts,
- bool ignore_requirements,
- bool ignore_order,
- DBusError *e) {
- Job *ret;
- Iterator i;
- Unit *dep;
- int r;
- bool is_new;
-
- assert(tr);
- assert(type < _JOB_TYPE_MAX);
- assert(type < _JOB_TYPE_MAX_IN_TRANSACTION);
- assert(unit);
-
- /* log_debug("Pulling in %s/%s from %s/%s", */
- /* unit->id, job_type_to_string(type), */
- /* by ? by->unit->id : "NA", */
- /* by ? job_type_to_string(by->type) : "NA"); */
-
- if (unit->load_state != UNIT_LOADED &&
- unit->load_state != UNIT_ERROR &&
- unit->load_state != UNIT_MASKED) {
- dbus_set_error(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id);
- return -EINVAL;
- }
-
- if (type != JOB_STOP && unit->load_state == UNIT_ERROR) {
- dbus_set_error(e, BUS_ERROR_LOAD_FAILED,
- "Unit %s failed to load: %s. "
- "See system logs and 'systemctl status %s' for details.",
- unit->id,
- strerror(-unit->load_error),
- unit->id);
- return -EINVAL;
- }
-
- if (type != JOB_STOP && unit->load_state == UNIT_MASKED) {
- dbus_set_error(e, BUS_ERROR_MASKED, "Unit %s is masked.", unit->id);
- return -EADDRNOTAVAIL;
- }
-
- if (!unit_job_is_applicable(unit, type)) {
- dbus_set_error(e, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE, "Job type %s is not applicable for unit %s.", job_type_to_string(type), unit->id);
- return -EBADR;
- }
-
- /* First add the job. */
- ret = transaction_add_one_job(tr, type, unit, override, &is_new);
- if (!ret)
- return -ENOMEM;
-
- ret->ignore_order = ret->ignore_order || ignore_order;
-
- /* Then, add a link to the job. */
- if (by) {
- if (!job_dependency_new(by, ret, matters, conflicts))
- return -ENOMEM;
- } else {
- /* If the job has no parent job, it is the anchor job. */
- assert(!tr->anchor_job);
- tr->anchor_job = ret;
- }
-
- if (is_new && !ignore_requirements && type != JOB_NOP) {
- Set *following;
-
- /* If we are following some other unit, make sure we
- * add all dependencies of everybody following. */
- if (unit_following_set(ret->unit, &following) > 0) {
- SET_FOREACH(dep, following, i) {
- r = transaction_add_job_and_dependencies(tr, type, dep, ret, false, override, false, false, ignore_order, e);
- if (r < 0) {
- log_warning("Cannot add dependency job for unit %s, ignoring: %s", dep->id, bus_error(e, r));
-
- if (e)
- dbus_error_free(e);
- }
- }
-
- set_free(following);
- }
-
- /* Finally, recursively add in all dependencies. */
- if (type == JOB_START || type == JOB_RESTART) {
- SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUIRES], i) {
- r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, override, false, false, ignore_order, e);
- if (r < 0) {
- if (r != -EBADR)
- goto fail;
-
- if (e)
- dbus_error_free(e);
- }
- }
-
- SET_FOREACH(dep, ret->unit->dependencies[UNIT_BINDS_TO], i) {
- r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, override, false, false, ignore_order, e);
- if (r < 0) {
- if (r != -EBADR)
- goto fail;
-
- if (e)
- dbus_error_free(e);
- }
- }
-
- SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUIRES_OVERRIDABLE], i) {
- r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, !override, override, false, false, ignore_order, e);
- if (r < 0) {
- log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING,
- "Cannot add dependency job for unit %s, ignoring: %s", dep->id, bus_error(e, r));
-
- if (e)
- dbus_error_free(e);
- }
- }
-
- SET_FOREACH(dep, ret->unit->dependencies[UNIT_WANTS], i) {
- r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, false, false, false, false, ignore_order, e);
- if (r < 0) {
- log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING,
- "Cannot add dependency job for unit %s, ignoring: %s", dep->id, bus_error(e, r));
-
- if (e)
- dbus_error_free(e);
- }
- }
-
- SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUISITE], i) {
- r = transaction_add_job_and_dependencies(tr, JOB_VERIFY_ACTIVE, dep, ret, true, override, false, false, ignore_order, e);
- if (r < 0) {
- if (r != -EBADR)
- goto fail;
-
- if (e)
- dbus_error_free(e);
- }
- }
-
- SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUISITE_OVERRIDABLE], i) {
- r = transaction_add_job_and_dependencies(tr, JOB_VERIFY_ACTIVE, dep, ret, !override, override, false, false, ignore_order, e);
- if (r < 0) {
- log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING,
- "Cannot add dependency job for unit %s, ignoring: %s", dep->id, bus_error(e, r));
-
- if (e)
- dbus_error_free(e);
- }
- }
-
- SET_FOREACH(dep, ret->unit->dependencies[UNIT_CONFLICTS], i) {
- r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, true, override, true, false, ignore_order, e);
- if (r < 0) {
- if (r != -EBADR)
- goto fail;
-
- if (e)
- dbus_error_free(e);
- }
- }
-
- SET_FOREACH(dep, ret->unit->dependencies[UNIT_CONFLICTED_BY], i) {
- r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, false, override, false, false, ignore_order, e);
- if (r < 0) {
- log_warning("Cannot add dependency job for unit %s, ignoring: %s", dep->id, bus_error(e, r));
-
- if (e)
- dbus_error_free(e);
- }
- }
-
- }
-
- if (type == JOB_STOP || type == JOB_RESTART) {
-
- SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUIRED_BY], i) {
- r = transaction_add_job_and_dependencies(tr, type, dep, ret, true, override, false, false, ignore_order, e);
- if (r < 0) {
- if (r != -EBADR)
- goto fail;
-
- if (e)
- dbus_error_free(e);
- }
- }
-
- SET_FOREACH(dep, ret->unit->dependencies[UNIT_BOUND_BY], i) {
- r = transaction_add_job_and_dependencies(tr, type, dep, ret, true, override, false, false, ignore_order, e);
- if (r < 0) {
- if (r != -EBADR)
- goto fail;
-
- if (e)
- dbus_error_free(e);
- }
- }
-
- SET_FOREACH(dep, ret->unit->dependencies[UNIT_CONSISTS_OF], i) {
- r = transaction_add_job_and_dependencies(tr, type, dep, ret, true, override, false, false, ignore_order, e);
- if (r < 0) {
- if (r != -EBADR)
- goto fail;
-
- if (e)
- dbus_error_free(e);
- }
- }
-
- }
-
- if (type == JOB_RELOAD) {
-
- SET_FOREACH(dep, ret->unit->dependencies[UNIT_PROPAGATES_RELOAD_TO], i) {
- r = transaction_add_job_and_dependencies(tr, JOB_RELOAD, dep, ret, false, override, false, false, ignore_order, e);
- if (r < 0) {
- log_warning("Cannot add dependency reload job for unit %s, ignoring: %s", dep->id, bus_error(e, r));
-
- if (e)
- dbus_error_free(e);
- }
- }
- }
-
- /* JOB_VERIFY_STARTED require no dependency handling */
- }
-
- return 0;
-
-fail:
- return r;
-}
-
-int transaction_add_isolate_jobs(Transaction *tr, Manager *m) {
- Iterator i;
- Unit *u;
- char *k;
- int r;
-
- assert(tr);
- assert(m);
-
- HASHMAP_FOREACH_KEY(u, k, m->units, i) {
-
- /* ignore aliases */
- if (u->id != k)
- continue;
-
- if (u->ignore_on_isolate)
- continue;
-
- /* No need to stop inactive jobs */
- if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(u)) && !u->job)
- continue;
-
- /* Is there already something listed for this? */
- if (hashmap_get(tr->jobs, u))
- continue;
-
- r = transaction_add_job_and_dependencies(tr, JOB_STOP, u, tr->anchor_job, true, false, false, false, false, NULL);
- if (r < 0)
- log_warning("Cannot add isolate job for unit %s, ignoring: %s", u->id, strerror(-r));
- }
-
- return 0;
-}
-
-Transaction *transaction_new(void) {
- Transaction *tr;
-
- tr = new0(Transaction, 1);
- if (!tr)
- return NULL;
-
- tr->jobs = hashmap_new(trivial_hash_func, trivial_compare_func);
- if (!tr->jobs) {
- free(tr);
- return NULL;
- }
-
- return tr;
-}
-
-void transaction_free(Transaction *tr) {
- assert(hashmap_isempty(tr->jobs));
- hashmap_free(tr->jobs);
- free(tr);
-}
diff --git a/src/core/transaction.h b/src/core/transaction.h
deleted file mode 100644
index 67ace4da0b..0000000000
--- a/src/core/transaction.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef footransactionhfoo
-#define footransactionhfoo
-
-/***
- 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/>.
-***/
-
-typedef struct Transaction Transaction;
-
-#include "unit.h"
-#include "manager.h"
-#include "job.h"
-#include "hashmap.h"
-
-struct Transaction {
- /* Jobs to be added */
- Hashmap *jobs; /* Unit object => Job object list 1:1 */
- Job *anchor_job; /* the job the user asked for */
-};
-
-Transaction *transaction_new(void);
-void transaction_free(Transaction *tr);
-
-int transaction_add_job_and_dependencies(
- Transaction *tr,
- JobType type,
- Unit *unit,
- Job *by,
- bool matters,
- bool override,
- bool conflicts,
- bool ignore_requirements,
- bool ignore_order,
- DBusError *e);
-int transaction_activate(Transaction *tr, Manager *m, JobMode mode, DBusError *e);
-int transaction_add_isolate_jobs(Transaction *tr, Manager *m);
-void transaction_abort(Transaction *tr);
-
-#endif
diff --git a/src/core/umount.c b/src/core/umount.c
deleted file mode 100644
index 83c9de3e82..0000000000
--- a/src/core/umount.c
+++ /dev/null
@@ -1,639 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010 ProFUSION embedded systems
-
- 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 <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/mount.h>
-#include <sys/swap.h>
-#include <unistd.h>
-#include <linux/loop.h>
-#include <linux/dm-ioctl.h>
-#include <libudev.h>
-
-#include "list.h"
-#include "mount-setup.h"
-#include "umount.h"
-#include "path-util.h"
-#include "util.h"
-#include "virt.h"
-
-typedef struct MountPoint {
- char *path;
- dev_t devnum;
- LIST_FIELDS (struct MountPoint, mount_point);
-} MountPoint;
-
-static void mount_point_free(MountPoint **head, MountPoint *m) {
- assert(head);
- assert(m);
-
- LIST_REMOVE(MountPoint, mount_point, *head, m);
-
- free(m->path);
- free(m);
-}
-
-static void mount_points_list_free(MountPoint **head) {
- assert(head);
-
- while (*head)
- mount_point_free(head, *head);
-}
-
-static int mount_points_list_get(MountPoint **head) {
- FILE *proc_self_mountinfo;
- char *path, *p;
- unsigned int i;
- int r;
-
- assert(head);
-
- if (!(proc_self_mountinfo = fopen("/proc/self/mountinfo", "re")))
- return -errno;
-
- for (i = 1;; i++) {
- int k;
- MountPoint *m;
-
- path = p = NULL;
-
- if ((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)) != 1) {
- if (k == EOF)
- break;
-
- log_warning("Failed to parse /proc/self/mountinfo:%u.", i);
-
- free(path);
- continue;
- }
-
- p = cunescape(path);
- free(path);
-
- if (!p) {
- r = -ENOMEM;
- goto finish;
- }
-
- /* Ignore mount points we can't unmount because they
- * are API or because we are keeping them open (like
- * /dev/console) */
- if (mount_point_is_api(p) ||
- mount_point_ignore(p) ||
- path_equal(p, "/dev/console")) {
- free(p);
- continue;
- }
-
- if (!(m = new0(MountPoint, 1))) {
- free(p);
- r = -ENOMEM;
- goto finish;
- }
-
- m->path = p;
- LIST_PREPEND(MountPoint, mount_point, *head, m);
- }
-
- r = 0;
-
-finish:
- fclose(proc_self_mountinfo);
-
- return r;
-}
-
-static int swap_list_get(MountPoint **head) {
- FILE *proc_swaps;
- unsigned int i;
- int r;
-
- assert(head);
-
- if (!(proc_swaps = fopen("/proc/swaps", "re")))
- return (errno == ENOENT) ? 0 : -errno;
-
- (void) fscanf(proc_swaps, "%*s %*s %*s %*s %*s\n");
-
- for (i = 2;; i++) {
- MountPoint *swap;
- char *dev = NULL, *d;
- int k;
-
- if ((k = fscanf(proc_swaps,
- "%ms " /* device/file */
- "%*s " /* type of swap */
- "%*s " /* swap size */
- "%*s " /* used */
- "%*s\n", /* priority */
- &dev)) != 1) {
-
- if (k == EOF)
- break;
-
- log_warning("Failed to parse /proc/swaps:%u.", i);
-
- free(dev);
- continue;
- }
-
- if (endswith(dev, "(deleted)")) {
- free(dev);
- continue;
- }
-
- d = cunescape(dev);
- free(dev);
-
- if (!d) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (!(swap = new0(MountPoint, 1))) {
- free(d);
- r = -ENOMEM;
- goto finish;
- }
-
- swap->path = d;
- LIST_PREPEND(MountPoint, mount_point, *head, swap);
- }
-
- r = 0;
-
-finish:
- fclose(proc_swaps);
-
- return r;
-}
-
-static int loopback_list_get(MountPoint **head) {
- int r;
- struct udev *udev;
- struct udev_enumerate *e = NULL;
- struct udev_list_entry *item = NULL, *first = NULL;
-
- assert(head);
-
- if (!(udev = udev_new())) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (!(e = udev_enumerate_new(udev))) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (udev_enumerate_add_match_subsystem(e, "block") < 0 ||
- udev_enumerate_add_match_sysname(e, "loop*") < 0) {
- r = -EIO;
- goto finish;
- }
-
- if (udev_enumerate_scan_devices(e) < 0) {
- r = -EIO;
- goto finish;
- }
-
- first = udev_enumerate_get_list_entry(e);
- udev_list_entry_foreach(item, first) {
- MountPoint *lb;
- struct udev_device *d;
- char *loop;
- const char *dn;
-
- if (!(d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)))) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (!(dn = udev_device_get_devnode(d))) {
- udev_device_unref(d);
- continue;
- }
-
- loop = strdup(dn);
- udev_device_unref(d);
-
- if (!loop) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (!(lb = new0(MountPoint, 1))) {
- free(loop);
- r = -ENOMEM;
- goto finish;
- }
-
- lb->path = loop;
- LIST_PREPEND(MountPoint, mount_point, *head, lb);
- }
-
- r = 0;
-
-finish:
- if (e)
- udev_enumerate_unref(e);
-
- if (udev)
- udev_unref(udev);
-
- return r;
-}
-
-static int dm_list_get(MountPoint **head) {
- int r;
- struct udev *udev;
- struct udev_enumerate *e = NULL;
- struct udev_list_entry *item = NULL, *first = NULL;
-
- assert(head);
-
- if (!(udev = udev_new())) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (!(e = udev_enumerate_new(udev))) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (udev_enumerate_add_match_subsystem(e, "block") < 0 ||
- udev_enumerate_add_match_sysname(e, "dm-*") < 0) {
- r = -EIO;
- goto finish;
- }
-
- if (udev_enumerate_scan_devices(e) < 0) {
- r = -EIO;
- goto finish;
- }
-
- first = udev_enumerate_get_list_entry(e);
-
- udev_list_entry_foreach(item, first) {
- MountPoint *m;
- struct udev_device *d;
- dev_t devnum;
- char *node;
- const char *dn;
-
- if (!(d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)))) {
- r = -ENOMEM;
- goto finish;
- }
-
- devnum = udev_device_get_devnum(d);
- dn = udev_device_get_devnode(d);
-
- if (major(devnum) == 0 || !dn) {
- udev_device_unref(d);
- continue;
- }
-
- node = strdup(dn);
- udev_device_unref(d);
-
- if (!node) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (!(m = new(MountPoint, 1))) {
- free(node);
- r = -ENOMEM;
- goto finish;
- }
-
- m->path = node;
- m->devnum = devnum;
- LIST_PREPEND(MountPoint, mount_point, *head, m);
- }
-
- r = 0;
-
-finish:
- if (e)
- udev_enumerate_unref(e);
-
- if (udev)
- udev_unref(udev);
-
- return r;
-}
-
-static int delete_loopback(const char *device) {
- int fd, r;
-
- if ((fd = open(device, O_RDONLY|O_CLOEXEC)) < 0)
- return errno == ENOENT ? 0 : -errno;
-
- r = ioctl(fd, LOOP_CLR_FD, 0);
- close_nointr_nofail(fd);
-
- if (r >= 0)
- return 1;
-
- /* ENXIO: not bound, so no error */
- if (errno == ENXIO)
- return 0;
-
- return -errno;
-}
-
-static int delete_dm(dev_t devnum) {
- int fd, r;
- struct dm_ioctl dm;
-
- assert(major(devnum) != 0);
-
- if ((fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC)) < 0)
- return -errno;
-
- zero(dm);
- dm.version[0] = DM_VERSION_MAJOR;
- dm.version[1] = DM_VERSION_MINOR;
- dm.version[2] = DM_VERSION_PATCHLEVEL;
-
- dm.data_size = sizeof(dm);
- dm.dev = devnum;
-
- r = ioctl(fd, DM_DEV_REMOVE, &dm);
- close_nointr_nofail(fd);
-
- return r >= 0 ? 0 : -errno;
-}
-
-static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_error) {
- MountPoint *m, *n;
- int n_failed = 0;
-
- assert(head);
-
- LIST_FOREACH_SAFE(mount_point, m, n, *head) {
- if (path_equal(m->path, "/")
-#ifndef HAVE_SPLIT_USR
- || path_equal(m->path, "/usr")
-#endif
- ) {
- n_failed++;
- continue;
- }
-
- /* Trying to umount. Forcing to umount if busy (only for NFS mounts) */
- if (umount2(m->path, MNT_FORCE) == 0) {
- log_info("Unmounted %s.", m->path);
- if (changed)
- *changed = true;
-
- mount_point_free(head, m);
- } else if (log_error) {
- log_warning("Could not unmount %s: %m", m->path);
- n_failed++;
- }
- }
-
- return n_failed;
-}
-
-static int mount_points_list_remount_read_only(MountPoint **head, bool *changed) {
- MountPoint *m, *n;
- int n_failed = 0;
-
- assert(head);
-
- LIST_FOREACH_SAFE(mount_point, m, n, *head) {
-
- /* Trying to remount read-only */
- if (mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, NULL) == 0) {
- if (changed)
- *changed = true;
-
- mount_point_free(head, m);
- } else {
- log_warning("Could not remount as read-only %s: %m", m->path);
- n_failed++;
- }
- }
-
- return n_failed;
-}
-
-static int swap_points_list_off(MountPoint **head, bool *changed) {
- MountPoint *m, *n;
- int n_failed = 0;
-
- assert(head);
-
- LIST_FOREACH_SAFE(mount_point, m, n, *head) {
- if (swapoff(m->path) == 0) {
- if (changed)
- *changed = true;
-
- mount_point_free(head, m);
- } else {
- log_warning("Could not deactivate swap %s: %m", m->path);
- n_failed++;
- }
- }
-
- return n_failed;
-}
-
-static int loopback_points_list_detach(MountPoint **head, bool *changed) {
- MountPoint *m, *n;
- int n_failed = 0, k;
- struct stat root_st;
-
- assert(head);
-
- k = lstat("/", &root_st);
-
- LIST_FOREACH_SAFE(mount_point, m, n, *head) {
- int r;
- struct stat loopback_st;
-
- if (k >= 0 &&
- major(root_st.st_dev) != 0 &&
- lstat(m->path, &loopback_st) >= 0 &&
- root_st.st_dev == loopback_st.st_rdev) {
- n_failed ++;
- continue;
- }
-
- if ((r = delete_loopback(m->path)) >= 0) {
-
- if (r > 0 && changed)
- *changed = true;
-
- mount_point_free(head, m);
- } else {
- log_warning("Could not delete loopback %s: %m", m->path);
- n_failed++;
- }
- }
-
- return n_failed;
-}
-
-static int dm_points_list_detach(MountPoint **head, bool *changed) {
- MountPoint *m, *n;
- int n_failed = 0, k;
- struct stat root_st;
-
- assert(head);
-
- k = lstat("/", &root_st);
-
- LIST_FOREACH_SAFE(mount_point, m, n, *head) {
- int r;
-
- if (k >= 0 &&
- major(root_st.st_dev) != 0 &&
- root_st.st_dev == m->devnum) {
- n_failed ++;
- continue;
- }
-
- if ((r = delete_dm(m->devnum)) >= 0) {
-
- if (r > 0 && changed)
- *changed = true;
-
- mount_point_free(head, m);
- } else {
- log_warning("Could not delete dm %s: %m", m->path);
- n_failed++;
- }
- }
-
- return n_failed;
-}
-
-int umount_all(bool *changed) {
- int r;
- bool umount_changed;
- LIST_HEAD(MountPoint, mp_list_head);
-
- LIST_HEAD_INIT(MountPoint, mp_list_head);
- r = mount_points_list_get(&mp_list_head);
- if (r < 0)
- goto end;
-
- /* retry umount, until nothing can be umounted anymore */
- do {
- umount_changed = false;
-
- mount_points_list_umount(&mp_list_head, &umount_changed, false);
- if (umount_changed)
- *changed = true;
-
- } while (umount_changed);
-
- /* umount one more time with logging enabled */
- r = mount_points_list_umount(&mp_list_head, &umount_changed, true);
- if (r <= 0)
- goto end;
-
- /* If we are in a container, don't attempt to read-only mount
- anything as that brings no real benefits, but might confuse
- the host, as we remount the superblock here, not the bind
- mound. */
- if (detect_container(NULL) <= 0)
- r = mount_points_list_remount_read_only(&mp_list_head, changed);
-
- end:
- mount_points_list_free(&mp_list_head);
-
- return r;
-}
-
-int swapoff_all(bool *changed) {
- int r;
- LIST_HEAD(MountPoint, swap_list_head);
-
- LIST_HEAD_INIT(MountPoint, swap_list_head);
-
- r = swap_list_get(&swap_list_head);
- if (r < 0)
- goto end;
-
- r = swap_points_list_off(&swap_list_head, changed);
-
- end:
- mount_points_list_free(&swap_list_head);
-
- return r;
-}
-
-int loopback_detach_all(bool *changed) {
- int r;
- LIST_HEAD(MountPoint, loopback_list_head);
-
- LIST_HEAD_INIT(MountPoint, loopback_list_head);
-
- r = loopback_list_get(&loopback_list_head);
- if (r < 0)
- goto end;
-
- r = loopback_points_list_detach(&loopback_list_head, changed);
-
- end:
- mount_points_list_free(&loopback_list_head);
-
- return r;
-}
-
-int dm_detach_all(bool *changed) {
- int r;
- LIST_HEAD(MountPoint, dm_list_head);
-
- LIST_HEAD_INIT(MountPoint, dm_list_head);
-
- r = dm_list_get(&dm_list_head);
- if (r < 0)
- goto end;
-
- r = dm_points_list_detach(&dm_list_head, changed);
-
- end:
- mount_points_list_free(&dm_list_head);
-
- return r;
-}
diff --git a/src/core/umount.h b/src/core/umount.h
deleted file mode 100644
index 8439ffe58f..0000000000
--- a/src/core/umount.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 ProFUSION embedded systems
-
- 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 umount_all(bool *changed);
-
-int swapoff_all(bool *changed);
-
-int loopback_detach_all(bool *changed);
-
-int dm_detach_all(bool *changed);
diff --git a/src/core/unit-printf.c b/src/core/unit-printf.c
deleted file mode 100644
index cbae45d9f7..0000000000
--- a/src/core/unit-printf.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/*-*- 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 "systemd/sd-id128.h"
-#include "unit.h"
-#include "specifier.h"
-#include "path-util.h"
-#include "strv.h"
-#include "unit-name.h"
-#include "unit-printf.h"
-
-static char *specifier_prefix_and_instance(char specifier, void *data, void *userdata) {
- Unit *u = userdata;
- assert(u);
-
- return unit_name_to_prefix_and_instance(u->id);
-}
-
-static char *specifier_prefix(char specifier, void *data, void *userdata) {
- Unit *u = userdata;
- assert(u);
-
- return unit_name_to_prefix(u->id);
-}
-
-static char *specifier_prefix_unescaped(char specifier, void *data, void *userdata) {
- Unit *u = userdata;
- char *p, *r;
-
- assert(u);
-
- p = unit_name_to_prefix(u->id);
- if (!p)
- return NULL;
-
- r = unit_name_unescape(p);
- free(p);
-
- return r;
-}
-
-static char *specifier_instance_unescaped(char specifier, void *data, void *userdata) {
- Unit *u = userdata;
- assert(u);
-
- if (u->instance)
- return unit_name_unescape(u->instance);
-
- return strdup("");
-}
-
-static char *specifier_filename(char specifier, void *data, void *userdata) {
- Unit *u = userdata;
- assert(u);
-
- if (u->instance)
- return unit_name_path_unescape(u->instance);
-
- return unit_name_to_path(u->id);
-}
-
-static char *specifier_cgroup(char specifier, void *data, void *userdata) {
- Unit *u = userdata;
- assert(u);
-
- return unit_default_cgroup_path(u);
-}
-
-static char *specifier_cgroup_root(char specifier, void *data, void *userdata) {
- Unit *u = userdata;
- char *p;
- assert(u);
-
- if (specifier == 'r')
- return strdup(u->manager->cgroup_hierarchy);
-
- if (path_get_parent(u->manager->cgroup_hierarchy, &p) < 0)
- return strdup("");
-
- if (streq(p, "/")) {
- free(p);
- return strdup("");
- }
-
- return p;
-}
-
-static char *specifier_runtime(char specifier, void *data, void *userdata) {
- Unit *u = userdata;
- assert(u);
-
- if (u->manager->running_as == SYSTEMD_USER) {
- const char *e;
-
- e = getenv("XDG_RUNTIME_DIR");
- if (e)
- return strdup(e);
- }
-
- return strdup("/run");
-}
-
-static char *specifier_user_name(char specifier, void *data, void *userdata) {
- Unit *u = userdata;
- ExecContext *c;
- int r;
- const char *username;
-
- assert(u);
-
- c = unit_get_exec_context(u);
- if (!c)
- return NULL;
-
- /* get USER env from our own env if set */
- if (!c->user)
- return getusername_malloc();
-
- /* fish username from passwd */
- username = c->user;
- r = get_user_creds(&username, NULL, NULL, NULL, NULL);
- if (r < 0)
- return NULL;
-
- return strdup(username);
-}
-
-static char *specifier_user_home(char specifier, void *data, void *userdata) {
- Unit *u = userdata;
- ExecContext *c;
- int r;
- const char *username, *home;
-
- assert(u);
-
- c = unit_get_exec_context(u);
- if (!c)
- return NULL;
-
- /* return HOME if set, otherwise from passwd */
- if (!c->user) {
- char *h;
-
- r = get_home_dir(&h);
- if (r < 0)
- return NULL;
-
- return h;
- }
-
- username = c->user;
- r = get_user_creds(&username, NULL, NULL, &home, NULL);
- if (r < 0)
- return NULL;
-
- return strdup(home);
-}
-
-static char *specifier_user_shell(char specifier, void *data, void *userdata) {
- Unit *u = userdata;
- ExecContext *c;
- int r;
- const char *username, *shell;
-
- assert(u);
-
- c = unit_get_exec_context(u);
- if (!c)
- return NULL;
-
- /* return HOME if set, otherwise from passwd */
- if (!c->user) {
- char *sh;
-
- r = get_shell(&sh);
- if (r < 0)
- return strdup("/bin/sh");
-
- return sh;
- }
-
- username = c->user;
- r = get_user_creds(&username, NULL, NULL, NULL, &shell);
- if (r < 0)
- return strdup("/bin/sh");
-
- return strdup(shell);
-}
-
-static char *specifier_machine_id(char specifier, void *data, void *userdata) {
- sd_id128_t id;
- char *buf;
- int r;
-
- r = sd_id128_get_machine(&id);
- if (r < 0)
- return NULL;
-
- buf = new(char, 33);
- if (!buf)
- return NULL;
-
- return sd_id128_to_string(id, buf);
-}
-
-static char *specifier_boot_id(char specifier, void *data, void *userdata) {
- sd_id128_t id;
- char *buf;
- int r;
-
- r = sd_id128_get_boot(&id);
- if (r < 0)
- return NULL;
-
- buf = new(char, 33);
- if (!buf)
- return NULL;
-
- return sd_id128_to_string(id, buf);
-}
-
-static char *specifier_host_name(char specifier, void *data, void *userdata) {
- return gethostname_malloc();
-}
-
-char *unit_name_printf(Unit *u, const char* format) {
-
- /*
- * This will use the passed string as format string and
- * replace the following specifiers:
- *
- * %n: the full id of the unit (foo@bar.waldo)
- * %N: the id of the unit without the suffix (foo@bar)
- * %p: the prefix (foo)
- * %i: the instance (bar)
- */
-
- const Specifier table[] = {
- { 'n', specifier_string, u->id },
- { 'N', specifier_prefix_and_instance, NULL },
- { 'p', specifier_prefix, NULL },
- { 'i', specifier_string, u->instance },
- { 0, NULL, NULL }
- };
-
- assert(u);
- assert(format);
-
- return specifier_printf(format, table, u);
-}
-
-char *unit_full_printf(Unit *u, const char *format) {
-
- /* This is similar to unit_name_printf() but also supports
- * unescaping. Also, adds a couple of additional codes:
- *
- * %f the the instance if set, otherwise the id
- * %c cgroup path of unit
- * %r root cgroup path of this systemd instance (e.g. "/user/lennart/shared/systemd-4711")
- * %R parent of root cgroup path (e.g. "/usr/lennart/shared")
- * %t the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR)
- * %u the username of the configured user or running user
- * %h the homedir of the configured user or running user
- * %s the shell of the configured user or running user
- * %m the machine ID of the running system
- * %b the boot ID of the running system
- * %H the host name of the running system
- */
-
- const Specifier table[] = {
- { 'n', specifier_string, u->id },
- { 'N', specifier_prefix_and_instance, NULL },
- { 'p', specifier_prefix, NULL },
- { 'P', specifier_prefix_unescaped, NULL },
- { 'i', specifier_string, u->instance },
- { 'I', specifier_instance_unescaped, NULL },
-
- { 'f', specifier_filename, NULL },
- { 'c', specifier_cgroup, NULL },
- { 'r', specifier_cgroup_root, NULL },
- { 'R', specifier_cgroup_root, NULL },
- { 't', specifier_runtime, NULL },
- { 'u', specifier_user_name, NULL },
- { 'h', specifier_user_home, NULL },
- { 's', specifier_user_shell, NULL },
-
- { 'm', specifier_machine_id, NULL },
- { 'H', specifier_host_name, NULL },
- { 'b', specifier_boot_id, NULL },
- { 0, NULL, NULL }
- };
-
- assert(u);
- assert(format);
-
- return specifier_printf(format, table, u);
-}
-
-char **unit_full_printf_strv(Unit *u, char **l) {
- size_t n;
- char **r, **i, **j;
-
- /* Applies unit_full_printf to every entry in l */
-
- assert(u);
-
- n = strv_length(l);
- r = new(char*, n+1);
- if (!r)
- return NULL;
-
- for (i = l, j = r; *i; i++, j++) {
- *j = unit_full_printf(u, *i);
- if (!*j)
- goto fail;
- }
-
- *j = NULL;
- return r;
-
-fail:
- for (j--; j >= r; j--)
- free(*j);
-
- free(r);
-
- return NULL;
-}
diff --git a/src/core/unit-printf.h b/src/core/unit-printf.h
deleted file mode 100644
index d2f4ccd178..0000000000
--- a/src/core/unit-printf.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*-*- 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 "unit.h"
-
-char *unit_name_printf(Unit *u, const char* text);
-char *unit_full_printf(Unit *u, const char *text);
-char **unit_full_printf_strv(Unit *u, char **l);
diff --git a/src/core/unit.c b/src/core/unit.c
deleted file mode 100644
index 99e1c27948..0000000000
--- a/src/core/unit.c
+++ /dev/null
@@ -1,2738 +0,0 @@
-/*-*- 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 <assert.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/epoll.h>
-#include <sys/timerfd.h>
-#include <sys/poll.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/stat.h>
-
-#include "systemd/sd-id128.h"
-#include "systemd/sd-messages.h"
-#include "set.h"
-#include "unit.h"
-#include "macro.h"
-#include "strv.h"
-#include "path-util.h"
-#include "load-fragment.h"
-#include "load-dropin.h"
-#include "log.h"
-#include "unit-name.h"
-#include "dbus-unit.h"
-#include "special.h"
-#include "cgroup-util.h"
-#include "missing.h"
-#include "cgroup-attr.h"
-
-const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
- [UNIT_SERVICE] = &service_vtable,
- [UNIT_TIMER] = &timer_vtable,
- [UNIT_SOCKET] = &socket_vtable,
- [UNIT_TARGET] = &target_vtable,
- [UNIT_DEVICE] = &device_vtable,
- [UNIT_MOUNT] = &mount_vtable,
- [UNIT_AUTOMOUNT] = &automount_vtable,
- [UNIT_SNAPSHOT] = &snapshot_vtable,
- [UNIT_SWAP] = &swap_vtable,
- [UNIT_PATH] = &path_vtable
-};
-
-Unit *unit_new(Manager *m, size_t size) {
- Unit *u;
-
- assert(m);
- assert(size >= sizeof(Unit));
-
- u = malloc0(size);
- if (!u)
- return NULL;
-
- u->names = set_new(string_hash_func, string_compare_func);
- if (!u->names) {
- free(u);
- return NULL;
- }
-
- u->manager = m;
- u->type = _UNIT_TYPE_INVALID;
- u->deserialized_job = _JOB_TYPE_INVALID;
- u->default_dependencies = true;
- u->unit_file_state = _UNIT_FILE_STATE_INVALID;
-
- return u;
-}
-
-bool unit_has_name(Unit *u, const char *name) {
- assert(u);
- assert(name);
-
- return !!set_get(u->names, (char*) name);
-}
-
-int unit_add_name(Unit *u, const char *text) {
- UnitType t;
- char *s, *i = NULL;
- int r;
-
- assert(u);
- assert(text);
-
- if (unit_name_is_template(text)) {
- if (!u->instance)
- return -EINVAL;
-
- s = unit_name_replace_instance(text, u->instance);
- } else
- s = strdup(text);
-
- if (!s)
- return -ENOMEM;
-
- if (!unit_name_is_valid(s, false)) {
- r = -EINVAL;
- goto fail;
- }
-
- assert_se((t = unit_name_to_type(s)) >= 0);
-
- if (u->type != _UNIT_TYPE_INVALID && t != u->type) {
- r = -EINVAL;
- goto fail;
- }
-
- if ((r = unit_name_to_instance(s, &i)) < 0)
- goto fail;
-
- if (i && unit_vtable[t]->no_instances) {
- r = -EINVAL;
- goto fail;
- }
-
- /* Ensure that this unit is either instanced or not instanced,
- * but not both. */
- if (u->type != _UNIT_TYPE_INVALID && !u->instance != !i) {
- r = -EINVAL;
- goto fail;
- }
-
- if (unit_vtable[t]->no_alias &&
- !set_isempty(u->names) &&
- !set_get(u->names, s)) {
- r = -EEXIST;
- goto fail;
- }
-
- if (hashmap_size(u->manager->units) >= MANAGER_MAX_NAMES) {
- r = -E2BIG;
- goto fail;
- }
-
- if ((r = set_put(u->names, s)) < 0) {
- if (r == -EEXIST)
- r = 0;
- goto fail;
- }
-
- if ((r = hashmap_put(u->manager->units, s, u)) < 0) {
- set_remove(u->names, s);
- goto fail;
- }
-
- if (u->type == _UNIT_TYPE_INVALID) {
-
- u->type = t;
- u->id = s;
- u->instance = i;
-
- LIST_PREPEND(Unit, units_by_type, u->manager->units_by_type[t], u);
-
- if (UNIT_VTABLE(u)->init)
- UNIT_VTABLE(u)->init(u);
- } else
- free(i);
-
- unit_add_to_dbus_queue(u);
- return 0;
-
-fail:
- free(s);
- free(i);
-
- return r;
-}
-
-int unit_choose_id(Unit *u, const char *name) {
- char *s, *t = NULL, *i;
- int r;
-
- assert(u);
- assert(name);
-
- if (unit_name_is_template(name)) {
-
- if (!u->instance)
- return -EINVAL;
-
- if (!(t = unit_name_replace_instance(name, u->instance)))
- return -ENOMEM;
-
- name = t;
- }
-
- /* Selects one of the names of this unit as the id */
- s = set_get(u->names, (char*) name);
- free(t);
-
- if (!s)
- return -ENOENT;
-
- if ((r = unit_name_to_instance(s, &i)) < 0)
- return r;
-
- u->id = s;
-
- free(u->instance);
- u->instance = i;
-
- unit_add_to_dbus_queue(u);
-
- return 0;
-}
-
-int unit_set_description(Unit *u, const char *description) {
- char *s;
-
- assert(u);
-
- if (!(s = strdup(description)))
- return -ENOMEM;
-
- free(u->description);
- u->description = s;
-
- unit_add_to_dbus_queue(u);
- return 0;
-}
-
-bool unit_check_gc(Unit *u) {
- assert(u);
-
- if (u->load_state == UNIT_STUB)
- return true;
-
- if (UNIT_VTABLE(u)->no_gc)
- return true;
-
- if (u->no_gc)
- return true;
-
- if (u->job)
- return true;
-
- if (u->nop_job)
- return true;
-
- if (unit_active_state(u) != UNIT_INACTIVE)
- return true;
-
- if (u->refs)
- return true;
-
- if (UNIT_VTABLE(u)->check_gc)
- if (UNIT_VTABLE(u)->check_gc(u))
- return true;
-
- return false;
-}
-
-void unit_add_to_load_queue(Unit *u) {
- assert(u);
- assert(u->type != _UNIT_TYPE_INVALID);
-
- if (u->load_state != UNIT_STUB || u->in_load_queue)
- return;
-
- LIST_PREPEND(Unit, load_queue, u->manager->load_queue, u);
- u->in_load_queue = true;
-}
-
-void unit_add_to_cleanup_queue(Unit *u) {
- assert(u);
-
- if (u->in_cleanup_queue)
- return;
-
- LIST_PREPEND(Unit, cleanup_queue, u->manager->cleanup_queue, u);
- u->in_cleanup_queue = true;
-}
-
-void unit_add_to_gc_queue(Unit *u) {
- assert(u);
-
- if (u->in_gc_queue || u->in_cleanup_queue)
- return;
-
- if (unit_check_gc(u))
- return;
-
- LIST_PREPEND(Unit, gc_queue, u->manager->gc_queue, u);
- u->in_gc_queue = true;
-
- u->manager->n_in_gc_queue ++;
-
- if (u->manager->gc_queue_timestamp <= 0)
- u->manager->gc_queue_timestamp = now(CLOCK_MONOTONIC);
-}
-
-void unit_add_to_dbus_queue(Unit *u) {
- assert(u);
- assert(u->type != _UNIT_TYPE_INVALID);
-
- if (u->load_state == UNIT_STUB || u->in_dbus_queue)
- return;
-
- /* Shortcut things if nobody cares */
- if (!bus_has_subscriber(u->manager)) {
- u->sent_dbus_new_signal = true;
- return;
- }
-
- LIST_PREPEND(Unit, dbus_queue, u->manager->dbus_unit_queue, u);
- u->in_dbus_queue = true;
-}
-
-static void bidi_set_free(Unit *u, Set *s) {
- Iterator i;
- Unit *other;
-
- assert(u);
-
- /* Frees the set and makes sure we are dropped from the
- * inverse pointers */
-
- SET_FOREACH(other, s, i) {
- UnitDependency d;
-
- for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
- set_remove(other->dependencies[d], u);
-
- unit_add_to_gc_queue(other);
- }
-
- set_free(s);
-}
-
-void unit_free(Unit *u) {
- UnitDependency d;
- Iterator i;
- char *t;
-
- assert(u);
-
- bus_unit_send_removed_signal(u);
-
- if (u->load_state != UNIT_STUB)
- if (UNIT_VTABLE(u)->done)
- UNIT_VTABLE(u)->done(u);
-
- SET_FOREACH(t, u->names, i)
- hashmap_remove_value(u->manager->units, t, u);
-
- if (u->job) {
- Job *j = u->job;
- job_uninstall(j);
- job_free(j);
- }
-
- if (u->nop_job) {
- Job *j = u->nop_job;
- job_uninstall(j);
- job_free(j);
- }
-
- for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
- bidi_set_free(u, u->dependencies[d]);
-
- if (u->requires_mounts_for) {
- LIST_REMOVE(Unit, has_requires_mounts_for, u->manager->has_requires_mounts_for, u);
- strv_free(u->requires_mounts_for);
- }
-
- if (u->type != _UNIT_TYPE_INVALID)
- LIST_REMOVE(Unit, units_by_type, u->manager->units_by_type[u->type], u);
-
- if (u->in_load_queue)
- LIST_REMOVE(Unit, load_queue, u->manager->load_queue, u);
-
- if (u->in_dbus_queue)
- LIST_REMOVE(Unit, dbus_queue, u->manager->dbus_unit_queue, u);
-
- if (u->in_cleanup_queue)
- LIST_REMOVE(Unit, cleanup_queue, u->manager->cleanup_queue, u);
-
- if (u->in_gc_queue) {
- LIST_REMOVE(Unit, gc_queue, u->manager->gc_queue, u);
- u->manager->n_in_gc_queue--;
- }
-
- cgroup_bonding_free_list(u->cgroup_bondings, u->manager->n_reloading <= 0);
- cgroup_attribute_free_list(u->cgroup_attributes);
-
- free(u->description);
- strv_free(u->documentation);
- free(u->fragment_path);
- free(u->source_path);
- free(u->instance);
-
- set_free_free(u->names);
-
- condition_free_list(u->conditions);
-
- while (u->refs)
- unit_ref_unset(u->refs);
-
- free(u);
-}
-
-UnitActiveState unit_active_state(Unit *u) {
- assert(u);
-
- if (u->load_state == UNIT_MERGED)
- return unit_active_state(unit_follow_merge(u));
-
- /* After a reload it might happen that a unit is not correctly
- * loaded but still has a process around. That's why we won't
- * shortcut failed loading to UNIT_INACTIVE_FAILED. */
-
- return UNIT_VTABLE(u)->active_state(u);
-}
-
-const char* unit_sub_state_to_string(Unit *u) {
- assert(u);
-
- return UNIT_VTABLE(u)->sub_state_to_string(u);
-}
-
-static void complete_move(Set **s, Set **other) {
- assert(s);
- assert(other);
-
- if (!*other)
- return;
-
- if (*s)
- set_move(*s, *other);
- else {
- *s = *other;
- *other = NULL;
- }
-}
-
-static void merge_names(Unit *u, Unit *other) {
- char *t;
- Iterator i;
-
- assert(u);
- assert(other);
-
- complete_move(&u->names, &other->names);
-
- set_free_free(other->names);
- other->names = NULL;
- other->id = NULL;
-
- SET_FOREACH(t, u->names, i)
- assert_se(hashmap_replace(u->manager->units, t, u) == 0);
-}
-
-static void merge_dependencies(Unit *u, Unit *other, UnitDependency d) {
- Iterator i;
- Unit *back;
- int r;
-
- assert(u);
- assert(other);
- assert(d < _UNIT_DEPENDENCY_MAX);
-
- /* Fix backwards pointers */
- SET_FOREACH(back, other->dependencies[d], i) {
- UnitDependency k;
-
- for (k = 0; k < _UNIT_DEPENDENCY_MAX; k++)
- if ((r = set_remove_and_put(back->dependencies[k], other, u)) < 0) {
-
- if (r == -EEXIST)
- set_remove(back->dependencies[k], other);
- else
- assert(r == -ENOENT);
- }
- }
-
- complete_move(&u->dependencies[d], &other->dependencies[d]);
-
- set_free(other->dependencies[d]);
- other->dependencies[d] = NULL;
-}
-
-int unit_merge(Unit *u, Unit *other) {
- UnitDependency d;
-
- assert(u);
- assert(other);
- assert(u->manager == other->manager);
- assert(u->type != _UNIT_TYPE_INVALID);
-
- other = unit_follow_merge(other);
-
- if (other == u)
- return 0;
-
- if (u->type != other->type)
- return -EINVAL;
-
- if (!u->instance != !other->instance)
- return -EINVAL;
-
- if (other->load_state != UNIT_STUB &&
- other->load_state != UNIT_ERROR)
- return -EEXIST;
-
- if (other->job)
- return -EEXIST;
-
- if (other->nop_job)
- return -EEXIST;
-
- if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other)))
- return -EEXIST;
-
- /* Merge names */
- merge_names(u, other);
-
- /* Redirect all references */
- while (other->refs)
- unit_ref_set(other->refs, u);
-
- /* Merge dependencies */
- for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
- merge_dependencies(u, other, d);
-
- other->load_state = UNIT_MERGED;
- other->merged_into = u;
-
- /* If there is still some data attached to the other node, we
- * don't need it anymore, and can free it. */
- if (other->load_state != UNIT_STUB)
- if (UNIT_VTABLE(other)->done)
- UNIT_VTABLE(other)->done(other);
-
- unit_add_to_dbus_queue(u);
- unit_add_to_cleanup_queue(other);
-
- return 0;
-}
-
-int unit_merge_by_name(Unit *u, const char *name) {
- Unit *other;
- int r;
- char *s = NULL;
-
- assert(u);
- assert(name);
-
- if (unit_name_is_template(name)) {
- if (!u->instance)
- return -EINVAL;
-
- if (!(s = unit_name_replace_instance(name, u->instance)))
- return -ENOMEM;
-
- name = s;
- }
-
- if (!(other = manager_get_unit(u->manager, name)))
- r = unit_add_name(u, name);
- else
- r = unit_merge(u, other);
-
- free(s);
- return r;
-}
-
-Unit* unit_follow_merge(Unit *u) {
- assert(u);
-
- while (u->load_state == UNIT_MERGED)
- assert_se(u = u->merged_into);
-
- return u;
-}
-
-int unit_add_exec_dependencies(Unit *u, ExecContext *c) {
- int r;
-
- assert(u);
- assert(c);
-
- if (c->std_output != EXEC_OUTPUT_KMSG &&
- c->std_output != EXEC_OUTPUT_SYSLOG &&
- c->std_output != EXEC_OUTPUT_JOURNAL &&
- c->std_output != EXEC_OUTPUT_KMSG_AND_CONSOLE &&
- c->std_output != EXEC_OUTPUT_SYSLOG_AND_CONSOLE &&
- c->std_output != EXEC_OUTPUT_JOURNAL_AND_CONSOLE &&
- c->std_error != EXEC_OUTPUT_KMSG &&
- c->std_error != EXEC_OUTPUT_SYSLOG &&
- c->std_error != EXEC_OUTPUT_JOURNAL &&
- c->std_error != EXEC_OUTPUT_KMSG_AND_CONSOLE &&
- c->std_error != EXEC_OUTPUT_JOURNAL_AND_CONSOLE &&
- c->std_error != EXEC_OUTPUT_SYSLOG_AND_CONSOLE)
- return 0;
-
- /* If syslog or kernel logging is requested, make sure our own
- * logging daemon is run first. */
-
- if (u->manager->running_as == SYSTEMD_SYSTEM)
- if ((r = unit_add_two_dependencies_by_name(u, UNIT_REQUIRES, UNIT_AFTER, SPECIAL_JOURNALD_SOCKET, NULL, true)) < 0)
- return r;
-
- return 0;
-}
-
-const char *unit_description(Unit *u) {
- assert(u);
-
- if (u->description)
- return u->description;
-
- return strna(u->id);
-}
-
-void unit_dump(Unit *u, FILE *f, const char *prefix) {
- char *t, **j;
- UnitDependency d;
- Iterator i;
- char *p2;
- const char *prefix2;
- char
- timestamp1[FORMAT_TIMESTAMP_MAX],
- timestamp2[FORMAT_TIMESTAMP_MAX],
- timestamp3[FORMAT_TIMESTAMP_MAX],
- timestamp4[FORMAT_TIMESTAMP_MAX],
- timespan[FORMAT_TIMESPAN_MAX];
- Unit *following;
-
- assert(u);
- assert(u->type >= 0);
-
- if (!prefix)
- prefix = "";
- p2 = strappend(prefix, "\t");
- prefix2 = p2 ? p2 : prefix;
-
- fprintf(f,
- "%s-> Unit %s:\n"
- "%s\tDescription: %s\n"
- "%s\tInstance: %s\n"
- "%s\tUnit Load State: %s\n"
- "%s\tUnit Active State: %s\n"
- "%s\tInactive Exit Timestamp: %s\n"
- "%s\tActive Enter Timestamp: %s\n"
- "%s\tActive Exit Timestamp: %s\n"
- "%s\tInactive Enter Timestamp: %s\n"
- "%s\tGC Check Good: %s\n"
- "%s\tNeed Daemon Reload: %s\n",
- prefix, u->id,
- prefix, unit_description(u),
- prefix, strna(u->instance),
- prefix, unit_load_state_to_string(u->load_state),
- prefix, unit_active_state_to_string(unit_active_state(u)),
- prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->inactive_exit_timestamp.realtime)),
- prefix, strna(format_timestamp(timestamp2, sizeof(timestamp2), u->active_enter_timestamp.realtime)),
- prefix, strna(format_timestamp(timestamp3, sizeof(timestamp3), u->active_exit_timestamp.realtime)),
- prefix, strna(format_timestamp(timestamp4, sizeof(timestamp4), u->inactive_enter_timestamp.realtime)),
- prefix, yes_no(unit_check_gc(u)),
- prefix, yes_no(unit_need_daemon_reload(u)));
-
- SET_FOREACH(t, u->names, i)
- fprintf(f, "%s\tName: %s\n", prefix, t);
-
- STRV_FOREACH(j, u->documentation)
- fprintf(f, "%s\tDocumentation: %s\n", prefix, *j);
-
- if ((following = unit_following(u)))
- fprintf(f, "%s\tFollowing: %s\n", prefix, following->id);
-
- if (u->fragment_path)
- fprintf(f, "%s\tFragment Path: %s\n", prefix, u->fragment_path);
-
- if (u->source_path)
- fprintf(f, "%s\tSource Path: %s\n", prefix, u->source_path);
-
- if (u->job_timeout > 0)
- fprintf(f, "%s\tJob Timeout: %s\n", prefix, format_timespan(timespan, sizeof(timespan), u->job_timeout));
-
- condition_dump_list(u->conditions, f, prefix);
-
- if (dual_timestamp_is_set(&u->condition_timestamp))
- fprintf(f,
- "%s\tCondition Timestamp: %s\n"
- "%s\tCondition Result: %s\n",
- prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->condition_timestamp.realtime)),
- prefix, yes_no(u->condition_result));
-
- for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) {
- Unit *other;
-
- SET_FOREACH(other, u->dependencies[d], i)
- fprintf(f, "%s\t%s: %s\n", prefix, unit_dependency_to_string(d), other->id);
- }
-
- if (!strv_isempty(u->requires_mounts_for)) {
- fprintf(f,
- "%s\tRequiresMountsFor:", prefix);
-
- STRV_FOREACH(j, u->requires_mounts_for)
- fprintf(f, " %s", *j);
-
- fputs("\n", f);
- }
-
- if (u->load_state == UNIT_LOADED) {
- CGroupBonding *b;
- CGroupAttribute *a;
-
- fprintf(f,
- "%s\tStopWhenUnneeded: %s\n"
- "%s\tRefuseManualStart: %s\n"
- "%s\tRefuseManualStop: %s\n"
- "%s\tDefaultDependencies: %s\n"
- "%s\tOnFailureIsolate: %s\n"
- "%s\tIgnoreOnIsolate: %s\n"
- "%s\tIgnoreOnSnapshot: %s\n",
- prefix, yes_no(u->stop_when_unneeded),
- prefix, yes_no(u->refuse_manual_start),
- prefix, yes_no(u->refuse_manual_stop),
- prefix, yes_no(u->default_dependencies),
- prefix, yes_no(u->on_failure_isolate),
- prefix, yes_no(u->ignore_on_isolate),
- prefix, yes_no(u->ignore_on_snapshot));
-
- LIST_FOREACH(by_unit, b, u->cgroup_bondings)
- fprintf(f, "%s\tControlGroup: %s:%s\n",
- prefix, b->controller, b->path);
-
- LIST_FOREACH(by_unit, a, u->cgroup_attributes) {
- char *v = NULL;
-
- if (a->map_callback)
- a->map_callback(a->controller, a->name, a->value, &v);
-
- fprintf(f, "%s\tControlGroupAttribute: %s %s \"%s\"\n",
- prefix, a->controller, a->name, v ? v : a->value);
-
- free(v);
- }
-
- if (UNIT_VTABLE(u)->dump)
- UNIT_VTABLE(u)->dump(u, f, prefix2);
-
- } else if (u->load_state == UNIT_MERGED)
- fprintf(f,
- "%s\tMerged into: %s\n",
- prefix, u->merged_into->id);
- else if (u->load_state == UNIT_ERROR)
- fprintf(f, "%s\tLoad Error Code: %s\n", prefix, strerror(-u->load_error));
-
-
- if (u->job)
- job_dump(u->job, f, prefix2);
-
- if (u->nop_job)
- job_dump(u->nop_job, f, prefix2);
-
- free(p2);
-}
-
-/* Common implementation for multiple backends */
-int unit_load_fragment_and_dropin(Unit *u) {
- int r;
-
- assert(u);
-
- /* Load a .service file */
- if ((r = unit_load_fragment(u)) < 0)
- return r;
-
- if (u->load_state == UNIT_STUB)
- return -ENOENT;
-
- /* Load drop-in directory data */
- if ((r = unit_load_dropin(unit_follow_merge(u))) < 0)
- return r;
-
- return 0;
-}
-
-/* Common implementation for multiple backends */
-int unit_load_fragment_and_dropin_optional(Unit *u) {
- int r;
-
- assert(u);
-
- /* Same as unit_load_fragment_and_dropin(), but whether
- * something can be loaded or not doesn't matter. */
-
- /* Load a .service file */
- if ((r = unit_load_fragment(u)) < 0)
- return r;
-
- if (u->load_state == UNIT_STUB)
- u->load_state = UNIT_LOADED;
-
- /* Load drop-in directory data */
- if ((r = unit_load_dropin(unit_follow_merge(u))) < 0)
- return r;
-
- return 0;
-}
-
-int unit_add_default_target_dependency(Unit *u, Unit *target) {
- assert(u);
- assert(target);
-
- if (target->type != UNIT_TARGET)
- return 0;
-
- /* Only add the dependency if both units are loaded, so that
- * that loop check below is reliable */
- if (u->load_state != UNIT_LOADED ||
- target->load_state != UNIT_LOADED)
- return 0;
-
- /* If either side wants no automatic dependencies, then let's
- * skip this */
- if (!u->default_dependencies ||
- !target->default_dependencies)
- return 0;
-
- /* Don't create loops */
- if (set_get(target->dependencies[UNIT_BEFORE], u))
- return 0;
-
- return unit_add_dependency(target, UNIT_AFTER, u, true);
-}
-
-static int unit_add_default_dependencies(Unit *u) {
- static const UnitDependency deps[] = {
- UNIT_REQUIRED_BY,
- UNIT_REQUIRED_BY_OVERRIDABLE,
- UNIT_WANTED_BY,
- UNIT_BOUND_BY
- };
-
- Unit *target;
- Iterator i;
- int r;
- unsigned k;
-
- assert(u);
-
- for (k = 0; k < ELEMENTSOF(deps); k++)
- SET_FOREACH(target, u->dependencies[deps[k]], i)
- if ((r = unit_add_default_target_dependency(u, target)) < 0)
- return r;
-
- return 0;
-}
-
-int unit_load(Unit *u) {
- int r;
-
- assert(u);
-
- if (u->in_load_queue) {
- LIST_REMOVE(Unit, load_queue, u->manager->load_queue, u);
- u->in_load_queue = false;
- }
-
- if (u->type == _UNIT_TYPE_INVALID)
- return -EINVAL;
-
- if (u->load_state != UNIT_STUB)
- return 0;
-
- if (UNIT_VTABLE(u)->load)
- if ((r = UNIT_VTABLE(u)->load(u)) < 0)
- goto fail;
-
- if (u->load_state == UNIT_STUB) {
- r = -ENOENT;
- goto fail;
- }
-
- if (u->load_state == UNIT_LOADED &&
- u->default_dependencies)
- if ((r = unit_add_default_dependencies(u)) < 0)
- goto fail;
-
- if (u->load_state == UNIT_LOADED) {
- r = unit_add_mount_links(u);
- if (r < 0)
- return r;
- }
-
- if (u->on_failure_isolate &&
- set_size(u->dependencies[UNIT_ON_FAILURE]) > 1) {
-
- log_error("More than one OnFailure= dependencies specified for %s but OnFailureIsolate= enabled. Refusing.",
- u->id);
-
- r = -EINVAL;
- goto fail;
- }
-
- assert((u->load_state != UNIT_MERGED) == !u->merged_into);
-
- unit_add_to_dbus_queue(unit_follow_merge(u));
- unit_add_to_gc_queue(u);
-
- return 0;
-
-fail:
- u->load_state = UNIT_ERROR;
- u->load_error = r;
- unit_add_to_dbus_queue(u);
- unit_add_to_gc_queue(u);
-
- log_debug("Failed to load configuration for %s: %s", u->id, strerror(-r));
-
- return r;
-}
-
-bool unit_condition_test(Unit *u) {
- assert(u);
-
- dual_timestamp_get(&u->condition_timestamp);
- u->condition_result = condition_test_list(u->conditions);
-
- return u->condition_result;
-}
-
-static const char* unit_get_status_message_format(Unit *u, JobType t) {
- const UnitStatusMessageFormats *format_table;
-
- assert(u);
- assert(t >= 0);
- assert(t < _JOB_TYPE_MAX);
-
- if (t != JOB_START && t != JOB_STOP)
- return NULL;
-
- format_table = &UNIT_VTABLE(u)->status_message_formats;
- if (!format_table)
- return NULL;
-
- return format_table->starting_stopping[t == JOB_STOP];
-}
-
-static const char *unit_get_status_message_format_try_harder(Unit *u, JobType t) {
- const char *format;
-
- assert(u);
- assert(t >= 0);
- assert(t < _JOB_TYPE_MAX);
-
- format = unit_get_status_message_format(u, t);
- if (format)
- return format;
-
- /* Return generic strings */
- if (t == JOB_START)
- return "Starting %s.";
- else if (t == JOB_STOP)
- return "Stopping %s.";
- else if (t == JOB_RELOAD)
- return "Reloading %s.";
-
- return NULL;
-}
-
-static void unit_status_print_starting_stopping(Unit *u, JobType t) {
- const char *format;
-
- assert(u);
-
- /* We only print status messages for selected units on
- * selected operations. */
-
- format = unit_get_status_message_format(u, t);
- if (!format)
- return;
-
- unit_status_printf(u, "", format, unit_description(u));
-}
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wformat-nonliteral"
-static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) {
- const char *format;
- char buf[LINE_MAX];
- sd_id128_t mid;
-
- assert(u);
-
- if (t != JOB_START && t != JOB_STOP && t != JOB_RELOAD)
- return;
-
- if (log_on_console())
- return;
-
- /* We log status messages for all units and all operations. */
-
- format = unit_get_status_message_format_try_harder(u, t);
- if (!format)
- return;
-
- snprintf(buf, sizeof(buf), format, unit_description(u));
- char_array_0(buf);
-
- mid = t == JOB_START ? SD_MESSAGE_UNIT_STARTING :
- t == JOB_STOP ? SD_MESSAGE_UNIT_STOPPING :
- SD_MESSAGE_UNIT_RELOADING;
-
- log_struct(LOG_INFO,
- MESSAGE_ID(mid),
- "UNIT=%s", u->id,
- "MESSAGE=%s", buf,
- NULL);
-}
-#pragma GCC diagnostic pop
-
-/* Errors:
- * -EBADR: This unit type does not support starting.
- * -EALREADY: Unit is already started.
- * -EAGAIN: An operation is already in progress. Retry later.
- * -ECANCELED: Too many requests for now.
- */
-int unit_start(Unit *u) {
- UnitActiveState state;
- Unit *following;
-
- assert(u);
-
- if (u->load_state != UNIT_LOADED)
- return -EINVAL;
-
- /* If this is already started, then this will succeed. Note
- * that this will even succeed if this unit is not startable
- * by the user. This is relied on to detect when we need to
- * wait for units and when waiting is finished. */
- state = unit_active_state(u);
- if (UNIT_IS_ACTIVE_OR_RELOADING(state))
- return -EALREADY;
-
- /* If the conditions failed, don't do anything at all. If we
- * already are activating this call might still be useful to
- * speed up activation in case there is some hold-off time,
- * but we don't want to recheck the condition in that case. */
- if (state != UNIT_ACTIVATING &&
- !unit_condition_test(u)) {
- log_debug("Starting of %s requested but condition failed. Ignoring.", u->id);
- return -EALREADY;
- }
-
- /* Forward to the main object, if we aren't it. */
- if ((following = unit_following(u))) {
- log_debug("Redirecting start request from %s to %s.", u->id, following->id);
- return unit_start(following);
- }
-
- unit_status_log_starting_stopping_reloading(u, JOB_START);
- unit_status_print_starting_stopping(u, JOB_START);
-
- /* If it is stopped, but we cannot start it, then fail */
- if (!UNIT_VTABLE(u)->start)
- return -EBADR;
-
- /* We don't suppress calls to ->start() here when we are
- * already starting, to allow this request to be used as a
- * "hurry up" call, for example when the unit is in some "auto
- * restart" state where it waits for a holdoff timer to elapse
- * before it will start again. */
-
- unit_add_to_dbus_queue(u);
-
- return UNIT_VTABLE(u)->start(u);
-}
-
-bool unit_can_start(Unit *u) {
- assert(u);
-
- return !!UNIT_VTABLE(u)->start;
-}
-
-bool unit_can_isolate(Unit *u) {
- assert(u);
-
- return unit_can_start(u) &&
- u->allow_isolate;
-}
-
-/* Errors:
- * -EBADR: This unit type does not support stopping.
- * -EALREADY: Unit is already stopped.
- * -EAGAIN: An operation is already in progress. Retry later.
- */
-int unit_stop(Unit *u) {
- UnitActiveState state;
- Unit *following;
-
- assert(u);
-
- state = unit_active_state(u);
- if (UNIT_IS_INACTIVE_OR_FAILED(state))
- return -EALREADY;
-
- if ((following = unit_following(u))) {
- log_debug("Redirecting stop request from %s to %s.", u->id, following->id);
- return unit_stop(following);
- }
-
- unit_status_log_starting_stopping_reloading(u, JOB_STOP);
- unit_status_print_starting_stopping(u, JOB_STOP);
-
- if (!UNIT_VTABLE(u)->stop)
- return -EBADR;
-
- unit_add_to_dbus_queue(u);
-
- return UNIT_VTABLE(u)->stop(u);
-}
-
-/* Errors:
- * -EBADR: This unit type does not support reloading.
- * -ENOEXEC: Unit is not started.
- * -EAGAIN: An operation is already in progress. Retry later.
- */
-int unit_reload(Unit *u) {
- UnitActiveState state;
- Unit *following;
-
- assert(u);
-
- if (u->load_state != UNIT_LOADED)
- return -EINVAL;
-
- if (!unit_can_reload(u))
- return -EBADR;
-
- state = unit_active_state(u);
- if (state == UNIT_RELOADING)
- return -EALREADY;
-
- if (state != UNIT_ACTIVE)
- return -ENOEXEC;
-
- if ((following = unit_following(u))) {
- log_debug("Redirecting reload request from %s to %s.", u->id, following->id);
- return unit_reload(following);
- }
-
- unit_status_log_starting_stopping_reloading(u, JOB_RELOAD);
-
- unit_add_to_dbus_queue(u);
- return UNIT_VTABLE(u)->reload(u);
-}
-
-bool unit_can_reload(Unit *u) {
- assert(u);
-
- if (!UNIT_VTABLE(u)->reload)
- return false;
-
- if (!UNIT_VTABLE(u)->can_reload)
- return true;
-
- return UNIT_VTABLE(u)->can_reload(u);
-}
-
-static void unit_check_unneeded(Unit *u) {
- Iterator i;
- Unit *other;
-
- assert(u);
-
- /* If this service shall be shut down when unneeded then do
- * so. */
-
- if (!u->stop_when_unneeded)
- return;
-
- if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)))
- return;
-
- SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i)
- if (unit_pending_active(other))
- return;
-
- SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
- if (unit_pending_active(other))
- return;
-
- SET_FOREACH(other, u->dependencies[UNIT_WANTED_BY], i)
- if (unit_pending_active(other))
- return;
-
- SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
- if (unit_pending_active(other))
- return;
-
- log_info("Service %s is not needed anymore. Stopping.", u->id);
-
- /* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */
- manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, true, NULL, NULL);
-}
-
-static void retroactively_start_dependencies(Unit *u) {
- Iterator i;
- Unit *other;
-
- assert(u);
- assert(UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)));
-
- SET_FOREACH(other, u->dependencies[UNIT_REQUIRES], i)
- if (!set_get(u->dependencies[UNIT_AFTER], other) &&
- !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
- manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, true, NULL, NULL);
-
- SET_FOREACH(other, u->dependencies[UNIT_BINDS_TO], i)
- if (!set_get(u->dependencies[UNIT_AFTER], other) &&
- !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
- manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, true, NULL, NULL);
-
- SET_FOREACH(other, u->dependencies[UNIT_REQUIRES_OVERRIDABLE], i)
- if (!set_get(u->dependencies[UNIT_AFTER], other) &&
- !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
- manager_add_job(u->manager, JOB_START, other, JOB_FAIL, false, NULL, NULL);
-
- SET_FOREACH(other, u->dependencies[UNIT_REQUISITE], i)
- if (!set_get(u->dependencies[UNIT_AFTER], other) &&
- !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
- manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, true, NULL, NULL);
-
- SET_FOREACH(other, u->dependencies[UNIT_WANTS], i)
- if (!set_get(u->dependencies[UNIT_AFTER], other) &&
- !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
- manager_add_job(u->manager, JOB_START, other, JOB_FAIL, false, NULL, NULL);
-
- SET_FOREACH(other, u->dependencies[UNIT_CONFLICTS], i)
- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
- manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL);
-
- SET_FOREACH(other, u->dependencies[UNIT_CONFLICTED_BY], i)
- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
- manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL);
-}
-
-static void retroactively_stop_dependencies(Unit *u) {
- Iterator i;
- Unit *other;
-
- assert(u);
- assert(UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u)));
-
- /* Pull down units which are bound to us recursively if enabled */
- SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
- manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL);
-}
-
-static void check_unneeded_dependencies(Unit *u) {
- Iterator i;
- Unit *other;
-
- assert(u);
- assert(UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u)));
-
- /* Garbage collect services that might not be needed anymore, if enabled */
- SET_FOREACH(other, u->dependencies[UNIT_REQUIRES], i)
- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
- unit_check_unneeded(other);
- SET_FOREACH(other, u->dependencies[UNIT_REQUIRES_OVERRIDABLE], i)
- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
- unit_check_unneeded(other);
- SET_FOREACH(other, u->dependencies[UNIT_WANTS], i)
- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
- unit_check_unneeded(other);
- SET_FOREACH(other, u->dependencies[UNIT_REQUISITE], i)
- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
- unit_check_unneeded(other);
- SET_FOREACH(other, u->dependencies[UNIT_REQUISITE_OVERRIDABLE], i)
- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
- unit_check_unneeded(other);
- SET_FOREACH(other, u->dependencies[UNIT_BINDS_TO], i)
- if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
- unit_check_unneeded(other);
-}
-
-void unit_trigger_on_failure(Unit *u) {
- Unit *other;
- Iterator i;
-
- assert(u);
-
- if (set_size(u->dependencies[UNIT_ON_FAILURE]) <= 0)
- return;
-
- log_info("Triggering OnFailure= dependencies of %s.", u->id);
-
- SET_FOREACH(other, u->dependencies[UNIT_ON_FAILURE], i) {
- int r;
-
- if ((r = manager_add_job(u->manager, JOB_START, other, u->on_failure_isolate ? JOB_ISOLATE : JOB_REPLACE, true, NULL, NULL)) < 0)
- log_error("Failed to enqueue OnFailure= job: %s", strerror(-r));
- }
-}
-
-void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success) {
- bool unexpected;
-
- assert(u);
- assert(os < _UNIT_ACTIVE_STATE_MAX);
- assert(ns < _UNIT_ACTIVE_STATE_MAX);
-
- /* Note that this is called for all low-level state changes,
- * even if they might map to the same high-level
- * UnitActiveState! That means that ns == os is OK an expected
- * behavior here. For example: if a mount point is remounted
- * this function will be called too! */
-
- if (u->manager->n_reloading <= 0) {
- dual_timestamp ts;
-
- dual_timestamp_get(&ts);
-
- if (UNIT_IS_INACTIVE_OR_FAILED(os) && !UNIT_IS_INACTIVE_OR_FAILED(ns))
- u->inactive_exit_timestamp = ts;
- else if (!UNIT_IS_INACTIVE_OR_FAILED(os) && UNIT_IS_INACTIVE_OR_FAILED(ns))
- u->inactive_enter_timestamp = ts;
-
- if (!UNIT_IS_ACTIVE_OR_RELOADING(os) && UNIT_IS_ACTIVE_OR_RELOADING(ns))
- u->active_enter_timestamp = ts;
- else if (UNIT_IS_ACTIVE_OR_RELOADING(os) && !UNIT_IS_ACTIVE_OR_RELOADING(ns))
- u->active_exit_timestamp = ts;
-
- timer_unit_notify(u, ns);
- path_unit_notify(u, ns);
- }
-
- if (UNIT_IS_INACTIVE_OR_FAILED(ns))
- cgroup_bonding_trim_list(u->cgroup_bondings, true);
-
- if (u->job) {
- unexpected = false;
-
- if (u->job->state == JOB_WAITING)
-
- /* So we reached a different state for this
- * job. Let's see if we can run it now if it
- * failed previously due to EAGAIN. */
- job_add_to_run_queue(u->job);
-
- /* Let's check whether this state change constitutes a
- * finished job, or maybe contradicts a running job and
- * hence needs to invalidate jobs. */
-
- switch (u->job->type) {
-
- case JOB_START:
- case JOB_VERIFY_ACTIVE:
-
- if (UNIT_IS_ACTIVE_OR_RELOADING(ns))
- job_finish_and_invalidate(u->job, JOB_DONE, true);
- else if (u->job->state == JOB_RUNNING && ns != UNIT_ACTIVATING) {
- unexpected = true;
-
- if (UNIT_IS_INACTIVE_OR_FAILED(ns))
- job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true);
- }
-
- break;
-
- case JOB_RELOAD:
- case JOB_RELOAD_OR_START:
-
- if (u->job->state == JOB_RUNNING) {
- if (ns == UNIT_ACTIVE)
- job_finish_and_invalidate(u->job, reload_success ? JOB_DONE : JOB_FAILED, true);
- else if (ns != UNIT_ACTIVATING && ns != UNIT_RELOADING) {
- unexpected = true;
-
- if (UNIT_IS_INACTIVE_OR_FAILED(ns))
- job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true);
- }
- }
-
- break;
-
- case JOB_STOP:
- case JOB_RESTART:
- case JOB_TRY_RESTART:
-
- if (UNIT_IS_INACTIVE_OR_FAILED(ns))
- job_finish_and_invalidate(u->job, JOB_DONE, true);
- else if (u->job->state == JOB_RUNNING && ns != UNIT_DEACTIVATING) {
- unexpected = true;
- job_finish_and_invalidate(u->job, JOB_FAILED, true);
- }
-
- break;
-
- default:
- assert_not_reached("Job type unknown");
- }
-
- } else
- unexpected = true;
-
- if (u->manager->n_reloading <= 0) {
-
- /* If this state change happened without being
- * requested by a job, then let's retroactively start
- * or stop dependencies. We skip that step when
- * deserializing, since we don't want to create any
- * additional jobs just because something is already
- * activated. */
-
- if (unexpected) {
- if (UNIT_IS_INACTIVE_OR_FAILED(os) && UNIT_IS_ACTIVE_OR_ACTIVATING(ns))
- retroactively_start_dependencies(u);
- else if (UNIT_IS_ACTIVE_OR_ACTIVATING(os) && UNIT_IS_INACTIVE_OR_DEACTIVATING(ns))
- retroactively_stop_dependencies(u);
- }
-
- /* stop unneeded units regardless if going down was expected or not */
- if (UNIT_IS_ACTIVE_OR_ACTIVATING(os) && UNIT_IS_INACTIVE_OR_DEACTIVATING(ns))
- check_unneeded_dependencies(u);
-
- if (ns != os && ns == UNIT_FAILED) {
- log_struct(LOG_NOTICE,
- "MESSAGE=Unit %s entered failed state", u->id,
- "UNIT=%s", u->id,
- NULL);
- unit_trigger_on_failure(u);
- }
- }
-
- /* Some names are special */
- if (UNIT_IS_ACTIVE_OR_RELOADING(ns)) {
-
- if (unit_has_name(u, SPECIAL_DBUS_SERVICE))
- /* The bus just might have become available,
- * hence try to connect to it, if we aren't
- * yet connected. */
- bus_init(u->manager, true);
-
- if (u->type == UNIT_SERVICE &&
- !UNIT_IS_ACTIVE_OR_RELOADING(os) &&
- u->manager->n_reloading <= 0) {
- /* Write audit record if we have just finished starting up */
- manager_send_unit_audit(u->manager, u, AUDIT_SERVICE_START, true);
- u->in_audit = true;
- }
-
- if (!UNIT_IS_ACTIVE_OR_RELOADING(os))
- manager_send_unit_plymouth(u->manager, u);
-
- } else {
-
- /* We don't care about D-Bus here, since we'll get an
- * asynchronous notification for it anyway. */
-
- if (u->type == UNIT_SERVICE &&
- UNIT_IS_INACTIVE_OR_FAILED(ns) &&
- !UNIT_IS_INACTIVE_OR_FAILED(os) &&
- u->manager->n_reloading <= 0) {
-
- /* Hmm, if there was no start record written
- * write it now, so that we always have a nice
- * pair */
- if (!u->in_audit) {
- manager_send_unit_audit(u->manager, u, AUDIT_SERVICE_START, ns == UNIT_INACTIVE);
-
- if (ns == UNIT_INACTIVE)
- manager_send_unit_audit(u->manager, u, AUDIT_SERVICE_STOP, true);
- } else
- /* Write audit record if we have just finished shutting down */
- manager_send_unit_audit(u->manager, u, AUDIT_SERVICE_STOP, ns == UNIT_INACTIVE);
-
- u->in_audit = false;
- }
- }
-
- manager_recheck_journal(u->manager);
-
- /* Maybe we finished startup and are now ready for being
- * stopped because unneeded? */
- unit_check_unneeded(u);
-
- unit_add_to_dbus_queue(u);
- unit_add_to_gc_queue(u);
-}
-
-int unit_watch_fd(Unit *u, int fd, uint32_t events, Watch *w) {
- struct epoll_event ev;
-
- assert(u);
- assert(fd >= 0);
- assert(w);
- assert(w->type == WATCH_INVALID || (w->type == WATCH_FD && w->fd == fd && w->data.unit == u));
-
- zero(ev);
- ev.data.ptr = w;
- ev.events = events;
-
- if (epoll_ctl(u->manager->epoll_fd,
- w->type == WATCH_INVALID ? EPOLL_CTL_ADD : EPOLL_CTL_MOD,
- fd,
- &ev) < 0)
- return -errno;
-
- w->fd = fd;
- w->type = WATCH_FD;
- w->data.unit = u;
-
- return 0;
-}
-
-void unit_unwatch_fd(Unit *u, Watch *w) {
- assert(u);
- assert(w);
-
- if (w->type == WATCH_INVALID)
- return;
-
- assert(w->type == WATCH_FD);
- assert(w->data.unit == u);
- assert_se(epoll_ctl(u->manager->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
-
- w->fd = -1;
- w->type = WATCH_INVALID;
- w->data.unit = NULL;
-}
-
-int unit_watch_pid(Unit *u, pid_t pid) {
- assert(u);
- assert(pid >= 1);
-
- /* Watch a specific PID. We only support one unit watching
- * each PID for now. */
-
- return hashmap_put(u->manager->watch_pids, LONG_TO_PTR(pid), u);
-}
-
-void unit_unwatch_pid(Unit *u, pid_t pid) {
- assert(u);
- assert(pid >= 1);
-
- hashmap_remove_value(u->manager->watch_pids, LONG_TO_PTR(pid), u);
-}
-
-int unit_watch_timer(Unit *u, usec_t delay, Watch *w) {
- struct itimerspec its;
- int flags, fd;
- bool ours;
-
- assert(u);
- assert(w);
- assert(w->type == WATCH_INVALID || (w->type == WATCH_UNIT_TIMER && w->data.unit == u));
-
- /* This will try to reuse the old timer if there is one */
-
- if (w->type == WATCH_UNIT_TIMER) {
- assert(w->data.unit == u);
- assert(w->fd >= 0);
-
- ours = false;
- fd = w->fd;
- } else if (w->type == WATCH_INVALID) {
-
- ours = true;
- if ((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0)
- return -errno;
- } else
- assert_not_reached("Invalid watch type");
-
- zero(its);
-
- if (delay <= 0) {
- /* Set absolute time in the past, but not 0, since we
- * don't want to disarm the timer */
- its.it_value.tv_sec = 0;
- its.it_value.tv_nsec = 1;
-
- flags = TFD_TIMER_ABSTIME;
- } else {
- timespec_store(&its.it_value, delay);
- flags = 0;
- }
-
- /* This will also flush the elapse counter */
- if (timerfd_settime(fd, flags, &its, NULL) < 0)
- goto fail;
-
- if (w->type == WATCH_INVALID) {
- struct epoll_event ev;
-
- zero(ev);
- ev.data.ptr = w;
- ev.events = EPOLLIN;
-
- if (epoll_ctl(u->manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0)
- goto fail;
- }
-
- w->type = WATCH_UNIT_TIMER;
- w->fd = fd;
- w->data.unit = u;
-
- return 0;
-
-fail:
- if (ours)
- close_nointr_nofail(fd);
-
- return -errno;
-}
-
-void unit_unwatch_timer(Unit *u, Watch *w) {
- assert(u);
- assert(w);
-
- if (w->type == WATCH_INVALID)
- return;
-
- assert(w->type == WATCH_UNIT_TIMER);
- assert(w->data.unit == u);
- assert(w->fd >= 0);
-
- assert_se(epoll_ctl(u->manager->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
- close_nointr_nofail(w->fd);
-
- w->fd = -1;
- w->type = WATCH_INVALID;
- w->data.unit = NULL;
-}
-
-bool unit_job_is_applicable(Unit *u, JobType j) {
- assert(u);
- assert(j >= 0 && j < _JOB_TYPE_MAX);
-
- switch (j) {
-
- case JOB_VERIFY_ACTIVE:
- case JOB_START:
- case JOB_STOP:
- case JOB_NOP:
- return true;
-
- case JOB_RESTART:
- case JOB_TRY_RESTART:
- return unit_can_start(u);
-
- case JOB_RELOAD:
- return unit_can_reload(u);
-
- case JOB_RELOAD_OR_START:
- return unit_can_reload(u) && unit_can_start(u);
-
- default:
- assert_not_reached("Invalid job type");
- }
-}
-
-int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_reference) {
-
- static const UnitDependency inverse_table[_UNIT_DEPENDENCY_MAX] = {
- [UNIT_REQUIRES] = UNIT_REQUIRED_BY,
- [UNIT_REQUIRES_OVERRIDABLE] = UNIT_REQUIRED_BY_OVERRIDABLE,
- [UNIT_WANTS] = UNIT_WANTED_BY,
- [UNIT_REQUISITE] = UNIT_REQUIRED_BY,
- [UNIT_REQUISITE_OVERRIDABLE] = UNIT_REQUIRED_BY_OVERRIDABLE,
- [UNIT_BINDS_TO] = UNIT_BOUND_BY,
- [UNIT_PART_OF] = UNIT_CONSISTS_OF,
- [UNIT_REQUIRED_BY] = _UNIT_DEPENDENCY_INVALID,
- [UNIT_REQUIRED_BY_OVERRIDABLE] = _UNIT_DEPENDENCY_INVALID,
- [UNIT_WANTED_BY] = _UNIT_DEPENDENCY_INVALID,
- [UNIT_BOUND_BY] = UNIT_BINDS_TO,
- [UNIT_CONSISTS_OF] = UNIT_PART_OF,
- [UNIT_CONFLICTS] = UNIT_CONFLICTED_BY,
- [UNIT_CONFLICTED_BY] = UNIT_CONFLICTS,
- [UNIT_BEFORE] = UNIT_AFTER,
- [UNIT_AFTER] = UNIT_BEFORE,
- [UNIT_ON_FAILURE] = _UNIT_DEPENDENCY_INVALID,
- [UNIT_REFERENCES] = UNIT_REFERENCED_BY,
- [UNIT_REFERENCED_BY] = UNIT_REFERENCES,
- [UNIT_TRIGGERS] = UNIT_TRIGGERED_BY,
- [UNIT_TRIGGERED_BY] = UNIT_TRIGGERS,
- [UNIT_PROPAGATES_RELOAD_TO] = UNIT_RELOAD_PROPAGATED_FROM,
- [UNIT_RELOAD_PROPAGATED_FROM] = UNIT_PROPAGATES_RELOAD_TO,
- };
- int r, q = 0, v = 0, w = 0;
-
- assert(u);
- assert(d >= 0 && d < _UNIT_DEPENDENCY_MAX);
- assert(other);
-
- u = unit_follow_merge(u);
- other = unit_follow_merge(other);
-
- /* We won't allow dependencies on ourselves. We will not
- * consider them an error however. */
- if (u == other)
- return 0;
-
- if ((r = set_ensure_allocated(&u->dependencies[d], trivial_hash_func, trivial_compare_func)) < 0)
- return r;
-
- if (inverse_table[d] != _UNIT_DEPENDENCY_INVALID)
- if ((r = set_ensure_allocated(&other->dependencies[inverse_table[d]], trivial_hash_func, trivial_compare_func)) < 0)
- return r;
-
- if (add_reference)
- if ((r = set_ensure_allocated(&u->dependencies[UNIT_REFERENCES], trivial_hash_func, trivial_compare_func)) < 0 ||
- (r = set_ensure_allocated(&other->dependencies[UNIT_REFERENCED_BY], trivial_hash_func, trivial_compare_func)) < 0)
- return r;
-
- if ((q = set_put(u->dependencies[d], other)) < 0)
- return q;
-
- if (inverse_table[d] != _UNIT_DEPENDENCY_INVALID)
- if ((v = set_put(other->dependencies[inverse_table[d]], u)) < 0) {
- r = v;
- goto fail;
- }
-
- if (add_reference) {
- if ((w = set_put(u->dependencies[UNIT_REFERENCES], other)) < 0) {
- r = w;
- goto fail;
- }
-
- if ((r = set_put(other->dependencies[UNIT_REFERENCED_BY], u)) < 0)
- goto fail;
- }
-
- unit_add_to_dbus_queue(u);
- return 0;
-
-fail:
- if (q > 0)
- set_remove(u->dependencies[d], other);
-
- if (v > 0)
- set_remove(other->dependencies[inverse_table[d]], u);
-
- if (w > 0)
- set_remove(u->dependencies[UNIT_REFERENCES], other);
-
- return r;
-}
-
-int unit_add_two_dependencies(Unit *u, UnitDependency d, UnitDependency e, Unit *other, bool add_reference) {
- int r;
-
- assert(u);
-
- if ((r = unit_add_dependency(u, d, other, add_reference)) < 0)
- return r;
-
- if ((r = unit_add_dependency(u, e, other, add_reference)) < 0)
- return r;
-
- return 0;
-}
-
-static const char *resolve_template(Unit *u, const char *name, const char*path, char **p) {
- char *s;
-
- assert(u);
- assert(name || path);
-
- if (!name)
- name = path_get_file_name(path);
-
- if (!unit_name_is_template(name)) {
- *p = NULL;
- return name;
- }
-
- if (u->instance)
- s = unit_name_replace_instance(name, u->instance);
- else {
- char *i;
-
- if (!(i = unit_name_to_prefix(u->id)))
- return NULL;
-
- s = unit_name_replace_instance(name, i);
- free(i);
- }
-
- if (!s)
- return NULL;
-
- *p = s;
- return s;
-}
-
-int unit_add_dependency_by_name(Unit *u, UnitDependency d, const char *name, const char *path, bool add_reference) {
- Unit *other;
- int r;
- char *s;
-
- assert(u);
- assert(name || path);
-
- if (!(name = resolve_template(u, name, path, &s)))
- return -ENOMEM;
-
- if ((r = manager_load_unit(u->manager, name, path, NULL, &other)) < 0)
- goto finish;
-
- r = unit_add_dependency(u, d, other, add_reference);
-
-finish:
- free(s);
- return r;
-}
-
-int unit_add_two_dependencies_by_name(Unit *u, UnitDependency d, UnitDependency e, const char *name, const char *path, bool add_reference) {
- Unit *other;
- int r;
- char *s;
-
- assert(u);
- assert(name || path);
-
- if (!(name = resolve_template(u, name, path, &s)))
- return -ENOMEM;
-
- if ((r = manager_load_unit(u->manager, name, path, NULL, &other)) < 0)
- goto finish;
-
- r = unit_add_two_dependencies(u, d, e, other, add_reference);
-
-finish:
- free(s);
- return r;
-}
-
-int unit_add_dependency_by_name_inverse(Unit *u, UnitDependency d, const char *name, const char *path, bool add_reference) {
- Unit *other;
- int r;
- char *s;
-
- assert(u);
- assert(name || path);
-
- if (!(name = resolve_template(u, name, path, &s)))
- return -ENOMEM;
-
- if ((r = manager_load_unit(u->manager, name, path, NULL, &other)) < 0)
- goto finish;
-
- r = unit_add_dependency(other, d, u, add_reference);
-
-finish:
- free(s);
- return r;
-}
-
-int unit_add_two_dependencies_by_name_inverse(Unit *u, UnitDependency d, UnitDependency e, const char *name, const char *path, bool add_reference) {
- Unit *other;
- int r;
- char *s;
-
- assert(u);
- assert(name || path);
-
- if (!(name = resolve_template(u, name, path, &s)))
- return -ENOMEM;
-
- if ((r = manager_load_unit(u->manager, name, path, NULL, &other)) < 0)
- goto finish;
-
- if ((r = unit_add_two_dependencies(other, d, e, u, add_reference)) < 0)
- goto finish;
-
-finish:
- free(s);
- return r;
-}
-
-int set_unit_path(const char *p) {
- char *cwd, *c;
- int r;
-
- /* This is mostly for debug purposes */
-
- if (path_is_absolute(p)) {
- if (!(c = strdup(p)))
- return -ENOMEM;
- } else {
- if (!(cwd = get_current_dir_name()))
- return -errno;
-
- r = asprintf(&c, "%s/%s", cwd, p);
- free(cwd);
-
- if (r < 0)
- return -ENOMEM;
- }
-
- if (setenv("SYSTEMD_UNIT_PATH", c, 0) < 0) {
- r = -errno;
- free(c);
- return r;
- }
-
- return 0;
-}
-
-char *unit_dbus_path(Unit *u) {
- assert(u);
-
- if (!u->id)
- return NULL;
-
- return unit_dbus_path_from_name(u->id);
-}
-
-int unit_add_cgroup(Unit *u, CGroupBonding *b) {
- int r;
-
- assert(u);
- assert(b);
-
- assert(b->path);
-
- if (!b->controller) {
- if (!(b->controller = strdup(SYSTEMD_CGROUP_CONTROLLER)))
- return -ENOMEM;
-
- b->ours = true;
- }
-
- /* Ensure this hasn't been added yet */
- assert(!b->unit);
-
- if (streq(b->controller, SYSTEMD_CGROUP_CONTROLLER)) {
- CGroupBonding *l;
-
- l = hashmap_get(u->manager->cgroup_bondings, b->path);
- LIST_PREPEND(CGroupBonding, by_path, l, b);
-
- if ((r = hashmap_replace(u->manager->cgroup_bondings, b->path, l)) < 0) {
- LIST_REMOVE(CGroupBonding, by_path, l, b);
- return r;
- }
- }
-
- LIST_PREPEND(CGroupBonding, by_unit, u->cgroup_bondings, b);
- b->unit = u;
-
- return 0;
-}
-
-char *unit_default_cgroup_path(Unit *u) {
- char *p;
-
- assert(u);
-
- if (u->instance) {
- char *t;
-
- t = unit_name_template(u->id);
- if (!t)
- return NULL;
-
- p = strjoin(u->manager->cgroup_hierarchy, "/", t, "/", u->instance, NULL);
- free(t);
- } else
- p = strjoin(u->manager->cgroup_hierarchy, "/", u->id, NULL);
-
- return p;
-}
-
-int unit_add_cgroup_from_text(Unit *u, const char *name) {
- char *controller = NULL, *path = NULL;
- CGroupBonding *b = NULL;
- bool ours = false;
- int r;
-
- assert(u);
- assert(name);
-
- if ((r = cg_split_spec(name, &controller, &path)) < 0)
- return r;
-
- if (!path) {
- path = unit_default_cgroup_path(u);
- ours = true;
- }
-
- if (!controller) {
- controller = strdup(SYSTEMD_CGROUP_CONTROLLER);
- ours = true;
- }
-
- if (!path || !controller) {
- free(path);
- free(controller);
-
- return -ENOMEM;
- }
-
- if (cgroup_bonding_find_list(u->cgroup_bondings, controller)) {
- r = -EEXIST;
- goto fail;
- }
-
- if (!(b = new0(CGroupBonding, 1))) {
- r = -ENOMEM;
- goto fail;
- }
-
- b->controller = controller;
- b->path = path;
- b->ours = ours;
- b->essential = streq(controller, SYSTEMD_CGROUP_CONTROLLER);
-
- if ((r = unit_add_cgroup(u, b)) < 0)
- goto fail;
-
- return 0;
-
-fail:
- free(path);
- free(controller);
- free(b);
-
- return r;
-}
-
-static int unit_add_one_default_cgroup(Unit *u, const char *controller) {
- CGroupBonding *b = NULL;
- int r = -ENOMEM;
-
- assert(u);
-
- if (!controller)
- controller = SYSTEMD_CGROUP_CONTROLLER;
-
- if (cgroup_bonding_find_list(u->cgroup_bondings, controller))
- return 0;
-
- if (!(b = new0(CGroupBonding, 1)))
- return -ENOMEM;
-
- if (!(b->controller = strdup(controller)))
- goto fail;
-
- b->path = unit_default_cgroup_path(u);
- if (!b->path)
- goto fail;
-
- b->ours = true;
- b->essential = streq(controller, SYSTEMD_CGROUP_CONTROLLER);
-
- if ((r = unit_add_cgroup(u, b)) < 0)
- goto fail;
-
- return 0;
-
-fail:
- free(b->path);
- free(b->controller);
- free(b);
-
- return r;
-}
-
-int unit_add_default_cgroups(Unit *u) {
- CGroupAttribute *a;
- char **c;
- int r;
-
- assert(u);
-
- /* Adds in the default cgroups, if they weren't specified
- * otherwise. */
-
- if (!u->manager->cgroup_hierarchy)
- return 0;
-
- if ((r = unit_add_one_default_cgroup(u, NULL)) < 0)
- return r;
-
- STRV_FOREACH(c, u->manager->default_controllers)
- unit_add_one_default_cgroup(u, *c);
-
- LIST_FOREACH(by_unit, a, u->cgroup_attributes)
- unit_add_one_default_cgroup(u, a->controller);
-
- return 0;
-}
-
-CGroupBonding* unit_get_default_cgroup(Unit *u) {
- assert(u);
-
- return cgroup_bonding_find_list(u->cgroup_bondings, SYSTEMD_CGROUP_CONTROLLER);
-}
-
-int unit_add_cgroup_attribute(Unit *u, const char *controller, const char *name, const char *value, CGroupAttributeMapCallback map_callback) {
- int r;
- char *c = NULL;
- CGroupAttribute *a;
-
- assert(u);
- assert(name);
- assert(value);
-
- if (!controller) {
- const char *dot;
-
- dot = strchr(name, '.');
- if (!dot)
- return -EINVAL;
-
- c = strndup(name, dot - name);
- if (!c)
- return -ENOMEM;
-
- controller = c;
- }
-
- if (streq(controller, SYSTEMD_CGROUP_CONTROLLER)) {
- r = -EINVAL;
- goto finish;
- }
-
- a = new0(CGroupAttribute, 1);
- if (!a) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (c) {
- a->controller = c;
- c = NULL;
- } else
- a->controller = strdup(controller);
-
- a->name = strdup(name);
- a->value = strdup(value);
-
- if (!a->controller || !a->name || !a->value) {
- free(a->controller);
- free(a->name);
- free(a->value);
- free(a);
-
- return -ENOMEM;
- }
-
- a->map_callback = map_callback;
-
- LIST_PREPEND(CGroupAttribute, by_unit, u->cgroup_attributes, a);
-
- r = 0;
-
-finish:
- free(c);
- return r;
-}
-
-int unit_load_related_unit(Unit *u, const char *type, Unit **_found) {
- char *t;
- int r;
-
- assert(u);
- assert(type);
- assert(_found);
-
- if (!(t = unit_name_change_suffix(u->id, type)))
- return -ENOMEM;
-
- assert(!unit_has_name(u, t));
-
- r = manager_load_unit(u->manager, t, NULL, NULL, _found);
- free(t);
-
- assert(r < 0 || *_found != u);
-
- return r;
-}
-
-int unit_get_related_unit(Unit *u, const char *type, Unit **_found) {
- Unit *found;
- char *t;
-
- assert(u);
- assert(type);
- assert(_found);
-
- if (!(t = unit_name_change_suffix(u->id, type)))
- return -ENOMEM;
-
- assert(!unit_has_name(u, t));
-
- found = manager_get_unit(u->manager, t);
- free(t);
-
- if (!found)
- return -ENOENT;
-
- *_found = found;
- return 0;
-}
-
-int unit_watch_bus_name(Unit *u, const char *name) {
- assert(u);
- assert(name);
-
- /* Watch a specific name on the bus. We only support one unit
- * watching each name for now. */
-
- return hashmap_put(u->manager->watch_bus, name, u);
-}
-
-void unit_unwatch_bus_name(Unit *u, const char *name) {
- assert(u);
- assert(name);
-
- hashmap_remove_value(u->manager->watch_bus, name, u);
-}
-
-bool unit_can_serialize(Unit *u) {
- assert(u);
-
- return UNIT_VTABLE(u)->serialize && UNIT_VTABLE(u)->deserialize_item;
-}
-
-int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
- int r;
-
- assert(u);
- assert(f);
- assert(fds);
-
- if (!unit_can_serialize(u))
- return 0;
-
- if ((r = UNIT_VTABLE(u)->serialize(u, f, fds)) < 0)
- return r;
-
-
- if (serialize_jobs) {
- if (u->job) {
- fprintf(f, "job\n");
- job_serialize(u->job, f, fds);
- }
-
- if (u->nop_job) {
- fprintf(f, "job\n");
- job_serialize(u->nop_job, f, fds);
- }
- }
-
- dual_timestamp_serialize(f, "inactive-exit-timestamp", &u->inactive_exit_timestamp);
- dual_timestamp_serialize(f, "active-enter-timestamp", &u->active_enter_timestamp);
- dual_timestamp_serialize(f, "active-exit-timestamp", &u->active_exit_timestamp);
- dual_timestamp_serialize(f, "inactive-enter-timestamp", &u->inactive_enter_timestamp);
- dual_timestamp_serialize(f, "condition-timestamp", &u->condition_timestamp);
-
- if (dual_timestamp_is_set(&u->condition_timestamp))
- unit_serialize_item(u, f, "condition-result", yes_no(u->condition_result));
-
- /* End marker */
- fputc('\n', f);
- return 0;
-}
-
-void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *format, ...) {
- va_list ap;
-
- assert(u);
- assert(f);
- assert(key);
- assert(format);
-
- fputs(key, f);
- fputc('=', f);
-
- va_start(ap, format);
- vfprintf(f, format, ap);
- va_end(ap);
-
- fputc('\n', f);
-}
-
-void unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value) {
- assert(u);
- assert(f);
- assert(key);
- assert(value);
-
- fprintf(f, "%s=%s\n", key, value);
-}
-
-int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
- int r;
-
- assert(u);
- assert(f);
- assert(fds);
-
- if (!unit_can_serialize(u))
- return 0;
-
- for (;;) {
- char line[LINE_MAX], *l, *v;
- size_t k;
-
- if (!fgets(line, sizeof(line), f)) {
- if (feof(f))
- return 0;
- return -errno;
- }
-
- char_array_0(line);
- l = strstrip(line);
-
- /* End marker */
- if (l[0] == 0)
- return 0;
-
- k = strcspn(l, "=");
-
- if (l[k] == '=') {
- l[k] = 0;
- v = l+k+1;
- } else
- v = l+k;
-
- if (streq(l, "job")) {
- if (v[0] == '\0') {
- /* new-style serialized job */
- Job *j = job_new_raw(u);
- if (!j)
- return -ENOMEM;
-
- r = job_deserialize(j, f, fds);
- if (r < 0) {
- job_free(j);
- return r;
- }
-
- r = hashmap_put(u->manager->jobs, UINT32_TO_PTR(j->id), j);
- if (r < 0) {
- job_free(j);
- return r;
- }
-
- r = job_install_deserialized(j);
- if (r < 0) {
- hashmap_remove(u->manager->jobs, UINT32_TO_PTR(j->id));
- job_free(j);
- return r;
- }
- } else {
- /* legacy */
- JobType type = job_type_from_string(v);
- if (type < 0)
- log_debug("Failed to parse job type value %s", v);
- else
- u->deserialized_job = type;
- }
- continue;
- } else if (streq(l, "inactive-exit-timestamp")) {
- dual_timestamp_deserialize(v, &u->inactive_exit_timestamp);
- continue;
- } else if (streq(l, "active-enter-timestamp")) {
- dual_timestamp_deserialize(v, &u->active_enter_timestamp);
- continue;
- } else if (streq(l, "active-exit-timestamp")) {
- dual_timestamp_deserialize(v, &u->active_exit_timestamp);
- continue;
- } else if (streq(l, "inactive-enter-timestamp")) {
- dual_timestamp_deserialize(v, &u->inactive_enter_timestamp);
- continue;
- } else if (streq(l, "condition-timestamp")) {
- dual_timestamp_deserialize(v, &u->condition_timestamp);
- continue;
- } else if (streq(l, "condition-result")) {
- int b;
-
- if ((b = parse_boolean(v)) < 0)
- log_debug("Failed to parse condition result value %s", v);
- else
- u->condition_result = b;
-
- continue;
- }
-
- if ((r = UNIT_VTABLE(u)->deserialize_item(u, l, v, fds)) < 0)
- return r;
- }
-}
-
-int unit_add_node_link(Unit *u, const char *what, bool wants) {
- Unit *device;
- char *e;
- int r;
-
- assert(u);
-
- if (!what)
- return 0;
-
- /* Adds in links to the device node that this unit is based on */
-
- if (!is_device_path(what))
- return 0;
-
- e = unit_name_from_path(what, ".device");
- if (!e)
- return -ENOMEM;
-
- r = manager_load_unit(u->manager, e, NULL, NULL, &device);
- free(e);
- if (r < 0)
- return r;
-
- r = unit_add_two_dependencies(u, UNIT_AFTER, UNIT_BINDS_TO, device, true);
- if (r < 0)
- return r;
-
- if (wants) {
- r = unit_add_dependency(device, UNIT_WANTS, u, false);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-int unit_coldplug(Unit *u) {
- int r;
-
- assert(u);
-
- if (UNIT_VTABLE(u)->coldplug)
- if ((r = UNIT_VTABLE(u)->coldplug(u)) < 0)
- return r;
-
- if (u->job) {
- r = job_coldplug(u->job);
- if (r < 0)
- return r;
- } else if (u->deserialized_job >= 0) {
- /* legacy */
- r = manager_add_job(u->manager, u->deserialized_job, u, JOB_IGNORE_REQUIREMENTS, false, NULL, NULL);
- if (r < 0)
- return r;
-
- u->deserialized_job = _JOB_TYPE_INVALID;
- }
-
- return 0;
-}
-
-void unit_status_printf(Unit *u, const char *status, const char *format, ...) {
- va_list ap;
-
- assert(u);
- assert(format);
-
- if (!manager_get_show_status(u->manager))
- return;
-
- if (!manager_is_booting_or_shutting_down(u->manager))
- return;
-
- va_start(ap, format);
- status_vprintf(status, true, format, ap);
- va_end(ap);
-}
-
-bool unit_need_daemon_reload(Unit *u) {
- struct stat st;
-
- assert(u);
-
- if (u->fragment_path) {
- zero(st);
- if (stat(u->fragment_path, &st) < 0)
- /* What, cannot access this anymore? */
- return true;
-
- if (u->fragment_mtime > 0 &&
- timespec_load(&st.st_mtim) != u->fragment_mtime)
- return true;
- }
-
- if (u->source_path) {
- zero(st);
- if (stat(u->source_path, &st) < 0)
- return true;
-
- if (u->source_mtime > 0 &&
- timespec_load(&st.st_mtim) != u->source_mtime)
- return true;
- }
-
- return false;
-}
-
-void unit_reset_failed(Unit *u) {
- assert(u);
-
- if (UNIT_VTABLE(u)->reset_failed)
- UNIT_VTABLE(u)->reset_failed(u);
-}
-
-Unit *unit_following(Unit *u) {
- assert(u);
-
- if (UNIT_VTABLE(u)->following)
- return UNIT_VTABLE(u)->following(u);
-
- return NULL;
-}
-
-bool unit_pending_inactive(Unit *u) {
- assert(u);
-
- /* Returns true if the unit is inactive or going down */
-
- if (UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u)))
- return true;
-
- if (u->job && u->job->type == JOB_STOP)
- return true;
-
- return false;
-}
-
-bool unit_pending_active(Unit *u) {
- assert(u);
-
- /* Returns true if the unit is active or going up */
-
- if (UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)))
- return true;
-
- if (u->job &&
- (u->job->type == JOB_START ||
- u->job->type == JOB_RELOAD_OR_START ||
- u->job->type == JOB_RESTART))
- return true;
-
- return false;
-}
-
-int unit_kill(Unit *u, KillWho w, int signo, DBusError *error) {
- assert(u);
- assert(w >= 0 && w < _KILL_WHO_MAX);
- assert(signo > 0);
- assert(signo < _NSIG);
-
- if (!UNIT_VTABLE(u)->kill)
- return -ENOTSUP;
-
- return UNIT_VTABLE(u)->kill(u, w, signo, error);
-}
-
-int unit_following_set(Unit *u, Set **s) {
- assert(u);
- assert(s);
-
- if (UNIT_VTABLE(u)->following_set)
- return UNIT_VTABLE(u)->following_set(u, s);
-
- *s = NULL;
- return 0;
-}
-
-UnitFileState unit_get_unit_file_state(Unit *u) {
- assert(u);
-
- if (u->unit_file_state < 0 && u->fragment_path)
- u->unit_file_state = unit_file_get_state(
- u->manager->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER,
- NULL, path_get_file_name(u->fragment_path));
-
- return u->unit_file_state;
-}
-
-Unit* unit_ref_set(UnitRef *ref, Unit *u) {
- assert(ref);
- assert(u);
-
- if (ref->unit)
- unit_ref_unset(ref);
-
- ref->unit = u;
- LIST_PREPEND(UnitRef, refs, u->refs, ref);
- return u;
-}
-
-void unit_ref_unset(UnitRef *ref) {
- assert(ref);
-
- if (!ref->unit)
- return;
-
- LIST_REMOVE(UnitRef, refs, ref->unit->refs, ref);
- ref->unit = NULL;
-}
-
-int unit_add_one_mount_link(Unit *u, Mount *m) {
- char **i;
-
- assert(u);
- assert(m);
-
- if (u->load_state != UNIT_LOADED ||
- UNIT(m)->load_state != UNIT_LOADED)
- return 0;
-
- STRV_FOREACH(i, u->requires_mounts_for) {
-
- if (UNIT(m) == u)
- continue;
-
- if (!path_startswith(*i, m->where))
- continue;
-
- return unit_add_two_dependencies(u, UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true);
- }
-
- return 0;
-}
-
-int unit_add_mount_links(Unit *u) {
- Unit *other;
- int r;
-
- assert(u);
-
- LIST_FOREACH(units_by_type, other, u->manager->units_by_type[UNIT_MOUNT]) {
- r = unit_add_one_mount_link(u, MOUNT(other));
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-int unit_exec_context_defaults(Unit *u, ExecContext *c) {
- unsigned i;
- int r;
-
- assert(u);
- assert(c);
-
- /* This only copies in the ones that need memory */
-
- for (i = 0; i < RLIMIT_NLIMITS; i++)
- if (u->manager->rlimit[i] && !c->rlimit[i]) {
- c->rlimit[i] = newdup(struct rlimit, u->manager->rlimit[i], 1);
- if (!c->rlimit[i])
- return -ENOMEM;
- }
-
- if (u->manager->running_as == SYSTEMD_USER &&
- !c->working_directory) {
-
- r = get_home_dir(&c->working_directory);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-ExecContext *unit_get_exec_context(Unit *u) {
- size_t offset;
- assert(u);
-
- offset = UNIT_VTABLE(u)->exec_context_offset;
- if (offset <= 0)
- return NULL;
-
- return (ExecContext*) ((uint8_t*) u + offset);
-}
-
-static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
- [UNIT_ACTIVE] = "active",
- [UNIT_RELOADING] = "reloading",
- [UNIT_INACTIVE] = "inactive",
- [UNIT_FAILED] = "failed",
- [UNIT_ACTIVATING] = "activating",
- [UNIT_DEACTIVATING] = "deactivating"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(unit_active_state, UnitActiveState);
-
-static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = {
- [UNIT_REQUIRES] = "Requires",
- [UNIT_REQUIRES_OVERRIDABLE] = "RequiresOverridable",
- [UNIT_REQUISITE] = "Requisite",
- [UNIT_REQUISITE_OVERRIDABLE] = "RequisiteOverridable",
- [UNIT_WANTS] = "Wants",
- [UNIT_BINDS_TO] = "BindsTo",
- [UNIT_PART_OF] = "PartOf",
- [UNIT_REQUIRED_BY] = "RequiredBy",
- [UNIT_REQUIRED_BY_OVERRIDABLE] = "RequiredByOverridable",
- [UNIT_WANTED_BY] = "WantedBy",
- [UNIT_BOUND_BY] = "BoundBy",
- [UNIT_CONSISTS_OF] = "ConsistsOf",
- [UNIT_CONFLICTS] = "Conflicts",
- [UNIT_CONFLICTED_BY] = "ConflictedBy",
- [UNIT_BEFORE] = "Before",
- [UNIT_AFTER] = "After",
- [UNIT_ON_FAILURE] = "OnFailure",
- [UNIT_TRIGGERS] = "Triggers",
- [UNIT_TRIGGERED_BY] = "TriggeredBy",
- [UNIT_PROPAGATES_RELOAD_TO] = "PropagatesReloadTo",
- [UNIT_RELOAD_PROPAGATED_FROM] = "ReloadPropagatedFrom",
- [UNIT_REFERENCES] = "References",
- [UNIT_REFERENCED_BY] = "ReferencedBy",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency);
diff --git a/src/core/unit.h b/src/core/unit.h
deleted file mode 100644
index bf961c2aac..0000000000
--- a/src/core/unit.h
+++ /dev/null
@@ -1,551 +0,0 @@
-/*-*- 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 <stdlib.h>
-
-typedef struct Unit Unit;
-typedef struct UnitVTable UnitVTable;
-typedef enum UnitActiveState UnitActiveState;
-typedef enum UnitDependency UnitDependency;
-typedef struct UnitRef UnitRef;
-typedef struct UnitStatusMessageFormats UnitStatusMessageFormats;
-
-#include "set.h"
-#include "util.h"
-#include "list.h"
-#include "socket-util.h"
-#include "execute.h"
-#include "condition.h"
-#include "install.h"
-#include "unit-name.h"
-
-enum UnitActiveState {
- UNIT_ACTIVE,
- UNIT_RELOADING,
- UNIT_INACTIVE,
- UNIT_FAILED,
- UNIT_ACTIVATING,
- UNIT_DEACTIVATING,
- _UNIT_ACTIVE_STATE_MAX,
- _UNIT_ACTIVE_STATE_INVALID = -1
-};
-
-static inline bool UNIT_IS_ACTIVE_OR_RELOADING(UnitActiveState t) {
- return t == UNIT_ACTIVE || t == UNIT_RELOADING;
-}
-
-static inline bool UNIT_IS_ACTIVE_OR_ACTIVATING(UnitActiveState t) {
- return t == UNIT_ACTIVE || t == UNIT_ACTIVATING || t == UNIT_RELOADING;
-}
-
-static inline bool UNIT_IS_INACTIVE_OR_DEACTIVATING(UnitActiveState t) {
- return t == UNIT_INACTIVE || t == UNIT_FAILED || t == UNIT_DEACTIVATING;
-}
-
-static inline bool UNIT_IS_INACTIVE_OR_FAILED(UnitActiveState t) {
- return t == UNIT_INACTIVE || t == UNIT_FAILED;
-}
-
-enum UnitDependency {
- /* Positive dependencies */
- UNIT_REQUIRES,
- UNIT_REQUIRES_OVERRIDABLE,
- UNIT_REQUISITE,
- UNIT_REQUISITE_OVERRIDABLE,
- UNIT_WANTS,
- UNIT_BINDS_TO,
- UNIT_PART_OF,
-
- /* Inverse of the above */
- UNIT_REQUIRED_BY, /* inverse of 'requires' and 'requisite' is 'required_by' */
- UNIT_REQUIRED_BY_OVERRIDABLE, /* inverse of 'requires_overridable' and 'requisite_overridable' is 'soft_required_by' */
- UNIT_WANTED_BY, /* inverse of 'wants' */
- UNIT_BOUND_BY, /* inverse of 'binds_to' */
- UNIT_CONSISTS_OF, /* inverse of 'part_of' */
-
- /* Negative dependencies */
- UNIT_CONFLICTS, /* inverse of 'conflicts' is 'conflicted_by' */
- UNIT_CONFLICTED_BY,
-
- /* Order */
- UNIT_BEFORE, /* inverse of 'before' is 'after' and vice versa */
- UNIT_AFTER,
-
- /* On Failure */
- UNIT_ON_FAILURE,
-
- /* Triggers (i.e. a socket triggers a service) */
- UNIT_TRIGGERS,
- UNIT_TRIGGERED_BY,
-
- /* Propagate reloads */
- UNIT_PROPAGATES_RELOAD_TO,
- UNIT_RELOAD_PROPAGATED_FROM,
-
- /* Reference information for GC logic */
- UNIT_REFERENCES, /* Inverse of 'references' is 'referenced_by' */
- UNIT_REFERENCED_BY,
-
- _UNIT_DEPENDENCY_MAX,
- _UNIT_DEPENDENCY_INVALID = -1
-};
-
-#include "manager.h"
-#include "job.h"
-#include "cgroup.h"
-#include "cgroup-attr.h"
-
-struct Unit {
- Manager *manager;
-
- UnitType type;
- UnitLoadState load_state;
- Unit *merged_into;
-
- char *id; /* One name is special because we use it for identification. Points to an entry in the names set */
- char *instance;
-
- Set *names;
- Set *dependencies[_UNIT_DEPENDENCY_MAX];
-
- char **requires_mounts_for;
-
- char *description;
- char **documentation;
-
- char *fragment_path; /* if loaded from a config file this is the primary path to it */
- char *source_path; /* if converted, the source file */
- usec_t fragment_mtime;
- usec_t source_mtime;
-
- /* If there is something to do with this unit, then this is the installed job for it */
- Job *job;
-
- /* JOB_NOP jobs are special and can be installed without disturbing the real job. */
- Job *nop_job;
-
- usec_t job_timeout;
-
- /* References to this */
- LIST_HEAD(UnitRef, refs);
-
- /* Conditions to check */
- LIST_HEAD(Condition, conditions);
-
- dual_timestamp condition_timestamp;
-
- dual_timestamp inactive_exit_timestamp;
- dual_timestamp active_enter_timestamp;
- dual_timestamp active_exit_timestamp;
- dual_timestamp inactive_enter_timestamp;
-
- /* Counterparts in the cgroup filesystem */
- CGroupBonding *cgroup_bondings;
- CGroupAttribute *cgroup_attributes;
-
- /* Per type list */
- LIST_FIELDS(Unit, units_by_type);
-
- /* All units which have requires_mounts_for set */
- LIST_FIELDS(Unit, has_requires_mounts_for);
-
- /* Load queue */
- LIST_FIELDS(Unit, load_queue);
-
- /* D-Bus queue */
- LIST_FIELDS(Unit, dbus_queue);
-
- /* Cleanup queue */
- LIST_FIELDS(Unit, cleanup_queue);
-
- /* GC queue */
- LIST_FIELDS(Unit, gc_queue);
-
- /* Used during GC sweeps */
- unsigned gc_marker;
-
- /* When deserializing, temporarily store the job type for this
- * unit here, if there was a job scheduled.
- * Only for deserializing from a legacy version. New style uses full
- * serialized jobs. */
- int deserialized_job; /* This is actually of type JobType */
-
- /* Error code when we didn't manage to load the unit (negative) */
- int load_error;
-
- /* Cached unit file state */
- UnitFileState unit_file_state;
-
- /* Garbage collect us we nobody wants or requires us anymore */
- bool stop_when_unneeded;
-
- /* Create default dependencies */
- bool default_dependencies;
-
- /* Refuse manual starting, allow starting only indirectly via dependency. */
- bool refuse_manual_start;
-
- /* Don't allow the user to stop this unit manually, allow stopping only indirectly via dependency. */
- bool refuse_manual_stop;
-
- /* Allow isolation requests */
- bool allow_isolate;
-
- /* Isolate OnFailure unit */
- bool on_failure_isolate;
-
- /* Ignore this unit when isolating */
- bool ignore_on_isolate;
-
- /* Ignore this unit when snapshotting */
- bool ignore_on_snapshot;
-
- /* Did the last condition check succeed? */
- bool condition_result;
-
- bool in_load_queue:1;
- bool in_dbus_queue:1;
- bool in_cleanup_queue:1;
- bool in_gc_queue:1;
-
- bool sent_dbus_new_signal:1;
-
- bool no_gc:1;
-
- bool in_audit:1;
-};
-
-struct UnitRef {
- /* Keeps tracks of references to a unit. This is useful so
- * that we can merge two units if necessary and correct all
- * references to them */
-
- Unit* unit;
- LIST_FIELDS(UnitRef, refs);
-};
-
-struct UnitStatusMessageFormats {
- const char *starting_stopping[2];
- const char *finished_start_job[_JOB_RESULT_MAX];
- const char *finished_stop_job[_JOB_RESULT_MAX];
-};
-
-#include "service.h"
-#include "timer.h"
-#include "socket.h"
-#include "target.h"
-#include "device.h"
-#include "mount.h"
-#include "automount.h"
-#include "snapshot.h"
-#include "swap.h"
-#include "path.h"
-
-struct UnitVTable {
- /* How much memory does an object of this unit type need */
- size_t object_size;
-
- /* If greater than 0, the offset into the object where
- * ExecContext is found, if the unit type has that */
- size_t exec_context_offset;
-
- /* Config file sections this unit type understands, separated
- * by NUL chars */
- const char *sections;
-
- /* This should reset all type-specific variables. This should
- * not allocate memory, and is called with zero-initialized
- * data. It should hence only initialize variables that need
- * to be set != 0. */
- void (*init)(Unit *u);
-
- /* This should free all type-specific variables. It should be
- * idempotent. */
- void (*done)(Unit *u);
-
- /* Actually load data from disk. This may fail, and should set
- * load_state to UNIT_LOADED, UNIT_MERGED or leave it at
- * UNIT_STUB if no configuration could be found. */
- int (*load)(Unit *u);
-
- /* If a lot of units got created via enumerate(), this is
- * where to actually set the state and call unit_notify(). */
- int (*coldplug)(Unit *u);
-
- void (*dump)(Unit *u, FILE *f, const char *prefix);
-
- int (*start)(Unit *u);
- int (*stop)(Unit *u);
- int (*reload)(Unit *u);
-
- int (*kill)(Unit *u, KillWho w, int signo, DBusError *error);
-
- bool (*can_reload)(Unit *u);
-
- /* Write all data that cannot be restored from other sources
- * away using unit_serialize_item() */
- int (*serialize)(Unit *u, FILE *f, FDSet *fds);
-
- /* Restore one item from the serialization */
- int (*deserialize_item)(Unit *u, const char *key, const char *data, FDSet *fds);
-
- /* Boils down the more complex internal state of this unit to
- * a simpler one that the engine can understand */
- UnitActiveState (*active_state)(Unit *u);
-
- /* Returns the substate specific to this unit type as
- * string. This is purely information so that we can give the
- * user a more fine grained explanation in which actual state a
- * unit is in. */
- const char* (*sub_state_to_string)(Unit *u);
-
- /* Return true when there is reason to keep this entry around
- * even nothing references it and it isn't active in any
- * way */
- bool (*check_gc)(Unit *u);
-
- /* Return true when this unit is suitable for snapshotting */
- bool (*check_snapshot)(Unit *u);
-
- void (*fd_event)(Unit *u, int fd, uint32_t events, Watch *w);
- void (*sigchld_event)(Unit *u, pid_t pid, int code, int status);
- void (*timer_event)(Unit *u, uint64_t n_elapsed, Watch *w);
-
- /* Reset failed state if we are in failed state */
- void (*reset_failed)(Unit *u);
-
- /* Called whenever any of the cgroups this unit watches for
- * ran empty */
- void (*cgroup_notify_empty)(Unit *u);
-
- /* Called whenever a process of this unit sends us a message */
- void (*notify_message)(Unit *u, pid_t pid, char **tags);
-
- /* Called whenever a name thus Unit registered for comes or
- * goes away. */
- void (*bus_name_owner_change)(Unit *u, const char *name, const char *old_owner, const char *new_owner);
-
- /* Called whenever a bus PID lookup finishes */
- void (*bus_query_pid_done)(Unit *u, const char *name, pid_t pid);
-
- /* Called for each message received on the bus */
- DBusHandlerResult (*bus_message_handler)(Unit *u, DBusConnection *c, DBusMessage *message);
-
- /* Return the unit this unit is following */
- Unit *(*following)(Unit *u);
-
- /* Return the set of units that are following each other */
- int (*following_set)(Unit *u, Set **s);
-
- /* This is called for each unit type and should be used to
- * enumerate existing devices and load them. However,
- * everything that is loaded here should still stay in
- * inactive state. It is the job of the coldplug() call above
- * to put the units into the initial state. */
- int (*enumerate)(Manager *m);
-
- /* Type specific cleanups. */
- void (*shutdown)(Manager *m);
-
- /* When sending out PropertiesChanged signal, which properties
- * shall be invalidated? This is a NUL separated list of
- * strings, to minimize relocations a little. */
- const char *bus_invalidating_properties;
-
- /* The interface name */
- const char *bus_interface;
-
- UnitStatusMessageFormats status_message_formats;
-
- /* Can units of this type have multiple names? */
- bool no_alias:1;
-
- /* Instances make no sense for this type */
- bool no_instances:1;
-
- /* Exclude from automatic gc */
- bool no_gc:1;
-};
-
-extern const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX];
-
-#define UNIT_VTABLE(u) unit_vtable[(u)->type]
-
-/* For casting a unit into the various unit types */
-#define DEFINE_CAST(UPPERCASE, MixedCase) \
- static inline MixedCase* UPPERCASE(Unit *u) { \
- if (_unlikely_(!u || u->type != UNIT_##UPPERCASE)) \
- return NULL; \
- \
- return (MixedCase*) u; \
- }
-
-/* For casting the various unit types into a unit */
-#define UNIT(u) (&(u)->meta)
-
-DEFINE_CAST(SOCKET, Socket);
-DEFINE_CAST(TIMER, Timer);
-DEFINE_CAST(SERVICE, Service);
-DEFINE_CAST(TARGET, Target);
-DEFINE_CAST(DEVICE, Device);
-DEFINE_CAST(MOUNT, Mount);
-DEFINE_CAST(AUTOMOUNT, Automount);
-DEFINE_CAST(SNAPSHOT, Snapshot);
-DEFINE_CAST(SWAP, Swap);
-DEFINE_CAST(PATH, Path);
-
-Unit *unit_new(Manager *m, size_t size);
-void unit_free(Unit *u);
-
-int unit_add_name(Unit *u, const char *name);
-
-int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_reference);
-int unit_add_two_dependencies(Unit *u, UnitDependency d, UnitDependency e, Unit *other, bool add_reference);
-
-int unit_add_dependency_by_name(Unit *u, UnitDependency d, const char *name, const char *filename, bool add_reference);
-int unit_add_two_dependencies_by_name(Unit *u, UnitDependency d, UnitDependency e, const char *name, const char *path, bool add_reference);
-
-int unit_add_dependency_by_name_inverse(Unit *u, UnitDependency d, const char *name, const char *filename, bool add_reference);
-int unit_add_two_dependencies_by_name_inverse(Unit *u, UnitDependency d, UnitDependency e, const char *name, const char *path, bool add_reference);
-
-int unit_add_exec_dependencies(Unit *u, ExecContext *c);
-
-int unit_add_cgroup(Unit *u, CGroupBonding *b);
-int unit_add_cgroup_from_text(Unit *u, const char *name);
-int unit_add_default_cgroups(Unit *u);
-CGroupBonding* unit_get_default_cgroup(Unit *u);
-int unit_add_cgroup_attribute(Unit *u, const char *controller, const char *name, const char *value, CGroupAttributeMapCallback map_callback);
-
-int unit_choose_id(Unit *u, const char *name);
-int unit_set_description(Unit *u, const char *description);
-
-bool unit_check_gc(Unit *u);
-
-void unit_add_to_load_queue(Unit *u);
-void unit_add_to_dbus_queue(Unit *u);
-void unit_add_to_cleanup_queue(Unit *u);
-void unit_add_to_gc_queue(Unit *u);
-
-int unit_merge(Unit *u, Unit *other);
-int unit_merge_by_name(Unit *u, const char *other);
-
-Unit *unit_follow_merge(Unit *u);
-
-int unit_load_fragment_and_dropin(Unit *u);
-int unit_load_fragment_and_dropin_optional(Unit *u);
-int unit_load(Unit *unit);
-
-const char *unit_description(Unit *u);
-
-bool unit_has_name(Unit *u, const char *name);
-
-UnitActiveState unit_active_state(Unit *u);
-
-const char* unit_sub_state_to_string(Unit *u);
-
-void unit_dump(Unit *u, FILE *f, const char *prefix);
-
-bool unit_can_reload(Unit *u);
-bool unit_can_start(Unit *u);
-bool unit_can_isolate(Unit *u);
-
-int unit_start(Unit *u);
-int unit_stop(Unit *u);
-int unit_reload(Unit *u);
-
-int unit_kill(Unit *u, KillWho w, int signo, DBusError *error);
-
-void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success);
-
-int unit_watch_fd(Unit *u, int fd, uint32_t events, Watch *w);
-void unit_unwatch_fd(Unit *u, Watch *w);
-
-int unit_watch_pid(Unit *u, pid_t pid);
-void unit_unwatch_pid(Unit *u, pid_t pid);
-
-int unit_watch_timer(Unit *u, usec_t delay, Watch *w);
-void unit_unwatch_timer(Unit *u, Watch *w);
-
-int unit_watch_bus_name(Unit *u, const char *name);
-void unit_unwatch_bus_name(Unit *u, const char *name);
-
-bool unit_job_is_applicable(Unit *u, JobType j);
-
-int set_unit_path(const char *p);
-
-char *unit_dbus_path(Unit *u);
-
-int unit_load_related_unit(Unit *u, const char *type, Unit **_found);
-int unit_get_related_unit(Unit *u, const char *type, Unit **_found);
-
-bool unit_can_serialize(Unit *u);
-int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs);
-void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *value, ...) _printf_attr_(4,5);
-void unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value);
-int unit_deserialize(Unit *u, FILE *f, FDSet *fds);
-
-int unit_add_node_link(Unit *u, const char *what, bool wants);
-
-int unit_coldplug(Unit *u);
-
-void unit_status_printf(Unit *u, const char *status, const char *format, ...);
-
-bool unit_need_daemon_reload(Unit *u);
-
-void unit_reset_failed(Unit *u);
-
-Unit *unit_following(Unit *u);
-
-bool unit_pending_inactive(Unit *u);
-bool unit_pending_active(Unit *u);
-
-int unit_add_default_target_dependency(Unit *u, Unit *target);
-
-char *unit_default_cgroup_path(Unit *u);
-
-int unit_following_set(Unit *u, Set **s);
-
-void unit_trigger_on_failure(Unit *u);
-
-bool unit_condition_test(Unit *u);
-
-UnitFileState unit_get_unit_file_state(Unit *u);
-
-Unit* unit_ref_set(UnitRef *ref, Unit *u);
-void unit_ref_unset(UnitRef *ref);
-
-#define UNIT_DEREF(ref) ((ref).unit)
-
-int unit_add_one_mount_link(Unit *u, Mount *m);
-int unit_add_mount_links(Unit *u);
-
-int unit_exec_context_defaults(Unit *u, ExecContext *c);
-
-ExecContext *unit_get_exec_context(Unit *u);
-
-const char *unit_active_state_to_string(UnitActiveState i);
-UnitActiveState unit_active_state_from_string(const char *s);
-
-const char *unit_dependency_to_string(UnitDependency i);
-UnitDependency unit_dependency_from_string(const char *s);
diff --git a/src/core/user.conf b/src/core/user.conf
deleted file mode 100644
index e02b46bc3a..0000000000
--- a/src/core/user.conf
+++ /dev/null
@@ -1,17 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# See systemd.conf(5) for details
-
-[Manager]
-#LogLevel=info
-#LogTarget=console
-#LogColor=yes
-#LogLocation=no
-#DefaultControllers=cpu
-#DefaultStandardOutput=inherit
-#DefaultStandardError=inherit
diff --git a/src/cryptsetup/Makefile b/src/cryptsetup/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/cryptsetup/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
deleted file mode 100644
index 386714b4fd..0000000000
--- a/src/cryptsetup/cryptsetup-generator.c
+++ /dev/null
@@ -1,449 +0,0 @@
-/*-*- 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 <errno.h>
-#include <unistd.h>
-
-#include "log.h"
-#include "util.h"
-#include "unit-name.h"
-#include "mkdir.h"
-#include "virt.h"
-#include "strv.h"
-
-static const char *arg_dest = "/tmp";
-static bool arg_enabled = true;
-static bool arg_read_crypttab = true;
-static char **arg_proc_cmdline_disks = NULL;
-
-static bool has_option(const char *haystack, const char *needle) {
- const char *f = haystack;
- size_t l;
-
- assert(needle);
-
- if (!haystack)
- return false;
-
- l = strlen(needle);
-
- while ((f = strstr(f, needle))) {
-
- if (f > haystack && f[-1] != ',') {
- f++;
- continue;
- }
-
- if (f[l] != 0 && f[l] != ',') {
- f++;
- continue;
- }
-
- return true;
- }
-
- return false;
-}
-
-static int create_disk(
- const char *name,
- const char *device,
- const char *password,
- const char *options) {
-
- char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *from = NULL, *to = NULL, *e = NULL;
- int r;
- FILE *f = NULL;
- bool noauto, nofail;
-
- assert(name);
- assert(device);
-
- noauto = has_option(options, "noauto");
- nofail = has_option(options, "nofail");
-
- n = unit_name_from_path_instance("systemd-cryptsetup", name, ".service");
- if (!n) {
- r = -ENOMEM;
- log_error("Failed to allocate unit name.");
- goto fail;
- }
-
- p = strjoin(arg_dest, "/", n, NULL);
- if (!p) {
- r = -ENOMEM;
- log_error("Failed to allocate unit file name.");
- goto fail;
- }
-
- u = fstab_node_to_udev_node(device);
- if (!u) {
- r = -ENOMEM;
- log_error("Failed to allocate device node.");
- goto fail;
- }
-
- d = unit_name_from_path(u, ".device");
- if (!d) {
- r = -ENOMEM;
- log_error("Failed to allocate device name.");
- goto fail;
- }
-
- f = fopen(p, "wxe");
- if (!f) {
- r = -errno;
- log_error("Failed to create unit file: %m");
- goto fail;
- }
-
- fprintf(f,
- "# Automatically generated by systemd-cryptsetup-generator\n\n"
- "[Unit]\n"
- "Description=Cryptography Setup for %%I\n"
- "Documentation=man:systemd-cryptsetup@.service(8) man:crypttab(5)\n"
- "SourcePath=/etc/crypttab\n"
- "Conflicts=umount.target\n"
- "DefaultDependencies=no\n"
- "BindsTo=%s dev-mapper-%%i.device\n"
- "After=systemd-readahead-collect.service systemd-readahead-replay.service %s\n"
- "Before=umount.target\n",
- d, d);
-
- if (!nofail)
- fprintf(f,
- "Before=cryptsetup.target\n");
-
- if (password && (streq(password, "/dev/urandom") ||
- streq(password, "/dev/random") ||
- streq(password, "/dev/hw_random")))
- fputs("After=systemd-random-seed-load.service\n", f);
- else
- fputs("Before=local-fs.target\n", f);
-
- fprintf(f,
- "\n[Service]\n"
- "Type=oneshot\n"
- "RemainAfterExit=yes\n"
- "TimeoutSec=0\n" /* the binary handles timeouts anyway */
- "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '%s' '%s'\n"
- "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
- name, u, strempty(password), strempty(options),
- name);
-
- if (has_option(options, "tmp"))
- fprintf(f,
- "ExecStartPost=/sbin/mke2fs '/dev/mapper/%s'\n",
- name);
-
- if (has_option(options, "swap"))
- fprintf(f,
- "ExecStartPost=/sbin/mkswap '/dev/mapper/%s'\n",
- name);
-
- fflush(f);
-
- if (ferror(f)) {
- r = -errno;
- log_error("Failed to write file: %m");
- goto fail;
- }
-
- if (asprintf(&from, "../%s", n) < 0) {
- r = -ENOMEM;
- goto fail;
- }
-
- if (!noauto) {
-
- to = strjoin(arg_dest, "/", d, ".wants/", n, NULL);
- if (!to) {
- r = -ENOMEM;
- goto fail;
- }
-
- mkdir_parents_label(to, 0755);
- if (symlink(from, to) < 0) {
- log_error("Failed to create symlink '%s' to '%s': %m", from, to);
- r = -errno;
- goto fail;
- }
-
- free(to);
-
- if (!nofail)
- to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL);
- else
- to = strjoin(arg_dest, "/cryptsetup.target.wants/", n, NULL);
- if (!to) {
- r = -ENOMEM;
- goto fail;
- }
-
- mkdir_parents_label(to, 0755);
- if (symlink(from, to) < 0) {
- log_error("Failed to create symlink '%s' to '%s': %m", from, to);
- r = -errno;
- goto fail;
- }
-
- free(to);
- to = NULL;
- }
-
- e = unit_name_escape(name);
- to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL);
- if (!to) {
- r = -ENOMEM;
- goto fail;
- }
-
- mkdir_parents_label(to, 0755);
- if (symlink(from, to) < 0) {
- log_error("Failed to create symlink '%s' to '%s': %m", from, to);
- r = -errno;
- goto fail;
- }
-
- r = 0;
-
-fail:
- free(p);
- free(n);
- free(d);
- free(e);
-
- free(from);
- free(to);
-
- if (f)
- fclose(f);
-
- return r;
-}
-
-static int parse_proc_cmdline(void) {
- char *line, *w, *state;
- int r;
- size_t l;
-
- if (detect_container(NULL) > 0)
- return 0;
-
- r = read_one_line_file("/proc/cmdline", &line);
- if (r < 0) {
- log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
- return 0;
- }
-
- FOREACH_WORD_QUOTED(w, l, line, state) {
- char *word;
-
- word = strndup(w, l);
- if (!word) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (startswith(word, "luks=")) {
- r = parse_boolean(word + 5);
- if (r < 0)
- log_warning("Failed to parse luks switch %s. Ignoring.", word + 5);
- else
- arg_enabled = r;
-
- } else if (startswith(word, "rd.luks=")) {
-
- if (in_initrd()) {
- r = parse_boolean(word + 8);
- if (r < 0)
- log_warning("Failed to parse luks switch %s. Ignoring.", word + 8);
- else
- arg_enabled = r;
- }
-
- } else if (startswith(word, "luks.crypttab=")) {
- r = parse_boolean(word + 14);
- if (r < 0)
- log_warning("Failed to parse luks crypttab switch %s. Ignoring.", word + 14);
- else
- arg_read_crypttab = r;
-
- } else if (startswith(word, "rd.luks.crypttab=")) {
-
- if (in_initrd()) {
- r = parse_boolean(word + 17);
- if (r < 0)
- log_warning("Failed to parse luks crypttab switch %s. Ignoring.", word + 17);
- else
- arg_read_crypttab = r;
- }
-
- } else if (startswith(word, "luks.uuid=")) {
- char **t;
-
- t = strv_append(arg_proc_cmdline_disks, word + 10);
- if (!t) {
- r = log_oom();
- goto finish;
- }
- strv_free(arg_proc_cmdline_disks);
- arg_proc_cmdline_disks = t;
-
- } else if (startswith(word, "rd.luks.uuid=")) {
-
- if (in_initrd()) {
- char **t;
-
- t = strv_append(arg_proc_cmdline_disks, word + 13);
- if (!t) {
- r = log_oom();
- goto finish;
- }
- strv_free(arg_proc_cmdline_disks);
- arg_proc_cmdline_disks = t;
- }
-
- } else if (startswith(word, "luks.") ||
- (in_initrd() && startswith(word, "rd.luks."))) {
-
- log_warning("Unknown kernel switch %s. Ignoring.", word);
- }
-
- free(word);
- }
-
- r = 0;
-
-finish:
- free(line);
- return r;
-}
-
-int main(int argc, char *argv[]) {
- FILE *f = NULL;
- int r = EXIT_SUCCESS;
- unsigned n = 0;
- char **i;
-
- if (argc > 1 && argc != 4) {
- log_error("This program takes three or no arguments.");
- return EXIT_FAILURE;
- }
-
- if (argc > 1)
- arg_dest = argv[1];
-
- log_set_target(LOG_TARGET_SAFE);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- if (parse_proc_cmdline() < 0)
- return EXIT_FAILURE;
-
- if (!arg_enabled) {
- r = EXIT_SUCCESS;
- goto finish;
- }
-
- STRV_FOREACH(i, arg_proc_cmdline_disks) {
- char *name, *device;
- const char *p = *i;
-
- if (startswith(p, "luks-"))
- p += 5;
-
- name = strappend("luks-", p);
- device = strappend("UUID=", p);
-
- if (!name || !device) {
- log_oom();
- r = EXIT_FAILURE;
- free(name);
- free(device);
- goto finish;
- }
-
- if (create_disk(name, device, NULL, NULL) < 0)
- r = EXIT_FAILURE;
-
- free(name);
- free(device);
- }
-
- if (!arg_read_crypttab)
- return r;
-
- f = fopen("/etc/crypttab", "re");
- if (!f) {
-
- if (errno == ENOENT)
- r = EXIT_SUCCESS;
- else {
- r = EXIT_FAILURE;
- log_error("Failed to open /etc/crypttab: %m");
- }
-
- goto finish;
- }
-
- for (;;) {
- char line[LINE_MAX], *l;
- char *name = NULL, *device = NULL, *password = NULL, *options = NULL;
- int k;
-
- if (!fgets(line, sizeof(line), f))
- break;
-
- n++;
-
- l = strstrip(line);
- if (*l == '#' || *l == 0)
- continue;
-
- k = sscanf(l, "%ms %ms %ms %ms", &name, &device, &password, &options);
- if (k < 2 || k > 4) {
- log_error("Failed to parse /etc/crypttab:%u, ignoring.", n);
- r = EXIT_FAILURE;
- goto next;
- }
-
- if (create_disk(name, device, password, options) < 0)
- r = EXIT_FAILURE;
-
- next:
- free(name);
- free(device);
- free(password);
- free(options);
- }
-
-finish:
- if (f)
- fclose(f);
-
- strv_free(arg_proc_cmdline_disks);
-
- return r;
-}
diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
deleted file mode 100644
index 56a3b50974..0000000000
--- a/src/cryptsetup/cryptsetup.c
+++ /dev/null
@@ -1,560 +0,0 @@
-/*-*- 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 <errno.h>
-#include <sys/mman.h>
-#include <mntent.h>
-
-#include <libcryptsetup.h>
-#include <libudev.h>
-
-#include "log.h"
-#include "util.h"
-#include "path-util.h"
-#include "strv.h"
-#include "ask-password-api.h"
-#include "def.h"
-
-static const char *opt_type = NULL; /* LUKS1 or PLAIN */
-static char *opt_cipher = NULL;
-static unsigned opt_key_size = 0;
-static unsigned opt_keyfile_size = 0;
-static unsigned opt_keyfile_offset = 0;
-static char *opt_hash = NULL;
-static unsigned opt_tries = 0;
-static bool opt_readonly = false;
-static bool opt_verify = false;
-static bool opt_discards = false;
-static usec_t opt_timeout = DEFAULT_TIMEOUT_USEC;
-
-/* Options Debian's crypttab knows we don't:
-
- offset=
- skip=
- precheck=
- check=
- checkargs=
- noearly=
- loud=
- keyscript=
-*/
-
-static int parse_one_option(const char *option) {
- assert(option);
-
- /* Handled outside of this tool */
- if (streq(option, "noauto"))
- return 0;
-
- if (startswith(option, "cipher=")) {
- char *t;
-
- if (!(t = strdup(option+7)))
- return -ENOMEM;
-
- free(opt_cipher);
- opt_cipher = t;
-
- } else if (startswith(option, "size=")) {
-
- if (safe_atou(option+5, &opt_key_size) < 0) {
- log_error("size= parse failure, ignoring.");
- return 0;
- }
-
- } else if (startswith(option, "keyfile-size=")) {
-
- if (safe_atou(option+13, &opt_keyfile_size) < 0) {
- log_error("keyfile-size= parse failure, ignoring.");
- return 0;
- }
-
- } else if (startswith(option, "keyfile-offset=")) {
-
- if (safe_atou(option+15, &opt_keyfile_offset) < 0) {
- log_error("keyfile-offset= parse failure, ignoring.");
- return 0;
- }
-
- } else if (startswith(option, "hash=")) {
- char *t;
-
- if (!(t = strdup(option+5)))
- return -ENOMEM;
-
- free(opt_hash);
- opt_hash = t;
-
- } else if (startswith(option, "tries=")) {
-
- if (safe_atou(option+6, &opt_tries) < 0) {
- log_error("tries= parse failure, ignoring.");
- return 0;
- }
-
- } else if (streq(option, "readonly"))
- opt_readonly = true;
- else if (streq(option, "verify"))
- opt_verify = true;
- else if (streq(option, "allow-discards"))
- opt_discards = true;
- else if (streq(option, "luks"))
- opt_type = CRYPT_LUKS1;
- else if (streq(option, "plain") ||
- streq(option, "swap") ||
- streq(option, "tmp"))
- opt_type = CRYPT_PLAIN;
- else if (startswith(option, "timeout=")) {
-
- if (parse_usec(option+8, &opt_timeout) < 0) {
- log_error("timeout= parse failure, ignoring.");
- return 0;
- }
-
- } else if (!streq(option, "none"))
- log_error("Encountered unknown /etc/crypttab option '%s', ignoring.", option);
-
- return 0;
-}
-
-static int parse_options(const char *options) {
- char *state;
- char *w;
- size_t l;
-
- assert(options);
-
- FOREACH_WORD_SEPARATOR(w, l, options, ",", state) {
- char *o;
- int r;
-
- if (!(o = strndup(w, l)))
- return -ENOMEM;
-
- r = parse_one_option(o);
- free(o);
-
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-static void log_glue(int level, const char *msg, void *usrptr) {
- log_debug("%s", msg);
-}
-
-static char *disk_description(const char *path) {
- struct udev *udev = NULL;
- struct udev_device *device = NULL;
- struct stat st;
- char *description = NULL;
- const char *model;
-
- assert(path);
-
- if (stat(path, &st) < 0)
- return NULL;
-
- if (!S_ISBLK(st.st_mode))
- return NULL;
-
- if (!(udev = udev_new()))
- return NULL;
-
- if (!(device = udev_device_new_from_devnum(udev, 'b', st.st_rdev)))
- goto finish;
-
- if ((model = udev_device_get_property_value(device, "ID_MODEL_FROM_DATABASE")) ||
- (model = udev_device_get_property_value(device, "ID_MODEL")) ||
- (model = udev_device_get_property_value(device, "DM_NAME")))
- description = strdup(model);
-
-finish:
- if (device)
- udev_device_unref(device);
-
- if (udev)
- udev_unref(udev);
-
- return description;
-}
-
-static char *disk_mount_point(const char *label) {
- char *mp = NULL, *device = NULL;
- FILE *f = NULL;
- struct mntent *m;
-
- /* Yeah, we don't support native systemd unit files here for now */
-
- if (asprintf(&device, "/dev/mapper/%s", label) < 0)
- goto finish;
-
- f = setmntent("/etc/fstab", "r");
- if (!f)
- goto finish;
-
- while ((m = getmntent(f)))
- if (path_equal(m->mnt_fsname, device)) {
- mp = strdup(m->mnt_dir);
- break;
- }
-
-finish:
- if (f)
- endmntent(f);
-
- free(device);
-
- return mp;
-}
-
-static int help(void) {
-
- printf("%s attach VOLUME SOURCEDEVICE [PASSWORD] [OPTIONS]\n"
- "%s detach VOLUME\n\n"
- "Attaches or detaches an encrypted block device.\n",
- program_invocation_short_name,
- program_invocation_short_name);
-
- return 0;
-}
-
-int main(int argc, char *argv[]) {
- int r = EXIT_FAILURE;
- struct crypt_device *cd = NULL;
- char **passwords = NULL, *truncated_cipher = NULL;
- const char *cipher = NULL, *cipher_mode = NULL, *hash = NULL, *name = NULL;
- char *description = NULL, *name_buffer = NULL, *mount_point = NULL;
-
- if (argc <= 1) {
- help();
- return EXIT_SUCCESS;
- }
-
- if (argc < 3) {
- log_error("This program requires at least two arguments.");
- return EXIT_FAILURE;
- }
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- if (streq(argv[1], "attach")) {
- uint32_t flags = 0;
- int k;
- unsigned try;
- const char *key_file = NULL;
- usec_t until;
- crypt_status_info status;
-
- /* Arguments: systemd-cryptsetup attach VOLUME SOURCE-DEVICE [PASSWORD] [OPTIONS] */
-
- if (argc < 4) {
- log_error("attach requires at least two arguments.");
- goto finish;
- }
-
- if (argc >= 5 &&
- argv[4][0] &&
- !streq(argv[4], "-") &&
- !streq(argv[4], "none")) {
-
- if (!path_is_absolute(argv[4]))
- log_error("Password file path %s is not absolute. Ignoring.", argv[4]);
- else
- key_file = argv[4];
- }
-
- if (argc >= 6 && argv[5][0] && !streq(argv[5], "-"))
- parse_options(argv[5]);
-
- /* A delicious drop of snake oil */
- mlockall(MCL_FUTURE);
-
- description = disk_description(argv[3]);
- mount_point = disk_mount_point(argv[2]);
-
- if (description && streq(argv[2], description)) {
- /* If the description string is simply the
- * volume name, then let's not show this
- * twice */
- free(description);
- description = NULL;
- }
-
- if (mount_point && description)
- asprintf(&name_buffer, "%s (%s) on %s", description, argv[2], mount_point);
- else if (mount_point)
- asprintf(&name_buffer, "%s on %s", argv[2], mount_point);
- else if (description)
- asprintf(&name_buffer, "%s (%s)", description, argv[2]);
-
- name = name_buffer ? name_buffer : argv[2];
-
- if ((k = crypt_init(&cd, argv[3]))) {
- log_error("crypt_init() failed: %s", strerror(-k));
- goto finish;
- }
-
- crypt_set_log_callback(cd, log_glue, NULL);
-
- status = crypt_status(cd, argv[2]);
- if (status == CRYPT_ACTIVE || status == CRYPT_BUSY) {
- log_info("Volume %s already active.", argv[2]);
- r = EXIT_SUCCESS;
- goto finish;
- }
-
- if (opt_readonly)
- flags |= CRYPT_ACTIVATE_READONLY;
-
- if (opt_discards)
- flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
-
- if (opt_timeout > 0)
- until = now(CLOCK_MONOTONIC) + opt_timeout;
- else
- until = 0;
-
- opt_tries = opt_tries > 0 ? opt_tries : 3;
- opt_key_size = (opt_key_size > 0 ? opt_key_size : 256);
- if (opt_hash) {
- /* plain isn't a real hash type. it just means "use no hash" */
- if (!streq(opt_hash, "plain"))
- hash = opt_hash;
- } else
- hash = "ripemd160";
-
- if (opt_cipher) {
- size_t l;
-
- l = strcspn(opt_cipher, "-");
-
- if (!(truncated_cipher = strndup(opt_cipher, l))) {
- log_oom();
- goto finish;
- }
-
- cipher = truncated_cipher;
- cipher_mode = opt_cipher[l] ? opt_cipher+l+1 : "plain";
- } else {
- cipher = "aes";
- cipher_mode = "cbc-essiv:sha256";
- }
-
- for (try = 0; try < opt_tries; try++) {
- bool pass_volume_key = false;
-
- strv_free(passwords);
- passwords = NULL;
-
- if (!key_file) {
- char *text;
- char **p;
-
- if (asprintf(&text, "Please enter passphrase for disk %s!", name) < 0) {
- log_oom();
- goto finish;
- }
-
- k = ask_password_auto(text, "drive-harddisk", until, try == 0 && !opt_verify, &passwords);
- free(text);
-
- if (k < 0) {
- log_error("Failed to query password: %s", strerror(-k));
- goto finish;
- }
-
- if (opt_verify) {
- char **passwords2 = NULL;
-
- assert(strv_length(passwords) == 1);
-
- if (asprintf(&text, "Please enter passphrase for disk %s! (verification)", name) < 0) {
- log_oom();
- goto finish;
- }
-
- k = ask_password_auto(text, "drive-harddisk", until, false, &passwords2);
- free(text);
-
- if (k < 0) {
- log_error("Failed to query verification password: %s", strerror(-k));
- goto finish;
- }
-
- assert(strv_length(passwords2) == 1);
-
- if (!streq(passwords[0], passwords2[0])) {
- log_warning("Passwords did not match, retrying.");
- strv_free(passwords2);
- continue;
- }
-
- strv_free(passwords2);
- }
-
- strv_uniq(passwords);
-
- STRV_FOREACH(p, passwords) {
- char *c;
-
- if (strlen(*p)+1 >= opt_key_size)
- continue;
-
- /* Pad password if necessary */
- if (!(c = new(char, opt_key_size))) {
- log_oom();
- goto finish;
- }
-
- strncpy(c, *p, opt_key_size);
- free(*p);
- *p = c;
- }
- }
-
- k = 0;
-
- if (!opt_type || streq(opt_type, CRYPT_LUKS1))
- k = crypt_load(cd, CRYPT_LUKS1, NULL);
-
- if ((!opt_type && k < 0) || streq_ptr(opt_type, CRYPT_PLAIN)) {
- struct crypt_params_plain params;
-
- zero(params);
- params.hash = hash;
-
- /* for CRYPT_PLAIN limit reads
- * from keyfile to key length, and
- * ignore keyfile-size */
- opt_keyfile_size = opt_key_size / 8;
-
- /* In contrast to what the name
- * crypt_setup() might suggest this
- * doesn't actually format anything,
- * it just configures encryption
- * parameters when used for plain
- * mode. */
- k = crypt_format(cd, CRYPT_PLAIN,
- cipher,
- cipher_mode,
- NULL,
- NULL,
- opt_keyfile_size,
- &params);
-
- /* hash == NULL implies the user passed "plain" */
- pass_volume_key = (hash == NULL);
- }
-
- if (k < 0) {
- log_error("Loading of cryptographic parameters failed: %s", strerror(-k));
- goto finish;
- }
-
- log_info("Set cipher %s, mode %s, key size %i bits for device %s.",
- crypt_get_cipher(cd),
- crypt_get_cipher_mode(cd),
- crypt_get_volume_key_size(cd)*8,
- argv[3]);
-
- if (key_file)
- k = crypt_activate_by_keyfile_offset(cd, argv[2], CRYPT_ANY_SLOT, key_file, opt_keyfile_size,
- opt_keyfile_offset, flags);
- else {
- char **p;
-
- STRV_FOREACH(p, passwords) {
-
- if (pass_volume_key)
- k = crypt_activate_by_volume_key(cd, argv[2], *p, opt_key_size, flags);
- else
- k = crypt_activate_by_passphrase(cd, argv[2], CRYPT_ANY_SLOT, *p, strlen(*p), flags);
-
- if (k >= 0)
- break;
- }
- }
-
- if (k >= 0)
- break;
-
- if (k != -EPERM) {
- log_error("Failed to activate: %s", strerror(-k));
- goto finish;
- }
-
- log_warning("Invalid passphrase.");
- }
-
- if (try >= opt_tries) {
- log_error("Too many attempts.");
- r = EXIT_FAILURE;
- goto finish;
- }
-
- } else if (streq(argv[1], "detach")) {
- int k;
-
- if ((k = crypt_init_by_name(&cd, argv[2]))) {
- log_error("crypt_init() failed: %s", strerror(-k));
- goto finish;
- }
-
- crypt_set_log_callback(cd, log_glue, NULL);
-
- if ((k = crypt_deactivate(cd, argv[2])) < 0) {
- log_error("Failed to deactivate: %s", strerror(-k));
- goto finish;
- }
-
- } else {
- log_error("Unknown verb %s.", argv[1]);
- goto finish;
- }
-
- r = EXIT_SUCCESS;
-
-finish:
-
- if (cd)
- crypt_free(cd);
-
- free(opt_cipher);
- free(opt_hash);
-
- free(truncated_cipher);
-
- strv_free(passwords);
-
- free(description);
- free(mount_point);
- free(name_buffer);
-
- return r;
-}
diff --git a/src/delta/Makefile b/src/delta/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/delta/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/delta/delta.c b/src/delta/delta.c
deleted file mode 100644
index a65cea51bc..0000000000
--- a/src/delta/delta.c
+++ /dev/null
@@ -1,490 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <assert.h>
-#include <string.h>
-#include <unistd.h>
-#include <getopt.h>
-
-#include "hashmap.h"
-#include "util.h"
-#include "path-util.h"
-#include "log.h"
-#include "pager.h"
-#include "build.h"
-
-static bool arg_no_pager = false;
-static int arg_diff = -1;
-
-static enum {
- SHOW_MASKED = 1 << 0,
- SHOW_EQUIVALENT = 1 << 1,
- SHOW_REDIRECTED = 1 << 2,
- SHOW_OVERRIDDEN = 1 << 3,
- SHOW_UNCHANGED = 1 << 4,
-
- SHOW_DEFAULTS =
- (SHOW_MASKED | SHOW_EQUIVALENT | SHOW_REDIRECTED | SHOW_OVERRIDDEN)
-} arg_flags = 0;
-
-static int equivalent(const char *a, const char *b) {
- _cleanup_free_ char *x = NULL, *y = NULL;
-
- x = canonicalize_file_name(a);
- if (!x)
- return -errno;
-
- y = canonicalize_file_name(b);
- if (!y)
- return -errno;
-
- return path_equal(x, y);
-}
-
-static int notify_override_masked(const char *top, const char *bottom) {
- if (!(arg_flags & SHOW_MASKED))
- return 0;
-
- printf(ANSI_HIGHLIGHT_RED_ON "[MASKED]" ANSI_HIGHLIGHT_OFF " %s → %s\n", top, bottom);
- return 1;
-}
-
-static int notify_override_equivalent(const char *top, const char *bottom) {
- if (!(arg_flags & SHOW_EQUIVALENT))
- return 0;
-
- printf(ANSI_HIGHLIGHT_GREEN_ON "[EQUIVALENT]" ANSI_HIGHLIGHT_OFF " %s → %s\n", top, bottom);
- return 1;
-}
-
-static int notify_override_redirected(const char *top, const char *bottom) {
- if (!(arg_flags & SHOW_REDIRECTED))
- return 0;
-
- printf(ANSI_HIGHLIGHT_ON "[REDIRECTED]" ANSI_HIGHLIGHT_OFF " %s → %s\n", top, bottom);
- return 1;
-}
-
-static int notify_override_overridden(const char *top, const char *bottom) {
- if (!(arg_flags & SHOW_OVERRIDDEN))
- return 0;
-
- printf(ANSI_HIGHLIGHT_ON "[OVERRIDDEN]" ANSI_HIGHLIGHT_OFF " %s → %s\n", top, bottom);
- return 1;
-}
-
-static int notify_override_unchanged(const char *f) {
- if (!(arg_flags & SHOW_UNCHANGED))
- return 0;
-
- printf("[UNCHANGED] %s\n", f);
- return 1;
-}
-
-static int found_override(const char *top, const char *bottom) {
- _cleanup_free_ char *dest = NULL;
- int k;
- pid_t pid;
-
- assert(top);
- assert(bottom);
-
- if (null_or_empty_path(top) > 0) {
- notify_override_masked(top, bottom);
- return 0;
- }
-
- k = readlink_malloc(top, &dest);
- if (k >= 0) {
- if (equivalent(dest, bottom) > 0)
- notify_override_equivalent(top, bottom);
- else
- notify_override_redirected(top, bottom);
-
- return 0;
- }
-
- notify_override_overridden(top, bottom);
- if (!arg_diff)
- return 0;
-
- putchar('\n');
-
- fflush(stdout);
-
- pid = fork();
- if (pid < 0) {
- log_error("Failed to fork off diff: %m");
- return -errno;
- } else if (pid == 0) {
- execlp("diff", "diff", "-us", "--", bottom, top, NULL);
- log_error("Failed to execute diff: %m");
- _exit(1);
- }
-
- wait_for_terminate(pid, NULL);
-
- putchar('\n');
-
- return 0;
-}
-
-static int enumerate_dir(Hashmap *top, Hashmap *bottom, const char *path) {
- _cleanup_closedir_ DIR *d;
-
- assert(top);
- assert(bottom);
- assert(path);
-
- d = opendir(path);
- if (!d) {
- if (errno == ENOENT)
- return 0;
-
- log_error("Failed to enumerate %s: %m", path);
- return -errno;
- }
-
- for (;;) {
- struct dirent *de;
- union dirent_storage buf;
- int k;
- char *p;
-
- k = readdir_r(d, &buf.de, &de);
- if (k != 0)
- return -k;
-
- if (!de)
- break;
-
- if (!dirent_is_file(de))
- continue;
-
- p = strjoin(path, "/", de->d_name, NULL);
- if (!p)
- return -ENOMEM;
-
- path_kill_slashes(p);
-
- k = hashmap_put(top, path_get_file_name(p), p);
- if (k >= 0) {
- p = strdup(p);
- if (!p)
- return -ENOMEM;
- } else if (k != -EEXIST) {
- free(p);
- return k;
- }
-
- free(hashmap_remove(bottom, path_get_file_name(p)));
- k = hashmap_put(bottom, path_get_file_name(p), p);
- if (k < 0) {
- free(p);
- return k;
- }
- }
-
- return 0;
-}
-
-static int process_suffix(const char *prefixes, const char *suffix) {
- const char *p;
- char *f;
- Hashmap *top, *bottom=NULL;
- int r = 0, k;
- Iterator i;
- int n_found = 0;
-
- assert(prefixes);
- assert(suffix);
-
- top = hashmap_new(string_hash_func, string_compare_func);
- if (!top) {
- r = -ENOMEM;
- goto finish;
- }
-
- bottom = hashmap_new(string_hash_func, string_compare_func);
- if (!bottom) {
- r = -ENOMEM;
- goto finish;
- }
-
- NULSTR_FOREACH(p, prefixes) {
- _cleanup_free_ char *t = NULL;
-
- t = strjoin(p, "/", suffix, NULL);
- if (!t) {
- r = -ENOMEM;
- goto finish;
- }
-
- k = enumerate_dir(top, bottom, t);
- if (k < 0)
- r = k;
-
- log_debug("Looking at %s", t);
- }
-
- HASHMAP_FOREACH(f, top, i) {
- char *o;
-
- o = hashmap_get(bottom, path_get_file_name(f));
- assert(o);
-
- if (path_equal(o, f)) {
- notify_override_unchanged(f);
- continue;
- }
-
- k = found_override(f, o);
- if (k < 0)
- r = k;
-
- n_found ++;
- }
-
-finish:
- if (top)
- hashmap_free_free(top);
- if (bottom)
- hashmap_free_free(bottom);
-
- return r < 0 ? r : n_found;
-}
-
-static int process_suffix_chop(const char *prefixes, const char *suffix) {
- const char *p;
-
- assert(prefixes);
- assert(suffix);
-
- if (!path_is_absolute(suffix))
- return process_suffix(prefixes, suffix);
-
- /* Strip prefix from the suffix */
- NULSTR_FOREACH(p, prefixes) {
- if (startswith(suffix, p)) {
- suffix += strlen(p);
- suffix += strspn(suffix, "/");
- return process_suffix(prefixes, suffix);
- }
- }
-
- log_error("Invalid suffix specification %s.", suffix);
- return -EINVAL;
-}
-
-static void help(void) {
-
- printf("%s [OPTIONS...] [SUFFIX...]\n\n"
- "Find overridden configuration files.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --no-pager Do not pipe output into a pager\n"
- " --diff[=1|0] Show a diff when overridden files differ\n"
- " -t --type=LIST... Only display a selected set of override types\n",
- program_invocation_short_name);
-}
-
-static int parse_flags(const char *flag_str, int flags) {
- char *w, *state;
- size_t l;
-
- FOREACH_WORD(w, l, flag_str, state) {
- if (strncmp("masked", w, l) == 0)
- flags |= SHOW_MASKED;
- else if (strncmp ("equivalent", w, l) == 0)
- flags |= SHOW_EQUIVALENT;
- else if (strncmp("redirected", w, l) == 0)
- flags |= SHOW_REDIRECTED;
- else if (strncmp("overridden", w, l) == 0)
- flags |= SHOW_OVERRIDDEN;
- else if (strncmp("unchanged", w, l) == 0)
- flags |= SHOW_UNCHANGED;
- else if (strncmp("default", w, l) == 0)
- flags |= SHOW_DEFAULTS;
- else
- return -EINVAL;
- }
- return flags;
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_NO_PAGER = 0x100,
- ARG_DIFF,
- ARG_VERSION
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "no-pager", no_argument, NULL, ARG_NO_PAGER },
- { "diff", optional_argument, NULL, ARG_DIFF },
- { "type", required_argument, NULL, 't' },
- { NULL, 0, NULL, 0 }
- };
-
- int c;
-
- assert(argc >= 1);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "ht:", options, NULL)) >= 0) {
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(DISTRIBUTION);
- puts(SYSTEMD_FEATURES);
- return 0;
-
- case ARG_NO_PAGER:
- arg_no_pager = true;
- break;
-
- case '?':
- return -EINVAL;
-
- case 't': {
- int f;
- f = parse_flags(optarg, arg_flags);
- if (f < 0) {
- log_error("Failed to parse flags field.");
- return -EINVAL;
- }
- arg_flags = f;
- break;
- }
-
- case ARG_DIFF:
- if (!optarg)
- arg_diff = 1;
- else {
- int b;
-
- b = parse_boolean(optarg);
- if (b < 0) {
- log_error("Failed to parse diff boolean.");
- return -EINVAL;
- } else if (b)
- arg_diff = 1;
- else
- arg_diff = 0;
- }
- break;
-
- default:
- log_error("Unknown option code %c", c);
- return -EINVAL;
- }
- }
-
- return 1;
-}
-
-int main(int argc, char *argv[]) {
-
- const char prefixes[] =
- "/etc\0"
- "/run\0"
- "/usr/local/lib\0"
- "/usr/local/share\0"
- "/usr/lib\0"
- "/usr/share\0"
-#ifdef HAVE_SPLIT_USR
- "/lib\0"
-#endif
- ;
-
- const char suffixes[] =
- "sysctl.d\0"
- "tmpfiles.d\0"
- "modules-load.d\0"
- "binfmt.d\0"
- "systemd/system\0"
- "systemd/user\0"
- "systemd/system-preset\0"
- "systemd/user-preset\0"
- "udev/rules.d\0"
- "modprobe.d\0";
-
- int r = 0, k;
- int n_found = 0;
-
- log_parse_environment();
- log_open();
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- goto finish;
-
- if (arg_flags == 0)
- arg_flags = SHOW_DEFAULTS;
-
- if (arg_diff < 0)
- arg_diff = !!(arg_flags & SHOW_OVERRIDDEN);
- else if (arg_diff)
- arg_flags |= SHOW_OVERRIDDEN;
-
- if (!arg_no_pager)
- pager_open();
-
- if (optind < argc) {
- int i;
-
- for (i = optind; i < argc; i++) {
- k = process_suffix_chop(prefixes, argv[i]);
- if (k < 0)
- r = k;
- else
- n_found += k;
- }
-
- } else {
- const char *n;
-
- NULSTR_FOREACH(n, suffixes) {
- k = process_suffix(prefixes, n);
- if (k < 0)
- r = k;
- else
- n_found += k;
- }
- }
-
- if (r >= 0)
- printf("\n%i overridden configuration files found.\n", n_found);
-
-finish:
- pager_close();
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/detect-virt/Makefile b/src/detect-virt/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/detect-virt/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/detect-virt/detect-virt.c b/src/detect-virt/detect-virt.c
deleted file mode 100644
index bbb9dfc19a..0000000000
--- a/src/detect-virt/detect-virt.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*-*- 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 <stdlib.h>
-#include <stdbool.h>
-#include <errno.h>
-#include <string.h>
-#include <getopt.h>
-
-#include "util.h"
-#include "virt.h"
-#include "build.h"
-
-static bool arg_quiet = false;
-static enum {
- ANY_VIRTUALIZATION,
- ONLY_VM,
- ONLY_CONTAINER
-} arg_mode = ANY_VIRTUALIZATION;
-
-static int help(void) {
-
- printf("%s [OPTIONS...]\n\n"
- "Detect execution in a virtualized environment.\n\n"
- " -h --help Show this help\n"
- " --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"
- " -q --quiet Don't output anything, just set return value\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "container", no_argument, NULL, 'c' },
- { "vm", optional_argument, NULL, 'v' },
- { "quiet", no_argument, NULL, 'q' },
- { NULL, 0, NULL, 0 }
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "hqcv", options, NULL)) >= 0) {
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(DISTRIBUTION);
- puts(SYSTEMD_FEATURES);
- return 0;
-
- case 'q':
- arg_quiet = true;
- break;
-
- case 'c':
- arg_mode = ONLY_CONTAINER;
- break;
-
- case 'v':
- arg_mode = ONLY_VM;
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- log_error("Unknown option code %c", c);
- return -EINVAL;
- }
- }
-
- if (optind < argc) {
- help();
- return -EINVAL;
- }
-
- return 1;
-}
-
-int main(int argc, char *argv[]) {
- const char *id = NULL;
- int r;
- int retval = EXIT_SUCCESS;
-
- /* This is mostly intended to be used for scripts which want
- * to detect whether we are being run in a virtualized
- * environment or not */
-
- log_parse_environment();
- log_open();
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-
- switch (arg_mode) {
-
- case ANY_VIRTUALIZATION: {
- Virtualization v;
-
- v = detect_virtualization(&id);
- if (v < 0) {
- log_error("Failed to check for virtualization: %s", strerror(-v));
- return EXIT_FAILURE;
- }
-
- retval = v != VIRTUALIZATION_NONE ? EXIT_SUCCESS : EXIT_FAILURE;
- break;
- }
-
- case ONLY_CONTAINER:
- r = detect_container(&id);
- if (r < 0) {
- log_error("Failed to check for container: %s", strerror(-r));
- return EXIT_FAILURE;
- }
-
- retval = r > 0 ? EXIT_SUCCESS : EXIT_FAILURE;
- break;
-
- case ONLY_VM:
- r = detect_vm(&id);
- if (r < 0) {
- log_error("Failed to check for vm: %s", strerror(-r));
- return EXIT_FAILURE;
- }
-
- retval = r > 0 ? EXIT_SUCCESS : EXIT_FAILURE;
- break;
- }
-
- if (!arg_quiet)
- puts(id ? id : "none");
-
- return retval;
-}
diff --git a/src/fsck/Makefile b/src/fsck/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/fsck/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c
deleted file mode 100644
index 058f34d64f..0000000000
--- a/src/fsck/fsck.c
+++ /dev/null
@@ -1,407 +0,0 @@
-/*-*- 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 <stdio.h>
-#include <stdbool.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/file.h>
-
-#include <libudev.h>
-#include <dbus/dbus.h>
-
-#include "util.h"
-#include "dbus-common.h"
-#include "special.h"
-#include "bus-errors.h"
-#include "virt.h"
-
-static bool arg_skip = false;
-static bool arg_force = false;
-static bool arg_show_progress = false;
-
-static void start_target(const char *target, bool isolate) {
- DBusMessage *m = NULL, *reply = NULL;
- DBusError error;
- const char *mode, *basic_target = "basic.target";
- DBusConnection *bus = NULL;
-
- assert(target);
-
- dbus_error_init(&error);
-
- if (bus_connect(DBUS_BUS_SYSTEM, &bus, NULL, &error) < 0) {
- log_error("Failed to get D-Bus connection: %s", bus_error_message(&error));
- goto finish;
- }
-
- if (isolate)
- mode = "isolate";
- else
- mode = "replace";
-
- log_info("Running request %s/start/%s", target, mode);
-
- if (!(m = dbus_message_new_method_call("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartUnitReplace"))) {
- log_error("Could not allocate message.");
- goto finish;
- }
-
- /* Start these units only if we can replace base.target with it */
-
- if (!dbus_message_append_args(m,
- DBUS_TYPE_STRING, &basic_target,
- DBUS_TYPE_STRING, &target,
- DBUS_TYPE_STRING, &mode,
- DBUS_TYPE_INVALID)) {
- log_error("Could not attach target and flag information to message.");
- goto finish;
- }
-
- if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-
- /* Don't print a warning if we aren't called during
- * startup */
- if (!dbus_error_has_name(&error, BUS_ERROR_NO_SUCH_JOB))
- log_error("Failed to start unit: %s", bus_error_message(&error));
-
- goto finish;
- }
-
-finish:
- if (m)
- dbus_message_unref(m);
-
- if (reply)
- dbus_message_unref(reply);
-
- if (bus) {
- dbus_connection_flush(bus);
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
- }
-
- dbus_error_free(&error);
-}
-
-static int parse_proc_cmdline(void) {
- char *line, *w, *state;
- int r;
- size_t l;
-
- if (detect_container(NULL) > 0)
- return 0;
-
- r = read_one_line_file("/proc/cmdline", &line);
- if (r < 0) {
- log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
- return 0;
- }
-
- FOREACH_WORD_QUOTED(w, l, line, state) {
-
- if (strneq(w, "fsck.mode=auto", l))
- arg_force = arg_skip = false;
- else if (strneq(w, "fsck.mode=force", l))
- arg_force = true;
- else if (strneq(w, "fsck.mode=skip", l))
- arg_skip = true;
- else if (startswith(w, "fsck"))
- log_warning("Invalid fsck parameter. Ignoring.");
-#if defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_MAGEIA)
- else if (strneq(w, "fastboot", l))
- arg_skip = true;
- else if (strneq(w, "forcefsck", l))
- arg_force = true;
-#endif
- }
-
- free(line);
- return 0;
-}
-
-static void test_files(void) {
- if (access("/fastboot", F_OK) >= 0)
- arg_skip = true;
-
- if (access("/forcefsck", F_OK) >= 0)
- arg_force = true;
-
- if (access("/run/systemd/show-status", F_OK) >= 0 || plymouth_running())
- arg_show_progress = true;
-}
-
-static double percent(int pass, unsigned long cur, unsigned long max) {
- /* Values stolen from e2fsck */
-
- static const int pass_table[] = {
- 0, 70, 90, 92, 95, 100
- };
-
- if (pass <= 0)
- return 0.0;
-
- if ((unsigned) pass >= ELEMENTSOF(pass_table) || max == 0)
- return 100.0;
-
- return (double) pass_table[pass-1] +
- ((double) pass_table[pass] - (double) pass_table[pass-1]) *
- (double) cur / (double) max;
-}
-
-static int process_progress(int fd) {
- FILE *f, *console;
- usec_t last = 0;
- bool locked = false;
- int clear = 0;
-
- f = fdopen(fd, "r");
- if (!f) {
- close_nointr_nofail(fd);
- return -errno;
- }
-
- console = fopen("/dev/console", "w");
- if (!console) {
- fclose(f);
- return -ENOMEM;
- }
-
- while (!feof(f)) {
- int pass, m;
- unsigned long cur, max;
- char *device;
- double p;
- usec_t t;
-
- if (fscanf(f, "%i %lu %lu %ms", &pass, &cur, &max, &device) != 4)
- break;
-
- /* Only show one progress counter at max */
- if (!locked) {
- if (flock(fileno(console), LOCK_EX|LOCK_NB) < 0) {
- free(device);
- continue;
- }
-
- locked = true;
- }
-
- /* Only update once every 50ms */
- t = now(CLOCK_MONOTONIC);
- if (last + 50 * USEC_PER_MSEC > t) {
- free(device);
- continue;
- }
-
- last = t;
-
- p = percent(pass, cur, max);
- fprintf(console, "\r%s: fsck %3.1f%% complete...\r%n", device, p, &m);
- fflush(console);
-
- free(device);
-
- if (m > clear)
- clear = m;
- }
-
- if (clear > 0) {
- unsigned j;
-
- fputc('\r', console);
- for (j = 0; j < (unsigned) clear; j++)
- fputc(' ', console);
- fputc('\r', console);
- fflush(console);
- }
-
- fclose(f);
- fclose(console);
- return 0;
-}
-
-int main(int argc, char *argv[]) {
- const char *cmdline[9];
- int i = 0, r = EXIT_FAILURE, q;
- pid_t pid;
- siginfo_t status;
- struct udev *udev = NULL;
- struct udev_device *udev_device = NULL;
- const char *device;
- bool root_directory;
- int progress_pipe[2] = { -1, -1 };
- char dash_c[2+10+1];
-
- if (argc > 2) {
- log_error("This program expects one or no arguments.");
- return EXIT_FAILURE;
- }
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- parse_proc_cmdline();
- test_files();
-
- if (!arg_force && arg_skip)
- return 0;
-
- if (argc > 1) {
- device = argv[1];
- root_directory = false;
- } else {
- struct stat st;
- struct timespec times[2];
-
- /* Find root device */
-
- if (stat("/", &st) < 0) {
- log_error("Failed to stat() the root directory: %m");
- goto finish;
- }
-
- /* Virtual root devices don't need an fsck */
- if (major(st.st_dev) == 0)
- return 0;
-
- /* check if we are already writable */
- times[0] = st.st_atim;
- times[1] = st.st_mtim;
- if (utimensat(AT_FDCWD, "/", times, 0) == 0) {
- log_info("Root directory is writable, skipping check.");
- return 0;
- }
-
- if (!(udev = udev_new())) {
- log_oom();
- goto finish;
- }
-
- if (!(udev_device = udev_device_new_from_devnum(udev, 'b', st.st_dev))) {
- log_error("Failed to detect root device.");
- goto finish;
- }
-
- if (!(device = udev_device_get_devnode(udev_device))) {
- log_error("Failed to detect device node of root directory.");
- goto finish;
- }
-
- root_directory = true;
- }
-
- if (arg_show_progress)
- if (pipe(progress_pipe) < 0) {
- log_error("pipe(): %m");
- goto finish;
- }
-
- cmdline[i++] = "/sbin/fsck";
- cmdline[i++] = "-a";
- cmdline[i++] = "-T";
- cmdline[i++] = "-l";
-
- if (!root_directory)
- cmdline[i++] = "-M";
-
- if (arg_force)
- cmdline[i++] = "-f";
-
- if (progress_pipe[1] >= 0) {
- snprintf(dash_c, sizeof(dash_c), "-C%i", progress_pipe[1]);
- char_array_0(dash_c);
- cmdline[i++] = dash_c;
- }
-
- cmdline[i++] = device;
- cmdline[i++] = NULL;
-
- pid = fork();
- if (pid < 0) {
- log_error("fork(): %m");
- goto finish;
- } else if (pid == 0) {
- /* Child */
- if (progress_pipe[0] >= 0)
- close_nointr_nofail(progress_pipe[0]);
- execv(cmdline[0], (char**) cmdline);
- _exit(8); /* Operational error */
- }
-
- if (progress_pipe[1] >= 0) {
- close_nointr_nofail(progress_pipe[1]);
- progress_pipe[1] = -1;
- }
-
- if (progress_pipe[0] >= 0) {
- process_progress(progress_pipe[0]);
- progress_pipe[0] = -1;
- }
-
- q = wait_for_terminate(pid, &status);
- if (q < 0) {
- log_error("waitid(): %s", strerror(-q));
- goto finish;
- }
-
- if (status.si_code != CLD_EXITED || (status.si_status & ~1)) {
-
- if (status.si_code == CLD_KILLED || status.si_code == CLD_DUMPED)
- log_error("fsck terminated by signal %s.", signal_to_string(status.si_status));
- else if (status.si_code == CLD_EXITED)
- log_error("fsck failed with error code %i.", status.si_status);
- else
- log_error("fsck failed due to unknown reason.");
-
- if (status.si_code == CLD_EXITED && (status.si_status & 2) && root_directory)
- /* System should be rebooted. */
- start_target(SPECIAL_REBOOT_TARGET, false);
- else if (status.si_code == CLD_EXITED && (status.si_status & 6))
- /* Some other problem */
- start_target(SPECIAL_EMERGENCY_TARGET, true);
- else {
- r = EXIT_SUCCESS;
- log_warning("Ignoring error.");
- }
-
- } else
- r = EXIT_SUCCESS;
-
- if (status.si_code == CLD_EXITED && (status.si_status & 1))
- touch("/run/systemd/quotacheck");
-
-finish:
- if (udev_device)
- udev_device_unref(udev_device);
-
- if (udev)
- udev_unref(udev);
-
- close_pipe(progress_pipe);
-
- return r;
-}
diff --git a/src/fstab-generator/Makefile b/src/fstab-generator/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/fstab-generator/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
deleted file mode 100644
index 62053b7f35..0000000000
--- a/src/fstab-generator/fstab-generator.c
+++ /dev/null
@@ -1,560 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdio.h>
-#include <mntent.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "log.h"
-#include "util.h"
-#include "unit-name.h"
-#include "path-util.h"
-#include "mount-setup.h"
-#include "special.h"
-#include "mkdir.h"
-#include "virt.h"
-
-static const char *arg_dest = "/tmp";
-static bool arg_enabled = true;
-
-static int device_name(const char *path, char **unit) {
- char *p;
-
- assert(path);
-
- if (!is_device_path(path))
- return 0;
-
- p = unit_name_from_path(path, ".device");
- if (!p)
- return log_oom();
-
- *unit = p;
- return 1;
-}
-
-static int mount_find_pri(struct mntent *me, int *ret) {
- char *end, *pri;
- unsigned long r;
-
- assert(me);
- assert(ret);
-
- pri = hasmntopt(me, "pri");
- if (!pri)
- return 0;
-
- pri += 4;
-
- errno = 0;
- r = strtoul(pri, &end, 10);
- if (errno != 0)
- return -errno;
-
- if (end == pri || (*end != ',' && *end != 0))
- return -EINVAL;
-
- *ret = (int) r;
- return 1;
-}
-
-static int add_swap(const char *what, struct mntent *me) {
- char *name = NULL, *unit = NULL, *lnk = NULL, *device = NULL;
- FILE *f = NULL;
- bool noauto, nofail;
- int r, pri = -1;
-
- assert(what);
- assert(me);
-
- r = mount_find_pri(me, &pri);
- if (r < 0) {
- log_error("Failed to parse priority");
- return pri;
- }
-
- noauto = !!hasmntopt(me, "noauto");
- nofail = !!hasmntopt(me, "nofail");
-
- name = unit_name_from_path(what, ".swap");
- if (!name) {
- r = log_oom();
- goto finish;
- }
-
- unit = strjoin(arg_dest, "/", name, NULL);
- if (!unit) {
- r = log_oom();
- goto finish;
- }
-
- f = fopen(unit, "wxe");
- if (!f) {
- r = -errno;
- log_error("Failed to create unit file %s: %m", unit);
- goto finish;
- }
-
- fputs("# Automatically generated by systemd-fstab-generator\n\n"
- "[Unit]\n"
- "SourcePath=/etc/fstab\n"
- "DefaultDependencies=no\n"
- "Conflicts=" SPECIAL_UMOUNT_TARGET "\n"
- "Before=" SPECIAL_UMOUNT_TARGET "\n", f);
-
- if (!noauto && !nofail)
- fputs("Before=" SPECIAL_SWAP_TARGET "\n", f);
-
- fprintf(f,
- "\n"
- "[Swap]\n"
- "What=%s\n",
- what);
-
- if (pri >= 0)
- fprintf(f,
- "Priority=%i\n",
- pri);
-
- fflush(f);
- if (ferror(f)) {
- log_error("Failed to write unit file %s: %m", unit);
- r = -errno;
- goto finish;
- }
-
- if (!noauto) {
- lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL);
- if (!lnk) {
- r = log_oom();
- goto finish;
- }
-
- mkdir_parents_label(lnk, 0755);
- if (symlink(unit, lnk) < 0) {
- log_error("Failed to create symlink %s: %m", lnk);
- r = -errno;
- goto finish;
- }
-
- r = device_name(what, &device);
- if (r < 0)
- goto finish;
-
- if (r > 0) {
- free(lnk);
- lnk = strjoin(arg_dest, "/", device, ".wants/", name, NULL);
- if (!lnk) {
- r = log_oom();
- goto finish;
- }
-
- mkdir_parents_label(lnk, 0755);
- if (symlink(unit, lnk) < 0) {
- log_error("Failed to create symlink %s: %m", lnk);
- r = -errno;
- goto finish;
- }
- }
- }
-
- r = 0;
-finish:
- if (f)
- fclose(f);
-
- free(unit);
- free(lnk);
- free(name);
- free(device);
-
- return r;
-}
-
-static bool mount_is_bind(struct mntent *me) {
- assert(me);
-
- return
- hasmntopt(me, "bind") ||
- streq(me->mnt_opts, "bind");
-}
-
-static bool mount_is_network(struct mntent *me) {
- assert(me);
-
- return
- hasmntopt(me, "_netdev") ||
- fstype_is_network(me->mnt_type);
-}
-
-static int add_mount(const char *what, const char *where, struct mntent *me) {
- char *name = NULL, *unit = NULL, *lnk = NULL, *device = NULL, *automount_name = NULL, *automount_unit = NULL;
- FILE *f = NULL;
- bool noauto, nofail, automount, isbind, isnetwork;
- int r;
- const char *post, *pre;
-
- assert(what);
- assert(where);
- assert(me);
-
- if (streq(me->mnt_type, "autofs"))
- return 0;
-
- if (!is_path(where)) {
- log_warning("Mount point %s is not a valid path, ignoring.", where);
- return 0;
- }
-
- if (mount_point_is_api(where) ||
- mount_point_ignore(where))
- return 0;
-
- isnetwork = mount_is_network(me);
- isbind = mount_is_bind(me);
-
- noauto = !!hasmntopt(me, "noauto");
- nofail = !!hasmntopt(me, "nofail");
- automount =
- hasmntopt(me, "comment=systemd.automount") ||
- hasmntopt(me, "x-systemd.automount");
-
- if (isnetwork) {
- post = SPECIAL_REMOTE_FS_TARGET;
- pre = SPECIAL_REMOTE_FS_PRE_TARGET;
- } else {
- post = SPECIAL_LOCAL_FS_TARGET;
- pre = SPECIAL_LOCAL_FS_PRE_TARGET;
- }
-
- name = unit_name_from_path(where, ".mount");
- if (!name) {
- r = log_oom();
- goto finish;
- }
-
- unit = strjoin(arg_dest, "/", name, NULL);
- if (!unit) {
- r = log_oom();
- goto finish;
- }
-
- f = fopen(unit, "wxe");
- if (!f) {
- r = -errno;
- log_error("Failed to create unit file %s: %m", unit);
- goto finish;
- }
-
- fputs("# Automatically generated by systemd-fstab-generator\n\n"
- "[Unit]\n"
- "SourcePath=/etc/fstab\n"
- "DefaultDependencies=no\n", f);
-
- if (!path_equal(where, "/"))
- fprintf(f,
- "After=%s\n"
- "Wants=%s\n"
- "Conflicts=" SPECIAL_UMOUNT_TARGET "\n"
- "Before=" SPECIAL_UMOUNT_TARGET "\n",
- pre,
- pre);
-
-
- if (!noauto && !nofail && !automount)
- fprintf(f,
- "Before=%s\n",
- post);
-
- fprintf(f,
- "\n"
- "[Mount]\n"
- "What=%s\n"
- "Where=%s\n"
- "Type=%s\n"
- "FsckPassNo=%i\n",
- what,
- where,
- me->mnt_type,
- me->mnt_passno);
-
- if (!isempty(me->mnt_opts) &&
- !streq(me->mnt_opts, "defaults"))
- fprintf(f,
- "Options=%s\n",
- me->mnt_opts);
-
- fflush(f);
- if (ferror(f)) {
- log_error("Failed to write unit file %s: %m", unit);
- r = -errno;
- goto finish;
- }
-
- if (!noauto) {
- lnk = strjoin(arg_dest, "/", post, nofail || automount ? ".wants/" : ".requires/", name, NULL);
- if (!lnk) {
- r = log_oom();
- goto finish;
- }
-
- mkdir_parents_label(lnk, 0755);
- if (symlink(unit, lnk) < 0) {
- log_error("Failed to create symlink %s: %m", lnk);
- r = -errno;
- goto finish;
- }
-
- if (!isbind &&
- !path_equal(where, "/")) {
-
- r = device_name(what, &device);
- if (r < 0)
- goto finish;
-
- if (r > 0) {
- free(lnk);
- lnk = strjoin(arg_dest, "/", device, ".wants/", name, NULL);
- if (!lnk) {
- r = log_oom();
- goto finish;
- }
-
- mkdir_parents_label(lnk, 0755);
- if (symlink(unit, lnk) < 0) {
- log_error("Failed to create symlink %s: %m", lnk);
- r = -errno;
- goto finish;
- }
- }
- }
- }
-
- if (automount && !path_equal(where, "/")) {
- automount_name = unit_name_from_path(where, ".automount");
- if (!name) {
- r = log_oom();
- goto finish;
- }
-
- automount_unit = strjoin(arg_dest, "/", automount_name, NULL);
- if (!automount_unit) {
- r = log_oom();
- goto finish;
- }
-
- fclose(f);
- f = fopen(automount_unit, "wxe");
- if (!f) {
- r = -errno;
- log_error("Failed to create unit file %s: %m", automount_unit);
- goto finish;
- }
-
- fprintf(f,
- "# Automatically generated by systemd-fstab-generator\n\n"
- "[Unit]\n"
- "SourcePath=/etc/fstab\n"
- "DefaultDependencies=no\n"
- "Conflicts=" SPECIAL_UMOUNT_TARGET "\n"
- "Before=" SPECIAL_UMOUNT_TARGET " %s\n"
- "\n"
- "[Automount]\n"
- "Where=%s\n",
- post,
- where);
-
- fflush(f);
- if (ferror(f)) {
- log_error("Failed to write unit file %s: %m", automount_unit);
- r = -errno;
- goto finish;
- }
-
- free(lnk);
- lnk = strjoin(arg_dest, "/", post, nofail ? ".wants/" : ".requires/", automount_name, NULL);
- if (!lnk) {
- r = log_oom();
- goto finish;
- }
-
- mkdir_parents_label(lnk, 0755);
- if (symlink(automount_unit, lnk) < 0) {
- log_error("Failed to create symlink %s: %m", lnk);
- r = -errno;
- goto finish;
- }
- }
-
- r = 0;
-finish:
- if (f)
- fclose(f);
-
- free(unit);
- free(lnk);
- free(name);
- free(device);
- free(automount_name);
- free(automount_unit);
-
- return r;
-}
-
-static int parse_fstab(void) {
- FILE *f;
- int r = 0;
- struct mntent *me;
-
- errno = 0;
- f = setmntent("/etc/fstab", "r");
- if (!f) {
- if (errno == ENOENT)
- return 0;
-
- log_error("Failed to open /etc/fstab: %m");
- return -errno;
- }
-
- while ((me = getmntent(f))) {
- char *where, *what;
- int k;
-
- what = fstab_node_to_udev_node(me->mnt_fsname);
- if (!what) {
- r = log_oom();
- goto finish;
- }
-
- where = strdup(me->mnt_dir);
- if (!where) {
- r = log_oom();
- free(what);
- goto finish;
- }
-
- if (is_path(where))
- path_kill_slashes(where);
-
- log_debug("Found entry what=%s where=%s type=%s", what, where, me->mnt_type);
-
- if (streq(me->mnt_type, "swap"))
- k = add_swap(what, me);
- else
- k = add_mount(what, where, me);
-
- free(what);
- free(where);
-
- if (k < 0)
- r = k;
- }
-
-finish:
- endmntent(f);
- return r;
-}
-
-static int parse_proc_cmdline(void) {
- char *line, *w, *state;
- int r;
- size_t l;
-
- if (detect_container(NULL) > 0)
- return 0;
-
- r = read_one_line_file("/proc/cmdline", &line);
- if (r < 0) {
- log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
- return 0;
- }
-
- FOREACH_WORD_QUOTED(w, l, line, state) {
- char *word;
-
- word = strndup(w, l);
- if (!word) {
- r = log_oom();
- goto finish;
- }
-
- if (startswith(word, "fstab=")) {
- r = parse_boolean(word + 6);
- if (r < 0)
- log_warning("Failed to parse fstab switch %s. Ignoring.", word + 6);
- else
- arg_enabled = r;
-
- } else if (startswith(word, "rd.fstab=")) {
-
- if (in_initrd()) {
- r = parse_boolean(word + 6);
- if (r < 0)
- log_warning("Failed to parse fstab switch %s. Ignoring.", word + 6);
- else
- arg_enabled = r;
- }
-
- } else if (startswith(word, "fstab.") ||
- (in_initrd() && startswith(word, "rd.fstab."))) {
-
- log_warning("Unknown kernel switch %s. Ignoring.", word);
- }
-
- free(word);
- }
-
- r = 0;
-
-finish:
- free(line);
- return r;
-}
-
-int main(int argc, char *argv[]) {
- int r;
-
- if (argc > 1 && argc != 4) {
- log_error("This program takes three or no arguments.");
- return EXIT_FAILURE;
- }
-
- if (argc > 1)
- arg_dest = argv[1];
-
- log_set_target(LOG_TARGET_SAFE);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- if (parse_proc_cmdline() < 0)
- return EXIT_FAILURE;
-
- if (!arg_enabled)
- return EXIT_SUCCESS;
-
- r = parse_fstab();
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/getty-generator/Makefile b/src/getty-generator/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/getty-generator/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/getty-generator/getty-generator.c b/src/getty-generator/getty-generator.c
deleted file mode 100644
index 1cef6aeae9..0000000000
--- a/src/getty-generator/getty-generator.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*-*- 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 <errno.h>
-#include <unistd.h>
-
-#include "log.h"
-#include "util.h"
-#include "mkdir.h"
-#include "unit-name.h"
-#include "virt.h"
-
-static const char *arg_dest = "/tmp";
-
-static int add_symlink(const char *fservice, const char *tservice) {
- char *from = NULL, *to = NULL;
- int r;
-
- assert(fservice);
- assert(tservice);
-
- from = strappend(SYSTEM_DATA_UNIT_PATH "/", fservice);
- to = strjoin(arg_dest,"/getty.target.wants/", tservice, NULL);
-
- if (!from || !to) {
- r = log_oom();
- goto finish;
- }
-
- mkdir_parents_label(to, 0755);
-
- r = symlink(from, to);
- if (r < 0) {
- if (errno == EEXIST)
- /* In case console=hvc0 is passed this will very likely result in EEXIST */
- r = 0;
- else {
- log_error("Failed to create symlink from %s to %s: %m", from, to);
- r = -errno;
- }
- }
-
-finish:
-
- free(from);
- free(to);
-
- return r;
-}
-
-static int add_serial_getty(const char *tty) {
- char *n;
- int r;
-
- assert(tty);
-
- log_debug("Automatically adding serial getty for /dev/%s.", tty);
-
- n = unit_name_replace_instance("serial-getty@.service", tty);
- if (!n)
- return log_oom();
-
- r = add_symlink("serial-getty@.service", n);
- free(n);
-
- return r;
-}
-
-int main(int argc, char *argv[]) {
-
- static const char virtualization_consoles[] =
- "hvc0\0"
- "xvc0\0"
- "hvsi0\0";
-
- int r = EXIT_SUCCESS;
- char *active;
- const char *j;
-
- if (argc > 1 && argc != 4) {
- log_error("This program takes three or no arguments.");
- return EXIT_FAILURE;
- }
-
- if (argc > 1)
- arg_dest = argv[1];
-
- log_set_target(LOG_TARGET_SAFE);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- if (detect_container(NULL) > 0) {
- log_debug("Automatically adding console shell.");
-
- if (add_symlink("console-getty.service", "console-getty.service") < 0)
- r = EXIT_FAILURE;
-
- /* Don't add any further magic if we are in a container */
- goto finish;
- }
-
- if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
- const char *tty;
-
- tty = strrchr(active, ' ');
- if (tty)
- tty ++;
- else
- tty = active;
-
- /* Automatically add in a serial getty on the kernel
- * console */
- if (tty_is_vc(tty))
- free(active);
- else {
- int k;
-
- /* We assume that gettys on virtual terminals are
- * started via manual configuration and do this magic
- * only for non-VC terminals. */
-
- k = add_serial_getty(tty);
- free(active);
-
- if (k < 0) {
- r = EXIT_FAILURE;
- goto finish;
- }
- }
- }
-
- /* Automatically add in a serial getty on the first
- * virtualizer console */
- NULSTR_FOREACH(j, virtualization_consoles) {
- char *p;
- int k;
-
- if (asprintf(&p, "/sys/class/tty/%s", j) < 0) {
- log_oom();
- r = EXIT_FAILURE;
- goto finish;
- }
-
- k = access(p, F_OK);
- free(p);
-
- if (k < 0)
- continue;
-
- k = add_serial_getty(j);
- if (k < 0) {
- r = EXIT_FAILURE;
- goto finish;
- }
- }
-
-finish:
- return r;
-}
diff --git a/src/gudev/.gitignore b/src/gudev/.gitignore
deleted file mode 100644
index 4577903c40..0000000000
--- a/src/gudev/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-gudev-1.0.pc
-gudevenumtypes.c
-gudevenumtypes.h
-gudevmarshal.c
-gudevmarshal.h
-GUdev-1.0.gir
-GUdev-1.0.typelib
diff --git a/src/gudev/Makefile b/src/gudev/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/gudev/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/hostname/.gitignore b/src/hostname/.gitignore
deleted file mode 100644
index 1ff281b231..0000000000
--- a/src/hostname/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-org.freedesktop.hostname1.policy
diff --git a/src/hostname/Makefile b/src/hostname/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/hostname/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c
deleted file mode 100644
index b7ae5ccc6c..0000000000
--- a/src/hostname/hostnamectl.c
+++ /dev/null
@@ -1,546 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdlib.h>
-#include <stdbool.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <locale.h>
-#include <string.h>
-#include <sys/timex.h>
-#include <sys/utsname.h>
-
-#include "dbus-common.h"
-#include "util.h"
-#include "spawn-polkit-agent.h"
-#include "build.h"
-#include "hwclock.h"
-#include "strv.h"
-#include "sd-id128.h"
-#include "virt.h"
-
-static enum transport {
- TRANSPORT_NORMAL,
- TRANSPORT_SSH,
- TRANSPORT_POLKIT
-} arg_transport = TRANSPORT_NORMAL;
-static bool arg_ask_password = true;
-static const char *arg_host = NULL;
-static bool arg_set_transient = false;
-static bool arg_set_pretty = false;
-static bool arg_set_static = false;
-
-static void polkit_agent_open_if_enabled(void) {
-
- /* Open the polkit agent as a child process if necessary */
-
- if (!arg_ask_password)
- return;
-
- polkit_agent_open();
-}
-
-typedef struct StatusInfo {
- const char *hostname;
- const char *static_hostname;
- const char *pretty_hostname;
- const char *icon_name;
-} StatusInfo;
-
-static void print_status_info(StatusInfo *i) {
- sd_id128_t mid, bid;
- int r;
- const char *id = NULL;
- _cleanup_free_ char *pretty_name = NULL, *cpe_name = NULL;
- struct utsname u;
-
- assert(i);
-
- printf(" Static hostname: %s\n",
- strna(i->static_hostname));
-
- if (!streq_ptr(i->hostname, i->static_hostname))
- printf("Transient hostname: %s\n",
- strna(i->hostname));
-
- printf(" Pretty hostname: %s\n"
- " Icon name: %s\n",
- strna(i->pretty_hostname),
- strna(i->icon_name));
-
- r = sd_id128_get_machine(&mid);
- if (r >= 0)
- printf(" Machine ID: " SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(mid));
-
- r = sd_id128_get_boot(&bid);
- if (r >= 0)
- printf(" Boot ID: " SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(bid));
-
- if (detect_virtualization(&id) > 0)
- printf(" Virtualization: %s\n", id);
-
- r = parse_env_file("/etc/os-release", NEWLINE,
- "PRETTY_NAME", &pretty_name,
- "CPE_NAME", &cpe_name,
- NULL);
-
- if (!isempty(pretty_name))
- printf(" Operating System: %s\n", pretty_name);
-
- if (!isempty(cpe_name))
- printf(" CPE OS Name: %s\n", cpe_name);
-
- assert_se(uname(&u) >= 0);
- printf(" Kernel: %s %s\n"
- " Architecture: %s\n", u.sysname, u.release, u.machine);
-
-}
-
-static int status_property(const char *name, DBusMessageIter *iter, StatusInfo *i) {
- assert(name);
- assert(iter);
-
- switch (dbus_message_iter_get_arg_type(iter)) {
-
- case DBUS_TYPE_STRING: {
- const char *s;
-
- dbus_message_iter_get_basic(iter, &s);
- if (!isempty(s)) {
- if (streq(name, "Hostname"))
- i->hostname = s;
- if (streq(name, "StaticHostname"))
- i->static_hostname = s;
- if (streq(name, "PrettyHostname"))
- i->pretty_hostname = s;
- if (streq(name, "IconName"))
- i->icon_name = s;
- }
- break;
- }
- }
-
- return 0;
-}
-
-static int show_status(DBusConnection *bus, char **args, unsigned n) {
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- const char *interface = "";
- int r;
- DBusMessageIter iter, sub, sub2, sub3;
- StatusInfo info;
-
- assert(args);
-
- r = bus_method_call_with_reply(
- bus,
- "org.freedesktop.hostname1",
- "/org/freedesktop/hostname1",
- "org.freedesktop.DBus.Properties",
- "GetAll",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &interface,
- DBUS_TYPE_INVALID);
- if (r < 0)
- return r;
-
- if (!dbus_message_iter_init(reply, &iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
- log_error("Failed to parse reply.");
- return -EIO;
- }
-
- zero(info);
- dbus_message_iter_recurse(&iter, &sub);
-
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- const char *name;
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
- log_error("Failed to parse reply.");
- return -EIO;
- }
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
- log_error("Failed to parse reply.");
- return -EIO;
- }
-
- if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
- log_error("Failed to parse reply.");
- return -EIO;
- }
-
- dbus_message_iter_recurse(&sub2, &sub3);
-
- r = status_property(name, &sub3, &info);
- if (r < 0) {
- log_error("Failed to parse reply.");
- return r;
- }
-
- dbus_message_iter_next(&sub);
- }
-
- print_status_info(&info);
- return 0;
-}
-
-static char* hostname_simplify(char *s) {
- char *p, *d;
-
- for (p = s, d = s; *p; p++) {
- if ((*p >= 'a' && *p <= 'z') ||
- (*p >= '0' && *p <= '9') ||
- *p == '-' || *p == '_')
- *(d++) = *p;
- else if (*p >= 'A' && *p <= 'Z')
- *(d++) = *p - 'A' + 'a';
- else if (*p == ' ')
- *(d++) = '-';
- }
-
- *d = 0;
-
- strshorten(s, HOST_NAME_MAX);
- return s;
-}
-
-static int set_hostname(DBusConnection *bus, char **args, unsigned n) {
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- dbus_bool_t interactive = true;
- _cleanup_free_ char *h = NULL;
- const char *hostname = args[1];
- int r;
-
- assert(args);
- assert(n == 2);
-
- polkit_agent_open_if_enabled();
-
- if (arg_set_pretty) {
- r = bus_method_call_with_reply(
- bus,
- "org.freedesktop.hostname1",
- "/org/freedesktop/hostname1",
- "org.freedesktop.hostname1",
- "SetPrettyHostname",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &hostname,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID);
- if (r < 0)
- return r;
-
- h = strdup(hostname);
- if (!h)
- return log_oom();
-
- hostname = hostname_simplify(h);
- }
-
- if (arg_set_static) {
- r = bus_method_call_with_reply(
- bus,
- "org.freedesktop.hostname1",
- "/org/freedesktop/hostname1",
- "org.freedesktop.hostname1",
- "SetStaticHostname",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &hostname,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID);
-
- if (r < 0)
- return r;
- }
-
- if (arg_set_transient) {
- r = bus_method_call_with_reply(
- bus,
- "org.freedesktop.hostname1",
- "/org/freedesktop/hostname1",
- "org.freedesktop.hostname1",
- "SetHostname",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &hostname,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID);
-
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-static int set_icon_name(DBusConnection *bus, char **args, unsigned n) {
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- dbus_bool_t interactive = true;
-
- assert(args);
- assert(n == 2);
-
- polkit_agent_open_if_enabled();
-
- return bus_method_call_with_reply(
- bus,
- "org.freedesktop.hostname1",
- "/org/freedesktop/hostname1",
- "org.freedesktop.hostname1",
- "SetIconName",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &args[1],
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID);
-}
-
-static int help(void) {
-
- printf("%s [OPTIONS...] COMMAND ...\n\n"
- "Query or change system hostname.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --transient Only set transient hostname\n"
- " --static Only set static hostname\n"
- " --pretty Only set pretty hostname\n"
- " --no-ask-password Do not prompt for password\n"
- " -H --host=[USER@]HOST Operate on remote host\n\n"
- "Commands:\n"
- " status Show current hostname settings\n"
- " set-hostname NAME Set system hostname\n"
- " set-icon-name NAME Set icon name for host\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100,
- ARG_NO_ASK_PASSWORD,
- ARG_SET_TRANSIENT,
- ARG_SET_STATIC,
- ARG_SET_PRETTY
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "transient", no_argument, NULL, ARG_SET_TRANSIENT },
- { "static", no_argument, NULL, ARG_SET_STATIC },
- { "pretty", no_argument, NULL, ARG_SET_PRETTY },
- { "host", required_argument, NULL, 'H' },
- { "privileged", no_argument, NULL, 'P' },
- { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
- { NULL, 0, NULL, 0 }
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "hH:P", options, NULL)) >= 0) {
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(DISTRIBUTION);
- puts(SYSTEMD_FEATURES);
- return 0;
-
- case 'P':
- arg_transport = TRANSPORT_POLKIT;
- break;
-
- case 'H':
- arg_transport = TRANSPORT_SSH;
- arg_host = optarg;
- break;
-
- case ARG_SET_TRANSIENT:
- arg_set_transient = true;
- break;
-
- case ARG_SET_PRETTY:
- arg_set_pretty = true;
- break;
-
- case ARG_SET_STATIC:
- arg_set_static = true;
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- log_error("Unknown option code %c", c);
- return -EINVAL;
- }
- }
-
- if (!arg_set_transient && !arg_set_pretty && !arg_set_static)
- arg_set_transient = arg_set_pretty = arg_set_static = true;
-
- return 1;
-}
-
-static int hostnamectl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
-
- static const struct {
- const char* verb;
- const enum {
- MORE,
- LESS,
- EQUAL
- } argc_cmp;
- const int argc;
- int (* const dispatch)(DBusConnection *bus, char **args, unsigned n);
- } verbs[] = {
- { "status", LESS, 1, show_status },
- { "set-hostname", EQUAL, 2, set_hostname },
- { "set-icon-name", EQUAL, 2, set_icon_name },
- };
-
- int left;
- unsigned i;
-
- assert(argc >= 0);
- assert(argv);
- assert(error);
-
- left = argc - optind;
-
- if (left <= 0)
- /* Special rule: no arguments means "status" */
- i = 0;
- else {
- if (streq(argv[optind], "help")) {
- help();
- return 0;
- }
-
- for (i = 0; i < ELEMENTSOF(verbs); i++)
- if (streq(argv[optind], verbs[i].verb))
- break;
-
- if (i >= ELEMENTSOF(verbs)) {
- log_error("Unknown operation %s", argv[optind]);
- return -EINVAL;
- }
- }
-
- switch (verbs[i].argc_cmp) {
-
- case EQUAL:
- if (left != verbs[i].argc) {
- log_error("Invalid number of arguments.");
- return -EINVAL;
- }
-
- break;
-
- case MORE:
- if (left < verbs[i].argc) {
- log_error("Too few arguments.");
- return -EINVAL;
- }
-
- break;
-
- case LESS:
- if (left > verbs[i].argc) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
- break;
-
- default:
- assert_not_reached("Unknown comparison operator.");
- }
-
- if (!bus) {
- log_error("Failed to get D-Bus connection: %s", error->message);
- return -EIO;
- }
-
- return verbs[i].dispatch(bus, argv + optind, left);
-}
-
-int main(int argc, char *argv[]) {
- int r, retval = EXIT_FAILURE;
- DBusConnection *bus = NULL;
- DBusError error;
-
- dbus_error_init(&error);
-
- setlocale(LC_ALL, "");
- log_parse_environment();
- log_open();
-
- r = parse_argv(argc, argv);
- if (r < 0)
- goto finish;
- else if (r == 0) {
- retval = EXIT_SUCCESS;
- goto finish;
- }
-
- if (arg_transport == TRANSPORT_NORMAL)
- bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
- else if (arg_transport == TRANSPORT_POLKIT)
- bus_connect_system_polkit(&bus, &error);
- else if (arg_transport == TRANSPORT_SSH)
- bus_connect_system_ssh(NULL, arg_host, &bus, &error);
- else
- assert_not_reached("Uh, invalid transport...");
-
- r = hostnamectl_main(bus, argc, argv, &error);
- retval = r < 0 ? EXIT_FAILURE : r;
-
-finish:
- if (bus) {
- dbus_connection_flush(bus);
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
- }
-
- dbus_error_free(&error);
- dbus_shutdown();
-
- return retval;
-}
diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
deleted file mode 100644
index cd3ef491ac..0000000000
--- a/src/hostname/hostnamed.c
+++ /dev/null
@@ -1,636 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <dbus/dbus.h>
-
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <dlfcn.h>
-
-#include "util.h"
-#include "strv.h"
-#include "dbus-common.h"
-#include "polkit.h"
-#include "def.h"
-#include "virt.h"
-
-#define INTERFACE \
- " <interface name=\"org.freedesktop.hostname1\">\n" \
- " <property name=\"Hostname\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"StaticHostname\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"PrettyHostname\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"IconName\" type=\"s\" access=\"read\"/>\n" \
- " <method name=\"SetHostname\">\n" \
- " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"SetStaticHostname\">\n" \
- " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"SetPrettyHostname\">\n" \
- " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"SetIconName\">\n" \
- " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
- " </method>\n" \
- " </interface>\n"
-
-#define INTROSPECTION \
- DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
- "<node>\n" \
- INTERFACE \
- BUS_PROPERTIES_INTERFACE \
- BUS_INTROSPECTABLE_INTERFACE \
- BUS_PEER_INTERFACE \
- "</node>\n"
-
-#define INTERFACES_LIST \
- BUS_GENERIC_INTERFACES_LIST \
- "org.freedesktop.hostname1\0"
-
-const char hostname_interface[] _introspect_("hostname1") = INTERFACE;
-
-enum {
- PROP_HOSTNAME,
- PROP_STATIC_HOSTNAME,
- PROP_PRETTY_HOSTNAME,
- PROP_ICON_NAME,
- _PROP_MAX
-};
-
-static char *data[_PROP_MAX] = {
- NULL,
- NULL,
- NULL,
- NULL
-};
-
-static usec_t remain_until = 0;
-
-static void free_data(void) {
- int p;
-
- for (p = 0; p < _PROP_MAX; p++) {
- free(data[p]);
- data[p] = NULL;
- }
-}
-
-static int read_data(void) {
- int r;
-
- free_data();
-
- data[PROP_HOSTNAME] = gethostname_malloc();
- if (!data[PROP_HOSTNAME])
- return -ENOMEM;
-
- r = read_one_line_file("/etc/hostname", &data[PROP_STATIC_HOSTNAME]);
- if (r < 0 && r != -ENOENT)
- return r;
-
- r = parse_env_file("/etc/machine-info", NEWLINE,
- "PRETTY_HOSTNAME", &data[PROP_PRETTY_HOSTNAME],
- "ICON_NAME", &data[PROP_ICON_NAME],
- NULL);
- if (r < 0 && r != -ENOENT)
- return r;
-
- return 0;
-}
-
-static bool check_nss(void) {
-
- void *dl;
-
- if ((dl = dlopen("libnss_myhostname.so.2", RTLD_LAZY))) {
- dlclose(dl);
- return true;
- }
-
- return false;
-}
-
-static const char* fallback_icon_name(void) {
-
-#if defined(__i386__) || defined(__x86_64__)
- int r;
- char *type;
- unsigned t;
-#endif
-
- if (detect_virtualization(NULL) > 0)
- return "computer-vm";
-
-#if defined(__i386__) || defined(__x86_64__)
- r = read_one_line_file("/sys/class/dmi/id/chassis_type", &type);
- if (r < 0)
- return NULL;
-
- r = safe_atou(type, &t);
- free(type);
-
- if (r < 0)
- return NULL;
-
- /* We only list the really obvious cases here. The DMI data is
- unreliable enough, so let's not do any additional guesswork
- on top of that.
-
- See the SMBIOS Specification 2.7.1 section 7.4.1 for
- details about the values listed here:
-
- http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.7.1.pdf
- */
-
- switch (t) {
-
- case 0x3:
- case 0x4:
- case 0x6:
- case 0x7:
- return "computer-desktop";
-
- case 0x9:
- case 0xA:
- case 0xE:
- return "computer-laptop";
-
- case 0x11:
- case 0x1C:
- return "computer-server";
- }
-
-#endif
- return NULL;
-}
-
-static int write_data_hostname(void) {
- const char *hn;
-
- if (isempty(data[PROP_HOSTNAME]))
- hn = "localhost";
- else
- hn = data[PROP_HOSTNAME];
-
- if (sethostname(hn, strlen(hn)) < 0)
- return -errno;
-
- return 0;
-}
-
-static int write_data_static_hostname(void) {
-
- if (isempty(data[PROP_STATIC_HOSTNAME])) {
-
- if (unlink("/etc/hostname") < 0)
- return errno == ENOENT ? 0 : -errno;
-
- return 0;
- }
-
- return write_one_line_file_atomic("/etc/hostname", data[PROP_STATIC_HOSTNAME]);
-}
-
-static int write_data_other(void) {
-
- static const char * const name[_PROP_MAX] = {
- [PROP_PRETTY_HOSTNAME] = "PRETTY_HOSTNAME",
- [PROP_ICON_NAME] = "ICON_NAME"
- };
-
- char **l = NULL;
- int r, p;
-
- r = load_env_file("/etc/machine-info", &l);
- if (r < 0 && r != -ENOENT)
- return r;
-
- for (p = 2; p < _PROP_MAX; p++) {
- char *t, **u;
-
- assert(name[p]);
-
- if (isempty(data[p])) {
- strv_env_unset(l, name[p]);
- continue;
- }
-
- if (asprintf(&t, "%s=%s", name[p], strempty(data[p])) < 0) {
- strv_free(l);
- return -ENOMEM;
- }
-
- u = strv_env_set(l, t);
- free(t);
- strv_free(l);
-
- if (!u)
- return -ENOMEM;
- l = u;
- }
-
- if (strv_isempty(l)) {
-
- if (unlink("/etc/machine-info") < 0)
- return errno == ENOENT ? 0 : -errno;
-
- return 0;
- }
-
- r = write_env_file("/etc/machine-info", l);
- strv_free(l);
-
- return r;
-}
-
-static int bus_hostname_append_icon_name(DBusMessageIter *i, const char *property, void *userdata) {
- const char *name;
-
- assert(i);
- assert(property);
-
- if (isempty(data[PROP_ICON_NAME]))
- name = fallback_icon_name();
- else
- name = data[PROP_ICON_NAME];
-
- return bus_property_append_string(i, property, (void*) name);
-}
-
-static const BusProperty bus_hostname_properties[] = {
- { "Hostname", bus_property_append_string, "s", sizeof(data[0])*PROP_HOSTNAME, true },
- { "StaticHostname", bus_property_append_string, "s", sizeof(data[0])*PROP_STATIC_HOSTNAME, true },
- { "PrettyHostname", bus_property_append_string, "s", sizeof(data[0])*PROP_PRETTY_HOSTNAME, true },
- { "IconName", bus_hostname_append_icon_name, "s", sizeof(data[0])*PROP_ICON_NAME, true },
- { NULL, }
-};
-
-static const BusBoundProperties bps[] = {
- { "org.freedesktop.hostname1", bus_hostname_properties, data },
- { NULL, }
-};
-
-static DBusHandlerResult hostname_message_handler(
- DBusConnection *connection,
- DBusMessage *message,
- void *userdata) {
-
-
- DBusMessage *reply = NULL, *changed = NULL;
- DBusError error;
- int r;
-
- assert(connection);
- assert(message);
-
- dbus_error_init(&error);
-
- if (dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetHostname")) {
- const char *name;
- dbus_bool_t interactive;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- if (isempty(name))
- name = data[PROP_STATIC_HOSTNAME];
-
- if (isempty(name))
- name = "localhost";
-
- if (!hostname_is_valid(name))
- return bus_send_error_reply(connection, message, NULL, -EINVAL);
-
- if (!streq_ptr(name, data[PROP_HOSTNAME])) {
- char *h;
-
- r = verify_polkit(connection, message, "org.freedesktop.hostname1.set-hostname", interactive, NULL, &error);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- h = strdup(name);
- if (!h)
- goto oom;
-
- free(data[PROP_HOSTNAME]);
- data[PROP_HOSTNAME] = h;
-
- r = write_data_hostname();
- if (r < 0) {
- log_error("Failed to set host name: %s", strerror(-r));
- return bus_send_error_reply(connection, message, NULL, r);
- }
-
- log_info("Changed host name to '%s'", strempty(data[PROP_HOSTNAME]));
-
- changed = bus_properties_changed_new(
- "/org/freedesktop/hostname1",
- "org.freedesktop.hostname1",
- "Hostname\0");
- if (!changed)
- goto oom;
- }
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetStaticHostname")) {
- const char *name;
- dbus_bool_t interactive;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- if (isempty(name))
- name = NULL;
-
- if (!streq_ptr(name, data[PROP_STATIC_HOSTNAME])) {
-
- r = verify_polkit(connection, message, "org.freedesktop.hostname1.set-static-hostname", interactive, NULL, &error);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- if (isempty(name)) {
- free(data[PROP_STATIC_HOSTNAME]);
- data[PROP_STATIC_HOSTNAME] = NULL;
- } else {
- char *h;
-
- if (!hostname_is_valid(name))
- return bus_send_error_reply(connection, message, NULL, -EINVAL);
-
- h = strdup(name);
- if (!h)
- goto oom;
-
- free(data[PROP_STATIC_HOSTNAME]);
- data[PROP_STATIC_HOSTNAME] = h;
- }
-
- r = write_data_static_hostname();
- if (r < 0) {
- log_error("Failed to write static host name: %s", strerror(-r));
- return bus_send_error_reply(connection, message, NULL, r);
- }
-
- log_info("Changed static host name to '%s'", strempty(data[PROP_STATIC_HOSTNAME]));
-
- changed = bus_properties_changed_new(
- "/org/freedesktop/hostname1",
- "org.freedesktop.hostname1",
- "StaticHostname\0");
- if (!changed)
- goto oom;
- }
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetPrettyHostname") ||
- dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetIconName")) {
-
- const char *name;
- dbus_bool_t interactive;
- int k;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- if (isempty(name))
- name = NULL;
-
- k = streq(dbus_message_get_member(message), "SetPrettyHostname") ? PROP_PRETTY_HOSTNAME : PROP_ICON_NAME;
-
- if (!streq_ptr(name, data[k])) {
-
- /* Since the pretty hostname should always be
- * changed at the same time as the static one,
- * use the same policy action for both... */
-
- r = verify_polkit(connection, message, k == PROP_PRETTY_HOSTNAME ?
- "org.freedesktop.hostname1.set-static-hostname" :
- "org.freedesktop.hostname1.set-machine-info", interactive, NULL, &error);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- if (isempty(name)) {
- free(data[k]);
- data[k] = NULL;
- } else {
- char *h;
-
- /* The icon name might ultimately be
- * used as file name, so better be
- * safe than sorry */
- if (k == PROP_ICON_NAME && !filename_is_safe(name))
- return bus_send_error_reply(connection, message, NULL, -EINVAL);
- if (k == PROP_PRETTY_HOSTNAME && !string_is_safe(name))
- return bus_send_error_reply(connection, message, NULL, -EINVAL);
-
- h = strdup(name);
- if (!h)
- goto oom;
-
- free(data[k]);
- data[k] = h;
- }
-
- r = write_data_other();
- if (r < 0) {
- log_error("Failed to write machine info: %s", strerror(-r));
- return bus_send_error_reply(connection, message, NULL, r);
- }
-
- log_info("Changed %s to '%s'", k == PROP_PRETTY_HOSTNAME ? "pretty host name" : "icon name", strempty(data[k]));
-
- changed = bus_properties_changed_new(
- "/org/freedesktop/hostname1",
- "org.freedesktop.hostname1",
- k == PROP_PRETTY_HOSTNAME ? "PrettyHostname\0" : "IconName\0");
- if (!changed)
- goto oom;
- }
-
- } else
- return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps);
-
- if (!(reply = dbus_message_new_method_return(message)))
- goto oom;
-
- if (!dbus_connection_send(connection, reply, NULL))
- goto oom;
-
- dbus_message_unref(reply);
- reply = NULL;
-
- if (changed) {
-
- if (!dbus_connection_send(connection, changed, NULL))
- goto oom;
-
- dbus_message_unref(changed);
- }
-
- return DBUS_HANDLER_RESULT_HANDLED;
-
-oom:
- if (reply)
- dbus_message_unref(reply);
-
- if (changed)
- dbus_message_unref(changed);
-
- dbus_error_free(&error);
-
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-}
-
-static int connect_bus(DBusConnection **_bus) {
- static const DBusObjectPathVTable hostname_vtable = {
- .message_function = hostname_message_handler
- };
- DBusError error;
- DBusConnection *bus = NULL;
- int r;
-
- assert(_bus);
-
- dbus_error_init(&error);
-
- bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
- if (!bus) {
- log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
- r = -ECONNREFUSED;
- goto fail;
- }
-
- dbus_connection_set_exit_on_disconnect(bus, FALSE);
-
- if (!dbus_connection_register_object_path(bus, "/org/freedesktop/hostname1", &hostname_vtable, NULL) ||
- !dbus_connection_add_filter(bus, bus_exit_idle_filter, &remain_until, NULL)) {
- r = log_oom();
- goto fail;
- }
-
- r = dbus_bus_request_name(bus, "org.freedesktop.hostname1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
- if (dbus_error_is_set(&error)) {
- log_error("Failed to register name on bus: %s", bus_error_message(&error));
- r = -EEXIST;
- goto fail;
- }
-
- if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
- log_error("Failed to acquire name.");
- r = -EEXIST;
- goto fail;
- }
-
- if (_bus)
- *_bus = bus;
-
- return 0;
-
-fail:
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
-
- dbus_error_free(&error);
-
- return r;
-}
-
-int main(int argc, char *argv[]) {
- int r;
- DBusConnection *bus = NULL;
- bool exiting = false;
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- if (argc == 2 && streq(argv[1], "--introspect")) {
- fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
- "<node>\n", stdout);
- fputs(hostname_interface, stdout);
- fputs("</node>\n", stdout);
- return 0;
- }
-
- if (argc != 1) {
- log_error("This program takes no arguments.");
- r = -EINVAL;
- goto finish;
- }
-
- if (!check_nss())
- log_warning("Warning: nss-myhostname is not installed. Changing the local hostname might make it unresolveable. Please install nss-myhostname!");
-
- r = read_data();
- if (r < 0) {
- log_error("Failed to read hostname data: %s", strerror(-r));
- goto finish;
- }
-
- r = connect_bus(&bus);
- if (r < 0)
- goto finish;
-
- remain_until = now(CLOCK_MONOTONIC) + DEFAULT_EXIT_USEC;
- for (;;) {
-
- if (!dbus_connection_read_write_dispatch(bus, exiting ? -1 : (int) (DEFAULT_EXIT_USEC/USEC_PER_MSEC)))
- break;
-
- if (!exiting && remain_until < now(CLOCK_MONOTONIC)) {
- exiting = true;
- bus_async_unregister_and_exit(bus, "org.freedesktop.hostname1");
- }
- }
-
- r = 0;
-
-finish:
- free_data();
-
- if (bus) {
- dbus_connection_flush(bus);
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
- }
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/hostname/org.freedesktop.hostname1.conf b/src/hostname/org.freedesktop.hostname1.conf
deleted file mode 100644
index 46b4aadc83..0000000000
--- a/src/hostname/org.freedesktop.hostname1.conf
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0"?> <!--*-nxml-*-->
-<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
-
-<!--
- This file is part of systemd.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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.
--->
-
-<busconfig>
-
- <policy user="root">
- <allow own="org.freedesktop.hostname1"/>
- <allow send_destination="org.freedesktop.hostname1"/>
- <allow receive_sender="org.freedesktop.hostname1"/>
- </policy>
-
- <policy context="default">
- <allow send_destination="org.freedesktop.hostname1"/>
- <allow receive_sender="org.freedesktop.hostname1"/>
- </policy>
-
-</busconfig>
diff --git a/src/hostname/org.freedesktop.hostname1.policy.in b/src/hostname/org.freedesktop.hostname1.policy.in
deleted file mode 100644
index df082d8e6f..0000000000
--- a/src/hostname/org.freedesktop.hostname1.policy.in
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?> <!--*-nxml-*-->
-<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
-
-<!--
- This file is part of systemd.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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.
--->
-
-<policyconfig>
-
- <vendor>The systemd Project</vendor>
- <vendor_url>http://www.freedesktop.org/wiki/Software/systemd</vendor_url>
-
- <action id="org.freedesktop.hostname1.set-hostname">
- <_description>Set host name</_description>
- <_message>Authentication is required to set the local host name.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.hostname1.set-static-hostname">
- <_description>Set static host name</_description>
- <_message>Authentication is required to set the statically configured local host name, as well as the pretty host name.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.hostname1.set-machine-info">
- <_description>Set machine information</_description>
- <_message>Authentication is required to set local machine information.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
- </defaults>
- </action>
-
-</policyconfig>
diff --git a/src/hostname/org.freedesktop.hostname1.service b/src/hostname/org.freedesktop.hostname1.service
deleted file mode 100644
index 6041ed60ca..0000000000
--- a/src/hostname/org.freedesktop.hostname1.service
+++ /dev/null
@@ -1,12 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-
-[D-BUS Service]
-Name=org.freedesktop.hostname1
-Exec=/bin/false
-User=root
-SystemdService=dbus-org.freedesktop.hostname1.service
diff --git a/src/initctl/Makefile b/src/initctl/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/initctl/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/initctl/initctl.c b/src/initctl/initctl.c
deleted file mode 100644
index 0eb008d9e6..0000000000
--- a/src/initctl/initctl.c
+++ /dev/null
@@ -1,451 +0,0 @@
-/*-*- 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/socket.h>
-#include <sys/types.h>
-#include <assert.h>
-#include <time.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/poll.h>
-#include <sys/epoll.h>
-#include <sys/un.h>
-#include <fcntl.h>
-#include <ctype.h>
-
-#include <dbus/dbus.h>
-#include <systemd/sd-daemon.h>
-
-#include "util.h"
-#include "log.h"
-#include "list.h"
-#include "initreq.h"
-#include "special.h"
-#include "dbus-common.h"
-#include "def.h"
-
-#define SERVER_FD_MAX 16
-#define TIMEOUT_MSEC ((int) (DEFAULT_EXIT_USEC/USEC_PER_MSEC))
-
-typedef struct Fifo Fifo;
-
-typedef struct Server {
- int epoll_fd;
-
- LIST_HEAD(Fifo, fifos);
- unsigned n_fifos;
-
- DBusConnection *bus;
-
- bool quit;
-} Server;
-
-struct Fifo {
- Server *server;
-
- int fd;
-
- struct init_request buffer;
- size_t bytes_read;
-
- LIST_FIELDS(Fifo, fifo);
-};
-
-static const char *translate_runlevel(int runlevel, bool *isolate) {
- static const struct {
- const int runlevel;
- const char *special;
- bool isolate;
- } table[] = {
- { '0', SPECIAL_POWEROFF_TARGET, false },
- { '1', SPECIAL_RESCUE_TARGET, true },
- { 's', SPECIAL_RESCUE_TARGET, true },
- { 'S', SPECIAL_RESCUE_TARGET, true },
- { '2', SPECIAL_RUNLEVEL2_TARGET, true },
- { '3', SPECIAL_RUNLEVEL3_TARGET, true },
- { '4', SPECIAL_RUNLEVEL4_TARGET, true },
- { '5', SPECIAL_RUNLEVEL5_TARGET, true },
- { '6', SPECIAL_REBOOT_TARGET, false },
- };
-
- unsigned i;
-
- assert(isolate);
-
- for (i = 0; i < ELEMENTSOF(table); i++)
- if (table[i].runlevel == runlevel) {
- *isolate = table[i].isolate;
- if (runlevel == '6' && kexec_loaded())
- return SPECIAL_KEXEC_TARGET;
- return table[i].special;
- }
-
- return NULL;
-}
-
-static void change_runlevel(Server *s, int runlevel) {
- const char *target;
- DBusMessage *m = NULL, *reply = NULL;
- DBusError error;
- const char *mode;
- bool isolate = false;
-
- assert(s);
-
- dbus_error_init(&error);
-
- if (!(target = translate_runlevel(runlevel, &isolate))) {
- log_warning("Got request for unknown runlevel %c, ignoring.", runlevel);
- goto finish;
- }
-
- if (isolate)
- mode = "isolate";
- else
- mode = "replace";
-
- log_debug("Running request %s/start/%s", target, mode);
-
- if (!(m = dbus_message_new_method_call("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartUnit"))) {
- log_error("Could not allocate message.");
- goto finish;
- }
-
- if (!dbus_message_append_args(m,
- DBUS_TYPE_STRING, &target,
- DBUS_TYPE_STRING, &mode,
- DBUS_TYPE_INVALID)) {
- log_error("Could not attach target and flag information to message.");
- goto finish;
- }
-
- if (!(reply = dbus_connection_send_with_reply_and_block(s->bus, m, -1, &error))) {
- log_error("Failed to start unit: %s", bus_error_message(&error));
- goto finish;
- }
-
-finish:
- if (m)
- dbus_message_unref(m);
-
- if (reply)
- dbus_message_unref(reply);
-
- dbus_error_free(&error);
-}
-
-static void request_process(Server *s, const struct init_request *req) {
- assert(s);
- assert(req);
-
- if (req->magic != INIT_MAGIC) {
- log_error("Got initctl request with invalid magic. Ignoring.");
- return;
- }
-
- switch (req->cmd) {
-
- case INIT_CMD_RUNLVL:
- if (!isprint(req->runlevel))
- log_error("Got invalid runlevel. Ignoring.");
- else
- switch (req->runlevel) {
-
- /* we are async anyway, so just use kill for reexec/reload */
- case 'u':
- case 'U':
- if (kill(1, SIGTERM) < 0)
- log_error("kill() failed: %m");
-
- /* The bus connection will be
- * terminated if PID 1 is reexecuted,
- * hence let's just exit here, and
- * rely on that we'll be restarted on
- * the next request */
- s->quit = true;
- break;
-
- case 'q':
- case 'Q':
- if (kill(1, SIGHUP) < 0)
- log_error("kill() failed: %m");
- break;
-
- default:
- change_runlevel(s, req->runlevel);
- }
- return;
-
- case INIT_CMD_POWERFAIL:
- case INIT_CMD_POWERFAILNOW:
- case INIT_CMD_POWEROK:
- log_warning("Received UPS/power initctl request. This is not implemented in systemd. Upgrade your UPS daemon!");
- return;
-
- case INIT_CMD_CHANGECONS:
- log_warning("Received console change initctl request. This is not implemented in systemd.");
- return;
-
- case INIT_CMD_SETENV:
- case INIT_CMD_UNSETENV:
- log_warning("Received environment initctl request. This is not implemented in systemd.");
- return;
-
- default:
- log_warning("Received unknown initctl request. Ignoring.");
- return;
- }
-}
-
-static int fifo_process(Fifo *f) {
- ssize_t l;
-
- assert(f);
-
- errno = EIO;
- if ((l = read(f->fd, ((uint8_t*) &f->buffer) + f->bytes_read, sizeof(f->buffer) - f->bytes_read)) <= 0) {
-
- if (errno == EAGAIN)
- return 0;
-
- log_warning("Failed to read from fifo: %s", strerror(errno));
- return -1;
- }
-
- f->bytes_read += l;
- assert(f->bytes_read <= sizeof(f->buffer));
-
- if (f->bytes_read == sizeof(f->buffer)) {
- request_process(f->server, &f->buffer);
- f->bytes_read = 0;
- }
-
- return 0;
-}
-
-static void fifo_free(Fifo *f) {
- assert(f);
-
- if (f->server) {
- assert(f->server->n_fifos > 0);
- f->server->n_fifos--;
- LIST_REMOVE(Fifo, fifo, f->server->fifos, f);
- }
-
- if (f->fd >= 0) {
- if (f->server)
- epoll_ctl(f->server->epoll_fd, EPOLL_CTL_DEL, f->fd, NULL);
-
- close_nointr_nofail(f->fd);
- }
-
- free(f);
-}
-
-static void server_done(Server *s) {
- assert(s);
-
- while (s->fifos)
- fifo_free(s->fifos);
-
- if (s->epoll_fd >= 0)
- close_nointr_nofail(s->epoll_fd);
-
- if (s->bus) {
- dbus_connection_flush(s->bus);
- dbus_connection_close(s->bus);
- dbus_connection_unref(s->bus);
- }
-}
-
-static int server_init(Server *s, unsigned n_sockets) {
- int r;
- unsigned i;
- DBusError error;
-
- assert(s);
- assert(n_sockets > 0);
-
- dbus_error_init(&error);
-
- zero(*s);
-
- if ((s->epoll_fd = epoll_create1(EPOLL_CLOEXEC)) < 0) {
- r = -errno;
- log_error("Failed to create epoll object: %s", strerror(errno));
- goto fail;
- }
-
- for (i = 0; i < n_sockets; i++) {
- struct epoll_event ev;
- Fifo *f;
- int fd;
-
- fd = SD_LISTEN_FDS_START+i;
-
- if ((r = sd_is_fifo(fd, NULL)) < 0) {
- log_error("Failed to determine file descriptor type: %s", strerror(-r));
- goto fail;
- }
-
- if (!r) {
- log_error("Wrong file descriptor type.");
- r = -EINVAL;
- goto fail;
- }
-
- if (!(f = new0(Fifo, 1))) {
- r = -ENOMEM;
- log_error("Failed to create fifo object: %s", strerror(errno));
- goto fail;
- }
-
- f->fd = -1;
-
- zero(ev);
- ev.events = EPOLLIN;
- ev.data.ptr = f;
- if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
- r = -errno;
- fifo_free(f);
- log_error("Failed to add fifo fd to epoll object: %s", strerror(errno));
- goto fail;
- }
-
- f->fd = fd;
- LIST_PREPEND(Fifo, fifo, s->fifos, f);
- f->server = s;
- s->n_fifos ++;
- }
-
- if (bus_connect(DBUS_BUS_SYSTEM, &s->bus, NULL, &error) < 0) {
- log_error("Failed to get D-Bus connection: %s", bus_error_message(&error));
- goto fail;
- }
-
- return 0;
-
-fail:
- server_done(s);
-
- dbus_error_free(&error);
- return r;
-}
-
-static int process_event(Server *s, struct epoll_event *ev) {
- int r;
- Fifo *f;
-
- assert(s);
-
- if (!(ev->events & EPOLLIN)) {
- log_info("Got invalid event from epoll. (3)");
- return -EIO;
- }
-
- f = (Fifo*) ev->data.ptr;
-
- if ((r = fifo_process(f)) < 0) {
- log_info("Got error on fifo: %s", strerror(-r));
- fifo_free(f);
- return r;
- }
-
- return 0;
-}
-
-int main(int argc, char *argv[]) {
- Server server;
- int r = EXIT_FAILURE, n;
-
- if (getppid() != 1) {
- log_error("This program should be invoked by init only.");
- return EXIT_FAILURE;
- }
-
- if (argc > 1) {
- log_error("This program does not take arguments.");
- return EXIT_FAILURE;
- }
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- if ((n = sd_listen_fds(true)) < 0) {
- log_error("Failed to read listening file descriptors from environment: %s", strerror(-r));
- return EXIT_FAILURE;
- }
-
- if (n <= 0 || n > SERVER_FD_MAX) {
- log_error("No or too many file descriptors passed.");
- return EXIT_FAILURE;
- }
-
- if (server_init(&server, (unsigned) n) < 0)
- return EXIT_FAILURE;
-
- log_debug("systemd-initctl running as pid %lu", (unsigned long) getpid());
-
- sd_notify(false,
- "READY=1\n"
- "STATUS=Processing requests...");
-
- while (!server.quit) {
- struct epoll_event event;
- int k;
-
- if ((k = epoll_wait(server.epoll_fd,
- &event, 1,
- TIMEOUT_MSEC)) < 0) {
-
- if (errno == EINTR)
- continue;
-
- log_error("epoll_wait() failed: %s", strerror(errno));
- goto fail;
- }
-
- if (k <= 0)
- break;
-
- if (process_event(&server, &event) < 0)
- goto fail;
- }
-
- r = EXIT_SUCCESS;
-
- log_debug("systemd-initctl stopped as pid %lu", (unsigned long) getpid());
-
-fail:
- sd_notify(false,
- "STATUS=Shutting down...");
-
- server_done(&server);
-
- dbus_shutdown();
-
- return r;
-}
diff --git a/src/journal/.gitignore b/src/journal/.gitignore
deleted file mode 100644
index d6a79460cd..0000000000
--- a/src/journal/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/journald-gperf.c
-/libsystemd-journal.pc
diff --git a/src/journal/Makefile b/src/journal/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/journal/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/journal/browse.html b/src/journal/browse.html
deleted file mode 100644
index 3594f70c87..0000000000
--- a/src/journal/browse.html
+++ /dev/null
@@ -1,544 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <title>Journal</title>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
- <style type="text/css">
- div#divlogs, div#diventry {
- font-family: monospace;
- font-size: 7pt;
- background-color: #ffffff;
- padding: 1em;
- margin: 2em 0em;
- border-radius: 10px 10px 10px 10px;
- border: 1px solid threedshadow;
- white-space: nowrap;
- overflow-x: scroll;
- }
- div#diventry {
- display: none;
- }
- div#divlogs {
- display: block;
- }
- body {
- background-color: #ededed;
- color: #313739;
- font: message-box;
- margin: 3em;
- }
- td.timestamp {
- text-align: right;
- border-right: 1px dotted lightgrey;
- padding-right: 5px;
- }
- td.process {
- border-right: 1px dotted lightgrey;
- padding-left: 5px;
- padding-right: 5px;
- }
- td.message {
- padding-left: 5px;
- }
- td.message > a:link, td.message > a:visited {
- text-decoration: none;
- color: #313739;
- }
- td.message-error {
- padding-left: 5px;
- color: red;
- font-weight: bold;
- }
- td.message-error > a:link, td.message-error > a:visited {
- text-decoration: none;
- color: red;
- }
- td.message-highlight {
- padding-left: 5px;
- font-weight: bold;
- }
- td.message-highlight > a:link, td.message-highlight > a:visited {
- text-decoration: none;
- color: #313739;
- }
- td > a:hover, td > a:active {
- text-decoration: underline;
- color: #c13739;
- }
- table#tablelogs, table#tableentry {
- border-collapse: collapse;
- }
- td.field {
- text-align: right;
- border-right: 1px dotted lightgrey;
- padding-right: 5px;
- }
- td.data {
- padding-left: 5px;
- }
- div#keynav {
- text-align: center;
- font-size: 7pt;
- color: #818789;
- padding-top: 2em;
- }
- span.key {
- font-weight: bold;
- color: #313739;
- }
- div#buttonnav {
- text-align: center;
- }
- button {
- font-size: 18pt;
- font-weight: bold;
- width: 2em;
- height: 2em;
- }
- div#filternav {
- text-align: center;
- }
- select {
- width: 50em;
- }
- </style>
-</head>
-
-<body>
- <!-- TODO:
- - live display
- - show red lines for reboots -->
-
- <h1 id="title"></h1>
-
- <div id="os"></div>
- <div id="virtualization"></div>
- <div id="cutoff"></div>
- <div id="machine"></div>
- <div id="usage"></div>
- <div id="showing"></div>
-
- <div id="filternav">
- <select id="filter" onchange="onFilterChange(this);" onfocus="onFilterFocus(this);">
- <option>No filter</option>
- </select>
- &nbsp;&nbsp;&nbsp;&nbsp;
- <input id="boot" type="checkbox" onchange="onBootChange(this);">Only current boot</input>
- </div>
-
- <div id="divlogs"><table id="tablelogs"></table></div>
- <a name="entry"></a>
- <div id="diventry"><table id="tableentry"></table></div>
-
- <div id="buttonnav">
- <button id="head" onclick="entriesLoadHead();" title="First Page">&#8676;</button>
- <button id="previous" type="button" onclick="entriesLoadPrevious();" title="Previous Page"/>&#8592;</button>
- <button id="next" type="button" onclick="entriesLoadNext();" title="Next Page"/>&#8594;</button>
- <button id="tail" type="button" onclick="entriesLoadTail();" title="Last Page"/>&#8677;</button>
- &nbsp;&nbsp;&nbsp;&nbsp;
- <button id="more" type="button" onclick="entriesMore();" title="More Entries"/>+</button>
- <button id="less" type="button" onclick="entriesLess();" title="Fewer Entries"/>-</button>
- </div>
-
- <div id="keynav">
- <span class="key">g</span>: First Page &nbsp;&nbsp;&nbsp;&nbsp;
- <span class="key">&#8592;, k, BACKSPACE</span>: Previous Page &nbsp;&nbsp;&nbsp;&nbsp;
- <span class="key">&#8594;, j, SPACE</span>: Next Page &nbsp;&nbsp;&nbsp;&nbsp;
- <span class="key">G</span>: Last Page &nbsp;&nbsp;&nbsp;&nbsp;
- <span class="key">+</span>: More entries &nbsp;&nbsp;&nbsp;&nbsp;
- <span class="key">-</span>: Fewer entries
- </div>
-
- <script type="text/javascript">
- var first_cursor = null;
- var last_cursor = null;
-
- function getNEntries() {
- var n;
- n = localStorage["n_entries"];
- if (n == null)
- return 50;
- n = parseInt(n);
- if (n < 10)
- return 10;
- if (n > 1000)
- return 1000;
- return n;
- }
-
- function showNEntries(n) {
- var showing = document.getElementById("showing");
- showing.innerHTML = "Showing <b>" + n.toString() + "</b> entries.";
- }
-
- function setNEntries(n) {
- if (n < 10)
- return 10;
- if (n > 1000)
- return 1000;
- localStorage["n_entries"] = n.toString();
- showNEntries(n);
- }
-
- function machineLoad() {
- var request = new XMLHttpRequest();
- request.open("GET", "/machine");
- request.onreadystatechange = machineOnResult;
- request.setRequestHeader("Accept", "application/json");
- request.send(null);
- }
-
- function formatBytes(u) {
- if (u >= 1024*1024*1024*1024)
- return (u/1024/1024/1024/1024).toFixed(1) + " TiB";
- else if (u >= 1024*1024*1024)
- return (u/1024/1024/1024).toFixed(1) + " GiB";
- else if (u >= 1024*1024)
- return (u/1024/1024).toFixed(1) + " MiB";
- else if (u >= 1024)
- return (u/1024).toFixed(1) + " KiB";
- else
- return u.toString() + " B";
- }
-
- function escapeHTML(s) {
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
- }
-
- function machineOnResult(event) {
- if ((event.currentTarget.readyState != 4) ||
- (event.currentTarget.status != 200 && event.currentTarget.status != 0))
- return;
-
- var d = JSON.parse(event.currentTarget.responseText);
-
- var title = document.getElementById("title");
- title.innerHTML = 'Journal of ' + escapeHTML(d.hostname);
- document.title = 'Journal of ' + escapeHTML(d.hostname);
-
- var machine = document.getElementById("machine");
- machine.innerHTML = 'Machine ID is <b>' + d.machine_id + '</b>, current boot ID is <b>' + d.boot_id + '</b>.';
-
- var cutoff = document.getElementById("cutoff");
- var from = new Date(parseInt(d.cutoff_from_realtime) / 1000);
- var to = new Date(parseInt(d.cutoff_to_realtime) / 1000);
- cutoff.innerHTML = 'Journal begins at <b>' + from.toLocaleString() + '</b> and ends at <b>' + to.toLocaleString() + '</b>.';
-
- var usage = document.getElementById("usage");
- usage.innerHTML = 'Disk usage is <b>' + formatBytes(parseInt(d.usage)) + '</b>.';
-
- var os = document.getElementById("os");
- os.innerHTML = 'Operating system is <b>' + escapeHTML(d.os_pretty_name) + '</b>.';
-
- var virtualization = document.getElementById("virtualization");
- virtualization.innerHTML = d.virtualization == "bare" ? "Running on <b>bare metal</b>." : "Running on virtualization <b>" + escapeHTML(d.virtualization) + "</b>.";
- }
-
- function entriesLoad(range) {
-
- if (range == null)
- range = localStorage["cursor"] + ":0";
- if (range == null)
- range = "";
-
- var url = "/entries";
-
- if (localStorage["filter"] != "" && localStorage["filter"] != null) {
- url += "?_SYSTEMD_UNIT=" + escape(localStorage["filter"]);
-
- if (localStorage["boot"] == "1")
- url += "&boot";
- } else {
- if (localStorage["boot"] == "1")
- url += "?boot";
- }
-
- var request = new XMLHttpRequest();
- request.open("GET", url);
- request.onreadystatechange = entriesOnResult;
- request.setRequestHeader("Accept", "application/json");
- request.setRequestHeader("Range", "entries=" + range + ":" + getNEntries().toString());
- request.send(null);
- }
-
- function entriesLoadNext() {
- if (last_cursor == null)
- entriesLoad("");
- else
- entriesLoad(last_cursor + ":1");
- }
-
- function entriesLoadPrevious() {
- if (first_cursor == null)
- entriesLoad("");
- else
- entriesLoad(first_cursor + ":-" + getNEntries().toString());
- }
-
- function entriesLoadHead() {
- entriesLoad("");
- }
-
- function entriesLoadTail() {
- entriesLoad(":-" + getNEntries().toString());
- }
-
- function entriesOnResult(event) {
-
- if ((event.currentTarget.readyState != 4) ||
- (event.currentTarget.status != 200 && event.currentTarget.status != 0))
- return;
-
- var logs = document.getElementById("tablelogs");
-
- var lc = null;
- var fc = null;
-
- var i, l = event.currentTarget.responseText.split('\n');
-
- if (l.length <= 1) {
- logs.innerHTML = '<tbody><tr><td colspan="3"><i>No further entries...</i></td></tr></tbody>';
- return;
- }
-
- var buf = '';
-
- for (i in l) {
-
- if (l[i] == '')
- continue;
-
- var d = JSON.parse(l[i]);
- if (d.MESSAGE == undefined || d.__CURSOR == undefined)
- continue;
-
- if (fc == null)
- fc = d.__CURSOR;
- lc = d.__CURSOR;
-
- var priority;
- if (d.PRIORITY != undefined)
- priority = parseInt(d.PRIORITY);
- else
- priority = 6;
-
- if (priority <= 3)
- clazz = "message-error";
- else if (priority <= 5)
- clazz = "message-highlight";
- else
- clazz = "message";
-
- buf += '<tr><td class="timestamp">';
-
- if (d.__REALTIME_TIMESTAMP != undefined) {
- var timestamp = new Date(parseInt(d.__REALTIME_TIMESTAMP) / 1000);
- buf += timestamp.toLocaleString();
- }
-
- buf += '</td><td class="process">';
-
- if (d.SYSLOG_IDENTIFIER != undefined)
- buf += escapeHTML(d.SYSLOG_IDENTIFIER);
- else if (d._COMM != undefined)
- buf += escapeHTML(d._COMM);
-
- if (d._PID != undefined)
- buf += "[" + escapeHTML(d._PID) + "]";
- else if (d.SYSLOG_PID != undefined)
- buf += "[" + escapeHTML(d.SYSLOG_PID) + "]";
-
- buf += '</td><td class="' + clazz + '"><a href="#entry" onclick="onMessageClick(\'' + d.__CURSOR + '\');">';
-
- if (d.MESSAGE == null)
- buf += "[blob data]";
- else if (d.MESSAGE instanceof Array)
- buf += "[" + formatBytes(d.MESSAGE.length) + " blob data]";
- else
- buf += escapeHTML(d.MESSAGE);
-
- buf += '</a></td></tr>';
- }
-
- logs.innerHTML = '<tbody>' + buf + '</tbody>';
-
- if (fc != null) {
- first_cursor = fc;
- localStorage["cursor"] = fc;
- }
- if (lc != null)
- last_cursor = lc;
- }
-
- function entriesMore() {
- setNEntries(getNEntries() + 10);
- entriesLoad(first_cursor);
- }
-
- function entriesLess() {
- setNEntries(getNEntries() - 10);
- entriesLoad(first_cursor);
- }
-
- function onResultMessageClick(event) {
- if ((event.currentTarget.readyState != 4) ||
- (event.currentTarget.status != 200 && event.currentTarget.status != 0))
- return;
-
- var d = JSON.parse(event.currentTarget.responseText);
-
- document.getElementById("diventry").style.display = "block";
- entry = document.getElementById("tableentry");
-
- var buf = "";
- for (var key in d){
- var data = d[key];
-
- if (data == null)
- data = "[blob data]";
- else if (data instanceof Array)
- data = "[" + formatBytes(data.length) + " blob data]";
- else
- data = escapeHTML(data);
-
- buf += '<tr><td class="field">' + key + '</td><td class="data">' + data + '</td></tr>';
- }
- entry.innerHTML = '<tbody>' + buf + '</tbody>';
- }
-
- function onMessageClick(t) {
- var request = new XMLHttpRequest();
- request.open("GET", "/entries?discrete");
- request.onreadystatechange = onResultMessageClick;
- request.setRequestHeader("Accept", "application/json");
- request.setRequestHeader("Range", "entries=" + t + ":0:1");
- request.send(null);
- }
-
- function onKeyUp(event) {
- switch (event.keyCode) {
- case 8:
- case 37:
- case 75:
- entriesLoadPrevious();
- break;
- case 32:
- case 39:
- case 74:
- entriesLoadNext();
- break;
-
- case 71:
- if (event.shiftKey)
- entriesLoadTail();
- else
- entriesLoadHead();
- break;
- case 171:
- entriesMore();
- break;
- case 173:
- entriesLess();
- break;
- }
- }
-
- function onMouseWheel(event) {
- if (event.detail < 0 || event.wheelDelta > 0)
- entriesLoadPrevious();
- else
- entriesLoadNext();
- }
-
- function onResultFilterFocus(event) {
- if ((event.currentTarget.readyState != 4) ||
- (event.currentTarget.status != 200 && event.currentTarget.status != 0))
- return;
-
- f = document.getElementById("filter");
-
- var l = event.currentTarget.responseText.split('\n');
- var buf = '<option>No filter</option>';
- var j = -1;
-
- for (i in l) {
-
- if (l[i] == '')
- continue;
-
- var d = JSON.parse(l[i]);
- if (d._SYSTEMD_UNIT == undefined)
- continue;
-
- buf += '<option value="' + escape(d._SYSTEMD_UNIT) + '">' + escapeHTML(d._SYSTEMD_UNIT) + '</option>';
-
- if (d._SYSTEMD_UNIT == localStorage["filter"])
- j = i;
- }
-
- if (j < 0) {
- if (localStorage["filter"] != null && localStorage["filter"] != "") {
- buf += '<option value="' + escape(localStorage["filter"]) + '">' + escapeHTML(localStorage["filter"]) + '</option>';
- j = i + 1;
- } else
- j = 0;
- }
-
- f.innerHTML = buf;
- f.selectedIndex = j;
- }
-
- function onFilterFocus(w) {
- var request = new XMLHttpRequest();
- request.open("GET", "/fields/_SYSTEMD_UNIT");
- request.onreadystatechange = onResultFilterFocus;
- request.setRequestHeader("Accept", "application/json");
- request.send(null);
- }
-
- function onFilterChange(w) {
- if (w.selectedIndex <= 0)
- localStorage["filter"] = "";
- else
- localStorage["filter"] = unescape(w.options[w.selectedIndex].value);
-
- entriesLoadHead();
- }
-
- function onBootChange(w) {
- localStorage["boot"] = w.checked ? "1" : "0";
- entriesLoadHead();
- }
-
- function initFilter() {
- f = document.getElementById("filter");
-
- var buf = '<option>No filter</option>';
-
- var filter = localStorage["filter"];
- if (filter != null && filter != "") {
- buf += '<option value="' + escape(filter) + '">' + escapeHTML(filter) + '</option>';
- j = 1;
- } else
- j = 0;
-
- f.innerHTML = buf;
- f.selectedIndex = j;
- }
-
- function installHandlers() {
- document.onkeyup = onKeyUp;
-
- logs = document.getElementById("divlogs");
- logs.addEventListener("mousewheel", onMouseWheel, false);
- logs.addEventListener("DOMMouseScroll", onMouseWheel, false);
- }
-
- machineLoad();
- entriesLoad(null);
- showNEntries(getNEntries());
- initFilter();
- installHandlers();
- </script>
-</body>
-</html>
diff --git a/src/journal/cat.c b/src/journal/cat.c
deleted file mode 100644
index 523a7a2eda..0000000000
--- a/src/journal/cat.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdio.h>
-#include <getopt.h>
-#include <assert.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/fcntl.h>
-
-#include <systemd/sd-journal.h>
-
-#include "util.h"
-#include "build.h"
-
-static char *arg_identifier = NULL;
-static int arg_priority = LOG_INFO;
-static bool arg_level_prefix = true;
-
-static int help(void) {
-
- printf("%s [OPTIONS...] {COMMAND} ...\n\n"
- "Execute process with stdout/stderr connected to the journal.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " -t --identifier=STRING Set syslog identifier\n"
- " -p --priority=PRIORITY Set priority value (0..7)\n"
- " --level-prefix=BOOL Control whether level prefix shall be parsed\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100,
- ARG_LEVEL_PREFIX
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "identifier", required_argument, NULL, 't' },
- { "priority", required_argument, NULL, 'p' },
- { "level-prefix", required_argument, NULL, ARG_LEVEL_PREFIX },
- { NULL, 0, NULL, 0 }
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "+ht:p:", options, NULL)) >= 0) {
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(DISTRIBUTION);
- puts(SYSTEMD_FEATURES);
- return 0;
-
- case 't':
- free(arg_identifier);
- if (isempty(optarg))
- arg_identifier = NULL;
- else {
- arg_identifier = strdup(optarg);
- if (!arg_identifier)
- return log_oom();
- }
- break;
-
- case 'p':
- arg_priority = log_level_from_string(optarg);
- if (arg_priority < 0) {
- log_error("Failed to parse priority value.");
- return arg_priority;
- }
- break;
-
- case ARG_LEVEL_PREFIX: {
- int k;
-
- k = parse_boolean(optarg);
- if (k < 0) {
- log_error("Failed to parse level prefix value.");
- return k;
- }
- arg_level_prefix = k;
- break;
- }
-
- default:
- log_error("Unknown option code %c", c);
- return -EINVAL;
- }
- }
-
- return 1;
-}
-
-int main(int argc, char *argv[]) {
- int r, fd = -1, saved_stderr = -1;
-
- log_parse_environment();
- log_open();
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- goto finish;
-
- fd = sd_journal_stream_fd(arg_identifier, arg_priority, arg_level_prefix);
- if (fd < 0) {
- log_error("Failed to create stream fd: %s", strerror(-fd));
- r = fd;
- goto finish;
- }
-
- saved_stderr = fcntl(STDERR_FILENO, F_DUPFD_CLOEXEC, 3);
-
- if (dup3(fd, STDOUT_FILENO, 0) < 0 ||
- dup3(fd, STDERR_FILENO, 0) < 0) {
- log_error("Failed to duplicate fd: %m");
- r = -errno;
- goto finish;
- }
-
- if (fd >= 3)
- close_nointr_nofail(fd);
-
- fd = -1;
-
- if (argc <= optind)
- execl("/bin/cat", "/bin/cat", NULL);
- else
- execvp(argv[optind], argv + optind);
-
- r = -errno;
-
- /* Let's try to restore a working stderr, so we can print the error message */
- if (saved_stderr >= 0)
- dup3(saved_stderr, STDERR_FILENO, 0);
-
- log_error("Failed to execute process: %s", strerror(-r));
-
-finish:
- if (fd >= 0)
- close_nointr_nofail(fd);
-
- if (saved_stderr >= 0)
- close_nointr_nofail(saved_stderr);
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/journal/compress.c b/src/journal/compress.c
deleted file mode 100644
index 75e70c5ffa..0000000000
--- a/src/journal/compress.c
+++ /dev/null
@@ -1,208 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <lzma.h>
-
-#include "compress.h"
-
-bool compress_blob(const void *src, uint64_t src_size, void *dst, uint64_t *dst_size) {
- lzma_stream s = LZMA_STREAM_INIT;
- lzma_ret ret;
- bool b = false;
-
- assert(src);
- assert(src_size > 0);
- assert(dst);
- assert(dst_size);
-
- /* Returns false if we couldn't compress the data or the
- * compressed result is longer than the original */
-
- ret = lzma_easy_encoder(&s, LZMA_PRESET_DEFAULT, LZMA_CHECK_NONE);
- if (ret != LZMA_OK)
- return false;
-
- s.next_in = src;
- s.avail_in = src_size;
- s.next_out = dst;
- s.avail_out = src_size;
-
- /* Does it fit? */
- if (lzma_code(&s, LZMA_FINISH) != LZMA_STREAM_END)
- goto fail;
-
- /* Is it actually shorter? */
- if (s.avail_out == 0)
- goto fail;
-
- *dst_size = src_size - s.avail_out;
- b = true;
-
-fail:
- lzma_end(&s);
-
- return b;
-}
-
-bool uncompress_blob(const void *src, uint64_t src_size,
- void **dst, uint64_t *dst_alloc_size, uint64_t* dst_size) {
-
- lzma_stream s = LZMA_STREAM_INIT;
- lzma_ret ret;
- bool b = false;
-
- assert(src);
- assert(src_size > 0);
- assert(dst);
- assert(dst_alloc_size);
- assert(dst_size);
- assert(*dst_alloc_size == 0 || *dst);
-
- ret = lzma_stream_decoder(&s, UINT64_MAX, 0);
- if (ret != LZMA_OK)
- return false;
-
- if (*dst_alloc_size <= src_size) {
- void *p;
-
- p = realloc(*dst, src_size*2);
- if (!p)
- return false;
-
- *dst = p;
- *dst_alloc_size = src_size*2;
- }
-
- s.next_in = src;
- s.avail_in = src_size;
-
- s.next_out = *dst;
- s.avail_out = *dst_alloc_size;
-
- for (;;) {
- void *p;
-
- ret = lzma_code(&s, LZMA_FINISH);
-
- if (ret == LZMA_STREAM_END)
- break;
-
- if (ret != LZMA_OK)
- goto fail;
-
- p = realloc(*dst, *dst_alloc_size*2);
- if (!p)
- goto fail;
-
- s.next_out = (uint8_t*) p + ((uint8_t*) s.next_out - (uint8_t*) *dst);
- s.avail_out += *dst_alloc_size;
-
- *dst = p;
- *dst_alloc_size *= 2;
- }
-
- *dst_size = *dst_alloc_size - s.avail_out;
- b = true;
-
-fail:
- lzma_end(&s);
-
- return b;
-}
-
-bool uncompress_startswith(const void *src, uint64_t src_size,
- void **buffer, uint64_t *buffer_size,
- const void *prefix, uint64_t prefix_len,
- uint8_t extra) {
-
- lzma_stream s = LZMA_STREAM_INIT;
- lzma_ret ret;
- bool b = false;
-
- /* Checks whether the uncompressed blob starts with the
- * mentioned prefix. The byte extra needs to follow the
- * prefix */
-
- assert(src);
- assert(src_size > 0);
- assert(buffer);
- assert(buffer_size);
- assert(prefix);
- assert(*buffer_size == 0 || *buffer);
-
- ret = lzma_stream_decoder(&s, UINT64_MAX, 0);
- if (ret != LZMA_OK)
- return false;
-
- if (*buffer_size <= prefix_len) {
- void *p;
-
- p = realloc(*buffer, prefix_len*2);
- if (!p)
- return false;
-
- *buffer = p;
- *buffer_size = prefix_len*2;
- }
-
- s.next_in = src;
- s.avail_in = src_size;
-
- s.next_out = *buffer;
- s.avail_out = *buffer_size;
-
- for (;;) {
- void *p;
-
- ret = lzma_code(&s, LZMA_FINISH);
-
- if (ret != LZMA_STREAM_END && ret != LZMA_OK)
- goto fail;
-
- if ((*buffer_size - s.avail_out > prefix_len) &&
- memcmp(*buffer, prefix, prefix_len) == 0 &&
- ((const uint8_t*) *buffer)[prefix_len] == extra)
- break;
-
- if (ret == LZMA_STREAM_END)
- goto fail;
-
- p = realloc(*buffer, *buffer_size*2);
- if (!p)
- goto fail;
-
- s.next_out = (uint8_t*) p + ((uint8_t*) s.next_out - (uint8_t*) *buffer);
- s.avail_out += *buffer_size;
-
- *buffer = p;
- *buffer_size *= 2;
- }
-
- b = true;
-
-fail:
- lzma_end(&s);
-
- return b;
-}
diff --git a/src/journal/compress.h b/src/journal/compress.h
deleted file mode 100644
index b6f1aa0ed7..0000000000
--- a/src/journal/compress.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <stdbool.h>
-
-bool compress_blob(const void *src, uint64_t src_size, void *dst, uint64_t *dst_size);
-
-bool uncompress_blob(const void *src, uint64_t src_size,
- void **dst, uint64_t *dst_alloc_size, uint64_t* dst_size);
-
-bool uncompress_startswith(const void *src, uint64_t src_size,
- void **buffer, uint64_t *buffer_size,
- const void *prefix, uint64_t prefix_len,
- uint8_t extra);
diff --git a/src/journal/coredump.c b/src/journal/coredump.c
deleted file mode 100644
index a507fc65f8..0000000000
--- a/src/journal/coredump.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <sys/prctl.h>
-
-#include <systemd/sd-journal.h>
-
-#ifdef HAVE_LOGIND
-#include <systemd/sd-login.h>
-#endif
-
-#include "log.h"
-#include "util.h"
-#include "mkdir.h"
-#include "special.h"
-#include "cgroup-util.h"
-
-#define COREDUMP_MAX (24*1024*1024)
-
-enum {
- ARG_PID = 1,
- ARG_UID,
- ARG_GID,
- ARG_SIGNAL,
- ARG_TIMESTAMP,
- ARG_COMM,
- _ARG_MAX
-};
-
-static int divert_coredump(void) {
- FILE *f;
- int r;
-
- log_info("Detected coredump of the journal daemon itself, diverting coredump to /var/lib/systemd/coredump/.");
-
- mkdir_p_label("/var/lib/systemd/coredump", 0755);
-
- f = fopen("/var/lib/systemd/coredump/core.systemd-journald", "we");
- if (!f) {
- log_error("Failed to create coredump file: %m");
- return -errno;
- }
-
- for (;;) {
- uint8_t buffer[4096];
- size_t l, q;
-
- l = fread(buffer, 1, sizeof(buffer), stdin);
- if (l <= 0) {
- if (ferror(f)) {
- log_error("Failed to read coredump: %m");
- r = -errno;
- goto finish;
- }
-
- r = 0;
- break;
- }
-
- q = fwrite(buffer, 1, l, f);
- if (q != l) {
- log_error("Failed to write coredump: %m");
- r = -errno;
- goto finish;
- }
- }
-
- fflush(f);
-
- if (ferror(f)) {
- log_error("Failed to write coredump: %m");
- r = -errno;
- }
-
-finish:
- fclose(f);
- return r;
-}
-
-int main(int argc, char* argv[]) {
- int r, j = 0;
- char *p = NULL;
- ssize_t n;
- pid_t pid;
- uid_t uid;
- gid_t gid;
- struct iovec iovec[14];
- char *core_pid = NULL, *core_uid = NULL, *core_gid = NULL, *core_signal = NULL,
- *core_timestamp = NULL, *core_comm = NULL, *core_exe = NULL, *core_unit = NULL,
- *core_session = NULL, *core_message = NULL, *core_cmdline = NULL, *t;
-
- prctl(PR_SET_DUMPABLE, 0);
-
- if (argc != _ARG_MAX) {
- log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
- log_open();
-
- log_error("Invalid number of arguments passed from kernel.");
- r = -EINVAL;
- goto finish;
- }
-
- r = parse_pid(argv[ARG_PID], &pid);
- if (r < 0) {
- log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
- log_open();
-
- log_error("Failed to parse PID.");
- goto finish;
- }
-
- if (cg_pid_get_unit(pid, &t) >= 0) {
-
- if (streq(t, SPECIAL_JOURNALD_SERVICE)) {
- /* Make sure we don't make use of the journal,
- * if it's the journal which is crashing */
- log_set_target(LOG_TARGET_KMSG);
- log_open();
-
- r = divert_coredump();
- goto finish;
- }
-
- core_unit = strappend("COREDUMP_UNIT=", t);
- free(t);
-
- if (core_unit)
- IOVEC_SET_STRING(iovec[j++], core_unit);
- }
-
- /* OK, now we know it's not the journal, hence make use of
- * it */
- log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
- log_open();
-
- r = parse_uid(argv[ARG_UID], &uid);
- if (r < 0) {
- log_error("Failed to parse UID.");
- goto finish;
- }
-
- r = parse_gid(argv[ARG_GID], &gid);
- if (r < 0) {
- log_error("Failed to parse GID.");
- goto finish;
- }
-
- core_pid = strappend("COREDUMP_PID=", argv[ARG_PID]);
- if (core_pid)
- IOVEC_SET_STRING(iovec[j++], core_pid);
-
- core_uid = strappend("COREDUMP_UID=", argv[ARG_UID]);
- if (core_uid)
- IOVEC_SET_STRING(iovec[j++], core_uid);
-
- core_gid = strappend("COREDUMP_GID=", argv[ARG_GID]);
- if (core_gid)
- IOVEC_SET_STRING(iovec[j++], core_gid);
-
- core_signal = strappend("COREDUMP_SIGNAL=", argv[ARG_SIGNAL]);
- if (core_signal)
- IOVEC_SET_STRING(iovec[j++], core_signal);
-
- core_comm = strappend("COREDUMP_COMM=", argv[ARG_COMM]);
- if (core_comm)
- IOVEC_SET_STRING(iovec[j++], core_comm);
-
-#ifdef HAVE_LOGIND
- if (sd_pid_get_session(pid, &t) >= 0) {
- core_session = strappend("COREDUMP_SESSION=", t);
- free(t);
-
- if (core_session)
- IOVEC_SET_STRING(iovec[j++], core_session);
- }
-
-#endif
-
- if (get_process_exe(pid, &t) >= 0) {
- core_exe = strappend("COREDUMP_EXE=", t);
- free(t);
-
- if (core_exe)
- IOVEC_SET_STRING(iovec[j++], core_exe);
- }
-
- if (get_process_cmdline(pid, LINE_MAX, false, &t) >= 0) {
- core_cmdline = strappend("COREDUMP_CMDLINE=", t);
- free(t);
-
- if (core_cmdline)
- IOVEC_SET_STRING(iovec[j++], core_cmdline);
- }
-
- core_timestamp = strjoin("COREDUMP_TIMESTAMP=", argv[ARG_TIMESTAMP], "000000", NULL);
- if (core_timestamp)
- IOVEC_SET_STRING(iovec[j++], core_timestamp);
-
- IOVEC_SET_STRING(iovec[j++], "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1");
- IOVEC_SET_STRING(iovec[j++], "PRIORITY=2");
-
- core_message = strjoin("MESSAGE=Process ", argv[ARG_PID], " (", argv[ARG_COMM], ") dumped core.", NULL);
- if (core_message)
- IOVEC_SET_STRING(iovec[j++], core_message);
-
- /* Now, let's drop privileges to become the user who owns the
- * segfaulted process and allocate the coredump memory under
- * his uid. This also ensures that the credentials journald
- * will see are the ones of the coredumping user, thus making
- * sure the user himself gets access to the core dump. */
-
- if (setresgid(gid, gid, gid) < 0 ||
- setresuid(uid, uid, uid) < 0) {
- log_error("Failed to drop privileges: %m");
- r = -errno;
- goto finish;
- }
-
- p = malloc(9 + COREDUMP_MAX);
- if (!p) {
- r = log_oom();
- goto finish;
- }
-
- memcpy(p, "COREDUMP=", 9);
-
- n = loop_read(STDIN_FILENO, p + 9, COREDUMP_MAX, false);
- if (n < 0) {
- log_error("Failed to read core dump data: %s", strerror(-n));
- r = (int) n;
- goto finish;
- }
-
- iovec[j].iov_base = p;
- iovec[j].iov_len = 9 + n;
- j++;
-
- r = sd_journal_sendv(iovec, j);
- if (r < 0)
- log_error("Failed to send coredump: %s", strerror(-r));
-
-finish:
- free(p);
- free(core_pid);
- free(core_uid);
- free(core_gid);
- free(core_signal);
- free(core_timestamp);
- free(core_comm);
- free(core_exe);
- free(core_cmdline);
- free(core_unit);
- free(core_session);
- free(core_message);
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/journal/coredumpctl.c b/src/journal/coredumpctl.c
deleted file mode 100644
index 4adc9236f1..0000000000
--- a/src/journal/coredumpctl.c
+++ /dev/null
@@ -1,583 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 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 <locale.h>
-#include <stdio.h>
-#include <string.h>
-#include <getopt.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <systemd/sd-journal.h>
-
-#include "build.h"
-#include "set.h"
-#include "util.h"
-#include "log.h"
-#include "path-util.h"
-#include "pager.h"
-
-static enum {
- ACTION_NONE,
- ACTION_LIST,
- ACTION_DUMP,
- ACTION_GDB,
-} arg_action = ACTION_LIST;
-
-static Set *matches = NULL;
-static FILE* output = NULL;
-static char* field = NULL;
-
-static int arg_no_pager = false;
-static int arg_no_legend = false;
-
-static Set *new_matches(void) {
- Set *set;
- char *tmp;
- int r;
-
- set = set_new(trivial_hash_func, trivial_compare_func);
- if (!set) {
- log_oom();
- return NULL;
- }
-
- tmp = strdup("MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1");
- if (!tmp) {
- log_oom();
- set_free(set);
- return NULL;
- }
-
- r = set_put(set, tmp);
- if (r < 0) {
- log_error("failed to add to set: %s", strerror(-r));
- free(tmp);
- set_free(set);
- return NULL;
- }
-
- return set;
-}
-
-static int help(void) {
- printf("%s [OPTIONS...] [MATCHES...]\n\n"
- "List or retrieve coredumps from the journal.\n\n"
- "Flags:\n"
- " -o --output=FILE Write output to FILE\n"
- " --no-pager Do not pipe output into a pager\n"
-
- "Commands:\n"
- " -h --help Show this help\n"
- " --version Print version string\n"
- " -F --field=FIELD List all values a certain field takes\n"
- " gdb Start gdb for the first matching coredump\n"
- " list List available coredumps\n"
- " dump PID Print coredump to stdout\n"
- " dump PATH Print coredump to stdout\n"
- , program_invocation_short_name);
-
- return 0;
-}
-
-static int add_match(Set *set, const char *match) {
- int r = -ENOMEM;
- unsigned pid;
- const char* prefix;
- char *pattern = NULL;
- char _cleanup_free_ *p = NULL;
-
- if (strchr(match, '='))
- prefix = "";
- else if (strchr(match, '/')) {
- p = path_make_absolute_cwd(match);
- if (!p)
- goto fail;
-
- match = p;
- prefix = "COREDUMP_EXE=";
- }
- else if (safe_atou(match, &pid) == 0)
- prefix = "COREDUMP_PID=";
- else
- prefix = "COREDUMP_COMM=";
-
- pattern = strjoin(prefix, match, NULL);
- if (!pattern)
- goto fail;
-
- r = set_put(set, pattern);
- if (r < 0) {
- log_error("failed to add pattern '%s': %s",
- pattern, strerror(-r));
- goto fail;
- }
- log_debug("Added pattern: %s", pattern);
-
- return 0;
-fail:
- free(pattern);
- log_error("failed to add match: %s", strerror(-r));
- return r;
-}
-
-static int parse_argv(int argc, char *argv[]) {
- enum {
- ARG_VERSION = 0x100,
- ARG_NO_PAGER,
- ARG_NO_LEGEND,
- };
-
- int r, c;
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version" , no_argument, NULL, ARG_VERSION },
- { "no-pager", no_argument, NULL, ARG_NO_PAGER },
- { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
- { "output", required_argument, NULL, 'o' },
- { "field", required_argument, NULL, 'F' },
- { NULL, 0, NULL, 0 }
- };
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "ho:F:", options, NULL)) >= 0)
- switch(c) {
- case 'h':
- help();
- arg_action = ACTION_NONE;
- return 0;
-
- case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(DISTRIBUTION);
- puts(SYSTEMD_FEATURES);
- arg_action = ACTION_NONE;
- return 0;
-
- case ARG_NO_PAGER:
- arg_no_pager = true;
- break;
-
- case ARG_NO_LEGEND:
- arg_no_legend = true;
- break;
-
- case 'o':
- if (output) {
- log_error("cannot set output more than once");
- return -EINVAL;
- }
-
- output = fopen(optarg, "we");
- if (!output) {
- log_error("writing to '%s': %m", optarg);
- return -errno;
- }
-
- break;
-
- case 'F':
- if (field) {
- log_error("cannot use --field/-F more than once");
- return -EINVAL;
- }
-
- field = optarg;
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- log_error("Unknown option code %c", c);
- return -EINVAL;
- }
-
- if (optind < argc) {
- const char *cmd = argv[optind++];
- if(streq(cmd, "list"))
- arg_action = ACTION_LIST;
- else if (streq(cmd, "dump"))
- arg_action = ACTION_DUMP;
- else if (streq(cmd, "gdb"))
- arg_action = ACTION_GDB;
- else {
- log_error("Unknown action '%s'", cmd);
- return -EINVAL;
- }
- }
-
- if (field && arg_action != ACTION_LIST) {
- log_error("Option --field/-F only makes sense with list");
- return -EINVAL;
- }
-
- while (optind < argc) {
- r = add_match(matches, argv[optind]);
- if (r != 0)
- return r;
- optind++;
- }
-
- return 0;
-}
-
-static int retrieve(const void *data,
- size_t len,
- const char *name,
- const char **var) {
-
- size_t ident;
-
- ident = strlen(name) + 1; /* name + "=" */
-
- if (len < ident)
- return 0;
-
- if (memcmp(data, name, ident - 1) != 0)
- return 0;
-
- if (((const char*) data)[ident - 1] != '=')
- return 0;
-
- *var = strndup((const char*)data + ident, len - ident);
- if (!var)
- return log_oom();
-
- return 0;
-}
-
-static void print_field(FILE* file, sd_journal *j) {
- const char _cleanup_free_ *value = NULL;
- const void *d;
- size_t l;
-
- assert(field);
-
- SD_JOURNAL_FOREACH_DATA(j, d, l)
- retrieve(d, l, field, &value);
- if (value)
- fprintf(file, "%s\n", value);
-}
-
-static int print_entry(FILE* file, sd_journal *j, int had_legend) {
- const char _cleanup_free_
- *pid = NULL, *uid = NULL, *gid = NULL,
- *sgnl = NULL, *exe = NULL;
- const void *d;
- size_t l;
- usec_t t;
- char buf[FORMAT_TIMESTAMP_MAX];
- int r;
-
- SD_JOURNAL_FOREACH_DATA(j, d, l) {
- retrieve(d, l, "COREDUMP_PID", &pid);
- retrieve(d, l, "COREDUMP_PID", &pid);
- retrieve(d, l, "COREDUMP_UID", &uid);
- retrieve(d, l, "COREDUMP_GID", &gid);
- retrieve(d, l, "COREDUMP_SIGNAL", &sgnl);
- retrieve(d, l, "COREDUMP_EXE", &exe);
- if (!exe)
- retrieve(d, l, "COREDUMP_COMM", &exe);
- if (!exe)
- retrieve(d, l, "COREDUMP_CMDLINE", &exe);
- }
-
- if (!pid && !uid && !gid && !sgnl && !exe) {
- log_warning("Empty coredump log entry");
- return -EINVAL;
- }
-
- r = sd_journal_get_realtime_usec(j, &t);
- if (r < 0) {
- log_error("Failed to get realtime timestamp: %s", strerror(-r));
- return r;
- }
-
- format_timestamp(buf, sizeof(buf), t);
-
- if (!had_legend && !arg_no_legend)
- fprintf(file, "%-*s %*s %*s %*s %*s %s\n",
- FORMAT_TIMESTAMP_MAX-1, "TIME",
- 6, "PID",
- 5, "UID",
- 5, "GID",
- 3, "SIG",
- "EXE");
-
- fprintf(file, "%*s %*s %*s %*s %*s %s\n",
- FORMAT_TIMESTAMP_MAX-1, buf,
- 6, pid,
- 5, uid,
- 5, gid,
- 3, sgnl,
- exe);
-
- return 0;
-}
-
-static int dump_list(sd_journal *j) {
- int found = 0;
-
- assert(j);
-
- SD_JOURNAL_FOREACH(j) {
- if (field)
- print_field(stdout, j);
- else
- print_entry(stdout, j, found++);
- }
-
- if (!field && !found) {
- log_notice("No coredumps found");
- return -ESRCH;
- }
-
- return 0;
-}
-
-static int focus(sd_journal *j) {
- int r;
-
- r = sd_journal_seek_tail(j);
- if (r == 0)
- r = sd_journal_previous(j);
- if (r < 0) {
- log_error("Failed to search journal: %s", strerror(-r));
- return r;
- }
- if (r == 0) {
- log_error("No match found");
- return -ESRCH;
- }
- return r;
-}
-
-static int dump_core(sd_journal* j) {
- const void *data;
- size_t len, ret;
- int r;
-
- assert(j);
-
- r = focus(j);
- if (r < 0)
- return r;
-
- print_entry(output ? stdout : stderr, j, false);
-
- if (on_tty() && !output) {
- log_error("Refusing to dump core to tty");
- return -ENOTTY;
- }
-
- r = sd_journal_get_data(j, "COREDUMP", (const void**) &data, &len);
- if (r < 0) {
- log_error("Failed to retrieve COREDUMP field: %s", strerror(-r));
- return r;
- }
-
- assert(len >= 9);
- data = (const uint8_t*) data + 9;
- len -= 9;
-
- ret = fwrite(data, len, 1, output ? output : stdout);
- if (ret != 1) {
- log_error("dumping coredump: %m (%zu)", ret);
- return -errno;
- }
-
- r = sd_journal_previous(j);
- if (r >= 0)
- log_warning("More than one entry matches, ignoring rest.\n");
-
- return 0;
-}
-
-static int run_gdb(sd_journal *j) {
- char path[] = "/var/tmp/coredump-XXXXXX";
- const void *data;
- size_t len;
- ssize_t sz;
- pid_t pid;
- _cleanup_free_ char *exe = NULL;
- int r;
- _cleanup_close_ int fd = -1;
- siginfo_t st;
-
- assert(j);
-
- r = focus(j);
- if (r < 0)
- return r;
-
- print_entry(stdout, j, false);
-
- r = sd_journal_get_data(j, "COREDUMP_EXE", (const void**) &data, &len);
- if (r < 0) {
- log_error("Failed to retrieve COREDUMP_EXE field: %s", strerror(-r));
- return r;
- }
-
- assert(len >= 13);
- data = (const uint8_t*) data + 13;
- len -= 13;
-
- exe = strndup(data, len);
- if (!exe)
- return log_oom();
-
- if (endswith(exe, " (deleted)")) {
- log_error("Binary already deleted.");
- return -ENOENT;
- }
-
- r = sd_journal_get_data(j, "COREDUMP", (const void**) &data, &len);
- if (r < 0) {
- log_error("Failed to retrieve COREDUMP field: %s", strerror(-r));
- return r;
- }
-
- assert(len >= 9);
- data = (const uint8_t*) data + 9;
- len -= 9;
-
- fd = mkostemp(path, O_WRONLY);
- if (fd < 0) {
- log_error("Failed to create temporary file: %m");
- return -errno;
- }
-
- sz = write(fd, data, len);
- if (sz < 0) {
- log_error("Failed to write temporary file: %s", strerror(errno));
- r = -errno;
- goto finish;
- }
- if (sz != (ssize_t) len) {
- log_error("Short write to temporary file.");
- r = -EIO;
- goto finish;
- }
-
- close_nointr_nofail(fd);
- fd = -1;
-
- pid = fork();
- if (pid < 0) {
- log_error("Failed to fork(): %m");
- r = -errno;
- goto finish;
- }
- if (pid == 0) {
- execlp("gdb", "gdb", exe, path, NULL);
- log_error("Failed to invoke gdb: %m");
- _exit(1);
- }
-
- r = wait_for_terminate(pid, &st);
- if (r < 0) {
- log_error("Failed to wait for gdb: %m");
- goto finish;
- }
-
- r = st.si_code == CLD_EXITED ? st.si_status : 255;
-
-finish:
- unlink(path);
- return r;
-}
-
-int main(int argc, char *argv[]) {
- sd_journal *j = NULL;
- const char* match;
- Iterator it;
- int r = 0;
-
- setlocale(LC_ALL, "");
- log_parse_environment();
- log_open();
-
- matches = new_matches();
- if (!matches) {
- r = -ENOMEM;
- goto end;
- }
-
- r = parse_argv(argc, argv);
- if (r < 0)
- goto end;
-
- if (arg_action == ACTION_NONE)
- goto end;
-
- r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
- if (r < 0) {
- log_error("Failed to open journal: %s", strerror(-r));
- goto end;
- }
-
- SET_FOREACH(match, matches, it) {
- r = sd_journal_add_match(j, match, strlen(match));
- if (r != 0) {
- log_error("Failed to add match '%s': %s",
- match, strerror(-r));
- goto end;
- }
- }
-
- switch(arg_action) {
-
- case ACTION_LIST:
- if (!arg_no_pager)
- pager_open();
-
- r = dump_list(j);
- break;
-
- case ACTION_DUMP:
- r = dump_core(j);
- break;
-
- case ACTION_GDB:
- r = run_gdb(j);
- break;
-
- default:
- assert_not_reached("Shouldn't be here");
- }
-
-end:
- if (j)
- sd_journal_close(j);
-
- set_free_free(matches);
-
- pager_close();
-
- if (output)
- fclose(output);
-
- return r >= 0 ? r : EXIT_FAILURE;
-}
diff --git a/src/journal/fsprg.c b/src/journal/fsprg.c
deleted file mode 100644
index 2190b7c796..0000000000
--- a/src/journal/fsprg.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/*
- * fsprg v0.1 - (seekable) forward-secure pseudorandom generator
- * Copyright (C) 2012 B. Poettering
- * Contact: fsprg@point-at-infinity.org
- *
- * This library 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.
- *
- * This library 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 this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <gcrypt.h>
-#include <string.h>
-#include <assert.h>
-
-#include "fsprg.h"
-
-#define ISVALID_SECPAR(secpar) (((secpar) % 16 == 0) && ((secpar) >= 16) && ((secpar) <= 16384))
-#define VALIDATE_SECPAR(secpar) assert(ISVALID_SECPAR(secpar));
-
-#define RND_HASH GCRY_MD_SHA256
-#define RND_GEN_P 0x01
-#define RND_GEN_Q 0x02
-#define RND_GEN_X 0x03
-
-/******************************************************************************/
-
-static void mpi_export(void *buf, size_t buflen, const gcry_mpi_t x) {
- unsigned len;
- size_t nwritten;
-
- assert(gcry_mpi_cmp_ui(x, 0) >= 0);
- len = (gcry_mpi_get_nbits(x) + 7) / 8;
- assert(len <= buflen);
- memset(buf, 0, buflen);
- gcry_mpi_print(GCRYMPI_FMT_USG, buf + (buflen - len), len, &nwritten, x);
- assert(nwritten == len);
-}
-
-static gcry_mpi_t mpi_import(const void *buf, size_t buflen) {
- gcry_mpi_t h;
- unsigned len;
-
- gcry_mpi_scan(&h, GCRYMPI_FMT_USG, buf, buflen, NULL);
- len = (gcry_mpi_get_nbits(h) + 7) / 8;
- assert(len <= buflen);
- assert(gcry_mpi_cmp_ui(h, 0) >= 0);
-
- return h;
-}
-
-static void uint64_export(void *buf, size_t buflen, uint64_t x) {
- assert(buflen == 8);
- ((uint8_t*) buf)[0] = (x >> 56) & 0xff;
- ((uint8_t*) buf)[1] = (x >> 48) & 0xff;
- ((uint8_t*) buf)[2] = (x >> 40) & 0xff;
- ((uint8_t*) buf)[3] = (x >> 32) & 0xff;
- ((uint8_t*) buf)[4] = (x >> 24) & 0xff;
- ((uint8_t*) buf)[5] = (x >> 16) & 0xff;
- ((uint8_t*) buf)[6] = (x >> 8) & 0xff;
- ((uint8_t*) buf)[7] = (x >> 0) & 0xff;
-}
-
-static uint64_t uint64_import(const void *buf, size_t buflen) {
- assert(buflen == 8);
- return
- (uint64_t)(((uint8_t*) buf)[0]) << 56 |
- (uint64_t)(((uint8_t*) buf)[1]) << 48 |
- (uint64_t)(((uint8_t*) buf)[2]) << 40 |
- (uint64_t)(((uint8_t*) buf)[3]) << 32 |
- (uint64_t)(((uint8_t*) buf)[4]) << 24 |
- (uint64_t)(((uint8_t*) buf)[5]) << 16 |
- (uint64_t)(((uint8_t*) buf)[6]) << 8 |
- (uint64_t)(((uint8_t*) buf)[7]) << 0;
-}
-
-/* deterministically generate from seed/idx a string of buflen pseudorandom bytes */
-static void det_randomize(void *buf, size_t buflen, const void *seed, size_t seedlen, uint32_t idx) {
- gcry_md_hd_t hd, hd2;
- size_t olen, cpylen;
- uint32_t ctr;
-
- olen = gcry_md_get_algo_dlen(RND_HASH);
- gcry_md_open(&hd, RND_HASH, 0);
- gcry_md_write(hd, seed, seedlen);
- gcry_md_putc(hd, (idx >> 24) & 0xff);
- gcry_md_putc(hd, (idx >> 16) & 0xff);
- gcry_md_putc(hd, (idx >> 8) & 0xff);
- gcry_md_putc(hd, (idx >> 0) & 0xff);
-
- for (ctr = 0; buflen; ctr++) {
- gcry_md_copy(&hd2, hd);
- gcry_md_putc(hd2, (ctr >> 24) & 0xff);
- gcry_md_putc(hd2, (ctr >> 16) & 0xff);
- gcry_md_putc(hd2, (ctr >> 8) & 0xff);
- gcry_md_putc(hd2, (ctr >> 0) & 0xff);
- gcry_md_final(hd2);
- cpylen = (buflen < olen) ? buflen : olen;
- memcpy(buf, gcry_md_read(hd2, RND_HASH), cpylen);
- gcry_md_close(hd2);
- buf += cpylen;
- buflen -= cpylen;
- }
- gcry_md_close(hd);
-}
-
-/* deterministically generate from seed/idx a prime of length `bits' that is 3 (mod 4) */
-static gcry_mpi_t genprime3mod4(int bits, const void *seed, size_t seedlen, uint32_t idx) {
- size_t buflen = bits / 8;
- uint8_t buf[buflen];
- gcry_mpi_t p;
-
- assert(bits % 8 == 0);
- assert(buflen > 0);
-
- det_randomize(buf, buflen, seed, seedlen, idx);
- buf[0] |= 0xc0; /* set upper two bits, so that n=pq has maximum size */
- buf[buflen - 1] |= 0x03; /* set lower two bits, to have result 3 (mod 4) */
-
- p = mpi_import(buf, buflen);
- while (gcry_prime_check(p, 0))
- gcry_mpi_add_ui(p, p, 4);
-
- return p;
-}
-
-/* deterministically generate from seed/idx a quadratic residue (mod n) */
-static gcry_mpi_t gensquare(const gcry_mpi_t n, const void *seed, size_t seedlen, uint32_t idx, unsigned secpar) {
- size_t buflen = secpar / 8;
- uint8_t buf[buflen];
- gcry_mpi_t x;
-
- det_randomize(buf, buflen, seed, seedlen, idx);
- buf[0] &= 0x7f; /* clear upper bit, so that we have x < n */
- x = mpi_import(buf, buflen);
- assert(gcry_mpi_cmp(x, n) < 0);
- gcry_mpi_mulm(x, x, x, n);
- return x;
-}
-
-/* compute 2^m (mod phi(p)), for a prime p */
-static gcry_mpi_t twopowmodphi(uint64_t m, const gcry_mpi_t p) {
- gcry_mpi_t phi, r;
- int n;
-
- phi = gcry_mpi_new(0);
- gcry_mpi_sub_ui(phi, p, 1);
-
- /* count number of used bits in m */
- for (n = 0; (1ULL << n) <= m; n++)
- ;
-
- r = gcry_mpi_new(0);
- gcry_mpi_set_ui(r, 1);
- while (n) { /* square and multiply algorithm for fast exponentiation */
- n--;
- gcry_mpi_mulm(r, r, r, phi);
- if (m & ((uint64_t)1 << n)) {
- gcry_mpi_add(r, r, r);
- if (gcry_mpi_cmp(r, phi) >= 0)
- gcry_mpi_sub(r, r, phi);
- }
- }
-
- gcry_mpi_release(phi);
- return r;
-}
-
-/* Decompose $x \in Z_n$ into $(xp,xq) \in Z_p \times Z_q$ using Chinese Remainder Theorem */
-static void CRT_decompose(gcry_mpi_t *xp, gcry_mpi_t *xq, const gcry_mpi_t x, const gcry_mpi_t p, const gcry_mpi_t q) {
- *xp = gcry_mpi_new(0);
- *xq = gcry_mpi_new(0);
- gcry_mpi_mod(*xp, x, p);
- gcry_mpi_mod(*xq, x, q);
-}
-
-/* Compose $(xp,xq) \in Z_p \times Z_q$ into $x \in Z_n$ using Chinese Remainder Theorem */
-static void CRT_compose(gcry_mpi_t *x, const gcry_mpi_t xp, const gcry_mpi_t xq, const gcry_mpi_t p, const gcry_mpi_t q) {
- gcry_mpi_t a, u;
-
- a = gcry_mpi_new(0);
- u = gcry_mpi_new(0);
- *x = gcry_mpi_new(0);
- gcry_mpi_subm(a, xq, xp, q);
- gcry_mpi_invm(u, p, q);
- gcry_mpi_mulm(a, a, u, q); /* a = (xq - xp) / p (mod q) */
- gcry_mpi_mul(*x, p, a);
- gcry_mpi_add(*x, *x, xp); /* x = p * ((xq - xp) / p mod q) + xp */
- gcry_mpi_release(a);
- gcry_mpi_release(u);
-}
-
-static void initialize_libgcrypt(void) {
- const char *p;
- if (gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P))
- return;
-
- p = gcry_check_version("1.4.5");
- assert(p);
-
- /* Turn off "secmem". Clients which whish to make use of this
- * feature should initialize the library manually */
- gcry_control(GCRYCTL_DISABLE_SECMEM);
- gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
-}
-
-/******************************************************************************/
-
-size_t FSPRG_mskinbytes(unsigned _secpar) {
- VALIDATE_SECPAR(_secpar);
- return 2 + 2 * (_secpar / 2) / 8; /* to store header,p,q */
-}
-
-size_t FSPRG_mpkinbytes(unsigned _secpar) {
- VALIDATE_SECPAR(_secpar);
- return 2 + _secpar / 8; /* to store header,n */
-}
-
-size_t FSPRG_stateinbytes(unsigned _secpar) {
- VALIDATE_SECPAR(_secpar);
- return 2 + 2 * _secpar / 8 + 8; /* to store header,n,x,epoch */
-}
-
-static void store_secpar(void *buf, uint16_t secpar) {
- secpar = secpar / 16 - 1;
- ((uint8_t*) buf)[0] = (secpar >> 8) & 0xff;
- ((uint8_t*) buf)[1] = (secpar >> 0) & 0xff;
-}
-
-static uint16_t read_secpar(const void *buf) {
- uint16_t secpar;
- secpar =
- (uint16_t)(((uint8_t*) buf)[0]) << 8 |
- (uint16_t)(((uint8_t*) buf)[1]) << 0;
- return 16 * (secpar + 1);
-}
-
-void FSPRG_GenMK(void *msk, void *mpk, const void *seed, size_t seedlen, unsigned _secpar) {
- uint8_t iseed[FSPRG_RECOMMENDED_SEEDLEN];
- gcry_mpi_t n, p, q;
- uint16_t secpar;
-
- VALIDATE_SECPAR(_secpar);
- secpar = _secpar;
-
- initialize_libgcrypt();
-
- if (!seed) {
- gcry_randomize(iseed, FSPRG_RECOMMENDED_SEEDLEN, GCRY_STRONG_RANDOM);
- seed = iseed;
- seedlen = FSPRG_RECOMMENDED_SEEDLEN;
- }
-
- p = genprime3mod4(secpar / 2, seed, seedlen, RND_GEN_P);
- q = genprime3mod4(secpar / 2, seed, seedlen, RND_GEN_Q);
-
- if (msk) {
- store_secpar(msk + 0, secpar);
- mpi_export(msk + 2 + 0 * (secpar / 2) / 8, (secpar / 2) / 8, p);
- mpi_export(msk + 2 + 1 * (secpar / 2) / 8, (secpar / 2) / 8, q);
- }
-
- if (mpk) {
- n = gcry_mpi_new(0);
- gcry_mpi_mul(n, p, q);
- assert(gcry_mpi_get_nbits(n) == secpar);
-
- store_secpar(mpk + 0, secpar);
- mpi_export(mpk + 2, secpar / 8, n);
-
- gcry_mpi_release(n);
- }
-
- gcry_mpi_release(p);
- gcry_mpi_release(q);
-}
-
-void FSPRG_GenState0(void *state, const void *mpk, const void *seed, size_t seedlen) {
- gcry_mpi_t n, x;
- uint16_t secpar;
-
- initialize_libgcrypt();
-
- secpar = read_secpar(mpk + 0);
- n = mpi_import(mpk + 2, secpar / 8);
- x = gensquare(n, seed, seedlen, RND_GEN_X, secpar);
-
- memcpy(state, mpk, 2 + secpar / 8);
- mpi_export(state + 2 + 1 * secpar / 8, secpar / 8, x);
- memset(state + 2 + 2 * secpar / 8, 0, 8);
-
- gcry_mpi_release(n);
- gcry_mpi_release(x);
-}
-
-void FSPRG_Evolve(void *state) {
- gcry_mpi_t n, x;
- uint16_t secpar;
- uint64_t epoch;
-
- initialize_libgcrypt();
-
- secpar = read_secpar(state + 0);
- n = mpi_import(state + 2 + 0 * secpar / 8, secpar / 8);
- x = mpi_import(state + 2 + 1 * secpar / 8, secpar / 8);
- epoch = uint64_import(state + 2 + 2 * secpar / 8, 8);
-
- gcry_mpi_mulm(x, x, x, n);
- epoch++;
-
- mpi_export(state + 2 + 1 * secpar / 8, secpar / 8, x);
- uint64_export(state + 2 + 2 * secpar / 8, 8, epoch);
-
- gcry_mpi_release(n);
- gcry_mpi_release(x);
-}
-
-uint64_t FSPRG_GetEpoch(const void *state) {
- uint16_t secpar;
- secpar = read_secpar(state + 0);
- return uint64_import(state + 2 + 2 * secpar / 8, 8);
-}
-
-void FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed, size_t seedlen) {
- gcry_mpi_t p, q, n, x, xp, xq, kp, kq, xm;
- uint16_t secpar;
-
- initialize_libgcrypt();
-
- secpar = read_secpar(msk + 0);
- p = mpi_import(msk + 2 + 0 * (secpar / 2) / 8, (secpar / 2) / 8);
- q = mpi_import(msk + 2 + 1 * (secpar / 2) / 8, (secpar / 2) / 8);
-
- n = gcry_mpi_new(0);
- gcry_mpi_mul(n, p, q);
-
- x = gensquare(n, seed, seedlen, RND_GEN_X, secpar);
- CRT_decompose(&xp, &xq, x, p, q); /* split (mod n) into (mod p) and (mod q) using CRT */
-
- kp = twopowmodphi(epoch, p); /* compute 2^epoch (mod phi(p)) */
- kq = twopowmodphi(epoch, q); /* compute 2^epoch (mod phi(q)) */
-
- gcry_mpi_powm(xp, xp, kp, p); /* compute x^(2^epoch) (mod p) */
- gcry_mpi_powm(xq, xq, kq, q); /* compute x^(2^epoch) (mod q) */
-
- CRT_compose(&xm, xp, xq, p, q); /* combine (mod p) and (mod q) to (mod n) using CRT */
-
- store_secpar(state + 0, secpar);
- mpi_export(state + 2 + 0 * secpar / 8, secpar / 8, n);
- mpi_export(state + 2 + 1 * secpar / 8, secpar / 8, xm);
- uint64_export(state + 2 + 2 * secpar / 8, 8, epoch);
-
- gcry_mpi_release(p);
- gcry_mpi_release(q);
- gcry_mpi_release(n);
- gcry_mpi_release(x);
- gcry_mpi_release(xp);
- gcry_mpi_release(xq);
- gcry_mpi_release(kp);
- gcry_mpi_release(kq);
- gcry_mpi_release(xm);
-}
-
-void FSPRG_GetKey(const void *state, void *key, size_t keylen, uint32_t idx) {
- uint16_t secpar;
-
- initialize_libgcrypt();
-
- secpar = read_secpar(state + 0);
- det_randomize(key, keylen, state + 2, 2 * secpar / 8 + 8, idx);
-}
diff --git a/src/journal/fsprg.h b/src/journal/fsprg.h
deleted file mode 100644
index 306ef18d73..0000000000
--- a/src/journal/fsprg.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef __fsprgh__
-#define __fsprgh__
-
-/*
- * fsprg v0.1 - (seekable) forward-secure pseudorandom generator
- * Copyright (C) 2012 B. Poettering
- * Contact: fsprg@point-at-infinity.org
- *
- * This library 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.
- *
- * This library 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 this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <sys/types.h>
-#include <inttypes.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define FSPRG_RECOMMENDED_SECPAR 1536
-#define FSPRG_RECOMMENDED_SEEDLEN (96/8)
-
-size_t FSPRG_mskinbytes(unsigned secpar);
-size_t FSPRG_mpkinbytes(unsigned secpar);
-size_t FSPRG_stateinbytes(unsigned secpar);
-
-/* Setup msk and mpk. Providing seed != NULL makes this algorithm deterministic. */
-void FSPRG_GenMK(void *msk, void *mpk, const void *seed, size_t seedlen, unsigned secpar);
-
-/* Initialize state deterministically in dependence on seed. */
-/* Note: in case one wants to run only one GenState0 per GenMK it is safe to use
- the same seed for both GenMK and GenState0.
-*/
-void FSPRG_GenState0(void *state, const void *mpk, const void *seed, size_t seedlen);
-
-void FSPRG_Evolve(void *state);
-
-uint64_t FSPRG_GetEpoch(const void *state);
-
-/* Seek to any arbitrary state (by providing msk together with seed from GenState0). */
-void FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed, size_t seedlen);
-
-void FSPRG_GetKey(const void *state, void *key, size_t keylen, uint32_t idx);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/journal/journal-authenticate.c b/src/journal/journal-authenticate.c
deleted file mode 100644
index 64bf96874e..0000000000
--- a/src/journal/journal-authenticate.c
+++ /dev/null
@@ -1,563 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <fcntl.h>
-#include <sys/mman.h>
-
-#include "journal-def.h"
-#include "journal-file.h"
-#include "journal-authenticate.h"
-#include "fsprg.h"
-
-static uint64_t journal_file_tag_seqnum(JournalFile *f) {
- uint64_t r;
-
- assert(f);
-
- r = le64toh(f->header->n_tags) + 1;
- f->header->n_tags = htole64(r);
-
- return r;
-}
-
-int journal_file_append_tag(JournalFile *f) {
- Object *o;
- uint64_t p;
- int r;
-
- assert(f);
-
- if (!f->seal)
- return 0;
-
- if (!f->hmac_running)
- return 0;
-
- assert(f->hmac);
-
- r = journal_file_append_object(f, OBJECT_TAG, sizeof(struct TagObject), &o, &p);
- if (r < 0)
- return r;
-
- o->tag.seqnum = htole64(journal_file_tag_seqnum(f));
- o->tag.epoch = htole64(FSPRG_GetEpoch(f->fsprg_state));
-
- log_debug("Writing tag %llu for epoch %llu\n",
- (unsigned long long) le64toh(o->tag.seqnum),
- (unsigned long long) FSPRG_GetEpoch(f->fsprg_state));
-
- /* Add the tag object itself, so that we can protect its
- * header. This will exclude the actual hash value in it */
- r = journal_file_hmac_put_object(f, OBJECT_TAG, o, p);
- if (r < 0)
- return r;
-
- /* Get the HMAC tag and store it in the object */
- memcpy(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH);
- f->hmac_running = false;
-
- return 0;
-}
-
-int journal_file_hmac_start(JournalFile *f) {
- uint8_t key[256 / 8]; /* Let's pass 256 bit from FSPRG to HMAC */
- assert(f);
-
- if (!f->seal)
- return 0;
-
- if (f->hmac_running)
- return 0;
-
- /* Prepare HMAC for next cycle */
- gcry_md_reset(f->hmac);
- FSPRG_GetKey(f->fsprg_state, key, sizeof(key), 0);
- gcry_md_setkey(f->hmac, key, sizeof(key));
-
- f->hmac_running = true;
-
- return 0;
-}
-
-static int journal_file_get_epoch(JournalFile *f, uint64_t realtime, uint64_t *epoch) {
- uint64_t t;
-
- assert(f);
- assert(epoch);
- assert(f->seal);
-
- if (f->fss_start_usec == 0 ||
- f->fss_interval_usec == 0)
- return -ENOTSUP;
-
- if (realtime < f->fss_start_usec)
- return -ESTALE;
-
- t = realtime - f->fss_start_usec;
- t = t / f->fss_interval_usec;
-
- *epoch = t;
- return 0;
-}
-
-static int journal_file_fsprg_need_evolve(JournalFile *f, uint64_t realtime) {
- uint64_t goal, epoch;
- int r;
- assert(f);
-
- if (!f->seal)
- return 0;
-
- r = journal_file_get_epoch(f, realtime, &goal);
- if (r < 0)
- return r;
-
- epoch = FSPRG_GetEpoch(f->fsprg_state);
- if (epoch > goal)
- return -ESTALE;
-
- return epoch != goal;
-}
-
-int journal_file_fsprg_evolve(JournalFile *f, uint64_t realtime) {
- uint64_t goal, epoch;
- int r;
-
- assert(f);
-
- if (!f->seal)
- return 0;
-
- r = journal_file_get_epoch(f, realtime, &goal);
- if (r < 0)
- return r;
-
- epoch = FSPRG_GetEpoch(f->fsprg_state);
- if (epoch < goal)
- log_debug("Evolving FSPRG key from epoch %llu to %llu.", (unsigned long long) epoch, (unsigned long long) goal);
-
- for (;;) {
- if (epoch > goal)
- return -ESTALE;
- if (epoch == goal)
- return 0;
-
- FSPRG_Evolve(f->fsprg_state);
- epoch = FSPRG_GetEpoch(f->fsprg_state);
- }
-}
-
-int journal_file_fsprg_seek(JournalFile *f, uint64_t goal) {
- void *msk;
- uint64_t epoch;
-
- assert(f);
-
- if (!f->seal)
- return 0;
-
- assert(f->fsprg_seed);
-
- if (f->fsprg_state) {
- /* Cheaper... */
-
- epoch = FSPRG_GetEpoch(f->fsprg_state);
- if (goal == epoch)
- return 0;
-
- if (goal == epoch+1) {
- FSPRG_Evolve(f->fsprg_state);
- return 0;
- }
- } else {
- f->fsprg_state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
- f->fsprg_state = malloc(f->fsprg_state_size);
-
- if (!f->fsprg_state)
- return -ENOMEM;
- }
-
- log_debug("Seeking FSPRG key to %llu.", (unsigned long long) goal);
-
- msk = alloca(FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR));
- FSPRG_GenMK(msk, NULL, f->fsprg_seed, f->fsprg_seed_size, FSPRG_RECOMMENDED_SECPAR);
- FSPRG_Seek(f->fsprg_state, goal, msk, f->fsprg_seed, f->fsprg_seed_size);
- return 0;
-}
-
-int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime) {
- int r;
-
- assert(f);
-
- if (!f->seal)
- return 0;
-
- if (realtime <= 0)
- realtime = now(CLOCK_REALTIME);
-
- r = journal_file_fsprg_need_evolve(f, realtime);
- if (r <= 0)
- return 0;
-
- r = journal_file_append_tag(f);
- if (r < 0)
- return r;
-
- r = journal_file_fsprg_evolve(f, realtime);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-int journal_file_hmac_put_object(JournalFile *f, int type, Object *o, uint64_t p) {
- int r;
-
- assert(f);
-
- if (!f->seal)
- return 0;
-
- r = journal_file_hmac_start(f);
- if (r < 0)
- return r;
-
- if (!o) {
- r = journal_file_move_to_object(f, type, p, &o);
- if (r < 0)
- return r;
- } else {
- if (type >= 0 && o->object.type != type)
- return -EBADMSG;
- }
-
- gcry_md_write(f->hmac, o, offsetof(ObjectHeader, payload));
-
- switch (o->object.type) {
-
- case OBJECT_DATA:
- /* All but hash and payload are mutable */
- gcry_md_write(f->hmac, &o->data.hash, sizeof(o->data.hash));
- gcry_md_write(f->hmac, o->data.payload, le64toh(o->object.size) - offsetof(DataObject, payload));
- break;
-
- case OBJECT_FIELD:
- /* Same here */
- gcry_md_write(f->hmac, &o->field.hash, sizeof(o->field.hash));
- gcry_md_write(f->hmac, o->field.payload, le64toh(o->object.size) - offsetof(FieldObject, payload));
- break;
-
- case OBJECT_ENTRY:
- /* All */
- gcry_md_write(f->hmac, &o->entry.seqnum, le64toh(o->object.size) - offsetof(EntryObject, seqnum));
- break;
-
- case OBJECT_FIELD_HASH_TABLE:
- case OBJECT_DATA_HASH_TABLE:
- case OBJECT_ENTRY_ARRAY:
- /* Nothing: everything is mutable */
- break;
-
- case OBJECT_TAG:
- /* All but the tag itself */
- gcry_md_write(f->hmac, &o->tag.seqnum, sizeof(o->tag.seqnum));
- gcry_md_write(f->hmac, &o->tag.epoch, sizeof(o->tag.epoch));
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-int journal_file_hmac_put_header(JournalFile *f) {
- int r;
-
- assert(f);
-
- if (!f->seal)
- return 0;
-
- r = journal_file_hmac_start(f);
- if (r < 0)
- return r;
-
- /* All but state+reserved, boot_id, arena_size,
- * tail_object_offset, n_objects, n_entries,
- * tail_entry_seqnum, head_entry_seqnum, entry_array_offset,
- * head_entry_realtime, tail_entry_realtime,
- * tail_entry_monotonic, n_data, n_fields, n_tags,
- * n_entry_arrays. */
-
- gcry_md_write(f->hmac, f->header->signature, offsetof(Header, state) - offsetof(Header, signature));
- gcry_md_write(f->hmac, &f->header->file_id, offsetof(Header, boot_id) - offsetof(Header, file_id));
- gcry_md_write(f->hmac, &f->header->seqnum_id, offsetof(Header, arena_size) - offsetof(Header, seqnum_id));
- gcry_md_write(f->hmac, &f->header->data_hash_table_offset, offsetof(Header, tail_object_offset) - offsetof(Header, data_hash_table_offset));
-
- return 0;
-}
-
-int journal_file_fss_load(JournalFile *f) {
- int r, fd = -1;
- char *p = NULL;
- struct stat st;
- FSSHeader *m = NULL;
- sd_id128_t machine;
-
- assert(f);
-
- if (!f->seal)
- return 0;
-
- r = sd_id128_get_machine(&machine);
- if (r < 0)
- return r;
-
- if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
- SD_ID128_FORMAT_VAL(machine)) < 0)
- return -ENOMEM;
-
- fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY, 0600);
- if (fd < 0) {
- if (errno != ENOENT)
- log_error("Failed to open %s: %m", p);
-
- r = -errno;
- goto finish;
- }
-
- if (fstat(fd, &st) < 0) {
- r = -errno;
- goto finish;
- }
-
- if (st.st_size < (off_t) sizeof(FSSHeader)) {
- r = -ENODATA;
- goto finish;
- }
-
- m = mmap(NULL, PAGE_ALIGN(sizeof(FSSHeader)), PROT_READ, MAP_SHARED, fd, 0);
- if (m == MAP_FAILED) {
- m = NULL;
- r = -errno;
- goto finish;
- }
-
- if (memcmp(m->signature, FSS_HEADER_SIGNATURE, 8) != 0) {
- r = -EBADMSG;
- goto finish;
- }
-
- if (m->incompatible_flags != 0) {
- r = -EPROTONOSUPPORT;
- goto finish;
- }
-
- if (le64toh(m->header_size) < sizeof(FSSHeader)) {
- r = -EBADMSG;
- goto finish;
- }
-
- if (le64toh(m->fsprg_state_size) != FSPRG_stateinbytes(le16toh(m->fsprg_secpar))) {
- r = -EBADMSG;
- goto finish;
- }
-
- f->fss_file_size = le64toh(m->header_size) + le64toh(m->fsprg_state_size);
- if ((uint64_t) st.st_size < f->fss_file_size) {
- r = -ENODATA;
- goto finish;
- }
-
- if (!sd_id128_equal(machine, m->machine_id)) {
- r = -EHOSTDOWN;
- goto finish;
- }
-
- if (le64toh(m->start_usec) <= 0 ||
- le64toh(m->interval_usec) <= 0) {
- r = -EBADMSG;
- goto finish;
- }
-
- f->fss_file = mmap(NULL, PAGE_ALIGN(f->fss_file_size), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
- if (f->fss_file == MAP_FAILED) {
- f->fss_file = NULL;
- r = -errno;
- goto finish;
- }
-
- f->fss_start_usec = le64toh(f->fss_file->start_usec);
- f->fss_interval_usec = le64toh(f->fss_file->interval_usec);
-
- f->fsprg_state = (uint8_t*) f->fss_file + le64toh(f->fss_file->header_size);
- f->fsprg_state_size = le64toh(f->fss_file->fsprg_state_size);
-
- r = 0;
-
-finish:
- if (m)
- munmap(m, PAGE_ALIGN(sizeof(FSSHeader)));
-
- if (fd >= 0)
- close_nointr_nofail(fd);
-
- free(p);
- return r;
-}
-
-static void initialize_libgcrypt(void) {
- const char *p;
-
- if (gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P))
- return;
-
- p = gcry_check_version("1.4.5");
- assert(p);
-
- gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
-}
-
-int journal_file_hmac_setup(JournalFile *f) {
- gcry_error_t e;
-
- if (!f->seal)
- return 0;
-
- initialize_libgcrypt();
-
- e = gcry_md_open(&f->hmac, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
- if (e != 0)
- return -ENOTSUP;
-
- return 0;
-}
-
-int journal_file_append_first_tag(JournalFile *f) {
- int r;
- uint64_t p;
-
- if (!f->seal)
- return 0;
-
- log_debug("Calculating first tag...");
-
- r = journal_file_hmac_put_header(f);
- if (r < 0)
- return r;
-
- p = le64toh(f->header->field_hash_table_offset);
- if (p < offsetof(Object, hash_table.items))
- return -EINVAL;
- p -= offsetof(Object, hash_table.items);
-
- r = journal_file_hmac_put_object(f, OBJECT_FIELD_HASH_TABLE, NULL, p);
- if (r < 0)
- return r;
-
- p = le64toh(f->header->data_hash_table_offset);
- if (p < offsetof(Object, hash_table.items))
- return -EINVAL;
- p -= offsetof(Object, hash_table.items);
-
- r = journal_file_hmac_put_object(f, OBJECT_DATA_HASH_TABLE, NULL, p);
- if (r < 0)
- return r;
-
- r = journal_file_append_tag(f);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-int journal_file_parse_verification_key(JournalFile *f, const char *key) {
- uint8_t *seed;
- size_t seed_size, c;
- const char *k;
- int r;
- unsigned long long start, interval;
-
- seed_size = FSPRG_RECOMMENDED_SEEDLEN;
- seed = malloc(seed_size);
- if (!seed)
- return -ENOMEM;
-
- k = key;
- for (c = 0; c < seed_size; c++) {
- int x, y;
-
- while (*k == '-')
- k++;
-
- x = unhexchar(*k);
- if (x < 0) {
- free(seed);
- return -EINVAL;
- }
- k++;
- y = unhexchar(*k);
- if (y < 0) {
- free(seed);
- return -EINVAL;
- }
- k++;
-
- seed[c] = (uint8_t) (x * 16 + y);
- }
-
- if (*k != '/') {
- free(seed);
- return -EINVAL;
- }
- k++;
-
- r = sscanf(k, "%llx-%llx", &start, &interval);
- if (r != 2) {
- free(seed);
- return -EINVAL;
- }
-
- f->fsprg_seed = seed;
- f->fsprg_seed_size = seed_size;
-
- f->fss_start_usec = start * interval;
- f->fss_interval_usec = interval;
-
- return 0;
-}
-
-bool journal_file_next_evolve_usec(JournalFile *f, usec_t *u) {
- uint64_t epoch;
-
- assert(f);
- assert(u);
-
- if (!f->seal)
- return false;
-
- epoch = FSPRG_GetEpoch(f->fsprg_state);
-
- *u = (usec_t) (f->fss_start_usec + f->fss_interval_usec * epoch + f->fss_interval_usec);
-
- return true;
-}
diff --git a/src/journal/journal-authenticate.h b/src/journal/journal-authenticate.h
deleted file mode 100644
index 0aaf836721..0000000000
--- a/src/journal/journal-authenticate.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdbool.h>
-#include <inttypes.h>
-
-#include "journal-file.h"
-
-int journal_file_append_tag(JournalFile *f);
-int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime);
-int journal_file_append_first_tag(JournalFile *f);
-
-int journal_file_hmac_setup(JournalFile *f);
-int journal_file_hmac_start(JournalFile *f);
-int journal_file_hmac_put_header(JournalFile *f);
-int journal_file_hmac_put_object(JournalFile *f, int type, Object *o, uint64_t p);
-
-int journal_file_fss_load(JournalFile *f);
-int journal_file_parse_verification_key(JournalFile *f, const char *key);
-
-int journal_file_fsprg_evolve(JournalFile *f, uint64_t realtime);
-int journal_file_fsprg_seek(JournalFile *f, uint64_t epoch);
-
-bool journal_file_next_evolve_usec(JournalFile *f, usec_t *u);
diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h
deleted file mode 100644
index ac5611c310..0000000000
--- a/src/journal/journal-def.h
+++ /dev/null
@@ -1,216 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 "sparse-endian.h"
-
-#include <systemd/sd-id128.h>
-
-#include "macro.h"
-
-/*
- * If you change this file you probably should also change its documentation:
- *
- * http://www.freedesktop.org/wiki/Software/systemd/journal-files
- *
- */
-
-typedef struct Header Header;
-
-typedef struct ObjectHeader ObjectHeader;
-typedef union Object Object;
-
-typedef struct DataObject DataObject;
-typedef struct FieldObject FieldObject;
-typedef struct EntryObject EntryObject;
-typedef struct HashTableObject HashTableObject;
-typedef struct EntryArrayObject EntryArrayObject;
-typedef struct TagObject TagObject;
-
-typedef struct EntryItem EntryItem;
-typedef struct HashItem HashItem;
-
-typedef struct FSSHeader FSSHeader;
-
-/* Object types */
-enum {
- OBJECT_UNUSED,
- OBJECT_DATA,
- OBJECT_FIELD,
- OBJECT_ENTRY,
- OBJECT_DATA_HASH_TABLE,
- OBJECT_FIELD_HASH_TABLE,
- OBJECT_ENTRY_ARRAY,
- OBJECT_TAG,
- _OBJECT_TYPE_MAX
-};
-
-/* Object flags */
-enum {
- OBJECT_COMPRESSED = 1
-};
-
-_packed_ struct ObjectHeader {
- uint8_t type;
- uint8_t flags;
- uint8_t reserved[6];
- le64_t size;
- uint8_t payload[];
-};
-
-_packed_ struct DataObject {
- ObjectHeader object;
- le64_t hash;
- le64_t next_hash_offset;
- le64_t next_field_offset;
- le64_t entry_offset; /* the first array entry we store inline */
- le64_t entry_array_offset;
- le64_t n_entries;
- uint8_t payload[];
-};
-
-_packed_ struct FieldObject {
- ObjectHeader object;
- le64_t hash;
- le64_t next_hash_offset;
- le64_t head_data_offset;
- uint8_t payload[];
-};
-
-_packed_ struct EntryItem {
- le64_t object_offset;
- le64_t hash;
-};
-
-_packed_ struct EntryObject {
- ObjectHeader object;
- le64_t seqnum;
- le64_t realtime;
- le64_t monotonic;
- sd_id128_t boot_id;
- le64_t xor_hash;
- EntryItem items[];
-};
-
-_packed_ struct HashItem {
- le64_t head_hash_offset;
- le64_t tail_hash_offset;
-};
-
-_packed_ struct HashTableObject {
- ObjectHeader object;
- HashItem items[];
-};
-
-_packed_ struct EntryArrayObject {
- ObjectHeader object;
- le64_t next_entry_array_offset;
- le64_t items[];
-};
-
-#define TAG_LENGTH (256/8)
-
-_packed_ struct TagObject {
- ObjectHeader object;
- le64_t seqnum;
- le64_t epoch;
- uint8_t tag[TAG_LENGTH]; /* SHA-256 HMAC */
-};
-
-union Object {
- ObjectHeader object;
- DataObject data;
- FieldObject field;
- EntryObject entry;
- HashTableObject hash_table;
- EntryArrayObject entry_array;
- TagObject tag;
-};
-
-enum {
- STATE_OFFLINE = 0,
- STATE_ONLINE = 1,
- STATE_ARCHIVED = 2,
- _STATE_MAX
-};
-
-/* Header flags */
-enum {
- HEADER_INCOMPATIBLE_COMPRESSED = 1
-};
-
-enum {
- HEADER_COMPATIBLE_SEALED = 1
-};
-
-#define HEADER_SIGNATURE ((char[]) { 'L', 'P', 'K', 'S', 'H', 'H', 'R', 'H' })
-
-_packed_ struct Header {
- uint8_t signature[8]; /* "LPKSHHRH" */
- le32_t compatible_flags;
- le32_t incompatible_flags;
- uint8_t state;
- uint8_t reserved[7];
- sd_id128_t file_id;
- sd_id128_t machine_id;
- sd_id128_t boot_id; /* last writer */
- sd_id128_t seqnum_id;
- le64_t header_size;
- le64_t arena_size;
- le64_t data_hash_table_offset;
- le64_t data_hash_table_size;
- le64_t field_hash_table_offset;
- le64_t field_hash_table_size;
- le64_t tail_object_offset;
- le64_t n_objects;
- le64_t n_entries;
- le64_t tail_entry_seqnum;
- le64_t head_entry_seqnum;
- le64_t entry_array_offset;
- le64_t head_entry_realtime;
- le64_t tail_entry_realtime;
- le64_t tail_entry_monotonic;
- /* Added in 187 */
- le64_t n_data;
- le64_t n_fields;
- /* Added in 189 */
- le64_t n_tags;
- le64_t n_entry_arrays;
-
- /* Size: 224 */
-};
-
-#define FSS_HEADER_SIGNATURE ((char[]) { 'K', 'S', 'H', 'H', 'R', 'H', 'L', 'P' })
-
-_packed_ struct FSSHeader {
- uint8_t signature[8]; /* "KSHHRHLP" */
- le32_t compatible_flags;
- le32_t incompatible_flags;
- sd_id128_t machine_id;
- sd_id128_t boot_id; /* last writer */
- le64_t header_size;
- le64_t start_usec;
- le64_t interval_usec;
- le16_t fsprg_secpar;
- le16_t reserved[3];
- le64_t fsprg_state_size;
-};
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
deleted file mode 100644
index 3df099dbd2..0000000000
--- a/src/journal/journal-file.c
+++ /dev/null
@@ -1,2872 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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/mman.h>
-#include <errno.h>
-#include <sys/uio.h>
-#include <unistd.h>
-#include <sys/statvfs.h>
-#include <fcntl.h>
-#include <stddef.h>
-
-#ifdef HAVE_XATTR
-#include <attr/xattr.h>
-#endif
-
-#include "journal-def.h"
-#include "journal-file.h"
-#include "journal-authenticate.h"
-#include "lookup3.h"
-#include "compress.h"
-#include "fsprg.h"
-
-#define DEFAULT_DATA_HASH_TABLE_SIZE (2047ULL*sizeof(HashItem))
-#define DEFAULT_FIELD_HASH_TABLE_SIZE (333ULL*sizeof(HashItem))
-
-#define COMPRESSION_SIZE_THRESHOLD (512ULL)
-
-/* This is the minimum journal file size */
-#define JOURNAL_FILE_SIZE_MIN (64ULL*1024ULL) /* 64 KiB */
-
-/* These are the lower and upper bounds if we deduce the max_use value
- * from the file system size */
-#define DEFAULT_MAX_USE_LOWER (1ULL*1024ULL*1024ULL) /* 1 MiB */
-#define DEFAULT_MAX_USE_UPPER (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */
-
-/* This is the upper bound if we deduce max_size from max_use */
-#define DEFAULT_MAX_SIZE_UPPER (128ULL*1024ULL*1024ULL) /* 128 MiB */
-
-/* This is the upper bound if we deduce the keep_free value from the
- * file system size */
-#define DEFAULT_KEEP_FREE_UPPER (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */
-
-/* This is the keep_free value when we can't determine the system
- * size */
-#define DEFAULT_KEEP_FREE (1024ULL*1024ULL) /* 1 MB */
-
-/* n_data was the first entry we added after the initial file format design */
-#define HEADER_SIZE_MIN ALIGN64(offsetof(Header, n_data))
-
-/* How many entries to keep in the entry array chain cache at max */
-#define CHAIN_CACHE_MAX 20
-
-void journal_file_close(JournalFile *f) {
- assert(f);
-
-#ifdef HAVE_GCRYPT
- /* Write the final tag */
- if (f->seal && f->writable)
- journal_file_append_tag(f);
-#endif
-
- /* Sync everything to disk, before we mark the file offline */
- if (f->mmap && f->fd >= 0)
- mmap_cache_close_fd(f->mmap, f->fd);
-
- if (f->writable && f->fd >= 0)
- fdatasync(f->fd);
-
- if (f->header) {
- /* Mark the file offline. Don't override the archived state if it already is set */
- if (f->writable && f->header->state == STATE_ONLINE)
- f->header->state = STATE_OFFLINE;
-
- munmap(f->header, PAGE_ALIGN(sizeof(Header)));
- }
-
- if (f->fd >= 0)
- close_nointr_nofail(f->fd);
-
- free(f->path);
-
- if (f->mmap)
- mmap_cache_unref(f->mmap);
-
- hashmap_free_free(f->chain_cache);
-
-#ifdef HAVE_XZ
- free(f->compress_buffer);
-#endif
-
-#ifdef HAVE_GCRYPT
- if (f->fss_file)
- munmap(f->fss_file, PAGE_ALIGN(f->fss_file_size));
- else if (f->fsprg_state)
- free(f->fsprg_state);
-
- free(f->fsprg_seed);
-
- if (f->hmac)
- gcry_md_close(f->hmac);
-#endif
-
- free(f);
-}
-
-static int journal_file_init_header(JournalFile *f, JournalFile *template) {
- Header h;
- ssize_t k;
- int r;
-
- assert(f);
-
- zero(h);
- memcpy(h.signature, HEADER_SIGNATURE, 8);
- h.header_size = htole64(ALIGN64(sizeof(h)));
-
- h.incompatible_flags =
- htole32(f->compress ? HEADER_INCOMPATIBLE_COMPRESSED : 0);
-
- h.compatible_flags =
- htole32(f->seal ? HEADER_COMPATIBLE_SEALED : 0);
-
- r = sd_id128_randomize(&h.file_id);
- if (r < 0)
- return r;
-
- if (template) {
- h.seqnum_id = template->header->seqnum_id;
- h.tail_entry_seqnum = template->header->tail_entry_seqnum;
- } else
- h.seqnum_id = h.file_id;
-
- k = pwrite(f->fd, &h, sizeof(h), 0);
- if (k < 0)
- return -errno;
-
- if (k != sizeof(h))
- return -EIO;
-
- return 0;
-}
-
-static int journal_file_refresh_header(JournalFile *f) {
- int r;
- sd_id128_t boot_id;
-
- assert(f);
-
- r = sd_id128_get_machine(&f->header->machine_id);
- if (r < 0)
- return r;
-
- r = sd_id128_get_boot(&boot_id);
- if (r < 0)
- return r;
-
- if (sd_id128_equal(boot_id, f->header->boot_id))
- f->tail_entry_monotonic_valid = true;
-
- f->header->boot_id = boot_id;
-
- f->header->state = STATE_ONLINE;
-
- /* Sync the online state to disk */
- msync(f->header, PAGE_ALIGN(sizeof(Header)), MS_SYNC);
- fdatasync(f->fd);
-
- return 0;
-}
-
-static int journal_file_verify_header(JournalFile *f) {
- assert(f);
-
- if (memcmp(f->header->signature, HEADER_SIGNATURE, 8))
- return -EBADMSG;
-
- /* In both read and write mode we refuse to open files with
- * incompatible flags we don't know */
-#ifdef HAVE_XZ
- if ((le32toh(f->header->incompatible_flags) & ~HEADER_INCOMPATIBLE_COMPRESSED) != 0)
- return -EPROTONOSUPPORT;
-#else
- if (f->header->incompatible_flags != 0)
- return -EPROTONOSUPPORT;
-#endif
-
- /* When open for writing we refuse to open files with
- * compatible flags, too */
- if (f->writable) {
-#ifdef HAVE_GCRYPT
- if ((le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_SEALED) != 0)
- return -EPROTONOSUPPORT;
-#else
- if (f->header->compatible_flags != 0)
- return -EPROTONOSUPPORT;
-#endif
- }
-
- if (f->header->state >= _STATE_MAX)
- return -EBADMSG;
-
- /* The first addition was n_data, so check that we are at least this large */
- if (le64toh(f->header->header_size) < HEADER_SIZE_MIN)
- return -EBADMSG;
-
- if (JOURNAL_HEADER_SEALED(f->header) && !JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays))
- return -EBADMSG;
-
- if ((le64toh(f->header->header_size) + le64toh(f->header->arena_size)) > (uint64_t) f->last_stat.st_size)
- return -ENODATA;
-
- if (le64toh(f->header->tail_object_offset) > (le64toh(f->header->header_size) + le64toh(f->header->arena_size)))
- return -ENODATA;
-
- if (!VALID64(le64toh(f->header->data_hash_table_offset)) ||
- !VALID64(le64toh(f->header->field_hash_table_offset)) ||
- !VALID64(le64toh(f->header->tail_object_offset)) ||
- !VALID64(le64toh(f->header->entry_array_offset)))
- return -ENODATA;
-
- if (le64toh(f->header->data_hash_table_offset) < le64toh(f->header->header_size) ||
- le64toh(f->header->field_hash_table_offset) < le64toh(f->header->header_size) ||
- le64toh(f->header->tail_object_offset) < le64toh(f->header->header_size) ||
- le64toh(f->header->entry_array_offset) < le64toh(f->header->header_size))
- return -ENODATA;
-
- if (f->writable) {
- uint8_t state;
- sd_id128_t machine_id;
- int r;
-
- r = sd_id128_get_machine(&machine_id);
- if (r < 0)
- return r;
-
- if (!sd_id128_equal(machine_id, f->header->machine_id))
- return -EHOSTDOWN;
-
- state = f->header->state;
-
- if (state == STATE_ONLINE) {
- log_debug("Journal file %s is already online. Assuming unclean closing.", f->path);
- return -EBUSY;
- } else if (state == STATE_ARCHIVED)
- return -ESHUTDOWN;
- else if (state != STATE_OFFLINE) {
- log_debug("Journal file %s has unknown state %u.", f->path, state);
- return -EBUSY;
- }
- }
-
- f->compress = JOURNAL_HEADER_COMPRESSED(f->header);
-
- f->seal = JOURNAL_HEADER_SEALED(f->header);
-
- return 0;
-}
-
-static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size) {
- uint64_t old_size, new_size;
- int r;
-
- assert(f);
-
- /* We assume that this file is not sparse, and we know that
- * for sure, since we always call posix_fallocate()
- * ourselves */
-
- old_size =
- le64toh(f->header->header_size) +
- le64toh(f->header->arena_size);
-
- new_size = PAGE_ALIGN(offset + size);
- if (new_size < le64toh(f->header->header_size))
- new_size = le64toh(f->header->header_size);
-
- if (new_size <= old_size)
- return 0;
-
- if (f->metrics.max_size > 0 &&
- new_size > f->metrics.max_size)
- return -E2BIG;
-
- if (new_size > f->metrics.min_size &&
- f->metrics.keep_free > 0) {
- struct statvfs svfs;
-
- if (fstatvfs(f->fd, &svfs) >= 0) {
- uint64_t available;
-
- available = svfs.f_bfree * svfs.f_bsize;
-
- if (available >= f->metrics.keep_free)
- available -= f->metrics.keep_free;
- else
- available = 0;
-
- if (new_size - old_size > available)
- return -E2BIG;
- }
- }
-
- /* Note that the glibc fallocate() fallback is very
- inefficient, hence we try to minimize the allocation area
- as we can. */
- r = posix_fallocate(f->fd, old_size, new_size - old_size);
- if (r != 0)
- return -r;
-
- if (fstat(f->fd, &f->last_stat) < 0)
- return -errno;
-
- f->header->arena_size = htole64(new_size - le64toh(f->header->header_size));
-
- return 0;
-}
-
-static int journal_file_move_to(JournalFile *f, int context, bool keep_always, uint64_t offset, uint64_t size, void **ret) {
- assert(f);
- assert(ret);
-
- if (size <= 0)
- return -EINVAL;
-
- /* Avoid SIGBUS on invalid accesses */
- if (offset + size > (uint64_t) f->last_stat.st_size) {
- /* Hmm, out of range? Let's refresh the fstat() data
- * first, before we trust that check. */
-
- if (fstat(f->fd, &f->last_stat) < 0 ||
- offset + size > (uint64_t) f->last_stat.st_size)
- return -EADDRNOTAVAIL;
- }
-
- return mmap_cache_get(f->mmap, f->fd, f->prot, context, keep_always, offset, size, &f->last_stat, ret);
-}
-
-static uint64_t minimum_header_size(Object *o) {
-
- static uint64_t table[] = {
- [OBJECT_DATA] = sizeof(DataObject),
- [OBJECT_FIELD] = sizeof(FieldObject),
- [OBJECT_ENTRY] = sizeof(EntryObject),
- [OBJECT_DATA_HASH_TABLE] = sizeof(HashTableObject),
- [OBJECT_FIELD_HASH_TABLE] = sizeof(HashTableObject),
- [OBJECT_ENTRY_ARRAY] = sizeof(EntryArrayObject),
- [OBJECT_TAG] = sizeof(TagObject),
- };
-
- if (o->object.type >= ELEMENTSOF(table) || table[o->object.type] <= 0)
- return sizeof(ObjectHeader);
-
- return table[o->object.type];
-}
-
-int journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Object **ret) {
- int r;
- void *t;
- Object *o;
- uint64_t s;
- unsigned context;
-
- assert(f);
- assert(ret);
-
- /* Objects may only be located at multiple of 64 bit */
- if (!VALID64(offset))
- return -EFAULT;
-
- /* One context for each type, plus one catch-all for the rest */
- context = type > 0 && type < _OBJECT_TYPE_MAX ? type : 0;
-
- r = journal_file_move_to(f, context, false, offset, sizeof(ObjectHeader), &t);
- if (r < 0)
- return r;
-
- o = (Object*) t;
- s = le64toh(o->object.size);
-
- if (s < sizeof(ObjectHeader))
- return -EBADMSG;
-
- if (o->object.type <= OBJECT_UNUSED)
- return -EBADMSG;
-
- if (s < minimum_header_size(o))
- return -EBADMSG;
-
- if (type > 0 && o->object.type != type)
- return -EBADMSG;
-
- if (s > sizeof(ObjectHeader)) {
- r = journal_file_move_to(f, o->object.type, false, offset, s, &t);
- if (r < 0)
- return r;
-
- o = (Object*) t;
- }
-
- *ret = o;
- return 0;
-}
-
-static uint64_t journal_file_entry_seqnum(JournalFile *f, uint64_t *seqnum) {
- uint64_t r;
-
- assert(f);
-
- r = le64toh(f->header->tail_entry_seqnum) + 1;
-
- if (seqnum) {
- /* If an external seqnum counter was passed, we update
- * both the local and the external one, and set it to
- * the maximum of both */
-
- if (*seqnum + 1 > r)
- r = *seqnum + 1;
-
- *seqnum = r;
- }
-
- f->header->tail_entry_seqnum = htole64(r);
-
- if (f->header->head_entry_seqnum == 0)
- f->header->head_entry_seqnum = htole64(r);
-
- return r;
-}
-
-int journal_file_append_object(JournalFile *f, int type, uint64_t size, Object **ret, uint64_t *offset) {
- int r;
- uint64_t p;
- Object *tail, *o;
- void *t;
-
- assert(f);
- assert(type > 0 && type < _OBJECT_TYPE_MAX);
- assert(size >= sizeof(ObjectHeader));
- assert(offset);
- assert(ret);
-
- p = le64toh(f->header->tail_object_offset);
- if (p == 0)
- p = le64toh(f->header->header_size);
- else {
- r = journal_file_move_to_object(f, -1, p, &tail);
- if (r < 0)
- return r;
-
- p += ALIGN64(le64toh(tail->object.size));
- }
-
- r = journal_file_allocate(f, p, size);
- if (r < 0)
- return r;
-
- r = journal_file_move_to(f, type, false, p, size, &t);
- if (r < 0)
- return r;
-
- o = (Object*) t;
-
- zero(o->object);
- o->object.type = type;
- o->object.size = htole64(size);
-
- f->header->tail_object_offset = htole64(p);
- f->header->n_objects = htole64(le64toh(f->header->n_objects) + 1);
-
- *ret = o;
- *offset = p;
-
- return 0;
-}
-
-static int journal_file_setup_data_hash_table(JournalFile *f) {
- uint64_t s, p;
- Object *o;
- int r;
-
- assert(f);
-
- /* We estimate that we need 1 hash table entry per 768 of
- journal file and we want to make sure we never get beyond
- 75% fill level. Calculate the hash table size for the
- maximum file size based on these metrics. */
-
- s = (f->metrics.max_size * 4 / 768 / 3) * sizeof(HashItem);
- if (s < DEFAULT_DATA_HASH_TABLE_SIZE)
- s = DEFAULT_DATA_HASH_TABLE_SIZE;
-
- log_debug("Reserving %llu entries in hash table.", (unsigned long long) (s / sizeof(HashItem)));
-
- r = journal_file_append_object(f,
- OBJECT_DATA_HASH_TABLE,
- offsetof(Object, hash_table.items) + s,
- &o, &p);
- if (r < 0)
- return r;
-
- memset(o->hash_table.items, 0, s);
-
- f->header->data_hash_table_offset = htole64(p + offsetof(Object, hash_table.items));
- f->header->data_hash_table_size = htole64(s);
-
- return 0;
-}
-
-static int journal_file_setup_field_hash_table(JournalFile *f) {
- uint64_t s, p;
- Object *o;
- int r;
-
- assert(f);
-
- /* We use a fixed size hash table for the fields as this
- * number should grow very slowly only */
-
- s = DEFAULT_FIELD_HASH_TABLE_SIZE;
- r = journal_file_append_object(f,
- OBJECT_FIELD_HASH_TABLE,
- offsetof(Object, hash_table.items) + s,
- &o, &p);
- if (r < 0)
- return r;
-
- memset(o->hash_table.items, 0, s);
-
- f->header->field_hash_table_offset = htole64(p + offsetof(Object, hash_table.items));
- f->header->field_hash_table_size = htole64(s);
-
- return 0;
-}
-
-static int journal_file_map_data_hash_table(JournalFile *f) {
- uint64_t s, p;
- void *t;
- int r;
-
- assert(f);
-
- p = le64toh(f->header->data_hash_table_offset);
- s = le64toh(f->header->data_hash_table_size);
-
- r = journal_file_move_to(f,
- OBJECT_DATA_HASH_TABLE,
- true,
- p, s,
- &t);
- if (r < 0)
- return r;
-
- f->data_hash_table = t;
- return 0;
-}
-
-static int journal_file_map_field_hash_table(JournalFile *f) {
- uint64_t s, p;
- void *t;
- int r;
-
- assert(f);
-
- p = le64toh(f->header->field_hash_table_offset);
- s = le64toh(f->header->field_hash_table_size);
-
- r = journal_file_move_to(f,
- OBJECT_FIELD_HASH_TABLE,
- true,
- p, s,
- &t);
- if (r < 0)
- return r;
-
- f->field_hash_table = t;
- return 0;
-}
-
-static int journal_file_link_field(
- JournalFile *f,
- Object *o,
- uint64_t offset,
- uint64_t hash) {
-
- uint64_t p, h;
- int r;
-
- assert(f);
- assert(o);
- assert(offset > 0);
-
- if (o->object.type != OBJECT_FIELD)
- return -EINVAL;
-
- /* This might alter the window we are looking at */
-
- o->field.next_hash_offset = o->field.head_data_offset = 0;
-
- h = hash % (le64toh(f->header->field_hash_table_size) / sizeof(HashItem));
- p = le64toh(f->field_hash_table[h].tail_hash_offset);
- if (p == 0)
- f->field_hash_table[h].head_hash_offset = htole64(offset);
- else {
- r = journal_file_move_to_object(f, OBJECT_FIELD, p, &o);
- if (r < 0)
- return r;
-
- o->field.next_hash_offset = htole64(offset);
- }
-
- f->field_hash_table[h].tail_hash_offset = htole64(offset);
-
- if (JOURNAL_HEADER_CONTAINS(f->header, n_fields))
- f->header->n_fields = htole64(le64toh(f->header->n_fields) + 1);
-
- return 0;
-}
-
-static int journal_file_link_data(
- JournalFile *f,
- Object *o,
- uint64_t offset,
- uint64_t hash) {
-
- uint64_t p, h;
- int r;
-
- assert(f);
- assert(o);
- assert(offset > 0);
-
- if (o->object.type != OBJECT_DATA)
- return -EINVAL;
-
- /* This might alter the window we are looking at */
-
- o->data.next_hash_offset = o->data.next_field_offset = 0;
- o->data.entry_offset = o->data.entry_array_offset = 0;
- o->data.n_entries = 0;
-
- h = hash % (le64toh(f->header->data_hash_table_size) / sizeof(HashItem));
- p = le64toh(f->data_hash_table[h].tail_hash_offset);
- if (p == 0)
- /* Only entry in the hash table is easy */
- f->data_hash_table[h].head_hash_offset = htole64(offset);
- else {
- /* Move back to the previous data object, to patch in
- * pointer */
-
- r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
- if (r < 0)
- return r;
-
- o->data.next_hash_offset = htole64(offset);
- }
-
- f->data_hash_table[h].tail_hash_offset = htole64(offset);
-
- if (JOURNAL_HEADER_CONTAINS(f->header, n_data))
- f->header->n_data = htole64(le64toh(f->header->n_data) + 1);
-
- return 0;
-}
-
-int journal_file_find_field_object_with_hash(
- JournalFile *f,
- const void *field, uint64_t size, uint64_t hash,
- Object **ret, uint64_t *offset) {
-
- uint64_t p, osize, h;
- int r;
-
- assert(f);
- assert(field && size > 0);
-
- osize = offsetof(Object, field.payload) + size;
-
- if (f->header->field_hash_table_size == 0)
- return -EBADMSG;
-
- h = hash % (le64toh(f->header->field_hash_table_size) / sizeof(HashItem));
- p = le64toh(f->field_hash_table[h].head_hash_offset);
-
- while (p > 0) {
- Object *o;
-
- r = journal_file_move_to_object(f, OBJECT_FIELD, p, &o);
- if (r < 0)
- return r;
-
- if (le64toh(o->field.hash) == hash &&
- le64toh(o->object.size) == osize &&
- memcmp(o->field.payload, field, size) == 0) {
-
- if (ret)
- *ret = o;
- if (offset)
- *offset = p;
-
- return 1;
- }
-
- p = le64toh(o->field.next_hash_offset);
- }
-
- return 0;
-}
-
-int journal_file_find_field_object(
- JournalFile *f,
- const void *field, uint64_t size,
- Object **ret, uint64_t *offset) {
-
- uint64_t hash;
-
- assert(f);
- assert(field && size > 0);
-
- hash = hash64(field, size);
-
- return journal_file_find_field_object_with_hash(f,
- field, size, hash,
- ret, offset);
-}
-
-int journal_file_find_data_object_with_hash(
- JournalFile *f,
- const void *data, uint64_t size, uint64_t hash,
- Object **ret, uint64_t *offset) {
-
- uint64_t p, osize, h;
- int r;
-
- assert(f);
- assert(data || size == 0);
-
- osize = offsetof(Object, data.payload) + size;
-
- if (f->header->data_hash_table_size == 0)
- return -EBADMSG;
-
- h = hash % (le64toh(f->header->data_hash_table_size) / sizeof(HashItem));
- p = le64toh(f->data_hash_table[h].head_hash_offset);
-
- while (p > 0) {
- Object *o;
-
- r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
- if (r < 0)
- return r;
-
- if (le64toh(o->data.hash) != hash)
- goto next;
-
- if (o->object.flags & OBJECT_COMPRESSED) {
-#ifdef HAVE_XZ
- uint64_t l, rsize;
-
- l = le64toh(o->object.size);
- if (l <= offsetof(Object, data.payload))
- return -EBADMSG;
-
- l -= offsetof(Object, data.payload);
-
- if (!uncompress_blob(o->data.payload, l, &f->compress_buffer, &f->compress_buffer_size, &rsize))
- return -EBADMSG;
-
- if (rsize == size &&
- memcmp(f->compress_buffer, data, size) == 0) {
-
- if (ret)
- *ret = o;
-
- if (offset)
- *offset = p;
-
- return 1;
- }
-#else
- return -EPROTONOSUPPORT;
-#endif
-
- } else if (le64toh(o->object.size) == osize &&
- memcmp(o->data.payload, data, size) == 0) {
-
- if (ret)
- *ret = o;
-
- if (offset)
- *offset = p;
-
- return 1;
- }
-
- next:
- p = le64toh(o->data.next_hash_offset);
- }
-
- return 0;
-}
-
-int journal_file_find_data_object(
- JournalFile *f,
- const void *data, uint64_t size,
- Object **ret, uint64_t *offset) {
-
- uint64_t hash;
-
- assert(f);
- assert(data || size == 0);
-
- hash = hash64(data, size);
-
- return journal_file_find_data_object_with_hash(f,
- data, size, hash,
- ret, offset);
-}
-
-static int journal_file_append_field(
- JournalFile *f,
- const void *field, uint64_t size,
- Object **ret, uint64_t *offset) {
-
- uint64_t hash, p;
- uint64_t osize;
- Object *o;
- int r;
-
- assert(f);
- assert(field && size > 0);
-
- hash = hash64(field, size);
-
- r = journal_file_find_field_object_with_hash(f, field, size, hash, &o, &p);
- if (r < 0)
- return r;
- else if (r > 0) {
-
- if (ret)
- *ret = o;
-
- if (offset)
- *offset = p;
-
- return 0;
- }
-
- osize = offsetof(Object, field.payload) + size;
- r = journal_file_append_object(f, OBJECT_FIELD, osize, &o, &p);
-
- o->field.hash = htole64(hash);
- memcpy(o->field.payload, field, size);
-
- r = journal_file_link_field(f, o, p, hash);
- if (r < 0)
- return r;
-
- /* The linking might have altered the window, so let's
- * refresh our pointer */
- r = journal_file_move_to_object(f, OBJECT_FIELD, p, &o);
- if (r < 0)
- return r;
-
-#ifdef HAVE_GCRYPT
- r = journal_file_hmac_put_object(f, OBJECT_FIELD, o, p);
- if (r < 0)
- return r;
-#endif
-
- if (ret)
- *ret = o;
-
- if (offset)
- *offset = p;
-
- return 0;
-}
-
-static int journal_file_append_data(
- JournalFile *f,
- const void *data, uint64_t size,
- Object **ret, uint64_t *offset) {
-
- uint64_t hash, p;
- uint64_t osize;
- Object *o;
- int r;
- bool compressed = false;
- const void *eq;
-
- assert(f);
- assert(data || size == 0);
-
- hash = hash64(data, size);
-
- r = journal_file_find_data_object_with_hash(f, data, size, hash, &o, &p);
- if (r < 0)
- return r;
- else if (r > 0) {
-
- if (ret)
- *ret = o;
-
- if (offset)
- *offset = p;
-
- return 0;
- }
-
- osize = offsetof(Object, data.payload) + size;
- r = journal_file_append_object(f, OBJECT_DATA, osize, &o, &p);
- if (r < 0)
- return r;
-
- o->data.hash = htole64(hash);
-
-#ifdef HAVE_XZ
- if (f->compress &&
- size >= COMPRESSION_SIZE_THRESHOLD) {
- uint64_t rsize;
-
- compressed = compress_blob(data, size, o->data.payload, &rsize);
-
- if (compressed) {
- o->object.size = htole64(offsetof(Object, data.payload) + rsize);
- o->object.flags |= OBJECT_COMPRESSED;
-
- log_debug("Compressed data object %lu -> %lu", (unsigned long) size, (unsigned long) rsize);
- }
- }
-#endif
-
- if (!compressed && size > 0)
- memcpy(o->data.payload, data, size);
-
- r = journal_file_link_data(f, o, p, hash);
- if (r < 0)
- return r;
-
- /* The linking might have altered the window, so let's
- * refresh our pointer */
- r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
- if (r < 0)
- return r;
-
- eq = memchr(data, '=', size);
- if (eq && eq > data) {
- uint64_t fp;
- Object *fo;
-
- /* Create field object ... */
- r = journal_file_append_field(f, data, (uint8_t*) eq - (uint8_t*) data, &fo, &fp);
- if (r < 0)
- return r;
-
- /* ... and link it in. */
- o->data.next_field_offset = fo->field.head_data_offset;
- fo->field.head_data_offset = le64toh(p);
- }
-
-#ifdef HAVE_GCRYPT
- r = journal_file_hmac_put_object(f, OBJECT_DATA, o, p);
- if (r < 0)
- return r;
-#endif
-
- if (ret)
- *ret = o;
-
- if (offset)
- *offset = p;
-
- return 0;
-}
-
-uint64_t journal_file_entry_n_items(Object *o) {
- assert(o);
-
- if (o->object.type != OBJECT_ENTRY)
- return 0;
-
- return (le64toh(o->object.size) - offsetof(Object, entry.items)) / sizeof(EntryItem);
-}
-
-uint64_t journal_file_entry_array_n_items(Object *o) {
- assert(o);
-
- if (o->object.type != OBJECT_ENTRY_ARRAY)
- return 0;
-
- return (le64toh(o->object.size) - offsetof(Object, entry_array.items)) / sizeof(uint64_t);
-}
-
-uint64_t journal_file_hash_table_n_items(Object *o) {
- assert(o);
-
- if (o->object.type != OBJECT_DATA_HASH_TABLE &&
- o->object.type != OBJECT_FIELD_HASH_TABLE)
- return 0;
-
- return (le64toh(o->object.size) - offsetof(Object, hash_table.items)) / sizeof(HashItem);
-}
-
-static int link_entry_into_array(JournalFile *f,
- le64_t *first,
- le64_t *idx,
- uint64_t p) {
- int r;
- uint64_t n = 0, ap = 0, q, i, a, hidx;
- Object *o;
-
- assert(f);
- assert(first);
- assert(idx);
- assert(p > 0);
-
- a = le64toh(*first);
- i = hidx = le64toh(*idx);
- while (a > 0) {
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
- if (r < 0)
- return r;
-
- n = journal_file_entry_array_n_items(o);
- if (i < n) {
- o->entry_array.items[i] = htole64(p);
- *idx = htole64(hidx + 1);
- return 0;
- }
-
- i -= n;
- ap = a;
- a = le64toh(o->entry_array.next_entry_array_offset);
- }
-
- if (hidx > n)
- n = (hidx+1) * 2;
- else
- n = n * 2;
-
- if (n < 4)
- n = 4;
-
- r = journal_file_append_object(f, OBJECT_ENTRY_ARRAY,
- offsetof(Object, entry_array.items) + n * sizeof(uint64_t),
- &o, &q);
- if (r < 0)
- return r;
-
-#ifdef HAVE_GCRYPT
- r = journal_file_hmac_put_object(f, OBJECT_ENTRY_ARRAY, o, q);
- if (r < 0)
- return r;
-#endif
-
- o->entry_array.items[i] = htole64(p);
-
- if (ap == 0)
- *first = htole64(q);
- else {
- r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, ap, &o);
- if (r < 0)
- return r;
-
- o->entry_array.next_entry_array_offset = htole64(q);
- }
-
- if (JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays))
- f->header->n_entry_arrays = htole64(le64toh(f->header->n_entry_arrays) + 1);
-
- *idx = htole64(hidx + 1);
-
- return 0;
-}
-
-static int link_entry_into_array_plus_one(JournalFile *f,
- le64_t *extra,
- le64_t *first,
- le64_t *idx,
- uint64_t p) {
-
- int r;
-
- assert(f);
- assert(extra);
- assert(first);
- assert(idx);
- assert(p > 0);
-
- if (*idx == 0)
- *extra = htole64(p);
- else {
- le64_t i;
-
- i = htole64(le64toh(*idx) - 1);
- r = link_entry_into_array(f, first, &i, p);
- if (r < 0)
- return r;
- }
-
- *idx = htole64(le64toh(*idx) + 1);
- return 0;
-}
-
-static int journal_file_link_entry_item(JournalFile *f, Object *o, uint64_t offset, uint64_t i) {
- uint64_t p;
- int r;
- assert(f);
- assert(o);
- assert(offset > 0);
-
- p = le64toh(o->entry.items[i].object_offset);
- if (p == 0)
- return -EINVAL;
-
- r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
- if (r < 0)
- return r;
-
- return link_entry_into_array_plus_one(f,
- &o->data.entry_offset,
- &o->data.entry_array_offset,
- &o->data.n_entries,
- offset);
-}
-
-static int journal_file_link_entry(JournalFile *f, Object *o, uint64_t offset) {
- uint64_t n, i;
- int r;
-
- assert(f);
- assert(o);
- assert(offset > 0);
-
- if (o->object.type != OBJECT_ENTRY)
- return -EINVAL;
-
- __sync_synchronize();
-
- /* Link up the entry itself */
- r = link_entry_into_array(f,
- &f->header->entry_array_offset,
- &f->header->n_entries,
- offset);
- if (r < 0)
- return r;
-
- /* log_debug("=> %s seqnr=%lu n_entries=%lu", f->path, (unsigned long) o->entry.seqnum, (unsigned long) f->header->n_entries); */
-
- if (f->header->head_entry_realtime == 0)
- f->header->head_entry_realtime = o->entry.realtime;
-
- f->header->tail_entry_realtime = o->entry.realtime;
- f->header->tail_entry_monotonic = o->entry.monotonic;
-
- f->tail_entry_monotonic_valid = true;
-
- /* Link up the items */
- n = journal_file_entry_n_items(o);
- for (i = 0; i < n; i++) {
- r = journal_file_link_entry_item(f, o, offset, i);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-static int journal_file_append_entry_internal(
- JournalFile *f,
- const dual_timestamp *ts,
- uint64_t xor_hash,
- const EntryItem items[], unsigned n_items,
- uint64_t *seqnum,
- Object **ret, uint64_t *offset) {
- uint64_t np;
- uint64_t osize;
- Object *o;
- int r;
-
- assert(f);
- assert(items || n_items == 0);
- assert(ts);
-
- osize = offsetof(Object, entry.items) + (n_items * sizeof(EntryItem));
-
- r = journal_file_append_object(f, OBJECT_ENTRY, osize, &o, &np);
- if (r < 0)
- return r;
-
- o->entry.seqnum = htole64(journal_file_entry_seqnum(f, seqnum));
- memcpy(o->entry.items, items, n_items * sizeof(EntryItem));
- o->entry.realtime = htole64(ts->realtime);
- o->entry.monotonic = htole64(ts->monotonic);
- o->entry.xor_hash = htole64(xor_hash);
- o->entry.boot_id = f->header->boot_id;
-
-#ifdef HAVE_GCRYPT
- r = journal_file_hmac_put_object(f, OBJECT_ENTRY, o, np);
- if (r < 0)
- return r;
-#endif
-
- r = journal_file_link_entry(f, o, np);
- if (r < 0)
- return r;
-
- if (ret)
- *ret = o;
-
- if (offset)
- *offset = np;
-
- return 0;
-}
-
-void journal_file_post_change(JournalFile *f) {
- assert(f);
-
- /* inotify() does not receive IN_MODIFY events from file
- * accesses done via mmap(). After each access we hence
- * trigger IN_MODIFY by truncating the journal file to its
- * current size which triggers IN_MODIFY. */
-
- __sync_synchronize();
-
- if (ftruncate(f->fd, f->last_stat.st_size) < 0)
- log_error("Failed to truncate file to its own size: %m");
-}
-
-static int entry_item_cmp(const void *_a, const void *_b) {
- const EntryItem *a = _a, *b = _b;
-
- if (le64toh(a->object_offset) < le64toh(b->object_offset))
- return -1;
- if (le64toh(a->object_offset) > le64toh(b->object_offset))
- return 1;
- return 0;
-}
-
-int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, uint64_t *seqnum, Object **ret, uint64_t *offset) {
- unsigned i;
- EntryItem *items;
- int r;
- uint64_t xor_hash = 0;
- struct dual_timestamp _ts;
-
- assert(f);
- assert(iovec || n_iovec == 0);
-
- if (!f->writable)
- return -EPERM;
-
- if (!ts) {
- dual_timestamp_get(&_ts);
- ts = &_ts;
- }
-
- if (f->tail_entry_monotonic_valid &&
- ts->monotonic < le64toh(f->header->tail_entry_monotonic))
- return -EINVAL;
-
-#ifdef HAVE_GCRYPT
- r = journal_file_maybe_append_tag(f, ts->realtime);
- if (r < 0)
- return r;
-#endif
-
- /* alloca() can't take 0, hence let's allocate at least one */
- items = alloca(sizeof(EntryItem) * MAX(1, n_iovec));
-
- for (i = 0; i < n_iovec; i++) {
- uint64_t p;
- Object *o;
-
- r = journal_file_append_data(f, iovec[i].iov_base, iovec[i].iov_len, &o, &p);
- if (r < 0)
- return r;
-
- xor_hash ^= le64toh(o->data.hash);
- items[i].object_offset = htole64(p);
- items[i].hash = o->data.hash;
- }
-
- /* Order by the position on disk, in order to improve seek
- * times for rotating media. */
- qsort(items, n_iovec, sizeof(EntryItem), entry_item_cmp);
-
- r = journal_file_append_entry_internal(f, ts, xor_hash, items, n_iovec, seqnum, ret, offset);
-
- journal_file_post_change(f);
-
- return r;
-}
-
-typedef struct ChainCacheItem {
- uint64_t first; /* the array at the begin of the chain */
- uint64_t array; /* the cached array */
- uint64_t begin; /* the first item in the cached array */
- uint64_t total; /* the total number of items in all arrays before this one in the chain */
-} ChainCacheItem;
-
-static void chain_cache_put(
- Hashmap *h,
- ChainCacheItem *ci,
- uint64_t first,
- uint64_t array,
- uint64_t begin,
- uint64_t total) {
-
- if (!ci) {
- /* If the chain item to cache for this chain is the
- * first one it's not worth caching anything */
- if (array == first)
- return;
-
- if (hashmap_size(h) >= CHAIN_CACHE_MAX)
- ci = hashmap_steal_first(h);
- else {
- ci = new(ChainCacheItem, 1);
- if (!ci)
- return;
- }
-
- ci->first = first;
-
- if (hashmap_put(h, &ci->first, ci) < 0) {
- free(ci);
- return;
- }
- } else
- assert(ci->first == first);
-
- ci->array = array;
- ci->begin = begin;
- ci->total = total;
-}
-
-static int generic_array_get(JournalFile *f,
- uint64_t first,
- uint64_t i,
- Object **ret, uint64_t *offset) {
-
- Object *o;
- uint64_t p = 0, a, t = 0;
- int r;
- ChainCacheItem *ci;
-
- assert(f);
-
- a = first;
-
- /* Try the chain cache first */
- ci = hashmap_get(f->chain_cache, &first);
- if (ci && i > ci->total) {
- a = ci->array;
- i -= ci->total;
- t = ci->total;
- }
-
- while (a > 0) {
- uint64_t k;
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
- if (r < 0)
- return r;
-
- k = journal_file_entry_array_n_items(o);
- if (i < k) {
- p = le64toh(o->entry_array.items[i]);
- goto found;
- }
-
- i -= k;
- t += k;
- a = le64toh(o->entry_array.next_entry_array_offset);
- }
-
- return 0;
-
-found:
- /* Let's cache this item for the next invocation */
- chain_cache_put(f->chain_cache, ci, first, a, o->entry_array.items[0], t);
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o);
- if (r < 0)
- return r;
-
- if (ret)
- *ret = o;
-
- if (offset)
- *offset = p;
-
- return 1;
-}
-
-static int generic_array_get_plus_one(JournalFile *f,
- uint64_t extra,
- uint64_t first,
- uint64_t i,
- Object **ret, uint64_t *offset) {
-
- Object *o;
-
- assert(f);
-
- if (i == 0) {
- int r;
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, &o);
- if (r < 0)
- return r;
-
- if (ret)
- *ret = o;
-
- if (offset)
- *offset = extra;
-
- return 1;
- }
-
- return generic_array_get(f, first, i-1, ret, offset);
-}
-
-enum {
- TEST_FOUND,
- TEST_LEFT,
- TEST_RIGHT
-};
-
-static int generic_array_bisect(JournalFile *f,
- uint64_t first,
- uint64_t n,
- uint64_t needle,
- int (*test_object)(JournalFile *f, uint64_t p, uint64_t needle),
- direction_t direction,
- Object **ret,
- uint64_t *offset,
- uint64_t *idx) {
-
- uint64_t a, p, t = 0, i = 0, last_p = 0;
- bool subtract_one = false;
- Object *o, *array = NULL;
- int r;
- ChainCacheItem *ci;
-
- assert(f);
- assert(test_object);
-
- /* Start with the first array in the chain */
- a = first;
-
- ci = hashmap_get(f->chain_cache, &first);
- if (ci && n > ci->total) {
- /* Ah, we have iterated this bisection array chain
- * previously! Let's see if we can skip ahead in the
- * chain, as far as the last time. But we can't jump
- * backwards in the chain, so let's check that
- * first. */
-
- r = test_object(f, ci->begin, needle);
- if (r < 0)
- return r;
-
- if (r == TEST_LEFT) {
- /* OK, what we are looking for is right of th
- * begin of this EntryArray, so let's jump
- * straight to previously cached array in the
- * chain */
-
- a = ci->array;
- n -= ci->total;
- t = ci->total;
- }
- }
-
- while (a > 0) {
- uint64_t left, right, k, lp;
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &array);
- if (r < 0)
- return r;
-
- k = journal_file_entry_array_n_items(array);
- right = MIN(k, n);
- if (right <= 0)
- return 0;
-
- i = right - 1;
- lp = p = le64toh(array->entry_array.items[i]);
- if (p <= 0)
- return -EBADMSG;
-
- r = test_object(f, p, needle);
- if (r < 0)
- return r;
-
- if (r == TEST_FOUND)
- r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
-
- if (r == TEST_RIGHT) {
- left = 0;
- right -= 1;
- for (;;) {
- if (left == right) {
- if (direction == DIRECTION_UP)
- subtract_one = true;
-
- i = left;
- goto found;
- }
-
- assert(left < right);
-
- i = (left + right) / 2;
- p = le64toh(array->entry_array.items[i]);
- if (p <= 0)
- return -EBADMSG;
-
- r = test_object(f, p, needle);
- if (r < 0)
- return r;
-
- if (r == TEST_FOUND)
- r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
-
- if (r == TEST_RIGHT)
- right = i;
- else
- left = i + 1;
- }
- }
-
- if (k > n) {
- if (direction == DIRECTION_UP) {
- i = n;
- subtract_one = true;
- goto found;
- }
-
- return 0;
- }
-
- last_p = lp;
-
- n -= k;
- t += k;
- a = le64toh(array->entry_array.next_entry_array_offset);
- }
-
- return 0;
-
-found:
- if (subtract_one && t == 0 && i == 0)
- return 0;
-
- /* Let's cache this item for the next invocation */
- chain_cache_put(f->chain_cache, ci, first, a, array->entry_array.items[0], t);
-
- if (subtract_one && i == 0)
- p = last_p;
- else if (subtract_one)
- p = le64toh(array->entry_array.items[i-1]);
- else
- p = le64toh(array->entry_array.items[i]);
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o);
- if (r < 0)
- return r;
-
- if (ret)
- *ret = o;
-
- if (offset)
- *offset = p;
-
- if (idx)
- *idx = t + i + (subtract_one ? -1 : 0);
-
- return 1;
-}
-
-static int generic_array_bisect_plus_one(JournalFile *f,
- uint64_t extra,
- uint64_t first,
- uint64_t n,
- uint64_t needle,
- int (*test_object)(JournalFile *f, uint64_t p, uint64_t needle),
- direction_t direction,
- Object **ret,
- uint64_t *offset,
- uint64_t *idx) {
-
- int r;
- bool step_back = false;
- Object *o;
-
- assert(f);
- assert(test_object);
-
- if (n <= 0)
- return 0;
-
- /* This bisects the array in object 'first', but first checks
- * an extra */
- r = test_object(f, extra, needle);
- if (r < 0)
- return r;
-
- if (r == TEST_FOUND)
- r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
-
- /* if we are looking with DIRECTION_UP then we need to first
- see if in the actual array there is a matching entry, and
- return the last one of that. But if there isn't any we need
- to return this one. Hence remember this, and return it
- below. */
- if (r == TEST_LEFT)
- step_back = direction == DIRECTION_UP;
-
- if (r == TEST_RIGHT) {
- if (direction == DIRECTION_DOWN)
- goto found;
- else
- return 0;
- }
-
- r = generic_array_bisect(f, first, n-1, needle, test_object, direction, ret, offset, idx);
-
- if (r == 0 && step_back)
- goto found;
-
- if (r > 0 && idx)
- (*idx) ++;
-
- return r;
-
-found:
- r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, &o);
- if (r < 0)
- return r;
-
- if (ret)
- *ret = o;
-
- if (offset)
- *offset = extra;
-
- if (idx)
- *idx = 0;
-
- return 1;
-}
-
-static int test_object_offset(JournalFile *f, uint64_t p, uint64_t needle) {
- assert(f);
- assert(p > 0);
-
- if (p == needle)
- return TEST_FOUND;
- else if (p < needle)
- return TEST_LEFT;
- else
- return TEST_RIGHT;
-}
-
-int journal_file_move_to_entry_by_offset(
- JournalFile *f,
- uint64_t p,
- direction_t direction,
- Object **ret,
- uint64_t *offset) {
-
- return generic_array_bisect(f,
- le64toh(f->header->entry_array_offset),
- le64toh(f->header->n_entries),
- p,
- test_object_offset,
- direction,
- ret, offset, NULL);
-}
-
-
-static int test_object_seqnum(JournalFile *f, uint64_t p, uint64_t needle) {
- Object *o;
- int r;
-
- assert(f);
- assert(p > 0);
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o);
- if (r < 0)
- return r;
-
- if (le64toh(o->entry.seqnum) == needle)
- return TEST_FOUND;
- else if (le64toh(o->entry.seqnum) < needle)
- return TEST_LEFT;
- else
- return TEST_RIGHT;
-}
-
-int journal_file_move_to_entry_by_seqnum(
- JournalFile *f,
- uint64_t seqnum,
- direction_t direction,
- Object **ret,
- uint64_t *offset) {
-
- return generic_array_bisect(f,
- le64toh(f->header->entry_array_offset),
- le64toh(f->header->n_entries),
- seqnum,
- test_object_seqnum,
- direction,
- ret, offset, NULL);
-}
-
-static int test_object_realtime(JournalFile *f, uint64_t p, uint64_t needle) {
- Object *o;
- int r;
-
- assert(f);
- assert(p > 0);
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o);
- if (r < 0)
- return r;
-
- if (le64toh(o->entry.realtime) == needle)
- return TEST_FOUND;
- else if (le64toh(o->entry.realtime) < needle)
- return TEST_LEFT;
- else
- return TEST_RIGHT;
-}
-
-int journal_file_move_to_entry_by_realtime(
- JournalFile *f,
- uint64_t realtime,
- direction_t direction,
- Object **ret,
- uint64_t *offset) {
-
- return generic_array_bisect(f,
- le64toh(f->header->entry_array_offset),
- le64toh(f->header->n_entries),
- realtime,
- test_object_realtime,
- direction,
- ret, offset, NULL);
-}
-
-static int test_object_monotonic(JournalFile *f, uint64_t p, uint64_t needle) {
- Object *o;
- int r;
-
- assert(f);
- assert(p > 0);
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o);
- if (r < 0)
- return r;
-
- if (le64toh(o->entry.monotonic) == needle)
- return TEST_FOUND;
- else if (le64toh(o->entry.monotonic) < needle)
- return TEST_LEFT;
- else
- return TEST_RIGHT;
-}
-
-int journal_file_move_to_entry_by_monotonic(
- JournalFile *f,
- sd_id128_t boot_id,
- uint64_t monotonic,
- direction_t direction,
- Object **ret,
- uint64_t *offset) {
-
- char t[9+32+1] = "_BOOT_ID=";
- Object *o;
- int r;
-
- assert(f);
-
- sd_id128_to_string(boot_id, t + 9);
- r = journal_file_find_data_object(f, t, strlen(t), &o, NULL);
- if (r < 0)
- return r;
- if (r == 0)
- return -ENOENT;
-
- return generic_array_bisect_plus_one(f,
- le64toh(o->data.entry_offset),
- le64toh(o->data.entry_array_offset),
- le64toh(o->data.n_entries),
- monotonic,
- test_object_monotonic,
- direction,
- ret, offset, NULL);
-}
-
-int journal_file_next_entry(
- JournalFile *f,
- Object *o, uint64_t p,
- direction_t direction,
- Object **ret, uint64_t *offset) {
-
- uint64_t i, n;
- int r;
-
- assert(f);
- assert(p > 0 || !o);
-
- n = le64toh(f->header->n_entries);
- if (n <= 0)
- return 0;
-
- if (!o)
- i = direction == DIRECTION_DOWN ? 0 : n - 1;
- else {
- if (o->object.type != OBJECT_ENTRY)
- return -EINVAL;
-
- r = generic_array_bisect(f,
- le64toh(f->header->entry_array_offset),
- le64toh(f->header->n_entries),
- p,
- test_object_offset,
- DIRECTION_DOWN,
- NULL, NULL,
- &i);
- if (r <= 0)
- return r;
-
- if (direction == DIRECTION_DOWN) {
- if (i >= n - 1)
- return 0;
-
- i++;
- } else {
- if (i <= 0)
- return 0;
-
- i--;
- }
- }
-
- /* And jump to it */
- return generic_array_get(f,
- le64toh(f->header->entry_array_offset),
- i,
- ret, offset);
-}
-
-int journal_file_skip_entry(
- JournalFile *f,
- Object *o, uint64_t p,
- int64_t skip,
- Object **ret, uint64_t *offset) {
-
- uint64_t i, n;
- int r;
-
- assert(f);
- assert(o);
- assert(p > 0);
-
- if (o->object.type != OBJECT_ENTRY)
- return -EINVAL;
-
- r = generic_array_bisect(f,
- le64toh(f->header->entry_array_offset),
- le64toh(f->header->n_entries),
- p,
- test_object_offset,
- DIRECTION_DOWN,
- NULL, NULL,
- &i);
- if (r <= 0)
- return r;
-
- /* Calculate new index */
- if (skip < 0) {
- if ((uint64_t) -skip >= i)
- i = 0;
- else
- i = i - (uint64_t) -skip;
- } else
- i += (uint64_t) skip;
-
- n = le64toh(f->header->n_entries);
- if (n <= 0)
- return -EBADMSG;
-
- if (i >= n)
- i = n-1;
-
- return generic_array_get(f,
- le64toh(f->header->entry_array_offset),
- i,
- ret, offset);
-}
-
-int journal_file_next_entry_for_data(
- JournalFile *f,
- Object *o, uint64_t p,
- uint64_t data_offset,
- direction_t direction,
- Object **ret, uint64_t *offset) {
-
- uint64_t n, i;
- int r;
- Object *d;
-
- assert(f);
- assert(p > 0 || !o);
-
- r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d);
- if (r < 0)
- return r;
-
- n = le64toh(d->data.n_entries);
- if (n <= 0)
- return n;
-
- if (!o)
- i = direction == DIRECTION_DOWN ? 0 : n - 1;
- else {
- if (o->object.type != OBJECT_ENTRY)
- return -EINVAL;
-
- r = generic_array_bisect_plus_one(f,
- le64toh(d->data.entry_offset),
- le64toh(d->data.entry_array_offset),
- le64toh(d->data.n_entries),
- p,
- test_object_offset,
- DIRECTION_DOWN,
- NULL, NULL,
- &i);
-
- if (r <= 0)
- return r;
-
- if (direction == DIRECTION_DOWN) {
- if (i >= n - 1)
- return 0;
-
- i++;
- } else {
- if (i <= 0)
- return 0;
-
- i--;
- }
-
- }
-
- return generic_array_get_plus_one(f,
- le64toh(d->data.entry_offset),
- le64toh(d->data.entry_array_offset),
- i,
- ret, offset);
-}
-
-int journal_file_move_to_entry_by_offset_for_data(
- JournalFile *f,
- uint64_t data_offset,
- uint64_t p,
- direction_t direction,
- Object **ret, uint64_t *offset) {
-
- int r;
- Object *d;
-
- assert(f);
-
- r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d);
- if (r < 0)
- return r;
-
- return generic_array_bisect_plus_one(f,
- le64toh(d->data.entry_offset),
- le64toh(d->data.entry_array_offset),
- le64toh(d->data.n_entries),
- p,
- test_object_offset,
- direction,
- ret, offset, NULL);
-}
-
-int journal_file_move_to_entry_by_monotonic_for_data(
- JournalFile *f,
- uint64_t data_offset,
- sd_id128_t boot_id,
- uint64_t monotonic,
- direction_t direction,
- Object **ret, uint64_t *offset) {
-
- char t[9+32+1] = "_BOOT_ID=";
- Object *o, *d;
- int r;
- uint64_t b, z;
-
- assert(f);
-
- /* First, seek by time */
- sd_id128_to_string(boot_id, t + 9);
- r = journal_file_find_data_object(f, t, strlen(t), &o, &b);
- if (r < 0)
- return r;
- if (r == 0)
- return -ENOENT;
-
- r = generic_array_bisect_plus_one(f,
- le64toh(o->data.entry_offset),
- le64toh(o->data.entry_array_offset),
- le64toh(o->data.n_entries),
- monotonic,
- test_object_monotonic,
- direction,
- NULL, &z, NULL);
- if (r <= 0)
- return r;
-
- /* And now, continue seeking until we find an entry that
- * exists in both bisection arrays */
-
- for (;;) {
- Object *qo;
- uint64_t p, q;
-
- r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d);
- if (r < 0)
- return r;
-
- r = generic_array_bisect_plus_one(f,
- le64toh(d->data.entry_offset),
- le64toh(d->data.entry_array_offset),
- le64toh(d->data.n_entries),
- z,
- test_object_offset,
- direction,
- NULL, &p, NULL);
- if (r <= 0)
- return r;
-
- r = journal_file_move_to_object(f, OBJECT_DATA, b, &o);
- if (r < 0)
- return r;
-
- r = generic_array_bisect_plus_one(f,
- le64toh(o->data.entry_offset),
- le64toh(o->data.entry_array_offset),
- le64toh(o->data.n_entries),
- p,
- test_object_offset,
- direction,
- &qo, &q, NULL);
-
- if (r <= 0)
- return r;
-
- if (p == q) {
- if (ret)
- *ret = qo;
- if (offset)
- *offset = q;
-
- return 1;
- }
-
- z = q;
- }
-
- return 0;
-}
-
-int journal_file_move_to_entry_by_seqnum_for_data(
- JournalFile *f,
- uint64_t data_offset,
- uint64_t seqnum,
- direction_t direction,
- Object **ret, uint64_t *offset) {
-
- Object *d;
- int r;
-
- assert(f);
-
- r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d);
- if (r < 0)
- return r;
-
- return generic_array_bisect_plus_one(f,
- le64toh(d->data.entry_offset),
- le64toh(d->data.entry_array_offset),
- le64toh(d->data.n_entries),
- seqnum,
- test_object_seqnum,
- direction,
- ret, offset, NULL);
-}
-
-int journal_file_move_to_entry_by_realtime_for_data(
- JournalFile *f,
- uint64_t data_offset,
- uint64_t realtime,
- direction_t direction,
- Object **ret, uint64_t *offset) {
-
- Object *d;
- int r;
-
- assert(f);
-
- r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d);
- if (r < 0)
- return r;
-
- return generic_array_bisect_plus_one(f,
- le64toh(d->data.entry_offset),
- le64toh(d->data.entry_array_offset),
- le64toh(d->data.n_entries),
- realtime,
- test_object_realtime,
- direction,
- ret, offset, NULL);
-}
-
-void journal_file_dump(JournalFile *f) {
- Object *o;
- int r;
- uint64_t p;
-
- assert(f);
-
- journal_file_print_header(f);
-
- p = le64toh(f->header->header_size);
- while (p != 0) {
- r = journal_file_move_to_object(f, -1, p, &o);
- if (r < 0)
- goto fail;
-
- switch (o->object.type) {
-
- case OBJECT_UNUSED:
- printf("Type: OBJECT_UNUSED\n");
- break;
-
- case OBJECT_DATA:
- printf("Type: OBJECT_DATA\n");
- break;
-
- case OBJECT_FIELD:
- printf("Type: OBJECT_FIELD\n");
- break;
-
- case OBJECT_ENTRY:
- printf("Type: OBJECT_ENTRY seqnum=%llu monotonic=%llu realtime=%llu\n",
- (unsigned long long) le64toh(o->entry.seqnum),
- (unsigned long long) le64toh(o->entry.monotonic),
- (unsigned long long) le64toh(o->entry.realtime));
- break;
-
- case OBJECT_FIELD_HASH_TABLE:
- printf("Type: OBJECT_FIELD_HASH_TABLE\n");
- break;
-
- case OBJECT_DATA_HASH_TABLE:
- printf("Type: OBJECT_DATA_HASH_TABLE\n");
- break;
-
- case OBJECT_ENTRY_ARRAY:
- printf("Type: OBJECT_ENTRY_ARRAY\n");
- break;
-
- case OBJECT_TAG:
- printf("Type: OBJECT_TAG seqnum=%llu epoch=%llu\n",
- (unsigned long long) le64toh(o->tag.seqnum),
- (unsigned long long) le64toh(o->tag.epoch));
- break;
-
- default:
- printf("Type: unknown (%u)\n", o->object.type);
- break;
- }
-
- if (o->object.flags & OBJECT_COMPRESSED)
- printf("Flags: COMPRESSED\n");
-
- if (p == le64toh(f->header->tail_object_offset))
- p = 0;
- else
- p = p + ALIGN64(le64toh(o->object.size));
- }
-
- return;
-fail:
- log_error("File corrupt");
-}
-
-void journal_file_print_header(JournalFile *f) {
- char a[33], b[33], c[33];
- char x[FORMAT_TIMESTAMP_MAX], y[FORMAT_TIMESTAMP_MAX];
- struct stat st;
- char bytes[FORMAT_BYTES_MAX];
-
- assert(f);
-
- printf("File Path: %s\n"
- "File ID: %s\n"
- "Machine ID: %s\n"
- "Boot ID: %s\n"
- "Sequential Number ID: %s\n"
- "State: %s\n"
- "Compatible Flags:%s%s\n"
- "Incompatible Flags:%s%s\n"
- "Header size: %llu\n"
- "Arena size: %llu\n"
- "Data Hash Table Size: %llu\n"
- "Field Hash Table Size: %llu\n"
- "Rotate Suggested: %s\n"
- "Head Sequential Number: %llu\n"
- "Tail Sequential Number: %llu\n"
- "Head Realtime Timestamp: %s\n"
- "Tail Realtime Timestamp: %s\n"
- "Objects: %llu\n"
- "Entry Objects: %llu\n",
- f->path,
- sd_id128_to_string(f->header->file_id, a),
- sd_id128_to_string(f->header->machine_id, b),
- sd_id128_to_string(f->header->boot_id, c),
- sd_id128_to_string(f->header->seqnum_id, c),
- f->header->state == STATE_OFFLINE ? "OFFLINE" :
- f->header->state == STATE_ONLINE ? "ONLINE" :
- f->header->state == STATE_ARCHIVED ? "ARCHIVED" : "UNKNOWN",
- JOURNAL_HEADER_SEALED(f->header) ? " SEALED" : "",
- (le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_SEALED) ? " ???" : "",
- JOURNAL_HEADER_COMPRESSED(f->header) ? " COMPRESSED" : "",
- (le32toh(f->header->incompatible_flags) & ~HEADER_INCOMPATIBLE_COMPRESSED) ? " ???" : "",
- (unsigned long long) le64toh(f->header->header_size),
- (unsigned long long) le64toh(f->header->arena_size),
- (unsigned long long) le64toh(f->header->data_hash_table_size) / sizeof(HashItem),
- (unsigned long long) le64toh(f->header->field_hash_table_size) / sizeof(HashItem),
- yes_no(journal_file_rotate_suggested(f, 0)),
- (unsigned long long) le64toh(f->header->head_entry_seqnum),
- (unsigned long long) le64toh(f->header->tail_entry_seqnum),
- format_timestamp(x, sizeof(x), le64toh(f->header->head_entry_realtime)),
- format_timestamp(y, sizeof(y), le64toh(f->header->tail_entry_realtime)),
- (unsigned long long) le64toh(f->header->n_objects),
- (unsigned long long) le64toh(f->header->n_entries));
-
- if (JOURNAL_HEADER_CONTAINS(f->header, n_data))
- printf("Data Objects: %llu\n"
- "Data Hash Table Fill: %.1f%%\n",
- (unsigned long long) le64toh(f->header->n_data),
- 100.0 * (double) le64toh(f->header->n_data) / ((double) (le64toh(f->header->data_hash_table_size) / sizeof(HashItem))));
-
- if (JOURNAL_HEADER_CONTAINS(f->header, n_fields))
- printf("Field Objects: %llu\n"
- "Field Hash Table Fill: %.1f%%\n",
- (unsigned long long) le64toh(f->header->n_fields),
- 100.0 * (double) le64toh(f->header->n_fields) / ((double) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem))));
-
- if (JOURNAL_HEADER_CONTAINS(f->header, n_tags))
- printf("Tag Objects: %llu\n",
- (unsigned long long) le64toh(f->header->n_tags));
- if (JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays))
- printf("Entry Array Objects: %llu\n",
- (unsigned long long) le64toh(f->header->n_entry_arrays));
-
- if (fstat(f->fd, &st) >= 0)
- printf("Disk usage: %s\n", format_bytes(bytes, sizeof(bytes), (off_t) st.st_blocks * 512ULL));
-}
-
-int journal_file_open(
- const char *fname,
- int flags,
- mode_t mode,
- bool compress,
- bool seal,
- JournalMetrics *metrics,
- MMapCache *mmap_cache,
- JournalFile *template,
- JournalFile **ret) {
-
- JournalFile *f;
- int r;
- bool newly_created = false;
-
- assert(fname);
- assert(ret);
-
- if ((flags & O_ACCMODE) != O_RDONLY &&
- (flags & O_ACCMODE) != O_RDWR)
- return -EINVAL;
-
- if (!endswith(fname, ".journal") &&
- !endswith(fname, ".journal~"))
- return -EINVAL;
-
- f = new0(JournalFile, 1);
- if (!f)
- return -ENOMEM;
-
- f->fd = -1;
- f->mode = mode;
-
- f->flags = flags;
- f->prot = prot_from_flags(flags);
- f->writable = (flags & O_ACCMODE) != O_RDONLY;
-#ifdef HAVE_XZ
- f->compress = compress;
-#endif
-#ifdef HAVE_GCRYPT
- f->seal = seal;
-#endif
-
- if (mmap_cache)
- f->mmap = mmap_cache_ref(mmap_cache);
- else {
- f->mmap = mmap_cache_new();
- if (!f->mmap) {
- r = -ENOMEM;
- goto fail;
- }
- }
-
- f->path = strdup(fname);
- if (!f->path) {
- r = -ENOMEM;
- goto fail;
- }
-
- f->chain_cache = hashmap_new(uint64_hash_func, uint64_compare_func);
- if (!f->chain_cache) {
- r = -ENOMEM;
- goto fail;
- }
-
- f->fd = open(f->path, f->flags|O_CLOEXEC, f->mode);
- if (f->fd < 0) {
- r = -errno;
- goto fail;
- }
-
- if (fstat(f->fd, &f->last_stat) < 0) {
- r = -errno;
- goto fail;
- }
-
- if (f->last_stat.st_size == 0 && f->writable) {
-#ifdef HAVE_XATTR
- uint64_t crtime;
-
- /* Let's attach the creation time to the journal file,
- * so that the vacuuming code knows the age of this
- * file even if the file might end up corrupted one
- * day... Ideally we'd just use the creation time many
- * file systems maintain for each file, but there is
- * currently no usable API to query this, hence let's
- * emulate this via extended attributes. If extended
- * attributes are not supported we'll just skip this,
- * and rely solely on mtime/atime/ctime of the file.*/
-
- crtime = htole64((uint64_t) now(CLOCK_REALTIME));
- fsetxattr(f->fd, "user.crtime_usec", &crtime, sizeof(crtime), XATTR_CREATE);
-#endif
-
-#ifdef HAVE_GCRYPT
- /* Try to load the FSPRG state, and if we can't, then
- * just don't do sealing */
- if (f->seal) {
- r = journal_file_fss_load(f);
- if (r < 0)
- f->seal = false;
- }
-#endif
-
- r = journal_file_init_header(f, template);
- if (r < 0)
- goto fail;
-
- if (fstat(f->fd, &f->last_stat) < 0) {
- r = -errno;
- goto fail;
- }
-
- newly_created = true;
- }
-
- if (f->last_stat.st_size < (off_t) HEADER_SIZE_MIN) {
- r = -EIO;
- goto fail;
- }
-
- f->header = mmap(NULL, PAGE_ALIGN(sizeof(Header)), prot_from_flags(flags), MAP_SHARED, f->fd, 0);
- if (f->header == MAP_FAILED) {
- f->header = NULL;
- r = -errno;
- goto fail;
- }
-
- if (!newly_created) {
- r = journal_file_verify_header(f);
- if (r < 0)
- goto fail;
- }
-
-#ifdef HAVE_GCRYPT
- if (!newly_created && f->writable) {
- r = journal_file_fss_load(f);
- if (r < 0)
- goto fail;
- }
-#endif
-
- if (f->writable) {
- if (metrics) {
- journal_default_metrics(metrics, f->fd);
- f->metrics = *metrics;
- } else if (template)
- f->metrics = template->metrics;
-
- r = journal_file_refresh_header(f);
- if (r < 0)
- goto fail;
- }
-
-#ifdef HAVE_GCRYPT
- r = journal_file_hmac_setup(f);
- if (r < 0)
- goto fail;
-#endif
-
- if (newly_created) {
- r = journal_file_setup_field_hash_table(f);
- if (r < 0)
- goto fail;
-
- r = journal_file_setup_data_hash_table(f);
- if (r < 0)
- goto fail;
-
-#ifdef HAVE_GCRYPT
- r = journal_file_append_first_tag(f);
- if (r < 0)
- goto fail;
-#endif
- }
-
- r = journal_file_map_field_hash_table(f);
- if (r < 0)
- goto fail;
-
- r = journal_file_map_data_hash_table(f);
- if (r < 0)
- goto fail;
-
- *ret = f;
- return 0;
-
-fail:
- journal_file_close(f);
-
- return r;
-}
-
-int journal_file_rotate(JournalFile **f, bool compress, bool seal) {
- char *p;
- size_t l;
- JournalFile *old_file, *new_file = NULL;
- int r;
-
- assert(f);
- assert(*f);
-
- old_file = *f;
-
- if (!old_file->writable)
- return -EINVAL;
-
- if (!endswith(old_file->path, ".journal"))
- return -EINVAL;
-
- l = strlen(old_file->path);
-
- p = new(char, l + 1 + 32 + 1 + 16 + 1 + 16 + 1);
- if (!p)
- return -ENOMEM;
-
- memcpy(p, old_file->path, l - 8);
- p[l-8] = '@';
- sd_id128_to_string(old_file->header->seqnum_id, p + l - 8 + 1);
- snprintf(p + l - 8 + 1 + 32, 1 + 16 + 1 + 16 + 8 + 1,
- "-%016llx-%016llx.journal",
- (unsigned long long) le64toh((*f)->header->head_entry_seqnum),
- (unsigned long long) le64toh((*f)->header->head_entry_realtime));
-
- r = rename(old_file->path, p);
- free(p);
-
- if (r < 0)
- return -errno;
-
- old_file->header->state = STATE_ARCHIVED;
-
- r = journal_file_open(old_file->path, old_file->flags, old_file->mode, compress, seal, NULL, old_file->mmap, old_file, &new_file);
- journal_file_close(old_file);
-
- *f = new_file;
- return r;
-}
-
-int journal_file_open_reliably(
- const char *fname,
- int flags,
- mode_t mode,
- bool compress,
- bool seal,
- JournalMetrics *metrics,
- MMapCache *mmap_cache,
- JournalFile *template,
- JournalFile **ret) {
-
- int r;
- size_t l;
- char *p;
-
- r = journal_file_open(fname, flags, mode, compress, seal,
- metrics, mmap_cache, template, ret);
- if (r != -EBADMSG && /* corrupted */
- r != -ENODATA && /* truncated */
- r != -EHOSTDOWN && /* other machine */
- r != -EPROTONOSUPPORT && /* incompatible feature */
- r != -EBUSY && /* unclean shutdown */
- r != -ESHUTDOWN /* already archived */)
- return r;
-
- if ((flags & O_ACCMODE) == O_RDONLY)
- return r;
-
- if (!(flags & O_CREAT))
- return r;
-
- if (!endswith(fname, ".journal"))
- return r;
-
- /* The file is corrupted. Rotate it away and try it again (but only once) */
-
- l = strlen(fname);
- if (asprintf(&p, "%.*s@%016llx-%016llx.journal~",
- (int) (l-8), fname,
- (unsigned long long) now(CLOCK_REALTIME),
- random_ull()) < 0)
- return -ENOMEM;
-
- r = rename(fname, p);
- free(p);
- if (r < 0)
- return -errno;
-
- log_warning("File %s corrupted or uncleanly shut down, renaming and replacing.", fname);
-
- return journal_file_open(fname, flags, mode, compress, seal,
- metrics, mmap_cache, template, ret);
-}
-
-
-int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p, uint64_t *seqnum, Object **ret, uint64_t *offset) {
- uint64_t i, n;
- uint64_t q, xor_hash = 0;
- int r;
- EntryItem *items;
- dual_timestamp ts;
-
- assert(from);
- assert(to);
- assert(o);
- assert(p);
-
- if (!to->writable)
- return -EPERM;
-
- ts.monotonic = le64toh(o->entry.monotonic);
- ts.realtime = le64toh(o->entry.realtime);
-
- if (to->tail_entry_monotonic_valid &&
- ts.monotonic < le64toh(to->header->tail_entry_monotonic))
- return -EINVAL;
-
- n = journal_file_entry_n_items(o);
- items = alloca(sizeof(EntryItem) * n);
-
- for (i = 0; i < n; i++) {
- uint64_t l, h;
- le64_t le_hash;
- size_t t;
- void *data;
- Object *u;
-
- q = le64toh(o->entry.items[i].object_offset);
- le_hash = o->entry.items[i].hash;
-
- r = journal_file_move_to_object(from, OBJECT_DATA, q, &o);
- if (r < 0)
- return r;
-
- if (le_hash != o->data.hash)
- return -EBADMSG;
-
- l = le64toh(o->object.size) - offsetof(Object, data.payload);
- t = (size_t) l;
-
- /* We hit the limit on 32bit machines */
- if ((uint64_t) t != l)
- return -E2BIG;
-
- if (o->object.flags & OBJECT_COMPRESSED) {
-#ifdef HAVE_XZ
- uint64_t rsize;
-
- if (!uncompress_blob(o->data.payload, l, &from->compress_buffer, &from->compress_buffer_size, &rsize))
- return -EBADMSG;
-
- data = from->compress_buffer;
- l = rsize;
-#else
- return -EPROTONOSUPPORT;
-#endif
- } else
- data = o->data.payload;
-
- r = journal_file_append_data(to, data, l, &u, &h);
- if (r < 0)
- return r;
-
- xor_hash ^= le64toh(u->data.hash);
- items[i].object_offset = htole64(h);
- items[i].hash = u->data.hash;
-
- r = journal_file_move_to_object(from, OBJECT_ENTRY, p, &o);
- if (r < 0)
- return r;
- }
-
- return journal_file_append_entry_internal(to, &ts, xor_hash, items, n, seqnum, ret, offset);
-}
-
-void journal_default_metrics(JournalMetrics *m, int fd) {
- uint64_t fs_size = 0;
- struct statvfs ss;
- char a[FORMAT_BYTES_MAX], b[FORMAT_BYTES_MAX], c[FORMAT_BYTES_MAX], d[FORMAT_BYTES_MAX];
-
- assert(m);
- assert(fd >= 0);
-
- if (fstatvfs(fd, &ss) >= 0)
- fs_size = ss.f_frsize * ss.f_blocks;
-
- if (m->max_use == (uint64_t) -1) {
-
- if (fs_size > 0) {
- m->max_use = PAGE_ALIGN(fs_size / 10); /* 10% of file system size */
-
- if (m->max_use > DEFAULT_MAX_USE_UPPER)
- m->max_use = DEFAULT_MAX_USE_UPPER;
-
- if (m->max_use < DEFAULT_MAX_USE_LOWER)
- m->max_use = DEFAULT_MAX_USE_LOWER;
- } else
- m->max_use = DEFAULT_MAX_USE_LOWER;
- } else {
- m->max_use = PAGE_ALIGN(m->max_use);
-
- if (m->max_use < JOURNAL_FILE_SIZE_MIN*2)
- m->max_use = JOURNAL_FILE_SIZE_MIN*2;
- }
-
- if (m->max_size == (uint64_t) -1) {
- m->max_size = PAGE_ALIGN(m->max_use / 8); /* 8 chunks */
-
- if (m->max_size > DEFAULT_MAX_SIZE_UPPER)
- m->max_size = DEFAULT_MAX_SIZE_UPPER;
- } else
- m->max_size = PAGE_ALIGN(m->max_size);
-
- if (m->max_size < JOURNAL_FILE_SIZE_MIN)
- m->max_size = JOURNAL_FILE_SIZE_MIN;
-
- if (m->max_size*2 > m->max_use)
- m->max_use = m->max_size*2;
-
- if (m->min_size == (uint64_t) -1)
- m->min_size = JOURNAL_FILE_SIZE_MIN;
- else {
- m->min_size = PAGE_ALIGN(m->min_size);
-
- if (m->min_size < JOURNAL_FILE_SIZE_MIN)
- m->min_size = JOURNAL_FILE_SIZE_MIN;
-
- if (m->min_size > m->max_size)
- m->max_size = m->min_size;
- }
-
- if (m->keep_free == (uint64_t) -1) {
-
- if (fs_size > 0) {
- m->keep_free = PAGE_ALIGN(fs_size / 20); /* 5% of file system size */
-
- if (m->keep_free > DEFAULT_KEEP_FREE_UPPER)
- m->keep_free = DEFAULT_KEEP_FREE_UPPER;
-
- } else
- m->keep_free = DEFAULT_KEEP_FREE;
- }
-
- log_debug("Fixed max_use=%s max_size=%s min_size=%s keep_free=%s",
- format_bytes(a, sizeof(a), m->max_use),
- format_bytes(b, sizeof(b), m->max_size),
- format_bytes(c, sizeof(c), m->min_size),
- format_bytes(d, sizeof(d), m->keep_free));
-}
-
-int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *to) {
- assert(f);
- assert(from || to);
-
- if (from) {
- if (f->header->head_entry_realtime == 0)
- return -ENOENT;
-
- *from = le64toh(f->header->head_entry_realtime);
- }
-
- if (to) {
- if (f->header->tail_entry_realtime == 0)
- return -ENOENT;
-
- *to = le64toh(f->header->tail_entry_realtime);
- }
-
- return 1;
-}
-
-int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot_id, usec_t *from, usec_t *to) {
- char t[9+32+1] = "_BOOT_ID=";
- Object *o;
- uint64_t p;
- int r;
-
- assert(f);
- assert(from || to);
-
- sd_id128_to_string(boot_id, t + 9);
-
- r = journal_file_find_data_object(f, t, strlen(t), &o, &p);
- if (r <= 0)
- return r;
-
- if (le64toh(o->data.n_entries) <= 0)
- return 0;
-
- if (from) {
- r = journal_file_move_to_object(f, OBJECT_ENTRY, le64toh(o->data.entry_offset), &o);
- if (r < 0)
- return r;
-
- *from = le64toh(o->entry.monotonic);
- }
-
- if (to) {
- r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
- if (r < 0)
- return r;
-
- r = generic_array_get_plus_one(f,
- le64toh(o->data.entry_offset),
- le64toh(o->data.entry_array_offset),
- le64toh(o->data.n_entries)-1,
- &o, NULL);
- if (r <= 0)
- return r;
-
- *to = le64toh(o->entry.monotonic);
- }
-
- return 1;
-}
-
-bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec) {
- assert(f);
-
- /* If we gained new header fields we gained new features,
- * hence suggest a rotation */
- if (le64toh(f->header->header_size) < sizeof(Header)) {
- log_debug("%s uses an outdated header, suggesting rotation.", f->path);
- return true;
- }
-
- /* Let's check if the hash tables grew over a certain fill
- * level (75%, borrowing this value from Java's hash table
- * implementation), and if so suggest a rotation. To calculate
- * the fill level we need the n_data field, which only exists
- * in newer versions. */
-
- if (JOURNAL_HEADER_CONTAINS(f->header, n_data))
- if (le64toh(f->header->n_data) * 4ULL > (le64toh(f->header->data_hash_table_size) / sizeof(HashItem)) * 3ULL) {
- log_debug("Data hash table of %s has a fill level at %.1f (%llu of %llu items, %llu file size, %llu bytes per hash table item), suggesting rotation.",
- f->path,
- 100.0 * (double) le64toh(f->header->n_data) / ((double) (le64toh(f->header->data_hash_table_size) / sizeof(HashItem))),
- (unsigned long long) le64toh(f->header->n_data),
- (unsigned long long) (le64toh(f->header->data_hash_table_size) / sizeof(HashItem)),
- (unsigned long long) (f->last_stat.st_size),
- (unsigned long long) (f->last_stat.st_size / le64toh(f->header->n_data)));
- return true;
- }
-
- if (JOURNAL_HEADER_CONTAINS(f->header, n_fields))
- if (le64toh(f->header->n_fields) * 4ULL > (le64toh(f->header->field_hash_table_size) / sizeof(HashItem)) * 3ULL) {
- log_debug("Field hash table of %s has a fill level at %.1f (%llu of %llu items), suggesting rotation.",
- f->path,
- 100.0 * (double) le64toh(f->header->n_fields) / ((double) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem))),
- (unsigned long long) le64toh(f->header->n_fields),
- (unsigned long long) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem)));
- return true;
- }
-
- /* Are the data objects properly indexed by field objects? */
- if (JOURNAL_HEADER_CONTAINS(f->header, n_data) &&
- JOURNAL_HEADER_CONTAINS(f->header, n_fields) &&
- le64toh(f->header->n_data) > 0 &&
- le64toh(f->header->n_fields) == 0)
- return true;
-
- if (max_file_usec > 0) {
- usec_t t, h;
-
- h = le64toh(f->header->head_entry_realtime);
- t = now(CLOCK_REALTIME);
-
- if (h > 0 && t > h + max_file_usec)
- return true;
- }
-
- return false;
-}
diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h
deleted file mode 100644
index cdbc8e41f6..0000000000
--- a/src/journal/journal-file.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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>
-
-#ifdef HAVE_GCRYPT
-#include <gcrypt.h>
-#endif
-
-#include <systemd/sd-id128.h>
-
-#include "sparse-endian.h"
-#include "journal-def.h"
-#include "util.h"
-#include "mmap-cache.h"
-#include "hashmap.h"
-
-typedef struct JournalMetrics {
- uint64_t max_use;
- uint64_t max_size;
- uint64_t min_size;
- uint64_t keep_free;
-} JournalMetrics;
-
-typedef struct JournalFile {
- int fd;
- char *path;
- struct stat last_stat;
- mode_t mode;
-
- int flags;
- int prot;
- bool writable;
- bool compress;
- bool seal;
-
- bool tail_entry_monotonic_valid;
-
- Header *header;
- HashItem *data_hash_table;
- HashItem *field_hash_table;
-
- uint64_t current_offset;
-
- JournalMetrics metrics;
- MMapCache *mmap;
-
- Hashmap *chain_cache;
-
-#ifdef HAVE_XZ
- void *compress_buffer;
- uint64_t compress_buffer_size;
-#endif
-
-#ifdef HAVE_GCRYPT
- gcry_md_hd_t hmac;
- bool hmac_running;
-
- FSSHeader *fss_file;
- size_t fss_file_size;
-
- uint64_t fss_start_usec;
- uint64_t fss_interval_usec;
-
- void *fsprg_state;
- size_t fsprg_state_size;
-
- void *fsprg_seed;
- size_t fsprg_seed_size;
-#endif
-} JournalFile;
-
-typedef enum direction {
- DIRECTION_UP,
- DIRECTION_DOWN
-} direction_t;
-
-int journal_file_open(
- const char *fname,
- int flags,
- mode_t mode,
- bool compress,
- bool seal,
- JournalMetrics *metrics,
- MMapCache *mmap_cache,
- JournalFile *template,
- JournalFile **ret);
-
-void journal_file_close(JournalFile *j);
-
-int journal_file_open_reliably(
- const char *fname,
- int flags,
- mode_t mode,
- bool compress,
- bool seal,
- JournalMetrics *metrics,
- MMapCache *mmap_cache,
- JournalFile *template,
- JournalFile **ret);
-
-#define ALIGN64(x) (((x) + 7ULL) & ~7ULL)
-#define VALID64(x) (((x) & 7ULL) == 0ULL)
-
-static inline bool VALID_REALTIME(uint64_t u) {
- /* This considers timestamps until the year 3112 valid. That should be plenty room... */
- return u > 0 && u < (1ULL << 55);
-}
-
-static inline bool VALID_MONOTONIC(uint64_t u) {
- /* This considers timestamps until 1142 years of runtime valid. */
- return u < (1ULL << 55);
-}
-
-static inline bool VALID_EPOCH(uint64_t u) {
- /* This allows changing the key for 1142 years, every usec. */
- return u < (1ULL << 55);
-}
-
-#define JOURNAL_HEADER_CONTAINS(h, field) \
- (le64toh((h)->header_size) >= offsetof(Header, field) + sizeof((h)->field))
-
-#define JOURNAL_HEADER_SEALED(h) \
- (!!(le32toh((h)->compatible_flags) & HEADER_COMPATIBLE_SEALED))
-
-#define JOURNAL_HEADER_COMPRESSED(h) \
- (!!(le32toh((h)->incompatible_flags) & HEADER_INCOMPATIBLE_COMPRESSED))
-
-int journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Object **ret);
-
-uint64_t journal_file_entry_n_items(Object *o);
-uint64_t journal_file_entry_array_n_items(Object *o);
-uint64_t journal_file_hash_table_n_items(Object *o);
-
-int journal_file_append_object(JournalFile *f, int type, uint64_t size, Object **ret, uint64_t *offset);
-int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, uint64_t *seqno, Object **ret, uint64_t *offset);
-
-int journal_file_find_data_object(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset);
-int journal_file_find_data_object_with_hash(JournalFile *f, const void *data, uint64_t size, uint64_t hash, Object **ret, uint64_t *offset);
-
-int journal_file_find_field_object(JournalFile *f, const void *field, uint64_t size, Object **ret, uint64_t *offset);
-int journal_file_find_field_object_with_hash(JournalFile *f, const void *field, uint64_t size, uint64_t hash, Object **ret, uint64_t *offset);
-
-int journal_file_next_entry(JournalFile *f, Object *o, uint64_t p, direction_t direction, Object **ret, uint64_t *offset);
-int journal_file_skip_entry(JournalFile *f, Object *o, uint64_t p, int64_t skip, Object **ret, uint64_t *offset);
-
-int journal_file_next_entry_for_data(JournalFile *f, Object *o, uint64_t p, uint64_t data_offset, direction_t direction, Object **ret, uint64_t *offset);
-
-int journal_file_move_to_entry_by_offset(JournalFile *f, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset);
-int journal_file_move_to_entry_by_seqnum(JournalFile *f, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset);
-int journal_file_move_to_entry_by_realtime(JournalFile *f, uint64_t realtime, direction_t direction, Object **ret, uint64_t *offset);
-int journal_file_move_to_entry_by_monotonic(JournalFile *f, sd_id128_t boot_id, uint64_t monotonic, direction_t direction, Object **ret, uint64_t *offset);
-
-int journal_file_move_to_entry_by_offset_for_data(JournalFile *f, uint64_t data_offset, uint64_t p, direction_t direction, Object **ret, uint64_t *offset);
-int journal_file_move_to_entry_by_seqnum_for_data(JournalFile *f, uint64_t data_offset, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset);
-int journal_file_move_to_entry_by_realtime_for_data(JournalFile *f, uint64_t data_offset, uint64_t realtime, direction_t direction, Object **ret, uint64_t *offset);
-int journal_file_move_to_entry_by_monotonic_for_data(JournalFile *f, uint64_t data_offset, sd_id128_t boot_id, uint64_t monotonic, direction_t direction, Object **ret, uint64_t *offset);
-
-int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p, uint64_t *seqnum, Object **ret, uint64_t *offset);
-
-void journal_file_dump(JournalFile *f);
-void journal_file_print_header(JournalFile *f);
-
-int journal_file_rotate(JournalFile **f, bool compress, bool seal);
-
-void journal_file_post_change(JournalFile *f);
-
-void journal_default_metrics(JournalMetrics *m, int fd);
-
-int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *to);
-int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot, usec_t *from, usec_t *to);
-
-bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec);
diff --git a/src/journal/journal-gatewayd.c b/src/journal/journal-gatewayd.c
deleted file mode 100644
index 35462795c2..0000000000
--- a/src/journal/journal-gatewayd.c
+++ /dev/null
@@ -1,916 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include <microhttpd.h>
-
-#include "log.h"
-#include "util.h"
-#include "sd-journal.h"
-#include "sd-daemon.h"
-#include "logs-show.h"
-#include "virt.h"
-
-typedef struct RequestMeta {
- sd_journal *journal;
-
- OutputMode mode;
-
- char *cursor;
- int64_t n_skip;
- uint64_t n_entries;
- bool n_entries_set;
-
- FILE *tmp;
- uint64_t delta, size;
-
- int argument_parse_error;
-
- bool follow;
- bool discrete;
-
- uint64_t n_fields;
- bool n_fields_set;
-} RequestMeta;
-
-static const char* const mime_types[_OUTPUT_MODE_MAX] = {
- [OUTPUT_SHORT] = "text/plain",
- [OUTPUT_JSON] = "application/json",
- [OUTPUT_JSON_SSE] = "text/event-stream",
- [OUTPUT_EXPORT] = "application/vnd.fdo.journal",
-};
-
-static RequestMeta *request_meta(void **connection_cls) {
- RequestMeta *m;
-
- if (*connection_cls)
- return *connection_cls;
-
- m = new0(RequestMeta, 1);
- if (!m)
- return NULL;
-
- *connection_cls = m;
- return m;
-}
-
-static void request_meta_free(
- void *cls,
- struct MHD_Connection *connection,
- void **connection_cls,
- enum MHD_RequestTerminationCode toe) {
-
- RequestMeta *m = *connection_cls;
-
- if (!m)
- return;
-
- if (m->journal)
- sd_journal_close(m->journal);
-
- if (m->tmp)
- fclose(m->tmp);
-
- free(m->cursor);
- free(m);
-}
-
-static int open_journal(RequestMeta *m) {
- assert(m);
-
- if (m->journal)
- return 0;
-
- return sd_journal_open(&m->journal, SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM_ONLY);
-}
-
-
-static int respond_oom(struct MHD_Connection *connection) {
- struct MHD_Response *response;
- const char m[] = "Out of memory.\n";
- int ret;
-
- assert(connection);
-
- response = MHD_create_response_from_buffer(sizeof(m)-1, (char*) m, MHD_RESPMEM_PERSISTENT);
- if (!response)
- return MHD_NO;
-
- MHD_add_response_header(response, "Content-Type", "text/plain");
- ret = MHD_queue_response(connection, MHD_HTTP_SERVICE_UNAVAILABLE, response);
- MHD_destroy_response(response);
-
- return ret;
-}
-
-static int respond_error(
- struct MHD_Connection *connection,
- unsigned code,
- const char *format, ...) {
-
- struct MHD_Response *response;
- char *m;
- int r;
- va_list ap;
-
- assert(connection);
- assert(format);
-
- va_start(ap, format);
- r = vasprintf(&m, format, ap);
- va_end(ap);
-
- if (r < 0)
- return respond_oom(connection);
-
- response = MHD_create_response_from_buffer(strlen(m), m, MHD_RESPMEM_MUST_FREE);
- if (!response) {
- free(m);
- return respond_oom(connection);
- }
-
- MHD_add_response_header(response, "Content-Type", "text/plain");
- r = MHD_queue_response(connection, code, response);
- MHD_destroy_response(response);
-
- return r;
-}
-
-static ssize_t request_reader_entries(
- void *cls,
- uint64_t pos,
- char *buf,
- size_t max) {
-
- RequestMeta *m = cls;
- int r;
- size_t n, k;
-
- assert(m);
- assert(buf);
- assert(max > 0);
- assert(pos >= m->delta);
-
- pos -= m->delta;
-
- while (pos >= m->size) {
- off_t sz;
-
- /* End of this entry, so let's serialize the next
- * one */
-
- if (m->n_entries_set &&
- m->n_entries <= 0)
- return MHD_CONTENT_READER_END_OF_STREAM;
-
- if (m->n_skip < 0)
- r = sd_journal_previous_skip(m->journal, (uint64_t) -m->n_skip + 1);
- else if (m->n_skip > 0)
- r = sd_journal_next_skip(m->journal, (uint64_t) m->n_skip + 1);
- else
- r = sd_journal_next(m->journal);
-
- if (r < 0) {
- log_error("Failed to advance journal pointer: %s", strerror(-r));
- return MHD_CONTENT_READER_END_WITH_ERROR;
- } else if (r == 0) {
-
- if (m->follow) {
- r = sd_journal_wait(m->journal, (uint64_t) -1);
- if (r < 0) {
- log_error("Couldn't wait for journal event: %s", strerror(-r));
- return MHD_CONTENT_READER_END_WITH_ERROR;
- }
-
- continue;
- }
-
- return MHD_CONTENT_READER_END_OF_STREAM;
- }
-
- if (m->discrete) {
- assert(m->cursor);
-
- r = sd_journal_test_cursor(m->journal, m->cursor);
- if (r < 0) {
- log_error("Failed to test cursor: %s", strerror(-r));
- return MHD_CONTENT_READER_END_WITH_ERROR;
- }
-
- if (r == 0)
- return MHD_CONTENT_READER_END_OF_STREAM;
- }
-
- pos -= m->size;
- m->delta += m->size;
-
- if (m->n_entries_set)
- m->n_entries -= 1;
-
- m->n_skip = 0;
-
- if (m->tmp)
- rewind(m->tmp);
- else {
- m->tmp = tmpfile();
- if (!m->tmp) {
- log_error("Failed to create temporary file: %m");
- return MHD_CONTENT_READER_END_WITH_ERROR;
- }
- }
-
- r = output_journal(m->tmp, m->journal, m->mode, 0, OUTPUT_FULL_WIDTH);
- if (r < 0) {
- log_error("Failed to serialize item: %s", strerror(-r));
- return MHD_CONTENT_READER_END_WITH_ERROR;
- }
-
- sz = ftello(m->tmp);
- if (sz == (off_t) -1) {
- log_error("Failed to retrieve file position: %m");
- return MHD_CONTENT_READER_END_WITH_ERROR;
- }
-
- m->size = (uint64_t) sz;
- }
-
- if (fseeko(m->tmp, pos, SEEK_SET) < 0) {
- log_error("Failed to seek to position: %m");
- return MHD_CONTENT_READER_END_WITH_ERROR;
- }
-
- n = m->size - pos;
- if (n > max)
- n = max;
-
- errno = 0;
- k = fread(buf, 1, n, m->tmp);
- if (k != n) {
- log_error("Failed to read from file: %s", errno ? strerror(errno) : "Premature EOF");
- return MHD_CONTENT_READER_END_WITH_ERROR;
- }
-
- return (ssize_t) k;
-}
-
-static int request_parse_accept(
- RequestMeta *m,
- struct MHD_Connection *connection) {
-
- const char *header;
-
- assert(m);
- assert(connection);
-
- header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Accept");
- if (!header)
- return 0;
-
- if (streq(header, mime_types[OUTPUT_JSON]))
- m->mode = OUTPUT_JSON;
- else if (streq(header, mime_types[OUTPUT_JSON_SSE]))
- m->mode = OUTPUT_JSON_SSE;
- else if (streq(header, mime_types[OUTPUT_EXPORT]))
- m->mode = OUTPUT_EXPORT;
- else
- m->mode = OUTPUT_SHORT;
-
- return 0;
-}
-
-static int request_parse_range(
- RequestMeta *m,
- struct MHD_Connection *connection) {
-
- const char *range, *colon, *colon2;
- int r;
-
- assert(m);
- assert(connection);
-
- range = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Range");
- if (!range)
- return 0;
-
- if (!startswith(range, "entries="))
- return 0;
-
- range += 8;
- range += strspn(range, WHITESPACE);
-
- colon = strchr(range, ':');
- if (!colon)
- m->cursor = strdup(range);
- else {
- const char *p;
-
- colon2 = strchr(colon + 1, ':');
- if (colon2) {
- char *t;
-
- t = strndup(colon + 1, colon2 - colon - 1);
- if (!t)
- return -ENOMEM;
-
- r = safe_atoi64(t, &m->n_skip);
- free(t);
- if (r < 0)
- return r;
- }
-
- p = (colon2 ? colon2 : colon) + 1;
- if (*p) {
- r = safe_atou64(p, &m->n_entries);
- if (r < 0)
- return r;
-
- if (m->n_entries <= 0)
- return -EINVAL;
-
- m->n_entries_set = true;
- }
-
- m->cursor = strndup(range, colon - range);
- }
-
- if (!m->cursor)
- return -ENOMEM;
-
- m->cursor[strcspn(m->cursor, WHITESPACE)] = 0;
- if (isempty(m->cursor)) {
- free(m->cursor);
- m->cursor = NULL;
- }
-
- return 0;
-}
-
-static int request_parse_arguments_iterator(
- void *cls,
- enum MHD_ValueKind kind,
- const char *key,
- const char *value) {
-
- RequestMeta *m = cls;
- _cleanup_free_ char *p = NULL;
- int r;
-
- assert(m);
-
- if (isempty(key)) {
- m->argument_parse_error = -EINVAL;
- return MHD_NO;
- }
-
- if (streq(key, "follow")) {
- if (isempty(value)) {
- m->follow = true;
- return MHD_YES;
- }
-
- r = parse_boolean(value);
- if (r < 0) {
- m->argument_parse_error = r;
- return MHD_NO;
- }
-
- m->follow = r;
- return MHD_YES;
- }
-
- if (streq(key, "discrete")) {
- if (isempty(value)) {
- m->discrete = true;
- return MHD_YES;
- }
-
- r = parse_boolean(value);
- if (r < 0) {
- m->argument_parse_error = r;
- return MHD_NO;
- }
-
- m->discrete = r;
- return MHD_YES;
- }
-
- if (streq(key, "boot")) {
- if (isempty(value))
- r = true;
- else {
- r = parse_boolean(value);
- if (r < 0) {
- m->argument_parse_error = r;
- return MHD_NO;
- }
- }
-
- if (r) {
- char match[9 + 32 + 1] = "_BOOT_ID=";
- sd_id128_t bid;
-
- r = sd_id128_get_boot(&bid);
- if (r < 0) {
- log_error("Failed to get boot ID: %s", strerror(-r));
- return MHD_NO;
- }
-
- sd_id128_to_string(bid, match + 9);
- r = sd_journal_add_match(m->journal, match, sizeof(match)-1);
- if (r < 0) {
- m->argument_parse_error = r;
- return MHD_NO;
- }
- }
-
- return MHD_YES;
- }
-
- p = strjoin(key, "=", strempty(value), NULL);
- if (!p) {
- m->argument_parse_error = log_oom();
- return MHD_NO;
- }
-
- r = sd_journal_add_match(m->journal, p, 0);
- if (r < 0) {
- m->argument_parse_error = r;
- return MHD_NO;
- }
-
- return MHD_YES;
-}
-
-static int request_parse_arguments(
- RequestMeta *m,
- struct MHD_Connection *connection) {
-
- assert(m);
- assert(connection);
-
- m->argument_parse_error = 0;
- MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, request_parse_arguments_iterator, m);
-
- return m->argument_parse_error;
-}
-
-static int request_handler_entries(
- struct MHD_Connection *connection,
- void **connection_cls) {
-
- struct MHD_Response *response;
- RequestMeta *m;
- int r;
-
- assert(connection);
- assert(connection_cls);
-
- m = request_meta(connection_cls);
- if (!m)
- return respond_oom(connection);
-
- r = open_journal(m);
- if (r < 0)
- return respond_error(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %s\n", strerror(-r));
-
- if (request_parse_accept(m, connection) < 0)
- return respond_error(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Accept header.\n");
-
- if (request_parse_range(m, connection) < 0)
- return respond_error(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Range header.\n");
-
- if (request_parse_arguments(m, connection) < 0)
- return respond_error(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse URL arguments.\n");
-
- if (m->discrete) {
- if (!m->cursor)
- return respond_error(connection, MHD_HTTP_BAD_REQUEST, "Discrete seeks require a cursor specification.\n");
-
- m->n_entries = 1;
- m->n_entries_set = true;
- }
-
- if (m->cursor)
- r = sd_journal_seek_cursor(m->journal, m->cursor);
- else if (m->n_skip >= 0)
- r = sd_journal_seek_head(m->journal);
- else if (m->n_skip < 0)
- r = sd_journal_seek_tail(m->journal);
- if (r < 0)
- return respond_error(connection, MHD_HTTP_BAD_REQUEST, "Failed to seek in journal.\n");
-
- response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, 4*1024, request_reader_entries, m, NULL);
- if (!response)
- return respond_oom(connection);
-
- MHD_add_response_header(response, "Content-Type", mime_types[m->mode]);
-
- r = MHD_queue_response(connection, MHD_HTTP_OK, response);
- MHD_destroy_response(response);
-
- return r;
-}
-
-static int output_field(FILE *f, OutputMode m, const char *d, size_t l) {
- const char *eq;
- size_t j;
-
- eq = memchr(d, '=', l);
- if (!eq)
- return -EINVAL;
-
- j = l - (eq - d + 1);
-
- if (m == OUTPUT_JSON) {
- fprintf(f, "{ \"%.*s\" : ", (int) (eq - d), d);
- json_escape(f, eq+1, j, OUTPUT_FULL_WIDTH);
- fputs(" }\n", f);
- } else {
- fwrite(eq+1, 1, j, f);
- fputc('\n', f);
- }
-
- return 0;
-}
-
-static ssize_t request_reader_fields(
- void *cls,
- uint64_t pos,
- char *buf,
- size_t max) {
-
- RequestMeta *m = cls;
- int r;
- size_t n, k;
-
- assert(m);
- assert(buf);
- assert(max > 0);
- assert(pos >= m->delta);
-
- pos -= m->delta;
-
- while (pos >= m->size) {
- off_t sz;
- const void *d;
- size_t l;
-
- /* End of this field, so let's serialize the next
- * one */
-
- if (m->n_fields_set &&
- m->n_fields <= 0)
- return MHD_CONTENT_READER_END_OF_STREAM;
-
- r = sd_journal_enumerate_unique(m->journal, &d, &l);
- if (r < 0) {
- log_error("Failed to advance field index: %s", strerror(-r));
- return MHD_CONTENT_READER_END_WITH_ERROR;
- } else if (r == 0)
- return MHD_CONTENT_READER_END_OF_STREAM;
-
- pos -= m->size;
- m->delta += m->size;
-
- if (m->n_fields_set)
- m->n_fields -= 1;
-
- if (m->tmp)
- rewind(m->tmp);
- else {
- m->tmp = tmpfile();
- if (!m->tmp) {
- log_error("Failed to create temporary file: %m");
- return MHD_CONTENT_READER_END_WITH_ERROR;
- }
- }
-
- r = output_field(m->tmp, m->mode, d, l);
- if (r < 0) {
- log_error("Failed to serialize item: %s", strerror(-r));
- return MHD_CONTENT_READER_END_WITH_ERROR;
- }
-
- sz = ftello(m->tmp);
- if (sz == (off_t) -1) {
- log_error("Failed to retrieve file position: %m");
- return MHD_CONTENT_READER_END_WITH_ERROR;
- }
-
- m->size = (uint64_t) sz;
- }
-
- if (fseeko(m->tmp, pos, SEEK_SET) < 0) {
- log_error("Failed to seek to position: %m");
- return MHD_CONTENT_READER_END_WITH_ERROR;
- }
-
- n = m->size - pos;
- if (n > max)
- n = max;
-
- errno = 0;
- k = fread(buf, 1, n, m->tmp);
- if (k != n) {
- log_error("Failed to read from file: %s", errno ? strerror(errno) : "Premature EOF");
- return MHD_CONTENT_READER_END_WITH_ERROR;
- }
-
- return (ssize_t) k;
-}
-
-static int request_handler_fields(
- struct MHD_Connection *connection,
- const char *field,
- void *connection_cls) {
-
- struct MHD_Response *response;
- RequestMeta *m;
- int r;
-
- assert(connection);
- assert(connection_cls);
-
- m = request_meta(connection_cls);
- if (!m)
- return respond_oom(connection);
-
- r = open_journal(m);
- if (r < 0)
- return respond_error(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %s\n", strerror(-r));
-
- if (request_parse_accept(m, connection) < 0)
- return respond_error(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Accept header.\n");
-
- r = sd_journal_query_unique(m->journal, field);
- if (r < 0)
- return respond_error(connection, MHD_HTTP_BAD_REQUEST, "Failed to query unique fields.\n");
-
- response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, 4*1024, request_reader_fields, m, NULL);
- if (!response)
- return respond_oom(connection);
-
- MHD_add_response_header(response, "Content-Type", mime_types[m->mode == OUTPUT_JSON ? OUTPUT_JSON : OUTPUT_SHORT]);
-
- r = MHD_queue_response(connection, MHD_HTTP_OK, response);
- MHD_destroy_response(response);
-
- return r;
-}
-
-static int request_handler_redirect(
- struct MHD_Connection *connection,
- const char *target) {
-
- char *page;
- struct MHD_Response *response;
- int ret;
-
- assert(connection);
- assert(target);
-
- if (asprintf(&page, "<html><body>Please continue to the <a href=\"%s\">journal browser</a>.</body></html>", target) < 0)
- return respond_oom(connection);
-
- response = MHD_create_response_from_buffer(strlen(page), page, MHD_RESPMEM_MUST_FREE);
- if (!response) {
- free(page);
- return respond_oom(connection);
- }
-
- MHD_add_response_header(response, "Content-Type", "text/html");
- MHD_add_response_header(response, "Location", target);
-
- ret = MHD_queue_response(connection, MHD_HTTP_MOVED_PERMANENTLY, response);
- MHD_destroy_response(response);
-
- return ret;
-}
-
-static int request_handler_file(
- struct MHD_Connection *connection,
- const char *path,
- const char *mime_type) {
-
- struct MHD_Response *response;
- int ret;
- _cleanup_close_ int fd = -1;
- struct stat st;
-
- assert(connection);
- assert(path);
- assert(mime_type);
-
- fd = open(path, O_RDONLY|O_CLOEXEC);
- if (fd < 0)
- return respond_error(connection, MHD_HTTP_NOT_FOUND, "Failed to open file %s: %m\n", path);
-
- if (fstat(fd, &st) < 0)
- return respond_error(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to stat file: %m\n");
-
- response = MHD_create_response_from_fd_at_offset(st.st_size, fd, 0);
- if (!response)
- return respond_oom(connection);
-
- fd = -1;
-
- MHD_add_response_header(response, "Content-Type", mime_type);
-
- ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
- MHD_destroy_response(response);
-
- return ret;
-}
-
-static int request_handler_machine(
- struct MHD_Connection *connection,
- void **connection_cls) {
-
- struct MHD_Response *response;
- RequestMeta *m;
- int r;
- _cleanup_free_ char* hostname = NULL, *os_name = NULL;
- uint64_t cutoff_from, cutoff_to, usage;
- char *json;
- sd_id128_t mid, bid;
- const char *v = "bare";
-
- assert(connection);
-
- m = request_meta(connection_cls);
- if (!m)
- return respond_oom(connection);
-
- r = open_journal(m);
- if (r < 0)
- return respond_error(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %s\n", strerror(-r));
-
- r = sd_id128_get_machine(&mid);
- if (r < 0)
- return respond_error(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine machine ID: %s\n", strerror(-r));
-
- r = sd_id128_get_boot(&bid);
- if (r < 0)
- return respond_error(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine boot ID: %s\n", strerror(-r));
-
- hostname = gethostname_malloc();
- if (!hostname)
- return respond_oom(connection);
-
- r = sd_journal_get_usage(m->journal, &usage);
- if (r < 0)
- return respond_error(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %s\n", strerror(-r));
-
- r = sd_journal_get_cutoff_realtime_usec(m->journal, &cutoff_from, &cutoff_to);
- if (r < 0)
- return respond_error(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %s\n", strerror(-r));
-
- parse_env_file("/etc/os-release", NEWLINE, "PRETTY_NAME", &os_name, NULL);
-
- detect_virtualization(&v);
-
- r = asprintf(&json,
- "{ \"machine_id\" : \"" SD_ID128_FORMAT_STR "\","
- "\"boot_id\" : \"" SD_ID128_FORMAT_STR "\","
- "\"hostname\" : \"%s\","
- "\"os_pretty_name\" : \"%s\","
- "\"virtualization\" : \"%s\","
- "\"usage\" : \"%llu\","
- "\"cutoff_from_realtime\" : \"%llu\","
- "\"cutoff_to_realtime\" : \"%llu\" }\n",
- SD_ID128_FORMAT_VAL(mid),
- SD_ID128_FORMAT_VAL(bid),
- hostname_cleanup(hostname),
- os_name ? os_name : "Linux",
- v,
- (unsigned long long) usage,
- (unsigned long long) cutoff_from,
- (unsigned long long) cutoff_to);
-
- if (r < 0)
- return respond_oom(connection);
-
- response = MHD_create_response_from_buffer(strlen(json), json, MHD_RESPMEM_MUST_FREE);
- if (!response) {
- free(json);
- return respond_oom(connection);
- }
-
- MHD_add_response_header(response, "Content-Type", "application/json");
- r = MHD_queue_response(connection, MHD_HTTP_OK, response);
- MHD_destroy_response(response);
-
- return r;
-}
-
-static int request_handler(
- void *cls,
- struct MHD_Connection *connection,
- const char *url,
- const char *method,
- const char *version,
- const char *upload_data,
- size_t *upload_data_size,
- void **connection_cls) {
-
- assert(connection);
- assert(url);
- assert(method);
-
- if (!streq(method, "GET"))
- return MHD_NO;
-
- if (streq(url, "/"))
- return request_handler_redirect(connection, "/browse");
-
- if (streq(url, "/entries"))
- return request_handler_entries(connection, connection_cls);
-
- if (startswith(url, "/fields/"))
- return request_handler_fields(connection, url + 8, connection_cls);
-
- if (streq(url, "/browse"))
- return request_handler_file(connection, DOCUMENT_ROOT "/browse.html", "text/html");
-
- if (streq(url, "/machine"))
- return request_handler_machine(connection, connection_cls);
-
- return respond_error(connection, MHD_HTTP_NOT_FOUND, "Not found.\n");
-}
-
-int main(int argc, char *argv[]) {
- struct MHD_Daemon *d = NULL;
- int r = EXIT_FAILURE, n;
-
- if (argc > 1) {
- log_error("This program does not take arguments.");
- goto finish;
- }
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- n = sd_listen_fds(1);
- if (n < 0) {
- log_error("Failed to determine passed sockets: %s", strerror(-n));
- goto finish;
- } else if (n > 1) {
- log_error("Can't listen on more than one socket.");
- goto finish;
- } else if (n > 0) {
- d = MHD_start_daemon(
- MHD_USE_THREAD_PER_CONNECTION|MHD_USE_POLL|MHD_USE_DEBUG,
- 19531,
- NULL, NULL,
- request_handler, NULL,
- MHD_OPTION_LISTEN_SOCKET, SD_LISTEN_FDS_START,
- MHD_OPTION_NOTIFY_COMPLETED, request_meta_free, NULL,
- MHD_OPTION_END);
- } else {
- d = MHD_start_daemon(
- MHD_USE_DEBUG|MHD_USE_THREAD_PER_CONNECTION|MHD_USE_POLL,
- 19531,
- NULL, NULL,
- request_handler, NULL,
- MHD_OPTION_NOTIFY_COMPLETED, request_meta_free, NULL,
- MHD_OPTION_END);
- }
-
- if (!d) {
- log_error("Failed to start daemon!");
- goto finish;
- }
-
- pause();
-
- r = EXIT_SUCCESS;
-
-finish:
- if (d)
- MHD_stop_daemon(d);
-
- return r;
-}
diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h
deleted file mode 100644
index 75a4129e5b..0000000000
--- a/src/journal/journal-internal.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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/types.h>
-#include <inttypes.h>
-#include <stdbool.h>
-
-#include <systemd/sd-id128.h>
-
-#include "journal-def.h"
-#include "list.h"
-#include "hashmap.h"
-#include "journal-file.h"
-
-typedef struct Match Match;
-typedef struct Location Location;
-typedef struct Directory Directory;
-
-typedef enum MatchType {
- MATCH_DISCRETE,
- MATCH_OR_TERM,
- MATCH_AND_TERM
-} MatchType;
-
-struct Match {
- MatchType type;
- Match *parent;
- LIST_FIELDS(Match, matches);
-
- /* For concrete matches */
- char *data;
- size_t size;
- le64_t le_hash;
-
- /* For terms */
- LIST_HEAD(Match, matches);
-};
-
-typedef enum LocationType {
- /* The first and last entries, resp. */
- LOCATION_HEAD,
- LOCATION_TAIL,
-
- /* We already read the entry we currently point to, and the
- * next one to read should probably not be this one again. */
- LOCATION_DISCRETE,
-
- /* We should seek to the precise location specified, and
- * return it, as we haven't read it yet. */
- LOCATION_SEEK
-} LocationType;
-
-struct Location {
- LocationType type;
-
- uint64_t seqnum;
- sd_id128_t seqnum_id;
- bool seqnum_set;
-
- uint64_t realtime;
- bool realtime_set;
-
- uint64_t monotonic;
- sd_id128_t boot_id;
- bool monotonic_set;
-
- uint64_t xor_hash;
- bool xor_hash_set;
-};
-
-struct Directory {
- char *path;
- int wd;
- bool is_root;
-};
-
-struct sd_journal {
- int flags;
-
- char *path;
-
- Hashmap *files;
- MMapCache *mmap;
-
- Location current_location;
-
- JournalFile *current_file;
- uint64_t current_field;
-
- Hashmap *directories_by_path;
- Hashmap *directories_by_wd;
-
- int inotify_fd;
-
- Match *level0, *level1;
-
- unsigned current_invalidate_counter, last_invalidate_counter;
-
- char *unique_field;
- JournalFile *unique_file;
- uint64_t unique_offset;
-
- bool on_network;
-};
-
-char *journal_make_match_string(sd_journal *j);
-void journal_print_header(sd_journal *j);
diff --git a/src/journal/journal-qrcode.c b/src/journal/journal-qrcode.c
deleted file mode 100644
index 10a14e4def..0000000000
--- a/src/journal/journal-qrcode.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <assert.h>
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <stdbool.h>
-
-#include <qrencode.h>
-
-#include "journal-qrcode.h"
-
-#define WHITE_ON_BLACK "\033[40;37;1m"
-#define NORMAL "\033[0m"
-
-static void print_border(FILE *output, unsigned width) {
- unsigned x, y;
-
- /* Four rows of border */
- for (y = 0; y < 4; y += 2) {
- fputs(WHITE_ON_BLACK, output);
-
- for (x = 0; x < 4 + width + 4; x++)
- fputs("\342\226\210", output);
-
- fputs(NORMAL "\n", output);
- }
-}
-
-int print_qr_code(
- FILE *output,
- const void *seed,
- size_t seed_size,
- uint64_t start,
- uint64_t interval,
- const char *hn,
- sd_id128_t machine) {
-
- FILE *f;
- char *url = NULL;
- size_t url_size = 0, i;
- QRcode* qr;
- unsigned x, y;
-
- assert(seed);
- assert(seed_size > 0);
-
- f = open_memstream(&url, &url_size);
- if (!f)
- return -ENOMEM;
-
- fputs("fss://", f);
-
- for (i = 0; i < seed_size; i++) {
- if (i > 0 && i % 3 == 0)
- fputc('-', f);
- fprintf(f, "%02x", ((uint8_t*) seed)[i]);
- }
-
- fprintf(f, "/%llx-%llx?machine=" SD_ID128_FORMAT_STR,
- (unsigned long long) start,
- (unsigned long long) interval,
- SD_ID128_FORMAT_VAL(machine));
-
- if (hn)
- fprintf(f, ";hostname=%s", hn);
-
- if (ferror(f)) {
- fclose(f);
- free(url);
- return -ENOMEM;
- }
-
- fclose(f);
-
- qr = QRcode_encodeString(url, 0, QR_ECLEVEL_L, QR_MODE_8, 1);
- free(url);
-
- if (!qr)
- return -ENOMEM;
-
- print_border(output, qr->width);
-
- for (y = 0; y < (unsigned) qr->width; y += 2) {
- const uint8_t *row1, *row2;
-
- row1 = qr->data + qr->width * y;
- row2 = row1 + qr->width;
-
- fputs(WHITE_ON_BLACK, output);
- for (x = 0; x < 4; x++)
- fputs("\342\226\210", output);
-
- for (x = 0; x < (unsigned) qr->width; x ++) {
- bool a, b;
-
- a = row1[x] & 1;
- b = (y+1) < (unsigned) qr->width ? (row2[x] & 1) : false;
-
- if (a && b)
- fputc(' ', output);
- else if (a)
- fputs("\342\226\204", output);
- else if (b)
- fputs("\342\226\200", output);
- else
- fputs("\342\226\210", output);
- }
-
- for (x = 0; x < 4; x++)
- fputs("\342\226\210", output);
- fputs(NORMAL "\n", output);
- }
-
- print_border(output, qr->width);
-
- QRcode_free(qr);
- return 0;
-}
diff --git a/src/journal/journal-qrcode.h b/src/journal/journal-qrcode.h
deleted file mode 100644
index da6244c160..0000000000
--- a/src/journal/journal-qrcode.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <inttypes.h>
-#include <sys/types.h>
-#include <stdio.h>
-
-#include <systemd/sd-id128.h>
-
-int print_qr_code(FILE *f, const void *seed, size_t seed_size, uint64_t start, uint64_t interval, const char *hn, sd_id128_t machine);
diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c
deleted file mode 100644
index 8589d94479..0000000000
--- a/src/journal/journal-send.c
+++ /dev/null
@@ -1,608 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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/socket.h>
-#include <sys/un.h>
-#include <errno.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <printf.h>
-
-#define SD_JOURNAL_SUPPRESS_LOCATION
-
-#include "sd-journal.h"
-#include "util.h"
-#include "socket-util.h"
-
-#define SNDBUF_SIZE (8*1024*1024)
-
-/* We open a single fd, and we'll share it with the current process,
- * all its threads, and all its subprocesses. This means we need to
- * initialize it atomically, and need to operate on it atomically
- * never assuming we are the only user */
-
-static int journal_fd(void) {
- int fd;
- static int fd_plus_one = 0;
-
-retry:
- if (fd_plus_one > 0)
- return fd_plus_one - 1;
-
- fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
- if (fd < 0)
- return -errno;
-
- fd_inc_sndbuf(fd, SNDBUF_SIZE);
-
- if (!__sync_bool_compare_and_swap(&fd_plus_one, 0, fd+1)) {
- close_nointr_nofail(fd);
- goto retry;
- }
-
- return fd;
-}
-
-_public_ int sd_journal_print(int priority, const char *format, ...) {
- int r;
- va_list ap;
-
- va_start(ap, format);
- r = sd_journal_printv(priority, format, ap);
- va_end(ap);
-
- return r;
-}
-
-_public_ int sd_journal_printv(int priority, const char *format, va_list ap) {
-
- /* FIXME: Instead of limiting things to LINE_MAX we could do a
- C99 variable-length array on the stack here in a loop. */
-
- char buffer[8 + LINE_MAX], p[11]; struct iovec iov[2];
-
- if (priority < 0 || priority > 7)
- return -EINVAL;
-
- if (!format)
- return -EINVAL;
-
- snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
- char_array_0(p);
-
- memcpy(buffer, "MESSAGE=", 8);
- vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
- char_array_0(buffer);
-
- zero(iov);
- IOVEC_SET_STRING(iov[0], buffer);
- IOVEC_SET_STRING(iov[1], p);
-
- return sd_journal_sendv(iov, 2);
-}
-
-static int fill_iovec_sprintf(const char *format, va_list ap, int extra, struct iovec **_iov) {
- int r, n = 0, i = 0, j;
- struct iovec *iov = NULL;
- int saved_errno;
-
- assert(_iov);
- saved_errno = errno;
-
- if (extra > 0) {
- n = MAX(extra * 2, extra + 4);
- iov = malloc0(n * sizeof(struct iovec));
- if (!iov) {
- r = -ENOMEM;
- goto fail;
- }
-
- i = extra;
- }
-
- while (format) {
- struct iovec *c;
- char *buffer;
- va_list aq;
-
- if (i >= n) {
- n = MAX(i*2, 4);
- c = realloc(iov, n * sizeof(struct iovec));
- if (!c) {
- r = -ENOMEM;
- goto fail;
- }
-
- iov = c;
- }
-
- va_copy(aq, ap);
- if (vasprintf(&buffer, format, aq) < 0) {
- va_end(aq);
- r = -ENOMEM;
- goto fail;
- }
- va_end(aq);
-
- VA_FORMAT_ADVANCE(format, ap);
-
- IOVEC_SET_STRING(iov[i++], buffer);
-
- format = va_arg(ap, char *);
- }
-
- *_iov = iov;
-
- errno = saved_errno;
- return i;
-
-fail:
- for (j = 0; j < i; j++)
- free(iov[j].iov_base);
-
- free(iov);
-
- errno = saved_errno;
- return r;
-}
-
-_public_ int sd_journal_send(const char *format, ...) {
- int r, i, j;
- va_list ap;
- struct iovec *iov = NULL;
-
- va_start(ap, format);
- i = fill_iovec_sprintf(format, ap, 0, &iov);
- va_end(ap);
-
- if (_unlikely_(i < 0)) {
- r = i;
- goto finish;
- }
-
- r = sd_journal_sendv(iov, i);
-
-finish:
- for (j = 0; j < i; j++)
- free(iov[j].iov_base);
-
- free(iov);
-
- return r;
-}
-
-_public_ int sd_journal_sendv(const struct iovec *iov, int n) {
- int fd, buffer_fd;
- struct iovec *w;
- uint64_t *l;
- int r, i, j = 0;
- struct msghdr mh;
- struct sockaddr_un sa;
- ssize_t k;
- int saved_errno;
- union {
- struct cmsghdr cmsghdr;
- uint8_t buf[CMSG_SPACE(sizeof(int))];
- } control;
- struct cmsghdr *cmsg;
- /* We use /dev/shm instead of /tmp here, since we want this to
- * be a tmpfs, and one that is available from early boot on
- * and where unprivileged users can create files. */
- char path[] = "/dev/shm/journal.XXXXXX";
-
- if (_unlikely_(!iov))
- return -EINVAL;
-
- if (_unlikely_(n <= 0))
- return -EINVAL;
-
- saved_errno = errno;
-
- w = alloca(sizeof(struct iovec) * n * 5);
- l = alloca(sizeof(uint64_t) * n);
-
- for (i = 0; i < n; i++) {
- char *c, *nl;
-
- if (_unlikely_(!iov[i].iov_base || iov[i].iov_len <= 1)) {
- r = -EINVAL;
- goto finish;
- }
-
- c = memchr(iov[i].iov_base, '=', iov[i].iov_len);
- if (_unlikely_(!c || c == iov[i].iov_base)) {
- r = -EINVAL;
- goto finish;
- }
-
- nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len);
- if (nl) {
- if (_unlikely_(nl < c)) {
- r = -EINVAL;
- goto finish;
- }
-
- /* Already includes a newline? Bummer, then
- * let's write the variable name, then a
- * newline, then the size (64bit LE), followed
- * by the data and a final newline */
-
- w[j].iov_base = iov[i].iov_base;
- w[j].iov_len = c - (char*) iov[i].iov_base;
- j++;
-
- IOVEC_SET_STRING(w[j++], "\n");
-
- l[i] = htole64(iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1);
- w[j].iov_base = &l[i];
- w[j].iov_len = sizeof(uint64_t);
- j++;
-
- w[j].iov_base = c + 1;
- w[j].iov_len = iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1;
- j++;
-
- } else
- /* Nothing special? Then just add the line and
- * append a newline */
- w[j++] = iov[i];
-
- IOVEC_SET_STRING(w[j++], "\n");
- }
-
- fd = journal_fd();
- if (_unlikely_(fd < 0)) {
- r = fd;
- goto finish;
- }
-
- zero(sa);
- sa.sun_family = AF_UNIX;
- strncpy(sa.sun_path, "/run/systemd/journal/socket", sizeof(sa.sun_path));
-
- zero(mh);
- mh.msg_name = &sa;
- mh.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path);
- mh.msg_iov = w;
- mh.msg_iovlen = j;
-
- k = sendmsg(fd, &mh, MSG_NOSIGNAL);
- if (k >= 0) {
- r = 0;
- goto finish;
- }
-
- if (errno != EMSGSIZE && errno != ENOBUFS) {
- r = -errno;
- goto finish;
- }
-
- /* Message doesn't fit... Let's dump the data in a temporary
- * file and just pass a file descriptor of it to the other
- * side */
-
- buffer_fd = mkostemp(path, O_CLOEXEC|O_RDWR);
- if (buffer_fd < 0) {
- r = -errno;
- goto finish;
- }
-
- if (unlink(path) < 0) {
- close_nointr_nofail(buffer_fd);
- r = -errno;
- goto finish;
- }
-
- n = writev(buffer_fd, w, j);
- if (n < 0) {
- close_nointr_nofail(buffer_fd);
- r = -errno;
- goto finish;
- }
-
- mh.msg_iov = NULL;
- mh.msg_iovlen = 0;
-
- zero(control);
- mh.msg_control = &control;
- mh.msg_controllen = sizeof(control);
-
- cmsg = CMSG_FIRSTHDR(&mh);
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
- cmsg->cmsg_len = CMSG_LEN(sizeof(int));
- memcpy(CMSG_DATA(cmsg), &buffer_fd, sizeof(int));
-
- mh.msg_controllen = cmsg->cmsg_len;
-
- k = sendmsg(fd, &mh, MSG_NOSIGNAL);
- close_nointr_nofail(buffer_fd);
-
- if (k < 0) {
- r = -errno;
- goto finish;
- }
-
- r = 0;
-
-finish:
- errno = saved_errno;
-
- return r;
-}
-
-static int fill_iovec_perror_and_send(const char *message, int skip, struct iovec iov[]) {
- size_t n, k, r;
- int saved_errno;
-
- saved_errno = errno;
-
- k = isempty(message) ? 0 : strlen(message) + 2;
- n = 8 + k + 256 + 1;
-
- for (;;) {
- char buffer[n];
- char* j;
-
- errno = 0;
- j = strerror_r(saved_errno, buffer + 8 + k, n - 8 - k);
- if (errno == 0) {
- char error[6 + 10 + 1]; /* for a 32bit value */
-
- if (j != buffer + 8 + k)
- memmove(buffer + 8 + k, j, strlen(j)+1);
-
- memcpy(buffer, "MESSAGE=", 8);
-
- if (k > 0) {
- memcpy(buffer + 8, message, k - 2);
- memcpy(buffer + 8 + k - 2, ": ", 2);
- }
-
- snprintf(error, sizeof(error), "ERRNO=%u", saved_errno);
- char_array_0(error);
-
- IOVEC_SET_STRING(iov[skip+0], "PRIORITY=3");
- IOVEC_SET_STRING(iov[skip+1], buffer);
- IOVEC_SET_STRING(iov[skip+2], error);
-
- r = sd_journal_sendv(iov, skip + 3);
-
- errno = saved_errno;
- return r;
- }
-
- if (errno != ERANGE) {
- r = -errno;
- errno = saved_errno;
- return r;
- }
-
- n *= 2;
- }
-}
-
-_public_ int sd_journal_perror(const char *message) {
- struct iovec iovec[3];
-
- return fill_iovec_perror_and_send(message, 0, iovec);
-}
-
-_public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) {
- union sockaddr_union sa;
- int fd;
- char *header;
- size_t l;
- ssize_t r;
-
- if (priority < 0 || priority > 7)
- return -EINVAL;
-
- fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
- if (fd < 0)
- return -errno;
-
- zero(sa);
- sa.un.sun_family = AF_UNIX;
- strncpy(sa.un.sun_path, "/run/systemd/journal/stdout", sizeof(sa.un.sun_path));
-
- r = connect(fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
- if (r < 0) {
- close_nointr_nofail(fd);
- return -errno;
- }
-
- if (shutdown(fd, SHUT_RD) < 0) {
- close_nointr_nofail(fd);
- return -errno;
- }
-
- fd_inc_sndbuf(fd, SNDBUF_SIZE);
-
- if (!identifier)
- identifier = "";
-
- l = strlen(identifier);
- header = alloca(l + 1 + 1 + 2 + 2 + 2 + 2 + 2);
-
- memcpy(header, identifier, l);
- header[l++] = '\n';
- header[l++] = '\n'; /* unit id */
- header[l++] = '0' + priority;
- header[l++] = '\n';
- header[l++] = '0' + !!level_prefix;
- header[l++] = '\n';
- header[l++] = '0';
- header[l++] = '\n';
- header[l++] = '0';
- header[l++] = '\n';
- header[l++] = '0';
- header[l++] = '\n';
-
- r = loop_write(fd, header, l, false);
- if (r < 0) {
- close_nointr_nofail(fd);
- return (int) r;
- }
-
- if ((size_t) r != l) {
- close_nointr_nofail(fd);
- return -errno;
- }
-
- return fd;
-}
-
-_public_ int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) {
- int r;
- va_list ap;
-
- va_start(ap, format);
- r = sd_journal_printv_with_location(priority, file, line, func, format, ap);
- va_end(ap);
-
- return r;
-}
-
-_public_ int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap) {
- char buffer[8 + LINE_MAX], p[11];
- struct iovec iov[5];
- char *f;
- size_t fl;
-
- if (priority < 0 || priority > 7)
- return -EINVAL;
-
- if (_unlikely_(!format))
- return -EINVAL;
-
- snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
- char_array_0(p);
-
- memcpy(buffer, "MESSAGE=", 8);
- vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
- char_array_0(buffer);
-
- /* func is initialized from __func__ which is not a macro, but
- * a static const char[], hence cannot easily be prefixed with
- * CODE_FUNC=, hence let's do it manually here. */
- fl = strlen(func) + 1;
- f = alloca(fl + 10);
- memcpy(f, "CODE_FUNC=", 10);
- memcpy(f + 10, func, fl);
-
- zero(iov);
- IOVEC_SET_STRING(iov[0], buffer);
- IOVEC_SET_STRING(iov[1], p);
- IOVEC_SET_STRING(iov[2], file);
- IOVEC_SET_STRING(iov[3], line);
- IOVEC_SET_STRING(iov[4], f);
-
- return sd_journal_sendv(iov, ELEMENTSOF(iov));
-}
-
-_public_ int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) {
- int r, i, j;
- va_list ap;
- struct iovec *iov = NULL;
- char *f;
- size_t fl;
-
- va_start(ap, format);
- i = fill_iovec_sprintf(format, ap, 3, &iov);
- va_end(ap);
-
- if (_unlikely_(i < 0)) {
- r = i;
- goto finish;
- }
-
- fl = strlen(func) + 1;
- f = alloca(fl + 10);
- memcpy(f, "CODE_FUNC=", 10);
- memcpy(f + 10, func, fl);
-
- IOVEC_SET_STRING(iov[0], file);
- IOVEC_SET_STRING(iov[1], line);
- IOVEC_SET_STRING(iov[2], f);
-
- r = sd_journal_sendv(iov, i);
-
-finish:
- for (j = 3; j < i; j++)
- free(iov[j].iov_base);
-
- free(iov);
-
- return r;
-}
-
-_public_ int sd_journal_sendv_with_location(
- const char *file, const char *line,
- const char *func,
- const struct iovec *iov, int n) {
-
- struct iovec *niov;
- char *f;
- size_t fl;
-
- if (_unlikely_(!iov))
- return -EINVAL;
-
- if (_unlikely_(n <= 0))
- return -EINVAL;
-
- niov = alloca(sizeof(struct iovec) * (n + 3));
- memcpy(niov, iov, sizeof(struct iovec) * n);
-
- fl = strlen(func) + 1;
- f = alloca(fl + 10);
- memcpy(f, "CODE_FUNC=", 10);
- memcpy(f + 10, func, fl);
-
- IOVEC_SET_STRING(niov[n++], file);
- IOVEC_SET_STRING(niov[n++], line);
- IOVEC_SET_STRING(niov[n++], f);
-
- return sd_journal_sendv(niov, n);
-}
-
-_public_ int sd_journal_perror_with_location(
- const char *file, const char *line,
- const char *func,
- const char *message) {
-
- struct iovec iov[6];
- size_t fl;
- char *f;
-
- fl = strlen(func) + 1;
- f = alloca(fl + 10);
- memcpy(f, "CODE_FUNC=", 10);
- memcpy(f + 10, func, fl);
-
- IOVEC_SET_STRING(iov[0], file);
- IOVEC_SET_STRING(iov[1], line);
- IOVEC_SET_STRING(iov[2], f);
-
- return fill_iovec_perror_and_send(message, 3, iov);
-}
diff --git a/src/journal/journal-vacuum.c b/src/journal/journal-vacuum.c
deleted file mode 100644
index 731f6c770f..0000000000
--- a/src/journal/journal-vacuum.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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/types.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/statvfs.h>
-#include <unistd.h>
-
-#ifdef HAVE_XATTR
-#include <attr/xattr.h>
-#endif
-
-#include "journal-def.h"
-#include "journal-file.h"
-#include "journal-vacuum.h"
-#include "sd-id128.h"
-#include "util.h"
-
-struct vacuum_info {
- off_t usage;
- char *filename;
-
- uint64_t realtime;
- sd_id128_t seqnum_id;
- uint64_t seqnum;
-
- bool have_seqnum;
-};
-
-static int vacuum_compare(const void *_a, const void *_b) {
- const struct vacuum_info *a, *b;
-
- a = _a;
- b = _b;
-
- if (a->have_seqnum && b->have_seqnum &&
- sd_id128_equal(a->seqnum_id, b->seqnum_id)) {
- if (a->seqnum < b->seqnum)
- return -1;
- else if (a->seqnum > b->seqnum)
- return 1;
- else
- return 0;
- }
-
- if (a->realtime < b->realtime)
- return -1;
- else if (a->realtime > b->realtime)
- return 1;
- else if (a->have_seqnum && b->have_seqnum)
- return memcmp(&a->seqnum_id, &b->seqnum_id, 16);
- else
- return strcmp(a->filename, b->filename);
-}
-
-static void patch_realtime(
- const char *dir,
- const char *fn,
- const struct stat *st,
- unsigned long long *realtime) {
-
- usec_t x;
-
-#ifdef HAVE_XATTR
- uint64_t crtime;
- _cleanup_free_ const char *path = NULL;
-#endif
-
- /* The timestamp was determined by the file name, but let's
- * see if the file might actually be older than the file name
- * suggested... */
-
- assert(dir);
- assert(fn);
- assert(st);
- assert(realtime);
-
- x = timespec_load(&st->st_ctim);
- if (x > 0 && x != (usec_t) -1 && x < *realtime)
- *realtime = x;
-
- x = timespec_load(&st->st_atim);
- if (x > 0 && x != (usec_t) -1 && x < *realtime)
- *realtime = x;
-
- x = timespec_load(&st->st_mtim);
- if (x > 0 && x != (usec_t) -1 && x < *realtime)
- *realtime = x;
-
-#ifdef HAVE_XATTR
- /* Let's read the original creation time, if possible. Ideally
- * we'd just query the creation time the FS might provide, but
- * unfortunately there's currently no sane API to query
- * it. Hence let's implement this manually... */
-
- /* Unfortunately there is is not fgetxattrat(), so we need to
- * go via path here. :-( */
-
- path = strjoin(dir, "/", fn, NULL);
- if (!path)
- return;
-
- if (getxattr(path, "user.crtime_usec", &crtime, sizeof(crtime)) == sizeof(crtime)) {
- crtime = le64toh(crtime);
-
- if (crtime > 0 && crtime != (uint64_t) -1 && crtime < *realtime)
- *realtime = crtime;
- }
-#endif
-}
-
-int journal_directory_vacuum(
- const char *directory,
- uint64_t max_use,
- uint64_t min_free,
- usec_t max_retention_usec,
- usec_t *oldest_usec) {
-
- DIR *d;
- int r = 0;
- struct vacuum_info *list = NULL;
- unsigned n_list = 0, n_allocated = 0, i;
- uint64_t sum = 0;
- usec_t retention_limit = 0;
-
- assert(directory);
-
- if (max_use <= 0 && min_free <= 0 && max_retention_usec <= 0)
- return 0;
-
- if (max_retention_usec > 0) {
- retention_limit = now(CLOCK_REALTIME);
- if (retention_limit > max_retention_usec)
- retention_limit -= max_retention_usec;
- else
- max_retention_usec = retention_limit = 0;
- }
-
- d = opendir(directory);
- if (!d)
- return -errno;
-
- for (;;) {
- int k;
- struct dirent *de;
- union dirent_storage buf;
- size_t q;
- struct stat st;
- char *p;
- unsigned long long seqnum = 0, realtime;
- sd_id128_t seqnum_id;
- bool have_seqnum;
-
- k = readdir_r(d, &buf.de, &de);
- if (k != 0) {
- r = -k;
- goto finish;
- }
-
- if (!de)
- break;
-
- if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
- continue;
-
- if (!S_ISREG(st.st_mode))
- continue;
-
- q = strlen(de->d_name);
-
- if (endswith(de->d_name, ".journal")) {
-
- /* Vacuum archived files */
-
- if (q < 1 + 32 + 1 + 16 + 1 + 16 + 8)
- continue;
-
- if (de->d_name[q-8-16-1] != '-' ||
- de->d_name[q-8-16-1-16-1] != '-' ||
- de->d_name[q-8-16-1-16-1-32-1] != '@')
- continue;
-
- p = strdup(de->d_name);
- if (!p) {
- r = -ENOMEM;
- goto finish;
- }
-
- de->d_name[q-8-16-1-16-1] = 0;
- if (sd_id128_from_string(de->d_name + q-8-16-1-16-1-32, &seqnum_id) < 0) {
- free(p);
- continue;
- }
-
- if (sscanf(de->d_name + q-8-16-1-16, "%16llx-%16llx.journal", &seqnum, &realtime) != 2) {
- free(p);
- continue;
- }
-
- have_seqnum = true;
-
- } else if (endswith(de->d_name, ".journal~")) {
- unsigned long long tmp;
-
- /* Vacuum corrupted files */
-
- if (q < 1 + 16 + 1 + 16 + 8 + 1)
- continue;
-
- if (de->d_name[q-1-8-16-1] != '-' ||
- de->d_name[q-1-8-16-1-16-1] != '@')
- continue;
-
- p = strdup(de->d_name);
- if (!p) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (sscanf(de->d_name + q-1-8-16-1-16, "%16llx-%16llx.journal~", &realtime, &tmp) != 2) {
- free(p);
- continue;
- }
-
- have_seqnum = false;
- } else
- /* We do not vacuum active files or unknown files! */
- continue;
-
- patch_realtime(directory, de->d_name, &st, &realtime);
-
- if (n_list >= n_allocated) {
- struct vacuum_info *j;
-
- n_allocated = MAX(n_allocated * 2U, 8U);
- j = realloc(list, n_allocated * sizeof(struct vacuum_info));
- if (!j) {
- free(p);
- r = -ENOMEM;
- goto finish;
- }
-
- list = j;
- }
-
- list[n_list].filename = p;
- list[n_list].usage = 512UL * (uint64_t) st.st_blocks;
- list[n_list].seqnum = seqnum;
- list[n_list].realtime = realtime;
- list[n_list].seqnum_id = seqnum_id;
- list[n_list].have_seqnum = have_seqnum;
-
- sum += list[n_list].usage;
-
- n_list ++;
- }
-
- if (n_list > 0)
- qsort(list, n_list, sizeof(struct vacuum_info), vacuum_compare);
-
- for (i = 0; i < n_list; i++) {
- struct statvfs ss;
-
- if (fstatvfs(dirfd(d), &ss) < 0) {
- r = -errno;
- goto finish;
- }
-
- if ((max_retention_usec <= 0 || list[i].realtime >= retention_limit) &&
- (max_use <= 0 || sum <= max_use) &&
- (min_free <= 0 || (uint64_t) ss.f_bavail * (uint64_t) ss.f_bsize >= min_free))
- break;
-
- if (unlinkat(dirfd(d), list[i].filename, 0) >= 0) {
- log_debug("Deleted archived journal %s/%s.", directory, list[i].filename);
-
- if ((uint64_t) list[i].usage > sum)
- sum -= list[i].usage;
- else
- sum = 0;
-
- } else if (errno != ENOENT)
- log_warning("Failed to delete %s/%s: %m", directory, list[i].filename);
- }
-
- if (oldest_usec && i < n_list && (*oldest_usec == 0 || list[i].realtime < *oldest_usec))
- *oldest_usec = list[i].realtime;
-
-finish:
- for (i = 0; i < n_list; i++)
- free(list[i].filename);
-
- free(list);
-
- if (d)
- closedir(d);
-
- return r;
-}
diff --git a/src/journal/journal-vacuum.h b/src/journal/journal-vacuum.h
deleted file mode 100644
index f5e3e5291f..0000000000
--- a/src/journal/journal-vacuum.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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>
-
-int journal_directory_vacuum(const char *directory, uint64_t max_use, uint64_t min_free, usec_t max_retention_usec, usec_t *oldest_usec);
diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
deleted file mode 100644
index 1a67d5a04b..0000000000
--- a/src/journal/journal-verify.c
+++ /dev/null
@@ -1,1163 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <unistd.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-#include <stddef.h>
-
-#include "util.h"
-#include "macro.h"
-#include "journal-def.h"
-#include "journal-file.h"
-#include "journal-authenticate.h"
-#include "journal-verify.h"
-#include "lookup3.h"
-#include "compress.h"
-#include "fsprg.h"
-
-static int journal_file_object_verify(JournalFile *f, Object *o) {
- uint64_t i;
-
- assert(f);
- assert(o);
-
- /* This does various superficial tests about the length an
- * possible field values. It does not follow any references to
- * other objects. */
-
- if ((o->object.flags & OBJECT_COMPRESSED) &&
- o->object.type != OBJECT_DATA)
- return -EBADMSG;
-
- switch (o->object.type) {
-
- case OBJECT_DATA: {
- uint64_t h1, h2;
-
- if (le64toh(o->data.entry_offset) <= 0 ||
- le64toh(o->data.n_entries) <= 0)
- return -EBADMSG;
-
- if (le64toh(o->object.size) - offsetof(DataObject, payload) <= 0)
- return -EBADMSG;
-
- h1 = le64toh(o->data.hash);
-
- if (o->object.flags & OBJECT_COMPRESSED) {
-#ifdef HAVE_XZ
- void *b = NULL;
- uint64_t alloc = 0, b_size;
-
- if (!uncompress_blob(o->data.payload,
- le64toh(o->object.size) - offsetof(Object, data.payload),
- &b, &alloc, &b_size))
- return -EBADMSG;
-
- h2 = hash64(b, b_size);
- free(b);
-#else
- return -EPROTONOSUPPORT;
-#endif
- } else
- h2 = hash64(o->data.payload, le64toh(o->object.size) - offsetof(Object, data.payload));
-
- if (h1 != h2)
- return -EBADMSG;
-
- if (!VALID64(o->data.next_hash_offset) ||
- !VALID64(o->data.next_field_offset) ||
- !VALID64(o->data.entry_offset) ||
- !VALID64(o->data.entry_array_offset))
- return -EBADMSG;
-
- break;
- }
-
- case OBJECT_FIELD:
- if (le64toh(o->object.size) - offsetof(FieldObject, payload) <= 0)
- return -EBADMSG;
-
- if (!VALID64(o->field.next_hash_offset) ||
- !VALID64(o->field.head_data_offset))
- return -EBADMSG;
- break;
-
- case OBJECT_ENTRY:
- if ((le64toh(o->object.size) - offsetof(EntryObject, items)) % sizeof(EntryItem) != 0)
- return -EBADMSG;
-
- if ((le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem) <= 0)
- return -EBADMSG;
-
- if (le64toh(o->entry.seqnum) <= 0 ||
- !VALID_REALTIME(le64toh(o->entry.realtime)) ||
- !VALID_MONOTONIC(le64toh(o->entry.monotonic)))
- return -EBADMSG;
-
- for (i = 0; i < journal_file_entry_n_items(o); i++) {
- if (o->entry.items[i].object_offset == 0 ||
- !VALID64(o->entry.items[i].object_offset))
- return -EBADMSG;
- }
-
- break;
-
- case OBJECT_DATA_HASH_TABLE:
- case OBJECT_FIELD_HASH_TABLE:
- if ((le64toh(o->object.size) - offsetof(HashTableObject, items)) % sizeof(HashItem) != 0)
- return -EBADMSG;
-
- if ((le64toh(o->object.size) - offsetof(HashTableObject, items)) / sizeof(HashItem) <= 0)
- return -EBADMSG;
-
- for (i = 0; i < journal_file_hash_table_n_items(o); i++) {
- if (o->hash_table.items[i].head_hash_offset != 0 &&
- !VALID64(le64toh(o->hash_table.items[i].head_hash_offset)))
- return -EBADMSG;
- if (o->hash_table.items[i].tail_hash_offset != 0 &&
- !VALID64(le64toh(o->hash_table.items[i].tail_hash_offset)))
- return -EBADMSG;
-
- if ((o->hash_table.items[i].head_hash_offset != 0) !=
- (o->hash_table.items[i].tail_hash_offset != 0))
- return -EBADMSG;
- }
-
- break;
-
- case OBJECT_ENTRY_ARRAY:
- if ((le64toh(o->object.size) - offsetof(EntryArrayObject, items)) % sizeof(le64_t) != 0)
- return -EBADMSG;
-
- if ((le64toh(o->object.size) - offsetof(EntryArrayObject, items)) / sizeof(le64_t) <= 0)
- return -EBADMSG;
-
- if (!VALID64(o->entry_array.next_entry_array_offset))
- return -EBADMSG;
-
- for (i = 0; i < journal_file_entry_array_n_items(o); i++)
- if (o->entry_array.items[i] != 0 &&
- !VALID64(o->entry_array.items[i]))
- return -EBADMSG;
-
- break;
-
- case OBJECT_TAG:
- if (le64toh(o->object.size) != sizeof(TagObject))
- return -EBADMSG;
-
- if (!VALID_EPOCH(o->tag.epoch))
- return -EBADMSG;
-
- break;
- }
-
- return 0;
-}
-
-static void draw_progress(uint64_t p, usec_t *last_usec) {
- unsigned n, i, j, k;
- usec_t z, x;
-
- if (!on_tty())
- return;
-
- z = now(CLOCK_MONOTONIC);
- x = *last_usec;
-
- if (x != 0 && x + 40 * USEC_PER_MSEC > z)
- return;
-
- *last_usec = z;
-
- n = (3 * columns()) / 4;
- j = (n * (unsigned) p) / 65535ULL;
- k = n - j;
-
- fputs("\r\x1B[?25l" ANSI_HIGHLIGHT_GREEN_ON, stdout);
-
- for (i = 0; i < j; i++)
- fputs("\xe2\x96\x88", stdout);
-
- fputs(ANSI_HIGHLIGHT_OFF, stdout);
-
- for (i = 0; i < k; i++)
- fputs("\xe2\x96\x91", stdout);
-
- printf(" %3lu%%", 100LU * (unsigned long) p / 65535LU);
-
- fputs("\r\x1B[?25h", stdout);
- fflush(stdout);
-}
-
-static void flush_progress(void) {
- unsigned n, i;
-
- if (!on_tty())
- return;
-
- n = (3 * columns()) / 4;
-
- putchar('\r');
-
- for (i = 0; i < n + 5; i++)
- putchar(' ');
-
- putchar('\r');
- fflush(stdout);
-}
-
-static int write_uint64(int fd, uint64_t p) {
- ssize_t k;
-
- k = write(fd, &p, sizeof(p));
- if (k < 0)
- return -errno;
- if (k != sizeof(p))
- return -EIO;
-
- return 0;
-}
-
-static int contains_uint64(MMapCache *m, int fd, uint64_t n, uint64_t p) {
- uint64_t a, b;
- int r;
-
- assert(m);
- assert(fd >= 0);
-
- /* Bisection ... */
-
- a = 0; b = n;
- while (a < b) {
- uint64_t c, *z;
-
- c = (a + b) / 2;
-
- r = mmap_cache_get(m, fd, PROT_READ|PROT_WRITE, 0, false, c * sizeof(uint64_t), sizeof(uint64_t), NULL, (void **) &z);
- if (r < 0)
- return r;
-
- if (*z == p)
- return 1;
-
- if (a + 1 >= b)
- return 0;
-
- if (p < *z)
- b = c;
- else
- a = c;
- }
-
- return 0;
-}
-
-static int entry_points_to_data(
- JournalFile *f,
- int entry_fd,
- uint64_t n_entries,
- uint64_t entry_p,
- uint64_t data_p) {
-
- int r;
- uint64_t i, n, a;
- Object *o;
- bool found = false;
-
- assert(f);
- assert(entry_fd >= 0);
-
- if (!contains_uint64(f->mmap, entry_fd, n_entries, entry_p)) {
- log_error("Data object references invalid entry at %llu", (unsigned long long) data_p);
- return -EBADMSG;
- }
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY, entry_p, &o);
- if (r < 0)
- return r;
-
- n = journal_file_entry_n_items(o);
- for (i = 0; i < n; i++)
- if (le64toh(o->entry.items[i].object_offset) == data_p) {
- found = true;
- break;
- }
-
- if (!found) {
- log_error("Data object not referenced by linked entry at %llu", (unsigned long long) data_p);
- return -EBADMSG;
- }
-
- /* Check if this entry is also in main entry array. Since the
- * main entry array has already been verified we can rely on
- * its consistency.*/
-
- i = 0;
- n = le64toh(f->header->n_entries);
- a = le64toh(f->header->entry_array_offset);
-
- while (i < n) {
- uint64_t m, u;
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
- if (r < 0)
- return r;
-
- m = journal_file_entry_array_n_items(o);
- u = MIN(n - i, m);
-
- if (entry_p <= le64toh(o->entry_array.items[u-1])) {
- uint64_t x, y, z;
-
- x = 0;
- y = u;
-
- while (x < y) {
- z = (x + y) / 2;
-
- if (le64toh(o->entry_array.items[z]) == entry_p)
- return 0;
-
- if (x + 1 >= y)
- break;
-
- if (entry_p < le64toh(o->entry_array.items[z]))
- y = z;
- else
- x = z;
- }
-
- log_error("Entry object doesn't exist in main entry array at %llu", (unsigned long long) entry_p);
- return -EBADMSG;
- }
-
- i += u;
- a = le64toh(o->entry_array.next_entry_array_offset);
- }
-
- return 0;
-}
-
-static int verify_data(
- JournalFile *f,
- Object *o, uint64_t p,
- int entry_fd, uint64_t n_entries,
- int entry_array_fd, uint64_t n_entry_arrays) {
-
- uint64_t i, n, a, last, q;
- int r;
-
- assert(f);
- assert(o);
- assert(entry_fd >= 0);
- assert(entry_array_fd >= 0);
-
- n = le64toh(o->data.n_entries);
- a = le64toh(o->data.entry_array_offset);
-
- /* We already checked this earlier */
- assert(n > 0);
-
- last = q = le64toh(o->data.entry_offset);
- r = entry_points_to_data(f, entry_fd, n_entries, q, p);
- if (r < 0)
- return r;
-
- i = 1;
- while (i < n) {
- uint64_t next, m, j;
-
- if (a == 0) {
- log_error("Array chain too short at %llu", (unsigned long long) p);
- return -EBADMSG;
- }
-
- if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) {
- log_error("Invalid array at %llu", (unsigned long long) p);
- return -EBADMSG;
- }
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
- if (r < 0)
- return r;
-
- next = le64toh(o->entry_array.next_entry_array_offset);
- if (next != 0 && next <= a) {
- log_error("Array chain has cycle at %llu", (unsigned long long) p);
- return -EBADMSG;
- }
-
- m = journal_file_entry_array_n_items(o);
- for (j = 0; i < n && j < m; i++, j++) {
-
- q = le64toh(o->entry_array.items[j]);
- if (q <= last) {
- log_error("Data object's entry array not sorted at %llu", (unsigned long long) p);
- return -EBADMSG;
- }
- last = q;
-
- r = entry_points_to_data(f, entry_fd, n_entries, q, p);
- if (r < 0)
- return r;
-
- /* Pointer might have moved, reposition */
- r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
- if (r < 0)
- return r;
- }
-
- a = next;
- }
-
- return 0;
-}
-
-static int verify_hash_table(
- JournalFile *f,
- int data_fd, uint64_t n_data,
- int entry_fd, uint64_t n_entries,
- int entry_array_fd, uint64_t n_entry_arrays,
- usec_t *last_usec,
- bool show_progress) {
-
- uint64_t i, n;
- int r;
-
- assert(f);
- assert(data_fd >= 0);
- assert(entry_fd >= 0);
- assert(entry_array_fd >= 0);
- assert(last_usec);
-
- n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem);
- for (i = 0; i < n; i++) {
- uint64_t last = 0, p;
-
- if (show_progress)
- draw_progress(0xC000 + (0x3FFF * i / n), last_usec);
-
- p = le64toh(f->data_hash_table[i].head_hash_offset);
- while (p != 0) {
- Object *o;
- uint64_t next;
-
- if (!contains_uint64(f->mmap, data_fd, n_data, p)) {
- log_error("Invalid data object at hash entry %llu of %llu",
- (unsigned long long) i, (unsigned long long) n);
- return -EBADMSG;
- }
-
- r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
- if (r < 0)
- return r;
-
- next = le64toh(o->data.next_hash_offset);
- if (next != 0 && next <= p) {
- log_error("Hash chain has a cycle in hash entry %llu of %llu",
- (unsigned long long) i, (unsigned long long) n);
- return -EBADMSG;
- }
-
- if (le64toh(o->data.hash) % n != i) {
- log_error("Hash value mismatch in hash entry %llu of %llu",
- (unsigned long long) i, (unsigned long long) n);
- return -EBADMSG;
- }
-
- r = verify_data(f, o, p, entry_fd, n_entries, entry_array_fd, n_entry_arrays);
- if (r < 0)
- return r;
-
- last = p;
- p = next;
- }
-
- if (last != le64toh(f->data_hash_table[i].tail_hash_offset)) {
- log_error("Tail hash pointer mismatch in hash table");
- return -EBADMSG;
- }
- }
-
- return 0;
-}
-
-static int data_object_in_hash_table(JournalFile *f, uint64_t hash, uint64_t p) {
- uint64_t n, h, q;
- int r;
- assert(f);
-
- n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem);
- h = hash % n;
-
- q = le64toh(f->data_hash_table[h].head_hash_offset);
- while (q != 0) {
- Object *o;
-
- if (p == q)
- return 1;
-
- r = journal_file_move_to_object(f, OBJECT_DATA, q, &o);
- if (r < 0)
- return r;
-
- q = le64toh(o->data.next_hash_offset);
- }
-
- return 0;
-}
-
-static int verify_entry(
- JournalFile *f,
- Object *o, uint64_t p,
- int data_fd, uint64_t n_data) {
-
- uint64_t i, n;
- int r;
-
- assert(f);
- assert(o);
- assert(data_fd >= 0);
-
- n = journal_file_entry_n_items(o);
- for (i = 0; i < n; i++) {
- uint64_t q, h;
- Object *u;
-
- q = le64toh(o->entry.items[i].object_offset);
- h = le64toh(o->entry.items[i].hash);
-
- if (!contains_uint64(f->mmap, data_fd, n_data, q)) {
- log_error("Invalid data object at entry %llu",
- (unsigned long long) p);
- return -EBADMSG;
- }
-
- r = journal_file_move_to_object(f, OBJECT_DATA, q, &u);
- if (r < 0)
- return r;
-
- if (le64toh(u->data.hash) != h) {
- log_error("Hash mismatch for data object at entry %llu",
- (unsigned long long) p);
- return -EBADMSG;
- }
-
- r = data_object_in_hash_table(f, h, q);
- if (r < 0)
- return r;
- if (r == 0) {
- log_error("Data object missing from hash at entry %llu",
- (unsigned long long) p);
- return -EBADMSG;
- }
- }
-
- return 0;
-}
-
-static int verify_entry_array(
- JournalFile *f,
- int data_fd, uint64_t n_data,
- int entry_fd, uint64_t n_entries,
- int entry_array_fd, uint64_t n_entry_arrays,
- usec_t *last_usec,
- bool show_progress) {
-
- uint64_t i = 0, a, n, last = 0;
- int r;
-
- assert(f);
- assert(data_fd >= 0);
- assert(entry_fd >= 0);
- assert(entry_array_fd >= 0);
- assert(last_usec);
-
- n = le64toh(f->header->n_entries);
- a = le64toh(f->header->entry_array_offset);
- while (i < n) {
- uint64_t next, m, j;
- Object *o;
-
- if (show_progress)
- draw_progress(0x8000 + (0x3FFF * i / n), last_usec);
-
- if (a == 0) {
- log_error("Array chain too short at %llu of %llu",
- (unsigned long long) i, (unsigned long long) n);
- return -EBADMSG;
- }
-
- if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) {
- log_error("Invalid array at %llu of %llu",
- (unsigned long long) i, (unsigned long long) n);
- return -EBADMSG;
- }
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
- if (r < 0)
- return r;
-
- next = le64toh(o->entry_array.next_entry_array_offset);
- if (next != 0 && next <= a) {
- log_error("Array chain has cycle at %llu of %llu",
- (unsigned long long) i, (unsigned long long) n);
- return -EBADMSG;
- }
-
- m = journal_file_entry_array_n_items(o);
- for (j = 0; i < n && j < m; i++, j++) {
- uint64_t p;
-
- p = le64toh(o->entry_array.items[j]);
- if (p <= last) {
- log_error("Entry array not sorted at %llu of %llu",
- (unsigned long long) i, (unsigned long long) n);
- return -EBADMSG;
- }
- last = p;
-
- if (!contains_uint64(f->mmap, entry_fd, n_entries, p)) {
- log_error("Invalid array entry at %llu of %llu",
- (unsigned long long) i, (unsigned long long) n);
- return -EBADMSG;
- }
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o);
- if (r < 0)
- return r;
-
- r = verify_entry(f, o, p, data_fd, n_data);
- if (r < 0)
- return r;
-
- /* Pointer might have moved, reposition */
- r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
- if (r < 0)
- return r;
- }
-
- a = next;
- }
-
- return 0;
-}
-
-int journal_file_verify(
- JournalFile *f,
- const char *key,
- usec_t *first_contained, usec_t *last_validated, usec_t *last_contained,
- bool show_progress) {
- int r;
- Object *o;
- uint64_t p = 0, last_epoch = 0, last_tag_realtime = 0, last_sealed_realtime = 0;
-
- uint64_t entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0;
- sd_id128_t entry_boot_id;
- bool entry_seqnum_set = false, entry_monotonic_set = false, entry_realtime_set = false, found_main_entry_array = false;
- uint64_t n_weird = 0, n_objects = 0, n_entries = 0, n_data = 0, n_fields = 0, n_data_hash_tables = 0, n_field_hash_tables = 0, n_entry_arrays = 0, n_tags = 0;
- usec_t last_usec = 0;
- int data_fd = -1, entry_fd = -1, entry_array_fd = -1;
- char data_path[] = "/var/tmp/journal-data-XXXXXX",
- entry_path[] = "/var/tmp/journal-entry-XXXXXX",
- entry_array_path[] = "/var/tmp/journal-entry-array-XXXXXX";
- unsigned i;
- bool found_last;
-#ifdef HAVE_GCRYPT
- uint64_t last_tag = 0;
-#endif
- assert(f);
-
- if (key) {
-#ifdef HAVE_GCRYPT
- r = journal_file_parse_verification_key(f, key);
- if (r < 0) {
- log_error("Failed to parse seed.");
- return r;
- }
-#else
- return -ENOTSUP;
-#endif
- } else if (f->seal)
- return -ENOKEY;
-
- data_fd = mkostemp(data_path, O_CLOEXEC);
- if (data_fd < 0) {
- log_error("Failed to create data file: %m");
- r = -errno;
- goto fail;
- }
- unlink(data_path);
-
- entry_fd = mkostemp(entry_path, O_CLOEXEC);
- if (entry_fd < 0) {
- log_error("Failed to create entry file: %m");
- r = -errno;
- goto fail;
- }
- unlink(entry_path);
-
- entry_array_fd = mkostemp(entry_array_path, O_CLOEXEC);
- if (entry_array_fd < 0) {
- log_error("Failed to create entry array file: %m");
- r = -errno;
- goto fail;
- }
- unlink(entry_array_path);
-
-#ifdef HAVE_GCRYPT
- if ((le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_SEALED) != 0)
-#else
- if (f->header->compatible_flags != 0)
-#endif
- {
- log_error("Cannot verify file with unknown extensions.");
- r = -ENOTSUP;
- goto fail;
- }
-
- for (i = 0; i < sizeof(f->header->reserved); i++)
- if (f->header->reserved[i] != 0) {
- log_error("Reserved field in non-zero.");
- r = -EBADMSG;
- goto fail;
- }
-
- /* First iteration: we go through all objects, verify the
- * superficial structure, headers, hashes. */
-
- p = le64toh(f->header->header_size);
- while (p != 0) {
- if (show_progress)
- draw_progress(0x7FFF * p / le64toh(f->header->tail_object_offset), &last_usec);
-
- r = journal_file_move_to_object(f, -1, p, &o);
- if (r < 0) {
- log_error("Invalid object at %llu", (unsigned long long) p);
- goto fail;
- }
-
- if (p > le64toh(f->header->tail_object_offset)) {
- log_error("Invalid tail object pointer");
- r = -EBADMSG;
- goto fail;
- }
-
- if (p == le64toh(f->header->tail_object_offset))
- found_last = true;
-
- n_objects ++;
-
- r = journal_file_object_verify(f, o);
- if (r < 0) {
- log_error("Invalid object contents at %llu", (unsigned long long) p);
- goto fail;
- }
-
- if ((o->object.flags & OBJECT_COMPRESSED) && !JOURNAL_HEADER_COMPRESSED(f->header)) {
- log_error("Compressed object in file without compression at %llu", (unsigned long long) p);
- r = -EBADMSG;
- goto fail;
- }
-
- switch (o->object.type) {
-
- case OBJECT_DATA:
- r = write_uint64(data_fd, p);
- if (r < 0)
- goto fail;
-
- n_data++;
- break;
-
- case OBJECT_FIELD:
- n_fields++;
- break;
-
- case OBJECT_ENTRY:
- if (JOURNAL_HEADER_SEALED(f->header) && n_tags <= 0) {
- log_error("First entry before first tag at %llu", (unsigned long long) p);
- r = -EBADMSG;
- goto fail;
- }
-
- r = write_uint64(entry_fd, p);
- if (r < 0)
- goto fail;
-
- if (le64toh(o->entry.realtime) < last_tag_realtime) {
- log_error("Older entry after newer tag at %llu", (unsigned long long) p);
- r = -EBADMSG;
- goto fail;
- }
-
- if (!entry_seqnum_set &&
- le64toh(o->entry.seqnum) != le64toh(f->header->head_entry_seqnum)) {
- log_error("Head entry sequence number incorrect at %llu", (unsigned long long) p);
- r = -EBADMSG;
- goto fail;
- }
-
- if (entry_seqnum_set &&
- entry_seqnum >= le64toh(o->entry.seqnum)) {
- log_error("Entry sequence number out of synchronization at %llu", (unsigned long long) p);
- r = -EBADMSG;
- goto fail;
- }
-
- entry_seqnum = le64toh(o->entry.seqnum);
- entry_seqnum_set = true;
-
- if (entry_monotonic_set &&
- sd_id128_equal(entry_boot_id, o->entry.boot_id) &&
- entry_monotonic > le64toh(o->entry.monotonic)) {
- log_error("Entry timestamp out of synchronization at %llu", (unsigned long long) p);
- r = -EBADMSG;
- goto fail;
- }
-
- entry_monotonic = le64toh(o->entry.monotonic);
- entry_boot_id = o->entry.boot_id;
- entry_monotonic_set = true;
-
- if (!entry_realtime_set &&
- le64toh(o->entry.realtime) != le64toh(f->header->head_entry_realtime)) {
- log_error("Head entry realtime timestamp incorrect");
- r = -EBADMSG;
- goto fail;
- }
-
- entry_realtime = le64toh(o->entry.realtime);
- entry_realtime_set = true;
-
- n_entries ++;
- break;
-
- case OBJECT_DATA_HASH_TABLE:
- if (n_data_hash_tables > 1) {
- log_error("More than one data hash table at %llu", (unsigned long long) p);
- r = -EBADMSG;
- goto fail;
- }
-
- if (le64toh(f->header->data_hash_table_offset) != p + offsetof(HashTableObject, items) ||
- le64toh(f->header->data_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) {
- log_error("Header fields for data hash table invalid");
- r = -EBADMSG;
- goto fail;
- }
-
- n_data_hash_tables++;
- break;
-
- case OBJECT_FIELD_HASH_TABLE:
- if (n_field_hash_tables > 1) {
- log_error("More than one field hash table at %llu", (unsigned long long) p);
- r = -EBADMSG;
- goto fail;
- }
-
- if (le64toh(f->header->field_hash_table_offset) != p + offsetof(HashTableObject, items) ||
- le64toh(f->header->field_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) {
- log_error("Header fields for field hash table invalid");
- r = -EBADMSG;
- goto fail;
- }
-
- n_field_hash_tables++;
- break;
-
- case OBJECT_ENTRY_ARRAY:
- r = write_uint64(entry_array_fd, p);
- if (r < 0)
- goto fail;
-
- if (p == le64toh(f->header->entry_array_offset)) {
- if (found_main_entry_array) {
- log_error("More than one main entry array at %llu", (unsigned long long) p);
- r = -EBADMSG;
- goto fail;
- }
-
- found_main_entry_array = true;
- }
-
- n_entry_arrays++;
- break;
-
- case OBJECT_TAG:
- if (!JOURNAL_HEADER_SEALED(f->header)) {
- log_error("Tag object in file without sealing at %llu", (unsigned long long) p);
- r = -EBADMSG;
- goto fail;
- }
-
- if (le64toh(o->tag.seqnum) != n_tags + 1) {
- log_error("Tag sequence number out of synchronization at %llu", (unsigned long long) p);
- r = -EBADMSG;
- goto fail;
- }
-
- if (le64toh(o->tag.epoch) < last_epoch) {
- log_error("Epoch sequence out of synchronization at %llu", (unsigned long long) p);
- r = -EBADMSG;
- goto fail;
- }
-
-#ifdef HAVE_GCRYPT
- if (f->seal) {
- uint64_t q, rt;
-
- log_debug("Checking tag %llu..", (unsigned long long) le64toh(o->tag.seqnum));
-
- rt = f->fss_start_usec + o->tag.epoch * f->fss_interval_usec;
- if (entry_realtime_set && entry_realtime >= rt + f->fss_interval_usec) {
- log_error("Tag/entry realtime timestamp out of synchronization at %llu", (unsigned long long) p);
- r = -EBADMSG;
- goto fail;
- }
-
- /* OK, now we know the epoch. So let's now set
- * it, and calculate the HMAC for everything
- * since the last tag. */
- r = journal_file_fsprg_seek(f, le64toh(o->tag.epoch));
- if (r < 0)
- goto fail;
-
- r = journal_file_hmac_start(f);
- if (r < 0)
- goto fail;
-
- if (last_tag == 0) {
- r = journal_file_hmac_put_header(f);
- if (r < 0)
- goto fail;
-
- q = le64toh(f->header->header_size);
- } else
- q = last_tag;
-
- while (q <= p) {
- r = journal_file_move_to_object(f, -1, q, &o);
- if (r < 0)
- goto fail;
-
- r = journal_file_hmac_put_object(f, -1, o, q);
- if (r < 0)
- goto fail;
-
- q = q + ALIGN64(le64toh(o->object.size));
- }
-
- /* Position might have changed, let's reposition things */
- r = journal_file_move_to_object(f, -1, p, &o);
- if (r < 0)
- goto fail;
-
- if (memcmp(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH) != 0) {
- log_error("Tag failed verification at %llu", (unsigned long long) p);
- r = -EBADMSG;
- goto fail;
- }
-
- f->hmac_running = false;
- last_tag_realtime = rt;
- last_sealed_realtime = entry_realtime;
- }
-
- last_tag = p + ALIGN64(le64toh(o->object.size));
-#endif
-
- last_epoch = le64toh(o->tag.epoch);
-
- n_tags ++;
- break;
-
- default:
- n_weird ++;
- }
-
- if (p == le64toh(f->header->tail_object_offset))
- p = 0;
- else
- p = p + ALIGN64(le64toh(o->object.size));
- }
-
- if (!found_last) {
- log_error("Tail object pointer dead");
- r = -EBADMSG;
- goto fail;
- }
-
- if (n_objects != le64toh(f->header->n_objects)) {
- log_error("Object number mismatch");
- r = -EBADMSG;
- goto fail;
- }
-
- if (n_entries != le64toh(f->header->n_entries)) {
- log_error("Entry number mismatch");
- r = -EBADMSG;
- goto fail;
- }
-
- if (JOURNAL_HEADER_CONTAINS(f->header, n_data) &&
- n_data != le64toh(f->header->n_data)) {
- log_error("Data number mismatch");
- r = -EBADMSG;
- goto fail;
- }
-
- if (JOURNAL_HEADER_CONTAINS(f->header, n_fields) &&
- n_fields != le64toh(f->header->n_fields)) {
- log_error("Field number mismatch");
- r = -EBADMSG;
- goto fail;
- }
-
- if (JOURNAL_HEADER_CONTAINS(f->header, n_tags) &&
- n_tags != le64toh(f->header->n_tags)) {
- log_error("Tag number mismatch");
- r = -EBADMSG;
- goto fail;
- }
-
- if (JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays) &&
- n_entry_arrays != le64toh(f->header->n_entry_arrays)) {
- log_error("Entry array number mismatch");
- r = -EBADMSG;
- goto fail;
- }
-
- if (n_data_hash_tables != 1) {
- log_error("Missing data hash table");
- r = -EBADMSG;
- goto fail;
- }
-
- if (n_field_hash_tables != 1) {
- log_error("Missing field hash table");
- r = -EBADMSG;
- goto fail;
- }
-
- if (!found_main_entry_array) {
- log_error("Missing entry array");
- r = -EBADMSG;
- goto fail;
- }
-
- if (entry_seqnum_set &&
- entry_seqnum != le64toh(f->header->tail_entry_seqnum)) {
- log_error("Invalid tail seqnum");
- r = -EBADMSG;
- goto fail;
- }
-
- if (entry_monotonic_set &&
- (!sd_id128_equal(entry_boot_id, f->header->boot_id) ||
- entry_monotonic != le64toh(f->header->tail_entry_monotonic))) {
- log_error("Invalid tail monotonic timestamp");
- r = -EBADMSG;
- goto fail;
- }
-
- if (entry_realtime_set && entry_realtime != le64toh(f->header->tail_entry_realtime)) {
- log_error("Invalid tail realtime timestamp");
- r = -EBADMSG;
- goto fail;
- }
-
- /* Second iteration: we follow all objects referenced from the
- * two entry points: the object hash table and the entry
- * array. We also check that everything referenced (directly
- * or indirectly) in the data hash table also exists in the
- * entry array, and vice versa. Note that we do not care for
- * unreferenced objects. We only care that everything that is
- * referenced is consistent. */
-
- r = verify_entry_array(f,
- data_fd, n_data,
- entry_fd, n_entries,
- entry_array_fd, n_entry_arrays,
- &last_usec,
- show_progress);
- if (r < 0)
- goto fail;
-
- r = verify_hash_table(f,
- data_fd, n_data,
- entry_fd, n_entries,
- entry_array_fd, n_entry_arrays,
- &last_usec,
- show_progress);
- if (r < 0)
- goto fail;
-
- if (show_progress)
- flush_progress();
-
- mmap_cache_close_fd(f->mmap, data_fd);
- mmap_cache_close_fd(f->mmap, entry_fd);
- mmap_cache_close_fd(f->mmap, entry_array_fd);
-
- close_nointr_nofail(data_fd);
- close_nointr_nofail(entry_fd);
- close_nointr_nofail(entry_array_fd);
-
- if (first_contained)
- *first_contained = le64toh(f->header->head_entry_realtime);
- if (last_validated)
- *last_validated = last_sealed_realtime;
- if (last_contained)
- *last_contained = le64toh(f->header->tail_entry_realtime);
-
- return 0;
-
-fail:
- if (show_progress)
- flush_progress();
-
- log_error("File corruption detected at %s:%llu (of %llu, %llu%%).",
- f->path,
- (unsigned long long) p,
- (unsigned long long) f->last_stat.st_size,
- (unsigned long long) (100 * p / f->last_stat.st_size));
-
- if (data_fd >= 0) {
- mmap_cache_close_fd(f->mmap, data_fd);
- close_nointr_nofail(data_fd);
- }
-
- if (entry_fd >= 0) {
- mmap_cache_close_fd(f->mmap, entry_fd);
- close_nointr_nofail(entry_fd);
- }
-
- if (entry_array_fd >= 0) {
- mmap_cache_close_fd(f->mmap, entry_array_fd);
- close_nointr_nofail(entry_array_fd);
- }
-
- return r;
-}
diff --git a/src/journal/journal-verify.h b/src/journal/journal-verify.h
deleted file mode 100644
index e392ab61d7..0000000000
--- a/src/journal/journal-verify.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 "journal-file.h"
-
-int journal_file_verify(JournalFile *f, const char *key, usec_t *first_contained, usec_t *last_validated, usec_t *last_contained, bool show_progress);
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
deleted file mode 100644
index cccd8a7692..0000000000
--- a/src/journal/journalctl.c
+++ /dev/null
@@ -1,1060 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <fcntl.h>
-#include <errno.h>
-#include <stddef.h>
-#include <string.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/poll.h>
-#include <time.h>
-#include <getopt.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <linux/fs.h>
-
-#include <systemd/sd-journal.h>
-
-#include "log.h"
-#include "util.h"
-#include "path-util.h"
-#include "build.h"
-#include "pager.h"
-#include "logs-show.h"
-#include "strv.h"
-#include "journal-internal.h"
-#include "journal-def.h"
-#include "journal-verify.h"
-#include "journal-authenticate.h"
-#include "journal-qrcode.h"
-#include "fsprg.h"
-#include "unit-name.h"
-
-#define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
-
-static OutputMode arg_output = OUTPUT_SHORT;
-static bool arg_follow = false;
-static bool arg_all = false;
-static bool arg_no_pager = false;
-static unsigned arg_lines = 0;
-static bool arg_no_tail = false;
-static bool arg_quiet = false;
-static bool arg_merge = false;
-static bool arg_this_boot = false;
-static const char *arg_cursor = NULL;
-static const char *arg_directory = NULL;
-static int arg_priorities = 0xFF;
-static const char *arg_verify_key = NULL;
-#ifdef HAVE_GCRYPT
-static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
-#endif
-static usec_t arg_since, arg_until;
-static bool arg_since_set = false, arg_until_set = false;
-static const char *arg_unit = NULL;
-static const char *arg_field = NULL;
-
-static enum {
- ACTION_SHOW,
- ACTION_NEW_ID128,
- ACTION_PRINT_HEADER,
- ACTION_SETUP_KEYS,
- ACTION_VERIFY,
- ACTION_DISK_USAGE,
-} arg_action = ACTION_SHOW;
-
-static int help(void) {
-
- printf("%s [OPTIONS...] [MATCHES...]\n\n"
- "Query the journal.\n\n"
- "Flags:\n"
- " --since=DATE Start showing entries newer or of the specified date\n"
- " --until=DATE Stop showing entries older or of the specified date\n"
- " -c --cursor=CURSOR Start showing entries from specified cursor\n"
- " -b --this-boot Show data only from current boot\n"
- " -u --unit=UNIT Show data only from the specified unit\n"
- " -p --priority=RANGE Show only messages within the specified priority range\n"
- " -f --follow Follow journal\n"
- " -n --lines[=INTEGER] Number of journal entries to show\n"
- " --no-tail Show all lines, even in follow mode\n"
- " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
- " verbose, export, json, json-pretty, json-sse, cat)\n"
- " -a --all Show all fields, including long and unprintable\n"
- " -q --quiet Don't show privilege warning\n"
- " --no-pager Do not pipe output into a pager\n"
- " -m --merge Show entries from all available journals\n"
- " -D --directory=PATH Show journal files from directory\n"
-#ifdef HAVE_GCRYPT
- " --interval=TIME Time interval for changing the FSS sealing key\n"
- " --verify-key=KEY Specify FSS verification key\n"
-#endif
- "\nCommands:\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --new-id128 Generate a new 128 Bit ID\n"
- " --header Show journal header information\n"
- " --disk-usage Show total disk usage\n"
- " -F --field=FIELD List all values a certain field takes\n"
-#ifdef HAVE_GCRYPT
- " --setup-keys Generate new FSS key pair\n"
- " --verify Verify journal file consistency\n"
-#endif
- , program_invocation_short_name);
-
- return 0;
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100,
- ARG_NO_PAGER,
- ARG_NO_TAIL,
- ARG_NEW_ID128,
- ARG_HEADER,
- ARG_SETUP_KEYS,
- ARG_INTERVAL,
- ARG_VERIFY,
- ARG_VERIFY_KEY,
- ARG_DISK_USAGE,
- ARG_SINCE,
- ARG_UNTIL
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version" , no_argument, NULL, ARG_VERSION },
- { "no-pager", no_argument, NULL, ARG_NO_PAGER },
- { "follow", no_argument, NULL, 'f' },
- { "output", required_argument, NULL, 'o' },
- { "all", no_argument, NULL, 'a' },
- { "lines", optional_argument, NULL, 'n' },
- { "no-tail", no_argument, NULL, ARG_NO_TAIL },
- { "new-id128", no_argument, NULL, ARG_NEW_ID128 },
- { "quiet", no_argument, NULL, 'q' },
- { "merge", no_argument, NULL, 'm' },
- { "this-boot", no_argument, NULL, 'b' },
- { "directory", required_argument, NULL, 'D' },
- { "header", no_argument, NULL, ARG_HEADER },
- { "priority", no_argument, NULL, 'p' },
- { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS },
- { "interval", required_argument, NULL, ARG_INTERVAL },
- { "verify", no_argument, NULL, ARG_VERIFY },
- { "verify-key", required_argument, NULL, ARG_VERIFY_KEY },
- { "disk-usage", no_argument, NULL, ARG_DISK_USAGE },
- { "cursor", required_argument, NULL, 'c' },
- { "since", required_argument, NULL, ARG_SINCE },
- { "until", required_argument, NULL, ARG_UNTIL },
- { "unit", required_argument, NULL, 'u' },
- { "field", required_argument, NULL, 'F' },
- { NULL, 0, NULL, 0 }
- };
-
- int c, r;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "hfo:an::qmbD:p:c:u:F:", options, NULL)) >= 0) {
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(DISTRIBUTION);
- puts(SYSTEMD_FEATURES);
- return 0;
-
- case ARG_NO_PAGER:
- arg_no_pager = true;
- break;
-
- case 'f':
- arg_follow = true;
- break;
-
- case 'o':
- arg_output = output_mode_from_string(optarg);
- if (arg_output < 0) {
- log_error("Unknown output format '%s'.", optarg);
- return -EINVAL;
- }
-
- if (arg_output == OUTPUT_EXPORT ||
- arg_output == OUTPUT_JSON ||
- arg_output == OUTPUT_JSON_PRETTY ||
- arg_output == OUTPUT_JSON_SSE ||
- arg_output == OUTPUT_CAT)
- arg_quiet = true;
-
- break;
-
- case 'a':
- arg_all = true;
- break;
-
- case 'n':
- if (optarg) {
- r = safe_atou(optarg, &arg_lines);
- if (r < 0 || arg_lines <= 0) {
- log_error("Failed to parse lines '%s'", optarg);
- return -EINVAL;
- }
- } else
- arg_lines = 10;
-
- break;
-
- case ARG_NO_TAIL:
- arg_no_tail = true;
- break;
-
- case ARG_NEW_ID128:
- arg_action = ACTION_NEW_ID128;
- break;
-
- case 'q':
- arg_quiet = true;
- break;
-
- case 'm':
- arg_merge = true;
- break;
-
- case 'b':
- arg_this_boot = true;
- break;
-
- case 'D':
- arg_directory = optarg;
- break;
-
- case 'c':
- arg_cursor = optarg;
- break;
-
- case ARG_HEADER:
- arg_action = ACTION_PRINT_HEADER;
- break;
-
- case ARG_VERIFY:
- arg_action = ACTION_VERIFY;
- break;
-
- case ARG_DISK_USAGE:
- arg_action = ACTION_DISK_USAGE;
- break;
-
-#ifdef HAVE_GCRYPT
- case ARG_SETUP_KEYS:
- arg_action = ACTION_SETUP_KEYS;
- break;
-
-
- case ARG_VERIFY_KEY:
- arg_action = ACTION_VERIFY;
- arg_verify_key = optarg;
- arg_merge = false;
- break;
-
- case ARG_INTERVAL:
- r = parse_usec(optarg, &arg_interval);
- if (r < 0 || arg_interval <= 0) {
- log_error("Failed to parse sealing key change interval: %s", optarg);
- return -EINVAL;
- }
- break;
-#else
- case ARG_SETUP_KEYS:
- case ARG_VERIFY_KEY:
- case ARG_INTERVAL:
- log_error("Forward-secure sealing not available.");
- return -ENOTSUP;
-#endif
-
- case 'p': {
- const char *dots;
-
- dots = strstr(optarg, "..");
- if (dots) {
- char *a;
- int from, to, i;
-
- /* a range */
- a = strndup(optarg, dots - optarg);
- if (!a)
- return log_oom();
-
- from = log_level_from_string(a);
- to = log_level_from_string(dots + 2);
- free(a);
-
- if (from < 0 || to < 0) {
- log_error("Failed to parse log level range %s", optarg);
- return -EINVAL;
- }
-
- arg_priorities = 0;
-
- if (from < to) {
- for (i = from; i <= to; i++)
- arg_priorities |= 1 << i;
- } else {
- for (i = to; i <= from; i++)
- arg_priorities |= 1 << i;
- }
-
- } else {
- int p, i;
-
- p = log_level_from_string(optarg);
- if (p < 0) {
- log_error("Unknown log level %s", optarg);
- return -EINVAL;
- }
-
- arg_priorities = 0;
-
- for (i = 0; i <= p; i++)
- arg_priorities |= 1 << i;
- }
-
- break;
- }
-
- case ARG_SINCE:
- r = parse_timestamp(optarg, &arg_since);
- if (r < 0) {
- log_error("Failed to parse timestamp: %s", optarg);
- return -EINVAL;
- }
- arg_since_set = true;
- break;
-
- case ARG_UNTIL:
- r = parse_timestamp(optarg, &arg_until);
- if (r < 0) {
- log_error("Failed to parse timestamp: %s", optarg);
- return -EINVAL;
- }
- arg_until_set = true;
- break;
-
- case 'u':
- arg_unit = optarg;
- break;
-
- case '?':
- return -EINVAL;
-
- case 'F':
- arg_field = optarg;
- break;
-
- default:
- log_error("Unknown option code %c", c);
- return -EINVAL;
- }
- }
-
- if (arg_follow && !arg_no_tail && arg_lines <= 0)
- arg_lines = 10;
-
- if (arg_since_set && arg_until_set && arg_since_set > arg_until_set) {
- log_error("--since= must be before --until=.");
- return -EINVAL;
- }
-
- if (arg_cursor && arg_since_set) {
- log_error("Please specify either --since= or --cursor=, not both.");
- return -EINVAL;
- }
-
- return 1;
-}
-
-static int generate_new_id128(void) {
- sd_id128_t id;
- int r;
- unsigned i;
-
- r = sd_id128_randomize(&id);
- if (r < 0) {
- log_error("Failed to generate ID: %s", strerror(-r));
- return r;
- }
-
- printf("As string:\n"
- SD_ID128_FORMAT_STR "\n\n"
- "As UUID:\n"
- "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n"
- "As macro:\n"
- "#define MESSAGE_XYZ SD_ID128_MAKE(",
- SD_ID128_FORMAT_VAL(id),
- SD_ID128_FORMAT_VAL(id));
-
- for (i = 0; i < 16; i++)
- printf("%02x%s", id.bytes[i], i != 15 ? "," : "");
-
- fputs(")\n", stdout);
-
- return 0;
-}
-
-static int add_matches(sd_journal *j, char **args) {
- char **i;
- int r;
-
- assert(j);
-
- STRV_FOREACH(i, args) {
-
- if (streq(*i, "+"))
- r = sd_journal_add_disjunction(j);
- else if (path_is_absolute(*i)) {
- char *p, *t = NULL;
- const char *path;
- struct stat st;
-
- p = canonicalize_file_name(*i);
- path = p ? p : *i;
-
- if (stat(path, &st) < 0) {
- free(p);
- log_error("Couldn't stat file: %m");
- return -errno;
- }
-
- if (S_ISREG(st.st_mode) && (0111 & st.st_mode))
- t = strappend("_EXE=", path);
- else if (S_ISCHR(st.st_mode))
- asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
- else if (S_ISBLK(st.st_mode))
- asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
- else {
- free(p);
- log_error("File is not a device node, regular file or is not executable: %s", *i);
- return -EINVAL;
- }
-
- free(p);
-
- if (!t)
- return log_oom();
-
- r = sd_journal_add_match(j, t, 0);
- free(t);
- } else
- r = sd_journal_add_match(j, *i, 0);
-
- if (r < 0) {
- log_error("Failed to add match '%s': %s", *i, strerror(-r));
- return r;
- }
- }
-
- return 0;
-}
-
-static int add_this_boot(sd_journal *j) {
- char match[9+32+1] = "_BOOT_ID=";
- sd_id128_t boot_id;
- int r;
-
- assert(j);
-
- if (!arg_this_boot)
- return 0;
-
- r = sd_id128_get_boot(&boot_id);
- if (r < 0) {
- log_error("Failed to get boot id: %s", strerror(-r));
- return r;
- }
-
- sd_id128_to_string(boot_id, match + 9);
- r = sd_journal_add_match(j, match, strlen(match));
- if (r < 0) {
- log_error("Failed to add match: %s", strerror(-r));
- return r;
- }
-
- return 0;
-}
-
-static int add_unit(sd_journal *j) {
- _cleanup_free_ char *m = NULL, *u = NULL;
- int r;
-
- assert(j);
-
- if (isempty(arg_unit))
- return 0;
-
- u = unit_name_mangle(arg_unit);
- if (!u)
- return log_oom();
-
- m = strappend("_SYSTEMD_UNIT=", u);
- if (!m)
- return log_oom();
-
- r = sd_journal_add_match(j, m, strlen(m));
- if (r < 0) {
- log_error("Failed to add match: %s", strerror(-r));
- return r;
- }
-
- return 0;
-}
-
-static int add_priorities(sd_journal *j) {
- char match[] = "PRIORITY=0";
- int i, r;
-
- assert(j);
-
- if (arg_priorities == 0xFF)
- return 0;
-
- for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
- if (arg_priorities & (1 << i)) {
- match[sizeof(match)-2] = '0' + i;
-
- r = sd_journal_add_match(j, match, strlen(match));
- if (r < 0) {
- log_error("Failed to add match: %s", strerror(-r));
- return r;
- }
- }
-
- return 0;
-}
-
-static int setup_keys(void) {
-#ifdef HAVE_GCRYPT
- size_t mpk_size, seed_size, state_size, i;
- uint8_t *mpk, *seed, *state;
- ssize_t l;
- int fd = -1, r, attr = 0;
- sd_id128_t machine, boot;
- char *p = NULL, *k = NULL;
- struct FSSHeader h;
- uint64_t n;
-
- r = sd_id128_get_machine(&machine);
- if (r < 0) {
- log_error("Failed to get machine ID: %s", strerror(-r));
- return r;
- }
-
- r = sd_id128_get_boot(&boot);
- if (r < 0) {
- log_error("Failed to get boot ID: %s", strerror(-r));
- return r;
- }
-
- if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
- SD_ID128_FORMAT_VAL(machine)) < 0)
- return log_oom();
-
- if (access(p, F_OK) >= 0) {
- log_error("Sealing key file %s exists already.", p);
- r = -EEXIST;
- goto finish;
- }
-
- if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
- SD_ID128_FORMAT_VAL(machine)) < 0) {
- r = log_oom();
- goto finish;
- }
-
- mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
- mpk = alloca(mpk_size);
-
- seed_size = FSPRG_RECOMMENDED_SEEDLEN;
- seed = alloca(seed_size);
-
- state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
- state = alloca(state_size);
-
- fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0) {
- log_error("Failed to open /dev/random: %m");
- r = -errno;
- goto finish;
- }
-
- log_info("Generating seed...");
- l = loop_read(fd, seed, seed_size, true);
- if (l < 0 || (size_t) l != seed_size) {
- log_error("Failed to read random seed: %s", strerror(EIO));
- r = -EIO;
- goto finish;
- }
-
- log_info("Generating key pair...");
- FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
-
- log_info("Generating sealing key...");
- FSPRG_GenState0(state, mpk, seed, seed_size);
-
- assert(arg_interval > 0);
-
- n = now(CLOCK_REALTIME);
- n /= arg_interval;
-
- close_nointr_nofail(fd);
- fd = mkostemp(k, O_WRONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0) {
- log_error("Failed to open %s: %m", k);
- r = -errno;
- goto finish;
- }
-
- /* Enable secure remove, exclusion from dump, synchronous
- * writing and in-place updating */
- if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0)
- log_warning("FS_IOC_GETFLAGS failed: %m");
-
- attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL;
-
- if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0)
- log_warning("FS_IOC_SETFLAGS failed: %m");
-
- zero(h);
- memcpy(h.signature, "KSHHRHLP", 8);
- h.machine_id = machine;
- h.boot_id = boot;
- h.header_size = htole64(sizeof(h));
- h.start_usec = htole64(n * arg_interval);
- h.interval_usec = htole64(arg_interval);
- h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
- h.fsprg_state_size = htole64(state_size);
-
- l = loop_write(fd, &h, sizeof(h), false);
- if (l < 0 || (size_t) l != sizeof(h)) {
- log_error("Failed to write header: %s", strerror(EIO));
- r = -EIO;
- goto finish;
- }
-
- l = loop_write(fd, state, state_size, false);
- if (l < 0 || (size_t) l != state_size) {
- log_error("Failed to write state: %s", strerror(EIO));
- r = -EIO;
- goto finish;
- }
-
- if (link(k, p) < 0) {
- log_error("Failed to link file: %m");
- r = -errno;
- goto finish;
- }
-
- if (on_tty()) {
- fprintf(stderr,
- "\n"
- "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
- "the following local file. This key file is automatically updated when the\n"
- "sealing key is advanced. It should not be used on multiple hosts.\n"
- "\n"
- "\t%s\n"
- "\n"
- "Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n"
- "at a safe location and should not be saved locally on disk.\n"
- "\n\t" ANSI_HIGHLIGHT_RED_ON, p);
- fflush(stderr);
- }
- for (i = 0; i < seed_size; i++) {
- if (i > 0 && i % 3 == 0)
- putchar('-');
- printf("%02x", ((uint8_t*) seed)[i]);
- }
-
- printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
-
- if (on_tty()) {
- char tsb[FORMAT_TIMESPAN_MAX], *hn;
-
- fprintf(stderr,
- ANSI_HIGHLIGHT_OFF "\n"
- "The sealing key is automatically changed every %s.\n",
- format_timespan(tsb, sizeof(tsb), arg_interval));
-
- hn = gethostname_malloc();
-
- if (hn) {
- hostname_cleanup(hn);
- fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
- } else
- fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
-
-#ifdef HAVE_QRENCODE
- /* If this is not an UTF-8 system don't print any QR codes */
- if (is_locale_utf8()) {
- fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
- print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
- }
-#endif
- free(hn);
- }
-
- r = 0;
-
-finish:
- if (fd >= 0)
- close_nointr_nofail(fd);
-
- if (k) {
- unlink(k);
- free(k);
- }
-
- free(p);
-
- return r;
-#else
- log_error("Forward-secure sealing not available.");
- return -ENOTSUP;
-#endif
-}
-
-static int verify(sd_journal *j) {
- int r = 0;
- Iterator i;
- JournalFile *f;
-
- assert(j);
-
- log_show_color(true);
-
- HASHMAP_FOREACH(f, j->files, i) {
- int k;
- usec_t first, validated, last;
-
-#ifdef HAVE_GCRYPT
- if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
- log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
-#endif
-
- k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
- if (k == -EINVAL) {
- /* If the key was invalid give up right-away. */
- return k;
- } else if (k < 0) {
- log_warning("FAIL: %s (%s)", f->path, strerror(-k));
- r = k;
- } else {
- char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
- log_info("PASS: %s", f->path);
-
- if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
- if (validated > 0) {
- log_info("=> Validated from %s to %s, final %s entries not sealed.",
- format_timestamp(a, sizeof(a), first),
- format_timestamp(b, sizeof(b), validated),
- format_timespan(c, sizeof(c), last > validated ? last - validated : 0));
- } else if (last > 0)
- log_info("=> No sealing yet, %s of entries not sealed.",
- format_timespan(c, sizeof(c), last - first));
- else
- log_info("=> No sealing yet, no entries in file.");
- }
- }
- }
-
- return r;
-}
-
-static int access_check(void) {
-
-#ifdef HAVE_ACL
- if (access("/var/log/journal", F_OK) < 0 && geteuid() != 0 && in_group("adm") <= 0) {
- log_error("Unprivileged users can't see messages unless persistent log storage is enabled. Users in the group 'adm' can always see messages.");
- return -EACCES;
- }
-
- if (!arg_quiet && geteuid() != 0 && in_group("adm") <= 0)
- log_warning("Showing user generated messages only. Users in the group 'adm' can see all messages. Pass -q to turn this notice off.");
-#else
- if (geteuid() != 0 && in_group("adm") <= 0) {
- log_error("No access to messages. Only users in the group 'adm' can see messages.");
- return -EACCES;
- }
-#endif
-
- return 0;
-}
-
-int main(int argc, char *argv[]) {
- int r;
- sd_journal *j = NULL;
- bool need_seek = false;
- sd_id128_t previous_boot_id;
- bool previous_boot_id_valid = false;
- unsigned n_shown = 0;
-
- setlocale(LC_ALL, "");
- log_parse_environment();
- log_open();
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- goto finish;
-
- signal(SIGWINCH, columns_lines_cache_reset);
-
- if (arg_action == ACTION_NEW_ID128) {
- r = generate_new_id128();
- goto finish;
- }
-
- if (arg_action == ACTION_SETUP_KEYS) {
- r = setup_keys();
- goto finish;
- }
-
- r = access_check();
- if (r < 0)
- goto finish;
-
- if (arg_directory)
- r = sd_journal_open_directory(&j, arg_directory, 0);
- else
- r = sd_journal_open(&j, arg_merge ? 0 : SD_JOURNAL_LOCAL_ONLY);
- if (r < 0) {
- log_error("Failed to open journal: %s", strerror(-r));
- goto finish;
- }
-
- if (arg_action == ACTION_VERIFY) {
- r = verify(j);
- goto finish;
- }
-
- if (arg_action == ACTION_PRINT_HEADER) {
- journal_print_header(j);
- r = 0;
- goto finish;
- }
-
- if (arg_action == ACTION_DISK_USAGE) {
- uint64_t bytes;
- char sbytes[FORMAT_BYTES_MAX];
-
- r = sd_journal_get_usage(j, &bytes);
- if (r < 0)
- goto finish;
-
- printf("Journals take up %s on disk.\n", format_bytes(sbytes, sizeof(sbytes), bytes));
- r = 0;
- goto finish;
- }
-
- r = add_this_boot(j);
- if (r < 0)
- goto finish;
-
- r = add_unit(j);
- if (r < 0)
- goto finish;
-
- r = add_matches(j, argv + optind);
- if (r < 0)
- goto finish;
-
- r = add_priorities(j);
- if (r < 0)
- goto finish;
-
- if (arg_field) {
- const void *data;
- size_t size;
-
- r = sd_journal_query_unique(j, arg_field);
- if (r < 0) {
- log_error("Failed to query unique data objects: %s", strerror(-r));
- goto finish;
- }
-
- SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
- const void *eq;
-
- if (arg_lines > 0 && n_shown >= arg_lines)
- break;
-
- eq = memchr(data, '=', size);
- if (eq)
- printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
- else
- printf("%.*s\n", (int) size, (const char*) data);
-
- n_shown ++;
- }
-
- r = 0;
- goto finish;
- }
-
- if (arg_cursor) {
- r = sd_journal_seek_cursor(j, arg_cursor);
- if (r < 0) {
- log_error("Failed to seek to cursor: %s", strerror(-r));
- goto finish;
- }
-
- r = sd_journal_next(j);
-
- } else if (arg_since_set) {
- r = sd_journal_seek_realtime_usec(j, arg_since);
- if (r < 0) {
- log_error("Failed to seek to date: %s", strerror(-r));
- goto finish;
- }
- r = sd_journal_next(j);
-
- } else if (arg_lines > 0) {
- r = sd_journal_seek_tail(j);
- if (r < 0) {
- log_error("Failed to seek to tail: %s", strerror(-r));
- goto finish;
- }
-
- r = sd_journal_previous_skip(j, arg_lines);
-
- } else {
- r = sd_journal_seek_head(j);
- if (r < 0) {
- log_error("Failed to seek to head: %s", strerror(-r));
- goto finish;
- }
-
- r = sd_journal_next(j);
- }
-
- if (r < 0) {
- log_error("Failed to iterate through journal: %s", strerror(-r));
- goto finish;
- }
-
- if (!arg_no_pager && !arg_follow)
- pager_open();
-
- if (!arg_quiet) {
- usec_t start, end;
- char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
-
- r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
- if (r < 0) {
- log_error("Failed to get cutoff: %s", strerror(-r));
- goto finish;
- }
-
- if (r > 0) {
- if (arg_follow)
- printf("-- Logs begin at %s. --\n",
- format_timestamp(start_buf, sizeof(start_buf), start));
- else
- printf("-- Logs begin at %s, end at %s. --\n",
- format_timestamp(start_buf, sizeof(start_buf), start),
- format_timestamp(end_buf, sizeof(end_buf), end));
- }
- }
-
- for (;;) {
- while (arg_lines == 0 || arg_follow || n_shown < arg_lines) {
- int flags;
-
- if (need_seek) {
- r = sd_journal_next(j);
- if (r < 0) {
- log_error("Failed to iterate through journal: %s", strerror(-r));
- goto finish;
- }
- }
-
- if (r == 0)
- break;
-
- if (arg_until_set) {
- usec_t usec;
-
- r = sd_journal_get_realtime_usec(j, &usec);
- if (r < 0) {
- log_error("Failed to determine timestamp: %s", strerror(-r));
- goto finish;
- }
- }
-
- if (!arg_merge) {
- sd_id128_t boot_id;
-
- r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
- if (r >= 0) {
- if (previous_boot_id_valid &&
- !sd_id128_equal(boot_id, previous_boot_id))
- printf(ANSI_HIGHLIGHT_ON "-- Reboot --" ANSI_HIGHLIGHT_OFF "\n");
-
- previous_boot_id = boot_id;
- previous_boot_id_valid = true;
- }
- }
-
- flags =
- arg_all * OUTPUT_SHOW_ALL |
- (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
- on_tty() * OUTPUT_COLOR;
-
- r = output_journal(stdout, j, arg_output, 0, flags);
- if (r < 0)
- goto finish;
-
- need_seek = true;
- n_shown++;
- }
-
- if (!arg_follow)
- break;
-
- r = sd_journal_wait(j, (uint64_t) -1);
- if (r < 0) {
- log_error("Couldn't wait for journal event: %s", strerror(-r));
- goto finish;
- }
- }
-
-finish:
- if (j)
- sd_journal_close(j);
-
- pager_close();
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/journal/journald-console.c b/src/journal/journald-console.c
deleted file mode 100644
index be55f94878..0000000000
--- a/src/journal/journald-console.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <unistd.h>
-#include <sys/socket.h>
-
-#include "journald-server.h"
-#include "journald-console.h"
-
-void server_forward_console(
- Server *s,
- int priority,
- const char *identifier,
- const char *message,
- struct ucred *ucred) {
-
- struct iovec iovec[4];
- char header_pid[16];
- int n = 0, fd;
- char *ident_buf = NULL;
- const char *tty;
-
- assert(s);
- assert(message);
-
- if (LOG_PRI(priority) > s->max_level_console)
- return;
-
- /* First: identifier and PID */
- if (ucred) {
- if (!identifier) {
- get_process_comm(ucred->pid, &ident_buf);
- identifier = ident_buf;
- }
-
- snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) ucred->pid);
- char_array_0(header_pid);
-
- if (identifier)
- IOVEC_SET_STRING(iovec[n++], identifier);
-
- IOVEC_SET_STRING(iovec[n++], header_pid);
- } else if (identifier) {
- IOVEC_SET_STRING(iovec[n++], identifier);
- IOVEC_SET_STRING(iovec[n++], ": ");
- }
-
- /* Third: message */
- IOVEC_SET_STRING(iovec[n++], message);
- IOVEC_SET_STRING(iovec[n++], "\n");
-
- tty = s->tty_path ? s->tty_path : "/dev/console";
-
- fd = open_terminal(tty, O_WRONLY|O_NOCTTY|O_CLOEXEC);
- if (fd < 0) {
- log_debug("Failed to open %s for logging: %s", tty, strerror(errno));
- goto finish;
- }
-
- if (writev(fd, iovec, n) < 0)
- log_debug("Failed to write to %s for logging: %s", tty, strerror(errno));
-
- close_nointr_nofail(fd);
-
-finish:
- free(ident_buf);
-}
diff --git a/src/journal/journald-console.h b/src/journal/journald-console.h
deleted file mode 100644
index aa8e6579ba..0000000000
--- a/src/journal/journald-console.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 "journald-server.h"
-
-void server_forward_console(Server *s, int priority, const char *identifier, const char *message, struct ucred *ucred);
diff --git a/src/journal/journald-gperf.gperf b/src/journal/journald-gperf.gperf
deleted file mode 100644
index 1baef1411c..0000000000
--- a/src/journal/journald-gperf.gperf
+++ /dev/null
@@ -1,39 +0,0 @@
-%{
-#include <stddef.h>
-#include <sys/socket.h>
-#include "conf-parser.h"
-#include "journald-server.h"
-%}
-struct ConfigPerfItem;
-%null_strings
-%language=ANSI-C
-%define slot-name section_and_lvalue
-%define hash-function-name journald_gperf_hash
-%define lookup-function-name journald_gperf_lookup
-%readonly-tables
-%omit-struct-type
-%struct-type
-%includes
-%%
-Journal.Storage, config_parse_storage, 0, offsetof(Server, storage)
-Journal.Compress, config_parse_bool, 0, offsetof(Server, compress)
-Journal.Seal, config_parse_bool, 0, offsetof(Server, seal)
-Journal.RateLimitInterval, config_parse_usec, 0, offsetof(Server, rate_limit_interval)
-Journal.RateLimitBurst, config_parse_unsigned, 0, offsetof(Server, rate_limit_burst)
-Journal.SystemMaxUse, config_parse_bytes_off, 0, offsetof(Server, system_metrics.max_use)
-Journal.SystemMaxFileSize, config_parse_bytes_off, 0, offsetof(Server, system_metrics.max_size)
-Journal.SystemKeepFree, config_parse_bytes_off, 0, offsetof(Server, system_metrics.keep_free)
-Journal.RuntimeMaxUse, config_parse_bytes_off, 0, offsetof(Server, runtime_metrics.max_use)
-Journal.RuntimeMaxFileSize, config_parse_bytes_off, 0, offsetof(Server, runtime_metrics.max_size)
-Journal.RuntimeKeepFree, config_parse_bytes_off, 0, offsetof(Server, runtime_metrics.keep_free)
-Journal.MaxRetentionSec, config_parse_usec, 0, offsetof(Server, max_retention_usec)
-Journal.MaxFileSec, config_parse_usec, 0, offsetof(Server, max_file_usec)
-Journal.ForwardToSyslog, config_parse_bool, 0, offsetof(Server, forward_to_syslog)
-Journal.ForwardToKMsg, config_parse_bool, 0, offsetof(Server, forward_to_kmsg)
-Journal.ForwardToConsole, config_parse_bool, 0, offsetof(Server, forward_to_console)
-Journal.TTYPath, config_parse_path, 0, offsetof(Server, tty_path)
-Journal.MaxLevelStore, config_parse_level, 0, offsetof(Server, max_level_store)
-Journal.MaxLevelSyslog, config_parse_level, 0, offsetof(Server, max_level_syslog)
-Journal.MaxLevelKMsg, config_parse_level, 0, offsetof(Server, max_level_kmsg)
-Journal.MaxLevelConsole, config_parse_level, 0, offsetof(Server, max_level_console)
-Journal.SplitMode, config_parse_split_mode,0, offsetof(Server, split_mode)
diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c
deleted file mode 100644
index b8198760d6..0000000000
--- a/src/journal/journald-kmsg.c
+++ /dev/null
@@ -1,438 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <unistd.h>
-#include <sys/epoll.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/socket.h>
-
-#include <systemd/sd-messages.h>
-#include <libudev.h>
-
-#include "journald-server.h"
-#include "journald-kmsg.h"
-#include "journald-syslog.h"
-
-void server_forward_kmsg(
- Server *s,
- int priority,
- const char *identifier,
- const char *message,
- struct ucred *ucred) {
-
- struct iovec iovec[5];
- char header_priority[6], header_pid[16];
- int n = 0;
- char *ident_buf = NULL;
-
- assert(s);
- assert(priority >= 0);
- assert(priority <= 999);
- assert(message);
-
- if (_unlikely_(LOG_PRI(priority) > s->max_level_kmsg))
- return;
-
- if (_unlikely_(s->dev_kmsg_fd < 0))
- return;
-
- /* Never allow messages with kernel facility to be written to
- * kmsg, regardless where the data comes from. */
- priority = syslog_fixup_facility(priority);
-
- /* First: priority field */
- snprintf(header_priority, sizeof(header_priority), "<%i>", priority);
- char_array_0(header_priority);
- IOVEC_SET_STRING(iovec[n++], header_priority);
-
- /* Second: identifier and PID */
- if (ucred) {
- if (!identifier) {
- get_process_comm(ucred->pid, &ident_buf);
- identifier = ident_buf;
- }
-
- snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) ucred->pid);
- char_array_0(header_pid);
-
- if (identifier)
- IOVEC_SET_STRING(iovec[n++], identifier);
-
- IOVEC_SET_STRING(iovec[n++], header_pid);
- } else if (identifier) {
- IOVEC_SET_STRING(iovec[n++], identifier);
- IOVEC_SET_STRING(iovec[n++], ": ");
- }
-
- /* Fourth: message */
- IOVEC_SET_STRING(iovec[n++], message);
- IOVEC_SET_STRING(iovec[n++], "\n");
-
- if (writev(s->dev_kmsg_fd, iovec, n) < 0)
- log_debug("Failed to write to /dev/kmsg for logging: %s", strerror(errno));
-
- free(ident_buf);
-}
-
-static bool is_us(const char *pid) {
- pid_t t;
-
- assert(pid);
-
- if (parse_pid(pid, &t) < 0)
- return false;
-
- return t == getpid();
-}
-
-static void dev_kmsg_record(Server *s, char *p, size_t l) {
- struct iovec iovec[N_IOVEC_META_FIELDS + 7 + N_IOVEC_KERNEL_FIELDS + 2 + N_IOVEC_UDEV_FIELDS];
- char *message = NULL, *syslog_priority = NULL, *syslog_pid = NULL, *syslog_facility = NULL, *syslog_identifier = NULL, *source_time = NULL;
- int priority, r;
- unsigned n = 0, z = 0, j;
- unsigned long long usec;
- char *identifier = NULL, *pid = NULL, *e, *f, *k;
- uint64_t serial;
- size_t pl;
- char *kernel_device = NULL;
-
- assert(s);
- assert(p);
-
- if (l <= 0)
- return;
-
- e = memchr(p, ',', l);
- if (!e)
- return;
- *e = 0;
-
- r = safe_atoi(p, &priority);
- if (r < 0 || priority < 0 || priority > 999)
- return;
-
- if (s->forward_to_kmsg && (priority & LOG_FACMASK) != LOG_KERN)
- return;
-
- l -= (e - p) + 1;
- p = e + 1;
- e = memchr(p, ',', l);
- if (!e)
- return;
- *e = 0;
-
- r = safe_atou64(p, &serial);
- if (r < 0)
- return;
-
- if (s->kernel_seqnum) {
- /* We already read this one? */
- if (serial < *s->kernel_seqnum)
- return;
-
- /* Did we lose any? */
- if (serial > *s->kernel_seqnum)
- server_driver_message(s, SD_MESSAGE_JOURNAL_MISSED, "Missed %llu kernel messages", (unsigned long long) serial - *s->kernel_seqnum - 1);
-
- /* Make sure we never read this one again. Note that
- * we always store the next message serial we expect
- * here, simply because this makes handling the first
- * message with serial 0 easy. */
- *s->kernel_seqnum = serial + 1;
- }
-
- l -= (e - p) + 1;
- p = e + 1;
- f = memchr(p, ';', l);
- if (!f)
- return;
- /* Kernel 3.6 has the flags field, kernel 3.5 lacks that */
- e = memchr(p, ',', l);
- if (!e || f < e)
- e = f;
- *e = 0;
-
- r = safe_atollu(p, &usec);
- if (r < 0)
- return;
-
- l -= (f - p) + 1;
- p = f + 1;
- e = memchr(p, '\n', l);
- if (!e)
- return;
- *e = 0;
-
- pl = e - p;
- l -= (e - p) + 1;
- k = e + 1;
-
- for (j = 0; l > 0 && j < N_IOVEC_KERNEL_FIELDS; j++) {
- char *m;
- /* Meta data fields attached */
-
- if (*k != ' ')
- break;
-
- k ++, l --;
-
- e = memchr(k, '\n', l);
- if (!e)
- return;
-
- *e = 0;
-
- m = cunescape_length_with_prefix(k, e - k, "_KERNEL_");
- if (!m)
- break;
-
- if (startswith(m, "_KERNEL_DEVICE="))
- kernel_device = m + 15;
-
- IOVEC_SET_STRING(iovec[n++], m);
- z++;
-
- l -= (e - k) + 1;
- k = e + 1;
- }
-
- if (kernel_device) {
- struct udev_device *ud;
-
- ud = udev_device_new_from_device_id(s->udev, kernel_device);
- if (ud) {
- const char *g;
- struct udev_list_entry *ll;
- char *b;
-
- g = udev_device_get_devnode(ud);
- if (g) {
- b = strappend("_UDEV_DEVNODE=", g);
- if (b) {
- IOVEC_SET_STRING(iovec[n++], b);
- z++;
- }
- }
-
- g = udev_device_get_sysname(ud);
- if (g) {
- b = strappend("_UDEV_SYSNAME=", g);
- if (b) {
- IOVEC_SET_STRING(iovec[n++], b);
- z++;
- }
- }
-
- j = 0;
- ll = udev_device_get_devlinks_list_entry(ud);
- udev_list_entry_foreach(ll, ll) {
-
- if (j > N_IOVEC_UDEV_FIELDS)
- break;
-
- g = udev_list_entry_get_name(ll);
- b = strappend("_UDEV_DEVLINK=", g);
- if (g) {
- IOVEC_SET_STRING(iovec[n++], b);
- z++;
- }
-
- j++;
- }
-
- udev_device_unref(ud);
- }
- }
-
- if (asprintf(&source_time, "_SOURCE_MONOTONIC_TIMESTAMP=%llu", usec) >= 0)
- IOVEC_SET_STRING(iovec[n++], source_time);
-
- IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=kernel");
-
- if (asprintf(&syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK) >= 0)
- IOVEC_SET_STRING(iovec[n++], syslog_priority);
-
- if ((priority & LOG_FACMASK) == LOG_KERN)
- IOVEC_SET_STRING(iovec[n++], "SYSLOG_IDENTIFIER=kernel");
- else {
- pl -= syslog_parse_identifier((const char**) &p, &identifier, &pid);
-
- /* Avoid any messages we generated ourselves via
- * log_info() and friends. */
- if (pid && is_us(pid))
- goto finish;
-
- if (identifier) {
- syslog_identifier = strappend("SYSLOG_IDENTIFIER=", identifier);
- if (syslog_identifier)
- IOVEC_SET_STRING(iovec[n++], syslog_identifier);
- }
-
- if (pid) {
- syslog_pid = strappend("SYSLOG_PID=", pid);
- if (syslog_pid)
- IOVEC_SET_STRING(iovec[n++], syslog_pid);
- }
-
- if (asprintf(&syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority)) >= 0)
- IOVEC_SET_STRING(iovec[n++], syslog_facility);
- }
-
- message = cunescape_length_with_prefix(p, pl, "MESSAGE=");
- if (message)
- IOVEC_SET_STRING(iovec[n++], message);
-
- server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), NULL, NULL, NULL, 0, NULL, priority);
-
-finish:
- for (j = 0; j < z; j++)
- free(iovec[j].iov_base);
-
- free(message);
- free(syslog_priority);
- free(syslog_identifier);
- free(syslog_pid);
- free(syslog_facility);
- free(source_time);
- free(identifier);
- free(pid);
-}
-
-int server_read_dev_kmsg(Server *s) {
- char buffer[8192+1]; /* the kernel-side limit per record is 8K currently */
- ssize_t l;
-
- assert(s);
- assert(s->dev_kmsg_fd >= 0);
-
- l = read(s->dev_kmsg_fd, buffer, sizeof(buffer) - 1);
- if (l == 0)
- return 0;
- if (l < 0) {
- /* Old kernels who don't allow reading from /dev/kmsg
- * return EINVAL when we try. So handle this cleanly,
- * but don' try to ever read from it again. */
- if (errno == EINVAL) {
- epoll_ctl(s->epoll_fd, EPOLL_CTL_DEL, s->dev_kmsg_fd, NULL);
- return 0;
- }
-
- if (errno == EAGAIN || errno == EINTR || errno == EPIPE)
- return 0;
-
- log_error("Failed to read from kernel: %m");
- return -errno;
- }
-
- dev_kmsg_record(s, buffer, l);
- return 1;
-}
-
-int server_flush_dev_kmsg(Server *s) {
- int r;
-
- assert(s);
-
- if (s->dev_kmsg_fd < 0)
- return 0;
-
- if (!s->dev_kmsg_readable)
- return 0;
-
- log_debug("Flushing /dev/kmsg...");
-
- for (;;) {
- r = server_read_dev_kmsg(s);
- if (r < 0)
- return r;
-
- if (r == 0)
- break;
- }
-
- return 0;
-}
-
-int server_open_dev_kmsg(Server *s) {
- struct epoll_event ev;
-
- assert(s);
-
- s->dev_kmsg_fd = open("/dev/kmsg", O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
- if (s->dev_kmsg_fd < 0) {
- log_warning("Failed to open /dev/kmsg, ignoring: %m");
- return 0;
- }
-
- zero(ev);
- ev.events = EPOLLIN;
- ev.data.fd = s->dev_kmsg_fd;
- if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->dev_kmsg_fd, &ev) < 0) {
-
- /* This will fail with EPERM on older kernels where
- * /dev/kmsg is not readable. */
- if (errno == EPERM)
- return 0;
-
- log_error("Failed to add /dev/kmsg fd to epoll object: %m");
- return -errno;
- }
-
- s->dev_kmsg_readable = true;
-
- return 0;
-}
-
-int server_open_kernel_seqnum(Server *s) {
- int fd;
- uint64_t *p;
-
- assert(s);
-
- /* We store the seqnum we last read in an mmaped file. That
- * way we can just use it like a variable, but it is
- * persistent and automatically flushed at reboot. */
-
- fd = open("/run/systemd/journal/kernel-seqnum", O_RDWR|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644);
- if (fd < 0) {
- log_error("Failed to open /run/systemd/journal/kernel-seqnum, ignoring: %m");
- return 0;
- }
-
- if (posix_fallocate(fd, 0, sizeof(uint64_t)) < 0) {
- log_error("Failed to allocate sequential number file, ignoring: %m");
- close_nointr_nofail(fd);
- return 0;
- }
-
- p = mmap(NULL, sizeof(uint64_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
- if (p == MAP_FAILED) {
- log_error("Failed to map sequential number file, ignoring: %m");
- close_nointr_nofail(fd);
- return 0;
- }
-
- close_nointr_nofail(fd);
- s->kernel_seqnum = p;
-
- return 0;
-}
diff --git a/src/journal/journald-kmsg.h b/src/journal/journald-kmsg.h
deleted file mode 100644
index f287161329..0000000000
--- a/src/journal/journald-kmsg.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 "journald-server.h"
-
-int server_open_dev_kmsg(Server *s);
-int server_read_dev_kmsg(Server *s);
-int server_flush_dev_kmsg(Server *s);
-
-void server_forward_kmsg(Server *s, int priority, const char *identifier, const char *message, struct ucred *ucred);
-
-int server_open_kernel_seqnum(Server *s);
diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c
deleted file mode 100644
index ac3183ece3..0000000000
--- a/src/journal/journald-native.c
+++ /dev/null
@@ -1,420 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <unistd.h>
-#include <stddef.h>
-#include <sys/epoll.h>
-
-#include "socket-util.h"
-#include "path-util.h"
-#include "journald-server.h"
-#include "journald-native.h"
-#include "journald-kmsg.h"
-#include "journald-console.h"
-#include "journald-syslog.h"
-
-#define ENTRY_SIZE_MAX (1024*1024*64)
-#define DATA_SIZE_MAX (1024*1024*64)
-
-static bool valid_user_field(const char *p, size_t l) {
- const char *a;
-
- /* We kinda enforce POSIX syntax recommendations for
- environment variables here, but make a couple of additional
- requirements.
-
- http://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html */
-
- /* No empty field names */
- if (l <= 0)
- return false;
-
- /* Don't allow names longer than 64 chars */
- if (l > 64)
- return false;
-
- /* Variables starting with an underscore are protected */
- if (p[0] == '_')
- return false;
-
- /* Don't allow digits as first character */
- if (p[0] >= '0' && p[0] <= '9')
- return false;
-
- /* Only allow A-Z0-9 and '_' */
- for (a = p; a < p + l; a++)
- if (!((*a >= 'A' && *a <= 'Z') ||
- (*a >= '0' && *a <= '9') ||
- *a == '_'))
- return false;
-
- return true;
-}
-
-void server_process_native_message(
- Server *s,
- const void *buffer, size_t buffer_size,
- struct ucred *ucred,
- struct timeval *tv,
- const char *label, size_t label_len) {
-
- struct iovec *iovec = NULL;
- unsigned n = 0, m = 0, j, tn = (unsigned) -1;
- const char *p;
- size_t remaining;
- int priority = LOG_INFO;
- char *identifier = NULL, *message = NULL;
-
- assert(s);
- assert(buffer || buffer_size == 0);
-
- p = buffer;
- remaining = buffer_size;
-
- while (remaining > 0) {
- const char *e, *q;
-
- e = memchr(p, '\n', remaining);
-
- if (!e) {
- /* Trailing noise, let's ignore it, and flush what we collected */
- log_debug("Received message with trailing noise, ignoring.");
- break;
- }
-
- if (e == p) {
- /* Entry separator */
- server_dispatch_message(s, iovec, n, m, ucred, tv, label, label_len, NULL, priority);
- n = 0;
- priority = LOG_INFO;
-
- p++;
- remaining--;
- continue;
- }
-
- if (*p == '.' || *p == '#') {
- /* Ignore control commands for now, and
- * comments too. */
- remaining -= (e - p) + 1;
- p = e + 1;
- continue;
- }
-
- /* A property follows */
-
- if (n+N_IOVEC_META_FIELDS >= m) {
- struct iovec *c;
- unsigned u;
-
- u = MAX((n+N_IOVEC_META_FIELDS+1) * 2U, 4U);
- c = realloc(iovec, u * sizeof(struct iovec));
- if (!c) {
- log_oom();
- break;
- }
-
- iovec = c;
- m = u;
- }
-
- q = memchr(p, '=', e - p);
- if (q) {
- if (valid_user_field(p, q - p)) {
- size_t l;
-
- l = e - p;
-
- /* If the field name starts with an
- * underscore, skip the variable,
- * since that indidates a trusted
- * field */
- iovec[n].iov_base = (char*) p;
- iovec[n].iov_len = l;
- n++;
-
- /* We need to determine the priority
- * of this entry for the rate limiting
- * logic */
- if (l == 10 &&
- memcmp(p, "PRIORITY=", 9) == 0 &&
- p[9] >= '0' && p[9] <= '9')
- priority = (priority & LOG_FACMASK) | (p[9] - '0');
-
- else if (l == 17 &&
- memcmp(p, "SYSLOG_FACILITY=", 16) == 0 &&
- p[16] >= '0' && p[16] <= '9')
- priority = (priority & LOG_PRIMASK) | ((p[16] - '0') << 3);
-
- else if (l == 18 &&
- memcmp(p, "SYSLOG_FACILITY=", 16) == 0 &&
- p[16] >= '0' && p[16] <= '9' &&
- p[17] >= '0' && p[17] <= '9')
- priority = (priority & LOG_PRIMASK) | (((p[16] - '0')*10 + (p[17] - '0')) << 3);
-
- else if (l >= 19 &&
- memcmp(p, "SYSLOG_IDENTIFIER=", 18) == 0) {
- char *t;
-
- t = strndup(p + 18, l - 18);
- if (t) {
- free(identifier);
- identifier = t;
- }
- } else if (l >= 8 &&
- memcmp(p, "MESSAGE=", 8) == 0) {
- char *t;
-
- t = strndup(p + 8, l - 8);
- if (t) {
- free(message);
- message = t;
- }
- }
- }
-
- remaining -= (e - p) + 1;
- p = e + 1;
- continue;
- } else {
- le64_t l_le;
- uint64_t l;
- char *k;
-
- if (remaining < e - p + 1 + sizeof(uint64_t) + 1) {
- log_debug("Failed to parse message, ignoring.");
- break;
- }
-
- memcpy(&l_le, e + 1, sizeof(uint64_t));
- l = le64toh(l_le);
-
- if (l > DATA_SIZE_MAX) {
- log_debug("Received binary data block too large, ignoring.");
- break;
- }
-
- if ((uint64_t) remaining < e - p + 1 + sizeof(uint64_t) + l + 1 ||
- e[1+sizeof(uint64_t)+l] != '\n') {
- log_debug("Failed to parse message, ignoring.");
- break;
- }
-
- k = malloc((e - p) + 1 + l);
- if (!k) {
- log_oom();
- break;
- }
-
- memcpy(k, p, e - p);
- k[e - p] = '=';
- memcpy(k + (e - p) + 1, e + 1 + sizeof(uint64_t), l);
-
- if (valid_user_field(p, e - p)) {
- iovec[n].iov_base = k;
- iovec[n].iov_len = (e - p) + 1 + l;
- n++;
- } else
- free(k);
-
- remaining -= (e - p) + 1 + sizeof(uint64_t) + l + 1;
- p = e + 1 + sizeof(uint64_t) + l + 1;
- }
- }
-
- if (n <= 0)
- goto finish;
-
- tn = n++;
- IOVEC_SET_STRING(iovec[tn], "_TRANSPORT=journal");
-
- if (message) {
- if (s->forward_to_syslog)
- server_forward_syslog(s, priority, identifier, message, ucred, tv);
-
- if (s->forward_to_kmsg)
- server_forward_kmsg(s, priority, identifier, message, ucred);
-
- if (s->forward_to_console)
- server_forward_console(s, priority, identifier, message, ucred);
- }
-
- server_dispatch_message(s, iovec, n, m, ucred, tv, label, label_len, NULL, priority);
-
-finish:
- for (j = 0; j < n; j++) {
- if (j == tn)
- continue;
-
- if (iovec[j].iov_base < buffer ||
- (const uint8_t*) iovec[j].iov_base >= (const uint8_t*) buffer + buffer_size)
- free(iovec[j].iov_base);
- }
-
- free(iovec);
- free(identifier);
- free(message);
-}
-
-void server_process_native_file(
- Server *s,
- int fd,
- struct ucred *ucred,
- struct timeval *tv,
- const char *label, size_t label_len) {
-
- struct stat st;
- _cleanup_free_ void *p = NULL;
- ssize_t n;
- int r;
-
- assert(s);
- assert(fd >= 0);
-
- if (!ucred || ucred->uid != 0) {
- _cleanup_free_ char *sl = NULL, *k = NULL;
- const char *e;
-
- if (asprintf(&sl, "/proc/self/fd/%i", fd) < 0) {
- log_oom();
- return;
- }
-
- r = readlink_malloc(sl, &k);
- if (r < 0) {
- log_error("readlink(%s) failed: %m", sl);
- return;
- }
-
- e = path_startswith(k, "/dev/shm/");
- if (!e)
- e = path_startswith(k, "/tmp/");
- if (!e)
- e = path_startswith(k, "/var/tmp/");
- if (!e) {
- log_error("Received file outside of allowed directories. Refusing.");
- return;
- }
-
- if (!filename_is_safe(e)) {
- log_error("Received file in subdirectory of allowed directories. Refusing.");
- return;
- }
- }
-
- /* Data is in the passed file, since it didn't fit in a
- * datagram. We can't map the file here, since clients might
- * then truncate it and trigger a SIGBUS for us. So let's
- * stupidly read it */
-
- if (fstat(fd, &st) < 0) {
- log_error("Failed to stat passed file, ignoring: %m");
- return;
- }
-
- if (!S_ISREG(st.st_mode)) {
- log_error("File passed is not regular. Ignoring.");
- return;
- }
-
- if (st.st_size <= 0)
- return;
-
- if (st.st_size > ENTRY_SIZE_MAX) {
- log_error("File passed too large. Ignoring.");
- return;
- }
-
- p = malloc(st.st_size);
- if (!p) {
- log_oom();
- return;
- }
-
- n = pread(fd, p, st.st_size, 0);
- if (n < 0)
- log_error("Failed to read file, ignoring: %s", strerror(-n));
- else if (n > 0)
- server_process_native_message(s, p, n, ucred, tv, label, label_len);
-}
-
-int server_open_native_socket(Server*s) {
- union sockaddr_union sa;
- int one, r;
- struct epoll_event ev;
-
- assert(s);
-
- if (s->native_fd < 0) {
-
- s->native_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (s->native_fd < 0) {
- log_error("socket() failed: %m");
- return -errno;
- }
-
- zero(sa);
- sa.un.sun_family = AF_UNIX;
- strncpy(sa.un.sun_path, "/run/systemd/journal/socket", sizeof(sa.un.sun_path));
-
- unlink(sa.un.sun_path);
-
- r = bind(s->native_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
- if (r < 0) {
- log_error("bind() failed: %m");
- return -errno;
- }
-
- chmod(sa.un.sun_path, 0666);
- } else
- fd_nonblock(s->native_fd, 1);
-
- one = 1;
- r = setsockopt(s->native_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
- if (r < 0) {
- log_error("SO_PASSCRED failed: %m");
- return -errno;
- }
-
-#ifdef HAVE_SELINUX
- one = 1;
- r = setsockopt(s->syslog_fd, SOL_SOCKET, SO_PASSSEC, &one, sizeof(one));
- if (r < 0)
- log_warning("SO_PASSSEC failed: %m");
-#endif
-
- one = 1;
- r = setsockopt(s->native_fd, SOL_SOCKET, SO_TIMESTAMP, &one, sizeof(one));
- if (r < 0) {
- log_error("SO_TIMESTAMP failed: %m");
- return -errno;
- }
-
- zero(ev);
- ev.events = EPOLLIN;
- ev.data.fd = s->native_fd;
- if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->native_fd, &ev) < 0) {
- log_error("Failed to add native server fd to epoll object: %m");
- return -errno;
- }
-
- return 0;
-}
diff --git a/src/journal/journald-native.h b/src/journal/journald-native.h
deleted file mode 100644
index 16c09f523e..0000000000
--- a/src/journal/journald-native.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 "journald-server.h"
-
-void server_process_native_message(Server *s, const void *buffer, size_t buffer_size, struct ucred *ucred, struct timeval *tv, const char *label, size_t label_len);
-
-void server_process_native_file(Server *s, int fd, struct ucred *ucred, struct timeval *tv, const char *label, size_t label_len);
-
-int server_open_native_socket(Server*s);
diff --git a/src/journal/journald-rate-limit.c b/src/journal/journald-rate-limit.c
deleted file mode 100644
index 8bd68476a3..0000000000
--- a/src/journal/journald-rate-limit.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <errno.h>
-
-#include "journald-rate-limit.h"
-#include "list.h"
-#include "util.h"
-#include "hashmap.h"
-
-#define POOLS_MAX 5
-#define BUCKETS_MAX 127
-#define GROUPS_MAX 2047
-
-static const int priority_map[] = {
- [LOG_EMERG] = 0,
- [LOG_ALERT] = 0,
- [LOG_CRIT] = 0,
- [LOG_ERR] = 1,
- [LOG_WARNING] = 2,
- [LOG_NOTICE] = 3,
- [LOG_INFO] = 3,
- [LOG_DEBUG] = 4
-};
-
-typedef struct JournalRateLimitPool JournalRateLimitPool;
-typedef struct JournalRateLimitGroup JournalRateLimitGroup;
-
-struct JournalRateLimitPool {
- usec_t begin;
- unsigned num;
- unsigned suppressed;
-};
-
-struct JournalRateLimitGroup {
- JournalRateLimit *parent;
-
- char *id;
- JournalRateLimitPool pools[POOLS_MAX];
- unsigned hash;
-
- LIST_FIELDS(JournalRateLimitGroup, bucket);
- LIST_FIELDS(JournalRateLimitGroup, lru);
-};
-
-struct JournalRateLimit {
- usec_t interval;
- unsigned burst;
-
- JournalRateLimitGroup* buckets[BUCKETS_MAX];
- JournalRateLimitGroup *lru, *lru_tail;
-
- unsigned n_groups;
-};
-
-JournalRateLimit *journal_rate_limit_new(usec_t interval, unsigned burst) {
- JournalRateLimit *r;
-
- assert(interval > 0 || burst == 0);
-
- r = new0(JournalRateLimit, 1);
- if (!r)
- return NULL;
-
- r->interval = interval;
- r->burst = burst;
-
- return r;
-}
-
-static void journal_rate_limit_group_free(JournalRateLimitGroup *g) {
- assert(g);
-
- if (g->parent) {
- assert(g->parent->n_groups > 0);
-
- if (g->parent->lru_tail == g)
- g->parent->lru_tail = g->lru_prev;
-
- LIST_REMOVE(JournalRateLimitGroup, lru, g->parent->lru, g);
- LIST_REMOVE(JournalRateLimitGroup, bucket, g->parent->buckets[g->hash % BUCKETS_MAX], g);
-
- g->parent->n_groups --;
- }
-
- free(g->id);
- free(g);
-}
-
-void journal_rate_limit_free(JournalRateLimit *r) {
- assert(r);
-
- while (r->lru)
- journal_rate_limit_group_free(r->lru);
-
- free(r);
-}
-
-static bool journal_rate_limit_group_expired(JournalRateLimitGroup *g, usec_t ts) {
- unsigned i;
-
- assert(g);
-
- for (i = 0; i < POOLS_MAX; i++)
- if (g->pools[i].begin + g->parent->interval >= ts)
- return false;
-
- return true;
-}
-
-static void journal_rate_limit_vacuum(JournalRateLimit *r, usec_t ts) {
- assert(r);
-
- /* Makes room for at least one new item, but drop all
- * expored items too. */
-
- while (r->n_groups >= GROUPS_MAX ||
- (r->lru_tail && journal_rate_limit_group_expired(r->lru_tail, ts)))
- journal_rate_limit_group_free(r->lru_tail);
-}
-
-static JournalRateLimitGroup* journal_rate_limit_group_new(JournalRateLimit *r, const char *id, usec_t ts) {
- JournalRateLimitGroup *g;
-
- assert(r);
- assert(id);
-
- g = new0(JournalRateLimitGroup, 1);
- if (!g)
- return NULL;
-
- g->id = strdup(id);
- if (!g->id)
- goto fail;
-
- g->hash = string_hash_func(g->id);
-
- journal_rate_limit_vacuum(r, ts);
-
- LIST_PREPEND(JournalRateLimitGroup, bucket, r->buckets[g->hash % BUCKETS_MAX], g);
- LIST_PREPEND(JournalRateLimitGroup, lru, r->lru, g);
- if (!g->lru_next)
- r->lru_tail = g;
- r->n_groups ++;
-
- g->parent = r;
- return g;
-
-fail:
- journal_rate_limit_group_free(g);
- return NULL;
-}
-
-static uint64_t u64log2(uint64_t n) {
- unsigned r;
-
- if (n <= 1)
- return 0;
-
- r = 0;
- for (;;) {
- n = n >> 1;
- if (!n)
- return r;
- r++;
- }
-}
-
-static unsigned burst_modulate(unsigned burst, uint64_t available) {
- unsigned k;
-
- /* Modulates the burst rate a bit with the amount of available
- * disk space */
-
- k = u64log2(available);
-
- /* 1MB */
- if (k <= 20)
- return burst;
-
- burst = (burst * (k-20)) / 4;
-
- /*
- * Example:
- *
- * <= 1MB = rate * 1
- * 16MB = rate * 2
- * 256MB = rate * 3
- * 4GB = rate * 4
- * 64GB = rate * 5
- * 1TB = rate * 6
- */
-
- return burst;
-}
-
-int journal_rate_limit_test(JournalRateLimit *r, const char *id, int priority, uint64_t available) {
- unsigned h;
- JournalRateLimitGroup *g;
- JournalRateLimitPool *p;
- unsigned burst;
- usec_t ts;
-
- assert(id);
-
- if (!r)
- return 1;
-
- if (r->interval == 0 || r->burst == 0)
- return 1;
-
- burst = burst_modulate(r->burst, available);
-
- ts = now(CLOCK_MONOTONIC);
-
- h = string_hash_func(id);
- g = r->buckets[h % BUCKETS_MAX];
-
- LIST_FOREACH(bucket, g, g)
- if (streq(g->id, id))
- break;
-
- if (!g) {
- g = journal_rate_limit_group_new(r, id, ts);
- if (!g)
- return -ENOMEM;
- }
-
- p = &g->pools[priority_map[priority]];
-
- if (p->begin <= 0) {
- p->suppressed = 0;
- p->num = 1;
- p->begin = ts;
- return 1;
- }
-
- if (p->begin + r->interval < ts) {
- unsigned s;
-
- s = p->suppressed;
- p->suppressed = 0;
- p->num = 1;
- p->begin = ts;
-
- return 1 + s;
- }
-
- if (p->num <= burst) {
- p->num++;
- return 1;
- }
-
- p->suppressed++;
- return 0;
-}
diff --git a/src/journal/journald-rate-limit.h b/src/journal/journald-rate-limit.h
deleted file mode 100644
index 648ab22786..0000000000
--- a/src/journal/journald-rate-limit.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 "macro.h"
-#include "util.h"
-
-typedef struct JournalRateLimit JournalRateLimit;
-
-JournalRateLimit *journal_rate_limit_new(usec_t interval, unsigned burst);
-void journal_rate_limit_free(JournalRateLimit *r);
-int journal_rate_limit_test(JournalRateLimit *r, const char *id, int priority, uint64_t available);
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
deleted file mode 100644
index 0ff2866c11..0000000000
--- a/src/journal/journald-server.c
+++ /dev/null
@@ -1,1502 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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/signalfd.h>
-#include <sys/ioctl.h>
-#include <linux/sockios.h>
-#include <sys/statvfs.h>
-#include <sys/mman.h>
-
-#include <libudev.h>
-#include <systemd/sd-journal.h>
-#include <systemd/sd-messages.h>
-#include <systemd/sd-daemon.h>
-
-#ifdef HAVE_LOGIND
-#include <systemd/sd-login.h>
-#endif
-
-#include "mkdir.h"
-#include "hashmap.h"
-#include "journal-file.h"
-#include "socket-util.h"
-#include "cgroup-util.h"
-#include "list.h"
-#include "virt.h"
-#include "missing.h"
-#include "conf-parser.h"
-#include "journal-internal.h"
-#include "journal-vacuum.h"
-#include "journal-authenticate.h"
-#include "journald-server.h"
-#include "journald-rate-limit.h"
-#include "journald-kmsg.h"
-#include "journald-syslog.h"
-#include "journald-stream.h"
-#include "journald-console.h"
-#include "journald-native.h"
-
-#ifdef HAVE_ACL
-#include <sys/acl.h>
-#include <acl/libacl.h>
-#include "acl-util.h"
-#endif
-
-#ifdef HAVE_SELINUX
-#include <selinux/selinux.h>
-#endif
-
-#define USER_JOURNALS_MAX 1024
-
-#define DEFAULT_RATE_LIMIT_INTERVAL (10*USEC_PER_SEC)
-#define DEFAULT_RATE_LIMIT_BURST 200
-
-#define RECHECK_AVAILABLE_SPACE_USEC (30*USEC_PER_SEC)
-
-static const char* const storage_table[] = {
- [STORAGE_AUTO] = "auto",
- [STORAGE_VOLATILE] = "volatile",
- [STORAGE_PERSISTENT] = "persistent",
- [STORAGE_NONE] = "none"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(storage, Storage);
-DEFINE_CONFIG_PARSE_ENUM(config_parse_storage, storage, Storage, "Failed to parse storage setting");
-
-static const char* const split_mode_table[] = {
- [SPLIT_NONE] = "none",
- [SPLIT_UID] = "uid",
- [SPLIT_LOGIN] = "login"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(split_mode, SplitMode);
-DEFINE_CONFIG_PARSE_ENUM(config_parse_split_mode, split_mode, SplitMode, "Failed to parse split mode setting");
-
-static uint64_t available_space(Server *s) {
- char ids[33], *p;
- const char *f;
- sd_id128_t machine;
- struct statvfs ss;
- uint64_t sum = 0, avail = 0, ss_avail = 0;
- int r;
- DIR *d;
- usec_t ts;
- JournalMetrics *m;
-
- ts = now(CLOCK_MONOTONIC);
-
- if (s->cached_available_space_timestamp + RECHECK_AVAILABLE_SPACE_USEC > ts)
- return s->cached_available_space;
-
- r = sd_id128_get_machine(&machine);
- if (r < 0)
- return 0;
-
- if (s->system_journal) {
- f = "/var/log/journal/";
- m = &s->system_metrics;
- } else {
- f = "/run/log/journal/";
- m = &s->runtime_metrics;
- }
-
- assert(m);
-
- p = strappend(f, sd_id128_to_string(machine, ids));
- if (!p)
- return 0;
-
- d = opendir(p);
- free(p);
-
- if (!d)
- return 0;
-
- if (fstatvfs(dirfd(d), &ss) < 0)
- goto finish;
-
- for (;;) {
- struct stat st;
- struct dirent *de;
- union dirent_storage buf;
-
- r = readdir_r(d, &buf.de, &de);
- if (r != 0)
- break;
-
- if (!de)
- break;
-
- if (!endswith(de->d_name, ".journal") &&
- !endswith(de->d_name, ".journal~"))
- continue;
-
- if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
- continue;
-
- if (!S_ISREG(st.st_mode))
- continue;
-
- sum += (uint64_t) st.st_blocks * 512UL;
- }
-
- avail = sum >= m->max_use ? 0 : m->max_use - sum;
-
- ss_avail = ss.f_bsize * ss.f_bavail;
-
- ss_avail = ss_avail < m->keep_free ? 0 : ss_avail - m->keep_free;
-
- if (ss_avail < avail)
- avail = ss_avail;
-
- s->cached_available_space = avail;
- s->cached_available_space_timestamp = ts;
-
-finish:
- closedir(d);
-
- return avail;
-}
-
-static void server_read_file_gid(Server *s) {
- const char *adm = "adm";
- int r;
-
- assert(s);
-
- if (s->file_gid_valid)
- return;
-
- r = get_group_creds(&adm, &s->file_gid);
- if (r < 0)
- log_warning("Failed to resolve 'adm' group: %s", strerror(-r));
-
- /* if we couldn't read the gid, then it will be 0, but that's
- * fine and we shouldn't try to resolve the group again, so
- * let's just pretend it worked right-away. */
- s->file_gid_valid = true;
-}
-
-void server_fix_perms(Server *s, JournalFile *f, uid_t uid) {
- int r;
-#ifdef HAVE_ACL
- acl_t acl;
- acl_entry_t entry;
- acl_permset_t permset;
-#endif
-
- assert(f);
-
- server_read_file_gid(s);
-
- r = fchmod_and_fchown(f->fd, 0640, 0, s->file_gid);
- if (r < 0)
- log_warning("Failed to fix access mode/rights on %s, ignoring: %s", f->path, strerror(-r));
-
-#ifdef HAVE_ACL
- if (uid <= 0)
- return;
-
- acl = acl_get_fd(f->fd);
- if (!acl) {
- log_warning("Failed to read ACL on %s, ignoring: %m", f->path);
- return;
- }
-
- r = acl_find_uid(acl, uid, &entry);
- if (r <= 0) {
-
- if (acl_create_entry(&acl, &entry) < 0 ||
- acl_set_tag_type(entry, ACL_USER) < 0 ||
- acl_set_qualifier(entry, &uid) < 0) {
- log_warning("Failed to patch ACL on %s, ignoring: %m", f->path);
- goto finish;
- }
- }
-
- if (acl_get_permset(entry, &permset) < 0 ||
- acl_add_perm(permset, ACL_READ) < 0 ||
- acl_calc_mask(&acl) < 0) {
- log_warning("Failed to patch ACL on %s, ignoring: %m", f->path);
- goto finish;
- }
-
- if (acl_set_fd(f->fd, acl) < 0)
- log_warning("Failed to set ACL on %s, ignoring: %m", f->path);
-
-finish:
- acl_free(acl);
-#endif
-}
-
-static JournalFile* find_journal(Server *s, uid_t uid) {
- char *p;
- int r;
- JournalFile *f;
- sd_id128_t machine;
-
- assert(s);
-
- /* We split up user logs only on /var, not on /run. If the
- * runtime file is open, we write to it exclusively, in order
- * to guarantee proper order as soon as we flush /run to
- * /var and close the runtime file. */
-
- if (s->runtime_journal)
- return s->runtime_journal;
-
- if (uid <= 0)
- return s->system_journal;
-
- r = sd_id128_get_machine(&machine);
- if (r < 0)
- return s->system_journal;
-
- f = hashmap_get(s->user_journals, UINT32_TO_PTR(uid));
- if (f)
- return f;
-
- if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/user-%lu.journal",
- SD_ID128_FORMAT_VAL(machine), (unsigned long) uid) < 0)
- return s->system_journal;
-
- while (hashmap_size(s->user_journals) >= USER_JOURNALS_MAX) {
- /* Too many open? Then let's close one */
- f = hashmap_steal_first(s->user_journals);
- assert(f);
- journal_file_close(f);
- }
-
- r = journal_file_open_reliably(p, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, s->system_journal, &f);
- free(p);
-
- if (r < 0)
- return s->system_journal;
-
- server_fix_perms(s, f, uid);
-
- r = hashmap_put(s->user_journals, UINT32_TO_PTR(uid), f);
- if (r < 0) {
- journal_file_close(f);
- return s->system_journal;
- }
-
- return f;
-}
-
-void server_rotate(Server *s) {
- JournalFile *f;
- void *k;
- Iterator i;
- int r;
-
- log_debug("Rotating...");
-
- if (s->runtime_journal) {
- r = journal_file_rotate(&s->runtime_journal, s->compress, false);
- if (r < 0)
- if (s->runtime_journal)
- log_error("Failed to rotate %s: %s", s->runtime_journal->path, strerror(-r));
- else
- log_error("Failed to create new runtime journal: %s", strerror(-r));
- else
- server_fix_perms(s, s->runtime_journal, 0);
- }
-
- if (s->system_journal) {
- r = journal_file_rotate(&s->system_journal, s->compress, s->seal);
- if (r < 0)
- if (s->system_journal)
- log_error("Failed to rotate %s: %s", s->system_journal->path, strerror(-r));
- else
- log_error("Failed to create new system journal: %s", strerror(-r));
-
- else
- server_fix_perms(s, s->system_journal, 0);
- }
-
- HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) {
- r = journal_file_rotate(&f, s->compress, s->seal);
- if (r < 0)
- if (f->path)
- log_error("Failed to rotate %s: %s", f->path, strerror(-r));
- else
- log_error("Failed to create user journal: %s", strerror(-r));
- else {
- hashmap_replace(s->user_journals, k, f);
- server_fix_perms(s, f, PTR_TO_UINT32(k));
- }
- }
-}
-
-void server_vacuum(Server *s) {
- char *p;
- char ids[33];
- sd_id128_t machine;
- int r;
-
- log_debug("Vacuuming...");
-
- s->oldest_file_usec = 0;
-
- r = sd_id128_get_machine(&machine);
- if (r < 0) {
- log_error("Failed to get machine ID: %s", strerror(-r));
- return;
- }
-
- sd_id128_to_string(machine, ids);
-
- if (s->system_journal) {
- p = strappend("/var/log/journal/", ids);
- if (!p) {
- log_oom();
- return;
- }
-
- r = journal_directory_vacuum(p, s->system_metrics.max_use, s->system_metrics.keep_free, s->max_retention_usec, &s->oldest_file_usec);
- if (r < 0 && r != -ENOENT)
- log_error("Failed to vacuum %s: %s", p, strerror(-r));
- free(p);
- }
-
- if (s->runtime_journal) {
- p = strappend("/run/log/journal/", ids);
- if (!p) {
- log_oom();
- return;
- }
-
- r = journal_directory_vacuum(p, s->runtime_metrics.max_use, s->runtime_metrics.keep_free, s->max_retention_usec, &s->oldest_file_usec);
- if (r < 0 && r != -ENOENT)
- log_error("Failed to vacuum %s: %s", p, strerror(-r));
- free(p);
- }
-
- s->cached_available_space_timestamp = 0;
-}
-
-static char *shortened_cgroup_path(pid_t pid) {
- int r;
- char *process_path, *init_path, *path;
-
- assert(pid > 0);
-
- r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &process_path);
- if (r < 0)
- return NULL;
-
- r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &init_path);
- if (r < 0) {
- free(process_path);
- return NULL;
- }
-
- if (endswith(init_path, "/system"))
- init_path[strlen(init_path) - 7] = 0;
- else if (streq(init_path, "/"))
- init_path[0] = 0;
-
- if (startswith(process_path, init_path)) {
- char *p;
-
- p = strdup(process_path + strlen(init_path));
- if (!p) {
- free(process_path);
- free(init_path);
- return NULL;
- }
- path = p;
- } else {
- path = process_path;
- process_path = NULL;
- }
-
- free(process_path);
- free(init_path);
-
- return path;
-}
-
-bool shall_try_append_again(JournalFile *f, int r) {
-
- /* -E2BIG Hit configured limit
- -EFBIG Hit fs limit
- -EDQUOT Quota limit hit
- -ENOSPC Disk full
- -EHOSTDOWN Other machine
- -EBUSY Unclean shutdown
- -EPROTONOSUPPORT Unsupported feature
- -EBADMSG Corrupted
- -ENODATA Truncated
- -ESHUTDOWN Already archived */
-
- if (r == -E2BIG || r == -EFBIG || r == -EDQUOT || r == -ENOSPC)
- log_debug("%s: Allocation limit reached, rotating.", f->path);
- else if (r == -EHOSTDOWN)
- log_info("%s: Journal file from other machine, rotating.", f->path);
- else if (r == -EBUSY)
- log_info("%s: Unclean shutdown, rotating.", f->path);
- else if (r == -EPROTONOSUPPORT)
- log_info("%s: Unsupported feature, rotating.", f->path);
- else if (r == -EBADMSG || r == -ENODATA || r == ESHUTDOWN)
- log_warning("%s: Journal file corrupted, rotating.", f->path);
- else
- return false;
-
- return true;
-}
-
-static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned n) {
- JournalFile *f;
- bool vacuumed = false;
- int r;
-
- assert(s);
- assert(iovec);
- assert(n > 0);
-
- f = find_journal(s, uid);
- if (!f)
- return;
-
- if (journal_file_rotate_suggested(f, s->max_file_usec)) {
- log_debug("%s: Journal header limits reached or header out-of-date, rotating.", f->path);
- server_rotate(s);
- server_vacuum(s);
- vacuumed = true;
-
- f = find_journal(s, uid);
- if (!f)
- return;
- }
-
- r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
- if (r >= 0)
- return;
-
- if (vacuumed || !shall_try_append_again(f, r)) {
- log_error("Failed to write entry, ignoring: %s", strerror(-r));
- return;
- }
-
- server_rotate(s);
- server_vacuum(s);
-
- f = find_journal(s, uid);
- if (!f)
- return;
-
- log_debug("Retrying write.");
- r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
- if (r < 0)
- log_error("Failed to write entry, ignoring: %s", strerror(-r));
-}
-
-static void dispatch_message_real(
- Server *s,
- struct iovec *iovec, unsigned n, unsigned m,
- struct ucred *ucred,
- struct timeval *tv,
- const char *label, size_t label_len,
- const char *unit_id) {
-
- char *pid = NULL, *uid = NULL, *gid = NULL,
- *source_time = NULL, *boot_id = NULL, *machine_id = NULL,
- *comm = NULL, *cmdline = NULL, *hostname = NULL,
- *audit_session = NULL, *audit_loginuid = NULL,
- *exe = NULL, *cgroup = NULL, *session = NULL,
- *owner_uid = NULL, *unit = NULL, *selinux_context = NULL;
-
- char idbuf[33];
- sd_id128_t id;
- int r;
- char *t;
- uid_t loginuid = 0, realuid = 0;
-
- assert(s);
- assert(iovec);
- assert(n > 0);
- assert(n + N_IOVEC_META_FIELDS <= m);
-
- if (ucred) {
- uint32_t audit;
-#ifdef HAVE_LOGIND
- uid_t owner;
-#endif
-
- realuid = ucred->uid;
-
- if (asprintf(&pid, "_PID=%lu", (unsigned long) ucred->pid) >= 0)
- IOVEC_SET_STRING(iovec[n++], pid);
-
- if (asprintf(&uid, "_UID=%lu", (unsigned long) ucred->uid) >= 0)
- IOVEC_SET_STRING(iovec[n++], uid);
-
- if (asprintf(&gid, "_GID=%lu", (unsigned long) ucred->gid) >= 0)
- IOVEC_SET_STRING(iovec[n++], gid);
-
- r = get_process_comm(ucred->pid, &t);
- if (r >= 0) {
- comm = strappend("_COMM=", t);
- free(t);
-
- if (comm)
- IOVEC_SET_STRING(iovec[n++], comm);
- }
-
- r = get_process_exe(ucred->pid, &t);
- if (r >= 0) {
- exe = strappend("_EXE=", t);
- free(t);
-
- if (exe)
- IOVEC_SET_STRING(iovec[n++], exe);
- }
-
- r = get_process_cmdline(ucred->pid, LINE_MAX, false, &t);
- if (r >= 0) {
- cmdline = strappend("_CMDLINE=", t);
- free(t);
-
- if (cmdline)
- IOVEC_SET_STRING(iovec[n++], cmdline);
- }
-
- r = audit_session_from_pid(ucred->pid, &audit);
- if (r >= 0)
- if (asprintf(&audit_session, "_AUDIT_SESSION=%lu", (unsigned long) audit) >= 0)
- IOVEC_SET_STRING(iovec[n++], audit_session);
-
- r = audit_loginuid_from_pid(ucred->pid, &loginuid);
- if (r >= 0)
- if (asprintf(&audit_loginuid, "_AUDIT_LOGINUID=%lu", (unsigned long) loginuid) >= 0)
- IOVEC_SET_STRING(iovec[n++], audit_loginuid);
-
- t = shortened_cgroup_path(ucred->pid);
- if (t) {
- cgroup = strappend("_SYSTEMD_CGROUP=", t);
- free(t);
-
- if (cgroup)
- IOVEC_SET_STRING(iovec[n++], cgroup);
- }
-
-#ifdef HAVE_LOGIND
- if (sd_pid_get_session(ucred->pid, &t) >= 0) {
- session = strappend("_SYSTEMD_SESSION=", t);
- free(t);
-
- if (session)
- IOVEC_SET_STRING(iovec[n++], session);
- }
-
- if (sd_pid_get_owner_uid(ucred->uid, &owner) >= 0)
- if (asprintf(&owner_uid, "_SYSTEMD_OWNER_UID=%lu", (unsigned long) owner) >= 0)
- IOVEC_SET_STRING(iovec[n++], owner_uid);
-#endif
-
- if (cg_pid_get_unit(ucred->pid, &t) >= 0) {
- unit = strappend("_SYSTEMD_UNIT=", t);
- free(t);
- } else if (unit_id)
- unit = strappend("_SYSTEMD_UNIT=", unit_id);
-
- if (unit)
- IOVEC_SET_STRING(iovec[n++], unit);
-
-#ifdef HAVE_SELINUX
- if (label) {
- selinux_context = malloc(sizeof("_SELINUX_CONTEXT=") + label_len);
- if (selinux_context) {
- memcpy(selinux_context, "_SELINUX_CONTEXT=", sizeof("_SELINUX_CONTEXT=")-1);
- memcpy(selinux_context+sizeof("_SELINUX_CONTEXT=")-1, label, label_len);
- selinux_context[sizeof("_SELINUX_CONTEXT=")-1+label_len] = 0;
- IOVEC_SET_STRING(iovec[n++], selinux_context);
- }
- } else {
- security_context_t con;
-
- if (getpidcon(ucred->pid, &con) >= 0) {
- selinux_context = strappend("_SELINUX_CONTEXT=", con);
- if (selinux_context)
- IOVEC_SET_STRING(iovec[n++], selinux_context);
-
- freecon(con);
- }
- }
-#endif
- }
-
- if (tv) {
- if (asprintf(&source_time, "_SOURCE_REALTIME_TIMESTAMP=%llu",
- (unsigned long long) timeval_load(tv)) >= 0)
- IOVEC_SET_STRING(iovec[n++], source_time);
- }
-
- /* Note that strictly speaking storing the boot id here is
- * redundant since the entry includes this in-line
- * anyway. However, we need this indexed, too. */
- r = sd_id128_get_boot(&id);
- if (r >= 0)
- if (asprintf(&boot_id, "_BOOT_ID=%s", sd_id128_to_string(id, idbuf)) >= 0)
- IOVEC_SET_STRING(iovec[n++], boot_id);
-
- r = sd_id128_get_machine(&id);
- if (r >= 0)
- if (asprintf(&machine_id, "_MACHINE_ID=%s", sd_id128_to_string(id, idbuf)) >= 0)
- IOVEC_SET_STRING(iovec[n++], machine_id);
-
- t = gethostname_malloc();
- if (t) {
- hostname = strappend("_HOSTNAME=", t);
- free(t);
- if (hostname)
- IOVEC_SET_STRING(iovec[n++], hostname);
- }
-
- assert(n <= m);
-
- write_to_journal(s,
- s->split_mode == SPLIT_NONE ? 0 :
- (s->split_mode == SPLIT_UID ? realuid :
- (realuid == 0 ? 0 : loginuid)), iovec, n);
-
- free(pid);
- free(uid);
- free(gid);
- free(comm);
- free(exe);
- free(cmdline);
- free(source_time);
- free(boot_id);
- free(machine_id);
- free(hostname);
- free(audit_session);
- free(audit_loginuid);
- free(cgroup);
- free(session);
- free(owner_uid);
- free(unit);
- free(selinux_context);
-}
-
-void server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) {
- char mid[11 + 32 + 1];
- char buffer[16 + LINE_MAX + 1];
- struct iovec iovec[N_IOVEC_META_FIELDS + 4];
- int n = 0;
- va_list ap;
- struct ucred ucred;
-
- assert(s);
- assert(format);
-
- IOVEC_SET_STRING(iovec[n++], "PRIORITY=6");
- IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=driver");
-
- memcpy(buffer, "MESSAGE=", 8);
- va_start(ap, format);
- vsnprintf(buffer + 8, sizeof(buffer) - 8, format, ap);
- va_end(ap);
- char_array_0(buffer);
- IOVEC_SET_STRING(iovec[n++], buffer);
-
- if (!sd_id128_equal(message_id, SD_ID128_NULL)) {
- snprintf(mid, sizeof(mid), MESSAGE_ID(message_id));
- char_array_0(mid);
- IOVEC_SET_STRING(iovec[n++], mid);
- }
-
- zero(ucred);
- ucred.pid = getpid();
- ucred.uid = getuid();
- ucred.gid = getgid();
-
- dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL);
-}
-
-void server_dispatch_message(
- Server *s,
- struct iovec *iovec, unsigned n, unsigned m,
- struct ucred *ucred,
- struct timeval *tv,
- const char *label, size_t label_len,
- const char *unit_id,
- int priority) {
-
- int rl;
- char *path = NULL, *c;
-
- assert(s);
- assert(iovec || n == 0);
-
- if (n == 0)
- return;
-
- if (LOG_PRI(priority) > s->max_level_store)
- return;
-
- if (!ucred)
- goto finish;
-
- path = shortened_cgroup_path(ucred->pid);
- if (!path)
- goto finish;
-
- /* example: /user/lennart/3/foobar
- * /system/dbus.service/foobar
- *
- * So let's cut of everything past the third /, since that is
- * where user directories start */
-
- c = strchr(path, '/');
- if (c) {
- c = strchr(c+1, '/');
- if (c) {
- c = strchr(c+1, '/');
- if (c)
- *c = 0;
- }
- }
-
- rl = journal_rate_limit_test(s->rate_limit, path, priority & LOG_PRIMASK, available_space(s));
-
- if (rl == 0) {
- free(path);
- return;
- }
-
- /* Write a suppression message if we suppressed something */
- if (rl > 1)
- server_driver_message(s, SD_MESSAGE_JOURNAL_DROPPED, "Suppressed %u messages from %s", rl - 1, path);
-
- free(path);
-
-finish:
- dispatch_message_real(s, iovec, n, m, ucred, tv, label, label_len, unit_id);
-}
-
-
-static int system_journal_open(Server *s) {
- int r;
- char *fn;
- sd_id128_t machine;
- char ids[33];
-
- r = sd_id128_get_machine(&machine);
- if (r < 0)
- return r;
-
- sd_id128_to_string(machine, ids);
-
- if (!s->system_journal &&
- (s->storage == STORAGE_PERSISTENT || s->storage == STORAGE_AUTO) &&
- access("/run/systemd/journal/flushed", F_OK) >= 0) {
-
- /* If in auto mode: first try to create the machine
- * path, but not the prefix.
- *
- * If in persistent mode: create /var/log/journal and
- * the machine path */
-
- if (s->storage == STORAGE_PERSISTENT)
- (void) mkdir("/var/log/journal/", 0755);
-
- fn = strappend("/var/log/journal/", ids);
- if (!fn)
- return -ENOMEM;
-
- (void) mkdir(fn, 0755);
- free(fn);
-
- fn = strjoin("/var/log/journal/", ids, "/system.journal", NULL);
- if (!fn)
- return -ENOMEM;
-
- r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &s->system_journal);
- free(fn);
-
- if (r >= 0) {
- char fb[FORMAT_BYTES_MAX];
-
- server_fix_perms(s, s->system_journal, 0);
- server_driver_message(s, SD_ID128_NULL, "Allowing system journal files to grow to %s.",
- format_bytes(fb, sizeof(fb), s->system_metrics.max_use));
-
- } else if (r < 0) {
-
- if (r != -ENOENT && r != -EROFS)
- log_warning("Failed to open system journal: %s", strerror(-r));
-
- r = 0;
- }
- }
-
- if (!s->runtime_journal &&
- (s->storage != STORAGE_NONE)) {
-
- fn = strjoin("/run/log/journal/", ids, "/system.journal", NULL);
- if (!fn)
- return -ENOMEM;
-
- if (s->system_journal) {
-
- /* Try to open the runtime journal, but only
- * if it already exists, so that we can flush
- * it into the system journal */
-
- r = journal_file_open(fn, O_RDWR, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
- free(fn);
-
- if (r < 0) {
- if (r != -ENOENT)
- log_warning("Failed to open runtime journal: %s", strerror(-r));
-
- r = 0;
- }
-
- } else {
-
- /* OK, we really need the runtime journal, so create
- * it if necessary. */
-
- (void) mkdir_parents(fn, 0755);
- r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
- free(fn);
-
- if (r < 0) {
- log_error("Failed to open runtime journal: %s", strerror(-r));
- return r;
- }
- }
-
- if (s->runtime_journal) {
- char fb[FORMAT_BYTES_MAX];
-
- server_fix_perms(s, s->runtime_journal, 0);
- server_driver_message(s, SD_ID128_NULL, "Allowing runtime journal files to grow to %s.",
- format_bytes(fb, sizeof(fb), s->runtime_metrics.max_use));
- }
- }
-
- return r;
-}
-
-int server_flush_to_var(Server *s) {
- int r;
- sd_id128_t machine;
- sd_journal *j = NULL;
-
- assert(s);
-
- if (s->storage != STORAGE_AUTO &&
- s->storage != STORAGE_PERSISTENT)
- return 0;
-
- if (!s->runtime_journal)
- return 0;
-
- system_journal_open(s);
-
- if (!s->system_journal)
- return 0;
-
- log_debug("Flushing to /var...");
-
- r = sd_id128_get_machine(&machine);
- if (r < 0) {
- log_error("Failed to get machine id: %s", strerror(-r));
- return r;
- }
-
- r = sd_journal_open(&j, SD_JOURNAL_RUNTIME_ONLY);
- if (r < 0) {
- log_error("Failed to read runtime journal: %s", strerror(-r));
- return r;
- }
-
- SD_JOURNAL_FOREACH(j) {
- Object *o = NULL;
- JournalFile *f;
-
- f = j->current_file;
- assert(f && f->current_offset > 0);
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
- if (r < 0) {
- log_error("Can't read entry: %s", strerror(-r));
- goto finish;
- }
-
- r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset, NULL, NULL, NULL);
- if (r >= 0)
- continue;
-
- if (!shall_try_append_again(s->system_journal, r)) {
- log_error("Can't write entry: %s", strerror(-r));
- goto finish;
- }
-
- server_rotate(s);
- server_vacuum(s);
-
- log_debug("Retrying write.");
- r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset, NULL, NULL, NULL);
- if (r < 0) {
- log_error("Can't write entry: %s", strerror(-r));
- goto finish;
- }
- }
-
-finish:
- journal_file_post_change(s->system_journal);
-
- journal_file_close(s->runtime_journal);
- s->runtime_journal = NULL;
-
- if (r >= 0)
- rm_rf("/run/log/journal", false, true, false);
-
- if (j)
- sd_journal_close(j);
-
- return r;
-}
-
-int process_event(Server *s, struct epoll_event *ev) {
- assert(s);
- assert(ev);
-
- if (ev->data.fd == s->signal_fd) {
- struct signalfd_siginfo sfsi;
- ssize_t n;
-
- if (ev->events != EPOLLIN) {
- log_error("Got invalid event from epoll.");
- return -EIO;
- }
-
- n = read(s->signal_fd, &sfsi, sizeof(sfsi));
- if (n != sizeof(sfsi)) {
-
- if (n >= 0)
- return -EIO;
-
- if (errno == EINTR || errno == EAGAIN)
- return 1;
-
- return -errno;
- }
-
- log_info("Received SIG%s", signal_to_string(sfsi.ssi_signo));
-
- if (sfsi.ssi_signo == SIGUSR1) {
- touch("/run/systemd/journal/flushed");
- server_flush_to_var(s);
- return 1;
- }
-
- if (sfsi.ssi_signo == SIGUSR2) {
- server_rotate(s);
- server_vacuum(s);
- return 1;
- }
-
- return 0;
-
- } else if (ev->data.fd == s->dev_kmsg_fd) {
- int r;
-
- if (ev->events != EPOLLIN) {
- log_error("Got invalid event from epoll.");
- return -EIO;
- }
-
- r = server_read_dev_kmsg(s);
- if (r < 0)
- return r;
-
- return 1;
-
- } else if (ev->data.fd == s->native_fd ||
- ev->data.fd == s->syslog_fd) {
-
- if (ev->events != EPOLLIN) {
- log_error("Got invalid event from epoll.");
- return -EIO;
- }
-
- for (;;) {
- struct msghdr msghdr;
- struct iovec iovec;
- struct ucred *ucred = NULL;
- struct timeval *tv = NULL;
- struct cmsghdr *cmsg;
- char *label = NULL;
- size_t label_len = 0;
- union {
- struct cmsghdr cmsghdr;
-
- /* We use NAME_MAX space for the
- * SELinux label here. The kernel
- * currently enforces no limit, but
- * according to suggestions from the
- * SELinux people this will change and
- * it will probably be identical to
- * NAME_MAX. For now we use that, but
- * this should be updated one day when
- * the final limit is known.*/
- uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
- CMSG_SPACE(sizeof(struct timeval)) +
- CMSG_SPACE(sizeof(int)) + /* fd */
- CMSG_SPACE(NAME_MAX)]; /* selinux label */
- } control;
- ssize_t n;
- int v;
- int *fds = NULL;
- unsigned n_fds = 0;
-
- if (ioctl(ev->data.fd, SIOCINQ, &v) < 0) {
- log_error("SIOCINQ failed: %m");
- return -errno;
- }
-
- if (s->buffer_size < (size_t) v) {
- void *b;
- size_t l;
-
- l = MAX(LINE_MAX + (size_t) v, s->buffer_size * 2);
- b = realloc(s->buffer, l+1);
-
- if (!b) {
- log_error("Couldn't increase buffer.");
- return -ENOMEM;
- }
-
- s->buffer_size = l;
- s->buffer = b;
- }
-
- zero(iovec);
- iovec.iov_base = s->buffer;
- iovec.iov_len = s->buffer_size;
-
- zero(control);
- zero(msghdr);
- msghdr.msg_iov = &iovec;
- msghdr.msg_iovlen = 1;
- msghdr.msg_control = &control;
- msghdr.msg_controllen = sizeof(control);
-
- n = recvmsg(ev->data.fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
- if (n < 0) {
-
- if (errno == EINTR || errno == EAGAIN)
- return 1;
-
- log_error("recvmsg() failed: %m");
- return -errno;
- }
-
- for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
-
- 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);
- else if (cmsg->cmsg_level == SOL_SOCKET &&
- cmsg->cmsg_type == SCM_SECURITY) {
- label = (char*) CMSG_DATA(cmsg);
- label_len = cmsg->cmsg_len - CMSG_LEN(0);
- } else if (cmsg->cmsg_level == SOL_SOCKET &&
- cmsg->cmsg_type == SO_TIMESTAMP &&
- cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
- tv = (struct timeval*) CMSG_DATA(cmsg);
- else if (cmsg->cmsg_level == SOL_SOCKET &&
- cmsg->cmsg_type == SCM_RIGHTS) {
- fds = (int*) CMSG_DATA(cmsg);
- n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
- }
- }
-
- if (ev->data.fd == s->syslog_fd) {
- char *e;
-
- if (n > 0 && n_fds == 0) {
- e = memchr(s->buffer, '\n', n);
- if (e)
- *e = 0;
- else
- s->buffer[n] = 0;
-
- server_process_syslog_message(s, strstrip(s->buffer), ucred, tv, label, label_len);
- } else if (n_fds > 0)
- log_warning("Got file descriptors via syslog socket. Ignoring.");
-
- } else {
- if (n > 0 && n_fds == 0)
- server_process_native_message(s, s->buffer, n, ucred, tv, label, label_len);
- else if (n == 0 && n_fds == 1)
- server_process_native_file(s, fds[0], ucred, tv, label, label_len);
- else if (n_fds > 0)
- log_warning("Got too many file descriptors via native socket. Ignoring.");
- }
-
- close_many(fds, n_fds);
- }
-
- return 1;
-
- } else if (ev->data.fd == s->stdout_fd) {
-
- if (ev->events != EPOLLIN) {
- log_error("Got invalid event from epoll.");
- return -EIO;
- }
-
- stdout_stream_new(s);
- return 1;
-
- } else {
- StdoutStream *stream;
-
- if ((ev->events|EPOLLIN|EPOLLHUP) != (EPOLLIN|EPOLLHUP)) {
- log_error("Got invalid event from epoll.");
- return -EIO;
- }
-
- /* If it is none of the well-known fds, it must be an
- * stdout stream fd. Note that this is a bit ugly here
- * (since we rely that none of the well-known fds
- * could be interpreted as pointer), but nonetheless
- * safe, since the well-known fds would never get an
- * fd > 4096, i.e. beyond the first memory page */
-
- stream = ev->data.ptr;
-
- if (stdout_stream_process(stream) <= 0)
- stdout_stream_free(stream);
-
- return 1;
- }
-
- log_error("Unknown event.");
- return 0;
-}
-
-static int open_signalfd(Server *s) {
- sigset_t mask;
- struct epoll_event ev;
-
- assert(s);
-
- assert_se(sigemptyset(&mask) == 0);
- sigset_add_many(&mask, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, -1);
- assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
-
- s->signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
- if (s->signal_fd < 0) {
- log_error("signalfd(): %m");
- return -errno;
- }
-
- zero(ev);
- ev.events = EPOLLIN;
- ev.data.fd = s->signal_fd;
-
- if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->signal_fd, &ev) < 0) {
- log_error("epoll_ctl(): %m");
- return -errno;
- }
-
- return 0;
-}
-
-static int server_parse_proc_cmdline(Server *s) {
- char *line, *w, *state;
- int r;
- size_t l;
-
- if (detect_container(NULL) > 0)
- return 0;
-
- r = read_one_line_file("/proc/cmdline", &line);
- if (r < 0) {
- log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
- return 0;
- }
-
- FOREACH_WORD_QUOTED(w, l, line, state) {
- char *word;
-
- word = strndup(w, l);
- if (!word) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (startswith(word, "systemd.journald.forward_to_syslog=")) {
- r = parse_boolean(word + 35);
- if (r < 0)
- log_warning("Failed to parse forward to syslog switch %s. Ignoring.", word + 35);
- else
- s->forward_to_syslog = r;
- } else if (startswith(word, "systemd.journald.forward_to_kmsg=")) {
- r = parse_boolean(word + 33);
- if (r < 0)
- log_warning("Failed to parse forward to kmsg switch %s. Ignoring.", word + 33);
- else
- s->forward_to_kmsg = r;
- } else if (startswith(word, "systemd.journald.forward_to_console=")) {
- r = parse_boolean(word + 36);
- if (r < 0)
- log_warning("Failed to parse forward to console switch %s. Ignoring.", word + 36);
- else
- s->forward_to_console = r;
- } else if (startswith(word, "systemd.journald"))
- log_warning("Invalid systemd.journald parameter. Ignoring.");
-
- free(word);
- }
-
- r = 0;
-
-finish:
- free(line);
- return r;
-}
-
-static int server_parse_config_file(Server *s) {
- FILE *f;
- const char *fn;
- int r;
-
- assert(s);
-
- fn = "/etc/systemd/journald.conf";
- f = fopen(fn, "re");
- if (!f) {
- if (errno == ENOENT)
- return 0;
-
- log_warning("Failed to open configuration file %s: %m", fn);
- return -errno;
- }
-
- r = config_parse(fn, f, "Journal\0", config_item_perf_lookup, (void*) journald_gperf_lookup, false, s);
- if (r < 0)
- log_warning("Failed to parse configuration file: %s", strerror(-r));
-
- fclose(f);
-
- return r;
-}
-
-int server_init(Server *s) {
- int n, r, fd;
-
- assert(s);
-
- zero(*s);
- s->syslog_fd = s->native_fd = s->stdout_fd = s->signal_fd = s->epoll_fd = s->dev_kmsg_fd = -1;
- s->compress = true;
- s->seal = true;
-
- s->rate_limit_interval = DEFAULT_RATE_LIMIT_INTERVAL;
- s->rate_limit_burst = DEFAULT_RATE_LIMIT_BURST;
-
- s->forward_to_syslog = true;
-
- s->max_level_store = LOG_DEBUG;
- s->max_level_syslog = LOG_DEBUG;
- s->max_level_kmsg = LOG_NOTICE;
- s->max_level_console = LOG_INFO;
-
- memset(&s->system_metrics, 0xFF, sizeof(s->system_metrics));
- memset(&s->runtime_metrics, 0xFF, sizeof(s->runtime_metrics));
-
- server_parse_config_file(s);
- server_parse_proc_cmdline(s);
-
- mkdir_p("/run/systemd/journal", 0755);
-
- s->user_journals = hashmap_new(trivial_hash_func, trivial_compare_func);
- if (!s->user_journals)
- return log_oom();
-
- s->mmap = mmap_cache_new();
- if (!s->mmap)
- return log_oom();
-
- s->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
- if (s->epoll_fd < 0) {
- log_error("Failed to create epoll object: %m");
- return -errno;
- }
-
- n = sd_listen_fds(true);
- if (n < 0) {
- log_error("Failed to read listening file descriptors from environment: %s", strerror(-n));
- return n;
- }
-
- for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) {
-
- if (sd_is_socket_unix(fd, SOCK_DGRAM, -1, "/run/systemd/journal/socket", 0) > 0) {
-
- if (s->native_fd >= 0) {
- log_error("Too many native sockets passed.");
- return -EINVAL;
- }
-
- s->native_fd = fd;
-
- } else if (sd_is_socket_unix(fd, SOCK_STREAM, 1, "/run/systemd/journal/stdout", 0) > 0) {
-
- if (s->stdout_fd >= 0) {
- log_error("Too many stdout sockets passed.");
- return -EINVAL;
- }
-
- s->stdout_fd = fd;
-
- } else if (sd_is_socket_unix(fd, SOCK_DGRAM, -1, "/dev/log", 0) > 0) {
-
- if (s->syslog_fd >= 0) {
- log_error("Too many /dev/log sockets passed.");
- return -EINVAL;
- }
-
- s->syslog_fd = fd;
-
- } else {
- log_error("Unknown socket passed.");
- return -EINVAL;
- }
- }
-
- r = server_open_syslog_socket(s);
- if (r < 0)
- return r;
-
- r = server_open_native_socket(s);
- if (r < 0)
- return r;
-
- r = server_open_stdout_socket(s);
- if (r < 0)
- return r;
-
- r = server_open_dev_kmsg(s);
- if (r < 0)
- return r;
-
- r = server_open_kernel_seqnum(s);
- if (r < 0)
- return r;
-
- r = open_signalfd(s);
- if (r < 0)
- return r;
-
- s->udev = udev_new();
- if (!s->udev)
- return -ENOMEM;
-
- s->rate_limit = journal_rate_limit_new(s->rate_limit_interval, s->rate_limit_burst);
- if (!s->rate_limit)
- return -ENOMEM;
-
- r = system_journal_open(s);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-void server_maybe_append_tags(Server *s) {
-#ifdef HAVE_GCRYPT
- JournalFile *f;
- Iterator i;
- usec_t n;
-
- n = now(CLOCK_REALTIME);
-
- if (s->system_journal)
- journal_file_maybe_append_tag(s->system_journal, n);
-
- HASHMAP_FOREACH(f, s->user_journals, i)
- journal_file_maybe_append_tag(f, n);
-#endif
-}
-
-void server_done(Server *s) {
- JournalFile *f;
- assert(s);
-
- while (s->stdout_streams)
- stdout_stream_free(s->stdout_streams);
-
- if (s->system_journal)
- journal_file_close(s->system_journal);
-
- if (s->runtime_journal)
- journal_file_close(s->runtime_journal);
-
- while ((f = hashmap_steal_first(s->user_journals)))
- journal_file_close(f);
-
- hashmap_free(s->user_journals);
-
- if (s->epoll_fd >= 0)
- close_nointr_nofail(s->epoll_fd);
-
- if (s->signal_fd >= 0)
- close_nointr_nofail(s->signal_fd);
-
- if (s->syslog_fd >= 0)
- close_nointr_nofail(s->syslog_fd);
-
- if (s->native_fd >= 0)
- close_nointr_nofail(s->native_fd);
-
- if (s->stdout_fd >= 0)
- close_nointr_nofail(s->stdout_fd);
-
- if (s->dev_kmsg_fd >= 0)
- close_nointr_nofail(s->dev_kmsg_fd);
-
- if (s->rate_limit)
- journal_rate_limit_free(s->rate_limit);
-
- if (s->kernel_seqnum)
- munmap(s->kernel_seqnum, sizeof(uint64_t));
-
- free(s->buffer);
- free(s->tty_path);
-
- if (s->mmap)
- mmap_cache_unref(s->mmap);
-
- if (s->udev)
- udev_unref(s->udev);
-}
diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h
deleted file mode 100644
index 9f50a29e50..0000000000
--- a/src/journal/journald-server.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <stdbool.h>
-#include <sys/epoll.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include "journal-file.h"
-#include "hashmap.h"
-#include "util.h"
-#include "audit.h"
-#include "journald-rate-limit.h"
-#include "list.h"
-
-typedef enum Storage {
- STORAGE_AUTO,
- STORAGE_VOLATILE,
- STORAGE_PERSISTENT,
- STORAGE_NONE,
- _STORAGE_MAX,
- _STORAGE_INVALID = -1
-} Storage;
-
-typedef enum SplitMode {
- SPLIT_LOGIN,
- SPLIT_UID,
- SPLIT_NONE,
- _SPLIT_MAX,
- _SPLIT_INVALID = -1
-} SplitMode;
-
-typedef struct StdoutStream StdoutStream;
-
-typedef struct Server {
- int epoll_fd;
- int signal_fd;
- int syslog_fd;
- int native_fd;
- int stdout_fd;
- int dev_kmsg_fd;
-
- JournalFile *runtime_journal;
- JournalFile *system_journal;
- Hashmap *user_journals;
-
- uint64_t seqnum;
-
- char *buffer;
- size_t buffer_size;
-
- JournalRateLimit *rate_limit;
- usec_t rate_limit_interval;
- unsigned rate_limit_burst;
-
- JournalMetrics runtime_metrics;
- JournalMetrics system_metrics;
-
- bool compress;
- bool seal;
-
- bool forward_to_kmsg;
- bool forward_to_syslog;
- bool forward_to_console;
-
- unsigned n_forward_syslog_missed;
- usec_t last_warn_forward_syslog_missed;
-
- uint64_t cached_available_space;
- usec_t cached_available_space_timestamp;
-
- uint64_t var_available_timestamp;
-
- usec_t max_retention_usec;
- usec_t max_file_usec;
- usec_t oldest_file_usec;
-
- gid_t file_gid;
- bool file_gid_valid;
-
- LIST_HEAD(StdoutStream, stdout_streams);
- unsigned n_stdout_streams;
-
- char *tty_path;
-
- int max_level_store;
- int max_level_syslog;
- int max_level_kmsg;
- int max_level_console;
-
- Storage storage;
- SplitMode split_mode;
-
- MMapCache *mmap;
-
- bool dev_kmsg_readable;
-
- uint64_t *kernel_seqnum;
-
- struct udev *udev;
-} Server;
-
-#define N_IOVEC_META_FIELDS 17
-#define N_IOVEC_KERNEL_FIELDS 64
-#define N_IOVEC_UDEV_FIELDS 32
-
-void server_dispatch_message(Server *s, struct iovec *iovec, unsigned n, unsigned m, struct ucred *ucred, struct timeval *tv, const char *label, size_t label_len, const char *unit_id, int priority);
-void server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...);
-
-/* gperf lookup function */
-const struct ConfigPerfItem* journald_gperf_lookup(const char *key, unsigned length);
-
-int config_parse_storage(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-
-const char *storage_to_string(Storage s);
-Storage storage_from_string(const char *s);
-
-int config_parse_split_mode(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-
-const char *split_mode_to_string(SplitMode s);
-SplitMode split_mode_from_string(const char *s);
-
-void server_fix_perms(Server *s, JournalFile *f, uid_t uid);
-bool shall_try_append_again(JournalFile *f, int r);
-int server_init(Server *s);
-void server_done(Server *s);
-void server_vacuum(Server *s);
-void server_rotate(Server *s);
-int server_flush_to_var(Server *s);
-int process_event(Server *s, struct epoll_event *ev);
-void server_maybe_append_tags(Server *s);
diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c
deleted file mode 100644
index 7b88f747db..0000000000
--- a/src/journal/journald-stream.c
+++ /dev/null
@@ -1,459 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <unistd.h>
-#include <stddef.h>
-#include <sys/epoll.h>
-
-#ifdef HAVE_SELINUX
-#include <selinux/selinux.h>
-#endif
-
-#include "socket-util.h"
-#include "journald-server.h"
-#include "journald-stream.h"
-#include "journald-syslog.h"
-#include "journald-kmsg.h"
-#include "journald-console.h"
-
-#define STDOUT_STREAMS_MAX 4096
-
-typedef enum StdoutStreamState {
- STDOUT_STREAM_IDENTIFIER,
- STDOUT_STREAM_UNIT_ID,
- STDOUT_STREAM_PRIORITY,
- STDOUT_STREAM_LEVEL_PREFIX,
- STDOUT_STREAM_FORWARD_TO_SYSLOG,
- STDOUT_STREAM_FORWARD_TO_KMSG,
- STDOUT_STREAM_FORWARD_TO_CONSOLE,
- STDOUT_STREAM_RUNNING
-} StdoutStreamState;
-
-struct StdoutStream {
- Server *server;
- StdoutStreamState state;
-
- int fd;
-
- struct ucred ucred;
-#ifdef HAVE_SELINUX
- security_context_t security_context;
-#endif
-
- char *identifier;
- char *unit_id;
- int priority;
- bool level_prefix:1;
- bool forward_to_syslog:1;
- bool forward_to_kmsg:1;
- bool forward_to_console:1;
-
- char buffer[LINE_MAX+1];
- size_t length;
-
- LIST_FIELDS(StdoutStream, stdout_stream);
-};
-
-static int stdout_stream_log(StdoutStream *s, const char *p) {
- struct iovec iovec[N_IOVEC_META_FIELDS + 5];
- char *message = NULL, *syslog_priority = NULL, *syslog_facility = NULL, *syslog_identifier = NULL;
- unsigned n = 0;
- int priority;
- char *label = NULL;
- size_t label_len = 0;
-
- assert(s);
- assert(p);
-
- if (isempty(p))
- return 0;
-
- priority = s->priority;
-
- if (s->level_prefix)
- syslog_parse_priority((char**) &p, &priority);
-
- if (s->forward_to_syslog || s->server->forward_to_syslog)
- server_forward_syslog(s->server, syslog_fixup_facility(priority), s->identifier, p, &s->ucred, NULL);
-
- if (s->forward_to_kmsg || s->server->forward_to_kmsg)
- server_forward_kmsg(s->server, priority, s->identifier, p, &s->ucred);
-
- if (s->forward_to_console || s->server->forward_to_console)
- server_forward_console(s->server, priority, s->identifier, p, &s->ucred);
-
- IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=stdout");
-
- if (asprintf(&syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK) >= 0)
- IOVEC_SET_STRING(iovec[n++], syslog_priority);
-
- if (priority & LOG_FACMASK)
- if (asprintf(&syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority)) >= 0)
- IOVEC_SET_STRING(iovec[n++], syslog_facility);
-
- if (s->identifier) {
- syslog_identifier = strappend("SYSLOG_IDENTIFIER=", s->identifier);
- if (syslog_identifier)
- IOVEC_SET_STRING(iovec[n++], syslog_identifier);
- }
-
- message = strappend("MESSAGE=", p);
- if (message)
- IOVEC_SET_STRING(iovec[n++], message);
-
-#ifdef HAVE_SELINUX
- if (s->security_context) {
- label = (char*) s->security_context;
- label_len = strlen((char*) s->security_context);
- }
-#endif
-
- server_dispatch_message(s->server, iovec, n, ELEMENTSOF(iovec), &s->ucred, NULL, label, label_len, s->unit_id, priority);
-
- free(message);
- free(syslog_priority);
- free(syslog_facility);
- free(syslog_identifier);
-
- return 0;
-}
-
-static int stdout_stream_line(StdoutStream *s, char *p) {
- int r;
-
- assert(s);
- assert(p);
-
- p = strstrip(p);
-
- switch (s->state) {
-
- case STDOUT_STREAM_IDENTIFIER:
- if (isempty(p))
- s->identifier = NULL;
- else {
- s->identifier = strdup(p);
- if (!s->identifier)
- return log_oom();
- }
-
- s->state = STDOUT_STREAM_UNIT_ID;
- return 0;
-
- case STDOUT_STREAM_UNIT_ID:
- if (s->ucred.uid == 0) {
- if (isempty(p))
- s->unit_id = NULL;
- else {
- s->unit_id = strdup(p);
- if (!s->unit_id)
- return log_oom();
- }
- }
-
- s->state = STDOUT_STREAM_PRIORITY;
- return 0;
-
- case STDOUT_STREAM_PRIORITY:
- r = safe_atoi(p, &s->priority);
- if (r < 0 || s->priority <= 0 || s->priority >= 999) {
- log_warning("Failed to parse log priority line.");
- return -EINVAL;
- }
-
- s->state = STDOUT_STREAM_LEVEL_PREFIX;
- return 0;
-
- case STDOUT_STREAM_LEVEL_PREFIX:
- r = parse_boolean(p);
- if (r < 0) {
- log_warning("Failed to parse level prefix line.");
- return -EINVAL;
- }
-
- s->level_prefix = !!r;
- s->state = STDOUT_STREAM_FORWARD_TO_SYSLOG;
- return 0;
-
- case STDOUT_STREAM_FORWARD_TO_SYSLOG:
- r = parse_boolean(p);
- if (r < 0) {
- log_warning("Failed to parse forward to syslog line.");
- return -EINVAL;
- }
-
- s->forward_to_syslog = !!r;
- s->state = STDOUT_STREAM_FORWARD_TO_KMSG;
- return 0;
-
- case STDOUT_STREAM_FORWARD_TO_KMSG:
- r = parse_boolean(p);
- if (r < 0) {
- log_warning("Failed to parse copy to kmsg line.");
- return -EINVAL;
- }
-
- s->forward_to_kmsg = !!r;
- s->state = STDOUT_STREAM_FORWARD_TO_CONSOLE;
- return 0;
-
- case STDOUT_STREAM_FORWARD_TO_CONSOLE:
- r = parse_boolean(p);
- if (r < 0) {
- log_warning("Failed to parse copy to console line.");
- return -EINVAL;
- }
-
- s->forward_to_console = !!r;
- s->state = STDOUT_STREAM_RUNNING;
- return 0;
-
- case STDOUT_STREAM_RUNNING:
- return stdout_stream_log(s, p);
- }
-
- assert_not_reached("Unknown stream state");
-}
-
-static int stdout_stream_scan(StdoutStream *s, bool force_flush) {
- char *p;
- size_t remaining;
- int r;
-
- assert(s);
-
- p = s->buffer;
- remaining = s->length;
- for (;;) {
- char *end;
- size_t skip;
-
- end = memchr(p, '\n', remaining);
- if (end)
- skip = end - p + 1;
- else if (remaining >= sizeof(s->buffer) - 1) {
- end = p + sizeof(s->buffer) - 1;
- skip = remaining;
- } else
- break;
-
- *end = 0;
-
- r = stdout_stream_line(s, p);
- if (r < 0)
- return r;
-
- remaining -= skip;
- p += skip;
- }
-
- if (force_flush && remaining > 0) {
- p[remaining] = 0;
- r = stdout_stream_line(s, p);
- if (r < 0)
- return r;
-
- p += remaining;
- remaining = 0;
- }
-
- if (p > s->buffer) {
- memmove(s->buffer, p, remaining);
- s->length = remaining;
- }
-
- return 0;
-}
-
-int stdout_stream_process(StdoutStream *s) {
- ssize_t l;
- int r;
-
- assert(s);
-
- l = read(s->fd, s->buffer+s->length, sizeof(s->buffer)-1-s->length);
- if (l < 0) {
-
- if (errno == EAGAIN)
- return 0;
-
- log_warning("Failed to read from stream: %m");
- return -errno;
- }
-
- if (l == 0) {
- r = stdout_stream_scan(s, true);
- if (r < 0)
- return r;
-
- return 0;
- }
-
- s->length += l;
- r = stdout_stream_scan(s, false);
- if (r < 0)
- return r;
-
- return 1;
-
-}
-
-void stdout_stream_free(StdoutStream *s) {
- assert(s);
-
- if (s->server) {
- assert(s->server->n_stdout_streams > 0);
- s->server->n_stdout_streams --;
- LIST_REMOVE(StdoutStream, stdout_stream, s->server->stdout_streams, s);
- }
-
- if (s->fd >= 0) {
- if (s->server)
- epoll_ctl(s->server->epoll_fd, EPOLL_CTL_DEL, s->fd, NULL);
-
- close_nointr_nofail(s->fd);
- }
-
-#ifdef HAVE_SELINUX
- if (s->security_context)
- freecon(s->security_context);
-#endif
-
- free(s->identifier);
- free(s);
-}
-
-int stdout_stream_new(Server *s) {
- StdoutStream *stream;
- int fd, r;
- socklen_t len;
- struct epoll_event ev;
-
- assert(s);
-
- fd = accept4(s->stdout_fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
- if (fd < 0) {
- if (errno == EAGAIN)
- return 0;
-
- log_error("Failed to accept stdout connection: %m");
- return -errno;
- }
-
- if (s->n_stdout_streams >= STDOUT_STREAMS_MAX) {
- log_warning("Too many stdout streams, refusing connection.");
- close_nointr_nofail(fd);
- return 0;
- }
-
- stream = new0(StdoutStream, 1);
- if (!stream) {
- close_nointr_nofail(fd);
- return log_oom();
- }
-
- stream->fd = fd;
-
- len = sizeof(stream->ucred);
- if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &stream->ucred, &len) < 0) {
- log_error("Failed to determine peer credentials: %m");
- r = -errno;
- goto fail;
- }
-
-#ifdef HAVE_SELINUX
- if (getpeercon(fd, &stream->security_context) < 0 && errno != ENOPROTOOPT)
- log_error("Failed to determine peer security context: %m");
-#endif
-
- if (shutdown(fd, SHUT_WR) < 0) {
- log_error("Failed to shutdown writing side of socket: %m");
- r = -errno;
- goto fail;
- }
-
- zero(ev);
- ev.data.ptr = stream;
- ev.events = EPOLLIN;
- if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
- log_error("Failed to add stream to event loop: %m");
- r = -errno;
- goto fail;
- }
-
- stream->server = s;
- LIST_PREPEND(StdoutStream, stdout_stream, s->stdout_streams, stream);
- s->n_stdout_streams ++;
-
- return 0;
-
-fail:
- stdout_stream_free(stream);
- return r;
-}
-
-int server_open_stdout_socket(Server *s) {
- union sockaddr_union sa;
- int r;
- struct epoll_event ev;
-
- assert(s);
-
- if (s->stdout_fd < 0) {
-
- s->stdout_fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (s->stdout_fd < 0) {
- log_error("socket() failed: %m");
- return -errno;
- }
-
- zero(sa);
- sa.un.sun_family = AF_UNIX;
- strncpy(sa.un.sun_path, "/run/systemd/journal/stdout", sizeof(sa.un.sun_path));
-
- unlink(sa.un.sun_path);
-
- r = bind(s->stdout_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
- if (r < 0) {
- log_error("bind() failed: %m");
- return -errno;
- }
-
- chmod(sa.un.sun_path, 0666);
-
- if (listen(s->stdout_fd, SOMAXCONN) < 0) {
- log_error("liste() failed: %m");
- return -errno;
- }
- } else
- fd_nonblock(s->stdout_fd, 1);
-
- zero(ev);
- ev.events = EPOLLIN;
- ev.data.fd = s->stdout_fd;
- if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->stdout_fd, &ev) < 0) {
- log_error("Failed to add stdout server fd to epoll object: %m");
- return -errno;
- }
-
- return 0;
-}
diff --git a/src/journal/journald-stream.h b/src/journal/journald-stream.h
deleted file mode 100644
index dfb6267bf6..0000000000
--- a/src/journal/journald-stream.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 "journald-server.h"
-
-int server_open_stdout_socket(Server *s);
-
-int stdout_stream_new(Server *s);
-void stdout_stream_free(StdoutStream *s);
-int stdout_stream_process(StdoutStream *s);
diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c
deleted file mode 100644
index afddca3630..0000000000
--- a/src/journal/journald-syslog.c
+++ /dev/null
@@ -1,492 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <unistd.h>
-#include <stddef.h>
-#include <sys/epoll.h>
-
-#include "systemd/sd-messages.h"
-#include "socket-util.h"
-#include "journald-server.h"
-#include "journald-syslog.h"
-#include "journald-kmsg.h"
-#include "journald-console.h"
-
-/* Warn once every 30s if we missed syslog message */
-#define WARN_FORWARD_SYSLOG_MISSED_USEC (30 * USEC_PER_SEC)
-
-static void forward_syslog_iovec(Server *s, const struct iovec *iovec, unsigned n_iovec, struct ucred *ucred, struct timeval *tv) {
- struct msghdr msghdr;
- struct cmsghdr *cmsg;
- union {
- struct cmsghdr cmsghdr;
- uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
- } control;
- union sockaddr_union sa;
-
- assert(s);
- assert(iovec);
- assert(n_iovec > 0);
-
- zero(msghdr);
- msghdr.msg_iov = (struct iovec*) iovec;
- msghdr.msg_iovlen = n_iovec;
-
- zero(sa);
- sa.un.sun_family = AF_UNIX;
- strncpy(sa.un.sun_path, "/run/systemd/journal/syslog", sizeof(sa.un.sun_path));
- msghdr.msg_name = &sa;
- msghdr.msg_namelen = offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path);
-
- if (ucred) {
- zero(control);
- msghdr.msg_control = &control;
- msghdr.msg_controllen = sizeof(control);
-
- cmsg = CMSG_FIRSTHDR(&msghdr);
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_CREDENTIALS;
- cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
- memcpy(CMSG_DATA(cmsg), ucred, sizeof(struct ucred));
- msghdr.msg_controllen = cmsg->cmsg_len;
- }
-
- /* Forward the syslog message we received via /dev/log to
- * /run/systemd/syslog. Unfortunately we currently can't set
- * the SO_TIMESTAMP auxiliary data, and hence we don't. */
-
- if (sendmsg(s->syslog_fd, &msghdr, MSG_NOSIGNAL) >= 0)
- return;
-
- /* The socket is full? I guess the syslog implementation is
- * too slow, and we shouldn't wait for that... */
- if (errno == EAGAIN) {
- s->n_forward_syslog_missed++;
- return;
- }
-
- if (ucred && errno == ESRCH) {
- struct ucred u;
-
- /* Hmm, presumably the sender process vanished
- * by now, so let's fix it as good as we
- * can, and retry */
-
- u = *ucred;
- u.pid = getpid();
- memcpy(CMSG_DATA(cmsg), &u, sizeof(struct ucred));
-
- if (sendmsg(s->syslog_fd, &msghdr, MSG_NOSIGNAL) >= 0)
- return;
-
- if (errno == EAGAIN) {
- s->n_forward_syslog_missed++;
- return;
- }
- }
-
- if (errno != ENOENT)
- log_debug("Failed to forward syslog message: %m");
-}
-
-static void forward_syslog_raw(Server *s, int priority, const char *buffer, struct ucred *ucred, struct timeval *tv) {
- struct iovec iovec;
-
- assert(s);
- assert(buffer);
-
- if (LOG_PRI(priority) > s->max_level_syslog)
- return;
-
- IOVEC_SET_STRING(iovec, buffer);
- forward_syslog_iovec(s, &iovec, 1, ucred, tv);
-}
-
-void server_forward_syslog(Server *s, int priority, const char *identifier, const char *message, struct ucred *ucred, struct timeval *tv) {
- struct iovec iovec[5];
- char header_priority[6], header_time[64], header_pid[16];
- int n = 0;
- time_t t;
- struct tm *tm;
- char *ident_buf = NULL;
-
- assert(s);
- assert(priority >= 0);
- assert(priority <= 999);
- assert(message);
-
- if (LOG_PRI(priority) > s->max_level_syslog)
- return;
-
- /* First: priority field */
- snprintf(header_priority, sizeof(header_priority), "<%i>", priority);
- char_array_0(header_priority);
- IOVEC_SET_STRING(iovec[n++], header_priority);
-
- /* Second: timestamp */
- t = tv ? tv->tv_sec : ((time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC));
- tm = localtime(&t);
- if (!tm)
- return;
- if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
- return;
- IOVEC_SET_STRING(iovec[n++], header_time);
-
- /* Third: identifier and PID */
- if (ucred) {
- if (!identifier) {
- get_process_comm(ucred->pid, &ident_buf);
- identifier = ident_buf;
- }
-
- snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) ucred->pid);
- char_array_0(header_pid);
-
- if (identifier)
- IOVEC_SET_STRING(iovec[n++], identifier);
-
- IOVEC_SET_STRING(iovec[n++], header_pid);
- } else if (identifier) {
- IOVEC_SET_STRING(iovec[n++], identifier);
- IOVEC_SET_STRING(iovec[n++], ": ");
- }
-
- /* Fourth: message */
- IOVEC_SET_STRING(iovec[n++], message);
-
- forward_syslog_iovec(s, iovec, n, ucred, tv);
-
- free(ident_buf);
-}
-
-int syslog_fixup_facility(int priority) {
-
- if ((priority & LOG_FACMASK) == 0)
- return (priority & LOG_PRIMASK) | LOG_USER;
-
- return priority;
-}
-
-size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid) {
- const char *p;
- char *t;
- size_t l, e;
-
- assert(buf);
- assert(identifier);
- assert(pid);
-
- p = *buf;
-
- p += strspn(p, WHITESPACE);
- l = strcspn(p, WHITESPACE);
-
- if (l <= 0 ||
- p[l-1] != ':')
- return 0;
-
- e = l;
- l--;
-
- if (p[l-1] == ']') {
- size_t k = l-1;
-
- for (;;) {
-
- if (p[k] == '[') {
- t = strndup(p+k+1, l-k-2);
- if (t)
- *pid = t;
-
- l = k;
- break;
- }
-
- if (k == 0)
- break;
-
- k--;
- }
- }
-
- t = strndup(p, l);
- if (t)
- *identifier = t;
-
- e += strspn(p + e, WHITESPACE);
- *buf = p + e;
- return e;
-}
-
-void syslog_parse_priority(char **p, int *priority) {
- int a = 0, b = 0, c = 0;
- int k;
-
- assert(p);
- assert(*p);
- assert(priority);
-
- if ((*p)[0] != '<')
- return;
-
- if (!strchr(*p, '>'))
- return;
-
- 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;
-
- if (a < 0 || b < 0 || c < 0)
- return;
-
- *priority = a*100+b*10+c;
- *p += k;
-}
-
-static void syslog_skip_date(char **buf) {
- enum {
- LETTER,
- SPACE,
- NUMBER,
- SPACE_OR_NUMBER,
- COLON
- } sequence[] = {
- LETTER, LETTER, LETTER,
- SPACE,
- SPACE_OR_NUMBER, NUMBER,
- SPACE,
- SPACE_OR_NUMBER, NUMBER,
- COLON,
- SPACE_OR_NUMBER, NUMBER,
- COLON,
- SPACE_OR_NUMBER, NUMBER,
- SPACE
- };
-
- char *p;
- unsigned i;
-
- assert(buf);
- assert(*buf);
-
- p = *buf;
-
- for (i = 0; i < ELEMENTSOF(sequence); i++, p++) {
-
- if (!*p)
- return;
-
- switch (sequence[i]) {
-
- case SPACE:
- if (*p != ' ')
- return;
- break;
-
- case SPACE_OR_NUMBER:
- if (*p == ' ')
- break;
-
- /* fall through */
-
- case NUMBER:
- if (*p < '0' || *p > '9')
- return;
-
- break;
-
- case LETTER:
- if (!(*p >= 'A' && *p <= 'Z') &&
- !(*p >= 'a' && *p <= 'z'))
- return;
-
- break;
-
- case COLON:
- if (*p != ':')
- return;
- break;
-
- }
- }
-
- *buf = p;
-}
-
-void server_process_syslog_message(
- Server *s,
- const char *buf,
- struct ucred *ucred,
- struct timeval *tv,
- const char *label,
- size_t label_len) {
-
- char *message = NULL, *syslog_priority = NULL, *syslog_facility = NULL, *syslog_identifier = NULL, *syslog_pid = NULL;
- struct iovec iovec[N_IOVEC_META_FIELDS + 6];
- unsigned n = 0;
- int priority = LOG_USER | LOG_INFO;
- char *identifier = NULL, *pid = NULL;
- const char *orig;
-
- assert(s);
- assert(buf);
-
- orig = buf;
- syslog_parse_priority((char**) &buf, &priority);
-
- if (s->forward_to_syslog)
- forward_syslog_raw(s, priority, orig, ucred, tv);
-
- syslog_skip_date((char**) &buf);
- syslog_parse_identifier(&buf, &identifier, &pid);
-
- if (s->forward_to_kmsg)
- server_forward_kmsg(s, priority, identifier, buf, ucred);
-
- if (s->forward_to_console)
- server_forward_console(s, priority, identifier, buf, ucred);
-
- IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=syslog");
-
- if (asprintf(&syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK) >= 0)
- IOVEC_SET_STRING(iovec[n++], syslog_priority);
-
- if (priority & LOG_FACMASK)
- if (asprintf(&syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority)) >= 0)
- IOVEC_SET_STRING(iovec[n++], syslog_facility);
-
- if (identifier) {
- syslog_identifier = strappend("SYSLOG_IDENTIFIER=", identifier);
- if (syslog_identifier)
- IOVEC_SET_STRING(iovec[n++], syslog_identifier);
- }
-
- if (pid) {
- syslog_pid = strappend("SYSLOG_PID=", pid);
- if (syslog_pid)
- IOVEC_SET_STRING(iovec[n++], syslog_pid);
- }
-
- message = strappend("MESSAGE=", buf);
- if (message)
- IOVEC_SET_STRING(iovec[n++], message);
-
- server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), ucred, tv, label, label_len, NULL, priority);
-
- free(message);
- free(identifier);
- free(pid);
- free(syslog_priority);
- free(syslog_facility);
- free(syslog_identifier);
- free(syslog_pid);
-}
-
-int server_open_syslog_socket(Server *s) {
- union sockaddr_union sa;
- int one, r;
- struct epoll_event ev;
-
- assert(s);
-
- if (s->syslog_fd < 0) {
-
- s->syslog_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (s->syslog_fd < 0) {
- log_error("socket() failed: %m");
- return -errno;
- }
-
- zero(sa);
- sa.un.sun_family = AF_UNIX;
- strncpy(sa.un.sun_path, "/dev/log", sizeof(sa.un.sun_path));
-
- unlink(sa.un.sun_path);
-
- r = bind(s->syslog_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
- if (r < 0) {
- log_error("bind() failed: %m");
- return -errno;
- }
-
- chmod(sa.un.sun_path, 0666);
- } else
- fd_nonblock(s->syslog_fd, 1);
-
- one = 1;
- r = setsockopt(s->syslog_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
- if (r < 0) {
- log_error("SO_PASSCRED failed: %m");
- return -errno;
- }
-
-#ifdef HAVE_SELINUX
- one = 1;
- r = setsockopt(s->syslog_fd, SOL_SOCKET, SO_PASSSEC, &one, sizeof(one));
- if (r < 0)
- log_warning("SO_PASSSEC failed: %m");
-#endif
-
- one = 1;
- r = setsockopt(s->syslog_fd, SOL_SOCKET, SO_TIMESTAMP, &one, sizeof(one));
- if (r < 0) {
- log_error("SO_TIMESTAMP failed: %m");
- return -errno;
- }
-
- zero(ev);
- ev.events = EPOLLIN;
- ev.data.fd = s->syslog_fd;
- if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->syslog_fd, &ev) < 0) {
- log_error("Failed to add syslog server fd to epoll object: %m");
- return -errno;
- }
-
- return 0;
-}
-
-void server_maybe_warn_forward_syslog_missed(Server *s) {
- usec_t n;
- assert(s);
-
- if (s->n_forward_syslog_missed <= 0)
- return;
-
- n = now(CLOCK_MONOTONIC);
- if (s->last_warn_forward_syslog_missed + WARN_FORWARD_SYSLOG_MISSED_USEC > n)
- return;
-
- server_driver_message(s, SD_MESSAGE_FORWARD_SYSLOG_MISSED, "Forwarding to syslog missed %u messages.", s->n_forward_syslog_missed);
-
- s->n_forward_syslog_missed = 0;
- s->last_warn_forward_syslog_missed = n;
-}
diff --git a/src/journal/journald-syslog.h b/src/journal/journald-syslog.h
deleted file mode 100644
index 7ff215b524..0000000000
--- a/src/journal/journald-syslog.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 "journald-server.h"
-
-int syslog_fixup_facility(int priority);
-
-void syslog_parse_priority(char **p, int *priority);
-size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid);
-
-void server_forward_syslog(Server *s, int priority, const char *identifier, const char *message, struct ucred *ucred, struct timeval *tv);
-
-void server_process_syslog_message(Server *s, const char *buf, struct ucred *ucred, struct timeval *tv, const char *label, size_t label_len);
-int server_open_syslog_socket(Server *s);
-
-void server_maybe_warn_forward_syslog_missed(Server *s);
diff --git a/src/journal/journald.c b/src/journal/journald.c
deleted file mode 100644
index d6b9be5974..0000000000
--- a/src/journal/journald.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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/epoll.h>
-#include <sys/socket.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include <systemd/sd-journal.h>
-#include <systemd/sd-messages.h>
-#include <systemd/sd-daemon.h>
-
-#include "journal-authenticate.h"
-#include "journald-server.h"
-#include "journald-kmsg.h"
-#include "journald-syslog.h"
-
-int main(int argc, char *argv[]) {
- Server server;
- int r;
-
- /* if (getppid() != 1) { */
- /* log_error("This program should be invoked by init only."); */
- /* return EXIT_FAILURE; */
- /* } */
-
- if (argc > 1) {
- log_error("This program does not take arguments.");
- return EXIT_FAILURE;
- }
-
- log_set_target(LOG_TARGET_SAFE);
- log_set_facility(LOG_SYSLOG);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- r = server_init(&server);
- if (r < 0)
- goto finish;
-
- server_vacuum(&server);
- server_flush_to_var(&server);
- server_flush_dev_kmsg(&server);
-
- log_debug("systemd-journald running as pid %lu", (unsigned long) getpid());
- server_driver_message(&server, SD_MESSAGE_JOURNAL_START, "Journal started");
-
- sd_notify(false,
- "READY=1\n"
- "STATUS=Processing requests...");
-
- for (;;) {
- struct epoll_event event;
- int t = -1;
- usec_t n;
-
- n = now(CLOCK_REALTIME);
-
- if (server.max_retention_usec > 0 && server.oldest_file_usec > 0) {
-
- /* The retention time is reached, so let's vacuum! */
- if (server.oldest_file_usec + server.max_retention_usec < n) {
- log_info("Retention time reached.");
- server_rotate(&server);
- server_vacuum(&server);
- continue;
- }
-
- /* Calculate when to rotate the next time */
- t = (int) ((server.oldest_file_usec + server.max_retention_usec - n + USEC_PER_MSEC - 1) / USEC_PER_MSEC);
- log_info("Sleeping for %i ms", t);
- }
-
-#ifdef HAVE_GCRYPT
- if (server.system_journal) {
- usec_t u;
-
- if (journal_file_next_evolve_usec(server.system_journal, &u)) {
- if (n >= u)
- t = 0;
- else
- t = MIN(t, (int) ((u - n + USEC_PER_MSEC - 1) / USEC_PER_MSEC));
- }
- }
-#endif
-
- r = epoll_wait(server.epoll_fd, &event, 1, t);
- if (r < 0) {
-
- if (errno == EINTR)
- continue;
-
- log_error("epoll_wait() failed: %m");
- r = -errno;
- goto finish;
- }
-
- if (r > 0) {
- r = process_event(&server, &event);
- if (r < 0)
- goto finish;
- else if (r == 0)
- break;
- }
-
- server_maybe_append_tags(&server);
- server_maybe_warn_forward_syslog_missed(&server);
- }
-
- log_debug("systemd-journald stopped as pid %lu", (unsigned long) getpid());
- server_driver_message(&server, SD_MESSAGE_JOURNAL_STOP, "Journal stopped");
-
-finish:
- sd_notify(false,
- "STATUS=Shutting down...");
-
- server_done(&server);
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/journal/journald.conf b/src/journal/journald.conf
deleted file mode 100644
index 948318bc62..0000000000
--- a/src/journal/journald.conf
+++ /dev/null
@@ -1,32 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# See journald.conf(5) for details
-
-[Journal]
-#Storage=auto
-#Compress=yes
-#Seal=yes
-#SplitMode=login
-#RateLimitInterval=10s
-#RateLimitBurst=200
-#SystemMaxUse=
-#SystemKeepFree=
-#SystemMaxFileSize=
-#RuntimeMaxUse=
-#RuntimeKeepFree=
-#RuntimeMaxFileSize=
-#MaxRetentionSec=
-#MaxFileSec=1month
-#ForwardToSyslog=yes
-#ForwardToKMsg=no
-#ForwardToConsole=no
-#TTYPath=/dev/console
-#MaxLevelStore=debug
-#MaxLevelSyslog=debug
-#MaxLevelKMsg=notice
-#MaxLevelConsole=info
diff --git a/src/journal/libsystemd-journal.pc.in b/src/journal/libsystemd-journal.pc.in
deleted file mode 100644
index 9883595644..0000000000
--- a/src/journal/libsystemd-journal.pc.in
+++ /dev/null
@@ -1,19 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-
-Name: systemd
-Description: systemd Journal Utility Library
-URL: @PACKAGE_URL@
-Version: @PACKAGE_VERSION@
-Requires: libsystemd-id128 = @PACKAGE_VERSION@
-Libs: -L${libdir} -lsystemd-journal
-Cflags: -I${includedir}
diff --git a/src/journal/libsystemd-journal.sym b/src/journal/libsystemd-journal.sym
deleted file mode 100644
index ad78fcc74d..0000000000
--- a/src/journal/libsystemd-journal.sym
+++ /dev/null
@@ -1,87 +0,0 @@
-/***
- This file is part of systemd.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-***/
-
-/* Original symbols from systemd v38 */
-
-LIBSYSTEMD_JOURNAL_38 {
-global:
- sd_journal_print;
- sd_journal_printv;
- sd_journal_send;
- sd_journal_sendv;
- sd_journal_stream_fd;
- sd_journal_open;
- sd_journal_close;
- sd_journal_previous;
- sd_journal_next;
- sd_journal_previous_skip;
- sd_journal_next_skip;
- sd_journal_get_realtime_usec;
- sd_journal_get_monotonic_usec;
- sd_journal_get_data;
- sd_journal_enumerate_data;
- sd_journal_restart_data;
- sd_journal_add_match;
- sd_journal_flush_matches;
- sd_journal_seek_head;
- sd_journal_seek_tail;
- sd_journal_seek_monotonic_usec;
- sd_journal_seek_realtime_usec;
- sd_journal_seek_cursor;
- sd_journal_get_cursor;
- sd_journal_get_fd;
- sd_journal_process;
-local:
- *;
-};
-
-LIBSYSTEMD_JOURNAL_183 {
-global:
- sd_journal_print_with_location;
- sd_journal_printv_with_location;
- sd_journal_send_with_location;
- sd_journal_sendv_with_location;
-} LIBSYSTEMD_JOURNAL_38;
-
-LIBSYSTEMD_JOURNAL_184 {
-global:
- sd_journal_get_cutoff_realtime_usec;
- sd_journal_get_cutoff_monotonic_usec;
-} LIBSYSTEMD_JOURNAL_183;
-
-LIBSYSTEMD_JOURNAL_187 {
-global:
- sd_journal_wait;
- sd_journal_open_directory;
- sd_journal_add_disjunction;
-} LIBSYSTEMD_JOURNAL_184;
-
-LIBSYSTEMD_JOURNAL_188 {
-global:
- sd_journal_perror;
- sd_journal_perror_with_location;
-} LIBSYSTEMD_JOURNAL_187;
-
-LIBSYSTEMD_JOURNAL_190 {
-global:
- sd_journal_get_usage;
-} LIBSYSTEMD_JOURNAL_188;
-
-LIBSYSTEMD_JOURNAL_195 {
-global:
- sd_journal_test_cursor;
- sd_journal_query_unique;
- sd_journal_enumerate_unique;
- sd_journal_restart_unique;
-} LIBSYSTEMD_JOURNAL_190;
-
-LIBSYSTEMD_JOURNAL_196 {
-global:
- sd_journal_fd_reliable;
-} LIBSYSTEMD_JOURNAL_195;
diff --git a/src/journal/lookup3.c b/src/journal/lookup3.c
deleted file mode 100644
index 52ffdf7b1d..0000000000
--- a/src/journal/lookup3.c
+++ /dev/null
@@ -1,1009 +0,0 @@
-/* Slightly modified by Lennart Poettering, to avoid name clashes, and
- * unexport a few functions. */
-
-#include "lookup3.h"
-
-/*
--------------------------------------------------------------------------------
-lookup3.c, by Bob Jenkins, May 2006, Public Domain.
-
-These are functions for producing 32-bit hashes for hash table lookup.
-hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
-are externally useful functions. Routines to test the hash are included
-if SELF_TEST is defined. You can use this free for any purpose. It's in
-the public domain. It has no warranty.
-
-You probably want to use hashlittle(). hashlittle() and hashbig()
-hash byte arrays. hashlittle() is faster than hashbig() on
-little-endian machines. Intel and AMD are little-endian machines.
-On second thought, you probably want hashlittle2(), which is identical to
-hashlittle() except it returns two 32-bit hashes for the price of one.
-You could implement hashbig2() if you wanted but I haven't bothered here.
-
-If you want to find a hash of, say, exactly 7 integers, do
- a = i1; b = i2; c = i3;
- mix(a,b,c);
- a += i4; b += i5; c += i6;
- mix(a,b,c);
- a += i7;
- final(a,b,c);
-then use c as the hash value. If you have a variable length array of
-4-byte integers to hash, use hashword(). If you have a byte array (like
-a character string), use hashlittle(). If you have several byte arrays, or
-a mix of things, see the comments above hashlittle().
-
-Why is this so big? I read 12 bytes at a time into 3 4-byte integers,
-then mix those integers. This is fast (you can do a lot more thorough
-mixing with 12*3 instructions on 3 integers than you can with 3 instructions
-on 1 byte), but shoehorning those bytes into integers efficiently is messy.
--------------------------------------------------------------------------------
-*/
-/* #define SELF_TEST 1 */
-
-#include <stdio.h> /* defines printf for tests */
-#include <time.h> /* defines time_t for timings in the test */
-#include <stdint.h> /* defines uint32_t etc */
-#include <sys/param.h> /* attempt to define endianness */
-#ifdef linux
-# include <endian.h> /* attempt to define endianness */
-#endif
-
-/*
- * My best guess at if you are big-endian or little-endian. This may
- * need adjustment.
- */
-#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
- __BYTE_ORDER == __LITTLE_ENDIAN) || \
- (defined(i386) || defined(__i386__) || defined(__i486__) || \
- defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL))
-# define HASH_LITTLE_ENDIAN 1
-# define HASH_BIG_ENDIAN 0
-#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
- __BYTE_ORDER == __BIG_ENDIAN) || \
- (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
-# define HASH_LITTLE_ENDIAN 0
-# define HASH_BIG_ENDIAN 1
-#else
-# define HASH_LITTLE_ENDIAN 0
-# define HASH_BIG_ENDIAN 0
-#endif
-
-#define hashsize(n) ((uint32_t)1<<(n))
-#define hashmask(n) (hashsize(n)-1)
-#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
-
-/*
--------------------------------------------------------------------------------
-mix -- mix 3 32-bit values reversibly.
-
-This is reversible, so any information in (a,b,c) before mix() is
-still in (a,b,c) after mix().
-
-If four pairs of (a,b,c) inputs are run through mix(), or through
-mix() in reverse, there are at least 32 bits of the output that
-are sometimes the same for one pair and different for another pair.
-This was tested for:
-* pairs that differed by one bit, by two bits, in any combination
- of top bits of (a,b,c), or in any combination of bottom bits of
- (a,b,c).
-* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
- the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
- is commonly produced by subtraction) look like a single 1-bit
- difference.
-* the base values were pseudorandom, all zero but one bit set, or
- all zero plus a counter that starts at zero.
-
-Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that
-satisfy this are
- 4 6 8 16 19 4
- 9 15 3 18 27 15
- 14 9 3 7 17 3
-Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing
-for "differ" defined as + with a one-bit base and a two-bit delta. I
-used http://burtleburtle.net/bob/hash/avalanche.html to choose
-the operations, constants, and arrangements of the variables.
-
-This does not achieve avalanche. There are input bits of (a,b,c)
-that fail to affect some output bits of (a,b,c), especially of a. The
-most thoroughly mixed value is c, but it doesn't really even achieve
-avalanche in c.
-
-This allows some parallelism. Read-after-writes are good at doubling
-the number of bits affected, so the goal of mixing pulls in the opposite
-direction as the goal of parallelism. I did what I could. Rotates
-seem to cost as much as shifts on every machine I could lay my hands
-on, and rotates are much kinder to the top and bottom bits, so I used
-rotates.
--------------------------------------------------------------------------------
-*/
-#define mix(a,b,c) \
-{ \
- a -= c; a ^= rot(c, 4); c += b; \
- b -= a; b ^= rot(a, 6); a += c; \
- c -= b; c ^= rot(b, 8); b += a; \
- a -= c; a ^= rot(c,16); c += b; \
- b -= a; b ^= rot(a,19); a += c; \
- c -= b; c ^= rot(b, 4); b += a; \
-}
-
-/*
--------------------------------------------------------------------------------
-final -- final mixing of 3 32-bit values (a,b,c) into c
-
-Pairs of (a,b,c) values differing in only a few bits will usually
-produce values of c that look totally different. This was tested for
-* pairs that differed by one bit, by two bits, in any combination
- of top bits of (a,b,c), or in any combination of bottom bits of
- (a,b,c).
-* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
- the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
- is commonly produced by subtraction) look like a single 1-bit
- difference.
-* the base values were pseudorandom, all zero but one bit set, or
- all zero plus a counter that starts at zero.
-
-These constants passed:
- 14 11 25 16 4 14 24
- 12 14 25 16 4 14 24
-and these came close:
- 4 8 15 26 3 22 24
- 10 8 15 26 3 22 24
- 11 8 15 26 3 22 24
--------------------------------------------------------------------------------
-*/
-#define final(a,b,c) \
-{ \
- c ^= b; c -= rot(b,14); \
- a ^= c; a -= rot(c,11); \
- b ^= a; b -= rot(a,25); \
- c ^= b; c -= rot(b,16); \
- a ^= c; a -= rot(c,4); \
- b ^= a; b -= rot(a,14); \
- c ^= b; c -= rot(b,24); \
-}
-
-/*
---------------------------------------------------------------------
- This works on all machines. To be useful, it requires
- -- that the key be an array of uint32_t's, and
- -- that the length be the number of uint32_t's in the key
-
- The function hashword() is identical to hashlittle() on little-endian
- machines, and identical to hashbig() on big-endian machines,
- except that the length has to be measured in uint32_ts rather than in
- bytes. hashlittle() is more complicated than hashword() only because
- hashlittle() has to dance around fitting the key bytes into registers.
---------------------------------------------------------------------
-*/
-uint32_t jenkins_hashword(
-const uint32_t *k, /* the key, an array of uint32_t values */
-size_t length, /* the length of the key, in uint32_ts */
-uint32_t initval) /* the previous hash, or an arbitrary value */
-{
- uint32_t a,b,c;
-
- /* Set up the internal state */
- a = b = c = 0xdeadbeef + (((uint32_t)length)<<2) + initval;
-
- /*------------------------------------------------- handle most of the key */
- while (length > 3)
- {
- a += k[0];
- b += k[1];
- c += k[2];
- mix(a,b,c);
- length -= 3;
- k += 3;
- }
-
- /*------------------------------------------- handle the last 3 uint32_t's */
- switch(length) /* all the case statements fall through */
- {
- case 3 : c+=k[2];
- case 2 : b+=k[1];
- case 1 : a+=k[0];
- final(a,b,c);
- case 0: /* case 0: nothing left to add */
- break;
- }
- /*------------------------------------------------------ report the result */
- return c;
-}
-
-
-/*
---------------------------------------------------------------------
-hashword2() -- same as hashword(), but take two seeds and return two
-32-bit values. pc and pb must both be nonnull, and *pc and *pb must
-both be initialized with seeds. If you pass in (*pb)==0, the output
-(*pc) will be the same as the return value from hashword().
---------------------------------------------------------------------
-*/
-void jenkins_hashword2 (
-const uint32_t *k, /* the key, an array of uint32_t values */
-size_t length, /* the length of the key, in uint32_ts */
-uint32_t *pc, /* IN: seed OUT: primary hash value */
-uint32_t *pb) /* IN: more seed OUT: secondary hash value */
-{
- uint32_t a,b,c;
-
- /* Set up the internal state */
- a = b = c = 0xdeadbeef + ((uint32_t)(length<<2)) + *pc;
- c += *pb;
-
- /*------------------------------------------------- handle most of the key */
- while (length > 3)
- {
- a += k[0];
- b += k[1];
- c += k[2];
- mix(a,b,c);
- length -= 3;
- k += 3;
- }
-
- /*------------------------------------------- handle the last 3 uint32_t's */
- switch(length) /* all the case statements fall through */
- {
- case 3 : c+=k[2];
- case 2 : b+=k[1];
- case 1 : a+=k[0];
- final(a,b,c);
- case 0: /* case 0: nothing left to add */
- break;
- }
- /*------------------------------------------------------ report the result */
- *pc=c; *pb=b;
-}
-
-
-/*
--------------------------------------------------------------------------------
-hashlittle() -- hash a variable-length key into a 32-bit value
- k : the key (the unaligned variable-length array of bytes)
- length : the length of the key, counting by bytes
- initval : can be any 4-byte value
-Returns a 32-bit value. Every bit of the key affects every bit of
-the return value. Two keys differing by one or two bits will have
-totally different hash values.
-
-The best hash table sizes are powers of 2. There is no need to do
-mod a prime (mod is sooo slow!). If you need less than 32 bits,
-use a bitmask. For example, if you need only 10 bits, do
- h = (h & hashmask(10));
-In which case, the hash table should have hashsize(10) elements.
-
-If you are hashing n strings (uint8_t **)k, do it like this:
- for (i=0, h=0; i<n; ++i) h = hashlittle( k[i], len[i], h);
-
-By Bob Jenkins, 2006. bob_jenkins@burtleburtle.net. You may use this
-code any way you wish, private, educational, or commercial. It's free.
-
-Use for hash table lookup, or anything where one collision in 2^^32 is
-acceptable. Do NOT use for cryptographic purposes.
--------------------------------------------------------------------------------
-*/
-
-uint32_t jenkins_hashlittle( const void *key, size_t length, uint32_t initval)
-{
- uint32_t a,b,c; /* internal state */
- union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */
-
- /* Set up the internal state */
- a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
-
- u.ptr = key;
- if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
- const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
-
- /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
- while (length > 12)
- {
- a += k[0];
- b += k[1];
- c += k[2];
- mix(a,b,c);
- length -= 12;
- k += 3;
- }
-
- /*----------------------------- handle the last (probably partial) block */
- /*
- * "k[2]&0xffffff" actually reads beyond the end of the string, but
- * then masks off the part it's not allowed to read. Because the
- * string is aligned, the masked-off tail is in the same word as the
- * rest of the string. Every machine with memory protection I've seen
- * does it on word boundaries, so is OK with this. But VALGRIND will
- * still catch it and complain. The masking trick does make the hash
- * noticeably faster for short strings (like English words).
- */
-#ifndef VALGRIND
-
- switch(length)
- {
- case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
- case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
- case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
- case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
- case 8 : b+=k[1]; a+=k[0]; break;
- case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
- case 6 : b+=k[1]&0xffff; a+=k[0]; break;
- case 5 : b+=k[1]&0xff; a+=k[0]; break;
- case 4 : a+=k[0]; break;
- case 3 : a+=k[0]&0xffffff; break;
- case 2 : a+=k[0]&0xffff; break;
- case 1 : a+=k[0]&0xff; break;
- case 0 : return c; /* zero length strings require no mixing */
- }
-
-#else /* make valgrind happy */
- {
- const uint8_t *k8 = (const uint8_t *) k;
-
- switch(length)
- {
- case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
- case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
- case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
- case 9 : c+=k8[8]; /* fall through */
- case 8 : b+=k[1]; a+=k[0]; break;
- case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
- case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
- case 5 : b+=k8[4]; /* fall through */
- case 4 : a+=k[0]; break;
- case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
- case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
- case 1 : a+=k8[0]; break;
- case 0 : return c;
- }
- }
-
-#endif /* !valgrind */
-
- } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
- const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
- const uint8_t *k8;
-
- /*--------------- all but last block: aligned reads and different mixing */
- while (length > 12)
- {
- a += k[0] + (((uint32_t)k[1])<<16);
- b += k[2] + (((uint32_t)k[3])<<16);
- c += k[4] + (((uint32_t)k[5])<<16);
- mix(a,b,c);
- length -= 12;
- k += 6;
- }
-
- /*----------------------------- handle the last (probably partial) block */
- k8 = (const uint8_t *)k;
- switch(length)
- {
- case 12: c+=k[4]+(((uint32_t)k[5])<<16);
- b+=k[2]+(((uint32_t)k[3])<<16);
- a+=k[0]+(((uint32_t)k[1])<<16);
- break;
- case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
- case 10: c+=k[4];
- b+=k[2]+(((uint32_t)k[3])<<16);
- a+=k[0]+(((uint32_t)k[1])<<16);
- break;
- case 9 : c+=k8[8]; /* fall through */
- case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
- a+=k[0]+(((uint32_t)k[1])<<16);
- break;
- case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
- case 6 : b+=k[2];
- a+=k[0]+(((uint32_t)k[1])<<16);
- break;
- case 5 : b+=k8[4]; /* fall through */
- case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
- break;
- case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
- case 2 : a+=k[0];
- break;
- case 1 : a+=k8[0];
- break;
- case 0 : return c; /* zero length requires no mixing */
- }
-
- } else { /* need to read the key one byte at a time */
- const uint8_t *k = (const uint8_t *)key;
-
- /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
- while (length > 12)
- {
- a += k[0];
- a += ((uint32_t)k[1])<<8;
- a += ((uint32_t)k[2])<<16;
- a += ((uint32_t)k[3])<<24;
- b += k[4];
- b += ((uint32_t)k[5])<<8;
- b += ((uint32_t)k[6])<<16;
- b += ((uint32_t)k[7])<<24;
- c += k[8];
- c += ((uint32_t)k[9])<<8;
- c += ((uint32_t)k[10])<<16;
- c += ((uint32_t)k[11])<<24;
- mix(a,b,c);
- length -= 12;
- k += 12;
- }
-
- /*-------------------------------- last block: affect all 32 bits of (c) */
- switch(length) /* all the case statements fall through */
- {
- case 12: c+=((uint32_t)k[11])<<24;
- case 11: c+=((uint32_t)k[10])<<16;
- case 10: c+=((uint32_t)k[9])<<8;
- case 9 : c+=k[8];
- case 8 : b+=((uint32_t)k[7])<<24;
- case 7 : b+=((uint32_t)k[6])<<16;
- case 6 : b+=((uint32_t)k[5])<<8;
- case 5 : b+=k[4];
- case 4 : a+=((uint32_t)k[3])<<24;
- case 3 : a+=((uint32_t)k[2])<<16;
- case 2 : a+=((uint32_t)k[1])<<8;
- case 1 : a+=k[0];
- break;
- case 0 : return c;
- }
- }
-
- final(a,b,c);
- return c;
-}
-
-
-/*
- * hashlittle2: return 2 32-bit hash values
- *
- * This is identical to hashlittle(), except it returns two 32-bit hash
- * values instead of just one. This is good enough for hash table
- * lookup with 2^^64 buckets, or if you want a second hash if you're not
- * happy with the first, or if you want a probably-unique 64-bit ID for
- * the key. *pc is better mixed than *pb, so use *pc first. If you want
- * a 64-bit value do something like "*pc + (((uint64_t)*pb)<<32)".
- */
-void jenkins_hashlittle2(
- const void *key, /* the key to hash */
- size_t length, /* length of the key */
- uint32_t *pc, /* IN: primary initval, OUT: primary hash */
- uint32_t *pb) /* IN: secondary initval, OUT: secondary hash */
-{
- uint32_t a,b,c; /* internal state */
- union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */
-
- /* Set up the internal state */
- a = b = c = 0xdeadbeef + ((uint32_t)length) + *pc;
- c += *pb;
-
- u.ptr = key;
- if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
- const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
-
- /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
- while (length > 12)
- {
- a += k[0];
- b += k[1];
- c += k[2];
- mix(a,b,c);
- length -= 12;
- k += 3;
- }
-
- /*----------------------------- handle the last (probably partial) block */
- /*
- * "k[2]&0xffffff" actually reads beyond the end of the string, but
- * then masks off the part it's not allowed to read. Because the
- * string is aligned, the masked-off tail is in the same word as the
- * rest of the string. Every machine with memory protection I've seen
- * does it on word boundaries, so is OK with this. But VALGRIND will
- * still catch it and complain. The masking trick does make the hash
- * noticeably faster for short strings (like English words).
- */
-#ifndef VALGRIND
-
- switch(length)
- {
- case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
- case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
- case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
- case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
- case 8 : b+=k[1]; a+=k[0]; break;
- case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
- case 6 : b+=k[1]&0xffff; a+=k[0]; break;
- case 5 : b+=k[1]&0xff; a+=k[0]; break;
- case 4 : a+=k[0]; break;
- case 3 : a+=k[0]&0xffffff; break;
- case 2 : a+=k[0]&0xffff; break;
- case 1 : a+=k[0]&0xff; break;
- case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */
- }
-
-#else /* make valgrind happy */
-
- {
- const uint8_t *k8 = (const uint8_t *)k;
- switch(length)
- {
- case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
- case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
- case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
- case 9 : c+=k8[8]; /* fall through */
- case 8 : b+=k[1]; a+=k[0]; break;
- case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
- case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
- case 5 : b+=k8[4]; /* fall through */
- case 4 : a+=k[0]; break;
- case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
- case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
- case 1 : a+=k8[0]; break;
- case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */
- }
- }
-
-#endif /* !valgrind */
-
- } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
- const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
- const uint8_t *k8;
-
- /*--------------- all but last block: aligned reads and different mixing */
- while (length > 12)
- {
- a += k[0] + (((uint32_t)k[1])<<16);
- b += k[2] + (((uint32_t)k[3])<<16);
- c += k[4] + (((uint32_t)k[5])<<16);
- mix(a,b,c);
- length -= 12;
- k += 6;
- }
-
- /*----------------------------- handle the last (probably partial) block */
- k8 = (const uint8_t *)k;
- switch(length)
- {
- case 12: c+=k[4]+(((uint32_t)k[5])<<16);
- b+=k[2]+(((uint32_t)k[3])<<16);
- a+=k[0]+(((uint32_t)k[1])<<16);
- break;
- case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
- case 10: c+=k[4];
- b+=k[2]+(((uint32_t)k[3])<<16);
- a+=k[0]+(((uint32_t)k[1])<<16);
- break;
- case 9 : c+=k8[8]; /* fall through */
- case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
- a+=k[0]+(((uint32_t)k[1])<<16);
- break;
- case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
- case 6 : b+=k[2];
- a+=k[0]+(((uint32_t)k[1])<<16);
- break;
- case 5 : b+=k8[4]; /* fall through */
- case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
- break;
- case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
- case 2 : a+=k[0];
- break;
- case 1 : a+=k8[0];
- break;
- case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */
- }
-
- } else { /* need to read the key one byte at a time */
- const uint8_t *k = (const uint8_t *)key;
-
- /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
- while (length > 12)
- {
- a += k[0];
- a += ((uint32_t)k[1])<<8;
- a += ((uint32_t)k[2])<<16;
- a += ((uint32_t)k[3])<<24;
- b += k[4];
- b += ((uint32_t)k[5])<<8;
- b += ((uint32_t)k[6])<<16;
- b += ((uint32_t)k[7])<<24;
- c += k[8];
- c += ((uint32_t)k[9])<<8;
- c += ((uint32_t)k[10])<<16;
- c += ((uint32_t)k[11])<<24;
- mix(a,b,c);
- length -= 12;
- k += 12;
- }
-
- /*-------------------------------- last block: affect all 32 bits of (c) */
- switch(length) /* all the case statements fall through */
- {
- case 12: c+=((uint32_t)k[11])<<24;
- case 11: c+=((uint32_t)k[10])<<16;
- case 10: c+=((uint32_t)k[9])<<8;
- case 9 : c+=k[8];
- case 8 : b+=((uint32_t)k[7])<<24;
- case 7 : b+=((uint32_t)k[6])<<16;
- case 6 : b+=((uint32_t)k[5])<<8;
- case 5 : b+=k[4];
- case 4 : a+=((uint32_t)k[3])<<24;
- case 3 : a+=((uint32_t)k[2])<<16;
- case 2 : a+=((uint32_t)k[1])<<8;
- case 1 : a+=k[0];
- break;
- case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */
- }
- }
-
- final(a,b,c);
- *pc=c; *pb=b;
-}
-
-
-
-/*
- * hashbig():
- * This is the same as hashword() on big-endian machines. It is different
- * from hashlittle() on all machines. hashbig() takes advantage of
- * big-endian byte ordering.
- */
-uint32_t jenkins_hashbig( const void *key, size_t length, uint32_t initval)
-{
- uint32_t a,b,c;
- union { const void *ptr; size_t i; } u; /* to cast key to (size_t) happily */
-
- /* Set up the internal state */
- a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
-
- u.ptr = key;
- if (HASH_BIG_ENDIAN && ((u.i & 0x3) == 0)) {
- const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
-
- /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
- while (length > 12)
- {
- a += k[0];
- b += k[1];
- c += k[2];
- mix(a,b,c);
- length -= 12;
- k += 3;
- }
-
- /*----------------------------- handle the last (probably partial) block */
- /*
- * "k[2]<<8" actually reads beyond the end of the string, but
- * then shifts out the part it's not allowed to read. Because the
- * string is aligned, the illegal read is in the same word as the
- * rest of the string. Every machine with memory protection I've seen
- * does it on word boundaries, so is OK with this. But VALGRIND will
- * still catch it and complain. The masking trick does make the hash
- * noticeably faster for short strings (like English words).
- */
-#ifndef VALGRIND
-
- switch(length)
- {
- case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
- case 11: c+=k[2]&0xffffff00; b+=k[1]; a+=k[0]; break;
- case 10: c+=k[2]&0xffff0000; b+=k[1]; a+=k[0]; break;
- case 9 : c+=k[2]&0xff000000; b+=k[1]; a+=k[0]; break;
- case 8 : b+=k[1]; a+=k[0]; break;
- case 7 : b+=k[1]&0xffffff00; a+=k[0]; break;
- case 6 : b+=k[1]&0xffff0000; a+=k[0]; break;
- case 5 : b+=k[1]&0xff000000; a+=k[0]; break;
- case 4 : a+=k[0]; break;
- case 3 : a+=k[0]&0xffffff00; break;
- case 2 : a+=k[0]&0xffff0000; break;
- case 1 : a+=k[0]&0xff000000; break;
- case 0 : return c; /* zero length strings require no mixing */
- }
-
-#else /* make valgrind happy */
-
- {
- const uint8_t *k8 = (const uint8_t *)k;
- switch(length) /* all the case statements fall through */
- {
- case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
- case 11: c+=((uint32_t)k8[10])<<8; /* fall through */
- case 10: c+=((uint32_t)k8[9])<<16; /* fall through */
- case 9 : c+=((uint32_t)k8[8])<<24; /* fall through */
- case 8 : b+=k[1]; a+=k[0]; break;
- case 7 : b+=((uint32_t)k8[6])<<8; /* fall through */
- case 6 : b+=((uint32_t)k8[5])<<16; /* fall through */
- case 5 : b+=((uint32_t)k8[4])<<24; /* fall through */
- case 4 : a+=k[0]; break;
- case 3 : a+=((uint32_t)k8[2])<<8; /* fall through */
- case 2 : a+=((uint32_t)k8[1])<<16; /* fall through */
- case 1 : a+=((uint32_t)k8[0])<<24; break;
- case 0 : return c;
- }
- }
-
-#endif /* !VALGRIND */
-
- } else { /* need to read the key one byte at a time */
- const uint8_t *k = (const uint8_t *)key;
-
- /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
- while (length > 12)
- {
- a += ((uint32_t)k[0])<<24;
- a += ((uint32_t)k[1])<<16;
- a += ((uint32_t)k[2])<<8;
- a += ((uint32_t)k[3]);
- b += ((uint32_t)k[4])<<24;
- b += ((uint32_t)k[5])<<16;
- b += ((uint32_t)k[6])<<8;
- b += ((uint32_t)k[7]);
- c += ((uint32_t)k[8])<<24;
- c += ((uint32_t)k[9])<<16;
- c += ((uint32_t)k[10])<<8;
- c += ((uint32_t)k[11]);
- mix(a,b,c);
- length -= 12;
- k += 12;
- }
-
- /*-------------------------------- last block: affect all 32 bits of (c) */
- switch(length) /* all the case statements fall through */
- {
- case 12: c+=k[11];
- case 11: c+=((uint32_t)k[10])<<8;
- case 10: c+=((uint32_t)k[9])<<16;
- case 9 : c+=((uint32_t)k[8])<<24;
- case 8 : b+=k[7];
- case 7 : b+=((uint32_t)k[6])<<8;
- case 6 : b+=((uint32_t)k[5])<<16;
- case 5 : b+=((uint32_t)k[4])<<24;
- case 4 : a+=k[3];
- case 3 : a+=((uint32_t)k[2])<<8;
- case 2 : a+=((uint32_t)k[1])<<16;
- case 1 : a+=((uint32_t)k[0])<<24;
- break;
- case 0 : return c;
- }
- }
-
- final(a,b,c);
- return c;
-}
-
-
-#ifdef SELF_TEST
-
-/* used for timings */
-void driver1()
-{
- uint8_t buf[256];
- uint32_t i;
- uint32_t h=0;
- time_t a,z;
-
- time(&a);
- for (i=0; i<256; ++i) buf[i] = 'x';
- for (i=0; i<1; ++i)
- {
- h = hashlittle(&buf[0],1,h);
- }
- time(&z);
- if (z-a > 0) printf("time %d %.8x\n", z-a, h);
-}
-
-/* check that every input bit changes every output bit half the time */
-#define HASHSTATE 1
-#define HASHLEN 1
-#define MAXPAIR 60
-#define MAXLEN 70
-void driver2()
-{
- uint8_t qa[MAXLEN+1], qb[MAXLEN+2], *a = &qa[0], *b = &qb[1];
- uint32_t c[HASHSTATE], d[HASHSTATE], i=0, j=0, k, l, m=0, z;
- uint32_t e[HASHSTATE],f[HASHSTATE],g[HASHSTATE],h[HASHSTATE];
- uint32_t x[HASHSTATE],y[HASHSTATE];
- uint32_t hlen;
-
- printf("No more than %d trials should ever be needed \n",MAXPAIR/2);
- for (hlen=0; hlen < MAXLEN; ++hlen)
- {
- z=0;
- for (i=0; i<hlen; ++i) /*----------------------- for each input byte, */
- {
- for (j=0; j<8; ++j) /*------------------------ for each input bit, */
- {
- for (m=1; m<8; ++m) /*------------ for serveral possible initvals, */
- {
- for (l=0; l<HASHSTATE; ++l)
- e[l]=f[l]=g[l]=h[l]=x[l]=y[l]=~((uint32_t)0);
-
- /*---- check that every output bit is affected by that input bit */
- for (k=0; k<MAXPAIR; k+=2)
- {
- uint32_t finished=1;
- /* keys have one bit different */
- for (l=0; l<hlen+1; ++l) {a[l] = b[l] = (uint8_t)0;}
- /* have a and b be two keys differing in only one bit */
- a[i] ^= (k<<j);
- a[i] ^= (k>>(8-j));
- c[0] = hashlittle(a, hlen, m);
- b[i] ^= ((k+1)<<j);
- b[i] ^= ((k+1)>>(8-j));
- d[0] = hashlittle(b, hlen, m);
- /* check every bit is 1, 0, set, and not set at least once */
- for (l=0; l<HASHSTATE; ++l)
- {
- e[l] &= (c[l]^d[l]);
- f[l] &= ~(c[l]^d[l]);
- g[l] &= c[l];
- h[l] &= ~c[l];
- x[l] &= d[l];
- y[l] &= ~d[l];
- if (e[l]|f[l]|g[l]|h[l]|x[l]|y[l]) finished=0;
- }
- if (finished) break;
- }
- if (k>z) z=k;
- if (k==MAXPAIR)
- {
- printf("Some bit didn't change: ");
- printf("%.8x %.8x %.8x %.8x %.8x %.8x ",
- e[0],f[0],g[0],h[0],x[0],y[0]);
- printf("i %d j %d m %d len %d\n", i, j, m, hlen);
- }
- if (z==MAXPAIR) goto done;
- }
- }
- }
- done:
- if (z < MAXPAIR)
- {
- printf("Mix success %2d bytes %2d initvals ",i,m);
- printf("required %d trials\n", z/2);
- }
- }
- printf("\n");
-}
-
-/* Check for reading beyond the end of the buffer and alignment problems */
-void driver3()
-{
- uint8_t buf[MAXLEN+20], *b;
- uint32_t len;
- uint8_t q[] = "This is the time for all good men to come to the aid of their country...";
- uint32_t h;
- uint8_t qq[] = "xThis is the time for all good men to come to the aid of their country...";
- uint32_t i;
- uint8_t qqq[] = "xxThis is the time for all good men to come to the aid of their country...";
- uint32_t j;
- uint8_t qqqq[] = "xxxThis is the time for all good men to come to the aid of their country...";
- uint32_t ref,x,y;
- uint8_t *p;
-
- printf("Endianness. These lines should all be the same (for values filled in):\n");
- printf("%.8x %.8x %.8x\n",
- hashword((const uint32_t *)q, (sizeof(q)-1)/4, 13),
- hashword((const uint32_t *)q, (sizeof(q)-5)/4, 13),
- hashword((const uint32_t *)q, (sizeof(q)-9)/4, 13));
- p = q;
- printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
- hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13),
- hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13),
- hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13),
- hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13),
- hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13),
- hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13));
- p = &qq[1];
- printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
- hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13),
- hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13),
- hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13),
- hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13),
- hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13),
- hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13));
- p = &qqq[2];
- printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
- hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13),
- hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13),
- hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13),
- hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13),
- hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13),
- hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13));
- p = &qqqq[3];
- printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
- hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13),
- hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13),
- hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13),
- hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13),
- hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13),
- hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13));
- printf("\n");
-
- /* check that hashlittle2 and hashlittle produce the same results */
- i=47; j=0;
- hashlittle2(q, sizeof(q), &i, &j);
- if (hashlittle(q, sizeof(q), 47) != i)
- printf("hashlittle2 and hashlittle mismatch\n");
-
- /* check that hashword2 and hashword produce the same results */
- len = 0xdeadbeef;
- i=47, j=0;
- hashword2(&len, 1, &i, &j);
- if (hashword(&len, 1, 47) != i)
- printf("hashword2 and hashword mismatch %x %x\n",
- i, hashword(&len, 1, 47));
-
- /* check hashlittle doesn't read before or after the ends of the string */
- for (h=0, b=buf+1; h<8; ++h, ++b)
- {
- for (i=0; i<MAXLEN; ++i)
- {
- len = i;
- for (j=0; j<i; ++j) *(b+j)=0;
-
- /* these should all be equal */
- ref = hashlittle(b, len, (uint32_t)1);
- *(b+i)=(uint8_t)~0;
- *(b-1)=(uint8_t)~0;
- x = hashlittle(b, len, (uint32_t)1);
- y = hashlittle(b, len, (uint32_t)1);
- if ((ref != x) || (ref != y))
- {
- printf("alignment error: %.8x %.8x %.8x %d %d\n",ref,x,y,
- h, i);
- }
- }
- }
-}
-
-/* check for problems with nulls */
- void driver4()
-{
- uint8_t buf[1];
- uint32_t h,i,state[HASHSTATE];
-
-
- buf[0] = ~0;
- for (i=0; i<HASHSTATE; ++i) state[i] = 1;
- printf("These should all be different\n");
- for (i=0, h=0; i<8; ++i)
- {
- h = hashlittle(buf, 0, h);
- printf("%2ld 0-byte strings, hash is %.8x\n", i, h);
- }
-}
-
-void driver5()
-{
- uint32_t b,c;
- b=0, c=0, hashlittle2("", 0, &c, &b);
- printf("hash is %.8lx %.8lx\n", c, b); /* deadbeef deadbeef */
- b=0xdeadbeef, c=0, hashlittle2("", 0, &c, &b);
- printf("hash is %.8lx %.8lx\n", c, b); /* bd5b7dde deadbeef */
- b=0xdeadbeef, c=0xdeadbeef, hashlittle2("", 0, &c, &b);
- printf("hash is %.8lx %.8lx\n", c, b); /* 9c093ccd bd5b7dde */
- b=0, c=0, hashlittle2("Four score and seven years ago", 30, &c, &b);
- printf("hash is %.8lx %.8lx\n", c, b); /* 17770551 ce7226e6 */
- b=1, c=0, hashlittle2("Four score and seven years ago", 30, &c, &b);
- printf("hash is %.8lx %.8lx\n", c, b); /* e3607cae bd371de4 */
- b=0, c=1, hashlittle2("Four score and seven years ago", 30, &c, &b);
- printf("hash is %.8lx %.8lx\n", c, b); /* cd628161 6cbea4b3 */
- c = hashlittle("Four score and seven years ago", 30, 0);
- printf("hash is %.8lx\n", c); /* 17770551 */
- c = hashlittle("Four score and seven years ago", 30, 1);
- printf("hash is %.8lx\n", c); /* cd628161 */
-}
-
-
-int main()
-{
- driver1(); /* test that the key is hashed: used for timings */
- driver2(); /* test that whole key is hashed thoroughly */
- driver3(); /* test that nothing but the key is hashed */
- driver4(); /* test hashing multiple buffers (all buffers are null) */
- driver5(); /* test the hash against known vectors */
- return 1;
-}
-
-#endif /* SELF_TEST */
diff --git a/src/journal/lookup3.h b/src/journal/lookup3.h
deleted file mode 100644
index 502b42c209..0000000000
--- a/src/journal/lookup3.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-#include <inttypes.h>
-#include <sys/types.h>
-
-uint32_t jenkins_hashword(const uint32_t *k, size_t length, uint32_t initval);
-void jenkins_hashword2(const uint32_t *k, size_t length, uint32_t *pc, uint32_t *pb);
-
-uint32_t jenkins_hashlittle(const void *key, size_t length, uint32_t initval);
-void jenkins_hashlittle2(const void *key, size_t length, uint32_t *pc, uint32_t *pb);
-
-uint32_t jenkins_hashbig(const void *key, size_t length, uint32_t initval);
-
-static inline uint64_t hash64(const void *data, size_t length) {
- uint32_t a = 0, b = 0;
-
- jenkins_hashlittle2(data, length, &a, &b);
-
- return ((uint64_t) a << 32ULL) | (uint64_t) b;
-}
diff --git a/src/journal/mmap-cache.c b/src/journal/mmap-cache.c
deleted file mode 100644
index 251aefe121..0000000000
--- a/src/journal/mmap-cache.c
+++ /dev/null
@@ -1,577 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <stdlib.h>
-#include <sys/mman.h>
-#include <string.h>
-
-#include "hashmap.h"
-#include "list.h"
-#include "log.h"
-#include "util.h"
-#include "macro.h"
-#include "mmap-cache.h"
-
-typedef struct Window Window;
-typedef struct Context Context;
-typedef struct FileDescriptor FileDescriptor;
-
-struct Window {
- MMapCache *cache;
-
- bool keep_always;
- bool in_unused;
-
- void *ptr;
- uint64_t offset;
- int prot;
- size_t size;
-
- FileDescriptor *fd;
-
- LIST_FIELDS(Window, by_fd);
- LIST_FIELDS(Window, unused);
-
- LIST_HEAD(Context, contexts);
-};
-
-struct Context {
- MMapCache *cache;
- unsigned id;
- Window *window;
-
- LIST_FIELDS(Context, by_window);
-};
-
-struct FileDescriptor {
- MMapCache *cache;
- int fd;
- LIST_HEAD(Window, windows);
-};
-
-struct MMapCache {
- int n_ref;
-
- Hashmap *fds;
- Hashmap *contexts;
-
- unsigned n_windows;
-
- LIST_HEAD(Window, unused);
- Window *last_unused;
-};
-
-#define WINDOWS_MIN 64
-#define WINDOW_SIZE (8ULL*1024ULL*1024ULL)
-
-MMapCache* mmap_cache_new(void) {
- MMapCache *m;
-
- m = new0(MMapCache, 1);
- if (!m)
- return NULL;
-
- m->n_ref = 1;
- return m;
-}
-
-MMapCache* mmap_cache_ref(MMapCache *m) {
- assert(m);
- assert(m->n_ref > 0);
-
- m->n_ref ++;
- return m;
-}
-
-static void window_unlink(Window *w) {
- Context *c;
-
- assert(w);
-
- if (w->ptr)
- munmap(w->ptr, w->size);
-
- if (w->fd)
- LIST_REMOVE(Window, by_fd, w->fd->windows, w);
-
- if (w->in_unused) {
- if (w->cache->last_unused == w)
- w->cache->last_unused = w->unused_prev;
-
- LIST_REMOVE(Window, unused, w->cache->unused, w);
- }
-
- LIST_FOREACH(by_window, c, w->contexts) {
- assert(c->window == w);
- c->window = NULL;
- }
-}
-
-static void window_free(Window *w) {
- assert(w);
-
- window_unlink(w);
- w->cache->n_windows--;
- free(w);
-}
-
-static bool window_matches(Window *w, int fd, int prot, uint64_t offset, size_t size) {
- assert(w);
- assert(fd >= 0);
- assert(size > 0);
-
- return
- w->fd &&
- fd == w->fd->fd &&
- prot == w->prot &&
- offset >= w->offset &&
- offset + size <= w->offset + w->size;
-}
-
-static Window *window_add(MMapCache *m) {
- Window *w;
-
- assert(m);
-
- if (!m->last_unused || m->n_windows <= WINDOWS_MIN) {
-
- /* Allocate a new window */
- w = new0(Window, 1);
- if (!w)
- return NULL;
- m->n_windows++;
- } else {
-
- /* Reuse an existing one */
- w = m->last_unused;
- window_unlink(w);
- zero(*w);
- }
-
- w->cache = m;
- return w;
-}
-
-static void context_detach_window(Context *c) {
- Window *w;
-
- assert(c);
-
- if (!c->window)
- return;
-
- w = c->window;
- c->window = NULL;
- LIST_REMOVE(Context, by_window, w->contexts, c);
-
- if (!w->contexts && !w->keep_always) {
- /* Not used anymore? */
- LIST_PREPEND(Window, unused, c->cache->unused, w);
- if (!c->cache->last_unused)
- c->cache->last_unused = w;
-
- w->in_unused = true;
- }
-}
-
-static void context_attach_window(Context *c, Window *w) {
- assert(c);
- assert(w);
-
- if (c->window == w)
- return;
-
- context_detach_window(c);
-
- if (w->in_unused) {
- /* Used again? */
- LIST_REMOVE(Window, unused, c->cache->unused, w);
- if (c->cache->last_unused == w)
- c->cache->last_unused = w->unused_prev;
-
- w->in_unused = false;
- }
-
- c->window = w;
- LIST_PREPEND(Context, by_window, w->contexts, c);
-}
-
-static Context *context_add(MMapCache *m, unsigned id) {
- Context *c;
- int r;
-
- assert(m);
-
- c = hashmap_get(m->contexts, UINT_TO_PTR(id + 1));
- if (c)
- return c;
-
- r = hashmap_ensure_allocated(&m->contexts, trivial_hash_func, trivial_compare_func);
- if (r < 0)
- return NULL;
-
- c = new0(Context, 1);
- if (!c)
- return NULL;
-
- c->cache = m;
- c->id = id;
-
- r = hashmap_put(m->contexts, UINT_TO_PTR(id + 1), c);
- if (r < 0) {
- free(c);
- return NULL;
- }
-
- return c;
-}
-
-static void context_free(Context *c) {
- assert(c);
-
- context_detach_window(c);
-
- if (c->cache)
- assert_se(hashmap_remove(c->cache->contexts, UINT_TO_PTR(c->id + 1)));
-
- free(c);
-}
-
-static void fd_free(FileDescriptor *f) {
- assert(f);
-
- while (f->windows)
- window_free(f->windows);
-
- if (f->cache)
- assert_se(hashmap_remove(f->cache->fds, INT_TO_PTR(f->fd + 1)));
-
- free(f);
-}
-
-static FileDescriptor* fd_add(MMapCache *m, int fd) {
- FileDescriptor *f;
- int r;
-
- assert(m);
- assert(fd >= 0);
-
- f = hashmap_get(m->fds, INT_TO_PTR(fd + 1));
- if (f)
- return f;
-
- r = hashmap_ensure_allocated(&m->fds, trivial_hash_func, trivial_compare_func);
- if (r < 0)
- return NULL;
-
- f = new0(FileDescriptor, 1);
- if (!f)
- return NULL;
-
- f->cache = m;
- f->fd = fd;
-
- r = hashmap_put(m->fds, UINT_TO_PTR(fd + 1), f);
- if (r < 0) {
- free(f);
- return NULL;
- }
-
- return f;
-}
-
-static void mmap_cache_free(MMapCache *m) {
- Context *c;
- FileDescriptor *f;
-
- assert(m);
-
- while ((c = hashmap_first(m->contexts)))
- context_free(c);
-
- while ((f = hashmap_first(m->fds)))
- fd_free(f);
-
- while (m->unused)
- window_free(m->unused);
-
- free(m);
-}
-
-MMapCache* mmap_cache_unref(MMapCache *m) {
- assert(m);
- assert(m->n_ref > 0);
-
- m->n_ref --;
- if (m->n_ref == 0)
- mmap_cache_free(m);
-
- return NULL;
-}
-
-static int make_room(MMapCache *m) {
- assert(m);
-
- if (!m->last_unused)
- return 0;
-
- window_free(m->last_unused);
- return 1;
-}
-
-static int try_context(
- MMapCache *m,
- int fd,
- int prot,
- unsigned context,
- bool keep_always,
- uint64_t offset,
- size_t size,
- void **ret) {
-
- Context *c;
-
- assert(m);
- assert(m->n_ref > 0);
- assert(fd >= 0);
- assert(size > 0);
- assert(ret);
-
- c = hashmap_get(m->contexts, UINT_TO_PTR(context+1));
- if (!c)
- return 0;
-
- assert(c->id == context);
-
- if (!c->window)
- return 0;
-
- if (!window_matches(c->window, fd, prot, offset, size)) {
-
- /* Drop the reference to the window, since it's unnecessary now */
- context_detach_window(c);
- return 0;
- }
-
- c->window->keep_always = c->window->keep_always || keep_always;
-
- *ret = (uint8_t*) c->window->ptr + (offset - c->window->offset);
- return 1;
-}
-
-static int find_mmap(
- MMapCache *m,
- int fd,
- int prot,
- unsigned context,
- bool keep_always,
- uint64_t offset,
- size_t size,
- void **ret) {
-
- FileDescriptor *f;
- Window *w;
- Context *c;
-
- assert(m);
- assert(m->n_ref > 0);
- assert(fd >= 0);
- assert(size > 0);
- assert(ret);
-
- f = hashmap_get(m->fds, INT_TO_PTR(fd + 1));
- if (!f)
- return 0;
-
- assert(f->fd == fd);
-
- LIST_FOREACH(by_fd, w, f->windows)
- if (window_matches(w, fd, prot, offset, size))
- break;
-
- if (!w)
- return 0;
-
- c = context_add(m, context);
- if (!c)
- return -ENOMEM;
-
- context_attach_window(c, w);
- w->keep_always = w->keep_always || keep_always;
-
- *ret = (uint8_t*) w->ptr + (offset - w->offset);
- return 1;
-}
-
-static int add_mmap(
- MMapCache *m,
- int fd,
- int prot,
- unsigned context,
- bool keep_always,
- uint64_t offset,
- size_t size,
- struct stat *st,
- void **ret) {
-
- uint64_t woffset, wsize;
- Context *c;
- FileDescriptor *f;
- Window *w;
- void *d;
- int r;
-
- assert(m);
- assert(m->n_ref > 0);
- assert(fd >= 0);
- assert(size > 0);
- assert(ret);
-
- woffset = offset & ~((uint64_t) page_size() - 1ULL);
- wsize = size + (offset - woffset);
- wsize = PAGE_ALIGN(wsize);
-
- if (wsize < WINDOW_SIZE) {
- uint64_t delta;
-
- delta = PAGE_ALIGN((WINDOW_SIZE - wsize) / 2);
-
- if (delta > offset)
- woffset = 0;
- else
- woffset -= delta;
-
- wsize = WINDOW_SIZE;
- }
-
- if (st) {
- /* Memory maps that are larger then the files
- underneath have undefined behavior. Hence, clamp
- things to the file size if we know it */
-
- if (woffset >= (uint64_t) st->st_size)
- return -EADDRNOTAVAIL;
-
- if (woffset + wsize > (uint64_t) st->st_size)
- wsize = PAGE_ALIGN(st->st_size - woffset);
- }
-
- for (;;) {
- d = mmap(NULL, wsize, prot, MAP_SHARED, fd, woffset);
- if (d != MAP_FAILED)
- break;
- if (errno != ENOMEM)
- return -errno;
-
- r = make_room(m);
- if (r < 0)
- return r;
- if (r == 0)
- return -ENOMEM;
- }
-
- c = context_add(m, context);
- if (!c)
- return -ENOMEM;
-
- f = fd_add(m, fd);
- if (!f)
- return -ENOMEM;
-
- w = window_add(m);
- if (!w)
- return -ENOMEM;
-
- w->keep_always = keep_always;
- w->ptr = d;
- w->offset = woffset;
- w->prot = prot;
- w->size = wsize;
- w->fd = f;
-
- LIST_PREPEND(Window, by_fd, f->windows, w);
-
- context_detach_window(c);
- c->window = w;
- LIST_PREPEND(Context, by_window, w->contexts, c);
-
- *ret = (uint8_t*) w->ptr + (offset - w->offset);
- return 1;
-}
-
-int mmap_cache_get(
- MMapCache *m,
- int fd,
- int prot,
- unsigned context,
- bool keep_always,
- uint64_t offset,
- size_t size,
- struct stat *st,
- void **ret) {
-
- int r;
-
- assert(m);
- assert(m->n_ref > 0);
- assert(fd >= 0);
- assert(size > 0);
- assert(ret);
-
- /* Check whether the current context is the right one already */
- r = try_context(m, fd, prot, context, keep_always, offset, size, ret);
- if (r != 0)
- return r;
-
- /* Search for a matching mmap */
- r = find_mmap(m, fd, prot, context, keep_always, offset, size, ret);
- if (r != 0)
- return r;
-
- /* Create a new mmap */
- return add_mmap(m, fd, prot, context, keep_always, offset, size, st, ret);
-}
-
-void mmap_cache_close_fd(MMapCache *m, int fd) {
- FileDescriptor *f;
-
- assert(m);
- assert(fd >= 0);
-
- f = hashmap_get(m->fds, INT_TO_PTR(fd + 1));
- if (!f)
- return;
-
- fd_free(f);
-}
-
-void mmap_cache_close_context(MMapCache *m, unsigned context) {
- Context *c;
-
- assert(m);
-
- c = hashmap_get(m->contexts, UINT_TO_PTR(context + 1));
- if (!c)
- return;
-
- context_free(c);
-}
diff --git a/src/journal/mmap-cache.h b/src/journal/mmap-cache.h
deleted file mode 100644
index 0c42fb88e6..0000000000
--- a/src/journal/mmap-cache.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <inttypes.h>
-#include <stdbool.h>
-#include <sys/stat.h>
-
-typedef struct MMapCache MMapCache;
-
-MMapCache* mmap_cache_new(void);
-MMapCache* mmap_cache_ref(MMapCache *m);
-MMapCache* mmap_cache_unref(MMapCache *m);
-
-int mmap_cache_get(MMapCache *m, int fd, int prot, unsigned context, bool keep_always, uint64_t offset, size_t size, struct stat *st, void **ret);
-void mmap_cache_close_fd(MMapCache *m, int fd);
-void mmap_cache_close_context(MMapCache *m, unsigned context);
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
deleted file mode 100644
index a346691e21..0000000000
--- a/src/journal/sd-journal.c
+++ /dev/null
@@ -1,2391 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <errno.h>
-#include <fcntl.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <sys/inotify.h>
-#include <sys/poll.h>
-#include <sys/vfs.h>
-#include <linux/magic.h>
-
-#include "sd-journal.h"
-#include "journal-def.h"
-#include "journal-file.h"
-#include "hashmap.h"
-#include "list.h"
-#include "path-util.h"
-#include "lookup3.h"
-#include "compress.h"
-#include "journal-internal.h"
-#include "missing.h"
-
-#define JOURNAL_FILES_MAX 1024
-
-#define JOURNAL_FILES_RECHECK_USEC (2 * USEC_PER_SEC)
-
-static void detach_location(sd_journal *j) {
- Iterator i;
- JournalFile *f;
-
- assert(j);
-
- j->current_file = NULL;
- j->current_field = 0;
-
- HASHMAP_FOREACH(f, j->files, i)
- f->current_offset = 0;
-}
-
-static void reset_location(sd_journal *j) {
- assert(j);
-
- detach_location(j);
- zero(j->current_location);
-}
-
-static void init_location(Location *l, LocationType type, JournalFile *f, Object *o) {
- assert(l);
- assert(type == LOCATION_DISCRETE || type == LOCATION_SEEK);
- assert(f);
- assert(o->object.type == OBJECT_ENTRY);
-
- l->type = type;
- l->seqnum = le64toh(o->entry.seqnum);
- l->seqnum_id = f->header->seqnum_id;
- l->realtime = le64toh(o->entry.realtime);
- l->monotonic = le64toh(o->entry.monotonic);
- l->boot_id = o->entry.boot_id;
- l->xor_hash = le64toh(o->entry.xor_hash);
-
- l->seqnum_set = l->realtime_set = l->monotonic_set = l->xor_hash_set = true;
-}
-
-static void set_location(sd_journal *j, LocationType type, JournalFile *f, Object *o, uint64_t offset) {
- assert(j);
- assert(type == LOCATION_DISCRETE || type == LOCATION_SEEK);
- assert(f);
- assert(o);
-
- init_location(&j->current_location, type, f, o);
-
- j->current_file = f;
- j->current_field = 0;
-
- f->current_offset = offset;
-}
-
-static int match_is_valid(const void *data, size_t size) {
- const char *b, *p;
-
- assert(data);
-
- if (size < 2)
- return false;
-
- if (startswith(data, "__"))
- return false;
-
- b = data;
- for (p = b; p < b + size; p++) {
-
- if (*p == '=')
- return p > b;
-
- if (*p == '_')
- continue;
-
- if (*p >= 'A' && *p <= 'Z')
- continue;
-
- if (*p >= '0' && *p <= '9')
- continue;
-
- return false;
- }
-
- return false;
-}
-
-static bool same_field(const void *_a, size_t s, const void *_b, size_t t) {
- const uint8_t *a = _a, *b = _b;
- size_t j;
-
- for (j = 0; j < s && j < t; j++) {
-
- if (a[j] != b[j])
- return false;
-
- if (a[j] == '=')
- return true;
- }
-
- return true;
-}
-
-static Match *match_new(Match *p, MatchType t) {
- Match *m;
-
- m = new0(Match, 1);
- if (!m)
- return NULL;
-
- m->type = t;
-
- if (p) {
- m->parent = p;
- LIST_PREPEND(Match, matches, p->matches, m);
- }
-
- return m;
-}
-
-static void match_free(Match *m) {
- assert(m);
-
- while (m->matches)
- match_free(m->matches);
-
- if (m->parent)
- LIST_REMOVE(Match, matches, m->parent->matches, m);
-
- free(m->data);
- free(m);
-}
-
-static void match_free_if_empty(Match *m) {
- assert(m);
-
- if (m->matches)
- return;
-
- match_free(m);
-}
-
-_public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size) {
- Match *l2, *l3, *add_here = NULL, *m;
- le64_t le_hash;
-
- if (!j)
- return -EINVAL;
-
- if (!data)
- return -EINVAL;
-
- if (size == 0)
- size = strlen(data);
-
- if (!match_is_valid(data, size))
- return -EINVAL;
-
- /* level 0: OR term
- * level 1: AND terms
- * level 2: OR terms
- * level 3: concrete matches */
-
- if (!j->level0) {
- j->level0 = match_new(NULL, MATCH_OR_TERM);
- if (!j->level0)
- return -ENOMEM;
- }
-
- if (!j->level1) {
- j->level1 = match_new(j->level0, MATCH_AND_TERM);
- if (!j->level1)
- return -ENOMEM;
- }
-
- assert(j->level0->type == MATCH_OR_TERM);
- assert(j->level1->type == MATCH_AND_TERM);
-
- le_hash = htole64(hash64(data, size));
-
- LIST_FOREACH(matches, l2, j->level1->matches) {
- assert(l2->type == MATCH_OR_TERM);
-
- LIST_FOREACH(matches, l3, l2->matches) {
- assert(l3->type == MATCH_DISCRETE);
-
- /* Exactly the same match already? Then ignore
- * this addition */
- if (l3->le_hash == le_hash &&
- l3->size == size &&
- memcmp(l3->data, data, size) == 0)
- return 0;
-
- /* Same field? Then let's add this to this OR term */
- if (same_field(data, size, l3->data, l3->size)) {
- add_here = l2;
- break;
- }
- }
-
- if (add_here)
- break;
- }
-
- if (!add_here) {
- add_here = match_new(j->level1, MATCH_OR_TERM);
- if (!add_here)
- goto fail;
- }
-
- m = match_new(add_here, MATCH_DISCRETE);
- if (!m)
- goto fail;
-
- m->le_hash = le_hash;
- m->size = size;
- m->data = memdup(data, size);
- if (!m->data)
- goto fail;
-
- detach_location(j);
-
- return 0;
-
-fail:
- if (add_here)
- match_free_if_empty(add_here);
-
- if (j->level1)
- match_free_if_empty(j->level1);
-
- if (j->level0)
- match_free_if_empty(j->level0);
-
- return -ENOMEM;
-}
-
-_public_ int sd_journal_add_disjunction(sd_journal *j) {
- Match *m;
-
- assert(j);
-
- if (!j->level0)
- return 0;
-
- if (!j->level1)
- return 0;
-
- if (!j->level1->matches)
- return 0;
-
- m = match_new(j->level0, MATCH_AND_TERM);
- if (!m)
- return -ENOMEM;
-
- j->level1 = m;
- return 0;
-}
-
-static char *match_make_string(Match *m) {
- char *p, *r;
- Match *i;
- bool enclose = false;
-
- if (!m)
- return strdup("");
-
- if (m->type == MATCH_DISCRETE)
- return strndup(m->data, m->size);
-
- p = NULL;
- LIST_FOREACH(matches, i, m->matches) {
- char *t, *k;
-
- t = match_make_string(i);
- if (!t) {
- free(p);
- return NULL;
- }
-
- if (p) {
- k = strjoin(p, m->type == MATCH_OR_TERM ? " OR " : " AND ", t, NULL);
- free(p);
- free(t);
-
- if (!k)
- return NULL;
-
- p = k;
-
- enclose = true;
- } else {
- free(p);
- p = t;
- }
- }
-
- if (enclose) {
- r = strjoin("(", p, ")", NULL);
- free(p);
- return r;
- }
-
- return p;
-}
-
-char *journal_make_match_string(sd_journal *j) {
- assert(j);
-
- return match_make_string(j->level0);
-}
-
-_public_ void sd_journal_flush_matches(sd_journal *j) {
-
- if (!j)
- return;
-
- if (j->level0)
- match_free(j->level0);
-
- j->level0 = j->level1 = NULL;
-
- detach_location(j);
-}
-
-static int compare_entry_order(JournalFile *af, Object *_ao,
- JournalFile *bf, uint64_t bp) {
-
- uint64_t a, b;
- Object *ao, *bo;
- int r;
-
- assert(af);
- assert(bf);
- assert(_ao);
-
- /* The mmap cache might invalidate the object from the first
- * file if we look at the one from the second file. Hence
- * temporarily copy the header of the first one, and look at
- * that only. */
- ao = alloca(offsetof(EntryObject, items));
- memcpy(ao, _ao, offsetof(EntryObject, items));
-
- r = journal_file_move_to_object(bf, OBJECT_ENTRY, bp, &bo);
- if (r < 0)
- return strcmp(af->path, bf->path);
-
- /* We operate on two different files here, hence we can access
- * two objects at the same time, which we normally can't.
- *
- * If contents and timestamps match, these entries are
- * identical, even if the seqnum does not match */
-
- if (sd_id128_equal(ao->entry.boot_id, bo->entry.boot_id) &&
- ao->entry.monotonic == bo->entry.monotonic &&
- ao->entry.realtime == bo->entry.realtime &&
- ao->entry.xor_hash == bo->entry.xor_hash)
- return 0;
-
- if (sd_id128_equal(af->header->seqnum_id, bf->header->seqnum_id)) {
-
- /* If this is from the same seqnum source, compare
- * seqnums */
- a = le64toh(ao->entry.seqnum);
- b = le64toh(bo->entry.seqnum);
-
- if (a < b)
- return -1;
- if (a > b)
- return 1;
-
- /* Wow! This is weird, different data but the same
- * seqnums? Something is borked, but let's make the
- * best of it and compare by time. */
- }
-
- if (sd_id128_equal(ao->entry.boot_id, bo->entry.boot_id)) {
-
- /* If the boot id matches compare monotonic time */
- a = le64toh(ao->entry.monotonic);
- b = le64toh(bo->entry.monotonic);
-
- if (a < b)
- return -1;
- if (a > b)
- return 1;
- }
-
- /* Otherwise compare UTC time */
- a = le64toh(ao->entry.realtime);
- b = le64toh(bo->entry.realtime);
-
- if (a < b)
- return -1;
- if (a > b)
- return 1;
-
- /* Finally, compare by contents */
- a = le64toh(ao->entry.xor_hash);
- b = le64toh(bo->entry.xor_hash);
-
- if (a < b)
- return -1;
- if (a > b)
- return 1;
-
- return 0;
-}
-
-static int compare_with_location(JournalFile *af, Object *ao, Location *l) {
- uint64_t a;
-
- assert(af);
- assert(ao);
- assert(l);
- assert(l->type == LOCATION_DISCRETE || l->type == LOCATION_SEEK);
-
- if (l->monotonic_set &&
- sd_id128_equal(ao->entry.boot_id, l->boot_id) &&
- l->realtime_set &&
- le64toh(ao->entry.realtime) == l->realtime &&
- l->xor_hash_set &&
- le64toh(ao->entry.xor_hash) == l->xor_hash)
- return 0;
-
- if (l->seqnum_set &&
- sd_id128_equal(af->header->seqnum_id, l->seqnum_id)) {
-
- a = le64toh(ao->entry.seqnum);
-
- if (a < l->seqnum)
- return -1;
- if (a > l->seqnum)
- return 1;
- }
-
- if (l->monotonic_set &&
- sd_id128_equal(ao->entry.boot_id, l->boot_id)) {
-
- a = le64toh(ao->entry.monotonic);
-
- if (a < l->monotonic)
- return -1;
- if (a > l->monotonic)
- return 1;
- }
-
- if (l->realtime_set) {
-
- a = le64toh(ao->entry.realtime);
-
- if (a < l->realtime)
- return -1;
- if (a > l->realtime)
- return 1;
- }
-
- if (l->xor_hash_set) {
- a = le64toh(ao->entry.xor_hash);
-
- if (a < l->xor_hash)
- return -1;
- if (a > l->xor_hash)
- return 1;
- }
-
- return 0;
-}
-
-static int next_for_match(
- sd_journal *j,
- Match *m,
- JournalFile *f,
- uint64_t after_offset,
- direction_t direction,
- Object **ret,
- uint64_t *offset) {
-
- int r;
- uint64_t np = 0;
- Object *n;
-
- assert(j);
- assert(m);
- assert(f);
-
- if (m->type == MATCH_DISCRETE) {
- uint64_t dp;
-
- r = journal_file_find_data_object_with_hash(f, m->data, m->size, le64toh(m->le_hash), NULL, &dp);
- if (r <= 0)
- return r;
-
- return journal_file_move_to_entry_by_offset_for_data(f, dp, after_offset, direction, ret, offset);
-
- } else if (m->type == MATCH_OR_TERM) {
- Match *i;
-
- /* Find the earliest match beyond after_offset */
-
- LIST_FOREACH(matches, i, m->matches) {
- uint64_t cp;
-
- r = next_for_match(j, i, f, after_offset, direction, NULL, &cp);
- if (r < 0)
- return r;
- else if (r > 0) {
- if (np == 0 || (direction == DIRECTION_DOWN ? np > cp : np < cp))
- np = cp;
- }
- }
-
- } else if (m->type == MATCH_AND_TERM) {
- Match *i;
- bool continue_looking;
-
- /* Always jump to the next matching entry and repeat
- * this until we fine and offset that matches for all
- * matches. */
-
- if (!m->matches)
- return 0;
-
- np = 0;
- do {
- continue_looking = false;
-
- LIST_FOREACH(matches, i, m->matches) {
- uint64_t cp, limit;
-
- if (np == 0)
- limit = after_offset;
- else if (direction == DIRECTION_DOWN)
- limit = MAX(np, after_offset);
- else
- limit = MIN(np, after_offset);
-
- r = next_for_match(j, i, f, limit, direction, NULL, &cp);
- if (r <= 0)
- return r;
-
- if ((direction == DIRECTION_DOWN ? cp >= after_offset : cp <= after_offset) &&
- (np == 0 || (direction == DIRECTION_DOWN ? cp > np : np < cp))) {
- np = cp;
- continue_looking = true;
- }
- }
-
- } while (continue_looking);
- }
-
- if (np == 0)
- return 0;
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY, np, &n);
- if (r < 0)
- return r;
-
- if (ret)
- *ret = n;
- if (offset)
- *offset = np;
-
- return 1;
-}
-
-static int find_location_for_match(
- sd_journal *j,
- Match *m,
- JournalFile *f,
- direction_t direction,
- Object **ret,
- uint64_t *offset) {
-
- int r;
-
- assert(j);
- assert(m);
- assert(f);
-
- if (m->type == MATCH_DISCRETE) {
- uint64_t dp;
-
- r = journal_file_find_data_object_with_hash(f, m->data, m->size, le64toh(m->le_hash), NULL, &dp);
- if (r <= 0)
- return r;
-
- /* FIXME: missing: find by monotonic */
-
- if (j->current_location.type == LOCATION_HEAD)
- return journal_file_next_entry_for_data(f, NULL, 0, dp, DIRECTION_DOWN, ret, offset);
- if (j->current_location.type == LOCATION_TAIL)
- return journal_file_next_entry_for_data(f, NULL, 0, dp, DIRECTION_UP, ret, offset);
- if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id))
- return journal_file_move_to_entry_by_seqnum_for_data(f, dp, j->current_location.seqnum, direction, ret, offset);
- if (j->current_location.monotonic_set) {
- r = journal_file_move_to_entry_by_monotonic_for_data(f, dp, j->current_location.boot_id, j->current_location.monotonic, direction, ret, offset);
- if (r != -ENOENT)
- return r;
- }
- if (j->current_location.realtime_set)
- return journal_file_move_to_entry_by_realtime_for_data(f, dp, j->current_location.realtime, direction, ret, offset);
-
- return journal_file_next_entry_for_data(f, NULL, 0, dp, direction, ret, offset);
-
- } else if (m->type == MATCH_OR_TERM) {
- uint64_t np = 0;
- Object *n;
- Match *i;
-
- /* Find the earliest match */
-
- LIST_FOREACH(matches, i, m->matches) {
- uint64_t cp;
-
- r = find_location_for_match(j, i, f, direction, NULL, &cp);
- if (r < 0)
- return r;
- else if (r > 0) {
- if (np == 0 || (direction == DIRECTION_DOWN ? np > cp : np < cp))
- np = cp;
- }
- }
-
- if (np == 0)
- return 0;
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY, np, &n);
- if (r < 0)
- return r;
-
- if (ret)
- *ret = n;
- if (offset)
- *offset = np;
-
- return 1;
-
- } else {
- Match *i;
- uint64_t np = 0;
-
- assert(m->type == MATCH_AND_TERM);
-
- /* First jump to the last match, and then find the
- * next one where all matches match */
-
- if (!m->matches)
- return 0;
-
- LIST_FOREACH(matches, i, m->matches) {
- uint64_t cp;
-
- r = find_location_for_match(j, i, f, direction, NULL, &cp);
- if (r <= 0)
- return r;
-
- if (np == 0 || (direction == DIRECTION_DOWN ? np < cp : np > cp))
- np = cp;
- }
-
- return next_for_match(j, m, f, np, direction, ret, offset);
- }
-}
-
-static int find_location_with_matches(
- sd_journal *j,
- JournalFile *f,
- direction_t direction,
- Object **ret,
- uint64_t *offset) {
-
- int r;
-
- assert(j);
- assert(f);
- assert(ret);
- assert(offset);
-
- if (!j->level0) {
- /* No matches is simple */
-
- if (j->current_location.type == LOCATION_HEAD)
- return journal_file_next_entry(f, NULL, 0, DIRECTION_DOWN, ret, offset);
- if (j->current_location.type == LOCATION_TAIL)
- return journal_file_next_entry(f, NULL, 0, DIRECTION_UP, ret, offset);
- if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id))
- return journal_file_move_to_entry_by_seqnum(f, j->current_location.seqnum, direction, ret, offset);
- if (j->current_location.monotonic_set) {
- r = journal_file_move_to_entry_by_monotonic(f, j->current_location.boot_id, j->current_location.monotonic, direction, ret, offset);
- if (r != -ENOENT)
- return r;
- }
- if (j->current_location.realtime_set)
- return journal_file_move_to_entry_by_realtime(f, j->current_location.realtime, direction, ret, offset);
-
- return journal_file_next_entry(f, NULL, 0, direction, ret, offset);
- } else
- return find_location_for_match(j, j->level0, f, direction, ret, offset);
-}
-
-static int next_with_matches(
- sd_journal *j,
- JournalFile *f,
- direction_t direction,
- Object **ret,
- uint64_t *offset) {
-
- Object *c;
- uint64_t cp;
-
- assert(j);
- assert(f);
- assert(ret);
- assert(offset);
-
- c = *ret;
- cp = *offset;
-
- /* No matches is easy. We simple advance the file
- * pointer by one. */
- if (!j->level0)
- return journal_file_next_entry(f, c, cp, direction, ret, offset);
-
- /* If we have a match then we look for the next matching entry
- * with an offset at least one step larger */
- return next_for_match(j, j->level0, f, direction == DIRECTION_DOWN ? cp+1 : cp-1, direction, ret, offset);
-}
-
-static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direction, Object **ret, uint64_t *offset) {
- Object *c;
- uint64_t cp;
- int r;
-
- assert(j);
- assert(f);
-
- if (f->current_offset > 0) {
- cp = f->current_offset;
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY, cp, &c);
- if (r < 0)
- return r;
-
- r = next_with_matches(j, f, direction, &c, &cp);
- if (r <= 0)
- return r;
- } else {
- r = find_location_with_matches(j, f, direction, &c, &cp);
- if (r <= 0)
- return r;
- }
-
- /* OK, we found the spot, now let's advance until to an entry
- * that is actually different from what we were previously
- * looking at. This is necessary to handle entries which exist
- * in two (or more) journal files, and which shall all be
- * suppressed but one. */
-
- for (;;) {
- bool found;
-
- if (j->current_location.type == LOCATION_DISCRETE) {
- int k;
-
- k = compare_with_location(f, c, &j->current_location);
- if (direction == DIRECTION_DOWN)
- found = k > 0;
- else
- found = k < 0;
- } else
- found = true;
-
- if (found) {
- if (ret)
- *ret = c;
- if (offset)
- *offset = cp;
- return 1;
- }
-
- r = next_with_matches(j, f, direction, &c, &cp);
- if (r <= 0)
- return r;
- }
-}
-
-static int real_journal_next(sd_journal *j, direction_t direction) {
- JournalFile *f, *new_file = NULL;
- uint64_t new_offset = 0;
- Object *o;
- uint64_t p;
- Iterator i;
- int r;
-
- if (!j)
- return -EINVAL;
-
- HASHMAP_FOREACH(f, j->files, i) {
- bool found;
-
- r = next_beyond_location(j, f, direction, &o, &p);
- if (r < 0) {
- log_debug("Can't iterate through %s, ignoring: %s", f->path, strerror(-r));
- continue;
- } else if (r == 0)
- continue;
-
- if (!new_file)
- found = true;
- else {
- int k;
-
- k = compare_entry_order(f, o, new_file, new_offset);
-
- if (direction == DIRECTION_DOWN)
- found = k < 0;
- else
- found = k > 0;
- }
-
- if (found) {
- new_file = f;
- new_offset = p;
- }
- }
-
- if (!new_file)
- return 0;
-
- r = journal_file_move_to_object(new_file, OBJECT_ENTRY, new_offset, &o);
- if (r < 0)
- return r;
-
- set_location(j, LOCATION_DISCRETE, new_file, o, new_offset);
-
- return 1;
-}
-
-_public_ int sd_journal_next(sd_journal *j) {
- return real_journal_next(j, DIRECTION_DOWN);
-}
-
-_public_ int sd_journal_previous(sd_journal *j) {
- return real_journal_next(j, DIRECTION_UP);
-}
-
-static int real_journal_next_skip(sd_journal *j, direction_t direction, uint64_t skip) {
- int c = 0, r;
-
- if (!j)
- return -EINVAL;
-
- if (skip == 0) {
- /* If this is not a discrete skip, then at least
- * resolve the current location */
- if (j->current_location.type != LOCATION_DISCRETE)
- return real_journal_next(j, direction);
-
- return 0;
- }
-
- do {
- r = real_journal_next(j, direction);
- if (r < 0)
- return r;
-
- if (r == 0)
- return c;
-
- skip--;
- c++;
- } while (skip > 0);
-
- return c;
-}
-
-_public_ int sd_journal_next_skip(sd_journal *j, uint64_t skip) {
- return real_journal_next_skip(j, DIRECTION_DOWN, skip);
-}
-
-_public_ int sd_journal_previous_skip(sd_journal *j, uint64_t skip) {
- return real_journal_next_skip(j, DIRECTION_UP, skip);
-}
-
-_public_ int sd_journal_get_cursor(sd_journal *j, char **cursor) {
- Object *o;
- int r;
- char bid[33], sid[33];
-
- if (!j)
- return -EINVAL;
- if (!cursor)
- return -EINVAL;
-
- if (!j->current_file || j->current_file->current_offset <= 0)
- return -EADDRNOTAVAIL;
-
- r = journal_file_move_to_object(j->current_file, OBJECT_ENTRY, j->current_file->current_offset, &o);
- if (r < 0)
- return r;
-
- sd_id128_to_string(j->current_file->header->seqnum_id, sid);
- sd_id128_to_string(o->entry.boot_id, bid);
-
- if (asprintf(cursor,
- "s=%s;i=%llx;b=%s;m=%llx;t=%llx;x=%llx",
- sid, (unsigned long long) le64toh(o->entry.seqnum),
- bid, (unsigned long long) le64toh(o->entry.monotonic),
- (unsigned long long) le64toh(o->entry.realtime),
- (unsigned long long) le64toh(o->entry.xor_hash)) < 0)
- return -ENOMEM;
-
- return 1;
-}
-
-_public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) {
- char *w, *state;
- size_t l;
- unsigned long long seqnum, monotonic, realtime, xor_hash;
- bool
- seqnum_id_set = false,
- seqnum_set = false,
- boot_id_set = false,
- monotonic_set = false,
- realtime_set = false,
- xor_hash_set = false;
- sd_id128_t seqnum_id, boot_id;
-
- if (!j)
- return -EINVAL;
- if (isempty(cursor))
- return -EINVAL;
-
- FOREACH_WORD_SEPARATOR(w, l, cursor, ";", state) {
- char *item;
- int k = 0;
-
- if (l < 2 || w[1] != '=')
- return -EINVAL;
-
- item = strndup(w, l);
- if (!item)
- return -ENOMEM;
-
- switch (w[0]) {
-
- case 's':
- seqnum_id_set = true;
- k = sd_id128_from_string(item+2, &seqnum_id);
- break;
-
- case 'i':
- seqnum_set = true;
- if (sscanf(item+2, "%llx", &seqnum) != 1)
- k = -EINVAL;
- break;
-
- case 'b':
- boot_id_set = true;
- k = sd_id128_from_string(item+2, &boot_id);
- break;
-
- case 'm':
- monotonic_set = true;
- if (sscanf(item+2, "%llx", &monotonic) != 1)
- k = -EINVAL;
- break;
-
- case 't':
- realtime_set = true;
- if (sscanf(item+2, "%llx", &realtime) != 1)
- k = -EINVAL;
- break;
-
- case 'x':
- xor_hash_set = true;
- if (sscanf(item+2, "%llx", &xor_hash) != 1)
- k = -EINVAL;
- break;
- }
-
- free(item);
-
- if (k < 0)
- return k;
- }
-
- if ((!seqnum_set || !seqnum_id_set) &&
- (!monotonic_set || !boot_id_set) &&
- !realtime_set)
- return -EINVAL;
-
- reset_location(j);
-
- j->current_location.type = LOCATION_SEEK;
-
- if (realtime_set) {
- j->current_location.realtime = (uint64_t) realtime;
- j->current_location.realtime_set = true;
- }
-
- if (seqnum_set && seqnum_id_set) {
- j->current_location.seqnum = (uint64_t) seqnum;
- j->current_location.seqnum_id = seqnum_id;
- j->current_location.seqnum_set = true;
- }
-
- if (monotonic_set && boot_id_set) {
- j->current_location.monotonic = (uint64_t) monotonic;
- j->current_location.boot_id = boot_id;
- j->current_location.monotonic_set = true;
- }
-
- if (xor_hash_set) {
- j->current_location.xor_hash = (uint64_t) xor_hash;
- j->current_location.xor_hash_set = true;
- }
-
- return 0;
-}
-
-_public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) {
- int r;
- char *w, *state;
- size_t l;
- Object *o;
-
- if (!j)
- return -EINVAL;
- if (isempty(cursor))
- return -EINVAL;
-
- if (!j->current_file || j->current_file->current_offset <= 0)
- return -EADDRNOTAVAIL;
-
- r = journal_file_move_to_object(j->current_file, OBJECT_ENTRY, j->current_file->current_offset, &o);
- if (r < 0)
- return r;
-
- FOREACH_WORD_SEPARATOR(w, l, cursor, ";", state) {
- _cleanup_free_ char *item = NULL;
- sd_id128_t id;
- unsigned long long ll;
- int k = 0;
-
- if (l < 2 || w[1] != '=')
- return -EINVAL;
-
- item = strndup(w, l);
- if (!item)
- return -ENOMEM;
-
- switch (w[0]) {
-
- case 's':
- k = sd_id128_from_string(item+2, &id);
- if (k < 0)
- return k;
- if (!sd_id128_equal(id, j->current_file->header->seqnum_id))
- return 0;
- break;
-
- case 'i':
- if (sscanf(item+2, "%llx", &ll) != 1)
- return -EINVAL;
- if (ll != le64toh(o->entry.seqnum))
- return 0;
- break;
-
- case 'b':
- k = sd_id128_from_string(item+2, &id);
- if (k < 0)
- return k;
- if (!sd_id128_equal(id, o->entry.boot_id))
- return 0;
- break;
-
- case 'm':
- if (sscanf(item+2, "%llx", &ll) != 1)
- return -EINVAL;
- if (ll != le64toh(o->entry.monotonic))
- return 0;
- break;
-
- case 't':
- if (sscanf(item+2, "%llx", &ll) != 1)
- return -EINVAL;
- if (ll != le64toh(o->entry.realtime))
- return 0;
- break;
-
- case 'x':
- if (sscanf(item+2, "%llx", &ll) != 1)
- return -EINVAL;
- if (ll != le64toh(o->entry.xor_hash))
- return 0;
- break;
- }
- }
-
- return 1;
-}
-
-
-_public_ int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t usec) {
- if (!j)
- return -EINVAL;
-
- reset_location(j);
- j->current_location.type = LOCATION_SEEK;
- j->current_location.boot_id = boot_id;
- j->current_location.monotonic = usec;
- j->current_location.monotonic_set = true;
-
- return 0;
-}
-
-_public_ int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec) {
- if (!j)
- return -EINVAL;
-
- reset_location(j);
- j->current_location.type = LOCATION_SEEK;
- j->current_location.realtime = usec;
- j->current_location.realtime_set = true;
-
- return 0;
-}
-
-_public_ int sd_journal_seek_head(sd_journal *j) {
- if (!j)
- return -EINVAL;
-
- reset_location(j);
- j->current_location.type = LOCATION_HEAD;
-
- return 0;
-}
-
-_public_ int sd_journal_seek_tail(sd_journal *j) {
- if (!j)
- return -EINVAL;
-
- reset_location(j);
- j->current_location.type = LOCATION_TAIL;
-
- return 0;
-}
-
-static void check_network(sd_journal *j, int fd) {
- struct statfs sfs;
-
- assert(j);
-
- if (j->on_network)
- return;
-
- if (fstatfs(fd, &sfs) < 0)
- return;
-
- j->on_network =
- sfs.f_type == CIFS_MAGIC_NUMBER ||
- sfs.f_type == CODA_SUPER_MAGIC ||
- sfs.f_type == NCP_SUPER_MAGIC ||
- sfs.f_type == NFS_SUPER_MAGIC ||
- sfs.f_type == SMB_SUPER_MAGIC;
-}
-
-static int add_file(sd_journal *j, const char *prefix, const char *filename) {
- char *path;
- int r;
- JournalFile *f;
-
- assert(j);
- assert(prefix);
- assert(filename);
-
- if ((j->flags & SD_JOURNAL_SYSTEM_ONLY) &&
- !(streq(filename, "system.journal") ||
- streq(filename, "system.journal~") ||
- (startswith(filename, "system@") &&
- (endswith(filename, ".journal") || endswith(filename, ".journal~")))))
- return 0;
-
- path = strjoin(prefix, "/", filename, NULL);
- if (!path)
- return -ENOMEM;
-
- if (hashmap_get(j->files, path)) {
- free(path);
- return 0;
- }
-
- if (hashmap_size(j->files) >= JOURNAL_FILES_MAX) {
- log_debug("Too many open journal files, not adding %s, ignoring.", path);
- free(path);
- return 0;
- }
-
- r = journal_file_open(path, O_RDONLY, 0, false, false, NULL, j->mmap, NULL, &f);
- free(path);
-
- if (r < 0) {
- if (errno == ENOENT)
- return 0;
-
- return r;
- }
-
- /* journal_file_dump(f); */
-
- r = hashmap_put(j->files, f->path, f);
- if (r < 0) {
- journal_file_close(f);
- return r;
- }
-
- check_network(j, f->fd);
-
- j->current_invalidate_counter ++;
-
- log_debug("File %s got added.", f->path);
-
- return 0;
-}
-
-static int remove_file(sd_journal *j, const char *prefix, const char *filename) {
- char *path;
- JournalFile *f;
-
- assert(j);
- assert(prefix);
- assert(filename);
-
- path = strjoin(prefix, "/", filename, NULL);
- if (!path)
- return -ENOMEM;
-
- f = hashmap_get(j->files, path);
- free(path);
- if (!f)
- return 0;
-
- hashmap_remove(j->files, f->path);
-
- log_debug("File %s got removed.", f->path);
-
- if (j->current_file == f) {
- j->current_file = NULL;
- j->current_field = 0;
- }
-
- if (j->unique_file == f) {
- j->unique_file = NULL;
- j->unique_offset = 0;
- }
-
- journal_file_close(f);
-
- j->current_invalidate_counter ++;
-
- return 0;
-}
-
-static int add_directory(sd_journal *j, const char *prefix, const char *dirname) {
- char *path;
- int r;
- DIR *d;
- sd_id128_t id, mid;
- Directory *m;
-
- assert(j);
- assert(prefix);
- assert(dirname);
-
- if ((j->flags & SD_JOURNAL_LOCAL_ONLY) &&
- (sd_id128_from_string(dirname, &id) < 0 ||
- sd_id128_get_machine(&mid) < 0 ||
- !sd_id128_equal(id, mid)))
- return 0;
-
- path = strjoin(prefix, "/", dirname, NULL);
- if (!path)
- return -ENOMEM;
-
- d = opendir(path);
- if (!d) {
- log_debug("Failed to open %s: %m", path);
- free(path);
-
- if (errno == ENOENT)
- return 0;
- return -errno;
- }
-
- m = hashmap_get(j->directories_by_path, path);
- if (!m) {
- m = new0(Directory, 1);
- if (!m) {
- closedir(d);
- free(path);
- return -ENOMEM;
- }
-
- m->is_root = false;
- m->path = path;
-
- if (hashmap_put(j->directories_by_path, m->path, m) < 0) {
- closedir(d);
- free(m->path);
- free(m);
- return -ENOMEM;
- }
-
- j->current_invalidate_counter ++;
-
- log_debug("Directory %s got added.", m->path);
-
- } else if (m->is_root) {
- free (path);
- closedir(d);
- return 0;
- } else
- free(path);
-
- if (m->wd <= 0 && j->inotify_fd >= 0) {
-
- m->wd = inotify_add_watch(j->inotify_fd, m->path,
- IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
- IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT|IN_MOVED_FROM|
- IN_ONLYDIR);
-
- if (m->wd > 0 && hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m) < 0)
- inotify_rm_watch(j->inotify_fd, m->wd);
- }
-
- for (;;) {
- struct dirent *de;
- union dirent_storage buf;
-
- r = readdir_r(d, &buf.de, &de);
- if (r != 0 || !de)
- break;
-
- if (dirent_is_file_with_suffix(de, ".journal") ||
- dirent_is_file_with_suffix(de, ".journal~")) {
- r = add_file(j, m->path, de->d_name);
- if (r < 0)
- log_debug("Failed to add file %s/%s: %s", m->path, de->d_name, strerror(-r));
- }
- }
-
- check_network(j, dirfd(d));
-
- closedir(d);
-
- return 0;
-}
-
-static int add_root_directory(sd_journal *j, const char *p) {
- DIR *d;
- Directory *m;
- int r;
-
- assert(j);
- assert(p);
-
- if ((j->flags & SD_JOURNAL_RUNTIME_ONLY) &&
- !path_startswith(p, "/run"))
- return -EINVAL;
-
- d = opendir(p);
- if (!d)
- return -errno;
-
- m = hashmap_get(j->directories_by_path, p);
- if (!m) {
- m = new0(Directory, 1);
- if (!m) {
- closedir(d);
- return -ENOMEM;
- }
-
- m->is_root = true;
- m->path = strdup(p);
- if (!m->path) {
- closedir(d);
- free(m);
- return -ENOMEM;
- }
-
- if (hashmap_put(j->directories_by_path, m->path, m) < 0) {
- closedir(d);
- free(m->path);
- free(m);
- return -ENOMEM;
- }
-
- j->current_invalidate_counter ++;
-
- log_debug("Root directory %s got added.", m->path);
-
- } else if (!m->is_root) {
- closedir(d);
- return 0;
- }
-
- if (m->wd <= 0 && j->inotify_fd >= 0) {
-
- m->wd = inotify_add_watch(j->inotify_fd, m->path,
- IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
- IN_ONLYDIR);
-
- if (m->wd > 0 && hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m) < 0)
- inotify_rm_watch(j->inotify_fd, m->wd);
- }
-
- for (;;) {
- struct dirent *de;
- union dirent_storage buf;
- sd_id128_t id;
-
- r = readdir_r(d, &buf.de, &de);
- if (r != 0 || !de)
- break;
-
- if (dirent_is_file_with_suffix(de, ".journal") ||
- dirent_is_file_with_suffix(de, ".journal~")) {
- r = add_file(j, m->path, de->d_name);
- if (r < 0)
- log_debug("Failed to add file %s/%s: %s", m->path, de->d_name, strerror(-r));
-
- } else if ((de->d_type == DT_DIR || de->d_type == DT_LNK || de->d_type == DT_UNKNOWN) &&
- sd_id128_from_string(de->d_name, &id) >= 0) {
-
- r = add_directory(j, m->path, de->d_name);
- if (r < 0)
- log_debug("Failed to add directory %s/%s: %s", m->path, de->d_name, strerror(-r));
- }
- }
-
- check_network(j, dirfd(d));
-
- closedir(d);
-
- return 0;
-}
-
-static int remove_directory(sd_journal *j, Directory *d) {
- assert(j);
-
- if (d->wd > 0) {
- hashmap_remove(j->directories_by_wd, INT_TO_PTR(d->wd));
-
- if (j->inotify_fd >= 0)
- inotify_rm_watch(j->inotify_fd, d->wd);
- }
-
- hashmap_remove(j->directories_by_path, d->path);
-
- if (d->is_root)
- log_debug("Root directory %s got removed.", d->path);
- else
- log_debug("Directory %s got removed.", d->path);
-
- free(d->path);
- free(d);
-
- return 0;
-}
-
-static int add_search_paths(sd_journal *j) {
-
- const char search_paths[] =
- "/run/log/journal\0"
- "/var/log/journal\0";
- const char *p;
-
- assert(j);
-
- /* We ignore most errors here, since the idea is to only open
- * what's actually accessible, and ignore the rest. */
-
- NULSTR_FOREACH(p, search_paths)
- add_root_directory(j, p);
-
- return 0;
-}
-
-static int allocate_inotify(sd_journal *j) {
- assert(j);
-
- if (j->inotify_fd < 0) {
- j->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
- if (j->inotify_fd < 0)
- return -errno;
- }
-
- if (!j->directories_by_wd) {
- j->directories_by_wd = hashmap_new(trivial_hash_func, trivial_compare_func);
- if (!j->directories_by_wd)
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static sd_journal *journal_new(int flags, const char *path) {
- sd_journal *j;
-
- j = new0(sd_journal, 1);
- if (!j)
- return NULL;
-
- j->inotify_fd = -1;
- j->flags = flags;
-
- if (path) {
- j->path = strdup(path);
- if (!j->path) {
- free(j);
- return NULL;
- }
- }
-
- j->files = hashmap_new(string_hash_func, string_compare_func);
- if (!j->files) {
- free(j->path);
- free(j);
- return NULL;
- }
-
- j->directories_by_path = hashmap_new(string_hash_func, string_compare_func);
- if (!j->directories_by_path) {
- hashmap_free(j->files);
- free(j->path);
- free(j);
- return NULL;
- }
-
- j->mmap = mmap_cache_new();
- if (!j->mmap) {
- hashmap_free(j->files);
- hashmap_free(j->directories_by_path);
- free(j->path);
- free(j);
- return NULL;
- }
-
- return j;
-}
-
-_public_ int sd_journal_open(sd_journal **ret, int flags) {
- sd_journal *j;
- int r;
-
- if (!ret)
- return -EINVAL;
-
- if (flags & ~(SD_JOURNAL_LOCAL_ONLY|
- SD_JOURNAL_RUNTIME_ONLY|
- SD_JOURNAL_SYSTEM_ONLY))
- return -EINVAL;
-
- j = journal_new(flags, NULL);
- if (!j)
- return -ENOMEM;
-
- r = add_search_paths(j);
- if (r < 0)
- goto fail;
-
- *ret = j;
- return 0;
-
-fail:
- sd_journal_close(j);
-
- return r;
-}
-
-_public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int flags) {
- sd_journal *j;
- int r;
-
- if (!ret)
- return -EINVAL;
-
- if (!path || !path_is_absolute(path))
- return -EINVAL;
-
- if (flags != 0)
- return -EINVAL;
-
- j = journal_new(flags, path);
- if (!j)
- return -ENOMEM;
-
- r = add_root_directory(j, path);
- if (r < 0)
- goto fail;
-
- *ret = j;
- return 0;
-
-fail:
- sd_journal_close(j);
-
- return r;
-}
-
-_public_ void sd_journal_close(sd_journal *j) {
- Directory *d;
- JournalFile *f;
-
- if (!j)
- return;
-
- while ((f = hashmap_steal_first(j->files)))
- journal_file_close(f);
-
- hashmap_free(j->files);
-
- while ((d = hashmap_first(j->directories_by_path)))
- remove_directory(j, d);
-
- while ((d = hashmap_first(j->directories_by_wd)))
- remove_directory(j, d);
-
- hashmap_free(j->directories_by_path);
- hashmap_free(j->directories_by_wd);
-
- if (j->inotify_fd >= 0)
- close_nointr_nofail(j->inotify_fd);
-
- sd_journal_flush_matches(j);
-
- if (j->mmap)
- mmap_cache_unref(j->mmap);
-
- free(j->path);
- free(j->unique_field);
- free(j);
-}
-
-_public_ int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret) {
- Object *o;
- JournalFile *f;
- int r;
-
- if (!j)
- return -EINVAL;
- if (!ret)
- return -EINVAL;
-
- f = j->current_file;
- if (!f)
- return -EADDRNOTAVAIL;
-
- if (f->current_offset <= 0)
- return -EADDRNOTAVAIL;
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
- if (r < 0)
- return r;
-
- *ret = le64toh(o->entry.realtime);
- return 0;
-}
-
-_public_ int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id128_t *ret_boot_id) {
- Object *o;
- JournalFile *f;
- int r;
- sd_id128_t id;
-
- if (!j)
- return -EINVAL;
-
- f = j->current_file;
- if (!f)
- return -EADDRNOTAVAIL;
-
- if (f->current_offset <= 0)
- return -EADDRNOTAVAIL;
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
- if (r < 0)
- return r;
-
- if (ret_boot_id)
- *ret_boot_id = o->entry.boot_id;
- else {
- r = sd_id128_get_boot(&id);
- if (r < 0)
- return r;
-
- if (!sd_id128_equal(id, o->entry.boot_id))
- return -ESTALE;
- }
-
- if (ret)
- *ret = le64toh(o->entry.monotonic);
-
- return 0;
-}
-
-static bool field_is_valid(const char *field) {
- const char *p;
-
- assert(field);
-
- if (isempty(field))
- return false;
-
- if (startswith(field, "__"))
- return false;
-
- for (p = field; *p; p++) {
-
- if (*p == '_')
- continue;
-
- if (*p >= 'A' && *p <= 'Z')
- continue;
-
- if (*p >= '0' && *p <= '9')
- continue;
-
- return false;
- }
-
- return true;
-}
-
-_public_ int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *size) {
- JournalFile *f;
- uint64_t i, n;
- size_t field_length;
- int r;
- Object *o;
-
- if (!j)
- return -EINVAL;
- if (!field)
- return -EINVAL;
- if (!data)
- return -EINVAL;
- if (!size)
- return -EINVAL;
-
- if (!field_is_valid(field))
- return -EINVAL;
-
- f = j->current_file;
- if (!f)
- return -EADDRNOTAVAIL;
-
- if (f->current_offset <= 0)
- return -EADDRNOTAVAIL;
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
- if (r < 0)
- return r;
-
- field_length = strlen(field);
-
- n = journal_file_entry_n_items(o);
- for (i = 0; i < n; i++) {
- uint64_t p, l;
- le64_t le_hash;
- size_t t;
-
- p = le64toh(o->entry.items[i].object_offset);
- le_hash = o->entry.items[i].hash;
- r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
- if (r < 0)
- return r;
-
- if (le_hash != o->data.hash)
- return -EBADMSG;
-
- l = le64toh(o->object.size) - offsetof(Object, data.payload);
-
- if (o->object.flags & OBJECT_COMPRESSED) {
-
-#ifdef HAVE_XZ
- if (uncompress_startswith(o->data.payload, l,
- &f->compress_buffer, &f->compress_buffer_size,
- field, field_length, '=')) {
-
- uint64_t rsize;
-
- if (!uncompress_blob(o->data.payload, l,
- &f->compress_buffer, &f->compress_buffer_size, &rsize))
- return -EBADMSG;
-
- *data = f->compress_buffer;
- *size = (size_t) rsize;
-
- return 0;
- }
-#else
- return -EPROTONOSUPPORT;
-#endif
-
- } else if (l >= field_length+1 &&
- memcmp(o->data.payload, field, field_length) == 0 &&
- o->data.payload[field_length] == '=') {
-
- t = (size_t) l;
-
- if ((uint64_t) t != l)
- return -E2BIG;
-
- *data = o->data.payload;
- *size = t;
-
- return 0;
- }
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
- if (r < 0)
- return r;
- }
-
- return -ENOENT;
-}
-
-static int return_data(JournalFile *f, Object *o, const void **data, size_t *size) {
- size_t t;
- uint64_t l;
-
- l = le64toh(o->object.size) - offsetof(Object, data.payload);
- t = (size_t) l;
-
- /* We can't read objects larger than 4G on a 32bit machine */
- if ((uint64_t) t != l)
- return -E2BIG;
-
- if (o->object.flags & OBJECT_COMPRESSED) {
-#ifdef HAVE_XZ
- uint64_t rsize;
-
- if (!uncompress_blob(o->data.payload, l, &f->compress_buffer, &f->compress_buffer_size, &rsize))
- return -EBADMSG;
-
- *data = f->compress_buffer;
- *size = (size_t) rsize;
-#else
- return -EPROTONOSUPPORT;
-#endif
- } else {
- *data = o->data.payload;
- *size = t;
- }
-
- return 0;
-}
-
-_public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *size) {
- JournalFile *f;
- uint64_t p, n;
- le64_t le_hash;
- int r;
- Object *o;
-
- if (!j)
- return -EINVAL;
- if (!data)
- return -EINVAL;
- if (!size)
- return -EINVAL;
-
- f = j->current_file;
- if (!f)
- return -EADDRNOTAVAIL;
-
- if (f->current_offset <= 0)
- return -EADDRNOTAVAIL;
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
- if (r < 0)
- return r;
-
- n = journal_file_entry_n_items(o);
- if (j->current_field >= n)
- return 0;
-
- p = le64toh(o->entry.items[j->current_field].object_offset);
- le_hash = o->entry.items[j->current_field].hash;
- r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
- if (r < 0)
- return r;
-
- if (le_hash != o->data.hash)
- return -EBADMSG;
-
- r = return_data(f, o, data, size);
- if (r < 0)
- return r;
-
- j->current_field ++;
-
- return 1;
-}
-
-_public_ void sd_journal_restart_data(sd_journal *j) {
- if (!j)
- return;
-
- j->current_field = 0;
-}
-
-_public_ int sd_journal_get_fd(sd_journal *j) {
- int r;
-
- if (!j)
- return -EINVAL;
-
- if (j->inotify_fd >= 0)
- return j->inotify_fd;
-
- r = allocate_inotify(j);
- if (r < 0)
- return r;
-
- /* Iterate through all dirs again, to add them to the
- * inotify */
- if (j->path)
- r = add_root_directory(j, j->path);
- else
- r = add_search_paths(j);
- if (r < 0)
- return r;
-
- return j->inotify_fd;
-}
-
-static void process_inotify_event(sd_journal *j, struct inotify_event *e) {
- Directory *d;
- int r;
-
- assert(j);
- assert(e);
-
- /* Is this a subdirectory we watch? */
- d = hashmap_get(j->directories_by_wd, INT_TO_PTR(e->wd));
- if (d) {
- sd_id128_t id;
-
- if (!(e->mask & IN_ISDIR) && e->len > 0 &&
- (endswith(e->name, ".journal") ||
- endswith(e->name, ".journal~"))) {
-
- /* Event for a journal file */
-
- if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) {
- r = add_file(j, d->path, e->name);
- if (r < 0)
- log_debug("Failed to add file %s/%s: %s", d->path, e->name, strerror(-r));
-
- } else if (e->mask & (IN_DELETE|IN_MOVED_FROM|IN_UNMOUNT)) {
-
- r = remove_file(j, d->path, e->name);
- if (r < 0)
- log_debug("Failed to remove file %s/%s: %s", d->path, e->name, strerror(-r));
- }
-
- } else if (!d->is_root && e->len == 0) {
-
- /* Event for a subdirectory */
-
- if (e->mask & (IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT)) {
- r = remove_directory(j, d);
- if (r < 0)
- log_debug("Failed to remove directory %s: %s", d->path, strerror(-r));
- }
-
-
- } else if (d->is_root && (e->mask & IN_ISDIR) && e->len > 0 && sd_id128_from_string(e->name, &id) >= 0) {
-
- /* Event for root directory */
-
- if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) {
- r = add_directory(j, d->path, e->name);
- if (r < 0)
- log_debug("Failed to add directory %s/%s: %s", d->path, e->name, strerror(-r));
- }
- }
-
- return;
- }
-
- if (e->mask & IN_IGNORED)
- return;
-
- log_warning("Unknown inotify event.");
-}
-
-static int determine_change(sd_journal *j) {
- bool b;
-
- assert(j);
-
- b = j->current_invalidate_counter != j->last_invalidate_counter;
- j->last_invalidate_counter = j->current_invalidate_counter;
-
- return b ? SD_JOURNAL_INVALIDATE : SD_JOURNAL_APPEND;
-}
-
-_public_ int sd_journal_process(sd_journal *j) {
- uint8_t buffer[sizeof(struct inotify_event) + FILENAME_MAX] _alignas_(struct inotify_event);
- bool got_something = false;
-
- if (!j)
- return -EINVAL;
-
- for (;;) {
- struct inotify_event *e;
- ssize_t l;
-
- l = read(j->inotify_fd, buffer, sizeof(buffer));
- if (l < 0) {
- if (errno == EAGAIN || errno == EINTR)
- return got_something ? determine_change(j) : SD_JOURNAL_NOP;
-
- return -errno;
- }
-
- got_something = true;
-
- e = (struct inotify_event*) buffer;
- while (l > 0) {
- size_t step;
-
- process_inotify_event(j, e);
-
- step = sizeof(struct inotify_event) + e->len;
- assert(step <= (size_t) l);
-
- e = (struct inotify_event*) ((uint8_t*) e + step);
- l -= step;
- }
- }
-
- return determine_change(j);
-}
-
-_public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) {
- int r;
-
- assert(j);
-
- if (j->inotify_fd < 0) {
-
- /* This is the first invocation, hence create the
- * inotify watch */
- r = sd_journal_get_fd(j);
- if (r < 0)
- return r;
-
- /* The journal might have changed since the context
- * object was created and we weren't watching before,
- * hence don't wait for anything, and return
- * immediately. */
- return determine_change(j);
- }
-
- if (j->on_network) {
- /* If we are on the network we need to regularly check
- * for changes manually */
-
- if (timeout_usec == (uint64_t) -1 || timeout_usec > JOURNAL_FILES_RECHECK_USEC)
- timeout_usec = JOURNAL_FILES_RECHECK_USEC;
- }
-
- do {
- r = fd_wait_for_event(j->inotify_fd, POLLIN, timeout_usec);
- } while (r == -EINTR);
-
- if (r < 0)
- return r;
-
- return sd_journal_process(j);
-}
-
-_public_ int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, uint64_t *to) {
- Iterator i;
- JournalFile *f;
- bool first = true;
- int r;
-
- if (!j)
- return -EINVAL;
- if (!from && !to)
- return -EINVAL;
-
- HASHMAP_FOREACH(f, j->files, i) {
- usec_t fr, t;
-
- r = journal_file_get_cutoff_realtime_usec(f, &fr, &t);
- if (r == -ENOENT)
- continue;
- if (r < 0)
- return r;
- if (r == 0)
- continue;
-
- if (first) {
- if (from)
- *from = fr;
- if (to)
- *to = t;
- first = false;
- } else {
- if (from)
- *from = MIN(fr, *from);
- if (to)
- *to = MAX(t, *to);
- }
- }
-
- return first ? 0 : 1;
-}
-
-_public_ int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t *from, uint64_t *to) {
- Iterator i;
- JournalFile *f;
- bool first = true;
- int r;
-
- if (!j)
- return -EINVAL;
- if (!from && !to)
- return -EINVAL;
-
- HASHMAP_FOREACH(f, j->files, i) {
- usec_t fr, t;
-
- r = journal_file_get_cutoff_monotonic_usec(f, boot_id, &fr, &t);
- if (r == -ENOENT)
- continue;
- if (r < 0)
- return r;
- if (r == 0)
- continue;
-
- if (first) {
- if (from)
- *from = fr;
- if (to)
- *to = t;
- first = false;
- } else {
- if (from)
- *from = MIN(fr, *from);
- if (to)
- *to = MAX(t, *to);
- }
- }
-
- return first ? 0 : 1;
-}
-
-void journal_print_header(sd_journal *j) {
- Iterator i;
- JournalFile *f;
- bool newline = false;
-
- assert(j);
-
- HASHMAP_FOREACH(f, j->files, i) {
- if (newline)
- putchar('\n');
- else
- newline = true;
-
- journal_file_print_header(f);
- }
-}
-
-_public_ int sd_journal_get_usage(sd_journal *j, uint64_t *bytes) {
- Iterator i;
- JournalFile *f;
- uint64_t sum = 0;
-
- if (!j)
- return -EINVAL;
- if (!bytes)
- return -EINVAL;
-
- HASHMAP_FOREACH(f, j->files, i) {
- struct stat st;
-
- if (fstat(f->fd, &st) < 0)
- return -errno;
-
- sum += (uint64_t) st.st_blocks * 512ULL;
- }
-
- *bytes = sum;
- return 0;
-}
-
-_public_ int sd_journal_query_unique(sd_journal *j, const char *field) {
- char *f;
-
- if (!j)
- return -EINVAL;
- if (isempty(field))
- return -EINVAL;
- if (!field_is_valid(field))
- return -EINVAL;
-
- f = strdup(field);
- if (!f)
- return -ENOMEM;
-
- free(j->unique_field);
- j->unique_field = f;
- j->unique_file = NULL;
- j->unique_offset = 0;
-
- return 0;
-}
-
-_public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l) {
- Object *o;
- size_t k;
- int r;
-
- if (!j)
- return -EINVAL;
- if (!data)
- return -EINVAL;
- if (!l)
- return -EINVAL;
- if (!j->unique_field)
- return -EINVAL;
-
- k = strlen(j->unique_field);
-
- if (!j->unique_file) {
- j->unique_file = hashmap_first(j->files);
- if (!j->unique_file)
- return 0;
- j->unique_offset = 0;
- }
-
- for (;;) {
- JournalFile *of;
- Iterator i;
- const void *odata;
- size_t ol;
- bool found;
-
- /* Proceed to next data object in the field's linked list */
- if (j->unique_offset == 0) {
- r = journal_file_find_field_object(j->unique_file, j->unique_field, k, &o, NULL);
- if (r < 0)
- return r;
-
- j->unique_offset = r > 0 ? le64toh(o->field.head_data_offset) : 0;
- } else {
- r = journal_file_move_to_object(j->unique_file, OBJECT_DATA, j->unique_offset, &o);
- if (r < 0)
- return r;
-
- j->unique_offset = le64toh(o->data.next_field_offset);
- }
-
- /* We reached the end of the list? Then start again, with the next file */
- if (j->unique_offset == 0) {
- JournalFile *n;
-
- n = hashmap_next(j->files, j->unique_file->path);
- if (!n)
- return 0;
-
- j->unique_file = n;
- continue;
- }
-
- /* We do not use the type context here, but 0 instead,
- * so that we can look at this data object at the same
- * time as one on another file */
- r = journal_file_move_to_object(j->unique_file, 0, j->unique_offset, &o);
- if (r < 0)
- return r;
-
- /* Let's do the type check by hand, since we used 0 context above. */
- if (o->object.type != OBJECT_DATA)
- return -EBADMSG;
-
- r = return_data(j->unique_file, o, &odata, &ol);
- if (r < 0)
- return r;
-
- /* OK, now let's see if we already returned this data
- * object by checking if it exists in the earlier
- * traversed files. */
- found = false;
- HASHMAP_FOREACH(of, j->files, i) {
- Object *oo;
- uint64_t op;
-
- if (of == j->unique_file)
- break;
-
- /* Skip this file it didn't have any fields
- * indexed */
- if (JOURNAL_HEADER_CONTAINS(of->header, n_fields) &&
- le64toh(of->header->n_fields) <= 0)
- continue;
-
- r = journal_file_find_data_object_with_hash(of, odata, ol, le64toh(o->data.hash), &oo, &op);
- if (r < 0)
- return r;
-
- if (r > 0)
- found = true;
- }
-
- if (found)
- continue;
-
- r = return_data(j->unique_file, o, data, l);
- if (r < 0)
- return r;
-
- return 1;
- }
-}
-
-_public_ void sd_journal_restart_unique(sd_journal *j) {
- if (!j)
- return;
-
- j->unique_file = NULL;
- j->unique_offset = 0;
-}
-
-_public_ int sd_journal_reliable_fd(sd_journal *j) {
- if (!j)
- return -EINVAL;
-
- return !j->on_network;
-}
diff --git a/src/journal/test-journal-enum.c b/src/journal/test-journal-enum.c
deleted file mode 100644
index 8a843ecdda..0000000000
--- a/src/journal/test-journal-enum.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdio.h>
-
-#include "log.h"
-#include "sd-journal.h"
-
-int main(int argc, char *argv[]) {
- unsigned n = 0;
- sd_journal *j;
-
- log_set_max_level(LOG_DEBUG);
-
- assert_se(sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY) >= 0);
-
- assert_se(sd_journal_add_match(j, "_TRANSPORT=syslog", 0) >= 0);
- assert_se(sd_journal_add_match(j, "_UID=0", 0) >= 0);
-
- SD_JOURNAL_FOREACH_BACKWARDS(j) {
- const void *d;
- size_t l;
-
- assert_se(sd_journal_get_data(j, "MESSAGE", &d, &l) >= 0);
-
- printf("%.*s\n", (int) l, (char*) d);
-
- n ++;
- if (n >= 10)
- break;
- }
-
- sd_journal_close(j);
- return 0;
-}
diff --git a/src/journal/test-journal-match.c b/src/journal/test-journal-match.c
deleted file mode 100644
index fa228144f5..0000000000
--- a/src/journal/test-journal-match.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdio.h>
-
-#include <systemd/sd-journal.h>
-
-#include "journal-internal.h"
-#include "util.h"
-#include "log.h"
-
-int main(int argc, char *argv[]) {
- sd_journal *j;
- char *t;
-
- log_set_max_level(LOG_DEBUG);
-
- assert_se(sd_journal_open(&j, 0) >= 0);
-
- assert_se(sd_journal_add_match(j, "foobar", 0) < 0);
- assert_se(sd_journal_add_match(j, "foobar=waldo", 0) < 0);
- assert_se(sd_journal_add_match(j, "", 0) < 0);
- assert_se(sd_journal_add_match(j, "=", 0) < 0);
- assert_se(sd_journal_add_match(j, "=xxxxx", 0) < 0);
- assert_se(sd_journal_add_match(j, "HALLO=WALDO", 0) >= 0);
- assert_se(sd_journal_add_match(j, "QUUX=mmmm", 0) >= 0);
- assert_se(sd_journal_add_match(j, "QUUX=xxxxx", 0) >= 0);
- assert_se(sd_journal_add_match(j, "HALLO=", 0) >= 0);
- assert_se(sd_journal_add_match(j, "QUUX=xxxxx", 0) >= 0);
- assert_se(sd_journal_add_match(j, "QUUX=yyyyy", 0) >= 0);
- assert_se(sd_journal_add_match(j, "PIFF=paff", 0) >= 0);
-
- assert_se(sd_journal_add_disjunction(j) >= 0);
-
- assert_se(sd_journal_add_match(j, "ONE=one", 0) >= 0);
- assert_se(sd_journal_add_match(j, "ONE=two", 0) >= 0);
- assert_se(sd_journal_add_match(j, "TWO=two", 0) >= 0);
-
- assert_se(t = journal_make_match_string(j));
-
- assert_se(streq(t, "((TWO=two AND (ONE=two OR ONE=one)) OR (PIFF=paff AND (QUUX=yyyyy OR QUUX=xxxxx OR QUUX=mmmm) AND (HALLO= OR HALLO=WALDO)))"));
-
- printf("resulting match expression is: %s\n", t);
- free(t);
-
- sd_journal_close(j);
-
- return 0;
-}
diff --git a/src/journal/test-journal-send.c b/src/journal/test-journal-send.c
deleted file mode 100644
index 3e986ed99a..0000000000
--- a/src/journal/test-journal-send.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <systemd/sd-journal.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "log.h"
-
-int main(int argc, char *argv[]) {
- char huge[4096*1024];
-
- log_set_max_level(LOG_DEBUG);
-
- sd_journal_print(LOG_INFO, "piepapo");
-
- sd_journal_send("MESSAGE=foobar",
- "VALUE=%i", 7,
- NULL);
-
- errno = ENOENT;
- sd_journal_perror("Foobar");
-
- sd_journal_perror("");
-
- memset(huge, 'x', sizeof(huge));
- memcpy(huge, "HUGE=", 5);
- char_array_0(huge);
-
- sd_journal_send("MESSAGE=Huge field attached",
- huge,
- NULL);
-
- sd_journal_send("MESSAGE=uiui",
- "VALUE=A",
- "VALUE=B",
- "VALUE=C",
- "SINGLETON=1",
- "OTHERVALUE=X",
- "OTHERVALUE=Y",
- "WITH_BINARY=this is a binary value \a",
- NULL);
-
- syslog(LOG_NOTICE, "Hello World!");
-
- sd_journal_print(LOG_NOTICE, "Hello World");
-
- sd_journal_send("MESSAGE=Hello World!",
- "MESSAGE_ID=52fb62f99e2c49d89cfbf9d6de5e3555",
- "PRIORITY=5",
- "HOME=%s", getenv("HOME"),
- "TERM=%s", getenv("TERM"),
- "PAGE_SIZE=%li", sysconf(_SC_PAGESIZE),
- "N_CPUS=%li", sysconf(_SC_NPROCESSORS_ONLN),
- NULL);
-
- sleep(10);
-
- return 0;
-}
diff --git a/src/journal/test-journal-stream.c b/src/journal/test-journal-stream.c
deleted file mode 100644
index b3e816db70..0000000000
--- a/src/journal/test-journal-stream.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <unistd.h>
-#include <fcntl.h>
-
-#include <systemd/sd-journal.h>
-
-#include "journal-file.h"
-#include "journal-internal.h"
-#include "util.h"
-#include "log.h"
-
-#define N_ENTRIES 200
-
-static void verify_contents(sd_journal *j, unsigned skip) {
- unsigned i;
-
- assert(j);
-
- i = 0;
- SD_JOURNAL_FOREACH(j) {
- const void *d;
- char *k, *c;
- size_t l;
- unsigned u;
-
- assert_se(sd_journal_get_cursor(j, &k) >= 0);
- printf("cursor: %s\n", k);
- free(k);
-
- assert_se(sd_journal_get_data(j, "MAGIC", &d, &l) >= 0);
- printf("\t%.*s\n", (int) l, (const char*) d);
-
- assert_se(sd_journal_get_data(j, "NUMBER", &d, &l) >= 0);
- assert_se(k = strndup(d, l));
- printf("\t%s\n", k);
-
- if (skip > 0) {
- assert_se(safe_atou(k + 7, &u) >= 0);
- assert_se(i == u);
- i += skip;
- }
-
- free(k);
-
- assert_se(sd_journal_get_cursor(j, &c) >= 0);
- assert_se(sd_journal_test_cursor(j, c) > 0);
- free(c);
- }
-
- if (skip > 0)
- assert_se(i == N_ENTRIES);
-}
-
-int main(int argc, char *argv[]) {
- JournalFile *one, *two, *three;
- char t[] = "/tmp/journal-stream-XXXXXX";
- unsigned i;
- sd_journal *j;
- char *z;
- const void *data;
- size_t l;
-
- log_set_max_level(LOG_DEBUG);
-
- assert_se(mkdtemp(t));
- assert_se(chdir(t) >= 0);
-
- assert_se(journal_file_open("one.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, &one) == 0);
- assert_se(journal_file_open("two.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, &two) == 0);
- assert_se(journal_file_open("three.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, &three) == 0);
-
- for (i = 0; i < N_ENTRIES; i++) {
- char *p, *q;
- dual_timestamp ts;
- struct iovec iovec[2];
-
- dual_timestamp_get(&ts);
-
- assert_se(asprintf(&p, "NUMBER=%u", i) >= 0);
- iovec[0].iov_base = p;
- iovec[0].iov_len = strlen(p);
-
- assert_se(asprintf(&q, "MAGIC=%s", i % 5 == 0 ? "quux" : "waldo") >= 0);
-
- iovec[1].iov_base = q;
- iovec[1].iov_len = strlen(q);
-
- if (i % 10 == 0)
- assert_se(journal_file_append_entry(three, &ts, iovec, 2, NULL, NULL, NULL) == 0);
- else {
- if (i % 3 == 0)
- assert_se(journal_file_append_entry(two, &ts, iovec, 2, NULL, NULL, NULL) == 0);
-
- assert_se(journal_file_append_entry(one, &ts, iovec, 2, NULL, NULL, NULL) == 0);
- }
-
- free(p);
- free(q);
- }
-
- journal_file_close(one);
- journal_file_close(two);
- journal_file_close(three);
-
- assert_se(sd_journal_open_directory(&j, t, 0) >= 0);
-
- assert_se(sd_journal_add_match(j, "MAGIC=quux", 0) >= 0);
- SD_JOURNAL_FOREACH_BACKWARDS(j) {
- char *c;
-
- assert_se(sd_journal_get_data(j, "NUMBER", &data, &l) >= 0);
- printf("\t%.*s\n", (int) l, (const char*) data);
-
- assert_se(sd_journal_get_cursor(j, &c) >= 0);
- assert_se(sd_journal_test_cursor(j, c) > 0);
- free(c);
- }
-
- SD_JOURNAL_FOREACH(j) {
- char *c;
-
- assert_se(sd_journal_get_data(j, "NUMBER", &data, &l) >= 0);
- printf("\t%.*s\n", (int) l, (const char*) data);
-
- assert_se(sd_journal_get_cursor(j, &c) >= 0);
- assert_se(sd_journal_test_cursor(j, c) > 0);
- free(c);
- }
-
- sd_journal_flush_matches(j);
-
- verify_contents(j, 1);
-
- printf("NEXT TEST\n");
- assert_se(sd_journal_add_match(j, "MAGIC=quux", 0) >= 0);
-
- assert_se(z = journal_make_match_string(j));
- printf("resulting match expression is: %s\n", z);
- free(z);
-
- verify_contents(j, 5);
-
- printf("NEXT TEST\n");
- sd_journal_flush_matches(j);
- assert_se(sd_journal_add_match(j, "MAGIC=waldo", 0) >= 0);
- assert_se(sd_journal_add_match(j, "NUMBER=10", 0) >= 0);
- assert_se(sd_journal_add_match(j, "NUMBER=11", 0) >= 0);
- assert_se(sd_journal_add_match(j, "NUMBER=12", 0) >= 0);
-
- assert_se(z = journal_make_match_string(j));
- printf("resulting match expression is: %s\n", z);
- free(z);
-
- verify_contents(j, 0);
-
- assert_se(sd_journal_query_unique(j, "NUMBER") >= 0);
- SD_JOURNAL_FOREACH_UNIQUE(j, data, l)
- printf("%.*s\n", (int) l, (const char*) data);
-
- sd_journal_close(j);
-
- assert_se(rm_rf_dangerous(t, false, true, false) >= 0);
-
- return 0;
-}
diff --git a/src/journal/test-journal-syslog.c b/src/journal/test-journal-syslog.c
deleted file mode 100644
index 3ae8633f22..0000000000
--- a/src/journal/test-journal-syslog.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 "journald-syslog.h"
-#include "macro.h"
-
-static void test_syslog_parse_identifier(const char* str,
- const char *ident, const char*pid, int ret) {
- const char *buf = str;
- char *ident2 = NULL, *pid2 = NULL;
- int ret2;
-
- ret2 = syslog_parse_identifier(&buf, &ident2, &pid2);
-
- assert(ret == ret2);
- assert(ident==ident2 || !strcmp(ident, ident2));
- assert(pid==pid2 || !strcmp(pid, pid2));
-}
-
-int main(void) {
- test_syslog_parse_identifier("pidu[111]: xxx", "pidu", "111", 11);
- test_syslog_parse_identifier("pidu: xxx", "pidu", NULL, 6);
- test_syslog_parse_identifier("pidu xxx", NULL, NULL, 0);
-
- return 0;
-}
diff --git a/src/journal/test-journal-verify.c b/src/journal/test-journal-verify.c
deleted file mode 100644
index b6677215c0..0000000000
--- a/src/journal/test-journal-verify.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "util.h"
-#include "log.h"
-#include "journal-file.h"
-#include "journal-verify.h"
-#include "journal-authenticate.h"
-
-#define N_ENTRIES 6000
-#define RANDOM_RANGE 77
-
-static void bit_toggle(const char *fn, uint64_t p) {
- uint8_t b;
- ssize_t r;
- int fd;
-
- fd = open(fn, O_RDWR|O_CLOEXEC);
- assert(fd >= 0);
-
- r = pread(fd, &b, 1, p/8);
- assert(r == 1);
-
- b ^= 1 << (p % 8);
-
- r = pwrite(fd, &b, 1, p/8);
- assert(r == 1);
-
- close_nointr_nofail(fd);
-}
-
-static int raw_verify(const char *fn, const char *verification_key) {
- JournalFile *f;
- int r;
-
- r = journal_file_open(fn, O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, &f);
- if (r < 0)
- return r;
-
- r = journal_file_verify(f, verification_key, NULL, NULL, NULL, false);
- journal_file_close(f);
-
- return r;
-}
-
-int main(int argc, char *argv[]) {
- char t[] = "/tmp/journal-XXXXXX";
- unsigned n;
- JournalFile *f;
- const char *verification_key = argv[1];
- usec_t from = 0, to = 0, total = 0;
- char a[FORMAT_TIMESTAMP_MAX];
- char b[FORMAT_TIMESTAMP_MAX];
- char c[FORMAT_TIMESPAN_MAX];
- struct stat st;
- uint64_t p;
-
- log_set_max_level(LOG_DEBUG);
-
- assert_se(mkdtemp(t));
- assert_se(chdir(t) >= 0);
-
- log_info("Generating...");
-
- assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, true, !!verification_key, NULL, NULL, NULL, &f) == 0);
-
- for (n = 0; n < N_ENTRIES; n++) {
- struct iovec iovec;
- struct dual_timestamp ts;
- char *test;
-
- dual_timestamp_get(&ts);
-
- assert_se(asprintf(&test, "RANDOM=%lu", random() % RANDOM_RANGE));
-
- iovec.iov_base = (void*) test;
- iovec.iov_len = strlen(test);
-
- assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0);
-
- free(test);
- }
-
- journal_file_close(f);
-
- log_info("Verifying...");
-
- assert_se(journal_file_open("test.journal", O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, &f) == 0);
- /* journal_file_print_header(f); */
- journal_file_dump(f);
-
- assert_se(journal_file_verify(f, verification_key, &from, &to, &total, true) >= 0);
-
- if (verification_key && JOURNAL_HEADER_SEALED(f->header)) {
- log_info("=> Validated from %s to %s, %s missing",
- format_timestamp(a, sizeof(a), from),
- format_timestamp(b, sizeof(b), to),
- format_timespan(c, sizeof(c), total > to ? total - to : 0));
- }
-
- journal_file_close(f);
-
- if (verification_key) {
- log_info("Toggling bits...");
-
- assert_se(stat("test.journal", &st) >= 0);
-
- for (p = 38448*8+0; p < ((uint64_t) st.st_size * 8); p ++) {
- bit_toggle("test.journal", p);
-
- log_info("[ %llu+%llu]", (unsigned long long) p / 8, (unsigned long long) p % 8);
-
- if (raw_verify("test.journal", verification_key) >= 0)
- log_notice(ANSI_HIGHLIGHT_RED_ON ">>>> %llu (bit %llu) can be toggled without detection." ANSI_HIGHLIGHT_OFF, (unsigned long long) p / 8, (unsigned long long) p % 8);
-
- bit_toggle("test.journal", p);
- }
- }
-
- log_info("Exiting...");
-
- assert_se(rm_rf_dangerous(t, false, true, false) >= 0);
-
- return 0;
-}
diff --git a/src/journal/test-journal.c b/src/journal/test-journal.c
deleted file mode 100644
index f4dc52cd81..0000000000
--- a/src/journal/test-journal.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <unistd.h>
-
-#include <systemd/sd-journal.h>
-
-#include "log.h"
-#include "journal-file.h"
-#include "journal-authenticate.h"
-#include "journal-vacuum.h"
-
-int main(int argc, char *argv[]) {
- dual_timestamp ts;
- JournalFile *f;
- struct iovec iovec;
- static const char test[] = "TEST1=1", test2[] = "TEST2=2";
- Object *o;
- uint64_t p;
- char t[] = "/tmp/journal-XXXXXX";
-
- log_set_max_level(LOG_DEBUG);
-
- assert_se(mkdtemp(t));
- assert_se(chdir(t) >= 0);
-
- assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, true, true, NULL, NULL, NULL, &f) == 0);
-
- dual_timestamp_get(&ts);
-
- iovec.iov_base = (void*) test;
- iovec.iov_len = strlen(test);
- assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0);
-
- iovec.iov_base = (void*) test2;
- iovec.iov_len = strlen(test2);
- assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0);
-
- iovec.iov_base = (void*) test;
- iovec.iov_len = strlen(test);
- assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0);
-
-#ifdef HAVE_GCRYPT
- journal_file_append_tag(f);
-#endif
- journal_file_dump(f);
-
- assert(journal_file_next_entry(f, NULL, 0, DIRECTION_DOWN, &o, &p) == 1);
- assert(le64toh(o->entry.seqnum) == 1);
-
- assert(journal_file_next_entry(f, o, p, DIRECTION_DOWN, &o, &p) == 1);
- assert(le64toh(o->entry.seqnum) == 2);
-
- assert(journal_file_next_entry(f, o, p, DIRECTION_DOWN, &o, &p) == 1);
- assert(le64toh(o->entry.seqnum) == 3);
-
- assert(journal_file_next_entry(f, o, p, DIRECTION_DOWN, &o, &p) == 0);
-
- assert(journal_file_next_entry(f, NULL, 0, DIRECTION_DOWN, &o, &p) == 1);
- assert(le64toh(o->entry.seqnum) == 1);
-
- assert(journal_file_skip_entry(f, o, p, 2, &o, &p) == 1);
- assert(le64toh(o->entry.seqnum) == 3);
-
- assert(journal_file_skip_entry(f, o, p, -2, &o, &p) == 1);
- assert(le64toh(o->entry.seqnum) == 1);
-
- assert(journal_file_skip_entry(f, o, p, -2, &o, &p) == 1);
- assert(le64toh(o->entry.seqnum) == 1);
-
- assert(journal_file_find_data_object(f, test, strlen(test), NULL, &p) == 1);
- assert(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_DOWN, &o, NULL) == 1);
- assert(le64toh(o->entry.seqnum) == 1);
-
- assert(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_UP, &o, NULL) == 1);
- assert(le64toh(o->entry.seqnum) == 3);
-
- assert(journal_file_find_data_object(f, test2, strlen(test2), NULL, &p) == 1);
- assert(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_UP, &o, NULL) == 1);
- assert(le64toh(o->entry.seqnum) == 2);
-
- assert(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_DOWN, &o, NULL) == 1);
- assert(le64toh(o->entry.seqnum) == 2);
-
- assert(journal_file_find_data_object(f, "quux", 4, NULL, &p) == 0);
-
- assert(journal_file_move_to_entry_by_seqnum(f, 1, DIRECTION_DOWN, &o, NULL) == 1);
- assert(le64toh(o->entry.seqnum) == 1);
-
- assert(journal_file_move_to_entry_by_seqnum(f, 3, DIRECTION_DOWN, &o, NULL) == 1);
- assert(le64toh(o->entry.seqnum) == 3);
-
- assert(journal_file_move_to_entry_by_seqnum(f, 2, DIRECTION_DOWN, &o, NULL) == 1);
- assert(le64toh(o->entry.seqnum) == 2);
-
- assert(journal_file_move_to_entry_by_seqnum(f, 10, DIRECTION_DOWN, &o, NULL) == 0);
-
- journal_file_rotate(&f, true, true);
- journal_file_rotate(&f, true, true);
-
- journal_file_close(f);
-
- journal_directory_vacuum(".", 3000000, 0, 0, NULL);
-
- log_error("Exiting...");
-
- assert_se(rm_rf_dangerous(t, false, true, false) >= 0);
-
- return 0;
-}
diff --git a/src/journal/test-mmap-cache.c b/src/journal/test-mmap-cache.c
deleted file mode 100644
index e2ffaf4723..0000000000
--- a/src/journal/test-mmap-cache.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdlib.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-#include "log.h"
-#include "macro.h"
-#include "util.h"
-#include "mmap-cache.h"
-
-int main(int argc, char *argv[]) {
- int x, y, z, r;
- char px[] = "/tmp/testmmapXXXXXXX", py[] = "/tmp/testmmapYXXXXXX", pz[] = "/tmp/testmmapZXXXXXX";
- MMapCache *m;
- void *p, *q;
-
- assert_se(m = mmap_cache_new());
-
- x = mkstemp(px);
- assert(x >= 0);
- unlink(px);
-
- y = mkstemp(py);
- assert(y >= 0);
- unlink(py);
-
- z = mkstemp(pz);
- assert(z >= 0);
- unlink(pz);
-
- r = mmap_cache_get(m, x, PROT_READ, 0, false, 1, 2, NULL, &p);
- assert(r >= 0);
-
- r = mmap_cache_get(m, x, PROT_READ, 0, false, 2, 2, NULL, &q);
- assert(r >= 0);
-
- assert((uint8_t*) p + 1 == (uint8_t*) q);
-
- r = mmap_cache_get(m, x, PROT_READ, 1, false, 3, 2, NULL, &q);
- assert(r >= 0);
-
- assert((uint8_t*) p + 2 == (uint8_t*) q);
-
- r = mmap_cache_get(m, x, PROT_READ, 0, false, 16ULL*1024ULL*1024ULL, 2, NULL, &p);
- assert(r >= 0);
-
- r = mmap_cache_get(m, x, PROT_READ, 1, false, 16ULL*1024ULL*1024ULL+1, 2, NULL, &q);
- assert(r >= 0);
-
- assert((uint8_t*) p + 1 == (uint8_t*) q);
-
- mmap_cache_unref(m);
-
- close_nointr_nofail(x);
- close_nointr_nofail(y);
- close_nointr_nofail(z);
-
- return 0;
-}
diff --git a/src/libsystemd-daemon/.gitignore b/src/libsystemd-daemon/.gitignore
deleted file mode 100644
index 5184131b28..0000000000
--- a/src/libsystemd-daemon/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/libsystemd-daemon.pc
diff --git a/src/libsystemd-daemon/Makefile b/src/libsystemd-daemon/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/libsystemd-daemon/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/libsystemd-daemon/libsystemd-daemon.pc.in b/src/libsystemd-daemon/libsystemd-daemon.pc.in
deleted file mode 100644
index 8bb3a74c87..0000000000
--- a/src/libsystemd-daemon/libsystemd-daemon.pc.in
+++ /dev/null
@@ -1,19 +0,0 @@
-# Permission is hereby granted, free of charge, to any person
-# obtaining a copy of this software and associated documentation files
-# (the "Software"), to deal in the Software without restriction,
-# including without limitation the rights to use, copy, modify, merge,
-# publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so,
-# subject to the following conditions:
-
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-
-Name: systemd
-Description: systemd Daemon Utility Library
-URL: @PACKAGE_URL@
-Version: @PACKAGE_VERSION@
-Libs: -L${libdir} -lsystemd-daemon
-Cflags: -I${includedir}
diff --git a/src/libsystemd-daemon/libsystemd-daemon.sym b/src/libsystemd-daemon/libsystemd-daemon.sym
deleted file mode 100644
index f440238931..0000000000
--- a/src/libsystemd-daemon/libsystemd-daemon.sym
+++ /dev/null
@@ -1,27 +0,0 @@
-/***
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation files
- (the "Software"), to deal in the Software without restriction,
- including without limitation the rights to use, copy, modify, merge,
- publish, distribute, sublicense, and/or sell copies of the Software,
- and to permit persons to whom the Software is furnished to do so,
- subject to the following conditions:
-***/
-
-/* Original symbols from systemd v31 */
-
-LIBSYSTEMD_DAEMON_31 {
-global:
- sd_booted;
- sd_is_fifo;
- sd_is_mq;
- sd_is_socket;
- sd_is_socket_inet;
- sd_is_socket_unix;
- sd_is_special;
- sd_listen_fds;
- sd_notify;
- sd_notifyf;
-local:
- *;
-};
diff --git a/src/libsystemd-daemon/sd-daemon.c b/src/libsystemd-daemon/sd-daemon.c
deleted file mode 100644
index 4801d2cd18..0000000000
--- a/src/libsystemd-daemon/sd-daemon.c
+++ /dev/null
@@ -1,536 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- Copyright 2010 Lennart Poettering
-
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation files
- (the "Software"), to deal in the Software without restriction,
- including without limitation the rights to use, copy, modify, merge,
- publish, distribute, sublicense, and/or sell copies of the Software,
- and to permit persons to whom the Software is furnished to do so,
- subject to the following conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
-***/
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#ifdef __BIONIC__
-#include <linux/fcntl.h>
-#else
-#include <sys/fcntl.h>
-#endif
-#include <netinet/in.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stddef.h>
-#include <limits.h>
-
-#if defined(__linux__)
-#include <mqueue.h>
-#endif
-
-#include "sd-daemon.h"
-
-#if (__GNUC__ >= 4)
-#ifdef SD_EXPORT_SYMBOLS
-/* Export symbols */
-#define _sd_export_ __attribute__ ((visibility("default")))
-#else
-/* Don't export the symbols */
-#define _sd_export_ __attribute__ ((visibility("hidden")))
-#endif
-#else
-#define _sd_export_
-#endif
-
-_sd_export_ int sd_listen_fds(int unset_environment) {
-
-#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
- return 0;
-#else
- int r, fd;
- const char *e;
- char *p = NULL;
- unsigned long l;
-
- e = getenv("LISTEN_PID");
- if (!e) {
- r = 0;
- goto finish;
- }
-
- errno = 0;
- l = strtoul(e, &p, 10);
-
- if (errno != 0) {
- r = -errno;
- goto finish;
- }
-
- if (!p || p == e || *p || l <= 0) {
- r = -EINVAL;
- goto finish;
- }
-
- /* Is this for us? */
- if (getpid() != (pid_t) l) {
- r = 0;
- goto finish;
- }
-
- e = getenv("LISTEN_FDS");
- if (!e) {
- r = 0;
- goto finish;
- }
-
- errno = 0;
- l = strtoul(e, &p, 10);
-
- if (errno != 0) {
- r = -errno;
- goto finish;
- }
-
- if (!p || p == e || *p) {
- r = -EINVAL;
- goto finish;
- }
-
- for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) l; fd ++) {
- int flags;
-
- flags = fcntl(fd, F_GETFD);
- if (flags < 0) {
- r = -errno;
- goto finish;
- }
-
- if (flags & FD_CLOEXEC)
- continue;
-
- if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) {
- r = -errno;
- goto finish;
- }
- }
-
- r = (int) l;
-
-finish:
- if (unset_environment) {
- unsetenv("LISTEN_PID");
- unsetenv("LISTEN_FDS");
- }
-
- return r;
-#endif
-}
-
-_sd_export_ int sd_is_fifo(int fd, const char *path) {
- struct stat st_fd;
-
- if (fd < 0)
- return -EINVAL;
-
- if (fstat(fd, &st_fd) < 0)
- return -errno;
-
- if (!S_ISFIFO(st_fd.st_mode))
- return 0;
-
- if (path) {
- struct stat st_path;
-
- if (stat(path, &st_path) < 0) {
-
- if (errno == ENOENT || errno == ENOTDIR)
- return 0;
-
- return -errno;
- }
-
- return
- st_path.st_dev == st_fd.st_dev &&
- st_path.st_ino == st_fd.st_ino;
- }
-
- return 1;
-}
-
-_sd_export_ int sd_is_special(int fd, const char *path) {
- struct stat st_fd;
-
- if (fd < 0)
- return -EINVAL;
-
- if (fstat(fd, &st_fd) < 0)
- return -errno;
-
- if (!S_ISREG(st_fd.st_mode) && !S_ISCHR(st_fd.st_mode))
- return 0;
-
- if (path) {
- struct stat st_path;
-
- if (stat(path, &st_path) < 0) {
-
- if (errno == ENOENT || errno == ENOTDIR)
- return 0;
-
- return -errno;
- }
-
- if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode))
- return
- st_path.st_dev == st_fd.st_dev &&
- st_path.st_ino == st_fd.st_ino;
- else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode))
- return st_path.st_rdev == st_fd.st_rdev;
- else
- return 0;
- }
-
- return 1;
-}
-
-static int sd_is_socket_internal(int fd, int type, int listening) {
- struct stat st_fd;
-
- if (fd < 0 || type < 0)
- return -EINVAL;
-
- if (fstat(fd, &st_fd) < 0)
- return -errno;
-
- if (!S_ISSOCK(st_fd.st_mode))
- return 0;
-
- if (type != 0) {
- int other_type = 0;
- socklen_t l = sizeof(other_type);
-
- if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0)
- return -errno;
-
- if (l != sizeof(other_type))
- return -EINVAL;
-
- if (other_type != type)
- return 0;
- }
-
- if (listening >= 0) {
- int accepting = 0;
- socklen_t l = sizeof(accepting);
-
- if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0)
- return -errno;
-
- if (l != sizeof(accepting))
- return -EINVAL;
-
- if (!accepting != !listening)
- return 0;
- }
-
- return 1;
-}
-
-union sockaddr_union {
- struct sockaddr sa;
- struct sockaddr_in in4;
- struct sockaddr_in6 in6;
- struct sockaddr_un un;
- struct sockaddr_storage storage;
-};
-
-_sd_export_ int sd_is_socket(int fd, int family, int type, int listening) {
- int r;
-
- if (family < 0)
- return -EINVAL;
-
- r = sd_is_socket_internal(fd, type, listening);
- if (r <= 0)
- return r;
-
- if (family > 0) {
- union sockaddr_union sockaddr;
- socklen_t l;
-
- memset(&sockaddr, 0, sizeof(sockaddr));
- l = sizeof(sockaddr);
-
- if (getsockname(fd, &sockaddr.sa, &l) < 0)
- return -errno;
-
- if (l < sizeof(sa_family_t))
- return -EINVAL;
-
- return sockaddr.sa.sa_family == family;
- }
-
- return 1;
-}
-
-_sd_export_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) {
- union sockaddr_union sockaddr;
- socklen_t l;
- int r;
-
- if (family != 0 && family != AF_INET && family != AF_INET6)
- return -EINVAL;
-
- r = sd_is_socket_internal(fd, type, listening);
- if (r <= 0)
- return r;
-
- memset(&sockaddr, 0, sizeof(sockaddr));
- l = sizeof(sockaddr);
-
- if (getsockname(fd, &sockaddr.sa, &l) < 0)
- return -errno;
-
- if (l < sizeof(sa_family_t))
- return -EINVAL;
-
- if (sockaddr.sa.sa_family != AF_INET &&
- sockaddr.sa.sa_family != AF_INET6)
- return 0;
-
- if (family > 0)
- if (sockaddr.sa.sa_family != family)
- return 0;
-
- if (port > 0) {
- if (sockaddr.sa.sa_family == AF_INET) {
- if (l < sizeof(struct sockaddr_in))
- return -EINVAL;
-
- return htons(port) == sockaddr.in4.sin_port;
- } else {
- if (l < sizeof(struct sockaddr_in6))
- return -EINVAL;
-
- return htons(port) == sockaddr.in6.sin6_port;
- }
- }
-
- return 1;
-}
-
-_sd_export_ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) {
- union sockaddr_union sockaddr;
- socklen_t l;
- int r;
-
- r = sd_is_socket_internal(fd, type, listening);
- if (r <= 0)
- return r;
-
- memset(&sockaddr, 0, sizeof(sockaddr));
- l = sizeof(sockaddr);
-
- if (getsockname(fd, &sockaddr.sa, &l) < 0)
- return -errno;
-
- if (l < sizeof(sa_family_t))
- return -EINVAL;
-
- if (sockaddr.sa.sa_family != AF_UNIX)
- return 0;
-
- if (path) {
- if (length <= 0)
- length = strlen(path);
-
- if (length <= 0)
- /* Unnamed socket */
- return l == offsetof(struct sockaddr_un, sun_path);
-
- if (path[0])
- /* Normal path socket */
- return
- (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) &&
- memcmp(path, sockaddr.un.sun_path, length+1) == 0;
- else
- /* Abstract namespace socket */
- return
- (l == offsetof(struct sockaddr_un, sun_path) + length) &&
- memcmp(path, sockaddr.un.sun_path, length) == 0;
- }
-
- return 1;
-}
-
-_sd_export_ int sd_is_mq(int fd, const char *path) {
-#if !defined(__linux__)
- return 0;
-#else
- struct mq_attr attr;
-
- if (fd < 0)
- return -EINVAL;
-
- if (mq_getattr(fd, &attr) < 0)
- return -errno;
-
- if (path) {
- char fpath[PATH_MAX];
- struct stat a, b;
-
- if (path[0] != '/')
- return -EINVAL;
-
- if (fstat(fd, &a) < 0)
- return -errno;
-
- strncpy(stpcpy(fpath, "/dev/mqueue"), path, sizeof(fpath) - 12);
- fpath[sizeof(fpath)-1] = 0;
-
- if (stat(fpath, &b) < 0)
- return -errno;
-
- if (a.st_dev != b.st_dev ||
- a.st_ino != b.st_ino)
- return 0;
- }
-
- return 1;
-#endif
-}
-
-_sd_export_ int sd_notify(int unset_environment, const char *state) {
-#if defined(DISABLE_SYSTEMD) || !defined(__linux__) || !defined(SOCK_CLOEXEC)
- return 0;
-#else
- int fd = -1, r;
- struct msghdr msghdr;
- struct iovec iovec;
- union sockaddr_union sockaddr;
- const char *e;
-
- if (!state) {
- r = -EINVAL;
- goto finish;
- }
-
- e = getenv("NOTIFY_SOCKET");
- if (!e)
- return 0;
-
- /* Must be an abstract socket, or an absolute path */
- if ((e[0] != '@' && e[0] != '/') || e[1] == 0) {
- r = -EINVAL;
- goto finish;
- }
-
- fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
- if (fd < 0) {
- r = -errno;
- goto finish;
- }
-
- memset(&sockaddr, 0, sizeof(sockaddr));
- sockaddr.sa.sa_family = AF_UNIX;
- strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path));
-
- if (sockaddr.un.sun_path[0] == '@')
- sockaddr.un.sun_path[0] = 0;
-
- memset(&iovec, 0, sizeof(iovec));
- iovec.iov_base = (char*) state;
- iovec.iov_len = strlen(state);
-
- memset(&msghdr, 0, sizeof(msghdr));
- msghdr.msg_name = &sockaddr;
- msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(e);
-
- if (msghdr.msg_namelen > sizeof(struct sockaddr_un))
- msghdr.msg_namelen = sizeof(struct sockaddr_un);
-
- msghdr.msg_iov = &iovec;
- msghdr.msg_iovlen = 1;
-
- if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
- r = -errno;
- goto finish;
- }
-
- r = 1;
-
-finish:
- if (unset_environment)
- unsetenv("NOTIFY_SOCKET");
-
- if (fd >= 0)
- close(fd);
-
- return r;
-#endif
-}
-
-_sd_export_ int sd_notifyf(int unset_environment, const char *format, ...) {
-#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
- return 0;
-#else
- va_list ap;
- char *p = NULL;
- int r;
-
- va_start(ap, format);
- r = vasprintf(&p, format, ap);
- va_end(ap);
-
- if (r < 0 || !p)
- return -ENOMEM;
-
- r = sd_notify(unset_environment, p);
- free(p);
-
- return r;
-#endif
-}
-
-_sd_export_ int sd_booted(void) {
-#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
- return 0;
-#else
-
- struct stat a, b;
-
- /* We simply test whether the systemd cgroup hierarchy is
- * mounted */
-
- if (lstat("/sys/fs/cgroup", &a) < 0)
- return 0;
-
- if (lstat("/sys/fs/cgroup/systemd", &b) < 0)
- return 0;
-
- return a.st_dev != b.st_dev;
-#endif
-}
diff --git a/src/libsystemd-id128/.gitignore b/src/libsystemd-id128/.gitignore
deleted file mode 100644
index 144adf9bea..0000000000
--- a/src/libsystemd-id128/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/libsystemd-id128.pc
diff --git a/src/libsystemd-id128/Makefile b/src/libsystemd-id128/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/libsystemd-id128/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/libsystemd-id128/libsystemd-id128.pc.in b/src/libsystemd-id128/libsystemd-id128.pc.in
deleted file mode 100644
index bb65ffde33..0000000000
--- a/src/libsystemd-id128/libsystemd-id128.pc.in
+++ /dev/null
@@ -1,18 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-
-Name: systemd
-Description: systemd 128 Bit ID Utility Library
-URL: @PACKAGE_URL@
-Version: @PACKAGE_VERSION@
-Libs: -L${libdir} -lsystemd-id128
-Cflags: -I${includedir}
diff --git a/src/libsystemd-id128/libsystemd-id128.sym b/src/libsystemd-id128/libsystemd-id128.sym
deleted file mode 100644
index 604c0026c6..0000000000
--- a/src/libsystemd-id128/libsystemd-id128.sym
+++ /dev/null
@@ -1,21 +0,0 @@
-/***
- This file is part of systemd.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-***/
-
-/* Original symbols from systemd v38 */
-
-LIBSYSTEMD_ID128_38 {
-global:
- sd_id128_to_string;
- sd_id128_from_string;
- sd_id128_randomize;
- sd_id128_get_machine;
- sd_id128_get_boot;
-local:
- *;
-};
diff --git a/src/libsystemd-id128/sd-id128.c b/src/libsystemd-id128/sd-id128.c
deleted file mode 100644
index 4286ae7d14..0000000000
--- a/src/libsystemd-id128/sd-id128.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include "sd-id128.h"
-
-#include "util.h"
-#include "macro.h"
-
-_public_ char *sd_id128_to_string(sd_id128_t id, char s[33]) {
- unsigned n;
-
- if (!s)
- return NULL;
-
- for (n = 0; n < 16; n++) {
- s[n*2] = hexchar(id.bytes[n] >> 4);
- s[n*2+1] = hexchar(id.bytes[n] & 0xF);
- }
-
- s[32] = 0;
-
- return s;
-}
-
-_public_ int sd_id128_from_string(const char s[33], sd_id128_t *ret) {
- unsigned n;
- sd_id128_t t;
-
- if (!s)
- return -EINVAL;
- if (!ret)
- return -EINVAL;
-
- for (n = 0; n < 16; n++) {
- int a, b;
-
- a = unhexchar(s[n*2]);
- if (a < 0)
- return -EINVAL;
-
- b = unhexchar(s[n*2+1]);
- if (b < 0)
- return -EINVAL;
-
- t.bytes[n] = (a << 4) | b;
- }
-
- if (s[32] != 0)
- return -EINVAL;
-
- *ret = t;
- return 0;
-}
-
-static sd_id128_t make_v4_uuid(sd_id128_t id) {
- /* Stolen from generate_random_uuid() of drivers/char/random.c
- * in the kernel sources */
-
- /* Set UUID version to 4 --- truly random generation */
- id.bytes[6] = (id.bytes[6] & 0x0F) | 0x40;
-
- /* Set the UUID variant to DCE */
- id.bytes[8] = (id.bytes[8] & 0x3F) | 0x80;
-
- return id;
-}
-
-_public_ int sd_id128_get_machine(sd_id128_t *ret) {
- static __thread sd_id128_t saved_machine_id;
- static __thread bool saved_machine_id_valid = false;
- int fd;
- char buf[32];
- ssize_t k;
- unsigned j;
- sd_id128_t t;
-
- if (!ret)
- return -EINVAL;
-
- if (saved_machine_id_valid) {
- *ret = saved_machine_id;
- return 0;
- }
-
- fd = open("/etc/machine-id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0)
- return -errno;
-
- k = loop_read(fd, buf, 32, false);
- close_nointr_nofail(fd);
-
- if (k < 0)
- return (int) k;
-
- if (k < 32)
- return -EIO;
-
- for (j = 0; j < 16; j++) {
- int a, b;
-
- a = unhexchar(buf[j*2]);
- b = unhexchar(buf[j*2+1]);
-
- if (a < 0 || b < 0)
- return -EIO;
-
- t.bytes[j] = a << 4 | b;
- }
-
- saved_machine_id = t;
- saved_machine_id_valid = true;
-
- *ret = t;
- return 0;
-}
-
-_public_ int sd_id128_get_boot(sd_id128_t *ret) {
- static __thread sd_id128_t saved_boot_id;
- static __thread bool saved_boot_id_valid = false;
- int fd;
- char buf[36];
- ssize_t k;
- unsigned j;
- sd_id128_t t;
- char *p;
-
- if (!ret)
- return -EINVAL;
-
- if (saved_boot_id_valid) {
- *ret = saved_boot_id;
- return 0;
- }
-
- fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0)
- return -errno;
-
- k = loop_read(fd, buf, 36, false);
- close_nointr_nofail(fd);
-
- if (k < 0)
- return (int) k;
-
- if (k < 36)
- return -EIO;
-
- for (j = 0, p = buf; j < 16; j++) {
- int a, b;
-
- if (*p == '-')
- p++;
-
- a = unhexchar(p[0]);
- b = unhexchar(p[1]);
-
- if (a < 0 || b < 0)
- return -EIO;
-
- t.bytes[j] = a << 4 | b;
-
- p += 2;
- }
-
- saved_boot_id = t;
- saved_boot_id_valid = true;
-
- *ret = t;
- return 0;
-}
-
-_public_ int sd_id128_randomize(sd_id128_t *ret) {
- int fd;
- ssize_t k;
- sd_id128_t t;
-
- if (!ret)
- return -EINVAL;
-
- fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0)
- return -errno;
-
- k = loop_read(fd, &t, 16, false);
- close_nointr_nofail(fd);
-
- if (k < 0)
- return (int) k;
-
- if (k < 16)
- return -EIO;
-
- /* Turn this into a valid v4 UUID, to be nice. Note that we
- * only guarantee this for newly generated UUIDs, not for
- * pre-existing ones.*/
-
- *ret = make_v4_uuid(t);
- return 0;
-}
diff --git a/src/libudev/.gitignore b/src/libudev/.gitignore
deleted file mode 100644
index 0c8a5d5231..0000000000
--- a/src/libudev/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/libudev.pc
diff --git a/src/libudev/Makefile b/src/libudev/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/libudev/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/locale/.gitignore b/src/locale/.gitignore
deleted file mode 100644
index b1e0ba755e..0000000000
--- a/src/locale/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-org.freedesktop.locale1.policy
diff --git a/src/locale/Makefile b/src/locale/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/locale/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/locale/generate-kbd-model-map b/src/locale/generate-kbd-model-map
deleted file mode 100755
index 624c5179fa..0000000000
--- a/src/locale/generate-kbd-model-map
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/python
-
-import sys
-import system_config_keyboard.keyboard_models
-
-def strdash(s):
- return s.strip() or '-'
-
-def tab_extend(s, n=1):
- s = strdash(s)
- k = len(s) // 8
-
- if k >= n:
- f = 1
- else:
- f = n - k
-
- return s + '\t'*f
-
-
-models = system_config_keyboard.keyboard_models.KeyboardModels().get_models()
-
-print "# Generated from system-config-keyboard's model list"
-print "# consolelayout\t\txlayout\txmodel\t\txvariant\txoptions"
-
-for key, value in reversed(models.items()):
- options = "terminate:ctrl_alt_bksp"
- if value[4]:
- options += ',' + value[4]
-
- print ''.join((tab_extend(key, 3), tab_extend(value[1]),
- tab_extend(value[2], 2), tab_extend(value[3], 2),
- options))
diff --git a/src/locale/kbd-model-map b/src/locale/kbd-model-map
deleted file mode 100644
index a895880269..0000000000
--- a/src/locale/kbd-model-map
+++ /dev/null
@@ -1,72 +0,0 @@
-# Generated from system-config-keyboard's model list
-# consolelayout xlayout xmodel xvariant xoptions
-sg ch pc105 de_nodeadkeys terminate:ctrl_alt_bksp
-nl nl pc105 - terminate:ctrl_alt_bksp
-mk-utf mkd,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
-trq tr pc105 - terminate:ctrl_alt_bksp
-guj in,us pc105 guj terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
-uk gb pc105 - terminate:ctrl_alt_bksp
-is-latin1 is pc105 - terminate:ctrl_alt_bksp
-de de pc105 - terminate:ctrl_alt_bksp
-gur gur,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
-la-latin1 latam pc105 - terminate:ctrl_alt_bksp
-us us pc105+inet - terminate:ctrl_alt_bksp
-ko kr pc105 - terminate:ctrl_alt_bksp
-ro-std ro pc105 std terminate:ctrl_alt_bksp
-de-latin1 de pc105 - terminate:ctrl_alt_bksp
-tml-inscript in,us pc105 tam terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
-slovene si pc105 - terminate:ctrl_alt_bksp
-hu101 hu pc105 qwerty terminate:ctrl_alt_bksp
-jp106 jp jp106 - terminate:ctrl_alt_bksp
-croat hr pc105 - terminate:ctrl_alt_bksp
-ben-probhat in,us pc105 ben_probhat terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
-fi-latin1 fi pc105 - terminate:ctrl_alt_bksp
-it2 it pc105 - terminate:ctrl_alt_bksp
-hu hu pc105 - terminate:ctrl_alt_bksp
-sr-latin rs pc105 latin terminate:ctrl_alt_bksp
-fi fi pc105 - terminate:ctrl_alt_bksp
-fr_CH ch pc105 fr terminate:ctrl_alt_bksp
-dk-latin1 dk pc105 - terminate:ctrl_alt_bksp
-fr fr pc105 - terminate:ctrl_alt_bksp
-it it pc105 - terminate:ctrl_alt_bksp
-tml-uni in,us pc105 tam_TAB terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
-ua-utf ua,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
-fr-latin1 fr pc105 - terminate:ctrl_alt_bksp
-sg-latin1 ch pc105 de_nodeadkeys terminate:ctrl_alt_bksp
-be-latin1 be pc105 - terminate:ctrl_alt_bksp
-dk dk pc105 - terminate:ctrl_alt_bksp
-fr-pc fr pc105 - terminate:ctrl_alt_bksp
-bg_pho-utf8 bg,us pc105 ,phonetic terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
-it-ibm it pc105 - terminate:ctrl_alt_bksp
-cz-us-qwertz cz,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
-ar-digits ara,us pc105 digits terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
-br-abnt2 br abnt2 - terminate:ctrl_alt_bksp
-ro ro pc105 - terminate:ctrl_alt_bksp
-us-acentos us pc105 intl terminate:ctrl_alt_bksp
-pt-latin1 pt pc105 - terminate:ctrl_alt_bksp
-ro-std-cedilla ro pc105 std_cedilla terminate:ctrl_alt_bksp
-tj tj pc105 - terminate:ctrl_alt_bksp
-ar-qwerty ara,us pc105 qwerty terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
-ar-azerty-digits ara,us pc105 azerty_digits terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
-ben in,us pc105 ben terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
-de-latin1-nodeadkeys de pc105 nodeadkeys terminate:ctrl_alt_bksp
-no no pc105 - terminate:ctrl_alt_bksp
-bg_bds-utf8 bg,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
-dvorak us pc105 dvorak terminate:ctrl_alt_bksp
-ru ru,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
-cz-lat2 cz pc105 qwerty terminate:ctrl_alt_bksp
-pl2 pl pc105 - terminate:ctrl_alt_bksp
-es es pc105 - terminate:ctrl_alt_bksp
-ro-cedilla ro pc105 cedilla terminate:ctrl_alt_bksp
-ie ie pc105 - terminate:ctrl_alt_bksp
-ar-azerty ara,us pc105 azerty terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
-ar-qwerty-digits ara,us pc105 qwerty_digits terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
-et ee pc105 - terminate:ctrl_alt_bksp
-sk-qwerty sk pc105 - terminate:ctrl_alt_bksp,qwerty
-dev dev,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
-fr-latin9 fr pc105 latin9 terminate:ctrl_alt_bksp
-fr_CH-latin1 ch pc105 fr terminate:ctrl_alt_bksp
-cf ca(fr) pc105 - terminate:ctrl_alt_bksp
-sv-latin1 se pc105 - terminate:ctrl_alt_bksp
-sr-cy rs pc105 - terminate:ctrl_alt_bksp
-gr gr,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
diff --git a/src/locale/localectl.c b/src/locale/localectl.c
deleted file mode 100644
index fa73bcaac6..0000000000
--- a/src/locale/localectl.c
+++ /dev/null
@@ -1,781 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <locale.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <string.h>
-#include <ftw.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-
-#include "dbus-common.h"
-#include "util.h"
-#include "spawn-polkit-agent.h"
-#include "build.h"
-#include "strv.h"
-#include "pager.h"
-#include "set.h"
-#include "path-util.h"
-
-static bool arg_no_pager = false;
-static enum transport {
- TRANSPORT_NORMAL,
- TRANSPORT_SSH,
- TRANSPORT_POLKIT
-} arg_transport = TRANSPORT_NORMAL;
-static bool arg_ask_password = true;
-static const char *arg_host = NULL;
-static bool arg_convert = true;
-
-static void pager_open_if_enabled(void) {
-
- if (arg_no_pager)
- return;
-
- pager_open();
-}
-
-static void polkit_agent_open_if_enabled(void) {
-
- /* Open the polkit agent as a child process if necessary */
-
- if (!arg_ask_password)
- return;
-
- polkit_agent_open();
-}
-
-typedef struct StatusInfo {
- char **locale;
- const char *vconsole_keymap;
- const char *vconsole_keymap_toggle;
- const char *x11_layout;
- const char *x11_model;
- const char *x11_variant;
- const char *x11_options;
-} StatusInfo;
-
-static void print_status_info(StatusInfo *i) {
- assert(i);
-
- if (strv_isempty(i->locale))
- puts(" System Locale: n/a\n");
- else {
- char **j;
-
- printf(" System Locale: %s\n", i->locale[0]);
- STRV_FOREACH(j, i->locale + 1)
- printf(" %s\n", *j);
- }
-
- printf(" VC Keymap: %s\n", strna(i->vconsole_keymap));
- if (!isempty(i->vconsole_keymap_toggle))
- printf("VC Toggle Keymap: %s\n", i->vconsole_keymap_toggle);
-
- printf(" X11 Layout: %s\n", strna(i->x11_layout));
- if (!isempty(i->x11_model))
- printf(" X11 Model: %s\n", i->x11_model);
- if (!isempty(i->x11_variant))
- printf(" X11 Variant: %s\n", i->x11_variant);
- if (!isempty(i->x11_options))
- printf(" X11 Options: %s\n", i->x11_options);
-}
-
-static int status_property(const char *name, DBusMessageIter *iter, StatusInfo *i) {
- int r;
-
- assert(name);
- assert(iter);
-
- switch (dbus_message_iter_get_arg_type(iter)) {
-
- case DBUS_TYPE_STRING: {
- const char *s;
-
- dbus_message_iter_get_basic(iter, &s);
- if (!isempty(s)) {
- if (streq(name, "VConsoleKeymap"))
- i->vconsole_keymap = s;
- else if (streq(name, "VConsoleKeymapToggle"))
- i->vconsole_keymap_toggle = s;
- else if (streq(name, "X11Layout"))
- i->x11_layout = s;
- else if (streq(name, "X11Model"))
- i->x11_model = s;
- else if (streq(name, "X11Variant"))
- i->x11_variant = s;
- else if (streq(name, "X11Options"))
- i->x11_options = s;
- }
- break;
- }
-
- case DBUS_TYPE_ARRAY:
-
- if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
- char **l;
-
- r = bus_parse_strv_iter(iter, &l);
- if (r < 0)
- return r;
-
- if (streq(name, "Locale")) {
- strv_free(i->locale);
- i->locale = l;
- l = NULL;
- }
-
- strv_free(l);
- }
- }
-
- return 0;
-}
-
-static int show_status(DBusConnection *bus, char **args, unsigned n) {
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- const char *interface = "";
- int r;
- DBusMessageIter iter, sub, sub2, sub3;
- StatusInfo info;
-
- assert(args);
-
- r = bus_method_call_with_reply(
- bus,
- "org.freedesktop.locale1",
- "/org/freedesktop/locale1",
- "org.freedesktop.DBus.Properties",
- "GetAll",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &interface,
- DBUS_TYPE_INVALID);
- if (r < 0)
- return r;
-
- if (!dbus_message_iter_init(reply, &iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
- log_error("Failed to parse reply.");
- return -EIO;
- }
-
- zero(info);
- dbus_message_iter_recurse(&iter, &sub);
-
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- const char *name;
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
- log_error("Failed to parse reply.");
- return -EIO;
- }
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
- log_error("Failed to parse reply.");
- return -EIO;
- }
-
- if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
- log_error("Failed to parse reply.");
- return -EIO;
- }
-
- dbus_message_iter_recurse(&sub2, &sub3);
-
- r = status_property(name, &sub3, &info);
- if (r < 0) {
- log_error("Failed to parse reply.");
- return r;
- }
-
- dbus_message_iter_next(&sub);
- }
-
- print_status_info(&info);
- strv_free(info.locale);
- return 0;
-}
-
-static int set_locale(DBusConnection *bus, char **args, unsigned n) {
- _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
- dbus_bool_t interactive = true;
- DBusError error;
- DBusMessageIter iter;
- int r;
-
- assert(bus);
- assert(args);
-
- dbus_error_init(&error);
-
- polkit_agent_open_if_enabled();
-
- m = dbus_message_new_method_call(
- "org.freedesktop.locale1",
- "/org/freedesktop/locale1",
- "org.freedesktop.locale1",
- "SetLocale");
- if (!m)
- return log_oom();
-
- dbus_message_iter_init_append(m, &iter);
-
- r = bus_append_strv_iter(&iter, args + 1);
- if (r < 0)
- return log_oom();
-
- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &interactive))
- return log_oom();
-
- reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
- if (!reply) {
- log_error("Failed to issue method call: %s", bus_error_message(&error));
- r = -EIO;
- goto finish;
- }
-
- r = 0;
-
-finish:
- dbus_error_free(&error);
- return r;
-}
-
-static int list_locales(DBusConnection *bus, char **args, unsigned n) {
- /* Stolen from glibc... */
-
- struct locarhead {
- uint32_t magic;
- /* Serial number. */
- uint32_t serial;
- /* Name hash table. */
- uint32_t namehash_offset;
- uint32_t namehash_used;
- uint32_t namehash_size;
- /* String table. */
- uint32_t string_offset;
- uint32_t string_used;
- uint32_t string_size;
- /* Table with locale records. */
- uint32_t locrectab_offset;
- uint32_t locrectab_used;
- uint32_t locrectab_size;
- /* MD5 sum hash table. */
- uint32_t sumhash_offset;
- uint32_t sumhash_used;
- uint32_t sumhash_size;
- };
-
- struct namehashent {
- /* Hash value of the name. */
- uint32_t hashval;
- /* Offset of the name in the string table. */
- uint32_t name_offset;
- /* Offset of the locale record. */
- uint32_t locrec_offset;
- };
-
- const struct locarhead *h;
- const struct namehashent *e;
- const void *p = MAP_FAILED;
- _cleanup_close_ int fd = -1;
- _cleanup_strv_free_ char **l = NULL;
- char **j;
- Set *locales;
- size_t sz = 0;
- struct stat st;
- unsigned i;
- int r;
-
- locales = set_new(string_hash_func, string_compare_func);
- if (!locales)
- return log_oom();
-
- fd = open("/usr/lib/locale/locale-archive", O_RDONLY|O_NOCTTY|O_CLOEXEC);
- if (fd < 0) {
- log_error("Failed to open locale archive: %m");
- r = -errno;
- goto finish;
- }
-
- if (fstat(fd, &st) < 0) {
- log_error("fstat() failed: %m");
- r = -errno;
- goto finish;
- }
-
- if (!S_ISREG(st.st_mode)) {
- log_error("Archive file is not regular");
- r = -EBADMSG;
- goto finish;
- }
-
- if (st.st_size < (off_t) sizeof(struct locarhead)) {
- log_error("Archive has invalid size");
- r = -EBADMSG;
- goto finish;
- }
-
- p = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
- if (p == MAP_FAILED) {
- log_error("Failed to map archive: %m");
- r = -errno;
- goto finish;
- }
-
- h = (const struct locarhead *) p;
- if (h->magic != 0xde020109 ||
- h->namehash_offset + h->namehash_size > st.st_size ||
- h->string_offset + h->string_size > st.st_size ||
- h->locrectab_offset + h->locrectab_size > st.st_size ||
- h->sumhash_offset + h->sumhash_size > st.st_size) {
- log_error("Invalid archive file.");
- r = -EBADMSG;
- goto finish;
- }
-
- e = (const struct namehashent*) ((const uint8_t*) p + h->namehash_offset);
- for (i = 0; i < h->namehash_size; i++) {
- char *z;
-
- if (e[i].locrec_offset == 0)
- continue;
-
- z = strdup((char*) p + e[i].name_offset);
- if (!z) {
- r = log_oom();
- goto finish;
- }
-
- r = set_put(locales, z);
- if (r < 0) {
- free(z);
- log_error("Failed to add locale: %s", strerror(-r));
- goto finish;
- }
- }
-
- l = set_get_strv(locales);
- if (!l) {
- r = log_oom();
- goto finish;
- }
-
- set_free(locales);
- locales = NULL;
-
- strv_sort(l);
-
- pager_open_if_enabled();
-
- STRV_FOREACH(j, l)
- puts(*j);
-
- r = 0;
-
-finish:
- if (p != MAP_FAILED)
- munmap((void*) p, sz);
-
- set_free_free(locales);
-
- return r;
-}
-
-static int set_vconsole_keymap(DBusConnection *bus, char **args, unsigned n) {
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- dbus_bool_t interactive = true, b;
- const char *map, *toggle_map;
-
- assert(bus);
- assert(args);
-
- if (n > 3) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
- polkit_agent_open_if_enabled();
-
- map = args[1];
- toggle_map = n > 2 ? args[2] : "";
- b = arg_convert;
-
- return bus_method_call_with_reply(
- bus,
- "org.freedesktop.locale1",
- "/org/freedesktop/locale1",
- "org.freedesktop.locale1",
- "SetVConsoleKeyboard",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &map,
- DBUS_TYPE_STRING, &toggle_map,
- DBUS_TYPE_BOOLEAN, &b,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID);
-}
-
-static Set *keymaps = NULL;
-
-static int nftw_cb(
- const char *fpath,
- const struct stat *sb,
- int tflag,
- struct FTW *ftwbuf) {
-
- char *p, *e;
- int r;
-
- if (tflag != FTW_F)
- return 0;
-
- if (!endswith(fpath, ".map") &&
- !endswith(fpath, ".map.gz"))
- return 0;
-
- p = strdup(path_get_file_name(fpath));
- if (!p)
- return log_oom();
-
- e = endswith(p, ".map");
- if (e)
- *e = 0;
-
- e = endswith(p, ".map.gz");
- if (e)
- *e = 0;
-
- r = set_put(keymaps, p);
- if (r == -EEXIST)
- free(p);
- else if (r < 0) {
- log_error("Can't add keymap: %s", strerror(-r));
- free(p);
- return r;
- }
-
- return 0;
-}
-
-static int list_vconsole_keymaps(DBusConnection *bus, char **args, unsigned n) {
- char _cleanup_strv_free_ **l = NULL;
- char **i;
-
- keymaps = set_new(string_hash_func, string_compare_func);
- if (!keymaps)
- return log_oom();
-
- nftw("/usr/share/kbd/keymaps/", nftw_cb, 20, FTW_MOUNT|FTW_PHYS);
- nftw("/usr/lib/kbd/keymaps/", nftw_cb, 20, FTW_MOUNT|FTW_PHYS);
- nftw("/lib/kbd/keymaps/", nftw_cb, 20, FTW_MOUNT|FTW_PHYS);
-
- l = set_get_strv(keymaps);
- if (!l) {
- set_free_free(keymaps);
- return log_oom();
- }
-
- set_free(keymaps);
-
- if (strv_isempty(l)) {
- log_error("Couldn't find any console keymaps.");
- return -ENOENT;
- }
-
- strv_sort(l);
-
- pager_open_if_enabled();
-
- STRV_FOREACH(i, l)
- puts(*i);
-
-
- return 0;
-}
-
-static int set_x11_keymap(DBusConnection *bus, char **args, unsigned n) {
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- dbus_bool_t interactive = true, b;
- const char *layout, *model, *variant, *options;
-
- assert(bus);
- assert(args);
-
- if (n > 5) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
- polkit_agent_open_if_enabled();
-
- layout = args[1];
- model = n > 2 ? args[2] : "";
- variant = n > 3 ? args[3] : "";
- options = n > 3 ? args[4] : "";
- b = arg_convert;
-
- return bus_method_call_with_reply(
- bus,
- "org.freedesktop.locale1",
- "/org/freedesktop/locale1",
- "org.freedesktop.locale1",
- "SetX11Keyboard",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &layout,
- DBUS_TYPE_STRING, &model,
- DBUS_TYPE_STRING, &variant,
- DBUS_TYPE_STRING, &options,
- DBUS_TYPE_BOOLEAN, &b,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID);
-}
-
-static int help(void) {
-
- printf("%s [OPTIONS...] COMMAND ...\n\n"
- "Query or change system time and date settings.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --no-convert Don't convert keyboard mappings\n"
- " --no-pager Do not pipe output into a pager\n"
- " --no-ask-password Do not prompt for password\n"
- " -H --host=[USER@]HOST Operate on remote host\n\n"
- "Commands:\n"
- " status Show current locale settings\n"
- " set-locale LOCALE... Set system locale\n"
- " list-locales Show known locales\n"
- " set-keymap MAP [MAP] Set virtual console keyboard mapping\n"
- " list-keymaps Show known virtual console keyboard mappings\n"
- " set-x11-keymap LAYOUT [MODEL] [VARIANT] [OPTIONS]\n"
- " Set X11 keyboard mapping\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100,
- ARG_NO_PAGER,
- ARG_NO_CONVERT,
- ARG_NO_ASK_PASSWORD
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "no-pager", no_argument, NULL, ARG_NO_PAGER },
- { "host", required_argument, NULL, 'H' },
- { "privileged", no_argument, NULL, 'P' },
- { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
- { "no-convert", no_argument, NULL, ARG_NO_CONVERT },
- { NULL, 0, NULL, 0 }
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "has:H:P", options, NULL)) >= 0) {
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(DISTRIBUTION);
- puts(SYSTEMD_FEATURES);
- return 0;
-
- case 'P':
- arg_transport = TRANSPORT_POLKIT;
- break;
-
- case 'H':
- arg_transport = TRANSPORT_SSH;
- arg_host = optarg;
- break;
-
- case ARG_NO_CONVERT:
- arg_convert = false;
- break;
-
- case ARG_NO_PAGER:
- arg_no_pager = true;
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- log_error("Unknown option code %c", c);
- return -EINVAL;
- }
- }
-
- return 1;
-}
-
-static int localectl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
-
- static const struct {
- const char* verb;
- const enum {
- MORE,
- LESS,
- EQUAL
- } argc_cmp;
- const int argc;
- int (* const dispatch)(DBusConnection *bus, char **args, unsigned n);
- } verbs[] = {
- { "status", LESS, 1, show_status },
- { "set-locale", MORE, 2, set_locale },
- { "list-locales", EQUAL, 1, list_locales },
- { "set-keymap", MORE, 2, set_vconsole_keymap },
- { "list-keymaps", EQUAL, 1, list_vconsole_keymaps },
- { "set-x11-keymap", MORE, 2, set_x11_keymap },
- };
-
- int left;
- unsigned i;
-
- assert(argc >= 0);
- assert(argv);
- assert(error);
-
- left = argc - optind;
-
- if (left <= 0)
- /* Special rule: no arguments means "status" */
- i = 0;
- else {
- if (streq(argv[optind], "help")) {
- help();
- return 0;
- }
-
- for (i = 0; i < ELEMENTSOF(verbs); i++)
- if (streq(argv[optind], verbs[i].verb))
- break;
-
- if (i >= ELEMENTSOF(verbs)) {
- log_error("Unknown operation %s", argv[optind]);
- return -EINVAL;
- }
- }
-
- switch (verbs[i].argc_cmp) {
-
- case EQUAL:
- if (left != verbs[i].argc) {
- log_error("Invalid number of arguments.");
- return -EINVAL;
- }
-
- break;
-
- case MORE:
- if (left < verbs[i].argc) {
- log_error("Too few arguments.");
- return -EINVAL;
- }
-
- break;
-
- case LESS:
- if (left > verbs[i].argc) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
- break;
-
- default:
- assert_not_reached("Unknown comparison operator.");
- }
-
- if (!bus) {
- log_error("Failed to get D-Bus connection: %s", error->message);
- return -EIO;
- }
-
- return verbs[i].dispatch(bus, argv + optind, left);
-}
-
-int main(int argc, char *argv[]) {
- int r, retval = EXIT_FAILURE;
- DBusConnection *bus = NULL;
- DBusError error;
-
- dbus_error_init(&error);
-
- setlocale(LC_ALL, "");
- log_parse_environment();
- log_open();
-
- r = parse_argv(argc, argv);
- if (r < 0)
- goto finish;
- else if (r == 0) {
- retval = EXIT_SUCCESS;
- goto finish;
- }
-
- if (arg_transport == TRANSPORT_NORMAL)
- bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
- else if (arg_transport == TRANSPORT_POLKIT)
- bus_connect_system_polkit(&bus, &error);
- else if (arg_transport == TRANSPORT_SSH)
- bus_connect_system_ssh(NULL, arg_host, &bus, &error);
- else
- assert_not_reached("Uh, invalid transport...");
-
- r = localectl_main(bus, argc, argv, &error);
- retval = r < 0 ? EXIT_FAILURE : r;
-
-finish:
- if (bus) {
- dbus_connection_flush(bus);
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
- }
-
- dbus_error_free(&error);
- dbus_shutdown();
-
- pager_close();
-
- return retval;
-}
diff --git a/src/locale/localed.c b/src/locale/localed.c
deleted file mode 100644
index 04268a1982..0000000000
--- a/src/locale/localed.c
+++ /dev/null
@@ -1,1417 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <dbus/dbus.h>
-
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "util.h"
-#include "mkdir.h"
-#include "strv.h"
-#include "dbus-common.h"
-#include "polkit.h"
-#include "def.h"
-
-#define INTERFACE \
- " <interface name=\"org.freedesktop.locale1\">\n" \
- " <property name=\"Locale\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"VConsoleKeymap\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"VConsoleKeymapToggle\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"X11Layout\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"X11Model\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"X11Variant\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"X11Options\" type=\"s\" access=\"read\"/>\n" \
- " <method name=\"SetLocale\">\n" \
- " <arg name=\"locale\" type=\"as\" direction=\"in\"/>\n" \
- " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"SetVConsoleKeyboard\">\n" \
- " <arg name=\"keymap\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"keymap_toggle\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"convert\" type=\"b\" direction=\"in\"/>\n" \
- " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"SetX11Keyboard\">\n" \
- " <arg name=\"layout\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"model\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"variant\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"options\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"convert\" type=\"b\" direction=\"in\"/>\n" \
- " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
- " </method>\n" \
- " </interface>\n"
-
-#define INTROSPECTION \
- DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
- "<node>\n" \
- INTERFACE \
- BUS_PROPERTIES_INTERFACE \
- BUS_INTROSPECTABLE_INTERFACE \
- BUS_PEER_INTERFACE \
- "</node>\n"
-
-#define INTERFACES_LIST \
- BUS_GENERIC_INTERFACES_LIST \
- "org.freedesktop.locale1\0"
-
-const char locale_interface[] _introspect_("locale1") = INTERFACE;
-
-enum {
- /* We don't list LC_ALL here on purpose. People should be
- * using LANG instead. */
-
- PROP_LANG,
- PROP_LANGUAGE,
- PROP_LC_CTYPE,
- PROP_LC_NUMERIC,
- PROP_LC_TIME,
- PROP_LC_COLLATE,
- PROP_LC_MONETARY,
- PROP_LC_MESSAGES,
- PROP_LC_PAPER,
- PROP_LC_NAME,
- PROP_LC_ADDRESS,
- PROP_LC_TELEPHONE,
- PROP_LC_MEASUREMENT,
- PROP_LC_IDENTIFICATION,
- _PROP_MAX
-};
-
-static const char * const names[_PROP_MAX] = {
- [PROP_LANG] = "LANG",
- [PROP_LANGUAGE] = "LANGUAGE",
- [PROP_LC_CTYPE] = "LC_CTYPE",
- [PROP_LC_NUMERIC] = "LC_NUMERIC",
- [PROP_LC_TIME] = "LC_TIME",
- [PROP_LC_COLLATE] = "LC_COLLATE",
- [PROP_LC_MONETARY] = "LC_MONETARY",
- [PROP_LC_MESSAGES] = "LC_MESSAGES",
- [PROP_LC_PAPER] = "LC_PAPER",
- [PROP_LC_NAME] = "LC_NAME",
- [PROP_LC_ADDRESS] = "LC_ADDRESS",
- [PROP_LC_TELEPHONE] = "LC_TELEPHONE",
- [PROP_LC_MEASUREMENT] = "LC_MEASUREMENT",
- [PROP_LC_IDENTIFICATION] = "LC_IDENTIFICATION"
-};
-
-static char *data[_PROP_MAX] = {
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
-};
-
-typedef struct State {
- char *x11_layout, *x11_model, *x11_variant, *x11_options;
- char *vc_keymap, *vc_keymap_toggle;
-} State;
-
-static State state;
-
-static usec_t remain_until = 0;
-
-static int free_and_set(char **s, const char *v) {
- int r;
- char *t;
-
- assert(s);
-
- r = strdup_or_null(isempty(v) ? NULL : v, &t);
- if (r < 0)
- return r;
-
- free(*s);
- *s = t;
-
- return 0;
-}
-
-static void free_data_locale(void) {
- int p;
-
- for (p = 0; p < _PROP_MAX; p++) {
- free(data[p]);
- data[p] = NULL;
- }
-}
-
-static void free_data_x11(void) {
- free(state.x11_layout);
- free(state.x11_model);
- free(state.x11_variant);
- free(state.x11_options);
-
- state.x11_layout = state.x11_model = state.x11_variant = state.x11_options = NULL;
-}
-
-static void free_data_vconsole(void) {
- free(state.vc_keymap);
- free(state.vc_keymap_toggle);
-
- state.vc_keymap = state.vc_keymap_toggle = NULL;
-}
-
-static void simplify(void) {
- int p;
-
- for (p = 1; p < _PROP_MAX; p++)
- if (isempty(data[p]) || streq_ptr(data[PROP_LANG], data[p])) {
- free(data[p]);
- data[p] = NULL;
- }
-}
-
-static int read_data_locale(void) {
- int r;
-
- free_data_locale();
-
- r = parse_env_file("/etc/locale.conf", NEWLINE,
- "LANG", &data[PROP_LANG],
- "LANGUAGE", &data[PROP_LANGUAGE],
- "LC_CTYPE", &data[PROP_LC_CTYPE],
- "LC_NUMERIC", &data[PROP_LC_NUMERIC],
- "LC_TIME", &data[PROP_LC_TIME],
- "LC_COLLATE", &data[PROP_LC_COLLATE],
- "LC_MONETARY", &data[PROP_LC_MONETARY],
- "LC_MESSAGES", &data[PROP_LC_MESSAGES],
- "LC_PAPER", &data[PROP_LC_PAPER],
- "LC_NAME", &data[PROP_LC_NAME],
- "LC_ADDRESS", &data[PROP_LC_ADDRESS],
- "LC_TELEPHONE", &data[PROP_LC_TELEPHONE],
- "LC_MEASUREMENT", &data[PROP_LC_MEASUREMENT],
- "LC_IDENTIFICATION", &data[PROP_LC_IDENTIFICATION],
- NULL);
-
- if (r == -ENOENT) {
- int p;
-
- /* Fill in what we got passed from systemd. */
-
- for (p = 0; p < _PROP_MAX; p++) {
- char *e, *d;
-
- assert(names[p]);
-
- e = getenv(names[p]);
- if (e) {
- d = strdup(e);
- if (!d)
- return -ENOMEM;
- } else
- d = NULL;
-
- free(data[p]);
- data[p] = d;
- }
-
- r = 0;
- }
-
- simplify();
- return r;
-}
-
-static void free_data(void) {
- free_data_locale();
- free_data_vconsole();
- free_data_x11();
-}
-
-static int read_data_vconsole(void) {
- int r;
-
- free_data_vconsole();
-
- r = parse_env_file("/etc/vconsole.conf", NEWLINE,
- "KEYMAP", &state.vc_keymap,
- "KEYMAP_TOGGLE", &state.vc_keymap_toggle,
- NULL);
-
- if (r < 0 && r != -ENOENT)
- return r;
-
- return 0;
-}
-
-static int read_data_x11(void) {
- FILE *f;
- char line[LINE_MAX];
- bool in_section = false;
-
- free_data_x11();
-
- f = fopen("/etc/X11/xorg.conf.d/00-keyboard.conf", "re");
- if (!f)
- return errno == ENOENT ? 0 : -errno;
-
- while (fgets(line, sizeof(line), f)) {
- char *l;
-
- char_array_0(line);
- l = strstrip(line);
-
- if (l[0] == 0 || l[0] == '#')
- continue;
-
- if (in_section && first_word(l, "Option")) {
- char **a;
-
- a = strv_split_quoted(l);
- if (!a) {
- fclose(f);
- return -ENOMEM;
- }
-
- if (strv_length(a) == 3) {
-
- if (streq(a[1], "XkbLayout")) {
- free(state.x11_layout);
- state.x11_layout = a[2];
- a[2] = NULL;
- } else if (streq(a[1], "XkbModel")) {
- free(state.x11_model);
- state.x11_model = a[2];
- a[2] = NULL;
- } else if (streq(a[1], "XkbVariant")) {
- free(state.x11_variant);
- state.x11_variant = a[2];
- a[2] = NULL;
- } else if (streq(a[1], "XkbOptions")) {
- free(state.x11_options);
- state.x11_options = a[2];
- a[2] = NULL;
- }
- }
-
- strv_free(a);
-
- } else if (!in_section && first_word(l, "Section")) {
- char **a;
-
- a = strv_split_quoted(l);
- if (!a) {
- fclose(f);
- return -ENOMEM;
- }
-
- if (strv_length(a) == 2 && streq(a[1], "InputClass"))
- in_section = true;
-
- strv_free(a);
- } else if (in_section && first_word(l, "EndSection"))
- in_section = false;
- }
-
- fclose(f);
-
- return 0;
-}
-
-static int read_data(void) {
- int r, q, p;
-
- r = read_data_locale();
- q = read_data_vconsole();
- p = read_data_x11();
-
- return r < 0 ? r : q < 0 ? q : p;
-}
-
-static int write_data_locale(void) {
- int r, p;
- char **l = NULL;
-
- r = load_env_file("/etc/locale.conf", &l);
- if (r < 0 && r != -ENOENT)
- return r;
-
- for (p = 0; p < _PROP_MAX; p++) {
- char *t, **u;
-
- assert(names[p]);
-
- if (isempty(data[p])) {
- l = strv_env_unset(l, names[p]);
- continue;
- }
-
- if (asprintf(&t, "%s=%s", names[p], data[p]) < 0) {
- strv_free(l);
- return -ENOMEM;
- }
-
- u = strv_env_set(l, t);
- free(t);
- strv_free(l);
-
- if (!u)
- return -ENOMEM;
-
- l = u;
- }
-
- if (strv_isempty(l)) {
- strv_free(l);
-
- if (unlink("/etc/locale.conf") < 0)
- return errno == ENOENT ? 0 : -errno;
-
- return 0;
- }
-
- r = write_env_file("/etc/locale.conf", l);
- strv_free(l);
-
- return r;
-}
-
-static void push_data(DBusConnection *bus) {
- char **l_set = NULL, **l_unset = NULL, **t;
- int c_set = 0, c_unset = 0, p;
- DBusError error;
- DBusMessage *m = NULL, *reply = NULL;
- DBusMessageIter iter, sub;
-
- dbus_error_init(&error);
-
- assert(bus);
-
- l_set = new0(char*, _PROP_MAX);
- l_unset = new0(char*, _PROP_MAX);
- if (!l_set || !l_unset) {
- log_oom();
- goto finish;
- }
-
- for (p = 0; p < _PROP_MAX; p++) {
- assert(names[p]);
-
- if (isempty(data[p]))
- l_unset[c_set++] = (char*) names[p];
- else {
- char *s;
-
- if (asprintf(&s, "%s=%s", names[p], data[p]) < 0) {
- log_oom();
- goto finish;
- }
-
- l_set[c_unset++] = s;
- }
- }
-
- assert(c_set + c_unset == _PROP_MAX);
- m = dbus_message_new_method_call("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment");
- if (!m) {
- log_error("Could not allocate message.");
- goto finish;
- }
-
- dbus_message_iter_init_append(m, &iter);
-
- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
- log_oom();
- goto finish;
- }
-
- STRV_FOREACH(t, l_unset)
- if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, t)) {
- log_oom();
- goto finish;
- }
-
- if (!dbus_message_iter_close_container(&iter, &sub) ||
- !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
- log_oom();
- goto finish;
- }
-
- STRV_FOREACH(t, l_set)
- if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, t)) {
- log_oom();
- goto finish;
- }
-
- if (!dbus_message_iter_close_container(&iter, &sub)) {
- log_oom();
- goto finish;
- }
-
- reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
- if (!reply) {
- log_error("Failed to set locale information: %s", bus_error_message(&error));
- goto finish;
- }
-
-finish:
- if (m)
- dbus_message_unref(m);
-
- if (reply)
- dbus_message_unref(reply);
-
- dbus_error_free(&error);
-
- strv_free(l_set);
- free(l_unset);
-}
-
-static int write_data_vconsole(void) {
- int r;
- char **l = NULL;
-
- r = load_env_file("/etc/vconsole.conf", &l);
- if (r < 0 && r != -ENOENT)
- return r;
-
- if (isempty(state.vc_keymap))
- l = strv_env_unset(l, "KEYMAP");
- else {
- char *s, **u;
-
- s = strappend("KEYMAP=", state.vc_keymap);
- if (!s) {
- strv_free(l);
- return -ENOMEM;
- }
-
- u = strv_env_set(l, s);
- free(s);
- strv_free(l);
-
- if (!u)
- return -ENOMEM;
-
- l = u;
- }
-
- if (isempty(state.vc_keymap_toggle))
- l = strv_env_unset(l, "KEYMAP_TOGGLE");
- else {
- char *s, **u;
-
- s = strappend("KEYMAP_TOGGLE=", state.vc_keymap_toggle);
- if (!s) {
- strv_free(l);
- return -ENOMEM;
- }
-
- u = strv_env_set(l, s);
- free(s);
- strv_free(l);
-
- if (!u)
- return -ENOMEM;
-
- l = u;
- }
-
- if (strv_isempty(l)) {
- strv_free(l);
-
- if (unlink("/etc/vconsole.conf") < 0)
- return errno == ENOENT ? 0 : -errno;
-
- return 0;
- }
-
- r = write_env_file("/etc/vconsole.conf", l);
- strv_free(l);
-
- return r;
-}
-
-static int write_data_x11(void) {
- FILE *f;
- char *temp_path;
- int r;
-
- if (isempty(state.x11_layout) &&
- isempty(state.x11_model) &&
- isempty(state.x11_variant) &&
- isempty(state.x11_options)) {
-
- if (unlink("/etc/X11/xorg.conf.d/00-keyboard.conf") < 0)
- return errno == ENOENT ? 0 : -errno;
-
- return 0;
- }
-
- mkdir_parents_label("/etc/X11/xorg.conf.d", 0755);
-
- r = fopen_temporary("/etc/X11/xorg.conf.d/00-keyboard.conf", &f, &temp_path);
- if (r < 0)
- return r;
-
- fchmod(fileno(f), 0644);
-
- fputs("# Read and parsed by systemd-localed. It's probably wise not to edit this file\n"
- "# manually too freely.\n"
- "Section \"InputClass\"\n"
- " Identifier \"system-keyboard\"\n"
- " MatchIsKeyboard \"on\"\n", f);
-
- if (!isempty(state.x11_layout))
- fprintf(f, " Option \"XkbLayout\" \"%s\"\n", state.x11_layout);
-
- if (!isempty(state.x11_model))
- fprintf(f, " Option \"XkbModel\" \"%s\"\n", state.x11_model);
-
- if (!isempty(state.x11_variant))
- fprintf(f, " Option \"XkbVariant\" \"%s\"\n", state.x11_variant);
-
- if (!isempty(state.x11_options))
- fprintf(f, " Option \"XkbOptions\" \"%s\"\n", state.x11_options);
-
- fputs("EndSection\n", f);
- fflush(f);
-
- if (ferror(f) || rename(temp_path, "/etc/X11/xorg.conf.d/00-keyboard.conf") < 0) {
- r = -errno;
- unlink("/etc/X11/xorg.conf.d/00-keyboard.conf");
- unlink(temp_path);
- } else
- r = 0;
-
- fclose(f);
- free(temp_path);
-
- return r;
-}
-
-static int load_vconsole_keymap(DBusConnection *bus, DBusError *error) {
- DBusMessage *m = NULL, *reply = NULL;
- const char *name = "systemd-vconsole-setup.service", *mode = "replace";
- int r;
- DBusError _error;
-
- assert(bus);
-
- if (!error) {
- dbus_error_init(&_error);
- error = &_error;
- }
-
- m = dbus_message_new_method_call(
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "RestartUnit");
- if (!m) {
- log_error("Could not allocate message.");
- r = -ENOMEM;
- goto finish;
- }
-
- if (!dbus_message_append_args(m,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_STRING, &mode,
- DBUS_TYPE_INVALID)) {
- log_error("Could not append arguments to message.");
- r = -ENOMEM;
- goto finish;
- }
-
- reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error);
- if (!reply) {
- log_error("Failed to issue method call: %s", bus_error_message(error));
- r = -EIO;
- goto finish;
- }
-
- r = 0;
-
-finish:
- if (m)
- dbus_message_unref(m);
-
- if (reply)
- dbus_message_unref(reply);
-
- if (error == &_error)
- dbus_error_free(error);
-
- return r;
-}
-
-static char *strnulldash(const char *s) {
- return s == NULL || *s == 0 || (s[0] == '-' && s[1] == 0) ? NULL : (char*) s;
-}
-
-static int read_next_mapping(FILE *f, unsigned *n, char ***a) {
- assert(f);
- assert(n);
- assert(a);
-
- for (;;) {
- char line[LINE_MAX];
- char *l, **b;
-
- errno = 0;
- if (!fgets(line, sizeof(line), f)) {
-
- if (ferror(f))
- return errno ? -errno : -EIO;
-
- return 0;
- }
-
- (*n) ++;
-
- l = strstrip(line);
- if (l[0] == 0 || l[0] == '#')
- continue;
-
- b = strv_split_quoted(l);
- if (!b)
- return -ENOMEM;
-
- if (strv_length(b) < 5) {
- log_error("Invalid line "SYSTEMD_KBD_MODEL_MAP":%u, ignoring.", *n);
- strv_free(b);
- continue;
-
- }
-
- *a = b;
- return 1;
- }
-}
-
-static int convert_vconsole_to_x11(DBusConnection *connection) {
- bool modified = false;
-
- assert(connection);
-
- if (isempty(state.vc_keymap)) {
-
- modified =
- !isempty(state.x11_layout) ||
- !isempty(state.x11_model) ||
- !isempty(state.x11_variant) ||
- !isempty(state.x11_options);
-
- free_data_x11();
- } else {
- FILE *f;
- unsigned n = 0;
-
- f = fopen(SYSTEMD_KBD_MODEL_MAP, "re");
- if (!f)
- return -errno;
-
- for (;;) {
- char **a;
- int r;
-
- r = read_next_mapping(f, &n, &a);
- if (r < 0) {
- fclose(f);
- return r;
- }
-
- if (r == 0)
- break;
-
- if (!streq(state.vc_keymap, a[0])) {
- strv_free(a);
- continue;
- }
-
- if (!streq_ptr(state.x11_layout, strnulldash(a[1])) ||
- !streq_ptr(state.x11_model, strnulldash(a[2])) ||
- !streq_ptr(state.x11_variant, strnulldash(a[3])) ||
- !streq_ptr(state.x11_options, strnulldash(a[4]))) {
-
- if (free_and_set(&state.x11_layout, strnulldash(a[1])) < 0 ||
- free_and_set(&state.x11_model, strnulldash(a[2])) < 0 ||
- free_and_set(&state.x11_variant, strnulldash(a[3])) < 0 ||
- free_and_set(&state.x11_options, strnulldash(a[4])) < 0) {
- strv_free(a);
- fclose(f);
- return -ENOMEM;
- }
-
- modified = true;
- }
-
- strv_free(a);
- break;
- }
-
- fclose(f);
- }
-
- if (modified) {
- dbus_bool_t b;
- DBusMessage *changed;
- int r;
-
- r = write_data_x11();
- if (r < 0)
- log_error("Failed to set X11 keyboard layout: %s", strerror(-r));
-
- changed = bus_properties_changed_new(
- "/org/freedesktop/locale1",
- "org.freedesktop.locale1",
- "X11Layout\0"
- "X11Model\0"
- "X11Variant\0"
- "X11Options\0");
-
- if (!changed)
- return -ENOMEM;
-
- b = dbus_connection_send(connection, changed, NULL);
- dbus_message_unref(changed);
-
- if (!b)
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static int convert_x11_to_vconsole(DBusConnection *connection) {
- bool modified = false;
-
- assert(connection);
-
- if (isempty(state.x11_layout)) {
-
- modified =
- !isempty(state.vc_keymap) ||
- !isempty(state.vc_keymap_toggle);
-
- free_data_x11();
- } else {
- FILE *f;
- unsigned n = 0;
- unsigned best_matching = 0;
- char *new_keymap = NULL;
-
- f = fopen(SYSTEMD_KBD_MODEL_MAP, "re");
- if (!f)
- return -errno;
-
- for (;;) {
- char **a;
- unsigned matching = 0;
- int r;
-
- r = read_next_mapping(f, &n, &a);
- if (r < 0) {
- fclose(f);
- return r;
- }
-
- if (r == 0)
- break;
-
- /* Determine how well matching this entry is */
- if (streq_ptr(state.x11_layout, a[1]))
- /* If we got an exact match, this is best */
- matching = 10;
- else {
- size_t x;
-
- x = strcspn(state.x11_layout, ",");
-
- /* We have multiple X layouts, look
- * for an entry that matches our key
- * with the everything but the first
- * layout stripped off. */
- if (x > 0 &&
- strlen(a[1]) == x &&
- strncmp(state.x11_layout, a[1], x) == 0)
- matching = 5;
- else {
- size_t w;
-
- /* If that didn't work, strip
- * off the other layouts from
- * the entry, too */
-
- w = strcspn(a[1], ",");
-
- if (x > 0 && x == w &&
- memcmp(state.x11_layout, a[1], x) == 0)
- matching = 1;
- }
- }
-
- if (matching > 0 &&
- streq_ptr(state.x11_model, a[2])) {
- matching++;
-
- if (streq_ptr(state.x11_variant, a[3])) {
- matching++;
-
- if (streq_ptr(state.x11_options, a[4]))
- matching++;
- }
- }
-
- /* The best matching entry so far, then let's
- * save that */
- if (matching > best_matching) {
- best_matching = matching;
-
- free(new_keymap);
- new_keymap = strdup(a[0]);
-
- if (!new_keymap) {
- strv_free(a);
- fclose(f);
- return -ENOMEM;
- }
- }
-
- strv_free(a);
- }
-
- fclose(f);
-
- if (!streq_ptr(state.vc_keymap, new_keymap)) {
- free(state.vc_keymap);
- state.vc_keymap = new_keymap;
-
- free(state.vc_keymap_toggle);
- state.vc_keymap_toggle = NULL;
-
- modified = true;
- } else
- free(new_keymap);
- }
-
- if (modified) {
- dbus_bool_t b;
- DBusMessage *changed;
- int r;
-
- r = write_data_vconsole();
- if (r < 0)
- log_error("Failed to set virtual console keymap: %s", strerror(-r));
-
- changed = bus_properties_changed_new(
- "/org/freedesktop/locale1",
- "org.freedesktop.locale1",
- "VConsoleKeymap\0"
- "VConsoleKeymapToggle\0");
-
- if (!changed)
- return -ENOMEM;
-
- b = dbus_connection_send(connection, changed, NULL);
- dbus_message_unref(changed);
-
- if (!b)
- return -ENOMEM;
-
- return load_vconsole_keymap(connection, NULL);
- }
-
- return 0;
-}
-
-static int append_locale(DBusMessageIter *i, const char *property, void *userdata) {
- int r, c = 0, p;
- char **l;
-
- l = new0(char*, _PROP_MAX+1);
- if (!l)
- return -ENOMEM;
-
- for (p = 0; p < _PROP_MAX; p++) {
- char *t;
-
- if (isempty(data[p]))
- continue;
-
- if (asprintf(&t, "%s=%s", names[p], data[p]) < 0) {
- strv_free(l);
- return -ENOMEM;
- }
-
- l[c++] = t;
- }
-
- r = bus_property_append_strv(i, property, (void*) l);
- strv_free(l);
-
- return r;
-}
-
-static const BusProperty bus_locale_properties[] = {
- { "Locale", append_locale, "as", 0 },
- { "X11Layout", bus_property_append_string, "s", offsetof(State, x11_layout), true },
- { "X11Model", bus_property_append_string, "s", offsetof(State, x11_model), true },
- { "X11Variant", bus_property_append_string, "s", offsetof(State, x11_variant), true },
- { "X11Options", bus_property_append_string, "s", offsetof(State, x11_options), true },
- { "VConsoleKeymap", bus_property_append_string, "s", offsetof(State, vc_keymap), true },
- { "VConsoleKeymapToggle", bus_property_append_string, "s", offsetof(State, vc_keymap_toggle), true },
- { NULL, }
-};
-
-static const BusBoundProperties bps[] = {
- { "org.freedesktop.locale1", bus_locale_properties, &state },
- { NULL, }
-};
-
-static DBusHandlerResult locale_message_handler(
- DBusConnection *connection,
- DBusMessage *message,
- void *userdata) {
-
- DBusMessage *reply = NULL, *changed = NULL;
- DBusError error;
- int r;
-
- assert(connection);
- assert(message);
-
- dbus_error_init(&error);
-
- if (dbus_message_is_method_call(message, "org.freedesktop.locale1", "SetLocale")) {
- char **l = NULL, **i;
- dbus_bool_t interactive;
- DBusMessageIter iter;
- bool modified = false;
- bool passed[_PROP_MAX];
- int p;
-
- if (!dbus_message_iter_init(message, &iter))
- return bus_send_error_reply(connection, message, NULL, -EINVAL);
-
- r = bus_parse_strv_iter(&iter, &l);
- if (r < 0) {
- if (r == -ENOMEM)
- goto oom;
-
- return bus_send_error_reply(connection, message, NULL, r);
- }
-
- if (!dbus_message_iter_next(&iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN) {
- strv_free(l);
- return bus_send_error_reply(connection, message, NULL, -EINVAL);
- }
-
- dbus_message_iter_get_basic(&iter, &interactive);
-
- zero(passed);
-
- /* Check whether a variable changed and if so valid */
- STRV_FOREACH(i, l) {
- bool valid = false;
-
- for (p = 0; p < _PROP_MAX; p++) {
- size_t k;
-
- k = strlen(names[p]);
- if (startswith(*i, names[p]) &&
- (*i)[k] == '=' &&
- string_is_safe((*i) + k + 1)) {
- valid = true;
- passed[p] = true;
-
- if (!streq_ptr(*i + k + 1, data[p]))
- modified = true;
-
- break;
- }
- }
-
- if (!valid) {
- strv_free(l);
- return bus_send_error_reply(connection, message, NULL, -EINVAL);
- }
- }
-
- /* Check whether a variable is unset */
- if (!modified) {
- for (p = 0; p < _PROP_MAX; p++)
- if (!isempty(data[p]) && !passed[p]) {
- modified = true;
- break;
- }
- }
-
- if (modified) {
-
- r = verify_polkit(connection, message, "org.freedesktop.locale1.set-locale", interactive, NULL, &error);
- if (r < 0) {
- strv_free(l);
- return bus_send_error_reply(connection, message, &error, r);
- }
-
- STRV_FOREACH(i, l) {
- for (p = 0; p < _PROP_MAX; p++) {
- size_t k;
-
- k = strlen(names[p]);
- if (startswith(*i, names[p]) && (*i)[k] == '=') {
- char *t;
-
- t = strdup(*i + k + 1);
- if (!t) {
- strv_free(l);
- goto oom;
- }
-
- free(data[p]);
- data[p] = t;
-
- break;
- }
- }
- }
-
- strv_free(l);
-
- for (p = 0; p < _PROP_MAX; p++) {
- if (passed[p])
- continue;
-
- free(data[p]);
- data[p] = NULL;
- }
-
- simplify();
-
- r = write_data_locale();
- if (r < 0) {
- log_error("Failed to set locale: %s", strerror(-r));
- return bus_send_error_reply(connection, message, NULL, r);
- }
-
- push_data(connection);
-
- log_info("Changed locale information.");
-
- changed = bus_properties_changed_new(
- "/org/freedesktop/locale1",
- "org.freedesktop.locale1",
- "Locale\0");
- if (!changed)
- goto oom;
- } else
- strv_free(l);
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.locale1", "SetVConsoleKeyboard")) {
-
- const char *keymap, *keymap_toggle;
- dbus_bool_t convert, interactive;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &keymap,
- DBUS_TYPE_STRING, &keymap_toggle,
- DBUS_TYPE_BOOLEAN, &convert,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- if (isempty(keymap))
- keymap = NULL;
-
- if (isempty(keymap_toggle))
- keymap_toggle = NULL;
-
- if (!streq_ptr(keymap, state.vc_keymap) ||
- !streq_ptr(keymap_toggle, state.vc_keymap_toggle)) {
-
- if ((keymap && (!filename_is_safe(keymap) || !string_is_safe(keymap))) ||
- (keymap_toggle && (!filename_is_safe(keymap_toggle) || !string_is_safe(keymap_toggle))))
- return bus_send_error_reply(connection, message, NULL, -EINVAL);
-
- r = verify_polkit(connection, message, "org.freedesktop.locale1.set-keyboard", interactive, NULL, &error);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- if (free_and_set(&state.vc_keymap, keymap) < 0 ||
- free_and_set(&state.vc_keymap_toggle, keymap_toggle) < 0)
- goto oom;
-
- r = write_data_vconsole();
- if (r < 0) {
- log_error("Failed to set virtual console keymap: %s", strerror(-r));
- return bus_send_error_reply(connection, message, NULL, r);
- }
-
- log_info("Changed virtual console keymap to '%s'", strempty(state.vc_keymap));
-
- r = load_vconsole_keymap(connection, NULL);
- if (r < 0)
- log_error("Failed to request keymap reload: %s", strerror(-r));
-
- changed = bus_properties_changed_new(
- "/org/freedesktop/locale1",
- "org.freedesktop.locale1",
- "VConsoleKeymap\0"
- "VConsoleKeymapToggle\0");
- if (!changed)
- goto oom;
-
- if (convert) {
- r = convert_vconsole_to_x11(connection);
-
- if (r < 0)
- log_error("Failed to convert keymap data: %s", strerror(-r));
- }
- }
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.locale1", "SetX11Keyboard")) {
-
- const char *layout, *model, *variant, *options;
- dbus_bool_t convert, interactive;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &layout,
- DBUS_TYPE_STRING, &model,
- DBUS_TYPE_STRING, &variant,
- DBUS_TYPE_STRING, &options,
- DBUS_TYPE_BOOLEAN, &convert,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- if (isempty(layout))
- layout = NULL;
-
- if (isempty(model))
- model = NULL;
-
- if (isempty(variant))
- variant = NULL;
-
- if (isempty(options))
- options = NULL;
-
- if (!streq_ptr(layout, state.x11_layout) ||
- !streq_ptr(model, state.x11_model) ||
- !streq_ptr(variant, state.x11_variant) ||
- !streq_ptr(options, state.x11_options)) {
-
- if ((layout && !string_is_safe(layout)) ||
- (model && !string_is_safe(model)) ||
- (variant && !string_is_safe(variant)) ||
- (options && !string_is_safe(options)))
- return bus_send_error_reply(connection, message, NULL, -EINVAL);
-
- r = verify_polkit(connection, message, "org.freedesktop.locale1.set-keyboard", interactive, NULL, &error);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- if (free_and_set(&state.x11_layout, layout) < 0 ||
- free_and_set(&state.x11_model, model) < 0 ||
- free_and_set(&state.x11_variant, variant) < 0 ||
- free_and_set(&state.x11_options, options) < 0)
- goto oom;
-
- r = write_data_x11();
- if (r < 0) {
- log_error("Failed to set X11 keyboard layout: %s", strerror(-r));
- return bus_send_error_reply(connection, message, NULL, r);
- }
-
- log_info("Changed X11 keyboard layout to '%s'", strempty(state.x11_layout));
-
- changed = bus_properties_changed_new(
- "/org/freedesktop/locale1",
- "org.freedesktop.locale1",
- "X11Layout\0"
- "X11Model\0"
- "X11Variant\0"
- "X11Options\0");
- if (!changed)
- goto oom;
-
- if (convert) {
- r = convert_x11_to_vconsole(connection);
-
- if (r < 0)
- log_error("Failed to convert keymap data: %s", strerror(-r));
- }
- }
- } else
- return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps);
-
- if (!(reply = dbus_message_new_method_return(message)))
- goto oom;
-
- if (!dbus_connection_send(connection, reply, NULL))
- goto oom;
-
- dbus_message_unref(reply);
- reply = NULL;
-
- if (changed) {
-
- if (!dbus_connection_send(connection, changed, NULL))
- goto oom;
-
- dbus_message_unref(changed);
- }
-
- return DBUS_HANDLER_RESULT_HANDLED;
-
-oom:
- if (reply)
- dbus_message_unref(reply);
-
- if (changed)
- dbus_message_unref(changed);
-
- dbus_error_free(&error);
-
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-}
-
-static int connect_bus(DBusConnection **_bus) {
- static const DBusObjectPathVTable locale_vtable = {
- .message_function = locale_message_handler
- };
- DBusError error;
- DBusConnection *bus = NULL;
- int r;
-
- assert(_bus);
-
- dbus_error_init(&error);
-
- bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
- if (!bus) {
- log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
- r = -ECONNREFUSED;
- goto fail;
- }
-
- dbus_connection_set_exit_on_disconnect(bus, FALSE);
-
- if (!dbus_connection_register_object_path(bus, "/org/freedesktop/locale1", &locale_vtable, NULL) ||
- !dbus_connection_add_filter(bus, bus_exit_idle_filter, &remain_until, NULL)) {
- r = log_oom();
- goto fail;
- }
-
- r = dbus_bus_request_name(bus, "org.freedesktop.locale1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
- if (dbus_error_is_set(&error)) {
- log_error("Failed to register name on bus: %s", bus_error_message(&error));
- r = -EEXIST;
- goto fail;
- }
-
- if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
- log_error("Failed to acquire name.");
- r = -EEXIST;
- goto fail;
- }
-
- if (_bus)
- *_bus = bus;
-
- return 0;
-
-fail:
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
-
- dbus_error_free(&error);
-
- return r;
-}
-
-int main(int argc, char *argv[]) {
- int r;
- DBusConnection *bus = NULL;
- bool exiting = false;
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- if (argc == 2 && streq(argv[1], "--introspect")) {
- fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
- "<node>\n", stdout);
- fputs(locale_interface, stdout);
- fputs("</node>\n", stdout);
- return 0;
- }
-
- if (argc != 1) {
- log_error("This program takes no arguments.");
- r = -EINVAL;
- goto finish;
- }
-
- r = read_data();
- if (r < 0) {
- log_error("Failed to read locale data: %s", strerror(-r));
- goto finish;
- }
-
- r = connect_bus(&bus);
- if (r < 0)
- goto finish;
-
- remain_until = now(CLOCK_MONOTONIC) + DEFAULT_EXIT_USEC;
- for (;;) {
-
- if (!dbus_connection_read_write_dispatch(bus, exiting ? -1 : (int) (DEFAULT_EXIT_USEC/USEC_PER_MSEC)))
- break;
-
- if (!exiting && remain_until < now(CLOCK_MONOTONIC)) {
- exiting = true;
- bus_async_unregister_and_exit(bus, "org.freedesktop.locale1");
- }
- }
-
- r = 0;
-
-finish:
- free_data();
-
- if (bus) {
- dbus_connection_flush(bus);
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
- }
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/locale/org.freedesktop.locale1.conf b/src/locale/org.freedesktop.locale1.conf
deleted file mode 100644
index 79d0ecd2bb..0000000000
--- a/src/locale/org.freedesktop.locale1.conf
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0"?> <!--*-nxml-*-->
-<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
-
-<!--
- This file is part of systemd.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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.
--->
-
-<busconfig>
-
- <policy user="root">
- <allow own="org.freedesktop.locale1"/>
- <allow send_destination="org.freedesktop.locale1"/>
- <allow receive_sender="org.freedesktop.locale1"/>
- </policy>
-
- <policy context="default">
- <allow send_destination="org.freedesktop.locale1"/>
- <allow receive_sender="org.freedesktop.locale1"/>
- </policy>
-
-</busconfig>
diff --git a/src/locale/org.freedesktop.locale1.policy.in b/src/locale/org.freedesktop.locale1.policy.in
deleted file mode 100644
index 91296c2356..0000000000
--- a/src/locale/org.freedesktop.locale1.policy.in
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?> <!--*-nxml-*-->
-<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
-
-<!--
- This file is part of systemd.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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.
--->
-
-<policyconfig>
-
- <vendor>The systemd Project</vendor>
- <vendor_url>http://www.freedesktop.org/wiki/Software/systemd</vendor_url>
-
- <action id="org.freedesktop.locale1.set-locale">
- <_description>Set system locale</_description>
- <_message>Authentication is required to set the system locale.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.locale1.set-keyboard">
- <_description>Set system keyboard settings</_description>
- <_message>Authentication is required to set the system keyboard settings.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
- </defaults>
- </action>
-
-</policyconfig>
diff --git a/src/locale/org.freedesktop.locale1.service b/src/locale/org.freedesktop.locale1.service
deleted file mode 100644
index 025f9a0fc2..0000000000
--- a/src/locale/org.freedesktop.locale1.service
+++ /dev/null
@@ -1,12 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-
-[D-BUS Service]
-Name=org.freedesktop.locale1
-Exec=/bin/false
-User=root
-SystemdService=dbus-org.freedesktop.locale1.service
diff --git a/src/login/.gitignore b/src/login/.gitignore
deleted file mode 100644
index d3840c7afc..0000000000
--- a/src/login/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-/libsystemd-login.pc
-/logind-gperf.c
-/org.freedesktop.login1.policy
-/71-seat.rules
-/73-seat-late.rules
diff --git a/src/login/70-power-switch.rules b/src/login/70-power-switch.rules
deleted file mode 100644
index 36fb827315..0000000000
--- a/src/login/70-power-switch.rules
+++ /dev/null
@@ -1,13 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-
-ACTION=="remove", GOTO="power_switch_end"
-
-SUBSYSTEM=="input", KERNEL=="event*", SUBSYSTEMS=="acpi", TAG+="power-switch"
-SUBSYSTEM=="input", KERNEL=="event*", KERNELS=="thinkpad_acpi", TAG+="power-switch"
-
-LABEL="power_switch_end"
diff --git a/src/login/70-uaccess.rules b/src/login/70-uaccess.rules
deleted file mode 100644
index d1275f2ca9..0000000000
--- a/src/login/70-uaccess.rules
+++ /dev/null
@@ -1,75 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-
-ACTION=="remove", GOTO="uaccess_end"
-ENV{MAJOR}=="", GOTO="uaccess_end"
-
-# PTP/MTP protocol devices, cameras, portable media players
-SUBSYSTEM=="usb", ENV{ID_USB_INTERFACES}=="", ENV{DEVTYPE}=="usb_device", IMPORT{builtin}="usb_id"
-SUBSYSTEM=="usb", ENV{ID_USB_INTERFACES}=="*:060101:*", TAG+="uaccess"
-
-# Digicams with proprietary protocol
-ENV{ID_GPHOTO2}=="*?", TAG+="uaccess"
-
-# SCSI and USB scanners
-ENV{libsane_matched}=="yes", TAG+="uaccess"
-
-# HPLIP devices (necessary for ink level check and HP tool maintenance)
-ENV{ID_HPLIP}=="1", TAG+="uaccess"
-
-# optical drives
-SUBSYSTEM=="block", ENV{ID_CDROM}=="1", TAG+="uaccess"
-SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="4|5", TAG+="uaccess"
-
-# Sound devices
-SUBSYSTEM=="sound", TAG+="uaccess"
-
-# ffado is an userspace driver for firewire sound cards
-SUBSYSTEM=="firewire", ENV{ID_FFADO}=="1", TAG+="uaccess"
-
-# Webcams, frame grabber, TV cards
-SUBSYSTEM=="video4linux", TAG+="uaccess"
-SUBSYSTEM=="dvb", TAG+="uaccess"
-
-# IIDC devices: industrial cameras and some webcams
-SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x00010*", TAG+="uaccess"
-SUBSYSTEM=="firewire", ATTR{units}=="*0x00b09d:0x00010*", TAG+="uaccess"
-# AV/C devices: camcorders, set-top boxes, TV sets, audio devices, and more
-SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x010001*", TAG+="uaccess"
-SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x014001*", TAG+="uaccess"
-
-# DRI video devices
-SUBSYSTEM=="drm", KERNEL=="card*", TAG+="uaccess"
-
-# KVM
-SUBSYSTEM=="misc", KERNEL=="kvm", TAG+="uaccess"
-
-# smart-card readers
-ENV{ID_SMARTCARD_READER}=="*?", TAG+="uaccess"
-
-# (USB) authentication devices
-ENV{ID_SECURITY_TOKEN}=="*?", TAG+="uaccess"
-
-# PDA devices
-ENV{ID_PDA}=="*?", TAG+="uaccess"
-
-# Programmable remote control
-ENV{ID_REMOTE_CONTROL}=="1", TAG+="uaccess"
-
-# joysticks
-SUBSYSTEM=="input", ENV{ID_INPUT_JOYSTICK}=="?*", TAG+="uaccess"
-
-# color measurement devices
-ENV{COLOR_MEASUREMENT_DEVICE}=="*?", TAG+="uaccess"
-
-# DDC/CI device, usually high-end monitors such as the DreamColor
-ENV{DDC_DEVICE}=="*?", TAG+="uaccess"
-
-# media player raw devices (for user-mode drivers, Android SDK, etc.)
-SUBSYSTEM=="usb", ENV{ID_MEDIA_PLAYER}=="?*", TAG+="uaccess"
-
-LABEL="uaccess_end"
diff --git a/src/login/71-seat.rules.in b/src/login/71-seat.rules.in
deleted file mode 100644
index f554d7f615..0000000000
--- a/src/login/71-seat.rules.in
+++ /dev/null
@@ -1,48 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-
-ACTION=="remove", GOTO="seat_end"
-
-TAG=="uaccess", SUBSYSTEM!="sound", TAG+="seat"
-SUBSYSTEM=="sound", KERNEL=="card*", TAG+="seat"
-SUBSYSTEM=="input", KERNEL=="input*", TAG+="seat"
-SUBSYSTEM=="graphics", KERNEL=="fb[0-9]*", TAG+="seat"
-SUBSYSTEM=="usb", ATTR{bDeviceClass}=="09", TAG+="seat"
-
-# 'Plugable' USB hub, sound, network, graphics adapter
-SUBSYSTEM=="usb", ATTR{idVendor}=="2230", ATTR{idProduct}=="000[13]", ENV{ID_AUTOSEAT}="1"
-
-# Mimo 720, with integrated USB hub, displaylink graphics, and e2i
-# touchscreen. This device carries no proper VID/PID in the USB hub,
-# but it does carry good ID data in the graphics component, hence we
-# check it from the parent. There's a bit of a race here however,
-# given that the child devices might not exist yet at the time this
-# rule is executed. To work around this we'll trigger the parent from
-# the child if we notice that the parent wasn't recognized yet.
-
-# Match parent
-SUBSYSTEM=="usb", ATTR{idVendor}=="058f", ATTR{idProduct}=="6254", \
- ATTR{%k.2/idVendor}=="17e9", ATTR{%k.2/idProduct}=="401a", ATTR{%k.2/product}=="mimo inc", \
- ENV{ID_AUTOSEAT}="1", ENV{ID_AVOID_LOOP}="1"
-
-# Match child, look for parent's ID_AVOID_LOOP
-SUBSYSTEM=="usb", ATTR{idVendor}=="17e9", ATTR{idProduct}=="401a", ATTR{product}=="mimo inc", \
- ATTR{../idVendor}=="058f", ATTR{../idProduct}=="6254", \
- IMPORT{parent}="ID_AVOID_LOOP"
-
-# Match child, retrigger parent
-SUBSYSTEM=="usb", ATTR{idVendor}=="17e9", ATTR{idProduct}=="401a", ATTR{product}=="mimo inc", \
- ATTR{../idVendor}=="058f", ATTR{../idProduct}=="6254", \
- ENV{ID_AVOID_LOOP}=="", \
- RUN+="@bindir@/udevadm trigger --parent-match=%p/.."
-
-TAG=="seat", ENV{ID_PATH}=="", IMPORT{builtin}="path_id"
-TAG=="seat", ENV{ID_FOR_SEAT}=="", ENV{ID_PATH_TAG}!="", ENV{ID_FOR_SEAT}="$env{SUBSYSTEM}-$env{ID_PATH_TAG}"
-
-SUBSYSTEM=="input", ATTR{name}=="Wiebetech LLC Wiebetech", RUN+="@rootbindir@/loginctl lock-sessions"
-
-LABEL="seat_end"
diff --git a/src/login/73-seat-late.rules.in b/src/login/73-seat-late.rules.in
deleted file mode 100644
index 901df750fd..0000000000
--- a/src/login/73-seat-late.rules.in
+++ /dev/null
@@ -1,17 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-
-ACTION=="remove", GOTO="seat_late_end"
-
-ENV{ID_SEAT}=="", ENV{ID_AUTOSEAT}=="1", ENV{ID_FOR_SEAT}!="", ENV{ID_SEAT}="seat-$env{ID_FOR_SEAT}"
-ENV{ID_SEAT}=="", IMPORT{parent}="ID_SEAT"
-
-ENV{ID_SEAT}!="", TAG+="$env{ID_SEAT}"
-
-TAG=="uaccess", ENV{MAJOR}!="", RUN{builtin}+="uaccess"
-
-LABEL="seat_late_end"
diff --git a/src/login/Makefile b/src/login/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/login/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/login/inhibit.c b/src/login/inhibit.c
deleted file mode 100644
index 4735df7d3b..0000000000
--- a/src/login/inhibit.c
+++ /dev/null
@@ -1,332 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <getopt.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <dbus.h>
-#include <unistd.h>
-
-#include "dbus-common.h"
-#include "util.h"
-#include "build.h"
-#include "strv.h"
-
-static const char* arg_what = "idle:sleep:shutdown";
-static const char* arg_who = NULL;
-static const char* arg_why = "Unknown reason";
-static const char* arg_mode = "block";
-
-static enum {
- ACTION_INHIBIT,
- ACTION_LIST
-} arg_action = ACTION_INHIBIT;
-
-static int inhibit(DBusConnection *bus, DBusError *error) {
- DBusMessage *reply = NULL;
- int r;
-
- r = bus_method_call_with_reply(
- bus,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "Inhibit",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &arg_what,
- DBUS_TYPE_STRING, &arg_who,
- DBUS_TYPE_STRING, &arg_why,
- DBUS_TYPE_STRING, &arg_mode,
- DBUS_TYPE_INVALID);
- if (r < 0)
- return r;
-
- if (!dbus_message_get_args(reply, error,
- DBUS_TYPE_UNIX_FD, &r,
- DBUS_TYPE_INVALID))
- r = -EIO;
-
- dbus_message_unref(reply);
-
- return r;
-}
-
-static int print_inhibitors(DBusConnection *bus, DBusError *error) {
- DBusMessage *reply = NULL;
- unsigned n = 0;
- DBusMessageIter iter, sub, sub2;
- int r;
-
- r = bus_method_call_with_reply(
- bus,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "ListInhibitors",
- &reply,
- NULL,
- DBUS_TYPE_INVALID);
- if (r < 0)
- goto finish;
-
- if (!dbus_message_iter_init(reply, &iter)) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
- r = -EIO;
- goto finish;
- }
-
- printf("%-21s %-20s %-20s %-5s %6s %6s\n",
- "WHAT",
- "WHO",
- "WHY",
- "MODE",
- "UID",
- "PID");
-
- dbus_message_iter_recurse(&iter, &sub);
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- const char *what, *who, *why, *mode;
- char *ewho, *ewhy;
- dbus_uint32_t uid, pid;
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
- r = -EIO;
- goto finish;
- }
-
- ewho = ellipsize(who, 20, 66);
- ewhy = ellipsize(why, 20, 66);
-
- printf("%-21s %-20s %-20s %-5s %6lu %6lu\n",
- what, ewho ? ewho : who, ewhy ? ewhy : why, mode, (unsigned long) uid, (unsigned long) pid);
-
- free(ewho);
- free(ewhy);
-
- dbus_message_iter_next(&sub);
-
- n++;
- }
-
- printf("\n%u inhibitors listed.\n", n);
- r = 0;
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- return r;
-}
-
-static int help(void) {
-
- printf("%s [OPTIONS...] {COMMAND} ...\n\n"
- "Execute a process while inhibiting shutdown/sleep/idle.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --what=WHAT Operations to inhibit, colon separated list of:\n"
- " shutdown, sleep, idle, handle-power-key,\n"
- " handle-suspend-key, handle-hibernate-key,\n"
- " handle-lid-switch\n"
- " --who=STRING A descriptive string who is inhibiting\n"
- " --why=STRING A descriptive string why is being inhibited\n"
- " --mode=MODE One of block or delay\n"
- " --list List active inhibitors\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100,
- ARG_WHAT,
- ARG_WHO,
- ARG_WHY,
- ARG_MODE,
- ARG_LIST,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "what", required_argument, NULL, ARG_WHAT },
- { "who", required_argument, NULL, ARG_WHO },
- { "why", required_argument, NULL, ARG_WHY },
- { "mode", required_argument, NULL, ARG_MODE },
- { "list", no_argument, NULL, ARG_LIST },
- { NULL, 0, NULL, 0 }
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "+h", options, NULL)) >= 0) {
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(DISTRIBUTION);
- puts(SYSTEMD_FEATURES);
- return 0;
-
- case ARG_WHAT:
- arg_what = optarg;
- break;
-
- case ARG_WHO:
- arg_who = optarg;
- break;
-
- case ARG_WHY:
- arg_why = optarg;
- break;
-
- case ARG_MODE:
- arg_mode = optarg;
- break;
-
- case ARG_LIST:
- arg_action = ACTION_LIST;
- break;
-
- default:
- log_error("Unknown option code %c", c);
- return -EINVAL;
- }
- }
-
- if (arg_action == ACTION_INHIBIT && optind >= argc) {
- log_error("Missing command line to execute.");
- return -EINVAL;
- }
-
- return 1;
-}
-
-int main(int argc, char *argv[]) {
- int r, exit_code = 0;
- DBusConnection *bus = NULL;
- DBusError error;
- int fd = -1;
-
- dbus_error_init(&error);
-
- log_parse_environment();
- log_open();
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- goto finish;
-
- bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
- if (!bus) {
- log_error("Failed to connect to bus: %s", bus_error_message(&error));
- r = -EIO;
- goto finish;
- }
-
- if (arg_action == ACTION_LIST) {
-
- r = print_inhibitors(bus, &error);
- if (r < 0) {
- log_error("Failed to list inhibitors: %s", bus_error_message_or_strerror(&error, -r));
- goto finish;
- }
-
- } else {
- char *w = NULL;
- pid_t pid;
-
- if (!arg_who)
- arg_who = w = strv_join(argv + optind, " ");
-
- fd = inhibit(bus, &error);
- free(w);
-
- if (fd < 0) {
- log_error("Failed to inhibit: %s", bus_error_message_or_strerror(&error, -r));
- r = fd;
- goto finish;
- }
-
- pid = fork();
- if (pid < 0) {
- log_error("Failed to fork: %m");
- r = -errno;
- goto finish;
- }
-
- if (pid == 0) {
- /* Child */
-
- close_nointr_nofail(fd);
- close_all_fds(NULL, 0);
-
- execvp(argv[optind], argv + optind);
- log_error("Failed to execute %s: %m", argv[optind]);
- _exit(EXIT_FAILURE);
- }
-
- r = wait_for_terminate_and_warn(argv[optind], pid);
- if (r >= 0)
- exit_code = r;
- }
-
-finish:
- if (bus) {
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
- }
-
- dbus_error_free(&error);
-
- if (fd >= 0)
- close_nointr_nofail(fd);
-
- return r < 0 ? EXIT_FAILURE : exit_code;
-}
diff --git a/src/login/libsystemd-login.pc.in b/src/login/libsystemd-login.pc.in
deleted file mode 100644
index 7b2a7245fc..0000000000
--- a/src/login/libsystemd-login.pc.in
+++ /dev/null
@@ -1,18 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-
-Name: systemd
-Description: systemd Login Utility Library
-URL: @PACKAGE_URL@
-Version: @PACKAGE_VERSION@
-Libs: -L${libdir} -lsystemd-login
-Cflags: -I${includedir}
diff --git a/src/login/libsystemd-login.sym b/src/login/libsystemd-login.sym
deleted file mode 100644
index ff51be729b..0000000000
--- a/src/login/libsystemd-login.sym
+++ /dev/null
@@ -1,55 +0,0 @@
-/***
- This file is part of systemd.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-***/
-
-/* Original symbols from systemd v31 */
-
-LIBSYSTEMD_LOGIN_31 {
-global:
- sd_get_seats;
- sd_get_sessions;
- sd_get_uids;
- sd_login_monitor_flush;
- sd_login_monitor_get_fd;
- sd_login_monitor_new;
- sd_login_monitor_unref;
- sd_pid_get_owner_uid;
- sd_pid_get_session;
- sd_seat_can_multi_session;
- sd_seat_get_active;
- sd_seat_get_sessions;
- sd_session_get_seat;
- sd_session_get_uid;
- sd_session_is_active;
- sd_uid_get_seats;
- sd_uid_get_sessions;
- sd_uid_get_state;
- sd_uid_is_on_seat;
-local:
- *;
-};
-
-LIBSYSTEMD_LOGIN_38 {
-global:
- sd_pid_get_unit;
- sd_session_get_service;
-} LIBSYSTEMD_LOGIN_31;
-
-LIBSYSTEMD_LOGIN_43 {
-global:
- sd_session_get_type;
- sd_session_get_class;
- sd_session_get_display;
-} LIBSYSTEMD_LOGIN_38;
-
-LIBSYSTEMD_LOGIN_186 {
-global:
- sd_session_get_state;
- sd_seat_can_tty;
- sd_seat_can_graphical;
-} LIBSYSTEMD_LOGIN_43;
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
deleted file mode 100644
index 146986b46e..0000000000
--- a/src/login/loginctl.c
+++ /dev/null
@@ -1,1611 +0,0 @@
-/*-*- 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 <dbus/dbus.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <getopt.h>
-#include <pwd.h>
-#include <locale.h>
-
-#include "log.h"
-#include "util.h"
-#include "macro.h"
-#include "pager.h"
-#include "dbus-common.h"
-#include "build.h"
-#include "strv.h"
-#include "cgroup-show.h"
-#include "sysfs-show.h"
-#include "spawn-polkit-agent.h"
-
-static char **arg_property = NULL;
-static bool arg_all = false;
-static bool arg_no_pager = false;
-static const char *arg_kill_who = NULL;
-static int arg_signal = SIGTERM;
-static enum transport {
- TRANSPORT_NORMAL,
- TRANSPORT_SSH,
- TRANSPORT_POLKIT
-} arg_transport = TRANSPORT_NORMAL;
-static bool arg_ask_password = true;
-static const char *arg_host = NULL;
-
-static void pager_open_if_enabled(void) {
-
- /* Cache result before we open the pager */
- if (arg_no_pager)
- return;
-
- pager_open();
-}
-
-static void polkit_agent_open_if_enabled(void) {
-
- /* Open the polkit agent as a child process if necessary */
-
- if (!arg_ask_password)
- return;
-
- polkit_agent_open();
-}
-
-static int list_sessions(DBusConnection *bus, char **args, unsigned n) {
- DBusMessage *reply = NULL;
- int r;
- DBusMessageIter iter, sub, sub2;
- unsigned k = 0;
-
- pager_open_if_enabled();
-
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "ListSessions",
- &reply,
- NULL,
- DBUS_TYPE_INVALID);
- if (r)
- goto finish;
-
- if (!dbus_message_iter_init(reply, &iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&iter, &sub);
-
- if (on_tty())
- printf("%10s %10s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT");
-
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- const char *id, *user, *seat, *object;
- uint32_t uid;
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &user, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &seat, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &object, false) < 0) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- printf("%10s %10u %-16s %-16s\n", id, (unsigned) uid, user, seat);
-
- k++;
-
- dbus_message_iter_next(&sub);
- }
-
- if (on_tty())
- printf("\n%u sessions listed.\n", k);
-
- r = 0;
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- return r;
-}
-
-static int list_users(DBusConnection *bus, char **args, unsigned n) {
- DBusMessage *reply = NULL;
- int r;
- DBusMessageIter iter, sub, sub2;
- unsigned k = 0;
-
- pager_open_if_enabled();
-
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "ListUsers",
- &reply,
- NULL,
- DBUS_TYPE_INVALID);
- if (r)
- goto finish;
-
- if (!dbus_message_iter_init(reply, &iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&iter, &sub);
-
- if (on_tty())
- printf("%10s %-16s\n", "UID", "USER");
-
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- const char *user, *object;
- uint32_t uid;
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &user, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &object, false) < 0) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- printf("%10u %-16s\n", (unsigned) uid, user);
-
- k++;
-
- dbus_message_iter_next(&sub);
- }
-
- if (on_tty())
- printf("\n%u users listed.\n", k);
-
- r = 0;
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- return r;
-}
-
-static int list_seats(DBusConnection *bus, char **args, unsigned n) {
- DBusMessage *reply = NULL;
- int r;
- DBusMessageIter iter, sub, sub2;
- unsigned k = 0;
-
- pager_open_if_enabled();
-
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "ListSeats",
- &reply,
- NULL,
- DBUS_TYPE_INVALID);
- if (r)
- goto finish;
-
- if (!dbus_message_iter_init(reply, &iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&iter, &sub);
-
- if (on_tty())
- printf("%-16s\n", "SEAT");
-
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- const char *seat, *object;
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &seat, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &object, false) < 0) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- printf("%-16s\n", seat);
-
- k++;
-
- dbus_message_iter_next(&sub);
- }
-
- if (on_tty())
- printf("\n%u seats listed.\n", k);
-
- r = 0;
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- return r;
-}
-
-typedef struct SessionStatusInfo {
- const char *id;
- uid_t uid;
- const char *name;
- usec_t timestamp;
- const char *default_control_group;
- int vtnr;
- const char *seat;
- const char *tty;
- const char *display;
- bool remote;
- const char *remote_host;
- const char *remote_user;
- const char *service;
- pid_t leader;
- const char *type;
- const char *class;
- const char *state;
-} SessionStatusInfo;
-
-typedef struct UserStatusInfo {
- uid_t uid;
- const char *name;
- usec_t timestamp;
- const char *default_control_group;
- const char *state;
- char **sessions;
- const char *display;
-} UserStatusInfo;
-
-typedef struct SeatStatusInfo {
- const char *id;
- const char *active_session;
- char **sessions;
-} SeatStatusInfo;
-
-static void print_session_status_info(SessionStatusInfo *i) {
- char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
- char since2[FORMAT_TIMESTAMP_MAX], *s2;
- assert(i);
-
- printf("%s - ", strna(i->id));
-
- if (i->name)
- printf("%s (%u)\n", i->name, (unsigned) i->uid);
- else
- printf("%u\n", (unsigned) i->uid);
-
- s1 = format_timestamp_pretty(since1, sizeof(since1), i->timestamp);
- s2 = format_timestamp(since2, sizeof(since2), i->timestamp);
-
- if (s1)
- printf("\t Since: %s; %s\n", s2, s1);
- else if (s2)
- printf("\t Since: %s\n", s2);
-
- if (i->leader > 0) {
- char *t = NULL;
-
- printf("\t Leader: %u", (unsigned) i->leader);
-
- get_process_comm(i->leader, &t);
- if (t) {
- printf(" (%s)", t);
- free(t);
- }
-
- printf("\n");
- }
-
- if (i->seat) {
- printf("\t Seat: %s", i->seat);
-
- if (i->vtnr > 0)
- printf("; vc%i", i->vtnr);
-
- printf("\n");
- }
-
- if (i->tty)
- printf("\t TTY: %s\n", i->tty);
- else if (i->display)
- printf("\t Display: %s\n", i->display);
-
- if (i->remote_host && i->remote_user)
- printf("\t Remote: %s@%s\n", i->remote_user, i->remote_host);
- else if (i->remote_host)
- printf("\t Remote: %s\n", i->remote_host);
- else if (i->remote_user)
- printf("\t Remote: user %s\n", i->remote_user);
- else if (i->remote)
- printf("\t Remote: Yes\n");
-
- if (i->service) {
- printf("\t Service: %s", i->service);
-
- if (i->type)
- printf("; type %s", i->type);
-
- if (i->class)
- printf("; class %s", i->class);
-
- printf("\n");
- } else if (i->type) {
- printf("\t Type: %s\n", i->type);
-
- if (i->class)
- printf("; class %s", i->class);
- } else if (i->class)
- printf("\t Class: %s\n", i->class);
-
- if (i->state)
- printf("\t State: %s\n", i->state);
-
- if (i->default_control_group) {
- unsigned c;
-
- printf("\t CGroup: %s\n", i->default_control_group);
-
- if (arg_transport != TRANSPORT_SSH) {
- c = columns();
- if (c > 18)
- c -= 18;
- else
- c = 0;
-
- show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, &i->leader, i->leader > 0 ? 1 : 0);
- }
- }
-}
-
-static void print_user_status_info(UserStatusInfo *i) {
- char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
- char since2[FORMAT_TIMESTAMP_MAX], *s2;
- assert(i);
-
- if (i->name)
- printf("%s (%u)\n", i->name, (unsigned) i->uid);
- else
- printf("%u\n", (unsigned) i->uid);
-
- s1 = format_timestamp_pretty(since1, sizeof(since1), i->timestamp);
- s2 = format_timestamp(since2, sizeof(since2), i->timestamp);
-
- if (s1)
- printf("\t Since: %s; %s\n", s2, s1);
- else if (s2)
- printf("\t Since: %s\n", s2);
-
- if (!isempty(i->state))
- printf("\t State: %s\n", i->state);
-
- if (!strv_isempty(i->sessions)) {
- char **l;
- printf("\tSessions:");
-
- STRV_FOREACH(l, i->sessions) {
- if (streq_ptr(*l, i->display))
- printf(" *%s", *l);
- else
- printf(" %s", *l);
- }
-
- printf("\n");
- }
-
- if (i->default_control_group) {
- unsigned c;
-
- printf("\t CGroup: %s\n", i->default_control_group);
-
- if (arg_transport != TRANSPORT_SSH) {
- c = columns();
- if (c > 18)
- c -= 18;
- else
- c = 0;
-
- show_cgroup_by_path(i->default_control_group, "\t\t ", c, false, arg_all);
- }
- }
-}
-
-static void print_seat_status_info(SeatStatusInfo *i) {
- assert(i);
-
- printf("%s\n", strna(i->id));
-
- if (!strv_isempty(i->sessions)) {
- char **l;
- printf("\tSessions:");
-
- STRV_FOREACH(l, i->sessions) {
- if (streq_ptr(*l, i->active_session))
- printf(" *%s", *l);
- else
- printf(" %s", *l);
- }
-
- printf("\n");
- }
-
- if (arg_transport != TRANSPORT_SSH) {
- unsigned c;
-
- c = columns();
- if (c > 21)
- c -= 21;
- else
- c = 0;
-
- printf("\t Devices:\n");
-
- show_sysfs(i->id, "\t\t ", c);
- }
-}
-
-static int status_property_session(const char *name, DBusMessageIter *iter, SessionStatusInfo *i) {
- assert(name);
- assert(iter);
- assert(i);
-
- switch (dbus_message_iter_get_arg_type(iter)) {
-
- case DBUS_TYPE_STRING: {
- const char *s;
-
- dbus_message_iter_get_basic(iter, &s);
-
- if (!isempty(s)) {
- if (streq(name, "Id"))
- i->id = s;
- else if (streq(name, "Name"))
- i->name = s;
- else if (streq(name, "DefaultControlGroup"))
- i->default_control_group = s;
- else if (streq(name, "TTY"))
- i->tty = s;
- else if (streq(name, "Display"))
- i->display = s;
- else if (streq(name, "RemoteHost"))
- i->remote_host = s;
- else if (streq(name, "RemoteUser"))
- i->remote_user = s;
- else if (streq(name, "Service"))
- i->service = s;
- else if (streq(name, "Type"))
- i->type = s;
- else if (streq(name, "Class"))
- i->class = s;
- else if (streq(name, "State"))
- i->state = s;
- }
- break;
- }
-
- case DBUS_TYPE_UINT32: {
- uint32_t u;
-
- dbus_message_iter_get_basic(iter, &u);
-
- if (streq(name, "VTNr"))
- i->vtnr = (int) u;
- else if (streq(name, "Leader"))
- i->leader = (pid_t) u;
-
- break;
- }
-
- case DBUS_TYPE_BOOLEAN: {
- dbus_bool_t b;
-
- dbus_message_iter_get_basic(iter, &b);
-
- if (streq(name, "Remote"))
- i->remote = b;
-
- break;
- }
-
- case DBUS_TYPE_UINT64: {
- uint64_t u;
-
- dbus_message_iter_get_basic(iter, &u);
-
- if (streq(name, "Timestamp"))
- i->timestamp = (usec_t) u;
-
- break;
- }
-
- case DBUS_TYPE_STRUCT: {
- DBusMessageIter sub;
-
- dbus_message_iter_recurse(iter, &sub);
-
- if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "User")) {
- uint32_t u;
-
- dbus_message_iter_get_basic(&sub, &u);
- i->uid = (uid_t) u;
-
- } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Seat")) {
- const char *s;
-
- dbus_message_iter_get_basic(&sub, &s);
-
- if (!isempty(s))
- i->seat = s;
- }
-
- break;
- }
- }
-
- return 0;
-}
-
-static int status_property_user(const char *name, DBusMessageIter *iter, UserStatusInfo *i) {
- assert(name);
- assert(iter);
- assert(i);
-
- switch (dbus_message_iter_get_arg_type(iter)) {
-
- case DBUS_TYPE_STRING: {
- const char *s;
-
- dbus_message_iter_get_basic(iter, &s);
-
- if (!isempty(s)) {
- if (streq(name, "Name"))
- i->name = s;
- else if (streq(name, "DefaultControlGroup"))
- i->default_control_group = s;
- else if (streq(name, "State"))
- i->state = s;
- }
- break;
- }
-
- case DBUS_TYPE_UINT32: {
- uint32_t u;
-
- dbus_message_iter_get_basic(iter, &u);
-
- if (streq(name, "UID"))
- i->uid = (uid_t) u;
-
- break;
- }
-
- case DBUS_TYPE_UINT64: {
- uint64_t u;
-
- dbus_message_iter_get_basic(iter, &u);
-
- if (streq(name, "Timestamp"))
- i->timestamp = (usec_t) u;
-
- break;
- }
-
- case DBUS_TYPE_STRUCT: {
- DBusMessageIter sub;
-
- dbus_message_iter_recurse(iter, &sub);
-
- if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Display")) {
- const char *s;
-
- dbus_message_iter_get_basic(&sub, &s);
-
- if (!isempty(s))
- i->display = s;
- }
-
- break;
- }
-
- case DBUS_TYPE_ARRAY: {
-
- if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Sessions")) {
- DBusMessageIter sub, sub2;
-
- dbus_message_iter_recurse(iter, &sub);
- while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
- const char *id;
- const char *path;
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) >= 0 &&
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &path, false) >= 0) {
- char **l;
-
- l = strv_append(i->sessions, id);
- if (!l)
- return -ENOMEM;
-
- strv_free(i->sessions);
- i->sessions = l;
- }
-
- dbus_message_iter_next(&sub);
- }
-
- return 0;
- }
- }
- }
-
- return 0;
-}
-
-static int status_property_seat(const char *name, DBusMessageIter *iter, SeatStatusInfo *i) {
- assert(name);
- assert(iter);
- assert(i);
-
- switch (dbus_message_iter_get_arg_type(iter)) {
-
- case DBUS_TYPE_STRING: {
- const char *s;
-
- dbus_message_iter_get_basic(iter, &s);
-
- if (!isempty(s)) {
- if (streq(name, "Id"))
- i->id = s;
- }
- break;
- }
-
- case DBUS_TYPE_STRUCT: {
- DBusMessageIter sub;
-
- dbus_message_iter_recurse(iter, &sub);
-
- if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "ActiveSession")) {
- const char *s;
-
- dbus_message_iter_get_basic(&sub, &s);
-
- if (!isempty(s))
- i->active_session = s;
- }
-
- break;
- }
-
- case DBUS_TYPE_ARRAY: {
-
- if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Sessions")) {
- DBusMessageIter sub, sub2;
-
- dbus_message_iter_recurse(iter, &sub);
- while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
- const char *id;
- const char *path;
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) >= 0 &&
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &path, false) >= 0) {
- char **l;
-
- l = strv_append(i->sessions, id);
- if (!l)
- return -ENOMEM;
-
- strv_free(i->sessions);
- i->sessions = l;
- }
-
- dbus_message_iter_next(&sub);
- }
-
- return 0;
- }
- }
- }
-
- return 0;
-}
-
-static int print_property(const char *name, DBusMessageIter *iter) {
- assert(name);
- assert(iter);
-
- if (arg_property && !strv_find(arg_property, name))
- return 0;
-
- switch (dbus_message_iter_get_arg_type(iter)) {
-
- case DBUS_TYPE_STRUCT: {
- DBusMessageIter sub;
-
- dbus_message_iter_recurse(iter, &sub);
-
- if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING &&
- (streq(name, "Display") || streq(name, "ActiveSession"))) {
- const char *s;
-
- dbus_message_iter_get_basic(&sub, &s);
-
- if (arg_all || !isempty(s))
- printf("%s=%s\n", name, s);
- return 0;
- }
- break;
- }
-
- case DBUS_TYPE_ARRAY:
-
- if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Sessions")) {
- DBusMessageIter sub, sub2;
- bool found = false;
-
- dbus_message_iter_recurse(iter, &sub);
- while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
- const char *id;
- const char *path;
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) >= 0 &&
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &path, false) >= 0) {
- if (found)
- printf(" %s", id);
- else {
- printf("%s=%s", name, id);
- found = true;
- }
- }
-
- dbus_message_iter_next(&sub);
- }
-
- if (!found && arg_all)
- printf("%s=\n", name);
- else if (found)
- printf("\n");
-
- return 0;
- }
-
- break;
- }
-
- if (generic_print_property(name, iter, arg_all) > 0)
- return 0;
-
- if (arg_all)
- printf("%s=[unprintable]\n", name);
-
- return 0;
-}
-
-static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- const char *interface = "";
- int r;
- DBusMessageIter iter, sub, sub2, sub3;
- SessionStatusInfo session_info;
- UserStatusInfo user_info;
- SeatStatusInfo seat_info;
-
- assert(path);
- assert(new_line);
-
- zero(session_info);
- zero(user_info);
- zero(seat_info);
-
- r = bus_method_call_with_reply(
- bus,
- "org.freedesktop.login1",
- path,
- "org.freedesktop.DBus.Properties",
- "GetAll",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &interface,
- DBUS_TYPE_INVALID);
- if (r < 0)
- goto finish;
-
- if (!dbus_message_iter_init(reply, &iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&iter, &sub);
-
- if (*new_line)
- printf("\n");
-
- *new_line = true;
-
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- const char *name;
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&sub2, &sub3);
-
- if (show_properties)
- r = print_property(name, &sub3);
- else if (strstr(verb, "session"))
- r = status_property_session(name, &sub3, &session_info);
- else if (strstr(verb, "user"))
- r = status_property_user(name, &sub3, &user_info);
- else
- r = status_property_seat(name, &sub3, &seat_info);
-
- if (r < 0) {
- log_error("Failed to parse reply.");
- goto finish;
- }
-
- dbus_message_iter_next(&sub);
- }
-
- if (!show_properties) {
- if (strstr(verb, "session"))
- print_session_status_info(&session_info);
- else if (strstr(verb, "user"))
- print_user_status_info(&user_info);
- else
- print_seat_status_info(&seat_info);
- }
-
- r = 0;
-
-finish:
- strv_free(seat_info.sessions);
- strv_free(user_info.sessions);
-
- return r;
-}
-
-static int show(DBusConnection *bus, char **args, unsigned n) {
- DBusMessage *reply = NULL;
- int r, ret = 0;
- DBusError error;
- unsigned i;
- bool show_properties, new_line = false;
-
- assert(bus);
- assert(args);
-
- dbus_error_init(&error);
-
- show_properties = !strstr(args[0], "status");
-
- pager_open_if_enabled();
-
- if (show_properties && n <= 1) {
- /* If not argument is specified inspect the manager
- * itself */
-
- ret = show_one(args[0], bus, "/org/freedesktop/login1", show_properties, &new_line);
- goto finish;
- }
-
- for (i = 1; i < n; i++) {
- const char *path = NULL;
-
- if (strstr(args[0], "session")) {
-
- ret = bus_method_call_with_reply (
- bus,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "GetSession",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &args[i],
- DBUS_TYPE_INVALID);
-
- } else if (strstr(args[0], "user")) {
- uid_t uid;
- uint32_t u;
-
- ret = get_user_creds((const char**) (args+i), &uid, NULL, NULL, NULL);
- if (ret < 0) {
- log_error("User %s unknown.", args[i]);
- goto finish;
- }
-
- u = (uint32_t) uid;
- ret = bus_method_call_with_reply (
- bus,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "GetUser",
- &reply,
- NULL,
- DBUS_TYPE_UINT32, &u,
- DBUS_TYPE_INVALID);
- } else {
-
- ret = bus_method_call_with_reply (
- bus,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "GetSeat",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &args[i],
- DBUS_TYPE_INVALID);
- }
- if (ret)
- goto finish;
-
- if (!dbus_message_get_args(reply, &error,
- DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID)) {
- log_error("Failed to parse reply: %s", bus_error_message(&error));
- ret = -EIO;
- goto finish;
- }
-
- r = show_one(args[0], bus, path, show_properties, &new_line);
- if (r != 0)
- ret = r;
-
- dbus_message_unref(reply);
- reply = NULL;
- }
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- dbus_error_free(&error);
-
- return ret;
-}
-
-static int activate(DBusConnection *bus, char **args, unsigned n) {
- int ret = 0;
- unsigned i;
-
- assert(args);
-
- for (i = 1; i < n; i++) {
-
- ret = bus_method_call_with_reply (
- bus,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- streq(args[0], "lock-session") ? "LockSession" :
- streq(args[0], "unlock-session") ? "UnlockSession" :
- streq(args[0], "terminate-session") ? "TerminateSession" :
- "ActivateSession",
- NULL,
- NULL,
- DBUS_TYPE_STRING, &args[i],
- DBUS_TYPE_INVALID);
- if (ret)
- goto finish;
- }
-
-finish:
- return ret;
-}
-
-static int kill_session(DBusConnection *bus, char **args, unsigned n) {
- int ret = 0;
- unsigned i;
-
- assert(args);
-
- if (!arg_kill_who)
- arg_kill_who = "all";
-
- for (i = 1; i < n; i++) {
- ret = bus_method_call_with_reply (
- bus,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "KillSession",
- NULL,
- NULL,
- DBUS_TYPE_STRING, &args[i],
- DBUS_TYPE_STRING, &arg_kill_who,
- DBUS_TYPE_INT32, &arg_signal,
- DBUS_TYPE_INVALID);
- if (ret)
- goto finish;
- }
-
-finish:
- return ret;
-}
-
-static int enable_linger(DBusConnection *bus, char **args, unsigned n) {
- int ret = 0;
- unsigned i;
- dbus_bool_t b, interactive = true;
-
- assert(args);
-
- polkit_agent_open_if_enabled();
-
- b = streq(args[0], "enable-linger");
-
- for (i = 1; i < n; i++) {
- uint32_t u;
- uid_t uid;
-
- ret = get_user_creds((const char**) (args+i), &uid, NULL, NULL, NULL);
- if (ret < 0) {
- log_error("Failed to resolve user %s: %s", args[i], strerror(-ret));
- goto finish;
- }
-
- u = (uint32_t) uid;
- ret = bus_method_call_with_reply (
- bus,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "SetUserLinger",
- NULL,
- NULL,
- DBUS_TYPE_UINT32, &u,
- DBUS_TYPE_BOOLEAN, &b,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID);
- if (ret)
- goto finish;
- }
-
-finish:
- return ret;
-}
-
-static int terminate_user(DBusConnection *bus, char **args, unsigned n) {
- int ret = 0;
- unsigned i;
-
- assert(args);
-
- for (i = 1; i < n; i++) {
- uint32_t u;
- uid_t uid;
-
- ret = get_user_creds((const char**) (args+i), &uid, NULL, NULL, NULL);
- if (ret < 0) {
- log_error("Failed to look up user %s: %s", args[i], strerror(-ret));
- goto finish;
- }
-
- u = (uint32_t) uid;
- ret = bus_method_call_with_reply (
- bus,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "TerminateUser",
- NULL,
- NULL,
- DBUS_TYPE_UINT32, &u,
- DBUS_TYPE_INVALID);
- if (ret)
- goto finish;
- }
-
-finish:
- return ret;
-}
-
-static int kill_user(DBusConnection *bus, char **args, unsigned n) {
- int ret = 0;
- unsigned i;
-
- assert(args);
-
- if (!arg_kill_who)
- arg_kill_who = "all";
-
- for (i = 1; i < n; i++) {
- uid_t uid;
- uint32_t u;
-
- ret = get_user_creds((const char**) (args+i), &uid, NULL, NULL, NULL);
- if (ret < 0) {
- log_error("Failed to look up user %s: %s", args[i], strerror(-ret));
- goto finish;
- }
-
- u = (uint32_t) uid;
- ret = bus_method_call_with_reply (
- bus,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "KillUser",
- NULL,
- NULL,
- DBUS_TYPE_UINT32, &u,
- DBUS_TYPE_INT32, &arg_signal,
- DBUS_TYPE_INVALID);
- if (ret)
- goto finish;
- }
-
-finish:
- return ret;
-}
-
-static int attach(DBusConnection *bus, char **args, unsigned n) {
- int ret = 0;
- unsigned i;
- dbus_bool_t interactive = true;
-
- assert(args);
-
- polkit_agent_open_if_enabled();
-
- for (i = 2; i < n; i++) {
- ret = bus_method_call_with_reply (
- bus,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "AttachDevice",
- NULL,
- NULL,
- DBUS_TYPE_STRING, &args[1],
- DBUS_TYPE_STRING, &args[i],
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID);
- if (ret)
- goto finish;
- }
-
-finish:
- return ret;
-}
-
-static int flush_devices(DBusConnection *bus, char **args, unsigned n) {
- dbus_bool_t interactive = true;
-
- assert(args);
-
- polkit_agent_open_if_enabled();
-
- return bus_method_call_with_reply (
- bus,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "FlushDevices",
- NULL,
- NULL,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID);
-}
-
-static int lock_sessions(DBusConnection *bus, char **args, unsigned n) {
- polkit_agent_open_if_enabled();
-
- return bus_method_call_with_reply (
- bus,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "LockSessions",
- NULL,
- NULL,
- DBUS_TYPE_INVALID);
-}
-
-static int terminate_seat(DBusConnection *bus, char **args, unsigned n) {
- int ret = 0;
- unsigned i;
-
- assert(args);
-
- for (i = 1; i < n; i++) {
- ret = bus_method_call_with_reply (
- bus,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "TerminateSeat",
- NULL,
- NULL,
- DBUS_TYPE_STRING, &args[i],
- DBUS_TYPE_INVALID);
- if (ret)
- goto finish;
- }
-
-finish:
- return ret;
-}
-
-static int help(void) {
-
- printf("%s [OPTIONS...] {COMMAND} ...\n\n"
- "Send control commands to or query the login manager.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " -p --property=NAME Show only properties by this name\n"
- " -a --all Show all properties, including empty ones\n"
- " --kill-who=WHO Who to send signal to\n"
- " -s --signal=SIGNAL Which signal to send\n"
- " --no-ask-password Don't prompt for password\n"
- " -H --host=[USER@]HOST Show information for remote host\n"
- " -P --privileged Acquire privileges before execution\n"
- " --no-pager Do not pipe output into a pager\n\n"
- "Commands:\n"
- " list-sessions List sessions\n"
- " session-status [ID...] Show session status\n"
- " show-session [ID...] Show properties of one or more sessions\n"
- " activate [ID] Activate a session\n"
- " lock-session [ID...] Screen lock one or more sessions\n"
- " unlock-session [ID...] Screen unlock one or more sessions\n"
- " lock-sessions Screen lock all current sessions\n"
- " terminate-session [ID...] Terminate one or more sessions\n"
- " kill-session [ID...] Send signal to processes of a session\n"
- " list-users List users\n"
- " user-status [USER...] Show user status\n"
- " show-user [USER...] Show properties of one or more users\n"
- " enable-linger [USER...] Enable linger state of one or more users\n"
- " disable-linger [USER...] Disable linger state of one or more users\n"
- " terminate-user [USER...] Terminate all sessions of one or more users\n"
- " kill-user [USER...] Send signal to processes of a user\n"
- " list-seats List seats\n"
- " seat-status [NAME...] Show seat status\n"
- " show-seat [NAME...] Show properties of one or more seats\n"
- " attach [NAME] [DEVICE...] Attach one or more devices to a seat\n"
- " flush-devices Flush all device associations\n"
- " terminate-seat [NAME...] Terminate all sessions on one or more seats\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100,
- ARG_NO_PAGER,
- ARG_KILL_WHO,
- ARG_NO_ASK_PASSWORD
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "property", required_argument, NULL, 'p' },
- { "all", no_argument, NULL, 'a' },
- { "no-pager", no_argument, NULL, ARG_NO_PAGER },
- { "kill-who", required_argument, NULL, ARG_KILL_WHO },
- { "signal", required_argument, NULL, 's' },
- { "host", required_argument, NULL, 'H' },
- { "privileged", no_argument, NULL, 'P' },
- { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
- { NULL, 0, NULL, 0 }
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "hp:as:H:P", options, NULL)) >= 0) {
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(DISTRIBUTION);
- puts(SYSTEMD_FEATURES);
- return 0;
-
- case 'p': {
- char **l;
-
- l = strv_append(arg_property, optarg);
- if (!l)
- return -ENOMEM;
-
- strv_free(arg_property);
- arg_property = l;
-
- /* If the user asked for a particular
- * property, show it to him, even if it is
- * empty. */
- arg_all = true;
- break;
- }
-
- case 'a':
- arg_all = true;
- break;
-
- case ARG_NO_PAGER:
- arg_no_pager = true;
- break;
-
- case ARG_NO_ASK_PASSWORD:
- arg_ask_password = false;
- break;
-
- case ARG_KILL_WHO:
- arg_kill_who = optarg;
- break;
-
- case 's':
- arg_signal = signal_from_string_try_harder(optarg);
- if (arg_signal < 0) {
- log_error("Failed to parse signal string %s.", optarg);
- return -EINVAL;
- }
- break;
-
- case 'P':
- arg_transport = TRANSPORT_POLKIT;
- break;
-
- case 'H':
- arg_transport = TRANSPORT_SSH;
- arg_host = optarg;
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- log_error("Unknown option code %c", c);
- return -EINVAL;
- }
- }
-
- return 1;
-}
-
-static int loginctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
-
- static const struct {
- const char* verb;
- const enum {
- MORE,
- LESS,
- EQUAL
- } argc_cmp;
- const int argc;
- int (* const dispatch)(DBusConnection *bus, char **args, unsigned n);
- } verbs[] = {
- { "list-sessions", LESS, 1, list_sessions },
- { "session-status", MORE, 2, show },
- { "show-session", MORE, 1, show },
- { "activate", EQUAL, 2, activate },
- { "lock-session", MORE, 2, activate },
- { "unlock-session", MORE, 2, activate },
- { "lock-sessions", EQUAL, 1, lock_sessions },
- { "terminate-session", MORE, 2, activate },
- { "kill-session", MORE, 2, kill_session },
- { "list-users", EQUAL, 1, list_users },
- { "user-status", MORE, 2, show },
- { "show-user", MORE, 1, show },
- { "enable-linger", MORE, 2, enable_linger },
- { "disable-linger", MORE, 2, enable_linger },
- { "terminate-user", MORE, 2, terminate_user },
- { "kill-user", MORE, 2, kill_user },
- { "list-seats", EQUAL, 1, list_seats },
- { "seat-status", MORE, 2, show },
- { "show-seat", MORE, 1, show },
- { "attach", MORE, 3, attach },
- { "flush-devices", EQUAL, 1, flush_devices },
- { "terminate-seat", MORE, 2, terminate_seat },
- };
-
- int left;
- unsigned i;
-
- assert(argc >= 0);
- assert(argv);
- assert(error);
-
- left = argc - optind;
-
- if (left <= 0)
- /* Special rule: no arguments means "list-sessions" */
- i = 0;
- else {
- if (streq(argv[optind], "help")) {
- help();
- return 0;
- }
-
- for (i = 0; i < ELEMENTSOF(verbs); i++)
- if (streq(argv[optind], verbs[i].verb))
- break;
-
- if (i >= ELEMENTSOF(verbs)) {
- log_error("Unknown operation %s", argv[optind]);
- return -EINVAL;
- }
- }
-
- switch (verbs[i].argc_cmp) {
-
- case EQUAL:
- if (left != verbs[i].argc) {
- log_error("Invalid number of arguments.");
- return -EINVAL;
- }
-
- break;
-
- case MORE:
- if (left < verbs[i].argc) {
- log_error("Too few arguments.");
- return -EINVAL;
- }
-
- break;
-
- case LESS:
- if (left > verbs[i].argc) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
- break;
-
- default:
- assert_not_reached("Unknown comparison operator.");
- }
-
- if (!bus) {
- log_error("Failed to get D-Bus connection: %s", error->message);
- return -EIO;
- }
-
- return verbs[i].dispatch(bus, argv + optind, left);
-}
-
-int main(int argc, char*argv[]) {
- int r, retval = EXIT_FAILURE;
- DBusConnection *bus = NULL;
- DBusError error;
-
- dbus_error_init(&error);
-
- setlocale(LC_ALL, "");
- log_parse_environment();
- log_open();
-
- r = parse_argv(argc, argv);
- if (r < 0)
- goto finish;
- else if (r == 0) {
- retval = EXIT_SUCCESS;
- goto finish;
- }
-
- if (arg_transport == TRANSPORT_NORMAL)
- bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
- else if (arg_transport == TRANSPORT_POLKIT)
- bus_connect_system_polkit(&bus, &error);
- else if (arg_transport == TRANSPORT_SSH)
- bus_connect_system_ssh(NULL, arg_host, &bus, &error);
- else
- assert_not_reached("Uh, invalid transport...");
-
- r = loginctl_main(bus, argc, argv, &error);
- retval = r < 0 ? EXIT_FAILURE : r;
-
-finish:
- if (bus) {
- dbus_connection_flush(bus);
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
- }
-
- dbus_error_free(&error);
- dbus_shutdown();
-
- strv_free(arg_property);
-
- pager_close();
-
- return retval;
-}
diff --git a/src/login/logind-acl.c b/src/login/logind-acl.c
deleted file mode 100644
index cb045a9928..0000000000
--- a/src/login/logind-acl.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <assert.h>
-#include <sys/acl.h>
-#include <acl/libacl.h>
-#include <errno.h>
-#include <string.h>
-
-#include "logind-acl.h"
-#include "util.h"
-#include "acl-util.h"
-
-static int flush_acl(acl_t acl) {
- acl_entry_t i;
- int found;
- bool changed = false;
-
- assert(acl);
-
- for (found = acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
- found > 0;
- found = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
-
- acl_tag_t tag;
-
- if (acl_get_tag_type(i, &tag) < 0)
- return -errno;
-
- if (tag != ACL_USER)
- continue;
-
- if (acl_delete_entry(acl, i) < 0)
- return -errno;
-
- changed = true;
- }
-
- if (found < 0)
- return -errno;
-
- return changed;
-}
-
-int devnode_acl(const char *path,
- bool flush,
- bool del, uid_t old_uid,
- bool add, uid_t new_uid) {
-
- acl_t acl;
- int r = 0;
- bool changed = false;
-
- assert(path);
-
- acl = acl_get_file(path, ACL_TYPE_ACCESS);
- if (!acl)
- return -errno;
-
- if (flush) {
-
- r = flush_acl(acl);
- if (r < 0)
- goto finish;
- if (r > 0)
- changed = true;
-
- } else if (del && old_uid > 0) {
- acl_entry_t entry;
-
- r = acl_find_uid(acl, old_uid, &entry);
- if (r < 0)
- goto finish;
-
- if (r > 0) {
- if (acl_delete_entry(acl, entry) < 0) {
- r = -errno;
- goto finish;
- }
-
- changed = true;
- }
- }
-
- if (add && new_uid > 0) {
- acl_entry_t entry;
- acl_permset_t permset;
- int rd, wt;
-
- r = acl_find_uid(acl, new_uid, &entry);
- if (r < 0)
- goto finish;
-
- if (r == 0) {
- if (acl_create_entry(&acl, &entry) < 0) {
- r = -errno;
- goto finish;
- }
-
- if (acl_set_tag_type(entry, ACL_USER) < 0 ||
- acl_set_qualifier(entry, &new_uid) < 0) {
- r = -errno;
- goto finish;
- }
- }
-
- if (acl_get_permset(entry, &permset) < 0) {
- r = -errno;
- goto finish;
- }
-
- rd = acl_get_perm(permset, ACL_READ);
- if (rd < 0) {
- r = -errno;
- goto finish;
- }
-
- wt = acl_get_perm(permset, ACL_WRITE);
- if (wt < 0) {
- r = -errno;
- goto finish;
- }
-
- if (!rd || !wt) {
-
- if (acl_add_perm(permset, ACL_READ|ACL_WRITE) < 0) {
- r = -errno;
- goto finish;
- }
-
- changed = true;
- }
- }
-
- if (!changed)
- goto finish;
-
- if (acl_calc_mask(&acl) < 0) {
- r = -errno;
- goto finish;
- }
-
- if (acl_set_file(path, ACL_TYPE_ACCESS, acl) < 0) {
- r = -errno;
- goto finish;
- }
-
- r = 0;
-
-finish:
- acl_free(acl);
-
- return r;
-}
-
-int devnode_acl_all(struct udev *udev,
- const char *seat,
- bool flush,
- bool del, uid_t old_uid,
- bool add, uid_t new_uid) {
-
- struct udev_list_entry *item = NULL, *first = NULL;
- struct udev_enumerate *e;
- int r;
-
- assert(udev);
-
- if (isempty(seat))
- seat = "seat0";
-
- e = udev_enumerate_new(udev);
- if (!e)
- return -ENOMEM;
-
- /* We can only match by one tag in libudev. We choose
- * "uaccess" for that. If we could match for two tags here we
- * could add the seat name as second match tag, but this would
- * be hardly optimizable in libudev, and hence checking the
- * second tag manually in our loop is a good solution. */
-
- r = udev_enumerate_add_match_tag(e, "uaccess");
- if (r < 0)
- goto finish;
-
- r = udev_enumerate_scan_devices(e);
- if (r < 0)
- goto finish;
-
- first = udev_enumerate_get_list_entry(e);
- udev_list_entry_foreach(item, first) {
- struct udev_device *d;
- const char *node, *sn;
-
- d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
- if (!d) {
- r = -ENOMEM;
- goto finish;
- }
-
- sn = udev_device_get_property_value(d, "ID_SEAT");
- if (isempty(sn))
- sn = "seat0";
-
- if (!streq(seat, sn)) {
- udev_device_unref(d);
- continue;
- }
-
- node = udev_device_get_devnode(d);
- if (!node) {
- /* In case people mistag devices with nodes, we need to ignore this */
- udev_device_unref(d);
- continue;
- }
-
- log_debug("Fixing up %s for seat %s...", node, sn);
-
- r = devnode_acl(node, flush, del, old_uid, add, new_uid);
- udev_device_unref(d);
-
- if (r < 0)
- goto finish;
- }
-
-finish:
- if (e)
- udev_enumerate_unref(e);
-
- return r;
-}
diff --git a/src/login/logind-acl.h b/src/login/logind-acl.h
deleted file mode 100644
index ec09843a78..0000000000
--- a/src/login/logind-acl.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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/types.h>
-#include <stdbool.h>
-#include <libudev.h>
-
-#ifdef HAVE_ACL
-
-int devnode_acl(const char *path,
- bool flush,
- bool del, uid_t old_uid,
- bool add, uid_t new_uid);
-
-int devnode_acl_all(struct udev *udev,
- const char *seat,
- bool flush,
- bool del, uid_t old_uid,
- bool add, uid_t new_uid);
-#else
-
-static inline int devnode_acl(const char *path,
- bool flush,
- bool del, uid_t old_uid,
- bool add, uid_t new_uid) {
- return 0;
-}
-
-static inline int devnode_acl_all(struct udev *udev,
- const char *seat,
- bool flush,
- bool del, uid_t old_uid,
- bool add, uid_t new_uid) {
- return 0;
-}
-
-#endif
diff --git a/src/login/logind-button.c b/src/login/logind-button.c
deleted file mode 100644
index 8bbd731ae4..0000000000
--- a/src/login/logind-button.c
+++ /dev/null
@@ -1,322 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <assert.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-#include <linux/input.h>
-#include <sys/epoll.h>
-
-#include "conf-parser.h"
-#include "util.h"
-#include "logind-button.h"
-#include "special.h"
-#include "dbus-common.h"
-
-Button* button_new(Manager *m, const char *name) {
- Button *b;
-
- assert(m);
- assert(name);
-
- b = new0(Button, 1);
- if (!b)
- return NULL;
-
- b->name = strdup(name);
- if (!b->name) {
- free(b);
- return NULL;
- }
-
- if (hashmap_put(m->buttons, b->name, b) < 0) {
- free(b->name);
- free(b);
- return NULL;
- }
-
- b->manager = m;
- b->fd = -1;
-
- return b;
-}
-
-void button_free(Button *b) {
- assert(b);
-
- hashmap_remove(b->manager->buttons, b->name);
-
- if (b->fd >= 0) {
- hashmap_remove(b->manager->button_fds, INT_TO_PTR(b->fd + 1));
- assert_se(epoll_ctl(b->manager->epoll_fd, EPOLL_CTL_DEL, b->fd, NULL) == 0);
- close_nointr_nofail(b->fd);
- }
-
- free(b->name);
- free(b->seat);
- free(b);
-}
-
-int button_set_seat(Button *b, const char *sn) {
- char *s;
-
- assert(b);
- assert(sn);
-
- s = strdup(sn);
- if (!s)
- return -ENOMEM;
-
- free(b->seat);
- b->seat = s;
-
- return 0;
-}
-
-int button_open(Button *b) {
- char name[256], *p;
- struct epoll_event ev;
- int r;
-
- assert(b);
-
- if (b->fd >= 0) {
- close_nointr_nofail(b->fd);
- b->fd = -1;
- }
-
- p = strappend("/dev/input/", b->name);
- if (!p)
- return log_oom();
-
- b->fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
- free(p);
- if (b->fd < 0) {
- log_warning("Failed to open %s: %m", b->name);
- return -errno;
- }
-
- if (ioctl(b->fd, EVIOCGNAME(sizeof(name)), name) < 0) {
- log_error("Failed to get input name: %m");
- r = -errno;
- goto fail;
- }
-
- zero(ev);
- ev.events = EPOLLIN;
- ev.data.u32 = FD_OTHER_BASE + b->fd;
-
- if (epoll_ctl(b->manager->epoll_fd, EPOLL_CTL_ADD, b->fd, &ev) < 0) {
- log_error("Failed to add to epoll: %m");
- r = -errno;
- goto fail;
- }
-
- r = hashmap_put(b->manager->button_fds, INT_TO_PTR(b->fd + 1), b);
- if (r < 0) {
- log_error("Failed to add to hash map: %s", strerror(-r));
- assert_se(epoll_ctl(b->manager->epoll_fd, EPOLL_CTL_DEL, b->fd, NULL) == 0);
- goto fail;
- }
-
- log_info("Watching system buttons on /dev/input/%s (%s)", b->name, name);
-
- return 0;
-
-fail:
- close_nointr_nofail(b->fd);
- b->fd = -1;
- return r;
-}
-
-static int button_handle(
- Button *b,
- InhibitWhat inhibit_key,
- HandleButton handle,
- bool ignore_inhibited,
- bool is_edge) {
-
- static const char * const message_table[_HANDLE_BUTTON_MAX] = {
- [HANDLE_POWEROFF] = "Powering Off...",
- [HANDLE_REBOOT] = "Rebooting...",
- [HANDLE_HALT] = "Halting...",
- [HANDLE_KEXEC] = "Rebooting via kexec...",
- [HANDLE_SUSPEND] = "Suspending...",
- [HANDLE_HIBERNATE] = "Hibernating...",
- [HANDLE_HYBRID_SLEEP] = "Hibernating and suspending..."
- };
-
- static const char * const target_table[_HANDLE_BUTTON_MAX] = {
- [HANDLE_POWEROFF] = SPECIAL_POWEROFF_TARGET,
- [HANDLE_REBOOT] = SPECIAL_REBOOT_TARGET,
- [HANDLE_HALT] = SPECIAL_HALT_TARGET,
- [HANDLE_KEXEC] = SPECIAL_KEXEC_TARGET,
- [HANDLE_SUSPEND] = SPECIAL_SUSPEND_TARGET,
- [HANDLE_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
- [HANDLE_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
- };
-
- DBusError error;
- int r;
- InhibitWhat inhibit_operation;
-
- assert(b);
-
- /* If the key handling is turned off, don't do anything */
- if (handle == HANDLE_IGNORE) {
- log_debug("Refusing key handling, as it is turned off.");
- return 0;
- }
-
- /* If the key handling is inhibited, don't do anything */
- if (manager_is_inhibited(b->manager, inhibit_key, INHIBIT_BLOCK, NULL, true, false, 0)) {
- log_debug("Refusing key handling, %s is inhibited.", inhibit_what_to_string(inhibit_key));
- return 0;
- }
-
- /* Locking is handled differently from the rest. */
- if (handle == HANDLE_LOCK) {
- log_info("Locking sessions...");
- session_send_lock_all(b->manager, true);
- return 1;
- }
-
- inhibit_operation = handle == HANDLE_SUSPEND || handle == HANDLE_HIBERNATE || handle == HANDLE_HYBRID_SLEEP ? INHIBIT_SLEEP : INHIBIT_SHUTDOWN;
-
- /* If the actual operation is inhibited, warn and fail */
- if (!ignore_inhibited &&
- manager_is_inhibited(b->manager, inhibit_operation, INHIBIT_BLOCK, NULL, false, false, 0)) {
-
-
- /* If this is just a recheck of the lid switch then don't warn about anything */
- if (!is_edge) {
- log_debug("Refusing operation, %s is inhibited.", inhibit_what_to_string(inhibit_operation));
- return 0;
- }
-
- log_error("Refusing operation, %s is inhibited.", inhibit_what_to_string(inhibit_operation));
- warn_melody();
- return -EPERM;
- }
-
- log_info("%s", message_table[handle]);
-
- /* We are executing the operation, so make sure we don't
- * execute another one until the lid is opened/closed again */
- b->lid_close_queued = false;
-
- dbus_error_init(&error);
- r = bus_manager_shutdown_or_sleep_now_or_later(b->manager, target_table[handle], inhibit_operation, &error);
- if (r < 0) {
- log_error("Failed to execute operation: %s", bus_error_message(&error));
- dbus_error_free(&error);
- return r;
- }
-
- return 1;
-}
-
-int button_process(Button *b) {
- struct input_event ev;
- ssize_t l;
-
- assert(b);
-
- l = read(b->fd, &ev, sizeof(ev));
- if (l < 0)
- return errno != EAGAIN ? -errno : 0;
- if ((size_t) l < sizeof(ev))
- return -EIO;
-
- if (ev.type == EV_KEY && ev.value > 0) {
-
- switch (ev.code) {
-
- case KEY_POWER:
- case KEY_POWER2:
- log_info("Power key pressed.");
- return button_handle(b, INHIBIT_HANDLE_POWER_KEY, b->manager->handle_power_key, b->manager->power_key_ignore_inhibited, true);
-
- /* The kernel is a bit confused here:
-
- KEY_SLEEP = suspend-to-ram, which everybody else calls "suspend"
- KEY_SUSPEND = suspend-to-disk, which everybody else calls "hibernate"
- */
-
- case KEY_SLEEP:
- log_info("Suspend key pressed.");
- return button_handle(b, INHIBIT_HANDLE_SUSPEND_KEY, b->manager->handle_suspend_key, b->manager->suspend_key_ignore_inhibited, true);
-
- case KEY_SUSPEND:
- log_info("Hibernate key pressed.");
- return button_handle(b, INHIBIT_HANDLE_HIBERNATE_KEY, b->manager->handle_hibernate_key, b->manager->hibernate_key_ignore_inhibited, true);
- }
-
- } else if (ev.type == EV_SW && ev.value > 0) {
-
- switch (ev.code) {
-
- case SW_LID:
- log_info("Lid closed.");
- b->lid_close_queued = true;
-
- return button_handle(b, INHIBIT_HANDLE_LID_SWITCH, b->manager->handle_lid_switch, b->manager->lid_switch_ignore_inhibited, true);
- }
-
- } else if (ev.type == EV_SW && ev.value == 0) {
-
- switch (ev.code) {
-
- case SW_LID:
- log_info("Lid opened.");
- b->lid_close_queued = false;
- break;
- }
- }
-
- return 0;
-}
-
-int button_recheck(Button *b) {
- assert(b);
-
- if (!b->lid_close_queued)
- return 0;
-
- return button_handle(b, INHIBIT_HANDLE_LID_SWITCH, b->manager->handle_lid_switch, b->manager->lid_switch_ignore_inhibited, false);
-}
-
-static const char* const handle_button_table[_HANDLE_BUTTON_MAX] = {
- [HANDLE_IGNORE] = "ignore",
- [HANDLE_POWEROFF] = "poweroff",
- [HANDLE_REBOOT] = "reboot",
- [HANDLE_HALT] = "halt",
- [HANDLE_KEXEC] = "kexec",
- [HANDLE_SUSPEND] = "suspend",
- [HANDLE_HIBERNATE] = "hibernate",
- [HANDLE_HYBRID_SLEEP] = "hybrid-sleep",
- [HANDLE_LOCK] = "lock"
-};
-DEFINE_STRING_TABLE_LOOKUP(handle_button, HandleButton);
-DEFINE_CONFIG_PARSE_ENUM(config_parse_handle_button, handle_button, HandleButton, "Failed to parse handle button setting");
diff --git a/src/login/logind-button.h b/src/login/logind-button.h
deleted file mode 100644
index b76ca32c08..0000000000
--- a/src/login/logind-button.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef foologindbuttonhfoo
-#define foologindbuttonhfoo
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-typedef struct Button Button;
-
-typedef enum HandleButton {
- HANDLE_IGNORE,
- HANDLE_POWEROFF,
- HANDLE_REBOOT,
- HANDLE_HALT,
- HANDLE_KEXEC,
- HANDLE_SUSPEND,
- HANDLE_HIBERNATE,
- HANDLE_HYBRID_SLEEP,
- HANDLE_LOCK,
- _HANDLE_BUTTON_MAX,
- _HANDLE_BUTTON_INVALID = -1
-} HandleButton;
-
-#include "list.h"
-#include "util.h"
-#include "logind.h"
-
-struct Button {
- Manager *manager;
-
- char *name;
- char *seat;
- int fd;
-
- bool lid_close_queued;
-};
-
-Button* button_new(Manager *m, const char *name);
-void button_free(Button*b);
-int button_open(Button *b);
-int button_process(Button *b);
-int button_recheck(Button *b);
-int button_set_seat(Button *b, const char *sn);
-
-const char* handle_button_to_string(HandleButton h);
-HandleButton handle_button_from_string(const char *s);
-
-int config_parse_handle_button(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-
-#endif
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
deleted file mode 100644
index 8b6021d35f..0000000000
--- a/src/login/logind-dbus.c
+++ /dev/null
@@ -1,2389 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <pwd.h>
-
-#include "logind.h"
-#include "dbus-common.h"
-#include "strv.h"
-#include "mkdir.h"
-#include "path-util.h"
-#include "polkit.h"
-#include "special.h"
-#include "systemd/sd-id128.h"
-#include "systemd/sd-messages.h"
-
-#define BUS_MANAGER_INTERFACE \
- " <interface name=\"org.freedesktop.login1.Manager\">\n" \
- " <method name=\"GetSession\">\n" \
- " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"session\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"GetSessionByPID\">\n" \
- " <arg name=\"pid\" type=\"u\" direction=\"in\"/>\n" \
- " <arg name=\"session\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"GetUser\">\n" \
- " <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \
- " <arg name=\"user\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"GetSeat\">\n" \
- " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"seat\" type=\"o\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"ListSessions\">\n" \
- " <arg name=\"sessions\" type=\"a(susso)\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"ListUsers\">\n" \
- " <arg name=\"users\" type=\"a(uso)\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"ListSeats\">\n" \
- " <arg name=\"seats\" type=\"a(so)\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"CreateSession\">\n" \
- " <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \
- " <arg name=\"leader\" type=\"u\" direction=\"in\"/>\n" \
- " <arg name=\"sevice\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"type\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"class\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"seat\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"vtnr\" type=\"u\" direction=\"in\"/>\n" \
- " <arg name=\"tty\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"display\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"remote\" type=\"b\" direction=\"in\"/>\n" \
- " <arg name=\"remote_user\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"remote_host\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"controllers\" type=\"as\" direction=\"in\"/>\n" \
- " <arg name=\"reset_controllers\" type=\"as\" direction=\"in\"/>\n" \
- " <arg name=\"kill_processes\" type=\"b\" direction=\"in\"/>\n" \
- " <arg name=\"id\" type=\"s\" direction=\"out\"/>\n" \
- " <arg name=\"path\" type=\"o\" direction=\"out\"/>\n" \
- " <arg name=\"runtime_path\" type=\"o\" direction=\"out\"/>\n" \
- " <arg name=\"fd\" type=\"h\" direction=\"out\"/>\n" \
- " <arg name=\"seat\" type=\"s\" direction=\"out\"/>\n" \
- " <arg name=\"vtnr\" type=\"u\" direction=\"out\"/>\n" \
- " <arg name=\"existing\" type=\"b\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"ReleaseSession\">\n" \
- " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"ActivateSession\">\n" \
- " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"ActivateSessionOnSeat\">\n" \
- " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"seat\" type=\"s\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"LockSession\">\n" \
- " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"UnlockSession\">\n" \
- " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"LockSessions\"/>\n" \
- " <method name=\"KillSession\">\n" \
- " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"who\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"signal\" type=\"s\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"KillUser\">\n" \
- " <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \
- " <arg name=\"signal\" type=\"s\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"TerminateSession\">\n" \
- " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"TerminateUser\">\n" \
- " <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"TerminateSeat\">\n" \
- " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"SetUserLinger\">\n" \
- " <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \
- " <arg name=\"b\" type=\"b\" direction=\"in\"/>\n" \
- " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"AttachDevice\">\n" \
- " <arg name=\"seat\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"sysfs\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"FlushDevices\">\n" \
- " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"PowerOff\">\n" \
- " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"Reboot\">\n" \
- " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"Suspend\">\n" \
- " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"Hibernate\">\n" \
- " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"HybridSleep\">\n" \
- " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"CanPowerOff\">\n" \
- " <arg name=\"result\" type=\"s\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"CanReboot\">\n" \
- " <arg name=\"result\" type=\"s\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"CanSuspend\">\n" \
- " <arg name=\"result\" type=\"s\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"CanHibernate\">\n" \
- " <arg name=\"result\" type=\"s\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"CanHybridSleep\">\n" \
- " <arg name=\"result\" type=\"s\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"Inhibit\">\n" \
- " <arg name=\"what\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"who\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"why\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"fd\" type=\"h\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"ListInhibitors\">\n" \
- " <arg name=\"inhibitors\" type=\"a(ssssuu)\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <signal name=\"SessionNew\">\n" \
- " <arg name=\"id\" type=\"s\"/>\n" \
- " <arg name=\"path\" type=\"o\"/>\n" \
- " </signal>\n" \
- " <signal name=\"SessionRemoved\">\n" \
- " <arg name=\"id\" type=\"s\"/>\n" \
- " <arg name=\"path\" type=\"o\"/>\n" \
- " </signal>\n" \
- " <signal name=\"UserNew\">\n" \
- " <arg name=\"uid\" type=\"u\"/>\n" \
- " <arg name=\"path\" type=\"o\"/>\n" \
- " </signal>\n" \
- " <signal name=\"UserRemoved\">\n" \
- " <arg name=\"uid\" type=\"u\"/>\n" \
- " <arg name=\"path\" type=\"o\"/>\n" \
- " </signal>\n" \
- " <signal name=\"SeatNew\">\n" \
- " <arg name=\"id\" type=\"s\"/>\n" \
- " <arg name=\"path\" type=\"o\"/>\n" \
- " </signal>\n" \
- " <signal name=\"SeatRemoved\">\n" \
- " <arg name=\"id\" type=\"s\"/>\n" \
- " <arg name=\"path\" type=\"o\"/>\n" \
- " </signal>\n" \
- " <signal name=\"PrepareForShutdown\">\n" \
- " <arg name=\"active\" type=\"b\"/>\n" \
- " </signal>\n" \
- " <signal name=\"PrepareForSleep\">\n" \
- " <arg name=\"active\" type=\"b\"/>\n" \
- " </signal>\n" \
- " <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Controllers\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"ResetControllers\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"NAutoVTs\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"KillOnlyUsers\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"KillExcludeUsers\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"KillUserProcesses\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"IdleHint\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"IdleSinceHint\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"IdleSinceHintMonotonic\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"BlockInhibited\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"DelayInhibited\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"InhibitDelayMaxUSec\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"HandlePowerKey\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"HandleSuspendKey\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"HandleHibernateKey\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"HandleLidSwitch\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"PreparingForShutdown\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"PreparingForSleep\" type=\"b\" access=\"read\"/>\n" \
- " </interface>\n"
-
-#define INTROSPECTION_BEGIN \
- DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
- "<node>\n" \
- BUS_MANAGER_INTERFACE \
- BUS_PROPERTIES_INTERFACE \
- BUS_PEER_INTERFACE \
- BUS_INTROSPECTABLE_INTERFACE
-
-#define INTROSPECTION_END \
- "</node>\n"
-
-#define INTERFACES_LIST \
- BUS_GENERIC_INTERFACES_LIST \
- "org.freedesktop.login1.Manager\0"
-
-static int bus_manager_append_idle_hint(DBusMessageIter *i, const char *property, void *data) {
- Manager *m = data;
- dbus_bool_t b;
-
- assert(i);
- assert(property);
- assert(m);
-
- b = manager_get_idle_hint(m, NULL) > 0;
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_manager_append_idle_hint_since(DBusMessageIter *i, const char *property, void *data) {
- Manager *m = data;
- dual_timestamp t;
- uint64_t u;
-
- assert(i);
- assert(property);
- assert(m);
-
- manager_get_idle_hint(m, &t);
- u = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_manager_append_inhibited(DBusMessageIter *i, const char *property, void *data) {
- Manager *m = data;
- InhibitWhat w;
- const char *p;
-
- w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
- p = inhibit_what_to_string(w);
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &p))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_manager_append_preparing(DBusMessageIter *i, const char *property, void *data) {
- Manager *m = data;
- dbus_bool_t b;
-
- assert(i);
- assert(property);
-
- if (streq(property, "PreparingForShutdown"))
- b = !!(m->delayed_what & INHIBIT_SHUTDOWN);
- else
- b = !!(m->delayed_what & INHIBIT_SLEEP);
-
- dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b);
- return 0;
-}
-
-static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMessage **_reply) {
- Session *session = NULL;
- User *user = NULL;
- const char *type, *class, *seat, *tty, *display, *remote_user, *remote_host, *service;
- uint32_t uid, leader, audit_id = 0;
- dbus_bool_t remote, kill_processes, exists;
- char **controllers = NULL, **reset_controllers = NULL;
- SessionType t;
- SessionClass c;
- Seat *s;
- DBusMessageIter iter;
- int r;
- char *id = NULL, *p;
- uint32_t vtnr = 0;
- int fifo_fd = -1;
- DBusMessage *reply = NULL;
- bool b;
-
- assert(m);
- assert(message);
- assert(_reply);
-
- if (!dbus_message_iter_init(message, &iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
- return -EINVAL;
-
- dbus_message_iter_get_basic(&iter, &uid);
-
- if (!dbus_message_iter_next(&iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
- return -EINVAL;
-
- dbus_message_iter_get_basic(&iter, &leader);
-
- if (leader <= 0 ||
- !dbus_message_iter_next(&iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
- return -EINVAL;
-
- dbus_message_iter_get_basic(&iter, &service);
-
- if (!dbus_message_iter_next(&iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
- return -EINVAL;
-
- dbus_message_iter_get_basic(&iter, &type);
- t = session_type_from_string(type);
-
- if (t < 0 ||
- !dbus_message_iter_next(&iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
- return -EINVAL;
-
- dbus_message_iter_get_basic(&iter, &class);
- if (isempty(class))
- c = SESSION_USER;
- else
- c = session_class_from_string(class);
-
- if (c < 0 ||
- !dbus_message_iter_next(&iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
- return -EINVAL;
-
- dbus_message_iter_get_basic(&iter, &seat);
-
- if (isempty(seat))
- s = NULL;
- else {
- s = hashmap_get(m->seats, seat);
- if (!s)
- return -ENOENT;
- }
-
- if (!dbus_message_iter_next(&iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
- return -EINVAL;
-
- dbus_message_iter_get_basic(&iter, &vtnr);
-
- if (!dbus_message_iter_next(&iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
- return -EINVAL;
-
- dbus_message_iter_get_basic(&iter, &tty);
-
- if (tty_is_vc(tty)) {
- int v;
-
- if (!s)
- s = m->vtconsole;
- else if (s != m->vtconsole)
- return -EINVAL;
-
- v = vtnr_from_tty(tty);
-
- if (v <= 0)
- return v < 0 ? v : -EINVAL;
-
- if (vtnr <= 0)
- vtnr = (uint32_t) v;
- else if (vtnr != (uint32_t) v)
- return -EINVAL;
- } else if (tty_is_console(tty)) {
-
- if (!s)
- s = m->vtconsole;
- else if (s != m->vtconsole)
- return -EINVAL;
-
- if (vtnr != 0)
- return -EINVAL;
-
- }
-
- if (s) {
- if (seat_can_multi_session(s)) {
- if (vtnr > 63)
- return -EINVAL;
- } else {
- if (vtnr != 0)
- return -EINVAL;
- }
- }
-
- if (!dbus_message_iter_next(&iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
- return -EINVAL;
-
- dbus_message_iter_get_basic(&iter, &display);
-
- if (!dbus_message_iter_next(&iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
- return -EINVAL;
-
- dbus_message_iter_get_basic(&iter, &remote);
-
- if (!dbus_message_iter_next(&iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
- return -EINVAL;
-
- dbus_message_iter_get_basic(&iter, &remote_user);
-
- if (!dbus_message_iter_next(&iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
- return -EINVAL;
-
- dbus_message_iter_get_basic(&iter, &remote_host);
-
- if (!dbus_message_iter_next(&iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRING)
- return -EINVAL;
-
- r = bus_parse_strv_iter(&iter, &controllers);
- if (r < 0)
- return -EINVAL;
-
- if (strv_contains(controllers, "systemd") ||
- !dbus_message_iter_next(&iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRING) {
- r = -EINVAL;
- goto fail;
- }
-
- r = bus_parse_strv_iter(&iter, &reset_controllers);
- if (r < 0)
- goto fail;
-
- if (strv_contains(reset_controllers, "systemd") ||
- !dbus_message_iter_next(&iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN) {
- r = -EINVAL;
- goto fail;
- }
-
- dbus_message_iter_get_basic(&iter, &kill_processes);
-
- r = manager_add_user_by_uid(m, uid, &user);
- if (r < 0)
- goto fail;
-
- audit_session_from_pid(leader, &audit_id);
-
- if (audit_id > 0) {
- asprintf(&id, "%lu", (unsigned long) audit_id);
-
- if (!id) {
- r = -ENOMEM;
- goto fail;
- }
-
- session = hashmap_get(m->sessions, id);
-
- if (session) {
- free(id);
-
- fifo_fd = session_create_fifo(session);
- if (fifo_fd < 0) {
- r = fifo_fd;
- goto fail;
- }
-
- /* Session already exists, client is probably
- * something like "su" which changes uid but
- * is still the same audit session */
-
- reply = dbus_message_new_method_return(message);
- if (!reply) {
- r = -ENOMEM;
- goto fail;
- }
-
- p = session_bus_path(session);
- if (!p) {
- r = -ENOMEM;
- goto fail;
- }
-
- seat = session->seat ? session->seat->id : "";
- vtnr = session->vtnr;
- exists = true;
-
- b = dbus_message_append_args(
- reply,
- DBUS_TYPE_STRING, &session->id,
- DBUS_TYPE_OBJECT_PATH, &p,
- DBUS_TYPE_STRING, &session->user->runtime_path,
- DBUS_TYPE_UNIX_FD, &fifo_fd,
- DBUS_TYPE_STRING, &seat,
- DBUS_TYPE_UINT32, &vtnr,
- DBUS_TYPE_BOOLEAN, &exists,
- DBUS_TYPE_INVALID);
- free(p);
-
- if (!b) {
- r = -ENOMEM;
- goto fail;
- }
-
- close_nointr_nofail(fifo_fd);
- *_reply = reply;
-
- strv_free(controllers);
- strv_free(reset_controllers);
-
- return 0;
- }
-
- } else {
- do {
- free(id);
- id = NULL;
-
- if (asprintf(&id, "c%lu", ++m->session_counter) < 0) {
- r = -ENOMEM;
- goto fail;
- }
-
- } while (hashmap_get(m->sessions, id));
- }
-
- r = manager_add_session(m, user, id, &session);
- free(id);
- if (r < 0)
- goto fail;
-
- session->leader = leader;
- session->audit_id = audit_id;
- session->type = t;
- session->class = c;
- session->remote = remote;
- session->controllers = controllers;
- session->reset_controllers = reset_controllers;
- session->kill_processes = kill_processes;
- session->vtnr = vtnr;
-
- controllers = reset_controllers = NULL;
-
- if (!isempty(tty)) {
- session->tty = strdup(tty);
- if (!session->tty) {
- r = -ENOMEM;
- goto fail;
- }
- }
-
- if (!isempty(display)) {
- session->display = strdup(display);
- if (!session->display) {
- r = -ENOMEM;
- goto fail;
- }
- }
-
- if (!isempty(remote_user)) {
- session->remote_user = strdup(remote_user);
- if (!session->remote_user) {
- r = -ENOMEM;
- goto fail;
- }
- }
-
- if (!isempty(remote_host)) {
- session->remote_host = strdup(remote_host);
- if (!session->remote_host) {
- r = -ENOMEM;
- goto fail;
- }
- }
-
- if (!isempty(service)) {
- session->service = strdup(service);
- if (!session->service) {
- r = -ENOMEM;
- goto fail;
- }
- }
-
- fifo_fd = session_create_fifo(session);
- if (fifo_fd < 0) {
- r = fifo_fd;
- goto fail;
- }
-
- if (s) {
- r = seat_attach_session(s, session);
- if (r < 0)
- goto fail;
- }
-
- r = session_start(session);
- if (r < 0)
- goto fail;
-
- reply = dbus_message_new_method_return(message);
- if (!reply) {
- r = -ENOMEM;
- goto fail;
- }
-
- p = session_bus_path(session);
- if (!p) {
- r = -ENOMEM;
- goto fail;
- }
-
- seat = s ? s->id : "";
- exists = false;
- b = dbus_message_append_args(
- reply,
- DBUS_TYPE_STRING, &session->id,
- DBUS_TYPE_OBJECT_PATH, &p,
- DBUS_TYPE_STRING, &session->user->runtime_path,
- DBUS_TYPE_UNIX_FD, &fifo_fd,
- DBUS_TYPE_STRING, &seat,
- DBUS_TYPE_UINT32, &vtnr,
- DBUS_TYPE_BOOLEAN, &exists,
- DBUS_TYPE_INVALID);
- free(p);
-
- if (!b) {
- r = -ENOMEM;
- goto fail;
- }
-
- close_nointr_nofail(fifo_fd);
- *_reply = reply;
-
- return 0;
-
-fail:
- strv_free(controllers);
- strv_free(reset_controllers);
-
- if (session)
- session_add_to_gc_queue(session);
-
- if (user)
- user_add_to_gc_queue(user);
-
- if (fifo_fd >= 0)
- close_nointr_nofail(fifo_fd);
-
- if (reply)
- dbus_message_unref(reply);
-
- return r;
-}
-
-static int bus_manager_inhibit(Manager *m, DBusConnection *connection, DBusMessage *message, DBusError *error, DBusMessage **_reply) {
- Inhibitor *i = NULL;
- char *id = NULL;
- const char *who, *why, *what, *mode;
- pid_t pid;
- InhibitWhat w;
- InhibitMode mm;
- unsigned long ul;
- int r, fifo_fd = -1;
- DBusMessage *reply = NULL;
-
- assert(m);
- assert(connection);
- assert(message);
- assert(error);
- assert(_reply);
-
- if (!dbus_message_get_args(
- message,
- error,
- DBUS_TYPE_STRING, &what,
- DBUS_TYPE_STRING, &who,
- DBUS_TYPE_STRING, &why,
- DBUS_TYPE_STRING, &mode,
- DBUS_TYPE_INVALID)) {
- r = -EIO;
- goto fail;
- }
-
- w = inhibit_what_from_string(what);
- if (w <= 0) {
- r = -EINVAL;
- goto fail;
- }
-
- mm = inhibit_mode_from_string(mode);
- if (mm < 0) {
- r = -EINVAL;
- goto fail;
- }
-
- /* Delay is only supported for shutdown/sleep */
- if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP))) {
- r = -EINVAL;
- goto fail;
- }
-
- r = verify_polkit(connection, message,
- w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
- w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
- w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
- w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
- w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
- w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
- "org.freedesktop.login1.inhibit-handle-lid-switch",
- false, NULL, error);
- if (r < 0)
- goto fail;
-
- ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), error);
- if (ul == (unsigned long) -1) {
- r = -EIO;
- goto fail;
- }
-
- pid = bus_get_unix_process_id(connection, dbus_message_get_sender(message), error);
- if (pid <= 0) {
- r = -EIO;
- goto fail;
- }
-
- do {
- free(id);
- id = NULL;
-
- if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0) {
- r = -ENOMEM;
- goto fail;
- }
- } while (hashmap_get(m->inhibitors, id));
-
- r = manager_add_inhibitor(m, id, &i);
- free(id);
-
- if (r < 0)
- goto fail;
-
- i->what = w;
- i->mode = mm;
- i->pid = pid;
- i->uid = (uid_t) ul;
- i->why = strdup(why);
- i->who = strdup(who);
-
- if (!i->why || !i->who) {
- r = -ENOMEM;
- goto fail;
- }
-
- fifo_fd = inhibitor_create_fifo(i);
- if (fifo_fd < 0) {
- r = fifo_fd;
- goto fail;
- }
-
- reply = dbus_message_new_method_return(message);
- if (!reply) {
- r = -ENOMEM;
- goto fail;
- }
-
- if (!dbus_message_append_args(
- reply,
- DBUS_TYPE_UNIX_FD, &fifo_fd,
- DBUS_TYPE_INVALID)) {
- r = -ENOMEM;
- goto fail;
- }
-
- close_nointr_nofail(fifo_fd);
- *_reply = reply;
-
- inhibitor_start(i);
-
- return 0;
-
-fail:
- if (i)
- inhibitor_free(i);
-
- if (fifo_fd >= 0)
- close_nointr_nofail(fifo_fd);
-
- if (reply)
- dbus_message_unref(reply);
-
- return r;
-}
-
-static int trigger_device(Manager *m, struct udev_device *d) {
- struct udev_enumerate *e;
- struct udev_list_entry *first, *item;
- int r;
-
- assert(m);
-
- e = udev_enumerate_new(m->udev);
- if (!e) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (d) {
- if (udev_enumerate_add_match_parent(e, d) < 0) {
- r = -EIO;
- goto finish;
- }
- }
-
- if (udev_enumerate_scan_devices(e) < 0) {
- r = -EIO;
- goto finish;
- }
-
- first = udev_enumerate_get_list_entry(e);
- udev_list_entry_foreach(item, first) {
- char *t;
- const char *p;
-
- p = udev_list_entry_get_name(item);
-
- t = strappend(p, "/uevent");
- if (!t) {
- r = -ENOMEM;
- goto finish;
- }
-
- write_one_line_file(t, "change");
- free(t);
- }
-
- r = 0;
-
-finish:
- if (e)
- udev_enumerate_unref(e);
-
- return r;
-}
-
-static int attach_device(Manager *m, const char *seat, const char *sysfs) {
- struct udev_device *d;
- char *rule = NULL, *file = NULL;
- const char *id_for_seat;
- int r;
-
- assert(m);
- assert(seat);
- assert(sysfs);
-
- d = udev_device_new_from_syspath(m->udev, sysfs);
- if (!d)
- return -ENODEV;
-
- if (!udev_device_has_tag(d, "seat")) {
- r = -ENODEV;
- goto finish;
- }
-
- id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
- if (!id_for_seat) {
- r = -ENODEV;
- goto finish;
- }
-
- if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0) {
- r = -ENOMEM;
- goto finish;
- }
-
- mkdir_p_label("/etc/udev/rules.d", 0755);
- r = write_one_line_file_atomic(file, rule);
- if (r < 0)
- goto finish;
-
- r = trigger_device(m, d);
-
-finish:
- free(rule);
- free(file);
-
- if (d)
- udev_device_unref(d);
-
- return r;
-}
-
-static int flush_devices(Manager *m) {
- DIR *d;
-
- assert(m);
-
- d = opendir("/etc/udev/rules.d");
- if (!d) {
- if (errno != ENOENT)
- log_warning("Failed to open /etc/udev/rules.d: %m");
- } else {
- struct dirent *de;
-
- while ((de = readdir(d))) {
-
- if (!dirent_is_file(de))
- continue;
-
- if (!startswith(de->d_name, "72-seat-"))
- continue;
-
- if (!endswith(de->d_name, ".rules"))
- continue;
-
- if (unlinkat(dirfd(d), de->d_name, 0) < 0)
- log_warning("Failed to unlink %s: %m", de->d_name);
- }
-
- closedir(d);
- }
-
- return trigger_device(m, NULL);
-}
-
-static int have_multiple_sessions(
- Manager *m,
- uid_t uid) {
-
- Session *session;
- Iterator i;
-
- assert(m);
-
- /* Check for other users' sessions. Greeter sessions do not count. */
- HASHMAP_FOREACH(session, m->sessions, i)
- if (session->class == SESSION_USER && session->user->uid != uid)
- return true;
-
- return false;
-}
-
-static int send_start_unit(DBusConnection *connection, const char *unit_name, DBusError *error) {
- const char *mode = "replace";
-
- assert(unit_name);
-
- return bus_method_call_with_reply (
- connection,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "StartUnit",
- NULL,
- NULL,
- DBUS_TYPE_STRING, &unit_name,
- DBUS_TYPE_STRING, &mode,
- DBUS_TYPE_INVALID);
-}
-
-static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
- static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
- [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
- [INHIBIT_SLEEP] = "PrepareForSleep"
- };
-
- dbus_bool_t active = _active;
- DBusMessage *message;
- int r = 0;
-
- assert(m);
- assert(w >= 0);
- assert(w < _INHIBIT_WHAT_MAX);
- assert(signal_name[w]);
-
- message = dbus_message_new_signal("/org/freedesktop/login1", "org.freedesktop.login1.Manager", signal_name[w]);
- if (!message)
- return -ENOMEM;
-
- if (!dbus_message_append_args(message, DBUS_TYPE_BOOLEAN, &active, DBUS_TYPE_INVALID) ||
- !dbus_connection_send(m->bus, message, NULL))
- r = -ENOMEM;
-
- dbus_message_unref(message);
- return r;
-}
-
-static int delay_shutdown_or_sleep(Manager *m, InhibitWhat w, const char *unit_name) {
- assert(m);
- assert(w >= 0);
- assert(w < _INHIBIT_WHAT_MAX);
-
- /* Tell everybody to prepare for shutdown/sleep */
- send_prepare_for(m, w, true);
-
- /* Update timestamp for timeout */
- if (!m->delayed_unit)
- m->delayed_timestamp = now(CLOCK_MONOTONIC);
-
- /* Remember what we want to do, possibly overriding what kind
- * of unit we previously queued. */
- m->delayed_unit = unit_name;
- m->delayed_what = w;
-
- return 0;
-}
-
-static int bus_manager_can_shutdown_or_sleep(
- Manager *m,
- DBusConnection *connection,
- DBusMessage *message,
- InhibitWhat w,
- const char *action,
- const char *action_multiple_sessions,
- const char *action_ignore_inhibit,
- const char *sleep_type,
- const char *sleep_disk_type,
- DBusError *error,
- DBusMessage **_reply) {
-
- bool multiple_sessions, challenge, blocked, b;
- const char *result;
- DBusMessage *reply = NULL;
- int r;
- unsigned long ul;
-
- assert(m);
- assert(connection);
- assert(message);
- assert(w >= 0);
- assert(w <= _INHIBIT_WHAT_MAX);
- assert(action);
- assert(action_multiple_sessions);
- assert(action_ignore_inhibit);
- assert(error);
- assert(_reply);
-
- if (sleep_type) {
- r = can_sleep(sleep_type);
- if (r < 0)
- return r;
-
- if (r == 0) {
- result = "na";
- goto finish;
- }
- }
-
- if (sleep_disk_type) {
- r = can_sleep_disk(sleep_disk_type);
- if (r < 0)
- return r;
-
- if (r == 0) {
- result = "na";
- goto finish;
- }
- }
-
- ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), error);
- if (ul == (unsigned long) -1)
- return -EIO;
-
- r = have_multiple_sessions(m, (uid_t) ul);
- if (r < 0)
- return r;
-
- multiple_sessions = r > 0;
- blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, (uid_t) ul);
-
- if (multiple_sessions) {
- r = verify_polkit(connection, message, action_multiple_sessions, false, &challenge, error);
- if (r < 0)
- return r;
-
- if (r > 0)
- result = "yes";
- else if (challenge)
- result = "challenge";
- else
- result = "no";
- }
-
- if (blocked) {
- r = verify_polkit(connection, message, action_ignore_inhibit, false, &challenge, error);
- if (r < 0)
- return r;
-
- if (r > 0 && !result)
- result = "yes";
- else if (challenge && (!result || streq(result, "yes")))
- result = "challenge";
- else
- result = "no";
- }
-
- if (!multiple_sessions && !blocked) {
- /* If neither inhibit nor multiple sessions
- * apply then just check the normal policy */
-
- r = verify_polkit(connection, message, action, false, &challenge, error);
- if (r < 0)
- return r;
-
- if (r > 0)
- result = "yes";
- else if (challenge)
- result = "challenge";
- else
- result = "no";
- }
-
-finish:
- reply = dbus_message_new_method_return(message);
- if (!reply)
- return -ENOMEM;
-
- b = dbus_message_append_args(
- reply,
- DBUS_TYPE_STRING, &result,
- DBUS_TYPE_INVALID);
- if (!b) {
- dbus_message_unref(reply);
- return -ENOMEM;
- }
-
- *_reply = reply;
- return 0;
-}
-
-static int bus_manager_log_shutdown(
- Manager *m,
- InhibitWhat w,
- const char *unit_name) {
-
- const char *p, *q;
-
- assert(m);
- assert(unit_name);
-
- if (w != INHIBIT_SHUTDOWN)
- return 0;
-
- if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
- p = "MESSAGE=System is powering down.";
- q = "SHUTDOWN=power-off";
- } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
- p = "MESSAGE=System is halting.";
- q = "SHUTDOWN=halt";
- } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
- p = "MESSAGE=System is rebooting.";
- q = "SHUTDOWN=reboot";
- } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
- p = "MESSAGE=System is rebooting with kexec.";
- q = "SHUTDOWN=kexec";
- } else {
- p = "MESSAGE=System is shutting down.";
- q = NULL;
- }
-
- return log_struct(LOG_NOTICE, MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
- p,
- q, NULL);
-}
-
-int bus_manager_shutdown_or_sleep_now_or_later(
- Manager *m,
- const char *unit_name,
- InhibitWhat w,
- DBusError *error) {
-
- bool delayed;
- int r;
-
- assert(m);
- assert(unit_name);
- assert(w >= 0);
- assert(w <= _INHIBIT_WHAT_MAX);
-
- delayed =
- m->inhibit_delay_max > 0 &&
- manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0);
-
- if (delayed)
- /* Shutdown is delayed, keep in mind what we
- * want to do, and start a timeout */
- r = delay_shutdown_or_sleep(m, w, unit_name);
- else {
- bus_manager_log_shutdown(m, w, unit_name);
-
- /* Shutdown is not delayed, execute it
- * immediately */
- r = send_start_unit(m->bus, unit_name, error);
- }
-
- return r;
-}
-
-static int bus_manager_do_shutdown_or_sleep(
- Manager *m,
- DBusConnection *connection,
- DBusMessage *message,
- const char *unit_name,
- InhibitWhat w,
- const char *action,
- const char *action_multiple_sessions,
- const char *action_ignore_inhibit,
- const char *sleep_type,
- const char *sleep_disk_type,
- DBusError *error,
- DBusMessage **_reply) {
-
- dbus_bool_t interactive;
- bool multiple_sessions, blocked;
- DBusMessage *reply = NULL;
- int r;
- unsigned long ul;
-
- assert(m);
- assert(connection);
- assert(message);
- assert(unit_name);
- assert(w >= 0);
- assert(w <= _INHIBIT_WHAT_MAX);
- assert(action);
- assert(action_multiple_sessions);
- assert(action_ignore_inhibit);
- assert(error);
- assert(_reply);
-
- if (!dbus_message_get_args(
- message,
- error,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID))
- return -EINVAL;
-
- if (sleep_type) {
- r = can_sleep(sleep_type);
- if (r < 0)
- return r;
-
- if (r == 0)
- return -ENOTSUP;
- }
-
- if (sleep_disk_type) {
- r = can_sleep_disk(sleep_disk_type);
- if (r < 0)
- return r;
-
- if (r == 0)
- return -ENOTSUP;
- }
-
- ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), error);
- if (ul == (unsigned long) -1)
- return -EIO;
-
- r = have_multiple_sessions(m, (uid_t) ul);
- if (r < 0)
- return r;
-
- multiple_sessions = r > 0;
- blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, (uid_t) ul);
-
- if (multiple_sessions) {
- r = verify_polkit(connection, message, action_multiple_sessions, interactive, NULL, error);
- if (r < 0)
- return r;
- }
-
- if (blocked) {
- r = verify_polkit(connection, message, action_ignore_inhibit, interactive, NULL, error);
- if (r < 0)
- return r;
- }
-
- if (!multiple_sessions && !blocked) {
- r = verify_polkit(connection, message, action, interactive, NULL, error);
- if (r < 0)
- return r;
- }
-
- r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
- if (r < 0)
- return r;
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- return -ENOMEM;
-
- *_reply = reply;
- return 0;
-}
-
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_handle_button, handle_button, HandleButton);
-
-static const BusProperty bus_login_manager_properties[] = {
- { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_path), true },
- { "Controllers", bus_property_append_strv, "as", offsetof(Manager, controllers), true },
- { "ResetControllers", bus_property_append_strv, "as", offsetof(Manager, reset_controllers), true },
- { "NAutoVTs", bus_property_append_unsigned, "u", offsetof(Manager, n_autovts) },
- { "KillOnlyUsers", bus_property_append_strv, "as", offsetof(Manager, kill_only_users), true },
- { "KillExcludeUsers", bus_property_append_strv, "as", offsetof(Manager, kill_exclude_users), true },
- { "KillUserProcesses", bus_property_append_bool, "b", offsetof(Manager, kill_user_processes) },
- { "IdleHint", bus_manager_append_idle_hint, "b", 0 },
- { "IdleSinceHint", bus_manager_append_idle_hint_since, "t", 0 },
- { "IdleSinceHintMonotonic", bus_manager_append_idle_hint_since, "t", 0 },
- { "BlockInhibited", bus_manager_append_inhibited, "s", 0 },
- { "DelayInhibited", bus_manager_append_inhibited, "s", 0 },
- { "InhibitDelayMaxUSec", bus_property_append_usec, "t", offsetof(Manager, inhibit_delay_max) },
- { "HandlePowerKey", bus_manager_append_handle_button, "s", offsetof(Manager, handle_power_key) },
- { "HandleSuspendKey", bus_manager_append_handle_button, "s", offsetof(Manager, handle_suspend_key) },
- { "HandleHibernateKey", bus_manager_append_handle_button, "s", offsetof(Manager, handle_hibernate_key)},
- { "HandleLidSwitch", bus_manager_append_handle_button, "s", offsetof(Manager, handle_lid_switch) },
- { "PreparingForShutdown", bus_manager_append_preparing, "b", 0 },
- { "PreparingForSleep", bus_manager_append_preparing, "b", 0 },
- { NULL, }
-};
-
-static DBusHandlerResult manager_message_handler(
- DBusConnection *connection,
- DBusMessage *message,
- void *userdata) {
-
- Manager *m = userdata;
-
- DBusError error;
- DBusMessage *reply = NULL;
- int r;
-
- assert(connection);
- assert(message);
- assert(m);
-
- dbus_error_init(&error);
-
- if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "GetSession")) {
- const char *name;
- char *p;
- Session *session;
- bool b;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- session = hashmap_get(m->sessions, name);
- if (!session)
- return bus_send_error_reply(connection, message, &error, -ENOENT);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- p = session_bus_path(session);
- if (!p)
- goto oom;
-
- b = dbus_message_append_args(
- reply,
- DBUS_TYPE_OBJECT_PATH, &p,
- DBUS_TYPE_INVALID);
- free(p);
-
- if (!b)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "GetSessionByPID")) {
- uint32_t pid;
- char *p;
- Session *session;
- bool b;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_UINT32, &pid,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- r = manager_get_session_by_pid(m, pid, &session);
- if (r <= 0)
- return bus_send_error_reply(connection, message, NULL, r < 0 ? r : -ENOENT);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- p = session_bus_path(session);
- if (!p)
- goto oom;
-
- b = dbus_message_append_args(
- reply,
- DBUS_TYPE_OBJECT_PATH, &p,
- DBUS_TYPE_INVALID);
- free(p);
-
- if (!b)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "GetUser")) {
- uint32_t uid;
- char *p;
- User *user;
- bool b;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_UINT32, &uid,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
- if (!user)
- return bus_send_error_reply(connection, message, &error, -ENOENT);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- p = user_bus_path(user);
- if (!p)
- goto oom;
-
- b = dbus_message_append_args(
- reply,
- DBUS_TYPE_OBJECT_PATH, &p,
- DBUS_TYPE_INVALID);
- free(p);
-
- if (!b)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "GetSeat")) {
- const char *name;
- char *p;
- Seat *seat;
- bool b;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- seat = hashmap_get(m->seats, name);
- if (!seat)
- return bus_send_error_reply(connection, message, &error, -ENOENT);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- p = seat_bus_path(seat);
- if (!p)
- goto oom;
-
- b = dbus_message_append_args(
- reply,
- DBUS_TYPE_OBJECT_PATH, &p,
- DBUS_TYPE_INVALID);
- free(p);
-
- if (!b)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ListSessions")) {
- char *p;
- Session *session;
- Iterator i;
- DBusMessageIter iter, sub;
- const char *empty = "";
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- dbus_message_iter_init_append(reply, &iter);
-
- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(susso)", &sub))
- goto oom;
-
- HASHMAP_FOREACH(session, m->sessions, i) {
- DBusMessageIter sub2;
- uint32_t uid;
-
- if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
- goto oom;
-
- uid = session->user->uid;
-
- p = session_bus_path(session);
- if (!p)
- goto oom;
-
- if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &session->id) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &uid) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &session->user->name) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, session->seat ? (const char**) &session->seat->id : &empty) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &p)) {
- free(p);
- goto oom;
- }
-
- free(p);
-
- if (!dbus_message_iter_close_container(&sub, &sub2))
- goto oom;
- }
-
- if (!dbus_message_iter_close_container(&iter, &sub))
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ListUsers")) {
- char *p;
- User *user;
- Iterator i;
- DBusMessageIter iter, sub;
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- dbus_message_iter_init_append(reply, &iter);
-
- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(uso)", &sub))
- goto oom;
-
- HASHMAP_FOREACH(user, m->users, i) {
- DBusMessageIter sub2;
- uint32_t uid;
-
- if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
- goto oom;
-
- uid = user->uid;
-
- p = user_bus_path(user);
- if (!p)
- goto oom;
-
- if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &uid) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &user->name) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &p)) {
- free(p);
- goto oom;
- }
-
- free(p);
-
- if (!dbus_message_iter_close_container(&sub, &sub2))
- goto oom;
- }
-
- if (!dbus_message_iter_close_container(&iter, &sub))
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ListSeats")) {
- char *p;
- Seat *seat;
- Iterator i;
- DBusMessageIter iter, sub;
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- dbus_message_iter_init_append(reply, &iter);
-
- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(so)", &sub))
- goto oom;
-
- HASHMAP_FOREACH(seat, m->seats, i) {
- DBusMessageIter sub2;
-
- if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
- goto oom;
-
- p = seat_bus_path(seat);
- if (!p)
- goto oom;
-
- if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &seat->id) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &p)) {
- free(p);
- goto oom;
- }
-
- free(p);
-
- if (!dbus_message_iter_close_container(&sub, &sub2))
- goto oom;
- }
-
- if (!dbus_message_iter_close_container(&iter, &sub))
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ListInhibitors")) {
- Inhibitor *inhibitor;
- Iterator i;
- DBusMessageIter iter, sub;
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- dbus_message_iter_init_append(reply, &iter);
-
- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssuu)", &sub))
- goto oom;
-
- HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
- DBusMessageIter sub2;
- dbus_uint32_t uid, pid;
- const char *what, *who, *why, *mode;
-
- if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
- goto oom;
-
- what = strempty(inhibit_what_to_string(inhibitor->what));
- who = strempty(inhibitor->who);
- why = strempty(inhibitor->why);
- mode = strempty(inhibit_mode_to_string(inhibitor->mode));
- uid = (dbus_uint32_t) inhibitor->uid;
- pid = (dbus_uint32_t) inhibitor->pid;
-
- if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &what) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &who) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &why) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &mode) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &uid) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &pid))
- goto oom;
-
- if (!dbus_message_iter_close_container(&sub, &sub2))
- goto oom;
- }
-
- if (!dbus_message_iter_close_container(&iter, &sub))
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "Inhibit")) {
-
- r = bus_manager_inhibit(m, connection, message, &error, &reply);
-
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CreateSession")) {
-
- r = bus_manager_create_session(m, message, &reply);
-
- /* Don't delay the work on OOM here, since it might be
- * triggered by a low RLIMIT_NOFILE here (since we
- * send a dupped fd to the client), and we'd rather
- * see this fail quickly then be retried later */
-
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ReleaseSession")) {
- const char *name;
- Session *session;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- session = hashmap_get(m->sessions, name);
- if (!session)
- return bus_send_error_reply(connection, message, &error, -ENOENT);
-
- /* We use the FIFO to detect stray sessions where the
- process invoking PAM dies abnormally. We need to make
- sure that that process is not killed if at the clean
- end of the session it closes the FIFO. Hence, with
- this call explicitly turn off the FIFO logic, so that
- the PAM code can finish clean up on its own */
- session_remove_fifo(session);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ActivateSession")) {
- const char *name;
- Session *session;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- session = hashmap_get(m->sessions, name);
- if (!session)
- return bus_send_error_reply(connection, message, &error, -ENOENT);
-
- r = session_activate(session);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ActivateSessionOnSeat")) {
- const char *session_name, *seat_name;
- Session *session;
- Seat *seat;
-
- /* Same as ActivateSession() but refuses to work if
- * the seat doesn't match */
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &session_name,
- DBUS_TYPE_STRING, &seat_name,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- session = hashmap_get(m->sessions, session_name);
- if (!session)
- return bus_send_error_reply(connection, message, &error, -ENOENT);
-
- seat = hashmap_get(m->seats, seat_name);
- if (!seat)
- return bus_send_error_reply(connection, message, &error, -ENOENT);
-
- if (session->seat != seat)
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- r = session_activate(session);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "LockSession") ||
- dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "UnlockSession")) {
- const char *name;
- Session *session;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- session = hashmap_get(m->sessions, name);
- if (!session)
- return bus_send_error_reply(connection, message, NULL, -ENOENT);
-
- if (session_send_lock(session, streq(dbus_message_get_member(message), "LockSession")) < 0)
- goto oom;
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "LockSessions")) {
- r = session_send_lock_all(m, true);
- if (r < 0)
- bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "KillSession")) {
- const char *swho;
- int32_t signo;
- KillWho who;
- const char *name;
- Session *session;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_STRING, &swho,
- DBUS_TYPE_INT32, &signo,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- if (isempty(swho))
- who = KILL_ALL;
- else {
- who = kill_who_from_string(swho);
- if (who < 0)
- return bus_send_error_reply(connection, message, &error, -EINVAL);
- }
-
- if (signo <= 0 || signo >= _NSIG)
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- session = hashmap_get(m->sessions, name);
- if (!session)
- return bus_send_error_reply(connection, message, &error, -ENOENT);
-
- r = session_kill(session, who, signo);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "KillUser")) {
- uint32_t uid;
- User *user;
- int32_t signo;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_UINT32, &uid,
- DBUS_TYPE_INT32, &signo,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- if (signo <= 0 || signo >= _NSIG)
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
- if (!user)
- return bus_send_error_reply(connection, message, &error, -ENOENT);
-
- r = user_kill(user, signo);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "TerminateSession")) {
- const char *name;
- Session *session;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- session = hashmap_get(m->sessions, name);
- if (!session)
- return bus_send_error_reply(connection, message, &error, -ENOENT);
-
- r = session_stop(session);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "TerminateUser")) {
- uint32_t uid;
- User *user;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_UINT32, &uid,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
- if (!user)
- return bus_send_error_reply(connection, message, &error, -ENOENT);
-
- r = user_stop(user);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "TerminateSeat")) {
- const char *name;
- Seat *seat;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- seat = hashmap_get(m->seats, name);
- if (!seat)
- return bus_send_error_reply(connection, message, &error, -ENOENT);
-
- r = seat_stop_sessions(seat);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "SetUserLinger")) {
- uint32_t uid;
- struct passwd *pw;
- dbus_bool_t b, interactive;
- char *path;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_UINT32, &uid,
- DBUS_TYPE_BOOLEAN, &b,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- errno = 0;
- pw = getpwuid(uid);
- if (!pw)
- return bus_send_error_reply(connection, message, NULL, errno ? -errno : -EINVAL);
-
- r = verify_polkit(connection, message, "org.freedesktop.login1.set-user-linger", interactive, NULL, &error);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- mkdir_p_label("/var/lib/systemd", 0755);
-
- r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- path = strappend("/var/lib/systemd/linger/", pw->pw_name);
- if (!path)
- goto oom;
-
- if (b) {
- User *u;
-
- r = touch(path);
- free(path);
-
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- if (manager_add_user_by_uid(m, uid, &u) >= 0)
- user_start(u);
-
- } else {
- User *u;
-
- r = unlink(path);
- free(path);
-
- if (r < 0 && errno != ENOENT)
- return bus_send_error_reply(connection, message, &error, -errno);
-
- u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
- if (u)
- user_add_to_gc_queue(u);
- }
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "AttachDevice")) {
- const char *sysfs, *seat;
- dbus_bool_t interactive;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &seat,
- DBUS_TYPE_STRING, &sysfs,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- if (!path_startswith(sysfs, "/sys") || !seat_name_is_valid(seat))
- return bus_send_error_reply(connection, message, NULL, -EINVAL);
-
- r = verify_polkit(connection, message, "org.freedesktop.login1.attach-device", interactive, NULL, &error);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- r = attach_device(m, seat, sysfs);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, -EINVAL);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "FlushDevices")) {
- dbus_bool_t interactive;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- r = verify_polkit(connection, message, "org.freedesktop.login1.flush-devices", interactive, NULL, &error);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- r = flush_devices(m);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, -EINVAL);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "PowerOff")) {
-
- r = bus_manager_do_shutdown_or_sleep(
- m, connection, message,
- SPECIAL_POWEROFF_TARGET,
- INHIBIT_SHUTDOWN,
- "org.freedesktop.login1.power-off",
- "org.freedesktop.login1.power-off-multiple-sessions",
- "org.freedesktop.login1.power-off-ignore-inhibit",
- NULL, NULL,
- &error, &reply);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "Reboot")) {
- r = bus_manager_do_shutdown_or_sleep(
- m, connection, message,
- SPECIAL_REBOOT_TARGET,
- INHIBIT_SHUTDOWN,
- "org.freedesktop.login1.reboot",
- "org.freedesktop.login1.reboot-multiple-sessions",
- "org.freedesktop.login1.reboot-ignore-inhibit",
- NULL, NULL,
- &error, &reply);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "Suspend")) {
- r = bus_manager_do_shutdown_or_sleep(
- m, connection, message,
- SPECIAL_SUSPEND_TARGET,
- INHIBIT_SLEEP,
- "org.freedesktop.login1.suspend",
- "org.freedesktop.login1.suspend-multiple-sessions",
- "org.freedesktop.login1.suspend-ignore-inhibit",
- "mem", NULL,
- &error, &reply);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "Hibernate")) {
- r = bus_manager_do_shutdown_or_sleep(
- m, connection, message,
- SPECIAL_HIBERNATE_TARGET,
- INHIBIT_SLEEP,
- "org.freedesktop.login1.hibernate",
- "org.freedesktop.login1.hibernate-multiple-sessions",
- "org.freedesktop.login1.hibernate-ignore-inhibit",
- "disk", NULL,
- &error, &reply);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "HybridSleep")) {
- r = bus_manager_do_shutdown_or_sleep(
- m, connection, message,
- SPECIAL_HYBRID_SLEEP_TARGET,
- INHIBIT_SLEEP,
- "org.freedesktop.login1.hibernate",
- "org.freedesktop.login1.hibernate-multiple-sessions",
- "org.freedesktop.login1.hibernate-ignore-inhibit",
- "disk", "suspend",
- &error, &reply);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanPowerOff")) {
-
- r = bus_manager_can_shutdown_or_sleep(
- m, connection, message,
- INHIBIT_SHUTDOWN,
- "org.freedesktop.login1.power-off",
- "org.freedesktop.login1.power-off-multiple-sessions",
- "org.freedesktop.login1.power-off-ignore-inhibit",
- NULL, NULL,
- &error, &reply);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanReboot")) {
- r = bus_manager_can_shutdown_or_sleep(
- m, connection, message,
- INHIBIT_SHUTDOWN,
- "org.freedesktop.login1.reboot",
- "org.freedesktop.login1.reboot-multiple-sessions",
- "org.freedesktop.login1.reboot-ignore-inhibit",
- NULL, NULL,
- &error, &reply);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanSuspend")) {
- r = bus_manager_can_shutdown_or_sleep(
- m, connection, message,
- INHIBIT_SLEEP,
- "org.freedesktop.login1.suspend",
- "org.freedesktop.login1.suspend-multiple-sessions",
- "org.freedesktop.login1.suspend-ignore-inhibit",
- "mem", NULL,
- &error, &reply);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanHibernate")) {
- r = bus_manager_can_shutdown_or_sleep(
- m, connection, message,
- INHIBIT_SLEEP,
- "org.freedesktop.login1.hibernate",
- "org.freedesktop.login1.hibernate-multiple-sessions",
- "org.freedesktop.login1.hibernate-ignore-inhibit",
- "disk", NULL,
- &error, &reply);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanHybridSleep")) {
- r = bus_manager_can_shutdown_or_sleep(
- m, connection, message,
- INHIBIT_SLEEP,
- "org.freedesktop.login1.hibernate",
- "org.freedesktop.login1.hibernate-multiple-sessions",
- "org.freedesktop.login1.hibernate-ignore-inhibit",
- "disk", "suspend",
- &error, &reply);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
- char *introspection = NULL;
- FILE *f;
- Iterator i;
- Session *session;
- Seat *seat;
- User *user;
- size_t size;
- char *p;
-
- if (!(reply = dbus_message_new_method_return(message)))
- goto oom;
-
- /* We roll our own introspection code here, instead of
- * relying on bus_default_message_handler() because we
- * need to generate our introspection string
- * dynamically. */
-
- if (!(f = open_memstream(&introspection, &size)))
- goto oom;
-
- fputs(INTROSPECTION_BEGIN, f);
-
- HASHMAP_FOREACH(seat, m->seats, i) {
- p = bus_path_escape(seat->id);
-
- if (p) {
- fprintf(f, "<node name=\"seat/%s\"/>", p);
- free(p);
- }
- }
-
- HASHMAP_FOREACH(user, m->users, i)
- fprintf(f, "<node name=\"user/%llu\"/>", (unsigned long long) user->uid);
-
- HASHMAP_FOREACH(session, m->sessions, i) {
- p = bus_path_escape(session->id);
-
- if (p) {
- fprintf(f, "<node name=\"session/%s\"/>", p);
- free(p);
- }
- }
-
- fputs(INTROSPECTION_END, f);
-
- if (ferror(f)) {
- fclose(f);
- free(introspection);
- goto oom;
- }
-
- fclose(f);
-
- if (!introspection)
- goto oom;
-
- if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
- free(introspection);
- goto oom;
- }
-
- free(introspection);
- } else {
- const BusBoundProperties bps[] = {
- { "org.freedesktop.login1.Manager", bus_login_manager_properties, m },
- { NULL, }
- };
- return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
- }
-
- if (reply) {
- if (!dbus_connection_send(connection, reply, NULL))
- goto oom;
-
- dbus_message_unref(reply);
- }
-
- return DBUS_HANDLER_RESULT_HANDLED;
-
-oom:
- if (reply)
- dbus_message_unref(reply);
-
- dbus_error_free(&error);
-
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-}
-
-const DBusObjectPathVTable bus_manager_vtable = {
- .message_function = manager_message_handler
-};
-
-DBusHandlerResult bus_message_filter(
- DBusConnection *connection,
- DBusMessage *message,
- void *userdata) {
-
- Manager *m = userdata;
- DBusError error;
-
- assert(m);
- assert(connection);
- assert(message);
-
- dbus_error_init(&error);
-
- if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
- const char *cgroup;
-
- if (!dbus_message_get_args(message, &error,
- DBUS_TYPE_STRING, &cgroup,
- DBUS_TYPE_INVALID))
- log_error("Failed to parse Released message: %s", bus_error_message(&error));
- else
- manager_cgroup_notify_empty(m, cgroup);
- }
-
- dbus_error_free(&error);
-
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-int manager_send_changed(Manager *manager, const char *properties) {
- DBusMessage *m;
- int r = -ENOMEM;
-
- assert(manager);
-
- m = bus_properties_changed_new("/org/freedesktop/login1", "org.freedesktop.login1.Manager", properties);
- if (!m)
- goto finish;
-
- if (!dbus_connection_send(manager->bus, m, NULL))
- goto finish;
-
- r = 0;
-
-finish:
- if (m)
- dbus_message_unref(m);
-
- return r;
-}
-
-int manager_dispatch_delayed(Manager *manager) {
- const char *unit_name;
- DBusError error;
- bool delayed;
- int r;
-
- assert(manager);
-
- if (!manager->delayed_unit)
- return 0;
-
- /* Continue delay? */
- delayed =
- manager->delayed_timestamp + manager->inhibit_delay_max > now(CLOCK_MONOTONIC) &&
- manager_is_inhibited(manager, manager->delayed_what, INHIBIT_DELAY, NULL, false, false, 0);
- if (delayed)
- return 0;
-
- bus_manager_log_shutdown(manager, manager->delayed_what, manager->delayed_unit);
-
- /* Reset delay data */
- unit_name = manager->delayed_unit;
- manager->delayed_unit = NULL;
-
- /* Actually do the shutdown */
- dbus_error_init(&error);
- r = send_start_unit(manager->bus, unit_name, &error);
- if (r < 0) {
- log_warning("Failed to send delayed message: %s", bus_error_message_or_strerror(&error, -r));
- dbus_error_free(&error);
- return r;
- }
-
- /* Tell people about it */
- send_prepare_for(manager, manager->delayed_what, false);
-
- return 1;
-}
diff --git a/src/login/logind-device.c b/src/login/logind-device.c
deleted file mode 100644
index 51b15358ba..0000000000
--- a/src/login/logind-device.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <assert.h>
-#include <string.h>
-
-#include "logind-device.h"
-#include "util.h"
-
-Device* device_new(Manager *m, const char *sysfs) {
- Device *d;
-
- assert(m);
- assert(sysfs);
-
- d = new0(Device, 1);
- if (!d)
- return NULL;
-
- d->sysfs = strdup(sysfs);
- if (!d->sysfs) {
- free(d);
- return NULL;
- }
-
- if (hashmap_put(m->devices, d->sysfs, d) < 0) {
- free(d->sysfs);
- free(d);
- return NULL;
- }
-
- d->manager = m;
- dual_timestamp_get(&d->timestamp);
-
- return d;
-}
-
-void device_free(Device *d) {
- assert(d);
-
- device_detach(d);
-
- hashmap_remove(d->manager->devices, d->sysfs);
-
- free(d->sysfs);
- free(d);
-}
-
-void device_detach(Device *d) {
- Seat *s;
- assert(d);
-
- if (!d->seat)
- return;
-
- s = d->seat;
- LIST_REMOVE(Device, devices, d->seat->devices, d);
- d->seat = NULL;
-
- seat_add_to_gc_queue(s);
- seat_send_changed(s, "CanGraphical\0");
-}
-
-void device_attach(Device *d, Seat *s) {
- assert(d);
- assert(s);
-
- if (d->seat == s)
- return;
-
- if (d->seat)
- device_detach(d);
-
- d->seat = s;
- LIST_PREPEND(Device, devices, s->devices, d);
-
- seat_send_changed(s, "CanGraphical\0");
-}
diff --git a/src/login/logind-device.h b/src/login/logind-device.h
deleted file mode 100644
index 3b153568cb..0000000000
--- a/src/login/logind-device.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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/>.
-***/
-
-typedef struct Device Device;
-
-#include "list.h"
-#include "util.h"
-#include "logind.h"
-#include "logind-seat.h"
-
-struct Device {
- Manager *manager;
-
- char *sysfs;
- Seat *seat;
-
- dual_timestamp timestamp;
-
- LIST_FIELDS(struct Device, devices);
-};
-
-Device* device_new(Manager *m, const char *sysfs);
-void device_free(Device *d);
-void device_attach(Device *d, Seat *s);
-void device_detach(Device *d);
diff --git a/src/login/logind-gperf.gperf b/src/login/logind-gperf.gperf
deleted file mode 100644
index 1bd1b285d8..0000000000
--- a/src/login/logind-gperf.gperf
+++ /dev/null
@@ -1,32 +0,0 @@
-%{
-#include <stddef.h>
-#include "conf-parser.h"
-#include "logind.h"
-%}
-struct ConfigPerfItem;
-%null_strings
-%language=ANSI-C
-%define slot-name section_and_lvalue
-%define hash-function-name logind_gperf_hash
-%define lookup-function-name logind_gperf_lookup
-%readonly-tables
-%omit-struct-type
-%struct-type
-%includes
-%%
-Login.NAutoVTs, config_parse_unsigned, 0, offsetof(Manager, n_autovts)
-Login.ReserveVT, config_parse_unsigned, 0, offsetof(Manager, reserve_vt)
-Login.KillUserProcesses, config_parse_bool, 0, offsetof(Manager, kill_user_processes)
-Login.KillOnlyUsers, config_parse_strv, 0, offsetof(Manager, kill_only_users)
-Login.KillExcludeUsers, config_parse_strv, 0, offsetof(Manager, kill_exclude_users)
-Login.Controllers, config_parse_strv, 0, offsetof(Manager, controllers)
-Login.ResetControllers, config_parse_strv, 0, offsetof(Manager, reset_controllers)
-Login.InhibitDelayMaxSec, config_parse_usec, 0, offsetof(Manager, inhibit_delay_max)
-Login.HandlePowerKey, config_parse_handle_button, 0, offsetof(Manager, handle_power_key)
-Login.HandleSuspendKey, config_parse_handle_button, 0, offsetof(Manager, handle_suspend_key)
-Login.HandleHibernateKey, config_parse_handle_button, 0, offsetof(Manager, handle_hibernate_key)
-Login.HandleLidSwitch, config_parse_handle_button, 0, offsetof(Manager, handle_lid_switch)
-Login.PowerKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, power_key_ignore_inhibited)
-Login.SuspendKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, suspend_key_ignore_inhibited)
-Login.HibernateKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, hibernate_key_ignore_inhibited)
-Login.LidSwitchIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, lid_switch_ignore_inhibited)
diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c
deleted file mode 100644
index f1b9cca834..0000000000
--- a/src/login/logind-inhibit.c
+++ /dev/null
@@ -1,468 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/epoll.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include "util.h"
-#include "mkdir.h"
-#include "path-util.h"
-#include "logind-inhibit.h"
-
-Inhibitor* inhibitor_new(Manager *m, const char* id) {
- Inhibitor *i;
-
- assert(m);
-
- i = new0(Inhibitor, 1);
- if (!i)
- return NULL;
-
- i->state_file = strappend("/run/systemd/inhibit/", id);
- if (!i->state_file) {
- free(i);
- return NULL;
- }
-
- i->id = path_get_file_name(i->state_file);
-
- if (hashmap_put(m->inhibitors, i->id, i) < 0) {
- free(i->state_file);
- free(i);
- return NULL;
- }
-
- i->manager = m;
- i->fifo_fd = -1;
-
- return i;
-}
-
-void inhibitor_free(Inhibitor *i) {
- assert(i);
-
- free(i->who);
- free(i->why);
-
- hashmap_remove(i->manager->inhibitors, i->id);
- inhibitor_remove_fifo(i);
-
- if (i->state_file) {
- unlink(i->state_file);
- free(i->state_file);
- }
-
- free(i);
-}
-
-int inhibitor_save(Inhibitor *i) {
- char *temp_path, *cc;
- int r;
- FILE *f;
-
- assert(i);
-
- r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0);
- if (r < 0)
- goto finish;
-
- r = fopen_temporary(i->state_file, &f, &temp_path);
- if (r < 0)
- goto finish;
-
- fchmod(fileno(f), 0644);
-
- fprintf(f,
- "# This is private data. Do not parse.\n"
- "WHAT=%s\n"
- "MODE=%s\n"
- "UID=%lu\n"
- "PID=%lu\n",
- inhibit_what_to_string(i->what),
- inhibit_mode_to_string(i->mode),
- (unsigned long) i->uid,
- (unsigned long) i->pid);
-
- if (i->who) {
- cc = cescape(i->who);
- if (!cc)
- r = -ENOMEM;
- else {
- fprintf(f, "WHO=%s\n", cc);
- free(cc);
- }
- }
-
- if (i->why) {
- cc = cescape(i->why);
- if (!cc)
- r = -ENOMEM;
- else {
- fprintf(f, "WHY=%s\n", cc);
- free(cc);
- }
- }
-
- if (i->fifo_path)
- fprintf(f, "FIFO=%s\n", i->fifo_path);
-
- fflush(f);
-
- if (ferror(f) || rename(temp_path, i->state_file) < 0) {
- r = -errno;
- unlink(i->state_file);
- unlink(temp_path);
- }
-
- fclose(f);
- free(temp_path);
-
-finish:
- if (r < 0)
- log_error("Failed to save inhibit data for %s: %s", i->id, strerror(-r));
-
- return r;
-}
-
-int inhibitor_start(Inhibitor *i) {
- assert(i);
-
- if (i->started)
- return 0;
-
- dual_timestamp_get(&i->since);
-
- log_debug("Inhibitor %s (%s) pid=%lu uid=%lu mode=%s started.",
- strna(i->who), strna(i->why),
- (unsigned long) i->pid, (unsigned long) i->uid,
- inhibit_mode_to_string(i->mode));
-
- inhibitor_save(i);
-
- i->started = true;
-
- manager_send_changed(i->manager, i->mode == INHIBIT_BLOCK ? "BlockInhibited\0" : "DelayInhibited\0");
-
- return 0;
-}
-
-int inhibitor_stop(Inhibitor *i) {
- assert(i);
-
- if (i->started)
- log_debug("Inhibitor %s (%s) pid=%lu uid=%lu mode=%s stopped.",
- strna(i->who), strna(i->why),
- (unsigned long) i->pid, (unsigned long) i->uid,
- inhibit_mode_to_string(i->mode));
-
- if (i->state_file)
- unlink(i->state_file);
-
- i->started = false;
-
- manager_send_changed(i->manager, i->mode == INHIBIT_BLOCK ? "BlockInhibited\0" : "DelayInhibited\0");
-
- return 0;
-}
-
-int inhibitor_load(Inhibitor *i) {
- InhibitWhat w;
- InhibitMode mm;
- int r;
- char *cc,
- *what = NULL,
- *uid = NULL,
- *pid = NULL,
- *who = NULL,
- *why = NULL,
- *mode = NULL;
-
- r = parse_env_file(i->state_file, NEWLINE,
- "WHAT", &what,
- "UID", &uid,
- "PID", &pid,
- "WHO", &who,
- "WHY", &why,
- "MODE", &mode,
- "FIFO", &i->fifo_path,
- NULL);
- if (r < 0)
- goto finish;
-
- w = what ? inhibit_what_from_string(what) : 0;
- if (w >= 0)
- i->what = w;
-
- mm = mode ? inhibit_mode_from_string(mode) : INHIBIT_BLOCK;
- if (mm >= 0)
- i->mode = mm;
-
- if (uid) {
- r = parse_uid(uid, &i->uid);
- if (r < 0)
- goto finish;
- }
-
- if (pid) {
- r = parse_pid(pid, &i->pid);
- if (r < 0)
- goto finish;
- }
-
- if (who) {
- cc = cunescape(who);
- if (!cc) {
- r = -ENOMEM;
- goto finish;
- }
-
- free(i->who);
- i->who = cc;
- }
-
- if (why) {
- cc = cunescape(why);
- if (!cc) {
- r = -ENOMEM;
- goto finish;
- }
-
- free(i->why);
- i->why = cc;
- }
-
- if (i->fifo_path) {
- int fd;
-
- fd = inhibitor_create_fifo(i);
- if (fd >= 0)
- close_nointr_nofail(fd);
- }
-
-finish:
- free(what);
- free(uid);
- free(pid);
- free(who);
- free(why);
-
- return r;
-}
-
-int inhibitor_create_fifo(Inhibitor *i) {
- int r;
-
- assert(i);
-
- /* Create FIFO */
- if (!i->fifo_path) {
- r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0);
- if (r < 0)
- return r;
-
- if (asprintf(&i->fifo_path, "/run/systemd/inhibit/%s.ref", i->id) < 0)
- return -ENOMEM;
-
- if (mkfifo(i->fifo_path, 0600) < 0 && errno != EEXIST)
- return -errno;
- }
-
- /* Open reading side */
- if (i->fifo_fd < 0) {
- struct epoll_event ev;
-
- i->fifo_fd = open(i->fifo_path, O_RDONLY|O_CLOEXEC|O_NDELAY);
- if (i->fifo_fd < 0)
- return -errno;
-
- r = hashmap_put(i->manager->inhibitor_fds, INT_TO_PTR(i->fifo_fd + 1), i);
- if (r < 0)
- return r;
-
- zero(ev);
- ev.events = 0;
- ev.data.u32 = FD_OTHER_BASE + i->fifo_fd;
-
- if (epoll_ctl(i->manager->epoll_fd, EPOLL_CTL_ADD, i->fifo_fd, &ev) < 0)
- return -errno;
- }
-
- /* Open writing side */
- r = open(i->fifo_path, O_WRONLY|O_CLOEXEC|O_NDELAY);
- if (r < 0)
- return -errno;
-
- return r;
-}
-
-void inhibitor_remove_fifo(Inhibitor *i) {
- assert(i);
-
- if (i->fifo_fd >= 0) {
- assert_se(hashmap_remove(i->manager->inhibitor_fds, INT_TO_PTR(i->fifo_fd + 1)) == i);
- assert_se(epoll_ctl(i->manager->epoll_fd, EPOLL_CTL_DEL, i->fifo_fd, NULL) == 0);
- close_nointr_nofail(i->fifo_fd);
- i->fifo_fd = -1;
- }
-
- if (i->fifo_path) {
- unlink(i->fifo_path);
- free(i->fifo_path);
- i->fifo_path = NULL;
- }
-}
-
-InhibitWhat manager_inhibit_what(Manager *m, InhibitMode mm) {
- Inhibitor *i;
- Iterator j;
- InhibitWhat what = 0;
-
- assert(m);
-
- HASHMAP_FOREACH(i, m->inhibitor_fds, j)
- if (i->mode == mm)
- what |= i->what;
-
- return what;
-}
-
-static int pid_is_active(Manager *m, pid_t pid) {
- Session *s;
- int r;
-
- r = manager_get_session_by_pid(m, pid, &s);
- if (r <= 0)
- return r;
-
- return session_is_active(s);
-}
-
-bool manager_is_inhibited(
- Manager *m,
- InhibitWhat w,
- InhibitMode mm,
- dual_timestamp *since,
- bool ignore_inactive,
- bool ignore_uid,
- uid_t uid) {
-
- Inhibitor *i;
- Iterator j;
- struct dual_timestamp ts = { 0, 0 };
- bool inhibited = false;
-
- assert(m);
- assert(w > 0 && w < _INHIBIT_WHAT_MAX);
-
- HASHMAP_FOREACH(i, m->inhibitor_fds, j) {
- if (!(i->what & w))
- continue;
-
- if (i->mode != mm)
- continue;
-
- if (ignore_inactive && pid_is_active(m, i->pid) <= 0)
- continue;
-
- if (ignore_uid && i->uid == uid)
- continue;
-
- if (!inhibited ||
- i->since.monotonic < ts.monotonic)
- ts = i->since;
-
- inhibited = true;
- }
-
- if (since)
- *since = ts;
-
- return inhibited;
-}
-
-const char *inhibit_what_to_string(InhibitWhat w) {
- static __thread char buffer[97];
- char *p;
-
- if (w < 0 || w >= _INHIBIT_WHAT_MAX)
- return NULL;
-
- p = buffer;
- if (w & INHIBIT_SHUTDOWN)
- p = stpcpy(p, "shutdown:");
- if (w & INHIBIT_SLEEP)
- p = stpcpy(p, "sleep:");
- if (w & INHIBIT_IDLE)
- p = stpcpy(p, "idle:");
- if (w & INHIBIT_HANDLE_POWER_KEY)
- p = stpcpy(p, "handle-power-key:");
- if (w & INHIBIT_HANDLE_SUSPEND_KEY)
- p = stpcpy(p, "handle-suspend-key:");
- if (w & INHIBIT_HANDLE_HIBERNATE_KEY)
- p = stpcpy(p, "handle-hibernate-key:");
- if (w & INHIBIT_HANDLE_LID_SWITCH)
- p = stpcpy(p, "handle-lid-switch:");
-
- if (p > buffer)
- *(p-1) = 0;
- else
- *p = 0;
-
- return buffer;
-}
-
-InhibitWhat inhibit_what_from_string(const char *s) {
- InhibitWhat what = 0;
- char *w, *state;
- size_t l;
-
- FOREACH_WORD_SEPARATOR(w, l, s, ":", state) {
- if (l == 8 && strncmp(w, "shutdown", l) == 0)
- what |= INHIBIT_SHUTDOWN;
- else if (l == 5 && strncmp(w, "sleep", l) == 0)
- what |= INHIBIT_SLEEP;
- else if (l == 4 && strncmp(w, "idle", l) == 0)
- what |= INHIBIT_IDLE;
- else if (l == 16 && strncmp(w, "handle-power-key", l) == 0)
- what |= INHIBIT_HANDLE_POWER_KEY;
- else if (l == 18 && strncmp(w, "handle-suspend-key", l) == 0)
- what |= INHIBIT_HANDLE_SUSPEND_KEY;
- else if (l == 20 && strncmp(w, "handle-hibernate-key", l) == 0)
- what |= INHIBIT_HANDLE_HIBERNATE_KEY;
- else if (l == 17 && strncmp(w, "handle-lid-switch", l) == 0)
- what |= INHIBIT_HANDLE_LID_SWITCH;
- else
- return _INHIBIT_WHAT_INVALID;
- }
-
- return what;
-}
-
-static const char* const inhibit_mode_table[_INHIBIT_MODE_MAX] = {
- [INHIBIT_BLOCK] = "block",
- [INHIBIT_DELAY] = "delay"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(inhibit_mode, InhibitMode);
diff --git a/src/login/logind-inhibit.h b/src/login/logind-inhibit.h
deleted file mode 100644
index 4c158ee0fe..0000000000
--- a/src/login/logind-inhibit.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef foologindinhibithfoo
-#define foologindinhibithfoo
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-typedef struct Inhibitor Inhibitor;
-
-#include "list.h"
-#include "util.h"
-
-typedef enum InhibitWhat {
- INHIBIT_SHUTDOWN = 1,
- INHIBIT_SLEEP = 2,
- INHIBIT_IDLE = 4,
- INHIBIT_HANDLE_POWER_KEY = 8,
- INHIBIT_HANDLE_SUSPEND_KEY = 16,
- INHIBIT_HANDLE_HIBERNATE_KEY = 32,
- INHIBIT_HANDLE_LID_SWITCH = 64,
- _INHIBIT_WHAT_MAX = 128,
- _INHIBIT_WHAT_INVALID = -1
-} InhibitWhat;
-
-typedef enum InhibitMode {
- INHIBIT_BLOCK,
- INHIBIT_DELAY,
- _INHIBIT_MODE_MAX,
- _INHIBIT_MODE_INVALID = -1
-} InhibitMode;
-
-#include "logind.h"
-#include "logind-seat.h"
-
-struct Inhibitor {
- Manager *manager;
-
- char *id;
- char *state_file;
-
- bool started;
-
- InhibitWhat what;
- char *who;
- char *why;
- InhibitMode mode;
-
- pid_t pid;
- uid_t uid;
-
- dual_timestamp since;
-
- char *fifo_path;
- int fifo_fd;
-};
-
-Inhibitor* inhibitor_new(Manager *m, const char *id);
-void inhibitor_free(Inhibitor *i);
-
-int inhibitor_save(Inhibitor *i);
-int inhibitor_load(Inhibitor *i);
-
-int inhibitor_start(Inhibitor *i);
-int inhibitor_stop(Inhibitor *i);
-
-int inhibitor_create_fifo(Inhibitor *i);
-void inhibitor_remove_fifo(Inhibitor *i);
-
-InhibitWhat manager_inhibit_what(Manager *m, InhibitMode mm);
-bool manager_is_inhibited(Manager *m, InhibitWhat w, InhibitMode mm, dual_timestamp *since, bool ignore_inactive, bool ignore_uid, uid_t uid);
-
-const char *inhibit_what_to_string(InhibitWhat k);
-InhibitWhat inhibit_what_from_string(const char *s);
-
-const char *inhibit_mode_to_string(InhibitMode k);
-InhibitMode inhibit_mode_from_string(const char *s);
-
-#endif
diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c
deleted file mode 100644
index 7833d70a03..0000000000
--- a/src/login/logind-seat-dbus.c
+++ /dev/null
@@ -1,444 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <errno.h>
-#include <string.h>
-
-#include "logind.h"
-#include "logind-seat.h"
-#include "dbus-common.h"
-#include "util.h"
-
-#define BUS_SEAT_INTERFACE \
- " <interface name=\"org.freedesktop.login1.Seat\">\n" \
- " <method name=\"Terminate\"/>\n" \
- " <method name=\"ActivateSession\">\n" \
- " <arg name=\"id\" type=\"s\"/>\n" \
- " </method>\n" \
- " <property name=\"Id\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"ActiveSession\" type=\"so\" access=\"read\"/>\n" \
- " <property name=\"CanMultiSession\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"CanTTY\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"CanGraphical\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"Sessions\" type=\"a(so)\" access=\"read\"/>\n" \
- " <property name=\"IdleHint\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"IdleSinceHint\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"IdleSinceHintMonotonic\" type=\"t\" access=\"read\"/>\n" \
- " </interface>\n" \
-
-#define INTROSPECTION \
- DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
- "<node>\n" \
- BUS_SEAT_INTERFACE \
- BUS_PROPERTIES_INTERFACE \
- BUS_PEER_INTERFACE \
- BUS_INTROSPECTABLE_INTERFACE \
- "</node>\n"
-
-#define INTERFACES_LIST \
- BUS_GENERIC_INTERFACES_LIST \
- "org.freedesktop.login1.Seat\0"
-
-static int bus_seat_append_active(DBusMessageIter *i, const char *property, void *data) {
- DBusMessageIter sub;
- Seat *s = data;
- const char *id, *path;
- char *p = NULL;
-
- assert(i);
- assert(property);
- assert(s);
-
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub))
- return -ENOMEM;
-
- if (s->active) {
- id = s->active->id;
- path = p = session_bus_path(s->active);
-
- if (!p)
- return -ENOMEM;
- } else {
- id = "";
- path = "/";
- }
-
- if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &id) ||
- !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &path)) {
- free(p);
- return -ENOMEM;
- }
-
- free(p);
-
- if (!dbus_message_iter_close_container(i, &sub))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_seat_append_sessions(DBusMessageIter *i, const char *property, void *data) {
- DBusMessageIter sub, sub2;
- Seat *s = data;
- Session *session;
-
- assert(i);
- assert(property);
- assert(s);
-
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(so)", &sub))
- return -ENOMEM;
-
- LIST_FOREACH(sessions_by_seat, session, s->sessions) {
- char *p;
-
- if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
- return -ENOMEM;
-
- p = session_bus_path(session);
- if (!p)
- return -ENOMEM;
-
- if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &session->id) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &p)) {
- free(p);
- return -ENOMEM;
- }
-
- free(p);
-
- if (!dbus_message_iter_close_container(&sub, &sub2))
- return -ENOMEM;
- }
-
- if (!dbus_message_iter_close_container(i, &sub))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_seat_append_can_multi_session(DBusMessageIter *i, const char *property, void *data) {
- Seat *s = data;
- dbus_bool_t b;
-
- assert(i);
- assert(property);
- assert(s);
-
- b = seat_can_multi_session(s);
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_seat_append_can_tty(DBusMessageIter *i, const char *property, void *data) {
- Seat *s = data;
- dbus_bool_t b;
-
- assert(i);
- assert(property);
- assert(s);
-
- b = seat_can_tty(s);
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_seat_append_can_graphical(DBusMessageIter *i, const char *property, void *data) {
- Seat *s = data;
- dbus_bool_t b;
-
- assert(i);
- assert(property);
- assert(s);
-
- b = seat_can_graphical(s);
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_seat_append_idle_hint(DBusMessageIter *i, const char *property, void *data) {
- Seat *s = data;
- dbus_bool_t b;
-
- assert(i);
- assert(property);
- assert(s);
-
- b = seat_get_idle_hint(s, NULL) > 0;
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_seat_append_idle_hint_since(DBusMessageIter *i, const char *property, void *data) {
- Seat *s = data;
- dual_timestamp t;
- uint64_t k;
-
- assert(i);
- assert(property);
- assert(s);
-
- seat_get_idle_hint(s, &t);
- k = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &k))
- return -ENOMEM;
-
- return 0;
-}
-
-static int get_seat_for_path(Manager *m, const char *path, Seat **_s) {
- Seat *s;
- char *id;
-
- assert(m);
- assert(path);
- assert(_s);
-
- if (!startswith(path, "/org/freedesktop/login1/seat/"))
- return -EINVAL;
-
- id = bus_path_unescape(path + 29);
- if (!id)
- return -ENOMEM;
-
- s = hashmap_get(m->seats, id);
- free(id);
-
- if (!s)
- return -ENOENT;
-
- *_s = s;
- return 0;
-}
-
-static const BusProperty bus_login_seat_properties[] = {
- { "Id", bus_property_append_string, "s", offsetof(Seat, id), true },
- { "ActiveSession", bus_seat_append_active, "(so)", 0 },
- { "CanMultiSession", bus_seat_append_can_multi_session, "b", 0 },
- { "CanTTY", bus_seat_append_can_tty, "b", 0 },
- { "CanGraphical", bus_seat_append_can_graphical, "b", 0 },
- { "Sessions", bus_seat_append_sessions, "a(so)", 0 },
- { "IdleHint", bus_seat_append_idle_hint, "b", 0 },
- { "IdleSinceHint", bus_seat_append_idle_hint_since, "t", 0 },
- { "IdleSinceHintMonotonic", bus_seat_append_idle_hint_since, "t", 0 },
- { NULL, }
-};
-
-static DBusHandlerResult seat_message_dispatch(
- Seat *s,
- DBusConnection *connection,
- DBusMessage *message) {
-
- DBusError error;
- DBusMessage *reply = NULL;
- int r;
-
- assert(s);
- assert(connection);
- assert(message);
-
- dbus_error_init(&error);
-
- if (dbus_message_is_method_call(message, "org.freedesktop.login1.Seat", "Terminate")) {
-
- r = seat_stop_sessions(s);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Seat", "ActivateSession")) {
- const char *name;
- Session *session;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- session = hashmap_get(s->manager->sessions, name);
- if (!session || session->seat != s)
- return bus_send_error_reply(connection, message, &error, -ENOENT);
-
- r = session_activate(session);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
- } else {
- const BusBoundProperties bps[] = {
- { "org.freedesktop.login1.Seat", bus_login_seat_properties, s },
- { NULL, }
- };
- return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps);
- }
-
- if (reply) {
- if (!dbus_connection_send(connection, reply, NULL))
- goto oom;
-
- dbus_message_unref(reply);
- }
-
- return DBUS_HANDLER_RESULT_HANDLED;
-
-oom:
- if (reply)
- dbus_message_unref(reply);
-
- dbus_error_free(&error);
-
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-}
-
-static DBusHandlerResult seat_message_handler(
- DBusConnection *connection,
- DBusMessage *message,
- void *userdata) {
-
- Manager *m = userdata;
- Seat *s;
- int r;
-
- r = get_seat_for_path(m, dbus_message_get_path(message), &s);
- if (r < 0) {
-
- if (r == -ENOMEM)
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
- if (r == -ENOENT) {
- DBusError e;
-
- dbus_error_init(&e);
- dbus_set_error_const(&e, DBUS_ERROR_UNKNOWN_OBJECT, "Unknown seat");
- return bus_send_error_reply(connection, message, &e, r);
- }
-
- return bus_send_error_reply(connection, message, NULL, r);
- }
-
- return seat_message_dispatch(s, connection, message);
-}
-
-const DBusObjectPathVTable bus_seat_vtable = {
- .message_function = seat_message_handler
-};
-
-char *seat_bus_path(Seat *s) {
- char *t, *r;
-
- assert(s);
-
- t = bus_path_escape(s->id);
- if (!t)
- return NULL;
-
- r = strappend("/org/freedesktop/login1/seat/", t);
- free(t);
-
- return r;
-}
-
-int seat_send_signal(Seat *s, bool new_seat) {
- DBusMessage *m;
- int r = -ENOMEM;
- char *p = NULL;
-
- assert(s);
-
- m = dbus_message_new_signal("/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- new_seat ? "SeatNew" : "SeatRemoved");
-
- if (!m)
- return -ENOMEM;
-
- p = seat_bus_path(s);
- if (!p)
- goto finish;
-
- if (!dbus_message_append_args(
- m,
- DBUS_TYPE_STRING, &s->id,
- DBUS_TYPE_OBJECT_PATH, &p,
- DBUS_TYPE_INVALID))
- goto finish;
-
- if (!dbus_connection_send(s->manager->bus, m, NULL))
- goto finish;
-
- r = 0;
-
-finish:
- dbus_message_unref(m);
- free(p);
-
- return r;
-}
-
-int seat_send_changed(Seat *s, const char *properties) {
- DBusMessage *m;
- int r = -ENOMEM;
- char *p = NULL;
-
- assert(s);
-
- if (!s->started)
- return 0;
-
- p = seat_bus_path(s);
- if (!p)
- return -ENOMEM;
-
- m = bus_properties_changed_new(p, "org.freedesktop.login1.Seat", properties);
- if (!m)
- goto finish;
-
- if (!dbus_connection_send(s->manager->bus, m, NULL))
- goto finish;
-
- r = 0;
-
-finish:
- if (m)
- dbus_message_unref(m);
- free(p);
-
- return r;
-}
diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c
deleted file mode 100644
index 470d08bc05..0000000000
--- a/src/login/logind-seat.c
+++ /dev/null
@@ -1,543 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <assert.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <linux/vt.h>
-#include <string.h>
-
-#include "systemd/sd-id128.h"
-#include "systemd/sd-messages.h"
-#include "logind-seat.h"
-#include "logind-acl.h"
-#include "util.h"
-#include "mkdir.h"
-#include "path-util.h"
-
-Seat *seat_new(Manager *m, const char *id) {
- Seat *s;
-
- assert(m);
- assert(id);
-
- s = new0(Seat, 1);
- if (!s)
- return NULL;
-
- s->state_file = strappend("/run/systemd/seats/", id);
- if (!s->state_file) {
- free(s);
- return NULL;
- }
-
- s->id = path_get_file_name(s->state_file);
- s->manager = m;
-
- if (hashmap_put(m->seats, s->id, s) < 0) {
- free(s->state_file);
- free(s);
- return NULL;
- }
-
- return s;
-}
-
-void seat_free(Seat *s) {
- assert(s);
-
- if (s->in_gc_queue)
- LIST_REMOVE(Seat, gc_queue, s->manager->seat_gc_queue, s);
-
- while (s->sessions)
- session_free(s->sessions);
-
- assert(!s->active);
-
- while (s->devices)
- device_free(s->devices);
-
- hashmap_remove(s->manager->seats, s->id);
-
- free(s->state_file);
- free(s);
-}
-
-int seat_save(Seat *s) {
- int r;
- FILE *f;
- char *temp_path;
-
- assert(s);
-
- if (!s->started)
- return 0;
-
- r = mkdir_safe_label("/run/systemd/seats", 0755, 0, 0);
- if (r < 0)
- goto finish;
-
- r = fopen_temporary(s->state_file, &f, &temp_path);
- if (r < 0)
- goto finish;
-
- fchmod(fileno(f), 0644);
-
- fprintf(f,
- "# This is private data. Do not parse.\n"
- "IS_VTCONSOLE=%i\n"
- "CAN_MULTI_SESSION=%i\n"
- "CAN_TTY=%i\n"
- "CAN_GRAPHICAL=%i\n",
- seat_is_vtconsole(s),
- seat_can_multi_session(s),
- seat_can_tty(s),
- seat_can_graphical(s));
-
- if (s->active) {
- assert(s->active->user);
-
- fprintf(f,
- "ACTIVE=%s\n"
- "ACTIVE_UID=%lu\n",
- s->active->id,
- (unsigned long) s->active->user->uid);
- }
-
- if (s->sessions) {
- Session *i;
-
- fputs("SESSIONS=", f);
- LIST_FOREACH(sessions_by_seat, i, s->sessions) {
- fprintf(f,
- "%s%c",
- i->id,
- i->sessions_by_seat_next ? ' ' : '\n');
- }
-
- fputs("UIDS=", f);
- LIST_FOREACH(sessions_by_seat, i, s->sessions)
- fprintf(f,
- "%lu%c",
- (unsigned long) i->user->uid,
- i->sessions_by_seat_next ? ' ' : '\n');
- }
-
- fflush(f);
-
- if (ferror(f) || rename(temp_path, s->state_file) < 0) {
- r = -errno;
- unlink(s->state_file);
- unlink(temp_path);
- }
-
- fclose(f);
- free(temp_path);
-
-finish:
- if (r < 0)
- log_error("Failed to save seat data for %s: %s", s->id, strerror(-r));
-
- return r;
-}
-
-int seat_load(Seat *s) {
- assert(s);
-
- /* There isn't actually anything to read here ... */
-
- return 0;
-}
-
-static int vt_allocate(int vtnr) {
- int fd, r;
- char *p;
-
- assert(vtnr >= 1);
-
- if (asprintf(&p, "/dev/tty%i", vtnr) < 0)
- return -ENOMEM;
-
- fd = open_terminal(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
- free(p);
-
- r = fd < 0 ? -errno : 0;
-
- if (fd >= 0)
- close_nointr_nofail(fd);
-
- return r;
-}
-
-int seat_preallocate_vts(Seat *s) {
- int r = 0;
- unsigned i;
-
- assert(s);
- assert(s->manager);
-
- log_debug("Preallocating VTs...");
-
- if (s->manager->n_autovts <= 0)
- return 0;
-
- if (!seat_can_multi_session(s))
- return 0;
-
- for (i = 1; i <= s->manager->n_autovts; i++) {
- int q;
-
- q = vt_allocate(i);
- if (q < 0) {
- log_error("Failed to preallocate VT %i: %s", i, strerror(-q));
- r = q;
- }
- }
-
- return r;
-}
-
-int seat_apply_acls(Seat *s, Session *old_active) {
- int r;
-
- assert(s);
-
- r = devnode_acl_all(s->manager->udev,
- s->id,
- false,
- !!old_active, old_active ? old_active->user->uid : 0,
- !!s->active, s->active ? s->active->user->uid : 0);
-
- if (r < 0)
- log_error("Failed to apply ACLs: %s", strerror(-r));
-
- return r;
-}
-
-int seat_set_active(Seat *s, Session *session) {
- Session *old_active;
-
- assert(s);
- assert(!session || session->seat == s);
-
- if (session == s->active)
- return 0;
-
- old_active = s->active;
- s->active = session;
-
- seat_apply_acls(s, old_active);
-
- if (session && session->started)
- session_send_changed(session, "Active\0");
-
- if (!session || session->started)
- seat_send_changed(s, "ActiveSession\0");
-
- seat_save(s);
-
- if (session) {
- session_save(session);
- user_save(session->user);
- }
-
- if (old_active) {
- session_save(old_active);
- if (!session || session->user != old_active->user)
- user_save(old_active->user);
- }
-
- return 0;
-}
-
-int seat_active_vt_changed(Seat *s, int vtnr) {
- Session *i, *new_active = NULL;
- int r;
-
- assert(s);
- assert(vtnr >= 1);
-
- if (!seat_can_multi_session(s))
- return -EINVAL;
-
- log_debug("VT changed to %i", vtnr);
-
- LIST_FOREACH(sessions_by_seat, i, s->sessions)
- if (i->vtnr == vtnr) {
- new_active = i;
- break;
- }
-
- r = seat_set_active(s, new_active);
- manager_spawn_autovt(s->manager, vtnr);
-
- return r;
-}
-
-int seat_read_active_vt(Seat *s) {
- char t[64];
- ssize_t k;
- int r, vtnr;
-
- assert(s);
-
- if (!seat_can_multi_session(s))
- return 0;
-
- lseek(s->manager->console_active_fd, SEEK_SET, 0);
-
- k = read(s->manager->console_active_fd, t, sizeof(t)-1);
- if (k <= 0) {
- log_error("Failed to read current console: %s", k < 0 ? strerror(-errno) : "EOF");
- return k < 0 ? -errno : -EIO;
- }
-
- t[k] = 0;
- truncate_nl(t);
-
- if (!startswith(t, "tty")) {
- log_error("Hm, /sys/class/tty/tty0/active is badly formatted.");
- return -EIO;
- }
-
- r = safe_atoi(t+3, &vtnr);
- if (r < 0) {
- log_error("Failed to parse VT number %s", t+3);
- return r;
- }
-
- if (vtnr <= 0) {
- log_error("VT number invalid: %s", t+3);
- return -EIO;
- }
-
- return seat_active_vt_changed(s, vtnr);
-}
-
-int seat_start(Seat *s) {
- assert(s);
-
- if (s->started)
- return 0;
-
- log_struct(LOG_INFO,
- MESSAGE_ID(SD_MESSAGE_SEAT_START),
- "SEAT_ID=%s", s->id,
- "MESSAGE=New seat %s.", s->id,
- NULL);
-
- /* Initialize VT magic stuff */
- seat_preallocate_vts(s);
-
- /* Read current VT */
- seat_read_active_vt(s);
-
- s->started = true;
-
- /* Save seat data */
- seat_save(s);
-
- seat_send_signal(s, true);
-
- return 0;
-}
-
-int seat_stop(Seat *s) {
- int r = 0;
-
- assert(s);
-
- if (s->started)
- log_struct(LOG_INFO,
- MESSAGE_ID(SD_MESSAGE_SEAT_STOP),
- "SEAT_ID=%s", s->id,
- "MESSAGE=Removed seat %s.", s->id,
- NULL);
-
- seat_stop_sessions(s);
-
- unlink(s->state_file);
- seat_add_to_gc_queue(s);
-
- if (s->started)
- seat_send_signal(s, false);
-
- s->started = false;
-
- return r;
-}
-
-int seat_stop_sessions(Seat *s) {
- Session *session;
- int r = 0, k;
-
- assert(s);
-
- LIST_FOREACH(sessions_by_seat, session, s->sessions) {
- k = session_stop(session);
- if (k < 0)
- r = k;
- }
-
- return r;
-}
-
-int seat_attach_session(Seat *s, Session *session) {
- assert(s);
- assert(session);
- assert(!session->seat);
-
- session->seat = s;
- LIST_PREPEND(Session, sessions_by_seat, s->sessions, session);
-
- seat_send_changed(s, "Sessions\0");
-
- /* Note that even if a seat is not multi-session capable it
- * still might have multiple sessions on it since old, dead
- * sessions might continue to be tracked until all their
- * processes are gone. The most recently added session
- * (i.e. the first in s->sessions) is the one that matters. */
-
- if (!seat_can_multi_session(s))
- seat_set_active(s, session);
-
- return 0;
-}
-
-bool seat_is_vtconsole(Seat *s) {
- assert(s);
-
- return s->manager->vtconsole == s;
-}
-
-bool seat_can_multi_session(Seat *s) {
- assert(s);
-
- if (!seat_is_vtconsole(s))
- return false;
-
- /* If we can't watch which VT is in the foreground, we don't
- * support VT switching */
-
- return s->manager->console_active_fd >= 0;
-}
-
-bool seat_can_tty(Seat *s) {
- assert(s);
-
- return seat_is_vtconsole(s);
-}
-
-bool seat_can_graphical(Seat *s) {
- assert(s);
-
- return !!s->devices;
-}
-
-int seat_get_idle_hint(Seat *s, dual_timestamp *t) {
- Session *session;
- bool idle_hint = true;
- dual_timestamp ts = { 0, 0 };
-
- assert(s);
-
- LIST_FOREACH(sessions_by_seat, session, s->sessions) {
- dual_timestamp k;
- int ih;
-
- ih = session_get_idle_hint(session, &k);
- if (ih < 0)
- return ih;
-
- if (!ih) {
- if (!idle_hint) {
- if (k.monotonic > ts.monotonic)
- ts = k;
- } else {
- idle_hint = false;
- ts = k;
- }
- } else if (idle_hint) {
-
- if (k.monotonic > ts.monotonic)
- ts = k;
- }
- }
-
- if (t)
- *t = ts;
-
- return idle_hint;
-}
-
-int seat_check_gc(Seat *s, bool drop_not_started) {
- assert(s);
-
- if (drop_not_started && !s->started)
- return 0;
-
- if (seat_is_vtconsole(s))
- return 1;
-
- return !!s->devices;
-}
-
-void seat_add_to_gc_queue(Seat *s) {
- assert(s);
-
- if (s->in_gc_queue)
- return;
-
- LIST_PREPEND(Seat, gc_queue, s->manager->seat_gc_queue, s);
- s->in_gc_queue = true;
-}
-
-static bool seat_name_valid_char(char c) {
- return
- (c >= 'a' && c <= 'z') ||
- (c >= 'A' && c <= 'Z') ||
- (c >= '0' && c <= '9') ||
- c == '-' ||
- c == '_';
-}
-
-bool seat_name_is_valid(const char *name) {
- const char *p;
-
- assert(name);
-
- if (!startswith(name, "seat"))
- return false;
-
- if (!name[4])
- return false;
-
- for (p = name; *p; p++)
- if (!seat_name_valid_char(*p))
- return false;
-
- if (strlen(name) > 255)
- return false;
-
- return true;
-}
diff --git a/src/login/logind-seat.h b/src/login/logind-seat.h
deleted file mode 100644
index c8ab17f7cf..0000000000
--- a/src/login/logind-seat.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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/>.
-***/
-
-typedef struct Seat Seat;
-
-#include "list.h"
-#include "util.h"
-#include "logind.h"
-#include "logind-device.h"
-#include "logind-session.h"
-
-struct Seat {
- Manager *manager;
- char *id;
-
- char *state_file;
-
- LIST_HEAD(Device, devices);
-
- Session *active;
- LIST_HEAD(Session, sessions);
-
- bool in_gc_queue:1;
- bool started:1;
-
- LIST_FIELDS(Seat, gc_queue);
-};
-
-Seat *seat_new(Manager *m, const char *id);
-void seat_free(Seat *s);
-
-int seat_save(Seat *s);
-int seat_load(Seat *s);
-
-int seat_apply_acls(Seat *s, Session *old_active);
-int seat_set_active(Seat *s, Session *session);
-int seat_active_vt_changed(Seat *s, int vtnr);
-int seat_read_active_vt(Seat *s);
-int seat_preallocate_vts(Seat *s);
-
-int seat_attach_session(Seat *s, Session *session);
-
-bool seat_is_vtconsole(Seat *s);
-bool seat_can_multi_session(Seat *s);
-bool seat_can_tty(Seat *s);
-bool seat_can_graphical(Seat *s);
-
-int seat_get_idle_hint(Seat *s, dual_timestamp *t);
-
-int seat_start(Seat *s);
-int seat_stop(Seat *s);
-int seat_stop_sessions(Seat *s);
-
-int seat_check_gc(Seat *s, bool drop_not_started);
-void seat_add_to_gc_queue(Seat *s);
-
-bool seat_name_is_valid(const char *name);
-char *seat_bus_path(Seat *s);
-
-extern const DBusObjectPathVTable bus_seat_vtable;
-
-int seat_send_signal(Seat *s, bool new_seat);
-int seat_send_changed(Seat *s, const char *properties);
diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c
deleted file mode 100644
index ef73cd434a..0000000000
--- a/src/login/logind-session-dbus.c
+++ /dev/null
@@ -1,590 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <errno.h>
-#include <string.h>
-
-#include "logind.h"
-#include "logind-session.h"
-#include "dbus-common.h"
-#include "util.h"
-
-#define BUS_SESSION_INTERFACE \
- " <interface name=\"org.freedesktop.login1.Session\">\n" \
- " <method name=\"Terminate\"/>\n" \
- " <method name=\"Activate\"/>\n" \
- " <method name=\"Lock\"/>\n" \
- " <method name=\"Unlock\"/>\n" \
- " <method name=\"SetIdleHint\">\n" \
- " <arg name=\"b\" type=\"b\"/>\n" \
- " </method>\n" \
- " <method name=\"Kill\">\n" \
- " <arg name=\"who\" type=\"s\"/>\n" \
- " <arg name=\"signal\" type=\"s\"/>\n" \
- " </method>\n" \
- " <signal name=\"Lock\"/>\n" \
- " <signal name=\"Unlock\"/>\n" \
- " <property name=\"Id\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"User\" type=\"(uo)\" access=\"read\"/>\n" \
- " <property name=\"Name\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Timestamp\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"TimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"DefaultControlGroup\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"VTNr\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"Seat\" type=\"(so)\" access=\"read\"/>\n" \
- " <property name=\"TTY\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Display\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Remote\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"RemoteHost\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"RemoteUser\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Service\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Leader\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"Audit\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"Type\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Class\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Active\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"State\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Controllers\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"ResetControllers\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"KillProcesses\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"IdleHint\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"IdleSinceHint\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"IdleSinceHintMonotonic\" type=\"t\" access=\"read\"/>\n" \
- " </interface>\n"
-
-#define INTROSPECTION \
- DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
- "<node>\n" \
- BUS_SESSION_INTERFACE \
- BUS_PROPERTIES_INTERFACE \
- BUS_PEER_INTERFACE \
- BUS_INTROSPECTABLE_INTERFACE \
- "</node>\n"
-
-#define INTERFACES_LIST \
- BUS_GENERIC_INTERFACES_LIST \
- "org.freedesktop.login1.Session\0"
-
-static int bus_session_append_seat(DBusMessageIter *i, const char *property, void *data) {
- DBusMessageIter sub;
- Session *s = data;
- const char *id, *path;
- char *p = NULL;
-
- assert(i);
- assert(property);
- assert(s);
-
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub))
- return -ENOMEM;
-
- if (s->seat) {
- id = s->seat->id;
- path = p = seat_bus_path(s->seat);
-
- if (!p)
- return -ENOMEM;
- } else {
- id = "";
- path = "/";
- }
-
- if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &id) ||
- !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &path)) {
- free(p);
- return -ENOMEM;
- }
-
- free(p);
-
- if (!dbus_message_iter_close_container(i, &sub))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_session_append_user(DBusMessageIter *i, const char *property, void *data) {
- DBusMessageIter sub;
- User *u = data;
- char *p = NULL;
-
- assert(i);
- assert(property);
- assert(u);
-
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub))
- return -ENOMEM;
-
- p = user_bus_path(u);
- if (!p)
- return -ENOMEM;
-
- if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT32, &u->uid) ||
- !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &p)) {
- free(p);
- return -ENOMEM;
- }
-
- free(p);
-
- if (!dbus_message_iter_close_container(i, &sub))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_session_append_active(DBusMessageIter *i, const char *property, void *data) {
- Session *s = data;
- dbus_bool_t b;
-
- assert(i);
- assert(property);
- assert(s);
-
- b = session_is_active(s);
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_session_append_idle_hint(DBusMessageIter *i, const char *property, void *data) {
- Session *s = data;
- int b;
-
- assert(i);
- assert(property);
- assert(s);
-
- b = session_get_idle_hint(s, NULL) > 0;
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_session_append_idle_hint_since(DBusMessageIter *i, const char *property, void *data) {
- Session *s = data;
- dual_timestamp t;
- uint64_t u;
- int r;
-
- assert(i);
- assert(property);
- assert(s);
-
- r = session_get_idle_hint(s, &t);
- if (r < 0)
- return r;
-
- u = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_session_append_default_cgroup(DBusMessageIter *i, const char *property, void *data) {
- Session *s = data;
- char *t;
- int r;
- bool success;
-
- assert(i);
- assert(property);
- assert(s);
-
- r = cg_join_spec(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, &t);
- if (r < 0)
- return r;
-
- success = dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t);
- free(t);
-
- return success ? 0 : -ENOMEM;
-}
-
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_session_append_type, session_type, SessionType);
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_session_append_class, session_class, SessionClass);
-
-static int bus_session_append_state(DBusMessageIter *i, const char *property, void *data) {
- Session *s = data;
- const char *state;
-
- assert(i);
- assert(property);
- assert(s);
-
- state = session_state_to_string(session_get_state(s));
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &state))
- return -ENOMEM;
-
- return 0;
-}
-
-static int get_session_for_path(Manager *m, const char *path, Session **_s) {
- Session *s;
- char *id;
-
- assert(m);
- assert(path);
- assert(_s);
-
- if (!startswith(path, "/org/freedesktop/login1/session/"))
- return -EINVAL;
-
- id = bus_path_unescape(path + 32);
- if (!id)
- return -ENOMEM;
-
- s = hashmap_get(m->sessions, id);
- free(id);
-
- if (!s)
- return -ENOENT;
-
- *_s = s;
- return 0;
-}
-
-static const BusProperty bus_login_session_properties[] = {
- { "Id", bus_property_append_string, "s", offsetof(Session, id), true },
- { "Timestamp", bus_property_append_usec, "t", offsetof(Session, timestamp.realtime) },
- { "TimestampMonotonic", bus_property_append_usec, "t", offsetof(Session, timestamp.monotonic) },
- { "DefaultControlGroup", bus_session_append_default_cgroup, "s", 0, },
- { "VTNr", bus_property_append_uint32, "u", offsetof(Session, vtnr) },
- { "Seat", bus_session_append_seat, "(so)", 0 },
- { "TTY", bus_property_append_string, "s", offsetof(Session, tty), true },
- { "Display", bus_property_append_string, "s", offsetof(Session, display), true },
- { "Remote", bus_property_append_bool, "b", offsetof(Session, remote) },
- { "RemoteUser", bus_property_append_string, "s", offsetof(Session, remote_user), true },
- { "RemoteHost", bus_property_append_string, "s", offsetof(Session, remote_host), true },
- { "Service", bus_property_append_string, "s", offsetof(Session, service), true },
- { "Leader", bus_property_append_pid, "u", offsetof(Session, leader) },
- { "Audit", bus_property_append_uint32, "u", offsetof(Session, audit_id) },
- { "Type", bus_session_append_type, "s", offsetof(Session, type) },
- { "Class", bus_session_append_class, "s", offsetof(Session, class) },
- { "Active", bus_session_append_active, "b", 0 },
- { "State", bus_session_append_state, "s", 0 },
- { "Controllers", bus_property_append_strv, "as", offsetof(Session, controllers), true },
- { "ResetControllers", bus_property_append_strv, "as", offsetof(Session, reset_controllers), true },
- { "KillProcesses", bus_property_append_bool, "b", offsetof(Session, kill_processes) },
- { "IdleHint", bus_session_append_idle_hint, "b", 0 },
- { "IdleSinceHint", bus_session_append_idle_hint_since, "t", 0 },
- { "IdleSinceHintMonotonic", bus_session_append_idle_hint_since, "t", 0 },
- { NULL, }
-};
-
-static const BusProperty bus_login_session_user_properties[] = {
- { "User", bus_session_append_user, "(uo)", 0 },
- { "Name", bus_property_append_string, "s", offsetof(User, name), true },
- { NULL, }
-};
-
-static DBusHandlerResult session_message_dispatch(
- Session *s,
- DBusConnection *connection,
- DBusMessage *message) {
-
- DBusError error;
- DBusMessage *reply = NULL;
- int r;
-
- assert(s);
- assert(connection);
- assert(message);
-
- dbus_error_init(&error);
-
- if (dbus_message_is_method_call(message, "org.freedesktop.login1.Session", "Terminate")) {
-
- r = session_stop(s);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Session", "Activate")) {
-
- r = session_activate(s);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Session", "Lock") ||
- dbus_message_is_method_call(message, "org.freedesktop.login1.Session", "Unlock")) {
-
- if (session_send_lock(s, streq(dbus_message_get_member(message), "Lock")) < 0)
- goto oom;
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Session", "SetIdleHint")) {
- dbus_bool_t b;
- unsigned long ul;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_BOOLEAN, &b,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), &error);
- if (ul == (unsigned long) -1)
- return bus_send_error_reply(connection, message, &error, -EIO);
-
- if (ul != 0 && ul != s->user->uid)
- return bus_send_error_reply(connection, message, NULL, -EPERM);
-
- session_set_idle_hint(s, b);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Session", "Kill")) {
- const char *swho;
- int32_t signo;
- KillWho who;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &swho,
- DBUS_TYPE_INT32, &signo,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- if (isempty(swho))
- who = KILL_ALL;
- else {
- who = kill_who_from_string(swho);
- if (who < 0)
- return bus_send_error_reply(connection, message, &error, -EINVAL);
- }
-
- if (signo <= 0 || signo >= _NSIG)
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- r = session_kill(s, who, signo);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else {
- const BusBoundProperties bps[] = {
- { "org.freedesktop.login1.Session", bus_login_session_properties, s },
- { "org.freedesktop.login1.Session", bus_login_session_user_properties, s->user },
- { NULL, }
- };
- return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps);
- }
-
- if (reply) {
- if (!dbus_connection_send(connection, reply, NULL))
- goto oom;
-
- dbus_message_unref(reply);
- }
-
- return DBUS_HANDLER_RESULT_HANDLED;
-
-oom:
- if (reply)
- dbus_message_unref(reply);
-
- dbus_error_free(&error);
-
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-}
-
-static DBusHandlerResult session_message_handler(
- DBusConnection *connection,
- DBusMessage *message,
- void *userdata) {
-
- Manager *m = userdata;
- Session *s;
- int r;
-
- r = get_session_for_path(m, dbus_message_get_path(message), &s);
- if (r < 0) {
-
- if (r == -ENOMEM)
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
- if (r == -ENOENT) {
- DBusError e;
-
- dbus_error_init(&e);
- dbus_set_error_const(&e, DBUS_ERROR_UNKNOWN_OBJECT, "Unknown session");
- return bus_send_error_reply(connection, message, &e, r);
- }
-
- return bus_send_error_reply(connection, message, NULL, r);
- }
-
- return session_message_dispatch(s, connection, message);
-}
-
-const DBusObjectPathVTable bus_session_vtable = {
- .message_function = session_message_handler
-};
-
-char *session_bus_path(Session *s) {
- char *t, *r;
-
- assert(s);
-
- t = bus_path_escape(s->id);
- if (!t)
- return NULL;
-
- r = strappend("/org/freedesktop/login1/session/", t);
- free(t);
-
- return r;
-}
-
-int session_send_signal(Session *s, bool new_session) {
- DBusMessage *m;
- int r = -ENOMEM;
- char *p = NULL;
-
- assert(s);
-
- m = dbus_message_new_signal("/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- new_session ? "SessionNew" : "SessionRemoved");
-
- if (!m)
- return -ENOMEM;
-
- p = session_bus_path(s);
- if (!p)
- goto finish;
-
- if (!dbus_message_append_args(
- m,
- DBUS_TYPE_STRING, &s->id,
- DBUS_TYPE_OBJECT_PATH, &p,
- DBUS_TYPE_INVALID))
- goto finish;
-
- if (!dbus_connection_send(s->manager->bus, m, NULL))
- goto finish;
-
- r = 0;
-
-finish:
- dbus_message_unref(m);
- free(p);
-
- return r;
-}
-
-int session_send_changed(Session *s, const char *properties) {
- DBusMessage *m;
- int r = -ENOMEM;
- char *p = NULL;
-
- assert(s);
-
- if (!s->started)
- return 0;
-
- p = session_bus_path(s);
- if (!p)
- return -ENOMEM;
-
- m = bus_properties_changed_new(p, "org.freedesktop.login1.Session", properties);
- if (!m)
- goto finish;
-
- if (!dbus_connection_send(s->manager->bus, m, NULL))
- goto finish;
-
- r = 0;
-
-finish:
- if (m)
- dbus_message_unref(m);
- free(p);
-
- return r;
-}
-
-int session_send_lock(Session *s, bool lock) {
- DBusMessage *m;
- bool b;
- char *p;
-
- assert(s);
-
- p = session_bus_path(s);
- if (!p)
- return -ENOMEM;
-
- m = dbus_message_new_signal(p, "org.freedesktop.login1.Session", lock ? "Lock" : "Unlock");
- free(p);
-
- if (!m)
- return -ENOMEM;
-
- b = dbus_connection_send(s->manager->bus, m, NULL);
- dbus_message_unref(m);
-
- if (!b)
- return -ENOMEM;
-
- return 0;
-}
-
-int session_send_lock_all(Manager *m, bool lock) {
- Session *session;
- Iterator i;
- int r = 0;
-
- assert(m);
-
- HASHMAP_FOREACH(session, m->sessions, i) {
- int k;
-
- k = session_send_lock(session, lock);
- if (k < 0)
- r = k;
- }
-
- return r;
-}
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
deleted file mode 100644
index 5d9401b223..0000000000
--- a/src/login/logind-session.c
+++ /dev/null
@@ -1,1010 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/epoll.h>
-#include <fcntl.h>
-
-#include "systemd/sd-id128.h"
-#include "systemd/sd-messages.h"
-#include "strv.h"
-#include "util.h"
-#include "mkdir.h"
-#include "path-util.h"
-#include "cgroup-util.h"
-#include "logind-session.h"
-
-#define IDLE_THRESHOLD_USEC (5*USEC_PER_MINUTE)
-
-Session* session_new(Manager *m, User *u, const char *id) {
- Session *s;
-
- assert(m);
- assert(id);
-
- s = new0(Session, 1);
- if (!s)
- return NULL;
-
- s->state_file = strappend("/run/systemd/sessions/", id);
- if (!s->state_file) {
- free(s);
- return NULL;
- }
-
- s->id = path_get_file_name(s->state_file);
-
- if (hashmap_put(m->sessions, s->id, s) < 0) {
- free(s->state_file);
- free(s);
- return NULL;
- }
-
- s->manager = m;
- s->fifo_fd = -1;
- s->user = u;
-
- LIST_PREPEND(Session, sessions_by_user, u->sessions, s);
-
- return s;
-}
-
-void session_free(Session *s) {
- assert(s);
-
- if (s->in_gc_queue)
- LIST_REMOVE(Session, gc_queue, s->manager->session_gc_queue, s);
-
- if (s->user) {
- LIST_REMOVE(Session, sessions_by_user, s->user->sessions, s);
-
- if (s->user->display == s)
- s->user->display = NULL;
- }
-
- if (s->seat) {
- if (s->seat->active == s)
- s->seat->active = NULL;
-
- LIST_REMOVE(Session, sessions_by_seat, s->seat->sessions, s);
- }
-
- if (s->cgroup_path)
- hashmap_remove(s->manager->session_cgroups, s->cgroup_path);
-
- free(s->cgroup_path);
- strv_free(s->controllers);
-
- free(s->tty);
- free(s->display);
- free(s->remote_host);
- free(s->remote_user);
- free(s->service);
-
- hashmap_remove(s->manager->sessions, s->id);
- session_remove_fifo(s);
-
- free(s->state_file);
- free(s);
-}
-
-int session_save(Session *s) {
- FILE *f;
- int r = 0;
- char *temp_path;
-
- assert(s);
-
- if (!s->started)
- return 0;
-
- r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
- if (r < 0)
- goto finish;
-
- r = fopen_temporary(s->state_file, &f, &temp_path);
- if (r < 0)
- goto finish;
-
- assert(s->user);
-
- fchmod(fileno(f), 0644);
-
- fprintf(f,
- "# This is private data. Do not parse.\n"
- "UID=%lu\n"
- "USER=%s\n"
- "ACTIVE=%i\n"
- "STATE=%s\n"
- "REMOTE=%i\n"
- "KILL_PROCESSES=%i\n",
- (unsigned long) s->user->uid,
- s->user->name,
- session_is_active(s),
- session_state_to_string(session_get_state(s)),
- s->remote,
- s->kill_processes);
-
- if (s->type >= 0)
- fprintf(f,
- "TYPE=%s\n",
- session_type_to_string(s->type));
-
- if (s->class >= 0)
- fprintf(f,
- "CLASS=%s\n",
- session_class_to_string(s->class));
-
- if (s->cgroup_path)
- fprintf(f,
- "CGROUP=%s\n",
- s->cgroup_path);
-
- if (s->fifo_path)
- fprintf(f,
- "FIFO=%s\n",
- s->fifo_path);
-
- if (s->seat)
- fprintf(f,
- "SEAT=%s\n",
- s->seat->id);
-
- if (s->tty)
- fprintf(f,
- "TTY=%s\n",
- s->tty);
-
- if (s->display)
- fprintf(f,
- "DISPLAY=%s\n",
- s->display);
-
- if (s->remote_host)
- fprintf(f,
- "REMOTE_HOST=%s\n",
- s->remote_host);
-
- if (s->remote_user)
- fprintf(f,
- "REMOTE_USER=%s\n",
- s->remote_user);
-
- if (s->service)
- fprintf(f,
- "SERVICE=%s\n",
- s->service);
-
- if (s->seat && seat_can_multi_session(s->seat))
- fprintf(f,
- "VTNR=%i\n",
- s->vtnr);
-
- if (s->leader > 0)
- fprintf(f,
- "LEADER=%lu\n",
- (unsigned long) s->leader);
-
- if (s->audit_id > 0)
- fprintf(f,
- "AUDIT=%llu\n",
- (unsigned long long) s->audit_id);
-
- fflush(f);
-
- if (ferror(f) || rename(temp_path, s->state_file) < 0) {
- r = -errno;
- unlink(s->state_file);
- unlink(temp_path);
- }
-
- fclose(f);
- free(temp_path);
-
-finish:
- if (r < 0)
- log_error("Failed to save session data for %s: %s", s->id, strerror(-r));
-
- return r;
-}
-
-int session_load(Session *s) {
- char *remote = NULL,
- *kill_processes = NULL,
- *seat = NULL,
- *vtnr = NULL,
- *leader = NULL,
- *audit_id = NULL,
- *type = NULL,
- *class = NULL;
-
- int k, r;
-
- assert(s);
-
- r = parse_env_file(s->state_file, NEWLINE,
- "REMOTE", &remote,
- "KILL_PROCESSES", &kill_processes,
- "CGROUP", &s->cgroup_path,
- "FIFO", &s->fifo_path,
- "SEAT", &seat,
- "TTY", &s->tty,
- "DISPLAY", &s->display,
- "REMOTE_HOST", &s->remote_host,
- "REMOTE_USER", &s->remote_user,
- "SERVICE", &s->service,
- "VTNR", &vtnr,
- "LEADER", &leader,
- "TYPE", &type,
- "CLASS", &class,
- NULL);
-
- if (r < 0)
- goto finish;
-
- if (remote) {
- k = parse_boolean(remote);
- if (k >= 0)
- s->remote = k;
- }
-
- if (kill_processes) {
- k = parse_boolean(kill_processes);
- if (k >= 0)
- s->kill_processes = k;
- }
-
- if (seat && !s->seat) {
- Seat *o;
-
- o = hashmap_get(s->manager->seats, seat);
- if (o)
- seat_attach_session(o, s);
- }
-
- if (vtnr && s->seat && seat_can_multi_session(s->seat)) {
- int v;
-
- k = safe_atoi(vtnr, &v);
- if (k >= 0 && v >= 1)
- s->vtnr = v;
- }
-
- if (leader) {
- k = parse_pid(leader, &s->leader);
- if (k >= 0)
- audit_session_from_pid(s->leader, &s->audit_id);
- }
-
- if (type) {
- SessionType t;
-
- t = session_type_from_string(type);
- if (t >= 0)
- s->type = t;
- }
-
- if (class) {
- SessionClass c;
-
- c = session_class_from_string(class);
- if (c >= 0)
- s->class = c;
- }
-
- if (s->fifo_path) {
- int fd;
-
- /* If we open an unopened pipe for reading we will not
- get an EOF. to trigger an EOF we hence open it for
- reading, but close it right-away which then will
- trigger the EOF. */
-
- fd = session_create_fifo(s);
- if (fd >= 0)
- close_nointr_nofail(fd);
- }
-
-finish:
- free(remote);
- free(kill_processes);
- free(seat);
- free(vtnr);
- free(leader);
- free(audit_id);
- free(class);
-
- return r;
-}
-
-int session_activate(Session *s) {
- int r;
-
- assert(s);
-
- if (s->vtnr < 0)
- return -ENOTSUP;
-
- if (!s->seat)
- return -ENOTSUP;
-
- if (s->seat->active == s)
- return 0;
-
- assert(seat_is_vtconsole(s->seat));
-
- r = chvt(s->vtnr);
- if (r < 0)
- return r;
-
- return seat_set_active(s->seat, s);
-}
-
-static int session_link_x11_socket(Session *s) {
- char *t, *f, *c;
- size_t k;
-
- assert(s);
- assert(s->user);
- assert(s->user->runtime_path);
-
- if (s->user->display)
- return 0;
-
- if (!s->display || !display_is_local(s->display))
- return 0;
-
- k = strspn(s->display+1, "0123456789");
- f = new(char, sizeof("/tmp/.X11-unix/X") + k);
- if (!f)
- return log_oom();
-
- c = stpcpy(f, "/tmp/.X11-unix/X");
- memcpy(c, s->display+1, k);
- c[k] = 0;
-
- if (access(f, F_OK) < 0) {
- log_warning("Session %s has display %s with non-existing socket %s.", s->id, s->display, f);
- free(f);
- return -ENOENT;
- }
-
- /* Note that this cannot be in a subdir to avoid
- * vulnerabilities since we are privileged but the runtime
- * path is owned by the user */
-
- t = strappend(s->user->runtime_path, "/X11-display");
- if (!t) {
- free(f);
- return log_oom();
- }
-
- if (link(f, t) < 0) {
- if (errno == EEXIST) {
- unlink(t);
-
- if (link(f, t) >= 0)
- goto done;
- }
-
- if (symlink(f, t) < 0) {
-
- if (errno == EEXIST) {
- unlink(t);
-
- if (symlink(f, t) >= 0)
- goto done;
- }
-
- log_error("Failed to link %s to %s: %m", f, t);
- free(f);
- free(t);
- return -errno;
- }
- }
-
-done:
- log_info("Linked %s to %s.", f, t);
- free(f);
- free(t);
-
- s->user->display = s;
-
- return 0;
-}
-
-static int session_create_one_group(Session *s, const char *controller, const char *path) {
- int r;
-
- assert(s);
- assert(controller);
- assert(path);
-
- if (s->leader > 0) {
- r = cg_create_and_attach(controller, path, s->leader);
- if (r < 0)
- r = cg_create(controller, path);
- } else
- r = cg_create(controller, path);
-
- if (r < 0)
- return r;
-
- r = cg_set_task_access(controller, path, 0644, s->user->uid, s->user->gid, -1);
- if (r >= 0)
- r = cg_set_group_access(controller, path, 0755, s->user->uid, s->user->gid);
-
- return r;
-}
-
-static int session_create_cgroup(Session *s) {
- char **k;
- char *p;
- int r;
-
- assert(s);
- assert(s->user);
- assert(s->user->cgroup_path);
-
- if (!s->cgroup_path) {
- if (asprintf(&p, "%s/%s", s->user->cgroup_path, s->id) < 0)
- return log_oom();
- } else
- p = s->cgroup_path;
-
- r = session_create_one_group(s, SYSTEMD_CGROUP_CONTROLLER, p);
- if (r < 0) {
- log_error("Failed to create "SYSTEMD_CGROUP_CONTROLLER":%s: %s", p, strerror(-r));
- free(p);
- s->cgroup_path = NULL;
- return r;
- }
-
- s->cgroup_path = p;
-
- STRV_FOREACH(k, s->controllers) {
-
- if (strv_contains(s->reset_controllers, *k))
- continue;
-
- r = session_create_one_group(s, *k, p);
- if (r < 0)
- log_warning("Failed to create %s:%s: %s", *k, p, strerror(-r));
- }
-
- STRV_FOREACH(k, s->manager->controllers) {
-
- if (strv_contains(s->reset_controllers, *k) ||
- strv_contains(s->manager->reset_controllers, *k) ||
- strv_contains(s->controllers, *k))
- continue;
-
- r = session_create_one_group(s, *k, p);
- if (r < 0)
- log_warning("Failed to create %s:%s: %s", *k, p, strerror(-r));
- }
-
- if (s->leader > 0) {
-
- STRV_FOREACH(k, s->reset_controllers) {
- r = cg_attach(*k, "/", s->leader);
- if (r < 0)
- log_warning("Failed to reset controller %s: %s", *k, strerror(-r));
-
- }
-
- STRV_FOREACH(k, s->manager->reset_controllers) {
-
- if (strv_contains(s->reset_controllers, *k) ||
- strv_contains(s->controllers, *k))
- continue;
-
- r = cg_attach(*k, "/", s->leader);
- if (r < 0)
- log_warning("Failed to reset controller %s: %s", *k, strerror(-r));
-
- }
- }
-
- r = hashmap_put(s->manager->session_cgroups, s->cgroup_path, s);
- if (r < 0)
- log_warning("Failed to create mapping between cgroup and session");
-
- return 0;
-}
-
-int session_start(Session *s) {
- int r;
-
- assert(s);
- assert(s->user);
-
- if (s->started)
- return 0;
-
- r = user_start(s->user);
- if (r < 0)
- return r;
-
- log_struct(s->type == SESSION_TTY || s->type == SESSION_X11 ? LOG_INFO : LOG_DEBUG,
- MESSAGE_ID(SD_MESSAGE_SESSION_START),
- "SESSION_ID=%s", s->id,
- "USER_ID=%s", s->user->name,
- "LEADER=%lu", (unsigned long) s->leader,
- "MESSAGE=New session %s of user %s.", s->id, s->user->name,
- NULL);
-
- /* Create cgroup */
- r = session_create_cgroup(s);
- if (r < 0)
- return r;
-
- /* Create X11 symlink */
- session_link_x11_socket(s);
-
- dual_timestamp_get(&s->timestamp);
-
- if (s->seat)
- seat_read_active_vt(s->seat);
-
- s->started = true;
-
- /* Save session data */
- session_save(s);
- user_save(s->user);
-
- session_send_signal(s, true);
-
- if (s->seat) {
- seat_save(s->seat);
-
- if (s->seat->active == s)
- seat_send_changed(s->seat, "Sessions\0ActiveSession\0");
- else
- seat_send_changed(s->seat, "Sessions\0");
- }
-
- user_send_changed(s->user, "Sessions\0");
-
- return 0;
-}
-
-static bool session_shall_kill(Session *s) {
- assert(s);
-
- if (!s->kill_processes)
- return false;
-
- if (strv_contains(s->manager->kill_exclude_users, s->user->name))
- return false;
-
- if (strv_isempty(s->manager->kill_only_users))
- return true;
-
- return strv_contains(s->manager->kill_only_users, s->user->name);
-}
-
-static int session_terminate_cgroup(Session *s) {
- int r;
- char **k;
-
- assert(s);
-
- if (!s->cgroup_path)
- return 0;
-
- cg_trim(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, false);
-
- if (session_shall_kill(s)) {
-
- r = cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, true);
- if (r < 0)
- log_error("Failed to kill session cgroup: %s", strerror(-r));
-
- } else {
- if (s->leader > 0) {
- Session *t;
-
- /* We still send a HUP to the leader process,
- * even if we are not supposed to kill the
- * whole cgroup. But let's first check the
- * leader still exists and belongs to our
- * session... */
-
- r = manager_get_session_by_pid(s->manager, s->leader, &t);
- if (r > 0 && t == s) {
- kill(s->leader, SIGTERM); /* for normal processes */
- kill(s->leader, SIGHUP); /* for shells */
- kill(s->leader, SIGCONT); /* in case they are stopped */
- }
- }
-
- r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, true);
- if (r < 0)
- log_error("Failed to check session cgroup: %s", strerror(-r));
- else if (r > 0) {
- r = cg_delete(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path);
- if (r < 0)
- log_error("Failed to delete session cgroup: %s", strerror(-r));
- }
- }
-
- STRV_FOREACH(k, s->user->manager->controllers)
- cg_trim(*k, s->cgroup_path, true);
-
- hashmap_remove(s->manager->session_cgroups, s->cgroup_path);
-
- free(s->cgroup_path);
- s->cgroup_path = NULL;
-
- return 0;
-}
-
-static int session_unlink_x11_socket(Session *s) {
- char *t;
- int r;
-
- assert(s);
- assert(s->user);
-
- if (s->user->display != s)
- return 0;
-
- s->user->display = NULL;
-
- t = strappend(s->user->runtime_path, "/X11-display");
- if (!t)
- return log_oom();
-
- r = unlink(t);
- free(t);
-
- return r < 0 ? -errno : 0;
-}
-
-int session_stop(Session *s) {
- int r = 0, k;
-
- assert(s);
-
- if (s->started)
- log_struct(s->type == SESSION_TTY || s->type == SESSION_X11 ? LOG_INFO : LOG_DEBUG,
- MESSAGE_ID(SD_MESSAGE_SESSION_STOP),
- "SESSION_ID=%s", s->id,
- "USER_ID=%s", s->user->name,
- "LEADER=%lu", (unsigned long) s->leader,
- "MESSAGE=Removed session %s.", s->id,
- NULL);
-
- /* Kill cgroup */
- k = session_terminate_cgroup(s);
- if (k < 0)
- r = k;
-
- /* Remove X11 symlink */
- session_unlink_x11_socket(s);
-
- unlink(s->state_file);
- session_add_to_gc_queue(s);
- user_add_to_gc_queue(s->user);
-
- if (s->started)
- session_send_signal(s, false);
-
- if (s->seat) {
- if (s->seat->active == s)
- seat_set_active(s->seat, NULL);
-
- seat_send_changed(s->seat, "Sessions\0");
- seat_save(s->seat);
- }
-
- user_send_changed(s->user, "Sessions\0");
- user_save(s->user);
-
- s->started = false;
-
- return r;
-}
-
-bool session_is_active(Session *s) {
- assert(s);
-
- if (!s->seat)
- return true;
-
- return s->seat->active == s;
-}
-
-int session_get_idle_hint(Session *s, dual_timestamp *t) {
- char *p;
- struct stat st;
- usec_t u, n;
- int k;
-
- assert(s);
-
- if (s->idle_hint) {
- if (t)
- *t = s->idle_hint_timestamp;
-
- return s->idle_hint;
- }
-
- if (isempty(s->tty))
- goto dont_know;
-
- if (s->tty[0] != '/') {
- p = strappend("/dev/", s->tty);
- if (!p)
- return -ENOMEM;
- } else
- p = NULL;
-
- if (!startswith(p ? p : s->tty, "/dev/")) {
- free(p);
- goto dont_know;
- }
-
- k = lstat(p ? p : s->tty, &st);
- free(p);
-
- if (k < 0)
- goto dont_know;
-
- u = timespec_load(&st.st_atim);
- n = now(CLOCK_REALTIME);
-
- if (t)
- dual_timestamp_from_realtime(t, u);
-
- return u + IDLE_THRESHOLD_USEC < n;
-
-dont_know:
- if (t)
- *t = s->idle_hint_timestamp;
-
- return 0;
-}
-
-void session_set_idle_hint(Session *s, bool b) {
- assert(s);
-
- if (s->idle_hint == b)
- return;
-
- s->idle_hint = b;
- dual_timestamp_get(&s->idle_hint_timestamp);
-
- session_send_changed(s,
- "IdleHint\0"
- "IdleSinceHint\0"
- "IdleSinceHintMonotonic\0");
-
- if (s->seat)
- seat_send_changed(s->seat,
- "IdleHint\0"
- "IdleSinceHint\0"
- "IdleSinceHintMonotonic\0");
-
- user_send_changed(s->user,
- "IdleHint\0"
- "IdleSinceHint\0"
- "IdleSinceHintMonotonic\0");
-
- manager_send_changed(s->manager,
- "IdleHint\0"
- "IdleSinceHint\0"
- "IdleSinceHintMonotonic\0");
-}
-
-int session_create_fifo(Session *s) {
- int r;
-
- assert(s);
-
- /* Create FIFO */
- if (!s->fifo_path) {
- r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
- if (r < 0)
- return r;
-
- if (asprintf(&s->fifo_path, "/run/systemd/sessions/%s.ref", s->id) < 0)
- return -ENOMEM;
-
- if (mkfifo(s->fifo_path, 0600) < 0 && errno != EEXIST)
- return -errno;
- }
-
- /* Open reading side */
- if (s->fifo_fd < 0) {
- struct epoll_event ev;
-
- s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NDELAY);
- if (s->fifo_fd < 0)
- return -errno;
-
- r = hashmap_put(s->manager->session_fds, INT_TO_PTR(s->fifo_fd + 1), s);
- if (r < 0)
- return r;
-
- zero(ev);
- ev.events = 0;
- ev.data.u32 = FD_OTHER_BASE + s->fifo_fd;
-
- if (epoll_ctl(s->manager->epoll_fd, EPOLL_CTL_ADD, s->fifo_fd, &ev) < 0)
- return -errno;
- }
-
- /* Open writing side */
- r = open(s->fifo_path, O_WRONLY|O_CLOEXEC|O_NDELAY);
- if (r < 0)
- return -errno;
-
- return r;
-}
-
-void session_remove_fifo(Session *s) {
- assert(s);
-
- if (s->fifo_fd >= 0) {
- assert_se(hashmap_remove(s->manager->session_fds, INT_TO_PTR(s->fifo_fd + 1)) == s);
- assert_se(epoll_ctl(s->manager->epoll_fd, EPOLL_CTL_DEL, s->fifo_fd, NULL) == 0);
- close_nointr_nofail(s->fifo_fd);
- s->fifo_fd = -1;
-
- session_save(s);
- user_save(s->user);
- }
-
- if (s->fifo_path) {
- unlink(s->fifo_path);
- free(s->fifo_path);
- s->fifo_path = NULL;
- }
-}
-
-int session_check_gc(Session *s, bool drop_not_started) {
- int r;
-
- assert(s);
-
- if (drop_not_started && !s->started)
- return 0;
-
- if (s->fifo_fd >= 0) {
-
- r = pipe_eof(s->fifo_fd);
- if (r < 0)
- return r;
-
- if (r == 0)
- return 1;
- }
-
- if (s->cgroup_path) {
-
- r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, false);
- if (r < 0)
- return r;
-
- if (r <= 0)
- return 1;
- }
-
- return 0;
-}
-
-void session_add_to_gc_queue(Session *s) {
- assert(s);
-
- if (s->in_gc_queue)
- return;
-
- LIST_PREPEND(Session, gc_queue, s->manager->session_gc_queue, s);
- s->in_gc_queue = true;
-}
-
-SessionState session_get_state(Session *s) {
- assert(s);
-
- if (s->fifo_fd < 0)
- return SESSION_CLOSING;
-
- if (session_is_active(s))
- return SESSION_ACTIVE;
-
- return SESSION_ONLINE;
-}
-
-int session_kill(Session *s, KillWho who, int signo) {
- int r = 0;
- Set *pid_set = NULL;
-
- assert(s);
-
- if (!s->cgroup_path)
- return -ESRCH;
-
- if (s->leader <= 0 && who == KILL_LEADER)
- return -ESRCH;
-
- if (s->leader > 0)
- if (kill(s->leader, signo) < 0)
- r = -errno;
-
- if (who == KILL_ALL) {
- int q;
-
- pid_set = set_new(trivial_hash_func, trivial_compare_func);
- if (!pid_set)
- return -ENOMEM;
-
- if (s->leader > 0) {
- q = set_put(pid_set, LONG_TO_PTR(s->leader));
- if (q < 0)
- r = q;
- }
-
- q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, signo, false, true, false, pid_set);
- if (q < 0)
- if (q != -EAGAIN && q != -ESRCH && q != -ENOENT)
- r = q;
- }
-
- if (pid_set)
- set_free(pid_set);
-
- return r;
-}
-
-static const char* const session_state_table[_SESSION_TYPE_MAX] = {
- [SESSION_ONLINE] = "online",
- [SESSION_ACTIVE] = "active",
- [SESSION_CLOSING] = "closing"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState);
-
-static const char* const session_type_table[_SESSION_TYPE_MAX] = {
- [SESSION_TTY] = "tty",
- [SESSION_X11] = "x11",
- [SESSION_UNSPECIFIED] = "unspecified"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
-
-static const char* const session_class_table[_SESSION_CLASS_MAX] = {
- [SESSION_USER] = "user",
- [SESSION_GREETER] = "greeter",
- [SESSION_LOCK_SCREEN] = "lock-screen"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
-
-static const char* const kill_who_table[_KILL_WHO_MAX] = {
- [KILL_LEADER] = "leader",
- [KILL_ALL] = "all"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);
diff --git a/src/login/logind-session.h b/src/login/logind-session.h
deleted file mode 100644
index 7598afa618..0000000000
--- a/src/login/logind-session.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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/>.
-***/
-
-typedef struct Session Session;
-
-#include "list.h"
-#include "util.h"
-#include "logind.h"
-#include "logind-seat.h"
-#include "logind-user.h"
-
-typedef enum SessionState {
- SESSION_ONLINE, /* Logged in */
- SESSION_ACTIVE, /* Logged in and in the fg */
- SESSION_CLOSING, /* Logged out, but processes still remain */
- _SESSION_STATE_MAX,
- _SESSION_STATE_INVALID = -1
-} SessionState;
-
-typedef enum SessionType {
- SESSION_UNSPECIFIED,
- SESSION_TTY,
- SESSION_X11,
- _SESSION_TYPE_MAX,
- _SESSION_TYPE_INVALID = -1
-} SessionType;
-
-typedef enum SessionClass {
- SESSION_USER,
- SESSION_GREETER,
- SESSION_LOCK_SCREEN,
- _SESSION_CLASS_MAX,
- _SESSION_CLASS_INVALID = -1
-} SessionClass;
-
-typedef enum KillWho {
- KILL_LEADER,
- KILL_ALL,
- _KILL_WHO_MAX,
- _KILL_WHO_INVALID = -1
-} KillWho;
-
-struct Session {
- Manager *manager;
-
- char *id;
- SessionType type;
- SessionClass class;
-
- char *state_file;
-
- User *user;
-
- dual_timestamp timestamp;
-
- char *tty;
- char *display;
-
- bool remote;
- char *remote_user;
- char *remote_host;
-
- char *service;
-
- int vtnr;
- Seat *seat;
-
- pid_t leader;
- uint32_t audit_id;
-
- int fifo_fd;
- char *fifo_path;
-
- char *cgroup_path;
- char **controllers, **reset_controllers;
-
- bool idle_hint;
- dual_timestamp idle_hint_timestamp;
-
- bool kill_processes;
- bool in_gc_queue:1;
- bool started:1;
-
- LIST_FIELDS(Session, sessions_by_user);
- LIST_FIELDS(Session, sessions_by_seat);
-
- LIST_FIELDS(Session, gc_queue);
-};
-
-Session *session_new(Manager *m, User *u, const char *id);
-void session_free(Session *s);
-int session_check_gc(Session *s, bool drop_not_started);
-void session_add_to_gc_queue(Session *s);
-int session_activate(Session *s);
-bool session_is_active(Session *s);
-int session_get_idle_hint(Session *s, dual_timestamp *t);
-void session_set_idle_hint(Session *s, bool b);
-int session_create_fifo(Session *s);
-void session_remove_fifo(Session *s);
-int session_start(Session *s);
-int session_stop(Session *s);
-int session_save(Session *s);
-int session_load(Session *s);
-int session_kill(Session *s, KillWho who, int signo);
-
-char *session_bus_path(Session *s);
-
-SessionState session_get_state(Session *u);
-
-extern const DBusObjectPathVTable bus_session_vtable;
-
-int session_send_signal(Session *s, bool new_session);
-int session_send_changed(Session *s, const char *properties);
-int session_send_lock(Session *s, bool lock);
-int session_send_lock_all(Manager *m, bool lock);
-
-const char* session_state_to_string(SessionState t);
-SessionState session_state_from_string(const char *s);
-
-const char* session_type_to_string(SessionType t);
-SessionType session_type_from_string(const char *s);
-
-const char* session_class_to_string(SessionClass t);
-SessionClass session_class_from_string(const char *s);
-
-const char *kill_who_to_string(KillWho k);
-KillWho kill_who_from_string(const char *s);
diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c
deleted file mode 100644
index ddf9d9d5cf..0000000000
--- a/src/login/logind-user-dbus.c
+++ /dev/null
@@ -1,437 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <errno.h>
-#include <string.h>
-
-#include "logind.h"
-#include "logind-user.h"
-#include "dbus-common.h"
-
-#define BUS_USER_INTERFACE \
- " <interface name=\"org.freedesktop.login1.User\">\n" \
- " <method name=\"Terminate\"/>\n" \
- " <method name=\"Kill\">\n" \
- " <arg name=\"signal\" type=\"s\"/>\n" \
- " </method>\n" \
- " <property name=\"UID\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"GID\" type=\"u\" access=\"read\"/>\n" \
- " <property name=\"Name\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Timestamp\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"TimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"RuntimePath\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"DefaultControlGroup\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Service\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Display\" type=\"(so)\" access=\"read\"/>\n" \
- " <property name=\"State\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Sessions\" type=\"a(so)\" access=\"read\"/>\n" \
- " <property name=\"IdleHint\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"IdleSinceHint\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"IdleSinceHintMonotonic\" type=\"t\" access=\"read\"/>\n" \
- " </interface>\n" \
-
-#define INTROSPECTION \
- DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
- "<node>\n" \
- BUS_USER_INTERFACE \
- BUS_PROPERTIES_INTERFACE \
- BUS_PEER_INTERFACE \
- BUS_INTROSPECTABLE_INTERFACE \
- "</node>\n"
-
-#define INTERFACES_LIST \
- BUS_GENERIC_INTERFACES_LIST \
- "org.freedesktop.login1.User\0"
-
-static int bus_user_append_display(DBusMessageIter *i, const char *property, void *data) {
- DBusMessageIter sub;
- User *u = data;
- const char *id, *path;
- char *p = NULL;
-
- assert(i);
- assert(property);
- assert(u);
-
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub))
- return -ENOMEM;
-
- if (u->display) {
- id = u->display->id;
- path = p = session_bus_path(u->display);
-
- if (!p)
- return -ENOMEM;
- } else {
- id = "";
- path = "/";
- }
-
- if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &id) ||
- !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &path)) {
- free(p);
- return -ENOMEM;
- }
-
- free(p);
-
- if (!dbus_message_iter_close_container(i, &sub))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_user_append_state(DBusMessageIter *i, const char *property, void *data) {
- User *u = data;
- const char *state;
-
- assert(i);
- assert(property);
- assert(u);
-
- state = user_state_to_string(user_get_state(u));
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &state))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_user_append_sessions(DBusMessageIter *i, const char *property, void *data) {
- DBusMessageIter sub, sub2;
- User *u = data;
- Session *session;
-
- assert(i);
- assert(property);
- assert(u);
-
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(so)", &sub))
- return -ENOMEM;
-
- LIST_FOREACH(sessions_by_user, session, u->sessions) {
- char *p;
-
- if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
- return -ENOMEM;
-
- p = session_bus_path(session);
- if (!p)
- return -ENOMEM;
-
- if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &session->id) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &p)) {
- free(p);
- return -ENOMEM;
- }
-
- free(p);
-
- if (!dbus_message_iter_close_container(&sub, &sub2))
- return -ENOMEM;
- }
-
- if (!dbus_message_iter_close_container(i, &sub))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_user_append_idle_hint(DBusMessageIter *i, const char *property, void *data) {
- User *u = data;
- dbus_bool_t b;
-
- assert(i);
- assert(property);
- assert(u);
-
- b = user_get_idle_hint(u, NULL) > 0;
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_user_append_idle_hint_since(DBusMessageIter *i, const char *property, void *data) {
- User *u = data;
- dual_timestamp t;
- uint64_t k;
-
- assert(i);
- assert(property);
- assert(u);
-
- user_get_idle_hint(u, &t);
- k = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &k))
- return -ENOMEM;
-
- return 0;
-}
-
-static int bus_user_append_default_cgroup(DBusMessageIter *i, const char *property, void *data) {
- User *u = data;
- char *t;
- int r;
- bool success;
-
- assert(i);
- assert(property);
- assert(u);
-
- r = cg_join_spec(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &t);
- if (r < 0)
- return r;
-
- success = dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t);
- free(t);
-
- return success ? 0 : -ENOMEM;
-}
-
-static int get_user_for_path(Manager *m, const char *path, User **_u) {
- User *u;
- unsigned long lu;
- int r;
-
- assert(m);
- assert(path);
- assert(_u);
-
- if (!startswith(path, "/org/freedesktop/login1/user/"))
- return -EINVAL;
-
- r = safe_atolu(path + 29, &lu);
- if (r < 0)
- return r;
-
- u = hashmap_get(m->users, ULONG_TO_PTR(lu));
- if (!u)
- return -ENOENT;
-
- *_u = u;
- return 0;
-}
-
-static const BusProperty bus_login_user_properties[] = {
- { "UID", bus_property_append_uid, "u", offsetof(User, uid) },
- { "GID", bus_property_append_gid, "u", offsetof(User, gid) },
- { "Name", bus_property_append_string, "s", offsetof(User, name), true },
- { "Timestamp", bus_property_append_usec, "t", offsetof(User, timestamp.realtime) },
- { "TimestampMonotonic", bus_property_append_usec, "t", offsetof(User, timestamp.monotonic) },
- { "RuntimePath", bus_property_append_string, "s", offsetof(User, runtime_path), true },
- { "DefaultControlGroup", bus_user_append_default_cgroup, "s", 0 },
- { "Service", bus_property_append_string, "s", offsetof(User, service), true },
- { "Display", bus_user_append_display, "(so)", 0 },
- { "State", bus_user_append_state, "s", 0 },
- { "Sessions", bus_user_append_sessions, "a(so)", 0 },
- { "IdleHint", bus_user_append_idle_hint, "b", 0 },
- { "IdleSinceHint", bus_user_append_idle_hint_since, "t", 0 },
- { "IdleSinceHintMonotonic", bus_user_append_idle_hint_since, "t", 0 },
- { NULL, }
-};
-
-static DBusHandlerResult user_message_dispatch(
- User *u,
- DBusConnection *connection,
- DBusMessage *message) {
-
- DBusError error;
- DBusMessage *reply = NULL;
- int r;
-
- assert(u);
- assert(connection);
- assert(message);
-
- if (dbus_message_is_method_call(message, "org.freedesktop.login1.User", "Terminate")) {
-
- r = user_stop(u);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
- } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.User", "Kill")) {
- int32_t signo;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_INT32, &signo,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- if (signo <= 0 || signo >= _NSIG)
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- r = user_kill(u, signo);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else {
- const BusBoundProperties bps[] = {
- { "org.freedesktop.login1.User", bus_login_user_properties, u },
- { NULL, }
- };
-
- return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps);
- }
-
- if (reply) {
- if (!dbus_connection_send(connection, reply, NULL))
- goto oom;
-
- dbus_message_unref(reply);
- }
-
- return DBUS_HANDLER_RESULT_HANDLED;
-
-oom:
- if (reply)
- dbus_message_unref(reply);
-
- dbus_error_free(&error);
-
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-}
-
-static DBusHandlerResult user_message_handler(
- DBusConnection *connection,
- DBusMessage *message,
- void *userdata) {
-
- Manager *m = userdata;
- User *u;
- int r;
-
- r = get_user_for_path(m, dbus_message_get_path(message), &u);
- if (r < 0) {
-
- if (r == -ENOMEM)
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
- if (r == -ENOENT) {
- DBusError e;
-
- dbus_error_init(&e);
- dbus_set_error_const(&e, DBUS_ERROR_UNKNOWN_OBJECT, "Unknown user");
- return bus_send_error_reply(connection, message, &e, r);
- }
-
- return bus_send_error_reply(connection, message, NULL, r);
- }
-
- return user_message_dispatch(u, connection, message);
-}
-
-const DBusObjectPathVTable bus_user_vtable = {
- .message_function = user_message_handler
-};
-
-char *user_bus_path(User *u) {
- char *s;
-
- assert(u);
-
- if (asprintf(&s, "/org/freedesktop/login1/user/%llu", (unsigned long long) u->uid) < 0)
- return NULL;
-
- return s;
-}
-
-int user_send_signal(User *u, bool new_user) {
- DBusMessage *m;
- int r = -ENOMEM;
- char *p = NULL;
- uint32_t uid;
-
- assert(u);
-
- m = dbus_message_new_signal("/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- new_user ? "UserNew" : "UserRemoved");
-
- if (!m)
- return -ENOMEM;
-
- p = user_bus_path(u);
- if (!p)
- goto finish;
-
- uid = u->uid;
-
- if (!dbus_message_append_args(
- m,
- DBUS_TYPE_UINT32, &uid,
- DBUS_TYPE_OBJECT_PATH, &p,
- DBUS_TYPE_INVALID))
- goto finish;
-
- if (!dbus_connection_send(u->manager->bus, m, NULL))
- goto finish;
-
- r = 0;
-
-finish:
- dbus_message_unref(m);
- free(p);
-
- return r;
-}
-
-int user_send_changed(User *u, const char *properties) {
- DBusMessage *m;
- int r = -ENOMEM;
- char *p = NULL;
-
- assert(u);
-
- if (!u->started)
- return 0;
-
- p = user_bus_path(u);
- if (!p)
- return -ENOMEM;
-
- m = bus_properties_changed_new(p, "org.freedesktop.login1.User", properties);
- if (!m)
- goto finish;
-
- if (!dbus_connection_send(u->manager->bus, m, NULL))
- goto finish;
-
- r = 0;
-
-finish:
- if (m)
- dbus_message_unref(m);
- free(p);
-
- return r;
-}
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
deleted file mode 100644
index b692b533e2..0000000000
--- a/src/login/logind-user.c
+++ /dev/null
@@ -1,656 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <unistd.h>
-#include <errno.h>
-
-#include "logind-user.h"
-#include "util.h"
-#include "mkdir.h"
-#include "cgroup-util.h"
-#include "hashmap.h"
-#include "strv.h"
-
-User* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) {
- User *u;
-
- assert(m);
- assert(name);
-
- u = new0(User, 1);
- if (!u)
- return NULL;
-
- u->name = strdup(name);
- if (!u->name) {
- free(u);
- return NULL;
- }
-
- if (asprintf(&u->state_file, "/run/systemd/users/%lu", (unsigned long) uid) < 0) {
- free(u->name);
- free(u);
- return NULL;
- }
-
- if (hashmap_put(m->users, ULONG_TO_PTR((unsigned long) uid), u) < 0) {
- free(u->state_file);
- free(u->name);
- free(u);
- return NULL;
- }
-
- u->manager = m;
- u->uid = uid;
- u->gid = gid;
-
- return u;
-}
-
-void user_free(User *u) {
- assert(u);
-
- if (u->in_gc_queue)
- LIST_REMOVE(User, gc_queue, u->manager->user_gc_queue, u);
-
- while (u->sessions)
- session_free(u->sessions);
-
- if (u->cgroup_path)
- hashmap_remove(u->manager->user_cgroups, u->cgroup_path);
- free(u->cgroup_path);
-
- free(u->service);
- free(u->runtime_path);
-
- hashmap_remove(u->manager->users, ULONG_TO_PTR((unsigned long) u->uid));
-
- free(u->name);
- free(u->state_file);
- free(u);
-}
-
-int user_save(User *u) {
- FILE *f;
- int r;
- char *temp_path;
-
- assert(u);
- assert(u->state_file);
-
- if (!u->started)
- return 0;
-
- r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0);
- if (r < 0)
- goto finish;
-
- r = fopen_temporary(u->state_file, &f, &temp_path);
- if (r < 0)
- goto finish;
-
- fchmod(fileno(f), 0644);
-
- fprintf(f,
- "# This is private data. Do not parse.\n"
- "NAME=%s\n"
- "STATE=%s\n",
- u->name,
- user_state_to_string(user_get_state(u)));
-
- if (u->cgroup_path)
- fprintf(f,
- "CGROUP=%s\n",
- u->cgroup_path);
-
- if (u->runtime_path)
- fprintf(f,
- "RUNTIME=%s\n",
- u->runtime_path);
-
- if (u->service)
- fprintf(f,
- "SERVICE=%s\n",
- u->service);
-
- if (u->display)
- fprintf(f,
- "DISPLAY=%s\n",
- u->display->id);
-
- if (u->sessions) {
- Session *i;
- bool first;
-
- fputs("SESSIONS=", f);
- first = true;
- LIST_FOREACH(sessions_by_user, i, u->sessions) {
- if (first)
- first = false;
- else
- fputc(' ', f);
-
- fputs(i->id, f);
- }
-
- fputs("\nSEATS=", f);
- first = true;
- LIST_FOREACH(sessions_by_user, i, u->sessions) {
- if (!i->seat)
- continue;
-
- if (first)
- first = false;
- else
- fputc(' ', f);
-
- fputs(i->seat->id, f);
- }
-
- fputs("\nACTIVE_SESSIONS=", f);
- first = true;
- LIST_FOREACH(sessions_by_user, i, u->sessions) {
- if (!session_is_active(i))
- continue;
-
- if (first)
- first = false;
- else
- fputc(' ', f);
-
- fputs(i->id, f);
- }
-
- fputs("\nONLINE_SESSIONS=", f);
- first = true;
- LIST_FOREACH(sessions_by_user, i, u->sessions) {
- if (session_get_state(i) == SESSION_CLOSING)
- continue;
-
- if (first)
- first = false;
- else
- fputc(' ', f);
-
- fputs(i->id, f);
- }
-
- fputs("\nACTIVE_SEATS=", f);
- first = true;
- LIST_FOREACH(sessions_by_user, i, u->sessions) {
- if (!session_is_active(i) || !i->seat)
- continue;
-
- if (first)
- first = false;
- else
- fputc(' ', f);
-
- fputs(i->seat->id, f);
- }
-
- fputs("\nONLINE_SEATS=", f);
- first = true;
- LIST_FOREACH(sessions_by_user, i, u->sessions) {
- if (session_get_state(i) == SESSION_CLOSING || !i->seat)
- continue;
-
- if (first)
- first = false;
- else
- fputc(' ', f);
-
- fputs(i->seat->id, f);
- }
- fputc('\n', f);
- }
-
- fflush(f);
-
- if (ferror(f) || rename(temp_path, u->state_file) < 0) {
- r = -errno;
- unlink(u->state_file);
- unlink(temp_path);
- }
-
- fclose(f);
- free(temp_path);
-
-finish:
- if (r < 0)
- log_error("Failed to save user data for %s: %s", u->name, strerror(-r));
-
- return r;
-}
-
-int user_load(User *u) {
- int r;
- char *display = NULL;
- Session *s = NULL;
-
- assert(u);
-
- r = parse_env_file(u->state_file, NEWLINE,
- "CGROUP", &u->cgroup_path,
- "RUNTIME", &u->runtime_path,
- "SERVICE", &u->service,
- "DISPLAY", &display,
- NULL);
- if (r < 0) {
- free(display);
-
- if (r == -ENOENT)
- return 0;
-
- log_error("Failed to read %s: %s", u->state_file, strerror(-r));
- return r;
- }
-
- if (display) {
- s = hashmap_get(u->manager->sessions, display);
- free(display);
- }
-
- if (s && s->display && display_is_local(s->display))
- u->display = s;
-
- return r;
-}
-
-static int user_mkdir_runtime_path(User *u) {
- char *p;
- int r;
-
- assert(u);
-
- r = mkdir_safe_label("/run/user", 0755, 0, 0);
- if (r < 0) {
- log_error("Failed to create /run/user: %s", strerror(-r));
- return r;
- }
-
- if (!u->runtime_path) {
- if (asprintf(&p, "/run/user/%lu", (unsigned long) u->uid) < 0)
- return log_oom();
- } else
- p = u->runtime_path;
-
- r = mkdir_safe_label(p, 0700, u->uid, u->gid);
- if (r < 0) {
- log_error("Failed to create runtime directory %s: %s", p, strerror(-r));
- free(p);
- u->runtime_path = NULL;
- return r;
- }
-
- u->runtime_path = p;
- return 0;
-}
-
-static int user_create_cgroup(User *u) {
- char **k;
- char *p;
- int r;
-
- assert(u);
-
- if (!u->cgroup_path) {
- if (asprintf(&p, "%s/%s", u->manager->cgroup_path, u->name) < 0)
- return log_oom();
- } else
- p = u->cgroup_path;
-
- r = cg_create(SYSTEMD_CGROUP_CONTROLLER, p);
- if (r < 0) {
- log_error("Failed to create cgroup "SYSTEMD_CGROUP_CONTROLLER":%s: %s", p, strerror(-r));
- free(p);
- u->cgroup_path = NULL;
- return r;
- }
-
- u->cgroup_path = p;
-
- STRV_FOREACH(k, u->manager->controllers) {
-
- if (strv_contains(u->manager->reset_controllers, *k))
- continue;
-
- r = cg_create(*k, p);
- if (r < 0)
- log_warning("Failed to create cgroup %s:%s: %s", *k, p, strerror(-r));
- }
-
- r = hashmap_put(u->manager->user_cgroups, u->cgroup_path, u);
- if (r < 0)
- log_warning("Failed to create mapping between cgroup and user");
-
- return 0;
-}
-
-static int user_start_service(User *u) {
- assert(u);
-
- /* FIXME: Fill me in later ... */
-
- return 0;
-}
-
-int user_start(User *u) {
- int r;
-
- assert(u);
-
- if (u->started)
- return 0;
-
- log_debug("New user %s logged in.", u->name);
-
- /* Make XDG_RUNTIME_DIR */
- r = user_mkdir_runtime_path(u);
- if (r < 0)
- return r;
-
- /* Create cgroup */
- r = user_create_cgroup(u);
- if (r < 0)
- return r;
-
- /* Spawn user systemd */
- r = user_start_service(u);
- if (r < 0)
- return r;
-
- dual_timestamp_get(&u->timestamp);
-
- u->started = true;
-
- /* Save new user data */
- user_save(u);
-
- user_send_signal(u, true);
-
- return 0;
-}
-
-static int user_stop_service(User *u) {
- assert(u);
-
- if (!u->service)
- return 0;
-
- return 0;
-}
-
-static int user_shall_kill(User *u) {
- assert(u);
-
- if (!u->manager->kill_user_processes)
- return false;
-
- if (strv_contains(u->manager->kill_exclude_users, u->name))
- return false;
-
- if (strv_isempty(u->manager->kill_only_users))
- return true;
-
- return strv_contains(u->manager->kill_only_users, u->name);
-}
-
-static int user_terminate_cgroup(User *u) {
- int r;
- char **k;
-
- assert(u);
-
- if (!u->cgroup_path)
- return 0;
-
- cg_trim(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, false);
-
- if (user_shall_kill(u)) {
-
- r = cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
- if (r < 0)
- log_error("Failed to kill user cgroup: %s", strerror(-r));
- } else {
-
- r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
- if (r < 0)
- log_error("Failed to check user cgroup: %s", strerror(-r));
- else if (r > 0) {
- r = cg_delete(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path);
- if (r < 0)
- log_error("Failed to delete user cgroup: %s", strerror(-r));
- } else
- r = -EBUSY;
- }
-
- STRV_FOREACH(k, u->manager->controllers)
- cg_trim(*k, u->cgroup_path, true);
-
- hashmap_remove(u->manager->user_cgroups, u->cgroup_path);
-
- free(u->cgroup_path);
- u->cgroup_path = NULL;
-
- return r;
-}
-
-static int user_remove_runtime_path(User *u) {
- int r;
-
- assert(u);
-
- if (!u->runtime_path)
- return 0;
-
- r = rm_rf(u->runtime_path, false, true, false);
- if (r < 0)
- log_error("Failed to remove runtime directory %s: %s", u->runtime_path, strerror(-r));
-
- free(u->runtime_path);
- u->runtime_path = NULL;
-
- return r;
-}
-
-int user_stop(User *u) {
- Session *s;
- int r = 0, k;
- assert(u);
-
- if (u->started)
- log_debug("User %s logged out.", u->name);
-
- LIST_FOREACH(sessions_by_user, s, u->sessions) {
- k = session_stop(s);
- if (k < 0)
- r = k;
- }
-
- /* Kill systemd */
- k = user_stop_service(u);
- if (k < 0)
- r = k;
-
- /* Kill cgroup */
- k = user_terminate_cgroup(u);
- if (k < 0)
- r = k;
-
- /* Kill XDG_RUNTIME_DIR */
- k = user_remove_runtime_path(u);
- if (k < 0)
- r = k;
-
- unlink(u->state_file);
- user_add_to_gc_queue(u);
-
- if (u->started)
- user_send_signal(u, false);
-
- u->started = false;
-
- return r;
-}
-
-int user_get_idle_hint(User *u, dual_timestamp *t) {
- Session *s;
- bool idle_hint = true;
- dual_timestamp ts = { 0, 0 };
-
- assert(u);
-
- LIST_FOREACH(sessions_by_user, s, u->sessions) {
- dual_timestamp k;
- int ih;
-
- ih = session_get_idle_hint(s, &k);
- if (ih < 0)
- return ih;
-
- if (!ih) {
- if (!idle_hint) {
- if (k.monotonic < ts.monotonic)
- ts = k;
- } else {
- idle_hint = false;
- ts = k;
- }
- } else if (idle_hint) {
-
- if (k.monotonic > ts.monotonic)
- ts = k;
- }
- }
-
- if (t)
- *t = ts;
-
- return idle_hint;
-}
-
-static int user_check_linger_file(User *u) {
- char *p;
- int r;
-
- if (asprintf(&p, "/var/lib/systemd/linger/%s", u->name) < 0)
- return -ENOMEM;
-
- r = access(p, F_OK) >= 0;
- free(p);
-
- return r;
-}
-
-int user_check_gc(User *u, bool drop_not_started) {
- int r;
-
- assert(u);
-
- if (drop_not_started && !u->started)
- return 0;
-
- if (u->sessions)
- return 1;
-
- if (user_check_linger_file(u) > 0)
- return 1;
-
- if (u->cgroup_path) {
- r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, false);
- if (r < 0)
- return r;
-
- if (r <= 0)
- return 1;
- }
-
- return 0;
-}
-
-void user_add_to_gc_queue(User *u) {
- assert(u);
-
- if (u->in_gc_queue)
- return;
-
- LIST_PREPEND(User, gc_queue, u->manager->user_gc_queue, u);
- u->in_gc_queue = true;
-}
-
-UserState user_get_state(User *u) {
- Session *i;
- bool all_closing = true;
-
- assert(u);
-
-
- LIST_FOREACH(sessions_by_user, i, u->sessions) {
- if (session_is_active(i))
- return USER_ACTIVE;
- if (session_get_state(i) != SESSION_CLOSING)
- all_closing = false;
- }
-
- if (u->sessions)
- return all_closing ? USER_CLOSING : USER_ONLINE;
-
- if (user_check_linger_file(u) > 0)
- return USER_LINGERING;
-
- return USER_CLOSING;
-}
-
-int user_kill(User *u, int signo) {
- int r = 0, q;
- Set *pid_set = NULL;
-
- assert(u);
-
- if (!u->cgroup_path)
- return -ESRCH;
-
- pid_set = set_new(trivial_hash_func, trivial_compare_func);
- if (!pid_set)
- return -ENOMEM;
-
- q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, false, true, false, pid_set);
- if (q < 0)
- if (q != -EAGAIN && q != -ESRCH && q != -ENOENT)
- r = q;
-
- if (pid_set)
- set_free(pid_set);
-
- return r;
-}
-
-static const char* const user_state_table[_USER_STATE_MAX] = {
- [USER_OFFLINE] = "offline",
- [USER_LINGERING] = "lingering",
- [USER_ONLINE] = "online",
- [USER_ACTIVE] = "active",
- [USER_CLOSING] = "closing"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(user_state, UserState);
diff --git a/src/login/logind-user.h b/src/login/logind-user.h
deleted file mode 100644
index a679d43a30..0000000000
--- a/src/login/logind-user.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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/>.
-***/
-
-typedef struct User User;
-
-#include "list.h"
-#include "util.h"
-#include "logind.h"
-#include "logind-session.h"
-
-typedef enum UserState {
- USER_OFFLINE, /* Not logged in at all */
- USER_LINGERING, /* Lingering has been enabled by the admin for this user */
- USER_ONLINE, /* User logged in */
- USER_ACTIVE, /* User logged in and has a session in the fg */
- USER_CLOSING, /* User logged out, but processes still remain and lingering is not enabled */
- _USER_STATE_MAX,
- _USER_STATE_INVALID = -1
-} UserState;
-
-struct User {
- Manager *manager;
-
- uid_t uid;
- gid_t gid;
- char *name;
-
- char *state_file;
- char *runtime_path;
- char *service;
- char *cgroup_path;
-
- Session *display;
-
- dual_timestamp timestamp;
-
- bool in_gc_queue:1;
- bool started:1;
-
- LIST_HEAD(Session, sessions);
- LIST_FIELDS(User, gc_queue);
-};
-
-User* user_new(Manager *m, uid_t uid, gid_t gid, const char *name);
-void user_free(User *u);
-int user_check_gc(User *u, bool drop_not_started);
-void user_add_to_gc_queue(User *u);
-int user_start(User *u);
-int user_stop(User *u);
-UserState user_get_state(User *u);
-int user_get_idle_hint(User *u, dual_timestamp *t);
-int user_save(User *u);
-int user_load(User *u);
-int user_kill(User *u, int signo);
-
-char *user_bus_path(User *s);
-
-extern const DBusObjectPathVTable bus_user_vtable;
-
-int user_send_signal(User *u, bool new_user);
-int user_send_changed(User *u, const char *properties);
-
-const char* user_state_to_string(UserState s);
-UserState user_state_from_string(const char *s);
diff --git a/src/login/logind.c b/src/login/logind.c
deleted file mode 100644
index 9cce481340..0000000000
--- a/src/login/logind.c
+++ /dev/null
@@ -1,1680 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <errno.h>
-#include <pwd.h>
-#include <libudev.h>
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/epoll.h>
-#include <sys/ioctl.h>
-#include <linux/vt.h>
-
-#include <systemd/sd-daemon.h>
-
-#include "logind.h"
-#include "dbus-common.h"
-#include "dbus-loop.h"
-#include "strv.h"
-#include "conf-parser.h"
-
-Manager *manager_new(void) {
- Manager *m;
-
- m = new0(Manager, 1);
- if (!m)
- return NULL;
-
- m->console_active_fd = -1;
- m->bus_fd = -1;
- m->udev_seat_fd = -1;
- m->udev_vcsa_fd = -1;
- m->udev_button_fd = -1;
- m->epoll_fd = -1;
- m->reserve_vt_fd = -1;
-
- m->n_autovts = 6;
- m->reserve_vt = 6;
- m->inhibit_delay_max = 5 * USEC_PER_SEC;
- m->handle_power_key = HANDLE_POWEROFF;
- m->handle_suspend_key = HANDLE_SUSPEND;
- m->handle_hibernate_key = HANDLE_HIBERNATE;
- m->handle_lid_switch = HANDLE_SUSPEND;
- m->lid_switch_ignore_inhibited = true;
-
- m->devices = hashmap_new(string_hash_func, string_compare_func);
- m->seats = hashmap_new(string_hash_func, string_compare_func);
- m->sessions = hashmap_new(string_hash_func, string_compare_func);
- m->users = hashmap_new(trivial_hash_func, trivial_compare_func);
- m->inhibitors = hashmap_new(string_hash_func, string_compare_func);
- m->buttons = hashmap_new(string_hash_func, string_compare_func);
-
- m->user_cgroups = hashmap_new(string_hash_func, string_compare_func);
- m->session_cgroups = hashmap_new(string_hash_func, string_compare_func);
-
- m->session_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
- m->inhibitor_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
- m->button_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
-
- if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons ||
- !m->user_cgroups || !m->session_cgroups ||
- !m->session_fds || !m->inhibitor_fds || !m->button_fds) {
- manager_free(m);
- return NULL;
- }
-
- m->reset_controllers = strv_new("cpu", NULL);
- m->kill_exclude_users = strv_new("root", NULL);
- if (!m->reset_controllers || !m->kill_exclude_users) {
- manager_free(m);
- return NULL;
- }
-
- m->udev = udev_new();
- if (!m->udev) {
- manager_free(m);
- return NULL;
- }
-
- if (cg_get_user_path(&m->cgroup_path) < 0) {
- manager_free(m);
- return NULL;
- }
-
- return m;
-}
-
-void manager_free(Manager *m) {
- Session *session;
- User *u;
- Device *d;
- Seat *s;
- Inhibitor *i;
- Button *b;
-
- assert(m);
-
- while ((session = hashmap_first(m->sessions)))
- session_free(session);
-
- while ((u = hashmap_first(m->users)))
- user_free(u);
-
- while ((d = hashmap_first(m->devices)))
- device_free(d);
-
- while ((s = hashmap_first(m->seats)))
- seat_free(s);
-
- while ((i = hashmap_first(m->inhibitors)))
- inhibitor_free(i);
-
- while ((b = hashmap_first(m->buttons)))
- button_free(b);
-
- hashmap_free(m->devices);
- hashmap_free(m->seats);
- hashmap_free(m->sessions);
- hashmap_free(m->users);
- hashmap_free(m->inhibitors);
- hashmap_free(m->buttons);
-
- hashmap_free(m->user_cgroups);
- hashmap_free(m->session_cgroups);
-
- hashmap_free(m->session_fds);
- hashmap_free(m->inhibitor_fds);
- hashmap_free(m->button_fds);
-
- if (m->console_active_fd >= 0)
- close_nointr_nofail(m->console_active_fd);
-
- if (m->udev_seat_monitor)
- udev_monitor_unref(m->udev_seat_monitor);
- if (m->udev_vcsa_monitor)
- udev_monitor_unref(m->udev_vcsa_monitor);
- if (m->udev_button_monitor)
- udev_monitor_unref(m->udev_button_monitor);
-
- if (m->udev)
- udev_unref(m->udev);
-
- if (m->bus) {
- dbus_connection_flush(m->bus);
- dbus_connection_close(m->bus);
- dbus_connection_unref(m->bus);
- }
-
- if (m->bus_fd >= 0)
- close_nointr_nofail(m->bus_fd);
-
- if (m->epoll_fd >= 0)
- close_nointr_nofail(m->epoll_fd);
-
- if (m->reserve_vt_fd >= 0)
- close_nointr_nofail(m->reserve_vt_fd);
-
- strv_free(m->controllers);
- strv_free(m->reset_controllers);
- strv_free(m->kill_only_users);
- strv_free(m->kill_exclude_users);
-
- free(m->cgroup_path);
- free(m);
-}
-
-int manager_add_device(Manager *m, const char *sysfs, Device **_device) {
- Device *d;
-
- assert(m);
- assert(sysfs);
-
- d = hashmap_get(m->devices, sysfs);
- if (d) {
- if (_device)
- *_device = d;
-
- return 0;
- }
-
- d = device_new(m, sysfs);
- if (!d)
- return -ENOMEM;
-
- if (_device)
- *_device = d;
-
- return 0;
-}
-
-int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
- Seat *s;
-
- assert(m);
- assert(id);
-
- s = hashmap_get(m->seats, id);
- if (s) {
- if (_seat)
- *_seat = s;
-
- return 0;
- }
-
- s = seat_new(m, id);
- if (!s)
- return -ENOMEM;
-
- if (_seat)
- *_seat = s;
-
- return 0;
-}
-
-int manager_add_session(Manager *m, User *u, const char *id, Session **_session) {
- Session *s;
-
- assert(m);
- assert(id);
-
- s = hashmap_get(m->sessions, id);
- if (s) {
- if (_session)
- *_session = s;
-
- return 0;
- }
-
- s = session_new(m, u, id);
- if (!s)
- return -ENOMEM;
-
- if (_session)
- *_session = s;
-
- return 0;
-}
-
-int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
- User *u;
-
- assert(m);
- assert(name);
-
- u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
- if (u) {
- if (_user)
- *_user = u;
-
- return 0;
- }
-
- u = user_new(m, uid, gid, name);
- if (!u)
- return -ENOMEM;
-
- if (_user)
- *_user = u;
-
- return 0;
-}
-
-int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
- uid_t uid;
- gid_t gid;
- int r;
-
- assert(m);
- assert(name);
-
- r = get_user_creds(&name, &uid, &gid, NULL, NULL);
- if (r < 0)
- return r;
-
- return manager_add_user(m, uid, gid, name, _user);
-}
-
-int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
- struct passwd *p;
-
- assert(m);
-
- errno = 0;
- p = getpwuid(uid);
- if (!p)
- return errno ? -errno : -ENOENT;
-
- return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
-}
-
-int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
- Inhibitor *i;
-
- assert(m);
- assert(id);
-
- i = hashmap_get(m->inhibitors, id);
- if (i) {
- if (_inhibitor)
- *_inhibitor = i;
-
- return 0;
- }
-
- i = inhibitor_new(m, id);
- if (!i)
- return -ENOMEM;
-
- if (_inhibitor)
- *_inhibitor = i;
-
- return 0;
-}
-
-int manager_add_button(Manager *m, const char *name, Button **_button) {
- Button *b;
-
- assert(m);
- assert(name);
-
- b = hashmap_get(m->buttons, name);
- if (b) {
- if (_button)
- *_button = b;
-
- return 0;
- }
-
- b = button_new(m, name);
- if (!b)
- return -ENOMEM;
-
- if (_button)
- *_button = b;
-
- return 0;
-}
-
-int manager_process_seat_device(Manager *m, struct udev_device *d) {
- Device *device;
- int r;
-
- assert(m);
-
- if (streq_ptr(udev_device_get_action(d), "remove")) {
-
- device = hashmap_get(m->devices, udev_device_get_syspath(d));
- if (!device)
- return 0;
-
- seat_add_to_gc_queue(device->seat);
- device_free(device);
-
- } else {
- const char *sn;
- Seat *seat;
-
- sn = udev_device_get_property_value(d, "ID_SEAT");
- if (isempty(sn))
- sn = "seat0";
-
- if (!seat_name_is_valid(sn)) {
- log_warning("Device with invalid seat name %s found, ignoring.", sn);
- return 0;
- }
-
- r = manager_add_device(m, udev_device_get_syspath(d), &device);
- if (r < 0)
- return r;
-
- r = manager_add_seat(m, sn, &seat);
- if (r < 0) {
- if (!device->seat)
- device_free(device);
-
- return r;
- }
-
- device_attach(device, seat);
- seat_start(seat);
- }
-
- return 0;
-}
-
-int manager_process_button_device(Manager *m, struct udev_device *d) {
- Button *b;
-
- int r;
-
- assert(m);
-
- if (streq_ptr(udev_device_get_action(d), "remove")) {
-
- b = hashmap_get(m->buttons, udev_device_get_sysname(d));
- if (!b)
- return 0;
-
- button_free(b);
-
- } else {
- const char *sn;
-
- r = manager_add_button(m, udev_device_get_sysname(d), &b);
- if (r < 0)
- return r;
-
- sn = udev_device_get_property_value(d, "ID_SEAT");
- if (isempty(sn))
- sn = "seat0";
-
- button_set_seat(b, sn);
- button_open(b);
- }
-
- return 0;
-}
-
-int manager_enumerate_devices(Manager *m) {
- struct udev_list_entry *item = NULL, *first = NULL;
- struct udev_enumerate *e;
- int r;
-
- assert(m);
-
- /* Loads devices from udev and creates seats for them as
- * necessary */
-
- e = udev_enumerate_new(m->udev);
- if (!e) {
- r = -ENOMEM;
- goto finish;
- }
-
- r = udev_enumerate_add_match_subsystem(e, "graphics");
- if (r < 0)
- goto finish;
-
- r = udev_enumerate_add_match_tag(e, "seat");
- if (r < 0)
- goto finish;
-
- r = udev_enumerate_scan_devices(e);
- if (r < 0)
- goto finish;
-
- first = udev_enumerate_get_list_entry(e);
- udev_list_entry_foreach(item, first) {
- struct udev_device *d;
- int k;
-
- d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
- if (!d) {
- r = -ENOMEM;
- goto finish;
- }
-
- k = manager_process_seat_device(m, d);
- udev_device_unref(d);
-
- if (k < 0)
- r = k;
- }
-
-finish:
- if (e)
- udev_enumerate_unref(e);
-
- return r;
-}
-
-int manager_enumerate_buttons(Manager *m) {
- struct udev_list_entry *item = NULL, *first = NULL;
- struct udev_enumerate *e;
- int r;
-
- assert(m);
-
- /* Loads buttons from udev */
-
- if (m->handle_power_key == HANDLE_IGNORE &&
- m->handle_suspend_key == HANDLE_IGNORE &&
- m->handle_hibernate_key == HANDLE_IGNORE &&
- m->handle_lid_switch == HANDLE_IGNORE)
- return 0;
-
- e = udev_enumerate_new(m->udev);
- if (!e) {
- r = -ENOMEM;
- goto finish;
- }
-
- r = udev_enumerate_add_match_subsystem(e, "input");
- if (r < 0)
- goto finish;
-
- r = udev_enumerate_add_match_tag(e, "power-switch");
- if (r < 0)
- goto finish;
-
- r = udev_enumerate_scan_devices(e);
- if (r < 0)
- goto finish;
-
- first = udev_enumerate_get_list_entry(e);
- udev_list_entry_foreach(item, first) {
- struct udev_device *d;
- int k;
-
- d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
- if (!d) {
- r = -ENOMEM;
- goto finish;
- }
-
- k = manager_process_button_device(m, d);
- udev_device_unref(d);
-
- if (k < 0)
- r = k;
- }
-
-finish:
- if (e)
- udev_enumerate_unref(e);
-
- return r;
-}
-
-int manager_enumerate_seats(Manager *m) {
- DIR *d;
- struct dirent *de;
- int r = 0;
-
- assert(m);
-
- /* This loads data about seats stored on disk, but does not
- * actually create any seats. Removes data of seats that no
- * longer exist. */
-
- d = opendir("/run/systemd/seats");
- if (!d) {
- if (errno == ENOENT)
- return 0;
-
- log_error("Failed to open /run/systemd/seats: %m");
- return -errno;
- }
-
- while ((de = readdir(d))) {
- Seat *s;
- int k;
-
- if (!dirent_is_file(de))
- continue;
-
- s = hashmap_get(m->seats, de->d_name);
- if (!s) {
- unlinkat(dirfd(d), de->d_name, 0);
- continue;
- }
-
- k = seat_load(s);
- if (k < 0)
- r = k;
- }
-
- closedir(d);
-
- return r;
-}
-
-static int manager_enumerate_users_from_cgroup(Manager *m) {
- int r = 0, k;
- char *name;
- DIR *d;
-
- r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_path, &d);
- if (r < 0) {
- if (r == -ENOENT)
- return 0;
-
- log_error("Failed to open %s: %s", m->cgroup_path, strerror(-r));
- return r;
- }
-
- while ((k = cg_read_subgroup(d, &name)) > 0) {
- User *user;
-
- k = manager_add_user_by_name(m, name, &user);
- if (k < 0) {
- free(name);
- r = k;
- continue;
- }
-
- user_add_to_gc_queue(user);
-
- if (!user->cgroup_path)
- if (asprintf(&user->cgroup_path, "%s/%s", m->cgroup_path, name) < 0) {
- r = -ENOMEM;
- free(name);
- break;
- }
-
- free(name);
- }
-
- if (r >= 0 && k < 0)
- r = k;
-
- closedir(d);
-
- return r;
-}
-
-static int manager_enumerate_linger_users(Manager *m) {
- DIR *d;
- struct dirent *de;
- int r = 0;
-
- d = opendir("/var/lib/systemd/linger");
- if (!d) {
- if (errno == ENOENT)
- return 0;
-
- log_error("Failed to open /var/lib/systemd/linger/: %m");
- return -errno;
- }
-
- while ((de = readdir(d))) {
- int k;
-
- if (!dirent_is_file(de))
- continue;
-
- k = manager_add_user_by_name(m, de->d_name, NULL);
- if (k < 0) {
- log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
- r = k;
- }
- }
-
- closedir(d);
-
- return r;
-}
-
-int manager_enumerate_users(Manager *m) {
- DIR *d;
- struct dirent *de;
- int r, k;
-
- assert(m);
-
- /* First, enumerate user cgroups */
- r = manager_enumerate_users_from_cgroup(m);
-
- /* Second, add lingering users on top */
- k = manager_enumerate_linger_users(m);
- if (k < 0)
- r = k;
-
- /* Third, read in user data stored on disk */
- d = opendir("/run/systemd/users");
- if (!d) {
- if (errno == ENOENT)
- return 0;
-
- log_error("Failed to open /run/systemd/users: %m");
- return -errno;
- }
-
- while ((de = readdir(d))) {
- uid_t uid;
- User *u;
-
- if (!dirent_is_file(de))
- continue;
-
- k = parse_uid(de->d_name, &uid);
- if (k < 0) {
- log_error("Failed to parse file name %s: %s", de->d_name, strerror(-k));
- continue;
- }
-
- u = hashmap_get(m->users, ULONG_TO_PTR(uid));
- if (!u) {
- unlinkat(dirfd(d), de->d_name, 0);
- continue;
- }
-
- k = user_load(u);
- if (k < 0)
- r = k;
- }
-
- closedir(d);
-
- return r;
-}
-
-static int manager_enumerate_sessions_from_cgroup(Manager *m) {
- User *u;
- Iterator i;
- int r = 0;
-
- HASHMAP_FOREACH(u, m->users, i) {
- DIR *d;
- char *name;
- int k;
-
- if (!u->cgroup_path)
- continue;
-
- k = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &d);
- if (k < 0) {
- if (k == -ENOENT)
- continue;
-
- log_error("Failed to open %s: %s", u->cgroup_path, strerror(-k));
- r = k;
- continue;
- }
-
- while ((k = cg_read_subgroup(d, &name)) > 0) {
- Session *session;
-
- if (streq(name, "shared"))
- continue;
-
- k = manager_add_session(m, u, name, &session);
- if (k < 0) {
- free(name);
- break;
- }
-
- session_add_to_gc_queue(session);
-
- if (!session->cgroup_path)
- if (asprintf(&session->cgroup_path, "%s/%s", u->cgroup_path, name) < 0) {
- k = -ENOMEM;
- free(name);
- break;
- }
-
- free(name);
- }
-
- closedir(d);
-
- if (k < 0)
- r = k;
- }
-
- return r;
-}
-
-int manager_enumerate_sessions(Manager *m) {
- DIR *d;
- struct dirent *de;
- int r = 0;
-
- assert(m);
-
- /* First enumerate session cgroups */
- r = manager_enumerate_sessions_from_cgroup(m);
-
- /* Second, read in session data stored on disk */
- d = opendir("/run/systemd/sessions");
- if (!d) {
- if (errno == ENOENT)
- return 0;
-
- log_error("Failed to open /run/systemd/sessions: %m");
- return -errno;
- }
-
- while ((de = readdir(d))) {
- struct Session *s;
- int k;
-
- if (!dirent_is_file(de))
- continue;
-
- s = hashmap_get(m->sessions, de->d_name);
- if (!s) {
- unlinkat(dirfd(d), de->d_name, 0);
- continue;
- }
-
- k = session_load(s);
- if (k < 0)
- r = k;
- }
-
- closedir(d);
-
- return r;
-}
-
-int manager_enumerate_inhibitors(Manager *m) {
- DIR *d;
- struct dirent *de;
- int r = 0;
-
- assert(m);
-
- d = opendir("/run/systemd/inhibit");
- if (!d) {
- if (errno == ENOENT)
- return 0;
-
- log_error("Failed to open /run/systemd/inhibit: %m");
- return -errno;
- }
-
- while ((de = readdir(d))) {
- int k;
- Inhibitor *i;
-
- if (!dirent_is_file(de))
- continue;
-
- k = manager_add_inhibitor(m, de->d_name, &i);
- if (k < 0) {
- log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
- r = k;
- continue;
- }
-
- k = inhibitor_load(i);
- if (k < 0)
- r = k;
- }
-
- closedir(d);
-
- return r;
-}
-
-int manager_dispatch_seat_udev(Manager *m) {
- struct udev_device *d;
- int r;
-
- assert(m);
-
- d = udev_monitor_receive_device(m->udev_seat_monitor);
- if (!d)
- return -ENOMEM;
-
- r = manager_process_seat_device(m, d);
- udev_device_unref(d);
-
- return r;
-}
-
-int manager_dispatch_vcsa_udev(Manager *m) {
- struct udev_device *d;
- int r = 0;
- const char *name;
-
- assert(m);
-
- d = udev_monitor_receive_device(m->udev_vcsa_monitor);
- if (!d)
- return -ENOMEM;
-
- name = udev_device_get_sysname(d);
-
- /* Whenever a VCSA device is removed try to reallocate our
- * VTs, to make sure our auto VTs never go away. */
-
- if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
- r = seat_preallocate_vts(m->vtconsole);
-
- udev_device_unref(d);
-
- return r;
-}
-
-int manager_dispatch_button_udev(Manager *m) {
- struct udev_device *d;
- int r;
-
- assert(m);
-
- d = udev_monitor_receive_device(m->udev_button_monitor);
- if (!d)
- return -ENOMEM;
-
- r = manager_process_button_device(m, d);
- udev_device_unref(d);
-
- return r;
-}
-
-int manager_dispatch_console(Manager *m) {
- assert(m);
-
- if (m->vtconsole)
- seat_read_active_vt(m->vtconsole);
-
- return 0;
-}
-
-static int vt_is_busy(int vtnr) {
- struct vt_stat vt_stat;
- int r = 0, fd;
-
- assert(vtnr >= 1);
-
- /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
- * we'd open the latter we'd open the foreground tty which
- * hence would be unconditionally busy. By opening /dev/tty1
- * we avoid this. Since tty1 is special and needs to be an
- * explicitly loaded getty or DM this is safe. */
-
- fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return -errno;
-
- if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
- r = -errno;
- else
- r = !!(vt_stat.v_state & (1 << vtnr));
-
- close_nointr_nofail(fd);
-
- return r;
-}
-
-int manager_spawn_autovt(Manager *m, int vtnr) {
- int r;
- char *name = NULL;
- const char *mode = "fail";
-
- assert(m);
- assert(vtnr >= 1);
-
- if ((unsigned) vtnr > m->n_autovts &&
- (unsigned) vtnr != m->reserve_vt)
- return 0;
-
- if ((unsigned) vtnr != m->reserve_vt) {
- /* If this is the reserved TTY, we'll start the getty
- * on it in any case, but otherwise only if it is not
- * busy. */
-
- r = vt_is_busy(vtnr);
- if (r < 0)
- return r;
- else if (r > 0)
- return -EBUSY;
- }
-
- if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
- log_error("Could not allocate service name.");
- r = -ENOMEM;
- goto finish;
- }
-
- r = bus_method_call_with_reply (
- m->bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "StartUnit",
- NULL,
- NULL,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_STRING, &mode,
- DBUS_TYPE_INVALID);
-
-finish:
- free(name);
-
- return r;
-}
-
-static int manager_reserve_vt(Manager *m) {
- _cleanup_free_ char *p = NULL;
-
- assert(m);
-
- if (m->reserve_vt <= 0)
- return 0;
-
- if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
- return log_oom();
-
- m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
- if (m->reserve_vt_fd < 0) {
-
- /* Don't complain on VT-less systems */
- if (errno != ENOENT)
- log_warning("Failed to pin reserved VT: %m");
- return -errno;
- }
-
- return 0;
-}
-
-int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) {
- Session *s;
- char *p;
-
- assert(m);
- assert(cgroup);
- assert(session);
-
- s = hashmap_get(m->session_cgroups, cgroup);
- if (s) {
- *session = s;
- return 1;
- }
-
- p = strdup(cgroup);
- if (!p)
- return log_oom();
-
- for (;;) {
- char *e;
-
- e = strrchr(p, '/');
- if (!e || e == p) {
- free(p);
- *session = NULL;
- return 0;
- }
-
- *e = 0;
-
- s = hashmap_get(m->session_cgroups, p);
- if (s) {
- free(p);
- *session = s;
- return 1;
- }
- }
-}
-
-int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) {
- User *u;
- char *p;
-
- assert(m);
- assert(cgroup);
- assert(user);
-
- u = hashmap_get(m->user_cgroups, cgroup);
- if (u) {
- *user = u;
- return 1;
- }
-
- p = strdup(cgroup);
- if (!p)
- return log_oom();
-
- for (;;) {
- char *e;
-
- e = strrchr(p, '/');
- if (!e || e == p) {
- free(p);
- *user = NULL;
- return 0;
- }
-
- *e = 0;
-
- u = hashmap_get(m->user_cgroups, p);
- if (u) {
- free(p);
- *user = u;
- return 1;
- }
- }
-}
-
-int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
- char *p;
- int r;
-
- assert(m);
- assert(pid >= 1);
- assert(session);
-
- r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
- if (r < 0)
- return r;
-
- r = manager_get_session_by_cgroup(m, p, session);
- free(p);
-
- return r;
-}
-
-void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
- Session *s;
- User *u;
- int r;
-
- r = manager_get_session_by_cgroup(m, cgroup, &s);
- if (r > 0)
- session_add_to_gc_queue(s);
-
- r = manager_get_user_by_cgroup(m, cgroup, &u);
- if (r > 0)
- user_add_to_gc_queue(u);
-}
-
-static void manager_dispatch_other(Manager *m, int fd) {
- Session *s;
- Inhibitor *i;
- Button *b;
-
- assert_se(m);
- assert_se(fd >= 0);
-
- s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
- if (s) {
- assert(s->fifo_fd == fd);
- session_remove_fifo(s);
- session_stop(s);
- return;
- }
-
- i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
- if (i) {
- assert(i->fifo_fd == fd);
- inhibitor_stop(i);
- inhibitor_free(i);
- return;
- }
-
- b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
- if (b) {
- assert(b->fd == fd);
- button_process(b);
- return;
- }
-
- assert_not_reached("Got event for unknown fd");
-}
-
-static int manager_connect_bus(Manager *m) {
- DBusError error;
- int r;
- struct epoll_event ev;
-
- assert(m);
- assert(!m->bus);
- assert(m->bus_fd < 0);
-
- dbus_error_init(&error);
-
- m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
- if (!m->bus) {
- log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
- r = -ECONNREFUSED;
- goto fail;
- }
-
- if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
- !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
- !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
- !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
- !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
- r = log_oom();
- goto fail;
- }
-
- dbus_bus_add_match(m->bus,
- "type='signal',"
- "interface='org.freedesktop.systemd1.Agent',"
- "member='Released',"
- "path='/org/freedesktop/systemd1/agent'",
- &error);
-
- if (dbus_error_is_set(&error)) {
- log_error("Failed to register match: %s", bus_error_message(&error));
- r = -EIO;
- goto fail;
- }
-
- r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
- if (dbus_error_is_set(&error)) {
- log_error("Failed to register name on bus: %s", bus_error_message(&error));
- r = -EIO;
- goto fail;
- }
-
- if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
- log_error("Failed to acquire name.");
- r = -EEXIST;
- goto fail;
- }
-
- m->bus_fd = bus_loop_open(m->bus);
- if (m->bus_fd < 0) {
- r = m->bus_fd;
- goto fail;
- }
-
- zero(ev);
- ev.events = EPOLLIN;
- ev.data.u32 = FD_BUS;
-
- if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
- goto fail;
-
- return 0;
-
-fail:
- dbus_error_free(&error);
-
- return r;
-}
-
-static int manager_connect_console(Manager *m) {
- struct epoll_event ev;
-
- assert(m);
- assert(m->console_active_fd < 0);
-
- /* On certain architectures (S390 and Xen, and containers),
- /dev/tty0 does not exist, so don't fail if we can't open
- it. */
- if (access("/dev/tty0", F_OK) < 0) {
- m->console_active_fd = -1;
- return 0;
- }
-
- m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
- if (m->console_active_fd < 0) {
-
- /* On some systems the device node /dev/tty0 may exist
- * even though /sys/class/tty/tty0 does not. */
- if (errno == ENOENT)
- return 0;
-
- log_error("Failed to open /sys/class/tty/tty0/active: %m");
- return -errno;
- }
-
- zero(ev);
- ev.events = 0;
- ev.data.u32 = FD_CONSOLE;
-
- if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
- return -errno;
-
- return 0;
-}
-
-static int manager_connect_udev(Manager *m) {
- struct epoll_event ev;
- int r;
-
- assert(m);
- assert(!m->udev_seat_monitor);
- assert(!m->udev_vcsa_monitor);
- assert(!m->udev_button_monitor);
-
- m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
- if (!m->udev_seat_monitor)
- return -ENOMEM;
-
- r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "seat");
- if (r < 0)
- return r;
-
- r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_seat_monitor, "graphics", NULL);
- if (r < 0)
- return r;
-
- r = udev_monitor_enable_receiving(m->udev_seat_monitor);
- if (r < 0)
- return r;
-
- m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
-
- zero(ev);
- ev.events = EPOLLIN;
- ev.data.u32 = FD_SEAT_UDEV;
- if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
- return -errno;
-
- /* Don't watch keys if nobody cares */
- if (m->handle_power_key != HANDLE_IGNORE ||
- m->handle_suspend_key != HANDLE_IGNORE ||
- m->handle_hibernate_key != HANDLE_IGNORE ||
- m->handle_lid_switch != HANDLE_IGNORE) {
-
- m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
- if (!m->udev_button_monitor)
- return -ENOMEM;
-
- r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
- if (r < 0)
- return r;
-
- r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
- if (r < 0)
- return r;
-
- r = udev_monitor_enable_receiving(m->udev_button_monitor);
- if (r < 0)
- return r;
-
- m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
-
- zero(ev);
- ev.events = EPOLLIN;
- ev.data.u32 = FD_BUTTON_UDEV;
- if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
- return -errno;
- }
-
- /* Don't bother watching VCSA devices, if nobody cares */
- if (m->n_autovts > 0 && m->console_active_fd >= 0) {
-
- m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
- if (!m->udev_vcsa_monitor)
- return -ENOMEM;
-
- r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
- if (r < 0)
- return r;
-
- r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
- if (r < 0)
- return r;
-
- m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
-
- zero(ev);
- ev.events = EPOLLIN;
- ev.data.u32 = FD_VCSA_UDEV;
- if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
- return -errno;
- }
-
- return 0;
-}
-
-void manager_gc(Manager *m, bool drop_not_started) {
- Seat *seat;
- Session *session;
- User *user;
-
- assert(m);
-
- while ((seat = m->seat_gc_queue)) {
- LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
- seat->in_gc_queue = false;
-
- if (seat_check_gc(seat, drop_not_started) == 0) {
- seat_stop(seat);
- seat_free(seat);
- }
- }
-
- while ((session = m->session_gc_queue)) {
- LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
- session->in_gc_queue = false;
-
- if (session_check_gc(session, drop_not_started) == 0) {
- session_stop(session);
- session_free(session);
- }
- }
-
- while ((user = m->user_gc_queue)) {
- LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
- user->in_gc_queue = false;
-
- if (user_check_gc(user, drop_not_started) == 0) {
- user_stop(user);
- user_free(user);
- }
- }
-}
-
-int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
- Session *s;
- bool idle_hint;
- dual_timestamp ts = { 0, 0 };
- Iterator i;
-
- assert(m);
-
- idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0);
-
- HASHMAP_FOREACH(s, m->sessions, i) {
- dual_timestamp k;
- int ih;
-
- ih = session_get_idle_hint(s, &k);
- if (ih < 0)
- return ih;
-
- if (!ih) {
- if (!idle_hint) {
- if (k.monotonic < ts.monotonic)
- ts = k;
- } else {
- idle_hint = false;
- ts = k;
- }
- } else if (idle_hint) {
-
- if (k.monotonic > ts.monotonic)
- ts = k;
- }
- }
-
- if (t)
- *t = ts;
-
- return idle_hint;
-}
-
-int manager_startup(Manager *m) {
- int r;
- Seat *seat;
- Session *session;
- User *user;
- Inhibitor *inhibitor;
- Iterator i;
-
- assert(m);
- assert(m->epoll_fd <= 0);
-
- cg_shorten_controllers(m->reset_controllers);
- cg_shorten_controllers(m->controllers);
-
- m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
- if (m->epoll_fd < 0)
- return -errno;
-
- /* Connect to console */
- r = manager_connect_console(m);
- if (r < 0)
- return r;
-
- /* Connect to udev */
- r = manager_connect_udev(m);
- if (r < 0)
- return r;
-
- /* Connect to the bus */
- r = manager_connect_bus(m);
- if (r < 0)
- return r;
-
- /* Instantiate magic seat 0 */
- r = manager_add_seat(m, "seat0", &m->vtconsole);
- if (r < 0)
- return r;
-
- /* Deserialize state */
- manager_enumerate_devices(m);
- manager_enumerate_seats(m);
- manager_enumerate_users(m);
- manager_enumerate_sessions(m);
- manager_enumerate_inhibitors(m);
- manager_enumerate_buttons(m);
-
- /* Remove stale objects before we start them */
- manager_gc(m, false);
-
- /* Reserve the special reserved VT */
- manager_reserve_vt(m);
-
- /* And start everything */
- HASHMAP_FOREACH(seat, m->seats, i)
- seat_start(seat);
-
- HASHMAP_FOREACH(user, m->users, i)
- user_start(user);
-
- HASHMAP_FOREACH(session, m->sessions, i)
- session_start(session);
-
- HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
- inhibitor_start(inhibitor);
-
- return 0;
-}
-
-static int manager_recheck_buttons(Manager *m) {
- Iterator i;
- Button *b;
- int r = 0;
-
- assert(m);
-
- HASHMAP_FOREACH(b, m->buttons, i) {
- int q;
-
- q = button_recheck(b);
- if (q > 0)
- return 1;
- if (q < 0)
- r = q;
- }
-
- return r;
-}
-
-int manager_run(Manager *m) {
- assert(m);
-
- for (;;) {
- struct epoll_event event;
- int n;
- int msec = -1;
-
- manager_gc(m, true);
-
- if (manager_dispatch_delayed(m) > 0)
- continue;
-
- if (manager_recheck_buttons(m) > 0)
- continue;
-
- if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
- continue;
-
- manager_gc(m, true);
-
- if (m->delayed_unit) {
- usec_t x, y;
-
- x = now(CLOCK_MONOTONIC);
- y = m->delayed_timestamp + m->inhibit_delay_max;
-
- msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
- }
-
- n = epoll_wait(m->epoll_fd, &event, 1, msec);
- if (n < 0) {
- if (errno == EINTR || errno == EAGAIN)
- continue;
-
- log_error("epoll() failed: %m");
- return -errno;
- }
-
- if (n == 0)
- continue;
-
- switch (event.data.u32) {
-
- case FD_SEAT_UDEV:
- manager_dispatch_seat_udev(m);
- break;
-
- case FD_VCSA_UDEV:
- manager_dispatch_vcsa_udev(m);
- break;
-
- case FD_BUTTON_UDEV:
- manager_dispatch_button_udev(m);
- break;
-
- case FD_CONSOLE:
- manager_dispatch_console(m);
- break;
-
- case FD_BUS:
- bus_loop_dispatch(m->bus_fd);
- break;
-
- default:
- if (event.data.u32 >= FD_OTHER_BASE)
- manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
- }
- }
-
- return 0;
-}
-
-static int manager_parse_config_file(Manager *m) {
- FILE *f;
- const char *fn;
- int r;
-
- assert(m);
-
- fn = "/etc/systemd/logind.conf";
- f = fopen(fn, "re");
- if (!f) {
- if (errno == ENOENT)
- return 0;
-
- log_warning("Failed to open configuration file %s: %m", fn);
- return -errno;
- }
-
- r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
- if (r < 0)
- log_warning("Failed to parse configuration file: %s", strerror(-r));
-
- fclose(f);
-
- return r;
-}
-
-int main(int argc, char *argv[]) {
- Manager *m = NULL;
- int r;
-
- log_set_target(LOG_TARGET_AUTO);
- log_set_facility(LOG_AUTH);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- if (argc != 1) {
- log_error("This program takes no arguments.");
- r = -EINVAL;
- goto finish;
- }
-
- m = manager_new();
- if (!m) {
- r = log_oom();
- goto finish;
- }
-
- manager_parse_config_file(m);
-
- r = manager_startup(m);
- if (r < 0) {
- log_error("Failed to fully start up daemon: %s", strerror(-r));
- goto finish;
- }
-
- log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
-
- sd_notify(false,
- "READY=1\n"
- "STATUS=Processing requests...");
-
- r = manager_run(m);
-
- log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
-
-finish:
- sd_notify(false,
- "STATUS=Shutting down...");
-
- if (m)
- manager_free(m);
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/login/logind.conf b/src/login/logind.conf
deleted file mode 100644
index 2757fba30a..0000000000
--- a/src/login/logind.conf
+++ /dev/null
@@ -1,26 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# See logind.conf(5) for details
-
-[Login]
-#NAutoVTs=6
-#ReserveVT=6
-#KillUserProcesses=no
-#KillOnlyUsers=
-#KillExcludeUsers=root
-#Controllers=
-#ResetControllers=cpu
-#InhibitDelayMaxSec=5
-#HandlePowerKey=poweroff
-#HandleSuspendKey=suspend
-#HandleHibernateKey=hibernate
-#HandleLidSwitch=suspend
-#PowerKeyIgnoreInhibited=no
-#SuspendKeyIgnoreInhibited=no
-#HibernateKeyIgnoreInhibited=no
-#LidSwitchIgnoreInhibited=yes
diff --git a/src/login/logind.h b/src/login/logind.h
deleted file mode 100644
index f415dfbcbf..0000000000
--- a/src/login/logind.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <inttypes.h>
-#include <dbus/dbus.h>
-#include <libudev.h>
-
-#include "util.h"
-#include "audit.h"
-#include "list.h"
-#include "hashmap.h"
-#include "cgroup-util.h"
-
-typedef struct Manager Manager;
-
-#include "logind-device.h"
-#include "logind-seat.h"
-#include "logind-session.h"
-#include "logind-user.h"
-#include "logind-inhibit.h"
-#include "logind-button.h"
-
-struct Manager {
- DBusConnection *bus;
-
- Hashmap *devices;
- Hashmap *seats;
- Hashmap *sessions;
- Hashmap *users;
- Hashmap *inhibitors;
- Hashmap *buttons;
-
- LIST_HEAD(Seat, seat_gc_queue);
- LIST_HEAD(Session, session_gc_queue);
- LIST_HEAD(User, user_gc_queue);
-
- struct udev *udev;
- struct udev_monitor *udev_seat_monitor, *udev_vcsa_monitor, *udev_button_monitor;
-
- int udev_seat_fd;
- int udev_vcsa_fd;
- int udev_button_fd;
-
- int console_active_fd;
- int bus_fd;
- int epoll_fd;
-
- unsigned n_autovts;
-
- unsigned reserve_vt;
- int reserve_vt_fd;
-
- Seat *vtconsole;
-
- char *cgroup_path;
- char **controllers, **reset_controllers;
-
- char **kill_only_users, **kill_exclude_users;
-
- bool kill_user_processes;
-
- unsigned long session_counter;
- unsigned long inhibit_counter;
-
- Hashmap *session_cgroups;
- Hashmap *user_cgroups;
-
- Hashmap *session_fds;
- Hashmap *inhibitor_fds;
- Hashmap *button_fds;
-
- /* If a shutdown was delayed due to a inhibitor this contains
- the unit name we are supposed to start after the delay is
- over */
- const char *delayed_unit;
- InhibitWhat delayed_what;
- usec_t delayed_timestamp;
-
- usec_t inhibit_delay_max;
-
- HandleButton handle_power_key;
- HandleButton handle_suspend_key;
- HandleButton handle_hibernate_key;
- HandleButton handle_lid_switch;
-
- bool power_key_ignore_inhibited;
- bool suspend_key_ignore_inhibited;
- bool hibernate_key_ignore_inhibited;
- bool lid_switch_ignore_inhibited;
-};
-
-enum {
- FD_SEAT_UDEV,
- FD_VCSA_UDEV,
- FD_BUTTON_UDEV,
- FD_CONSOLE,
- FD_BUS,
- FD_OTHER_BASE
-};
-
-Manager *manager_new(void);
-void manager_free(Manager *m);
-
-int manager_add_device(Manager *m, const char *sysfs, Device **_device);
-int manager_add_button(Manager *m, const char *name, Button **_button);
-int manager_add_seat(Manager *m, const char *id, Seat **_seat);
-int manager_add_session(Manager *m, User *u, const char *id, Session **_session);
-int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user);
-int manager_add_user_by_name(Manager *m, const char *name, User **_user);
-int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user);
-int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor);
-
-int manager_process_seat_device(Manager *m, struct udev_device *d);
-int manager_process_button_device(Manager *m, struct udev_device *d);
-
-int manager_dispatch_seat_udev(Manager *m);
-int manager_dispatch_vcsa_udev(Manager *m);
-int manager_dispatch_button_udev(Manager *m);
-int manager_dispatch_console(Manager *m);
-
-int manager_enumerate_devices(Manager *m);
-int manager_enumerate_buttons(Manager *m);
-int manager_enumerate_seats(Manager *m);
-int manager_enumerate_sessions(Manager *m);
-int manager_enumerate_users(Manager *m);
-int manager_enumerate_inhibitors(Manager *m);
-
-int manager_startup(Manager *m);
-int manager_run(Manager *m);
-int manager_spawn_autovt(Manager *m, int vtnr);
-
-void manager_cgroup_notify_empty(Manager *m, const char *cgroup);
-
-void manager_gc(Manager *m, bool drop_not_started);
-
-int manager_get_idle_hint(Manager *m, dual_timestamp *t);
-
-int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user);
-int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session);
-int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session);
-
-extern const DBusObjectPathVTable bus_manager_vtable;
-
-DBusHandlerResult bus_message_filter(DBusConnection *c, DBusMessage *message, void *userdata);
-
-int bus_manager_shutdown_or_sleep_now_or_later(Manager *m, const char *unit_name, InhibitWhat w, DBusError *error);
-
-int manager_send_changed(Manager *manager, const char *properties);
-
-int manager_dispatch_delayed(Manager *manager);
-
-/* gperf lookup function */
-const struct ConfigPerfItem* logind_gperf_lookup(const char *key, unsigned length);
diff --git a/src/login/multi-seat-x.c b/src/login/multi-seat-x.c
deleted file mode 100644
index 83760d4191..0000000000
--- a/src/login/multi-seat-x.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <unistd.h>
-
-#include "util.h"
-#include "mkdir.h"
-
-int main(int argc, char *argv[]) {
-
- int i;
- const char *seat = NULL;
- char **new_argv;
- _cleanup_free_ char *path = NULL;
- int r;
- _cleanup_fclose_ FILE *f = NULL;
-
- /* This binary will go away as soon as X natively takes the
- * arguments in question as command line parameters, instead
- * of requiring them in the configuration file. */
-
- /* If this file is removed, don't forget to remove the code
- * that invokes this in gdm and other display managers. */
-
- for (i = 1; i < argc; i++)
- if (streq(argv[i], "-seat"))
- seat = argv[i+1];
-
- if (isempty(seat) || streq(seat, "seat0")) {
- argv[0] = (char*) X_SERVER;
- execv(X_SERVER, argv);
- log_error("Failed to execute real X server: %m");
- goto fail;
- }
-
- r = mkdir_safe_label("/run/systemd/multi-session-x", 0755, 0, 0);
- if (r < 0) {
- log_error("Failed to create directory: %s", strerror(-r));
- goto fail;
- }
-
- path = strappend("/run/systemd/multi-session-x/", seat);
- if (!path) {
- log_oom();
- goto fail;
- }
-
- f = fopen(path, "we");
- if (!f) {
- log_error("Failed to write configuration file: %m");
- goto fail;
- }
-
- fprintf(f,
- "Section \"ServerFlags\"\n"
- " Option \"AutoAddDevices\" \"True\"\n"
- " Option \"AllowEmptyInput\" \"True\"\n"
- " Option \"DontVTSwitch\" \"True\"\n"
- "EndSection\n"
- "Section \"InputClass\"\n"
- " Identifier \"Force Input Devices to Seat\"\n"
- " Option \"GrabDevice\" \"True\"\n"
- "EndSection\n");
-
- fflush(f);
-
- if (ferror(f)) {
- log_error("Failed to write configuration file: %m");
- goto fail;
- }
-
- fclose(f);
- f = NULL;
-
- new_argv = newa(char*, argc + 3 + 1);
- memcpy(new_argv, argv, sizeof(char*) * (argc + 2 + 1));
-
- new_argv[0] = (char*) X_SERVER;
- new_argv[argc+0] = (char*) "-config";
- new_argv[argc+1] = path;
- new_argv[argc+2] = (char*) "-sharevts";
- new_argv[argc+3] = NULL;
-
- execv(X_SERVER, new_argv);
- log_error("Failed to execute real X server: %m");
-
-fail:
- return EXIT_FAILURE;
-}
diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf
deleted file mode 100644
index 5860fd9226..0000000000
--- a/src/login/org.freedesktop.login1.conf
+++ /dev/null
@@ -1,142 +0,0 @@
-<?xml version="1.0"?> <!--*-nxml-*-->
-<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
-
-<!--
- This file is part of systemd.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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.
--->
-
-<busconfig>
-
- <policy user="root">
- <allow own="org.freedesktop.login1"/>
- <allow send_destination="org.freedesktop.login1"/>
- <allow receive_sender="org.freedesktop.login1"/>
- </policy>
-
- <policy context="default">
- <deny send_destination="org.freedesktop.login1"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.DBus.Introspectable"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.DBus.Peer"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.DBus.Properties"
- send_member="Get"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.DBus.Properties"
- send_member="GetAll"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Manager"
- send_member="GetSession"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Manager"
- send_member="GetSessionByPID"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Manager"
- send_member="GetUser"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Manager"
- send_member="GetSeat"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Manager"
- send_member="ListSessions"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Manager"
- send_member="ListUsers"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Manager"
- send_member="ListSeats"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Manager"
- send_member="ListInhibitors"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Manager"
- send_member="Inhibit"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Manager"
- send_member="SetUserLinger"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Manager"
- send_member="ActivateSession"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Manager"
- send_member="ActivateSessionOnSeat"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Manager"
- send_member="PowerOff"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Manager"
- send_member="Reboot"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Manager"
- send_member="Suspend"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Manager"
- send_member="Hibernate"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Manager"
- send_member="CanPowerOff"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Manager"
- send_member="CanReboot"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Manager"
- send_member="CanSuspend"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Manager"
- send_member="CanHibernate"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Manager"
- send_member="AttachDevice"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Manager"
- send_member="FlushDevices"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Seat"
- send_member="ActivateSession"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Session"
- send_member="Activate"/>
-
- <allow send_destination="org.freedesktop.login1"
- send_interface="org.freedesktop.login1.Session"
- send_member="SetIdleHint"/>
-
- <allow receive_sender="org.freedesktop.login1"/>
- </policy>
-
-</busconfig>
diff --git a/src/login/org.freedesktop.login1.policy.in b/src/login/org.freedesktop.login1.policy.in
deleted file mode 100644
index 57dfb2a8b6..0000000000
--- a/src/login/org.freedesktop.login1.policy.in
+++ /dev/null
@@ -1,259 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?> <!--*-nxml-*-->
-<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
-
-<!--
- This file is part of systemd.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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.
--->
-
-<policyconfig>
-
- <vendor>The systemd Project</vendor>
- <vendor_url>http://www.freedesktop.org/wiki/Software/systemd</vendor_url>
-
- <action id="org.freedesktop.login1.inhibit-block-shutdown">
- <_description>Allow applications to inhibit system shutdown</_description>
- <_message>Authentication is required to allow an application to inhibit system shutdown.</_message>
- <defaults>
- <allow_any>no</allow_any>
- <allow_inactive>yes</allow_inactive>
- <allow_active>yes</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.login1.inhibit-delay-shutdown">
- <_description>Allow applications to delay system shutdown</_description>
- <_message>Authentication is required to allow an application to delay system shutdown.</_message>
- <defaults>
- <allow_any>yes</allow_any>
- <allow_inactive>yes</allow_inactive>
- <allow_active>yes</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.login1.inhibit-block-sleep">
- <_description>Allow applications to inhibit system sleep</_description>
- <_message>Authentication is required to allow an application to inhibit system sleep.</_message>
- <defaults>
- <allow_any>no</allow_any>
- <allow_inactive>yes</allow_inactive>
- <allow_active>yes</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.login1.inhibit-delay-sleep">
- <_description>Allow applications to delay system sleep</_description>
- <_message>Authentication is required to allow an application to delay system sleep.</_message>
- <defaults>
- <allow_any>yes</allow_any>
- <allow_inactive>yes</allow_inactive>
- <allow_active>yes</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.login1.inhibit-block-idle">
- <_description>Allow applications to inhibit automatic system suspend</_description>
- <_message>Authentication is required to allow an application to inhibit automatic system suspend.</_message>
- <defaults>
- <allow_any>yes</allow_any>
- <allow_inactive>yes</allow_inactive>
- <allow_active>yes</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.login1.inhibit-handle-power-key">
- <_description>Allow applications to inhibit system handling of the power key</_description>
- <_message>Authentication is required to allow an application to inhibit system handling of the power key.</_message>
- <defaults>
- <allow_any>no</allow_any>
- <allow_inactive>yes</allow_inactive>
- <allow_active>yes</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.login1.inhibit-handle-suspend-key">
- <_description>Allow applications to inhibit system handling of the suspend key</_description>
- <_message>Authentication is required to allow an application to inhibit system handling of the suspend key.</_message>
- <defaults>
- <allow_any>no</allow_any>
- <allow_inactive>yes</allow_inactive>
- <allow_active>yes</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.login1.inhibit-handle-hibernate-key">
- <_description>Allow applications to inhibit system handling of the hibernate key</_description>
- <_message>Authentication is required to allow an application to inhibit system handling of the hibernate key.</_message>
- <defaults>
- <allow_any>no</allow_any>
- <allow_inactive>yes</allow_inactive>
- <allow_active>yes</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.login1.inhibit-handle-lid-switch">
- <_description>Allow applications to inhibit system handling of the lid switch</_description>
- <_message>Authentication is required to allow an application to inhibit system handling of the lid switch.</_message>
- <defaults>
- <allow_any>no</allow_any>
- <allow_inactive>yes</allow_inactive>
- <allow_active>yes</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.login1.set-user-linger">
- <_description>Allow non-logged-in users to run programs</_description>
- <_message>Authentication is required to allow a non-logged-in user to run programs.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.login1.attach-device">
- <_description>Allow attaching devices to seats</_description>
- <_message>Authentication is required for attaching a device to a seat.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.login1.flush-devices">
- <_description>Flush device to seat attachments</_description>
- <_message>Authentication is required for resetting how devices are attached to seats.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.login1.power-off">
- <_description>Power off the system</_description>
- <_message>Authentication is required for powering off the system.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>yes</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.login1.power-off-multiple-sessions">
- <_description>Power off the system while other users are logged in</_description>
- <_message>Authentication is required for powering off the system while other users are logged in.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.login1.power-off-ignore-inhibit">
- <_description>Power off the system while an application asked to inhibit it</_description>
- <_message>Authentication is required for powering off the system while an application asked to inhibit it.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.login1.reboot">
- <_description>Reboot the system</_description>
- <_message>Authentication is required for rebooting the system.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>yes</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.login1.reboot-multiple-sessions">
- <_description>Reboot the system while other users are logged in</_description>
- <_message>Authentication is required for rebooting the system while other users are logged in.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.login1.reboot-ignore-inhibit">
- <_description>Reboot the system while an application asked to inhibit it</_description>
- <_message>Authentication is required for rebooting the system while an application asked to inhibit it.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.login1.suspend">
- <_description>Suspend the system</_description>
- <_message>Authentication is required for suspending the system.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>yes</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.login1.suspend-multiple-sessions">
- <_description>Suspend the system while other users are logged in</_description>
- <_message>Authentication is required for suspending the system while other users are logged in.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>yes</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.login1.suspend-ignore-inhibit">
- <_description>Suspend the system while an application asked to inhibit it</_description>
- <_message>Authentication is required for suspending the system while an application asked to inhibit it.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.login1.hibernate">
- <_description>Hibernate the system</_description>
- <_message>Authentication is required for hibernating the system.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>yes</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.login1.hibernate-multiple-sessions">
- <_description>Hibernate the system while other users are logged in</_description>
- <_message>Authentication is required for hibernating the system while other users are logged in.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.login1.hibernate-ignore-inhibit">
- <_description>Hibernate the system while an application asked to inhibit it</_description>
- <_message>Authentication is required for hibernating the system while an application asked to inhibit it.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
- </defaults>
- </action>
-
-</policyconfig>
diff --git a/src/login/org.freedesktop.login1.service b/src/login/org.freedesktop.login1.service
deleted file mode 100644
index 762dae2bb3..0000000000
--- a/src/login/org.freedesktop.login1.service
+++ /dev/null
@@ -1,12 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-
-[D-BUS Service]
-Name=org.freedesktop.login1
-Exec=/bin/false
-User=root
-SystemdService=dbus-org.freedesktop.login1.service
diff --git a/src/login/pam-module.c b/src/login/pam-module.c
deleted file mode 100644
index 08a9328b65..0000000000
--- a/src/login/pam-module.c
+++ /dev/null
@@ -1,716 +0,0 @@
-/*-*- 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 <errno.h>
-#include <fcntl.h>
-#include <sys/file.h>
-#include <pwd.h>
-#include <endian.h>
-#include <sys/capability.h>
-
-#include <security/pam_modules.h>
-#include <security/_pam_macros.h>
-#include <security/pam_modutil.h>
-#include <security/pam_ext.h>
-#include <security/pam_misc.h>
-
-#include <systemd/sd-daemon.h>
-
-#include "util.h"
-#include "audit.h"
-#include "macro.h"
-#include "strv.h"
-#include "dbus-common.h"
-#include "def.h"
-#include "socket-util.h"
-
-static int parse_argv(pam_handle_t *handle,
- int argc, const char **argv,
- char ***controllers,
- char ***reset_controllers,
- bool *kill_processes,
- char ***kill_only_users,
- char ***kill_exclude_users,
- bool *debug) {
-
- unsigned i;
-
- assert(argc >= 0);
- assert(argc == 0 || argv);
-
- for (i = 0; i < (unsigned) argc; i++) {
- int k;
-
- if (startswith(argv[i], "kill-session-processes=")) {
- if ((k = parse_boolean(argv[i] + 23)) < 0) {
- pam_syslog(handle, LOG_ERR, "Failed to parse kill-session-processes= argument.");
- return k;
- }
-
- if (kill_processes)
- *kill_processes = k;
-
- } else if (startswith(argv[i], "kill-session=")) {
- /* As compatibility for old versions */
-
- if ((k = parse_boolean(argv[i] + 13)) < 0) {
- pam_syslog(handle, LOG_ERR, "Failed to parse kill-session= argument.");
- return k;
- }
-
- if (kill_processes)
- *kill_processes = k;
-
- } else if (startswith(argv[i], "controllers=")) {
-
- if (controllers) {
- char **l;
-
- if (!(l = strv_split(argv[i] + 12, ","))) {
- pam_syslog(handle, LOG_ERR, "Out of memory.");
- return -ENOMEM;
- }
-
- strv_free(*controllers);
- *controllers = l;
- }
-
- } else if (startswith(argv[i], "reset-controllers=")) {
-
- if (reset_controllers) {
- char **l;
-
- if (!(l = strv_split(argv[i] + 18, ","))) {
- pam_syslog(handle, LOG_ERR, "Out of memory.");
- return -ENOMEM;
- }
-
- strv_free(*reset_controllers);
- *reset_controllers = l;
- }
-
- } else if (startswith(argv[i], "kill-only-users=")) {
-
- if (kill_only_users) {
- char **l;
-
- if (!(l = strv_split(argv[i] + 16, ","))) {
- pam_syslog(handle, LOG_ERR, "Out of memory.");
- return -ENOMEM;
- }
-
- strv_free(*kill_only_users);
- *kill_only_users = l;
- }
-
- } else if (startswith(argv[i], "kill-exclude-users=")) {
-
- if (kill_exclude_users) {
- char **l;
-
- if (!(l = strv_split(argv[i] + 19, ","))) {
- pam_syslog(handle, LOG_ERR, "Out of memory.");
- return -ENOMEM;
- }
-
- strv_free(*kill_exclude_users);
- *kill_exclude_users = l;
- }
-
- } else if (startswith(argv[i], "debug=")) {
- if ((k = parse_boolean(argv[i] + 6)) < 0) {
- pam_syslog(handle, LOG_ERR, "Failed to parse debug= argument.");
- return k;
- }
-
- if (debug)
- *debug = k;
-
- } else if (startswith(argv[i], "create-session=") ||
- startswith(argv[i], "kill-user=")) {
-
- pam_syslog(handle, LOG_WARNING, "Option %s not supported anymore, ignoring.", argv[i]);
-
- } else {
- pam_syslog(handle, LOG_ERR, "Unknown parameter '%s'.", argv[i]);
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
-static int get_user_data(
- pam_handle_t *handle,
- const char **ret_username,
- struct passwd **ret_pw) {
-
- const char *username = NULL;
- struct passwd *pw = NULL;
- uid_t uid;
- int r;
-
- assert(handle);
- assert(ret_username);
- assert(ret_pw);
-
- r = audit_loginuid_from_pid(0, &uid);
- if (r >= 0)
- pw = pam_modutil_getpwuid(handle, uid);
- else {
- r = pam_get_user(handle, &username, NULL);
- if (r != PAM_SUCCESS) {
- pam_syslog(handle, LOG_ERR, "Failed to get user name.");
- return r;
- }
-
- if (isempty(username)) {
- pam_syslog(handle, LOG_ERR, "User name not valid.");
- return PAM_AUTH_ERR;
- }
-
- pw = pam_modutil_getpwnam(handle, username);
- }
-
- if (!pw) {
- pam_syslog(handle, LOG_ERR, "Failed to get user data.");
- return PAM_USER_UNKNOWN;
- }
-
- *ret_pw = pw;
- *ret_username = username ? username : pw->pw_name;
-
- return PAM_SUCCESS;
-}
-
-static bool check_user_lists(
- pam_handle_t *handle,
- uid_t uid,
- char **kill_only_users,
- char **kill_exclude_users) {
-
- const char *name = NULL;
- char **l;
-
- assert(handle);
-
- if (uid == 0)
- name = "root"; /* Avoid obvious NSS requests, to suppress network traffic */
- else {
- struct passwd *pw;
-
- pw = pam_modutil_getpwuid(handle, uid);
- if (pw)
- name = pw->pw_name;
- }
-
- STRV_FOREACH(l, kill_exclude_users) {
- uid_t u;
-
- if (parse_uid(*l, &u) >= 0)
- if (u == uid)
- return false;
-
- if (name && streq(name, *l))
- return false;
- }
-
- if (strv_isempty(kill_only_users))
- return true;
-
- STRV_FOREACH(l, kill_only_users) {
- uid_t u;
-
- if (parse_uid(*l, &u) >= 0)
- if (u == uid)
- return true;
-
- if (name && streq(name, *l))
- return true;
- }
-
- return false;
-}
-
-static int get_seat_from_display(const char *display, const char **seat, uint32_t *vtnr) {
- char *p = NULL;
- int r;
- int fd;
- union sockaddr_union sa;
- struct ucred ucred;
- socklen_t l;
- char *tty;
- int v;
-
- assert(display);
- assert(vtnr);
-
- /* We deduce the X11 socket from the display name, then use
- * SO_PEERCRED to determine the X11 server process, ask for
- * the controlling tty of that and if it's a VC then we know
- * the seat and the virtual terminal. Sounds ugly, is only
- * semi-ugly. */
-
- r = socket_from_display(display, &p);
- if (r < 0)
- return r;
-
- fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
- if (fd < 0) {
- free(p);
- return -errno;
- }
-
- zero(sa);
- sa.un.sun_family = AF_UNIX;
- strncpy(sa.un.sun_path, p, sizeof(sa.un.sun_path)-1);
- free(p);
-
- if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
- close_nointr_nofail(fd);
- return -errno;
- }
-
- l = sizeof(ucred);
- r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l);
- close_nointr_nofail(fd);
-
- if (r < 0)
- return -errno;
-
- r = get_ctty(ucred.pid, NULL, &tty);
- if (r < 0)
- return r;
-
- v = vtnr_from_tty(tty);
- free(tty);
-
- if (v < 0)
- return v;
- else if (v == 0)
- return -ENOENT;
-
- if (seat)
- *seat = "seat0";
- *vtnr = (uint32_t) v;
-
- return 0;
-}
-
-_public_ PAM_EXTERN int pam_sm_open_session(
- pam_handle_t *handle,
- int flags,
- int argc, const char **argv) {
-
- struct passwd *pw;
- bool kill_processes = false, debug = false;
- const char *username, *id, *object_path, *runtime_path, *service = NULL, *tty = NULL, *display = NULL, *remote_user = NULL, *remote_host = NULL, *seat = NULL, *type, *class, *cvtnr = NULL;
- char **controllers = NULL, **reset_controllers = NULL, **kill_only_users = NULL, **kill_exclude_users = NULL;
- DBusError error;
- uint32_t uid, pid;
- DBusMessageIter iter;
- dbus_bool_t kp;
- int session_fd = -1;
- DBusConnection *bus = NULL;
- DBusMessage *m = NULL, *reply = NULL;
- dbus_bool_t remote, existing;
- int r;
- uint32_t vtnr = 0;
-
- assert(handle);
-
- dbus_error_init(&error);
-
- /* pam_syslog(handle, LOG_INFO, "pam-systemd initializing"); */
-
- /* Make this a NOP on non-systemd systems */
- if (sd_booted() <= 0)
- return PAM_SUCCESS;
-
- if (parse_argv(handle,
- argc, argv,
- &controllers, &reset_controllers,
- &kill_processes, &kill_only_users, &kill_exclude_users,
- &debug) < 0) {
- r = PAM_SESSION_ERR;
- goto finish;
- }
-
- r = get_user_data(handle, &username, &pw);
- if (r != PAM_SUCCESS)
- goto finish;
-
- /* Make sure we don't enter a loop by talking to
- * systemd-logind when it is actually waiting for the
- * background to finish start-up. If the service is
- * "systemd-shared" we simply set XDG_RUNTIME_DIR and
- * leave. */
-
- pam_get_item(handle, PAM_SERVICE, (const void**) &service);
- if (streq_ptr(service, "systemd-shared")) {
- char *p, *rt = NULL;
-
- if (asprintf(&p, "/run/systemd/users/%lu", (unsigned long) pw->pw_uid) < 0) {
- r = PAM_BUF_ERR;
- goto finish;
- }
-
- r = parse_env_file(p, NEWLINE,
- "RUNTIME", &rt,
- NULL);
- free(p);
-
- if (r < 0 && r != -ENOENT) {
- r = PAM_SESSION_ERR;
- free(rt);
- goto finish;
- }
-
- if (rt) {
- r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", rt, 0);
- free(rt);
-
- if (r != PAM_SUCCESS) {
- pam_syslog(handle, LOG_ERR, "Failed to set runtime dir.");
- goto finish;
- }
- }
-
- r = PAM_SUCCESS;
- goto finish;
- }
-
- if (kill_processes)
- kill_processes = check_user_lists(handle, pw->pw_uid, kill_only_users, kill_exclude_users);
-
- dbus_connection_set_change_sigpipe(FALSE);
-
- bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
- if (!bus) {
- pam_syslog(handle, LOG_ERR, "Failed to connect to system bus: %s", bus_error_message(&error));
- r = PAM_SESSION_ERR;
- goto finish;
- }
-
- m = dbus_message_new_method_call(
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "CreateSession");
- if (!m) {
- pam_syslog(handle, LOG_ERR, "Could not allocate create session message.");
- r = PAM_BUF_ERR;
- goto finish;
- }
-
- uid = pw->pw_uid;
- pid = getpid();
-
- pam_get_item(handle, PAM_XDISPLAY, (const void**) &display);
- pam_get_item(handle, PAM_TTY, (const void**) &tty);
- pam_get_item(handle, PAM_RUSER, (const void**) &remote_user);
- pam_get_item(handle, PAM_RHOST, (const void**) &remote_host);
-
- seat = pam_getenv(handle, "XDG_SEAT");
- if (isempty(seat))
- seat = getenv("XDG_SEAT");
-
- cvtnr = pam_getenv(handle, "XDG_VTNR");
- if (isempty(cvtnr))
- cvtnr = getenv("XDG_VTNR");
-
- service = strempty(service);
- tty = strempty(tty);
- display = strempty(display);
- remote_user = strempty(remote_user);
- remote_host = strempty(remote_host);
- seat = strempty(seat);
-
- if (strchr(tty, ':')) {
- /* A tty with a colon is usually an X11 display, place
- * there to show up in utmp. We rearrange things and
- * don't pretend that an X display was a tty */
-
- if (isempty(display))
- display = tty;
- tty = "";
- } else if (streq(tty, "cron")) {
- /* cron has been setting PAM_TTY to "cron" for a very long time
- * and it cannot stop doing that for compatibility reasons. */
- tty = "";
- }
-
- /* If this fails vtnr will be 0, that's intended */
- if (!isempty(cvtnr))
- safe_atou32(cvtnr, &vtnr);
-
- if (!isempty(display) && vtnr <= 0) {
- if (isempty(seat))
- get_seat_from_display(display, &seat, &vtnr);
- else if (streq(seat, "seat0"))
- get_seat_from_display(display, NULL, &vtnr);
- }
-
- type = !isempty(display) ? "x11" :
- !isempty(tty) ? "tty" : "unspecified";
-
- class = pam_getenv(handle, "XDG_SESSION_CLASS");
- if (isempty(class))
- class = getenv("XDG_SESSION_CLASS");
- if (isempty(class))
- class = "user";
-
- remote = !isempty(remote_host) &&
- !streq(remote_host, "localhost") &&
- !streq(remote_host, "localhost.localdomain");
-
- if (!dbus_message_append_args(m,
- DBUS_TYPE_UINT32, &uid,
- DBUS_TYPE_UINT32, &pid,
- DBUS_TYPE_STRING, &service,
- DBUS_TYPE_STRING, &type,
- DBUS_TYPE_STRING, &class,
- DBUS_TYPE_STRING, &seat,
- DBUS_TYPE_UINT32, &vtnr,
- DBUS_TYPE_STRING, &tty,
- DBUS_TYPE_STRING, &display,
- DBUS_TYPE_BOOLEAN, &remote,
- DBUS_TYPE_STRING, &remote_user,
- DBUS_TYPE_STRING, &remote_host,
- DBUS_TYPE_INVALID)) {
- pam_syslog(handle, LOG_ERR, "Could not attach parameters to message.");
- r = PAM_BUF_ERR;
- goto finish;
- }
-
- dbus_message_iter_init_append(m, &iter);
-
- r = bus_append_strv_iter(&iter, controllers);
- if (r < 0) {
- pam_syslog(handle, LOG_ERR, "Could not attach parameter to message.");
- r = PAM_BUF_ERR;
- goto finish;
- }
-
- r = bus_append_strv_iter(&iter, reset_controllers);
- if (r < 0) {
- pam_syslog(handle, LOG_ERR, "Could not attach parameter to message.");
- r = PAM_BUF_ERR;
- goto finish;
- }
-
- kp = kill_processes;
- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &kp)) {
- pam_syslog(handle, LOG_ERR, "Could not attach parameter to message.");
- r = PAM_BUF_ERR;
- goto finish;
- }
-
- if (debug)
- pam_syslog(handle, LOG_DEBUG, "Asking logind to create session: "
- "uid=%u pid=%u service=%s type=%s class=%s seat=%s vtnr=%u tty=%s display=%s remote=%s remote_user=%s remote_host=%s",
- uid, pid, service, type, class, seat, vtnr, tty, display, yes_no(remote), remote_user, remote_host);
-
- reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
- if (!reply) {
- pam_syslog(handle, LOG_ERR, "Failed to create session: %s", bus_error_message(&error));
- r = PAM_SESSION_ERR;
- goto finish;
- }
-
- if (!dbus_message_get_args(reply, &error,
- DBUS_TYPE_STRING, &id,
- DBUS_TYPE_OBJECT_PATH, &object_path,
- DBUS_TYPE_STRING, &runtime_path,
- DBUS_TYPE_UNIX_FD, &session_fd,
- DBUS_TYPE_STRING, &seat,
- DBUS_TYPE_UINT32, &vtnr,
- DBUS_TYPE_BOOLEAN, &existing,
- DBUS_TYPE_INVALID)) {
- pam_syslog(handle, LOG_ERR, "Failed to parse message: %s", bus_error_message(&error));
- r = PAM_SESSION_ERR;
- goto finish;
- }
-
- if (debug)
- pam_syslog(handle, LOG_DEBUG, "Reply from logind: "
- "id=%s object_path=%s runtime_path=%s session_fd=%d seat=%s vtnr=%u",
- id, object_path, runtime_path, session_fd, seat, vtnr);
-
- r = pam_misc_setenv(handle, "XDG_SESSION_ID", id, 0);
- if (r != PAM_SUCCESS) {
- pam_syslog(handle, LOG_ERR, "Failed to set session id.");
- goto finish;
- }
-
- r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", runtime_path, 0);
- if (r != PAM_SUCCESS) {
- pam_syslog(handle, LOG_ERR, "Failed to set runtime dir.");
- goto finish;
- }
-
- if (!isempty(seat)) {
- r = pam_misc_setenv(handle, "XDG_SEAT", seat, 0);
- if (r != PAM_SUCCESS) {
- pam_syslog(handle, LOG_ERR, "Failed to set seat.");
- goto finish;
- }
- }
-
- if (vtnr > 0) {
- char buf[11];
- snprintf(buf, sizeof(buf), "%u", vtnr);
- char_array_0(buf);
-
- r = pam_misc_setenv(handle, "XDG_VTNR", buf, 0);
- if (r != PAM_SUCCESS) {
- pam_syslog(handle, LOG_ERR, "Failed to set virtual terminal number.");
- goto finish;
- }
- }
-
- r = pam_set_data(handle, "systemd.existing", INT_TO_PTR(!!existing), NULL);
- if (r != PAM_SUCCESS) {
- pam_syslog(handle, LOG_ERR, "Failed to install existing flag.");
- return r;
- }
-
- if (session_fd >= 0) {
- r = pam_set_data(handle, "systemd.session-fd", INT_TO_PTR(session_fd+1), NULL);
- if (r != PAM_SUCCESS) {
- pam_syslog(handle, LOG_ERR, "Failed to install session fd.");
- return r;
- }
- }
-
- session_fd = -1;
-
- r = PAM_SUCCESS;
-
-finish:
- strv_free(controllers);
- strv_free(reset_controllers);
- strv_free(kill_only_users);
- strv_free(kill_exclude_users);
-
- dbus_error_free(&error);
-
- if (bus) {
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
- }
-
- if (m)
- dbus_message_unref(m);
-
- if (reply)
- dbus_message_unref(reply);
-
- if (session_fd >= 0)
- close_nointr_nofail(session_fd);
-
- return r;
-}
-
-_public_ PAM_EXTERN int pam_sm_close_session(
- pam_handle_t *handle,
- int flags,
- int argc, const char **argv) {
-
- const void *p = NULL, *existing = NULL;
- const char *id;
- DBusConnection *bus = NULL;
- DBusMessage *m = NULL, *reply = NULL;
- DBusError error;
- int r;
-
- assert(handle);
-
- dbus_error_init(&error);
-
- /* Only release session if it wasn't pre-existing when we
- * tried to create it */
- pam_get_data(handle, "systemd.existing", &existing);
-
- id = pam_getenv(handle, "XDG_SESSION_ID");
- if (id && !existing) {
-
- /* Before we go and close the FIFO we need to tell
- * logind that this is a clean session shutdown, so
- * that it doesn't just go and slaughter us
- * immediately after closing the fd */
-
- bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
- if (!bus) {
- pam_syslog(handle, LOG_ERR, "Failed to connect to system bus: %s", bus_error_message(&error));
- r = PAM_SESSION_ERR;
- goto finish;
- }
-
- m = dbus_message_new_method_call(
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "ReleaseSession");
- if (!m) {
- pam_syslog(handle, LOG_ERR, "Could not allocate release session message.");
- r = PAM_BUF_ERR;
- goto finish;
- }
-
- if (!dbus_message_append_args(m,
- DBUS_TYPE_STRING, &id,
- DBUS_TYPE_INVALID)) {
- pam_syslog(handle, LOG_ERR, "Could not attach parameters to message.");
- r = PAM_BUF_ERR;
- goto finish;
- }
-
- reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
- if (!reply) {
- pam_syslog(handle, LOG_ERR, "Failed to release session: %s", bus_error_message(&error));
- r = PAM_SESSION_ERR;
- goto finish;
- }
- }
-
- r = PAM_SUCCESS;
-
-finish:
- pam_get_data(handle, "systemd.session-fd", &p);
- if (p)
- close_nointr(PTR_TO_INT(p) - 1);
-
- dbus_error_free(&error);
-
- if (bus) {
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
- }
-
- if (m)
- dbus_message_unref(m);
-
- if (reply)
- dbus_message_unref(reply);
-
- return r;
-}
diff --git a/src/login/sd-login.c b/src/login/sd-login.c
deleted file mode 100644
index 45e3bb8dcd..0000000000
--- a/src/login/sd-login.c
+++ /dev/null
@@ -1,794 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/inotify.h>
-
-#include "util.h"
-#include "cgroup-util.h"
-#include "macro.h"
-#include "sd-login.h"
-#include "strv.h"
-
-_public_ int sd_pid_get_session(pid_t pid, char **session) {
- int r;
- char *cgroup, *p;
-
- if (pid < 0)
- return -EINVAL;
-
- if (!session)
- return -EINVAL;
-
- r = cg_pid_get_cgroup(pid, NULL, &cgroup);
- if (r < 0)
- return r;
-
- if (!startswith(cgroup, "/user/")) {
- free(cgroup);
- return -ENOENT;
- }
-
- p = strchr(cgroup + 6, '/');
- if (!p) {
- free(cgroup);
- return -ENOENT;
- }
-
- p++;
- if (startswith(p, "shared/") || streq(p, "shared")) {
- free(cgroup);
- return -ENOENT;
- }
-
- p = strndup(p, strcspn(p, "/"));
- free(cgroup);
-
- if (!p)
- return -ENOMEM;
-
- *session = p;
- return 0;
-}
-
-_public_ int sd_pid_get_unit(pid_t pid, char **unit) {
-
- if (pid < 0)
- return -EINVAL;
-
- if (!unit)
- return -EINVAL;
-
- return cg_pid_get_unit(pid, unit);
-}
-
-_public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) {
- int r;
- char *root, *cgroup, *p, *cc;
- struct stat st;
-
- if (pid < 0)
- return -EINVAL;
-
- if (!uid)
- return -EINVAL;
-
- r = cg_pid_get_cgroup(pid, &root, &cgroup);
- if (r < 0)
- return r;
-
- if (!startswith(cgroup, "/user/")) {
- free(cgroup);
- free(root);
- return -ENOENT;
- }
-
- p = strchr(cgroup + 6, '/');
- if (!p) {
- free(cgroup);
- return -ENOENT;
- }
-
- p++;
- p += strcspn(p, "/");
- *p = 0;
-
- r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, root, cgroup, &cc);
- free(root);
- free(cgroup);
-
- if (r < 0)
- return -ENOMEM;
-
- r = lstat(cc, &st);
- free(cc);
-
- if (r < 0)
- return -errno;
-
- if (!S_ISDIR(st.st_mode))
- return -ENOTDIR;
-
- *uid = st.st_uid;
- return 0;
-}
-
-_public_ int sd_uid_get_state(uid_t uid, char**state) {
- char *p, *s = NULL;
- int r;
-
- if (!state)
- return -EINVAL;
-
- if (asprintf(&p, "/run/systemd/users/%lu", (unsigned long) uid) < 0)
- return -ENOMEM;
-
- r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
- free(p);
-
- if (r == -ENOENT) {
- free(s);
- s = strdup("offline");
- if (!s)
- return -ENOMEM;
-
- *state = s;
- return 0;
- } else if (r < 0) {
- free(s);
- return r;
- } else if (!s)
- return -EIO;
-
- *state = s;
- return 0;
-}
-
-_public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) {
- char *p, *w, *t, *state, *s = NULL;
- size_t l;
- int r;
- const char *variable;
-
- if (!seat)
- return -EINVAL;
-
- variable = require_active ? "ACTIVE_UID" : "UIDS";
-
- p = strappend("/run/systemd/seats/", seat);
- if (!p)
- return -ENOMEM;
-
- r = parse_env_file(p, NEWLINE, variable, &s, NULL);
- free(p);
-
- if (r < 0) {
- free(s);
- return r;
- }
-
- if (!s)
- return -EIO;
-
- if (asprintf(&t, "%lu", (unsigned long) uid) < 0) {
- free(s);
- return -ENOMEM;
- }
-
- FOREACH_WORD(w, l, s, state) {
- if (strncmp(t, w, l) == 0) {
- free(s);
- free(t);
-
- return 1;
- }
- }
-
- free(s);
- free(t);
-
- return 0;
-}
-
-static int uid_get_array(uid_t uid, const char *variable, char ***array) {
- char *p, *s = NULL;
- char **a;
- int r;
-
- if (asprintf(&p, "/run/systemd/users/%lu", (unsigned long) uid) < 0)
- return -ENOMEM;
-
- r = parse_env_file(p, NEWLINE,
- variable, &s,
- NULL);
- free(p);
-
- if (r < 0) {
- free(s);
-
- if (r == -ENOENT) {
- if (array)
- *array = NULL;
- return 0;
- }
-
- return r;
- }
-
- if (!s) {
- if (array)
- *array = NULL;
- return 0;
- }
-
- a = strv_split(s, " ");
- free(s);
-
- if (!a)
- return -ENOMEM;
-
- strv_uniq(a);
- r = strv_length(a);
-
- if (array)
- *array = a;
- else
- strv_free(a);
-
- return r;
-}
-
-_public_ int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions) {
- return uid_get_array(
- uid,
- require_active == 0 ? "ONLINE_SESSIONS" :
- require_active > 0 ? "ACTIVE_SESSIONS" :
- "SESSIONS",
- sessions);
-}
-
-_public_ int sd_uid_get_seats(uid_t uid, int require_active, char ***seats) {
- return uid_get_array(
- uid,
- require_active == 0 ? "ONLINE_SEATS" :
- require_active > 0 ? "ACTIVE_SEATS" :
- "SEATS",
- seats);
-}
-
-static int file_of_session(const char *session, char **_p) {
- char *p;
- int r;
-
- assert(_p);
-
- if (session)
- p = strappend("/run/systemd/sessions/", session);
- else {
- char *buf;
-
- r = sd_pid_get_session(0, &buf);
- if (r < 0)
- return r;
-
- p = strappend("/run/systemd/sessions/", buf);
- free(buf);
- }
-
- if (!p)
- return -ENOMEM;
-
- *_p = p;
- return 0;
-}
-
-_public_ int sd_session_is_active(const char *session) {
- int r;
- char *p, *s = NULL;
-
- r = file_of_session(session, &p);
- if (r < 0)
- return r;
-
- r = parse_env_file(p, NEWLINE, "ACTIVE", &s, NULL);
- free(p);
-
- if (r < 0) {
- free(s);
- return r;
- }
-
- if (!s)
- return -EIO;
-
- r = parse_boolean(s);
- free(s);
-
- return r;
-}
-
-_public_ int sd_session_get_state(const char *session, char **state) {
- char *p, *s = NULL;
- int r;
-
- if (!state)
- return -EINVAL;
-
- r = file_of_session(session, &p);
- if (r < 0)
- return r;
-
- r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
- free(p);
-
- if (r < 0) {
- free(s);
- return r;
- } else if (!s)
- return -EIO;
-
- *state = s;
- return 0;
-}
-
-_public_ int sd_session_get_uid(const char *session, uid_t *uid) {
- int r;
- char *p, *s = NULL;
-
- if (!uid)
- return -EINVAL;
-
- r = file_of_session(session, &p);
- if (r < 0)
- return r;
-
- r = parse_env_file(p, NEWLINE, "UID", &s, NULL);
- free(p);
-
- if (r < 0) {
- free(s);
- return r;
- }
-
- if (!s)
- return -EIO;
-
- r = parse_uid(s, uid);
- free(s);
-
- return r;
-}
-
-static int session_get_string(const char *session, const char *field, char **value) {
- char *p, *s = NULL;
- int r;
-
- if (!value)
- return -EINVAL;
-
- r = file_of_session(session, &p);
- if (r < 0)
- return r;
-
- r = parse_env_file(p, NEWLINE, field, &s, NULL);
- free(p);
-
- if (r < 0) {
- free(s);
- return r;
- }
-
- if (isempty(s))
- return -ENOENT;
-
- *value = s;
- return 0;
-}
-
-_public_ int sd_session_get_seat(const char *session, char **seat) {
- return session_get_string(session, "SEAT", seat);
-}
-
-_public_ int sd_session_get_service(const char *session, char **service) {
- return session_get_string(session, "SERVICE", service);
-}
-
-_public_ int sd_session_get_type(const char *session, char **type) {
- return session_get_string(session, "TYPE", type);
-}
-
-_public_ int sd_session_get_class(const char *session, char **class) {
- return session_get_string(session, "CLASS", class);
-}
-
-_public_ int sd_session_get_display(const char *session, char **display) {
- return session_get_string(session, "DISPLAY", display);
-}
-
-static int file_of_seat(const char *seat, char **_p) {
- char *p;
- int r;
-
- assert(_p);
-
- if (seat)
- p = strappend("/run/systemd/seats/", seat);
- else {
- char *buf;
-
- r = sd_session_get_seat(NULL, &buf);
- if (r < 0)
- return r;
-
- p = strappend("/run/systemd/seats/", buf);
- free(buf);
- }
-
- if (!p)
- return -ENOMEM;
-
- *_p = p;
- return 0;
-}
-
-_public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
- char *p, *s = NULL, *t = NULL;
- int r;
-
- if (!session && !uid)
- return -EINVAL;
-
- r = file_of_seat(seat, &p);
- if (r < 0)
- return r;
-
- r = parse_env_file(p, NEWLINE,
- "ACTIVE", &s,
- "ACTIVE_UID", &t,
- NULL);
- free(p);
-
- if (r < 0) {
- free(s);
- free(t);
- return r;
- }
-
- if (session && !s) {
- free(t);
- return -ENOENT;
- }
-
- if (uid && !t) {
- free(s);
- return -ENOENT;
- }
-
- if (uid && t) {
- r = parse_uid(t, uid);
- if (r < 0) {
- free(t);
- free(s);
- return r;
- }
- }
-
- free(t);
-
- if (session && s)
- *session = s;
- else
- free(s);
-
- return 0;
-}
-
-_public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uids, unsigned *n_uids) {
- char *p, *s = NULL, *t = NULL, **a = NULL;
- uid_t *b = NULL;
- unsigned n = 0;
- int r;
-
- r = file_of_seat(seat, &p);
- if (r < 0)
- return r;
-
- r = parse_env_file(p, NEWLINE,
- "SESSIONS", &s,
- "ACTIVE_SESSIONS", &t,
- NULL);
- free(p);
-
- if (r < 0) {
- free(s);
- free(t);
- return r;
- }
-
- if (s) {
- a = strv_split(s, " ");
- if (!a) {
- free(s);
- free(t);
- return -ENOMEM;
- }
- }
-
- free(s);
-
- if (uids && t) {
- char *w, *state;
- size_t l;
-
- FOREACH_WORD(w, l, t, state)
- n++;
-
- if (n == 0)
- b = NULL;
- else {
- unsigned i = 0;
-
- b = new(uid_t, n);
- if (!b) {
- strv_free(a);
- return -ENOMEM;
- }
-
- FOREACH_WORD(w, l, t, state) {
- char *k;
-
- k = strndup(w, l);
- if (!k) {
- free(t);
- free(b);
- strv_free(a);
- return -ENOMEM;
- }
-
- r = parse_uid(k, b + i);
- free(k);
- if (r < 0)
- continue;
-
- i++;
- }
- }
- }
-
- free(t);
-
- r = strv_length(a);
-
- if (sessions)
- *sessions = a;
- else
- strv_free(a);
-
- if (uids)
- *uids = b;
-
- if (n_uids)
- *n_uids = n;
-
- return r;
-}
-
-static int seat_get_can(const char *seat, const char *variable) {
- char *p, *s = NULL;
- int r;
-
- r = file_of_seat(seat, &p);
- if (r < 0)
- return r;
-
- r = parse_env_file(p, NEWLINE,
- variable, &s,
- NULL);
- free(p);
-
- if (r < 0) {
- free(s);
- return r;
- }
-
- if (s) {
- r = parse_boolean(s);
- free(s);
- } else
- r = 0;
-
- return r;
-}
-
-_public_ int sd_seat_can_multi_session(const char *seat) {
- return seat_get_can(seat, "CAN_MULTI_SESSION");
-}
-
-_public_ int sd_seat_can_tty(const char *seat) {
- return seat_get_can(seat, "CAN_TTY");
-}
-
-_public_ int sd_seat_can_graphical(const char *seat) {
- return seat_get_can(seat, "CAN_GRAPHICAL");
-}
-
-_public_ int sd_get_seats(char ***seats) {
- return get_files_in_directory("/run/systemd/seats/", seats);
-}
-
-_public_ int sd_get_sessions(char ***sessions) {
- return get_files_in_directory("/run/systemd/sessions/", sessions);
-}
-
-_public_ int sd_get_uids(uid_t **users) {
- DIR *d;
- int r = 0;
- unsigned n = 0;
- uid_t *l = NULL;
-
- d = opendir("/run/systemd/users/");
- if (!d)
- return -errno;
-
- for (;;) {
- struct dirent *de;
- union dirent_storage buf;
- int k;
- uid_t uid;
-
- k = readdir_r(d, &buf.de, &de);
- if (k != 0) {
- r = -k;
- goto finish;
- }
-
- if (!de)
- break;
-
- dirent_ensure_type(d, de);
-
- if (!dirent_is_file(de))
- continue;
-
- k = parse_uid(de->d_name, &uid);
- if (k < 0)
- continue;
-
- if (users) {
- if ((unsigned) r >= n) {
- uid_t *t;
-
- n = MAX(16, 2*r);
- t = realloc(l, sizeof(uid_t) * n);
- if (!t) {
- r = -ENOMEM;
- goto finish;
- }
-
- l = t;
- }
-
- assert((unsigned) r < n);
- l[r++] = uid;
- } else
- r++;
- }
-
-finish:
- if (d)
- closedir(d);
-
- if (r >= 0) {
- if (users)
- *users = l;
- } else
- free(l);
-
- return r;
-}
-
-static inline int MONITOR_TO_FD(sd_login_monitor *m) {
- return (int) (unsigned long) m - 1;
-}
-
-static inline sd_login_monitor* FD_TO_MONITOR(int fd) {
- return (sd_login_monitor*) (unsigned long) (fd + 1);
-}
-
-_public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) {
- int fd, k;
- bool good = false;
-
- if (!m)
- return -EINVAL;
-
- fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
- if (fd < 0)
- return errno;
-
- if (!category || streq(category, "seat")) {
- k = inotify_add_watch(fd, "/run/systemd/seats/", IN_MOVED_TO|IN_DELETE);
- if (k < 0) {
- close_nointr_nofail(fd);
- return -errno;
- }
-
- good = true;
- }
-
- if (!category || streq(category, "session")) {
- k = inotify_add_watch(fd, "/run/systemd/sessions/", IN_MOVED_TO|IN_DELETE);
- if (k < 0) {
- close_nointr_nofail(fd);
- return -errno;
- }
-
- good = true;
- }
-
- if (!category || streq(category, "uid")) {
- k = inotify_add_watch(fd, "/run/systemd/users/", IN_MOVED_TO|IN_DELETE);
- if (k < 0) {
- close_nointr_nofail(fd);
- return -errno;
- }
-
- good = true;
- }
-
- if (!good) {
- close_nointr(fd);
- return -EINVAL;
- }
-
- *m = FD_TO_MONITOR(fd);
- return 0;
-}
-
-_public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) {
- int fd;
-
- if (!m)
- return NULL;
-
- fd = MONITOR_TO_FD(m);
- close_nointr(fd);
-
- return NULL;
-}
-
-_public_ int sd_login_monitor_flush(sd_login_monitor *m) {
-
- if (!m)
- return -EINVAL;
-
- return flush_fd(MONITOR_TO_FD(m));
-}
-
-_public_ int sd_login_monitor_get_fd(sd_login_monitor *m) {
-
- if (!m)
- return -EINVAL;
-
- return MONITOR_TO_FD(m);
-}
diff --git a/src/login/sysfs-show.c b/src/login/sysfs-show.c
deleted file mode 100644
index d113ec3e43..0000000000
--- a/src/login/sysfs-show.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*-*- 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 <errno.h>
-#include <string.h>
-#include <libudev.h>
-
-#include "util.h"
-#include "sysfs-show.h"
-#include "path-util.h"
-
-static int show_sysfs_one(
- struct udev *udev,
- const char *seat,
- struct udev_list_entry **item,
- const char *sub,
- const char *prefix,
- unsigned n_columns) {
-
- assert(udev);
- assert(seat);
- assert(item);
- assert(prefix);
-
- while (*item) {
- struct udev_list_entry *next, *lookahead;
- struct udev_device *d;
- const char *sn, *name, *sysfs, *subsystem, *sysname;
- char *l, *k;
-
- sysfs = udev_list_entry_get_name(*item);
- if (!path_startswith(sysfs, sub))
- return 0;
-
- d = udev_device_new_from_syspath(udev, sysfs);
- if (!d) {
- *item = udev_list_entry_get_next(*item);
- continue;
- }
-
- sn = udev_device_get_property_value(d, "ID_SEAT");
- if (isempty(sn))
- sn = "seat0";
-
- /* fixme, also check for tag 'seat' here */
- if (!streq(seat, sn) || !udev_device_has_tag(d, "seat")) {
- udev_device_unref(d);
- *item = udev_list_entry_get_next(*item);
- continue;
- }
-
- name = udev_device_get_sysattr_value(d, "name");
- if (!name)
- name = udev_device_get_sysattr_value(d, "id");
- subsystem = udev_device_get_subsystem(d);
- sysname = udev_device_get_sysname(d);
-
- /* Look if there's more coming after this */
- lookahead = next = udev_list_entry_get_next(*item);
- while (lookahead) {
- const char *lookahead_sysfs;
-
- lookahead_sysfs = udev_list_entry_get_name(lookahead);
-
- if (path_startswith(lookahead_sysfs, sub) &&
- !path_startswith(lookahead_sysfs, sysfs)) {
- struct udev_device *lookahead_d;
-
- lookahead_d = udev_device_new_from_syspath(udev, lookahead_sysfs);
- if (lookahead_d) {
- const char *lookahead_sn;
- bool found;
-
- lookahead_sn = udev_device_get_property_value(d, "ID_SEAT");
- if (isempty(lookahead_sn))
- lookahead_sn = "seat0";
-
- found = streq(seat, lookahead_sn) && udev_device_has_tag(lookahead_d, "seat");
- udev_device_unref(lookahead_d);
-
- if (found)
- break;
- }
- }
-
- lookahead = udev_list_entry_get_next(lookahead);
- }
-
- k = ellipsize(sysfs, n_columns, 20);
- printf("%s%s%s\n", prefix, draw_special_char(lookahead ? DRAW_TREE_BRANCH : DRAW_TREE_RIGHT),
- k ? k : sysfs);
- free(k);
-
- if (asprintf(&l,
- "(%s:%s)%s%s%s",
- subsystem, sysname,
- name ? " \"" : "", name ? name : "", name ? "\"" : "") < 0) {
- udev_device_unref(d);
- return -ENOMEM;
- }
-
- k = ellipsize(l, n_columns, 70);
- printf("%s%s%s\n", prefix, lookahead ? draw_special_char(DRAW_TREE_VERT) : " ",
- k ? k : l);
- free(k);
- free(l);
-
- *item = next;
- if (*item) {
- char *p;
-
- p = strappend(prefix, lookahead ? draw_special_char(DRAW_TREE_VERT) : " ");
- show_sysfs_one(udev, seat, item, sysfs, p ? p : prefix, n_columns - 2);
- free(p);
- }
-
- udev_device_unref(d);
- }
-
- return 0;
-}
-
-int show_sysfs(const char *seat, const char *prefix, unsigned n_columns) {
- struct udev *udev;
- struct udev_list_entry *first = NULL;
- struct udev_enumerate *e;
- int r;
-
- if (n_columns <= 0)
- n_columns = columns();
-
- if (!prefix)
- prefix = "";
-
- if (isempty(seat))
- seat = "seat0";
-
- udev = udev_new();
- if (!udev)
- return -ENOMEM;
-
- e = udev_enumerate_new(udev);
- if (!e) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (!streq(seat, "seat0"))
- r = udev_enumerate_add_match_tag(e, seat);
- else
- r = udev_enumerate_add_match_tag(e, "seat");
-
- if (r < 0)
- goto finish;
-
- r = udev_enumerate_scan_devices(e);
- if (r < 0)
- goto finish;
-
- first = udev_enumerate_get_list_entry(e);
- if (first)
- show_sysfs_one(udev, seat, &first, "/", prefix, n_columns);
-
-finish:
- if (e)
- udev_enumerate_unref(e);
-
- if (udev)
- udev_unref(udev);
-
- return r;
-}
diff --git a/src/login/test-inhibit.c b/src/login/test-inhibit.c
deleted file mode 100644
index 7b6deffc3e..0000000000
--- a/src/login/test-inhibit.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <unistd.h>
-
-#include <dbus/dbus.h>
-
-#include "macro.h"
-#include "util.h"
-#include "dbus-common.h"
-
-static int inhibit(DBusConnection *bus, const char *what) {
- DBusMessage *m, *reply;
- DBusError error;
- const char *who = "Test Tool", *reason = "Just because!", *mode = "block";
- int fd;
-
- dbus_error_init(&error);
-
- m = dbus_message_new_method_call(
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "Inhibit");
- assert(m);
-
- assert_se(dbus_message_append_args(m,
- DBUS_TYPE_STRING, &what,
- DBUS_TYPE_STRING, &who,
- DBUS_TYPE_STRING, &reason,
- DBUS_TYPE_STRING, &mode,
- DBUS_TYPE_INVALID));
-
- reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
- assert(reply);
-
- assert(dbus_message_get_args(reply, &error,
- DBUS_TYPE_UNIX_FD, &fd,
- DBUS_TYPE_INVALID));
-
- dbus_message_unref(m);
- dbus_message_unref(reply);
-
- return fd;
-}
-
-static void print_inhibitors(DBusConnection *bus) {
- DBusMessage *m, *reply;
- DBusError error;
- unsigned n = 0;
- DBusMessageIter iter, sub, sub2;
-
- dbus_error_init(&error);
-
- m = dbus_message_new_method_call(
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "ListInhibitors");
- assert(m);
-
- reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
- assert(reply);
-
- assert(dbus_message_iter_init(reply, &iter));
- dbus_message_iter_recurse(&iter, &sub);
-
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- const char *what, *who, *why, *mode;
- dbus_uint32_t uid, pid;
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- assert_se(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) >= 0);
- assert_se(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) >= 0);
- assert_se(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) >= 0);
- assert_se(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) >= 0);
- assert_se(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) >= 0);
- assert_se(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) >= 0);
-
- printf("what=<%s> who=<%s> why=<%s> mode=<%s> uid=<%lu> pid=<%lu>\n",
- what, who, why, mode, (unsigned long) uid, (unsigned long) pid);
-
- dbus_message_iter_next(&sub);
-
- n++;
- }
-
- printf("%u inhibitors\n", n);
-
- dbus_message_unref(m);
- dbus_message_unref(reply);
-}
-
-int main(int argc, char*argv[]) {
- DBusConnection *bus;
- int fd1, fd2;
-
- bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, NULL);
- assert(bus);
-
- print_inhibitors(bus);
-
- fd1 = inhibit(bus, "sleep");
- assert(fd1 >= 0);
- print_inhibitors(bus);
-
- fd2 = inhibit(bus, "idle:shutdown");
- assert(fd2 >= 0);
- print_inhibitors(bus);
-
- close_nointr_nofail(fd1);
- sleep(1);
- print_inhibitors(bus);
-
- close_nointr_nofail(fd2);
- sleep(1);
- print_inhibitors(bus);
-
- return 0;
-}
diff --git a/src/login/test-login.c b/src/login/test-login.c
deleted file mode 100644
index 159ff3efc5..0000000000
--- a/src/login/test-login.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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/poll.h>
-#include <string.h>
-
-#include <systemd/sd-login.h>
-
-#include "util.h"
-#include "strv.h"
-
-int main(int argc, char* argv[]) {
- int r, k;
- uid_t u, u2;
- char *seat, *type, *class, *display;
- char *session;
- char *state;
- char *session2;
- char *t;
- char **seats, **sessions;
- uid_t *uids;
- unsigned n;
- struct pollfd pollfd;
- sd_login_monitor *m;
-
- assert_se(sd_pid_get_session(0, &session) == 0);
- printf("session = %s\n", session);
-
- assert_se(sd_pid_get_owner_uid(0, &u2) == 0);
- printf("user = %lu\n", (unsigned long) u2);
-
- r = sd_uid_get_sessions(u2, false, &sessions);
- assert_se(r >= 0);
- assert_se(r == (int) strv_length(sessions));
- assert_se(t = strv_join(sessions, ", "));
- strv_free(sessions);
- printf("sessions = %s\n", t);
- free(t);
-
- assert_se(r == sd_uid_get_sessions(u2, false, NULL));
-
- r = sd_uid_get_seats(u2, false, &seats);
- assert_se(r >= 0);
- assert_se(r == (int) strv_length(seats));
- assert_se(t = strv_join(seats, ", "));
- strv_free(seats);
- printf("seats = %s\n", t);
- free(t);
-
- assert_se(r == sd_uid_get_seats(u2, false, NULL));
-
- r = sd_session_is_active(session);
- assert_se(r >= 0);
- printf("active = %s\n", yes_no(r));
-
- r = sd_session_get_state(session, &state);
- assert_se(r >= 0);
- printf("state = %s\n", state);
- free(state);
-
- assert_se(sd_session_get_uid(session, &u) >= 0);
- printf("uid = %lu\n", (unsigned long) u);
- assert_se(u == u2);
-
- assert_se(sd_session_get_type(session, &type) >= 0);
- printf("type = %s\n", type);
- free(type);
-
- assert_se(sd_session_get_class(session, &class) >= 0);
- printf("class = %s\n", class);
- free(class);
-
- assert_se(sd_session_get_display(session, &display) >= 0);
- printf("display = %s\n", display);
- free(display);
-
- assert_se(sd_session_get_seat(session, &seat) >= 0);
- printf("seat = %s\n", seat);
-
- r = sd_seat_can_multi_session(seat);
- assert_se(r >= 0);
- printf("can do multi session = %s\n", yes_no(r));
-
- r = sd_seat_can_tty(seat);
- assert_se(r >= 0);
- printf("can do tty = %s\n", yes_no(r));
-
- r = sd_seat_can_graphical(seat);
- assert_se(r >= 0);
- printf("can do graphical = %s\n", yes_no(r));
-
- assert_se(sd_uid_get_state(u, &state) >= 0);
- printf("state = %s\n", state);
-
- assert_se(sd_uid_is_on_seat(u, 0, seat) > 0);
-
- k = sd_uid_is_on_seat(u, 1, seat);
- assert_se(k >= 0);
- assert_se(!!r == !!r);
-
- assert_se(sd_seat_get_active(seat, &session2, &u2) >= 0);
- printf("session2 = %s\n", session2);
- printf("uid2 = %lu\n", (unsigned long) u2);
-
- r = sd_seat_get_sessions(seat, &sessions, &uids, &n);
- assert_se(r >= 0);
- printf("n_sessions = %i\n", r);
- assert_se(r == (int) strv_length(sessions));
- assert_se(t = strv_join(sessions, ", "));
- strv_free(sessions);
- printf("sessions = %s\n", t);
- free(t);
- printf("uids =");
- for (k = 0; k < (int) n; k++)
- printf(" %lu", (unsigned long) uids[k]);
- printf("\n");
- free(uids);
-
- assert_se(sd_seat_get_sessions(seat, NULL, NULL, NULL) == r);
-
- free(session);
- free(state);
- free(session2);
- free(seat);
-
- r = sd_get_seats(&seats);
- assert_se(r >= 0);
- assert_se(r == (int) strv_length(seats));
- assert_se(t = strv_join(seats, ", "));
- strv_free(seats);
- printf("n_seats = %i\n", r);
- printf("seats = %s\n", t);
- free(t);
-
- assert_se(sd_get_seats(NULL) == r);
-
- r = sd_seat_get_active(NULL, &t, NULL);
- assert_se(r >= 0);
- printf("active session on current seat = %s\n", t);
- free(t);
-
- r = sd_get_sessions(&sessions);
- assert_se(r >= 0);
- assert_se(r == (int) strv_length(sessions));
- assert_se(t = strv_join(sessions, ", "));
- strv_free(sessions);
- printf("n_sessions = %i\n", r);
- printf("sessions = %s\n", t);
- free(t);
-
- assert_se(sd_get_sessions(NULL) == r);
-
- r = sd_get_uids(&uids);
- assert_se(r >= 0);
-
- printf("uids =");
- for (k = 0; k < r; k++)
- printf(" %lu", (unsigned long) uids[k]);
- printf("\n");
- free(uids);
-
- printf("n_uids = %i\n", r);
- assert_se(sd_get_uids(NULL) == r);
-
- r = sd_login_monitor_new("session", &m);
- assert_se(r >= 0);
-
- zero(pollfd);
- pollfd.fd = sd_login_monitor_get_fd(m);
- pollfd.events = POLLIN;
-
- for (n = 0; n < 5; n++) {
- r = poll(&pollfd, 1, -1);
- assert_se(r >= 0);
-
- sd_login_monitor_flush(m);
- printf("Wake!\n");
- }
-
- sd_login_monitor_unref(m);
-
- return 0;
-}
diff --git a/src/login/uaccess.c b/src/login/uaccess.c
deleted file mode 100644
index 2c530c8f39..0000000000
--- a/src/login/uaccess.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <errno.h>
-#include <string.h>
-
-#include <systemd/sd-daemon.h>
-#include <systemd/sd-login.h>
-
-#include "logind-acl.h"
-#include "util.h"
-#include "log.h"
-
-int main(int argc, char *argv[]) {
- int r;
- const char *path = NULL, *seat;
- bool changed_acl = false;
- uid_t uid;
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- if (argc < 2 || argc > 3) {
- log_error("This program expects one or two arguments.");
- r = -EINVAL;
- goto finish;
- }
-
- /* Make sure we don't muck around with ACLs the system is not
- * running systemd. */
- if (!sd_booted())
- return 0;
-
- path = argv[1];
- seat = argc < 3 || isempty(argv[2]) ? "seat0" : argv[2];
-
- r = sd_seat_get_active(seat, NULL, &uid);
- if (r == -ENOENT) {
- /* No active session on this seat */
- r = 0;
- goto finish;
- } else if (r < 0) {
- log_error("Failed to determine active user on seat %s.", seat);
- goto finish;
- }
-
- r = devnode_acl(path, true, false, 0, true, uid);
- if (r < 0) {
- log_error("Failed to apply ACL on %s: %s", path, strerror(-r));
- goto finish;
- }
-
- changed_acl = true;
- r = 0;
-
-finish:
- if (path && !changed_acl) {
- int k;
- /* Better be safe that sorry and reset ACL */
-
- k = devnode_acl(path, true, false, 0, false, 0);
- if (k < 0) {
- log_error("Failed to apply ACL on %s: %s", path, strerror(-k));
- if (r >= 0)
- r = k;
- }
- }
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/login/user-sessions.c b/src/login/user-sessions.c
deleted file mode 100644
index 91531e8f38..0000000000
--- a/src/login/user-sessions.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*-*- 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 <unistd.h>
-#include <errno.h>
-
-#include "log.h"
-#include "util.h"
-#include "cgroup-util.h"
-
-int main(int argc, char*argv[]) {
- int ret = EXIT_FAILURE;
-
- if (argc != 2) {
- log_error("This program requires one argument.");
- return EXIT_FAILURE;
- }
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- if (streq(argv[1], "start")) {
- int q = 0, r = 0;
-
- if (unlink("/run/nologin") < 0 && errno != ENOENT) {
- log_error("Failed to remove /run/nologin file: %m");
- r = -errno;
- }
-
- if (unlink("/etc/nologin") < 0 && errno != ENOENT) {
-
- /* If the file doesn't exist and /etc simply
- * was read-only (in which case unlink()
- * returns EROFS even if the file doesn't
- * exist), don't complain */
-
- if (errno != EROFS || access("/etc/nologin", F_OK) >= 0) {
- log_error("Failed to remove /etc/nologin file: %m");
- q = -errno;
- }
- }
-
- if (r < 0 || q < 0)
- goto finish;
-
- } else if (streq(argv[1], "stop")) {
- int r, q;
- char *cgroup_user_tree = NULL;
-
- r = write_one_line_file_atomic("/run/nologin", "System is going down.");
- if (r < 0)
- log_error("Failed to create /run/nologin: %s", strerror(-r));
-
- q = cg_get_user_path(&cgroup_user_tree);
- if (q < 0) {
- log_error("Failed to determine use path: %s", strerror(-q));
- goto finish;
- }
-
- q = cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, cgroup_user_tree, true);
- free(cgroup_user_tree);
- if (q < 0) {
- log_error("Failed to kill sessions: %s", strerror(-q));
- goto finish;
- }
-
- if (r < 0)
- goto finish;
-
- } else {
- log_error("Unknown verb %s.", argv[1]);
- goto finish;
- }
-
- ret = EXIT_SUCCESS;
-
-finish:
- return ret;
-}
diff --git a/src/machine-id-setup/Makefile b/src/machine-id-setup/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/machine-id-setup/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/machine-id-setup/machine-id-setup-main.c b/src/machine-id-setup/machine-id-setup-main.c
deleted file mode 100644
index 6373ebc2db..0000000000
--- a/src/machine-id-setup/machine-id-setup-main.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*-*- 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 <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <getopt.h>
-#include <errno.h>
-
-#include "machine-id-setup.h"
-#include "log.h"
-#include "build.h"
-
-static int help(void) {
-
- printf("%s [OPTIONS...]\n\n"
- "Initialize /etc/machine-id from a random source.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { NULL, 0, NULL, 0 }
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "hqcv", options, NULL)) >= 0) {
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(DISTRIBUTION);
- puts(SYSTEMD_FEATURES);
- return 0;
-
- case '?':
- return -EINVAL;
-
- default:
- log_error("Unknown option code %c", c);
- return -EINVAL;
- }
- }
-
- if (optind < argc) {
- help();
- return -EINVAL;
- }
-
- return 1;
-}
-
-int main(int argc, char *argv[]) {
- int r;
-
- log_parse_environment();
- log_open();
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-
- return machine_id_setup() < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/modules-load/Makefile b/src/modules-load/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/modules-load/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/modules-load/modules-load.c b/src/modules-load/modules-load.c
deleted file mode 100644
index e72e382e19..0000000000
--- a/src/modules-load/modules-load.c
+++ /dev/null
@@ -1,266 +0,0 @@
-/*-*- 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 <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <limits.h>
-#include <dirent.h>
-#include <libkmod.h>
-
-#include "log.h"
-#include "util.h"
-#include "strv.h"
-#include "conf-files.h"
-#include "virt.h"
-
-static char **arg_proc_cmdline_modules = NULL;
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wformat-nonliteral"
-static void systemd_kmod_log(void *data, int priority, const char *file, int line,
- const char *fn, const char *format, va_list args)
-{
- log_metav(priority, file, line, fn, format, args);
-}
-#pragma GCC diagnostic pop
-
-static int add_modules(const char *p) {
- char **t, **k;
-
- k = strv_split(p, ",");
- if (!k)
- return log_oom();
-
- t = strv_merge(arg_proc_cmdline_modules, k);
- strv_free(k);
- if (!t)
- return log_oom();
-
- strv_free(arg_proc_cmdline_modules);
- arg_proc_cmdline_modules = t;
-
- return 0;
-}
-
-static int parse_proc_cmdline(void) {
- char *line, *w, *state;
- int r;
- size_t l;
-
- if (detect_container(NULL) > 0)
- return 0;
-
- r = read_one_line_file("/proc/cmdline", &line);
- if (r < 0) {
- log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
- return 0;
- }
-
- FOREACH_WORD_QUOTED(w, l, line, state) {
- char *word;
-
- word = strndup(w, l);
- if (!word) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (startswith(word, "modules-load=")) {
-
- r = add_modules(word + 13);
- if (r < 0)
- goto finish;
-
- } else if (startswith(word, "rd.modules-load=")) {
-
- if (in_initrd()) {
- r = add_modules(word + 16);
- if (r < 0)
- goto finish;
- }
-
- }
-
- free(word);
- }
-
- r = 0;
-
-finish:
- free(line);
- return r;
-}
-
-static int load_module(struct kmod_ctx *ctx, const char *m) {
- const int probe_flags = KMOD_PROBE_APPLY_BLACKLIST;
- struct kmod_list *itr, *modlist = NULL;
- int r = 0;
-
- log_debug("load: %s\n", m);
-
- r = kmod_module_new_from_lookup(ctx, m, &modlist);
- if (r < 0) {
- log_error("Failed to lookup alias '%s': %s", m, strerror(-r));
- return r;
- }
-
- if (!modlist) {
- log_error("Failed to find module '%s'", m);
- return -ENOENT;
- }
-
- kmod_list_foreach(itr, modlist) {
- struct kmod_module *mod;
- int state, err;
-
- mod = kmod_module_get_module(itr);
- state = kmod_module_get_initstate(mod);
-
- switch (state) {
- case KMOD_MODULE_BUILTIN:
- log_info("Module '%s' is builtin", kmod_module_get_name(mod));
- break;
-
- case KMOD_MODULE_LIVE:
- log_info("Module '%s' is already loaded", kmod_module_get_name(mod));
- break;
-
- default:
- err = kmod_module_probe_insert_module(mod, probe_flags,
- NULL, NULL, NULL, NULL);
-
- if (err == 0)
- log_info("Inserted module '%s'", kmod_module_get_name(mod));
- else if (err == KMOD_PROBE_APPLY_BLACKLIST)
- log_info("Module '%s' is blacklisted", kmod_module_get_name(mod));
- else {
- log_error("Failed to insert '%s': %s", kmod_module_get_name(mod),
- strerror(-err));
- r = err;
- }
- }
-
- kmod_module_unref(mod);
- }
-
- kmod_module_unref_list(modlist);
-
- return r;
-}
-
-int main(int argc, char *argv[]) {
- int r = EXIT_FAILURE, k;
- char **files = NULL, **fn, **i;
- struct kmod_ctx *ctx;
-
- if (argc > 1) {
- log_error("This program takes no argument.");
- return EXIT_FAILURE;
- }
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- if (parse_proc_cmdline() < 0)
- return EXIT_FAILURE;
-
- ctx = kmod_new(NULL, NULL);
- if (!ctx) {
- log_error("Failed to allocate memory for kmod.");
- goto finish;
- }
-
- kmod_load_resources(ctx);
- kmod_set_log_fn(ctx, systemd_kmod_log, NULL);
-
- r = EXIT_SUCCESS;
-
- STRV_FOREACH(i, arg_proc_cmdline_modules) {
- k = load_module(ctx, *i);
- if (k < 0)
- r = EXIT_FAILURE;
- }
-
- k = conf_files_list(&files, ".conf",
- "/etc/modules-load.d",
- "/run/modules-load.d",
- "/usr/local/lib/modules-load.d",
- "/usr/lib/modules-load.d",
-#ifdef HAVE_SPLIT_USR
- "/lib/modules-load.d",
-#endif
- NULL);
- if (k < 0) {
- log_error("Failed to enumerate modules-load.d files: %s", strerror(-k));
- r = EXIT_FAILURE;
- goto finish;
- }
-
- STRV_FOREACH(fn, files) {
- FILE *f;
-
- f = fopen(*fn, "re");
- if (!f) {
- if (errno == ENOENT)
- continue;
-
- log_error("Failed to open %s: %m", *fn);
- r = EXIT_FAILURE;
- continue;
- }
-
- log_debug("apply: %s\n", *fn);
- for (;;) {
- char line[LINE_MAX], *l;
-
- if (!fgets(line, sizeof(line), f))
- break;
-
- l = strstrip(line);
- if (*l == '#' || *l == 0)
- continue;
-
- k = load_module(ctx, l);
- if (k < 0)
- r = EXIT_FAILURE;
- }
-
- if (ferror(f)) {
- log_error("Failed to read from file: %m");
- r = EXIT_FAILURE;
- }
-
- fclose(f);
- }
-
-finish:
- strv_free(files);
- kmod_unref(ctx);
- strv_free(arg_proc_cmdline_modules);
-
- return r;
-}
diff --git a/src/notify/Makefile b/src/notify/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/notify/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/notify/notify.c b/src/notify/notify.c
deleted file mode 100644
index ffc8dfeb9b..0000000000
--- a/src/notify/notify.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/*-*- 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 <stdio.h>
-#include <getopt.h>
-#include <error.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <systemd/sd-daemon.h>
-
-#include "strv.h"
-#include "util.h"
-#include "log.h"
-#include "sd-readahead.h"
-#include "build.h"
-
-static bool arg_ready = false;
-static pid_t arg_pid = 0;
-static const char *arg_status = NULL;
-static bool arg_booted = false;
-static const char *arg_readahead = NULL;
-
-static int help(void) {
-
- printf("%s [OPTIONS...] [VARIABLE=VALUE...]\n\n"
- "Notify the init system about service status updates.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --ready Inform the init system about service start-up completion\n"
- " --pid[=PID] Set main pid of daemon\n"
- " --status=TEXT Set status text\n"
- " --booted Returns 0 if the system was booted up with systemd, non-zero otherwise\n"
- " --readahead=ACTION Controls read-ahead operations\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_READY = 0x100,
- ARG_VERSION,
- ARG_PID,
- ARG_STATUS,
- ARG_BOOTED,
- ARG_READAHEAD
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "ready", no_argument, NULL, ARG_READY },
- { "pid", optional_argument, NULL, ARG_PID },
- { "status", required_argument, NULL, ARG_STATUS },
- { "booted", no_argument, NULL, ARG_BOOTED },
- { "readahead", required_argument, NULL, ARG_READAHEAD },
- { NULL, 0, NULL, 0 }
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(DISTRIBUTION);
- puts(SYSTEMD_FEATURES);
- return 0;
-
- case ARG_READY:
- arg_ready = true;
- break;
-
- case ARG_PID:
-
- if (optarg) {
- if (parse_pid(optarg, &arg_pid) < 0) {
- log_error("Failed to parse PID %s.", optarg);
- return -EINVAL;
- }
- } else
- arg_pid = getppid();
-
- break;
-
- case ARG_STATUS:
- arg_status = optarg;
- break;
-
- case ARG_BOOTED:
- arg_booted = true;
- break;
-
- case ARG_READAHEAD:
- arg_readahead = optarg;
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- log_error("Unknown option code %c", c);
- return -EINVAL;
- }
- }
-
- if (optind >= argc &&
- !arg_ready &&
- !arg_status &&
- !arg_pid &&
- !arg_booted &&
- !arg_readahead) {
- help();
- return -EINVAL;
- }
-
- return 1;
-}
-
-int main(int argc, char* argv[]) {
- char* our_env[4], **final_env = NULL;
- unsigned i = 0;
- char *status = NULL, *cpid = NULL, *n = NULL;
- int r, retval = EXIT_FAILURE;
-
- log_parse_environment();
- log_open();
-
- if ((r = parse_argv(argc, argv)) <= 0) {
- retval = r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
- goto finish;
- }
-
- if (arg_booted)
- return sd_booted() <= 0;
-
- if (arg_readahead) {
- if ((r = sd_readahead(arg_readahead)) < 0) {
- log_error("Failed to issue read-ahead control command: %s", strerror(-r));
- goto finish;
- }
- }
-
- if (arg_ready)
- our_env[i++] = (char*) "READY=1";
-
- if (arg_status) {
- if (!(status = strappend("STATUS=", arg_status))) {
- log_error("Failed to allocate STATUS string.");
- goto finish;
- }
-
- our_env[i++] = status;
- }
-
- if (arg_pid > 0) {
- if (asprintf(&cpid, "MAINPID=%lu", (unsigned long) arg_pid) < 0) {
- log_error("Failed to allocate MAINPID string.");
- goto finish;
- }
-
- our_env[i++] = cpid;
- }
-
- our_env[i++] = NULL;
-
- if (!(final_env = strv_env_merge(2, our_env, argv + optind))) {
- log_error("Failed to merge string sets.");
- goto finish;
- }
-
- if (strv_length(final_env) <= 0) {
- retval = EXIT_SUCCESS;
- goto finish;
- }
-
- if (!(n = strv_join(final_env, "\n"))) {
- log_error("Failed to concatenate strings.");
- goto finish;
- }
-
- if ((r = sd_notify(false, n)) < 0) {
- log_error("Failed to notify init system: %s", strerror(-r));
- goto finish;
- }
-
- retval = r <= 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-
-finish:
- free(status);
- free(cpid);
- free(n);
-
- strv_free(final_env);
-
- return retval;
-}
diff --git a/src/nspawn/Makefile b/src/nspawn/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/nspawn/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
deleted file mode 100644
index 244ebb8342..0000000000
--- a/src/nspawn/nspawn.c
+++ /dev/null
@@ -1,1444 +0,0 @@
-/*-*- 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 <signal.h>
-#include <sched.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/syscall.h>
-#include <sys/mount.h>
-#include <sys/wait.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-#include <sys/prctl.h>
-#include <sys/capability.h>
-#include <getopt.h>
-#include <sys/epoll.h>
-#include <termios.h>
-#include <sys/signalfd.h>
-#include <grp.h>
-#include <linux/fs.h>
-#include <sys/un.h>
-#include <sys/socket.h>
-
-#include <systemd/sd-daemon.h>
-
-#include "log.h"
-#include "util.h"
-#include "mkdir.h"
-#include "macro.h"
-#include "audit.h"
-#include "missing.h"
-#include "cgroup-util.h"
-#include "strv.h"
-#include "path-util.h"
-#include "loopback-setup.h"
-#include "sd-id128.h"
-#include "dev-setup.h"
-
-typedef enum LinkJournal {
- LINK_NO,
- LINK_AUTO,
- LINK_HOST,
- LINK_GUEST
-} LinkJournal;
-
-static char *arg_directory = NULL;
-static char *arg_user = NULL;
-static char **arg_controllers = NULL;
-static char *arg_uuid = NULL;
-static bool arg_private_network = false;
-static bool arg_read_only = false;
-static bool arg_boot = false;
-static LinkJournal arg_link_journal = LINK_AUTO;
-static uint64_t arg_retain =
- (1ULL << CAP_CHOWN) |
- (1ULL << CAP_DAC_OVERRIDE) |
- (1ULL << CAP_DAC_READ_SEARCH) |
- (1ULL << CAP_FOWNER) |
- (1ULL << CAP_FSETID) |
- (1ULL << CAP_IPC_OWNER) |
- (1ULL << CAP_KILL) |
- (1ULL << CAP_LEASE) |
- (1ULL << CAP_LINUX_IMMUTABLE) |
- (1ULL << CAP_NET_BIND_SERVICE) |
- (1ULL << CAP_NET_BROADCAST) |
- (1ULL << CAP_NET_RAW) |
- (1ULL << CAP_SETGID) |
- (1ULL << CAP_SETFCAP) |
- (1ULL << CAP_SETPCAP) |
- (1ULL << CAP_SETUID) |
- (1ULL << CAP_SYS_ADMIN) |
- (1ULL << CAP_SYS_CHROOT) |
- (1ULL << CAP_SYS_NICE) |
- (1ULL << CAP_SYS_PTRACE) |
- (1ULL << CAP_SYS_TTY_CONFIG) |
- (1ULL << CAP_SYS_RESOURCE) |
- (1ULL << CAP_SYS_BOOT);
-
-static int help(void) {
-
- printf("%s [OPTIONS...] [PATH] [ARGUMENTS...]\n\n"
- "Spawn a minimal namespace container for debugging, testing and building.\n\n"
- " -h --help Show this help\n"
- " -D --directory=NAME Root directory for the container\n"
- " -b --boot Boot up full system (i.e. invoke init)\n"
- " -u --user=USER Run the command under specified user or uid\n"
- " -C --controllers=LIST Put the container in specified comma-separated cgroup hierarchies\n"
- " --uuid=UUID Set a specific machine UUID for the container\n"
- " --private-network Disable network in container\n"
- " --read-only Mount the root directory read-only\n"
- " --capability=CAP In addition to the default, retain specified capability\n"
- " --link-journal=MODE Link up guest journal, one of no, auto, guest, host\n"
- " -j Equivalent to --link-journal=host\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_PRIVATE_NETWORK = 0x100,
- ARG_UUID,
- ARG_READ_ONLY,
- ARG_CAPABILITY,
- ARG_LINK_JOURNAL
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "directory", required_argument, NULL, 'D' },
- { "user", required_argument, NULL, 'u' },
- { "controllers", required_argument, NULL, 'C' },
- { "private-network", no_argument, NULL, ARG_PRIVATE_NETWORK },
- { "boot", no_argument, NULL, 'b' },
- { "uuid", required_argument, NULL, ARG_UUID },
- { "read-only", no_argument, NULL, ARG_READ_ONLY },
- { "capability", required_argument, NULL, ARG_CAPABILITY },
- { "link-journal", required_argument, NULL, ARG_LINK_JOURNAL },
- { NULL, 0, NULL, 0 }
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "+hD:u:C:bj", options, NULL)) >= 0) {
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case 'D':
- free(arg_directory);
- arg_directory = canonicalize_file_name(optarg);
- if (!arg_directory) {
- log_error("Failed to canonicalize root directory.");
- return -ENOMEM;
- }
-
- break;
-
- case 'u':
- free(arg_user);
- if (!(arg_user = strdup(optarg))) {
- log_error("Failed to duplicate user name.");
- return -ENOMEM;
- }
-
- break;
-
- case 'C':
- strv_free(arg_controllers);
- arg_controllers = strv_split(optarg, ",");
- if (!arg_controllers) {
- log_error("Failed to split controllers list.");
- return -ENOMEM;
- }
- strv_uniq(arg_controllers);
-
- break;
-
- case ARG_PRIVATE_NETWORK:
- arg_private_network = true;
- break;
-
- case 'b':
- arg_boot = true;
- break;
-
- case ARG_UUID:
- arg_uuid = optarg;
- break;
-
- case ARG_READ_ONLY:
- arg_read_only = true;
- break;
-
- case ARG_CAPABILITY: {
- char *state, *word;
- size_t length;
-
- FOREACH_WORD_SEPARATOR(word, length, optarg, ",", state) {
- cap_value_t cap;
- char *t;
-
- t = strndup(word, length);
- if (!t)
- return log_oom();
-
- if (cap_from_name(t, &cap) < 0) {
- log_error("Failed to parse capability %s.", t);
- free(t);
- return -EINVAL;
- }
-
- free(t);
- arg_retain |= 1ULL << (uint64_t) cap;
- }
-
- break;
- }
-
- case 'j':
- arg_link_journal = LINK_GUEST;
- break;
-
- case ARG_LINK_JOURNAL:
- if (streq(optarg, "auto"))
- arg_link_journal = LINK_AUTO;
- else if (streq(optarg, "no"))
- arg_link_journal = LINK_NO;
- else if (streq(optarg, "guest"))
- arg_link_journal = LINK_GUEST;
- else if (streq(optarg, "host"))
- arg_link_journal = LINK_HOST;
- else {
- log_error("Failed to parse link journal mode %s", optarg);
- return -EINVAL;
- }
-
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- log_error("Unknown option code %c", c);
- return -EINVAL;
- }
- }
-
- return 1;
-}
-
-static int mount_all(const char *dest) {
-
- typedef struct MountPoint {
- const char *what;
- const char *where;
- const char *type;
- const char *options;
- unsigned long flags;
- bool fatal;
- } MountPoint;
-
- static const MountPoint mount_table[] = {
- { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, true },
- { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND, true }, /* Bind mount first */
- { NULL, "/proc/sys", NULL, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, true }, /* Then, make it r/o */
- { "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, true },
- { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, true },
- { "/dev/pts", "/dev/pts", NULL, NULL, MS_BIND, true },
- { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true },
- { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true },
-#ifdef HAVE_SELINUX
- { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND, false }, /* Bind mount first */
- { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, false }, /* Then, make it r/o */
-#endif
- };
-
- unsigned k;
- int r = 0;
-
- for (k = 0; k < ELEMENTSOF(mount_table); k++) {
- char _cleanup_free_ *where = NULL;
- int t;
-
- if (asprintf(&where, "%s/%s", dest, mount_table[k].where) < 0) {
- log_oom();
-
- if (r == 0)
- r = -ENOMEM;
-
- break;
- }
-
- t = path_is_mount_point(where, true);
- if (t < 0) {
- log_error("Failed to detect whether %s is a mount point: %s", where, strerror(-t));
-
- if (r == 0)
- r = t;
-
- continue;
- }
-
- /* Skip this entry if it is not a remount. */
- if (mount_table[k].what && t > 0)
- continue;
-
- mkdir_p_label(where, 0755);
-
- if (mount(mount_table[k].what,
- where,
- mount_table[k].type,
- mount_table[k].flags,
- mount_table[k].options) < 0 &&
- mount_table[k].fatal) {
-
- log_error("mount(%s) failed: %m", where);
-
- if (r == 0)
- r = -errno;
- }
- }
-
- return r;
-}
-
-static int setup_timezone(const char *dest) {
- _cleanup_free_ char *where = NULL, *p = NULL, *q = NULL, *check = NULL, *what = NULL;
- char *z, *y;
- int r;
-
- assert(dest);
-
- /* Fix the timezone, if possible */
- r = readlink_malloc("/etc/localtime", &p);
- if (r < 0) {
- log_warning("/etc/localtime is not a symlink, not updating container timezone.");
- return 0;
- }
-
- z = path_startswith(p, "../usr/share/zoneinfo/");
- if (!z)
- z = path_startswith(p, "/usr/share/zoneinfo/");
- if (!z) {
- log_warning("/etc/localtime does not point into /usr/share/zoneinfo/, not updating container timezone.");
- return 0;
- }
-
- where = strappend(dest, "/etc/localtime");
- if (!where)
- return log_oom();
-
- r = readlink_malloc(where, &q);
- if (r >= 0) {
- y = path_startswith(q, "../usr/share/zoneinfo/");
- if (!y)
- y = path_startswith(q, "/usr/share/zoneinfo/");
-
-
- /* Already pointing to the right place? Then do nothing .. */
- if (y && streq(y, z))
- return 0;
- }
-
- check = strjoin(dest, "/usr/share/zoneinfo/", z, NULL);
- if (!check)
- return log_oom();
-
- if (access(check, F_OK) < 0) {
- log_warning("Timezone %s does not exist in container, not updating container timezone.", z);
- return 0;
- }
-
- what = strappend("../usr/share/zoneinfo/", z);
- if (!what)
- return log_oom();
-
- unlink(where);
- if (symlink(what, where) < 0) {
- log_error("Failed to correct timezone of container: %m");
- return 0;
- }
-
- return 0;
-}
-
-static int setup_resolv_conf(const char *dest) {
- char *where;
-
- assert(dest);
-
- if (arg_private_network)
- return 0;
-
- /* Fix resolv.conf, if possible */
- where = strappend(dest, "/etc/resolv.conf");
- if (!where)
- return log_oom();
-
- /* We don't really care for the results of this really. If it
- * fails, it fails, but meh... */
- if (mount("/etc/resolv.conf", where, "bind", MS_BIND, NULL) >= 0)
- mount("/etc/resolv.conf", where, "bind", MS_BIND|MS_REMOUNT|MS_RDONLY, NULL);
-
- free(where);
-
- return 0;
-}
-
-static int setup_boot_id(const char *dest) {
- char _cleanup_free_ *from = NULL, *to = NULL;
- sd_id128_t rnd;
- char as_uuid[37];
- int r;
-
- assert(dest);
-
- /* Generate a new randomized boot ID, so that each boot-up of
- * the container gets a new one */
-
- from = strappend(dest, "/dev/proc-sys-kernel-random-boot-id");
- to = strappend(dest, "/proc/sys/kernel/random/boot_id");
- if (!from || !to)
- return log_oom();
-
- r = sd_id128_randomize(&rnd);
- if (r < 0) {
- log_error("Failed to generate random boot id: %s", strerror(-r));
- return r;
- }
-
- snprintf(as_uuid, sizeof(as_uuid),
- "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- SD_ID128_FORMAT_VAL(rnd));
- char_array_0(as_uuid);
-
- r = write_one_line_file(from, as_uuid);
- if (r < 0) {
- log_error("Failed to write boot id: %s", strerror(-r));
- return r;
- }
-
- if (mount(from, to, "bind", MS_BIND, NULL) < 0) {
- log_error("Failed to bind mount boot id: %m");
- r = -errno;
- } else
- mount(from, to, "bind", MS_BIND|MS_REMOUNT|MS_RDONLY, NULL);
-
- unlink(from);
- return r;
-}
-
-static int copy_devnodes(const char *dest) {
-
- static const char devnodes[] =
- "null\0"
- "zero\0"
- "full\0"
- "random\0"
- "urandom\0"
- "tty\0"
- "ptmx\0";
-
- const char *d;
- int r = 0;
- mode_t _cleanup_umask_ u;
-
- assert(dest);
-
- u = umask(0000);
-
- NULSTR_FOREACH(d, devnodes) {
- struct stat st;
- char _cleanup_free_ *from = NULL, *to = NULL;
-
- asprintf(&from, "/dev/%s", d);
- asprintf(&to, "%s/dev/%s", dest, d);
-
- if (!from || !to) {
- log_oom();
-
- if (r == 0)
- r = -ENOMEM;
-
- break;
- }
-
- if (stat(from, &st) < 0) {
-
- if (errno != ENOENT) {
- log_error("Failed to stat %s: %m", from);
- if (r == 0)
- r = -errno;
- }
-
- } else if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
-
- log_error("%s is not a char or block device, cannot copy", from);
- if (r == 0)
- r = -EIO;
-
- } else if (mknod(to, st.st_mode, st.st_rdev) < 0) {
-
- log_error("mknod(%s) failed: %m", dest);
- if (r == 0)
- r = -errno;
- }
- }
-
- return r;
-}
-
-static int setup_dev_console(const char *dest, const char *console) {
- struct stat st;
- char _cleanup_free_ *to = NULL;
- int r;
- mode_t _cleanup_umask_ u;
-
- assert(dest);
- assert(console);
-
- u = umask(0000);
-
- if (stat(console, &st) < 0) {
- log_error("Failed to stat %s: %m", console);
- return -errno;
-
- } else if (!S_ISCHR(st.st_mode)) {
- log_error("/dev/console is not a char device");
- return -EIO;
- }
-
- r = chmod_and_chown(console, 0600, 0, 0);
- if (r < 0) {
- log_error("Failed to correct access mode for TTY: %s", strerror(-r));
- return r;
- }
-
- if (asprintf(&to, "%s/dev/console", dest) < 0)
- return log_oom();
-
- /* We need to bind mount the right tty to /dev/console since
- * ptys can only exist on pts file systems. To have something
- * to bind mount things on we create a device node first, that
- * has the right major/minor (note that the major minor
- * doesn't actually matter here, since we mount it over
- * anyway). */
-
- if (mknod(to, (st.st_mode & ~07777) | 0600, st.st_rdev) < 0) {
- log_error("mknod() for /dev/console failed: %m");
- return -errno;
- }
-
- if (mount(console, to, "bind", MS_BIND, NULL) < 0) {
- log_error("Bind mount for /dev/console failed: %m");
- return -errno;
- }
-
- return 0;
-}
-
-static int setup_kmsg(const char *dest, int kmsg_socket) {
- char _cleanup_free_ *from = NULL, *to = NULL;
- int r, fd, k;
- mode_t _cleanup_umask_ u;
- union {
- struct cmsghdr cmsghdr;
- uint8_t buf[CMSG_SPACE(sizeof(int))];
- } control;
- struct msghdr mh;
- struct cmsghdr *cmsg;
-
- assert(dest);
- assert(kmsg_socket >= 0);
-
- u = umask(0000);
-
- /* We create the kmsg FIFO as /dev/kmsg, but immediately
- * delete it after bind mounting it to /proc/kmsg. While FIFOs
- * on the reading side behave very similar to /proc/kmsg,
- * their writing side behaves differently from /dev/kmsg in
- * that writing blocks when nothing is reading. In order to
- * avoid any problems with containers deadlocking due to this
- * we simply make /dev/kmsg unavailable to the container. */
- if (asprintf(&from, "%s/dev/kmsg", dest) < 0 ||
- asprintf(&to, "%s/proc/kmsg", dest) < 0)
- return log_oom();
-
- if (mkfifo(from, 0600) < 0) {
- log_error("mkfifo() for /dev/kmsg failed: %m");
- return -errno;
- }
-
- r = chmod_and_chown(from, 0600, 0, 0);
- if (r < 0) {
- log_error("Failed to correct access mode for /dev/kmsg: %s", strerror(-r));
- return r;
- }
-
- if (mount(from, to, "bind", MS_BIND, NULL) < 0) {
- log_error("Bind mount for /proc/kmsg failed: %m");
- return -errno;
- }
-
- fd = open(from, O_RDWR|O_NDELAY|O_CLOEXEC);
- if (fd < 0) {
- log_error("Failed to open fifo: %m");
- return -errno;
- }
-
- zero(mh);
- zero(control);
-
- mh.msg_control = &control;
- mh.msg_controllen = sizeof(control);
-
- cmsg = CMSG_FIRSTHDR(&mh);
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
- cmsg->cmsg_len = CMSG_LEN(sizeof(int));
- memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
-
- mh.msg_controllen = cmsg->cmsg_len;
-
- /* Store away the fd in the socket, so that it stays open as
- * long as we run the child */
- k = sendmsg(kmsg_socket, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
- close_nointr_nofail(fd);
-
- if (k < 0) {
- log_error("Failed to send FIFO fd: %m");
- return -errno;
- }
-
- /* And now make the FIFO unavailable as /dev/kmsg... */
- unlink(from);
- return 0;
-}
-
-static int setup_hostname(void) {
- char *hn;
- int r = 0;
-
- hn = path_get_file_name(arg_directory);
- if (hn) {
- hn = strdup(hn);
- if (!hn)
- return -ENOMEM;
-
- hostname_cleanup(hn);
-
- if (!isempty(hn))
- if (sethostname(hn, strlen(hn)) < 0)
- r = -errno;
-
- free(hn);
- }
-
- return r;
-}
-
-static int setup_journal(const char *directory) {
- sd_id128_t machine_id;
- char _cleanup_free_ *p = NULL, *b = NULL, *q = NULL, *d = NULL;
- char *id;
- int r;
-
- if (arg_link_journal == LINK_NO)
- return 0;
-
- p = strappend(directory, "/etc/machine-id");
- if (!p)
- return log_oom();
-
- r = read_one_line_file(p, &b);
- if (r == -ENOENT && arg_link_journal == LINK_AUTO)
- return 0;
- else if (r < 0) {
- log_error("Failed to read machine ID from %s: %s", p, strerror(-r));
- return r;
- }
-
- id = strstrip(b);
- if (isempty(id) && arg_link_journal == LINK_AUTO)
- return 0;
-
- /* Verify validity */
- r = sd_id128_from_string(id, &machine_id);
- if (r < 0) {
- log_error("Failed to parse machine ID from %s: %s", p, strerror(-r));
- return r;
- }
-
- free(p);
- p = strappend("/var/log/journal/", id);
- q = strjoin(directory, "/var/log/journal/", id, NULL);
- if (!p || !q)
- return log_oom();
-
- if (path_is_mount_point(p, false) > 0) {
- if (arg_link_journal != LINK_AUTO) {
- log_error("%s: already a mount point, refusing to use for journal", p);
- return -EEXIST;
- }
-
- return 0;
- }
-
- if (path_is_mount_point(q, false) > 0) {
- if (arg_link_journal != LINK_AUTO) {
- log_error("%s: already a mount point, refusing to use for journal", q);
- return -EEXIST;
- }
-
- return 0;
- }
-
- r = readlink_and_make_absolute(p, &d);
- if (r >= 0) {
- if ((arg_link_journal == LINK_GUEST ||
- arg_link_journal == LINK_AUTO) &&
- path_equal(d, q)) {
-
- r = mkdir_p(q, 0755);
- if (r < 0)
- log_warning("failed to create directory %s: %m", q);
- return 0;
- }
-
- if (unlink(p) < 0) {
- log_error("Failed to remove symlink %s: %m", p);
- return -errno;
- }
- } else if (r == -EINVAL) {
-
- if (arg_link_journal == LINK_GUEST &&
- rmdir(p) < 0) {
-
- if (errno == ENOTDIR) {
- log_error("%s already exists and is neither a symlink nor a directory", p);
- return r;
- } else {
- log_error("Failed to remove %s: %m", p);
- return -errno;
- }
- }
- } else if (r != -ENOENT) {
- log_error("readlink(%s) failed: %m", p);
- return r;
- }
-
- if (arg_link_journal == LINK_GUEST) {
-
- if (symlink(q, p) < 0) {
- log_error("Failed to symlink %s to %s: %m", q, p);
- return -errno;
- }
-
- r = mkdir_p(q, 0755);
- if (r < 0)
- log_warning("failed to create directory %s: %m", q);
- return 0;
- }
-
- if (arg_link_journal == LINK_HOST) {
- r = mkdir_p(p, 0755);
- if (r < 0) {
- log_error("Failed to create %s: %m", p);
- return r;
- }
-
- } else if (access(p, F_OK) < 0)
- return 0;
-
- if (dir_is_empty(q) == 0) {
- log_error("%s not empty.", q);
- return -ENOTEMPTY;
- }
-
- r = mkdir_p(q, 0755);
- if (r < 0) {
- log_error("Failed to create %s: %m", q);
- return r;
- }
-
- if (mount(p, q, "bind", MS_BIND, NULL) < 0) {
- log_error("Failed to bind mount journal from host into guest: %m");
- return -errno;
- }
-
- return 0;
-}
-
-static int drop_capabilities(void) {
- return capability_bounding_set_drop(~arg_retain, false);
-}
-
-static int is_os_tree(const char *path) {
- int r;
- char *p;
- /* We use /bin/sh as flag file if something is an OS */
-
- if (asprintf(&p, "%s/bin/sh", path) < 0)
- return -ENOMEM;
-
- r = access(p, F_OK);
- free(p);
-
- return r < 0 ? 0 : 1;
-}
-
-static int process_pty(int master, sigset_t *mask) {
-
- char in_buffer[LINE_MAX], out_buffer[LINE_MAX];
- size_t in_buffer_full = 0, out_buffer_full = 0;
- struct epoll_event stdin_ev, stdout_ev, master_ev, signal_ev;
- bool stdin_readable = false, stdout_writable = false, master_readable = false, master_writable = false;
- int ep = -1, signal_fd = -1, r;
-
- fd_nonblock(STDIN_FILENO, 1);
- fd_nonblock(STDOUT_FILENO, 1);
- fd_nonblock(master, 1);
-
- signal_fd = signalfd(-1, mask, SFD_NONBLOCK|SFD_CLOEXEC);
- if (signal_fd < 0) {
- log_error("signalfd(): %m");
- r = -errno;
- goto finish;
- }
-
- ep = epoll_create1(EPOLL_CLOEXEC);
- if (ep < 0) {
- log_error("Failed to create epoll: %m");
- r = -errno;
- goto finish;
- }
-
- zero(stdin_ev);
- stdin_ev.events = EPOLLIN|EPOLLET;
- stdin_ev.data.fd = STDIN_FILENO;
-
- zero(stdout_ev);
- stdout_ev.events = EPOLLOUT|EPOLLET;
- stdout_ev.data.fd = STDOUT_FILENO;
-
- zero(master_ev);
- master_ev.events = EPOLLIN|EPOLLOUT|EPOLLET;
- master_ev.data.fd = master;
-
- zero(signal_ev);
- signal_ev.events = EPOLLIN;
- signal_ev.data.fd = signal_fd;
-
- if (epoll_ctl(ep, EPOLL_CTL_ADD, STDIN_FILENO, &stdin_ev) < 0 ||
- epoll_ctl(ep, EPOLL_CTL_ADD, STDOUT_FILENO, &stdout_ev) < 0 ||
- epoll_ctl(ep, EPOLL_CTL_ADD, master, &master_ev) < 0 ||
- epoll_ctl(ep, EPOLL_CTL_ADD, signal_fd, &signal_ev) < 0) {
- log_error("Failed to regiser fds in epoll: %m");
- r = -errno;
- goto finish;
- }
-
- for (;;) {
- struct epoll_event ev[16];
- ssize_t k;
- int i, nfds;
-
- nfds = epoll_wait(ep, ev, ELEMENTSOF(ev), -1);
- if (nfds < 0) {
-
- if (errno == EINTR || errno == EAGAIN)
- continue;
-
- log_error("epoll_wait(): %m");
- r = -errno;
- goto finish;
- }
-
- assert(nfds >= 1);
-
- for (i = 0; i < nfds; i++) {
- if (ev[i].data.fd == STDIN_FILENO) {
-
- if (ev[i].events & (EPOLLIN|EPOLLHUP))
- stdin_readable = true;
-
- } else if (ev[i].data.fd == STDOUT_FILENO) {
-
- if (ev[i].events & (EPOLLOUT|EPOLLHUP))
- stdout_writable = true;
-
- } else if (ev[i].data.fd == master) {
-
- if (ev[i].events & (EPOLLIN|EPOLLHUP))
- master_readable = true;
-
- if (ev[i].events & (EPOLLOUT|EPOLLHUP))
- master_writable = true;
-
- } else if (ev[i].data.fd == signal_fd) {
- struct signalfd_siginfo sfsi;
- ssize_t n;
-
- n = read(signal_fd, &sfsi, sizeof(sfsi));
- if (n != sizeof(sfsi)) {
-
- if (n >= 0) {
- log_error("Failed to read from signalfd: invalid block size");
- r = -EIO;
- goto finish;
- }
-
- if (errno != EINTR && errno != EAGAIN) {
- log_error("Failed to read from signalfd: %m");
- r = -errno;
- goto finish;
- }
- } else {
-
- if (sfsi.ssi_signo == SIGWINCH) {
- struct winsize ws;
-
- /* The window size changed, let's forward that. */
- if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) >= 0)
- ioctl(master, TIOCSWINSZ, &ws);
- } else {
- r = 0;
- goto finish;
- }
- }
- }
- }
-
- while ((stdin_readable && in_buffer_full <= 0) ||
- (master_writable && in_buffer_full > 0) ||
- (master_readable && out_buffer_full <= 0) ||
- (stdout_writable && out_buffer_full > 0)) {
-
- if (stdin_readable && in_buffer_full < LINE_MAX) {
-
- k = read(STDIN_FILENO, in_buffer + in_buffer_full, LINE_MAX - in_buffer_full);
- if (k < 0) {
-
- if (errno == EAGAIN || errno == EPIPE || errno == ECONNRESET || errno == EIO)
- stdin_readable = false;
- else {
- log_error("read(): %m");
- r = -errno;
- goto finish;
- }
- } else
- in_buffer_full += (size_t) k;
- }
-
- if (master_writable && in_buffer_full > 0) {
-
- k = write(master, in_buffer, in_buffer_full);
- if (k < 0) {
-
- if (errno == EAGAIN || errno == EPIPE || errno == ECONNRESET || errno == EIO)
- master_writable = false;
- else {
- log_error("write(): %m");
- r = -errno;
- goto finish;
- }
-
- } else {
- assert(in_buffer_full >= (size_t) k);
- memmove(in_buffer, in_buffer + k, in_buffer_full - k);
- in_buffer_full -= k;
- }
- }
-
- if (master_readable && out_buffer_full < LINE_MAX) {
-
- k = read(master, out_buffer + out_buffer_full, LINE_MAX - out_buffer_full);
- if (k < 0) {
-
- if (errno == EAGAIN || errno == EPIPE || errno == ECONNRESET || errno == EIO)
- master_readable = false;
- else {
- log_error("read(): %m");
- r = -errno;
- goto finish;
- }
- } else
- out_buffer_full += (size_t) k;
- }
-
- if (stdout_writable && out_buffer_full > 0) {
-
- k = write(STDOUT_FILENO, out_buffer, out_buffer_full);
- if (k < 0) {
-
- if (errno == EAGAIN || errno == EPIPE || errno == ECONNRESET || errno == EIO)
- stdout_writable = false;
- else {
- log_error("write(): %m");
- r = -errno;
- goto finish;
- }
-
- } else {
- assert(out_buffer_full >= (size_t) k);
- memmove(out_buffer, out_buffer + k, out_buffer_full - k);
- out_buffer_full -= k;
- }
- }
- }
- }
-
-finish:
- if (ep >= 0)
- close_nointr_nofail(ep);
-
- if (signal_fd >= 0)
- close_nointr_nofail(signal_fd);
-
- return r;
-}
-
-int main(int argc, char *argv[]) {
- pid_t pid = 0;
- int r = EXIT_FAILURE, k;
- char *oldcg = NULL, *newcg = NULL;
- char **controller = NULL;
- int master = -1;
- const char *console = NULL;
- struct termios saved_attr, raw_attr;
- sigset_t mask;
- bool saved_attr_valid = false;
- struct winsize ws;
- int kmsg_socket_pair[2] = { -1, -1 };
-
- log_parse_environment();
- log_open();
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- goto finish;
-
- if (arg_directory) {
- char *p;
-
- p = path_make_absolute_cwd(arg_directory);
- free(arg_directory);
- arg_directory = p;
- } else
- arg_directory = get_current_dir_name();
-
- if (!arg_directory) {
- log_error("Failed to determine path");
- goto finish;
- }
-
- path_kill_slashes(arg_directory);
-
- if (geteuid() != 0) {
- log_error("Need to be root.");
- goto finish;
- }
-
- if (sd_booted() <= 0) {
- log_error("Not running on a systemd system.");
- goto finish;
- }
-
- if (path_equal(arg_directory, "/")) {
- log_error("Spawning container on root directory not supported.");
- goto finish;
- }
-
- if (is_os_tree(arg_directory) <= 0) {
- log_error("Directory %s doesn't look like an OS root directory. Refusing.", arg_directory);
- goto finish;
- }
-
- k = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 0, &oldcg);
- if (k < 0) {
- log_error("Failed to determine current cgroup: %s", strerror(-k));
- goto finish;
- }
-
- if (asprintf(&newcg, "%s/nspawn-%lu", oldcg, (unsigned long) getpid()) < 0) {
- log_error("Failed to allocate cgroup path.");
- goto finish;
- }
-
- k = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, newcg, 0);
- if (k < 0) {
- log_error("Failed to create cgroup: %s", strerror(-k));
- goto finish;
- }
-
- STRV_FOREACH(controller, arg_controllers) {
- k = cg_create_and_attach(*controller, newcg, 0);
- if (k < 0)
- log_warning("Failed to create cgroup in controller %s: %s", *controller, strerror(-k));
- }
-
- master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY);
- if (master < 0) {
- log_error("Failed to acquire pseudo tty: %m");
- goto finish;
- }
-
- console = ptsname(master);
- if (!console) {
- log_error("Failed to determine tty name: %m");
- goto finish;
- }
-
- log_info("Spawning namespace container on %s (console is %s).", arg_directory, console);
-
- if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) >= 0)
- ioctl(master, TIOCSWINSZ, &ws);
-
- if (unlockpt(master) < 0) {
- log_error("Failed to unlock tty: %m");
- goto finish;
- }
-
- if (tcgetattr(STDIN_FILENO, &saved_attr) < 0) {
- log_error("Failed to get terminal attributes: %m");
- goto finish;
- }
-
- saved_attr_valid = true;
-
- raw_attr = saved_attr;
- cfmakeraw(&raw_attr);
- raw_attr.c_lflag &= ~ECHO;
-
- if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, kmsg_socket_pair) < 0) {
- log_error("Failed to create kmsg socket pair");
- goto finish;
- }
-
- assert_se(sigemptyset(&mask) == 0);
- sigset_add_many(&mask, SIGCHLD, SIGWINCH, SIGTERM, SIGINT, -1);
- assert_se(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
-
- for (;;) {
- siginfo_t status;
-
- if (tcsetattr(STDIN_FILENO, TCSANOW, &raw_attr) < 0) {
- log_error("Failed to set terminal attributes: %m");
- goto finish;
- }
-
- pid = syscall(__NR_clone, SIGCHLD|CLONE_NEWIPC|CLONE_NEWNS|CLONE_NEWPID|CLONE_NEWUTS|(arg_private_network ? CLONE_NEWNET : 0), NULL);
- if (pid < 0) {
- if (errno == EINVAL)
- log_error("clone() failed, do you have namespace support enabled in your kernel? (You need UTS, IPC, PID and NET namespacing built in): %m");
- else
- log_error("clone() failed: %m");
-
- goto finish;
- }
-
- if (pid == 0) {
- /* child */
-
- const char *home = NULL;
- uid_t uid = (uid_t) -1;
- gid_t gid = (gid_t) -1;
- const char *envp[] = {
- "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
- "container=systemd-nspawn", /* LXC sets container=lxc, so follow the scheme here */
- NULL, /* TERM */
- NULL, /* HOME */
- NULL, /* USER */
- NULL, /* LOGNAME */
- NULL, /* container_uuid */
- NULL
- };
-
- envp[2] = strv_find_prefix(environ, "TERM=");
-
- close_nointr_nofail(master);
-
- close_nointr(STDIN_FILENO);
- close_nointr(STDOUT_FILENO);
- close_nointr(STDERR_FILENO);
-
- close_all_fds(&kmsg_socket_pair[1], 1);
-
- reset_all_signal_handlers();
-
- assert_se(sigemptyset(&mask) == 0);
- assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
-
- if (open_terminal(console, O_RDWR) != STDIN_FILENO ||
- dup2(STDIN_FILENO, STDOUT_FILENO) != STDOUT_FILENO ||
- dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO)
- goto child_fail;
-
- if (setsid() < 0) {
- log_error("setsid() failed: %m");
- goto child_fail;
- }
-
- if (prctl(PR_SET_PDEATHSIG, SIGKILL) < 0) {
- log_error("PR_SET_PDEATHSIG failed: %m");
- goto child_fail;
- }
-
- /* Mark everything as slave, so that we still
- * receive mounts from the real root, but don't
- * propagate mounts to the real root. */
- if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) {
- log_error("MS_SLAVE|MS_REC failed: %m");
- goto child_fail;
- }
-
- /* Turn directory into bind mount */
- if (mount(arg_directory, arg_directory, "bind", MS_BIND|MS_REC, NULL) < 0) {
- log_error("Failed to make bind mount.");
- goto child_fail;
- }
-
- if (arg_read_only)
- if (mount(arg_directory, arg_directory, "bind", MS_BIND|MS_REMOUNT|MS_RDONLY|MS_REC, NULL) < 0) {
- log_error("Failed to make read-only.");
- goto child_fail;
- }
-
- if (mount_all(arg_directory) < 0)
- goto child_fail;
-
- if (copy_devnodes(arg_directory) < 0)
- goto child_fail;
-
- dev_setup(arg_directory);
-
- if (setup_dev_console(arg_directory, console) < 0)
- goto child_fail;
-
- if (setup_kmsg(arg_directory, kmsg_socket_pair[1]) < 0)
- goto child_fail;
-
- close_nointr_nofail(kmsg_socket_pair[1]);
-
- if (setup_boot_id(arg_directory) < 0)
- goto child_fail;
-
- if (setup_timezone(arg_directory) < 0)
- goto child_fail;
-
- if (setup_resolv_conf(arg_directory) < 0)
- goto child_fail;
-
- if (setup_journal(arg_directory) < 0)
- goto child_fail;
-
- if (chdir(arg_directory) < 0) {
- log_error("chdir(%s) failed: %m", arg_directory);
- goto child_fail;
- }
-
- if (mount(arg_directory, "/", NULL, MS_MOVE, NULL) < 0) {
- log_error("mount(MS_MOVE) failed: %m");
- goto child_fail;
- }
-
- if (chroot(".") < 0) {
- log_error("chroot() failed: %m");
- goto child_fail;
- }
-
- if (chdir("/") < 0) {
- log_error("chdir() failed: %m");
- goto child_fail;
- }
-
- umask(0022);
-
- loopback_setup();
-
- if (drop_capabilities() < 0) {
- log_error("drop_capabilities() failed: %m");
- goto child_fail;
- }
-
- if (arg_user) {
-
- /* Note that this resolves user names
- * inside the container, and hence
- * accesses the NSS modules from the
- * container and not the host. This is
- * a bit weird... */
-
- if (get_user_creds((const char**)&arg_user, &uid, &gid, &home, NULL) < 0) {
- log_error("get_user_creds() failed: %m");
- goto child_fail;
- }
-
- if (mkdir_parents_label(home, 0775) < 0) {
- log_error("mkdir_parents_label() failed: %m");
- goto child_fail;
- }
-
- if (mkdir_safe_label(home, 0775, uid, gid) < 0) {
- log_error("mkdir_safe_label() failed: %m");
- goto child_fail;
- }
-
- if (initgroups((const char*)arg_user, gid) < 0) {
- log_error("initgroups() failed: %m");
- goto child_fail;
- }
-
- if (setresgid(gid, gid, gid) < 0) {
- log_error("setregid() failed: %m");
- goto child_fail;
- }
-
- if (setresuid(uid, uid, uid) < 0) {
- log_error("setreuid() failed: %m");
- goto child_fail;
- }
- }
-
- if ((asprintf((char**)(envp + 3), "HOME=%s", home ? home: "/root") < 0) ||
- (asprintf((char**)(envp + 4), "USER=%s", arg_user ? arg_user : "root") < 0) ||
- (asprintf((char**)(envp + 5), "LOGNAME=%s", arg_user ? arg_user : "root") < 0)) {
- log_oom();
- goto child_fail;
- }
-
- if (arg_uuid) {
- if (asprintf((char**)(envp + 6), "container_uuid=%s", arg_uuid) < 0) {
- log_oom();
- goto child_fail;
- }
- }
-
- setup_hostname();
-
- if (arg_boot) {
- char **a;
- size_t l;
-
- /* Automatically search for the init system */
-
- l = 1 + argc - optind;
- a = newa(char*, l + 1);
- memcpy(a + 1, argv + optind, l * sizeof(char*));
-
- a[0] = (char*) "/usr/lib/systemd/systemd";
- execve(a[0], a, (char**) envp);
-
- a[0] = (char*) "/lib/systemd/systemd";
- execve(a[0], a, (char**) envp);
-
- a[0] = (char*) "/sbin/init";
- execve(a[0], a, (char**) envp);
- } else if (argc > optind)
- execvpe(argv[optind], argv + optind, (char**) envp);
- else {
- chdir(home ? home : "/root");
- execle("/bin/bash", "-bash", NULL, (char**) envp);
- }
-
- log_error("execv() failed: %m");
-
- child_fail:
- _exit(EXIT_FAILURE);
- }
-
- if (process_pty(master, &mask) < 0)
- goto finish;
-
-
- if (saved_attr_valid)
- tcsetattr(STDIN_FILENO, TCSANOW, &saved_attr);
-
- r = wait_for_terminate(pid, &status);
- if (r < 0) {
- r = EXIT_FAILURE;
- break;
- }
-
- if (status.si_code == CLD_EXITED) {
- if (status.si_status != 0) {
- log_error("Container failed with error code %i.", status.si_status);
- r = status.si_status;
- break;
- }
-
- log_debug("Container exited successfully.");
- break;
- } else if (status.si_code == CLD_KILLED &&
- status.si_status == SIGINT) {
- log_info("Container has been shut down.");
- r = 0;
- break;
- } else if (status.si_code == CLD_KILLED &&
- status.si_status == SIGHUP) {
- log_info("Container is being rebooted.");
- continue;
- } else if (status.si_code == CLD_KILLED ||
- status.si_code == CLD_DUMPED) {
-
- log_error("Container terminated by signal %s.", signal_to_string(status.si_status));
- r = EXIT_FAILURE;
- break;
- } else {
- log_error("Container failed due to unknown reason.");
- r = EXIT_FAILURE;
- break;
- }
- }
-
-finish:
- if (saved_attr_valid)
- tcsetattr(STDIN_FILENO, TCSANOW, &saved_attr);
-
- if (master >= 0)
- close_nointr_nofail(master);
-
- close_pipe(kmsg_socket_pair);
-
- if (oldcg)
- cg_attach(SYSTEMD_CGROUP_CONTROLLER, oldcg, 0);
-
- if (newcg)
- cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, newcg, true);
-
- free(arg_directory);
- strv_free(arg_controllers);
- free(oldcg);
- free(newcg);
-
- return r;
-}
diff --git a/src/python-systemd/Makefile b/src/python-systemd/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/python-systemd/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/python-systemd/__init__.py b/src/python-systemd/__init__.py
deleted file mode 100644
index 0d56b992f4..0000000000
--- a/src/python-systemd/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil -*- */
-#
-# This file is part of systemd.
-#
-# Copyright 2012 David Strauss
-#
-# 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/>.
diff --git a/src/python-systemd/_journal.c b/src/python-systemd/_journal.c
deleted file mode 100644
index 0bdf709aea..0000000000
--- a/src/python-systemd/_journal.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 David Strauss
-
- 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 <Python.h>
-
-#include <alloca.h>
-
-#define SD_JOURNAL_SUPPRESS_LOCATION
-#include <systemd/sd-journal.h>
-
-PyDoc_STRVAR(journal_sendv__doc__,
- "sendv('FIELD=value', 'FIELD=value', ...) -> None\n\n"
- "Send an entry to the journal."
-);
-
-static PyObject *journal_sendv(PyObject *self, PyObject *args) {
- struct iovec *iov = NULL;
- int argc;
- int i, r;
- PyObject *ret = NULL;
- PyObject **encoded;
-
- /* Allocate an array for the argument strings */
- argc = PyTuple_Size(args);
- encoded = alloca(argc * sizeof(PyObject*));
- memset(encoded, 0, argc * sizeof(PyObject*));
-
- /* Allocate sufficient iovector space for the arguments. */
- iov = alloca(argc * sizeof(struct iovec));
-
- /* Iterate through the Python arguments and fill the iovector. */
- for (i = 0; i < argc; ++i) {
- PyObject *item = PyTuple_GetItem(args, i);
- char *stritem;
- Py_ssize_t length;
-
- if (PyUnicode_Check(item)) {
- encoded[i] = PyUnicode_AsEncodedString(item, "utf-8", "strict");
- if (encoded[i] == NULL)
- goto out;
- item = encoded[i];
- }
- if (PyBytes_AsStringAndSize(item, &stritem, &length))
- goto out;
-
- iov[i].iov_base = stritem;
- iov[i].iov_len = length;
- }
-
- /* Send the iovector to the journal. */
- r = sd_journal_sendv(iov, argc);
- if (r < 0) {
- errno = -r;
- PyErr_SetFromErrno(PyExc_IOError);
- goto out;
- }
-
- /* End with success. */
- Py_INCREF(Py_None);
- ret = Py_None;
-
-out:
- for (i = 0; i < argc; ++i)
- Py_XDECREF(encoded[i]);
-
- return ret;
-}
-
-PyDoc_STRVAR(journal_stream_fd__doc__,
- "stream_fd(identifier, priority, level_prefix) -> fd\n\n"
- "Open a stream to journal by calling sd_journal_stream_fd(3)."
-);
-
-static PyObject* journal_stream_fd(PyObject *self, PyObject *args) {
- const char* identifier;
- int priority, level_prefix;
- int fd;
-
- if (!PyArg_ParseTuple(args, "sii:stream_fd",
- &identifier, &priority, &level_prefix))
- return NULL;
-
- fd = sd_journal_stream_fd(identifier, priority, level_prefix);
- if (fd < 0) {
- errno = -fd;
- return PyErr_SetFromErrno(PyExc_IOError);
- }
-
- return PyLong_FromLong(fd);
-}
-
-static PyMethodDef methods[] = {
- { "sendv", journal_sendv, METH_VARARGS, journal_sendv__doc__ },
- { "stream_fd", journal_stream_fd, METH_VARARGS, journal_stream_fd__doc__ },
- { NULL, NULL, 0, NULL } /* Sentinel */
-};
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
-#if PY_MAJOR_VERSION < 3
-
-PyMODINIT_FUNC init_journal(void) {
- (void) Py_InitModule("_journal", methods);
-}
-
-#else
-
-static struct PyModuleDef module = {
- PyModuleDef_HEAD_INIT,
- "_journal", /* name of module */
- NULL, /* module documentation, may be NULL */
- 0, /* size of per-interpreter state of the module */
- methods
-};
-
-PyMODINIT_FUNC PyInit__journal(void) {
- return PyModule_Create(&module);
-}
-
-#endif
-
-#pragma GCC diagnostic pop
diff --git a/src/python-systemd/journal.py b/src/python-systemd/journal.py
deleted file mode 100644
index 516ca1ab56..0000000000
--- a/src/python-systemd/journal.py
+++ /dev/null
@@ -1,201 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil -*- */
-#
-# This file is part of systemd.
-#
-# Copyright 2012 David Strauss
-#
-# 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/>.
-
-import traceback as _traceback
-import os as _os
-import logging as _logging
-from syslog import (LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR,
- LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG)
-from ._journal import sendv, stream_fd
-
-def _make_line(field, value):
- if isinstance(value, bytes):
- return field.encode('utf-8') + b'=' + value
- else:
- return field + '=' + value
-
-def send(MESSAGE, MESSAGE_ID=None,
- CODE_FILE=None, CODE_LINE=None, CODE_FUNC=None,
- **kwargs):
- r"""Send a message to journald.
-
- >>> journal.send('Hello world')
- >>> journal.send('Hello, again, world', FIELD2='Greetings!')
- >>> journal.send('Binary message', BINARY=b'\xde\xad\xbe\xef')
-
- Value of the MESSAGE argument will be used for the MESSAGE=
- field.
-
- MESSAGE_ID can be given to uniquely identify the type of
- message.
-
- Other parts of the message can be specified as keyword
- arguments.
-
- Both MESSAGE and MESSAGE_ID, if present, must be strings, and
- will be sent as UTF-8 to journal. Other arguments can be
- bytes, in which case they will be sent as-is to journal.
-
- CODE_LINE, CODE_FILE, and CODE_FUNC can be specified to
- identify the caller. Unless at least on of the three is given,
- values are extracted from the stack frame of the caller of
- send(). CODE_FILE and CODE_FUNC must be strings, CODE_LINE
- must be an integer.
-
- Other useful fields include PRIORITY, SYSLOG_FACILITY,
- SYSLOG_IDENTIFIER, SYSLOG_PID.
- """
-
- args = ['MESSAGE=' + MESSAGE]
-
- if MESSAGE_ID is not None:
- args.append('MESSAGE_ID=' + MESSAGE_ID)
-
- if CODE_LINE == CODE_FILE == CODE_FUNC == None:
- CODE_FILE, CODE_LINE, CODE_FUNC = \
- _traceback.extract_stack(limit=2)[0][:3]
- if CODE_FILE is not None:
- args.append('CODE_FILE=' + CODE_FILE)
- if CODE_LINE is not None:
- args.append('CODE_LINE={:d}'.format(CODE_LINE))
- if CODE_FUNC is not None:
- args.append('CODE_FUNC=' + CODE_FUNC)
-
- args.extend(_make_line(key, val) for key, val in kwargs.items())
- return sendv(*args)
-
-def stream(identifier, priority=LOG_DEBUG, level_prefix=False):
- r"""Return a file object wrapping a stream to journal.
-
- Log messages written to this file as simple newline sepearted
- text strings are written to the journal.
-
- The file will be line buffered, so messages are actually sent
- after a newline character is written.
-
- >>> stream = journal.stream('myapp')
- >>> stream
- <open file '<fdopen>', mode 'w' at 0x...>
- >>> stream.write('message...\n')
-
- will produce the following message in the journal:
-
- PRIORITY=7
- SYSLOG_IDENTIFIER=myapp
- MESSAGE=message...
-
- Using the interface with print might be more convinient:
-
- >>> from __future__ import print_function
- >>> print('message...', file=stream)
-
- priority is the syslog priority, one of LOG_EMERG, LOG_ALERT,
- LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG.
-
- level_prefix is a boolean. If true, kernel-style log priority
- level prefixes (such as '<1>') are interpreted. See
- sd-daemon(3) for more information.
- """
-
- fd = stream_fd(identifier, priority, level_prefix)
- return _os.fdopen(fd, 'w', 1)
-
-class JournalHandler(_logging.Handler):
- """Journal handler class for the Python logging framework.
-
- Please see the Python logging module documentation for an
- overview: http://docs.python.org/library/logging.html
-
- To create a custom logger whose messages go only to journal:
-
- >>> log = logging.getLogger('custom_logger_name')
- >>> log.propagate = False
- >>> log.addHandler(journal.JournalHandler())
- >>> log.warn("Some message: %s", detail)
-
- Note that by default, message levels INFO and DEBUG are ignored
- by the logging framework. To enable those log levels:
-
- >>> log.setLevel(logging.DEBUG)
-
- To attach journal MESSAGE_ID, an extra field is supported:
-
- >>> log.warn("Message with ID",
- >>> extra={'MESSAGE_ID': '22bb01335f724c959ac4799627d1cb61'})
-
- To redirect all logging messages to journal regardless of where
- they come from, attach it to the root logger:
-
- >>> logging.root.addHandler(journal.JournalHandler())
-
- For more complex configurations when using dictConfig or
- fileConfig, specify 'systemd.journal.JournalHandler' as the
- handler class. Only standard handler configuration options
- are supported: level, formatter, filters.
-
- The following journal fields will be sent:
-
- MESSAGE, PRIORITY, THREAD_NAME, CODE_FILE, CODE_LINE,
- CODE_FUNC, LOGGER (name as supplied to getLogger call),
- MESSAGE_ID (optional, see above).
- """
-
- def emit(self, record):
- """Write record as journal event.
-
- MESSAGE is taken from the message provided by the
- user, and PRIORITY, LOGGER, THREAD_NAME,
- CODE_{FILE,LINE,FUNC} fields are appended
- automatically. In addition, record.MESSAGE_ID will be
- used if present.
- """
- try:
- msg = self.format(record)
- pri = self.mapPriority(record.levelno)
- mid = getattr(record, 'MESSAGE_ID', None)
- send(msg,
- MESSAGE_ID=mid,
- PRIORITY=format(pri),
- LOGGER=record.name,
- THREAD_NAME=record.threadName,
- CODE_FILE=record.pathname,
- CODE_LINE=record.lineno,
- CODE_FUNC=record.funcName)
- except Exception:
- self.handleError(record)
-
- @staticmethod
- def mapPriority(levelno):
- """Map logging levels to journald priorities.
-
- Since Python log level numbers are "sparse", we have
- to map numbers in between the standard levels too.
- """
- if levelno <= _logging.DEBUG:
- return LOG_DEBUG
- elif levelno <= _logging.INFO:
- return LOG_INFO
- elif levelno <= _logging.WARNING:
- return LOG_WARNING
- elif levelno <= _logging.ERROR:
- return LOG_ERR
- elif levelno <= _logging.CRITICAL:
- return LOG_CRIT
- else:
- return LOG_ALERT
diff --git a/src/quotacheck/Makefile b/src/quotacheck/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/quotacheck/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/quotacheck/quotacheck.c b/src/quotacheck/quotacheck.c
deleted file mode 100644
index 05e4971487..0000000000
--- a/src/quotacheck/quotacheck.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*-*- 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 <stdio.h>
-#include <stdbool.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include "util.h"
-#include "virt.h"
-
-static bool arg_skip = false;
-static bool arg_force = false;
-
-static int parse_proc_cmdline(void) {
- char *line, *w, *state;
- int r;
- size_t l;
-
- if (detect_container(NULL) > 0)
- return 0;
-
- if ((r = read_one_line_file("/proc/cmdline", &line)) < 0) {
- log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
- return 0;
- }
-
- FOREACH_WORD_QUOTED(w, l, line, state) {
-
- if (strneq(w, "quotacheck.mode=auto", l))
- arg_force = arg_skip = false;
- else if (strneq(w, "quotacheck.mode=force", l))
- arg_force = true;
- else if (strneq(w, "quotacheck.mode=skip", l))
- arg_skip = true;
- else if (startswith(w, "quotacheck"))
- log_warning("Invalid quotacheck parameter. Ignoring.");
-#if defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_MAGEIA)
- else if (strneq(w, "forcequotacheck", l))
- arg_force = true;
-#endif
- }
-
- free(line);
- return 0;
-}
-
-static void test_files(void) {
-#if defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_MAGEIA)
- /* This exists only on Fedora, Mandriva or Mageia */
- if (access("/forcequotacheck", F_OK) >= 0)
- arg_force = true;
-#endif
-}
-
-int main(int argc, char *argv[]) {
- static const char * const cmdline[] = {
- "/sbin/quotacheck",
- "-anug",
- NULL
- };
-
- int r = EXIT_FAILURE;
- pid_t pid;
-
- if (argc > 1) {
- log_error("This program takes no arguments.");
- return EXIT_FAILURE;
- }
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- parse_proc_cmdline();
- test_files();
-
- if (!arg_force) {
- if (arg_skip)
- return 0;
-
- if (access("/run/systemd/quotacheck", F_OK) < 0)
- return 0;
- }
-
- if ((pid = fork()) < 0) {
- log_error("fork(): %m");
- goto finish;
- } else if (pid == 0) {
- /* Child */
- execv(cmdline[0], (char**) cmdline);
- _exit(1); /* Operational error */
- }
-
- r = wait_for_terminate_and_warn("quotacheck", pid) == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
-
-finish:
- return r;
-}
diff --git a/src/random-seed/Makefile b/src/random-seed/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/random-seed/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/random-seed/random-seed.c b/src/random-seed/random-seed.c
deleted file mode 100644
index fdcaa1e154..0000000000
--- a/src/random-seed/random-seed.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*-*- 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 <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/stat.h>
-
-#include "log.h"
-#include "util.h"
-#include "mkdir.h"
-
-#define POOL_SIZE_MIN 512
-
-int main(int argc, char *argv[]) {
- int seed_fd = -1, random_fd = -1;
- int ret = EXIT_FAILURE;
- void* buf;
- size_t buf_size = 0;
- ssize_t r;
- FILE *f;
-
- if (argc != 2) {
- log_error("This program requires one argument.");
- return EXIT_FAILURE;
- }
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- /* Read pool size, if possible */
- if ((f = fopen("/proc/sys/kernel/random/poolsize", "re"))) {
- if (fscanf(f, "%zu", &buf_size) > 0) {
- /* poolsize is in bits on 2.6, but we want bytes */
- buf_size /= 8;
- }
-
- fclose(f);
- }
-
- if (buf_size <= POOL_SIZE_MIN)
- buf_size = POOL_SIZE_MIN;
-
- if (!(buf = malloc(buf_size))) {
- log_error("Failed to allocate buffer.");
- goto finish;
- }
-
- if (mkdir_parents_label(RANDOM_SEED, 0755) < 0) {
- log_error("Failed to create directories parents of %s: %m", RANDOM_SEED);
- goto finish;
- }
-
- /* When we load the seed we read it and write it to the device
- * and then immediately update the saved seed with new data,
- * to make sure the next boot gets seeded differently. */
-
- if (streq(argv[1], "load")) {
-
- if ((seed_fd = open(RANDOM_SEED, O_RDWR|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600)) < 0) {
- if ((seed_fd = open(RANDOM_SEED, O_RDONLY|O_CLOEXEC|O_NOCTTY)) < 0) {
- log_error("Failed to open random seed: %m");
- goto finish;
- }
- }
-
- if ((random_fd = open("/dev/urandom", O_RDWR|O_CLOEXEC|O_NOCTTY, 0600)) < 0) {
- if ((random_fd = open("/dev/urandom", O_WRONLY|O_CLOEXEC|O_NOCTTY, 0600)) < 0) {
- log_error("Failed to open /dev/urandom: %m");
- goto finish;
- }
- }
-
- if ((r = loop_read(seed_fd, buf, buf_size, false)) <= 0) {
-
- if (r != 0)
- log_error("Failed to read seed file: %m");
- } else {
- lseek(seed_fd, 0, SEEK_SET);
-
- if ((r = loop_write(random_fd, buf, (size_t) r, false)) <= 0)
- log_error("Failed to write seed to /dev/urandom: %s",
- r < 0 ? strerror(errno) : "short write");
- }
-
- } else if (streq(argv[1], "save")) {
-
- if ((seed_fd = open(RANDOM_SEED, O_WRONLY|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600)) < 0) {
- log_error("Failed to open random seed: %m");
- goto finish;
- }
-
- if ((random_fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY)) < 0) {
- log_error("Failed to open /dev/urandom: %m");
- goto finish;
- }
- } else {
- log_error("Unknown verb %s.", argv[1]);
- goto finish;
- }
-
- /* This is just a safety measure. Given that we are root and
- * most likely created the file ourselves the mode and owner
- * should be correct anyway. */
- fchmod(seed_fd, 0600);
- fchown(seed_fd, 0, 0);
-
- if ((r = loop_read(random_fd, buf, buf_size, false)) <= 0)
- log_error("Failed to read new seed from /dev/urandom: %s", r < 0 ? strerror(errno) : "EOF");
- else {
- if ((r = loop_write(seed_fd, buf, (size_t) r, false)) <= 0)
- log_error("Failed to write new random seed file: %s", r < 0 ? strerror(errno) : "short write");
- }
-
- ret = EXIT_SUCCESS;
-
-finish:
- if (random_fd >= 0)
- close_nointr_nofail(random_fd);
-
- if (seed_fd >= 0)
- close_nointr_nofail(seed_fd);
-
- free(buf);
-
- return ret;
-}
diff --git a/src/rc-local-generator/Makefile b/src/rc-local-generator/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/rc-local-generator/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/rc-local-generator/rc-local-generator.c b/src/rc-local-generator/rc-local-generator.c
deleted file mode 100644
index c219e77047..0000000000
--- a/src/rc-local-generator/rc-local-generator.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2011 Michal Schmidt
-
- 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 <errno.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include "log.h"
-#include "util.h"
-#include "mkdir.h"
-
-#if defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_MAGEIA)
-#define SCRIPT_PATH_START "/etc/rc.d/rc.local"
-#elif defined(TARGET_SUSE)
-#define SCRIPT_PATH_START "/etc/init.d/boot.local"
-#endif
-
-#define SCRIPT_PATH_STOP "/sbin/halt.local"
-
-const char *arg_dest = "/tmp";
-
-static int add_symlink(const char *service, const char *where) {
- char *from = NULL, *to = NULL;
- int r;
-
- assert(service);
-
- asprintf(&from, SYSTEM_DATA_UNIT_PATH "/%s", service);
- asprintf(&to, "%s/%s.wants/%s", arg_dest, where, service);
-
- if (!from || !to) {
- r = log_oom();
- goto finish;
- }
-
- mkdir_parents_label(to, 0755);
-
- r = symlink(from, to);
- if (r < 0) {
- if (errno == EEXIST)
- r = 0;
- else {
- log_error("Failed to create symlink from %s to %s: %m", from, to);
- r = -errno;
- }
- }
-
-finish:
- free(from);
- free(to);
-
- return r;
-}
-
-static bool file_is_executable(const char *f) {
- struct stat st;
-
- if (stat(f, &st) < 0)
- return false;
-
- return S_ISREG(st.st_mode) && (st.st_mode & 0111);
-}
-
-int main(int argc, char *argv[]) {
- int r = EXIT_SUCCESS;
-
- if (argc > 1 && argc != 4) {
- log_error("This program takes three or no arguments.");
- return EXIT_FAILURE;
- }
-
- if (argc > 1)
- arg_dest = argv[1];
-
- log_set_target(LOG_TARGET_SAFE);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- if (file_is_executable(SCRIPT_PATH_START)) {
- log_debug("Automatically adding rc-local.service.");
-
- if (add_symlink("rc-local.service", "multi-user.target") < 0)
- r = EXIT_FAILURE;
- }
-
- if (file_is_executable(SCRIPT_PATH_STOP)) {
- log_debug("Automatically adding halt-local.service.");
-
- if (add_symlink("halt-local.service", "final.target") < 0)
- r = EXIT_FAILURE;
- }
-
- return r;
-}
diff --git a/src/readahead/Makefile b/src/readahead/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/readahead/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/readahead/readahead-analyze.c b/src/readahead/readahead-analyze.c
deleted file mode 100644
index 9a929c0937..0000000000
--- a/src/readahead/readahead-analyze.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Auke Kok <auke-jan.h.kok@intel.com>
-
- 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 <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <unistd.h>
-#include <inttypes.h>
-#include <linux/limits.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <string.h>
-
-#include "readahead-common.h"
-
-int main_analyze(const char *pack_path) {
- char line[LINE_MAX];
- FILE *pack;
- int a;
- int missing = 0;
- off_t tsize = 0;
-
- if (!pack_path)
- pack_path = "/.readahead";
-
- pack = fopen(pack_path, "re");
- if (!pack) {
- log_error("Pack file missing.");
- goto fail;
- }
-
- if (!fgets(line, sizeof(line), pack)) {
- log_error("Pack file corrupt.");
- goto fail;
- }
-
- char_array_0(line);
-
- if (!endswith(line, READAHEAD_PACK_FILE_VERSION)) {
- log_error("Pack file version incompatible with this parser.");
- goto fail;
- }
-
- if ((a = getc(pack)) == EOF) {
- log_error("Pack file corrupt.");
- goto fail;
- }
-
- fputs(" pct sections size: path\n"
- " === ======== ====: ====\n", stdout);
-
- for (;;) {
- char path[PATH_MAX];
- struct stat st;
- uint64_t inode;
- int pages = 0;
- int sections = 0;
-
- if (!fgets(path, sizeof(path), pack))
- break; /* done */
-
- path[strlen(path)-1] = 0;
-
- if (fread(&inode, sizeof(inode), 1, pack) != 1) {
- log_error("Pack file corrupt.");
- goto fail;
- }
-
- for (;;) {
- uint32_t b, c;
-
- if (fread(&b, sizeof(b), 1, pack) != 1 ||
- fread(&c, sizeof(c), 1, pack) != 1) {
- log_error("Pack file corrupt.");
- goto fail;
- }
- if ((b == 0) && (c == 0))
- break;
-
- /* Uncomment this to get all the chunks separately
- printf(" %d: %d %d\n", sections, b, c);
- */
-
- pages += (c - b);
- sections++;
- }
-
- if (stat(path, &st) == 0) {
- off_t size;
-
- if (sections == 0)
- size = st.st_size;
- else
- size = pages * page_size();
-
- tsize += size;
-
- printf(" %4d%% (%2d) %12ld: %s\n",
- sections ? (int) (size * 100 / st.st_size) : 100,
- sections ? sections : 1,
- (unsigned long)size,
- path);
- } else {
- printf(" %4dp (%2d) %12s: %s (MISSING)\n",
- sections ? pages : -1,
- sections ? sections : 1,
- "???",
- path);
- missing++;
- }
-
- }
-
- fclose(pack);
-
- printf("\nHOST: %s"
- "TYPE: %c\n"
- "MISSING: %d\n"
- "TOTAL: %llu\n",
- line,
- a,
- missing,
- (unsigned long long) tsize);
-
- return EXIT_SUCCESS;
-
-fail:
- if(pack)
- fclose(pack);
- return EXIT_FAILURE;
-}
diff --git a/src/readahead/readahead-collect.c b/src/readahead/readahead-collect.c
deleted file mode 100644
index 5d07f4704a..0000000000
--- a/src/readahead/readahead-collect.c
+++ /dev/null
@@ -1,623 +0,0 @@
-/*-*- 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 <errno.h>
-#include <inttypes.h>
-#include <fcntl.h>
-#include <linux/limits.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/select.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <linux/fanotify.h>
-#include <sys/signalfd.h>
-#include <sys/poll.h>
-#include <sys/mman.h>
-#include <linux/fs.h>
-#include <linux/fiemap.h>
-#include <sys/ioctl.h>
-#include <sys/vfs.h>
-#include <getopt.h>
-#include <sys/inotify.h>
-
-#ifdef HAVE_FANOTIFY_INIT
-#include <sys/fanotify.h>
-#endif
-
-#include <systemd/sd-daemon.h>
-
-#include "missing.h"
-#include "util.h"
-#include "set.h"
-#include "ioprio.h"
-#include "readahead-common.h"
-#include "virt.h"
-
-/* fixme:
- *
- * - detect ssd on btrfs/lvm...
- * - read ahead directories
- * - gzip?
- * - remount rw?
- * - handle files where nothing is in mincore
- * - does ioprio_set work with fadvise()?
- */
-
-static ReadaheadShared *shared = NULL;
-
-/* Avoid collisions with the NULL pointer */
-#define SECTOR_TO_PTR(s) ULONG_TO_PTR((s)+1)
-#define PTR_TO_SECTOR(p) (PTR_TO_ULONG(p)-1)
-
-static int btrfs_defrag(int fd) {
- struct btrfs_ioctl_vol_args data;
-
- zero(data);
- data.fd = fd;
-
- return ioctl(fd, BTRFS_IOC_DEFRAG, &data);
-}
-
-static int pack_file(FILE *pack, const char *fn, bool on_btrfs) {
- struct stat st;
- void *start = MAP_FAILED;
- uint8_t *vec;
- uint32_t b, c;
- uint64_t inode;
- size_t l, pages;
- bool mapped;
- int r = 0, fd = -1, k;
-
- assert(pack);
- assert(fn);
-
- fd = open(fn, O_RDONLY|O_CLOEXEC|O_NOATIME|O_NOCTTY|O_NOFOLLOW);
- if (fd < 0) {
-
- if (errno == ENOENT)
- return 0;
-
- if (errno == EPERM || errno == EACCES)
- return 0;
-
- log_warning("open(%s) failed: %m", fn);
- r = -errno;
- goto finish;
- }
-
- k = file_verify(fd, fn, arg_file_size_max, &st);
- if (k <= 0) {
- r = k;
- goto finish;
- }
-
- if (on_btrfs)
- btrfs_defrag(fd);
-
- l = PAGE_ALIGN(st.st_size);
- start = mmap(NULL, l, PROT_READ, MAP_SHARED, fd, 0);
- if (start == MAP_FAILED) {
- log_warning("mmap(%s) failed: %m", fn);
- r = -errno;
- goto finish;
- }
-
- pages = l / page_size();
- vec = alloca(pages);
- memset(vec, 0, pages);
- if (mincore(start, l, vec) < 0) {
- log_warning("mincore(%s) failed: %m", fn);
- r = -errno;
- goto finish;
- }
-
- fputs(fn, pack);
- fputc('\n', pack);
-
- /* Store the inode, so that we notice when the file is deleted */
- inode = (uint64_t) st.st_ino;
- fwrite(&inode, sizeof(inode), 1, pack);
-
- mapped = false;
- for (c = 0; c < pages; c++) {
- bool new_mapped = !!(vec[c] & 1);
-
- if (!mapped && new_mapped)
- b = c;
- else if (mapped && !new_mapped) {
- fwrite(&b, sizeof(b), 1, pack);
- fwrite(&c, sizeof(c), 1, pack);
-
- log_debug("%s: page %u to %u", fn, b, c);
- }
-
- mapped = new_mapped;
- }
-
- /* We don't write any range data if we should read the entire file */
- if (mapped && b > 0) {
- fwrite(&b, sizeof(b), 1, pack);
- fwrite(&c, sizeof(c), 1, pack);
-
- log_debug("%s: page %u to %u", fn, b, c);
- }
-
- /* End marker */
- b = 0;
- fwrite(&b, sizeof(b), 1, pack);
- fwrite(&b, sizeof(b), 1, pack);
-
-finish:
- if (start != MAP_FAILED)
- munmap(start, l);
-
- if (fd >= 0)
- close_nointr_nofail(fd);
-
- return r;
-}
-
-static unsigned long fd_first_block(int fd) {
- struct {
- struct fiemap fiemap;
- struct fiemap_extent extent;
- } data;
-
- zero(data);
- data.fiemap.fm_length = ~0ULL;
- data.fiemap.fm_extent_count = 1;
-
- if (ioctl(fd, FS_IOC_FIEMAP, &data) < 0)
- return 0;
-
- if (data.fiemap.fm_mapped_extents <= 0)
- return 0;
-
- if (data.fiemap.fm_extents[0].fe_flags & FIEMAP_EXTENT_UNKNOWN)
- return 0;
-
- return (unsigned long) data.fiemap.fm_extents[0].fe_physical;
-}
-
-struct item {
- const char *path;
- unsigned long block;
-};
-
-static int qsort_compare(const void *a, const void *b) {
- const struct item *i, *j;
-
- i = a;
- j = b;
-
- if (i->block < j->block)
- return -1;
- if (i->block > j->block)
- return 1;
-
- return strcmp(i->path, j->path);
-}
-
-static int collect(const char *root) {
- enum {
- FD_FANOTIFY, /* Get the actual fs events */
- FD_SIGNAL,
- FD_INOTIFY, /* We get notifications to quit early via this fd */
- _FD_MAX
- };
- struct pollfd pollfd[_FD_MAX];
- int fanotify_fd = -1, signal_fd = -1, inotify_fd = -1, r = 0;
- pid_t my_pid;
- Hashmap *files = NULL;
- Iterator i;
- char *p, *q;
- sigset_t mask;
- FILE *pack = NULL;
- char *pack_fn_new = NULL, *pack_fn = NULL;
- bool on_ssd, on_btrfs;
- struct statfs sfs;
- usec_t not_after;
- uint64_t previous_block_readahead;
- bool previous_block_readahead_set = false;
-
- assert(root);
-
- if (asprintf(&pack_fn, "%s/.readahead", root) < 0) {
- r = log_oom();
- goto finish;
- }
-
- /* If there's no pack file yet we lower the kernel readahead
- * so that mincore() is accurate. If there is a pack file
- * already we assume it is accurate enough so that kernel
- * readahead is never triggered. */
- previous_block_readahead_set =
- access(pack_fn, F_OK) < 0 &&
- block_get_readahead(root, &previous_block_readahead) >= 0 &&
- block_set_readahead(root, 8*1024) >= 0;
-
- if (ioprio_set(IOPRIO_WHO_PROCESS, getpid(), IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0)) < 0)
- log_warning("Failed to set IDLE IO priority class: %m");
-
- assert_se(sigemptyset(&mask) == 0);
- sigset_add_many(&mask, SIGINT, SIGTERM, -1);
- assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
-
- if ((signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC)) < 0) {
- log_error("signalfd(): %m");
- r = -errno;
- goto finish;
- }
-
- if (!(files = hashmap_new(string_hash_func, string_compare_func))) {
- log_error("Failed to allocate set.");
- r = -ENOMEM;
- goto finish;
- }
-
- if ((fanotify_fd = fanotify_init(FAN_CLOEXEC|FAN_NONBLOCK, O_RDONLY|O_LARGEFILE|O_CLOEXEC|O_NOATIME)) < 0) {
- log_error("Failed to create fanotify object: %m");
- r = -errno;
- goto finish;
- }
-
- if (fanotify_mark(fanotify_fd, FAN_MARK_ADD|FAN_MARK_MOUNT, FAN_OPEN, AT_FDCWD, root) < 0) {
- log_error("Failed to mark %s: %m", root);
- r = -errno;
- goto finish;
- }
-
- if ((inotify_fd = open_inotify()) < 0) {
- r = inotify_fd;
- goto finish;
- }
-
- not_after = now(CLOCK_MONOTONIC) + arg_timeout;
-
- my_pid = getpid();
-
- zero(pollfd);
- pollfd[FD_FANOTIFY].fd = fanotify_fd;
- pollfd[FD_FANOTIFY].events = POLLIN;
- pollfd[FD_SIGNAL].fd = signal_fd;
- pollfd[FD_SIGNAL].events = POLLIN;
- pollfd[FD_INOTIFY].fd = inotify_fd;
- pollfd[FD_INOTIFY].events = POLLIN;
-
- sd_notify(0,
- "READY=1\n"
- "STATUS=Collecting readahead data");
-
- log_debug("Collecting...");
-
- if (access("/run/systemd/readahead/cancel", F_OK) >= 0) {
- log_debug("Collection canceled");
- r = -ECANCELED;
- goto finish;
- }
-
- if (access("/run/systemd/readahead/done", F_OK) >= 0) {
- log_debug("Got termination request");
- goto done;
- }
-
- for (;;) {
- union {
- struct fanotify_event_metadata metadata;
- char buffer[4096];
- } data;
- ssize_t n;
- struct fanotify_event_metadata *m;
- usec_t t;
- int h;
-
- if (hashmap_size(files) > arg_files_max) {
- log_debug("Reached maximum number of read ahead files, ending collection.");
- break;
- }
-
- t = now(CLOCK_MONOTONIC);
- if (t >= not_after) {
- log_debug("Reached maximum collection time, ending collection.");
- break;
- }
-
- if ((h = poll(pollfd, _FD_MAX, (int) ((not_after - t) / USEC_PER_MSEC))) < 0) {
-
- if (errno == EINTR)
- continue;
-
- log_error("poll(): %m");
- r = -errno;
- goto finish;
- }
-
- if (h == 0) {
- log_debug("Reached maximum collection time, ending collection.");
- break;
- }
-
- if (pollfd[FD_SIGNAL].revents) {
- log_debug("Got signal.");
- break;
- }
-
- if (pollfd[FD_INOTIFY].revents) {
- uint8_t inotify_buffer[sizeof(struct inotify_event) + FILENAME_MAX];
- struct inotify_event *e;
-
- if ((n = read(inotify_fd, &inotify_buffer, sizeof(inotify_buffer))) < 0) {
- if (errno == EINTR || errno == EAGAIN)
- continue;
-
- log_error("Failed to read inotify event: %m");
- r = -errno;
- goto finish;
- }
-
- e = (struct inotify_event*) inotify_buffer;
- while (n > 0) {
- size_t step;
-
- if ((e->mask & IN_CREATE) && streq(e->name, "cancel")) {
- log_debug("Collection canceled");
- r = -ECANCELED;
- goto finish;
- }
-
- if ((e->mask & IN_CREATE) && streq(e->name, "done")) {
- log_debug("Got termination request");
- goto done;
- }
-
- step = sizeof(struct inotify_event) + e->len;
- assert(step <= (size_t) n);
-
- e = (struct inotify_event*) ((uint8_t*) e + step);
- n -= step;
- }
- }
-
- if ((n = read(fanotify_fd, &data, sizeof(data))) < 0) {
-
- if (errno == EINTR || errno == EAGAIN)
- continue;
-
- /* fanotify sometimes returns EACCES on read()
- * where it shouldn't. For now let's just
- * ignore it here (which is safe), but
- * eventually this should be
- * dropped when the kernel is fixed.
- *
- * https://bugzilla.redhat.com/show_bug.cgi?id=707577 */
- if (errno == EACCES)
- continue;
-
- log_error("Failed to read event: %m");
- r = -errno;
- goto finish;
- }
-
- for (m = &data.metadata; FAN_EVENT_OK(m, n); m = FAN_EVENT_NEXT(m, n)) {
- char fn[PATH_MAX];
- int k;
-
- if (m->fd < 0)
- goto next_iteration;
-
- if (m->pid == my_pid)
- goto next_iteration;
-
- __sync_synchronize();
- if (m->pid == shared->replay)
- goto next_iteration;
-
- snprintf(fn, sizeof(fn), "/proc/self/fd/%i", m->fd);
- char_array_0(fn);
-
- if ((k = readlink_malloc(fn, &p)) >= 0) {
- if (startswith(p, "/tmp") ||
- endswith(p, " (deleted)") ||
- hashmap_get(files, p))
- /* Not interesting, or
- * already read */
- free(p);
- else {
- unsigned long ul;
-
- ul = fd_first_block(m->fd);
-
- if ((k = hashmap_put(files, p, SECTOR_TO_PTR(ul))) < 0) {
- log_warning("set_put() failed: %s", strerror(-k));
- free(p);
- }
- }
-
- } else
- log_warning("readlink(%s) failed: %s", fn, strerror(-k));
-
- next_iteration:
- if (m->fd >= 0)
- close_nointr_nofail(m->fd);
- }
- }
-
-done:
- if (fanotify_fd >= 0) {
- close_nointr_nofail(fanotify_fd);
- fanotify_fd = -1;
- }
-
- log_debug("Writing Pack File...");
-
- on_ssd = fs_on_ssd(root) > 0;
- log_debug("On SSD: %s", yes_no(on_ssd));
-
- on_btrfs = statfs(root, &sfs) >= 0 && (long) sfs.f_type == (long) BTRFS_SUPER_MAGIC;
- log_debug("On btrfs: %s", yes_no(on_btrfs));
-
- if (asprintf(&pack_fn_new, "%s/.readahead.new", root) < 0) {
- r = log_oom();
- goto finish;
- }
-
- pack = fopen(pack_fn_new, "we");
- if (!pack) {
- log_error("Failed to open pack file: %m");
- r = -errno;
- goto finish;
- }
-
- fputs(CANONICAL_HOST READAHEAD_PACK_FILE_VERSION, pack);
- putc(on_ssd ? 'S' : 'R', pack);
-
- if (on_ssd || on_btrfs) {
-
- /* On SSD or on btrfs, just write things out in the
- * order the files were accessed. */
-
- HASHMAP_FOREACH_KEY(q, p, files, i)
- pack_file(pack, p, on_btrfs);
- } else {
- struct item *ordered, *j;
- unsigned k, n;
-
- /* On rotating media, order things by the block
- * numbers */
-
- log_debug("Ordering...");
-
- n = hashmap_size(files);
- if (!(ordered = new(struct item, n))) {
- r = log_oom();
- goto finish;
- }
-
- j = ordered;
- HASHMAP_FOREACH_KEY(q, p, files, i) {
- j->path = p;
- j->block = PTR_TO_SECTOR(q);
- j++;
- }
-
- assert(ordered + n == j);
-
- qsort(ordered, n, sizeof(struct item), qsort_compare);
-
- for (k = 0; k < n; k++)
- pack_file(pack, ordered[k].path, on_btrfs);
-
- free(ordered);
- }
-
- log_debug("Finalizing...");
-
- fflush(pack);
-
- if (ferror(pack)) {
- log_error("Failed to write pack file.");
- r = -EIO;
- goto finish;
- }
-
- if (rename(pack_fn_new, pack_fn) < 0) {
- log_error("Failed to rename readahead file: %m");
- r = -errno;
- goto finish;
- }
-
- fclose(pack);
- pack = NULL;
-
- log_debug("Done.");
-
-finish:
- if (fanotify_fd >= 0)
- close_nointr_nofail(fanotify_fd);
-
- if (signal_fd >= 0)
- close_nointr_nofail(signal_fd);
-
- if (inotify_fd >= 0)
- close_nointr_nofail(inotify_fd);
-
- if (pack) {
- fclose(pack);
- unlink(pack_fn_new);
- }
- free(pack_fn_new);
- free(pack_fn);
-
- while ((p = hashmap_steal_first_key(files)))
- free(p);
-
- hashmap_free(files);
-
- if (previous_block_readahead_set) {
- uint64_t bytes;
-
- /* Restore the original kernel readahead setting if we
- * changed it, and nobody has overwritten it since
- * yet. */
- if (block_get_readahead(root, &bytes) >= 0 && bytes == 8*1024)
- block_set_readahead(root, previous_block_readahead);
- }
-
- return r;
-}
-
-int main_collect(const char *root) {
-
- if (!root)
- root = "/";
-
- /* Skip this step on read-only media. Note that we check the
- * underlying block device here, not he read-only flag of the
- * file system on top, since that one is most likely mounted
- * read-only anyway at boot, even if the underlying block
- * device is theoretically writable. */
- if (fs_on_read_only(root) > 0) {
- log_info("Disabling readahead collector due to read-only media.");
- return EXIT_SUCCESS;
- }
-
- if (!enough_ram()) {
- log_info("Disabling readahead collector due to low memory.");
- return EXIT_SUCCESS;
- }
-
- shared = shared_get();
- if (!shared)
- return EXIT_FAILURE;
-
- shared->collect = getpid();
- __sync_synchronize();
-
- if (collect(root) < 0)
- return EXIT_FAILURE;
-
- return EXIT_SUCCESS;
-}
diff --git a/src/readahead/readahead-common.c b/src/readahead/readahead-common.c
deleted file mode 100644
index 10b0ccc548..0000000000
--- a/src/readahead/readahead-common.c
+++ /dev/null
@@ -1,359 +0,0 @@
-/*-*- 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 <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/sysinfo.h>
-#include <sys/inotify.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <unistd.h>
-#include <libudev.h>
-
-#include "log.h"
-#include "readahead-common.h"
-#include "util.h"
-
-int file_verify(int fd, const char *fn, off_t file_size_max, struct stat *st) {
- assert(fd >= 0);
- assert(fn);
- assert(st);
-
- if (fstat(fd, st) < 0) {
- log_warning("fstat(%s) failed: %m", fn);
- return -errno;
- }
-
- if (!S_ISREG(st->st_mode)) {
- log_debug("Not preloading special file %s", fn);
- return 0;
- }
-
- if (st->st_size <= 0 || st->st_size > file_size_max) {
- log_debug("Not preloading file %s with size out of bounds %llu", fn, (unsigned long long) st->st_size);
- return 0;
- }
-
- return 1;
-}
-
-int fs_on_ssd(const char *p) {
- struct stat st;
- struct udev *udev = NULL;
- struct udev_device *udev_device = NULL, *look_at = NULL;
- bool b = false;
- const char *devtype, *rotational, *model, *id;
-
- assert(p);
-
- if (stat(p, &st) < 0)
- return -errno;
-
- if (major(st.st_dev) == 0)
- return false;
-
- udev = udev_new();
- if (!udev)
- return -ENOMEM;
-
- udev_device = udev_device_new_from_devnum(udev, 'b', st.st_dev);
- if (!udev_device)
- goto finish;
-
- devtype = udev_device_get_property_value(udev_device, "DEVTYPE");
- if (devtype && streq(devtype, "partition"))
- look_at = udev_device_get_parent(udev_device);
- else
- look_at = udev_device;
-
- if (!look_at)
- goto finish;
-
- /* First, try high-level property */
- id = udev_device_get_property_value(look_at, "ID_SSD");
- if (id) {
- b = streq(id, "1");
- goto finish;
- }
-
- /* Second, try kernel attribute */
- rotational = udev_device_get_sysattr_value(look_at, "queue/rotational");
- if (rotational)
- if ((b = streq(rotational, "0")))
- goto finish;
-
- /* Finally, fallback to heuristics */
- look_at = udev_device_get_parent(look_at);
- if (!look_at)
- goto finish;
-
- model = udev_device_get_sysattr_value(look_at, "model");
- if (model)
- b = !!strstr(model, "SSD");
-
-finish:
- if (udev_device)
- udev_device_unref(udev_device);
-
- if (udev)
- udev_unref(udev);
-
- return b;
-}
-
-int fs_on_read_only(const char *p) {
- struct stat st;
- struct udev *udev = NULL;
- struct udev_device *udev_device = NULL;
- bool b = false;
- const char *read_only;
-
- assert(p);
-
- if (stat(p, &st) < 0)
- return -errno;
-
- if (major(st.st_dev) == 0)
- return false;
-
- if (!(udev = udev_new()))
- return -ENOMEM;
-
- if (!(udev_device = udev_device_new_from_devnum(udev, 'b', st.st_dev)))
- goto finish;
-
- if ((read_only = udev_device_get_sysattr_value(udev_device, "ro")))
- if ((b = streq(read_only, "1")))
- goto finish;
-
-finish:
- if (udev_device)
- udev_device_unref(udev_device);
-
- if (udev)
- udev_unref(udev);
-
- return b;
-}
-
-bool enough_ram(void) {
- struct sysinfo si;
-
- assert_se(sysinfo(&si) >= 0);
-
- /* Enable readahead only with at least 128MB memory */
- return si.totalram > 127 * 1024*1024 / si.mem_unit;
-}
-
-int open_inotify(void) {
- int fd;
-
- if ((fd = inotify_init1(IN_CLOEXEC|IN_NONBLOCK)) < 0) {
- log_error("Failed to create inotify handle: %m");
- return -errno;
- }
-
- mkdir("/run/systemd", 0755);
- mkdir("/run/systemd/readahead", 0755);
-
- if (inotify_add_watch(fd, "/run/systemd/readahead", IN_CREATE) < 0) {
- log_error("Failed to watch /run/systemd/readahead: %m");
- close_nointr_nofail(fd);
- return -errno;
- }
-
- return fd;
-}
-
-ReadaheadShared *shared_get(void) {
- int fd;
- ReadaheadShared *m = NULL;
-
- mkdir("/run/systemd", 0755);
- mkdir("/run/systemd/readahead", 0755);
-
- if ((fd = open("/run/systemd/readahead/shared", O_CREAT|O_RDWR|O_CLOEXEC, 0644)) < 0) {
- log_error("Failed to create shared memory segment: %m");
- goto finish;
- }
-
- if (ftruncate(fd, sizeof(ReadaheadShared)) < 0) {
- log_error("Failed to truncate shared memory segment: %m");
- goto finish;
- }
-
- if ((m = mmap(NULL, sizeof(ReadaheadShared), PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
- log_error("Failed to mmap shared memory segment: %m");
- m = NULL;
- goto finish;
- }
-
-finish:
- if (fd >= 0)
- close_nointr_nofail(fd);
-
- return m;
-}
-
-/* We use 20K instead of the more human digestable 16K here. Why?
- Simply so that it is more unlikely that users end up picking this
- value too so that we can recognize better whether the user changed
- the value while we had it temporarily bumped. */
-#define BUMP_REQUEST_NR (20*1024)
-
-int block_bump_request_nr(const char *p) {
- struct stat st;
- uint64_t u;
- char *ap = NULL, *line = NULL;
- int r;
- dev_t d;
-
- assert(p);
-
- if (stat(p, &st) < 0)
- return -errno;
-
- if (major(st.st_dev) == 0)
- return 0;
-
- d = st.st_dev;
- block_get_whole_disk(d, &d);
-
- if (asprintf(&ap, "/sys/dev/block/%u:%u/queue/nr_requests", major(d), minor(d)) < 0) {
- r= -ENOMEM;
- goto finish;
- }
-
- r = read_one_line_file(ap, &line);
- if (r < 0) {
- if (r == -ENOENT)
- r = 0;
- goto finish;
- }
-
- r = safe_atou64(line, &u);
- if (r >= 0 && u >= BUMP_REQUEST_NR) {
- r = 0;
- goto finish;
- }
-
- free(line);
- line = NULL;
-
- if (asprintf(&line, "%lu", (unsigned long) BUMP_REQUEST_NR) < 0) {
- r = -ENOMEM;
- goto finish;
- }
-
- r = write_one_line_file(ap, line);
- if (r < 0)
- goto finish;
-
- log_info("Bumped block_nr parameter of %u:%u to %lu. This is a temporary hack and should be removed one day.", major(d), minor(d), (unsigned long) BUMP_REQUEST_NR);
- r = 1;
-
-finish:
- free(ap);
- free(line);
-
- return r;
-}
-
-int block_get_readahead(const char *p, uint64_t *bytes) {
- struct stat st;
- char *ap = NULL, *line = NULL;
- int r;
- dev_t d;
- uint64_t u;
-
- assert(p);
- assert(bytes);
-
- if (stat(p, &st) < 0)
- return -errno;
-
- if (major(st.st_dev) == 0)
- return 0;
-
- d = st.st_dev;
- block_get_whole_disk(d, &d);
-
- if (asprintf(&ap, "/sys/dev/block/%u:%u/bdi/read_ahead_kb", major(d), minor(d)) < 0) {
- r = -ENOMEM;
- goto finish;
- }
-
- r = read_one_line_file(ap, &line);
- if (r < 0)
- goto finish;
-
- r = safe_atou64(line, &u);
- if (r < 0)
- goto finish;
-
- *bytes = u * 1024ULL;
-
-finish:
- free(ap);
- free(line);
-
- return r;
-}
-
-int block_set_readahead(const char *p, uint64_t bytes) {
- struct stat st;
- char *ap = NULL, *line = NULL;
- int r;
- dev_t d;
-
- assert(p);
- assert(bytes);
-
- if (stat(p, &st) < 0)
- return -errno;
-
- if (major(st.st_dev) == 0)
- return 0;
-
- d = st.st_dev;
- block_get_whole_disk(d, &d);
-
- if (asprintf(&ap, "/sys/dev/block/%u:%u/bdi/read_ahead_kb", major(d), minor(d)) < 0) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (asprintf(&line, "%llu", (unsigned long long) bytes / 1024ULL) < 0) {
- r = -ENOMEM;
- goto finish;
- }
-
- r = write_one_line_file(ap, line);
- if (r < 0)
- goto finish;
-
-finish:
- free(ap);
- free(line);
-
- return r;
-}
diff --git a/src/readahead/readahead-common.h b/src/readahead/readahead-common.h
deleted file mode 100644
index b34f3aadd7..0000000000
--- a/src/readahead/readahead-common.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*-*- 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/stat.h>
-#include <sys/types.h>
-
-#include "macro.h"
-#include "util.h"
-
-#define READAHEAD_FILE_SIZE_MAX (10*1024*1024)
-
-#define READAHEAD_PACK_FILE_VERSION ";VERSION=2\n"
-
-extern unsigned arg_files_max;
-extern off_t arg_file_size_max;
-extern usec_t arg_timeout;
-
-int file_verify(int fd, const char *fn, off_t file_size_max, struct stat *st);
-
-int fs_on_ssd(const char *p);
-int fs_on_read_only(const char *p);
-
-bool enough_ram(void);
-
-int open_inotify(void);
-
-typedef struct ReadaheadShared {
- pid_t collect;
- pid_t replay;
-} _packed_ ReadaheadShared;
-
-ReadaheadShared *shared_get(void);
-
-int block_bump_request_nr(const char *p);
-
-int block_get_readahead(const char *p, uint64_t *bytes);
-int block_set_readahead(const char *p, uint64_t bytes);
-
-int main_collect(const char *root);
-int main_replay(const char *root);
-int main_analyze(const char *pack_path);
diff --git a/src/readahead/readahead-replay.c b/src/readahead/readahead-replay.c
deleted file mode 100644
index a1ac6b0c91..0000000000
--- a/src/readahead/readahead-replay.c
+++ /dev/null
@@ -1,311 +0,0 @@
-/*-*- 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 <errno.h>
-#include <inttypes.h>
-#include <fcntl.h>
-#include <linux/limits.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/select.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <sys/inotify.h>
-
-#include <systemd/sd-daemon.h>
-
-#include "missing.h"
-#include "util.h"
-#include "set.h"
-#include "ioprio.h"
-#include "readahead-common.h"
-#include "virt.h"
-
-static ReadaheadShared *shared = NULL;
-
-static int unpack_file(FILE *pack) {
- char fn[PATH_MAX];
- int r = 0, fd = -1;
- bool any = false;
- struct stat st;
- uint64_t inode;
-
- assert(pack);
-
- if (!fgets(fn, sizeof(fn), pack))
- return 0;
-
- char_array_0(fn);
- truncate_nl(fn);
-
- fd = open(fn, O_RDONLY|O_CLOEXEC|O_NOATIME|O_NOCTTY|O_NOFOLLOW);
- if (fd < 0) {
-
- if (errno != ENOENT && errno != EPERM && errno != EACCES)
- log_warning("open(%s) failed: %m", fn);
-
- } else if (file_verify(fd, fn, arg_file_size_max, &st) <= 0) {
- close_nointr_nofail(fd);
- fd = -1;
- }
-
- if (fread(&inode, sizeof(inode), 1, pack) != 1) {
- log_error("Premature end of pack file.");
- r = -EIO;
- goto finish;
- }
-
- if (fd >= 0) {
- /* If the inode changed the file got deleted, so just
- * ignore this entry */
- if (st.st_ino != (uint64_t) inode) {
- close_nointr_nofail(fd);
- fd = -1;
- }
- }
-
- for (;;) {
- uint32_t b, c;
-
- if (fread(&b, sizeof(b), 1, pack) != 1 ||
- fread(&c, sizeof(c), 1, pack) != 1) {
- log_error("Premature end of pack file.");
- r = -EIO;
- goto finish;
- }
-
- if (b == 0 && c == 0)
- break;
-
- if (c <= b) {
- log_error("Invalid pack file.");
- r = -EIO;
- goto finish;
- }
-
- log_debug("%s: page %u to %u", fn, b, c);
-
- any = true;
-
- if (fd >= 0)
- if (posix_fadvise(fd, b * page_size(), (c - b) * page_size(), POSIX_FADV_WILLNEED) < 0) {
- log_warning("posix_fadvise() failed: %m");
- goto finish;
- }
- }
-
- if (!any && fd >= 0) {
- /* if no range is encoded in the pack file this is
- * intended to mean that the whole file shall be
- * read */
-
- if (posix_fadvise(fd, 0, st.st_size, POSIX_FADV_WILLNEED) < 0) {
- log_warning("posix_fadvise() failed: %m");
- goto finish;
- }
- }
-
-finish:
- if (fd >= 0)
- close_nointr_nofail(fd);
-
- return r;
-}
-
-static int replay(const char *root) {
- FILE *pack = NULL;
- char line[LINE_MAX];
- int r = 0;
- char *pack_fn = NULL;
- int c;
- bool on_ssd, ready = false;
- int prio;
- int inotify_fd = -1;
-
- assert(root);
-
- block_bump_request_nr(root);
-
- if (asprintf(&pack_fn, "%s/.readahead", root) < 0) {
- r = log_oom();
- goto finish;
- }
-
- pack = fopen(pack_fn, "re");
- if (!pack) {
- if (errno == ENOENT)
- log_debug("No pack file found.");
- else {
- log_error("Failed to open pack file: %m");
- r = -errno;
- }
-
- goto finish;
- }
-
- posix_fadvise(fileno(pack), 0, 0, POSIX_FADV_WILLNEED);
-
- if ((inotify_fd = open_inotify()) < 0) {
- r = inotify_fd;
- goto finish;
- }
-
- if (!(fgets(line, sizeof(line), pack))) {
- log_error("Premature end of pack file.");
- r = -EIO;
- goto finish;
- }
-
- char_array_0(line);
-
- if (!streq(line, CANONICAL_HOST READAHEAD_PACK_FILE_VERSION)) {
- log_debug("Pack file host or version type mismatch.");
- goto finish;
- }
-
- if ((c = getc(pack)) == EOF) {
- log_debug("Premature end of pack file.");
- r = -EIO;
- goto finish;
- }
-
- /* We do not retest SSD here, so that we can start replaying
- * before udev is up.*/
- on_ssd = c == 'S';
- log_debug("On SSD: %s", yes_no(on_ssd));
-
- if (on_ssd)
- prio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0);
- else
- /* We are not using RT here, since we'd starve IO that
- we didn't record (which is for example blkid, since
- its disk accesses go directly to the block device and
- are thus not visible in fallocate) to death. However,
- we do ask for an IO prio that is slightly higher than
- the default (which is BE. 4) */
- prio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 2);
-
- if (ioprio_set(IOPRIO_WHO_PROCESS, getpid(), prio) < 0)
- log_warning("Failed to set IDLE IO priority class: %m");
-
- sd_notify(0, "STATUS=Replaying readahead data");
-
- log_debug("Replaying...");
-
- if (access("/run/systemd/readahead/noreplay", F_OK) >= 0) {
- log_debug("Got termination request");
- goto done;
- }
-
- while (!feof(pack) && !ferror(pack)) {
- uint8_t inotify_buffer[sizeof(struct inotify_event) + FILENAME_MAX];
- int k;
- ssize_t n;
-
- if ((n = read(inotify_fd, &inotify_buffer, sizeof(inotify_buffer))) < 0) {
- if (errno != EINTR && errno != EAGAIN) {
- log_error("Failed to read inotify event: %m");
- r = -errno;
- goto finish;
- }
- } else {
- struct inotify_event *e = (struct inotify_event*) inotify_buffer;
-
- while (n > 0) {
- size_t step;
-
- if ((e->mask & IN_CREATE) && streq(e->name, "noreplay")) {
- log_debug("Got termination request");
- goto done;
- }
-
- step = sizeof(struct inotify_event) + e->len;
- assert(step <= (size_t) n);
-
- e = (struct inotify_event*) ((uint8_t*) e + step);
- n -= step;
- }
- }
-
- if ((k = unpack_file(pack)) < 0) {
- r = k;
- goto finish;
- }
-
- if (!ready) {
- /* We delay the ready notification until we
- * queued at least one read */
- sd_notify(0, "READY=1");
- ready = true;
- }
- }
-
-done:
- if (!ready)
- sd_notify(0, "READY=1");
-
- if (ferror(pack)) {
- log_error("Failed to read pack file.");
- r = -EIO;
- goto finish;
- }
-
- log_debug("Done.");
-
-finish:
- if (pack)
- fclose(pack);
-
- if (inotify_fd >= 0)
- close_nointr_nofail(inotify_fd);
-
- free(pack_fn);
-
- return r;
-}
-
-int main_replay(const char *root) {
-
- if (!root)
- root = "/";
-
- if (!enough_ram()) {
- log_info("Disabling readahead replay due to low memory.");
- return EXIT_SUCCESS;
- }
-
- shared = shared_get();
- if (!shared)
- return EXIT_FAILURE;
-
- shared->replay = getpid();
- __sync_synchronize();
-
- if (replay(root) < 0)
- return EXIT_FAILURE;
-
- return EXIT_SUCCESS;
-}
diff --git a/src/readahead/readahead.c b/src/readahead/readahead.c
deleted file mode 100644
index abeecc7634..0000000000
--- a/src/readahead/readahead.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdio.h>
-#include <getopt.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-
-#include "util.h"
-#include "def.h"
-#include "readahead-common.h"
-
-unsigned arg_files_max = 16*1024;
-off_t arg_file_size_max = READAHEAD_FILE_SIZE_MAX;
-usec_t arg_timeout = 2*USEC_PER_MINUTE;
-
-static int help(void) {
-
- printf("%s [OPTIONS...] collect [DIRECTORY]\n\n"
- "Collect read-ahead data on early boot.\n\n"
- " -h --help Show this help\n"
- " --max-files=INT Maximum number of files to read ahead\n"
- " --file-size-max=BYTES Maximum size of files to read ahead\n"
- " --timeout=USEC Maximum time to spend collecting data\n\n\n",
- program_invocation_short_name);
-
- printf("%s [OPTIONS...] replay [DIRECTORY]\n\n"
- "Replay collected read-ahead data on early boot.\n\n"
- " -h --help Show this help\n"
- " --file-size-max=BYTES Maximum size of files to read ahead\n\n\n",
- program_invocation_short_name);
-
- printf("%s [OPTIONS...] analyze [PACK FILE]\n\n"
- "Analyze collected read-ahead data.\n\n"
- " -h --help Show this help\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_FILES_MAX = 0x100,
- ARG_FILE_SIZE_MAX,
- ARG_TIMEOUT
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "files-max", required_argument, NULL, ARG_FILES_MAX },
- { "file-size-max", required_argument, NULL, ARG_FILE_SIZE_MAX },
- { "timeout", required_argument, NULL, ARG_TIMEOUT },
- { NULL, 0, NULL, 0 }
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_FILES_MAX:
- if (safe_atou(optarg, &arg_files_max) < 0 || arg_files_max <= 0) {
- log_error("Failed to parse maximum number of files %s.", optarg);
- return -EINVAL;
- }
- break;
-
- case ARG_FILE_SIZE_MAX: {
- unsigned long long ull;
-
- if (safe_atollu(optarg, &ull) < 0 || ull <= 0) {
- log_error("Failed to parse maximum file size %s.", optarg);
- return -EINVAL;
- }
-
- arg_file_size_max = (off_t) ull;
- break;
- }
-
- case ARG_TIMEOUT:
- if (parse_usec(optarg, &arg_timeout) < 0 || arg_timeout <= 0) {
- log_error("Failed to parse timeout %s.", optarg);
- return -EINVAL;
- }
-
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- log_error("Unknown option code %c", c);
- return -EINVAL;
- }
- }
-
- if (optind != argc-1 &&
- optind != argc-2) {
- help();
- return -EINVAL;
- }
-
- return 1;
-}
-
-int main(int argc, char *argv[]) {
- int r;
-
- log_set_target(LOG_TARGET_SAFE);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-
- if (streq(argv[optind], "collect"))
- return main_collect(argv[optind+1]);
- else if (streq(argv[optind], "replay"))
- return main_replay(argv[optind+1]);
- else if (streq(argv[optind], "analyze"))
- return main_analyze(argv[optind+1]);
-
- log_error("Unknown verb %s.", argv[optind]);
- return EXIT_FAILURE;
-}
diff --git a/src/readahead/sd-readahead.c b/src/readahead/sd-readahead.c
deleted file mode 100644
index d48cd76807..0000000000
--- a/src/readahead/sd-readahead.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- Copyright 2010 Lennart Poettering
-
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation files
- (the "Software"), to deal in the Software without restriction,
- including without limitation the rights to use, copy, modify, merge,
- publish, distribute, sublicense, and/or sell copies of the Software,
- and to permit persons to whom the Software is furnished to do so,
- subject to the following conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
-***/
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <unistd.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <string.h>
-
-#include "sd-readahead.h"
-
-#if (__GNUC__ >= 4)
-#ifdef SD_EXPORT_SYMBOLS
-/* Export symbols */
-#define _sd_export_ __attribute__ ((visibility("default")))
-#else
-/* Don't export the symbols */
-#define _sd_export_ __attribute__ ((visibility("hidden")))
-#endif
-#else
-#define _sd_export_
-#endif
-
-static int touch(const char *path) {
-
-#if !defined(DISABLE_SYSTEMD) && defined(__linux__)
- int fd;
-
- mkdir("/run/systemd", 0755);
- mkdir("/run/systemd/readahead", 0755);
-
- fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0666);
- if (fd < 0)
- return -errno;
-
- for (;;) {
- if (close(fd) >= 0)
- break;
-
- if (errno != -EINTR)
- return -errno;
- }
-
-#endif
- return 0;
-}
-
-_sd_export_ int sd_readahead(const char *action) {
-
- if (!action)
- return -EINVAL;
-
- if (strcmp(action, "cancel") == 0)
- return touch("/run/systemd/readahead/cancel");
- else if (strcmp(action, "done") == 0)
- return touch("/run/systemd/readahead/done");
- else if (strcmp(action, "noreplay") == 0)
- return touch("/run/systemd/readahead/noreplay");
-
- return -EINVAL;
-}
diff --git a/src/remount-fs/Makefile b/src/remount-fs/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/remount-fs/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/remount-fs/remount-fs.c b/src/remount-fs/remount-fs.c
deleted file mode 100644
index b49d095cbb..0000000000
--- a/src/remount-fs/remount-fs.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*-*- 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 <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <mntent.h>
-
-#include "log.h"
-#include "util.h"
-#include "path-util.h"
-#include "set.h"
-#include "mount-setup.h"
-#include "exit-status.h"
-
-/* Goes through /etc/fstab and remounts all API file systems, applying
- * options that are in /etc/fstab that systemd might not have
- * respected */
-
-int main(int argc, char *argv[]) {
- int ret = EXIT_FAILURE;
- FILE *f = NULL;
- struct mntent* me;
- Hashmap *pids = NULL;
-
- if (argc > 1) {
- log_error("This program takes no argument.");
- return EXIT_FAILURE;
- }
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- f = setmntent("/etc/fstab", "r");
- if (!f) {
- if (errno == ENOENT) {
- ret = EXIT_SUCCESS;
- goto finish;
- }
-
- log_error("Failed to open /etc/fstab: %m");
- goto finish;
- }
-
- pids = hashmap_new(trivial_hash_func, trivial_compare_func);
- if (!pids) {
- log_error("Failed to allocate set");
- goto finish;
- }
-
- ret = EXIT_SUCCESS;
-
- while ((me = getmntent(f))) {
- pid_t pid;
- int k;
- char *s;
-
- /* Remount the root fs, /usr and all API VFS */
- if (!mount_point_is_api(me->mnt_dir) &&
- !path_equal(me->mnt_dir, "/") &&
- !path_equal(me->mnt_dir, "/usr"))
- continue;
-
- log_debug("Remounting %s", me->mnt_dir);
-
- pid = fork();
- if (pid < 0) {
- log_error("Failed to fork: %m");
- ret = EXIT_FAILURE;
- continue;
- }
-
- if (pid == 0) {
- const char *arguments[5];
- /* Child */
-
- arguments[0] = "/bin/mount";
- arguments[1] = me->mnt_dir;
- arguments[2] = "-o";
- arguments[3] = "remount";
- arguments[4] = NULL;
-
- execv("/bin/mount", (char **) arguments);
-
- log_error("Failed to execute /bin/mount: %m");
- _exit(EXIT_FAILURE);
- }
-
- /* Parent */
-
- s = strdup(me->mnt_dir);
- if (!s) {
- log_oom();
- ret = EXIT_FAILURE;
- continue;
- }
-
-
- k = hashmap_put(pids, UINT_TO_PTR(pid), s);
- if (k < 0) {
- log_error("Failed to add PID to set: %s", strerror(-k));
- ret = EXIT_FAILURE;
- continue;
- }
- }
-
- while (!hashmap_isempty(pids)) {
- siginfo_t si;
- char *s;
-
- zero(si);
- if (waitid(P_ALL, 0, &si, WEXITED) < 0) {
-
- if (errno == EINTR)
- continue;
-
- log_error("waitid() failed: %m");
- ret = EXIT_FAILURE;
- break;
- }
-
- s = hashmap_remove(pids, UINT_TO_PTR(si.si_pid));
- if (s) {
- if (!is_clean_exit(si.si_code, si.si_status, NULL)) {
- if (si.si_code == CLD_EXITED)
- log_error("/bin/mount for %s exited with exit status %i.", s, si.si_status);
- else
- log_error("/bin/mount for %s terminated by signal %s.", s, signal_to_string(si.si_status));
-
- ret = EXIT_FAILURE;
- }
-
- free(s);
- }
- }
-
-finish:
-
- if (pids)
- hashmap_free_free(pids);
-
- if (f)
- endmntent(f);
-
- return ret;
-}
diff --git a/src/reply-password/Makefile b/src/reply-password/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/reply-password/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/reply-password/reply-password.c b/src/reply-password/reply-password.c
deleted file mode 100644
index a935d0f084..0000000000
--- a/src/reply-password/reply-password.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*-*- 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/socket.h>
-#include <sys/poll.h>
-#include <sys/types.h>
-#include <assert.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/un.h>
-#include <sys/stat.h>
-#include <sys/signalfd.h>
-#include <getopt.h>
-#include <stddef.h>
-
-#include "log.h"
-#include "macro.h"
-#include "util.h"
-
-static int send_on_socket(int fd, const char *socket_name, const void *packet, size_t size) {
- union {
- struct sockaddr sa;
- struct sockaddr_un un;
- } sa;
-
- assert(fd >= 0);
- assert(socket_name);
- assert(packet);
-
- zero(sa);
- sa.un.sun_family = AF_UNIX;
- strncpy(sa.un.sun_path, socket_name, sizeof(sa.un.sun_path));
-
- if (sendto(fd, packet, size, MSG_NOSIGNAL, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(socket_name)) < 0) {
- log_error("Failed to send: %m");
- return -1;
- }
-
- return 0;
-}
-
-int main(int argc, char *argv[]) {
- int fd = -1, r = EXIT_FAILURE;
- char packet[LINE_MAX];
- size_t length;
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- if (argc != 3) {
- log_error("Wrong number of arguments.");
- goto finish;
- }
-
- if (streq(argv[1], "1")) {
-
- packet[0] = '+';
- if (!fgets(packet+1, sizeof(packet)-1, stdin)) {
- log_error("Failed to read password: %m");
- goto finish;
- }
-
- truncate_nl(packet+1);
- length = 1 + strlen(packet+1) + 1;
- } else if (streq(argv[1], "0")) {
- packet[0] = '-';
- length = 1;
- } else {
- log_error("Invalid first argument %s", argv[1]);
- goto finish;
- }
-
- if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0)) < 0) {
- log_error("socket() failed: %m");
- goto finish;
- }
-
- if (send_on_socket(fd, argv[2], packet, length) < 0)
- goto finish;
-
- r = EXIT_SUCCESS;
-
-finish:
- if (fd >= 0)
- close_nointr_nofail(fd);
-
- return r;
-}
diff --git a/src/shared/Makefile b/src/shared/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/shared/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c
deleted file mode 100644
index d1eb6f2268..0000000000
--- a/src/shared/acl-util.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <assert.h>
-#include <sys/acl.h>
-#include <acl/libacl.h>
-#include <errno.h>
-#include <stdbool.h>
-
-#include "acl-util.h"
-
-int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry) {
- acl_entry_t i;
- int found;
-
- assert(acl);
- assert(entry);
-
- for (found = acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
- found > 0;
- found = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
-
- acl_tag_t tag;
- uid_t *u;
- bool b;
-
- if (acl_get_tag_type(i, &tag) < 0)
- return -errno;
-
- if (tag != ACL_USER)
- continue;
-
- u = acl_get_qualifier(i);
- if (!u)
- return -errno;
-
- b = *u == uid;
- acl_free(u);
-
- if (b) {
- *entry = i;
- return 1;
- }
- }
-
- if (found < 0)
- return -errno;
-
- return 0;
-}
diff --git a/src/shared/acl-util.h b/src/shared/acl-util.h
deleted file mode 100644
index 31fbbcd510..0000000000
--- a/src/shared/acl-util.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry);
diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c
deleted file mode 100644
index 8a0fb89a84..0000000000
--- a/src/shared/ask-password-api.c
+++ /dev/null
@@ -1,576 +0,0 @@
-/*-*- 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 <termios.h>
-#include <unistd.h>
-#include <sys/poll.h>
-#include <sys/inotify.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <string.h>
-#include <sys/un.h>
-#include <stddef.h>
-#include <sys/signalfd.h>
-
-#include "util.h"
-#include "mkdir.h"
-#include "strv.h"
-
-#include "ask-password-api.h"
-
-static void backspace_chars(int ttyfd, size_t p) {
-
- if (ttyfd < 0)
- return;
-
- while (p > 0) {
- p--;
-
- loop_write(ttyfd, "\b \b", 3, false);
- }
-}
-
-int ask_password_tty(
- const char *message,
- usec_t until,
- const char *flag_file,
- char **_passphrase) {
-
- struct termios old_termios, new_termios;
- char passphrase[LINE_MAX];
- size_t p = 0;
- int r, ttyfd = -1, notify = -1;
- struct pollfd pollfd[2];
- bool reset_tty = false;
- bool silent_mode = false;
- bool dirty = false;
- enum {
- POLL_TTY,
- POLL_INOTIFY
- };
-
- assert(message);
- assert(_passphrase);
-
- if (flag_file) {
- if ((notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK)) < 0) {
- r = -errno;
- goto finish;
- }
-
- if (inotify_add_watch(notify, flag_file, IN_ATTRIB /* for the link count */) < 0) {
- r = -errno;
- goto finish;
- }
- }
-
- if ((ttyfd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC)) >= 0) {
-
- if (tcgetattr(ttyfd, &old_termios) < 0) {
- r = -errno;
- goto finish;
- }
-
- loop_write(ttyfd, ANSI_HIGHLIGHT_ON, sizeof(ANSI_HIGHLIGHT_ON)-1, false);
- loop_write(ttyfd, message, strlen(message), false);
- loop_write(ttyfd, " ", 1, false);
- loop_write(ttyfd, ANSI_HIGHLIGHT_OFF, sizeof(ANSI_HIGHLIGHT_OFF)-1, false);
-
- new_termios = old_termios;
- new_termios.c_lflag &= ~(ICANON|ECHO);
- new_termios.c_cc[VMIN] = 1;
- new_termios.c_cc[VTIME] = 0;
-
- if (tcsetattr(ttyfd, TCSADRAIN, &new_termios) < 0) {
- r = -errno;
- goto finish;
- }
-
- reset_tty = true;
- }
-
- zero(pollfd);
-
- pollfd[POLL_TTY].fd = ttyfd >= 0 ? ttyfd : STDIN_FILENO;
- pollfd[POLL_TTY].events = POLLIN;
- pollfd[POLL_INOTIFY].fd = notify;
- pollfd[POLL_INOTIFY].events = POLLIN;
-
- for (;;) {
- char c;
- int sleep_for = -1, k;
- ssize_t n;
-
- if (until > 0) {
- usec_t y;
-
- y = now(CLOCK_MONOTONIC);
-
- if (y > until) {
- r = -ETIME;
- goto finish;
- }
-
- sleep_for = (int) ((until - y) / USEC_PER_MSEC);
- }
-
- if (flag_file)
- if (access(flag_file, F_OK) < 0) {
- r = -errno;
- goto finish;
- }
-
- if ((k = poll(pollfd, notify > 0 ? 2 : 1, sleep_for)) < 0) {
-
- if (errno == EINTR)
- continue;
-
- r = -errno;
- goto finish;
- } else if (k == 0) {
- r = -ETIME;
- goto finish;
- }
-
- if (notify > 0 && pollfd[POLL_INOTIFY].revents != 0)
- flush_fd(notify);
-
- if (pollfd[POLL_TTY].revents == 0)
- continue;
-
- if ((n = read(ttyfd >= 0 ? ttyfd : STDIN_FILENO, &c, 1)) < 0) {
-
- if (errno == EINTR || errno == EAGAIN)
- continue;
-
- r = -errno;
- goto finish;
-
- } else if (n == 0)
- break;
-
- if (c == '\n')
- break;
- else if (c == 21) { /* C-u */
-
- if (!silent_mode)
- backspace_chars(ttyfd, p);
- p = 0;
-
- } else if (c == '\b' || c == 127) {
-
- if (p > 0) {
-
- if (!silent_mode)
- backspace_chars(ttyfd, 1);
-
- p--;
- } else if (!dirty && !silent_mode) {
-
- silent_mode = true;
-
- /* There are two ways to enter silent
- * mode. Either by pressing backspace
- * as first key (and only as first key),
- * or ... */
- if (ttyfd >= 0)
- loop_write(ttyfd, "(no echo) ", 10, false);
-
- } else if (ttyfd >= 0)
- loop_write(ttyfd, "\a", 1, false);
-
- } else if (c == '\t' && !silent_mode) {
-
- backspace_chars(ttyfd, p);
- silent_mode = true;
-
- /* ... or by pressing TAB at any time. */
-
- if (ttyfd >= 0)
- loop_write(ttyfd, "(no echo) ", 10, false);
- } else {
- passphrase[p++] = c;
-
- if (!silent_mode && ttyfd >= 0)
- loop_write(ttyfd, "*", 1, false);
-
- dirty = true;
- }
- }
-
- passphrase[p] = 0;
-
- if (!(*_passphrase = strdup(passphrase))) {
- r = -ENOMEM;
- goto finish;
- }
-
- r = 0;
-
-finish:
- if (notify >= 0)
- close_nointr_nofail(notify);
-
- if (ttyfd >= 0) {
-
- if (reset_tty) {
- loop_write(ttyfd, "\n", 1, false);
- tcsetattr(ttyfd, TCSADRAIN, &old_termios);
- }
-
- close_nointr_nofail(ttyfd);
- }
-
- return r;
-}
-
-static int create_socket(char **name) {
- int fd;
- union {
- struct sockaddr sa;
- struct sockaddr_un un;
- } sa;
- int one = 1, r;
- char *c;
- mode_t u;
-
- assert(name);
-
- if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0)) < 0) {
- log_error("socket() failed: %m");
- return -errno;
- }
-
- zero(sa);
- sa.un.sun_family = AF_UNIX;
- snprintf(sa.un.sun_path, sizeof(sa.un.sun_path)-1, "/run/systemd/ask-password/sck.%llu", random_ull());
-
- u = umask(0177);
- r = bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
- umask(u);
-
- if (r < 0) {
- r = -errno;
- log_error("bind() failed: %m");
- goto fail;
- }
-
- if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) {
- r = -errno;
- log_error("SO_PASSCRED failed: %m");
- goto fail;
- }
-
- if (!(c = strdup(sa.un.sun_path))) {
- r = log_oom();
- goto fail;
- }
-
- *name = c;
- return fd;
-
-fail:
- close_nointr_nofail(fd);
-
- return r;
-}
-
-int ask_password_agent(
- const char *message,
- const char *icon,
- usec_t until,
- bool accept_cached,
- char ***_passphrases) {
-
- enum {
- FD_SOCKET,
- FD_SIGNAL,
- _FD_MAX
- };
-
- char temp[] = "/run/systemd/ask-password/tmp.XXXXXX";
- char final[sizeof(temp)] = "";
- int fd = -1, r;
- FILE *f = NULL;
- char *socket_name = NULL;
- int socket_fd = -1, signal_fd = -1;
- sigset_t mask, oldmask;
- struct pollfd pollfd[_FD_MAX];
- mode_t u;
-
- assert(_passphrases);
-
- assert_se(sigemptyset(&mask) == 0);
- sigset_add_many(&mask, SIGINT, SIGTERM, -1);
- assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) == 0);
-
- mkdir_p_label("/run/systemd/ask-password", 0755);
-
- u = umask(0022);
- fd = mkostemp(temp, O_CLOEXEC|O_CREAT|O_WRONLY);
- umask(u);
-
- if (fd < 0) {
- log_error("Failed to create password file: %m");
- r = -errno;
- goto finish;
- }
-
- fchmod(fd, 0644);
-
- if (!(f = fdopen(fd, "w"))) {
- log_error("Failed to allocate FILE: %m");
- r = -errno;
- goto finish;
- }
-
- fd = -1;
-
- if ((signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC)) < 0) {
- log_error("signalfd(): %m");
- r = -errno;
- goto finish;
- }
-
- if ((socket_fd = create_socket(&socket_name)) < 0) {
- r = socket_fd;
- goto finish;
- }
-
- fprintf(f,
- "[Ask]\n"
- "PID=%lu\n"
- "Socket=%s\n"
- "AcceptCached=%i\n"
- "NotAfter=%llu\n",
- (unsigned long) getpid(),
- socket_name,
- accept_cached ? 1 : 0,
- (unsigned long long) until);
-
- if (message)
- fprintf(f, "Message=%s\n", message);
-
- if (icon)
- fprintf(f, "Icon=%s\n", icon);
-
- fflush(f);
-
- if (ferror(f)) {
- log_error("Failed to write query file: %m");
- r = -errno;
- goto finish;
- }
-
- memcpy(final, temp, sizeof(temp));
-
- final[sizeof(final)-11] = 'a';
- final[sizeof(final)-10] = 's';
- final[sizeof(final)-9] = 'k';
-
- if (rename(temp, final) < 0) {
- log_error("Failed to rename query file: %m");
- r = -errno;
- goto finish;
- }
-
- zero(pollfd);
- pollfd[FD_SOCKET].fd = socket_fd;
- pollfd[FD_SOCKET].events = POLLIN;
- pollfd[FD_SIGNAL].fd = signal_fd;
- pollfd[FD_SIGNAL].events = POLLIN;
-
- for (;;) {
- char passphrase[LINE_MAX+1];
- struct msghdr msghdr;
- struct iovec iovec;
- struct ucred *ucred;
- union {
- struct cmsghdr cmsghdr;
- uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
- } control;
- ssize_t n;
- int k;
- usec_t t;
-
- t = now(CLOCK_MONOTONIC);
-
- if (until > 0 && until <= t) {
- log_notice("Timed out");
- r = -ETIME;
- goto finish;
- }
-
- if ((k = poll(pollfd, _FD_MAX, until > 0 ? (int) ((until-t)/USEC_PER_MSEC) : -1)) < 0) {
-
- if (errno == EINTR)
- continue;
-
- log_error("poll() failed: %m");
- r = -errno;
- goto finish;
- }
-
- if (k <= 0) {
- log_notice("Timed out");
- r = -ETIME;
- goto finish;
- }
-
- if (pollfd[FD_SIGNAL].revents & POLLIN) {
- r = -EINTR;
- goto finish;
- }
-
- if (pollfd[FD_SOCKET].revents != POLLIN) {
- log_error("Unexpected poll() event.");
- r = -EIO;
- goto finish;
- }
-
- zero(iovec);
- iovec.iov_base = passphrase;
- iovec.iov_len = sizeof(passphrase);
-
- zero(control);
- zero(msghdr);
- msghdr.msg_iov = &iovec;
- msghdr.msg_iovlen = 1;
- msghdr.msg_control = &control;
- msghdr.msg_controllen = sizeof(control);
-
- if ((n = recvmsg(socket_fd, &msghdr, 0)) < 0) {
-
- if (errno == EAGAIN ||
- errno == EINTR)
- continue;
-
- log_error("recvmsg() failed: %m");
- r = -errno;
- goto finish;
- }
-
- if (n <= 0) {
- log_error("Message too short");
- continue;
- }
-
- if (msghdr.msg_controllen < CMSG_LEN(sizeof(struct ucred)) ||
- control.cmsghdr.cmsg_level != SOL_SOCKET ||
- control.cmsghdr.cmsg_type != SCM_CREDENTIALS ||
- control.cmsghdr.cmsg_len != CMSG_LEN(sizeof(struct ucred))) {
- log_warning("Received message without credentials. Ignoring.");
- continue;
- }
-
- ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr);
- if (ucred->uid != 0) {
- log_warning("Got request from unprivileged user. Ignoring.");
- continue;
- }
-
- if (passphrase[0] == '+') {
- char **l;
-
- if (n == 1)
- l = strv_new("", NULL);
- else
- l = strv_parse_nulstr(passphrase+1, n-1);
- /* An empty message refers to the empty password */
-
- if (!l) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (strv_length(l) <= 0) {
- strv_free(l);
- log_error("Invalid packet");
- continue;
- }
-
- *_passphrases = l;
-
- } else if (passphrase[0] == '-') {
- r = -ECANCELED;
- goto finish;
- } else {
- log_error("Invalid packet");
- continue;
- }
-
- break;
- }
-
- r = 0;
-
-finish:
- if (fd >= 0)
- close_nointr_nofail(fd);
-
- if (socket_name) {
- unlink(socket_name);
- free(socket_name);
- }
-
- if (socket_fd >= 0)
- close_nointr_nofail(socket_fd);
-
- if (signal_fd >= 0)
- close_nointr_nofail(signal_fd);
-
- if (f)
- fclose(f);
-
- unlink(temp);
-
- if (final[0])
- unlink(final);
-
- assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) == 0);
-
- return r;
-}
-
-int ask_password_auto(const char *message, const char *icon, usec_t until, bool accept_cached, char ***_passphrases) {
- assert(message);
- assert(_passphrases);
-
- if (isatty(STDIN_FILENO)) {
- int r;
- char *s = NULL, **l = NULL;
-
- if ((r = ask_password_tty(message, until, NULL, &s)) < 0)
- return r;
-
- l = strv_new(s, NULL);
- free(s);
-
- if (!l)
- return -ENOMEM;
-
- *_passphrases = l;
- return r;
-
- } else
- return ask_password_agent(message, icon, until, accept_cached, _passphrases);
-}
diff --git a/src/shared/ask-password-api.h b/src/shared/ask-password-api.h
deleted file mode 100644
index 288a0f48cf..0000000000
--- a/src/shared/ask-password-api.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*-*- 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 "util.h"
-
-int ask_password_tty(const char *message, usec_t until, const char *flag_file, char **_passphrase);
-
-int ask_password_agent(const char *message, const char *icon, usec_t until, bool accept_cached, char ***_passphrases);
-
-int ask_password_auto(const char *message, const char *icon, usec_t until, bool accept_cached, char ***_passphrases);
diff --git a/src/shared/audit.c b/src/shared/audit.c
deleted file mode 100644
index e5c483ab08..0000000000
--- a/src/shared/audit.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*-*- 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 <assert.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/prctl.h>
-#include <sys/capability.h>
-
-#include "macro.h"
-#include "audit.h"
-#include "util.h"
-#include "log.h"
-
-int audit_session_from_pid(pid_t pid, uint32_t *id) {
- char *s;
- uint32_t u;
- int r;
-
- assert(id);
-
- if (have_effective_cap(CAP_AUDIT_CONTROL) <= 0)
- return -ENOENT;
-
- if (pid == 0)
- r = read_one_line_file("/proc/self/sessionid", &s);
- else {
- char *p;
-
- if (asprintf(&p, "/proc/%lu/sessionid", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- r = read_one_line_file(p, &s);
- free(p);
- }
-
- if (r < 0)
- return r;
-
- r = safe_atou32(s, &u);
- free(s);
-
- if (r < 0)
- return r;
-
- if (u == (uint32_t) -1 || u <= 0)
- return -ENOENT;
-
- *id = u;
- return 0;
-}
-
-int audit_loginuid_from_pid(pid_t pid, uid_t *uid) {
- char *s;
- uid_t u;
- int r;
-
- assert(uid);
-
- /* Only use audit login uid if we are executed with sufficient
- * capabilities so that pam_loginuid could do its job. If we
- * are lacking the CAP_AUDIT_CONTROL capabality we most likely
- * are being run in a container and /proc/self/loginuid is
- * useless since it probably contains a uid of the host
- * system. */
-
- if (have_effective_cap(CAP_AUDIT_CONTROL) <= 0)
- return -ENOENT;
-
- if (pid == 0)
- r = read_one_line_file("/proc/self/loginuid", &s);
- else {
- char *p;
-
- if (asprintf(&p, "/proc/%lu/loginuid", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- r = read_one_line_file(p, &s);
- free(p);
- }
-
- if (r < 0)
- return r;
-
- r = parse_uid(s, &u);
- free(s);
-
- if (r < 0)
- return r;
-
- if (u == (uid_t) -1)
- return -ENOENT;
-
- *uid = (uid_t) u;
- return 0;
-}
diff --git a/src/shared/audit.h b/src/shared/audit.h
deleted file mode 100644
index 490a0b0320..0000000000
--- a/src/shared/audit.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef fooaudithfoo
-#define fooaudithfoo
-
-/***
- 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/types.h>
-
-#include "capability.h"
-
-int audit_session_from_pid(pid_t pid, uint32_t *id);
-int audit_loginuid_from_pid(pid_t pid, uid_t *uid);
-
-#endif
diff --git a/src/shared/capability.c b/src/shared/capability.c
deleted file mode 100644
index 9b743e86d0..0000000000
--- a/src/shared/capability.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*-*- 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 <assert.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <sys/capability.h>
-#include <sys/prctl.h>
-
-#include "macro.h"
-#include "capability.h"
-#include "util.h"
-#include "log.h"
-
-int have_effective_cap(int value) {
- cap_t cap;
- cap_flag_value_t fv;
- int r;
-
- cap = cap_get_proc();
- if (!cap)
- return -errno;
-
- if (cap_get_flag(cap, value, CAP_EFFECTIVE, &fv) < 0)
- r = -errno;
- else
- r = fv == CAP_SET;
-
- cap_free(cap);
- return r;
-}
-
-unsigned long cap_last_cap(void) {
- static __thread unsigned long saved;
- static __thread bool valid = false;
- unsigned long p;
-
- if (valid)
- return saved;
-
- p = (unsigned long) CAP_LAST_CAP;
-
- if (prctl(PR_CAPBSET_READ, p) < 0) {
-
- /* Hmm, look downwards, until we find one that
- * works */
- for (p--; p > 0; p --)
- if (prctl(PR_CAPBSET_READ, p) >= 0)
- break;
-
- } else {
-
- /* Hmm, look upwards, until we find one that doesn't
- * work */
- for (;; p++)
- if (prctl(PR_CAPBSET_READ, p+1) < 0)
- break;
- }
-
- saved = p;
- valid = true;
-
- return p;
-}
-
-int capability_bounding_set_drop(uint64_t drop, bool right_now) {
- unsigned long i;
- cap_t after_cap = NULL, temp_cap = NULL;
- cap_flag_value_t fv;
- int r;
-
- /* If we are run as PID 1 we will lack CAP_SETPCAP by default
- * in the effective set (yes, the kernel drops that when
- * executing init!), so get it back temporarily so that we can
- * call PR_CAPBSET_DROP. */
-
- after_cap = cap_get_proc();
- if (!after_cap)
- return -errno;
-
- if (cap_get_flag(after_cap, CAP_SETPCAP, CAP_EFFECTIVE, &fv) < 0) {
- cap_free(after_cap);
- return -errno;
- }
-
- if (fv != CAP_SET) {
- static const cap_value_t v = CAP_SETPCAP;
-
- temp_cap = cap_dup(after_cap);
- if (!temp_cap) {
- r = -errno;
- goto finish;
- }
-
- if (cap_set_flag(temp_cap, CAP_EFFECTIVE, 1, &v, CAP_SET) < 0) {
- r = -errno;
- goto finish;
- }
-
- if (cap_set_proc(temp_cap) < 0) {
- r = -errno;
- goto finish;
- }
- }
-
- for (i = 0; i <= cap_last_cap(); i++) {
-
- if (drop & ((uint64_t) 1ULL << (uint64_t) i)) {
- cap_value_t v;
-
- /* Drop it from the bounding set */
- if (prctl(PR_CAPBSET_DROP, i) < 0) {
- r = -errno;
- goto finish;
- }
- v = i;
-
- /* Also drop it from the inheritable set, so
- * that anything we exec() loses the
- * capability for good. */
- if (cap_set_flag(after_cap, CAP_INHERITABLE, 1, &v, CAP_CLEAR) < 0) {
- r = -errno;
- goto finish;
- }
-
- /* If we shall apply this right now drop it
- * also from our own capability sets. */
- if (right_now) {
- if (cap_set_flag(after_cap, CAP_PERMITTED, 1, &v, CAP_CLEAR) < 0 ||
- cap_set_flag(after_cap, CAP_EFFECTIVE, 1, &v, CAP_CLEAR) < 0) {
- r = -errno;
- goto finish;
- }
- }
- }
- }
-
- r = 0;
-
-finish:
- if (temp_cap)
- cap_free(temp_cap);
-
- if (after_cap) {
- cap_set_proc(after_cap);
- cap_free(after_cap);
- }
-
- return r;
-}
-
-static int drop_from_file(const char *fn, uint64_t drop) {
- int r, k;
- uint32_t hi, lo;
- uint64_t current, after;
- char *p;
-
- r = read_one_line_file(fn, &p);
- if (r < 0)
- return r;
-
- assert_cc(sizeof(hi) == sizeof(unsigned));
- assert_cc(sizeof(lo) == sizeof(unsigned));
-
- k = sscanf(p, "%u %u", &lo, &hi);
- free(p);
-
- if (k != 2)
- return -EIO;
-
- current = (uint64_t) lo | ((uint64_t) hi << 32ULL);
- after = current & ~drop;
-
- if (current == after)
- return 0;
-
- lo = (unsigned) (after & 0xFFFFFFFFULL);
- hi = (unsigned) ((after >> 32ULL) & 0xFFFFFFFFULL);
-
- if (asprintf(&p, "%u %u", lo, hi) < 0)
- return -ENOMEM;
-
- r = write_one_line_file(fn, p);
- free(p);
-
- return r;
-}
-
-int capability_bounding_set_drop_usermode(uint64_t drop) {
- int r;
-
- r = drop_from_file("/proc/sys/kernel/usermodehelper/inheritable", drop);
- if (r < 0)
- return r;
-
- r = drop_from_file("/proc/sys/kernel/usermodehelper/bset", drop);
- if (r < 0)
- return r;
-
- return r;
-}
diff --git a/src/shared/capability.h b/src/shared/capability.h
deleted file mode 100644
index 6cb31bb510..0000000000
--- a/src/shared/capability.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef foocapabilityhfoo
-#define foocapabilityhfoo
-
-/***
- 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 <stdbool.h>
-
-unsigned long cap_last_cap(void);
-int have_effective_cap(int value);
-int capability_bounding_set_drop(uint64_t drop, bool right_now);
-int capability_bounding_set_drop_usermode(uint64_t drop);
-
-#endif
diff --git a/src/shared/cgroup-label.c b/src/shared/cgroup-label.c
deleted file mode 100644
index beeeec5830..0000000000
--- a/src/shared/cgroup-label.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*-*- 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 <errno.h>
-#include <unistd.h>
-#include <signal.h>
-#include <string.h>
-#include <stdlib.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <ftw.h>
-
-#include "cgroup-util.h"
-#include "log.h"
-#include "set.h"
-#include "macro.h"
-#include "util.h"
-#include "mkdir.h"
-
-int cg_create(const char *controller, const char *path) {
- char *fs;
- int r;
-
- assert(controller);
- assert(path);
-
- r = cg_get_path_and_check(controller, path, NULL, &fs);
- if (r < 0)
- return r;
-
- r = mkdir_parents_label(fs, 0755);
-
- if (r >= 0) {
- if (mkdir(fs, 0755) >= 0)
- r = 1;
- else if (errno == EEXIST)
- r = 0;
- else
- r = -errno;
- }
-
- free(fs);
-
- return r;
-}
-
-int cg_create_and_attach(const char *controller, const char *path, pid_t pid) {
- int r, q;
-
- assert(controller);
- assert(path);
- assert(pid >= 0);
-
- if ((r = cg_create(controller, path)) < 0)
- return r;
-
- if ((q = cg_attach(controller, path, pid)) < 0)
- return q;
-
- /* This does not remove the cgroup on failure */
-
- return r;
-}
diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c
deleted file mode 100644
index 437d09711b..0000000000
--- a/src/shared/cgroup-show.c
+++ /dev/null
@@ -1,351 +0,0 @@
-/*-*- 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 <stdio.h>
-#include <string.h>
-#include <dirent.h>
-#include <errno.h>
-
-#include "util.h"
-#include "macro.h"
-#include "path-util.h"
-#include "cgroup-util.h"
-#include "cgroup-show.h"
-
-static int compare(const void *a, const void *b) {
- const pid_t *p = a, *q = b;
-
- if (*p < *q)
- return -1;
- if (*p > *q)
- return 1;
- return 0;
-}
-
-static unsigned ilog10(unsigned long ul) {
- int n = 0;
-
- while (ul > 0) {
- n++;
- ul /= 10;
- }
-
- return n;
-}
-
-static void show_pid_array(int pids[], unsigned n_pids, const char *prefix, unsigned n_columns, bool extra, bool more, bool kernel_threads) {
- unsigned i, m, pid_width;
- pid_t biggest = 0;
-
- /* Filter duplicates */
- m = 0;
- for (i = 0; i < n_pids; i++) {
- unsigned j;
-
- if (pids[i] > biggest)
- biggest = pids[i];
-
- for (j = i+1; j < n_pids; j++)
- if (pids[i] == pids[j])
- break;
-
- if (j >= n_pids)
- pids[m++] = pids[i];
- }
- n_pids = m;
- pid_width = ilog10(biggest);
-
- /* And sort */
- qsort(pids, n_pids, sizeof(pid_t), compare);
-
- if (n_columns > pid_width+2)
- n_columns -= pid_width+2;
- else
- n_columns = 20;
-
- for (i = 0; i < n_pids; i++) {
- char *t = NULL;
-
- get_process_cmdline(pids[i], n_columns, true, &t);
-
- printf("%s%s%*lu %s\n",
- prefix,
- draw_special_char(extra ? DRAW_TRIANGULAR_BULLET :
- ((more || i < n_pids-1) ? DRAW_TREE_BRANCH : DRAW_TREE_RIGHT)),
- pid_width,
- (unsigned long) pids[i],
- strna(t));
-
- free(t);
- }
-}
-
-
-static int show_cgroup_one_by_path(const char *path, const char *prefix, unsigned n_columns, bool more, bool kernel_threads) {
- char *fn;
- FILE *f;
- size_t n = 0, n_allocated = 0;
- pid_t *pids = NULL;
- char *p;
- pid_t pid;
- int r;
-
- r = cg_fix_path(path, &p);
- if (r < 0)
- return r;
-
- r = asprintf(&fn, "%s/cgroup.procs", p);
- free(p);
- if (r < 0)
- return -ENOMEM;
-
- f = fopen(fn, "re");
- free(fn);
- if (!f)
- return -errno;
-
- while ((r = cg_read_pid(f, &pid)) > 0) {
-
- if (!kernel_threads && is_kernel_thread(pid) > 0)
- continue;
-
- if (n >= n_allocated) {
- pid_t *npids;
-
- n_allocated = MAX(16U, n*2U);
-
- npids = realloc(pids, sizeof(pid_t) * n_allocated);
- if (!npids) {
- r = -ENOMEM;
- goto finish;
- }
-
- pids = npids;
- }
-
- assert(n < n_allocated);
- pids[n++] = pid;
- }
-
- if (r < 0)
- goto finish;
-
- if (n > 0)
- show_pid_array(pids, n, prefix, n_columns, false, more, kernel_threads);
-
- r = 0;
-
-finish:
- free(pids);
-
- if (f)
- fclose(f);
-
- return r;
-}
-
-int show_cgroup_by_path(const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, bool all) {
- DIR *d;
- char *last = NULL;
- char *p1 = NULL, *p2 = NULL, *fn = NULL, *gn = NULL;
- bool shown_pids = false;
- int r;
-
- assert(path);
-
- if (n_columns <= 0)
- n_columns = columns();
-
- if (!prefix)
- prefix = "";
-
- r = cg_fix_path(path, &fn);
- if (r < 0)
- return r;
-
- d = opendir(fn);
- if (!d) {
- free(fn);
- return -errno;
- }
-
- while ((r = cg_read_subgroup(d, &gn)) > 0) {
- char *k;
-
- r = asprintf(&k, "%s/%s", fn, gn);
- free(gn);
- if (r < 0) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (!all && cg_is_empty_recursive(NULL, k, false) > 0) {
- free(k);
- continue;
- }
-
- if (!shown_pids) {
- show_cgroup_one_by_path(path, prefix, n_columns, true, kernel_threads);
- shown_pids = true;
- }
-
- if (last) {
- printf("%s%s%s\n", prefix, draw_special_char(DRAW_TREE_BRANCH),
- path_get_file_name(last));
-
- if (!p1) {
- p1 = strappend(prefix, draw_special_char(DRAW_TREE_VERT));
- if (!p1) {
- free(k);
- r = -ENOMEM;
- goto finish;
- }
- }
-
- show_cgroup_by_path(last, p1, n_columns-2, kernel_threads, all);
- free(last);
- }
-
- last = k;
- }
-
- if (r < 0)
- goto finish;
-
- if (!shown_pids)
- show_cgroup_one_by_path(path, prefix, n_columns, !!last, kernel_threads);
-
- if (last) {
- printf("%s%s%s\n", prefix, draw_special_char(DRAW_TREE_RIGHT),
- path_get_file_name(last));
-
- if (!p2) {
- p2 = strappend(prefix, " ");
- if (!p2) {
- r = -ENOMEM;
- goto finish;
- }
- }
-
- show_cgroup_by_path(last, p2, n_columns-2, kernel_threads, all);
- }
-
- r = 0;
-
-finish:
- free(p1);
- free(p2);
- free(last);
- free(fn);
-
- closedir(d);
-
- return r;
-}
-
-int show_cgroup(const char *controller, const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, bool all) {
- char *p;
- int r;
-
- assert(controller);
- assert(path);
-
- r = cg_get_path(controller, path, NULL, &p);
- if (r < 0)
- return r;
-
- r = show_cgroup_by_path(p, prefix, n_columns, kernel_threads, all);
- free(p);
-
- return r;
-}
-
-static int show_extra_pids(const char *controller, const char *path, const char *prefix, unsigned n_columns, const pid_t pids[], unsigned n_pids) {
- pid_t *copy;
- unsigned i, j;
- int r;
-
- assert(controller);
- assert(path);
-
- if (n_pids <= 0)
- return 0;
-
- if (n_columns <= 0)
- n_columns = columns();
-
- if (!prefix)
- prefix = "";
-
- copy = new(pid_t, n_pids);
- if (!copy)
- return -ENOMEM;
-
- for (i = 0, j = 0; i < n_pids; i++) {
- char *k;
-
- r = cg_get_by_pid(controller, pids[i], &k);
- if (r < 0) {
- free(copy);
- return r;
- }
-
- if (path_startswith(k, path))
- continue;
-
- copy[j++] = pids[i];
- }
-
- show_pid_array(copy, j, prefix, n_columns, true, false, false);
-
- free(copy);
- return 0;
-}
-
-int show_cgroup_and_extra(const char *controller, const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, bool all, const pid_t extra_pids[], unsigned n_extra_pids) {
- int r;
-
- assert(controller);
- assert(path);
-
- r = show_cgroup(controller, path, prefix, n_columns, kernel_threads, all);
- if (r < 0)
- return r;
-
- return show_extra_pids(controller, path, prefix, n_columns, extra_pids, n_extra_pids);
-}
-
-int show_cgroup_and_extra_by_spec(const char *spec, const char *prefix, unsigned n_columns, bool kernel_threads, bool all, const pid_t extra_pids[], unsigned n_extra_pids) {
- int r;
- char *controller, *path;
-
- assert(spec);
-
- r = cg_split_spec(spec, &controller, &path);
- if (r < 0)
- return r;
-
- r = show_cgroup_and_extra(controller, path, prefix, n_columns, kernel_threads, all, extra_pids, n_extra_pids);
- free(controller);
- free(path);
-
- return r;
-}
diff --git a/src/shared/cgroup-show.h b/src/shared/cgroup-show.h
deleted file mode 100644
index dba900a153..0000000000
--- a/src/shared/cgroup-show.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef foocgroupshowhfoo
-#define foocgroupshowhfoo
-
-/***
- 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>
-
-int show_cgroup_by_path(const char *path, const char *prefix, unsigned columns, bool kernel_threads, bool all);
-int show_cgroup(const char *controller, const char *path, const char *prefix, unsigned columns, bool kernel_threads, bool all);
-
-int show_cgroup_and_extra_by_spec(const char *spec, const char *prefix, unsigned n_columns, bool kernel_threads, bool all, const pid_t extra_pids[], unsigned n_extra_pids);
-int show_cgroup_and_extra(const char *controller, const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, bool all, const pid_t extra_pids[], unsigned n_extra_pids);
-
-#endif
diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c
deleted file mode 100644
index b0d378de5a..0000000000
--- a/src/shared/cgroup-util.c
+++ /dev/null
@@ -1,1256 +0,0 @@
-/*-*- 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 <errno.h>
-#include <unistd.h>
-#include <signal.h>
-#include <string.h>
-#include <stdlib.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <ftw.h>
-
-#include "cgroup-util.h"
-#include "log.h"
-#include "set.h"
-#include "macro.h"
-#include "util.h"
-#include "path-util.h"
-#include "strv.h"
-
-int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
- char *fs;
- int r;
- FILE *f;
-
- assert(path);
- assert(_f);
-
- r = cg_get_path(controller, path, "cgroup.procs", &fs);
- if (r < 0)
- return r;
-
- f = fopen(fs, "re");
- free(fs);
-
- if (!f)
- return -errno;
-
- *_f = f;
- return 0;
-}
-
-int cg_enumerate_tasks(const char *controller, const char *path, FILE **_f) {
- char *fs;
- int r;
- FILE *f;
-
- assert(path);
- assert(_f);
-
- r = cg_get_path(controller, path, "tasks", &fs);
- if (r < 0)
- return r;
-
- f = fopen(fs, "re");
- free(fs);
-
- if (!f)
- return -errno;
-
- *_f = f;
- return 0;
-}
-
-int cg_read_pid(FILE *f, pid_t *_pid) {
- unsigned long ul;
-
- /* Note that the cgroup.procs might contain duplicates! See
- * cgroups.txt for details. */
-
- errno = 0;
- if (fscanf(f, "%lu", &ul) != 1) {
-
- if (feof(f))
- return 0;
-
- return errno ? -errno : -EIO;
- }
-
- if (ul <= 0)
- return -EIO;
-
- *_pid = (pid_t) ul;
- return 1;
-}
-
-int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d) {
- char *fs;
- int r;
- DIR *d;
-
- assert(path);
- assert(_d);
-
- /* This is not recursive! */
-
- r = cg_get_path(controller, path, NULL, &fs);
- if (r < 0)
- return r;
-
- d = opendir(fs);
- free(fs);
-
- if (!d)
- return -errno;
-
- *_d = d;
- return 0;
-}
-
-int cg_read_subgroup(DIR *d, char **fn) {
- struct dirent *de;
-
- assert(d);
-
- errno = 0;
- while ((de = readdir(d))) {
- char *b;
-
- if (de->d_type != DT_DIR)
- continue;
-
- if (streq(de->d_name, ".") ||
- streq(de->d_name, ".."))
- continue;
-
- if (!(b = strdup(de->d_name)))
- return -ENOMEM;
-
- *fn = b;
- return 1;
- }
-
- if (errno)
- return -errno;
-
- return 0;
-}
-
-int cg_rmdir(const char *controller, const char *path, bool honour_sticky) {
- char *p;
- int r;
-
- r = cg_get_path(controller, path, NULL, &p);
- if (r < 0)
- return r;
-
- if (honour_sticky) {
- char *tasks;
-
- /* If the sticky bit is set don't remove the directory */
-
- tasks = strappend(p, "/tasks");
- if (!tasks) {
- free(p);
- return -ENOMEM;
- }
-
- r = file_is_priv_sticky(tasks);
- free(tasks);
-
- if (r > 0) {
- free(p);
- return 0;
- }
- }
-
- r = rmdir(p);
- free(p);
-
- return (r < 0 && errno != ENOENT) ? -errno : 0;
-}
-
-int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s) {
- bool done = false;
- int r, ret = 0;
- pid_t my_pid;
- FILE *f = NULL;
- Set *allocated_set = NULL;
-
- assert(controller);
- assert(path);
- assert(sig >= 0);
-
- /* This goes through the tasks list and kills them all. This
- * is repeated until no further processes are added to the
- * tasks list, to properly handle forking processes */
-
- if (!s)
- if (!(s = allocated_set = set_new(trivial_hash_func, trivial_compare_func)))
- return -ENOMEM;
-
- my_pid = getpid();
-
- do {
- pid_t pid = 0;
- done = true;
-
- if ((r = cg_enumerate_processes(controller, path, &f)) < 0) {
- if (ret >= 0 && r != -ENOENT)
- ret = r;
-
- goto finish;
- }
-
- while ((r = cg_read_pid(f, &pid)) > 0) {
-
- if (pid == my_pid && ignore_self)
- continue;
-
- if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
- continue;
-
- /* If we haven't killed this process yet, kill
- * it */
- if (kill(pid, sig) < 0) {
- if (ret >= 0 && errno != ESRCH)
- ret = -errno;
- } else if (ret == 0) {
-
- if (sigcont)
- kill(pid, SIGCONT);
-
- ret = 1;
- }
-
- done = false;
-
- if ((r = set_put(s, LONG_TO_PTR(pid))) < 0) {
- if (ret >= 0)
- ret = r;
-
- goto finish;
- }
- }
-
- if (r < 0) {
- if (ret >= 0)
- ret = r;
-
- goto finish;
- }
-
- fclose(f);
- f = NULL;
-
- /* To avoid racing against processes which fork
- * quicker than we can kill them we repeat this until
- * no new pids need to be killed. */
-
- } while (!done);
-
-finish:
- if (allocated_set)
- set_free(allocated_set);
-
- if (f)
- fclose(f);
-
- return ret;
-}
-
-int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool rem, Set *s) {
- int r, ret = 0;
- DIR *d = NULL;
- char *fn;
- Set *allocated_set = NULL;
-
- assert(path);
- assert(controller);
- assert(sig >= 0);
-
- if (!s)
- if (!(s = allocated_set = set_new(trivial_hash_func, trivial_compare_func)))
- return -ENOMEM;
-
- ret = cg_kill(controller, path, sig, sigcont, ignore_self, s);
-
- if ((r = cg_enumerate_subgroups(controller, path, &d)) < 0) {
- if (ret >= 0 && r != -ENOENT)
- ret = r;
-
- goto finish;
- }
-
- while ((r = cg_read_subgroup(d, &fn)) > 0) {
- char *p = NULL;
-
- r = asprintf(&p, "%s/%s", path, fn);
- free(fn);
-
- if (r < 0) {
- if (ret >= 0)
- ret = -ENOMEM;
-
- goto finish;
- }
-
- r = cg_kill_recursive(controller, p, sig, sigcont, ignore_self, rem, s);
- free(p);
-
- if (r != 0 && ret >= 0)
- ret = r;
- }
-
- if (r < 0 && ret >= 0)
- ret = r;
-
- if (rem)
- if ((r = cg_rmdir(controller, path, true)) < 0) {
- if (ret >= 0 &&
- r != -ENOENT &&
- r != -EBUSY)
- ret = r;
- }
-
-finish:
- if (d)
- closedir(d);
-
- if (allocated_set)
- set_free(allocated_set);
-
- return ret;
-}
-
-int cg_kill_recursive_and_wait(const char *controller, const char *path, bool rem) {
- unsigned i;
-
- assert(path);
- assert(controller);
-
- /* This safely kills all processes; first it sends a SIGTERM,
- * then checks 8 times after 200ms whether the group is now
- * empty, then kills everything that is left with SIGKILL and
- * finally checks 5 times after 200ms each whether the group
- * is finally empty. */
-
- for (i = 0; i < 15; i++) {
- int sig, r;
-
- if (i <= 0)
- sig = SIGTERM;
- else if (i == 9)
- sig = SIGKILL;
- else
- sig = 0;
-
- if ((r = cg_kill_recursive(controller, path, sig, true, true, rem, NULL)) <= 0)
- return r;
-
- usleep(200 * USEC_PER_MSEC);
- }
-
- return 0;
-}
-
-int cg_migrate(const char *controller, const char *from, const char *to, bool ignore_self) {
- bool done = false;
- Set *s;
- int r, ret = 0;
- pid_t my_pid;
- FILE *f = NULL;
-
- assert(controller);
- assert(from);
- assert(to);
-
- if (!(s = set_new(trivial_hash_func, trivial_compare_func)))
- return -ENOMEM;
-
- my_pid = getpid();
-
- do {
- pid_t pid = 0;
- done = true;
-
- if ((r = cg_enumerate_tasks(controller, from, &f)) < 0) {
- if (ret >= 0 && r != -ENOENT)
- ret = r;
-
- goto finish;
- }
-
- while ((r = cg_read_pid(f, &pid)) > 0) {
-
- /* This might do weird stuff if we aren't a
- * single-threaded program. However, we
- * luckily know we are not */
- if (pid == my_pid && ignore_self)
- continue;
-
- if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
- continue;
-
- if ((r = cg_attach(controller, to, pid)) < 0) {
- if (ret >= 0 && r != -ESRCH)
- ret = r;
- } else if (ret == 0)
- ret = 1;
-
- done = false;
-
- if ((r = set_put(s, LONG_TO_PTR(pid))) < 0) {
- if (ret >= 0)
- ret = r;
-
- goto finish;
- }
- }
-
- if (r < 0) {
- if (ret >= 0)
- ret = r;
-
- goto finish;
- }
-
- fclose(f);
- f = NULL;
-
- } while (!done);
-
-finish:
- set_free(s);
-
- if (f)
- fclose(f);
-
- return ret;
-}
-
-int cg_migrate_recursive(const char *controller, const char *from, const char *to, bool ignore_self, bool rem) {
- int r, ret = 0;
- DIR *d = NULL;
- char *fn;
-
- assert(controller);
- assert(from);
- assert(to);
-
- ret = cg_migrate(controller, from, to, ignore_self);
-
- if ((r = cg_enumerate_subgroups(controller, from, &d)) < 0) {
- if (ret >= 0 && r != -ENOENT)
- ret = r;
- goto finish;
- }
-
- while ((r = cg_read_subgroup(d, &fn)) > 0) {
- char *p = NULL;
-
- r = asprintf(&p, "%s/%s", from, fn);
- free(fn);
-
- if (r < 0) {
- if (ret >= 0)
- ret = -ENOMEM;
-
- goto finish;
- }
-
- r = cg_migrate_recursive(controller, p, to, ignore_self, rem);
- free(p);
-
- if (r != 0 && ret >= 0)
- ret = r;
- }
-
- if (r < 0 && ret >= 0)
- ret = r;
-
- if (rem)
- if ((r = cg_rmdir(controller, from, true)) < 0) {
- if (ret >= 0 &&
- r != -ENOENT &&
- r != -EBUSY)
- ret = r;
- }
-
-finish:
- if (d)
- closedir(d);
-
- return ret;
-}
-
-static const char *normalize_controller(const char *controller) {
-
- if (streq(controller, SYSTEMD_CGROUP_CONTROLLER))
- return "systemd";
- else if (startswith(controller, "name="))
- return controller + 5;
- else
- return controller;
-}
-
-static int join_path(const char *controller, const char *path, const char *suffix, char **fs) {
- char *t = NULL;
-
- if (!(controller || path))
- return -EINVAL;
-
- if (controller) {
- if (path && suffix)
- t = strjoin("/sys/fs/cgroup/", controller, "/", path, "/", suffix, NULL);
- else if (path)
- t = strjoin("/sys/fs/cgroup/", controller, "/", path, NULL);
- else if (suffix)
- t = strjoin("/sys/fs/cgroup/", controller, "/", suffix, NULL);
- else
- t = strjoin("/sys/fs/cgroup/", controller, NULL);
- } else {
- if (path && suffix)
- t = strjoin(path, "/", suffix, NULL);
- else if (path)
- t = strdup(path);
- }
-
- if (!t)
- return -ENOMEM;
-
- path_kill_slashes(t);
-
- *fs = t;
- return 0;
-}
-
-int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) {
- const char *p;
- static __thread bool good = false;
-
- assert(fs);
-
- if (_unlikely_(!good)) {
- int r;
-
- r = path_is_mount_point("/sys/fs/cgroup", false);
- if (r <= 0)
- return r < 0 ? r : -ENOENT;
-
- /* Cache this to save a few stat()s */
- good = true;
- }
-
- p = controller ? normalize_controller(controller) : NULL;
- return join_path(p, path, suffix, fs);
-}
-
-static int check(const char *p) {
- char *cc;
-
- assert(p);
-
- /* Check if this controller actually really exists */
- cc = alloca(sizeof("/sys/fs/cgroup/") + strlen(p));
- strcpy(stpcpy(cc, "/sys/fs/cgroup/"), p);
- if (access(cc, F_OK) < 0)
- return -errno;
-
- return 0;
-}
-
-int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs) {
- const char *p;
- int r;
-
- assert(controller);
- assert(fs);
-
- if (isempty(controller))
- return -EINVAL;
-
- /* Normalize the controller syntax */
- p = normalize_controller(controller);
-
- /* Check if this controller actually really exists */
- r = check(p);
- if (r < 0)
- return r;
-
- return join_path(p, path, suffix, fs);
-}
-
-static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
- char *p;
- bool is_sticky;
-
- if (typeflag != FTW_DP)
- return 0;
-
- if (ftwbuf->level < 1)
- return 0;
-
- p = strappend(path, "/tasks");
- if (!p) {
- errno = ENOMEM;
- return 1;
- }
-
- is_sticky = file_is_priv_sticky(p) > 0;
- free(p);
-
- if (is_sticky)
- return 0;
-
- rmdir(path);
- return 0;
-}
-
-int cg_trim(const char *controller, const char *path, bool delete_root) {
- char *fs;
- int r = 0;
-
- assert(controller);
- assert(path);
-
- r = cg_get_path(controller, path, NULL, &fs);
- if (r < 0)
- return r;
-
- errno = 0;
- if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) < 0)
- r = errno ? -errno : -EIO;
-
- if (delete_root) {
- bool is_sticky;
- char *p;
-
- p = strappend(fs, "/tasks");
- if (!p) {
- free(fs);
- return -ENOMEM;
- }
-
- is_sticky = file_is_priv_sticky(p) > 0;
- free(p);
-
- if (!is_sticky)
- if (rmdir(fs) < 0 && errno != ENOENT) {
- if (r == 0)
- r = -errno;
- }
- }
-
- free(fs);
-
- return r;
-}
-
-int cg_delete(const char *controller, const char *path) {
- char *parent;
- int r;
-
- assert(controller);
- assert(path);
-
- if ((r = path_get_parent(path, &parent)) < 0)
- return r;
-
- r = cg_migrate_recursive(controller, path, parent, false, true);
- free(parent);
-
- return r == -ENOENT ? 0 : r;
-}
-
-int cg_attach(const char *controller, const char *path, pid_t pid) {
- char *fs;
- int r;
- char c[32];
-
- assert(controller);
- assert(path);
- assert(pid >= 0);
-
- r = cg_get_path_and_check(controller, path, "tasks", &fs);
- if (r < 0)
- return r;
-
- if (pid == 0)
- pid = getpid();
-
- snprintf(c, sizeof(c), "%lu\n", (unsigned long) pid);
- char_array_0(c);
-
- r = write_one_line_file(fs, c);
- free(fs);
-
- return r;
-}
-
-int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid) {
- char *fs;
- int r;
-
- assert(controller);
- assert(path);
-
- if (mode != (mode_t) -1)
- mode &= 0777;
-
- r = cg_get_path(controller, path, NULL, &fs);
- if (r < 0)
- return r;
-
- r = chmod_and_chown(fs, mode, uid, gid);
- free(fs);
-
- return r;
-}
-
-int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid, int sticky) {
- char *fs;
- int r;
-
- assert(controller);
- assert(path);
-
- if (mode == (mode_t) -1 && uid == (uid_t) -1 && gid == (gid_t) -1 && sticky < 0)
- return 0;
-
- if (mode != (mode_t) -1)
- mode &= 0666;
-
- r = cg_get_path(controller, path, "tasks", &fs);
- if (r < 0)
- return r;
-
- if (sticky >= 0 && mode != (mode_t) -1)
- /* Both mode and sticky param are passed */
- mode |= (sticky ? S_ISVTX : 0);
- else if ((sticky >= 0 && mode == (mode_t) -1) ||
- (mode != (mode_t) -1 && sticky < 0)) {
- struct stat st;
-
- /* Only one param is passed, hence read the current
- * mode from the file itself */
-
- r = lstat(fs, &st);
- if (r < 0) {
- free(fs);
- return -errno;
- }
-
- if (mode == (mode_t) -1)
- /* No mode set, we just shall set the sticky bit */
- mode = (st.st_mode & ~S_ISVTX) | (sticky ? S_ISVTX : 0);
- else
- /* Only mode set, leave sticky bit untouched */
- mode = (st.st_mode & ~0777) | mode;
- }
-
- r = chmod_and_chown(fs, mode, uid, gid);
- free(fs);
-
- return r;
-}
-
-int cg_get_by_pid(const char *controller, pid_t pid, char **path) {
- int r;
- char *p = NULL;
- FILE *f;
- char *fs;
- size_t cs;
-
- assert(controller);
- assert(path);
- assert(pid >= 0);
-
- if (pid == 0)
- pid = getpid();
-
- if (asprintf(&fs, "/proc/%lu/cgroup", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- f = fopen(fs, "re");
- free(fs);
-
- if (!f)
- return errno == ENOENT ? -ESRCH : -errno;
-
- cs = strlen(controller);
-
- while (!feof(f)) {
- char line[LINE_MAX];
- char *l;
-
- errno = 0;
- if (!(fgets(line, sizeof(line), f))) {
- if (feof(f))
- break;
-
- r = errno ? -errno : -EIO;
- goto finish;
- }
-
- truncate_nl(line);
-
- if (!(l = strchr(line, ':')))
- continue;
-
- l++;
- if (strncmp(l, controller, cs) != 0)
- continue;
-
- if (l[cs] != ':')
- continue;
-
- if (!(p = strdup(l + cs + 1))) {
- r = -ENOMEM;
- goto finish;
- }
-
- *path = p;
- r = 0;
- goto finish;
- }
-
- r = -ENOENT;
-
-finish:
- fclose(f);
-
- return r;
-}
-
-int cg_install_release_agent(const char *controller, const char *agent) {
- char *fs = NULL, *contents = NULL, *line = NULL, *sc;
- int r;
-
- assert(controller);
- assert(agent);
-
- if ((r = cg_get_path(controller, NULL, "release_agent", &fs)) < 0)
- return r;
-
- if ((r = read_one_line_file(fs, &contents)) < 0)
- goto finish;
-
- sc = strstrip(contents);
- if (sc[0] == 0) {
-
- if (asprintf(&line, "%s\n", agent) < 0) {
- r = -ENOMEM;
- goto finish;
- }
-
- if ((r = write_one_line_file(fs, line)) < 0)
- goto finish;
-
- } else if (!streq(sc, agent)) {
- r = -EEXIST;
- goto finish;
- }
-
- free(fs);
- fs = NULL;
- if ((r = cg_get_path(controller, NULL, "notify_on_release", &fs)) < 0)
- goto finish;
-
- free(contents);
- contents = NULL;
- if ((r = read_one_line_file(fs, &contents)) < 0)
- goto finish;
-
- sc = strstrip(contents);
-
- if (streq(sc, "0")) {
- if ((r = write_one_line_file(fs, "1\n")) < 0)
- goto finish;
-
- r = 1;
- } else if (!streq(sc, "1")) {
- r = -EIO;
- goto finish;
- } else
- r = 0;
-
-finish:
- free(fs);
- free(contents);
- free(line);
-
- return r;
-}
-
-int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
- pid_t pid = 0, self_pid;
- int r;
- FILE *f = NULL;
- bool found = false;
-
- assert(path);
-
- r = cg_enumerate_tasks(controller, path, &f);
- if (r < 0)
- return r == -ENOENT ? 1 : r;
-
- self_pid = getpid();
-
- while ((r = cg_read_pid(f, &pid)) > 0) {
-
- if (ignore_self && pid == self_pid)
- continue;
-
- found = true;
- break;
- }
-
- fclose(f);
-
- if (r < 0)
- return r;
-
- return !found;
-}
-
-int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
- int r;
- DIR *d = NULL;
- char *fn;
-
- assert(path);
-
- r = cg_is_empty(controller, path, ignore_self);
- if (r <= 0)
- return r;
-
- r = cg_enumerate_subgroups(controller, path, &d);
- if (r < 0)
- return r == -ENOENT ? 1 : r;
-
- while ((r = cg_read_subgroup(d, &fn)) > 0) {
- char *p = NULL;
-
- r = asprintf(&p, "%s/%s", path, fn);
- free(fn);
-
- if (r < 0) {
- r = -ENOMEM;
- goto finish;
- }
-
- r = cg_is_empty_recursive(controller, p, ignore_self);
- free(p);
-
- if (r <= 0)
- goto finish;
- }
-
- if (r >= 0)
- r = 1;
-
-finish:
-
- if (d)
- closedir(d);
-
- return r;
-}
-
-int cg_split_spec(const char *spec, char **controller, char **path) {
- const char *e;
- char *t = NULL, *u = NULL;
-
- assert(spec);
- assert(controller || path);
-
- if (*spec == '/') {
-
- if (path) {
- if (!(t = strdup(spec)))
- return -ENOMEM;
-
- *path = t;
- }
-
- if (controller)
- *controller = NULL;
-
- return 0;
- }
-
- if (!(e = strchr(spec, ':'))) {
-
- if (strchr(spec, '/') || spec[0] == 0)
- return -EINVAL;
-
- if (controller) {
- if (!(t = strdup(spec)))
- return -ENOMEM;
-
- *controller = t;
- }
-
- if (path)
- *path = NULL;
-
- return 0;
- }
-
- if (e[1] != '/' ||
- e == spec ||
- memchr(spec, '/', e-spec))
- return -EINVAL;
-
- if (controller)
- if (!(t = strndup(spec, e-spec)))
- return -ENOMEM;
-
- if (path)
- if (!(u = strdup(e+1))) {
- free(t);
- return -ENOMEM;
- }
-
- if (controller)
- *controller = t;
-
- if (path)
- *path = u;
-
- return 0;
-}
-
-int cg_join_spec(const char *controller, const char *path, char **spec) {
- assert(controller);
- assert(path);
-
- if (!path_is_absolute(path) ||
- controller[0] == 0 ||
- strchr(controller, ':') ||
- strchr(controller, '/'))
- return -EINVAL;
-
- if (asprintf(spec, "%s:%s", controller, path) < 0)
- return -ENOMEM;
-
- return 0;
-}
-
-int cg_fix_path(const char *path, char **result) {
- char *t, *c, *p;
- int r;
-
- assert(path);
- assert(result);
-
- /* First check if it already is a filesystem path */
- if (path_startswith(path, "/sys/fs/cgroup") &&
- access(path, F_OK) >= 0) {
-
- t = strdup(path);
- if (!t)
- return -ENOMEM;
-
- *result = t;
- return 0;
- }
-
- /* Otherwise treat it as cg spec */
- r = cg_split_spec(path, &c, &p);
- if (r < 0)
- return r;
-
- r = cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
- free(c);
- free(p);
-
- return r;
-}
-
-int cg_get_user_path(char **path) {
- char *root, *p;
-
- assert(path);
-
- /* Figure out the place to put user cgroups below. We use the
- * same as PID 1 has but with the "/system" suffix replaced by
- * "/user" */
-
- if (cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &root) < 0)
- p = strdup("/user");
- else {
- if (endswith(root, "/system"))
- root[strlen(root) - 7] = 0;
- else if (streq(root, "/"))
- root[0] = 0;
-
- p = strappend(root, "/user");
- free(root);
- }
-
- if (!p)
- return -ENOMEM;
-
- *path = p;
- return 0;
-}
-
-char **cg_shorten_controllers(char **controllers) {
- char **f, **t;
-
- controllers = strv_uniq(controllers);
-
- if (!controllers)
- return controllers;
-
- for (f = controllers, t = controllers; *f; f++) {
- int r;
- const char *p;
-
- if (streq(*f, "systemd") || streq(*f, SYSTEMD_CGROUP_CONTROLLER)) {
- free(*f);
- continue;
- }
-
- p = normalize_controller(*f);
-
- r = check(p);
- if (r < 0) {
- log_debug("Controller %s is not available, removing from controllers list.", *f);
- free(*f);
- continue;
- }
-
- *(t++) = *f;
- }
-
- *t = NULL;
- return controllers;
-}
-
-int cg_pid_get_cgroup(pid_t pid, char **root, char **cgroup) {
- char *cg_process, *cg_init, *p;
- int r;
-
- assert(pid >= 0);
-
- if (pid == 0)
- pid = getpid();
-
- r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &cg_process);
- if (r < 0)
- return r;
-
- r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &cg_init);
- if (r < 0) {
- free(cg_process);
- return r;
- }
-
- if (endswith(cg_init, "/system"))
- cg_init[strlen(cg_init)-7] = 0;
- else if (streq(cg_init, "/"))
- cg_init[0] = 0;
-
- if (startswith(cg_process, cg_init))
- p = cg_process + strlen(cg_init);
- else
- p = cg_process;
-
- free(cg_init);
-
- if (cgroup) {
- char* c;
-
- c = strdup(p);
- if (!c) {
- free(cg_process);
- return -ENOMEM;
- }
-
- *cgroup = c;
- }
-
- if (root) {
- cg_process[p-cg_process] = 0;
- *root = cg_process;
- } else
- free(cg_process);
-
- return 0;
-}
-
-int cg_pid_get_unit(pid_t pid, char **unit) {
- int r;
- char *cgroup, *p, *at, *b;
- size_t k;
-
- assert(pid >= 0);
- assert(unit);
-
- r = cg_pid_get_cgroup(pid, NULL, &cgroup);
- if (r < 0)
- return r;
-
- if (!startswith(cgroup, "/system/")) {
- free(cgroup);
- return -ENOENT;
- }
-
- p = cgroup + 8;
- k = strcspn(p, "/");
-
- at = memchr(p, '@', k);
- if (at && at[1] == '.') {
- size_t j;
-
- /* This is a templated service */
- if (p[k] != '/') {
- free(cgroup);
- return -EIO;
- }
-
- j = strcspn(p+k+1, "/");
-
- b = malloc(k + j + 1);
-
- if (b) {
- memcpy(b, p, at - p + 1);
- memcpy(b + (at - p) + 1, p + k + 1, j);
- memcpy(b + (at - p) + 1 + j, at + 1, k - (at - p) - 1);
- b[k+j] = 0;
- }
- } else
- b = strndup(p, k);
-
- free(cgroup);
-
- if (!b)
- return -ENOMEM;
-
- *unit = b;
- return 0;
-
-}
diff --git a/src/shared/cgroup-util.h b/src/shared/cgroup-util.h
deleted file mode 100644
index 697669deba..0000000000
--- a/src/shared/cgroup-util.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*-*- 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/types.h>
-#include <stdio.h>
-#include <dirent.h>
-
-#include "set.h"
-#include "def.h"
-
-int cg_enumerate_processes(const char *controller, const char *path, FILE **_f);
-int cg_enumerate_tasks(const char *controller, const char *path, FILE **_f);
-int cg_read_pid(FILE *f, pid_t *_pid);
-
-int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d);
-int cg_read_subgroup(DIR *d, char **fn);
-
-int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s);
-int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool remove, Set *s);
-int cg_kill_recursive_and_wait(const char *controller, const char *path, bool remove);
-
-int cg_migrate(const char *controller, const char *from, const char *to, bool ignore_self);
-int cg_migrate_recursive(const char *controller, const char *from, const char *to, bool ignore_self, bool remove);
-
-int cg_split_spec(const char *spec, char **controller, char **path);
-int cg_join_spec(const char *controller, const char *path, char **spec);
-int cg_fix_path(const char *path, char **result);
-
-int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs);
-int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs);
-int cg_get_by_pid(const char *controller, pid_t pid, char **path);
-
-int cg_trim(const char *controller, const char *path, bool delete_root);
-
-int cg_rmdir(const char *controller, const char *path, bool honour_sticky);
-int cg_delete(const char *controller, const char *path);
-
-int cg_create(const char *controller, const char *path);
-int cg_attach(const char *controller, const char *path, pid_t pid);
-int cg_create_and_attach(const char *controller, const char *path, pid_t pid);
-
-int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid);
-int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid, int sticky);
-
-int cg_install_release_agent(const char *controller, const char *agent);
-
-int cg_is_empty(const char *controller, const char *path, bool ignore_self);
-int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self);
-
-int cg_get_user_path(char **path);
-int cg_pid_get_cgroup(pid_t pid, char **root, char **cgroup);
-int cg_pid_get_unit(pid_t pid, char **unit);
-
-char **cg_shorten_controllers(char **controllers);
diff --git a/src/shared/conf-files.c b/src/shared/conf-files.c
deleted file mode 100644
index 34b86293d3..0000000000
--- a/src/shared/conf-files.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*-*- 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 <assert.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <dirent.h>
-
-#include "macro.h"
-#include "util.h"
-#include "missing.h"
-#include "log.h"
-#include "strv.h"
-#include "path-util.h"
-#include "hashmap.h"
-#include "conf-files.h"
-
-static int files_add(Hashmap *h, const char *path, const char *suffix) {
- DIR *dir;
- int r = 0;
-
- dir = opendir(path);
- if (!dir) {
- if (errno == ENOENT)
- return 0;
- return -errno;
- }
-
- for (;;) {
- struct dirent *de;
- union dirent_storage buf;
- int k;
- char *p;
-
- k = readdir_r(dir, &buf.de, &de);
- if (k != 0) {
- r = -k;
- goto finish;
- }
-
- if (!de)
- break;
-
- if (!dirent_is_file_with_suffix(de, suffix))
- continue;
-
- if (asprintf(&p, "%s/%s", path, de->d_name) < 0) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (hashmap_put(h, path_get_file_name(p), p) <= 0) {
- log_debug("Skip overridden file: %s.", p);
- free(p);
- }
- }
-
-finish:
- closedir(dir);
- return r;
-}
-
-static int base_cmp(const void *a, const void *b) {
- const char *s1, *s2;
-
- s1 = *(char * const *)a;
- s2 = *(char * const *)b;
- return strcmp(path_get_file_name(s1), path_get_file_name(s2));
-}
-
-int conf_files_list_strv(char ***strv, const char *suffix, const char **dirs) {
- Hashmap *fh = NULL;
- char **files = NULL;
- const char **p;
- int r;
-
- assert(dirs);
-
- fh = hashmap_new(string_hash_func, string_compare_func);
- if (!fh) {
- r = -ENOMEM;
- goto finish;
- }
-
- STRV_FOREACH(p, dirs) {
- r = files_add(fh, *p, suffix);
- if (r < 0)
- log_warning("Failed to search for files in %s: %s",
- *p, strerror(-r));
- }
-
- files = hashmap_get_strv(fh);
- if (files == NULL) {
- log_error("Failed to compose list of files.");
- r = -ENOMEM;
- goto finish;
- }
- qsort(files, hashmap_size(fh), sizeof(char *), base_cmp);
- r = 0;
-
-finish:
- hashmap_free(fh);
- *strv = files;
- return r;
-}
-
-int conf_files_list(char ***strv, const char *suffix, const char *dir, ...) {
- char **dirs = NULL;
- va_list ap;
- int r;
-
- va_start(ap, dir);
- dirs = strv_new_ap(dir, ap);
- va_end(ap);
- if (!dirs) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (!path_strv_canonicalize(dirs)) {
- r = -ENOMEM;
- goto finish;
- }
- strv_uniq(dirs);
-
- r = conf_files_list_strv(strv, suffix, (const char **)dirs);
-
-finish:
- strv_free(dirs);
- return r;
-}
diff --git a/src/shared/conf-files.h b/src/shared/conf-files.h
deleted file mode 100644
index f37ee1f3db..0000000000
--- a/src/shared/conf-files.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef fooconffileshfoo
-#define fooconffileshfoo
-
-/***
- This file is part of systemd.
-
- Copyright 2010-2012 Lennart Poettering
- Copyright 2010-2012 Kay Sievers
-
- 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 "macro.h"
-
-int conf_files_list(char ***strv, const char *suffix, const char *dir, ...);
-int conf_files_list_strv(char ***strv, const char *suffix, const char **dirs);
-
-#endif
diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c
deleted file mode 100644
index 9f5c07c761..0000000000
--- a/src/shared/conf-parser.c
+++ /dev/null
@@ -1,1007 +0,0 @@
-/*-*- 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 <stdio.h>
-#include <errno.h>
-#include <assert.h>
-#include <stdlib.h>
-
-#include "conf-parser.h"
-#include "util.h"
-#include "macro.h"
-#include "strv.h"
-#include "log.h"
-#include "utf8.h"
-#include "path-util.h"
-#include "set.h"
-#include "exit-status.h"
-
-int config_item_table_lookup(
- void *table,
- const char *section,
- const char *lvalue,
- ConfigParserCallback *func,
- int *ltype,
- void **data,
- void *userdata) {
-
- ConfigTableItem *t;
-
- assert(table);
- assert(lvalue);
- assert(func);
- assert(ltype);
- assert(data);
-
- for (t = table; t->lvalue; t++) {
-
- if (!streq(lvalue, t->lvalue))
- continue;
-
- if (!streq_ptr(section, t->section))
- continue;
-
- *func = t->parse;
- *ltype = t->ltype;
- *data = t->data;
- return 1;
- }
-
- return 0;
-}
-
-int config_item_perf_lookup(
- void *table,
- const char *section,
- const char *lvalue,
- ConfigParserCallback *func,
- int *ltype,
- void **data,
- void *userdata) {
-
- ConfigPerfItemLookup lookup = (ConfigPerfItemLookup) table;
- const ConfigPerfItem *p;
-
- assert(table);
- assert(lvalue);
- assert(func);
- assert(ltype);
- assert(data);
-
- if (!section)
- p = lookup(lvalue, strlen(lvalue));
- else {
- char *key;
-
- key = strjoin(section, ".", lvalue, NULL);
- if (!key)
- return -ENOMEM;
-
- p = lookup(key, strlen(key));
- free(key);
- }
-
- if (!p)
- return 0;
-
- *func = p->parse;
- *ltype = p->ltype;
- *data = (uint8_t*) userdata + p->offset;
- return 1;
-}
-
-/* Run the user supplied parser for an assignment */
-static int next_assignment(
- const char *filename,
- unsigned line,
- ConfigItemLookup lookup,
- void *table,
- const char *section,
- const char *lvalue,
- const char *rvalue,
- bool relaxed,
- void *userdata) {
-
- ConfigParserCallback func = NULL;
- int ltype = 0;
- void *data = NULL;
- int r;
-
- assert(filename);
- assert(line > 0);
- assert(lookup);
- assert(lvalue);
- assert(rvalue);
-
- r = lookup(table, section, lvalue, &func, &ltype, &data, userdata);
- if (r < 0)
- return r;
-
- if (r > 0) {
- if (func)
- return func(filename, line, section, lvalue, ltype, rvalue, data, userdata);
-
- return 0;
- }
-
- /* Warn about unknown non-extension fields. */
- if (!relaxed && !startswith(lvalue, "X-"))
- log_info("[%s:%u] Unknown lvalue '%s' in section '%s'. Ignoring.", filename, line, lvalue, section);
-
- return 0;
-}
-
-/* Parse a variable assignment line */
-static int parse_line(
- const char *filename,
- unsigned line,
- const char *sections,
- ConfigItemLookup lookup,
- void *table,
- bool relaxed,
- char **section,
- char *l,
- void *userdata) {
-
- char *e;
-
- assert(filename);
- assert(line > 0);
- assert(lookup);
- assert(l);
-
- l = strstrip(l);
-
- if (!*l)
- return 0;
-
- if (strchr(COMMENTS, *l))
- return 0;
-
- if (startswith(l, ".include ")) {
- char *fn;
- int r;
-
- fn = file_in_same_dir(filename, strstrip(l+9));
- if (!fn)
- return -ENOMEM;
-
- r = config_parse(fn, NULL, sections, lookup, table, relaxed, userdata);
- free(fn);
-
- return r;
- }
-
- if (*l == '[') {
- size_t k;
- char *n;
-
- k = strlen(l);
- assert(k > 0);
-
- if (l[k-1] != ']') {
- log_error("[%s:%u] Invalid section header.", filename, line);
- return -EBADMSG;
- }
-
- n = strndup(l+1, k-2);
- if (!n)
- return -ENOMEM;
-
- if (sections && !nulstr_contains(sections, n)) {
-
- if (!relaxed)
- log_info("[%s:%u] Unknown section '%s'. Ignoring.", filename, line, n);
-
- free(n);
- *section = NULL;
- } else {
- free(*section);
- *section = n;
- }
-
- return 0;
- }
-
- if (sections && !*section) {
-
- if (!relaxed)
- log_info("[%s:%u] Assignment outside of section. Ignoring.", filename, line);
-
- return 0;
- }
-
- e = strchr(l, '=');
- if (!e) {
- log_error("[%s:%u] Missing '='.", filename, line);
- return -EBADMSG;
- }
-
- *e = 0;
- e++;
-
- return next_assignment(
- filename,
- line,
- lookup,
- table,
- *section,
- strstrip(l),
- strstrip(e),
- relaxed,
- userdata);
-}
-
-/* Go through the file and parse each line */
-int config_parse(
- const char *filename,
- FILE *f,
- const char *sections,
- ConfigItemLookup lookup,
- void *table,
- bool relaxed,
- void *userdata) {
-
- unsigned line = 0;
- char *section = NULL;
- int r;
- bool ours = false;
- char *continuation = NULL;
-
- assert(filename);
- assert(lookup);
-
- if (!f) {
- f = fopen(filename, "re");
- if (!f) {
- r = -errno;
- log_error("Failed to open configuration file '%s': %s", filename, strerror(-r));
- goto finish;
- }
-
- ours = true;
- }
-
- while (!feof(f)) {
- char l[LINE_MAX], *p, *c = NULL, *e;
- bool escaped = false;
-
- if (!fgets(l, sizeof(l), f)) {
- if (feof(f))
- break;
-
- r = -errno;
- log_error("Failed to read configuration file '%s': %s", filename, strerror(-r));
- goto finish;
- }
-
- truncate_nl(l);
-
- if (continuation) {
- c = strappend(continuation, l);
- if (!c) {
- r = -ENOMEM;
- goto finish;
- }
-
- free(continuation);
- continuation = NULL;
- p = c;
- } else
- p = l;
-
- for (e = p; *e; e++) {
- if (escaped)
- escaped = false;
- else if (*e == '\\')
- escaped = true;
- }
-
- if (escaped) {
- *(e-1) = ' ';
-
- if (c)
- continuation = c;
- else {
- continuation = strdup(l);
- if (!continuation) {
- r = -ENOMEM;
- goto finish;
- }
- }
-
- continue;
- }
-
- r = parse_line(filename,
- ++line,
- sections,
- lookup,
- table,
- relaxed,
- &section,
- p,
- userdata);
- free(c);
-
- if (r < 0)
- goto finish;
- }
-
- r = 0;
-
-finish:
- free(section);
- free(continuation);
-
- if (f && ours)
- fclose(f);
-
- return r;
-}
-
-int config_parse_int(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- int *i = data;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if ((r = safe_atoi(rvalue, i)) < 0) {
- log_error("[%s:%u] Failed to parse numeric value, ingoring: %s", filename, line, rvalue);
- return 0;
- }
-
- return 0;
-}
-
-int config_parse_long(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- long *i = data;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if ((r = safe_atoli(rvalue, i)) < 0) {
- log_error("[%s:%u] Failed to parse numeric value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- return 0;
-}
-
-int config_parse_uint64(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- uint64_t *u = data;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if ((r = safe_atou64(rvalue, u)) < 0) {
- log_error("[%s:%u] Failed to parse numeric value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- return 0;
-}
-
-int config_parse_unsigned(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- unsigned *u = data;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if ((r = safe_atou(rvalue, u)) < 0) {
- log_error("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue);
- return r;
- }
-
- return 0;
-}
-
-int config_parse_bytes_size(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- size_t *sz = data;
- off_t o;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (parse_bytes(rvalue, &o) < 0 || (off_t) (size_t) o != o) {
- log_error("[%s:%u] Failed to parse byte value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- *sz = (size_t) o;
- return 0;
-}
-
-
-int config_parse_bytes_off(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- off_t *bytes = data;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- assert_cc(sizeof(off_t) == sizeof(uint64_t));
-
- if (parse_bytes(rvalue, bytes) < 0) {
- log_error("[%s:%u] Failed to parse bytes value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- return 0;
-}
-
-int config_parse_bool(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- int k;
- bool *b = data;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if ((k = parse_boolean(rvalue)) < 0) {
- log_error("[%s:%u] Failed to parse boolean value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- *b = !!k;
- return 0;
-}
-
-int config_parse_tristate(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- int k;
- int *b = data;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- /* Tristates are like booleans, but can also take the 'default' value, i.e. "-1" */
-
- k = parse_boolean(rvalue);
- if (k < 0) {
- log_error("[%s:%u] Failed to parse boolean value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- *b = !!k;
- return 0;
-}
-
-int config_parse_string(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- char **s = data;
- char *n;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- n = strdup(rvalue);
- if (!n)
- return -ENOMEM;
-
- if (!utf8_is_valid(n)) {
- log_error("[%s:%u] String is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
- free(n);
- return 0;
- }
-
- free(*s);
- if (*n)
- *s = n;
- else {
- free(n);
- *s = NULL;
- }
-
- return 0;
-}
-
-int config_parse_path(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- char **s = data;
- char *n;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (!utf8_is_valid(rvalue)) {
- log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
- return 0;
- }
-
- if (!path_is_absolute(rvalue)) {
- log_error("[%s:%u] Not an absolute path, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- n = strdup(rvalue);
- if (!n)
- return -ENOMEM;
-
- path_kill_slashes(n);
-
- free(*s);
- *s = n;
-
- return 0;
-}
-
-int config_parse_strv(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- char*** sv = data;
- char **n;
- char *w;
- unsigned k;
- size_t l;
- char *state;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- k = strv_length(*sv);
- FOREACH_WORD_QUOTED(w, l, rvalue, state)
- k++;
-
- n = new(char*, k+1);
- if (!n)
- return -ENOMEM;
-
- if (*sv)
- for (k = 0; (*sv)[k]; k++)
- n[k] = (*sv)[k];
- else
- k = 0;
-
- FOREACH_WORD_QUOTED(w, l, rvalue, state) {
- n[k] = cunescape_length(w, l);
- if (!n[k]) {
- r = -ENOMEM;
- goto fail;
- }
-
- if (!utf8_is_valid(n[k])) {
- log_error("[%s:%u] String is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
- free(n[k]);
- continue;
- }
-
- k++;
- }
-
- n[k] = NULL;
- free(*sv);
- *sv = n;
-
- return 0;
-
-fail:
- for (; k > 0; k--)
- free(n[k-1]);
- free(n);
-
- return r;
-}
-
-int config_parse_path_strv(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- char*** sv = data;
- char **n;
- char *w;
- unsigned k;
- size_t l;
- char *state;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- k = strv_length(*sv);
- FOREACH_WORD_QUOTED(w, l, rvalue, state)
- k++;
-
- n = new(char*, k+1);
- if (!n)
- return -ENOMEM;
-
- k = 0;
- if (*sv)
- for (; (*sv)[k]; k++)
- n[k] = (*sv)[k];
-
- FOREACH_WORD_QUOTED(w, l, rvalue, state) {
- n[k] = strndup(w, l);
- if (!n[k]) {
- r = -ENOMEM;
- goto fail;
- }
-
- if (!utf8_is_valid(n[k])) {
- log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
- free(n[k]);
- continue;
- }
-
- if (!path_is_absolute(n[k])) {
- log_error("[%s:%u] Not an absolute path, ignoring: %s", filename, line, rvalue);
- free(n[k]);
- continue;
- }
-
- path_kill_slashes(n[k]);
- k++;
- }
-
- n[k] = NULL;
- free(*sv);
- *sv = n;
-
- return 0;
-
-fail:
- for (; k > 0; k--)
- free(n[k-1]);
- free(n);
-
- return r;
-}
-
-int config_parse_usec(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- usec_t *usec = data;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (parse_usec(rvalue, usec) < 0) {
- log_error("[%s:%u] Failed to parse time value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- return 0;
-}
-
-int config_parse_nsec(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- nsec_t *nsec = data;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (parse_nsec(rvalue, nsec) < 0) {
- log_error("[%s:%u] Failed to parse time value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- return 0;
-}
-
-int config_parse_mode(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- mode_t *m = data;
- long l;
- char *x = NULL;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- errno = 0;
- l = strtol(rvalue, &x, 8);
- if (!x || x == rvalue || *x || errno) {
- log_error("[%s:%u] Failed to parse mode value, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- if (l < 0000 || l > 07777) {
- log_error("[%s:%u] mode value out of range, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- *m = (mode_t) l;
- return 0;
-}
-
-int config_parse_facility(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
-
- int *o = data, x;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- x = log_facility_unshifted_from_string(rvalue);
- if (x < 0) {
- log_error("[%s:%u] Failed to parse log facility, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- *o = (x << 3) | LOG_PRI(*o);
-
- return 0;
-}
-
-int config_parse_level(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
-
- int *o = data, x;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- x = log_level_from_string(rvalue);
- if (x < 0) {
- log_error("[%s:%u] Failed to parse log level, ignoring: %s", filename, line, rvalue);
- return 0;
- }
-
- *o = (*o & LOG_FACMASK) | x;
- return 0;
-}
-
-int config_parse_set_status(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- char *w;
- size_t l;
- char *state;
- int r;
- ExitStatusSet *status_set = data;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- FOREACH_WORD(w, l, rvalue, state) {
- int val;
- char *temp;
-
- temp = strndup(w, l);
- if (!temp)
- return log_oom();
-
- r = safe_atoi(temp, &val);
- if (r < 0) {
- val = signal_from_string_try_harder(temp);
- free(temp);
-
- if (val > 0) {
- r = set_ensure_allocated(&status_set->signal, trivial_hash_func, trivial_compare_func);
- if (r < 0)
- return log_oom();
-
- r = set_put(status_set->signal, INT_TO_PTR(val));
- if (r < 0) {
- log_error("[%s:%u] Unable to store: %s", filename, line, w);
- return r;
- }
- } else {
- log_error("[%s:%u] Failed to parse value, ignoring: %s", filename, line, w);
- return 0;
- }
- } else {
- free(temp);
-
- if (val < 0 || val > 255)
- log_warning("[%s:%u] Value %d is outside range 0-255, ignoring", filename, line, val);
- else {
- r = set_ensure_allocated(&status_set->code, trivial_hash_func, trivial_compare_func);
- if (r < 0)
- return log_oom();
-
- r = set_put(status_set->code, INT_TO_PTR(val));
- if (r < 0) {
- log_error("[%s:%u] Unable to store: %s", filename, line, w);
- return r;
- }
- }
- }
- }
-
- return 0;
-}
diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h
deleted file mode 100644
index 56ffc2f8a8..0000000000
--- a/src/shared/conf-parser.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*-*- 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 <stdio.h>
-#include <stdbool.h>
-
-/* An abstract parser for simple, line based, shallow configuration
- * files consisting of variable assignments only. */
-
-/* Prototype for a parser for a specific configuration setting */
-typedef int (*ConfigParserCallback)(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata);
-
-/* Wraps information for parsing a specific configuration variable, to
- * be stored in a simple array */
-typedef struct ConfigTableItem {
- const char *section; /* Section */
- const char *lvalue; /* Name of the variable */
- ConfigParserCallback parse; /* Function that is called to parse the variable's value */
- int ltype; /* Distinguish different variables passed to the same callback */
- void *data; /* Where to store the variable's data */
-} ConfigTableItem;
-
-/* Wraps information for parsing a specific configuration variable, to
- * ve srored in a gperf perfect hashtable */
-typedef struct ConfigPerfItem {
- const char *section_and_lvalue; /* Section + "." + name of the variable */
- ConfigParserCallback parse; /* Function that is called to parse the variable's value */
- int ltype; /* Distinguish different variables passed to the same callback */
- size_t offset; /* Offset where to store data, from the beginning of userdata */
-} ConfigPerfItem;
-
-/* Prototype for a low-level gperf lookup function */
-typedef const ConfigPerfItem* (*ConfigPerfItemLookup)(const char *section_and_lvalue, unsigned length);
-
-/* Prototype for a generic high-level lookup function */
-typedef int (*ConfigItemLookup)(
- void *table,
- const char *section,
- const char *lvalue,
- ConfigParserCallback *func,
- int *ltype,
- void **data,
- void *userdata);
-
-/* Linear table search implementation of ConfigItemLookup, based on
- * ConfigTableItem arrays */
-int config_item_table_lookup(void *table, const char *section, const char *lvalue, ConfigParserCallback *func, int *ltype, void **data, void *userdata);
-
-/* gperf implementation of ConfigItemLookup, based on gperf
- * ConfigPerfItem tables */
-int config_item_perf_lookup(void *table, const char *section, const char *lvalue, ConfigParserCallback *func, int *ltype, void **data, void *userdata);
-
-int config_parse(
- const char *filename,
- FILE *f,
- const char *sections, /* nulstr */
- ConfigItemLookup lookup,
- void *table,
- bool relaxed,
- void *userdata);
-
-/* Generic parsers */
-int config_parse_int(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unsigned(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_long(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_uint64(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_bytes_size(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_bytes_off(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_bool(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_tristate(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_string(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_path(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_strv(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_path_strv(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_usec(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_nsec(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_mode(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_facility(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_level(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_set_status(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-
-#define DEFINE_CONFIG_PARSE_ENUM(function,name,type,msg) \
- int function( \
- const char *filename, \
- unsigned line, \
- const char *section, \
- const char *lvalue, \
- int ltype, \
- const char *rvalue, \
- void *data, \
- void *userdata) { \
- \
- type *i = data, x; \
- \
- assert(filename); \
- assert(lvalue); \
- assert(rvalue); \
- assert(data); \
- \
- if ((x = name##_from_string(rvalue)) < 0) { \
- log_error("[%s:%u] " msg ", ignoring: %s", filename, line, rvalue); \
- return 0; \
- } \
- \
- *i = x; \
- \
- return 0; \
- }
diff --git a/src/shared/dbus-common.c b/src/shared/dbus-common.c
deleted file mode 100644
index ee281e57f4..0000000000
--- a/src/shared/dbus-common.c
+++ /dev/null
@@ -1,1326 +0,0 @@
-/*-*- 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 <assert.h>
-#include <sys/socket.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <dbus/dbus.h>
-#include <string.h>
-#include <sys/epoll.h>
-
-#include "log.h"
-#include "dbus-common.h"
-#include "util.h"
-#include "missing.h"
-#include "def.h"
-#include "strv.h"
-
-int bus_check_peercred(DBusConnection *c) {
- int fd;
- struct ucred ucred;
- socklen_t l;
-
- assert(c);
-
- assert_se(dbus_connection_get_unix_fd(c, &fd));
-
- l = sizeof(struct ucred);
- if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0) {
- log_error("SO_PEERCRED failed: %m");
- return -errno;
- }
-
- if (l != sizeof(struct ucred)) {
- log_error("SO_PEERCRED returned wrong size.");
- return -E2BIG;
- }
-
- if (ucred.uid != 0 && ucred.uid != geteuid())
- return -EPERM;
-
- return 1;
-}
-
-static int sync_auth(DBusConnection *bus, DBusError *error) {
- usec_t begin, tstamp;
-
- assert(bus);
-
- /* This complexity should probably move into D-Bus itself:
- *
- * https://bugs.freedesktop.org/show_bug.cgi?id=35189 */
-
- begin = tstamp = now(CLOCK_MONOTONIC);
- for (;;) {
-
- if (tstamp > begin + DEFAULT_TIMEOUT_USEC)
- break;
-
- if (dbus_connection_get_is_authenticated(bus))
- break;
-
- if (!dbus_connection_read_write_dispatch(bus, ((begin + DEFAULT_TIMEOUT_USEC - tstamp) + USEC_PER_MSEC - 1) / USEC_PER_MSEC))
- break;
-
- tstamp = now(CLOCK_MONOTONIC);
- }
-
- if (!dbus_connection_get_is_connected(bus)) {
- dbus_set_error_const(error, DBUS_ERROR_NO_SERVER, "Connection terminated during authentication.");
- return -ECONNREFUSED;
- }
-
- if (!dbus_connection_get_is_authenticated(bus)) {
- dbus_set_error_const(error, DBUS_ERROR_TIMEOUT, "Failed to authenticate in time.");
- return -EACCES;
- }
-
- return 0;
-}
-
-int bus_connect(DBusBusType t, DBusConnection **_bus, bool *_private, DBusError *error) {
- DBusConnection *bus = NULL;
- int r;
- bool private = true;
-
- assert(_bus);
-
- if (geteuid() == 0 && t == DBUS_BUS_SYSTEM) {
- /* If we are root, then let's talk directly to the
- * system instance, instead of going via the bus */
-
- bus = dbus_connection_open_private("unix:path=/run/systemd/private", error);
- if (!bus)
- return -EIO;
-
- } else {
- if (t == DBUS_BUS_SESSION) {
- const char *e;
-
- /* If we are supposed to talk to the instance,
- * try via XDG_RUNTIME_DIR first, then
- * fallback to normal bus access */
-
- e = secure_getenv("XDG_RUNTIME_DIR");
- if (e) {
- char *p;
-
- if (asprintf(&p, "unix:path=%s/systemd/private", e) < 0)
- return -ENOMEM;
-
- bus = dbus_connection_open_private(p, NULL);
- free(p);
- }
- }
-
- if (!bus) {
- bus = dbus_bus_get_private(t, error);
- if (!bus)
- return -EIO;
-
- private = false;
- }
- }
-
- dbus_connection_set_exit_on_disconnect(bus, FALSE);
-
- if (private) {
- if (bus_check_peercred(bus) < 0) {
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
-
- dbus_set_error_const(error, DBUS_ERROR_ACCESS_DENIED, "Failed to verify owner of bus.");
- return -EACCES;
- }
- }
-
- r = sync_auth(bus, error);
- if (r < 0) {
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
- return r;
- }
-
- if (_private)
- *_private = private;
-
- *_bus = bus;
- return 0;
-}
-
-int bus_connect_system_ssh(const char *user, const char *host, DBusConnection **_bus, DBusError *error) {
- DBusConnection *bus;
- char *p = NULL;
- int r;
-
- assert(_bus);
- assert(user || host);
-
- if (user && host)
- asprintf(&p, "unixexec:path=ssh,argv1=-xT,argv2=%s@%s,argv3=systemd-stdio-bridge", user, host);
- else if (user)
- asprintf(&p, "unixexec:path=ssh,argv1=-xT,argv2=%s@localhost,argv3=systemd-stdio-bridge", user);
- else if (host)
- asprintf(&p, "unixexec:path=ssh,argv1=-xT,argv2=%s,argv3=systemd-stdio-bridge", host);
-
- if (!p) {
- dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
- return -ENOMEM;
- }
-
- bus = dbus_connection_open_private(p, error);
- free(p);
-
- if (!bus)
- return -EIO;
-
- dbus_connection_set_exit_on_disconnect(bus, FALSE);
-
- if ((r = sync_auth(bus, error)) < 0) {
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
- return r;
- }
-
- if (!dbus_bus_register(bus, error)) {
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
- return r;
- }
-
- *_bus = bus;
- return 0;
-}
-
-int bus_connect_system_polkit(DBusConnection **_bus, DBusError *error) {
- DBusConnection *bus;
- int r;
-
- assert(_bus);
-
- /* Don't bother with PolicyKit if we are root */
- if (geteuid() == 0)
- return bus_connect(DBUS_BUS_SYSTEM, _bus, NULL, error);
-
- bus = dbus_connection_open_private("unixexec:path=pkexec,argv1=" SYSTEMD_STDIO_BRIDGE_BINARY_PATH, error);
- if (!bus)
- return -EIO;
-
- dbus_connection_set_exit_on_disconnect(bus, FALSE);
-
- r = sync_auth(bus, error);
- if (r < 0) {
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
- return r;
- }
-
- if (!dbus_bus_register(bus, error)) {
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
- return r;
- }
-
- *_bus = bus;
- return 0;
-}
-
-const char *bus_error_message(const DBusError *error) {
- if (!error)
- return NULL;
-
- /* Sometimes the D-Bus server is a little bit too verbose with
- * its error messages, so let's override them here */
- if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED))
- return "Access denied";
-
- return error->message;
-}
-
-const char *bus_error_message_or_strerror(const DBusError *error, int err) {
-
- if (error && dbus_error_is_set(error))
- return bus_error_message(error);
-
- return strerror(err);
-}
-
-DBusHandlerResult bus_default_message_handler(
- DBusConnection *c,
- DBusMessage *message,
- const char *introspection,
- const char *interfaces,
- const BusBoundProperties *bound_properties) {
-
- DBusError error;
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- int r;
-
- assert(c);
- assert(message);
-
- dbus_error_init(&error);
-
- if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect") && introspection) {
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID))
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Get") && bound_properties) {
- const char *interface, *property;
- const BusBoundProperties *bp;
- const BusProperty *p;
- void *data;
- DBusMessageIter iter, sub;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &interface,
- DBUS_TYPE_STRING, &property,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(c, message, &error, -EINVAL);
-
- for (bp = bound_properties; bp->interface; bp++) {
- if (!streq(bp->interface, interface))
- continue;
-
- for (p = bp->properties; p->property; p++)
- if (streq(p->property, property))
- goto get_prop;
- }
-
- /* no match */
- if (!nulstr_contains(interfaces, interface))
- dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
- else
- dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property");
-
- return bus_send_error_reply(c, message, &error, -EINVAL);
-
-get_prop:
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- dbus_message_iter_init_append(reply, &iter);
-
- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, p->signature, &sub))
- goto oom;
-
- data = (char*)bp->base + p->offset;
- if (p->indirect)
- data = *(void**)data;
-
- r = p->append(&sub, property, data);
- if (r == -ENOMEM)
- goto oom;
- if (r < 0)
- return bus_send_error_reply(c, message, NULL, r);
-
- if (!dbus_message_iter_close_container(&iter, &sub))
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "GetAll") && bound_properties) {
- const char *interface;
- const BusBoundProperties *bp;
- const BusProperty *p;
- DBusMessageIter iter, sub, sub2, sub3;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &interface,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(c, message, &error, -EINVAL);
-
- if (interface[0] && !nulstr_contains(interfaces, interface)) {
- dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
- return bus_send_error_reply(c, message, &error, -EINVAL);
- }
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- dbus_message_iter_init_append(reply, &iter);
-
- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub))
- goto oom;
-
- for (bp = bound_properties; bp->interface; bp++) {
- if (interface[0] && !streq(bp->interface, interface))
- continue;
-
- for (p = bp->properties; p->property; p++) {
- void *data;
-
- if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_DICT_ENTRY, NULL, &sub2) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &p->property) ||
- !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, p->signature, &sub3))
- goto oom;
-
- data = (char*)bp->base + p->offset;
- if (p->indirect)
- data = *(void**)data;
- r = p->append(&sub3, p->property, data);
- if (r == -ENOMEM)
- goto oom;
- if (r < 0)
- return bus_send_error_reply(c, message, NULL, r);
-
- if (!dbus_message_iter_close_container(&sub2, &sub3) ||
- !dbus_message_iter_close_container(&sub, &sub2))
- goto oom;
- }
- }
-
- if (!dbus_message_iter_close_container(&iter, &sub))
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set") && bound_properties) {
- const char *interface, *property;
- DBusMessageIter iter;
- const BusBoundProperties *bp;
- const BusProperty *p;
- DBusMessageIter sub;
- char *sig;
- void *data;
- DBusMessage *changed;
-
- if (!dbus_message_iter_init(message, &iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
- return bus_send_error_reply(c, message, NULL, -EINVAL);
-
- dbus_message_iter_get_basic(&iter, &interface);
-
- if (!dbus_message_iter_next(&iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
- return bus_send_error_reply(c, message, NULL, -EINVAL);
-
- dbus_message_iter_get_basic(&iter, &property);
-
- if (!dbus_message_iter_next(&iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT ||
- dbus_message_iter_has_next(&iter))
- return bus_send_error_reply(c, message, NULL, -EINVAL);
-
- for (bp = bound_properties; bp->interface; bp++) {
- if (!streq(bp->interface, interface))
- continue;
-
- for (p = bp->properties; p->property; p++)
- if (streq(p->property, property))
- goto set_prop;
- }
-
- /* no match */
- if (!nulstr_contains(interfaces, interface))
- dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
- else
- dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property");
-
- return bus_send_error_reply(c, message, &error, -EINVAL);
-
-set_prop:
- if (!p->set) {
- dbus_set_error_const(&error, DBUS_ERROR_PROPERTY_READ_ONLY, "Property read-only");
- return bus_send_error_reply(c, message, &error, -EINVAL);
- }
-
- dbus_message_iter_recurse(&iter, &sub);
-
- sig = dbus_message_iter_get_signature(&sub);
- if (!sig)
- goto oom;
-
- if (!streq(sig, p->signature)) {
- dbus_free(sig);
- return bus_send_error_reply(c, message, NULL, -EINVAL);
- }
- dbus_free(sig);
-
- data = (uint8_t*) bp->base + p->offset;
- if (p->indirect)
- data = *(void**)data;
-
- r = p->set(&sub, property, data);
- if (r == -ENOMEM)
- goto oom;
- else if (r < 0)
- return bus_send_error_reply(c, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- /* Send out a signal about this, but it doesn't really
- * matter if this fails, so eat all errors */
- changed = bus_properties_changed_one_new(
- dbus_message_get_path(message),
- interface,
- property);
- if (changed) {
- dbus_connection_send(c, changed, NULL);
- dbus_message_unref(changed);
- }
-
-
- } else {
- const char *interface = dbus_message_get_interface(message);
-
- if (!interface || !nulstr_contains(interfaces, interface)) {
- dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
- return bus_send_error_reply(c, message, &error, -EINVAL);
- }
- }
-
- if (reply) {
- if (!dbus_connection_send(c, reply, NULL))
- goto oom;
-
- return DBUS_HANDLER_RESULT_HANDLED;
- }
-
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
-oom:
- dbus_error_free(&error);
-
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-}
-
-int bus_property_append_string(DBusMessageIter *i, const char *property, void *data) {
- const char *t = data;
-
- assert(i);
- assert(property);
-
- if (!t)
- t = "";
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_property_append_strv(DBusMessageIter *i, const char *property, void *data) {
- char **t = data;
-
- assert(i);
- assert(property);
-
- return bus_append_strv_iter(i, t);
-}
-
-int bus_property_append_bool(DBusMessageIter *i, const char *property, void *data) {
- bool *b = data;
- dbus_bool_t db;
-
- assert(i);
- assert(property);
- assert(b);
-
- db = *b;
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &db))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_property_append_tristate_false(DBusMessageIter *i, const char *property, void *data) {
- int *b = data;
- dbus_bool_t db;
-
- assert(i);
- assert(property);
- assert(b);
-
- db = *b > 0;
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &db))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_property_append_uint64(DBusMessageIter *i, const char *property, void *data) {
- assert(i);
- assert(property);
- assert(data);
-
- /* Let's ensure that usec_t is actually 64bit, and hence this
- * function can be used for usec_t */
- assert_cc(sizeof(uint64_t) == sizeof(usec_t));
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, data))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_property_append_uint32(DBusMessageIter *i, const char *property, void *data) {
- assert(i);
- assert(property);
- assert(data);
-
- /* Let's ensure that pid_t, mode_t, uid_t, gid_t are actually
- * 32bit, and hence this function can be used for
- * pid_t/mode_t/uid_t/gid_t */
- assert_cc(sizeof(uint32_t) == sizeof(pid_t));
- assert_cc(sizeof(uint32_t) == sizeof(mode_t));
- assert_cc(sizeof(uint32_t) == sizeof(unsigned));
- assert_cc(sizeof(uint32_t) == sizeof(uid_t));
- assert_cc(sizeof(uint32_t) == sizeof(gid_t));
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, data))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_property_append_int32(DBusMessageIter *i, const char *property, void *data) {
- assert(i);
- assert(property);
- assert(data);
-
- assert_cc(sizeof(int32_t) == sizeof(int));
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, data))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_property_append_size(DBusMessageIter *i, const char *property, void *data) {
- uint64_t u;
-
- assert(i);
- assert(property);
- assert(data);
-
- u = (uint64_t) *(size_t*) data;
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_property_append_ul(DBusMessageIter *i, const char *property, void *data) {
- uint64_t u;
-
- assert(i);
- assert(property);
- assert(data);
-
- u = (uint64_t) *(unsigned long*) data;
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_property_append_long(DBusMessageIter *i, const char *property, void *data) {
- int64_t l;
-
- assert(i);
- assert(property);
- assert(data);
-
- l = (int64_t) *(long*) data;
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT64, &l))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_property_set_uint64(DBusMessageIter *i, const char *property, void *data) {
- uint64_t *t = data;
-
- assert(i);
- assert(property);
-
- dbus_message_iter_get_basic(i, t);
- return 0;
-}
-
-const char *bus_errno_to_dbus(int error) {
-
- switch(error) {
-
- case -EINVAL:
- return DBUS_ERROR_INVALID_ARGS;
-
- case -ENOMEM:
- return DBUS_ERROR_NO_MEMORY;
-
- case -EPERM:
- case -EACCES:
- return DBUS_ERROR_ACCESS_DENIED;
-
- case -ESRCH:
- return DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN;
-
- case -ENOENT:
- return DBUS_ERROR_FILE_NOT_FOUND;
-
- case -EEXIST:
- return DBUS_ERROR_FILE_EXISTS;
-
- case -ETIMEDOUT:
- case -ETIME:
- return DBUS_ERROR_TIMEOUT;
-
- case -EIO:
- return DBUS_ERROR_IO_ERROR;
-
- case -ENETRESET:
- case -ECONNABORTED:
- case -ECONNRESET:
- return DBUS_ERROR_DISCONNECTED;
- }
-
- return DBUS_ERROR_FAILED;
-}
-
-DBusHandlerResult bus_send_error_reply(DBusConnection *c, DBusMessage *message, DBusError *berror, int error) {
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- const char *name, *text;
-
- if (berror && dbus_error_is_set(berror)) {
- name = berror->name;
- text = berror->message;
- } else {
- name = bus_errno_to_dbus(error);
- text = strerror(-error);
- }
-
- reply = dbus_message_new_error(message, name, text);
- if (!reply)
- goto oom;
-
- if (!dbus_connection_send(c, reply, NULL))
- goto oom;
-
- if (berror)
- dbus_error_free(berror);
-
- return DBUS_HANDLER_RESULT_HANDLED;
-
-oom:
- if (reply)
- dbus_message_unref(reply);
-
- if (berror)
- dbus_error_free(berror);
-
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-}
-
-DBusMessage* bus_properties_changed_new(const char *path, const char *interface, const char *properties) {
- DBusMessage *m;
- DBusMessageIter iter, sub;
- const char *i;
-
- assert(interface);
- assert(properties);
-
- m = dbus_message_new_signal(path, "org.freedesktop.DBus.Properties", "PropertiesChanged");
- if (!m)
- goto oom;
-
- dbus_message_iter_init_append(m, &iter);
-
- /* We won't send any property values, since they might be
- * large and sometimes not cheap to generated */
-
- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface) ||
- !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub) ||
- !dbus_message_iter_close_container(&iter, &sub) ||
- !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub))
- goto oom;
-
- NULSTR_FOREACH(i, properties)
- if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &i))
- goto oom;
-
- if (!dbus_message_iter_close_container(&iter, &sub))
- goto oom;
-
- return m;
-
-oom:
- if (m)
- dbus_message_unref(m);
-
- return NULL;
-}
-
-DBusMessage* bus_properties_changed_one_new(const char *path, const char *interface, const char *property) {
- DBusMessage *m;
- DBusMessageIter iter, sub;
-
- assert(interface);
- assert(property);
-
- m = dbus_message_new_signal(path, "org.freedesktop.DBus.Properties", "PropertiesChanged");
- if (!m)
- goto oom;
-
- dbus_message_iter_init_append(m, &iter);
-
- /* We won't send any property values, since they might be
- * large and sometimes not cheap to generated */
-
- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface) ||
- !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub) ||
- !dbus_message_iter_close_container(&iter, &sub) ||
- !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub))
- goto oom;
-
- if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &property))
- goto oom;
-
- if (!dbus_message_iter_close_container(&iter, &sub))
- goto oom;
-
- return m;
-
-oom:
- if (m)
- dbus_message_unref(m);
-
- return NULL;
-}
-
-uint32_t bus_flags_to_events(DBusWatch *bus_watch) {
- unsigned flags;
- uint32_t events = 0;
-
- assert(bus_watch);
-
- /* no watch flags for disabled watches */
- if (!dbus_watch_get_enabled(bus_watch))
- return 0;
-
- flags = dbus_watch_get_flags(bus_watch);
-
- if (flags & DBUS_WATCH_READABLE)
- events |= EPOLLIN;
- if (flags & DBUS_WATCH_WRITABLE)
- events |= EPOLLOUT;
-
- return events | EPOLLHUP | EPOLLERR;
-}
-
-unsigned bus_events_to_flags(uint32_t events) {
- unsigned flags = 0;
-
- if (events & EPOLLIN)
- flags |= DBUS_WATCH_READABLE;
- if (events & EPOLLOUT)
- flags |= DBUS_WATCH_WRITABLE;
- if (events & EPOLLHUP)
- flags |= DBUS_WATCH_HANGUP;
- if (events & EPOLLERR)
- flags |= DBUS_WATCH_ERROR;
-
- return flags;
-}
-
-int bus_parse_strv(DBusMessage *m, char ***_l) {
- DBusMessageIter iter;
-
- assert(m);
- assert(_l);
-
- if (!dbus_message_iter_init(m, &iter))
- return -EINVAL;
-
- return bus_parse_strv_iter(&iter, _l);
-}
-
-int bus_parse_strv_iter(DBusMessageIter *iter, char ***_l) {
- DBusMessageIter sub;
- unsigned n = 0, i = 0;
- char **l;
-
- assert(iter);
- assert(_l);
-
- if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(iter) != DBUS_TYPE_STRING)
- return -EINVAL;
-
- dbus_message_iter_recurse(iter, &sub);
-
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- n++;
- dbus_message_iter_next(&sub);
- }
-
- l = new(char*, n+1);
- if (!l)
- return -ENOMEM;
-
- dbus_message_iter_recurse(iter, &sub);
-
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- const char *s;
-
- assert_se(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
- dbus_message_iter_get_basic(&sub, &s);
-
- if (!(l[i++] = strdup(s))) {
- strv_free(l);
- return -ENOMEM;
- }
-
- dbus_message_iter_next(&sub);
- }
-
- assert(i == n);
- l[i] = NULL;
-
- if (_l)
- *_l = l;
-
- return 0;
-}
-
-int bus_append_strv_iter(DBusMessageIter *iter, char **l) {
- DBusMessageIter sub;
-
- assert(iter);
-
- if (!dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "s", &sub))
- return -ENOMEM;
-
- STRV_FOREACH(l, l)
- if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, l))
- return -ENOMEM;
-
- if (!dbus_message_iter_close_container(iter, &sub))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_iter_get_basic_and_next(DBusMessageIter *iter, int type, void *data, bool next) {
-
- assert(iter);
- assert(data);
-
- if (dbus_message_iter_get_arg_type(iter) != type)
- return -EIO;
-
- dbus_message_iter_get_basic(iter, data);
-
- if (!dbus_message_iter_next(iter) != !next)
- return -EIO;
-
- return 0;
-}
-
-int generic_print_property(const char *name, DBusMessageIter *iter, bool all) {
- assert(name);
- assert(iter);
-
- switch (dbus_message_iter_get_arg_type(iter)) {
-
- case DBUS_TYPE_STRING: {
- const char *s;
- dbus_message_iter_get_basic(iter, &s);
-
- if (all || !isempty(s))
- printf("%s=%s\n", name, s);
-
- return 1;
- }
-
- case DBUS_TYPE_BOOLEAN: {
- dbus_bool_t b;
-
- dbus_message_iter_get_basic(iter, &b);
- printf("%s=%s\n", name, yes_no(b));
-
- return 1;
- }
-
- case DBUS_TYPE_UINT64: {
- uint64_t u;
- dbus_message_iter_get_basic(iter, &u);
-
- /* Yes, heuristics! But we can change this check
- * should it turn out to not be sufficient */
-
- if (endswith(name, "Timestamp")) {
- char timestamp[FORMAT_TIMESTAMP_MAX], *t;
-
- t = format_timestamp(timestamp, sizeof(timestamp), u);
- if (t || all)
- printf("%s=%s\n", name, strempty(t));
-
- } else if (strstr(name, "USec")) {
- char timespan[FORMAT_TIMESPAN_MAX];
-
- printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u));
- } else
- printf("%s=%llu\n", name, (unsigned long long) u);
-
- return 1;
- }
-
- case DBUS_TYPE_UINT32: {
- uint32_t u;
- dbus_message_iter_get_basic(iter, &u);
-
- if (strstr(name, "UMask") || strstr(name, "Mode"))
- printf("%s=%04o\n", name, u);
- else
- printf("%s=%u\n", name, (unsigned) u);
-
- return 1;
- }
-
- case DBUS_TYPE_INT32: {
- int32_t i;
- dbus_message_iter_get_basic(iter, &i);
-
- printf("%s=%i\n", name, (int) i);
- return 1;
- }
-
- case DBUS_TYPE_DOUBLE: {
- double d;
- dbus_message_iter_get_basic(iter, &d);
-
- printf("%s=%g\n", name, d);
- return 1;
- }
-
- case DBUS_TYPE_ARRAY:
-
- if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
- DBusMessageIter sub;
- bool space = false;
-
- dbus_message_iter_recurse(iter, &sub);
- if (all ||
- dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- printf("%s=", name);
-
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- const char *s;
-
- assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
- dbus_message_iter_get_basic(&sub, &s);
- printf("%s%s", space ? " " : "", s);
-
- space = true;
- dbus_message_iter_next(&sub);
- }
-
- puts("");
- }
-
- return 1;
-
- } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_BYTE) {
- DBusMessageIter sub;
-
- dbus_message_iter_recurse(iter, &sub);
- if (all ||
- dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- printf("%s=", name);
-
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- uint8_t u;
-
- assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_BYTE);
- dbus_message_iter_get_basic(&sub, &u);
- printf("%02x", u);
-
- dbus_message_iter_next(&sub);
- }
-
- puts("");
- }
-
- return 1;
-
- } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_UINT32) {
- DBusMessageIter sub;
-
- dbus_message_iter_recurse(iter, &sub);
- if (all ||
- dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- printf("%s=", name);
-
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- uint32_t u;
-
- assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32);
- dbus_message_iter_get_basic(&sub, &u);
- printf("%08x", u);
-
- dbus_message_iter_next(&sub);
- }
-
- puts("");
- }
-
- return 1;
- }
-
- break;
- }
-
- return 0;
-}
-
-static void release_name_pending_cb(DBusPendingCall *pending, void *userdata) {
- DBusMessage *reply;
- DBusConnection *bus = userdata;
-
- assert_se(reply = dbus_pending_call_steal_reply(pending));
- dbus_message_unref(reply);
-
- dbus_connection_close(bus);
-}
-
-void bus_async_unregister_and_exit(DBusConnection *bus, const char *name) {
- _cleanup_dbus_message_unref_ DBusMessage *m = NULL;
- DBusPendingCall *pending = NULL;
-
- assert(bus);
-
- /* We unregister the name here, but we continue to process
- * requests, until we get the response for it, so that all
- * requests are guaranteed to be processed. */
-
- m = dbus_message_new_method_call(
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS,
- "ReleaseName");
- if (!m)
- goto oom;
-
- if (!dbus_message_append_args(
- m,
- DBUS_TYPE_STRING,
- &name,
- DBUS_TYPE_INVALID))
- goto oom;
-
- if (!dbus_connection_send_with_reply(bus, m, &pending, -1))
- goto oom;
-
- if (!dbus_pending_call_set_notify(pending, release_name_pending_cb, bus, NULL))
- goto oom;
-
- dbus_pending_call_unref(pending);
-
- return;
-
-oom:
- log_oom();
-
- if (pending) {
- dbus_pending_call_cancel(pending);
- dbus_pending_call_unref(pending);
- }
-}
-
-DBusHandlerResult bus_exit_idle_filter(DBusConnection *bus, DBusMessage *m, void *userdata) {
- usec_t *remain_until = userdata;
-
- assert(bus);
- assert(m);
- assert(remain_until);
-
- /* Every time we get a new message we reset out timeout */
- *remain_until = now(CLOCK_MONOTONIC) + DEFAULT_EXIT_USEC;
-
- if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected"))
- dbus_connection_close(bus);
-
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-/* This mimics dbus_bus_get_unix_user() */
-pid_t bus_get_unix_process_id(
- DBusConnection *connection,
- const char *name,
- DBusError *error) {
-
- _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
- uint32_t pid = 0;
-
- m = dbus_message_new_method_call(
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS,
- "GetConnectionUnixProcessID");
- if (!m) {
- dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
- return 0;
- }
-
- if (!dbus_message_append_args(
- m,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_INVALID)) {
- dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
- return 0;
- }
-
- reply = dbus_connection_send_with_reply_and_block(connection, m, -1, error);
- if (!reply)
- return 0;
-
- if (dbus_set_error_from_message(error, reply))
- return 0;
-
- if (!dbus_message_get_args(
- reply, error,
- DBUS_TYPE_UINT32, &pid,
- DBUS_TYPE_INVALID))
- return 0;
-
- return (pid_t) pid;
-}
-
-bool bus_error_is_no_service(const DBusError *error) {
- assert(error);
-
- if (!dbus_error_is_set(error))
- return false;
-
- if (dbus_error_has_name(error, DBUS_ERROR_NAME_HAS_NO_OWNER))
- return true;
-
- if (dbus_error_has_name(error, DBUS_ERROR_SERVICE_UNKNOWN))
- return true;
-
- return startswith(error->name, "org.freedesktop.DBus.Error.Spawn.");
-}
-
-int bus_method_call_with_reply(
- DBusConnection *bus,
- const char *destination,
- const char *path,
- const char *interface,
- const char *method,
- DBusMessage **return_reply,
- DBusError *return_error,
- int first_arg_type, ...) {
-
- DBusError error;
- _cleanup_dbus_message_unref_ DBusMessage *m = NULL;
- DBusMessage *reply;
- va_list ap;
- int r = 0;
-
- dbus_error_init(&error);
- assert(bus);
-
- m = dbus_message_new_method_call(destination, path, interface, method);
- if (!m) {
- r = log_oom();
- goto finish;
- }
-
- va_start(ap, first_arg_type);
- if (!dbus_message_append_args_valist(m, first_arg_type, ap)) {
- va_end(ap);
- r = log_oom();
- goto finish;
- }
- va_end(ap);
-
- reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
- if (!reply) {
- if (!return_error)
- log_error("Failed to issue method call: %s", bus_error_message(&error));
-
- if (bus_error_is_no_service(&error))
- r = -ENOENT;
- else if (dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED))
- r = -EACCES;
- else if (dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY))
- r = -ETIMEDOUT;
- else
- r = -EIO;
- goto finish;
- }
-
- if (return_reply)
- *return_reply = reply;
- else
- dbus_message_unref(reply);
-
-finish:
- if (return_error)
- *return_error = error;
- else
- dbus_error_free(&error);
-
- return r;
-}
-
-void bus_message_unrefp(DBusMessage **reply) {
- if (!reply)
- return;
-
- if (!*reply)
- return;
-
- dbus_message_unref(*reply);
-}
-
-const char *bus_message_get_sender_with_fallback(DBusMessage *m) {
- const char *s;
-
- assert(m);
-
- s = dbus_message_get_sender(m);
- if (s)
- return s;
-
- /* When the message came in from a direct connection the
- * message will have no sender. We fix that here. */
-
- return ":no-sender";
-}
diff --git a/src/shared/dbus-common.h b/src/shared/dbus-common.h
deleted file mode 100644
index 005a715d0a..0000000000
--- a/src/shared/dbus-common.h
+++ /dev/null
@@ -1,222 +0,0 @@
-/*-*- 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 <dbus/dbus.h>
-#include <inttypes.h>
-
-#ifndef DBUS_ERROR_UNKNOWN_OBJECT
-#define DBUS_ERROR_UNKNOWN_OBJECT "org.freedesktop.DBus.Error.UnknownObject"
-#endif
-
-#ifndef DBUS_ERROR_UNKNOWN_INTERFACE
-#define DBUS_ERROR_UNKNOWN_INTERFACE "org.freedesktop.DBus.Error.UnknownInterface"
-#endif
-
-#ifndef DBUS_ERROR_UNKNOWN_PROPERTY
-#define DBUS_ERROR_UNKNOWN_PROPERTY "org.freedesktop.DBus.Error.UnknownProperty"
-#endif
-
-#ifndef DBUS_ERROR_PROPERTY_READ_ONLY
-#define DBUS_ERROR_PROPERTY_READ_ONLY "org.freedesktop.DBus.Error.PropertyReadOnly"
-#endif
-
-#define BUS_PROPERTIES_INTERFACE \
- " <interface name=\"org.freedesktop.DBus.Properties\">\n" \
- " <method name=\"Get\">\n" \
- " <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n" \
- " <arg name=\"property\" direction=\"in\" type=\"s\"/>\n" \
- " <arg name=\"value\" direction=\"out\" type=\"v\"/>\n" \
- " </method>\n" \
- " <method name=\"GetAll\">\n" \
- " <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n" \
- " <arg name=\"properties\" direction=\"out\" type=\"a{sv}\"/>\n" \
- " </method>\n" \
- " <method name=\"Set\">\n" \
- " <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n" \
- " <arg name=\"property\" direction=\"in\" type=\"s\"/>\n" \
- " <arg name=\"value\" direction=\"in\" type=\"v\"/>\n" \
- " </method>\n" \
- " <signal name=\"PropertiesChanged\">\n" \
- " <arg type=\"s\" name=\"interface\"/>\n" \
- " <arg type=\"a{sv}\" name=\"changed_properties\"/>\n" \
- " <arg type=\"as\" name=\"invalidated_properties\"/>\n" \
- " </signal>\n" \
- " </interface>\n"
-
-#define BUS_INTROSPECTABLE_INTERFACE \
- " <interface name=\"org.freedesktop.DBus.Introspectable\">\n" \
- " <method name=\"Introspect\">\n" \
- " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n" \
- " </method>\n" \
- " </interface>\n"
-
-#define BUS_PEER_INTERFACE \
- "<interface name=\"org.freedesktop.DBus.Peer\">\n" \
- " <method name=\"Ping\"/>\n" \
- " <method name=\"GetMachineId\">\n" \
- " <arg type=\"s\" name=\"machine_uuid\" direction=\"out\"/>\n" \
- " </method>\n" \
- "</interface>\n"
-
-#define BUS_GENERIC_INTERFACES_LIST \
- "org.freedesktop.DBus.Properties\0" \
- "org.freedesktop.DBus.Introspectable\0" \
- "org.freedesktop.DBus.Peer\0"
-
-int bus_check_peercred(DBusConnection *c);
-
-int bus_connect(DBusBusType t, DBusConnection **_bus, bool *private_bus, DBusError *error);
-
-int bus_connect_system_ssh(const char *user, const char *host, DBusConnection **_bus, DBusError *error);
-int bus_connect_system_polkit(DBusConnection **_bus, DBusError *error);
-
-const char *bus_error_message(const DBusError *error);
-const char *bus_error_message_or_strerror(const DBusError *error, int err);
-
-typedef int (*BusPropertyCallback)(DBusMessageIter *iter, const char *property, void *data);
-typedef int (*BusPropertySetCallback)(DBusMessageIter *iter, const char *property, void *data);
-
-typedef struct BusProperty {
- const char *property; /* name of the property */
- BusPropertyCallback append; /* Function that is called to serialize this property */
- const char *signature;
- const uint16_t offset; /* Offset from BusBoundProperties::base address to the property data.
- * uint16_t is sufficient, because we have no structs too big.
- * -Werror=overflow will catch it if this does not hold. */
- bool indirect; /* data is indirect, ie. not base+offset, but *(base+offset) */
- BusPropertySetCallback set; /* Optional: Function that is called to set this property */
-} BusProperty;
-
-typedef struct BusBoundProperties {
- const char *interface; /* interface of the properties */
- const BusProperty *properties; /* array of properties, ended by a NULL-filled element */
- const void *const base; /* base pointer to which the offset must be added to reach data */
-} BusBoundProperties;
-
-DBusHandlerResult bus_send_error_reply(
- DBusConnection *c,
- DBusMessage *message,
- DBusError *bus_error,
- int error);
-
-DBusHandlerResult bus_default_message_handler(
- DBusConnection *c,
- DBusMessage *message,
- const char *introspection,
- const char *interfaces,
- const BusBoundProperties *bound_properties);
-
-int bus_property_append_string(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_strv(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_bool(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_tristate_false(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_int32(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_uint32(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_uint64(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_size(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_ul(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_long(DBusMessageIter *i, const char *property, void *data);
-
-#define bus_property_append_int bus_property_append_int32
-#define bus_property_append_pid bus_property_append_uint32
-#define bus_property_append_uid bus_property_append_uint32
-#define bus_property_append_gid bus_property_append_uint32
-#define bus_property_append_mode bus_property_append_uint32
-#define bus_property_append_unsigned bus_property_append_uint32
-#define bus_property_append_usec bus_property_append_uint64
-
-int bus_property_set_uint64(DBusMessageIter *i, const char *property, void *data);
-#define bus_property_set_usec bus_property_set_uint64
-
-#define DEFINE_BUS_PROPERTY_APPEND_ENUM(function,name,type) \
- int function(DBusMessageIter *i, const char *property, void *data) { \
- const char *value; \
- type *field = data; \
- \
- assert(i); \
- assert(property); \
- \
- value = strempty(name##_to_string(*field)); \
- \
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &value)) \
- return -ENOMEM; \
- \
- return 0; \
- }
-
-#define DEFINE_BUS_PROPERTY_SET_ENUM(function,name,type) \
- int function(DBusMessageIter *i, const char *property, void *data) { \
- const char *value; \
- type f, *field = data; \
- \
- assert(i); \
- assert(property); \
- \
- dbus_message_iter_get_basic(i, &value); \
- \
- f = name##_from_string(value); \
- if (f < 0) \
- return f; \
- \
- *field = f; \
- return 0; \
- }
-
-const char *bus_errno_to_dbus(int error);
-
-DBusMessage* bus_properties_changed_new(const char *path, const char *interface, const char *properties);
-DBusMessage* bus_properties_changed_one_new(const char *path, const char *interface, const char *property);
-
-uint32_t bus_flags_to_events(DBusWatch *bus_watch);
-unsigned bus_events_to_flags(uint32_t events);
-
-int bus_parse_strv(DBusMessage *m, char ***_l);
-int bus_parse_strv_iter(DBusMessageIter *iter, char ***_l);
-
-int bus_append_strv_iter(DBusMessageIter *iter, char **l);
-
-int bus_iter_get_basic_and_next(DBusMessageIter *iter, int type, void *data, bool next);
-
-int generic_print_property(const char *name, DBusMessageIter *iter, bool all);
-
-void bus_async_unregister_and_exit(DBusConnection *bus, const char *name);
-
-DBusHandlerResult bus_exit_idle_filter(DBusConnection *bus, DBusMessage *m, void *userdata);
-
-pid_t bus_get_unix_process_id(DBusConnection *connection, const char *name, DBusError *error);
-
-bool bus_error_is_no_service(const DBusError *error);
-int bus_method_call_with_reply(DBusConnection *bus,
- const char *destination,
- const char *path,
- const char *interface,
- const char *method,
- DBusMessage **return_reply,
- DBusError *return_error,
- int first_arg_type, ...);
-
-const char *bus_message_get_sender_with_fallback(DBusMessage *m);
-
-void bus_message_unrefp(DBusMessage **reply);
-
-#define _cleanup_dbus_message_unref_ __attribute__((cleanup(bus_message_unrefp)))
diff --git a/src/shared/dbus-loop.c b/src/shared/dbus-loop.c
deleted file mode 100644
index da0a00443a..0000000000
--- a/src/shared/dbus-loop.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <assert.h>
-#include <sys/epoll.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/timerfd.h>
-#include <unistd.h>
-
-#include "dbus-loop.h"
-#include "dbus-common.h"
-#include "util.h"
-
-/* Minimal implementation of the dbus loop which integrates all dbus
- * events into a single epoll fd which we can triviall integrate with
- * other loops. Note that this is not used in the main systemd daemon
- * since we run a more elaborate mainloop there. */
-
-typedef struct EpollData {
- int fd;
- void *object;
- bool is_timeout:1;
- bool fd_is_dupped:1;
-} EpollData;
-
-static dbus_bool_t add_watch(DBusWatch *watch, void *data) {
- EpollData *e;
- struct epoll_event ev;
-
- assert(watch);
-
- e = new0(EpollData, 1);
- if (!e)
- return FALSE;
-
- e->fd = dbus_watch_get_unix_fd(watch);
- e->object = watch;
- e->is_timeout = false;
-
- zero(ev);
- ev.events = bus_flags_to_events(watch);
- ev.data.ptr = e;
-
- if (epoll_ctl(PTR_TO_INT(data), EPOLL_CTL_ADD, e->fd, &ev) < 0) {
-
- if (errno != EEXIST) {
- free(e);
- return FALSE;
- }
-
- /* Hmm, bloody D-Bus creates multiple watches on the
- * same fd. epoll() does not like that. As a dirty
- * hack we simply dup() the fd and hence get a second
- * one we can safely add to the epoll(). */
-
- e->fd = dup(e->fd);
- if (e->fd < 0) {
- free(e);
- return FALSE;
- }
-
- if (epoll_ctl(PTR_TO_INT(data), EPOLL_CTL_ADD, e->fd, &ev) < 0) {
- close_nointr_nofail(e->fd);
- free(e);
- return FALSE;
- }
-
- e->fd_is_dupped = true;
- }
-
- dbus_watch_set_data(watch, e, NULL);
-
- return TRUE;
-}
-
-static void remove_watch(DBusWatch *watch, void *data) {
- EpollData *e;
-
- assert(watch);
-
- e = dbus_watch_get_data(watch);
- if (!e)
- return;
-
- assert_se(epoll_ctl(PTR_TO_INT(data), EPOLL_CTL_DEL, e->fd, NULL) >= 0);
-
- if (e->fd_is_dupped)
- close_nointr_nofail(e->fd);
-
- free(e);
-}
-
-static void toggle_watch(DBusWatch *watch, void *data) {
- EpollData *e;
- struct epoll_event ev;
-
- assert(watch);
-
- e = dbus_watch_get_data(watch);
- if (!e)
- return;
-
- zero(ev);
- ev.events = bus_flags_to_events(watch);
- ev.data.ptr = e;
-
- assert_se(epoll_ctl(PTR_TO_INT(data), EPOLL_CTL_MOD, e->fd, &ev) == 0);
-}
-
-static int timeout_arm(EpollData *e) {
- struct itimerspec its;
-
- assert(e);
- assert(e->is_timeout);
-
- zero(its);
-
- if (dbus_timeout_get_enabled(e->object)) {
- timespec_store(&its.it_value, dbus_timeout_get_interval(e->object) * USEC_PER_MSEC);
- its.it_interval = its.it_value;
- }
-
- if (timerfd_settime(e->fd, 0, &its, NULL) < 0)
- return -errno;
-
- return 0;
-}
-
-static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) {
- EpollData *e;
- struct epoll_event ev;
-
- assert(timeout);
-
- e = new0(EpollData, 1);
- if (!e)
- return FALSE;
-
- e->fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
- if (e->fd < 0)
- goto fail;
-
- e->object = timeout;
- e->is_timeout = true;
-
- if (timeout_arm(e) < 0)
- goto fail;
-
- zero(ev);
- ev.events = EPOLLIN;
- ev.data.ptr = e;
-
- if (epoll_ctl(PTR_TO_INT(data), EPOLL_CTL_ADD, e->fd, &ev) < 0)
- goto fail;
-
- dbus_timeout_set_data(timeout, e, NULL);
-
- return TRUE;
-
-fail:
- if (e->fd >= 0)
- close_nointr_nofail(e->fd);
-
- free(e);
- return FALSE;
-}
-
-static void remove_timeout(DBusTimeout *timeout, void *data) {
- EpollData *e;
-
- assert(timeout);
-
- e = dbus_timeout_get_data(timeout);
- if (!e)
- return;
-
- assert_se(epoll_ctl(PTR_TO_INT(data), EPOLL_CTL_DEL, e->fd, NULL) >= 0);
- close_nointr_nofail(e->fd);
- free(e);
-}
-
-static void toggle_timeout(DBusTimeout *timeout, void *data) {
- EpollData *e;
- int r;
-
- assert(timeout);
-
- e = dbus_timeout_get_data(timeout);
- if (!e)
- return;
-
- r = timeout_arm(e);
- if (r < 0)
- log_error("Failed to rearm timer: %s", strerror(-r));
-}
-
-int bus_loop_open(DBusConnection *c) {
- int fd;
-
- assert(c);
-
- fd = epoll_create1(EPOLL_CLOEXEC);
- if (fd < 0)
- return -errno;
-
- if (!dbus_connection_set_watch_functions(c, add_watch, remove_watch, toggle_watch, INT_TO_PTR(fd), NULL) ||
- !dbus_connection_set_timeout_functions(c, add_timeout, remove_timeout, toggle_timeout, INT_TO_PTR(fd), NULL)) {
- close_nointr_nofail(fd);
- return -ENOMEM;
- }
-
- return fd;
-}
-
-int bus_loop_dispatch(int fd) {
- int n;
- struct epoll_event event;
- EpollData *d;
-
- assert(fd >= 0);
-
- zero(event);
-
- n = epoll_wait(fd, &event, 1, 0);
- if (n < 0)
- return errno == EAGAIN || errno == EINTR ? 0 : -errno;
-
- assert_se(d = event.data.ptr);
-
- if (d->is_timeout) {
- DBusTimeout *t = d->object;
-
- if (dbus_timeout_get_enabled(t))
- dbus_timeout_handle(t);
- } else {
- DBusWatch *w = d->object;
-
- if (dbus_watch_get_enabled(w))
- dbus_watch_handle(w, bus_events_to_flags(event.events));
- }
-
- return 0;
-}
diff --git a/src/shared/dbus-loop.h b/src/shared/dbus-loop.h
deleted file mode 100644
index a5e768d931..0000000000
--- a/src/shared/dbus-loop.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <dbus/dbus.h>
-
-int bus_loop_open(DBusConnection *c);
-int bus_loop_dispatch(int fd);
diff --git a/src/shared/def.h b/src/shared/def.h
deleted file mode 100644
index 5ba170f965..0000000000
--- a/src/shared/def.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*-*- 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 "util.h"
-
-#define DEFAULT_TIMEOUT_USEC (90*USEC_PER_SEC)
-#define DEFAULT_RESTART_USEC (100*USEC_PER_MSEC)
-#define DEFAULT_CONFIRM_USEC (30*USEC_PER_SEC)
-
-#define DEFAULT_EXIT_USEC (5*USEC_PER_MINUTE)
-
-#define SYSTEMD_CGROUP_CONTROLLER "name=systemd"
-
-#define SIGNALS_CRASH_HANDLER SIGSEGV,SIGILL,SIGFPE,SIGBUS,SIGQUIT,SIGABRT
-#define SIGNALS_IGNORE SIGKILL,SIGPIPE
diff --git a/src/shared/dev-setup.c b/src/shared/dev-setup.c
deleted file mode 100644
index b0ac02d461..0000000000
--- a/src/shared/dev-setup.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*-*- 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 <errno.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <unistd.h>
-
-#include "dev-setup.h"
-#include "log.h"
-#include "macro.h"
-#include "util.h"
-#include "label.h"
-
-static int symlink_and_label(const char *old_path, const char *new_path) {
- int r;
-
- assert(old_path);
- assert(new_path);
-
- r = label_context_set(new_path, S_IFLNK);
- if (r < 0)
- return r;
-
- if (symlink(old_path, new_path) < 0)
- r = -errno;
-
- label_context_clear();
-
- return r;
-}
-
-void dev_setup(const char *prefix) {
- const char *j, *k;
-
- static const char symlinks[] =
- "/proc/kcore\0" "/dev/core\0"
- "/proc/self/fd\0" "/dev/fd\0"
- "/proc/self/fd/0\0" "/dev/stdin\0"
- "/proc/self/fd/1\0" "/dev/stdout\0"
- "/proc/self/fd/2\0" "/dev/stderr\0";
-
- NULSTR_FOREACH_PAIR(j, k, symlinks) {
-
- if (prefix) {
- char *linkname;
-
- if (asprintf(&linkname, "%s/%s", prefix, k) < 0) {
- log_oom();
- break;
- }
-
- symlink_and_label(j, linkname);
- free(linkname);
- } else
- symlink_and_label(j, k);
- }
-}
diff --git a/src/shared/dev-setup.h b/src/shared/dev-setup.h
deleted file mode 100644
index 320c0b30ba..0000000000
--- a/src/shared/dev-setup.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*-*- 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/>.
-***/
-
-void dev_setup(const char *pathprefix);
diff --git a/src/shared/exit-status.c b/src/shared/exit-status.c
deleted file mode 100644
index 45131f2b2a..0000000000
--- a/src/shared/exit-status.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*-*- 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 <stdlib.h>
-#include <sys/wait.h>
-
-#include "exit-status.h"
-#include "set.h"
-#include "macro.h"
-
-const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) {
-
- /* We cast to int here, so that -Wenum doesn't complain that
- * EXIT_SUCCESS/EXIT_FAILURE aren't in the enum */
-
- switch ((int) status) {
-
- case EXIT_SUCCESS:
- return "SUCCESS";
-
- case EXIT_FAILURE:
- return "FAILURE";
- }
-
-
- if (level == EXIT_STATUS_SYSTEMD || level == EXIT_STATUS_LSB) {
- switch ((int) status) {
-
- case EXIT_CHDIR:
- return "CHDIR";
-
- case EXIT_NICE:
- return "NICE";
-
- case EXIT_FDS:
- return "FDS";
-
- case EXIT_EXEC:
- return "EXEC";
-
- case EXIT_MEMORY:
- return "MEMORY";
-
- case EXIT_LIMITS:
- return "LIMITS";
-
- case EXIT_OOM_ADJUST:
- return "OOM_ADJUST";
-
- case EXIT_SIGNAL_MASK:
- return "SIGNAL_MASK";
-
- case EXIT_STDIN:
- return "STDIN";
-
- case EXIT_STDOUT:
- return "STDOUT";
-
- case EXIT_CHROOT:
- return "CHROOT";
-
- case EXIT_IOPRIO:
- return "IOPRIO";
-
- case EXIT_TIMERSLACK:
- return "TIMERSLACK";
-
- case EXIT_SECUREBITS:
- return "SECUREBITS";
-
- case EXIT_SETSCHEDULER:
- return "SETSCHEDULER";
-
- case EXIT_CPUAFFINITY:
- return "CPUAFFINITY";
-
- case EXIT_GROUP:
- return "GROUP";
-
- case EXIT_USER:
- return "USER";
-
- case EXIT_CAPABILITIES:
- return "CAPABILITIES";
-
- case EXIT_CGROUP:
- return "CGROUP";
-
- case EXIT_SETSID:
- return "SETSID";
-
- case EXIT_CONFIRM:
- return "CONFIRM";
-
- case EXIT_STDERR:
- return "STDERR";
-
- case EXIT_TCPWRAP:
- return "TCPWRAP";
-
- case EXIT_PAM:
- return "PAM";
-
- case EXIT_NETWORK:
- return "NETWORK";
-
- case EXIT_NAMESPACE:
- return "NAMESPACE";
-
- case EXIT_NO_NEW_PRIVILEGES:
- return "NO_NEW_PRIVILEGES";
-
- case EXIT_SECCOMP:
- return "SECCOMP";
- }
- }
-
- if (level == EXIT_STATUS_LSB) {
- switch ((int) status) {
-
- case EXIT_INVALIDARGUMENT:
- return "INVALIDARGUMENT";
-
- case EXIT_NOTIMPLEMENTED:
- return "NOTIMPLEMENTED";
-
- case EXIT_NOPERMISSION:
- return "NOPERMISSION";
-
- case EXIT_NOTINSTALLED:
- return "NOTINSSTALLED";
-
- case EXIT_NOTCONFIGURED:
- return "NOTCONFIGURED";
-
- case EXIT_NOTRUNNING:
- return "NOTRUNNING";
- }
- }
-
- return NULL;
-}
-
-
-bool is_clean_exit(int code, int status, ExitStatusSet *success_status) {
-
- if (code == CLD_EXITED)
- return status == 0 ||
- (success_status &&
- set_contains(success_status->code, INT_TO_PTR(status)));
-
- /* If a daemon does not implement handlers for some of the
- * signals that's not considered an unclean shutdown */
- if (code == CLD_KILLED)
- return
- status == SIGHUP ||
- status == SIGINT ||
- status == SIGTERM ||
- status == SIGPIPE ||
- (success_status &&
- set_contains(success_status->signal, INT_TO_PTR(status)));
-
- return false;
-}
-
-bool is_clean_exit_lsb(int code, int status, ExitStatusSet *success_status) {
-
- if (is_clean_exit(code, status, success_status))
- return true;
-
- return
- code == CLD_EXITED &&
- (status == EXIT_NOTINSTALLED || status == EXIT_NOTCONFIGURED);
-}
diff --git a/src/shared/exit-status.h b/src/shared/exit-status.h
deleted file mode 100644
index d3b548fc96..0000000000
--- a/src/shared/exit-status.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*-*- 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 "set.h"
-typedef enum ExitStatus {
- /* EXIT_SUCCESS defined by libc */
- /* EXIT_FAILURE defined by libc */
- EXIT_INVALIDARGUMENT = 2,
- EXIT_NOTIMPLEMENTED = 3,
- EXIT_NOPERMISSION = 4,
- EXIT_NOTINSTALLED = 5,
- EXIT_NOTCONFIGURED = 6,
- EXIT_NOTRUNNING = 7,
-
- /* The LSB suggests that error codes >= 200 are "reserved". We
- * use them here under the assumption that they hence are
- * unused by init scripts.
- *
- * http://refspecs.freestandards.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html */
-
- EXIT_CHDIR = 200,
- EXIT_NICE,
- EXIT_FDS,
- EXIT_EXEC,
- EXIT_MEMORY,
- EXIT_LIMITS,
- EXIT_OOM_ADJUST,
- EXIT_SIGNAL_MASK,
- EXIT_STDIN,
- EXIT_STDOUT,
- EXIT_CHROOT, /* 210 */
- EXIT_IOPRIO,
- EXIT_TIMERSLACK,
- EXIT_SECUREBITS,
- EXIT_SETSCHEDULER,
- EXIT_CPUAFFINITY,
- EXIT_GROUP,
- EXIT_USER,
- EXIT_CAPABILITIES,
- EXIT_CGROUP,
- EXIT_SETSID, /* 220 */
- EXIT_CONFIRM,
- EXIT_STDERR,
- EXIT_TCPWRAP,
- EXIT_PAM,
- EXIT_NETWORK,
- EXIT_NAMESPACE,
- EXIT_NO_NEW_PRIVILEGES,
- EXIT_SECCOMP
-} ExitStatus;
-
-typedef enum ExitStatusLevel {
- EXIT_STATUS_MINIMAL,
- EXIT_STATUS_SYSTEMD,
- EXIT_STATUS_LSB,
- EXIT_STATUS_FULL = EXIT_STATUS_LSB
-} ExitStatusLevel;
-
-typedef struct ExitStatusSet {
- Set *code;
- Set *signal;
-} ExitStatusSet;
-
-const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level);
-
-bool is_clean_exit(int code, int status, ExitStatusSet *success_status);
-bool is_clean_exit_lsb(int code, int status, ExitStatusSet *success_status);
diff --git a/src/shared/hashmap.c b/src/shared/hashmap.c
deleted file mode 100644
index dcfbb67228..0000000000
--- a/src/shared/hashmap.c
+++ /dev/null
@@ -1,835 +0,0 @@
-/*-*- 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 <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include "util.h"
-#include "hashmap.h"
-#include "macro.h"
-
-#define NBUCKETS 127
-
-struct hashmap_entry {
- const void *key;
- void *value;
- struct hashmap_entry *bucket_next, *bucket_previous;
- struct hashmap_entry *iterate_next, *iterate_previous;
-};
-
-struct Hashmap {
- hash_func_t hash_func;
- compare_func_t compare_func;
-
- struct hashmap_entry *iterate_list_head, *iterate_list_tail;
- unsigned n_entries;
-
- bool from_pool;
-};
-
-#define BY_HASH(h) ((struct hashmap_entry**) ((uint8_t*) (h) + ALIGN(sizeof(Hashmap))))
-
-struct pool {
- struct pool *next;
- unsigned n_tiles;
- unsigned n_used;
-};
-
-static struct pool *first_hashmap_pool = NULL;
-static void *first_hashmap_tile = NULL;
-
-static struct pool *first_entry_pool = NULL;
-static void *first_entry_tile = NULL;
-
-static void* allocate_tile(struct pool **first_pool, void **first_tile, size_t tile_size) {
- unsigned i;
-
- if (*first_tile) {
- void *r;
-
- r = *first_tile;
- *first_tile = * (void**) (*first_tile);
- return r;
- }
-
- if (_unlikely_(!*first_pool) || _unlikely_((*first_pool)->n_used >= (*first_pool)->n_tiles)) {
- unsigned n;
- size_t size;
- struct pool *p;
-
- n = *first_pool ? (*first_pool)->n_tiles : 0;
- n = MAX(512U, n * 2);
- size = PAGE_ALIGN(ALIGN(sizeof(struct pool)) + n*tile_size);
- n = (size - ALIGN(sizeof(struct pool))) / tile_size;
-
- p = malloc(size);
- if (!p)
- return NULL;
-
- p->next = *first_pool;
- p->n_tiles = n;
- p->n_used = 0;
-
- *first_pool = p;
- }
-
- i = (*first_pool)->n_used++;
-
- return ((uint8_t*) (*first_pool)) + ALIGN(sizeof(struct pool)) + i*tile_size;
-}
-
-static void deallocate_tile(void **first_tile, void *p) {
- * (void**) p = *first_tile;
- *first_tile = p;
-}
-
-#ifndef __OPTIMIZE__
-
-static void drop_pool(struct pool *p) {
- while (p) {
- struct pool *n;
- n = p->next;
- free(p);
- p = n;
- }
-}
-
-__attribute__((destructor)) static void cleanup_pool(void) {
- /* Be nice to valgrind */
-
- drop_pool(first_hashmap_pool);
- drop_pool(first_entry_pool);
-}
-
-#endif
-
-unsigned string_hash_func(const void *p) {
- unsigned hash = 5381;
- const signed char *c;
-
- /* DJB's hash function */
-
- for (c = p; *c; c++)
- hash = (hash << 5) + hash + (unsigned) *c;
-
- return hash;
-}
-
-int string_compare_func(const void *a, const void *b) {
- return strcmp(a, b);
-}
-
-unsigned trivial_hash_func(const void *p) {
- return PTR_TO_UINT(p);
-}
-
-int trivial_compare_func(const void *a, const void *b) {
- return a < b ? -1 : (a > b ? 1 : 0);
-}
-
-unsigned uint64_hash_func(const void *p) {
- uint64_t u;
-
- assert_cc(sizeof(uint64_t) == 2*sizeof(unsigned));
-
- u = *(const uint64_t*) p;
-
- return (unsigned) ((u >> 32) ^ u);
-}
-
-int uint64_compare_func(const void *_a, const void *_b) {
- uint64_t a, b;
-
- a = *(const uint64_t*) _a;
- b = *(const uint64_t*) _b;
-
- return a < b ? -1 : (a > b ? 1 : 0);
-}
-
-Hashmap *hashmap_new(hash_func_t hash_func, compare_func_t compare_func) {
- bool b;
- Hashmap *h;
- size_t size;
-
- b = is_main_thread();
-
- size = ALIGN(sizeof(Hashmap)) + NBUCKETS * sizeof(struct hashmap_entry*);
-
- if (b) {
- h = allocate_tile(&first_hashmap_pool, &first_hashmap_tile, size);
- if (!h)
- return NULL;
-
- memset(h, 0, size);
- } else {
- h = malloc0(size);
-
- if (!h)
- return NULL;
- }
-
- h->hash_func = hash_func ? hash_func : trivial_hash_func;
- h->compare_func = compare_func ? compare_func : trivial_compare_func;
-
- h->n_entries = 0;
- h->iterate_list_head = h->iterate_list_tail = NULL;
-
- h->from_pool = b;
-
- return h;
-}
-
-int hashmap_ensure_allocated(Hashmap **h, hash_func_t hash_func, compare_func_t compare_func) {
- assert(h);
-
- if (*h)
- return 0;
-
- if (!(*h = hashmap_new(hash_func, compare_func)))
- return -ENOMEM;
-
- return 0;
-}
-
-static void link_entry(Hashmap *h, struct hashmap_entry *e, unsigned hash) {
- assert(h);
- assert(e);
-
- /* Insert into hash table */
- e->bucket_next = BY_HASH(h)[hash];
- e->bucket_previous = NULL;
- if (BY_HASH(h)[hash])
- BY_HASH(h)[hash]->bucket_previous = e;
- BY_HASH(h)[hash] = e;
-
- /* Insert into iteration list */
- e->iterate_previous = h->iterate_list_tail;
- e->iterate_next = NULL;
- if (h->iterate_list_tail) {
- assert(h->iterate_list_head);
- h->iterate_list_tail->iterate_next = e;
- } else {
- assert(!h->iterate_list_head);
- h->iterate_list_head = e;
- }
- h->iterate_list_tail = e;
-
- h->n_entries++;
- assert(h->n_entries >= 1);
-}
-
-static void unlink_entry(Hashmap *h, struct hashmap_entry *e, unsigned hash) {
- assert(h);
- assert(e);
-
- /* Remove from iteration list */
- if (e->iterate_next)
- e->iterate_next->iterate_previous = e->iterate_previous;
- else
- h->iterate_list_tail = e->iterate_previous;
-
- if (e->iterate_previous)
- e->iterate_previous->iterate_next = e->iterate_next;
- else
- h->iterate_list_head = e->iterate_next;
-
- /* Remove from hash table bucket list */
- if (e->bucket_next)
- e->bucket_next->bucket_previous = e->bucket_previous;
-
- if (e->bucket_previous)
- e->bucket_previous->bucket_next = e->bucket_next;
- else
- BY_HASH(h)[hash] = e->bucket_next;
-
- assert(h->n_entries >= 1);
- h->n_entries--;
-}
-
-static void remove_entry(Hashmap *h, struct hashmap_entry *e) {
- unsigned hash;
-
- assert(h);
- assert(e);
-
- hash = h->hash_func(e->key) % NBUCKETS;
-
- unlink_entry(h, e, hash);
-
- if (h->from_pool)
- deallocate_tile(&first_entry_tile, e);
- else
- free(e);
-}
-
-void hashmap_free(Hashmap*h) {
-
- /* Free the hashmap, but nothing in it */
-
- if (!h)
- return;
-
- hashmap_clear(h);
-
- if (h->from_pool)
- deallocate_tile(&first_hashmap_tile, h);
- else
- free(h);
-}
-
-void hashmap_free_free(Hashmap *h) {
-
- /* Free the hashmap and all data objects in it, but not the
- * keys */
-
- if (!h)
- return;
-
- hashmap_clear_free(h);
- hashmap_free(h);
-}
-
-void hashmap_clear(Hashmap *h) {
- if (!h)
- return;
-
- while (h->iterate_list_head)
- remove_entry(h, h->iterate_list_head);
-}
-
-void hashmap_clear_free(Hashmap *h) {
- void *p;
-
- if (!h)
- return;
-
- while ((p = hashmap_steal_first(h)))
- free(p);
-}
-
-static struct hashmap_entry *hash_scan(Hashmap *h, unsigned hash, const void *key) {
- struct hashmap_entry *e;
- assert(h);
- assert(hash < NBUCKETS);
-
- for (e = BY_HASH(h)[hash]; e; e = e->bucket_next)
- if (h->compare_func(e->key, key) == 0)
- return e;
-
- return NULL;
-}
-
-int hashmap_put(Hashmap *h, const void *key, void *value) {
- struct hashmap_entry *e;
- unsigned hash;
-
- assert(h);
-
- hash = h->hash_func(key) % NBUCKETS;
-
- e = hash_scan(h, hash, key);
- if (e) {
-
- if (e->value == value)
- return 0;
-
- return -EEXIST;
- }
-
- if (h->from_pool)
- e = allocate_tile(&first_entry_pool, &first_entry_tile, sizeof(struct hashmap_entry));
- else
- e = new(struct hashmap_entry, 1);
-
- if (!e)
- return -ENOMEM;
-
- e->key = key;
- e->value = value;
-
- link_entry(h, e, hash);
-
- return 1;
-}
-
-int hashmap_replace(Hashmap *h, const void *key, void *value) {
- struct hashmap_entry *e;
- unsigned hash;
-
- assert(h);
-
- hash = h->hash_func(key) % NBUCKETS;
- e = hash_scan(h, hash, key);
- if (e) {
- e->key = key;
- e->value = value;
- return 0;
- }
-
- return hashmap_put(h, key, value);
-}
-
-int hashmap_update(Hashmap *h, const void *key, void *value) {
- struct hashmap_entry *e;
- unsigned hash;
-
- assert(h);
-
- hash = h->hash_func(key) % NBUCKETS;
- e = hash_scan(h, hash, key);
- if (!e)
- return -ENOENT;
-
- e->value = value;
- return 0;
-}
-
-void* hashmap_get(Hashmap *h, const void *key) {
- unsigned hash;
- struct hashmap_entry *e;
-
- if (!h)
- return NULL;
-
- hash = h->hash_func(key) % NBUCKETS;
- e = hash_scan(h, hash, key);
- if (!e)
- return NULL;
-
- return e->value;
-}
-
-void* hashmap_get2(Hashmap *h, const void *key, void **key2) {
- unsigned hash;
- struct hashmap_entry *e;
-
- if (!h)
- return NULL;
-
- hash = h->hash_func(key) % NBUCKETS;
- e = hash_scan(h, hash, key);
- if (!e)
- return NULL;
-
- if (key2)
- *key2 = (void*) e->key;
-
- return e->value;
-}
-
-bool hashmap_contains(Hashmap *h, const void *key) {
- unsigned hash;
-
- if (!h)
- return false;
-
- hash = h->hash_func(key) % NBUCKETS;
-
- if (!hash_scan(h, hash, key))
- return false;
-
- return true;
-}
-
-void* hashmap_remove(Hashmap *h, const void *key) {
- struct hashmap_entry *e;
- unsigned hash;
- void *data;
-
- if (!h)
- return NULL;
-
- hash = h->hash_func(key) % NBUCKETS;
-
- if (!(e = hash_scan(h, hash, key)))
- return NULL;
-
- data = e->value;
- remove_entry(h, e);
-
- return data;
-}
-
-int hashmap_remove_and_put(Hashmap *h, const void *old_key, const void *new_key, void *value) {
- struct hashmap_entry *e;
- unsigned old_hash, new_hash;
-
- if (!h)
- return -ENOENT;
-
- old_hash = h->hash_func(old_key) % NBUCKETS;
- if (!(e = hash_scan(h, old_hash, old_key)))
- return -ENOENT;
-
- new_hash = h->hash_func(new_key) % NBUCKETS;
- if (hash_scan(h, new_hash, new_key))
- return -EEXIST;
-
- unlink_entry(h, e, old_hash);
-
- e->key = new_key;
- e->value = value;
-
- link_entry(h, e, new_hash);
-
- return 0;
-}
-
-int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_key, void *value) {
- struct hashmap_entry *e, *k;
- unsigned old_hash, new_hash;
-
- if (!h)
- return -ENOENT;
-
- old_hash = h->hash_func(old_key) % NBUCKETS;
- if (!(e = hash_scan(h, old_hash, old_key)))
- return -ENOENT;
-
- new_hash = h->hash_func(new_key) % NBUCKETS;
-
- if ((k = hash_scan(h, new_hash, new_key)))
- if (e != k)
- remove_entry(h, k);
-
- unlink_entry(h, e, old_hash);
-
- e->key = new_key;
- e->value = value;
-
- link_entry(h, e, new_hash);
-
- return 0;
-}
-
-void* hashmap_remove_value(Hashmap *h, const void *key, void *value) {
- struct hashmap_entry *e;
- unsigned hash;
-
- if (!h)
- return NULL;
-
- hash = h->hash_func(key) % NBUCKETS;
-
- if (!(e = hash_scan(h, hash, key)))
- return NULL;
-
- if (e->value != value)
- return NULL;
-
- remove_entry(h, e);
-
- return value;
-}
-
-void *hashmap_iterate(Hashmap *h, Iterator *i, const void **key) {
- struct hashmap_entry *e;
-
- assert(i);
-
- if (!h)
- goto at_end;
-
- if (*i == ITERATOR_LAST)
- goto at_end;
-
- if (*i == ITERATOR_FIRST && !h->iterate_list_head)
- goto at_end;
-
- e = *i == ITERATOR_FIRST ? h->iterate_list_head : (struct hashmap_entry*) *i;
-
- if (e->iterate_next)
- *i = (Iterator) e->iterate_next;
- else
- *i = ITERATOR_LAST;
-
- if (key)
- *key = e->key;
-
- return e->value;
-
-at_end:
- *i = ITERATOR_LAST;
-
- if (key)
- *key = NULL;
-
- return NULL;
-}
-
-void *hashmap_iterate_backwards(Hashmap *h, Iterator *i, const void **key) {
- struct hashmap_entry *e;
-
- assert(i);
-
- if (!h)
- goto at_beginning;
-
- if (*i == ITERATOR_FIRST)
- goto at_beginning;
-
- if (*i == ITERATOR_LAST && !h->iterate_list_tail)
- goto at_beginning;
-
- e = *i == ITERATOR_LAST ? h->iterate_list_tail : (struct hashmap_entry*) *i;
-
- if (e->iterate_previous)
- *i = (Iterator) e->iterate_previous;
- else
- *i = ITERATOR_FIRST;
-
- if (key)
- *key = e->key;
-
- return e->value;
-
-at_beginning:
- *i = ITERATOR_FIRST;
-
- if (key)
- *key = NULL;
-
- return NULL;
-}
-
-void *hashmap_iterate_skip(Hashmap *h, const void *key, Iterator *i) {
- unsigned hash;
- struct hashmap_entry *e;
-
- if (!h)
- return NULL;
-
- hash = h->hash_func(key) % NBUCKETS;
-
- if (!(e = hash_scan(h, hash, key)))
- return NULL;
-
- *i = (Iterator) e;
-
- return e->value;
-}
-
-void* hashmap_first(Hashmap *h) {
-
- if (!h)
- return NULL;
-
- if (!h->iterate_list_head)
- return NULL;
-
- return h->iterate_list_head->value;
-}
-
-void* hashmap_first_key(Hashmap *h) {
-
- if (!h)
- return NULL;
-
- if (!h->iterate_list_head)
- return NULL;
-
- return (void*) h->iterate_list_head->key;
-}
-
-void* hashmap_last(Hashmap *h) {
-
- if (!h)
- return NULL;
-
- if (!h->iterate_list_tail)
- return NULL;
-
- return h->iterate_list_tail->value;
-}
-
-void* hashmap_steal_first(Hashmap *h) {
- void *data;
-
- if (!h)
- return NULL;
-
- if (!h->iterate_list_head)
- return NULL;
-
- data = h->iterate_list_head->value;
- remove_entry(h, h->iterate_list_head);
-
- return data;
-}
-
-void* hashmap_steal_first_key(Hashmap *h) {
- void *key;
-
- if (!h)
- return NULL;
-
- if (!h->iterate_list_head)
- return NULL;
-
- key = (void*) h->iterate_list_head->key;
- remove_entry(h, h->iterate_list_head);
-
- return key;
-}
-
-unsigned hashmap_size(Hashmap *h) {
-
- if (!h)
- return 0;
-
- return h->n_entries;
-}
-
-bool hashmap_isempty(Hashmap *h) {
-
- if (!h)
- return true;
-
- return h->n_entries == 0;
-}
-
-int hashmap_merge(Hashmap *h, Hashmap *other) {
- struct hashmap_entry *e;
-
- assert(h);
-
- if (!other)
- return 0;
-
- for (e = other->iterate_list_head; e; e = e->iterate_next) {
- int r;
-
- if ((r = hashmap_put(h, e->key, e->value)) < 0)
- if (r != -EEXIST)
- return r;
- }
-
- return 0;
-}
-
-void hashmap_move(Hashmap *h, Hashmap *other) {
- struct hashmap_entry *e, *n;
-
- assert(h);
-
- /* The same as hashmap_merge(), but every new item from other
- * is moved to h. This function is guaranteed to succeed. */
-
- if (!other)
- return;
-
- for (e = other->iterate_list_head; e; e = n) {
- unsigned h_hash, other_hash;
-
- n = e->iterate_next;
-
- h_hash = h->hash_func(e->key) % NBUCKETS;
-
- if (hash_scan(h, h_hash, e->key))
- continue;
-
- other_hash = other->hash_func(e->key) % NBUCKETS;
-
- unlink_entry(other, e, other_hash);
- link_entry(h, e, h_hash);
- }
-}
-
-int hashmap_move_one(Hashmap *h, Hashmap *other, const void *key) {
- unsigned h_hash, other_hash;
- struct hashmap_entry *e;
-
- if (!other)
- return 0;
-
- assert(h);
-
- h_hash = h->hash_func(key) % NBUCKETS;
- if (hash_scan(h, h_hash, key))
- return -EEXIST;
-
- other_hash = other->hash_func(key) % NBUCKETS;
- if (!(e = hash_scan(other, other_hash, key)))
- return -ENOENT;
-
- unlink_entry(other, e, other_hash);
- link_entry(h, e, h_hash);
-
- return 0;
-}
-
-Hashmap *hashmap_copy(Hashmap *h) {
- Hashmap *copy;
-
- assert(h);
-
- if (!(copy = hashmap_new(h->hash_func, h->compare_func)))
- return NULL;
-
- if (hashmap_merge(copy, h) < 0) {
- hashmap_free(copy);
- return NULL;
- }
-
- return copy;
-}
-
-char **hashmap_get_strv(Hashmap *h) {
- char **sv;
- Iterator it;
- char *item;
- int n;
-
- sv = new(char*, h->n_entries+1);
- if (!sv)
- return NULL;
-
- n = 0;
- HASHMAP_FOREACH(item, h, it)
- sv[n++] = item;
- sv[n] = NULL;
-
- return sv;
-}
-
-void *hashmap_next(Hashmap *h, const void *key) {
- unsigned hash;
- struct hashmap_entry *e;
-
- assert(h);
- assert(key);
-
- if (!h)
- return NULL;
-
- hash = h->hash_func(key) % NBUCKETS;
- e = hash_scan(h, hash, key);
- if (!e)
- return NULL;
-
- e = e->iterate_next;
- if (!e)
- return NULL;
-
- return e->value;
-}
diff --git a/src/shared/hashmap.h b/src/shared/hashmap.h
deleted file mode 100644
index 6fd71cf519..0000000000
--- a/src/shared/hashmap.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*-*- 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>
-
-/* Pretty straightforward hash table implementation. As a minor
- * optimization a NULL hashmap object will be treated as empty hashmap
- * for all read operations. That way it is not necessary to
- * instantiate an object for each Hashmap use. */
-
-typedef struct Hashmap Hashmap;
-typedef struct _IteratorStruct _IteratorStruct;
-typedef _IteratorStruct* Iterator;
-
-#define ITERATOR_FIRST ((Iterator) 0)
-#define ITERATOR_LAST ((Iterator) -1)
-
-typedef unsigned (*hash_func_t)(const void *p);
-typedef int (*compare_func_t)(const void *a, const void *b);
-
-unsigned string_hash_func(const void *p);
-int string_compare_func(const void *a, const void *b);
-
-unsigned trivial_hash_func(const void *p);
-int trivial_compare_func(const void *a, const void *b);
-
-unsigned uint64_hash_func(const void *p);
-int uint64_compare_func(const void *a, const void *b);
-
-Hashmap *hashmap_new(hash_func_t hash_func, compare_func_t compare_func);
-void hashmap_free(Hashmap *h);
-void hashmap_free_free(Hashmap *h);
-Hashmap *hashmap_copy(Hashmap *h);
-int hashmap_ensure_allocated(Hashmap **h, hash_func_t hash_func, compare_func_t compare_func);
-
-int hashmap_put(Hashmap *h, const void *key, void *value);
-int hashmap_update(Hashmap *h, const void *key, void *value);
-int hashmap_replace(Hashmap *h, const void *key, void *value);
-void* hashmap_get(Hashmap *h, const void *key);
-void* hashmap_get2(Hashmap *h, const void *key, void **rkey);
-bool hashmap_contains(Hashmap *h, const void *key);
-void* hashmap_remove(Hashmap *h, const void *key);
-void* hashmap_remove_value(Hashmap *h, const void *key, void *value);
-int hashmap_remove_and_put(Hashmap *h, const void *old_key, const void *new_key, void *value);
-int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_key, void *value);
-
-int hashmap_merge(Hashmap *h, Hashmap *other);
-void hashmap_move(Hashmap *h, Hashmap *other);
-int hashmap_move_one(Hashmap *h, Hashmap *other, const void *key);
-
-unsigned hashmap_size(Hashmap *h);
-bool hashmap_isempty(Hashmap *h);
-
-void *hashmap_iterate(Hashmap *h, Iterator *i, const void **key);
-void *hashmap_iterate_backwards(Hashmap *h, Iterator *i, const void **key);
-void *hashmap_iterate_skip(Hashmap *h, const void *key, Iterator *i);
-
-void hashmap_clear(Hashmap *h);
-void hashmap_clear_free(Hashmap *h);
-
-void *hashmap_steal_first(Hashmap *h);
-void *hashmap_steal_first_key(Hashmap *h);
-void* hashmap_first(Hashmap *h);
-void* hashmap_first_key(Hashmap *h);
-void* hashmap_last(Hashmap *h);
-
-void *hashmap_next(Hashmap *h, const void *key);
-
-char **hashmap_get_strv(Hashmap *h);
-
-#define HASHMAP_FOREACH(e, h, i) \
- for ((i) = ITERATOR_FIRST, (e) = hashmap_iterate((h), &(i), NULL); (e); (e) = hashmap_iterate((h), &(i), NULL))
-
-#define HASHMAP_FOREACH_KEY(e, k, h, i) \
- for ((i) = ITERATOR_FIRST, (e) = hashmap_iterate((h), &(i), (const void**) &(k)); (e); (e) = hashmap_iterate((h), &(i), (const void**) &(k)))
-
-#define HASHMAP_FOREACH_BACKWARDS(e, h, i) \
- for ((i) = ITERATOR_LAST, (e) = hashmap_iterate_backwards((h), &(i), NULL); (e); (e) = hashmap_iterate_backwards((h), &(i), NULL))
diff --git a/src/shared/hwclock.c b/src/shared/hwclock.c
deleted file mode 100644
index f9adf0369e..0000000000
--- a/src/shared/hwclock.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*-*- 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 <assert.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <sys/prctl.h>
-#include <sys/time.h>
-#include <linux/rtc.h>
-
-#include "macro.h"
-#include "util.h"
-#include "log.h"
-#include "strv.h"
-#include "hwclock.h"
-
-static int rtc_open(int flags) {
- int fd;
- DIR *d;
-
- /* First, we try to make use of the /dev/rtc symlink. If that
- * doesn't exist, we open the first RTC which has hctosys=1
- * set. If we don't find any we just take the first RTC that
- * exists at all. */
-
- fd = open("/dev/rtc", flags);
- if (fd >= 0)
- return fd;
-
- d = opendir("/sys/class/rtc");
- if (!d)
- goto fallback;
-
- for (;;) {
- char *p, *v;
- struct dirent *de;
- union dirent_storage buf;
- int r;
-
- r = readdir_r(d, &buf.de, &de);
- if (r != 0)
- goto fallback;
-
- if (!de)
- goto fallback;
-
- if (ignore_file(de->d_name))
- continue;
-
- p = strjoin("/sys/class/rtc/", de->d_name, "/hctosys", NULL);
- if (!p) {
- closedir(d);
- return -ENOMEM;
- }
-
- r = read_one_line_file(p, &v);
- free(p);
-
- if (r < 0)
- continue;
-
- r = parse_boolean(v);
- free(v);
-
- if (r <= 0)
- continue;
-
- p = strappend("/dev/", de->d_name);
- if (!p) {
- closedir(d);
- return -ENOMEM;
- }
-
- fd = open(p, flags);
- free(p);
-
- if (fd >= 0) {
- closedir(d);
- return fd;
- }
- }
-
-fallback:
- if (d)
- closedir(d);
-
- fd = open("/dev/rtc0", flags);
- if (fd < 0)
- return -errno;
-
- return fd;
-}
-
-int hwclock_get_time(struct tm *tm) {
- int fd;
- int err = 0;
-
- assert(tm);
-
- fd = rtc_open(O_RDONLY|O_CLOEXEC);
- if (fd < 0)
- return -errno;
-
- /* This leaves the timezone fields of struct tm
- * uninitialized! */
- if (ioctl(fd, RTC_RD_TIME, tm) < 0)
- err = -errno;
-
- /* We don't know daylight saving, so we reset this in order not
- * to confused mktime(). */
- tm->tm_isdst = -1;
-
- close_nointr_nofail(fd);
-
- return err;
-}
-
-int hwclock_set_time(const struct tm *tm) {
- int fd;
- int err = 0;
-
- assert(tm);
-
- fd = rtc_open(O_RDONLY|O_CLOEXEC);
- if (fd < 0)
- return -errno;
-
- if (ioctl(fd, RTC_SET_TIME, tm) < 0)
- err = -errno;
-
- close_nointr_nofail(fd);
-
- return err;
-}
-
-int hwclock_is_localtime(void) {
- FILE *f;
- bool local = false;
-
- /*
- * The third line of adjtime is "UTC" or "LOCAL" or nothing.
- * # /etc/adjtime
- * 0.0 0 0
- * 0
- * UTC
- */
- f = fopen("/etc/adjtime", "re");
- if (f) {
- char line[LINE_MAX];
- bool b;
-
- b = fgets(line, sizeof(line), f) &&
- fgets(line, sizeof(line), f) &&
- fgets(line, sizeof(line), f);
-
- fclose(f);
-
- if (!b)
- return -EIO;
-
- truncate_nl(line);
- local = streq(line, "LOCAL");
-
- } else if (errno != -ENOENT)
- return -errno;
-
- return local;
-}
-
-int hwclock_set_timezone(int *min) {
- const struct timeval *tv_null = NULL;
- struct timespec ts;
- struct tm *tm;
- int minutesdelta;
- struct timezone tz;
-
- assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
- assert_se(tm = localtime(&ts.tv_sec));
- minutesdelta = tm->tm_gmtoff / 60;
-
- tz.tz_minuteswest = -minutesdelta;
- tz.tz_dsttime = 0; /* DST_NONE*/
-
- /*
- * If the hardware clock does not run in UTC, but in local time:
- * The very first time we set the kernel's timezone, it will warp
- * the clock so that it runs in UTC instead of local time.
- */
- if (settimeofday(tv_null, &tz) < 0)
- return -errno;
- if (min)
- *min = minutesdelta;
- return 0;
-}
-
-int hwclock_reset_timezone(void) {
- const struct timeval *tv_null = NULL;
- struct timezone tz;
-
- tz.tz_minuteswest = 0;
- tz.tz_dsttime = 0; /* DST_NONE*/
-
- /*
- * The very first time we set the kernel's timezone, it will warp
- * the clock. Do a dummy call here, so the time warping is sealed
- * and we set only the time zone with next call.
- */
- if (settimeofday(tv_null, &tz) < 0)
- return -errno;
-
- return 0;
-}
diff --git a/src/shared/hwclock.h b/src/shared/hwclock.h
deleted file mode 100644
index b2bdc78f0c..0000000000
--- a/src/shared/hwclock.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef foohwclockhfoo
-#define foohwclockhfoo
-
-/***
- 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/>.
-***/
-
-int hwclock_is_localtime(void);
-int hwclock_set_timezone(int *min);
-int hwclock_reset_timezone(void);
-int hwclock_get_time(struct tm *tm);
-int hwclock_set_time(const struct tm *tm);
-
-#endif
diff --git a/src/shared/install.c b/src/shared/install.c
deleted file mode 100644
index a9d75f3b7c..0000000000
--- a/src/shared/install.c
+++ /dev/null
@@ -1,2059 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-#include <fnmatch.h>
-
-#include "util.h"
-#include "mkdir.h"
-#include "hashmap.h"
-#include "set.h"
-#include "path-util.h"
-#include "path-lookup.h"
-#include "strv.h"
-#include "unit-name.h"
-#include "install.h"
-#include "conf-parser.h"
-#include "conf-files.h"
-
-typedef struct {
- char *name;
- char *path;
-
- char **aliases;
- char **wanted_by;
- char **required_by;
-} InstallInfo;
-
-typedef struct {
- Hashmap *will_install;
- Hashmap *have_installed;
-} InstallContext;
-
-static int lookup_paths_init_from_scope(LookupPaths *paths, UnitFileScope scope) {
- assert(paths);
- assert(scope >= 0);
- assert(scope < _UNIT_FILE_SCOPE_MAX);
-
- zero(*paths);
-
- return lookup_paths_init(paths,
- scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
- scope == UNIT_FILE_USER,
- NULL, NULL, NULL);
-}
-
-static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
- char *p = NULL;
- int r;
-
- assert(scope >= 0);
- assert(scope < _UNIT_FILE_SCOPE_MAX);
- assert(ret);
-
- switch (scope) {
-
- case UNIT_FILE_SYSTEM:
-
- if (root_dir && runtime)
- asprintf(&p, "%s/run/systemd/system", root_dir);
- else if (runtime)
- p = strdup("/run/systemd/system");
- else if (root_dir)
- asprintf(&p, "%s/%s", root_dir, SYSTEM_CONFIG_UNIT_PATH);
- else
- p = strdup(SYSTEM_CONFIG_UNIT_PATH);
-
- break;
-
- case UNIT_FILE_GLOBAL:
-
- if (root_dir)
- return -EINVAL;
-
- if (runtime)
- p = strdup("/run/systemd/user");
- else
- p = strdup(USER_CONFIG_UNIT_PATH);
- break;
-
- case UNIT_FILE_USER:
-
- if (root_dir || runtime)
- return -EINVAL;
-
- r = user_config_home(&p);
- if (r <= 0)
- return r < 0 ? r : -ENOENT;
-
- break;
-
- default:
- assert_not_reached("Bad scope");
- }
-
- if (!p)
- return -ENOMEM;
-
- *ret = p;
- return 0;
-}
-
-static int add_file_change(
- UnitFileChange **changes,
- unsigned *n_changes,
- UnitFileChangeType type,
- const char *path,
- const char *source) {
-
- UnitFileChange *c;
- unsigned i;
-
- assert(path);
- assert(!changes == !n_changes);
-
- if (!changes)
- return 0;
-
- c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
- if (!c)
- return -ENOMEM;
-
- *changes = c;
- i = *n_changes;
-
- c[i].type = type;
- c[i].path = strdup(path);
- if (!c[i].path)
- return -ENOMEM;
-
- if (source) {
- c[i].source = strdup(source);
- if (!c[i].source) {
- free(c[i].path);
- return -ENOMEM;
- }
- } else
- c[i].source = NULL;
-
- *n_changes = i+1;
- return 0;
-}
-
-static int mark_symlink_for_removal(
- Set **remove_symlinks_to,
- const char *p) {
-
- char *n;
- int r;
-
- assert(p);
-
- r = set_ensure_allocated(remove_symlinks_to, string_hash_func, string_compare_func);
- if (r < 0)
- return r;
-
- n = strdup(p);
- if (!n)
- return -ENOMEM;
-
- path_kill_slashes(n);
-
- r = set_put(*remove_symlinks_to, n);
- if (r < 0) {
- free(n);
- return r == -EEXIST ? 0 : r;
- }
-
- return 0;
-}
-
-static int remove_marked_symlinks_fd(
- Set *remove_symlinks_to,
- int fd,
- const char *path,
- const char *config_path,
- bool *deleted,
- UnitFileChange **changes,
- unsigned *n_changes,
- char** files) {
-
- int r = 0;
- DIR *d;
-
- assert(remove_symlinks_to);
- assert(fd >= 0);
- assert(path);
- assert(config_path);
- assert(deleted);
-
- d = fdopendir(fd);
- if (!d) {
- close_nointr_nofail(fd);
- return -errno;
- }
-
- rewinddir(d);
-
- for (;;) {
- struct dirent *de;
- union dirent_storage buf;
- int k;
-
- k = readdir_r(d, &buf.de, &de);
- if (k != 0) {
- r = -errno;
- break;
- }
-
- if (!de)
- break;
-
- if (ignore_file(de->d_name))
- continue;
-
- dirent_ensure_type(d, de);
-
- if (de->d_type == DT_DIR) {
- int nfd, q;
- char *p;
-
- nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
- if (nfd < 0) {
- if (errno == ENOENT)
- continue;
-
- if (r == 0)
- r = -errno;
- continue;
- }
-
- p = path_make_absolute(de->d_name, path);
- if (!p) {
- close_nointr_nofail(nfd);
- r = -ENOMEM;
- break;
- }
-
- /* This will close nfd, regardless whether it succeeds or not */
- q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, files);
- free(p);
-
- if (r == 0)
- r = q;
-
- } else if (de->d_type == DT_LNK) {
- char *p, *dest;
- int q;
- bool found;
-
- p = path_make_absolute(de->d_name, path);
- if (!p) {
- r = -ENOMEM;
- break;
- }
-
- q = readlink_and_canonicalize(p, &dest);
- if (q < 0) {
- free(p);
-
- if (q == -ENOENT)
- continue;
-
- if (r == 0)
- r = q;
- continue;
- }
-
- found =
- set_get(remove_symlinks_to, dest) ||
- set_get(remove_symlinks_to, path_get_file_name(dest));
-
- if (unit_name_is_instance(p))
- found = found && strv_contains(files, path_get_file_name(p));
-
- if (found) {
-
- if (unlink(p) < 0 && errno != ENOENT) {
-
- if (r == 0)
- r = -errno;
- } else {
- rmdir_parents(p, config_path);
- path_kill_slashes(p);
-
- add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
-
- if (!set_get(remove_symlinks_to, p)) {
-
- q = mark_symlink_for_removal(&remove_symlinks_to, p);
- if (q < 0) {
- if (r == 0)
- r = q;
- } else
- *deleted = true;
- }
- }
- }
-
- free(p);
- free(dest);
- }
- }
-
- closedir(d);
-
- return r;
-}
-
-static int remove_marked_symlinks(
- Set *remove_symlinks_to,
- const char *config_path,
- UnitFileChange **changes,
- unsigned *n_changes,
- char** files) {
-
- int fd, r = 0;
- bool deleted;
-
- assert(config_path);
-
- if (set_size(remove_symlinks_to) <= 0)
- return 0;
-
- fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
- if (fd < 0)
- return -errno;
-
- do {
- int q, cfd;
- deleted = false;
-
- cfd = dup(fd);
- if (cfd < 0) {
- r = -errno;
- break;
- }
-
- /* This takes possession of cfd and closes it */
- q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, files);
- if (r == 0)
- r = q;
- } while (deleted);
-
- close_nointr_nofail(fd);
-
- return r;
-}
-
-static int find_symlinks_fd(
- const char *name,
- int fd,
- const char *path,
- const char *config_path,
- bool *same_name_link) {
-
- int r = 0;
- DIR *d;
-
- assert(name);
- assert(fd >= 0);
- assert(path);
- assert(config_path);
- assert(same_name_link);
-
- d = fdopendir(fd);
- if (!d) {
- close_nointr_nofail(fd);
- return -errno;
- }
-
- for (;;) {
- int k;
- struct dirent *de;
- union dirent_storage buf;
-
- k = readdir_r(d, &buf.de, &de);
- if (k != 0) {
- r = -errno;
- break;
- }
-
- if (!de)
- break;
-
- if (ignore_file(de->d_name))
- continue;
-
- dirent_ensure_type(d, de);
-
- if (de->d_type == DT_DIR) {
- int nfd, q;
- char *p;
-
- nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
- if (nfd < 0) {
- if (errno == ENOENT)
- continue;
-
- if (r == 0)
- r = -errno;
- continue;
- }
-
- p = path_make_absolute(de->d_name, path);
- if (!p) {
- close_nointr_nofail(nfd);
- r = -ENOMEM;
- break;
- }
-
- /* This will close nfd, regardless whether it succeeds or not */
- q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
- free(p);
-
- if (q > 0) {
- r = 1;
- break;
- }
-
- if (r == 0)
- r = q;
-
- } else if (de->d_type == DT_LNK) {
- char *p, *dest;
- bool found_path, found_dest, b = false;
- int q;
-
- /* Acquire symlink name */
- p = path_make_absolute(de->d_name, path);
- if (!p) {
- r = -ENOMEM;
- break;
- }
-
- /* Acquire symlink destination */
- q = readlink_and_canonicalize(p, &dest);
- if (q < 0) {
- free(p);
-
- if (q == -ENOENT)
- continue;
-
- if (r == 0)
- r = q;
- continue;
- }
-
- /* Check if the symlink itself matches what we
- * are looking for */
- if (path_is_absolute(name))
- found_path = path_equal(p, name);
- else
- found_path = streq(de->d_name, name);
-
- /* Check if what the symlink points to
- * matches what we are looking for */
- if (path_is_absolute(name))
- found_dest = path_equal(dest, name);
- else
- found_dest = streq(path_get_file_name(dest), name);
-
- free(dest);
-
- if (found_path && found_dest) {
- char *t;
-
- /* Filter out same name links in the main
- * config path */
- t = path_make_absolute(name, config_path);
- if (!t) {
- free(p);
- r = -ENOMEM;
- break;
- }
-
- b = path_equal(t, p);
- free(t);
- }
-
- free(p);
-
- if (b)
- *same_name_link = true;
- else if (found_path || found_dest) {
- r = 1;
- break;
- }
- }
- }
-
- closedir(d);
-
- return r;
-}
-
-static int find_symlinks(
- const char *name,
- const char *config_path,
- bool *same_name_link) {
-
- int fd;
-
- assert(name);
- assert(config_path);
- assert(same_name_link);
-
- fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
- if (fd < 0) {
- if (errno == ENOENT)
- return 0;
- return -errno;
- }
-
- /* This takes possession of fd and closes it */
- return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
-}
-
-static int find_symlinks_in_scope(
- UnitFileScope scope,
- const char *root_dir,
- const char *name,
- UnitFileState *state) {
-
- int r;
- char _cleanup_free_ *path = NULL;
- bool same_name_link_runtime = false, same_name_link = false;
-
- assert(scope >= 0);
- assert(scope < _UNIT_FILE_SCOPE_MAX);
- assert(name);
-
- if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
-
- /* First look in runtime config path */
- r = get_config_path(scope, true, root_dir, &path);
- if (r < 0)
- return r;
-
- r = find_symlinks(name, path, &same_name_link_runtime);
- if (r < 0)
- return r;
- else if (r > 0) {
- *state = UNIT_FILE_ENABLED_RUNTIME;
- return r;
- }
- }
-
- /* Then look in the normal config path */
- r = get_config_path(scope, false, root_dir, &path);
- if (r < 0)
- return r;
-
- r = find_symlinks(name, path, &same_name_link);
- if (r < 0)
- return r;
- else if (r > 0) {
- *state = UNIT_FILE_ENABLED;
- return r;
- }
-
- /* Hmm, we didn't find it, but maybe we found the same name
- * link? */
- if (same_name_link_runtime) {
- *state = UNIT_FILE_LINKED_RUNTIME;
- return 1;
- } else if (same_name_link) {
- *state = UNIT_FILE_LINKED;
- return 1;
- }
-
- return 0;
-}
-
-int unit_file_mask(
- UnitFileScope scope,
- bool runtime,
- const char *root_dir,
- char *files[],
- bool force,
- UnitFileChange **changes,
- unsigned *n_changes) {
-
- char **i;
- char _cleanup_free_ *prefix;
- int r;
-
- assert(scope >= 0);
- assert(scope < _UNIT_FILE_SCOPE_MAX);
-
- r = get_config_path(scope, runtime, root_dir, &prefix);
- if (r < 0)
- return r;
-
- STRV_FOREACH(i, files) {
- char _cleanup_free_ *path = NULL;
-
- if (!unit_name_is_valid(*i, true)) {
- if (r == 0)
- r = -EINVAL;
- continue;
- }
-
- path = path_make_absolute(*i, prefix);
- if (!path) {
- r = -ENOMEM;
- break;
- }
-
- if (symlink("/dev/null", path) >= 0) {
- add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
-
- continue;
- }
-
- if (errno == EEXIST) {
-
- if (null_or_empty_path(path) > 0)
- continue;
-
- if (force) {
- unlink(path);
-
- if (symlink("/dev/null", path) >= 0) {
-
- add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
- add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
-
- continue;
- }
- }
-
- if (r == 0)
- r = -EEXIST;
- } else {
- if (r == 0)
- r = -errno;
- }
- }
-
- return r;
-}
-
-int unit_file_unmask(
- UnitFileScope scope,
- bool runtime,
- const char *root_dir,
- char *files[],
- UnitFileChange **changes,
- unsigned *n_changes) {
-
- char **i, *config_path = NULL;
- int r, q;
- Set *remove_symlinks_to = NULL;
-
- assert(scope >= 0);
- assert(scope < _UNIT_FILE_SCOPE_MAX);
-
- r = get_config_path(scope, runtime, root_dir, &config_path);
- if (r < 0)
- goto finish;
-
- STRV_FOREACH(i, files) {
- char *path;
-
- if (!unit_name_is_valid(*i, true)) {
- if (r == 0)
- r = -EINVAL;
- continue;
- }
-
- path = path_make_absolute(*i, config_path);
- if (!path) {
- r = -ENOMEM;
- break;
- }
-
- q = null_or_empty_path(path);
- if (q > 0) {
- if (unlink(path) >= 0) {
- mark_symlink_for_removal(&remove_symlinks_to, path);
- add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
-
- free(path);
- continue;
- }
-
- q = -errno;
- }
-
- if (q != -ENOENT && r == 0)
- r = q;
-
- free(path);
- }
-
-
-finish:
- q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
- if (r == 0)
- r = q;
-
- set_free_free(remove_symlinks_to);
- free(config_path);
-
- return r;
-}
-
-int unit_file_link(
- UnitFileScope scope,
- bool runtime,
- const char *root_dir,
- char *files[],
- bool force,
- UnitFileChange **changes,
- unsigned *n_changes) {
-
- LookupPaths paths;
- char **i, *config_path = NULL;
- int r, q;
-
- assert(scope >= 0);
- assert(scope < _UNIT_FILE_SCOPE_MAX);
-
- zero(paths);
-
- r = lookup_paths_init_from_scope(&paths, scope);
- if (r < 0)
- return r;
-
- r = get_config_path(scope, runtime, root_dir, &config_path);
- if (r < 0)
- goto finish;
-
- STRV_FOREACH(i, files) {
- char *path, *fn;
- struct stat st;
-
- fn = path_get_file_name(*i);
-
- if (!path_is_absolute(*i) ||
- !unit_name_is_valid(fn, true)) {
- if (r == 0)
- r = -EINVAL;
- continue;
- }
-
- if (lstat(*i, &st) < 0) {
- if (r == 0)
- r = -errno;
- continue;
- }
-
- if (!S_ISREG(st.st_mode)) {
- r = -ENOENT;
- continue;
- }
-
- q = in_search_path(*i, paths.unit_path);
- if (q < 0) {
- r = q;
- break;
- }
-
- if (q > 0)
- continue;
-
- path = path_make_absolute(fn, config_path);
- if (!path) {
- r = -ENOMEM;
- break;
- }
-
- if (symlink(*i, path) >= 0) {
- add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
-
- free(path);
- continue;
- }
-
- if (errno == EEXIST) {
- char *dest = NULL;
-
- q = readlink_and_make_absolute(path, &dest);
-
- if (q < 0 && errno != ENOENT) {
- free(path);
-
- if (r == 0)
- r = q;
-
- continue;
- }
-
- if (q >= 0 && path_equal(dest, *i)) {
- free(dest);
- free(path);
- continue;
- }
-
- free(dest);
-
- if (force) {
- unlink(path);
-
- if (symlink(*i, path) >= 0) {
-
- add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
- add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
-
- free(path);
- continue;
- }
- }
-
- if (r == 0)
- r = -EEXIST;
- } else {
- if (r == 0)
- r = -errno;
- }
-
- free(path);
- }
-
- finish:
- lookup_paths_free(&paths);
- free(config_path);
-
- return r;
-}
-
-void unit_file_list_free(Hashmap *h) {
- UnitFileList *i;
-
- while ((i = hashmap_steal_first(h))) {
- free(i->path);
- free(i);
- }
-
- hashmap_free(h);
-}
-
-void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
- unsigned i;
-
- assert(changes || n_changes == 0);
-
- if (!changes)
- return;
-
- for (i = 0; i < n_changes; i++) {
- free(changes[i].path);
- free(changes[i].source);
- }
-
- free(changes);
-}
-
-static void install_info_free(InstallInfo *i) {
- assert(i);
-
- free(i->name);
- free(i->path);
- strv_free(i->aliases);
- strv_free(i->wanted_by);
- strv_free(i->required_by);
- free(i);
-}
-
-static void install_info_hashmap_free(Hashmap *m) {
- InstallInfo *i;
-
- if (!m)
- return;
-
- while ((i = hashmap_steal_first(m)))
- install_info_free(i);
-
- hashmap_free(m);
-}
-
-static void install_context_done(InstallContext *c) {
- assert(c);
-
- install_info_hashmap_free(c->will_install);
- install_info_hashmap_free(c->have_installed);
-
- c->will_install = c->have_installed = NULL;
-}
-
-static int install_info_add(
- InstallContext *c,
- const char *name,
- const char *path) {
- InstallInfo *i = NULL;
- int r;
-
- assert(c);
- assert(name || path);
-
- if (!name)
- name = path_get_file_name(path);
-
- if (!unit_name_is_valid(name, true))
- return -EINVAL;
-
- if (hashmap_get(c->have_installed, name) ||
- hashmap_get(c->will_install, name))
- return 0;
-
- r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func);
- if (r < 0)
- return r;
-
- i = new0(InstallInfo, 1);
- if (!i)
- return -ENOMEM;
-
- i->name = strdup(name);
- if (!i->name) {
- r = -ENOMEM;
- goto fail;
- }
-
- if (path) {
- i->path = strdup(path);
- if (!i->path) {
- r = -ENOMEM;
- goto fail;
- }
- }
-
- r = hashmap_put(c->will_install, i->name, i);
- if (r < 0)
- goto fail;
-
- return 0;
-
-fail:
- if (i)
- install_info_free(i);
-
- return r;
-}
-
-static int install_info_add_auto(
- InstallContext *c,
- const char *name_or_path) {
-
- assert(c);
- assert(name_or_path);
-
- if (path_is_absolute(name_or_path))
- return install_info_add(c, NULL, name_or_path);
- else
- return install_info_add(c, name_or_path, NULL);
-}
-
-static int config_parse_also(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- char *w;
- size_t l;
- char *state;
- InstallContext *c = data;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- FOREACH_WORD_QUOTED(w, l, rvalue, state) {
- char *n;
- int r;
-
- n = strndup(w, l);
- if (!n)
- return -ENOMEM;
-
- r = install_info_add(c, n, NULL);
- if (r < 0) {
- free(n);
- return r;
- }
-
- free(n);
- }
-
- return 0;
-}
-
-static int unit_file_load(
- InstallContext *c,
- InstallInfo *info,
- const char *path,
- bool allow_symlink) {
-
- const ConfigTableItem items[] = {
- { "Install", "Alias", config_parse_strv, 0, &info->aliases },
- { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
- { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
- { "Install", "Also", config_parse_also, 0, c },
- { NULL, NULL, NULL, 0, NULL }
- };
-
- int fd;
- FILE *f;
- int r;
-
- assert(c);
- assert(info);
- assert(path);
-
- fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
- if (fd < 0)
- return -errno;
-
- f = fdopen(fd, "re");
- if (!f) {
- close_nointr_nofail(fd);
- return -ENOMEM;
- }
-
- r = config_parse(path, f, NULL, config_item_table_lookup, (void*) items, true, info);
- fclose(f);
- if (r < 0)
- return r;
-
- return
- strv_length(info->aliases) +
- strv_length(info->wanted_by) +
- strv_length(info->required_by);
-}
-
-static int unit_file_search(
- InstallContext *c,
- InstallInfo *info,
- LookupPaths *paths,
- const char *root_dir,
- bool allow_symlink) {
-
- char **p;
- int r;
-
- assert(c);
- assert(info);
- assert(paths);
-
- if (info->path)
- return unit_file_load(c, info, info->path, allow_symlink);
-
- assert(info->name);
-
- STRV_FOREACH(p, paths->unit_path) {
- char *path = NULL;
-
- if (isempty(root_dir))
- asprintf(&path, "%s/%s", *p, info->name);
- else
- asprintf(&path, "%s/%s/%s", root_dir, *p, info->name);
-
- if (!path)
- return -ENOMEM;
-
- r = unit_file_load(c, info, path, allow_symlink);
-
- if (r >= 0)
- info->path = path;
- else {
- if (r == -ENOENT && unit_name_is_instance(info->name)) {
- /* unit file doesn't exist, however instance enablement was request */
- /* we will check if it is possible to load template unit file */
- char *template = NULL,
- *template_path = NULL,
- *template_dir = NULL;
-
- template = unit_name_template(info->name);
- if (!template) {
- free(path);
- return -ENOMEM;
- }
-
- /* we will reuse path variable since we don't need it anymore */
- template_dir = path;
- *(strrchr(path, '/') + 1) = '\0';
-
- template_path = strjoin(template_dir, template, NULL);
- if (!template_path) {
- free(path);
- free(template);
- return -ENOMEM;
- }
-
- /* let's try to load template unit */
- r = unit_file_load(c, info, template_path, allow_symlink);
- if (r >= 0) {
- info->path = strdup(template_path);
- if (!info->path) {
- free(path);
- free(template);
- free(template_path);
- return -ENOMEM;
- }
- }
-
- free(template);
- free(template_path);
- }
- free(path);
- }
-
- if (r != -ENOENT && r != -ELOOP)
- return r;
- }
-
- return -ENOENT;
-}
-
-static int unit_file_can_install(
- LookupPaths *paths,
- const char *root_dir,
- const char *name,
- bool allow_symlink) {
-
- InstallContext c;
- InstallInfo *i;
- int r;
-
- assert(paths);
- assert(name);
-
- zero(c);
-
- r = install_info_add_auto(&c, name);
- if (r < 0)
- return r;
-
- assert_se(i = hashmap_first(c.will_install));
-
- r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
-
- if (r >= 0)
- r =
- strv_length(i->aliases) +
- strv_length(i->wanted_by) +
- strv_length(i->required_by);
-
- install_context_done(&c);
-
- return r;
-}
-
-static int create_symlink(
- const char *old_path,
- const char *new_path,
- bool force,
- UnitFileChange **changes,
- unsigned *n_changes) {
-
- char *dest;
- int r;
-
- assert(old_path);
- assert(new_path);
-
- mkdir_parents_label(new_path, 0755);
-
- if (symlink(old_path, new_path) >= 0) {
- add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
- return 0;
- }
-
- if (errno != EEXIST)
- return -errno;
-
- r = readlink_and_make_absolute(new_path, &dest);
- if (r < 0)
- return r;
-
- if (path_equal(dest, old_path)) {
- free(dest);
- return 0;
- }
-
- free(dest);
-
- if (!force)
- return -EEXIST;
-
- unlink(new_path);
-
- if (symlink(old_path, new_path) >= 0) {
- add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
- add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
- return 0;
- }
-
- return -errno;
-}
-
-static int install_info_symlink_alias(
- InstallInfo *i,
- const char *config_path,
- bool force,
- UnitFileChange **changes,
- unsigned *n_changes) {
-
- char **s;
- int r = 0, q;
-
- assert(i);
- assert(config_path);
-
- STRV_FOREACH(s, i->aliases) {
- char *alias_path;
-
- alias_path = path_make_absolute(*s, config_path);
-
- if (!alias_path)
- return -ENOMEM;
-
- q = create_symlink(i->path, alias_path, force, changes, n_changes);
- free(alias_path);
-
- if (r == 0)
- r = q;
- }
-
- return r;
-}
-
-static int install_info_symlink_wants(
- InstallInfo *i,
- const char *config_path,
- bool force,
- UnitFileChange **changes,
- unsigned *n_changes) {
-
- char **s;
- int r = 0, q;
-
- assert(i);
- assert(config_path);
-
- STRV_FOREACH(s, i->wanted_by) {
- char *path;
-
- if (!unit_name_is_valid(*s, true)) {
- r = -EINVAL;
- continue;
- }
-
- if (asprintf(&path, "%s/%s.wants/%s", config_path, *s, i->name) < 0)
- return -ENOMEM;
-
- q = create_symlink(i->path, path, force, changes, n_changes);
- free(path);
-
- if (r == 0)
- r = q;
- }
-
- return r;
-}
-
-static int install_info_symlink_requires(
- InstallInfo *i,
- const char *config_path,
- bool force,
- UnitFileChange **changes,
- unsigned *n_changes) {
-
- char **s;
- int r = 0, q;
-
- assert(i);
- assert(config_path);
-
- STRV_FOREACH(s, i->required_by) {
- char *path;
-
- if (!unit_name_is_valid(*s, true)) {
- r = -EINVAL;
- continue;
- }
-
- if (asprintf(&path, "%s/%s.requires/%s", config_path, *s, i->name) < 0)
- return -ENOMEM;
-
- q = create_symlink(i->path, path, force, changes, n_changes);
- free(path);
-
- if (r == 0)
- r = q;
- }
-
- return r;
-}
-
-static int install_info_symlink_link(
- InstallInfo *i,
- LookupPaths *paths,
- const char *config_path,
- bool force,
- UnitFileChange **changes,
- unsigned *n_changes) {
-
- int r;
- char *path;
-
- assert(i);
- assert(paths);
- assert(config_path);
- assert(i->path);
-
- r = in_search_path(i->path, paths->unit_path);
- if (r != 0)
- return r;
-
- if (asprintf(&path, "%s/%s", config_path, i->name) < 0)
- return -ENOMEM;
-
- r = create_symlink(i->path, path, force, changes, n_changes);
- free(path);
-
- return r;
-}
-
-static int install_info_apply(
- InstallInfo *i,
- LookupPaths *paths,
- const char *config_path,
- bool force,
- UnitFileChange **changes,
- unsigned *n_changes) {
-
- int r, q;
-
- assert(i);
- assert(paths);
- assert(config_path);
-
- r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
-
- q = install_info_symlink_wants(i, config_path, force, changes, n_changes);
- if (r == 0)
- r = q;
-
- q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
- if (r == 0)
- r = q;
-
- q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
- if (r == 0)
- r = q;
-
- return r;
-}
-
-static int install_context_apply(
- InstallContext *c,
- LookupPaths *paths,
- const char *config_path,
- const char *root_dir,
- bool force,
- UnitFileChange **changes,
- unsigned *n_changes) {
-
- InstallInfo *i;
- int r = 0, q;
-
- assert(c);
- assert(paths);
- assert(config_path);
-
- while ((i = hashmap_first(c->will_install))) {
-
- q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
- if (q < 0)
- return q;
-
- assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
-
- q = unit_file_search(c, i, paths, root_dir, false);
- if (q < 0) {
- if (r >= 0)
- r = q;
-
- return r;
- } else if (r >= 0)
- r += q;
-
- q = install_info_apply(i, paths, config_path, force, changes, n_changes);
- if (r >= 0 && q < 0)
- r = q;
- }
-
- return r;
-}
-
-static int install_context_mark_for_removal(
- InstallContext *c,
- LookupPaths *paths,
- Set **remove_symlinks_to,
- const char *config_path,
- const char *root_dir) {
-
- InstallInfo *i;
- int r = 0, q;
-
- assert(c);
- assert(paths);
- assert(config_path);
-
- /* Marks all items for removal */
-
- while ((i = hashmap_first(c->will_install))) {
-
- q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
- if (q < 0)
- return q;
-
- assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
-
- q = unit_file_search(c, i, paths, root_dir, false);
- if (q < 0) {
- if (r >= 0)
- r = q;
-
- return r;
- } else if (r >= 0)
- r += q;
-
- if (unit_name_is_instance(i->name)) {
- char *unit_file = NULL;
-
- unit_file = path_get_file_name(i->path);
-
- if (unit_name_is_instance(unit_file))
- /* unit file named as instance exists, thus all symlinks pointing to it, will be removed */
- q = mark_symlink_for_removal(remove_symlinks_to, i->name);
- else
- /* does not exist, thus we will mark for removal symlinks to template unit file */
- q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
- } else
- q = mark_symlink_for_removal(remove_symlinks_to, i->name);
-
- if (r >= 0 && q < 0)
- r = q;
- }
-
- return r;
-}
-
-int unit_file_enable(
- UnitFileScope scope,
- bool runtime,
- const char *root_dir,
- char *files[],
- bool force,
- UnitFileChange **changes,
- unsigned *n_changes) {
-
- LookupPaths paths;
- InstallContext c;
- char **i, *config_path = NULL;
- int r;
-
- assert(scope >= 0);
- assert(scope < _UNIT_FILE_SCOPE_MAX);
-
- zero(paths);
- zero(c);
-
- r = lookup_paths_init_from_scope(&paths, scope);
- if (r < 0)
- return r;
-
- r = get_config_path(scope, runtime, root_dir, &config_path);
- if (r < 0)
- goto finish;
-
- STRV_FOREACH(i, files) {
- r = install_info_add_auto(&c, *i);
- if (r < 0)
- goto finish;
- }
-
- /* This will return the number of symlink rules that were
- supposed to be created, not the ones actually created. This is
- useful to determine whether the passed files had any
- installation data at all. */
- r = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
-
-finish:
- install_context_done(&c);
- lookup_paths_free(&paths);
- free(config_path);
-
- return r;
-}
-
-int unit_file_disable(
- UnitFileScope scope,
- bool runtime,
- const char *root_dir,
- char *files[],
- UnitFileChange **changes,
- unsigned *n_changes) {
-
- LookupPaths paths;
- InstallContext c;
- char **i, *config_path = NULL;
- Set *remove_symlinks_to = NULL;
- int r, q;
-
- assert(scope >= 0);
- assert(scope < _UNIT_FILE_SCOPE_MAX);
-
- zero(paths);
- zero(c);
-
- r = lookup_paths_init_from_scope(&paths, scope);
- if (r < 0)
- return r;
-
- r = get_config_path(scope, runtime, root_dir, &config_path);
- if (r < 0)
- goto finish;
-
- STRV_FOREACH(i, files) {
- r = install_info_add_auto(&c, *i);
- if (r < 0)
- goto finish;
- }
-
- r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
-
- q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
- if (r == 0)
- r = q;
-
-finish:
- install_context_done(&c);
- lookup_paths_free(&paths);
- set_free_free(remove_symlinks_to);
- free(config_path);
-
- return r;
-}
-
-int unit_file_reenable(
- UnitFileScope scope,
- bool runtime,
- const char *root_dir,
- char *files[],
- bool force,
- UnitFileChange **changes,
- unsigned *n_changes) {
-
- LookupPaths paths;
- InstallContext c;
- char **i, *config_path = NULL;
- Set *remove_symlinks_to = NULL;
- int r, q;
-
- assert(scope >= 0);
- assert(scope < _UNIT_FILE_SCOPE_MAX);
-
- zero(paths);
- zero(c);
-
- r = lookup_paths_init_from_scope(&paths, scope);
- if (r < 0)
- return r;
-
- r = get_config_path(scope, runtime, root_dir, &config_path);
- if (r < 0)
- goto finish;
-
- STRV_FOREACH(i, files) {
- r = mark_symlink_for_removal(&remove_symlinks_to, *i);
- if (r < 0)
- goto finish;
-
- r = install_info_add_auto(&c, *i);
- if (r < 0)
- goto finish;
- }
-
- r = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
-
- /* Returns number of symlinks that where supposed to be installed. */
- q = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
- if (r == 0)
- r = q;
-
-finish:
- lookup_paths_free(&paths);
- install_context_done(&c);
- set_free_free(remove_symlinks_to);
- free(config_path);
-
- return r;
-}
-
-UnitFileState unit_file_get_state(
- UnitFileScope scope,
- const char *root_dir,
- const char *name) {
-
- LookupPaths paths;
- UnitFileState state = _UNIT_FILE_STATE_INVALID;
- char **i, *path = NULL;
- int r;
-
- assert(scope >= 0);
- assert(scope < _UNIT_FILE_SCOPE_MAX);
- assert(name);
-
- zero(paths);
-
- if (root_dir && scope != UNIT_FILE_SYSTEM)
- return -EINVAL;
-
- if (!unit_name_is_valid(name, true))
- return -EINVAL;
-
- r = lookup_paths_init_from_scope(&paths, scope);
- if (r < 0)
- return r;
-
- STRV_FOREACH(i, paths.unit_path) {
- struct stat st;
-
- free(path);
- path = NULL;
-
- if (root_dir)
- asprintf(&path, "%s/%s/%s", root_dir, *i, name);
- else
- asprintf(&path, "%s/%s", *i, name);
-
- if (!path) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (lstat(path, &st) < 0) {
- r = -errno;
- if (errno == ENOENT)
- continue;
-
- goto finish;
- }
-
- if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) {
- r = -ENOENT;
- goto finish;
- }
-
- r = null_or_empty_path(path);
- if (r < 0 && r != -ENOENT)
- goto finish;
- else if (r > 0) {
- state = path_startswith(*i, "/run") ?
- UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
- r = 0;
- goto finish;
- }
-
- r = find_symlinks_in_scope(scope, root_dir, name, &state);
- if (r < 0) {
- goto finish;
- } else if (r > 0) {
- r = 0;
- goto finish;
- }
-
- r = unit_file_can_install(&paths, root_dir, path, true);
- if (r < 0 && errno != -ENOENT)
- goto finish;
- else if (r > 0) {
- state = UNIT_FILE_DISABLED;
- r = 0;
- goto finish;
- } else if (r == 0) {
- state = UNIT_FILE_STATIC;
- r = 0;
- goto finish;
- }
- }
-
-finish:
- lookup_paths_free(&paths);
- free(path);
-
- return r < 0 ? r : state;
-}
-
-int unit_file_query_preset(UnitFileScope scope, const char *name) {
- char **files, **i;
- int r;
-
- assert(scope >= 0);
- assert(scope < _UNIT_FILE_SCOPE_MAX);
- assert(name);
-
- if (scope == UNIT_FILE_SYSTEM)
- r = conf_files_list(&files, ".preset",
- "/etc/systemd/system-preset",
- "/usr/local/lib/systemd/system-preset",
- "/usr/lib/systemd/system-preset",
-#ifdef HAVE_SPLIT_USR
- "/lib/systemd/system-preset",
-#endif
- NULL);
- else if (scope == UNIT_FILE_GLOBAL)
- r = conf_files_list(&files, ".preset",
- "/etc/systemd/user-preset",
- "/usr/local/lib/systemd/user-preset",
- "/usr/lib/systemd/user-preset",
- NULL);
- else
- return 1;
-
- if (r < 0)
- return r;
-
- STRV_FOREACH(i, files) {
- FILE *f;
-
- f = fopen(*i, "re");
- if (!f) {
- if (errno == ENOENT)
- continue;
-
- r = -errno;
- goto finish;
- }
-
- for (;;) {
- char line[LINE_MAX], *l;
-
- if (!fgets(line, sizeof(line), f))
- break;
-
- l = strstrip(line);
- if (!*l)
- continue;
-
- if (strchr(COMMENTS, *l))
- continue;
-
- if (first_word(l, "enable")) {
- l += 6;
- l += strspn(l, WHITESPACE);
-
- if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
- r = 1;
- fclose(f);
- goto finish;
- }
- } else if (first_word(l, "disable")) {
- l += 7;
- l += strspn(l, WHITESPACE);
-
- if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
- r = 0;
- fclose(f);
- goto finish;
- }
- } else
- log_debug("Couldn't parse line '%s'", l);
- }
-
- fclose(f);
- }
-
- /* Default is "enable" */
- r = 1;
-
-finish:
- strv_free(files);
-
- return r;
-}
-
-int unit_file_preset(
- UnitFileScope scope,
- bool runtime,
- const char *root_dir,
- char *files[],
- bool force,
- UnitFileChange **changes,
- unsigned *n_changes) {
-
- LookupPaths paths;
- InstallContext plus, minus;
- char **i, *config_path = NULL;
- Set *remove_symlinks_to = NULL;
- int r, q;
-
- assert(scope >= 0);
- assert(scope < _UNIT_FILE_SCOPE_MAX);
-
- zero(paths);
- zero(plus);
- zero(minus);
-
- r = lookup_paths_init_from_scope(&paths, scope);
- if (r < 0)
- return r;
-
- r = get_config_path(scope, runtime, root_dir, &config_path);
- if (r < 0)
- goto finish;
-
- STRV_FOREACH(i, files) {
-
- if (!unit_name_is_valid(*i, true)) {
- r = -EINVAL;
- goto finish;
- }
-
- r = unit_file_query_preset(scope, *i);
- if (r < 0)
- goto finish;
-
- if (r)
- r = install_info_add_auto(&plus, *i);
- else
- r = install_info_add_auto(&minus, *i);
-
- if (r < 0)
- goto finish;
- }
-
- r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
-
- q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
- if (r == 0)
- r = q;
-
- /* Returns number of symlinks that where supposed to be installed. */
- q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
- if (r == 0)
- r = q;
-
-finish:
- lookup_paths_free(&paths);
- install_context_done(&plus);
- install_context_done(&minus);
- set_free_free(remove_symlinks_to);
- free(config_path);
-
- return r;
-}
-
-int unit_file_get_list(
- UnitFileScope scope,
- const char *root_dir,
- Hashmap *h) {
-
- LookupPaths paths;
- char **i, *buf = NULL;
- DIR *d = NULL;
- int r;
-
- assert(scope >= 0);
- assert(scope < _UNIT_FILE_SCOPE_MAX);
- assert(h);
-
- zero(paths);
-
- if (root_dir && scope != UNIT_FILE_SYSTEM)
- return -EINVAL;
-
- r = lookup_paths_init_from_scope(&paths, scope);
- if (r < 0)
- return r;
-
- STRV_FOREACH(i, paths.unit_path) {
- const char *units_dir;
-
- free(buf);
- buf = NULL;
-
- if (root_dir) {
- if (asprintf(&buf, "%s/%s", root_dir, *i) < 0) {
- r = -ENOMEM;
- goto finish;
- }
- units_dir = buf;
- } else
- units_dir = *i;
-
- if (d)
- closedir(d);
-
- d = opendir(units_dir);
- if (!d) {
- if (errno == ENOENT)
- continue;
-
- r = -errno;
- goto finish;
- }
-
- for (;;) {
- struct dirent *de;
- union dirent_storage buffer;
- UnitFileList *f;
-
- r = readdir_r(d, &buffer.de, &de);
- if (r != 0) {
- r = -r;
- goto finish;
- }
-
- if (!de)
- break;
-
- if (ignore_file(de->d_name))
- continue;
-
- if (!unit_name_is_valid(de->d_name, true))
- continue;
-
- if (hashmap_get(h, de->d_name))
- continue;
-
- r = dirent_ensure_type(d, de);
- if (r < 0) {
- if (r == -ENOENT)
- continue;
-
- goto finish;
- }
-
- if (de->d_type != DT_LNK && de->d_type != DT_REG)
- continue;
-
- f = new0(UnitFileList, 1);
- if (!f) {
- r = -ENOMEM;
- goto finish;
- }
-
- f->path = path_make_absolute(de->d_name, units_dir);
- if (!f->path) {
- free(f);
- r = -ENOMEM;
- goto finish;
- }
-
- r = null_or_empty_path(f->path);
- if (r < 0 && r != -ENOENT) {
- free(f->path);
- free(f);
- goto finish;
- } else if (r > 0) {
- f->state =
- path_startswith(*i, "/run") ?
- UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
- goto found;
- }
-
- r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
- if (r < 0) {
- free(f->path);
- free(f);
- goto finish;
- } else if (r > 0) {
- f->state = UNIT_FILE_ENABLED;
- goto found;
- }
-
- r = unit_file_can_install(&paths, root_dir, f->path, true);
- if (r == -EINVAL || /* Invalid setting? */
- r == -EBADMSG || /* Invalid format? */
- r == -ENOENT /* Included file not found? */)
- f->state = UNIT_FILE_INVALID;
- else if (r < 0) {
- free(f->path);
- free(f);
- goto finish;
- } else if (r > 0)
- f->state = UNIT_FILE_DISABLED;
- else
- f->state = UNIT_FILE_STATIC;
-
- found:
- r = hashmap_put(h, path_get_file_name(f->path), f);
- if (r < 0) {
- free(f->path);
- free(f);
- goto finish;
- }
- }
- }
-
-finish:
- lookup_paths_free(&paths);
- free(buf);
-
- if (d)
- closedir(d);
-
- return r;
-}
-
-static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
- [UNIT_FILE_ENABLED] = "enabled",
- [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
- [UNIT_FILE_LINKED] = "linked",
- [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
- [UNIT_FILE_MASKED] = "masked",
- [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
- [UNIT_FILE_STATIC] = "static",
- [UNIT_FILE_DISABLED] = "disabled",
- [UNIT_FILE_INVALID] = "invalid",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
-
-static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
- [UNIT_FILE_SYMLINK] = "symlink",
- [UNIT_FILE_UNLINK] = "unlink",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
diff --git a/src/shared/install.h b/src/shared/install.h
deleted file mode 100644
index 55249914b1..0000000000
--- a/src/shared/install.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 "hashmap.h"
-
-typedef enum UnitFileScope {
- UNIT_FILE_SYSTEM,
- UNIT_FILE_GLOBAL,
- UNIT_FILE_USER,
- _UNIT_FILE_SCOPE_MAX,
- _UNIT_FILE_SCOPE_INVALID = -1
-} UnitFileScope;
-
-typedef enum UnitFileState {
- UNIT_FILE_ENABLED,
- UNIT_FILE_ENABLED_RUNTIME,
- UNIT_FILE_LINKED,
- UNIT_FILE_LINKED_RUNTIME,
- UNIT_FILE_MASKED,
- UNIT_FILE_MASKED_RUNTIME,
- UNIT_FILE_STATIC,
- UNIT_FILE_DISABLED,
- UNIT_FILE_INVALID,
- _UNIT_FILE_STATE_MAX,
- _UNIT_FILE_STATE_INVALID = -1
-} UnitFileState;
-
-typedef enum UnitFileChangeType {
- UNIT_FILE_SYMLINK,
- UNIT_FILE_UNLINK,
- _UNIT_FILE_CHANGE_TYPE_MAX,
- _UNIT_FILE_CHANGE_TYPE_INVALID = -1
-} UnitFileChangeType;
-
-typedef struct UnitFileChange {
- UnitFileChangeType type;
- char *path;
- char *source;
-} UnitFileChange;
-
-typedef struct UnitFileList {
- char *path;
- UnitFileState state;
-} UnitFileList;
-
-int unit_file_enable(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);
-int unit_file_disable(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes);
-int unit_file_reenable(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);
-int unit_file_link(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);
-int unit_file_preset(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);
-int unit_file_mask(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);
-int unit_file_unmask(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes);
-
-UnitFileState unit_file_get_state(UnitFileScope scope, const char *root_dir, const char *filename);
-
-int unit_file_get_list(UnitFileScope scope, const char *root_dir, Hashmap *h);
-
-void unit_file_list_free(Hashmap *h);
-void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes);
-
-int unit_file_query_preset(UnitFileScope scope, const char *name);
-
-const char *unit_file_state_to_string(UnitFileState s);
-UnitFileState unit_file_state_from_string(const char *s);
-
-const char *unit_file_change_type_to_string(UnitFileChangeType s);
-UnitFileChangeType unit_file_change_type_from_string(const char *s);
diff --git a/src/shared/ioprio.h b/src/shared/ioprio.h
deleted file mode 100644
index 9800fc2553..0000000000
--- a/src/shared/ioprio.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef IOPRIO_H
-#define IOPRIO_H
-
-/* This is minimal version of Linux' linux/ioprio.h header file, which
- * is licensed GPL2 */
-
-#include <unistd.h>
-#include <sys/syscall.h>
-
-/*
- * Gives us 8 prio classes with 13-bits of data for each class
- */
-#define IOPRIO_BITS (16)
-#define IOPRIO_CLASS_SHIFT (13)
-#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1)
-
-#define IOPRIO_PRIO_CLASS(mask) ((mask) >> IOPRIO_CLASS_SHIFT)
-#define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK)
-#define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data)
-
-#define ioprio_valid(mask) (IOPRIO_PRIO_CLASS((mask)) != IOPRIO_CLASS_NONE)
-
-/*
- * These are the io priority groups as implemented by CFQ. RT is the realtime
- * class, it always gets premium service. BE is the best-effort scheduling
- * class, the default for any process. IDLE is the idle scheduling class, it
- * is only served when no one else is using the disk.
- */
-enum {
- IOPRIO_CLASS_NONE,
- IOPRIO_CLASS_RT,
- IOPRIO_CLASS_BE,
- IOPRIO_CLASS_IDLE,
-};
-
-/*
- * 8 best effort priority levels are supported
- */
-#define IOPRIO_BE_NR (8)
-
-enum {
- IOPRIO_WHO_PROCESS = 1,
- IOPRIO_WHO_PGRP,
- IOPRIO_WHO_USER,
-};
-
-static inline int ioprio_set(int which, int who, int ioprio)
-{
- return syscall(__NR_ioprio_set, which, who, ioprio);
-}
-
-static inline int ioprio_get(int which, int who)
-{
- return syscall(__NR_ioprio_get, which, who);
-}
-
-#endif
diff --git a/src/shared/label.c b/src/shared/label.c
deleted file mode 100644
index d353da57ec..0000000000
--- a/src/shared/label.c
+++ /dev/null
@@ -1,382 +0,0 @@
-/*-*- 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 <errno.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <malloc.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#include "label.h"
-#include "util.h"
-#include "path-util.h"
-
-#ifdef HAVE_SELINUX
-#include "selinux-util.h"
-#include <selinux/selinux.h>
-#include <selinux/label.h>
-
-static struct selabel_handle *label_hnd = NULL;
-
-#endif
-
-int label_init(const char *prefix) {
- int r = 0;
-
-#ifdef HAVE_SELINUX
- usec_t before_timestamp, after_timestamp;
- struct mallinfo before_mallinfo, after_mallinfo;
-
- if (!use_selinux())
- return 0;
-
- if (label_hnd)
- return 0;
-
- before_mallinfo = mallinfo();
- before_timestamp = now(CLOCK_MONOTONIC);
-
- if (prefix) {
- struct selinux_opt options[] = {
- { .type = SELABEL_OPT_SUBSET, .value = prefix },
- };
-
- label_hnd = selabel_open(SELABEL_CTX_FILE, options, ELEMENTSOF(options));
- } else
- label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
-
- if (!label_hnd) {
- log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG,
- "Failed to initialize SELinux context: %m");
- r = security_getenforce() == 1 ? -errno : 0;
- } else {
- char timespan[FORMAT_TIMESPAN_MAX];
- int l;
-
- after_timestamp = now(CLOCK_MONOTONIC);
- after_mallinfo = mallinfo();
-
- l = after_mallinfo.uordblks > before_mallinfo.uordblks ? after_mallinfo.uordblks - before_mallinfo.uordblks : 0;
-
- log_debug("Successfully loaded SELinux database in %s, size on heap is %iK.",
- format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp),
- (l+1023)/1024);
- }
-#endif
-
- return r;
-}
-
-int label_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
- int r = 0;
-
-#ifdef HAVE_SELINUX
- struct stat st;
- security_context_t fcon;
-
- if (!use_selinux() || !label_hnd)
- return 0;
-
- r = lstat(path, &st);
- if (r == 0) {
- r = selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode);
-
- /* If there's no label to set, then exit without warning */
- if (r < 0 && errno == ENOENT)
- return 0;
-
- if (r == 0) {
- r = lsetfilecon(path, fcon);
- freecon(fcon);
-
- /* If the FS doesn't support labels, then exit without warning */
- if (r < 0 && errno == ENOTSUP)
- return 0;
- }
- }
-
- if (r < 0) {
- /* Ignore ENOENT in some cases */
- if (ignore_enoent && errno == ENOENT)
- return 0;
-
- if (ignore_erofs && errno == EROFS)
- return 0;
-
- log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG,
- "Unable to fix label of %s: %m", path);
- r = security_getenforce() == 1 ? -errno : 0;
- }
-#endif
-
- return r;
-}
-
-void label_finish(void) {
-
-#ifdef HAVE_SELINUX
- if (use_selinux() && label_hnd)
- selabel_close(label_hnd);
-#endif
-}
-
-int label_get_create_label_from_exe(const char *exe, char **label) {
-
- int r = 0;
-
-#ifdef HAVE_SELINUX
- security_context_t mycon = NULL, fcon = NULL;
- security_class_t sclass;
-
- if (!use_selinux()) {
- *label = NULL;
- return 0;
- }
-
- r = getcon(&mycon);
- if (r < 0)
- goto fail;
-
- r = getfilecon(exe, &fcon);
- if (r < 0)
- goto fail;
-
- sclass = string_to_security_class("process");
- r = security_compute_create(mycon, fcon, sclass, (security_context_t *) label);
- if (r == 0)
- log_debug("SELinux Socket context for %s will be set to %s", exe, *label);
-
-fail:
- if (r < 0 && security_getenforce() == 1)
- r = -errno;
-
- freecon(mycon);
- freecon(fcon);
-#endif
-
- return r;
-}
-
-int label_context_set(const char *path, mode_t mode) {
- int r = 0;
-
-#ifdef HAVE_SELINUX
- security_context_t filecon = NULL;
-
- if (!use_selinux() || !label_hnd)
- return 0;
-
- r = selabel_lookup_raw(label_hnd, &filecon, path, mode);
- if (r < 0 && errno != ENOENT)
- r = -errno;
- else if (r == 0) {
- r = setfscreatecon(filecon);
- if (r < 0) {
- log_error("Failed to set SELinux file context on %s: %m", path);
- r = -errno;
- }
-
- freecon(filecon);
- }
-
- if (r < 0 && security_getenforce() == 0)
- r = 0;
-#endif
-
- return r;
-}
-
-int label_socket_set(const char *label) {
-
-#ifdef HAVE_SELINUX
- if (!use_selinux())
- return 0;
-
- if (setsockcreatecon((security_context_t) label) < 0) {
- log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG,
- "Failed to set SELinux context (%s) on socket: %m", label);
-
- if (security_getenforce() == 1)
- return -errno;
- }
-#endif
-
- return 0;
-}
-
-void label_context_clear(void) {
-
-#ifdef HAVE_SELINUX
- if (!use_selinux())
- return;
-
- setfscreatecon(NULL);
-#endif
-}
-
-void label_socket_clear(void) {
-
-#ifdef HAVE_SELINUX
- if (!use_selinux())
- return;
-
- setsockcreatecon(NULL);
-#endif
-}
-
-void label_free(const char *label) {
-
-#ifdef HAVE_SELINUX
- if (!use_selinux())
- return;
-
- freecon((security_context_t) label);
-#endif
-}
-
-int label_mkdir(const char *path, mode_t mode, bool apply) {
-
- /* Creates a directory and labels it according to the SELinux policy */
-#ifdef HAVE_SELINUX
- int r;
- security_context_t fcon = NULL;
-
- if (!apply || !use_selinux() || !label_hnd)
- goto skipped;
-
- if (path_is_absolute(path))
- r = selabel_lookup_raw(label_hnd, &fcon, path, S_IFDIR);
- else {
- char *newpath;
-
- newpath = path_make_absolute_cwd(path);
- if (!newpath)
- return -ENOMEM;
-
- r = selabel_lookup_raw(label_hnd, &fcon, newpath, S_IFDIR);
- free(newpath);
- }
-
- if (r == 0)
- r = setfscreatecon(fcon);
-
- if (r < 0 && errno != ENOENT) {
- log_error("Failed to set security context %s for %s: %m", fcon, path);
-
- if (security_getenforce() == 1) {
- r = -errno;
- goto finish;
- }
- }
-
- r = mkdir(path, mode);
- if (r < 0)
- r = -errno;
-
-finish:
- setfscreatecon(NULL);
- freecon(fcon);
-
- return r;
-
-skipped:
-#endif
- return mkdir(path, mode) < 0 ? -errno : 0;
-}
-
-int label_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
-
- /* Binds a socket and label its file system object according to the SELinux policy */
-
-#ifdef HAVE_SELINUX
- int r;
- security_context_t fcon = NULL;
- const struct sockaddr_un *un;
- char *path = NULL;
-
- assert(fd >= 0);
- assert(addr);
- assert(addrlen >= sizeof(sa_family_t));
-
- if (!use_selinux() || !label_hnd)
- goto skipped;
-
- /* Filter out non-local sockets */
- if (addr->sa_family != AF_UNIX)
- goto skipped;
-
- /* Filter out anonymous sockets */
- if (addrlen < sizeof(sa_family_t) + 1)
- goto skipped;
-
- /* Filter out abstract namespace sockets */
- un = (const struct sockaddr_un*) addr;
- if (un->sun_path[0] == 0)
- goto skipped;
-
- path = strndup(un->sun_path, addrlen - offsetof(struct sockaddr_un, sun_path));
- if (!path)
- return -ENOMEM;
-
- if (path_is_absolute(path))
- r = selabel_lookup_raw(label_hnd, &fcon, path, S_IFSOCK);
- else {
- char *newpath;
-
- newpath = path_make_absolute_cwd(path);
-
- if (!newpath) {
- free(path);
- return -ENOMEM;
- }
-
- r = selabel_lookup_raw(label_hnd, &fcon, newpath, S_IFSOCK);
- free(newpath);
- }
-
- if (r == 0)
- r = setfscreatecon(fcon);
-
- if (r < 0 && errno != ENOENT) {
- log_error("Failed to set security context %s for %s: %m", fcon, path);
-
- if (security_getenforce() == 1) {
- r = -errno;
- goto finish;
- }
- }
-
- r = bind(fd, addr, addrlen);
- if (r < 0)
- r = -errno;
-
-finish:
- setfscreatecon(NULL);
- freecon(fcon);
- free(path);
-
- return r;
-
-skipped:
-#endif
- return bind(fd, addr, addrlen) < 0 ? -errno : 0;
-}
diff --git a/src/shared/label.h b/src/shared/label.h
deleted file mode 100644
index 1220b18965..0000000000
--- a/src/shared/label.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*-*- 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/types.h>
-#include <stdbool.h>
-#include <sys/socket.h>
-
-int label_init(const char *prefix);
-void label_finish(void);
-
-int label_fix(const char *path, bool ignore_enoent, bool ignore_erofs);
-
-int label_socket_set(const char *label);
-void label_socket_clear(void);
-
-int label_context_set(const char *path, mode_t mode);
-void label_context_clear(void);
-
-void label_free(const char *label);
-
-int label_get_create_label_from_exe(const char *exe, char **label);
-
-int label_mkdir(const char *path, mode_t mode, bool apply);
-
-void label_retest_selinux(void);
-
-int label_bind(int fd, const struct sockaddr *addr, socklen_t addrlen);
diff --git a/src/shared/linux/Makefile b/src/shared/linux/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/shared/linux/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/shared/linux/auto_dev-ioctl.h b/src/shared/linux/auto_dev-ioctl.h
deleted file mode 100644
index 850f39b33e..0000000000
--- a/src/shared/linux/auto_dev-ioctl.h
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright 2008 Red Hat, Inc. All rights reserved.
- * Copyright 2008 Ian Kent <raven@themaw.net>
- *
- * This file is part of the Linux kernel and is made available under
- * the terms of the GNU General Public License, version 2, or at your
- * option, any later version, incorporated herein by reference.
- */
-
-#ifndef _LINUX_AUTO_DEV_IOCTL_H
-#define _LINUX_AUTO_DEV_IOCTL_H
-
-#include <linux/auto_fs.h>
-
-#ifdef __KERNEL__
-#include <linux/string.h>
-#else
-#include <string.h>
-#endif /* __KERNEL__ */
-
-#define AUTOFS_DEVICE_NAME "autofs"
-
-#define AUTOFS_DEV_IOCTL_VERSION_MAJOR 1
-#define AUTOFS_DEV_IOCTL_VERSION_MINOR 0
-
-#define AUTOFS_DEVID_LEN 16
-
-#define AUTOFS_DEV_IOCTL_SIZE sizeof(struct autofs_dev_ioctl)
-
-/*
- * An ioctl interface for autofs mount point control.
- */
-
-struct args_protover {
- __u32 version;
-};
-
-struct args_protosubver {
- __u32 sub_version;
-};
-
-struct args_openmount {
- __u32 devid;
-};
-
-struct args_ready {
- __u32 token;
-};
-
-struct args_fail {
- __u32 token;
- __s32 status;
-};
-
-struct args_setpipefd {
- __s32 pipefd;
-};
-
-struct args_timeout {
- __u64 timeout;
-};
-
-struct args_requester {
- __u32 uid;
- __u32 gid;
-};
-
-struct args_expire {
- __u32 how;
-};
-
-struct args_askumount {
- __u32 may_umount;
-};
-
-struct args_ismountpoint {
- union {
- struct args_in {
- __u32 type;
- } in;
- struct args_out {
- __u32 devid;
- __u32 magic;
- } out;
- };
-};
-
-/*
- * All the ioctls use this structure.
- * When sending a path size must account for the total length
- * of the chunk of memory otherwise is is the size of the
- * structure.
- */
-
-struct autofs_dev_ioctl {
- __u32 ver_major;
- __u32 ver_minor;
- __u32 size; /* total size of data passed in
- * including this struct */
- __s32 ioctlfd; /* automount command fd */
-
- /* Command parameters */
-
- union {
- struct args_protover protover;
- struct args_protosubver protosubver;
- struct args_openmount openmount;
- struct args_ready ready;
- struct args_fail fail;
- struct args_setpipefd setpipefd;
- struct args_timeout timeout;
- struct args_requester requester;
- struct args_expire expire;
- struct args_askumount askumount;
- struct args_ismountpoint ismountpoint;
- };
-
- char path[0];
-};
-
-static inline void init_autofs_dev_ioctl(struct autofs_dev_ioctl *in)
-{
- memset(in, 0, sizeof(struct autofs_dev_ioctl));
- in->ver_major = AUTOFS_DEV_IOCTL_VERSION_MAJOR;
- in->ver_minor = AUTOFS_DEV_IOCTL_VERSION_MINOR;
- in->size = sizeof(struct autofs_dev_ioctl);
- in->ioctlfd = -1;
- return;
-}
-
-/*
- * If you change this make sure you make the corresponding change
- * to autofs-dev-ioctl.c:lookup_ioctl()
- */
-enum {
- /* Get various version info */
- AUTOFS_DEV_IOCTL_VERSION_CMD = 0x71,
- AUTOFS_DEV_IOCTL_PROTOVER_CMD,
- AUTOFS_DEV_IOCTL_PROTOSUBVER_CMD,
-
- /* Open mount ioctl fd */
- AUTOFS_DEV_IOCTL_OPENMOUNT_CMD,
-
- /* Close mount ioctl fd */
- AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD,
-
- /* Mount/expire status returns */
- AUTOFS_DEV_IOCTL_READY_CMD,
- AUTOFS_DEV_IOCTL_FAIL_CMD,
-
- /* Activate/deactivate autofs mount */
- AUTOFS_DEV_IOCTL_SETPIPEFD_CMD,
- AUTOFS_DEV_IOCTL_CATATONIC_CMD,
-
- /* Expiry timeout */
- AUTOFS_DEV_IOCTL_TIMEOUT_CMD,
-
- /* Get mount last requesting uid and gid */
- AUTOFS_DEV_IOCTL_REQUESTER_CMD,
-
- /* Check for eligible expire candidates */
- AUTOFS_DEV_IOCTL_EXPIRE_CMD,
-
- /* Request busy status */
- AUTOFS_DEV_IOCTL_ASKUMOUNT_CMD,
-
- /* Check if path is a mountpoint */
- AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD,
-};
-
-#define AUTOFS_IOCTL 0x93
-
-#define AUTOFS_DEV_IOCTL_VERSION \
- _IOWR(AUTOFS_IOCTL, \
- AUTOFS_DEV_IOCTL_VERSION_CMD, struct autofs_dev_ioctl)
-
-#define AUTOFS_DEV_IOCTL_PROTOVER \
- _IOWR(AUTOFS_IOCTL, \
- AUTOFS_DEV_IOCTL_PROTOVER_CMD, struct autofs_dev_ioctl)
-
-#define AUTOFS_DEV_IOCTL_PROTOSUBVER \
- _IOWR(AUTOFS_IOCTL, \
- AUTOFS_DEV_IOCTL_PROTOSUBVER_CMD, struct autofs_dev_ioctl)
-
-#define AUTOFS_DEV_IOCTL_OPENMOUNT \
- _IOWR(AUTOFS_IOCTL, \
- AUTOFS_DEV_IOCTL_OPENMOUNT_CMD, struct autofs_dev_ioctl)
-
-#define AUTOFS_DEV_IOCTL_CLOSEMOUNT \
- _IOWR(AUTOFS_IOCTL, \
- AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD, struct autofs_dev_ioctl)
-
-#define AUTOFS_DEV_IOCTL_READY \
- _IOWR(AUTOFS_IOCTL, \
- AUTOFS_DEV_IOCTL_READY_CMD, struct autofs_dev_ioctl)
-
-#define AUTOFS_DEV_IOCTL_FAIL \
- _IOWR(AUTOFS_IOCTL, \
- AUTOFS_DEV_IOCTL_FAIL_CMD, struct autofs_dev_ioctl)
-
-#define AUTOFS_DEV_IOCTL_SETPIPEFD \
- _IOWR(AUTOFS_IOCTL, \
- AUTOFS_DEV_IOCTL_SETPIPEFD_CMD, struct autofs_dev_ioctl)
-
-#define AUTOFS_DEV_IOCTL_CATATONIC \
- _IOWR(AUTOFS_IOCTL, \
- AUTOFS_DEV_IOCTL_CATATONIC_CMD, struct autofs_dev_ioctl)
-
-#define AUTOFS_DEV_IOCTL_TIMEOUT \
- _IOWR(AUTOFS_IOCTL, \
- AUTOFS_DEV_IOCTL_TIMEOUT_CMD, struct autofs_dev_ioctl)
-
-#define AUTOFS_DEV_IOCTL_REQUESTER \
- _IOWR(AUTOFS_IOCTL, \
- AUTOFS_DEV_IOCTL_REQUESTER_CMD, struct autofs_dev_ioctl)
-
-#define AUTOFS_DEV_IOCTL_EXPIRE \
- _IOWR(AUTOFS_IOCTL, \
- AUTOFS_DEV_IOCTL_EXPIRE_CMD, struct autofs_dev_ioctl)
-
-#define AUTOFS_DEV_IOCTL_ASKUMOUNT \
- _IOWR(AUTOFS_IOCTL, \
- AUTOFS_DEV_IOCTL_ASKUMOUNT_CMD, struct autofs_dev_ioctl)
-
-#define AUTOFS_DEV_IOCTL_ISMOUNTPOINT \
- _IOWR(AUTOFS_IOCTL, \
- AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD, struct autofs_dev_ioctl)
-
-#endif /* _LINUX_AUTO_DEV_IOCTL_H */
diff --git a/src/shared/linux/fanotify.h b/src/shared/linux/fanotify.h
deleted file mode 100644
index 63531a6b4d..0000000000
--- a/src/shared/linux/fanotify.h
+++ /dev/null
@@ -1,98 +0,0 @@
-#ifndef _LINUX_FANOTIFY_H
-#define _LINUX_FANOTIFY_H
-
-#include <linux/types.h>
-
-/* the following events that user-space can register for */
-#define FAN_ACCESS 0x00000001 /* File was accessed */
-#define FAN_MODIFY 0x00000002 /* File was modified */
-#define FAN_CLOSE_WRITE 0x00000008 /* Unwrittable file closed */
-#define FAN_CLOSE_NOWRITE 0x00000010 /* Writtable file closed */
-#define FAN_OPEN 0x00000020 /* File was opened */
-
-#define FAN_EVENT_ON_CHILD 0x08000000 /* interested in child events */
-
-/* FIXME currently Q's have no limit.... */
-#define FAN_Q_OVERFLOW 0x00004000 /* Event queued overflowed */
-
-#define FAN_OPEN_PERM 0x00010000 /* File open in perm check */
-#define FAN_ACCESS_PERM 0x00020000 /* File accessed in perm check */
-
-/* helper events */
-#define FAN_CLOSE (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE) /* close */
-
-/* flags used for fanotify_init() */
-#define FAN_CLOEXEC 0x00000001
-#define FAN_NONBLOCK 0x00000002
-
-#define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK)
-
-/* flags used for fanotify_modify_mark() */
-#define FAN_MARK_ADD 0x00000001
-#define FAN_MARK_REMOVE 0x00000002
-#define FAN_MARK_DONT_FOLLOW 0x00000004
-#define FAN_MARK_ONLYDIR 0x00000008
-#define FAN_MARK_MOUNT 0x00000010
-#define FAN_MARK_IGNORED_MASK 0x00000020
-#define FAN_MARK_IGNORED_SURV_MODIFY 0x00000040
-#define FAN_MARK_FLUSH 0x00000080
-
-#define FAN_ALL_MARK_FLAGS (FAN_MARK_ADD |\
- FAN_MARK_REMOVE |\
- FAN_MARK_DONT_FOLLOW |\
- FAN_MARK_ONLYDIR |\
- FAN_MARK_MOUNT |\
- FAN_MARK_IGNORED_MASK |\
- FAN_MARK_IGNORED_SURV_MODIFY)
-
-/*
- * All of the events - we build the list by hand so that we can add flags in
- * the future and not break backward compatibility. Apps will get only the
- * events that they originally wanted. Be sure to add new events here!
- */
-#define FAN_ALL_EVENTS (FAN_ACCESS |\
- FAN_MODIFY |\
- FAN_CLOSE |\
- FAN_OPEN)
-
-/*
- * All events which require a permission response from userspace
- */
-#define FAN_ALL_PERM_EVENTS (FAN_OPEN_PERM |\
- FAN_ACCESS_PERM)
-
-#define FAN_ALL_OUTGOING_EVENTS (FAN_ALL_EVENTS |\
- FAN_ALL_PERM_EVENTS |\
- FAN_Q_OVERFLOW)
-
-#define FANOTIFY_METADATA_VERSION 2
-
-struct fanotify_event_metadata {
- __u32 event_len;
- __u32 vers;
- __u64 mask;
- __s32 fd;
- __s32 pid;
-} __attribute__ ((packed));
-
-struct fanotify_response {
- __s32 fd;
- __u32 response;
-} __attribute__ ((packed));
-
-/* Legit userspace responses to a _PERM event */
-#define FAN_ALLOW 0x01
-#define FAN_DENY 0x02
-
-/* Helper functions to deal with fanotify_event_metadata buffers */
-#define FAN_EVENT_METADATA_LEN (sizeof(struct fanotify_event_metadata))
-
-#define FAN_EVENT_NEXT(meta, len) ((len) -= (meta)->event_len, \
- (struct fanotify_event_metadata*)(((char *)(meta)) + \
- (meta)->event_len))
-
-#define FAN_EVENT_OK(meta, len) ((long)(len) >= (long)FAN_EVENT_METADATA_LEN && \
- (long)(meta)->event_len >= (long)FAN_EVENT_METADATA_LEN && \
- (long)(meta)->event_len <= (long)(len))
-
-#endif /* _LINUX_FANOTIFY_H */
diff --git a/src/shared/linux/seccomp-bpf.h b/src/shared/linux/seccomp-bpf.h
deleted file mode 100644
index 1e3d136739..0000000000
--- a/src/shared/linux/seccomp-bpf.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * seccomp example for x86 (32-bit and 64-bit) with BPF macros
- *
- * Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org>
- * Authors:
- * Will Drewry <wad@chromium.org>
- * Kees Cook <keescook@chromium.org>
- *
- * The code may be used by anyone for any purpose, and can serve as a
- * starting point for developing applications using mode 2 seccomp.
- */
-#ifndef _SECCOMP_BPF_H_
-#define _SECCOMP_BPF_H_
-
-#include <stdio.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <signal.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <sys/prctl.h>
-
-#include <linux/unistd.h>
-#include <linux/audit.h>
-#include <linux/filter.h>
-#include <linux/seccomp.h>
-
-#ifndef SECCOMP_MODE_FILTER
-# define SECCOMP_MODE_FILTER 2 /* uses user-supplied filter. */
-# define SECCOMP_RET_KILL 0x00000000U /* kill the task immediately */
-# define SECCOMP_RET_TRAP 0x00030000U /* disallow and force a SIGSYS */
-# define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */
-struct seccomp_data {
- int nr;
- __u32 arch;
- __u64 instruction_pointer;
- __u64 args[6];
-};
-#endif
-#ifndef SYS_SECCOMP
-# define SYS_SECCOMP 1
-#endif
-
-#define syscall_nr (offsetof(struct seccomp_data, nr))
-#define arch_nr (offsetof(struct seccomp_data, arch))
-
-#if defined(__i386__)
-# define REG_SYSCALL REG_EAX
-# define ARCH_NR AUDIT_ARCH_I386
-#elif defined(__x86_64__)
-# define REG_SYSCALL REG_RAX
-# define ARCH_NR AUDIT_ARCH_X86_64
-#else
-# warning "Platform does not support seccomp filter yet"
-# define REG_SYSCALL 0
-# define ARCH_NR 0
-#endif
-
-#define VALIDATE_ARCHITECTURE \
- BPF_STMT(BPF_LD+BPF_W+BPF_ABS, arch_nr), \
- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARCH_NR, 1, 0), \
- BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
-
-#define EXAMINE_SYSCALL \
- BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_nr)
-
-#define ALLOW_SYSCALL(name) \
- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_##name, 0, 1), \
- BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
-
-#define _KILL_PROCESS \
- BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
-
-#endif /* _SECCOMP_BPF_H_ */
diff --git a/src/shared/linux/seccomp.h b/src/shared/linux/seccomp.h
deleted file mode 100644
index 9c03683fa0..0000000000
--- a/src/shared/linux/seccomp.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef _LINUX_SECCOMP_H
-#define _LINUX_SECCOMP_H
-
-
-#include <linux/types.h>
-
-
-/* Valid values for seccomp.mode and prctl(PR_SET_SECCOMP, <mode>) */
-#define SECCOMP_MODE_DISABLED 0 /* seccomp is not in use. */
-#define SECCOMP_MODE_STRICT 1 /* uses hard-coded filter. */
-#define SECCOMP_MODE_FILTER 2 /* uses user-supplied filter. */
-
-/*
- * All BPF programs must return a 32-bit value.
- * The bottom 16-bits are for optional return data.
- * The upper 16-bits are ordered from least permissive values to most.
- *
- * The ordering ensures that a min_t() over composed return values always
- * selects the least permissive choice.
- */
-#define SECCOMP_RET_KILL 0x00000000U /* kill the task immediately */
-#define SECCOMP_RET_TRAP 0x00030000U /* disallow and force a SIGSYS */
-#define SECCOMP_RET_ERRNO 0x00050000U /* returns an errno */
-#define SECCOMP_RET_TRACE 0x7ff00000U /* pass to a tracer or disallow */
-#define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */
-
-/* Masks for the return value sections. */
-#define SECCOMP_RET_ACTION 0x7fff0000U
-#define SECCOMP_RET_DATA 0x0000ffffU
-
-/**
- * struct seccomp_data - the format the BPF program executes over.
- * @nr: the system call number
- * @arch: indicates system call convention as an AUDIT_ARCH_* value
- * as defined in <linux/audit.h>.
- * @instruction_pointer: at the time of the system call.
- * @args: up to 6 system call arguments always stored as 64-bit values
- * regardless of the architecture.
- */
-struct seccomp_data {
- int nr;
- __u32 arch;
- __u64 instruction_pointer;
- __u64 args[6];
-};
-
-#endif /* _LINUX_SECCOMP_H */
diff --git a/src/shared/list.h b/src/shared/list.h
deleted file mode 100644
index 47f275a019..0000000000
--- a/src/shared/list.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*-*- 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/>.
-***/
-
-/* The head of the linked list. Use this in the structure that shall
- * contain the head of the linked list */
-#define LIST_HEAD(t,name) \
- t *name
-
-/* The pointers in the linked list's items. Use this in the item structure */
-#define LIST_FIELDS(t,name) \
- t *name##_next, *name##_prev
-
-/* Initialize the list's head */
-#define LIST_HEAD_INIT(t,head) \
- do { \
- (head) = NULL; } \
- while(false)
-
-/* Initialize a list item */
-#define LIST_INIT(t,name,item) \
- do { \
- t *_item = (item); \
- assert(_item); \
- _item->name##_prev = _item->name##_next = NULL; \
- } while(false)
-
-/* Prepend an item to the list */
-#define LIST_PREPEND(t,name,head,item) \
- do { \
- t **_head = &(head), *_item = (item); \
- assert(_item); \
- if ((_item->name##_next = *_head)) \
- _item->name##_next->name##_prev = _item; \
- _item->name##_prev = NULL; \
- *_head = _item; \
- } while(false)
-
-/* Remove an item from the list */
-#define LIST_REMOVE(t,name,head,item) \
- do { \
- t **_head = &(head), *_item = (item); \
- assert(_item); \
- if (_item->name##_next) \
- _item->name##_next->name##_prev = _item->name##_prev; \
- if (_item->name##_prev) \
- _item->name##_prev->name##_next = _item->name##_next; \
- else { \
- assert(*_head == _item); \
- *_head = _item->name##_next; \
- } \
- _item->name##_next = _item->name##_prev = NULL; \
- } while(false)
-
-/* Find the head of the list */
-#define LIST_FIND_HEAD(t,name,item,head) \
- do { \
- t *_item = (item); \
- assert(_item); \
- while (_item->name##_prev) \
- _item = _item->name##_prev; \
- (head) = _item; \
- } while (false)
-
-/* Find the head of the list */
-#define LIST_FIND_TAIL(t,name,item,tail) \
- do { \
- t *_item = (item); \
- assert(_item); \
- while (_item->name##_next) \
- _item = _item->name##_next; \
- (tail) = _item; \
- } while (false)
-
-/* Insert an item after another one (a = where, b = what) */
-#define LIST_INSERT_AFTER(t,name,head,a,b) \
- do { \
- t **_head = &(head), *_a = (a), *_b = (b); \
- assert(_b); \
- if (!_a) { \
- if ((_b->name##_next = *_head)) \
- _b->name##_next->name##_prev = _b; \
- _b->name##_prev = NULL; \
- *_head = _b; \
- } else { \
- if ((_b->name##_next = _a->name##_next)) \
- _b->name##_next->name##_prev = _b; \
- _b->name##_prev = _a; \
- _a->name##_next = _b; \
- } \
- } while(false)
-
-#define LIST_JUST_US(name,item) \
- (!(item)->name##_prev && !(item)->name##_next) \
-
-#define LIST_FOREACH(name,i,head) \
- for ((i) = (head); (i); (i) = (i)->name##_next)
-
-#define LIST_FOREACH_SAFE(name,i,n,head) \
- for ((i) = (head); (i) && (((n) = (i)->name##_next), 1); (i) = (n))
-
-#define LIST_FOREACH_BEFORE(name,i,p) \
- for ((i) = (p)->name##_prev; (i); (i) = (i)->name##_prev)
-
-#define LIST_FOREACH_AFTER(name,i,p) \
- for ((i) = (p)->name##_next; (i); (i) = (i)->name##_next)
diff --git a/src/shared/log.c b/src/shared/log.c
deleted file mode 100644
index 63578683ab..0000000000
--- a/src/shared/log.c
+++ /dev/null
@@ -1,885 +0,0 @@
-/*-*- 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 <stdarg.h>
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <stddef.h>
-#include <printf.h>
-
-#include "log.h"
-#include "util.h"
-#include "missing.h"
-#include "macro.h"
-#include "socket-util.h"
-
-#define SNDBUF_SIZE (8*1024*1024)
-
-static LogTarget log_target = LOG_TARGET_CONSOLE;
-static int log_max_level = LOG_INFO;
-static int log_facility = LOG_DAEMON;
-
-static int console_fd = STDERR_FILENO;
-static int syslog_fd = -1;
-static int kmsg_fd = -1;
-static int journal_fd = -1;
-
-static bool syslog_is_stream = false;
-
-static bool show_color = false;
-static bool show_location = false;
-
-/* Akin to glibc's __abort_msg; which is private and we hence cannot
- * use here. */
-static char *log_abort_msg = NULL;
-
-void log_close_console(void) {
-
- if (console_fd < 0)
- return;
-
- if (getpid() == 1) {
- if (console_fd >= 3)
- close_nointr_nofail(console_fd);
-
- console_fd = -1;
- }
-}
-
-static int log_open_console(void) {
-
- if (console_fd >= 0)
- return 0;
-
- if (getpid() == 1) {
- console_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
- if (console_fd < 0)
- return console_fd;
- } else
- console_fd = STDERR_FILENO;
-
- return 0;
-}
-
-void log_close_kmsg(void) {
-
- if (kmsg_fd < 0)
- return;
-
- close_nointr_nofail(kmsg_fd);
- kmsg_fd = -1;
-}
-
-static int log_open_kmsg(void) {
-
- if (kmsg_fd >= 0)
- return 0;
-
- kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC);
- if (kmsg_fd < 0)
- return -errno;
-
- return 0;
-}
-
-void log_close_syslog(void) {
-
- if (syslog_fd < 0)
- return;
-
- close_nointr_nofail(syslog_fd);
- syslog_fd = -1;
-}
-
-static int create_log_socket(int type) {
- int fd;
-
- /* All output to the syslog/journal fds we do asynchronously,
- * and if the buffers are full we just drop the messages */
-
- fd = socket(AF_UNIX, type|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (fd < 0)
- return -errno;
-
- fd_inc_sndbuf(fd, SNDBUF_SIZE);
-
- return fd;
-}
-
-static int log_open_syslog(void) {
- union sockaddr_union sa;
- int r;
-
- if (syslog_fd >= 0)
- return 0;
-
- zero(sa);
- sa.un.sun_family = AF_UNIX;
- strncpy(sa.un.sun_path, "/dev/log", sizeof(sa.un.sun_path));
-
- syslog_fd = create_log_socket(SOCK_DGRAM);
- if (syslog_fd < 0) {
- r = syslog_fd;
- goto fail;
- }
-
- if (connect(syslog_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
- close_nointr_nofail(syslog_fd);
-
- /* Some legacy syslog systems still use stream
- * sockets. They really shouldn't. But what can we
- * do... */
- syslog_fd = create_log_socket(SOCK_STREAM);
- if (syslog_fd < 0) {
- r = syslog_fd;
- goto fail;
- }
-
- if (connect(syslog_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
- r = -errno;
- goto fail;
- }
-
- syslog_is_stream = true;
- } else
- syslog_is_stream = false;
-
- return 0;
-
-fail:
- log_close_syslog();
- return r;
-}
-
-void log_close_journal(void) {
-
- if (journal_fd < 0)
- return;
-
- close_nointr_nofail(journal_fd);
- journal_fd = -1;
-}
-
-static int log_open_journal(void) {
- union sockaddr_union sa;
- int r;
-
- if (journal_fd >= 0)
- return 0;
-
- journal_fd = create_log_socket(SOCK_DGRAM);
- if (journal_fd < 0) {
- r = journal_fd;
- goto fail;
- }
-
- zero(sa);
- sa.un.sun_family = AF_UNIX;
- strncpy(sa.un.sun_path, "/run/systemd/journal/socket", sizeof(sa.un.sun_path));
-
- if (connect(journal_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
- r = -errno;
- goto fail;
- }
-
- return 0;
-
-fail:
- log_close_journal();
- return r;
-}
-
-int log_open(void) {
- int r;
-
- /* If we don't use the console we close it here, to not get
- * killed by SAK. If we don't use syslog we close it here so
- * that we are not confused by somebody deleting the socket in
- * the fs. If we don't use /dev/kmsg we still keep it open,
- * because there is no reason to close it. */
-
- if (log_target == LOG_TARGET_NULL) {
- log_close_journal();
- log_close_syslog();
- log_close_console();
- return 0;
- }
-
- if ((log_target != LOG_TARGET_AUTO && log_target != LOG_TARGET_SAFE) ||
- getpid() == 1 ||
- isatty(STDERR_FILENO) <= 0) {
-
- if (log_target == LOG_TARGET_AUTO ||
- log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
- log_target == LOG_TARGET_JOURNAL) {
- r = log_open_journal();
- if (r >= 0) {
- log_close_syslog();
- log_close_console();
- return r;
- }
- }
-
- if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
- log_target == LOG_TARGET_SYSLOG) {
- r = log_open_syslog();
- if (r >= 0) {
- log_close_journal();
- log_close_console();
- return r;
- }
- }
-
- if (log_target == LOG_TARGET_AUTO ||
- log_target == LOG_TARGET_SAFE ||
- log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
- log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
- log_target == LOG_TARGET_KMSG) {
- r = log_open_kmsg();
- if (r >= 0) {
- log_close_journal();
- log_close_syslog();
- log_close_console();
- return r;
- }
- }
- }
-
- log_close_journal();
- log_close_syslog();
-
- /* Get the real /dev/console if we are PID=1, hence reopen */
- log_close_console();
- return log_open_console();
-}
-
-void log_set_target(LogTarget target) {
- assert(target >= 0);
- assert(target < _LOG_TARGET_MAX);
-
- log_target = target;
-}
-
-void log_close(void) {
- log_close_journal();
- log_close_syslog();
- log_close_kmsg();
- log_close_console();
-}
-
-void log_forget_fds(void) {
- console_fd = kmsg_fd = syslog_fd = journal_fd = -1;
-}
-
-void log_set_max_level(int level) {
- assert((level & LOG_PRIMASK) == level);
-
- log_max_level = level;
-}
-
-void log_set_facility(int facility) {
- log_facility = facility;
-}
-
-static int write_to_console(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *buffer) {
-
- char location[64];
- struct iovec iovec[5];
- unsigned n = 0;
- bool highlight;
-
- if (console_fd < 0)
- return 0;
-
- highlight = LOG_PRI(level) <= LOG_ERR && show_color;
-
- zero(iovec);
-
- if (show_location) {
- snprintf(location, sizeof(location), "(%s:%u) ", file, line);
- char_array_0(location);
- IOVEC_SET_STRING(iovec[n++], location);
- }
-
- if (highlight)
- IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_RED_ON);
- IOVEC_SET_STRING(iovec[n++], buffer);
- if (highlight)
- IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_OFF);
- IOVEC_SET_STRING(iovec[n++], "\n");
-
- if (writev(console_fd, iovec, n) < 0)
- return -errno;
-
- return 1;
-}
-
-static int write_to_syslog(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *buffer) {
-
- char header_priority[16], header_time[64], header_pid[16];
- struct iovec iovec[5];
- struct msghdr msghdr;
- time_t t;
- struct tm *tm;
-
- if (syslog_fd < 0)
- return 0;
-
- snprintf(header_priority, sizeof(header_priority), "<%i>", level);
- char_array_0(header_priority);
-
- t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
- if (!(tm = localtime(&t)))
- return -EINVAL;
-
- if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
- return -EINVAL;
-
- snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) getpid());
- char_array_0(header_pid);
-
- zero(iovec);
- IOVEC_SET_STRING(iovec[0], header_priority);
- IOVEC_SET_STRING(iovec[1], header_time);
- IOVEC_SET_STRING(iovec[2], program_invocation_short_name);
- IOVEC_SET_STRING(iovec[3], header_pid);
- IOVEC_SET_STRING(iovec[4], buffer);
-
- /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
- if (syslog_is_stream)
- iovec[4].iov_len++;
-
- zero(msghdr);
- msghdr.msg_iov = iovec;
- msghdr.msg_iovlen = ELEMENTSOF(iovec);
-
- for (;;) {
- ssize_t n;
-
- n = sendmsg(syslog_fd, &msghdr, MSG_NOSIGNAL);
- if (n < 0)
- return -errno;
-
- if (!syslog_is_stream ||
- (size_t) n >= IOVEC_TOTAL_SIZE(iovec, ELEMENTSOF(iovec)))
- break;
-
- IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n);
- }
-
- return 1;
-}
-
-static int write_to_kmsg(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *buffer) {
-
- char header_priority[16], header_pid[16];
- struct iovec iovec[5];
-
- if (kmsg_fd < 0)
- return 0;
-
- snprintf(header_priority, sizeof(header_priority), "<%i>", level);
- char_array_0(header_priority);
-
- snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) getpid());
- char_array_0(header_pid);
-
- zero(iovec);
- IOVEC_SET_STRING(iovec[0], header_priority);
- IOVEC_SET_STRING(iovec[1], program_invocation_short_name);
- IOVEC_SET_STRING(iovec[2], header_pid);
- IOVEC_SET_STRING(iovec[3], buffer);
- IOVEC_SET_STRING(iovec[4], "\n");
-
- if (writev(kmsg_fd, iovec, ELEMENTSOF(iovec)) < 0)
- return -errno;
-
- return 1;
-}
-
-static int write_to_journal(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *buffer) {
-
- char header[LINE_MAX];
- struct iovec iovec[3];
- struct msghdr mh;
-
- if (journal_fd < 0)
- return 0;
-
- snprintf(header, sizeof(header),
- "PRIORITY=%i\n"
- "SYSLOG_FACILITY=%i\n"
- "CODE_FILE=%s\n"
- "CODE_LINE=%i\n"
- "CODE_FUNCTION=%s\n"
- "SYSLOG_IDENTIFIER=%s\n"
- "MESSAGE=",
- LOG_PRI(level),
- LOG_FAC(level),
- file,
- line,
- func,
- program_invocation_short_name);
-
- char_array_0(header);
-
- zero(iovec);
- IOVEC_SET_STRING(iovec[0], header);
- IOVEC_SET_STRING(iovec[1], buffer);
- IOVEC_SET_STRING(iovec[2], "\n");
-
- zero(mh);
- mh.msg_iov = iovec;
- mh.msg_iovlen = ELEMENTSOF(iovec);
-
- if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
- return -errno;
-
- return 1;
-}
-
-static int log_dispatch(
- int level,
- const char*file,
- int line,
- const char *func,
- char *buffer) {
-
- int r = 0;
-
- if (log_target == LOG_TARGET_NULL)
- return 0;
-
- /* Patch in LOG_DAEMON facility if necessary */
- if ((level & LOG_FACMASK) == 0)
- level = log_facility | LOG_PRI(level);
-
- do {
- char *e;
- int k = 0;
-
- buffer += strspn(buffer, NEWLINE);
-
- if (buffer[0] == 0)
- break;
-
- if ((e = strpbrk(buffer, NEWLINE)))
- *(e++) = 0;
-
- if (log_target == LOG_TARGET_AUTO ||
- log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
- log_target == LOG_TARGET_JOURNAL) {
-
- k = write_to_journal(level, file, line, func, buffer);
- if (k < 0) {
- if (k != -EAGAIN)
- log_close_journal();
- log_open_kmsg();
- } else if (k > 0)
- r++;
- }
-
- if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
- log_target == LOG_TARGET_SYSLOG) {
-
- k = write_to_syslog(level, file, line, func, buffer);
- if (k < 0) {
- if (k != -EAGAIN)
- log_close_syslog();
- log_open_kmsg();
- } else if (k > 0)
- r++;
- }
-
- if (k <= 0 &&
- (log_target == LOG_TARGET_AUTO ||
- log_target == LOG_TARGET_SAFE ||
- log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
- log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
- log_target == LOG_TARGET_KMSG)) {
-
- k = write_to_kmsg(level, file, line, func, buffer);
- if (k < 0) {
- log_close_kmsg();
- log_open_console();
- } else if (k > 0)
- r++;
- }
-
- if (k <= 0) {
- k = write_to_console(level, file, line, func, buffer);
- if (k < 0)
- return k;
- }
-
- buffer = e;
- } while (buffer);
-
- return r;
-}
-
-int log_dump_internal(
- int level,
- const char*file,
- int line,
- const char *func,
- char *buffer) {
-
- int saved_errno, r;
-
- /* This modifies the buffer... */
-
- if (_likely_(LOG_PRI(level) > log_max_level))
- return 0;
-
- saved_errno = errno;
- r = log_dispatch(level, file, line, func, buffer);
- errno = saved_errno;
-
- return r;
-}
-
-int log_metav(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *format,
- va_list ap) {
-
- char buffer[LINE_MAX];
- int saved_errno, r;
-
- if (_likely_(LOG_PRI(level) > log_max_level))
- return 0;
-
- saved_errno = errno;
- vsnprintf(buffer, sizeof(buffer), format, ap);
- char_array_0(buffer);
-
- r = log_dispatch(level, file, line, func, buffer);
- errno = saved_errno;
-
- return r;
-}
-
-int log_meta(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *format, ...) {
-
- int r;
- va_list ap;
-
- va_start(ap, format);
- r = log_metav(level, file, line, func, format, ap);
- va_end(ap);
-
- return r;
-}
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wformat-nonliteral"
-_noreturn_ static void log_assert(const char *text, const char *file, int line, const char *func, const char *format) {
- static char buffer[LINE_MAX];
-
- snprintf(buffer, sizeof(buffer), format, text, file, line, func);
-
- char_array_0(buffer);
- log_abort_msg = buffer;
-
- log_dispatch(LOG_CRIT, file, line, func, buffer);
- abort();
-}
-#pragma GCC diagnostic pop
-
-_noreturn_ void log_assert_failed(const char *text, const char *file, int line, const char *func) {
- log_assert(text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
-}
-
-_noreturn_ void log_assert_failed_unreachable(const char *text, const char *file, int line, const char *func) {
- log_assert(text, file, line, func, "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
-}
-
-int log_oom_internal(const char *file, int line, const char *func) {
- log_meta(LOG_ERR, file, line, func, "Out of memory.");
- return -ENOMEM;
-}
-
-int log_struct_internal(
- int level,
- const char *file,
- int line,
- const char *func,
- const char *format, ...) {
-
- int saved_errno;
- va_list ap;
- int r;
-
- if (_likely_(LOG_PRI(level) > log_max_level))
- return 0;
-
- if (log_target == LOG_TARGET_NULL)
- return 0;
-
- if ((level & LOG_FACMASK) == 0)
- level = log_facility | LOG_PRI(level);
-
- saved_errno = errno;
-
- if ((log_target == LOG_TARGET_AUTO ||
- log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
- log_target == LOG_TARGET_JOURNAL) &&
- journal_fd >= 0) {
-
- char header[LINE_MAX];
- struct iovec iovec[17];
- unsigned n = 0, i;
- struct msghdr mh;
- const char nl = '\n';
-
- /* If the journal is available do structured logging */
-
- snprintf(header, sizeof(header),
- "PRIORITY=%i\n"
- "SYSLOG_FACILITY=%i\n"
- "CODE_FILE=%s\n"
- "CODE_LINE=%i\n"
- "CODE_FUNCTION=%s\n"
- "SYSLOG_IDENTIFIER=%s\n",
- LOG_PRI(level),
- LOG_FAC(level),
- file,
- line,
- func,
- program_invocation_short_name);
- char_array_0(header);
-
- zero(iovec);
- IOVEC_SET_STRING(iovec[n++], header);
-
- va_start(ap, format);
- while (format && n + 1 < ELEMENTSOF(iovec)) {
- char *buf;
- va_list aq;
-
- /* We need to copy the va_list structure,
- * since vasprintf() leaves it afterwards at
- * an undefined location */
-
- va_copy(aq, ap);
- if (vasprintf(&buf, format, aq) < 0) {
- va_end(aq);
- r = -ENOMEM;
- goto finish;
- }
- va_end(aq);
-
- /* Now, jump enough ahead, so that we point to
- * the next format string */
- VA_FORMAT_ADVANCE(format, ap);
-
- IOVEC_SET_STRING(iovec[n++], buf);
-
- iovec[n].iov_base = (char*) &nl;
- iovec[n].iov_len = 1;
- n++;
-
- format = va_arg(ap, char *);
- }
-
- zero(mh);
- mh.msg_iov = iovec;
- mh.msg_iovlen = n;
-
- if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
- r = -errno;
- else
- r = 1;
-
- finish:
- va_end(ap);
- for (i = 1; i < n; i += 2)
- free(iovec[i].iov_base);
-
- } else {
- char buf[LINE_MAX];
- bool found = false;
-
- /* Fallback if journal logging is not available */
-
- va_start(ap, format);
- while (format) {
- va_list aq;
-
- va_copy(aq, ap);
- vsnprintf(buf, sizeof(buf), format, aq);
- va_end(aq);
- char_array_0(buf);
-
- if (startswith(buf, "MESSAGE=")) {
- found = true;
- break;
- }
-
- VA_FORMAT_ADVANCE(format, ap);
-
- format = va_arg(ap, char *);
- }
- va_end(ap);
-
- if (found)
- r = log_dispatch(level, file, line, func, buf + 8);
- else
- r = -EINVAL;
- }
-
- errno = saved_errno;
- return r;
-}
-
-int log_set_target_from_string(const char *e) {
- LogTarget t;
-
- t = log_target_from_string(e);
- if (t < 0)
- return -EINVAL;
-
- log_set_target(t);
- return 0;
-}
-
-int log_set_max_level_from_string(const char *e) {
- int t;
-
- t = log_level_from_string(e);
- if (t < 0)
- return t;
-
- log_set_max_level(t);
- return 0;
-}
-
-void log_parse_environment(void) {
- const char *e;
-
- e = secure_getenv("SYSTEMD_LOG_TARGET");
- if (e && log_set_target_from_string(e) < 0)
- log_warning("Failed to parse log target %s. Ignoring.", e);
-
- e = secure_getenv("SYSTEMD_LOG_LEVEL");
- if (e && log_set_max_level_from_string(e) < 0)
- log_warning("Failed to parse log level %s. Ignoring.", e);
-
- e = secure_getenv("SYSTEMD_LOG_COLOR");
- if (e && log_show_color_from_string(e) < 0)
- log_warning("Failed to parse bool %s. Ignoring.", e);
-
- e = secure_getenv("SYSTEMD_LOG_LOCATION");
- if (e && log_show_location_from_string(e) < 0)
- log_warning("Failed to parse bool %s. Ignoring.", e);
-}
-
-LogTarget log_get_target(void) {
- return log_target;
-}
-
-int log_get_max_level(void) {
- return log_max_level;
-}
-
-void log_show_color(bool b) {
- show_color = b;
-}
-
-void log_show_location(bool b) {
- show_location = b;
-}
-
-int log_show_color_from_string(const char *e) {
- int t;
-
- t = parse_boolean(e);
- if (t < 0)
- return t;
-
- log_show_color(t);
- return 0;
-}
-
-int log_show_location_from_string(const char *e) {
- int t;
-
- t = parse_boolean(e);
- if (t < 0)
- return t;
-
- log_show_location(t);
- return 0;
-}
-
-bool log_on_console(void) {
- if (log_target == LOG_TARGET_CONSOLE)
- return true;
-
- return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0;
-}
-
-static const char *const log_target_table[] = {
- [LOG_TARGET_CONSOLE] = "console",
- [LOG_TARGET_KMSG] = "kmsg",
- [LOG_TARGET_JOURNAL] = "journal",
- [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg",
- [LOG_TARGET_SYSLOG] = "syslog",
- [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg",
- [LOG_TARGET_AUTO] = "auto",
- [LOG_TARGET_SAFE] = "safe",
- [LOG_TARGET_NULL] = "null"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);
diff --git a/src/shared/log.h b/src/shared/log.h
deleted file mode 100644
index 1bd9dbf27a..0000000000
--- a/src/shared/log.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*-*- 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 <syslog.h>
-#include <stdbool.h>
-#include <stdarg.h>
-#include <errno.h>
-
-#include "macro.h"
-
-typedef enum LogTarget{
- LOG_TARGET_CONSOLE,
- LOG_TARGET_KMSG,
- LOG_TARGET_JOURNAL,
- LOG_TARGET_JOURNAL_OR_KMSG,
- LOG_TARGET_SYSLOG,
- LOG_TARGET_SYSLOG_OR_KMSG,
- LOG_TARGET_AUTO, /* console if stderr is tty, JOURNAL_OR_KMSG otherwise */
- LOG_TARGET_SAFE, /* console if stderr is tty, KMSG otherwise */
- LOG_TARGET_NULL,
- _LOG_TARGET_MAX,
- _LOG_TARGET_INVALID = -1
-} LogTarget;
-
-void log_set_target(LogTarget target);
-void log_set_max_level(int level);
-void log_set_facility(int facility);
-
-int log_set_target_from_string(const char *e);
-int log_set_max_level_from_string(const char *e);
-
-void log_show_color(bool b);
-void log_show_location(bool b);
-
-int log_show_color_from_string(const char *e);
-int log_show_location_from_string(const char *e);
-
-LogTarget log_get_target(void);
-int log_get_max_level(void);
-
-int log_open(void);
-void log_close(void);
-void log_forget_fds(void);
-
-void log_close_syslog(void);
-void log_close_journal(void);
-void log_close_kmsg(void);
-void log_close_console(void);
-
-void log_parse_environment(void);
-
-int log_meta(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *format, ...) _printf_attr_(5,6);
-
-int log_metav(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *format,
- va_list ap);
-
-int log_struct_internal(
- int level,
- const char *file,
- int line,
- const char *func,
- const char *format, ...) _sentinel_;
-
-int log_oom_internal(
- const char *file,
- int line,
- const char *func);
-
-/* This modifies the buffer passed! */
-int log_dump_internal(
- int level,
- const char*file,
- int line,
- const char *func,
- char *buffer);
-
-_noreturn_ void log_assert_failed(
- const char *text,
- const char *file,
- int line,
- const char *func);
-
-_noreturn_ void log_assert_failed_unreachable(
- const char *text,
- const char *file,
- int line,
- const char *func);
-
-#define log_full(level, ...) log_meta(level, __FILE__, __LINE__, __func__, __VA_ARGS__)
-
-#define log_debug(...) log_meta(LOG_DEBUG, __FILE__, __LINE__, __func__, __VA_ARGS__)
-#define log_info(...) log_meta(LOG_INFO, __FILE__, __LINE__, __func__, __VA_ARGS__)
-#define log_notice(...) log_meta(LOG_NOTICE, __FILE__, __LINE__, __func__, __VA_ARGS__)
-#define log_warning(...) log_meta(LOG_WARNING, __FILE__, __LINE__, __func__, __VA_ARGS__)
-#define log_error(...) log_meta(LOG_ERR, __FILE__, __LINE__, __func__, __VA_ARGS__)
-
-#define log_struct(level, ...) log_struct_internal(level, __FILE__, __LINE__, __func__, __VA_ARGS__)
-
-#define log_oom() log_oom_internal(__FILE__, __LINE__, __func__)
-
-/* This modifies the buffer passed! */
-#define log_dump(level, buffer) log_dump_internal(level, __FILE__, __LINE__, __func__, buffer)
-
-bool log_on_console(void);
-
-const char *log_target_to_string(LogTarget target);
-LogTarget log_target_from_string(const char *s);
-
-#define MESSAGE_ID(x) "MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(x)
diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c
deleted file mode 100644
index 36cce73550..0000000000
--- a/src/shared/logs-show.c
+++ /dev/null
@@ -1,904 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <time.h>
-#include <assert.h>
-#include <errno.h>
-#include <sys/poll.h>
-#include <string.h>
-
-#include "logs-show.h"
-#include "log.h"
-#include "util.h"
-#include "utf8.h"
-#include "hashmap.h"
-
-#define PRINT_THRESHOLD 128
-#define JSON_THRESHOLD 4096
-
-static int parse_field(const void *data, size_t length, const char *field, char **target, size_t *target_size) {
- size_t fl, nl;
- void *buf;
-
- assert(data);
- assert(field);
- assert(target);
- assert(target_size);
-
- fl = strlen(field);
- if (length < fl)
- return 0;
-
- if (memcmp(data, field, fl))
- return 0;
-
- nl = length - fl;
- buf = malloc(nl+1);
- if (!buf)
- return log_oom();
-
- memcpy(buf, (const char*) data + fl, nl);
- ((char*)buf)[nl] = 0;
-
- free(*target);
- *target = buf;
- *target_size = nl;
-
- return 1;
-}
-
-static bool shall_print(const char *p, size_t l, OutputFlags flags) {
- assert(p);
-
- if (flags & OUTPUT_SHOW_ALL)
- return true;
-
- if (l > PRINT_THRESHOLD)
- return false;
-
- if (!utf8_is_printable_n(p, l))
- return false;
-
- return true;
-}
-
-static int output_short(
- FILE *f,
- sd_journal *j,
- OutputMode mode,
- unsigned n_columns,
- OutputFlags flags) {
-
- int r;
- const void *data;
- size_t length;
- size_t n = 0;
- _cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL;
- size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, realtime_len = 0, monotonic_len = 0, priority_len = 0;
- int p = LOG_INFO;
- const char *color_on = "", *color_off = "";
-
- assert(f);
- assert(j);
-
- SD_JOURNAL_FOREACH_DATA(j, data, length) {
-
- r = parse_field(data, length, "PRIORITY=", &priority, &priority_len);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- r = parse_field(data, length, "_HOSTNAME=", &hostname, &hostname_len);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- r = parse_field(data, length, "SYSLOG_IDENTIFIER=", &identifier, &identifier_len);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- r = parse_field(data, length, "_COMM=", &comm, &comm_len);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- r = parse_field(data, length, "_PID=", &pid, &pid_len);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- r = parse_field(data, length, "SYSLOG_PID=", &fake_pid, &fake_pid_len);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- r = parse_field(data, length, "_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- r = parse_field(data, length, "MESSAGE=", &message, &message_len);
- if (r < 0)
- return r;
- }
-
- if (!message)
- return 0;
-
- if (priority_len == 1 && *priority >= '0' && *priority <= '7')
- p = *priority - '0';
-
- if (mode == OUTPUT_SHORT_MONOTONIC) {
- uint64_t t;
- sd_id128_t boot_id;
-
- r = -ENOENT;
-
- if (monotonic)
- r = safe_atou64(monotonic, &t);
-
- if (r < 0)
- r = sd_journal_get_monotonic_usec(j, &t, &boot_id);
-
- if (r < 0) {
- log_error("Failed to get monotonic: %s", strerror(-r));
- return r;
- }
-
- fprintf(f, "[%5llu.%06llu]",
- (unsigned long long) (t / USEC_PER_SEC),
- (unsigned long long) (t % USEC_PER_SEC));
-
- n += 1 + 5 + 1 + 6 + 1;
-
- } else {
- char buf[64];
- uint64_t x;
- time_t t;
- struct tm tm;
-
- r = -ENOENT;
-
- if (realtime)
- r = safe_atou64(realtime, &x);
-
- if (r < 0)
- r = sd_journal_get_realtime_usec(j, &x);
-
- if (r < 0) {
- log_error("Failed to get realtime: %s", strerror(-r));
- return r;
- }
-
- t = (time_t) (x / USEC_PER_SEC);
- if (strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm)) <= 0) {
- log_error("Failed to format time.");
- return r;
- }
-
- fputs(buf, f);
- n += strlen(buf);
- }
-
- if (hostname && shall_print(hostname, hostname_len, flags)) {
- fprintf(f, " %.*s", (int) hostname_len, hostname);
- n += hostname_len + 1;
- }
-
- if (identifier && shall_print(identifier, identifier_len, flags)) {
- fprintf(f, " %.*s", (int) identifier_len, identifier);
- n += identifier_len + 1;
- } else if (comm && shall_print(comm, comm_len, flags)) {
- fprintf(f, " %.*s", (int) comm_len, comm);
- n += comm_len + 1;
- } else
- fputc(' ', f);
-
- if (pid && shall_print(pid, pid_len, flags)) {
- fprintf(f, "[%.*s]", (int) pid_len, pid);
- n += pid_len + 2;
- } else if (fake_pid && shall_print(fake_pid, fake_pid_len, flags)) {
- fprintf(f, "[%.*s]", (int) fake_pid_len, fake_pid);
- n += fake_pid_len + 2;
- }
-
- if (flags & OUTPUT_COLOR) {
- if (p <= LOG_ERR) {
- color_on = ANSI_HIGHLIGHT_RED_ON;
- color_off = ANSI_HIGHLIGHT_OFF;
- } else if (p <= LOG_NOTICE) {
- color_on = ANSI_HIGHLIGHT_ON;
- color_off = ANSI_HIGHLIGHT_OFF;
- }
- }
-
- if (flags & OUTPUT_SHOW_ALL)
- fprintf(f, ": %s%.*s%s\n", color_on, (int) message_len, message, color_off);
- else if (!utf8_is_printable_n(message, message_len)) {
- char bytes[FORMAT_BYTES_MAX];
- fprintf(f, ": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len));
- } else if ((flags & OUTPUT_FULL_WIDTH) || (message_len + n + 1 < n_columns))
- fprintf(f, ": %s%.*s%s\n", color_on, (int) message_len, message, color_off);
- else if (n < n_columns && n_columns - n - 2 >= 3) {
- char *e;
-
- e = ellipsize_mem(message, message_len, n_columns - n - 2, 90);
-
- if (!e)
- fprintf(f, ": %s%.*s%s\n", color_on, (int) message_len, message, color_off);
- else
- fprintf(f, ": %s%s%s\n", color_on, e, color_off);
-
- free(e);
- } else
- fputs("\n", f);
-
- return 0;
-}
-
-static int output_verbose(
- FILE *f,
- sd_journal *j,
- OutputMode mode,
- unsigned n_columns,
- OutputFlags flags) {
-
- const void *data;
- size_t length;
- char *cursor;
- uint64_t realtime;
- char ts[FORMAT_TIMESTAMP_MAX];
- int r;
-
- assert(f);
- assert(j);
-
- r = sd_journal_get_realtime_usec(j, &realtime);
- if (r < 0) {
- log_error("Failed to get realtime timestamp: %s", strerror(-r));
- return r;
- }
-
- r = sd_journal_get_cursor(j, &cursor);
- if (r < 0) {
- log_error("Failed to get cursor: %s", strerror(-r));
- return r;
- }
-
- fprintf(f, "%s [%s]\n",
- format_timestamp(ts, sizeof(ts), realtime),
- cursor);
-
- free(cursor);
-
- SD_JOURNAL_FOREACH_DATA(j, data, length) {
- if (!shall_print(data, length, flags)) {
- const char *c;
- char bytes[FORMAT_BYTES_MAX];
-
- c = memchr(data, '=', length);
- if (!c) {
- log_error("Invalid field.");
- return -EINVAL;
- }
-
- fprintf(f, "\t%.*s=[%s blob data]\n",
- (int) (c - (const char*) data),
- (const char*) data,
- format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1));
- } else
- fprintf(f, "\t%.*s\n", (int) length, (const char*) data);
- }
-
- return 0;
-}
-
-static int output_export(
- FILE *f,
- sd_journal *j,
- OutputMode mode,
- unsigned n_columns,
- OutputFlags flags) {
-
- sd_id128_t boot_id;
- char sid[33];
- int r;
- usec_t realtime, monotonic;
- char *cursor;
- const void *data;
- size_t length;
-
- assert(j);
-
- r = sd_journal_get_realtime_usec(j, &realtime);
- if (r < 0) {
- log_error("Failed to get realtime timestamp: %s", strerror(-r));
- return r;
- }
-
- r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
- if (r < 0) {
- log_error("Failed to get monotonic timestamp: %s", strerror(-r));
- return r;
- }
-
- r = sd_journal_get_cursor(j, &cursor);
- if (r < 0) {
- log_error("Failed to get cursor: %s", strerror(-r));
- return r;
- }
-
- fprintf(f,
- "__CURSOR=%s\n"
- "__REALTIME_TIMESTAMP=%llu\n"
- "__MONOTONIC_TIMESTAMP=%llu\n"
- "_BOOT_ID=%s\n",
- cursor,
- (unsigned long long) realtime,
- (unsigned long long) monotonic,
- sd_id128_to_string(boot_id, sid));
-
- free(cursor);
-
- SD_JOURNAL_FOREACH_DATA(j, data, length) {
-
- /* We already printed the boot id, from the data in
- * the header, hence let's suppress it here */
- if (length >= 9 &&
- memcmp(data, "_BOOT_ID=", 9) == 0)
- continue;
-
- if (!utf8_is_printable_n(data, length)) {
- const char *c;
- uint64_t le64;
-
- c = memchr(data, '=', length);
- if (!c) {
- log_error("Invalid field.");
- return -EINVAL;
- }
-
- fwrite(data, c - (const char*) data, 1, f);
- fputc('\n', f);
- le64 = htole64(length - (c - (const char*) data) - 1);
- fwrite(&le64, sizeof(le64), 1, f);
- fwrite(c + 1, length - (c - (const char*) data) - 1, 1, f);
- } else
- fwrite(data, length, 1, f);
-
- fputc('\n', f);
- }
-
- fputc('\n', f);
-
- return 0;
-}
-
-void json_escape(
- FILE *f,
- const char* p,
- size_t l,
- OutputFlags flags) {
-
- assert(f);
- assert(p);
-
- if (!(flags & OUTPUT_SHOW_ALL) && l > JSON_THRESHOLD)
-
- fputs("null", f);
-
- else if (!utf8_is_printable_n(p, l)) {
- bool not_first = false;
-
- fputs("[ ", f);
-
- while (l > 0) {
- if (not_first)
- fprintf(f, ", %u", (uint8_t) *p);
- else {
- not_first = true;
- fprintf(f, "%u", (uint8_t) *p);
- }
-
- p++;
- l--;
- }
-
- fputs(" ]", f);
- } else {
- fputc('\"', f);
-
- while (l > 0) {
- if (*p == '"' || *p == '\\') {
- fputc('\\', f);
- fputc(*p, f);
- } else if (*p < ' ')
- fprintf(f, "\\u%04x", *p);
- else
- fputc(*p, f);
-
- p++;
- l--;
- }
-
- fputc('\"', f);
- }
-}
-
-static int output_json(
- FILE *f,
- sd_journal *j,
- OutputMode mode,
- unsigned n_columns,
- OutputFlags flags) {
-
- uint64_t realtime, monotonic;
- char *cursor, *k;
- const void *data;
- size_t length;
- sd_id128_t boot_id;
- char sid[33];
- int r;
- Hashmap *h = NULL;
- bool done, separator;
-
- assert(j);
-
- r = sd_journal_get_realtime_usec(j, &realtime);
- if (r < 0) {
- log_error("Failed to get realtime timestamp: %s", strerror(-r));
- return r;
- }
-
- r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
- if (r < 0) {
- log_error("Failed to get monotonic timestamp: %s", strerror(-r));
- return r;
- }
-
- r = sd_journal_get_cursor(j, &cursor);
- if (r < 0) {
- log_error("Failed to get cursor: %s", strerror(-r));
- return r;
- }
-
- if (mode == OUTPUT_JSON_PRETTY)
- fprintf(f,
- "{\n"
- "\t\"__CURSOR\" : \"%s\",\n"
- "\t\"__REALTIME_TIMESTAMP\" : \"%llu\",\n"
- "\t\"__MONOTONIC_TIMESTAMP\" : \"%llu\",\n"
- "\t\"_BOOT_ID\" : \"%s\"",
- cursor,
- (unsigned long long) realtime,
- (unsigned long long) monotonic,
- sd_id128_to_string(boot_id, sid));
- else {
- if (mode == OUTPUT_JSON_SSE)
- fputs("data: ", f);
-
- fprintf(f,
- "{ \"__CURSOR\" : \"%s\", "
- "\"__REALTIME_TIMESTAMP\" : \"%llu\", "
- "\"__MONOTONIC_TIMESTAMP\" : \"%llu\", "
- "\"_BOOT_ID\" : \"%s\"",
- cursor,
- (unsigned long long) realtime,
- (unsigned long long) monotonic,
- sd_id128_to_string(boot_id, sid));
- }
- free(cursor);
-
- h = hashmap_new(string_hash_func, string_compare_func);
- if (!h)
- return -ENOMEM;
-
- /* First round, iterate through the entry and count how often each field appears */
- SD_JOURNAL_FOREACH_DATA(j, data, length) {
- const char *eq;
- char *n;
- unsigned u;
-
- if (length >= 9 &&
- memcmp(data, "_BOOT_ID=", 9) == 0)
- continue;
-
- eq = memchr(data, '=', length);
- if (!eq)
- continue;
-
- n = strndup(data, eq - (const char*) data);
- if (!n) {
- r = -ENOMEM;
- goto finish;
- }
-
- u = PTR_TO_UINT(hashmap_get(h, n));
- if (u == 0) {
- r = hashmap_put(h, n, UINT_TO_PTR(1));
- if (r < 0) {
- free(n);
- goto finish;
- }
- } else {
- r = hashmap_update(h, n, UINT_TO_PTR(u + 1));
- free(n);
- if (r < 0)
- goto finish;
- }
- }
-
- separator = true;
- do {
- done = true;
-
- SD_JOURNAL_FOREACH_DATA(j, data, length) {
- const char *eq;
- char *kk, *n;
- size_t m;
- unsigned u;
-
- /* We already printed the boot id, from the data in
- * the header, hence let's suppress it here */
- if (length >= 9 &&
- memcmp(data, "_BOOT_ID=", 9) == 0)
- continue;
-
- eq = memchr(data, '=', length);
- if (!eq)
- continue;
-
- if (separator) {
- if (mode == OUTPUT_JSON_PRETTY)
- fputs(",\n\t", f);
- else
- fputs(", ", f);
- }
-
- m = eq - (const char*) data;
-
- n = strndup(data, m);
- if (!n) {
- r = -ENOMEM;
- goto finish;
- }
-
- u = PTR_TO_UINT(hashmap_get2(h, n, (void**) &kk));
- if (u == 0) {
- /* We already printed this, let's jump to the next */
- free(n);
- separator = false;
-
- continue;
- } else if (u == 1) {
- /* Field only appears once, output it directly */
-
- json_escape(f, data, m, flags);
- fputs(" : ", f);
-
- json_escape(f, eq + 1, length - m - 1, flags);
-
- hashmap_remove(h, n);
- free(kk);
- free(n);
-
- separator = true;
-
- continue;
-
- } else {
- /* Field appears multiple times, output it as array */
- json_escape(f, data, m, flags);
- fputs(" : [ ", f);
- json_escape(f, eq + 1, length - m - 1, flags);
-
- /* Iterate through the end of the list */
-
- while (sd_journal_enumerate_data(j, &data, &length) > 0) {
- if (length < m + 1)
- continue;
-
- if (memcmp(data, n, m) != 0)
- continue;
-
- if (((const char*) data)[m] != '=')
- continue;
-
- fputs(", ", f);
- json_escape(f, (const char*) data + m + 1, length - m - 1, flags);
- }
-
- fputs(" ]", f);
-
- hashmap_remove(h, n);
- free(kk);
- free(n);
-
- /* Iterate data fields form the beginning */
- done = false;
- separator = true;
-
- break;
- }
- }
-
- } while (!done);
-
- if (mode == OUTPUT_JSON_PRETTY)
- fputs("\n}\n", f);
- else if (mode == OUTPUT_JSON_SSE)
- fputs("}\n\n", f);
- else
- fputs(" }\n", f);
-
- r = 0;
-
-finish:
- while ((k = hashmap_steal_first_key(h)))
- free(k);
-
- hashmap_free(h);
-
- return r;
-}
-
-static int output_cat(
- FILE *f,
- sd_journal *j,
- OutputMode mode,
- unsigned n_columns,
- OutputFlags flags) {
-
- const void *data;
- size_t l;
- int r;
-
- assert(j);
- assert(f);
-
- r = sd_journal_get_data(j, "MESSAGE", &data, &l);
- if (r < 0) {
- /* An entry without MESSAGE=? */
- if (r == -ENOENT)
- return 0;
-
- log_error("Failed to get data: %s", strerror(-r));
- return r;
- }
-
- assert(l >= 8);
-
- fwrite((const char*) data + 8, 1, l - 8, f);
- fputc('\n', f);
-
- return 0;
-}
-
-static int (*output_funcs[_OUTPUT_MODE_MAX])(
- FILE *f,
- sd_journal*j,
- OutputMode mode,
- unsigned n_columns,
- OutputFlags flags) = {
-
- [OUTPUT_SHORT] = output_short,
- [OUTPUT_SHORT_MONOTONIC] = output_short,
- [OUTPUT_VERBOSE] = output_verbose,
- [OUTPUT_EXPORT] = output_export,
- [OUTPUT_JSON] = output_json,
- [OUTPUT_JSON_PRETTY] = output_json,
- [OUTPUT_JSON_SSE] = output_json,
- [OUTPUT_CAT] = output_cat
-};
-
-int output_journal(
- FILE *f,
- sd_journal *j,
- OutputMode mode,
- unsigned n_columns,
- OutputFlags flags) {
-
- int ret;
- assert(mode >= 0);
- assert(mode < _OUTPUT_MODE_MAX);
-
- if (n_columns <= 0)
- n_columns = columns();
-
- ret = output_funcs[mode](f, j, mode, n_columns, flags);
- fflush(stdout);
- return ret;
-}
-
-int show_journal_by_unit(
- FILE *f,
- const char *unit,
- OutputMode mode,
- unsigned n_columns,
- usec_t not_before,
- unsigned how_many,
- OutputFlags flags) {
-
- _cleanup_free_ char *m1 = NULL, *m2 = NULL, *m3 = NULL;
- sd_journal *j = NULL;
- int r;
- unsigned line = 0;
- bool need_seek = false;
- int warn_cutoff = flags & OUTPUT_WARN_CUTOFF;
-
- assert(mode >= 0);
- assert(mode < _OUTPUT_MODE_MAX);
- assert(unit);
-
- if (!endswith(unit, ".service") &&
- !endswith(unit, ".socket") &&
- !endswith(unit, ".mount") &&
- !endswith(unit, ".swap"))
- return 0;
-
- if (how_many <= 0)
- return 0;
-
- if (asprintf(&m1, "_SYSTEMD_UNIT=%s", unit) < 0 ||
- asprintf(&m2, "COREDUMP_UNIT=%s", unit) < 0 ||
- asprintf(&m3, "UNIT=%s", unit) < 0) {
- r = -ENOMEM;
- goto finish;
- }
-
- r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM_ONLY);
- if (r < 0)
- goto finish;
-
- /* Look for messages from the service itself */
- r = sd_journal_add_match(j, m1, 0);
- if (r < 0)
- goto finish;
-
- /* Look for coredumps of the service */
- r = sd_journal_add_disjunction(j);
- if (r < 0)
- goto finish;
- r = sd_journal_add_match(j, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0);
- if (r < 0)
- goto finish;
- r = sd_journal_add_match(j, m2, 0);
- if (r < 0)
- goto finish;
-
- /* Look for messages from PID 1 about this service */
- r = sd_journal_add_disjunction(j);
- if (r < 0)
- goto finish;
- r = sd_journal_add_match(j, "_PID=1", 0);
- if (r < 0)
- goto finish;
- r = sd_journal_add_match(j, m3, 0);
- if (r < 0)
- goto finish;
-
- /* Seek to end */
- r = sd_journal_seek_tail(j);
- if (r < 0)
- goto finish;
-
- r = sd_journal_previous_skip(j, how_many);
- if (r < 0)
- goto finish;
-
- for (;;) {
- for (;;) {
- usec_t usec;
-
- if (need_seek) {
- r = sd_journal_next(j);
- if (r < 0)
- goto finish;
- }
-
- if (r == 0)
- break;
-
- need_seek = true;
-
- if (not_before > 0) {
- r = sd_journal_get_monotonic_usec(j, &usec, NULL);
-
- /* -ESTALE is returned if the
- timestamp is not from this boot */
- if (r == -ESTALE)
- continue;
- else if (r < 0)
- goto finish;
-
- if (usec < not_before)
- continue;
- }
-
- line ++;
-
- r = output_journal(f, j, mode, n_columns, flags);
- if (r < 0)
- goto finish;
- }
-
- if (warn_cutoff && line < how_many && not_before > 0) {
- sd_id128_t boot_id;
- usec_t cutoff;
-
- /* Check whether the cutoff line is too early */
-
- r = sd_id128_get_boot(&boot_id);
- if (r < 0)
- goto finish;
-
- r = sd_journal_get_cutoff_monotonic_usec(j, boot_id, &cutoff, NULL);
- if (r < 0)
- goto finish;
-
- if (r > 0 && not_before < cutoff)
- fprintf(f, "Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n");
-
- warn_cutoff = false;
- }
-
- if (!(flags & OUTPUT_FOLLOW))
- break;
-
- r = sd_journal_wait(j, (usec_t) -1);
- if (r < 0)
- goto finish;
-
- }
-
-finish:
- if (j)
- sd_journal_close(j);
-
- return r;
-}
-
-static const char *const output_mode_table[_OUTPUT_MODE_MAX] = {
- [OUTPUT_SHORT] = "short",
- [OUTPUT_SHORT_MONOTONIC] = "short-monotonic",
- [OUTPUT_VERBOSE] = "verbose",
- [OUTPUT_EXPORT] = "export",
- [OUTPUT_JSON] = "json",
- [OUTPUT_JSON_PRETTY] = "json-pretty",
- [OUTPUT_JSON_SSE] = "json-sse",
- [OUTPUT_CAT] = "cat"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode);
diff --git a/src/shared/logs-show.h b/src/shared/logs-show.h
deleted file mode 100644
index 06082800c8..0000000000
--- a/src/shared/logs-show.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdbool.h>
-
-#include <systemd/sd-journal.h>
-
-#include "util.h"
-
-typedef enum OutputMode {
- OUTPUT_SHORT,
- OUTPUT_SHORT_MONOTONIC,
- OUTPUT_VERBOSE,
- OUTPUT_EXPORT,
- OUTPUT_JSON,
- OUTPUT_JSON_PRETTY,
- OUTPUT_JSON_SSE,
- OUTPUT_CAT,
- _OUTPUT_MODE_MAX,
- _OUTPUT_MODE_INVALID = -1
-} OutputMode;
-
-typedef enum OutputFlags {
- OUTPUT_SHOW_ALL = 1 << 0,
- OUTPUT_FOLLOW = 1 << 1,
- OUTPUT_WARN_CUTOFF = 1 << 2,
- OUTPUT_FULL_WIDTH = 1 << 3,
- OUTPUT_COLOR = 1 << 4
-} OutputFlags;
-
-int output_journal(
- FILE *f,
- sd_journal *j,
- OutputMode mode,
- unsigned n_columns,
- OutputFlags flags);
-
-int show_journal_by_unit(
- FILE *f,
- const char *unit,
- OutputMode mode,
- unsigned n_columns,
- usec_t not_before,
- unsigned how_many,
- OutputFlags flags);
-
-void json_escape(
- FILE *f,
- const char* p,
- size_t l,
- OutputFlags flags);
-
-const char* output_mode_to_string(OutputMode m);
-OutputMode output_mode_from_string(const char *s);
diff --git a/src/shared/macro.h b/src/shared/macro.h
deleted file mode 100644
index e930fdab53..0000000000
--- a/src/shared/macro.h
+++ /dev/null
@@ -1,242 +0,0 @@
-/*-*- 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 <assert.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <inttypes.h>
-
-#define _printf_attr_(a,b) __attribute__ ((format (printf, a, b)))
-#define _sentinel_ __attribute__ ((sentinel))
-#define _noreturn_ __attribute__((noreturn))
-#define _unused_ __attribute__ ((unused))
-#define _destructor_ __attribute__ ((destructor))
-#define _pure_ __attribute__ ((pure))
-#define _const_ __attribute__ ((const))
-#define _deprecated_ __attribute__ ((deprecated))
-#define _packed_ __attribute__ ((packed))
-#define _malloc_ __attribute__ ((malloc))
-#define _weak_ __attribute__ ((weak))
-#define _likely_(x) (__builtin_expect(!!(x),1))
-#define _unlikely_(x) (__builtin_expect(!!(x),0))
-#define _public_ __attribute__ ((visibility("default")))
-#define _hidden_ __attribute__ ((visibility("hidden")))
-#define _weakref_(x) __attribute__((weakref(#x)))
-#define _introspect_(x) __attribute__((section("introspect." x)))
-#define _alignas_(x) __attribute__((aligned(__alignof(x))))
-
-#define XSTRINGIFY(x) #x
-#define STRINGIFY(x) XSTRINGIFY(x)
-
-/* Rounds up */
-#define ALIGN(l) ALIGN_TO((l), sizeof(void*))
-static inline size_t ALIGN_TO(size_t l, size_t ali) {
- return ((l + ali - 1) & ~(ali - 1));
-}
-
-#define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))
-
-/*
- * container_of - cast a member of a structure out to the containing structure
- * @ptr: the pointer to the member.
- * @type: the type of the container struct this is embedded in.
- * @member: the name of the member within the struct.
- *
- */
-#define container_of(ptr, type, member) ({ \
- const typeof( ((type *)0)->member ) *__mptr = (ptr); \
- (type *)( (char *)__mptr - offsetof(type,member) );})
-
-#ifndef MAX
-#define MAX(a,b) \
- __extension__ ({ \
- typeof(a) _a = (a); \
- typeof(b) _b = (b); \
- _a > _b ? _a : _b; \
- })
-#endif
-
-#define MAX3(a,b,c) \
- MAX(MAX(a,b),c)
-
-#ifndef MIN
-#define MIN(a,b) \
- __extension__ ({ \
- typeof(a) _a = (a); \
- typeof(b) _b = (b); \
- _a < _b ? _a : _b; \
- })
-#endif
-
-#define MIN3(a,b,c) \
- MIN(MIN(a,b),c)
-
-#define CLAMP(x, low, high) \
- __extension__ ({ \
- typeof(x) _x = (x); \
- typeof(low) _low = (low); \
- typeof(high) _high = (high); \
- ((_x > _high) ? _high : ((_x < _low) ? _low : _x)); \
- })
-
-#define assert_se(expr) \
- do { \
- if (_unlikely_(!(expr))) \
- log_assert_failed(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
- } while (false) \
-
-/* We override the glibc assert() here. */
-#undef assert
-#ifdef NDEBUG
-#define assert(expr) do {} while(false)
-#else
-#define assert(expr) assert_se(expr)
-#endif
-
-#define assert_not_reached(t) \
- do { \
- log_assert_failed_unreachable(t, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
- } while (false)
-
-#define assert_cc(expr) \
- do { \
- switch (0) { \
- case 0: \
- case !!(expr): \
- ; \
- } \
- } while (false)
-
-#define PTR_TO_UINT(p) ((unsigned int) ((uintptr_t) (p)))
-#define UINT_TO_PTR(u) ((void*) ((uintptr_t) (u)))
-
-#define PTR_TO_UINT32(p) ((uint32_t) ((uintptr_t) (p)))
-#define UINT32_TO_PTR(u) ((void*) ((uintptr_t) (u)))
-
-#define PTR_TO_ULONG(p) ((unsigned long) ((uintptr_t) (p)))
-#define ULONG_TO_PTR(u) ((void*) ((uintptr_t) (u)))
-
-#define PTR_TO_INT(p) ((int) ((intptr_t) (p)))
-#define INT_TO_PTR(u) ((void*) ((intptr_t) (u)))
-
-#define TO_INT32(p) ((int32_t) ((intptr_t) (p)))
-#define INT32_TO_PTR(u) ((void*) ((intptr_t) (u)))
-
-#define PTR_TO_LONG(p) ((long) ((intptr_t) (p)))
-#define LONG_TO_PTR(u) ((void*) ((intptr_t) (u)))
-
-#define memzero(x,l) (memset((x), 0, (l)))
-#define zero(x) (memzero(&(x), sizeof(x)))
-
-#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 _cleanup_free_ __attribute__((cleanup(freep)))
-#define _cleanup_fclose_ __attribute__((cleanup(fclosep)))
-#define _cleanup_close_ __attribute__((cleanup(closep)))
-#define _cleanup_closedir_ __attribute__((cleanup(closedirp)))
-#define _cleanup_umask_ __attribute__((cleanup(umaskp)))
-#define _cleanup_strv_free_ __attribute__((cleanup(strv_freep)))
-
-#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)
-
-#include "log.h"
diff --git a/src/shared/missing.h b/src/shared/missing.h
deleted file mode 100644
index 3777cf69b2..0000000000
--- a/src/shared/missing.h
+++ /dev/null
@@ -1,255 +0,0 @@
-/*-*- 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/>.
-***/
-
-/* Missing glibc definitions to access certain kernel APIs */
-
-#include <sys/resource.h>
-#include <sys/syscall.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <linux/oom.h>
-
-#ifdef HAVE_AUDIT
-#include <libaudit.h>
-#endif
-
-#include "macro.h"
-
-#ifdef ARCH_MIPS
-#include <asm/sgidefs.h>
-#endif
-
-#ifndef RLIMIT_RTTIME
-#define RLIMIT_RTTIME 15
-#endif
-
-#ifndef F_LINUX_SPECIFIC_BASE
-#define F_LINUX_SPECIFIC_BASE 1024
-#endif
-
-#ifndef F_SETPIPE_SZ
-#define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7)
-#endif
-
-#ifndef F_GETPIPE_SZ
-#define F_GETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 8)
-#endif
-
-#ifndef IP_FREEBIND
-#define IP_FREEBIND 15
-#endif
-
-#ifndef OOM_SCORE_ADJ_MIN
-#define OOM_SCORE_ADJ_MIN (-1000)
-#endif
-
-#ifndef OOM_SCORE_ADJ_MAX
-#define OOM_SCORE_ADJ_MAX 1000
-#endif
-
-#ifndef AUDIT_SERVICE_START
-#define AUDIT_SERVICE_START 1130 /* Service (daemon) start */
-#endif
-
-#ifndef AUDIT_SERVICE_STOP
-#define AUDIT_SERVICE_STOP 1131 /* Service (daemon) stop */
-#endif
-
-#ifndef TIOCVHANGUP
-#define TIOCVHANGUP 0x5437
-#endif
-
-#ifndef IP_TRANSPARENT
-#define IP_TRANSPARENT 19
-#endif
-
-#if !HAVE_DECL_PIVOT_ROOT
-static inline int pivot_root(const char *new_root, const char *put_old) {
- return syscall(SYS_pivot_root, new_root, put_old);
-}
-#endif
-
-#ifdef __x86_64__
-# ifndef __NR_fanotify_init
-# define __NR_fanotify_init 300
-# endif
-# ifndef __NR_fanotify_mark
-# define __NR_fanotify_mark 301
-# endif
-#elif defined _MIPS_SIM
-# if _MIPS_SIM == _MIPS_SIM_ABI32
-# ifndef __NR_fanotify_init
-# define __NR_fanotify_init 4336
-# endif
-# ifndef __NR_fanotify_mark
-# define __NR_fanotify_mark 4337
-# endif
-# elif _MIPS_SIM == _MIPS_SIM_NABI32
-# ifndef __NR_fanotify_init
-# define __NR_fanotify_init 6300
-# endif
-# ifndef __NR_fanotify_mark
-# define __NR_fanotify_mark 6301
-# endif
-# elif _MIPS_SIM == _MIPS_SIM_ABI64
-# ifndef __NR_fanotify_init
-# define __NR_fanotify_init 5295
-# endif
-# ifndef __NR_fanotify_mark
-# define __NR_fanotify_mark 5296
-# endif
-# endif
-#else
-# ifndef __NR_fanotify_init
-# define __NR_fanotify_init 338
-# endif
-# ifndef __NR_fanotify_mark
-# define __NR_fanotify_mark 339
-# endif
-#endif
-
-#ifndef HAVE_FANOTIFY_INIT
-static inline int fanotify_init(unsigned int flags, unsigned int event_f_flags) {
- return syscall(__NR_fanotify_init, flags, event_f_flags);
-}
-#endif
-
-#ifndef HAVE_FANOTIFY_MARK
-static inline int fanotify_mark(int fanotify_fd, unsigned int flags, uint64_t mask,
- int dfd, const char *pathname) {
-#if defined _MIPS_SIM && _MIPS_SIM == _MIPS_SIM_ABI32 || defined __powerpc__ && !defined __powerpc64__
- union {
- uint64_t _64;
- uint32_t _32[2];
- } _mask;
- _mask._64 = mask;
-
- return syscall(__NR_fanotify_mark, fanotify_fd, flags,
- _mask._32[0], _mask._32[1], dfd, pathname);
-#else
- return syscall(__NR_fanotify_mark, fanotify_fd, flags, mask, dfd, pathname);
-#endif
-}
-#endif
-
-#ifndef BTRFS_IOCTL_MAGIC
-#define BTRFS_IOCTL_MAGIC 0x94
-#endif
-
-#ifndef BTRFS_PATH_NAME_MAX
-#define BTRFS_PATH_NAME_MAX 4087
-#endif
-
-struct btrfs_ioctl_vol_args {
- int64_t fd;
- char name[BTRFS_PATH_NAME_MAX + 1];
-};
-
-#ifndef BTRFS_IOC_DEFRAG
-#define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, struct btrfs_ioctl_vol_args)
-#endif
-
-#ifndef BTRFS_SUPER_MAGIC
-#define BTRFS_SUPER_MAGIC 0x9123683E
-#endif
-
-#ifndef MS_MOVE
-#define MS_MOVE 8192
-#endif
-
-#ifndef MS_PRIVATE
-#define MS_PRIVATE (1 << 18)
-#endif
-
-#if !HAVE_DECL_GETTID
-static inline pid_t gettid(void) {
- return (pid_t) syscall(SYS_gettid);
-}
-#endif
-
-#ifndef SCM_SECURITY
-#define SCM_SECURITY 0x03
-#endif
-
-#ifndef MS_STRICTATIME
-#define MS_STRICTATIME (1<<24)
-#endif
-
-#ifndef PR_SET_NO_NEW_PRIVS
-#define PR_SET_NO_NEW_PRIVS 38
-#endif
-
-#ifndef PR_SET_CHILD_SUBREAPER
-#define PR_SET_CHILD_SUBREAPER 36
-#endif
-
-#ifndef MAX_HANDLE_SZ
-#define MAX_HANDLE_SZ 128
-#endif
-
-#if defined __x86_64__
-# ifndef __NR_name_to_handle_at
-# define __NR_name_to_handle_at 303
-# endif
-#elif defined __i386__
-# ifndef __NR_name_to_handle_at
-# define __NR_name_to_handle_at 341
-# endif
-#elif defined __arm__
-# ifndef __NR_name_to_handle_at
-# define __NR_name_to_handle_at 370
-# endif
-#elif defined __powerpc__
-# ifndef __NR_name_to_handle_at
-# define __NR_name_to_handle_at 345
-# endif
-#else
-# ifndef __NR_name_to_handle_at
-# error __NR_name_to_handle_at is not defined
-# endif
-#endif
-
-#if !HAVE_DECL_NAME_TO_HANDLE_AT
-struct file_handle {
- unsigned int handle_bytes;
- int handle_type;
- unsigned char f_handle[0];
-};
-
-static inline int name_to_handle_at(int fd, const char *name, struct file_handle *handle, int *mnt_id, int flags) {
- return syscall(__NR_name_to_handle_at, fd, name, handle, mnt_id, flags);
-}
-#endif
-
-#ifndef HAVE_SECURE_GETENV
-# ifdef HAVE___SECURE_GETENV
-# define secure_getenv __secure_getenv
-# else
-# error neither secure_getenv nor __secure_getenv are available
-# endif
-#endif
-
-#ifndef CIFS_MAGIC_NUMBER
-#define CIFS_MAGIC_NUMBER 0xFF534D42
-#endif
diff --git a/src/shared/mkdir.c b/src/shared/mkdir.c
deleted file mode 100644
index 0e51b64f69..0000000000
--- a/src/shared/mkdir.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*-*- 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 <assert.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "mkdir.h"
-#include "label.h"
-#include "util.h"
-
-int mkdir_label(const char *path, mode_t mode) {
- return label_mkdir(path, mode, true);
-}
-
-static int makedir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, bool apply) {
- struct stat st;
-
- if (label_mkdir(path, mode, apply) >= 0)
- if (chmod_and_chown(path, mode, uid, gid) < 0)
- return -errno;
-
- if (lstat(path, &st) < 0)
- return -errno;
-
- if ((st.st_mode & 0777) != mode ||
- st.st_uid != uid ||
- st.st_gid != gid ||
- !S_ISDIR(st.st_mode)) {
- errno = EEXIST;
- return -errno;
- }
-
- return 0;
-}
-
-int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid) {
- return makedir_safe(path, mode, uid, gid, false);
-}
-
-int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid) {
- return makedir_safe(path, mode, uid, gid, true);
-}
-
-static int makedir_parents(const char *path, mode_t mode, bool apply) {
- struct stat st;
- const char *p, *e;
-
- assert(path);
-
- /* return immediately if directory exists */
- e = strrchr(path, '/');
- if (!e)
- return -EINVAL;
- p = strndupa(path, e - path);
- if (stat(p, &st) >= 0) {
- if ((st.st_mode & S_IFMT) == S_IFDIR)
- return 0;
- else
- return -ENOTDIR;
- }
-
- /* create every parent directory in the path, except the last component */
- p = path + strspn(path, "/");
- for (;;) {
- int r;
- char *t;
-
- e = p + strcspn(p, "/");
- p = e + strspn(e, "/");
-
- /* Is this the last component? If so, then we're
- * done */
- if (*p == 0)
- return 0;
-
- t = strndup(path, e - path);
- if (!t)
- return -ENOMEM;
-
- r = label_mkdir(t, mode, apply);
- free(t);
-
- if (r < 0 && errno != EEXIST)
- return -errno;
- }
-}
-
-int mkdir_parents(const char *path, mode_t mode) {
- return makedir_parents(path, mode, false);
-}
-
-int mkdir_parents_label(const char *path, mode_t mode) {
- return makedir_parents(path, mode, true);
-}
-
-static int is_dir(const char* path) {
- struct stat st;
- if (stat(path, &st) < 0)
- return -errno;
- return S_ISDIR(st.st_mode);
-}
-
-static int makedir_p(const char *path, mode_t mode, bool apply) {
- int r;
-
- /* Like mkdir -p */
-
- r = makedir_parents(path, mode, apply);
- if (r < 0)
- return r;
-
- r = label_mkdir(path, mode, apply);
- if (r < 0 && (errno != EEXIST || is_dir(path) <= 0))
- return -errno;
-
- return 0;
-}
-
-int mkdir_p(const char *path, mode_t mode) {
- return makedir_p(path, mode, false);
-}
-
-int mkdir_p_label(const char *path, mode_t mode) {
- return makedir_p(path, mode, true);
-}
diff --git a/src/shared/mkdir.h b/src/shared/mkdir.h
deleted file mode 100644
index ce1c35e9ba..0000000000
--- a/src/shared/mkdir.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef foomkdirhfoo
-#define foomkdirhfoo
-
-/***
- 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 mkdir_label(const char *path, mode_t mode);
-int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid);
-int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid);
-int mkdir_parents(const char *path, mode_t mode);
-int mkdir_parents_label(const char *path, mode_t mode);
-int mkdir_p(const char *path, mode_t mode);
-int mkdir_p_label(const char *path, mode_t mode);
-#endif
diff --git a/src/shared/pager.c b/src/shared/pager.c
deleted file mode 100644
index 488a12c763..0000000000
--- a/src/shared/pager.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*-*- 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/types.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/prctl.h>
-
-#include "pager.h"
-#include "util.h"
-#include "macro.h"
-
-static pid_t pager_pid = 0;
-
-_noreturn_ static void pager_fallback(void) {
- ssize_t n;
- do {
- n = splice(STDIN_FILENO, NULL, STDOUT_FILENO, NULL, 64*1024, 0);
- } while (n > 0);
- if (n < 0) {
- log_error("Internal pager failed: %m");
- _exit(EXIT_FAILURE);
- }
- _exit(EXIT_SUCCESS);
-}
-
-int pager_open(void) {
- int fd[2];
- const char *pager;
- pid_t parent_pid;
- int r;
-
- if (pager_pid > 0)
- return 1;
-
- if ((pager = getenv("SYSTEMD_PAGER")) || (pager = getenv("PAGER")))
- if (!*pager || streq(pager, "cat"))
- return 0;
-
- if (!on_tty())
- return 0;
-
- /* Determine and cache number of columns before we spawn the
- * pager so that we get the value from the actual tty */
- columns();
-
- if (pipe(fd) < 0) {
- log_error("Failed to create pager pipe: %m");
- return -errno;
- }
-
- parent_pid = getpid();
-
- pager_pid = fork();
- if (pager_pid < 0) {
- r = -errno;
- log_error("Failed to fork pager: %m");
- close_pipe(fd);
- return r;
- }
-
- /* In the child start the pager */
- if (pager_pid == 0) {
-
- dup2(fd[0], STDIN_FILENO);
- close_pipe(fd);
-
- setenv("LESS", "FRSX", 0);
-
- /* Make sure the pager goes away when the parent dies */
- if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
- _exit(EXIT_FAILURE);
-
- /* Check whether our parent died before we were able
- * to set the death signal */
- if (getppid() != parent_pid)
- _exit(EXIT_SUCCESS);
-
- if (pager) {
- execlp(pager, pager, NULL);
- execl("/bin/sh", "sh", "-c", pager, NULL);
- }
-
- /* Debian's alternatives command for pagers is
- * called 'pager'. Note that we do not call
- * sensible-pagers here, since that is just a
- * shell script that implements a logic that
- * is similar to this one anyway, but is
- * Debian-specific. */
- execlp("pager", "pager", NULL);
-
- execlp("less", "less", NULL);
- execlp("more", "more", NULL);
-
- pager_fallback();
- /* not reached */
- }
-
- /* Return in the parent */
- if (dup2(fd[1], STDOUT_FILENO) < 0) {
- log_error("Failed to duplicate pager pipe: %m");
- return -errno;
- }
-
- close_pipe(fd);
- return 1;
-}
-
-void pager_close(void) {
-
- if (pager_pid <= 0)
- return;
-
- /* Inform pager that we are done */
- fclose(stdout);
- kill(pager_pid, SIGCONT);
- wait_for_terminate(pager_pid, NULL);
- pager_pid = 0;
-}
-
-bool pager_have(void) {
- return pager_pid > 0;
-}
diff --git a/src/shared/pager.h b/src/shared/pager.h
deleted file mode 100644
index 5e7b5ab91e..0000000000
--- a/src/shared/pager.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*-*- 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 pager_open(void);
-void pager_close(void);
-bool pager_have(void);
diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c
deleted file mode 100644
index 6e5529e0c7..0000000000
--- a/src/shared/path-lookup.c
+++ /dev/null
@@ -1,430 +0,0 @@
-/*-*- 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 <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include "util.h"
-#include "mkdir.h"
-#include "strv.h"
-#include "path-util.h"
-#include "path-lookup.h"
-
-static const char* const systemd_running_as_table[_SYSTEMD_RUNNING_AS_MAX] = {
- [SYSTEMD_SYSTEM] = "system",
- [SYSTEMD_USER] = "user"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(systemd_running_as, SystemdRunningAs);
-
-int user_config_home(char **config_home) {
- const char *e;
-
- e = getenv("XDG_CONFIG_HOME");
- if (e) {
- if (asprintf(config_home, "%s/systemd/user", e) < 0)
- return -ENOMEM;
-
- return 1;
- } else {
- const char *home;
-
- home = getenv("HOME");
- if (home) {
- if (asprintf(config_home, "%s/.config/systemd/user", home) < 0)
- return -ENOMEM;
-
- return 1;
- }
- }
-
- return 0;
-}
-
-static char** user_dirs(
- const char *generator,
- const char *generator_early,
- const char *generator_late) {
-
- const char * const config_unit_paths[] = {
- USER_CONFIG_UNIT_PATH,
- "/etc/systemd/user",
- "/run/systemd/user",
- NULL
- };
-
- const char * const data_unit_paths[] = {
- "/usr/local/lib/systemd/user",
- "/usr/local/share/systemd/user",
- USER_DATA_UNIT_PATH,
- "/usr/lib/systemd/user",
- "/usr/share/systemd/user",
- NULL
- };
-
- const char *home, *e;
- char *config_home = NULL, *data_home = NULL;
- char **config_dirs = NULL, **data_dirs = NULL;
- char **r = NULL, **t;
-
- /* Implement the mechanisms defined in
- *
- * http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
- *
- * We look in both the config and the data dirs because we
- * want to encourage that distributors ship their unit files
- * as data, and allow overriding as configuration.
- */
-
- if (user_config_home(&config_home) < 0)
- goto fail;
-
- home = getenv("HOME");
-
- e = getenv("XDG_CONFIG_DIRS");
- if (e) {
- config_dirs = strv_split(e, ":");
- if (!config_dirs)
- goto fail;
- }
-
- /* We don't treat /etc/xdg/systemd here as the spec
- * suggests because we assume that that is a link to
- * /etc/systemd/ anyway. */
-
- e = getenv("XDG_DATA_HOME");
- if (e) {
- if (asprintf(&data_home, "%s/systemd/user", e) < 0)
- goto fail;
-
- } else if (home) {
- if (asprintf(&data_home, "%s/.local/share/systemd/user", home) < 0)
- goto fail;
-
- /* There is really no need for two unit dirs in $HOME,
- * except to be fully compliant with the XDG spec. We
- * now try to link the two dirs, so that we can
- * minimize disk seeks a little. Further down we'll
- * then filter out this link, if it is actually is
- * one. */
-
- mkdir_parents_label(data_home, 0777);
- (void) symlink("../../../.config/systemd/user", data_home);
- }
-
- e = getenv("XDG_DATA_DIRS");
- if (e)
- data_dirs = strv_split(e, ":");
- else
- data_dirs = strv_new("/usr/local/share",
- "/usr/share",
- NULL);
- if (!data_dirs)
- goto fail;
-
- /* Now merge everything we found. */
- if (generator_early) {
- t = strv_append(r, generator_early);
- if (!t)
- goto fail;
- strv_free(r);
- r = t;
- }
-
- if (config_home) {
- t = strv_append(r, config_home);
- if (!t)
- goto fail;
- strv_free(r);
- r = t;
- }
-
- if (!strv_isempty(config_dirs)) {
- t = strv_merge_concat(r, config_dirs, "/systemd/user");
- if (!t)
- goto finish;
- strv_free(r);
- r = t;
- }
-
- t = strv_merge(r, (char**) config_unit_paths);
- if (!t)
- goto fail;
- strv_free(r);
- r = t;
-
- if (generator) {
- t = strv_append(r, generator);
- if (!t)
- goto fail;
- strv_free(r);
- r = t;
- }
-
- if (data_home) {
- t = strv_append(r, data_home);
- if (!t)
- goto fail;
- strv_free(r);
- r = t;
- }
-
- if (!strv_isempty(data_dirs)) {
- t = strv_merge_concat(r, data_dirs, "/systemd/user");
- if (!t)
- goto fail;
- strv_free(r);
- r = t;
- }
-
- t = strv_merge(r, (char**) data_unit_paths);
- if (!t)
- goto fail;
- strv_free(r);
- r = t;
-
- if (generator_late) {
- t = strv_append(r, generator_late);
- if (!t)
- goto fail;
- strv_free(r);
- r = t;
- }
-
- if (!path_strv_make_absolute_cwd(r))
- goto fail;
-
-finish:
- free(config_home);
- strv_free(config_dirs);
- free(data_home);
- strv_free(data_dirs);
-
- return r;
-
-fail:
- strv_free(r);
- r = NULL;
- goto finish;
-}
-
-int lookup_paths_init(
- LookupPaths *p,
- SystemdRunningAs running_as,
- bool personal,
- const char *generator,
- const char *generator_early,
- const char *generator_late) {
-
- const char *e;
- char *t;
-
- assert(p);
-
- /* First priority is whatever has been passed to us via env
- * vars */
- e = getenv("SYSTEMD_UNIT_PATH");
- if (e) {
- p->unit_path = path_split_and_make_absolute(e);
- if (!p->unit_path)
- return -ENOMEM;
- } else
- p->unit_path = NULL;
-
- if (strv_isempty(p->unit_path)) {
- /* Nothing is set, so let's figure something out. */
- strv_free(p->unit_path);
-
- /* For the user units we include share/ in the search
- * path in order to comply with the XDG basedir
- * spec. For the system stuff we avoid such
- * nonsense. OTOH we include /lib in the search path
- * for the system stuff but avoid it for user
- * stuff. */
-
- if (running_as == SYSTEMD_USER) {
-
- if (personal)
- p->unit_path = user_dirs(generator, generator_early, generator_late);
- else
- p->unit_path = strv_new(
- /* If you modify this you also want to modify
- * systemduserunitpath= in systemd.pc.in, and
- * the arrays in user_dirs() above! */
- STRV_IFNOTNULL(generator_early),
- USER_CONFIG_UNIT_PATH,
- "/etc/systemd/user",
- "/run/systemd/user",
- STRV_IFNOTNULL(generator),
- "/usr/local/lib/systemd/user",
- "/usr/local/share/systemd/user",
- USER_DATA_UNIT_PATH,
- "/usr/lib/systemd/user",
- "/usr/share/systemd/user",
- STRV_IFNOTNULL(generator_late),
- NULL);
-
- if (!p->unit_path)
- return -ENOMEM;
-
- } else {
- p->unit_path = strv_new(
- /* If you modify this you also want to modify
- * systemdsystemunitpath= in systemd.pc.in! */
- STRV_IFNOTNULL(generator_early),
- SYSTEM_CONFIG_UNIT_PATH,
- "/etc/systemd/system",
- "/run/systemd/system",
- STRV_IFNOTNULL(generator),
- "/usr/local/lib/systemd/system",
- SYSTEM_DATA_UNIT_PATH,
- "/usr/lib/systemd/system",
-#ifdef HAVE_SPLIT_USR
- "/lib/systemd/system",
-#endif
- STRV_IFNOTNULL(generator_late),
- NULL);
-
- if (!p->unit_path)
- return -ENOMEM;
- }
- }
-
- if (!path_strv_canonicalize(p->unit_path))
- return -ENOMEM;
-
- strv_uniq(p->unit_path);
- path_strv_remove_empty(p->unit_path);
-
- if (!strv_isempty(p->unit_path)) {
-
- t = strv_join(p->unit_path, "\n\t");
- if (!t)
- return -ENOMEM;
- log_debug("Looking for unit files in:\n\t%s", t);
- free(t);
- } else {
- log_debug("Ignoring unit files.");
- strv_free(p->unit_path);
- p->unit_path = NULL;
- }
-
- if (running_as == SYSTEMD_SYSTEM) {
-#ifdef HAVE_SYSV_COMPAT
- /* /etc/init.d/ compatibility does not matter to users */
-
- e = getenv("SYSTEMD_SYSVINIT_PATH");
- if (e) {
- p->sysvinit_path = path_split_and_make_absolute(e);
- if (!p->sysvinit_path)
- return -ENOMEM;
- } else
- p->sysvinit_path = NULL;
-
- if (strv_isempty(p->sysvinit_path)) {
- strv_free(p->sysvinit_path);
-
- p->sysvinit_path = strv_new(
- SYSTEM_SYSVINIT_PATH, /* /etc/init.d/ */
- NULL);
- if (!p->sysvinit_path)
- return -ENOMEM;
- }
-
- e = getenv("SYSTEMD_SYSVRCND_PATH");
- if (e) {
- p->sysvrcnd_path = path_split_and_make_absolute(e);
- if (!p->sysvrcnd_path)
- return -ENOMEM;
- } else
- p->sysvrcnd_path = NULL;
-
- if (strv_isempty(p->sysvrcnd_path)) {
- strv_free(p->sysvrcnd_path);
-
- p->sysvrcnd_path = strv_new(
- SYSTEM_SYSVRCND_PATH, /* /etc/rcN.d/ */
- NULL);
- if (!p->sysvrcnd_path)
- return -ENOMEM;
- }
-
- if (!path_strv_canonicalize(p->sysvinit_path))
- return -ENOMEM;
-
- if (!path_strv_canonicalize(p->sysvrcnd_path))
- return -ENOMEM;
-
- strv_uniq(p->sysvinit_path);
- strv_uniq(p->sysvrcnd_path);
- path_strv_remove_empty(p->sysvinit_path);
- path_strv_remove_empty(p->sysvrcnd_path);
-
- if (!strv_isempty(p->sysvinit_path)) {
-
- t = strv_join(p->sysvinit_path, "\n\t");
- if (!t)
- return -ENOMEM;
- log_debug("Looking for SysV init scripts in:\n\t%s", t);
- free(t);
- } else {
- log_debug("Ignoring SysV init scripts.");
- strv_free(p->sysvinit_path);
- p->sysvinit_path = NULL;
- }
-
- if (!strv_isempty(p->sysvrcnd_path)) {
-
- t = strv_join(p->sysvrcnd_path, "\n\t");
- if (!t)
- return -ENOMEM;
-
- log_debug("Looking for SysV rcN.d links in:\n\t%s", t);
- free(t);
- } else {
- log_debug("Ignoring SysV rcN.d links.");
- strv_free(p->sysvrcnd_path);
- p->sysvrcnd_path = NULL;
- }
-#else
- log_debug("Disabled SysV init scripts and rcN.d links support");
-#endif
- }
-
- return 0;
-}
-
-void lookup_paths_free(LookupPaths *p) {
- assert(p);
-
- strv_free(p->unit_path);
- p->unit_path = NULL;
-
-#ifdef HAVE_SYSV_COMPAT
- strv_free(p->sysvinit_path);
- strv_free(p->sysvrcnd_path);
- p->sysvinit_path = p->sysvrcnd_path = NULL;
-#endif
-}
diff --git a/src/shared/path-lookup.h b/src/shared/path-lookup.h
deleted file mode 100644
index baef62228a..0000000000
--- a/src/shared/path-lookup.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*-*- 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/>.
-***/
-
-typedef struct LookupPaths {
- char **unit_path;
-#ifdef HAVE_SYSV_COMPAT
- char **sysvinit_path;
- char **sysvrcnd_path;
-#endif
-} LookupPaths;
-
-typedef enum SystemdRunningAs {
- SYSTEMD_SYSTEM,
- SYSTEMD_USER,
- _SYSTEMD_RUNNING_AS_MAX,
- _SYSTEMD_RUNNING_AS_INVALID = -1
-} SystemdRunningAs;
-
-const char* systemd_running_as_to_string(SystemdRunningAs i);
-SystemdRunningAs systemd_running_as_from_string(const char *s);
-
-int user_config_home(char **config_home);
-
-int lookup_paths_init(LookupPaths *p, SystemdRunningAs running_as, bool personal, const char *generator, const char *generator_early, const char *generator_late);
-void lookup_paths_free(LookupPaths *p);
diff --git a/src/shared/path-util.c b/src/shared/path-util.c
deleted file mode 100644
index 70c8a8af06..0000000000
--- a/src/shared/path-util.c
+++ /dev/null
@@ -1,419 +0,0 @@
-/*-*- 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 <assert.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <sys/statvfs.h>
-
-#include "macro.h"
-#include "util.h"
-#include "log.h"
-#include "strv.h"
-#include "path-util.h"
-#include "missing.h"
-
-bool path_is_absolute(const char *p) {
- return p[0] == '/';
-}
-
-bool is_path(const char *p) {
- return !!strchr(p, '/');
-}
-
-char *path_get_file_name(const char *p) {
- char *r;
-
- assert(p);
-
- if ((r = strrchr(p, '/')))
- return r + 1;
-
- return (char*) 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;
-}
-
-char **path_split_and_make_absolute(const char *p) {
- char **l;
- assert(p);
-
- if (!(l = strv_split(p, ":")))
- return NULL;
-
- if (!path_strv_make_absolute_cwd(l)) {
- strv_free(l);
- return NULL;
- }
-
- return l;
-}
-
-char *path_make_absolute(const char *p, const char *prefix) {
- assert(p);
-
- /* Makes every item in the list an absolute path by prepending
- * the prefix, if specified and necessary */
-
- if (path_is_absolute(p) || !prefix)
- return strdup(p);
-
- return strjoin(prefix, "/", p, NULL);
-}
-
-char *path_make_absolute_cwd(const char *p) {
- char *cwd, *r;
-
- assert(p);
-
- /* Similar to path_make_absolute(), but prefixes with the
- * current working directory. */
-
- if (path_is_absolute(p))
- return strdup(p);
-
- if (!(cwd = get_current_dir_name()))
- return NULL;
-
- r = path_make_absolute(p, cwd);
- free(cwd);
-
- return r;
-}
-
-char **path_strv_make_absolute_cwd(char **l) {
- char **s;
-
- /* Goes through every item in the string list and makes it
- * absolute. This works in place and won't rollback any
- * changes on failure. */
-
- STRV_FOREACH(s, l) {
- char *t;
-
- if (!(t = path_make_absolute_cwd(*s)))
- return NULL;
-
- free(*s);
- *s = t;
- }
-
- return l;
-}
-
-char **path_strv_canonicalize(char **l) {
- char **s;
- unsigned k = 0;
- bool enomem = false;
-
- if (strv_isempty(l))
- return l;
-
- /* Goes through every item in the string list and canonicalize
- * the path. This works in place and won't rollback any
- * changes on failure. */
-
- STRV_FOREACH(s, l) {
- char *t, *u;
-
- t = path_make_absolute_cwd(*s);
- free(*s);
-
- if (!t) {
- enomem = true;
- continue;
- }
-
- errno = 0;
- u = canonicalize_file_name(t);
- free(t);
-
- if (!u) {
- if (errno == ENOMEM || !errno)
- enomem = true;
-
- continue;
- }
-
- l[k++] = u;
- }
-
- l[k] = NULL;
-
- if (enomem)
- return NULL;
-
- return l;
-}
-
-char **path_strv_remove_empty(char **l) {
- char **f, **t;
-
- if (!l)
- return NULL;
-
- for (f = t = l; *f; f++) {
-
- if (dir_is_empty(*f) > 0) {
- free(*f);
- continue;
- }
-
- *(t++) = *f;
- }
-
- *t = NULL;
- return l;
-}
-
-char *path_kill_slashes(char *path) {
- char *f, *t;
- bool slash = false;
-
- /* Removes redundant inner and trailing slashes. Modifies the
- * passed string in-place.
- *
- * ///foo///bar/ becomes /foo/bar
- */
-
- for (f = path, t = path; *f; f++) {
-
- if (*f == '/') {
- slash = true;
- continue;
- }
-
- if (slash) {
- slash = false;
- *(t++) = '/';
- }
-
- *(t++) = *f;
- }
-
- /* Special rule, if we are talking of the root directory, a
- trailing slash is good */
-
- if (t == path && slash)
- *(t++) = '/';
-
- *t = 0;
- return path;
-}
-
-char* path_startswith(const char *path, const char *prefix) {
- assert(path);
- assert(prefix);
-
- if ((path[0] == '/') != (prefix[0] == '/'))
- return NULL;
-
- for (;;) {
- size_t a, b;
-
- path += strspn(path, "/");
- prefix += strspn(prefix, "/");
-
- if (*prefix == 0)
- return (char*) path;
-
- if (*path == 0)
- return NULL;
-
- a = strcspn(path, "/");
- b = strcspn(prefix, "/");
-
- if (a != b)
- return NULL;
-
- if (memcmp(path, prefix, a) != 0)
- return NULL;
-
- path += a;
- prefix += b;
- }
-}
-
-bool path_equal(const char *a, const char *b) {
- assert(a);
- assert(b);
-
- if ((a[0] == '/') != (b[0] == '/'))
- return false;
-
- for (;;) {
- size_t j, k;
-
- a += strspn(a, "/");
- b += strspn(b, "/");
-
- if (*a == 0 && *b == 0)
- return true;
-
- if (*a == 0 || *b == 0)
- return false;
-
- j = strcspn(a, "/");
- k = strcspn(b, "/");
-
- if (j != k)
- return false;
-
- if (memcmp(a, b, j) != 0)
- return false;
-
- a += j;
- b += k;
- }
-}
-
-int path_is_mount_point(const char *t, bool allow_symlink) {
- char *parent;
- int r;
- struct file_handle *h;
- int mount_id, mount_id_parent;
- struct stat a, b;
-
- /* We are not actually interested in the file handles, but
- * name_to_handle_at() also passes us the mount ID, hence use
- * it but throw the handle away */
-
- if (path_equal(t, "/"))
- return 1;
-
- h = alloca(MAX_HANDLE_SZ);
- h->handle_bytes = MAX_HANDLE_SZ;
-
- r = name_to_handle_at(AT_FDCWD, t, h, &mount_id, allow_symlink ? AT_SYMLINK_FOLLOW : 0);
- if (r < 0) {
- if (errno == ENOSYS || errno == ENOTSUP)
- /* This kernel or file system does not support
- * name_to_handle_at(), hence fallback to the
- * traditional stat() logic */
- goto fallback;
-
- if (errno == ENOENT)
- return 0;
-
- return -errno;
- }
-
- r = path_get_parent(t, &parent);
- if (r < 0)
- return r;
-
- h->handle_bytes = MAX_HANDLE_SZ;
- r = name_to_handle_at(AT_FDCWD, parent, h, &mount_id_parent, 0);
- free(parent);
-
- if (r < 0) {
- /* 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 */
- if (errno == ENOTSUP)
- return 1;
-
- return -errno;
- }
-
- return mount_id != mount_id_parent;
-
-fallback:
- if (allow_symlink)
- r = stat(t, &a);
- else
- r = lstat(t, &a);
-
- if (r < 0) {
- if (errno == ENOENT)
- return 0;
-
- return -errno;
- }
-
- r = path_get_parent(t, &parent);
- if (r < 0)
- return r;
-
- r = lstat(parent, &b);
- free(parent);
-
- if (r < 0)
- return -errno;
-
- return a.st_dev != b.st_dev;
-}
-
-int path_is_read_only_fs(const char *path) {
- struct statvfs st;
-
- assert(path);
-
- if (statvfs(path, &st) < 0)
- return -errno;
-
- return !!(st.f_flag & ST_RDONLY);
-}
diff --git a/src/shared/path-util.h b/src/shared/path-util.h
deleted file mode 100644
index e81821a28f..0000000000
--- a/src/shared/path-util.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef foopathutilhfoo
-#define foopathutilhfoo
-
-/***
- 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"
-
-bool is_path(const char *p);
-char **path_split_and_make_absolute(const char *p);
-char *path_get_file_name(const char *p);
-int path_get_parent(const char *path, char **parent);
-bool path_is_absolute(const char *p);
-char *path_make_absolute(const char *p, const char *prefix);
-char *path_make_absolute_cwd(const char *p);
-char *path_kill_slashes(char *path);
-char *path_startswith(const char *path, const char *prefix);
-bool path_equal(const char *a, const char *b);
-
-char **path_strv_make_absolute_cwd(char **l);
-char **path_strv_canonicalize(char **l);
-char **path_strv_remove_empty(char **l);
-
-int path_is_mount_point(const char *path, bool allow_symlink);
-int path_is_read_only_fs(const char *path);
-
-#endif
diff --git a/src/shared/polkit.c b/src/shared/polkit.c
deleted file mode 100644
index 126096e64f..0000000000
--- a/src/shared/polkit.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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/types.h>
-
-#include <errno.h>
-
-#include "util.h"
-#include "dbus-common.h"
-#include "polkit.h"
-
-int verify_polkit(
- DBusConnection *c,
- DBusMessage *request,
- const char *action,
- bool interactive,
- bool *_challenge,
- DBusError *error) {
-
- DBusMessage *m = NULL, *reply = NULL;
- const char *unix_process = "unix-process", *pid = "pid", *starttime = "start-time", *cancel_id = "";
- const char *sender;
- uint32_t flags = interactive ? 1 : 0;
- pid_t pid_raw;
- uint32_t pid_u32;
- unsigned long long starttime_raw;
- uint64_t starttime_u64;
- DBusMessageIter iter_msg, iter_struct, iter_array, iter_dict, iter_variant;
- int r;
- dbus_bool_t authorized = FALSE, challenge = FALSE;
- unsigned long ul;
-
- assert(c);
- assert(request);
-
- sender = dbus_message_get_sender(request);
- if (!sender)
- return -EINVAL;
-
- ul = dbus_bus_get_unix_user(c, sender, error);
- if (ul == (unsigned long) -1)
- return -EINVAL;
-
- /* Shortcut things for root, to avoid the PK roundtrip and dependency */
- if (ul == 0)
- return 1;
-
- pid_raw = bus_get_unix_process_id(c, sender, error);
- if (pid_raw == 0)
- return -EINVAL;
-
- r = get_starttime_of_pid(pid_raw, &starttime_raw);
- if (r < 0)
- return r;
-
- m = dbus_message_new_method_call(
- "org.freedesktop.PolicyKit1",
- "/org/freedesktop/PolicyKit1/Authority",
- "org.freedesktop.PolicyKit1.Authority",
- "CheckAuthorization");
- if (!m)
- return -ENOMEM;
-
- dbus_message_iter_init_append(m, &iter_msg);
-
- pid_u32 = (uint32_t) pid_raw;
- starttime_u64 = (uint64_t) starttime_raw;
-
- if (!dbus_message_iter_open_container(&iter_msg, DBUS_TYPE_STRUCT, NULL, &iter_struct) ||
- !dbus_message_iter_append_basic(&iter_struct, DBUS_TYPE_STRING, &unix_process) ||
- !dbus_message_iter_open_container(&iter_struct, DBUS_TYPE_ARRAY, "{sv}", &iter_array) ||
- !dbus_message_iter_open_container(&iter_array, DBUS_TYPE_DICT_ENTRY, NULL, &iter_dict) ||
- !dbus_message_iter_append_basic(&iter_dict, DBUS_TYPE_STRING, &pid) ||
- !dbus_message_iter_open_container(&iter_dict, DBUS_TYPE_VARIANT, "u", &iter_variant) ||
- !dbus_message_iter_append_basic(&iter_variant, DBUS_TYPE_UINT32, &pid_u32) ||
- !dbus_message_iter_close_container(&iter_dict, &iter_variant) ||
- !dbus_message_iter_close_container(&iter_array, &iter_dict) ||
- !dbus_message_iter_open_container(&iter_array, DBUS_TYPE_DICT_ENTRY, NULL, &iter_dict) ||
- !dbus_message_iter_append_basic(&iter_dict, DBUS_TYPE_STRING, &starttime) ||
- !dbus_message_iter_open_container(&iter_dict, DBUS_TYPE_VARIANT, "t", &iter_variant) ||
- !dbus_message_iter_append_basic(&iter_variant, DBUS_TYPE_UINT64, &starttime_u64) ||
- !dbus_message_iter_close_container(&iter_dict, &iter_variant) ||
- !dbus_message_iter_close_container(&iter_array, &iter_dict) ||
- !dbus_message_iter_close_container(&iter_struct, &iter_array) ||
- !dbus_message_iter_close_container(&iter_msg, &iter_struct) ||
- !dbus_message_iter_append_basic(&iter_msg, DBUS_TYPE_STRING, &action) ||
- !dbus_message_iter_open_container(&iter_msg, DBUS_TYPE_ARRAY, "{ss}", &iter_array) ||
- !dbus_message_iter_close_container(&iter_msg, &iter_array) ||
- !dbus_message_iter_append_basic(&iter_msg, DBUS_TYPE_UINT32, &flags) ||
- !dbus_message_iter_append_basic(&iter_msg, DBUS_TYPE_STRING, &cancel_id)) {
- r = -ENOMEM;
- goto finish;
- }
-
- reply = dbus_connection_send_with_reply_and_block(c, m, -1, error);
- if (!reply) {
- r = -EIO;
- goto finish;
- }
-
- if (dbus_set_error_from_message(error, reply)) {
- r = -EIO;
- goto finish;
- }
-
- if (!dbus_message_iter_init(reply, &iter_msg) ||
- dbus_message_iter_get_arg_type(&iter_msg) != DBUS_TYPE_STRUCT) {
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&iter_msg, &iter_struct);
-
- if (dbus_message_iter_get_arg_type(&iter_struct) != DBUS_TYPE_BOOLEAN) {
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_get_basic(&iter_struct, &authorized);
-
- if (!dbus_message_iter_next(&iter_struct) ||
- dbus_message_iter_get_arg_type(&iter_struct) != DBUS_TYPE_BOOLEAN) {
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_get_basic(&iter_struct, &challenge);
-
- if (authorized)
- r = 1;
- else if (_challenge) {
- *_challenge = !!challenge;
- r = 0;
- } else
- r = -EPERM;
-
-finish:
- if (m)
- dbus_message_unref(m);
-
- if (reply)
- dbus_message_unref(reply);
-
- return r;
-}
diff --git a/src/shared/polkit.h b/src/shared/polkit.h
deleted file mode 100644
index 6255d1f617..0000000000
--- a/src/shared/polkit.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*-*- 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 <dbus/dbus.h>
-
-int verify_polkit(
- DBusConnection *c,
- DBusMessage *request,
- const char *action,
- bool interactive,
- bool *challenge,
- DBusError *error);
diff --git a/src/shared/ratelimit.c b/src/shared/ratelimit.c
deleted file mode 100644
index 1054d52f97..0000000000
--- a/src/shared/ratelimit.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*-*- 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 <assert.h>
-
-#include "ratelimit.h"
-#include "log.h"
-
-/* Modelled after Linux' lib/ratelimit.c by Dave Young
- * <hidave.darkstar@gmail.com>, which is licensed GPLv2. */
-
-bool ratelimit_test(RateLimit *r) {
- usec_t ts;
-
- assert(r);
-
- if (r->interval <= 0 || r->burst <= 0)
- return true;
-
- ts = now(CLOCK_MONOTONIC);
-
- if (r->begin <= 0 ||
- r->begin + r->interval < ts) {
- r->begin = ts;
-
- /* Reset counter */
- r->num = 0;
- goto good;
- }
-
- if (r->num <= r->burst)
- goto good;
-
- return false;
-
-good:
- r->num++;
- return true;
-}
diff --git a/src/shared/ratelimit.h b/src/shared/ratelimit.h
deleted file mode 100644
index 58efca7df1..0000000000
--- a/src/shared/ratelimit.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*-*- 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 "util.h"
-
-typedef struct RateLimit {
- usec_t interval;
- usec_t begin;
- unsigned burst;
- unsigned num;
-} RateLimit;
-
-#define RATELIMIT_DEFINE(_name, _interval, _burst) \
- RateLimit _name = { \
- .interval = (_interval), \
- .burst = (_burst), \
- .num = 0, \
- .begin = 0 \
- }
-
-#define RATELIMIT_INIT(v, _interval, _burst) \
- do { \
- RateLimit *_r = &(v); \
- _r->interval = (_interval); \
- _r->burst = (_burst); \
- _r->num = 0; \
- _r->begin = 0; \
- } while (false)
-
-#define RATELIMIT_RESET(v) \
- do { \
- RateLimit *_r = &(v); \
- _r->num = 0; \
- _r->begin = 0; \
- } while (false)
-
-bool ratelimit_test(RateLimit *r);
diff --git a/src/shared/replace-var.c b/src/shared/replace-var.c
deleted file mode 100644
index e11c57a43d..0000000000
--- a/src/shared/replace-var.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <string.h>
-
-#include "macro.h"
-#include "util.h"
-#include "replace-var.h"
-
-/*
- * Generic infrastructure for replacing @FOO@ style variables in
- * strings. Will call a callback for each replacement.
- */
-
-static int get_variable(const char *b, char **r) {
- size_t k;
- char *t;
-
- assert(b);
- assert(r);
-
- if (*b != '@')
- return 0;
-
- k = strspn(b + 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ_");
- if (k <= 0 || b[k+1] != '@')
- return 0;
-
- t = strndup(b + 1, k);
- if (!t)
- return -ENOMEM;
-
- *r = t;
- return 1;
-}
-
-char *replace_var(const char *text, char *(*lookup)(const char *variable, void*userdata), void *userdata) {
- char *r, *t;
- const char *f;
- size_t l;
-
- assert(text);
- assert(lookup);
-
- l = strlen(text);
- r = new(char, l+1);
- if (!r)
- return NULL;
-
- f = text;
- t = r;
- while (*f) {
- _cleanup_free_ char *v = NULL, *n = NULL;
- char *a;
- int k;
- size_t skip, d, nl;
-
- k = get_variable(f, &v);
- if (k < 0)
- goto oom;
- if (k == 0) {
- *(t++) = *(f++);
- continue;
- }
-
- n = lookup(v, userdata);
- if (!n)
- goto oom;
-
- skip = strlen(v) + 2;
-
- d = t - r;
- nl = l - skip + strlen(n);
- a = realloc(r, nl + 1);
- if (!a)
- goto oom;
-
- l = nl;
- r = a;
- t = r + d;
-
- t = stpcpy(t, n);
- f += skip;
- }
-
- *t = 0;
- return r;
-
-oom:
- free(r);
- return NULL;
-}
diff --git a/src/shared/replace-var.h b/src/shared/replace-var.h
deleted file mode 100644
index 7eaee93a3e..0000000000
--- a/src/shared/replace-var.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-char *replace_var(const char *text, char *(*lookup)(const char *variable, void*userdata), void *userdata);
diff --git a/src/shared/selinux-util.c b/src/shared/selinux-util.c
deleted file mode 100644
index ff3375607f..0000000000
--- a/src/shared/selinux-util.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*-*- 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 "selinux-util.h"
-
-#ifdef HAVE_SELINUX
-
-#include <selinux/selinux.h>
-
-static int use_selinux_cached = -1;
-
-bool use_selinux(void) {
-
- if (use_selinux_cached < 0)
- use_selinux_cached = is_selinux_enabled() > 0;
-
- return use_selinux_cached;
-}
-
-void retest_selinux(void) {
- use_selinux_cached = -1;
-}
-
-#endif
diff --git a/src/shared/selinux-util.h b/src/shared/selinux-util.h
deleted file mode 100644
index 4b81202741..0000000000
--- a/src/shared/selinux-util.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*-*- 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>
-
-bool use_selinux(void);
-void retest_selinux(void);
diff --git a/src/shared/set.c b/src/shared/set.c
deleted file mode 100644
index 5f83c50839..0000000000
--- a/src/shared/set.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*-*- 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 <stdlib.h>
-
-#include "set.h"
-#include "hashmap.h"
-
-#define MAKE_SET(h) ((Set*) (h))
-#define MAKE_HASHMAP(s) ((Hashmap*) (s))
-
-/* For now this is not much more than a wrapper around a hashmap */
-
-Set *set_new(hash_func_t hash_func, compare_func_t compare_func) {
- return MAKE_SET(hashmap_new(hash_func, compare_func));
-}
-
-void set_free(Set* s) {
- hashmap_free(MAKE_HASHMAP(s));
-}
-
-void set_free_free(Set *s) {
- hashmap_free_free(MAKE_HASHMAP(s));
-}
-
-int set_ensure_allocated(Set **s, hash_func_t hash_func, compare_func_t compare_func) {
- return hashmap_ensure_allocated((Hashmap**) s, hash_func, compare_func);
-}
-
-int set_put(Set *s, void *value) {
- return hashmap_put(MAKE_HASHMAP(s), value, value);
-}
-
-int set_replace(Set *s, void *value) {
- return hashmap_replace(MAKE_HASHMAP(s), value, value);
-}
-
-void *set_get(Set *s, void *value) {
- return hashmap_get(MAKE_HASHMAP(s), value);
-}
-
-bool set_contains(Set *s, void *value) {
- return hashmap_contains(MAKE_HASHMAP(s), value);
-}
-
-void *set_remove(Set *s, void *value) {
- return hashmap_remove(MAKE_HASHMAP(s), value);
-}
-
-int set_remove_and_put(Set *s, void *old_value, void *new_value) {
- return hashmap_remove_and_put(MAKE_HASHMAP(s), old_value, new_value, new_value);
-}
-
-unsigned set_size(Set *s) {
- return hashmap_size(MAKE_HASHMAP(s));
-}
-
-bool set_isempty(Set *s) {
- return hashmap_isempty(MAKE_HASHMAP(s));
-}
-
-void *set_iterate(Set *s, Iterator *i) {
- return hashmap_iterate(MAKE_HASHMAP(s), i, NULL);
-}
-
-void *set_iterate_backwards(Set *s, Iterator *i) {
- return hashmap_iterate_backwards(MAKE_HASHMAP(s), i, NULL);
-}
-
-void *set_iterate_skip(Set *s, void *value, Iterator *i) {
- return hashmap_iterate_skip(MAKE_HASHMAP(s), value, i);
-}
-
-void *set_steal_first(Set *s) {
- return hashmap_steal_first(MAKE_HASHMAP(s));
-}
-
-void* set_first(Set *s) {
- return hashmap_first(MAKE_HASHMAP(s));
-}
-
-void* set_last(Set *s) {
- return hashmap_last(MAKE_HASHMAP(s));
-}
-
-int set_merge(Set *s, Set *other) {
- return hashmap_merge(MAKE_HASHMAP(s), MAKE_HASHMAP(other));
-}
-
-void set_move(Set *s, Set *other) {
- return hashmap_move(MAKE_HASHMAP(s), MAKE_HASHMAP(other));
-}
-
-int set_move_one(Set *s, Set *other, void *value) {
- return hashmap_move_one(MAKE_HASHMAP(s), MAKE_HASHMAP(other), value);
-}
-
-Set* set_copy(Set *s) {
- return MAKE_SET(hashmap_copy(MAKE_HASHMAP(s)));
-}
-
-void set_clear(Set *s) {
- hashmap_clear(MAKE_HASHMAP(s));
-}
-
-void set_clear_free(Set *s) {
- hashmap_clear_free(MAKE_HASHMAP(s));
-}
-
-char **set_get_strv(Set *s) {
- return hashmap_get_strv(MAKE_HASHMAP(s));
-}
diff --git a/src/shared/set.h b/src/shared/set.h
deleted file mode 100644
index 9162e2ae80..0000000000
--- a/src/shared/set.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*-*- 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/>.
-***/
-
-/* Pretty straightforward set implementation. Internally based on the
- * hashmap. That means that as a minor optimization a NULL set
- * object will be treated as empty set for all read
- * operations. That way it is not necessary to instantiate an object
- * for each set use. */
-
-#include "hashmap.h"
-
-typedef struct Set Set;
-
-Set *set_new(hash_func_t hash_func, compare_func_t compare_func);
-void set_free(Set* s);
-void set_free_free(Set *s);
-Set* set_copy(Set *s);
-int set_ensure_allocated(Set **s, hash_func_t hash_func, compare_func_t compare_func);
-
-int set_put(Set *s, void *value);
-int set_replace(Set *s, void *value);
-void *set_get(Set *s, void *value);
-bool set_contains(Set *s, void *value);
-void *set_remove(Set *s, void *value);
-int set_remove_and_put(Set *s, void *old_value, void *new_value);
-
-int set_merge(Set *s, Set *other);
-void set_move(Set *s, Set *other);
-int set_move_one(Set *s, Set *other, void *value);
-
-unsigned set_size(Set *s);
-bool set_isempty(Set *s);
-
-void *set_iterate(Set *s, Iterator *i);
-void *set_iterate_backwards(Set *s, Iterator *i);
-void *set_iterate_skip(Set *s, void *value, Iterator *i);
-
-void set_clear(Set *s);
-void set_clear_free(Set *s);
-
-void *set_steal_first(Set *s);
-void* set_first(Set *s);
-void* set_last(Set *s);
-
-char **set_get_strv(Set *s);
-
-#define SET_FOREACH(e, s, i) \
- for ((i) = ITERATOR_FIRST, (e) = set_iterate((s), &(i)); (e); (e) = set_iterate((s), &(i)))
-
-#define SET_FOREACH_BACKWARDS(e, s, i) \
- for ((i) = ITERATOR_LAST, (e) = set_iterate_backwards((s), &(i)); (e); (e) = set_iterate_backwards((s), &(i)))
diff --git a/src/shared/socket-label.c b/src/shared/socket-label.c
deleted file mode 100644
index ff212de825..0000000000
--- a/src/shared/socket-label.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*-*- 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 <assert.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <arpa/inet.h>
-#include <stdio.h>
-#include <net/if.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stddef.h>
-#include <sys/ioctl.h>
-
-#include "macro.h"
-#include "util.h"
-#include "mkdir.h"
-#include "socket-util.h"
-#include "missing.h"
-#include "label.h"
-
-int socket_address_listen(
- const SocketAddress *a,
- int backlog,
- SocketAddressBindIPv6Only only,
- const char *bind_to_device,
- bool free_bind,
- bool transparent,
- mode_t directory_mode,
- mode_t socket_mode,
- const char *label,
- int *ret) {
-
- int r, fd, one;
- assert(a);
- assert(ret);
-
- if ((r = socket_address_verify(a)) < 0)
- return r;
-
- if (socket_address_family(a) == AF_INET6 && !socket_ipv6_is_supported())
- return -EAFNOSUPPORT;
-
- r = label_socket_set(label);
- if (r < 0)
- return r;
-
- fd = socket(socket_address_family(a), a->type | SOCK_NONBLOCK | SOCK_CLOEXEC, a->protocol);
- r = fd < 0 ? -errno : 0;
-
- label_socket_clear();
-
- if (r < 0)
- return r;
-
- if (socket_address_family(a) == AF_INET6 && only != SOCKET_ADDRESS_DEFAULT) {
- int flag = only == SOCKET_ADDRESS_IPV6_ONLY;
-
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag)) < 0)
- goto fail;
- }
-
- if (socket_address_family(a) == AF_INET || socket_address_family(a) == AF_INET6) {
- if (bind_to_device)
- if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, bind_to_device, strlen(bind_to_device)+1) < 0)
- goto fail;
-
- if (free_bind) {
- one = 1;
- if (setsockopt(fd, IPPROTO_IP, IP_FREEBIND, &one, sizeof(one)) < 0)
- log_warning("IP_FREEBIND failed: %m");
- }
-
- if (transparent) {
- one = 1;
- if (setsockopt(fd, IPPROTO_IP, IP_TRANSPARENT, &one, sizeof(one)) < 0)
- log_warning("IP_TRANSPARENT failed: %m");
- }
- }
-
- one = 1;
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
- goto fail;
-
- if (socket_address_family(a) == AF_UNIX && a->sockaddr.un.sun_path[0] != 0) {
- mode_t old_mask;
-
- /* Create parents */
- mkdir_parents_label(a->sockaddr.un.sun_path, directory_mode);
-
- /* Enforce the right access mode for the socket*/
- old_mask = umask(~ socket_mode);
-
- /* Include the original umask in our mask */
- umask(~socket_mode | old_mask);
-
- r = label_bind(fd, &a->sockaddr.sa, a->size);
-
- if (r < 0 && errno == EADDRINUSE) {
- /* Unlink and try again */
- unlink(a->sockaddr.un.sun_path);
- r = bind(fd, &a->sockaddr.sa, a->size);
- }
-
- umask(old_mask);
- } else
- r = bind(fd, &a->sockaddr.sa, a->size);
-
- if (r < 0)
- goto fail;
-
- if (socket_address_can_accept(a))
- if (listen(fd, backlog) < 0)
- goto fail;
-
- *ret = fd;
- return 0;
-
-fail:
- r = -errno;
- close_nointr_nofail(fd);
- return r;
-}
diff --git a/src/shared/socket-util.c b/src/shared/socket-util.c
deleted file mode 100644
index 49ea75880d..0000000000
--- a/src/shared/socket-util.c
+++ /dev/null
@@ -1,544 +0,0 @@
-/*-*- 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 <assert.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <arpa/inet.h>
-#include <stdio.h>
-#include <net/if.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stddef.h>
-#include <sys/ioctl.h>
-
-#include "macro.h"
-#include "util.h"
-#include "mkdir.h"
-#include "path-util.h"
-#include "socket-util.h"
-#include "missing.h"
-
-int socket_address_parse(SocketAddress *a, const char *s) {
- int r;
- char *e, *n;
- unsigned u;
-
- assert(a);
- assert(s);
-
- zero(*a);
- a->type = SOCK_STREAM;
-
- if (*s == '[') {
- /* IPv6 in [x:.....:z]:p notation */
-
- if (!socket_ipv6_is_supported()) {
- log_warning("Binding to IPv6 address not available since kernel does not support IPv6.");
- return -EAFNOSUPPORT;
- }
-
- if (!(e = strchr(s+1, ']')))
- return -EINVAL;
-
- if (!(n = strndup(s+1, e-s-1)))
- return -ENOMEM;
-
- errno = 0;
- if (inet_pton(AF_INET6, n, &a->sockaddr.in6.sin6_addr) <= 0) {
- free(n);
- return errno != 0 ? -errno : -EINVAL;
- }
-
- free(n);
-
- e++;
- if (*e != ':')
- return -EINVAL;
-
- e++;
- if ((r = safe_atou(e, &u)) < 0)
- return r;
-
- if (u <= 0 || u > 0xFFFF)
- return -EINVAL;
-
- a->sockaddr.in6.sin6_family = AF_INET6;
- a->sockaddr.in6.sin6_port = htons((uint16_t) u);
- a->size = sizeof(struct sockaddr_in6);
-
- } else if (*s == '/') {
- /* AF_UNIX socket */
-
- size_t l;
-
- l = strlen(s);
- if (l >= sizeof(a->sockaddr.un.sun_path))
- return -EINVAL;
-
- a->sockaddr.un.sun_family = AF_UNIX;
- memcpy(a->sockaddr.un.sun_path, s, l);
- a->size = offsetof(struct sockaddr_un, sun_path) + l + 1;
-
- } else if (*s == '@') {
- /* Abstract AF_UNIX socket */
- size_t l;
-
- l = strlen(s+1);
- if (l >= sizeof(a->sockaddr.un.sun_path) - 1)
- return -EINVAL;
-
- a->sockaddr.un.sun_family = AF_UNIX;
- memcpy(a->sockaddr.un.sun_path+1, s+1, l);
- a->size = offsetof(struct sockaddr_un, sun_path) + 1 + l;
-
- } else {
-
- if ((e = strchr(s, ':'))) {
-
- if ((r = safe_atou(e+1, &u)) < 0)
- return r;
-
- if (u <= 0 || u > 0xFFFF)
- return -EINVAL;
-
- if (!(n = strndup(s, e-s)))
- return -ENOMEM;
-
- /* IPv4 in w.x.y.z:p notation? */
- if ((r = inet_pton(AF_INET, n, &a->sockaddr.in4.sin_addr)) < 0) {
- free(n);
- return -errno;
- }
-
- if (r > 0) {
- /* Gotcha, it's a traditional IPv4 address */
- free(n);
-
- a->sockaddr.in4.sin_family = AF_INET;
- a->sockaddr.in4.sin_port = htons((uint16_t) u);
- a->size = sizeof(struct sockaddr_in);
- } else {
- unsigned idx;
-
- if (strlen(n) > IF_NAMESIZE-1) {
- free(n);
- return -EINVAL;
- }
-
- /* Uh, our last resort, an interface name */
- idx = if_nametoindex(n);
- free(n);
-
- if (idx == 0)
- return -EINVAL;
-
- if (!socket_ipv6_is_supported()) {
- log_warning("Binding to interface is not available since kernel does not support IPv6.");
- return -EAFNOSUPPORT;
- }
-
- a->sockaddr.in6.sin6_family = AF_INET6;
- a->sockaddr.in6.sin6_port = htons((uint16_t) u);
- a->sockaddr.in6.sin6_scope_id = idx;
- a->sockaddr.in6.sin6_addr = in6addr_any;
- a->size = sizeof(struct sockaddr_in6);
- }
- } else {
-
- /* Just a port */
- r = safe_atou(s, &u);
- if (r < 0)
- return r;
-
- if (u <= 0 || u > 0xFFFF)
- return -EINVAL;
-
- if (socket_ipv6_is_supported()) {
- a->sockaddr.in6.sin6_family = AF_INET6;
- a->sockaddr.in6.sin6_port = htons((uint16_t) u);
- a->sockaddr.in6.sin6_addr = in6addr_any;
- a->size = sizeof(struct sockaddr_in6);
- } else {
- a->sockaddr.in4.sin_family = AF_INET;
- a->sockaddr.in4.sin_port = htons((uint16_t) u);
- a->sockaddr.in4.sin_addr.s_addr = INADDR_ANY;
- a->size = sizeof(struct sockaddr_in);
- }
- }
- }
-
- return 0;
-}
-
-int socket_address_parse_netlink(SocketAddress *a, const char *s) {
- int family;
- unsigned group = 0;
- _cleanup_free_ char *sfamily = NULL;
- assert(a);
- assert(s);
-
- zero(*a);
- a->type = SOCK_RAW;
-
- errno = 0;
- if (sscanf(s, "%ms %u", &sfamily, &group) < 1)
- return errno ? -errno : -EINVAL;
-
- family = netlink_family_from_string(sfamily);
- if (family < 0)
- return -EINVAL;
-
- a->sockaddr.nl.nl_family = AF_NETLINK;
- a->sockaddr.nl.nl_groups = group;
-
- a->type = SOCK_RAW;
- a->size = sizeof(struct sockaddr_nl);
- a->protocol = family;
-
- return 0;
-}
-
-int socket_address_verify(const SocketAddress *a) {
- assert(a);
-
- switch (socket_address_family(a)) {
-
- case AF_INET:
- if (a->size != sizeof(struct sockaddr_in))
- return -EINVAL;
-
- if (a->sockaddr.in4.sin_port == 0)
- return -EINVAL;
-
- if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM)
- return -EINVAL;
-
- return 0;
-
- case AF_INET6:
- if (a->size != sizeof(struct sockaddr_in6))
- return -EINVAL;
-
- if (a->sockaddr.in6.sin6_port == 0)
- return -EINVAL;
-
- if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM)
- return -EINVAL;
-
- return 0;
-
- case AF_UNIX:
- if (a->size < offsetof(struct sockaddr_un, sun_path))
- return -EINVAL;
-
- if (a->size > offsetof(struct sockaddr_un, sun_path)) {
-
- if (a->sockaddr.un.sun_path[0] != 0) {
- char *e;
-
- /* path */
- if (!(e = memchr(a->sockaddr.un.sun_path, 0, sizeof(a->sockaddr.un.sun_path))))
- return -EINVAL;
-
- if (a->size != offsetof(struct sockaddr_un, sun_path) + (e - a->sockaddr.un.sun_path) + 1)
- return -EINVAL;
- }
- }
-
- if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM && a->type != SOCK_SEQPACKET)
- return -EINVAL;
-
- return 0;
-
- case AF_NETLINK:
-
- if (a->size != sizeof(struct sockaddr_nl))
- return -EINVAL;
-
- if (a->type != SOCK_RAW && a->type != SOCK_DGRAM)
- return -EINVAL;
-
- return 0;
-
- default:
- return -EAFNOSUPPORT;
- }
-}
-
-int socket_address_print(const SocketAddress *a, char **p) {
- int r;
- assert(a);
- assert(p);
-
- if ((r = socket_address_verify(a)) < 0)
- return r;
-
- switch (socket_address_family(a)) {
-
- case AF_INET: {
- char *ret;
-
- if (!(ret = new(char, INET_ADDRSTRLEN+1+5+1)))
- return -ENOMEM;
-
- if (!inet_ntop(AF_INET, &a->sockaddr.in4.sin_addr, ret, INET_ADDRSTRLEN)) {
- free(ret);
- return -errno;
- }
-
- sprintf(strchr(ret, 0), ":%u", ntohs(a->sockaddr.in4.sin_port));
- *p = ret;
- return 0;
- }
-
- case AF_INET6: {
- char *ret;
-
- if (!(ret = new(char, 1+INET6_ADDRSTRLEN+2+5+1)))
- return -ENOMEM;
-
- ret[0] = '[';
- if (!inet_ntop(AF_INET6, &a->sockaddr.in6.sin6_addr, ret+1, INET6_ADDRSTRLEN)) {
- free(ret);
- return -errno;
- }
-
- sprintf(strchr(ret, 0), "]:%u", ntohs(a->sockaddr.in6.sin6_port));
- *p = ret;
- return 0;
- }
-
- case AF_UNIX: {
- char *ret;
-
- if (a->size <= offsetof(struct sockaddr_un, sun_path)) {
-
- if (!(ret = strdup("<unnamed>")))
- return -ENOMEM;
-
- } else if (a->sockaddr.un.sun_path[0] == 0) {
- /* abstract */
-
- /* FIXME: We assume we can print the
- * socket path here and that it hasn't
- * more than one NUL byte. That is
- * actually an invalid assumption */
-
- if (!(ret = new(char, sizeof(a->sockaddr.un.sun_path)+1)))
- return -ENOMEM;
-
- ret[0] = '@';
- memcpy(ret+1, a->sockaddr.un.sun_path+1, sizeof(a->sockaddr.un.sun_path)-1);
- ret[sizeof(a->sockaddr.un.sun_path)] = 0;
-
- } else {
-
- if (!(ret = strdup(a->sockaddr.un.sun_path)))
- return -ENOMEM;
- }
-
- *p = ret;
- return 0;
- }
-
- case AF_NETLINK: {
- char _cleanup_free_ *sfamily = NULL;
-
- r = netlink_family_to_string_alloc(a->protocol, &sfamily);
- if (r < 0)
- return r;
- r = asprintf(p, "%s %u", sfamily, a->sockaddr.nl.nl_groups);
-
- return 0;
- }
-
- default:
- return -EINVAL;
- }
-}
-
-bool socket_address_can_accept(const SocketAddress *a) {
- assert(a);
-
- return
- a->type == SOCK_STREAM ||
- a->type == SOCK_SEQPACKET;
-}
-
-bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) {
- assert(a);
- assert(b);
-
- /* Invalid addresses are unequal to all */
- if (socket_address_verify(a) < 0 ||
- socket_address_verify(b) < 0)
- return false;
-
- if (a->type != b->type)
- return false;
-
- if (a->size != b->size)
- return false;
-
- if (socket_address_family(a) != socket_address_family(b))
- return false;
-
- switch (socket_address_family(a)) {
-
- case AF_INET:
- if (a->sockaddr.in4.sin_addr.s_addr != b->sockaddr.in4.sin_addr.s_addr)
- return false;
-
- if (a->sockaddr.in4.sin_port != b->sockaddr.in4.sin_port)
- return false;
-
- break;
-
- case AF_INET6:
- if (memcmp(&a->sockaddr.in6.sin6_addr, &b->sockaddr.in6.sin6_addr, sizeof(a->sockaddr.in6.sin6_addr)) != 0)
- return false;
-
- if (a->sockaddr.in6.sin6_port != b->sockaddr.in6.sin6_port)
- return false;
-
- break;
-
- case AF_UNIX:
-
- if ((a->sockaddr.un.sun_path[0] == 0) != (b->sockaddr.un.sun_path[0] == 0))
- return false;
-
- if (a->sockaddr.un.sun_path[0]) {
- if (strncmp(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, sizeof(a->sockaddr.un.sun_path)) != 0)
- return false;
- } else {
- if (memcmp(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, a->size) != 0)
- return false;
- }
-
- break;
-
- case AF_NETLINK:
-
- if (a->protocol != b->protocol)
- return false;
-
- if (a->sockaddr.nl.nl_groups != b->sockaddr.nl.nl_groups)
- return false;
-
- break;
-
- default:
- /* Cannot compare, so we assume the addresses are different */
- return false;
- }
-
- return true;
-}
-
-bool socket_address_is(const SocketAddress *a, const char *s, int type) {
- struct SocketAddress b;
-
- assert(a);
- assert(s);
-
- if (socket_address_parse(&b, s) < 0)
- return false;
-
- b.type = type;
-
- return socket_address_equal(a, &b);
-}
-
-bool socket_address_is_netlink(const SocketAddress *a, const char *s) {
- struct SocketAddress b;
-
- assert(a);
- assert(s);
-
- if (socket_address_parse_netlink(&b, s) < 0)
- return false;
-
- return socket_address_equal(a, &b);
-}
-
-bool socket_address_needs_mount(const SocketAddress *a, const char *prefix) {
- assert(a);
-
- if (socket_address_family(a) != AF_UNIX)
- return false;
-
- if (a->sockaddr.un.sun_path[0] == 0)
- return false;
-
- return path_startswith(a->sockaddr.un.sun_path, prefix);
-}
-
-bool socket_ipv6_is_supported(void) {
- char *l = 0;
- bool enabled;
-
- if (access("/sys/module/ipv6", F_OK) != 0)
- return 0;
-
- /* If we can't check "disable" parameter, assume enabled */
- if (read_one_line_file("/sys/module/ipv6/parameters/disable", &l) < 0)
- return 1;
-
- /* If module was loaded with disable=1 no IPv6 available */
- enabled = l[0] == '0';
- free(l);
-
- return enabled;
-}
-
-static const char* const netlink_family_table[] = {
- [NETLINK_ROUTE] = "route",
- [NETLINK_FIREWALL] = "firewall",
- [NETLINK_INET_DIAG] = "inet-diag",
- [NETLINK_NFLOG] = "nflog",
- [NETLINK_XFRM] = "xfrm",
- [NETLINK_SELINUX] = "selinux",
- [NETLINK_ISCSI] = "iscsi",
- [NETLINK_AUDIT] = "audit",
- [NETLINK_FIB_LOOKUP] = "fib-lookup",
- [NETLINK_CONNECTOR] = "connector",
- [NETLINK_NETFILTER] = "netfilter",
- [NETLINK_IP6_FW] = "ip6-fw",
- [NETLINK_DNRTMSG] = "dnrtmsg",
- [NETLINK_KOBJECT_UEVENT] = "kobject-uevent",
- [NETLINK_GENERIC] = "generic",
- [NETLINK_SCSITRANSPORT] = "scsitransport",
- [NETLINK_ECRYPTFS] = "ecryptfs"
-};
-
-DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family, int, INT_MAX);
-
-static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX] = {
- [SOCKET_ADDRESS_DEFAULT] = "default",
- [SOCKET_ADDRESS_BOTH] = "both",
- [SOCKET_ADDRESS_IPV6_ONLY] = "ipv6-only"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
diff --git a/src/shared/socket-util.h b/src/shared/socket-util.h
deleted file mode 100644
index 04cfb83f5a..0000000000
--- a/src/shared/socket-util.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*-*- 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/socket.h>
-#include <netinet/in.h>
-#include <sys/un.h>
-#include <net/if.h>
-#include <asm/types.h>
-#include <linux/netlink.h>
-
-#include "macro.h"
-#include "util.h"
-
-union sockaddr_union {
- struct sockaddr sa;
- struct sockaddr_in in4;
- struct sockaddr_in6 in6;
- struct sockaddr_un un;
- struct sockaddr_nl nl;
- struct sockaddr_storage storage;
-};
-
-typedef struct SocketAddress {
- union sockaddr_union sockaddr;
-
- /* We store the size here explicitly due to the weird
- * sockaddr_un semantics for abstract sockets */
- socklen_t size;
-
- /* Socket type, i.e. SOCK_STREAM, SOCK_DGRAM, ... */
- int type;
-
- /* Socket protocol, IPPROTO_xxx, usually 0, except for netlink */
- int protocol;
-} SocketAddress;
-
-typedef enum SocketAddressBindIPv6Only {
- SOCKET_ADDRESS_DEFAULT,
- SOCKET_ADDRESS_BOTH,
- SOCKET_ADDRESS_IPV6_ONLY,
- _SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX,
- _SOCKET_ADDRESS_BIND_IPV6_ONLY_INVALID = -1
-} SocketAddressBindIPv6Only;
-
-#define socket_address_family(a) ((a)->sockaddr.sa.sa_family)
-
-int socket_address_parse(SocketAddress *a, const char *s);
-int socket_address_parse_netlink(SocketAddress *a, const char *s);
-int socket_address_print(const SocketAddress *a, char **p);
-int socket_address_verify(const SocketAddress *a);
-
-bool socket_address_can_accept(const SocketAddress *a);
-
-int socket_address_listen(
- const SocketAddress *a,
- int backlog,
- SocketAddressBindIPv6Only only,
- const char *bind_to_device,
- bool free_bind,
- bool transparent,
- mode_t directory_mode,
- mode_t socket_mode,
- const char *label,
- int *ret);
-
-bool socket_address_is(const SocketAddress *a, const char *s, int type);
-bool socket_address_is_netlink(const SocketAddress *a, const char *s);
-
-bool socket_address_equal(const SocketAddress *a, const SocketAddress *b);
-
-bool socket_address_needs_mount(const SocketAddress *a, const char *prefix);
-
-const char* socket_address_bind_ipv6_only_to_string(SocketAddressBindIPv6Only b);
-SocketAddressBindIPv6Only socket_address_bind_ipv6_only_from_string(const char *s);
-
-int netlink_family_to_string_alloc(int b, char **s);
-int netlink_family_from_string(const char *s);
-
-bool socket_ipv6_is_supported(void);
diff --git a/src/shared/sparse-endian.h b/src/shared/sparse-endian.h
deleted file mode 100644
index eb4dbf3615..0000000000
--- a/src/shared/sparse-endian.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* Copyright (c) 2012 Josh Triplett <josh@joshtriplett.org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#ifndef SPARSE_ENDIAN_H
-#define SPARSE_ENDIAN_H
-
-#include <endian.h>
-#include <stdint.h>
-
-#ifdef __CHECKER__
-#define __bitwise __attribute__((bitwise))
-#define __force __attribute__((force))
-#else
-#define __bitwise
-#define __force
-#endif
-
-typedef uint16_t __bitwise le16_t;
-typedef uint16_t __bitwise be16_t;
-typedef uint32_t __bitwise le32_t;
-typedef uint32_t __bitwise be32_t;
-typedef uint64_t __bitwise le64_t;
-typedef uint64_t __bitwise be64_t;
-
-#undef htobe16
-#undef htole16
-#undef be16toh
-#undef le16toh
-#undef htobe32
-#undef htole32
-#undef be32toh
-#undef le32toh
-#undef htobe64
-#undef htole64
-#undef be64toh
-#undef le64toh
-
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define bswap_16_on_le(x) __bswap_16(x)
-#define bswap_32_on_le(x) __bswap_32(x)
-#define bswap_64_on_le(x) __bswap_64(x)
-#define bswap_16_on_be(x) (x)
-#define bswap_32_on_be(x) (x)
-#define bswap_64_on_be(x) (x)
-#elif __BYTE_ORDER == __BIG_ENDIAN
-#define bswap_16_on_le(x) (x)
-#define bswap_32_on_le(x) (x)
-#define bswap_64_on_le(x) (x)
-#define bswap_16_on_be(x) __bswap_16(x)
-#define bswap_32_on_be(x) __bswap_32(x)
-#define bswap_64_on_be(x) __bswap_64(x)
-#endif
-
-static inline le16_t htole16(uint16_t value) { return (le16_t __force) bswap_16_on_be(value); }
-static inline le32_t htole32(uint32_t value) { return (le32_t __force) bswap_32_on_be(value); }
-static inline le64_t htole64(uint64_t value) { return (le64_t __force) bswap_64_on_be(value); }
-
-static inline be16_t htobe16(uint16_t value) { return (be16_t __force) bswap_16_on_le(value); }
-static inline be32_t htobe32(uint32_t value) { return (be32_t __force) bswap_32_on_le(value); }
-static inline be64_t htobe64(uint64_t value) { return (be64_t __force) bswap_64_on_le(value); }
-
-static inline uint16_t le16toh(le16_t value) { return bswap_16_on_be((uint16_t __force)value); }
-static inline uint32_t le32toh(le32_t value) { return bswap_32_on_be((uint32_t __force)value); }
-static inline uint64_t le64toh(le64_t value) { return bswap_64_on_be((uint64_t __force)value); }
-
-static inline uint16_t be16toh(be16_t value) { return bswap_16_on_le((uint16_t __force)value); }
-static inline uint32_t be32toh(be32_t value) { return bswap_32_on_le((uint32_t __force)value); }
-static inline uint64_t be64toh(be64_t value) { return bswap_64_on_le((uint64_t __force)value); }
-
-#endif /* SPARSE_ENDIAN_H */
diff --git a/src/shared/spawn-ask-password-agent.c b/src/shared/spawn-ask-password-agent.c
deleted file mode 100644
index c1a9c58681..0000000000
--- a/src/shared/spawn-ask-password-agent.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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/types.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/prctl.h>
-#include <signal.h>
-#include <fcntl.h>
-
-#include "log.h"
-#include "util.h"
-#include "spawn-ask-password-agent.h"
-
-static pid_t agent_pid = 0;
-
-int ask_password_agent_open(void) {
- int r;
-
- if (agent_pid > 0)
- return 0;
-
- /* We check STDIN here, not STDOUT, since this is about input,
- * not output */
- if (!isatty(STDIN_FILENO))
- return 0;
-
- r = fork_agent(&agent_pid,
- NULL, 0,
- SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH,
- SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH, "--watch", NULL);
- if (r < 0)
- log_error("Failed to fork TTY ask password agent: %s", strerror(-r));
-
- return r;
-}
-
-void ask_password_agent_close(void) {
-
- if (agent_pid <= 0)
- return;
-
- /* Inform agent that we are done */
- kill(agent_pid, SIGTERM);
- kill(agent_pid, SIGCONT);
- wait_for_terminate(agent_pid, NULL);
- agent_pid = 0;
-}
diff --git a/src/shared/spawn-ask-password-agent.h b/src/shared/spawn-ask-password-agent.h
deleted file mode 100644
index 31b4beab58..0000000000
--- a/src/shared/spawn-ask-password-agent.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 ask_password_agent_open(void);
-void ask_password_agent_close(void);
diff --git a/src/shared/spawn-polkit-agent.c b/src/shared/spawn-polkit-agent.c
deleted file mode 100644
index fcb3722ddf..0000000000
--- a/src/shared/spawn-polkit-agent.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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/types.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/prctl.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/poll.h>
-
-#include "log.h"
-#include "util.h"
-#include "spawn-polkit-agent.h"
-
-static pid_t agent_pid = 0;
-
-int polkit_agent_open(void) {
- int r;
- int pipe_fd[2];
- char notify_fd[10 + 1];
-
- if (agent_pid > 0)
- return 0;
-
- /* We check STDIN here, not STDOUT, since this is about input,
- * not output */
- if (!isatty(STDIN_FILENO))
- return 0;
-
- if (pipe2(pipe_fd, 0) < 0)
- return -errno;
-
- snprintf(notify_fd, sizeof(notify_fd), "%i", pipe_fd[1]);
- char_array_0(notify_fd);
-
- r = fork_agent(&agent_pid,
- &pipe_fd[1], 1,
- POLKIT_AGENT_BINARY_PATH,
- POLKIT_AGENT_BINARY_PATH, "--notify-fd", notify_fd, "--fallback", NULL);
-
- /* Close the writing side, because that's the one for the agent */
- close_nointr_nofail(pipe_fd[1]);
-
- if (r < 0)
- log_error("Failed to fork TTY ask password agent: %s", strerror(-r));
- else
- /* Wait until the agent closes the fd */
- fd_wait_for_event(pipe_fd[0], POLLHUP, (usec_t) -1);
-
- close_nointr_nofail(pipe_fd[0]);
-
- return r;
-}
-
-void polkit_agent_close(void) {
-
- if (agent_pid <= 0)
- return;
-
- /* Inform agent that we are done */
- kill(agent_pid, SIGTERM);
- kill(agent_pid, SIGCONT);
- wait_for_terminate(agent_pid, NULL);
- agent_pid = 0;
-}
diff --git a/src/shared/spawn-polkit-agent.h b/src/shared/spawn-polkit-agent.h
deleted file mode 100644
index b91d20f120..0000000000
--- a/src/shared/spawn-polkit-agent.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef foospawnpolkitagenthfoo
-#define foospawnpolkitagenthfoo
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-int polkit_agent_open(void);
-void polkit_agent_close(void);
-
-#endif
diff --git a/src/shared/specifier.c b/src/shared/specifier.c
deleted file mode 100644
index 599027cd47..0000000000
--- a/src/shared/specifier.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*-*- 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 "macro.h"
-#include "util.h"
-#include "specifier.h"
-
-/*
- * Generic infrastructure for replacing %x style specifiers in
- * strings. Will call a callback for each replacement.
- *
- */
-
-char *specifier_printf(const char *text, const Specifier table[], void *userdata) {
- char *r, *t;
- const char *f;
- bool percent = false;
- size_t l;
-
- assert(text);
- assert(table);
-
- l = strlen(text);
- r = new(char, l+1);
- if (!r)
- return NULL;
-
- t = r;
-
- for (f = text; *f; f++, l--) {
-
- if (percent) {
- if (*f == '%')
- *(t++) = '%';
- else {
- const Specifier *i;
-
- for (i = table; i->specifier; i++)
- if (i->specifier == *f)
- break;
-
- if (i->lookup) {
- char *n, *w;
- size_t k, j;
-
- w = i->lookup(i->specifier, i->data, userdata);
- if (!w) {
- free(r);
- return NULL;
- }
-
- j = t - r;
- k = strlen(w);
-
- n = new(char, j + k + l + 1);
- if (!n) {
- free(r);
- free(w);
- return NULL;
- }
-
- memcpy(n, r, j);
- memcpy(n + j, w, k);
-
- free(r);
- free(w);
-
- r = n;
- t = n + j + k;
- } else {
- *(t++) = '%';
- *(t++) = *f;
- }
- }
-
- percent = false;
- } else if (*f == '%')
- percent = true;
- else
- *(t++) = *f;
- }
-
- *t = 0;
- return r;
-}
-
-/* Generic handler for simple string replacements */
-
-char* specifier_string(char specifier, void *data, void *userdata) {
- return strdup(strempty(data));
-}
diff --git a/src/shared/specifier.h b/src/shared/specifier.h
deleted file mode 100644
index 25a27a423f..0000000000
--- a/src/shared/specifier.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*-*- 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/>.
-***/
-
-typedef char* (*SpecifierCallback)(char specifier, void *data, void *userdata);
-
-typedef struct Specifier {
- const char specifier;
- const SpecifierCallback lookup;
- void *data;
-} Specifier;
-
-char *specifier_printf(const char *text, const Specifier table[], void *userdata);
-
-char* specifier_string(char specifier, void *data, void *userdata);
diff --git a/src/shared/strbuf.c b/src/shared/strbuf.c
deleted file mode 100644
index 915cd3ac99..0000000000
--- a/src/shared/strbuf.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Kay Sievers <kay@vrfy.org>
-
- 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 "util.h"
-#include "strbuf.h"
-
-/*
- * Strbuf stores given strings in a single continous allocated memory
- * area. Identical strings are de-duplicated and return the same offset
- * as the first string stored. If the tail of a string already exists
- * in the buffer, the tail is returned.
- *
- * A trie (http://en.wikipedia.org/wiki/Trie) is used to maintain the
- * information about the stored strings.
- *
- * Example of udev rules:
- * $ ./udevadm test .
- * ...
- * read rules file: /usr/lib/udev/rules.d/99-systemd.rules
- * rules contain 196608 bytes tokens (16384 * 12 bytes), 39742 bytes strings
- * 23939 strings (207859 bytes), 20404 de-duplicated (171653 bytes), 3536 trie nodes used
- * ...
- */
-
-struct strbuf *strbuf_new(void) {
- struct strbuf *str;
-
- str = new0(struct strbuf, 1);
- if (!str)
- return NULL;
-
- str->buf = new0(char, 1);
- if (!str->buf)
- goto err;
- str->len = 1;
-
- str->root = new0(struct strbuf_node, 1);
- if (!str->root)
- goto err;
- str->nodes_count = 1;
- return str;
-err:
- free(str->buf);
- free(str->root);
- free(str);
- return NULL;
-}
-
-static void strbuf_node_cleanup(struct strbuf_node *node) {
- size_t i;
-
- for (i = 0; i < node->children_count; i++)
- strbuf_node_cleanup(node->children[i].child);
- free(node->children);
- free(node);
-}
-
-/* clean up trie data, leave only the string buffer */
-void strbuf_complete(struct strbuf *str) {
- if (!str)
- return;
- if (str->root)
- strbuf_node_cleanup(str->root);
- str->root = NULL;
-}
-
-/* clean up everything */
-void strbuf_cleanup(struct strbuf *str) {
- if (!str)
- return;
- if (str->root)
- strbuf_node_cleanup(str->root);
- free(str->buf);
- free(str);
-}
-
-static int strbuf_children_cmp(const void *v1, const void *v2) {
- const struct strbuf_child_entry *n1 = v1;
- const struct strbuf_child_entry *n2 = v2;
-
- return n1->c - n2->c;
-}
-
-/* add string, return the index/offset into the buffer */
-ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len) {
- uint8_t c;
- struct strbuf_node *node;
- size_t depth;
- char *buf_new;
- struct strbuf_child_entry *child;
- struct strbuf_node *node_child;
- ssize_t off;
-
- if (!str->root)
- return -EINVAL;
-
- /* search string; start from last character to find possibly matching tails */
- if (len == 0)
- return 0;
- str->in_count++;
- str->in_len += len;
-
- node = str->root;
- c = s[len-1];
- for (depth = 0; depth <= len; depth++) {
- struct strbuf_child_entry search;
-
- /* match against current node */
- off = node->value_off + node->value_len - len;
- if (depth == len || (node->value_len >= len && memcmp(str->buf + off, s, len) == 0)) {
- str->dedup_len += len;
- str->dedup_count++;
- return off;
- }
-
- /* lookup child node */
- c = s[len - 1 - depth];
- search.c = c;
- child = bsearch(&search, node->children, node->children_count, sizeof(struct strbuf_child_entry),
- strbuf_children_cmp);
- if (!child)
- break;
- node = child->child;
- }
-
- /* add new string */
- buf_new = realloc(str->buf, str->len + len+1);
- if (!buf_new)
- return -ENOMEM;
- str->buf = buf_new;
- off = str->len;
- memcpy(str->buf + off, s, len);
- str->len += len;
- str->buf[str->len++] = '\0';
-
- /* new node */
- node_child = new0(struct strbuf_node, 1);
- if (!node_child)
- return -ENOMEM;
- str->nodes_count++;
- node_child->value_off = off;
- node_child->value_len = len;
-
- /* extend array, add new entry, sort for bisection */
- child = realloc(node->children, (node->children_count + 1) * sizeof(struct strbuf_child_entry));
- if (!child)
- return -ENOMEM;
- node->children = child;
- node->children[node->children_count].c = c;
- node->children[node->children_count].child = node_child;
- node->children_count++;
- qsort(node->children, node->children_count, sizeof(struct strbuf_child_entry), strbuf_children_cmp);
-
- return off;
-}
diff --git a/src/shared/strbuf.h b/src/shared/strbuf.h
deleted file mode 100644
index 2347fd4328..0000000000
--- a/src/shared/strbuf.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Kay Sievers <kay@vrfy.org>
-
- 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 <stdarg.h>
-#include <stdint.h>
-#include <stdbool.h>
-
-struct strbuf {
- char *buf;
- size_t len;
- struct strbuf_node *root;
-
- size_t nodes_count;
- size_t in_count;
- size_t in_len;
- size_t dedup_len;
- size_t dedup_count;
-};
-
-struct strbuf_node {
- size_t value_off;
- size_t value_len;
-
- struct strbuf_child_entry *children;
- uint8_t children_count;
-};
-
-struct strbuf_child_entry {
- uint8_t c;
- struct strbuf_node *child;
-};
-
-struct strbuf *strbuf_new(void);
-ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len);
-void strbuf_complete(struct strbuf *str);
-void strbuf_cleanup(struct strbuf *str);
diff --git a/src/shared/strv.c b/src/shared/strv.c
deleted file mode 100644
index 6b76d0eaef..0000000000
--- a/src/shared/strv.c
+++ /dev/null
@@ -1,750 +0,0 @@
-/*-*- 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 <assert.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <errno.h>
-
-#include "util.h"
-#include "strv.h"
-
-char *strv_find(char **l, const char *name) {
- char **i;
-
- assert(name);
-
- STRV_FOREACH(i, l)
- if (streq(*i, name))
- return *i;
-
- return NULL;
-}
-
-char *strv_find_prefix(char **l, const char *name) {
- char **i;
-
- assert(name);
-
- STRV_FOREACH(i, l)
- if (startswith(*i, name))
- return *i;
-
- return NULL;
-}
-
-void strv_free(char **l) {
- char **k;
-
- if (!l)
- return;
-
- for (k = l; *k; k++)
- free(*k);
-
- free(l);
-}
-
-void strv_freep(char ***l) {
- if (!l)
- return;
-
- strv_free(*l);
- *l = NULL;
-}
-
-char **strv_copy(char **l) {
- char **r, **k;
-
- k = r = new(char*, strv_length(l) + 1);
- if (!r)
- return NULL;
-
- if (l)
- for (; *l; k++, l++) {
- *k = strdup(*l);
- if (!*k) {
- strv_free(r);
- return NULL;
- }
- }
-
- *k = NULL;
- return r;
-}
-
-unsigned strv_length(char **l) {
- unsigned n = 0;
-
- if (!l)
- return 0;
-
- for (; *l; l++)
- n++;
-
- return n;
-}
-
-char **strv_new_ap(const char *x, va_list ap) {
- const char *s;
- char **a;
- unsigned n = 0, i = 0;
- va_list aq;
-
- /* As a special trick we ignore all listed strings that equal
- * (const char*) -1. This is supposed to be used with the
- * STRV_IFNOTNULL() macro to include possibly NULL strings in
- * the string list. */
-
- if (x) {
- n = x == (const char*) -1 ? 0 : 1;
-
- va_copy(aq, ap);
- while ((s = va_arg(aq, const char*))) {
- if (s == (const char*) -1)
- continue;
-
- n++;
- }
-
- va_end(aq);
- }
-
- a = new(char*, n+1);
- if (!a)
- return NULL;
-
- if (x) {
- if (x != (const char*) -1) {
- a[i] = strdup(x);
- if (!a[i])
- goto fail;
- i++;
- }
-
- while ((s = va_arg(ap, const char*))) {
-
- if (s == (const char*) -1)
- continue;
-
- a[i] = strdup(s);
- if (!a[i])
- goto fail;
-
- i++;
- }
- }
-
- a[i] = NULL;
-
- return a;
-
-fail:
- strv_free(a);
- return NULL;
-}
-
-char **strv_new(const char *x, ...) {
- char **r;
- va_list ap;
-
- va_start(ap, x);
- r = strv_new_ap(x, ap);
- va_end(ap);
-
- return r;
-}
-
-char **strv_merge(char **a, char **b) {
- char **r, **k;
-
- if (!a)
- return strv_copy(b);
-
- if (!b)
- return strv_copy(a);
-
- r = new(char*, strv_length(a) + strv_length(b) + 1);
- if (!r)
- return NULL;
-
- for (k = r; *a; k++, a++) {
- *k = strdup(*a);
- if (!*k)
- goto fail;
- }
-
- for (; *b; k++, b++) {
- *k = strdup(*b);
- if (!*k)
- goto fail;
- }
-
- *k = NULL;
- return r;
-
-fail:
- strv_free(r);
- return NULL;
-}
-
-char **strv_merge_concat(char **a, char **b, const char *suffix) {
- char **r, **k;
-
- /* Like strv_merge(), but appends suffix to all strings in b, before adding */
-
- if (!b)
- return strv_copy(a);
-
- r = new(char*, strv_length(a) + strv_length(b) + 1);
- if (!r)
- return NULL;
-
- k = r;
- if (a)
- for (; *a; k++, a++) {
- *k = strdup(*a);
- if (!*k)
- goto fail;
- }
-
- for (; *b; k++, b++) {
- *k = strappend(*b, suffix);
- if (!*k)
- goto fail;
- }
-
- *k = NULL;
- return r;
-
-fail:
- strv_free(r);
- return NULL;
-
-}
-
-char **strv_split(const char *s, const char *separator) {
- char *state;
- char *w;
- size_t l;
- unsigned n, i;
- char **r;
-
- assert(s);
-
- n = 0;
- FOREACH_WORD_SEPARATOR(w, l, s, separator, state)
- n++;
-
- r = new(char*, n+1);
- if (!r)
- return NULL;
-
- i = 0;
- FOREACH_WORD_SEPARATOR(w, l, s, separator, state) {
- r[i] = strndup(w, l);
- if (!r[i]) {
- strv_free(r);
- return NULL;
- }
-
- i++;
- }
-
- r[i] = NULL;
- return r;
-}
-
-char **strv_split_quoted(const char *s) {
- char *state;
- char *w;
- size_t l;
- unsigned n, i;
- char **r;
-
- assert(s);
-
- n = 0;
- FOREACH_WORD_QUOTED(w, l, s, state)
- n++;
-
- r = new(char*, n+1);
- if (!r)
- return NULL;
-
- i = 0;
- FOREACH_WORD_QUOTED(w, l, s, state) {
- r[i] = cunescape_length(w, l);
- if (!r[i]) {
- strv_free(r);
- return NULL;
- }
- i++;
- }
-
- r[i] = NULL;
- return r;
-}
-
-char *strv_join(char **l, const char *separator) {
- char *r, *e;
- char **s;
- size_t n, k;
-
- if (!separator)
- separator = " ";
-
- k = strlen(separator);
-
- n = 0;
- STRV_FOREACH(s, l) {
- if (n != 0)
- n += k;
- n += strlen(*s);
- }
-
- r = new(char, n+1);
- if (!r)
- return NULL;
-
- e = r;
- STRV_FOREACH(s, l) {
- if (e != r)
- e = stpcpy(e, separator);
-
- e = stpcpy(e, *s);
- }
-
- *e = 0;
-
- return r;
-}
-
-char **strv_append(char **l, const char *s) {
- char **r, **k;
-
- if (!l)
- return strv_new(s, NULL);
-
- if (!s)
- return strv_copy(l);
-
- r = new(char*, strv_length(l)+2);
- if (!r)
- return NULL;
-
- for (k = r; *l; k++, l++) {
- *k = strdup(*l);
- if (!*k)
- goto fail;
- }
-
- k[0] = strdup(s);
- if (!k[0])
- goto fail;
-
- k[1] = NULL;
- return r;
-
-fail:
- strv_free(r);
- return NULL;
-}
-
-char **strv_uniq(char **l) {
- char **i;
-
- /* Drops duplicate entries. The first identical string will be
- * kept, the others dropped */
-
- STRV_FOREACH(i, l)
- strv_remove(i+1, *i);
-
- return l;
-}
-
-char **strv_remove(char **l, const char *s) {
- char **f, **t;
-
- if (!l)
- return NULL;
-
- assert(s);
-
- /* Drops every occurrence of s in the string list, edits
- * in-place. */
-
- for (f = t = l; *f; f++) {
-
- if (streq(*f, s)) {
- free(*f);
- continue;
- }
-
- *(t++) = *f;
- }
-
- *t = NULL;
- return l;
-}
-
-char **strv_remove_prefix(char **l, const char *s) {
- char **f, **t;
-
- if (!l)
- return NULL;
-
- assert(s);
-
- /* Drops every occurrence of a string prefixed with s in the
- * string list, edits in-place. */
-
- for (f = t = l; *f; f++) {
-
- if (startswith(*f, s)) {
- free(*f);
- continue;
- }
-
- *(t++) = *f;
- }
-
- *t = NULL;
- return l;
-}
-
-static int env_append(char **r, char ***k, char **a) {
- assert(r);
- assert(k);
-
- if (!a)
- return 0;
-
- /* Add the entries of a to *k unless they already exist in *r
- * in which case they are overridden instead. This assumes
- * there is enough space in the r array. */
-
- for (; *a; a++) {
- char **j;
- size_t n;
-
- n = strcspn(*a, "=");
-
- if ((*a)[n] == '=')
- n++;
-
- for (j = r; j < *k; j++)
- if (strncmp(*j, *a, n) == 0)
- break;
-
- if (j >= *k)
- (*k)++;
- else
- free(*j);
-
- *j = strdup(*a);
- if (!*j)
- return -ENOMEM;
- }
-
- return 0;
-}
-
-char **strv_env_merge(unsigned n_lists, ...) {
- size_t n = 0;
- char **l, **k, **r;
- va_list ap;
- unsigned i;
-
- /* Merges an arbitrary number of environment sets */
-
- va_start(ap, n_lists);
- for (i = 0; i < n_lists; i++) {
- l = va_arg(ap, char**);
- n += strv_length(l);
- }
- va_end(ap);
-
- r = new(char*, n+1);
- if (!r)
- return NULL;
-
- k = r;
-
- va_start(ap, n_lists);
- for (i = 0; i < n_lists; i++) {
- l = va_arg(ap, char**);
- if (env_append(r, &k, l) < 0)
- goto fail;
- }
- va_end(ap);
-
- *k = NULL;
-
- return r;
-
-fail:
- va_end(ap);
- strv_free(r);
-
- return NULL;
-}
-
-static bool env_match(const char *t, const char *pattern) {
- assert(t);
- assert(pattern);
-
- /* pattern a matches string a
- * a matches a=
- * a matches a=b
- * a= matches a=
- * a=b matches a=b
- * a= does not match a
- * a=b does not match a=
- * a=b does not match a
- * a=b does not match a=c */
-
- if (streq(t, pattern))
- return true;
-
- if (!strchr(pattern, '=')) {
- size_t l = strlen(pattern);
-
- return strncmp(t, pattern, l) == 0 && t[l] == '=';
- }
-
- return false;
-}
-
-char **strv_env_delete(char **x, unsigned n_lists, ...) {
- size_t n, i = 0;
- char **k, **r;
- va_list ap;
-
- /* Deletes every entry from x that is mentioned in the other
- * string lists */
-
- n = strv_length(x);
-
- r = new(char*, n+1);
- if (!r)
- return NULL;
-
- STRV_FOREACH(k, x) {
- unsigned v;
-
- va_start(ap, n_lists);
- for (v = 0; v < n_lists; v++) {
- char **l, **j;
-
- l = va_arg(ap, char**);
- STRV_FOREACH(j, l)
- if (env_match(*k, *j))
- goto skip;
- }
- va_end(ap);
-
- r[i] = strdup(*k);
- if (!r[i]) {
- strv_free(r);
- return NULL;
- }
-
- i++;
- continue;
-
- skip:
- va_end(ap);
- }
-
- r[i] = NULL;
-
- assert(i <= n);
-
- return r;
-}
-
-char **strv_env_unset(char **l, const char *p) {
-
- char **f, **t;
-
- if (!l)
- return NULL;
-
- assert(p);
-
- /* Drops every occurrence of the env var setting p in the
- * string list. edits in-place. */
-
- for (f = t = l; *f; f++) {
-
- if (env_match(*f, p)) {
- free(*f);
- continue;
- }
-
- *(t++) = *f;
- }
-
- *t = NULL;
- return l;
-}
-
-char **strv_env_set(char **x, const char *p) {
-
- char **k, **r;
- char* m[2] = { (char*) p, NULL };
-
- /* Overrides the env var setting of p, returns a new copy */
-
- r = new(char*, strv_length(x)+2);
- if (!r)
- return NULL;
-
- k = r;
- if (env_append(r, &k, x) < 0)
- goto fail;
-
- if (env_append(r, &k, m) < 0)
- goto fail;
-
- *k = NULL;
-
- return r;
-
-fail:
- strv_free(r);
- return NULL;
-
-}
-
-char *strv_env_get_with_length(char **l, const char *name, size_t k) {
- char **i;
-
- assert(name);
-
- STRV_FOREACH(i, l)
- if (strncmp(*i, name, k) == 0 &&
- (*i)[k] == '=')
- return *i + k + 1;
-
- return NULL;
-}
-
-char *strv_env_get(char **l, const char *name) {
- return strv_env_get_with_length(l, name, strlen(name));
-}
-
-char **strv_env_clean(char **l) {
- char **r, **ret;
-
- for (r = ret = l; *l; l++) {
- const char *equal;
-
- equal = strchr(*l, '=');
-
- if (equal && equal[1] == 0) {
- free(*l);
- continue;
- }
-
- *(r++) = *l;
- }
-
- *r = NULL;
-
- return ret;
-}
-
-char **strv_parse_nulstr(const char *s, size_t l) {
- const char *p;
- unsigned c = 0, i = 0;
- char **v;
-
- assert(s || l <= 0);
-
- if (l <= 0)
- return strv_new(NULL, NULL);
-
- for (p = s; p < s + l; p++)
- if (*p == 0)
- c++;
-
- if (s[l-1] != 0)
- c++;
-
- v = new0(char*, c+1);
- if (!v)
- return NULL;
-
- p = s;
- while (p < s + l) {
- const char *e;
-
- e = memchr(p, 0, s + l - p);
-
- v[i] = strndup(p, e ? e - p : s + l - p);
- if (!v[i]) {
- strv_free(v);
- return NULL;
- }
-
- i++;
-
- if (!e)
- break;
-
- p = e + 1;
- }
-
- assert(i == c);
-
- return v;
-}
-
-bool strv_overlap(char **a, char **b) {
- char **i, **j;
-
- STRV_FOREACH(i, a) {
- STRV_FOREACH(j, b) {
- if (streq(*i, *j))
- return true;
- }
- }
-
- return false;
-}
-
-static int str_compare(const void *_a, const void *_b) {
- const char **a = (const char**) _a, **b = (const char**) _b;
-
- return strcmp(*a, *b);
-}
-
-char **strv_sort(char **l) {
-
- if (strv_isempty(l))
- return l;
-
- qsort(l, strv_length(l), sizeof(char*), str_compare);
- return l;
-}
diff --git a/src/shared/strv.h b/src/shared/strv.h
deleted file mode 100644
index 45558d8960..0000000000
--- a/src/shared/strv.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*-*- 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 <stdarg.h>
-#include <stdbool.h>
-
-#include "macro.h"
-
-char *strv_find(char **l, const char *name);
-char *strv_find_prefix(char **l, const char *name);
-
-void strv_free(char **l);
-void strv_freep(char ***l);
-char **strv_copy(char **l) _malloc_;
-unsigned strv_length(char **l);
-
-char **strv_merge(char **a, char **b);
-char **strv_merge_concat(char **a, char **b, const char *suffix);
-char **strv_append(char **l, const char *s);
-
-char **strv_remove(char **l, const char *s);
-char **strv_remove_prefix(char **l, const char *s);
-char **strv_uniq(char **l);
-
-#define strv_contains(l, s) (!!strv_find((l), (s)))
-
-char **strv_new(const char *x, ...) _sentinel_ _malloc_;
-char **strv_new_ap(const char *x, va_list ap) _malloc_;
-
-static inline const char* STRV_IFNOTNULL(const char *x) {
- return x ? x : (const char *) -1;
-}
-
-static inline bool strv_isempty(char **l) {
- return !l || !*l;
-}
-
-char **strv_split(const char *s, const char *separator) _malloc_;
-char **strv_split_quoted(const char *s) _malloc_;
-
-char *strv_join(char **l, const char *separator) _malloc_;
-
-char **strv_env_merge(unsigned n_lists, ...);
-char **strv_env_delete(char **x, unsigned n_lists, ...);
-
-char **strv_env_set(char **x, const char *p);
-char **strv_env_unset(char **l, const char *p);
-
-char *strv_env_get_with_length(char **l, const char *name, size_t k);
-char *strv_env_get(char **x, const char *n);
-
-char **strv_env_clean(char **l);
-
-char **strv_parse_nulstr(const char *s, size_t l);
-
-bool strv_overlap(char **a, char **b);
-
-#define STRV_FOREACH(s, l) \
- for ((s) = (l); (s) && *(s); (s)++)
-
-#define STRV_FOREACH_BACKWARDS(s, l) \
- for (; (l) && ((s) >= (l)); (s)--)
-
-char **strv_sort(char **l);
diff --git a/src/shared/time-dst.c b/src/shared/time-dst.c
deleted file mode 100644
index afc893cccc..0000000000
--- a/src/shared/time-dst.c
+++ /dev/null
@@ -1,341 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Timezone file reading code from glibc 2.16.
-
- Copyright (C) 1991-2012 Free Software Foundation, Inc.
- Copyright 2012 Kay Sievers
-
- 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 <errno.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <endian.h>
-#include <byteswap.h>
-#include <assert.h>
-#include <limits.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <sys/stat.h>
-
-#include "time-dst.h"
-
-/*
- * If tzh_version is '2' or greater, the above is followed by a second instance
- * of tzhead and a second instance of the data in which each coded transition
- * time uses 8 rather than 4 chars, then a POSIX-TZ-environment-variable-style
- * string for use in handling instants after the last transition time stored in
- * the file * (with nothing between the newlines if there is no POSIX
- * representation for such instants).
- */
-#define TZ_MAGIC "TZif"
-struct tzhead {
- char tzh_magic[4]; /* TZ_MAGIC */
- char tzh_version[1]; /* '\0' or '2' as of 2005 */
- char tzh_reserved[15]; /* reserved--must be zero */
- char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
- char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
- char tzh_leapcnt[4]; /* coded number of leap seconds */
- char tzh_timecnt[4]; /* coded number of transition times */
- char tzh_typecnt[4]; /* coded number of local time types */
- char tzh_charcnt[4]; /* coded number of abbr. chars */
-};
-
-struct ttinfo {
- long int offset; /* Seconds east of GMT. */
- unsigned char isdst; /* Used to set tm_isdst. */
- unsigned char idx; /* Index into `zone_names'. */
- unsigned char isstd; /* Transition times are in standard time. */
- unsigned char isgmt; /* Transition times are in GMT. */
-};
-
-struct leap {
- time_t transition; /* Time the transition takes effect. */
- long int change; /* Seconds of correction to apply. */
-};
-
-static inline int decode(const void *ptr) {
- return be32toh(*(int *)ptr);
-}
-
-static inline int64_t decode64(const void *ptr) {
- return be64toh(*(int64_t *)ptr);
-}
-
-int time_get_dst(time_t date, const char *tzfile,
- time_t *switch_cur, char **zone_cur, bool *dst_cur,
- time_t *switch_next, int *delta_next, char **zone_next, bool *dst_next) {
- time_t *transitions = NULL;
- size_t num_transitions = 0;
- unsigned char *type_idxs = 0;
- size_t num_types = 0;
- struct ttinfo *types = NULL;
- char *zone_names = NULL;
- struct stat st;
- size_t num_isstd, num_isgmt;
- FILE *f;
- struct tzhead tzhead;
- size_t chars;
- size_t i;
- size_t total_size;
- size_t types_idx;
- int trans_width = 4;
- size_t tzspec_len;
- size_t num_leaps;
- size_t lo, hi;
- int err = -EINVAL;
-
- f = fopen(tzfile, "re");
- if (f == NULL)
- return -errno;
-
- if (fstat(fileno(f), &st) < 0) {
- err = -errno;
- fclose(f);
- return err;
- }
-
-read_again:
- if (fread((void *)&tzhead, sizeof(tzhead), 1, f) != 1 ||
- memcmp(tzhead.tzh_magic, TZ_MAGIC, sizeof(tzhead.tzh_magic)) != 0)
- goto lose;
-
- num_transitions = (size_t)decode(tzhead.tzh_timecnt);
- num_types = (size_t)decode(tzhead.tzh_typecnt);
- chars = (size_t)decode(tzhead.tzh_charcnt);
- num_leaps = (size_t)decode(tzhead.tzh_leapcnt);
- num_isstd = (size_t)decode(tzhead.tzh_ttisstdcnt);
- num_isgmt = (size_t)decode(tzhead.tzh_ttisgmtcnt);
-
- /* For platforms with 64-bit time_t we use the new format if available. */
- if (sizeof(time_t) == 8 && trans_width == 4 && tzhead.tzh_version[0] != '\0') {
- size_t to_skip;
-
- /* We use the 8-byte format. */
- trans_width = 8;
-
- /* Position the stream before the second header. */
- to_skip = (num_transitions * (4 + 1)
- + num_types * 6
- + chars
- + num_leaps * 8 + num_isstd + num_isgmt);
- if (fseek(f, to_skip, SEEK_CUR) != 0)
- goto lose;
-
- goto read_again;
- }
-
- if (num_transitions > ((SIZE_MAX - (__alignof__(struct ttinfo) - 1)) / (sizeof(time_t) + 1)))
- goto lose;
-
- total_size = num_transitions * (sizeof(time_t) + 1);
- total_size = ((total_size + __alignof__(struct ttinfo) - 1) & ~(__alignof__(struct ttinfo) - 1));
- types_idx = total_size;
- if (num_leaps > (SIZE_MAX - total_size) / sizeof(struct ttinfo))
- goto lose;
-
- total_size += num_types * sizeof(struct ttinfo);
- if (chars > SIZE_MAX - total_size)
- goto lose;
-
- total_size += chars;
- if (__alignof__(struct leap) - 1 > SIZE_MAX - total_size)
- goto lose;
-
- total_size = ((total_size + __alignof__(struct leap) - 1) & ~(__alignof__(struct leap) - 1));
- if (num_leaps > (SIZE_MAX - total_size) / sizeof(struct leap))
- goto lose;
-
- total_size += num_leaps * sizeof(struct leap);
- tzspec_len = 0;
- if (sizeof(time_t) == 8 && trans_width == 8) {
- off_t rem = st.st_size - ftello(f);
-
- if (rem < 0 || (size_t) rem < (num_transitions * (8 + 1) + num_types * 6 + chars))
- goto lose;
- tzspec_len = (size_t) rem - (num_transitions * (8 + 1) + num_types * 6 + chars);
- if (num_leaps > SIZE_MAX / 12 || tzspec_len < num_leaps * 12)
- goto lose;
- tzspec_len -= num_leaps * 12;
- if (tzspec_len < num_isstd)
- goto lose;
- tzspec_len -= num_isstd;
- if (tzspec_len == 0 || tzspec_len - 1 < num_isgmt)
- goto lose;
- tzspec_len -= num_isgmt + 1;
- if (SIZE_MAX - total_size < tzspec_len)
- goto lose;
- }
-
- transitions = (time_t *)calloc(total_size + tzspec_len, 1);
- if (transitions == NULL)
- goto lose;
-
- type_idxs = (unsigned char *)transitions + (num_transitions
- * sizeof(time_t));
- types = (struct ttinfo *)((char *)transitions + types_idx);
- zone_names = (char *)types + num_types * sizeof(struct ttinfo);
-
- if (sizeof(time_t) == 4 || trans_width == 8) {
- if (fread(transitions, trans_width + 1, num_transitions, f) != num_transitions)
- goto lose;
- } else {
- if (fread(transitions, 4, num_transitions, f) != num_transitions ||
- fread(type_idxs, 1, num_transitions, f) != num_transitions)
- goto lose;
- }
-
- /* Check for bogus indices in the data file, so we can hereafter
- safely use type_idxs[T] as indices into `types' and never crash. */
- for (i = 0; i < num_transitions; ++i)
- if (type_idxs[i] >= num_types)
- goto lose;
-
- if ((BYTE_ORDER != BIG_ENDIAN && (sizeof(time_t) == 4 || trans_width == 4)) ||
- (BYTE_ORDER == BIG_ENDIAN && sizeof(time_t) == 8 && trans_width == 4)) {
- /* Decode the transition times, stored as 4-byte integers in
- network (big-endian) byte order. We work from the end of
- the array so as not to clobber the next element to be
- processed when sizeof (time_t) > 4. */
- i = num_transitions;
- while (i-- > 0)
- transitions[i] = decode((char *)transitions + i * 4);
- } else if (BYTE_ORDER != BIG_ENDIAN && sizeof(time_t) == 8) {
- /* Decode the transition times, stored as 8-byte integers in
- network (big-endian) byte order. */
- for (i = 0; i < num_transitions; ++i)
- transitions[i] = decode64((char *)transitions + i * 8);
- }
-
- for (i = 0; i < num_types; ++i) {
- unsigned char x[4];
- int c;
-
- if (fread(x, 1, sizeof(x), f) != sizeof(x))
- goto lose;
- c = getc(f);
- if ((unsigned int)c > 1u)
- goto lose;
- types[i].isdst = c;
- c = getc(f);
- if ((size_t) c > chars)
- /* Bogus index in data file. */
- goto lose;
- types[i].idx = c;
- types[i].offset = (long int)decode(x);
- }
-
- if (fread(zone_names, 1, chars, f) != chars)
- goto lose;
-
- for (i = 0; i < num_isstd; ++i) {
- int c = getc(f);
- if (c == EOF)
- goto lose;
- types[i].isstd = c != 0;
- }
-
- while (i < num_types)
- types[i++].isstd = 0;
-
- for (i = 0; i < num_isgmt; ++i) {
- int c = getc(f);
- if (c == EOF)
- goto lose;
- types[i].isgmt = c != 0;
- }
-
- while (i < num_types)
- types[i++].isgmt = 0;
-
- if (num_transitions == 0)
- goto lose;
-
- if (date < transitions[0] || date >= transitions[num_transitions - 1])
- goto lose;
-
- /* Find the first transition after TIMER, and
- then pick the type of the transition before it. */
- lo = 0;
- hi = num_transitions - 1;
-
- /* Assume that DST is changing twice a year and guess initial
- search spot from it.
- Half of a gregorian year has on average 365.2425 * 86400 / 2
- = 15778476 seconds. */
- i = (transitions[num_transitions - 1] - date) / 15778476;
- if (i < num_transitions) {
- i = num_transitions - 1 - i;
- if (date < transitions[i]) {
- if (i < 10 || date >= transitions[i - 10]) {
- /* Linear search. */
- while (date < transitions[i - 1])
- i--;
- goto found;
- }
- hi = i - 10;
- } else {
- if (i + 10 >= num_transitions || date < transitions[i + 10]) {
- /* Linear search. */
- while (date >= transitions[i])
- i++;
- goto found;
- }
- lo = i + 10;
- }
- }
-
- /* Binary search. */
- while (lo + 1 < hi) {
- i = (lo + hi) / 2;
- if (date < transitions[i])
- hi = i;
- else
- lo = i;
- }
- i = hi;
-
-found:
- if (switch_cur)
- *switch_cur = transitions[i-1];
- if (zone_cur)
- *zone_cur = strdup(&zone_names[types[type_idxs[i - 1]].idx]);
- if (dst_cur)
- *dst_cur = types[type_idxs[i-1]].isdst;
-
- if (switch_next)
- *switch_next = transitions[i];
- if (delta_next)
- *delta_next = (types[type_idxs[i]].offset - types[type_idxs[i-1]].offset) / 60;
- if (zone_next)
- *zone_next = strdup(&zone_names[types[type_idxs[i]].idx]);
- if (dst_next)
- *dst_next = types[type_idxs[i]].isdst;
-
- free(transitions);
- fclose(f);
- return 0;
-lose:
- free(transitions);
- fclose(f);
- return err;
-}
diff --git a/src/shared/time-dst.h b/src/shared/time-dst.h
deleted file mode 100644
index 536b6bbdfb..0000000000
--- a/src/shared/time-dst.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Kay Sievers
-
- 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 time_get_dst(time_t date, const char *tzfile,
- time_t *switch_cur, char **zone_cur, bool *dst_cur,
- time_t *switch_next, int *delta_next, char **zone_next, bool *dst_next);
diff --git a/src/shared/unit-name.c b/src/shared/unit-name.c
deleted file mode 100644
index 50031e608e..0000000000
--- a/src/shared/unit-name.c
+++ /dev/null
@@ -1,519 +0,0 @@
-/*-*- 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 <errno.h>
-#include <string.h>
-#include <assert.h>
-
-#include "path-util.h"
-#include "util.h"
-#include "unit-name.h"
-
-#define VALID_CHARS \
- "0123456789" \
- "abcdefghijklmnopqrstuvwxyz" \
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
- ":-_.\\"
-
-static const char* const unit_type_table[_UNIT_TYPE_MAX] = {
- [UNIT_SERVICE] = "service",
- [UNIT_SOCKET] = "socket",
- [UNIT_TARGET] = "target",
- [UNIT_DEVICE] = "device",
- [UNIT_MOUNT] = "mount",
- [UNIT_AUTOMOUNT] = "automount",
- [UNIT_SNAPSHOT] = "snapshot",
- [UNIT_TIMER] = "timer",
- [UNIT_SWAP] = "swap",
- [UNIT_PATH] = "path",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(unit_type, UnitType);
-
-static const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = {
- [UNIT_STUB] = "stub",
- [UNIT_LOADED] = "loaded",
- [UNIT_ERROR] = "error",
- [UNIT_MERGED] = "merged",
- [UNIT_MASKED] = "masked"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState);
-
-bool unit_name_is_valid(const char *n, bool template_ok) {
- const char *e, *i, *at;
-
- /* Valid formats:
- *
- * string@instance.suffix
- * string.suffix
- */
-
- assert(n);
-
- if (strlen(n) >= UNIT_NAME_MAX)
- return false;
-
- e = strrchr(n, '.');
- if (!e || e == n)
- return false;
-
- if (unit_type_from_string(e + 1) < 0)
- return false;
-
- for (i = n, at = NULL; i < e; i++) {
-
- if (*i == '@' && !at)
- at = i;
-
- if (!strchr("@" VALID_CHARS, *i))
- return false;
- }
-
- if (at) {
- if (at == n)
- return false;
-
- if (!template_ok && at+1 == e)
- return false;
- }
-
- return true;
-}
-
-bool unit_instance_is_valid(const char *i) {
- assert(i);
-
- /* The max length depends on the length of the string, so we
- * don't really check this here. */
-
- if (i[0] == 0)
- return false;
-
- /* We allow additional @ in the instance string, we do not
- * allow them in the prefix! */
-
- for (; *i; i++)
- if (!strchr("@" VALID_CHARS, *i))
- return false;
-
- return true;
-}
-
-bool unit_prefix_is_valid(const char *p) {
-
- /* We don't allow additional @ in the instance string */
-
- if (p[0] == 0)
- return false;
-
- for (; *p; p++)
- if (!strchr(VALID_CHARS, *p))
- return false;
-
- return true;
-}
-
-int unit_name_to_instance(const char *n, char **instance) {
- const char *p, *d;
- char *i;
-
- assert(n);
- assert(instance);
-
- /* Everything past the first @ and before the last . is the instance */
- p = strchr(n, '@');
- if (!p) {
- *instance = NULL;
- return 0;
- }
-
- assert_se(d = strrchr(n, '.'));
- assert(p < d);
-
- i = strndup(p+1, d-p-1);
- if (!i)
- return -ENOMEM;
-
- *instance = i;
- return 0;
-}
-
-char *unit_name_to_prefix_and_instance(const char *n) {
- const char *d;
-
- assert(n);
-
- assert_se(d = strrchr(n, '.'));
-
- return strndup(n, d - n);
-}
-
-char *unit_name_to_prefix(const char *n) {
- const char *p;
-
- p = strchr(n, '@');
- if (p)
- return strndup(n, p - n);
-
- return unit_name_to_prefix_and_instance(n);
-}
-
-char *unit_name_change_suffix(const char *n, const char *suffix) {
- char *e, *r;
- size_t a, b;
-
- assert(n);
- assert(unit_name_is_valid(n, true));
- assert(suffix);
-
- assert_se(e = strrchr(n, '.'));
- a = e - n;
- b = strlen(suffix);
-
- r = new(char, a + b + 1);
- if (!r)
- return NULL;
-
- memcpy(r, n, a);
- memcpy(r+a, suffix, b+1);
-
- return r;
-}
-
-char *unit_name_build(const char *prefix, const char *instance, const char *suffix) {
- assert(prefix);
- assert(unit_prefix_is_valid(prefix));
- assert(!instance || unit_instance_is_valid(instance));
- assert(suffix);
-
- if (!instance)
- return strappend(prefix, suffix);
-
- return strjoin(prefix, "@", instance, suffix, NULL);
-}
-
-static char *do_escape_char(char c, char *t) {
- *(t++) = '\\';
- *(t++) = 'x';
- *(t++) = hexchar(c >> 4);
- *(t++) = hexchar(c);
- return t;
-}
-
-static char *do_escape(const char *f, char *t) {
- assert(f);
- assert(t);
-
- /* do not create units with a leading '.', like for "/.dotdir" mount points */
- if (*f == '.') {
- t = do_escape_char(*f, t);
- f++;
- }
-
- for (; *f; f++) {
- if (*f == '/')
- *(t++) = '-';
- else if (*f == '-' || *f == '\\' || !strchr(VALID_CHARS, *f))
- t = do_escape_char(*f, t);
- else
- *(t++) = *f;
- }
-
- return t;
-}
-
-char *unit_name_escape(const char *f) {
- char *r, *t;
-
- r = new(char, strlen(f)*4+1);
- if (!r)
- return NULL;
-
- t = do_escape(f, r);
- *t = 0;
-
- return r;
-}
-
-char *unit_name_unescape(const char *f) {
- char *r, *t;
-
- assert(f);
-
- r = strdup(f);
- if (!r)
- return NULL;
-
- for (t = r; *f; f++) {
- if (*f == '-')
- *(t++) = '/';
- else if (*f == '\\') {
- int a, b;
-
- if (f[1] != 'x' ||
- (a = unhexchar(f[2])) < 0 ||
- (b = unhexchar(f[3])) < 0) {
- /* Invalid escape code, let's take it literal then */
- *(t++) = '\\';
- } else {
- *(t++) = (char) ((a << 4) | b);
- f += 3;
- }
- } else
- *(t++) = *f;
- }
-
- *t = 0;
-
- return r;
-}
-
-char *unit_name_path_escape(const char *f) {
- char *p, *e;
-
- assert(f);
-
- p = strdup(f);
- if (!p)
- return NULL;
-
- path_kill_slashes(p);
-
- if (streq(p, "/")) {
- free(p);
- return strdup("-");
- }
-
- e = unit_name_escape(p[0] == '/' ? p + 1 : p);
- free(p);
-
- return e;
-}
-
-char *unit_name_path_unescape(const char *f) {
- char *e;
-
- assert(f);
-
- e = unit_name_unescape(f);
- if (!e)
- return NULL;
-
- if (e[0] != '/') {
- char *w;
-
- w = strappend("/", e);
- free(e);
-
- return w;
- }
-
- return e;
-}
-
-bool unit_name_is_template(const char *n) {
- const char *p;
-
- assert(n);
-
- p = strchr(n, '@');
- if (!p)
- return false;
-
- return p[1] == '.';
-}
-
-bool unit_name_is_instance(const char *n) {
- const char *p;
-
- assert(n);
-
- p = strchr(n, '@');
- if (!p)
- return false;
-
- return p[1] != '.';
-}
-
-char *unit_name_replace_instance(const char *f, const char *i) {
- const char *p, *e;
- char *r, *k;
- size_t a, b;
-
- assert(f);
-
- p = strchr(f, '@');
- if (!p)
- return strdup(f);
-
- e = strrchr(f, '.');
- if (!e)
- assert_se(e = strchr(f, 0));
-
- a = p - f;
- b = strlen(i);
-
- r = new(char, a + 1 + b + strlen(e) + 1);
- if (!r)
- return NULL;
-
- k = mempcpy(r, f, a + 1);
- k = mempcpy(k, i, b);
- strcpy(k, e);
-
- return r;
-}
-
-char *unit_name_template(const char *f) {
- const char *p, *e;
- char *r;
- size_t a;
-
- p = strchr(f, '@');
- if (!p)
- return strdup(f);
-
- assert_se(e = strrchr(f, '.'));
- a = p - f + 1;
-
- r = new(char, a + strlen(e) + 1);
- if (!r)
- return NULL;
-
- strcpy(mempcpy(r, f, a), e);
- return r;
-
-}
-
-char *unit_name_from_path(const char *path, const char *suffix) {
- char *p, *r;
-
- assert(path);
- assert(suffix);
-
- p = unit_name_path_escape(path);
- if (!p)
- return NULL;
-
- r = strappend(p, suffix);
- free(p);
-
- return r;
-}
-
-char *unit_name_from_path_instance(const char *prefix, const char *path, const char *suffix) {
- char *p, *r;
-
- assert(prefix);
- assert(path);
- assert(suffix);
-
- p = unit_name_path_escape(path);
- if (!p)
- return NULL;
-
- r = strjoin(prefix, "@", p, suffix, NULL);
- free(p);
-
- return r;
-}
-
-char *unit_name_to_path(const char *name) {
- char *w, *e;
-
- assert(name);
-
- w = unit_name_to_prefix(name);
- if (!w)
- return NULL;
-
- e = unit_name_path_unescape(w);
- free(w);
-
- return e;
-}
-
-char *unit_dbus_path_from_name(const char *name) {
- char *e, *p;
-
- assert(name);
-
- e = bus_path_escape(name);
- if (!e)
- return NULL;
-
- p = strappend("/org/freedesktop/systemd1/unit/", e);
- free(e);
-
- return p;
-}
-
-char *unit_name_mangle(const char *name) {
- char *r, *t;
- const char *f;
-
- assert(name);
-
- /* Try to turn a string that might not be a unit name into a
- * sensible unit name. */
-
- if (is_device_path(name))
- return unit_name_from_path(name, ".device");
-
- if (path_is_absolute(name))
- return unit_name_from_path(name, ".mount");
-
- /* We'll only escape the obvious characters here, to play
- * safe. */
-
- r = new(char, strlen(name) * 4 + 1 + sizeof(".service")-1);
- if (!r)
- return NULL;
-
- for (f = name, t = r; *f; f++) {
- if (*f == '/')
- *(t++) = '-';
- else if (!strchr("@" VALID_CHARS, *f))
- t = do_escape_char(*f, t);
- else
- *(t++) = *f;
- }
-
- if (unit_name_to_type(name) < 0)
- strcpy(t, ".service");
- else
- *t = 0;
-
- return r;
-}
-
-UnitType unit_name_to_type(const char *n) {
- const char *e;
-
- assert(n);
-
- e = strrchr(n, '.');
- if (!e)
- return _UNIT_TYPE_INVALID;
-
- return unit_type_from_string(e + 1);
-}
diff --git a/src/shared/unit-name.h b/src/shared/unit-name.h
deleted file mode 100644
index 7be346590e..0000000000
--- a/src/shared/unit-name.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*-*- 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>
-
-#define UNIT_NAME_MAX 256
-
-typedef enum UnitType UnitType;
-typedef enum UnitLoadState UnitLoadState;
-
-enum UnitType {
- UNIT_SERVICE = 0,
- UNIT_SOCKET,
- UNIT_TARGET,
- UNIT_DEVICE,
- UNIT_MOUNT,
- UNIT_AUTOMOUNT,
- UNIT_SNAPSHOT,
- UNIT_TIMER,
- UNIT_SWAP,
- UNIT_PATH,
- _UNIT_TYPE_MAX,
- _UNIT_TYPE_INVALID = -1
-};
-
-enum UnitLoadState {
- UNIT_STUB,
- UNIT_LOADED,
- UNIT_ERROR,
- UNIT_MERGED,
- UNIT_MASKED,
- _UNIT_LOAD_STATE_MAX,
- _UNIT_LOAD_STATE_INVALID = -1
-};
-
-const char *unit_type_to_string(UnitType i);
-UnitType unit_type_from_string(const char *s);
-
-const char *unit_load_state_to_string(UnitLoadState i);
-UnitLoadState unit_load_state_from_string(const char *s);
-
-int unit_name_to_instance(const char *n, char **instance);
-char* unit_name_to_prefix(const char *n);
-char* unit_name_to_prefix_and_instance(const char *n);
-
-bool unit_name_is_valid(const char *n, bool template_ok);
-bool unit_prefix_is_valid(const char *p);
-bool unit_instance_is_valid(const char *i);
-
-UnitType unit_name_to_type(const char *n);
-
-char *unit_name_change_suffix(const char *n, const char *suffix);
-
-char *unit_name_build(const char *prefix, const char *instance, const char *suffix);
-
-char *unit_name_escape(const char *f);
-char *unit_name_unescape(const char *f);
-char *unit_name_path_escape(const char *f);
-char *unit_name_path_unescape(const char *f);
-
-bool unit_name_is_template(const char *n);
-bool unit_name_is_instance(const char *n);
-
-char *unit_name_replace_instance(const char *f, const char *i);
-
-char *unit_name_template(const char *f);
-
-char *unit_name_from_path(const char *path, const char *suffix);
-char *unit_name_from_path_instance(const char *prefix, const char *path, const char *suffix);
-char *unit_name_to_path(const char *name);
-
-char *unit_dbus_path_from_name(const char *name);
-
-char *unit_name_mangle(const char *name);
diff --git a/src/shared/utf8.c b/src/shared/utf8.c
deleted file mode 100644
index 5f9f3c60c5..0000000000
--- a/src/shared/utf8.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-/* This file is based on the GLIB utf8 validation functions. The
- * original license text follows. */
-
-/* gutf8.c - Operations on UTF-8 strings.
- *
- * Copyright (C) 1999 Tom Tromey
- * Copyright (C) 2000 Red Hat, Inc.
- *
- * This library 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 of the License, or (at your option) any later version.
- *
- * This library 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 this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include <errno.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <string.h>
-#include <stdbool.h>
-
-#include "utf8.h"
-
-#define FILTER_CHAR '_'
-
-static inline bool is_unicode_valid(uint32_t ch) {
-
- if (ch >= 0x110000) /* End of unicode space */
- return false;
- if ((ch & 0xFFFFF800) == 0xD800) /* Reserved area for UTF-16 */
- return false;
- if ((ch >= 0xFDD0) && (ch <= 0xFDEF)) /* Reserved */
- return false;
- if ((ch & 0xFFFE) == 0xFFFE) /* BOM (Byte Order Mark) */
- return false;
-
- return true;
-}
-
-static inline bool is_continuation_char(uint8_t ch) {
- if ((ch & 0xc0) != 0x80) /* 10xxxxxx */
- return false;
- return true;
-}
-
-static inline void merge_continuation_char(uint32_t *u_ch, uint8_t ch) {
- *u_ch <<= 6;
- *u_ch |= ch & 0x3f;
-}
-
-static bool is_unicode_control(uint32_t ch) {
-
- /*
- 0 to ' '-1 is the C0 range.
- DEL=0x7F, and DEL+1 to 0x9F is C1 range.
- '\t' is in C0 range, but more or less harmless and commonly used.
- */
-
- return (ch < ' ' && ch != '\t') ||
- (0x7F <= ch && ch <= 0x9F);
-}
-
-char* utf8_is_printable_n(const char* str, size_t length) {
- uint32_t val = 0;
- uint32_t min = 0;
- const uint8_t *p;
-
- assert(str);
-
- for (p = (const uint8_t*) str; length; p++, length--) {
- if (*p < 128) {
- val = *p;
- } else {
- if ((*p & 0xe0) == 0xc0) { /* 110xxxxx two-char seq. */
- min = 128;
- val = (uint32_t) (*p & 0x1e);
- goto ONE_REMAINING;
- } else if ((*p & 0xf0) == 0xe0) { /* 1110xxxx three-char seq.*/
- min = (1 << 11);
- val = (uint32_t) (*p & 0x0f);
- goto TWO_REMAINING;
- } else if ((*p & 0xf8) == 0xf0) { /* 11110xxx four-char seq */
- min = (1 << 16);
- val = (uint32_t) (*p & 0x07);
- } else
- goto error;
-
- p++;
- length--;
- if (!length || !is_continuation_char(*p))
- goto error;
- merge_continuation_char(&val, *p);
-
- TWO_REMAINING:
- p++;
- length--;
- if (!is_continuation_char(*p))
- goto error;
- merge_continuation_char(&val, *p);
-
- ONE_REMAINING:
- p++;
- length--;
- if (!is_continuation_char(*p))
- goto error;
- merge_continuation_char(&val, *p);
-
- if (val < min)
- goto error;
- }
-
- if (is_unicode_control(val))
- goto error;
- }
-
- return (char*) str;
-
-error:
- return NULL;
-}
-
-static char* utf8_validate(const char *str, char *output) {
- uint32_t val = 0;
- uint32_t min = 0;
- const uint8_t *p, *last;
- int size;
- uint8_t *o;
-
- assert(str);
-
- o = (uint8_t*) output;
- for (p = (const uint8_t*) str; *p; p++) {
- if (*p < 128) {
- if (o)
- *o = *p;
- } else {
- last = p;
-
- if ((*p & 0xe0) == 0xc0) { /* 110xxxxx two-char seq. */
- size = 2;
- min = 128;
- val = (uint32_t) (*p & 0x1e);
- goto ONE_REMAINING;
- } else if ((*p & 0xf0) == 0xe0) { /* 1110xxxx three-char seq.*/
- size = 3;
- min = (1 << 11);
- val = (uint32_t) (*p & 0x0f);
- goto TWO_REMAINING;
- } else if ((*p & 0xf8) == 0xf0) { /* 11110xxx four-char seq */
- size = 4;
- min = (1 << 16);
- val = (uint32_t) (*p & 0x07);
- } else
- goto error;
-
- p++;
- if (!is_continuation_char(*p))
- goto error;
- merge_continuation_char(&val, *p);
-
- TWO_REMAINING:
- p++;
- if (!is_continuation_char(*p))
- goto error;
- merge_continuation_char(&val, *p);
-
- ONE_REMAINING:
- p++;
- if (!is_continuation_char(*p))
- goto error;
- merge_continuation_char(&val, *p);
-
- if (val < min)
- goto error;
-
- if (!is_unicode_valid(val))
- goto error;
-
- if (o) {
- memcpy(o, last, (size_t) size);
- o += size;
- }
-
- continue;
-
- error:
- if (o) {
- *o = FILTER_CHAR;
- p = last; /* We retry at the next character */
- } else
- goto failure;
- }
-
- if (o)
- o++;
- }
-
- if (o) {
- *o = '\0';
- return output;
- }
-
- return (char*) str;
-
-failure:
- return NULL;
-}
-
-char* utf8_is_valid (const char *str) {
- return utf8_validate(str, NULL);
-}
-
-char* utf8_filter (const char *str) {
- char *new_str;
-
- assert(str);
-
- new_str = malloc(strlen(str) + 1);
- if (!new_str)
- return NULL;
-
- return utf8_validate(str, new_str);
-}
-
-char *ascii_is_valid(const char *str) {
- const char *p;
-
- assert(str);
-
- for (p = str; *p; p++)
- if ((unsigned char) *p >= 128)
- return NULL;
-
- return (char*) str;
-}
-
-char *ascii_filter(const char *str) {
- const char *s;
- char *r, *d;
- size_t l;
-
- assert(str);
-
- l = strlen(str);
- r = malloc(l + 1);
- if (!r)
- return NULL;
-
- for (s = str, d = r; *s; s++)
- if ((unsigned char) *s < 128)
- *(d++) = *s;
-
- *d = 0;
-
- return r;
-}
diff --git a/src/shared/utf8.h b/src/shared/utf8.h
deleted file mode 100644
index 13d2f6a980..0000000000
--- a/src/shared/utf8.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "macro.h"
-
-char *utf8_is_valid(const char *s) _pure_;
-char *ascii_is_valid(const char *s) _pure_;
-
-char *utf8_is_printable_n(const char* str, size_t length) _pure_;
-
-char *utf8_filter(const char *s);
-char *ascii_filter(const char *s);
diff --git a/src/shared/util.c b/src/shared/util.c
deleted file mode 100644
index 6d826b6f5e..0000000000
--- a/src/shared/util.c
+++ /dev/null
@@ -1,6215 +0,0 @@
-/*-*- 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 <assert.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <stdio.h>
-#include <syslog.h>
-#include <sched.h>
-#include <sys/resource.h>
-#include <linux/sched.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <sys/ioctl.h>
-#include <linux/vt.h>
-#include <linux/tiocl.h>
-#include <termios.h>
-#include <stdarg.h>
-#include <sys/inotify.h>
-#include <sys/poll.h>
-#include <libgen.h>
-#include <ctype.h>
-#include <sys/prctl.h>
-#include <sys/utsname.h>
-#include <pwd.h>
-#include <netinet/ip.h>
-#include <linux/kd.h>
-#include <dlfcn.h>
-#include <sys/wait.h>
-#include <sys/time.h>
-#include <glob.h>
-#include <grp.h>
-#include <sys/mman.h>
-#include <sys/vfs.h>
-#include <linux/magic.h>
-#include <limits.h>
-#include <langinfo.h>
-#include <locale.h>
-
-#include "macro.h"
-#include "util.h"
-#include "ioprio.h"
-#include "missing.h"
-#include "log.h"
-#include "strv.h"
-#include "label.h"
-#include "path-util.h"
-#include "exit-status.h"
-#include "hashmap.h"
-
-int saved_argc = 0;
-char **saved_argv = NULL;
-
-static volatile unsigned cached_columns = 0;
-static volatile unsigned cached_lines = 0;
-
-bool is_efiboot(void) {
- return access("/sys/firmware/efi", F_OK) >= 0;
-}
-
-size_t page_size(void) {
- static __thread size_t pgsz = 0;
- long r;
-
- if (_likely_(pgsz > 0))
- return pgsz;
-
- r = sysconf(_SC_PAGESIZE);
- assert(r > 0);
-
- pgsz = (size_t) r;
- return pgsz;
-}
-
-bool streq_ptr(const char *a, const char *b) {
-
- /* Like streq(), but tries to make sense of NULL pointers */
-
- if (a && b)
- return streq(a, b);
-
- if (!a && !b)
- return true;
-
- return false;
-}
-
-usec_t now(clockid_t clock_id) {
- struct timespec ts;
-
- assert_se(clock_gettime(clock_id, &ts) == 0);
-
- return timespec_load(&ts);
-}
-
-dual_timestamp* dual_timestamp_get(dual_timestamp *ts) {
- assert(ts);
-
- ts->realtime = now(CLOCK_REALTIME);
- ts->monotonic = now(CLOCK_MONOTONIC);
-
- return ts;
-}
-
-dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) {
- int64_t delta;
- assert(ts);
-
- ts->realtime = u;
-
- if (u == 0)
- ts->monotonic = 0;
- else {
- delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u;
-
- ts->monotonic = now(CLOCK_MONOTONIC);
-
- if ((int64_t) ts->monotonic > delta)
- ts->monotonic -= delta;
- else
- ts->monotonic = 0;
- }
-
- return ts;
-}
-
-usec_t timespec_load(const struct timespec *ts) {
- assert(ts);
-
- if (ts->tv_sec == (time_t) -1 &&
- ts->tv_nsec == (long) -1)
- return (usec_t) -1;
-
- if ((usec_t) ts->tv_sec > (UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / USEC_PER_SEC)
- return (usec_t) -1;
-
- return
- (usec_t) ts->tv_sec * USEC_PER_SEC +
- (usec_t) ts->tv_nsec / NSEC_PER_USEC;
-}
-
-struct timespec *timespec_store(struct timespec *ts, usec_t u) {
- assert(ts);
-
- if (u == (usec_t) -1) {
- ts->tv_sec = (time_t) -1;
- ts->tv_nsec = (long) -1;
- return ts;
- }
-
- ts->tv_sec = (time_t) (u / USEC_PER_SEC);
- ts->tv_nsec = (long int) ((u % USEC_PER_SEC) * NSEC_PER_USEC);
-
- return ts;
-}
-
-usec_t timeval_load(const struct timeval *tv) {
- assert(tv);
-
- if (tv->tv_sec == (time_t) -1 &&
- tv->tv_usec == (suseconds_t) -1)
- return (usec_t) -1;
-
- if ((usec_t) tv->tv_sec > (UINT64_MAX - tv->tv_usec) / USEC_PER_SEC)
- return (usec_t) -1;
-
- return
- (usec_t) tv->tv_sec * USEC_PER_SEC +
- (usec_t) tv->tv_usec;
-}
-
-struct timeval *timeval_store(struct timeval *tv, usec_t u) {
- assert(tv);
-
- if (u == (usec_t) -1) {
- tv->tv_sec = (time_t) -1;
- tv->tv_usec = (suseconds_t) -1;
- return tv;
- }
-
- tv->tv_sec = (time_t) (u / USEC_PER_SEC);
- tv->tv_usec = (suseconds_t) (u % USEC_PER_SEC);
-
- return tv;
-}
-
-char* endswith(const char *s, const char *postfix) {
- size_t sl, pl;
-
- assert(s);
- assert(postfix);
-
- sl = strlen(s);
- pl = strlen(postfix);
-
- if (pl == 0)
- return (char*) s + sl;
-
- if (sl < pl)
- return NULL;
-
- if (memcmp(s + sl - pl, postfix, pl) != 0)
- return NULL;
-
- return (char*) s + sl - pl;
-}
-
-char* startswith(const char *s, const char *prefix) {
- const char *a, *b;
-
- assert(s);
- assert(prefix);
-
- a = s, b = prefix;
- for (;;) {
- if (*b == 0)
- return (char*) a;
- if (*a != *b)
- return NULL;
-
- a++, b++;
- }
-}
-
-char* startswith_no_case(const char *s, const char *prefix) {
- const char *a, *b;
-
- assert(s);
- assert(prefix);
-
- a = s, b = prefix;
- for (;;) {
- if (*b == 0)
- return (char*) a;
- if (tolower(*a) != tolower(*b))
- return NULL;
-
- a++, b++;
- }
-}
-
-bool first_word(const char *s, const char *word) {
- size_t sl, wl;
-
- assert(s);
- assert(word);
-
- sl = strlen(s);
- wl = strlen(word);
-
- if (sl < wl)
- return false;
-
- if (wl == 0)
- return true;
-
- if (memcmp(s, word, wl) != 0)
- return false;
-
- return s[wl] == 0 ||
- strchr(WHITESPACE, s[wl]);
-}
-
-int close_nointr(int fd) {
- assert(fd >= 0);
-
- for (;;) {
- int r;
-
- r = close(fd);
- if (r >= 0)
- return r;
-
- if (errno != EINTR)
- return -errno;
- }
-}
-
-void close_nointr_nofail(int fd) {
- int saved_errno = errno;
-
- /* like close_nointr() but cannot fail, and guarantees errno
- * is unchanged */
-
- assert_se(close_nointr(fd) == 0);
-
- errno = saved_errno;
-}
-
-void close_many(const int fds[], unsigned n_fd) {
- unsigned i;
-
- for (i = 0; i < n_fd; i++)
- close_nointr_nofail(fds[i]);
-}
-
-int parse_boolean(const char *v) {
- assert(v);
-
- if (streq(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
- return 1;
- else if (streq(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(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_uid(const char *s, uid_t* ret_uid) {
- unsigned long ul = 0;
- uid_t uid;
- int r;
-
- assert(s);
- assert(ret_uid);
-
- r = safe_atolu(s, &ul);
- if (r < 0)
- return r;
-
- uid = (uid_t) ul;
-
- if ((unsigned long) uid != ul)
- return -ERANGE;
-
- *ret_uid = uid;
- 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 ? -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 ? -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;
-}
-
-/* Split a string into words. */
-char *split(const char *c, size_t *l, const char *separator, char **state) {
- char *current;
-
- current = *state ? *state : (char*) c;
-
- if (!*current || *c == 0)
- return NULL;
-
- current += strspn(current, separator);
- *l = strcspn(current, separator);
- *state = current+*l;
-
- return (char*) current;
-}
-
-/* Split a string into words, but consider strings enclosed in '' and
- * "" as words even if they include spaces. */
-char *split_quoted(const char *c, size_t *l, char **state) {
- char *current, *e;
- bool escaped = false;
-
- current = *state ? *state : (char*) c;
-
- if (!*current || *c == 0)
- return NULL;
-
- current += strspn(current, WHITESPACE);
-
- if (*current == '\'') {
- current ++;
-
- for (e = current; *e; e++) {
- if (escaped)
- escaped = false;
- else if (*e == '\\')
- escaped = true;
- else if (*e == '\'')
- break;
- }
-
- *l = e-current;
- *state = *e == 0 ? e : e+1;
- } else if (*current == '\"') {
- current ++;
-
- for (e = current; *e; e++) {
- if (escaped)
- escaped = false;
- else if (*e == '\\')
- escaped = true;
- else if (*e == '\"')
- break;
- }
-
- *l = e-current;
- *state = *e == 0 ? e : e+1;
- } else {
- for (e = current; *e; e++) {
- if (escaped)
- escaped = false;
- else if (*e == '\\')
- escaped = true;
- else if (strchr(WHITESPACE, *e))
- break;
- }
- *l = e-current;
- *state = e;
- }
-
- return (char*) current;
-}
-
-int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
- int r;
- _cleanup_fclose_ FILE *f = NULL;
- char fn[PATH_MAX], line[LINE_MAX], *p;
- long unsigned ppid;
-
- assert(pid > 0);
- assert(_ppid);
-
- assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1));
- char_array_0(fn);
-
- f = fopen(fn, "re");
- if (!f)
- return -errno;
-
- if (!fgets(line, sizeof(line), f)) {
- r = feof(f) ? -EIO : -errno;
- fclose(f);
- return r;
- }
-
- /* Let's skip the pid and comm fields. The latter is enclosed
- * in () but does not escape any () in its value, so let's
- * skip over it manually */
-
- p = strrchr(line, ')');
- if (!p)
- return -EIO;
-
- p++;
-
- if (sscanf(p, " "
- "%*c " /* state */
- "%lu ", /* ppid */
- &ppid) != 1)
- return -EIO;
-
- if ((long unsigned) (pid_t) ppid != ppid)
- return -ERANGE;
-
- *_ppid = (pid_t) ppid;
-
- return 0;
-}
-
-int get_starttime_of_pid(pid_t pid, unsigned long long *st) {
- _cleanup_fclose_ FILE *f = NULL;
- char fn[PATH_MAX], line[LINE_MAX], *p;
-
- assert(pid > 0);
- assert(st);
-
- assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1));
- char_array_0(fn);
-
- f = fopen(fn, "re");
- if (!f)
- return -errno;
-
- if (!fgets(line, sizeof(line), f)) {
- if (ferror(f))
- return -errno;
-
- return -EIO;
- }
-
- /* Let's skip the pid and comm fields. The latter is enclosed
- * in () but does not escape any () in its value, so let's
- * skip over it manually */
-
- p = strrchr(line, ')');
- if (!p)
- return -EIO;
-
- p++;
-
- if (sscanf(p, " "
- "%*c " /* state */
- "%*d " /* ppid */
- "%*d " /* pgrp */
- "%*d " /* session */
- "%*d " /* tty_nr */
- "%*d " /* tpgid */
- "%*u " /* flags */
- "%*u " /* minflt */
- "%*u " /* cminflt */
- "%*u " /* majflt */
- "%*u " /* cmajflt */
- "%*u " /* utime */
- "%*u " /* stime */
- "%*d " /* cutime */
- "%*d " /* cstime */
- "%*d " /* priority */
- "%*d " /* nice */
- "%*d " /* num_threads */
- "%*d " /* itrealvalue */
- "%llu " /* starttime */,
- st) != 1)
- return -EIO;
-
- return 0;
-}
-
-int write_one_line_file(const char *fn, const char *line) {
- _cleanup_fclose_ FILE *f = NULL;
-
- assert(fn);
- assert(line);
-
- f = fopen(fn, "we");
- if (!f)
- return -errno;
-
- errno = 0;
- if (fputs(line, f) < 0)
- return errno ? -errno : -EIO;
-
- if (!endswith(line, "\n"))
- fputc('\n', f);
-
- fflush(f);
-
- if (ferror(f))
- return errno ? -errno : -EIO;
-
- 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 write_one_line_file_atomic(const char *fn, const char *line) {
- FILE *f;
- int r;
- char *p;
-
- assert(fn);
- assert(line);
-
- r = fopen_temporary(fn, &f, &p);
- if (r < 0)
- return r;
-
- fchmod_umask(fileno(f), 0644);
-
- errno = 0;
- if (fputs(line, f) < 0) {
- r = -errno;
- goto finish;
- }
-
- if (!endswith(line, "\n"))
- fputc('\n', f);
-
- fflush(f);
-
- if (ferror(f)) {
- if (errno != 0)
- r = -errno;
- else
- r = -EIO;
- } else {
- if (rename(p, fn) < 0)
- r = -errno;
- else
- r = 0;
- }
-
-finish:
- if (r < 0)
- unlink(p);
-
- fclose(f);
- free(p);
-
- return r;
-}
-
-int read_one_line_file(const char *fn, char **line) {
- _cleanup_fclose_ FILE *f = NULL;
- char t[LINE_MAX], *c;
-
- assert(fn);
- assert(line);
-
- f = fopen(fn, "re");
- if (!f)
- return -errno;
-
- if (!fgets(t, sizeof(t), f)) {
-
- if (ferror(f))
- return errno ? -errno : -EIO;
-
- t[0] = 0;
- }
-
- c = strdup(t);
- if (!c)
- return -ENOMEM;
- truncate_nl(c);
-
- *line = c;
- return 0;
-}
-
-int read_full_file(const char *fn, char **contents, size_t *size) {
- _cleanup_fclose_ FILE *f = NULL;
- size_t n, l;
- _cleanup_free_ char *buf = NULL;
- struct stat st;
-
- f = fopen(fn, "re");
- if (!f)
- return -errno;
-
- if (fstat(fileno(f), &st) < 0)
- return -errno;
-
- /* Safety check */
- if (st.st_size > 4*1024*1024)
- return -E2BIG;
-
- n = st.st_size > 0 ? st.st_size : LINE_MAX;
- l = 0;
-
- for (;;) {
- char *t;
- size_t k;
-
- t = realloc(buf, n+1);
- if (!t)
- return -ENOMEM;
-
- buf = t;
- k = fread(buf + l, 1, n - l, f);
-
- if (k <= 0) {
- if (ferror(f))
- return -errno;
-
- break;
- }
-
- l += k;
- n *= 2;
-
- /* Safety check */
- if (n > 4*1024*1024)
- return -E2BIG;
- }
-
- buf[l] = 0;
- *contents = buf;
- buf = NULL;
-
- if (size)
- *size = l;
-
- return 0;
-}
-
-int parse_env_file(
- const char *fname,
- const char *separator, ...) {
-
- int r = 0;
- char *contents = NULL, *p;
-
- assert(fname);
- assert(separator);
-
- if ((r = read_full_file(fname, &contents, NULL)) < 0)
- return r;
-
- p = contents;
- for (;;) {
- const char *key = NULL;
-
- p += strspn(p, separator);
- p += strspn(p, WHITESPACE);
-
- if (!*p)
- break;
-
- if (!strchr(COMMENTS, *p)) {
- va_list ap;
- char **value;
-
- va_start(ap, separator);
- while ((key = va_arg(ap, char *))) {
- size_t n;
- char *v;
-
- value = va_arg(ap, char **);
-
- n = strlen(key);
- if (strncmp(p, key, n) != 0 ||
- p[n] != '=')
- continue;
-
- p += n + 1;
- n = strcspn(p, separator);
-
- if (n >= 2 &&
- strchr(QUOTES, p[0]) &&
- p[n-1] == p[0])
- v = strndup(p+1, n-2);
- else
- v = strndup(p, n);
-
- if (!v) {
- r = -ENOMEM;
- va_end(ap);
- goto fail;
- }
-
- if (v[0] == '\0') {
- /* return empty value strings as NULL */
- free(v);
- v = NULL;
- }
-
- free(*value);
- *value = v;
-
- p += n;
-
- r ++;
- break;
- }
- va_end(ap);
- }
-
- if (!key)
- p += strcspn(p, separator);
- }
-
-fail:
- free(contents);
- return r;
-}
-
-int load_env_file(
- const char *fname,
- char ***rl) {
-
- FILE *f;
- char **m = NULL;
- int r;
-
- assert(fname);
- assert(rl);
-
- if (!(f = fopen(fname, "re")))
- return -errno;
-
- while (!feof(f)) {
- char l[LINE_MAX], *p, *u;
- char **t;
-
- if (!fgets(l, sizeof(l), f)) {
- if (feof(f))
- break;
-
- r = -errno;
- goto finish;
- }
-
- p = strstrip(l);
-
- if (!*p)
- continue;
-
- if (strchr(COMMENTS, *p))
- continue;
-
- if (!(u = normalize_env_assignment(p))) {
- r = log_oom();
- goto finish;
- }
-
- t = strv_append(m, u);
- free(u);
-
- if (!t) {
- r = log_oom();
- goto finish;
- }
-
- strv_free(m);
- m = t;
- }
-
- r = 0;
-
- *rl = m;
- m = NULL;
-
-finish:
- if (f)
- fclose(f);
-
- strv_free(m);
-
- return r;
-}
-
-int write_env_file(const char *fname, char **l) {
- char **i, *p;
- FILE *f;
- int r;
-
- r = fopen_temporary(fname, &f, &p);
- if (r < 0)
- return r;
-
- fchmod_umask(fileno(f), 0644);
-
- errno = 0;
- STRV_FOREACH(i, l) {
- fputs(*i, f);
- fputc('\n', f);
- }
-
- fflush(f);
-
- if (ferror(f)) {
- if (errno != 0)
- r = -errno;
- else
- r = -EIO;
- } else {
- if (rename(p, fname) < 0)
- r = -errno;
- else
- r = 0;
- }
-
- if (r < 0)
- unlink(p);
-
- fclose(f);
- free(p);
-
- return r;
-}
-
-char *truncate_nl(char *s) {
- assert(s);
-
- s[strcspn(s, NEWLINE)] = 0;
- return s;
-}
-
-int get_process_comm(pid_t pid, char **name) {
- int r;
-
- assert(name);
-
- if (pid == 0)
- r = read_one_line_file("/proc/self/comm", name);
- else {
- char *p;
- if (asprintf(&p, "/proc/%lu/comm", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- r = read_one_line_file(p, name);
- free(p);
- }
-
- return r;
-}
-
-int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
- char *r, *k;
- int c;
- bool space = false;
- size_t left;
- FILE *f;
-
- assert(max_length > 0);
- assert(line);
-
- if (pid == 0)
- f = fopen("/proc/self/cmdline", "re");
- else {
- char *p;
- if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- f = fopen(p, "re");
- free(p);
- }
-
- if (!f)
- return -errno;
-
- r = new(char, max_length);
- if (!r) {
- fclose(f);
- return -ENOMEM;
- }
-
- k = r;
- left = max_length;
- while ((c = getc(f)) != EOF) {
-
- if (isprint(c)) {
- if (space) {
- if (left <= 4)
- break;
-
- *(k++) = ' ';
- left--;
- space = false;
- }
-
- if (left <= 4)
- break;
-
- *(k++) = (char) c;
- left--;
- } else
- space = true;
- }
-
- if (left <= 4) {
- size_t n = MIN(left-1, 3U);
- memcpy(k, "...", n);
- k[n] = 0;
- } else
- *k = 0;
-
- fclose(f);
-
- /* Kernel threads have no argv[] */
- if (r[0] == 0) {
- char *t;
- int h;
-
- free(r);
-
- if (!comm_fallback)
- return -ENOENT;
-
- h = get_process_comm(pid, &t);
- if (h < 0)
- return h;
-
- r = strjoin("[", t, "]", NULL);
- free(t);
-
- if (!r)
- return -ENOMEM;
- }
-
- *line = r;
- return 0;
-}
-
-int is_kernel_thread(pid_t pid) {
- char *p;
- size_t count;
- char c;
- bool eof;
- FILE *f;
-
- if (pid == 0)
- return 0;
-
- if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- f = fopen(p, "re");
- free(p);
-
- if (!f)
- return -errno;
-
- count = fread(&c, 1, 1, f);
- eof = feof(f);
- fclose(f);
-
- /* Kernel threads have an empty cmdline */
-
- if (count <= 0)
- return eof ? 1 : -errno;
-
- return 0;
-}
-
-int get_process_exe(pid_t pid, char **name) {
- int r;
-
- assert(name);
-
- if (pid == 0)
- r = readlink_malloc("/proc/self/exe", name);
- else {
- char *p;
- if (asprintf(&p, "/proc/%lu/exe", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- r = readlink_malloc(p, name);
- free(p);
- }
-
- return r;
-}
-
-static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
- char *p;
- FILE *f;
- int r;
-
- assert(uid);
-
- if (pid == 0)
- return getuid();
-
- if (asprintf(&p, "/proc/%lu/status", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- f = fopen(p, "re");
- free(p);
-
- if (!f)
- return -errno;
-
- while (!feof(f)) {
- char line[LINE_MAX], *l;
-
- if (!fgets(line, sizeof(line), f)) {
- if (feof(f))
- break;
-
- r = -errno;
- goto finish;
- }
-
- l = strstrip(line);
-
- if (startswith(l, field)) {
- l += strlen(field);
- l += strspn(l, WHITESPACE);
-
- l[strcspn(l, WHITESPACE)] = 0;
-
- r = parse_uid(l, uid);
- goto finish;
- }
- }
-
- r = -EIO;
-
-finish:
- fclose(f);
-
- return r;
-}
-
-int get_process_uid(pid_t pid, uid_t *uid) {
- return get_process_id(pid, "Uid:", uid);
-}
-
-int get_process_gid(pid_t pid, gid_t *gid) {
- return get_process_id(pid, "Gid:", gid);
-}
-
-char *strnappend(const char *s, const char *suffix, size_t b) {
- size_t a;
- char *r;
-
- if (!s && !suffix)
- return strdup("");
-
- if (!s)
- return strndup(suffix, b);
-
- if (!suffix)
- return strdup(s);
-
- assert(s);
- assert(suffix);
-
- a = strlen(s);
- if (b > ((size_t) -1) - a)
- return NULL;
-
- r = new(char, a+b+1);
- if (!r)
- return NULL;
-
- memcpy(r, s, a);
- memcpy(r+a, suffix, b);
- r[a+b] = 0;
-
- return r;
-}
-
-char *strappend(const char *s, const char *suffix) {
- return strnappend(s, suffix, suffix ? strlen(suffix) : 0);
-}
-
-int readlink_malloc(const char *p, char **r) {
- size_t l = 100;
-
- assert(p);
- assert(r);
-
- for (;;) {
- char *c;
- ssize_t n;
-
- if (!(c = new(char, l)))
- return -ENOMEM;
-
- if ((n = readlink(p, c, l-1)) < 0) {
- int ret = -errno;
- free(c);
- return ret;
- }
-
- if ((size_t) n < l-1) {
- c[n] = 0;
- *r = c;
- return 0;
- }
-
- free(c);
- l *= 2;
- }
-}
-
-int readlink_and_make_absolute(const char *p, char **r) {
- char *target, *k;
- int j;
-
- assert(p);
- assert(r);
-
- if ((j = readlink_malloc(p, &target)) < 0)
- return j;
-
- k = file_in_same_dir(p, target);
- free(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 reset_all_signal_handlers(void) {
- int sig;
-
- for (sig = 1; sig < _NSIG; sig++) {
- struct sigaction sa;
-
- if (sig == SIGKILL || sig == SIGSTOP)
- continue;
-
- zero(sa);
- sa.sa_handler = SIG_DFL;
- sa.sa_flags = SA_RESTART;
-
- /* On Linux the first two RT signals are reserved by
- * glibc, and sigaction() will return EINVAL for them. */
- if ((sigaction(sig, &sa, NULL) < 0))
- if (errno != EINVAL)
- return -errno;
- }
-
- return 0;
-}
-
-char *strstrip(char *s) {
- char *e;
-
- /* Drops trailing whitespace. Modifies the string in
- * place. Returns pointer to first non-space character */
-
- s += strspn(s, WHITESPACE);
-
- for (e = strchr(s, 0); e > s; e --)
- if (!strchr(WHITESPACE, e[-1]))
- break;
-
- *e = 0;
-
- return s;
-}
-
-char *delete_chars(char *s, const char *bad) {
- char *f, *t;
-
- /* Drops all whitespace, regardless where in the string */
-
- for (f = s, t = s; *f; f++) {
- if (strchr(bad, *f))
- continue;
-
- *(t++) = *f;
- }
-
- *t = 0;
-
- return s;
-}
-
-bool in_charset(const char *s, const char* charset) {
- const char *i;
-
- assert(s);
- assert(charset);
-
- for (i = s; *i; i++)
- if (!strchr(charset, *i))
- return false;
-
- return true;
-}
-
-char *file_in_same_dir(const char *path, const char *filename) {
- char *e, *r;
- 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);
-
- if (!(e = strrchr(path, '/')))
- return strdup(filename);
-
- k = strlen(filename);
- if (!(r = new(char, e-path+1+k+1)))
- return NULL;
-
- memcpy(r, path, e-path+1);
- memcpy(r+(e-path)+1, filename, k+1);
-
- return r;
-}
-
-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 -1;
-}
-
-char octchar(int x) {
- return '0' + (x & 7);
-}
-
-int unoctchar(char c) {
-
- if (c >= '0' && c <= '7')
- return c - '0';
-
- return -1;
-}
-
-char decchar(int x) {
- return '0' + (x % 10);
-}
-
-int undecchar(char c) {
-
- if (c >= '0' && c <= '9')
- return c - '0';
-
- return -1;
-}
-
-char *cescape(const char *s) {
- char *r, *t;
- const char *f;
-
- assert(s);
-
- /* Does C style string escaping. */
-
- r = new(char, strlen(s)*4 + 1);
- if (!r)
- return NULL;
-
- for (f = s, t = r; *f; f++)
-
- switch (*f) {
-
- case '\a':
- *(t++) = '\\';
- *(t++) = 'a';
- break;
- case '\b':
- *(t++) = '\\';
- *(t++) = 'b';
- break;
- case '\f':
- *(t++) = '\\';
- *(t++) = 'f';
- break;
- case '\n':
- *(t++) = '\\';
- *(t++) = 'n';
- break;
- case '\r':
- *(t++) = '\\';
- *(t++) = 'r';
- break;
- case '\t':
- *(t++) = '\\';
- *(t++) = 't';
- break;
- case '\v':
- *(t++) = '\\';
- *(t++) = 'v';
- break;
- case '\\':
- *(t++) = '\\';
- *(t++) = '\\';
- break;
- case '"':
- *(t++) = '\\';
- *(t++) = '"';
- break;
- case '\'':
- *(t++) = '\\';
- *(t++) = '\'';
- break;
-
- default:
- /* For special chars we prefer octal over
- * hexadecimal encoding, simply because glib's
- * g_strescape() does the same */
- if ((*f < ' ') || (*f >= 127)) {
- *(t++) = '\\';
- *(t++) = octchar((unsigned char) *f >> 6);
- *(t++) = octchar((unsigned char) *f >> 3);
- *(t++) = octchar((unsigned char) *f);
- } else
- *(t++) = *f;
- break;
- }
-
- *t = 0;
-
- return r;
-}
-
-char *cunescape_length_with_prefix(const char *s, size_t length, const char *prefix) {
- char *r, *t;
- const char *f;
- size_t pl;
-
- assert(s);
-
- /* Undoes C style string escaping, and optionally prefixes it. */
-
- pl = prefix ? strlen(prefix) : 0;
-
- r = new(char, pl+length+1);
- if (!r)
- return r;
-
- if (prefix)
- memcpy(r, prefix, pl);
-
- for (f = s, t = r + pl; f < s + length; f++) {
-
- if (*f != '\\') {
- *(t++) = *f;
- continue;
- }
-
- f++;
-
- switch (*f) {
-
- case 'a':
- *(t++) = '\a';
- break;
- case 'b':
- *(t++) = '\b';
- break;
- case 'f':
- *(t++) = '\f';
- break;
- case 'n':
- *(t++) = '\n';
- break;
- case 'r':
- *(t++) = '\r';
- break;
- case 't':
- *(t++) = '\t';
- break;
- case 'v':
- *(t++) = '\v';
- break;
- case '\\':
- *(t++) = '\\';
- break;
- case '"':
- *(t++) = '"';
- break;
- case '\'':
- *(t++) = '\'';
- break;
-
- case 's':
- /* This is an extension of the XDG syntax files */
- *(t++) = ' ';
- break;
-
- case 'x': {
- /* hexadecimal encoding */
- int a, b;
-
- a = unhexchar(f[1]);
- b = unhexchar(f[2]);
-
- if (a < 0 || b < 0) {
- /* Invalid escape code, let's take it literal then */
- *(t++) = '\\';
- *(t++) = 'x';
- } else {
- *(t++) = (char) ((a << 4) | b);
- f += 2;
- }
-
- break;
- }
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7': {
- /* octal encoding */
- int a, b, c;
-
- a = unoctchar(f[0]);
- b = unoctchar(f[1]);
- c = unoctchar(f[2]);
-
- if (a < 0 || b < 0 || c < 0) {
- /* Invalid escape code, let's take it literal then */
- *(t++) = '\\';
- *(t++) = f[0];
- } else {
- *(t++) = (char) ((a << 6) | (b << 3) | c);
- f += 2;
- }
-
- break;
- }
-
- case 0:
- /* premature end of string.*/
- *(t++) = '\\';
- goto finish;
-
- default:
- /* Invalid escape code, let's take it literal then */
- *(t++) = '\\';
- *(t++) = *f;
- break;
- }
- }
-
-finish:
- *t = 0;
- return r;
-}
-
-char *cunescape_length(const char *s, size_t length) {
- return cunescape_length_with_prefix(s, length, NULL);
-}
-
-char *cunescape(const char *s) {
- assert(s);
-
- return cunescape_length(s, strlen(s));
-}
-
-char *xescape(const char *s, const char *bad) {
- char *r, *t;
- const char *f;
-
- /* Escapes all chars in bad, in addition to \ and all special
- * chars, in \xFF style escaping. May be reversed with
- * cunescape. */
-
- r = new(char, strlen(s) * 4 + 1);
- if (!r)
- return NULL;
-
- for (f = s, t = r; *f; f++) {
-
- if ((*f < ' ') || (*f >= 127) ||
- (*f == '\\') || strchr(bad, *f)) {
- *(t++) = '\\';
- *(t++) = 'x';
- *(t++) = hexchar(*f >> 4);
- *(t++) = hexchar(*f);
- } else
- *(t++) = *f;
- }
-
- *t = 0;
-
- return r;
-}
-
-char *bus_path_escape(const char *s) {
- char *r, *t;
- const char *f;
-
- assert(s);
-
- /* Escapes all chars that D-Bus' object path cannot deal
- * with. Can be reverse with bus_path_unescape() */
-
- if (!(r = new(char, strlen(s)*3+1)))
- return NULL;
-
- for (f = s, t = r; *f; f++) {
-
- if (!(*f >= 'A' && *f <= 'Z') &&
- !(*f >= 'a' && *f <= 'z') &&
- !(*f >= '0' && *f <= '9')) {
- *(t++) = '_';
- *(t++) = hexchar(*f >> 4);
- *(t++) = hexchar(*f);
- } else
- *(t++) = *f;
- }
-
- *t = 0;
-
- return r;
-}
-
-char *bus_path_unescape(const char *f) {
- char *r, *t;
-
- assert(f);
-
- if (!(r = strdup(f)))
- return NULL;
-
- for (t = r; *f; f++) {
-
- if (*f == '_') {
- int a, b;
-
- if ((a = unhexchar(f[1])) < 0 ||
- (b = unhexchar(f[2])) < 0) {
- /* Invalid escape code, let's take it literal then */
- *(t++) = '_';
- } else {
- *(t++) = (char) ((a << 4) | b);
- f += 2;
- }
- } else
- *(t++) = *f;
- }
-
- *t = 0;
-
- return r;
-}
-
-char *ascii_strlower(char *t) {
- char *p;
-
- assert(t);
-
- for (p = t; *p; p++)
- if (*p >= 'A' && *p <= 'Z')
- *p = *p - 'A' + 'a';
-
- return t;
-}
-
-static bool ignore_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, ".swp");
-}
-
-bool ignore_file(const char *filename) {
- assert(filename);
-
- if (endswith(filename, "~"))
- return false;
-
- return ignore_file_allow_backup(filename);
-}
-
-int fd_nonblock(int fd, bool nonblock) {
- int flags;
-
- assert(fd >= 0);
-
- if ((flags = fcntl(fd, F_GETFL, 0)) < 0)
- return -errno;
-
- if (nonblock)
- flags |= O_NONBLOCK;
- else
- flags &= ~O_NONBLOCK;
-
- if (fcntl(fd, F_SETFL, flags) < 0)
- return -errno;
-
- return 0;
-}
-
-int fd_cloexec(int fd, bool cloexec) {
- int flags;
-
- assert(fd >= 0);
-
- if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
- return -errno;
-
- if (cloexec)
- flags |= FD_CLOEXEC;
- else
- flags &= ~FD_CLOEXEC;
-
- if (fcntl(fd, F_SETFD, flags) < 0)
- return -errno;
-
- return 0;
-}
-
-static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
- unsigned i;
-
- assert(n_fdset == 0 || fdset);
-
- for (i = 0; i < n_fdset; i++)
- if (fdset[i] == fd)
- return true;
-
- return false;
-}
-
-int close_all_fds(const int except[], unsigned n_except) {
- DIR *d;
- struct dirent *de;
- int r = 0;
-
- assert(n_except == 0 || except);
-
- d = opendir("/proc/self/fd");
- if (!d) {
- int fd;
- struct rlimit rl;
-
- /* When /proc isn't available (for example in chroots)
- * the fallback is brute forcing through the fd
- * table */
-
- assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
- for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
-
- if (fd_in_set(fd, except, n_except))
- continue;
-
- if (close_nointr(fd) < 0)
- if (errno != EBADF && r == 0)
- r = -errno;
- }
-
- return r;
- }
-
- while ((de = readdir(d))) {
- int fd = -1;
-
- if (ignore_file(de->d_name))
- continue;
-
- if (safe_atoi(de->d_name, &fd) < 0)
- /* Let's better ignore this, just in case */
- continue;
-
- if (fd < 3)
- continue;
-
- if (fd == dirfd(d))
- continue;
-
- if (fd_in_set(fd, except, n_except))
- continue;
-
- if (close_nointr(fd) < 0) {
- /* Valgrind has its own FD and doesn't want to have it closed */
- if (errno != EBADF && r == 0)
- r = -errno;
- }
- }
-
- closedir(d);
- return r;
-}
-
-bool chars_intersect(const char *a, const char *b) {
- const char *p;
-
- /* Returns true if any of the chars in a are in b. */
- for (p = a; *p; p++)
- if (strchr(b, *p))
- return true;
-
- return false;
-}
-
-char *format_timestamp(char *buf, size_t l, usec_t t) {
- struct tm tm;
- time_t sec;
-
- assert(buf);
- assert(l > 0);
-
- if (t <= 0)
- return NULL;
-
- sec = (time_t) (t / USEC_PER_SEC);
-
- if (strftime(buf, l, "%a, %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm)) <= 0)
- return NULL;
-
- return buf;
-}
-
-char *format_timestamp_pretty(char *buf, size_t l, usec_t t) {
- usec_t n, d;
-
- n = now(CLOCK_REALTIME);
-
- if (t <= 0 || t > n || t + USEC_PER_DAY*7 <= t)
- return NULL;
-
- d = n - t;
-
- if (d >= USEC_PER_YEAR)
- snprintf(buf, l, "%llu years and %llu months ago",
- (unsigned long long) (d / USEC_PER_YEAR),
- (unsigned long long) ((d % USEC_PER_YEAR) / USEC_PER_MONTH));
- else if (d >= USEC_PER_MONTH)
- snprintf(buf, l, "%llu months and %llu days ago",
- (unsigned long long) (d / USEC_PER_MONTH),
- (unsigned long long) ((d % USEC_PER_MONTH) / USEC_PER_DAY));
- else if (d >= USEC_PER_WEEK)
- snprintf(buf, l, "%llu weeks and %llu days ago",
- (unsigned long long) (d / USEC_PER_WEEK),
- (unsigned long long) ((d % USEC_PER_WEEK) / USEC_PER_DAY));
- else if (d >= 2*USEC_PER_DAY)
- snprintf(buf, l, "%llu days ago", (unsigned long long) (d / USEC_PER_DAY));
- else if (d >= 25*USEC_PER_HOUR)
- snprintf(buf, l, "1 day and %lluh ago",
- (unsigned long long) ((d - USEC_PER_DAY) / USEC_PER_HOUR));
- else if (d >= 6*USEC_PER_HOUR)
- snprintf(buf, l, "%lluh ago",
- (unsigned long long) (d / USEC_PER_HOUR));
- else if (d >= USEC_PER_HOUR)
- snprintf(buf, l, "%lluh %llumin ago",
- (unsigned long long) (d / USEC_PER_HOUR),
- (unsigned long long) ((d % USEC_PER_HOUR) / USEC_PER_MINUTE));
- else if (d >= 5*USEC_PER_MINUTE)
- snprintf(buf, l, "%llumin ago",
- (unsigned long long) (d / USEC_PER_MINUTE));
- else if (d >= USEC_PER_MINUTE)
- snprintf(buf, l, "%llumin %llus ago",
- (unsigned long long) (d / USEC_PER_MINUTE),
- (unsigned long long) ((d % USEC_PER_MINUTE) / USEC_PER_SEC));
- else if (d >= USEC_PER_SEC)
- snprintf(buf, l, "%llus ago",
- (unsigned long long) (d / USEC_PER_SEC));
- else if (d >= USEC_PER_MSEC)
- snprintf(buf, l, "%llums ago",
- (unsigned long long) (d / USEC_PER_MSEC));
- else if (d > 0)
- snprintf(buf, l, "%lluus ago",
- (unsigned long long) d);
- else
- snprintf(buf, l, "now");
-
- buf[l-1] = 0;
- return buf;
-}
-
-char *format_timespan(char *buf, size_t l, usec_t t) {
- static const struct {
- const char *suffix;
- usec_t usec;
- } table[] = {
- { "w", USEC_PER_WEEK },
- { "d", USEC_PER_DAY },
- { "h", USEC_PER_HOUR },
- { "min", USEC_PER_MINUTE },
- { "s", USEC_PER_SEC },
- { "ms", USEC_PER_MSEC },
- { "us", 1 },
- };
-
- unsigned i;
- char *p = buf;
-
- assert(buf);
- assert(l > 0);
-
- if (t == (usec_t) -1)
- return NULL;
-
- if (t == 0) {
- snprintf(p, l, "0");
- p[l-1] = 0;
- return p;
- }
-
- /* The result of this function can be parsed with parse_usec */
-
- for (i = 0; i < ELEMENTSOF(table); i++) {
- int k;
- size_t n;
-
- if (t < table[i].usec)
- continue;
-
- if (l <= 1)
- break;
-
- k = snprintf(p, l, "%s%llu%s", p > buf ? " " : "", (unsigned long long) (t / table[i].usec), table[i].suffix);
- n = MIN((size_t) k, l);
-
- l -= n;
- p += n;
-
- t %= table[i].usec;
- }
-
- *p = 0;
-
- return buf;
-}
-
-bool fstype_is_network(const char *fstype) {
- static const char table[] =
- "cifs\0"
- "smbfs\0"
- "ncpfs\0"
- "nfs\0"
- "nfs4\0"
- "gfs\0"
- "gfs2\0";
-
- return nulstr_contains(table, fstype);
-}
-
-int chvt(int vt) {
- _cleanup_close_ int fd;
-
- fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return -errno;
-
- if (vt < 0) {
- int tiocl[2] = {
- TIOCL_GETKMSGREDIRECT,
- 0
- };
-
- if (ioctl(fd, TIOCLINUX, tiocl) < 0)
- return -errno;
-
- vt = tiocl[0] <= 0 ? 1 : tiocl[0];
- }
-
- if (ioctl(fd, VT_ACTIVATE, vt) < 0)
- return -errno;
-
- return 0;
-}
-
-int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) {
- struct termios old_termios, new_termios;
- char c;
- char line[LINE_MAX];
-
- assert(f);
- assert(ret);
-
- if (tcgetattr(fileno(f), &old_termios) >= 0) {
- new_termios = old_termios;
-
- new_termios.c_lflag &= ~ICANON;
- new_termios.c_cc[VMIN] = 1;
- new_termios.c_cc[VTIME] = 0;
-
- if (tcsetattr(fileno(f), TCSADRAIN, &new_termios) >= 0) {
- size_t k;
-
- if (t != (usec_t) -1) {
- if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0) {
- tcsetattr(fileno(f), TCSADRAIN, &old_termios);
- return -ETIMEDOUT;
- }
- }
-
- k = fread(&c, 1, 1, f);
-
- tcsetattr(fileno(f), TCSADRAIN, &old_termios);
-
- if (k <= 0)
- return -EIO;
-
- if (need_nl)
- *need_nl = c != '\n';
-
- *ret = c;
- return 0;
- }
- }
-
- if (t != (usec_t) -1)
- if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0)
- return -ETIMEDOUT;
-
- if (!fgets(line, sizeof(line), f))
- return -EIO;
-
- truncate_nl(line);
-
- if (strlen(line) != 1)
- return -EBADMSG;
-
- if (need_nl)
- *need_nl = false;
-
- *ret = line[0];
- return 0;
-}
-
-int ask(char *ret, const char *replies, const char *text, ...) {
-
- assert(ret);
- assert(replies);
- assert(text);
-
- for (;;) {
- va_list ap;
- char c;
- int r;
- bool need_nl = true;
-
- if (on_tty())
- fputs(ANSI_HIGHLIGHT_ON, stdout);
-
- va_start(ap, text);
- vprintf(text, ap);
- va_end(ap);
-
- if (on_tty())
- fputs(ANSI_HIGHLIGHT_OFF, stdout);
-
- fflush(stdout);
-
- r = read_one_char(stdin, &c, (usec_t) -1, &need_nl);
- if (r < 0) {
-
- if (r == -EBADMSG) {
- puts("Bad input, please try again.");
- continue;
- }
-
- putchar('\n');
- return r;
- }
-
- if (need_nl)
- putchar('\n');
-
- if (strchr(replies, c)) {
- *ret = c;
- return 0;
- }
-
- puts("Read unexpected character, please try again.");
- }
-}
-
-int reset_terminal_fd(int fd, bool switch_to_text) {
- struct termios termios;
- int r = 0;
-
- /* Set terminal to some sane defaults */
-
- assert(fd >= 0);
-
- /* We leave locked terminal attributes untouched, so that
- * Plymouth may set whatever it wants to set, and we don't
- * interfere with that. */
-
- /* Disable exclusive mode, just in case */
- ioctl(fd, TIOCNXCL);
-
- /* Switch to text mode */
- if (switch_to_text)
- ioctl(fd, KDSETMODE, KD_TEXT);
-
- /* Enable console unicode mode */
- ioctl(fd, KDSKBMODE, K_UNICODE);
-
- if (tcgetattr(fd, &termios) < 0) {
- r = -errno;
- goto finish;
- }
-
- /* We only reset the stuff that matters to the software. How
- * hardware is set up we don't touch assuming that somebody
- * else will do that for us */
-
- termios.c_iflag &= ~(IGNBRK | BRKINT | ISTRIP | INLCR | IGNCR | IUCLC);
- termios.c_iflag |= ICRNL | IMAXBEL | IUTF8;
- termios.c_oflag |= ONLCR;
- termios.c_cflag |= CREAD;
- termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOPRT | ECHOKE;
-
- termios.c_cc[VINTR] = 03; /* ^C */
- termios.c_cc[VQUIT] = 034; /* ^\ */
- termios.c_cc[VERASE] = 0177;
- termios.c_cc[VKILL] = 025; /* ^X */
- termios.c_cc[VEOF] = 04; /* ^D */
- termios.c_cc[VSTART] = 021; /* ^Q */
- termios.c_cc[VSTOP] = 023; /* ^S */
- termios.c_cc[VSUSP] = 032; /* ^Z */
- termios.c_cc[VLNEXT] = 026; /* ^V */
- termios.c_cc[VWERASE] = 027; /* ^W */
- termios.c_cc[VREPRINT] = 022; /* ^R */
- termios.c_cc[VEOL] = 0;
- termios.c_cc[VEOL2] = 0;
-
- termios.c_cc[VTIME] = 0;
- termios.c_cc[VMIN] = 1;
-
- if (tcsetattr(fd, TCSANOW, &termios) < 0)
- r = -errno;
-
-finish:
- /* Just in case, flush all crap out */
- tcflush(fd, TCIOFLUSH);
-
- return r;
-}
-
-int reset_terminal(const char *name) {
- int fd, r;
-
- fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return fd;
-
- r = reset_terminal_fd(fd, true);
- close_nointr_nofail(fd);
-
- return r;
-}
-
-int open_terminal(const char *name, int mode) {
- int fd, r;
- unsigned c = 0;
-
- /*
- * If a TTY is in the process of being closed opening it might
- * cause EIO. This is horribly awful, but unlikely to be
- * changed in the kernel. Hence we work around this problem by
- * retrying a couple of times.
- *
- * https://bugs.launchpad.net/ubuntu/+source/linux/+bug/554172/comments/245
- */
-
- for (;;) {
- fd = open(name, mode);
- if (fd >= 0)
- break;
-
- if (errno != EIO)
- return -errno;
-
- /* Max 1s in total */
- if (c >= 20)
- return -errno;
-
- usleep(50 * USEC_PER_MSEC);
- c++;
- }
-
- if (fd < 0)
- return -errno;
-
- r = isatty(fd);
- if (r < 0) {
- close_nointr_nofail(fd);
- return -errno;
- }
-
- if (!r) {
- close_nointr_nofail(fd);
- return -ENOTTY;
- }
-
- return fd;
-}
-
-int flush_fd(int fd) {
- struct pollfd pollfd;
-
- zero(pollfd);
- pollfd.fd = fd;
- pollfd.events = POLLIN;
-
- for (;;) {
- char buf[LINE_MAX];
- ssize_t l;
- int r;
-
- if ((r = poll(&pollfd, 1, 0)) < 0) {
-
- if (errno == EINTR)
- continue;
-
- return -errno;
- }
-
- if (r == 0)
- return 0;
-
- if ((l = read(fd, buf, sizeof(buf))) < 0) {
-
- if (errno == EINTR)
- continue;
-
- if (errno == EAGAIN)
- return 0;
-
- return -errno;
- }
-
- if (l <= 0)
- return 0;
- }
-}
-
-int acquire_terminal(
- const char *name,
- bool fail,
- bool force,
- bool ignore_tiocstty_eperm,
- usec_t timeout) {
-
- int fd = -1, notify = -1, r = 0, wd = -1;
- usec_t ts = 0;
- struct sigaction sa_old, sa_new;
-
- assert(name);
-
- /* We use inotify to be notified when the tty is closed. We
- * create the watch before checking if we can actually acquire
- * it, so that we don't lose any event.
- *
- * Note: strictly speaking this actually watches for the
- * device being closed, it does *not* really watch whether a
- * tty loses its controlling process. However, unless some
- * rogue process uses TIOCNOTTY on /dev/tty *after* closing
- * its tty otherwise this will not become a problem. As long
- * as the administrator makes sure not configure any service
- * on the same tty as an untrusted user this should not be a
- * problem. (Which he probably should not do anyway.) */
-
- if (timeout != (usec_t) -1)
- ts = now(CLOCK_MONOTONIC);
-
- if (!fail && !force) {
- notify = inotify_init1(IN_CLOEXEC | (timeout != (usec_t) -1 ? IN_NONBLOCK : 0));
- if (notify < 0) {
- r = -errno;
- goto fail;
- }
-
- wd = inotify_add_watch(notify, name, IN_CLOSE);
- if (wd < 0) {
- r = -errno;
- goto fail;
- }
- }
-
- for (;;) {
- if (notify >= 0) {
- r = flush_fd(notify);
- if (r < 0)
- goto fail;
- }
-
- /* We pass here O_NOCTTY only so that we can check the return
- * value TIOCSCTTY and have a reliable way to figure out if we
- * successfully became the controlling process of the tty */
- fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return fd;
-
- /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
- * if we already own the tty. */
- zero(sa_new);
- sa_new.sa_handler = SIG_IGN;
- sa_new.sa_flags = SA_RESTART;
- assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
-
- /* First, try to get the tty */
- if (ioctl(fd, TIOCSCTTY, force) < 0)
- r = -errno;
-
- assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
-
- /* Sometimes it makes sense to ignore TIOCSCTTY
- * returning EPERM, i.e. when very likely we already
- * are have this controlling terminal. */
- if (r < 0 && r == -EPERM && ignore_tiocstty_eperm)
- r = 0;
-
- if (r < 0 && (force || fail || r != -EPERM)) {
- goto fail;
- }
-
- if (r >= 0)
- break;
-
- assert(!fail);
- assert(!force);
- assert(notify >= 0);
-
- for (;;) {
- uint8_t inotify_buffer[sizeof(struct inotify_event) + FILENAME_MAX];
- ssize_t l;
- struct inotify_event *e;
-
- if (timeout != (usec_t) -1) {
- usec_t n;
-
- n = now(CLOCK_MONOTONIC);
- if (ts + timeout < n) {
- r = -ETIMEDOUT;
- goto fail;
- }
-
- r = fd_wait_for_event(fd, POLLIN, ts + timeout - n);
- if (r < 0)
- goto fail;
-
- if (r == 0) {
- r = -ETIMEDOUT;
- goto fail;
- }
- }
-
- l = read(notify, inotify_buffer, sizeof(inotify_buffer));
- if (l < 0) {
-
- if (errno == EINTR || errno == EAGAIN)
- continue;
-
- r = -errno;
- goto fail;
- }
-
- e = (struct inotify_event*) inotify_buffer;
-
- while (l > 0) {
- size_t step;
-
- if (e->wd != wd || !(e->mask & IN_CLOSE)) {
- r = -EIO;
- goto fail;
- }
-
- step = sizeof(struct inotify_event) + e->len;
- assert(step <= (size_t) l);
-
- e = (struct inotify_event*) ((uint8_t*) e + step);
- l -= step;
- }
-
- break;
- }
-
- /* We close the tty fd here since if the old session
- * ended our handle will be dead. It's important that
- * we do this after sleeping, so that we don't enter
- * an endless loop. */
- close_nointr_nofail(fd);
- }
-
- if (notify >= 0)
- close_nointr_nofail(notify);
-
- r = reset_terminal_fd(fd, true);
- if (r < 0)
- log_warning("Failed to reset terminal: %s", strerror(-r));
-
- return fd;
-
-fail:
- if (fd >= 0)
- close_nointr_nofail(fd);
-
- if (notify >= 0)
- close_nointr_nofail(notify);
-
- return r;
-}
-
-int release_terminal(void) {
- int r = 0, fd;
- struct sigaction sa_old, sa_new;
-
- if ((fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY|O_CLOEXEC)) < 0)
- return -errno;
-
- /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
- * by our own TIOCNOTTY */
-
- zero(sa_new);
- sa_new.sa_handler = SIG_IGN;
- sa_new.sa_flags = SA_RESTART;
- assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
-
- if (ioctl(fd, TIOCNOTTY) < 0)
- r = -errno;
-
- assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
-
- close_nointr_nofail(fd);
- return r;
-}
-
-int sigaction_many(const struct sigaction *sa, ...) {
- va_list ap;
- int r = 0, sig;
-
- va_start(ap, sa);
- while ((sig = va_arg(ap, int)) > 0)
- if (sigaction(sig, sa, NULL) < 0)
- r = -errno;
- va_end(ap);
-
- return r;
-}
-
-int ignore_signals(int sig, ...) {
- struct sigaction sa;
- va_list ap;
- int r = 0;
-
- zero(sa);
- sa.sa_handler = SIG_IGN;
- sa.sa_flags = SA_RESTART;
-
- if (sigaction(sig, &sa, NULL) < 0)
- r = -errno;
-
- va_start(ap, sig);
- while ((sig = va_arg(ap, int)) > 0)
- if (sigaction(sig, &sa, NULL) < 0)
- r = -errno;
- va_end(ap);
-
- return r;
-}
-
-int default_signals(int sig, ...) {
- struct sigaction sa;
- va_list ap;
- int r = 0;
-
- zero(sa);
- sa.sa_handler = SIG_DFL;
- sa.sa_flags = SA_RESTART;
-
- if (sigaction(sig, &sa, NULL) < 0)
- r = -errno;
-
- va_start(ap, sig);
- while ((sig = va_arg(ap, int)) > 0)
- if (sigaction(sig, &sa, NULL) < 0)
- r = -errno;
- va_end(ap);
-
- return r;
-}
-
-int close_pipe(int p[]) {
- int a = 0, b = 0;
-
- assert(p);
-
- if (p[0] >= 0) {
- a = close_nointr(p[0]);
- p[0] = -1;
- }
-
- if (p[1] >= 0) {
- b = close_nointr(p[1]);
- p[1] = -1;
- }
-
- return a < 0 ? a : b;
-}
-
-ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
- uint8_t *p;
- ssize_t n = 0;
-
- assert(fd >= 0);
- assert(buf);
-
- p = buf;
-
- while (nbytes > 0) {
- ssize_t k;
-
- if ((k = read(fd, p, nbytes)) <= 0) {
-
- if (k < 0 && errno == EINTR)
- continue;
-
- if (k < 0 && errno == EAGAIN && do_poll) {
- struct pollfd pollfd;
-
- zero(pollfd);
- pollfd.fd = fd;
- pollfd.events = POLLIN;
-
- if (poll(&pollfd, 1, -1) < 0) {
- if (errno == EINTR)
- continue;
-
- return n > 0 ? n : -errno;
- }
-
- if (pollfd.revents != POLLIN)
- return n > 0 ? n : -EIO;
-
- continue;
- }
-
- return n > 0 ? n : (k < 0 ? -errno : 0);
- }
-
- p += k;
- nbytes -= k;
- n += k;
- }
-
- return n;
-}
-
-ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
- const uint8_t *p;
- ssize_t n = 0;
-
- assert(fd >= 0);
- assert(buf);
-
- p = buf;
-
- while (nbytes > 0) {
- ssize_t k;
-
- k = write(fd, p, nbytes);
- if (k <= 0) {
-
- if (k < 0 && errno == EINTR)
- continue;
-
- if (k < 0 && errno == EAGAIN && do_poll) {
- struct pollfd pollfd;
-
- zero(pollfd);
- pollfd.fd = fd;
- pollfd.events = POLLOUT;
-
- if (poll(&pollfd, 1, -1) < 0) {
- if (errno == EINTR)
- continue;
-
- return n > 0 ? n : -errno;
- }
-
- if (pollfd.revents != POLLOUT)
- return n > 0 ? n : -EIO;
-
- continue;
- }
-
- return n > 0 ? n : (k < 0 ? -errno : 0);
- }
-
- p += k;
- nbytes -= k;
- n += k;
- }
-
- return n;
-}
-
-int parse_usec(const char *t, usec_t *usec) {
- static const struct {
- const char *suffix;
- usec_t usec;
- } table[] = {
- { "seconds", USEC_PER_SEC },
- { "second", USEC_PER_SEC },
- { "sec", USEC_PER_SEC },
- { "s", USEC_PER_SEC },
- { "minutes", USEC_PER_MINUTE },
- { "minute", USEC_PER_MINUTE },
- { "min", USEC_PER_MINUTE },
- { "months", USEC_PER_MONTH },
- { "month", USEC_PER_MONTH },
- { "msec", USEC_PER_MSEC },
- { "ms", USEC_PER_MSEC },
- { "m", USEC_PER_MINUTE },
- { "hours", USEC_PER_HOUR },
- { "hour", USEC_PER_HOUR },
- { "hr", USEC_PER_HOUR },
- { "h", USEC_PER_HOUR },
- { "days", USEC_PER_DAY },
- { "day", USEC_PER_DAY },
- { "d", USEC_PER_DAY },
- { "weeks", USEC_PER_WEEK },
- { "week", USEC_PER_WEEK },
- { "w", USEC_PER_WEEK },
- { "years", USEC_PER_YEAR },
- { "year", USEC_PER_YEAR },
- { "y", USEC_PER_YEAR },
- { "usec", 1ULL },
- { "us", 1ULL },
- { "", USEC_PER_SEC }, /* default is sec */
- };
-
- const char *p;
- usec_t r = 0;
-
- assert(t);
- assert(usec);
-
- p = t;
- do {
- long long l;
- char *e;
- unsigned i;
-
- errno = 0;
- l = strtoll(p, &e, 10);
-
- if (errno != 0)
- return -errno;
-
- if (l < 0)
- return -ERANGE;
-
- if (e == p)
- return -EINVAL;
-
- e += strspn(e, WHITESPACE);
-
- for (i = 0; i < ELEMENTSOF(table); i++)
- if (startswith(e, table[i].suffix)) {
- r += (usec_t) l * table[i].usec;
- p = e + strlen(table[i].suffix);
- break;
- }
-
- if (i >= ELEMENTSOF(table))
- return -EINVAL;
-
- } while (*p != 0);
-
- *usec = r;
-
- return 0;
-}
-
-int parse_nsec(const char *t, nsec_t *nsec) {
- static const struct {
- const char *suffix;
- nsec_t nsec;
- } table[] = {
- { "seconds", NSEC_PER_SEC },
- { "second", NSEC_PER_SEC },
- { "sec", NSEC_PER_SEC },
- { "s", NSEC_PER_SEC },
- { "minutes", NSEC_PER_MINUTE },
- { "minute", NSEC_PER_MINUTE },
- { "min", NSEC_PER_MINUTE },
- { "months", NSEC_PER_MONTH },
- { "month", NSEC_PER_MONTH },
- { "msec", NSEC_PER_MSEC },
- { "ms", NSEC_PER_MSEC },
- { "m", NSEC_PER_MINUTE },
- { "hours", NSEC_PER_HOUR },
- { "hour", NSEC_PER_HOUR },
- { "hr", NSEC_PER_HOUR },
- { "h", NSEC_PER_HOUR },
- { "days", NSEC_PER_DAY },
- { "day", NSEC_PER_DAY },
- { "d", NSEC_PER_DAY },
- { "weeks", NSEC_PER_WEEK },
- { "week", NSEC_PER_WEEK },
- { "w", NSEC_PER_WEEK },
- { "years", NSEC_PER_YEAR },
- { "year", NSEC_PER_YEAR },
- { "y", NSEC_PER_YEAR },
- { "usec", NSEC_PER_USEC },
- { "us", NSEC_PER_USEC },
- { "nsec", 1ULL },
- { "ns", 1ULL },
- { "", 1ULL }, /* default is nsec */
- };
-
- const char *p;
- nsec_t r = 0;
-
- assert(t);
- assert(nsec);
-
- p = t;
- do {
- long long l;
- char *e;
- unsigned i;
-
- errno = 0;
- l = strtoll(p, &e, 10);
-
- if (errno != 0)
- return -errno;
-
- if (l < 0)
- return -ERANGE;
-
- if (e == p)
- return -EINVAL;
-
- e += strspn(e, WHITESPACE);
-
- for (i = 0; i < ELEMENTSOF(table); i++)
- if (startswith(e, table[i].suffix)) {
- r += (nsec_t) l * table[i].nsec;
- p = e + strlen(table[i].suffix);
- break;
- }
-
- if (i >= ELEMENTSOF(table))
- return -EINVAL;
-
- } while (*p != 0);
-
- *nsec = r;
-
- return 0;
-}
-
-int parse_bytes(const char *t, off_t *bytes) {
- static const struct {
- const char *suffix;
- off_t factor;
- } table[] = {
- { "B", 1 },
- { "K", 1024ULL },
- { "M", 1024ULL*1024ULL },
- { "G", 1024ULL*1024ULL*1024ULL },
- { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
- { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
- { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
- { "", 1 },
- };
-
- const char *p;
- off_t r = 0;
-
- assert(t);
- assert(bytes);
-
- p = t;
- do {
- long long l;
- char *e;
- unsigned i;
-
- errno = 0;
- l = strtoll(p, &e, 10);
-
- if (errno != 0)
- return -errno;
-
- if (l < 0)
- return -ERANGE;
-
- if (e == p)
- return -EINVAL;
-
- e += strspn(e, WHITESPACE);
-
- for (i = 0; i < ELEMENTSOF(table); i++)
- if (startswith(e, table[i].suffix)) {
- r += (off_t) l * table[i].factor;
- p = e + strlen(table[i].suffix);
- break;
- }
-
- if (i >= ELEMENTSOF(table))
- return -EINVAL;
-
- } while (*p != 0);
-
- *bytes = r;
-
- return 0;
-}
-
-int make_stdio(int fd) {
- int r, s, t;
-
- assert(fd >= 0);
-
- r = dup3(fd, STDIN_FILENO, 0);
- s = dup3(fd, STDOUT_FILENO, 0);
- t = dup3(fd, STDERR_FILENO, 0);
-
- if (fd >= 3)
- close_nointr_nofail(fd);
-
- if (r < 0 || s < 0 || t < 0)
- return -errno;
-
- /* We rely here that the new fd has O_CLOEXEC not set */
-
- return 0;
-}
-
-int make_null_stdio(void) {
- int null_fd;
-
- null_fd = open("/dev/null", O_RDWR|O_NOCTTY);
- if (null_fd < 0)
- return -errno;
-
- return make_stdio(null_fd);
-}
-
-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;
- int r;
-
- d = opendir(path);
- if (!d)
- return -errno;
-
- for (;;) {
- struct dirent *de;
- union dirent_storage buf;
-
- r = readdir_r(d, &buf.de, &de);
- if (r > 0)
- return -r;
-
- if (!de)
- return 1;
-
- if (!ignore_file(de->d_name))
- return 0;
- }
-}
-
-unsigned long long random_ull(void) {
- _cleanup_close_ int fd;
- uint64_t ull;
- ssize_t r;
-
- fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0)
- goto fallback;
-
- r = loop_read(fd, &ull, sizeof(ull), true);
- if (r != sizeof(ull))
- goto fallback;
-
- return ull;
-
-fallback:
- return random() * RAND_MAX + random();
-}
-
-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;
-
- memset(saved_argv[i], 0, strlen(saved_argv[i]));
- }
- }
-}
-
-void sigset_add_many(sigset_t *ss, ...) {
- va_list ap;
- int sig;
-
- assert(ss);
-
- va_start(ap, ss);
- while ((sig = va_arg(ap, int)) > 0)
- assert_se(sigaddset(ss, sig) == 0);
- va_end(ap);
-}
-
-char* gethostname_malloc(void) {
- struct utsname u;
-
- assert_se(uname(&u) >= 0);
-
- if (!isempty(u.nodename) && !streq(u.nodename, "(none)"))
- return strdup(u.nodename);
-
- return strdup(u.sysname);
-}
-
-bool hostname_is_set(void) {
- struct utsname u;
-
- assert_se(uname(&u) >= 0);
-
- return !isempty(u.nodename) && !streq(u.nodename, "(none)");
-}
-
-static char *lookup_uid(uid_t uid) {
- long bufsize;
- char *name;
- _cleanup_free_ char *buf = NULL;
- struct passwd pwbuf, *pw = NULL;
-
- /* Shortcut things to avoid NSS lookups */
- if (uid == 0)
- return strdup("root");
-
- bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
- if (bufsize <= 0)
- bufsize = 4096;
-
- buf = malloc(bufsize);
- if (!buf)
- return NULL;
-
- if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw)
- return strdup(pw->pw_name);
-
- if (asprintf(&name, "%lu", (unsigned long) uid) < 0)
- return NULL;
-
- return name;
-}
-
-char* getlogname_malloc(void) {
- uid_t uid;
- struct stat st;
-
- if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0)
- uid = st.st_uid;
- else
- uid = getuid();
-
- return lookup_uid(uid);
-}
-
-char *getusername_malloc(void) {
- const char *e;
-
- e = getenv("USER");
- if (e)
- return strdup(e);
-
- return lookup_uid(getuid());
-}
-
-int getttyname_malloc(int fd, char **r) {
- char path[PATH_MAX], *c;
- int k;
-
- assert(r);
-
- k = ttyname_r(fd, path, sizeof(path));
- if (k != 0)
- return -k;
-
- char_array_0(path);
-
- c = strdup(startswith(path, "/dev/") ? path + 5 : path);
- if (!c)
- return -ENOMEM;
-
- *r = c;
- return 0;
-}
-
-int getttyname_harder(int fd, char **r) {
- int k;
- char *s;
-
- k = getttyname_malloc(fd, &s);
- if (k < 0)
- return k;
-
- if (streq(s, "tty")) {
- free(s);
- return get_ctty(0, NULL, r);
- }
-
- *r = s;
- return 0;
-}
-
-int get_ctty_devnr(pid_t pid, dev_t *d) {
- int k;
- char line[LINE_MAX], *p, *fn;
- unsigned long ttynr;
- FILE *f;
-
- if (asprintf(&fn, "/proc/%lu/stat", (unsigned long) (pid <= 0 ? getpid() : pid)) < 0)
- return -ENOMEM;
-
- f = fopen(fn, "re");
- free(fn);
- if (!f)
- return -errno;
-
- if (!fgets(line, sizeof(line), f)) {
- k = feof(f) ? -EIO : -errno;
- fclose(f);
- return k;
- }
-
- fclose(f);
-
- p = strrchr(line, ')');
- if (!p)
- return -EIO;
-
- p++;
-
- if (sscanf(p, " "
- "%*c " /* state */
- "%*d " /* ppid */
- "%*d " /* pgrp */
- "%*d " /* session */
- "%lu ", /* ttynr */
- &ttynr) != 1)
- return -EIO;
-
- *d = (dev_t) ttynr;
- return 0;
-}
-
-int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
- int k;
- char fn[PATH_MAX], *s, *b, *p;
- dev_t devnr;
-
- assert(r);
-
- k = get_ctty_devnr(pid, &devnr);
- if (k < 0)
- return k;
-
- snprintf(fn, sizeof(fn), "/dev/char/%u:%u", major(devnr), minor(devnr));
- char_array_0(fn);
-
- if ((k = readlink_malloc(fn, &s)) < 0) {
-
- if (k != -ENOENT)
- return k;
-
- /* This is an ugly hack */
- if (major(devnr) == 136) {
- if (asprintf(&b, "pts/%lu", (unsigned long) minor(devnr)) < 0)
- return -ENOMEM;
-
- *r = b;
- if (_devnr)
- *_devnr = devnr;
-
- return 0;
- }
-
- /* Probably something like the ptys which have no
- * symlink in /dev/char. Let's return something
- * vaguely useful. */
-
- if (!(b = strdup(fn + 5)))
- return -ENOMEM;
-
- *r = b;
- if (_devnr)
- *_devnr = devnr;
-
- return 0;
- }
-
- if (startswith(s, "/dev/"))
- p = s + 5;
- else if (startswith(s, "../"))
- p = s + 3;
- else
- p = s;
-
- b = strdup(p);
- free(s);
-
- if (!b)
- return -ENOMEM;
-
- *r = b;
- if (_devnr)
- *_devnr = devnr;
-
- return 0;
-}
-
-int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
- DIR *d;
- int ret = 0;
-
- assert(fd >= 0);
-
- /* This returns the first error we run into, but nevertheless
- * tries to go on. This closes the passed fd. */
-
- d = fdopendir(fd);
- if (!d) {
- close_nointr_nofail(fd);
-
- return errno == ENOENT ? 0 : -errno;
- }
-
- for (;;) {
- struct dirent *de;
- union dirent_storage buf;
- bool is_dir, keep_around;
- struct stat st;
- int r;
-
- r = readdir_r(d, &buf.de, &de);
- if (r != 0 && ret == 0) {
- ret = -r;
- break;
- }
-
- if (!de)
- break;
-
- if (streq(de->d_name, ".") || streq(de->d_name, ".."))
- continue;
-
- if (de->d_type == DT_UNKNOWN ||
- honour_sticky ||
- (de->d_type == DT_DIR && root_dev)) {
- if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
- if (ret == 0 && errno != ENOENT)
- ret = -errno;
- continue;
- }
-
- is_dir = S_ISDIR(st.st_mode);
- keep_around =
- honour_sticky &&
- (st.st_uid == 0 || st.st_uid == getuid()) &&
- (st.st_mode & S_ISVTX);
- } else {
- is_dir = de->d_type == DT_DIR;
- keep_around = false;
- }
-
- if (is_dir) {
- int subdir_fd;
-
- /* if root_dev is set, remove subdirectories only, if device is same as dir */
- if (root_dev && st.st_dev != root_dev->st_dev)
- continue;
-
- subdir_fd = openat(fd, de->d_name,
- O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
- if (subdir_fd < 0) {
- if (ret == 0 && errno != ENOENT)
- ret = -errno;
- continue;
- }
-
- r = rm_rf_children_dangerous(subdir_fd, only_dirs, honour_sticky, root_dev);
- if (r < 0 && ret == 0)
- ret = r;
-
- if (!keep_around)
- if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
- if (ret == 0 && errno != ENOENT)
- ret = -errno;
- }
-
- } else if (!only_dirs && !keep_around) {
-
- if (unlinkat(fd, de->d_name, 0) < 0) {
- if (ret == 0 && errno != ENOENT)
- ret = -errno;
- }
- }
- }
-
- closedir(d);
-
- return ret;
-}
-
-int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
- struct statfs s;
-
- assert(fd >= 0);
-
- if (fstatfs(fd, &s) < 0) {
- close_nointr_nofail(fd);
- return -errno;
- }
-
- /* We refuse to clean disk file systems with this call. This
- * is extra paranoia just to be sure we never ever remove
- * non-state data */
-
- if (s.f_type != TMPFS_MAGIC &&
- s.f_type != RAMFS_MAGIC) {
- log_error("Attempted to remove disk file system, and we can't allow that.");
- close_nointr_nofail(fd);
- return -EPERM;
- }
-
- return rm_rf_children_dangerous(fd, only_dirs, honour_sticky, root_dev);
-}
-
-static int rm_rf_internal(const char *path, bool only_dirs, bool delete_root, bool honour_sticky, bool dangerous) {
- int fd, r;
- struct statfs s;
-
- assert(path);
-
- /* We refuse to clean the root file system with this
- * call. This is extra paranoia to never cause a really
- * seriously broken system. */
- if (path_equal(path, "/")) {
- log_error("Attempted to remove entire root file system, and we can't allow that.");
- return -EPERM;
- }
-
- fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
- if (fd < 0) {
-
- if (errno != ENOTDIR)
- return -errno;
-
- if (!dangerous) {
- if (statfs(path, &s) < 0)
- return -errno;
-
- if (s.f_type != TMPFS_MAGIC &&
- s.f_type != RAMFS_MAGIC) {
- log_error("Attempted to remove disk file system, and we can't allow that.");
- return -EPERM;
- }
- }
-
- if (delete_root && !only_dirs)
- if (unlink(path) < 0 && errno != ENOENT)
- return -errno;
-
- return 0;
- }
-
- if (!dangerous) {
- if (fstatfs(fd, &s) < 0) {
- close_nointr_nofail(fd);
- return -errno;
- }
-
- if (s.f_type != TMPFS_MAGIC &&
- s.f_type != RAMFS_MAGIC) {
- log_error("Attempted to remove disk file system, and we can't allow that.");
- close_nointr_nofail(fd);
- return -EPERM;
- }
- }
-
- r = rm_rf_children_dangerous(fd, only_dirs, honour_sticky, NULL);
- if (delete_root) {
-
- if (honour_sticky && file_is_priv_sticky(path) > 0)
- return r;
-
- if (rmdir(path) < 0 && errno != ENOENT) {
- if (r == 0)
- r = -errno;
- }
- }
-
- return r;
-}
-
-int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
- return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, false);
-}
-
-int rm_rf_dangerous(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
- return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, true);
-}
-
-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_t) -1)
- if (chmod(path, mode) < 0)
- return -errno;
-
- if (uid != (uid_t) -1 || gid != (gid_t) -1)
- 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 (fchmod(fd, mode) < 0)
- return -errno;
-
- if (fchown(fd, uid, gid) < 0)
- return -errno;
-
- return 0;
-}
-
-cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
- cpu_set_t *r;
- unsigned n = 1024;
-
- /* Allocates the cpuset in the right size */
-
- for (;;) {
- if (!(r = CPU_ALLOC(n)))
- return NULL;
-
- if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), r) >= 0) {
- CPU_ZERO_S(CPU_ALLOC_SIZE(n), r);
-
- if (ncpus)
- *ncpus = n;
-
- return r;
- }
-
- CPU_FREE(r);
-
- if (errno != EINVAL)
- return NULL;
-
- n *= 2;
- }
-}
-
-int status_vprintf(const char *status, bool ellipse, 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[5];
- int n = 0;
-
- 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, 75);
- if (e) {
- free(s);
- s = e;
- }
- }
-
- zero(iovec);
-
- 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);
- IOVEC_SET_STRING(iovec[n++], "\n");
-
- if (writev(fd, iovec, n) < 0)
- return -errno;
-
- return 0;
-}
-
-int status_printf(const char *status, bool ellipse, const char *format, ...) {
- va_list ap;
- int r;
-
- assert(format);
-
- va_start(ap, format);
- r = status_vprintf(status, ellipse, format, ap);
- va_end(ap);
-
- return r;
-}
-
-int status_welcome(void) {
- int r;
- _cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL;
-
- r = parse_env_file("/etc/os-release", NEWLINE,
- "PRETTY_NAME", &pretty_name,
- "ANSI_COLOR", &ansi_color,
- NULL);
- if (r < 0 && r != -ENOENT)
- log_warning("Failed to read /etc/os-release: %s", strerror(-r));
-
- return status_printf(NULL, false,
- "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
- isempty(ansi_color) ? "1" : ansi_color,
- isempty(pretty_name) ? "Linux" : pretty_name);
-}
-
-char *replace_env(const char *format, char **env) {
- enum {
- WORD,
- CURLY,
- VARIABLE
- } state = WORD;
-
- const char *e, *word = format;
- char *r = NULL, *k;
-
- assert(format);
-
- for (e = format; *e; e ++) {
-
- switch (state) {
-
- case WORD:
- if (*e == '$')
- state = CURLY;
- break;
-
- case CURLY:
- if (*e == '{') {
- if (!(k = strnappend(r, word, e-word-1)))
- goto fail;
-
- free(r);
- r = k;
-
- word = e-1;
- state = VARIABLE;
-
- } else if (*e == '$') {
- if (!(k = strnappend(r, word, e-word)))
- goto fail;
-
- free(r);
- r = k;
-
- word = e+1;
- state = WORD;
- } else
- state = WORD;
- break;
-
- case VARIABLE:
- if (*e == '}') {
- const char *t;
-
- if (!(t = strv_env_get_with_length(env, word+2, e-word-2)))
- t = "";
-
- if (!(k = strappend(r, t)))
- goto fail;
-
- free(r);
- r = k;
-
- word = e+1;
- state = WORD;
- }
- break;
- }
- }
-
- if (!(k = strnappend(r, word, e-word)))
- goto fail;
-
- free(r);
- return k;
-
-fail:
- free(r);
- return NULL;
-}
-
-char **replace_env_argv(char **argv, char **env) {
- char **r, **i;
- unsigned k = 0, l = 0;
-
- l = strv_length(argv);
-
- if (!(r = new(char*, l+1)))
- return NULL;
-
- STRV_FOREACH(i, argv) {
-
- /* If $FOO appears as single word, replace it by the split up variable */
- if ((*i)[0] == '$' && (*i)[1] != '{') {
- char *e;
- char **w, **m;
- unsigned q;
-
- if ((e = strv_env_get(env, *i+1))) {
-
- if (!(m = strv_split_quoted(e))) {
- r[k] = NULL;
- strv_free(r);
- return NULL;
- }
- } else
- m = NULL;
-
- q = strv_length(m);
- l = l + q - 1;
-
- if (!(w = realloc(r, sizeof(char*) * (l+1)))) {
- r[k] = NULL;
- strv_free(r);
- strv_free(m);
- return NULL;
- }
-
- r = w;
- if (m) {
- memcpy(r + k, m, q * sizeof(char*));
- free(m);
- }
-
- k += q;
- continue;
- }
-
- /* If ${FOO} appears as part of a word, replace it by the variable as-is */
- if (!(r[k++] = replace_env(*i, env))) {
- strv_free(r);
- return NULL;
- }
- }
-
- r[k] = NULL;
- return r;
-}
-
-int fd_columns(int fd) {
- struct winsize ws;
- zero(ws);
-
- if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
- return -errno;
-
- if (ws.ws_col <= 0)
- return -EIO;
-
- return ws.ws_col;
-}
-
-unsigned columns(void) {
- const char *e;
- unsigned c;
-
- if (_likely_(cached_columns > 0))
- return cached_columns;
-
- c = 0;
- e = getenv("COLUMNS");
- if (e)
- safe_atou(e, &c);
-
- if (c <= 0)
- c = fd_columns(STDOUT_FILENO);
-
- if (c <= 0)
- c = 80;
-
- cached_columns = c;
- return c;
-}
-
-int fd_lines(int fd) {
- struct winsize ws;
- zero(ws);
-
- if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
- return -errno;
-
- if (ws.ws_row <= 0)
- return -EIO;
-
- return ws.ws_row;
-}
-
-unsigned lines(void) {
- const char *e;
- unsigned l;
-
- if (_likely_(cached_lines > 0))
- return cached_lines;
-
- l = 0;
- e = getenv("LINES");
- if (e)
- safe_atou(e, &l);
-
- if (l <= 0)
- l = fd_lines(STDOUT_FILENO);
-
- if (l <= 0)
- l = 24;
-
- cached_lines = l;
- return cached_lines;
-}
-
-/* intended to be used as a SIGWINCH sighandler */
-void columns_lines_cache_reset(int signum) {
- cached_columns = 0;
- cached_lines = 0;
-}
-
-bool on_tty(void) {
- static int cached_on_tty = -1;
-
- if (_unlikely_(cached_on_tty < 0))
- cached_on_tty = isatty(STDOUT_FILENO) > 0;
-
- return cached_on_tty;
-}
-
-int running_in_chroot(void) {
- struct stat a, b;
-
- zero(a);
- zero(b);
-
- /* Only works as root */
-
- if (stat("/proc/1/root", &a) < 0)
- return -errno;
-
- if (stat("/", &b) < 0)
- return -errno;
-
- return
- a.st_dev != b.st_dev ||
- a.st_ino != b.st_ino;
-}
-
-char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
- size_t x;
- char *r;
-
- assert(s);
- assert(percent <= 100);
- assert(new_length >= 3);
-
- if (old_length <= 3 || old_length <= new_length)
- return strndup(s, old_length);
-
- r = new0(char, new_length+1);
- if (!r)
- return r;
-
- x = (new_length * percent) / 100;
-
- if (x > new_length - 3)
- x = new_length - 3;
-
- memcpy(r, s, x);
- r[x] = '.';
- r[x+1] = '.';
- r[x+2] = '.';
- memcpy(r + x + 3,
- s + old_length - (new_length - x - 3),
- new_length - x - 3);
-
- return r;
-}
-
-char *ellipsize(const char *s, size_t length, unsigned percent) {
- return ellipsize_mem(s, strlen(s), length, percent);
-}
-
-int touch(const char *path) {
- int fd;
-
- assert(path);
-
- /* This just opens the file for writing, ensuring it
- * exists. It doesn't call utimensat() the way /usr/bin/touch
- * does it. */
-
- fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0644);
- if (fd < 0)
- return -errno;
-
- close_nointr_nofail(fd);
- return 0;
-}
-
-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. We should make this smarter one
- * day...*/
-
- 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);
-}
-
-char *normalize_env_assignment(const char *s) {
- _cleanup_free_ char *name = NULL, *value = NULL, *p = NULL;
- char *eq, *r;
-
- eq = strchr(s, '=');
- if (!eq) {
- char *t;
-
- r = strdup(s);
- if (!r)
- return NULL;
-
- t = strstrip(r);
- if (t == r)
- return r;
-
- memmove(r, t, strlen(t) + 1);
- return r;
- }
-
- name = strndup(s, eq - s);
- if (!name)
- return NULL;
-
- p = strdup(eq + 1);
- if (!p)
- return NULL;
-
- value = unquote(strstrip(p), QUOTES);
- if (!value)
- return NULL;
-
- if (asprintf(&r, "%s=%s", strstrip(name), value) < 0)
- r = NULL;
-
- return r;
-}
-
-int wait_for_terminate(pid_t pid, siginfo_t *status) {
- siginfo_t dummy;
-
- assert(pid >= 1);
-
- if (!status)
- status = &dummy;
-
- for (;;) {
- zero(*status);
-
- if (waitid(P_PID, pid, status, WEXITED) < 0) {
-
- if (errno == EINTR)
- continue;
-
- return -errno;
- }
-
- return 0;
- }
-}
-
-int wait_for_terminate_and_warn(const char *name, pid_t pid) {
- int r;
- siginfo_t status;
-
- assert(name);
- assert(pid > 1);
-
- r = wait_for_terminate(pid, &status);
- if (r < 0) {
- log_warning("Failed to wait for %s: %s", name, strerror(-r));
- return r;
- }
-
- if (status.si_code == CLD_EXITED) {
- if (status.si_status != 0) {
- log_warning("%s failed with error code %i.", name, status.si_status);
- return status.si_status;
- }
-
- log_debug("%s succeeded.", name);
- return 0;
-
- } else if (status.si_code == CLD_KILLED ||
- status.si_code == CLD_DUMPED) {
-
- log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
- return -EPROTO;
- }
-
- log_warning("%s failed due to unknown reason.", name);
- return -EPROTO;
-}
-
-_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);
-}
-
-DIR *xopendirat(int fd, const char *name, int flags) {
- int nfd;
- DIR *d;
-
- nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags);
- if (nfd < 0)
- return NULL;
-
- d = fdopendir(nfd);
- if (!d) {
- close_nointr_nofail(nfd);
- return NULL;
- }
-
- return d;
-}
-
-int signal_from_string_try_harder(const char *s) {
- int signo;
- assert(s);
-
- signo = signal_from_string(s);
- if (signo <= 0)
- if (startswith(s, "SIG"))
- return signal_from_string(s+3);
-
- return signo;
-}
-
-void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t) {
-
- assert(f);
- assert(name);
- assert(t);
-
- if (!dual_timestamp_is_set(t))
- return;
-
- fprintf(f, "%s=%llu %llu\n",
- name,
- (unsigned long long) t->realtime,
- (unsigned long long) t->monotonic);
-}
-
-void dual_timestamp_deserialize(const char *value, dual_timestamp *t) {
- unsigned long long a, b;
-
- assert(value);
- assert(t);
-
- if (sscanf(value, "%lli %llu", &a, &b) != 2)
- log_debug("Failed to parse finish timestamp value %s", value);
- else {
- t->realtime = a;
- t->monotonic = b;
- }
-}
-
-static char *tag_to_udev_node(const char *tagvalue, const char *by) {
- char *dn, *t, *u;
- int r;
-
- /* FIXME: to follow udev's logic 100% we need to leave valid
- * UTF8 chars unescaped */
-
- u = unquote(tagvalue, "\"\'");
- if (u == NULL)
- return NULL;
-
- t = xescape(u, "/ ");
- free(u);
-
- if (t == NULL)
- return NULL;
-
- r = asprintf(&dn, "/dev/disk/by-%s/%s", by, t);
- free(t);
-
- if (r < 0)
- return NULL;
-
- return dn;
-}
-
-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 tty_is_vc(const char *tty) {
- assert(tty);
-
- if (startswith(tty, "/dev/"))
- tty += 5;
-
- return vtnr_from_tty(tty) >= 0;
-}
-
-bool tty_is_console(const char *tty) {
- assert(tty);
-
- if (startswith(tty, "/dev/"))
- tty += 5;
-
- return streq(tty, "console");
-}
-
-int vtnr_from_tty(const char *tty) {
- int i, r;
-
- assert(tty);
-
- if (startswith(tty, "/dev/"))
- tty += 5;
-
- if (!startswith(tty, "tty") )
- return -EINVAL;
-
- if (tty[3] < '0' || tty[3] > '9')
- return -EINVAL;
-
- r = safe_atoi(tty+3, &i);
- if (r < 0)
- return r;
-
- if (i < 0 || i > 63)
- return -EINVAL;
-
- return i;
-}
-
-bool tty_is_vc_resolve(const char *tty) {
- char *active = NULL;
- bool b;
-
- assert(tty);
-
- if (startswith(tty, "/dev/"))
- tty += 5;
-
- /* Resolve where /dev/console is pointing to, if /sys is
- * actually ours (i.e. not read-only-mounted which is a sign
- * for container setups) */
- if (streq(tty, "console") && path_is_read_only_fs("/sys") <= 0)
- if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
- /* If multiple log outputs are configured the
- * last one is what /dev/console points to */
- tty = strrchr(active, ' ');
- if (tty)
- tty++;
- else
- tty = active;
- }
-
- b = tty_is_vc(tty);
- free(active);
-
- return b;
-}
-
-const char *default_term_for_tty(const char *tty) {
- assert(tty);
-
- return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt102";
-}
-
-bool dirent_is_file(const struct dirent *de) {
- assert(de);
-
- if (ignore_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 (ignore_file_allow_backup(de->d_name))
- return false;
-
- return endswith(de->d_name, suffix);
-}
-
-void execute_directory(const char *directory, DIR *d, char *argv[]) {
- DIR *_d = NULL;
- struct dirent *de;
- Hashmap *pids = NULL;
-
- assert(directory);
-
- /* Executes all binaries in a directory in parallel and waits
- * until all they all finished. */
-
- if (!d) {
- if (!(_d = opendir(directory))) {
-
- if (errno == ENOENT)
- return;
-
- log_error("Failed to enumerate directory %s: %m", directory);
- return;
- }
-
- d = _d;
- }
-
- if (!(pids = hashmap_new(trivial_hash_func, trivial_compare_func))) {
- log_error("Failed to allocate set.");
- goto finish;
- }
-
- while ((de = readdir(d))) {
- char *path;
- pid_t pid;
- int k;
-
- if (!dirent_is_file(de))
- continue;
-
- if (asprintf(&path, "%s/%s", directory, de->d_name) < 0) {
- log_oom();
- continue;
- }
-
- if ((pid = fork()) < 0) {
- log_error("Failed to fork: %m");
- free(path);
- continue;
- }
-
- if (pid == 0) {
- char *_argv[2];
- /* Child */
-
- if (!argv) {
- _argv[0] = path;
- _argv[1] = NULL;
- argv = _argv;
- } else
- argv[0] = path;
-
- execv(path, argv);
-
- log_error("Failed to execute %s: %m", path);
- _exit(EXIT_FAILURE);
- }
-
- log_debug("Spawned %s as %lu", path, (unsigned long) pid);
-
- if ((k = hashmap_put(pids, UINT_TO_PTR(pid), path)) < 0) {
- log_error("Failed to add PID to set: %s", strerror(-k));
- free(path);
- }
- }
-
- while (!hashmap_isempty(pids)) {
- pid_t pid = PTR_TO_UINT(hashmap_first_key(pids));
- siginfo_t si;
- char *path;
-
- zero(si);
- if (waitid(P_PID, pid, &si, WEXITED) < 0) {
-
- if (errno == EINTR)
- continue;
-
- log_error("waitid() failed: %m");
- goto finish;
- }
-
- if ((path = hashmap_remove(pids, UINT_TO_PTR(si.si_pid)))) {
- if (!is_clean_exit(si.si_code, si.si_status, NULL)) {
- if (si.si_code == CLD_EXITED)
- log_error("%s exited with exit status %i.", path, si.si_status);
- else
- log_error("%s terminated by signal %s.", path, signal_to_string(si.si_status));
- } else
- log_debug("%s exited successfully.", path);
-
- free(path);
- }
- }
-
-finish:
- if (_d)
- closedir(_d);
-
- if (pids)
- hashmap_free_free(pids);
-}
-
-int kill_and_sigcont(pid_t pid, int sig) {
- int r;
-
- r = kill(pid, sig) < 0 ? -errno : 0;
-
- if (r >= 0)
- kill(pid, SIGCONT);
-
- return r;
-}
-
-bool nulstr_contains(const char*nulstr, const char *needle) {
- const char *i;
-
- if (!nulstr)
- return false;
-
- NULSTR_FOREACH(i, nulstr)
- if (streq(i, needle))
- return true;
-
- return false;
-}
-
-bool plymouth_running(void) {
- return access("/run/plymouth/pid", F_OK) >= 0;
-}
-
-char* strshorten(char *s, size_t l) {
- assert(s);
-
- if (l < strlen(s))
- s[l] = 0;
-
- return s;
-}
-
-static bool hostname_valid_char(char c) {
- return
- (c >= 'a' && c <= 'z') ||
- (c >= 'A' && c <= 'Z') ||
- (c >= '0' && c <= '9') ||
- c == '-' ||
- c == '_' ||
- c == '.';
-}
-
-bool hostname_is_valid(const char *s) {
- const char *p;
-
- if (isempty(s))
- return false;
-
- for (p = s; *p; p++)
- if (!hostname_valid_char(*p))
- return false;
-
- if (p-s > HOST_NAME_MAX)
- return false;
-
- return true;
-}
-
-char* hostname_cleanup(char *s) {
- char *p, *d;
-
- for (p = s, d = s; *p; p++)
- if ((*p >= 'a' && *p <= 'z') ||
- (*p >= 'A' && *p <= 'Z') ||
- (*p >= '0' && *p <= '9') ||
- *p == '-' ||
- *p == '_' ||
- *p == '.')
- *(d++) = *p;
-
- *d = 0;
-
- strshorten(s, HOST_NAME_MAX);
- return s;
-}
-
-int pipe_eof(int fd) {
- struct pollfd pollfd;
- int r;
-
- zero(pollfd);
- pollfd.fd = fd;
- pollfd.events = POLLIN|POLLHUP;
-
- r = poll(&pollfd, 1, 0);
- if (r < 0)
- return -errno;
-
- if (r == 0)
- return 0;
-
- return pollfd.revents & POLLHUP;
-}
-
-int fd_wait_for_event(int fd, int event, usec_t t) {
- struct pollfd pollfd;
- int r;
-
- zero(pollfd);
- pollfd.fd = fd;
- pollfd.events = event;
-
- r = poll(&pollfd, 1, t == (usec_t) -1 ? -1 : (int) (t / USEC_PER_MSEC));
- if (r < 0)
- return -errno;
-
- if (r == 0)
- return 0;
-
- return pollfd.revents;
-}
-
-int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
- FILE *f;
- char *t;
- const char *fn;
- size_t k;
- int fd;
-
- assert(path);
- assert(_f);
- assert(_temp_path);
-
- t = new(char, strlen(path) + 1 + 6 + 1);
- if (!t)
- return -ENOMEM;
-
- fn = path_get_file_name(path);
- k = fn-path;
- memcpy(t, path, k);
- t[k] = '.';
- stpcpy(stpcpy(t+k+1, fn), "XXXXXX");
-
- fd = mkostemp(t, O_WRONLY|O_CLOEXEC);
- if (fd < 0) {
- free(t);
- return -errno;
- }
-
- f = fdopen(fd, "we");
- if (!f) {
- unlink(t);
- free(t);
- return -errno;
- }
-
- *_f = f;
- *_temp_path = t;
-
- return 0;
-}
-
-int terminal_vhangup_fd(int fd) {
- assert(fd >= 0);
-
- if (ioctl(fd, TIOCVHANGUP) < 0)
- return -errno;
-
- return 0;
-}
-
-int terminal_vhangup(const char *name) {
- int fd, r;
-
- fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return fd;
-
- r = terminal_vhangup_fd(fd);
- close_nointr_nofail(fd);
-
- return r;
-}
-
-int vt_disallocate(const char *name) {
- int fd, r;
- unsigned u;
-
- /* Deallocate the VT if possible. If not possible
- * (i.e. because it is the active one), at least clear it
- * entirely (including the scrollback buffer) */
-
- if (!startswith(name, "/dev/"))
- return -EINVAL;
-
- if (!tty_is_vc(name)) {
- /* So this is not a VT. I guess we cannot deallocate
- * it then. But let's at least clear the screen */
-
- fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return fd;
-
- loop_write(fd,
- "\033[r" /* clear scrolling region */
- "\033[H" /* move home */
- "\033[2J", /* clear screen */
- 10, false);
- close_nointr_nofail(fd);
-
- return 0;
- }
-
- if (!startswith(name, "/dev/tty"))
- return -EINVAL;
-
- r = safe_atou(name+8, &u);
- if (r < 0)
- return r;
-
- if (u <= 0)
- return -EINVAL;
-
- /* Try to deallocate */
- fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return fd;
-
- r = ioctl(fd, VT_DISALLOCATE, u);
- close_nointr_nofail(fd);
-
- if (r >= 0)
- return 0;
-
- if (errno != EBUSY)
- return -errno;
-
- /* Couldn't deallocate, so let's clear it fully with
- * scrollback */
- fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return fd;
-
- loop_write(fd,
- "\033[r" /* clear scrolling region */
- "\033[H" /* move home */
- "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
- 10, false);
- close_nointr_nofail(fd);
-
- return 0;
-}
-
-int copy_file(const char *from, const char *to) {
- int r, fdf, fdt;
-
- assert(from);
- assert(to);
-
- fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fdf < 0)
- return -errno;
-
- fdt = open(to, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY, 0644);
- if (fdt < 0) {
- close_nointr_nofail(fdf);
- return -errno;
- }
-
- for (;;) {
- char buf[PIPE_BUF];
- ssize_t n, k;
-
- n = read(fdf, buf, sizeof(buf));
- if (n < 0) {
- r = -errno;
-
- close_nointr_nofail(fdf);
- close_nointr(fdt);
- unlink(to);
-
- return r;
- }
-
- if (n == 0)
- break;
-
- errno = 0;
- k = loop_write(fdt, buf, n, false);
- if (n != k) {
- r = k < 0 ? k : (errno ? -errno : -EIO);
-
- close_nointr_nofail(fdf);
- close_nointr(fdt);
-
- unlink(to);
- return r;
- }
- }
-
- close_nointr_nofail(fdf);
- r = close_nointr(fdt);
-
- if (r < 0) {
- unlink(to);
- return r;
- }
-
- return 0;
-}
-
-int symlink_atomic(const char *from, const char *to) {
- char *x;
- _cleanup_free_ char *t;
- const char *fn;
- size_t k;
- unsigned long long ull;
- unsigned i;
- int r;
-
- assert(from);
- assert(to);
-
- t = new(char, strlen(to) + 1 + 16 + 1);
- if (!t)
- return -ENOMEM;
-
- fn = path_get_file_name(to);
- k = fn-to;
- memcpy(t, to, k);
- t[k] = '.';
- x = stpcpy(t+k+1, fn);
-
- ull = random_ull();
- for (i = 0; i < 16; i++) {
- *(x++) = hexchar(ull & 0xF);
- ull >>= 4;
- }
-
- *x = 0;
-
- if (symlink(from, t) < 0)
- return -errno;
-
- if (rename(t, to) < 0) {
- r = -errno;
- unlink(t);
- return r;
- }
-
- return 0;
-}
-
-bool display_is_local(const char *display) {
- assert(display);
-
- return
- display[0] == ':' &&
- display[1] >= '0' &&
- display[1] <= '9';
-}
-
-int socket_from_display(const char *display, char **path) {
- size_t k;
- char *f, *c;
-
- assert(display);
- assert(path);
-
- if (!display_is_local(display))
- return -EINVAL;
-
- k = strspn(display+1, "0123456789");
-
- f = new(char, sizeof("/tmp/.X11-unix/X") + k);
- if (!f)
- return -ENOMEM;
-
- c = stpcpy(f, "/tmp/.X11-unix/X");
- memcpy(c, display+1, k);
- c[k] = 0;
-
- *path = f;
-
- return 0;
-}
-
-int get_user_creds(
- const char **username,
- uid_t *uid, gid_t *gid,
- const char **home,
- const char **shell) {
-
- struct passwd *p;
- uid_t u;
-
- assert(username);
- assert(*username);
-
- /* We enforce some special rules for uid=0: in order to avoid
- * NSS lookups for root we hardcode its data. */
-
- if (streq(*username, "root") || streq(*username, "0")) {
- *username = "root";
-
- if (uid)
- *uid = 0;
-
- if (gid)
- *gid = 0;
-
- if (home)
- *home = "/root";
-
- if (shell)
- *shell = "/bin/sh";
-
- return 0;
- }
-
- if (parse_uid(*username, &u) >= 0) {
- errno = 0;
- p = getpwuid(u);
-
- /* If there are multiple users with the same id, make
- * sure to leave $USER to the configured value instead
- * of the first occurrence in the database. However if
- * the uid was configured by a numeric uid, then let's
- * pick the real username from /etc/passwd. */
- if (p)
- *username = p->pw_name;
- } else {
- errno = 0;
- p = getpwnam(*username);
- }
-
- if (!p)
- return errno != 0 ? -errno : -ESRCH;
-
- if (uid)
- *uid = p->pw_uid;
-
- if (gid)
- *gid = p->pw_gid;
-
- if (home)
- *home = p->pw_dir;
-
- if (shell)
- *shell = p->pw_shell;
-
- return 0;
-}
-
-int get_group_creds(const char **groupname, gid_t *gid) {
- struct group *g;
- gid_t id;
-
- assert(groupname);
-
- /* We enforce some special rules for gid=0: in order to avoid
- * NSS lookups for root we hardcode its data. */
-
- if (streq(*groupname, "root") || streq(*groupname, "0")) {
- *groupname = "root";
-
- if (gid)
- *gid = 0;
-
- return 0;
- }
-
- if (parse_gid(*groupname, &id) >= 0) {
- errno = 0;
- g = getgrgid(id);
-
- if (g)
- *groupname = g->gr_name;
- } else {
- errno = 0;
- g = getgrnam(*groupname);
- }
-
- if (!g)
- return errno != 0 ? -errno : -ESRCH;
-
- if (gid)
- *gid = g->gr_gid;
-
- return 0;
-}
-
-int in_group(const char *name) {
- gid_t gid, *gids;
- int ngroups_max, r, i;
-
- r = get_group_creds(&name, &gid);
- if (r < 0)
- return r;
-
- if (getgid() == gid)
- return 1;
-
- if (getegid() == gid)
- return 1;
-
- ngroups_max = sysconf(_SC_NGROUPS_MAX);
- assert(ngroups_max > 0);
-
- gids = alloca(sizeof(gid_t) * ngroups_max);
-
- r = getgroups(ngroups_max, gids);
- if (r < 0)
- return -errno;
-
- for (i = 0; i < r; i++)
- if (gids[i] == gid)
- return 1;
-
- return 0;
-}
-
-int glob_exists(const char *path) {
- glob_t g;
- int r, k;
-
- assert(path);
-
- zero(g);
- errno = 0;
- k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
-
- if (k == GLOB_NOMATCH)
- r = 0;
- else if (k == GLOB_NOSPACE)
- r = -ENOMEM;
- else if (k == 0)
- r = !strv_isempty(g.gl_pathv);
- else
- r = errno ? -errno : -EIO;
-
- globfree(&g);
-
- return r;
-}
-
-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 in_search_path(const char *path, char **search) {
- char **i, *parent;
- int r;
-
- r = path_get_parent(path, &parent);
- if (r < 0)
- return r;
-
- r = 0;
-
- STRV_FOREACH(i, search) {
- if (path_equal(parent, *i)) {
- r = 1;
- break;
- }
- }
-
- free(parent);
-
- return r;
-}
-
-int get_files_in_directory(const char *path, char ***list) {
- DIR *d;
- int r = 0;
- unsigned n = 0;
- 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;
- union dirent_storage buf;
- int k;
-
- k = readdir_r(d, &buf.de, &de);
- if (k != 0) {
- r = -k;
- goto finish;
- }
-
- if (!de)
- break;
-
- dirent_ensure_type(d, de);
-
- if (!dirent_is_file(de))
- continue;
-
- if (list) {
- if ((unsigned) r >= n) {
- char **t;
-
- n = MAX(16, 2*r);
- t = realloc(l, sizeof(char*) * n);
- if (!t) {
- r = -ENOMEM;
- goto finish;
- }
-
- l = t;
- }
-
- assert((unsigned) r < n);
-
- l[r] = strdup(de->d_name);
- if (!l[r]) {
- r = -ENOMEM;
- goto finish;
- }
-
- l[++r] = NULL;
- } else
- r++;
- }
-
-finish:
- if (d)
- closedir(d);
-
- if (r >= 0) {
- if (list)
- *list = l;
- } else
- strv_free(l);
-
- return r;
-}
-
-char *strjoin(const char *x, ...) {
- va_list ap;
- size_t l;
- char *r, *p;
-
- va_start(ap, x);
-
- if (x) {
- l = strlen(x);
-
- for (;;) {
- const char *t;
- size_t n;
-
- t = va_arg(ap, const char *);
- if (!t)
- break;
-
- n = strlen(t);
- if (n > ((size_t) -1) - l) {
- va_end(ap);
- return NULL;
- }
-
- l += n;
- }
- } else
- l = 0;
-
- va_end(ap);
-
- r = new(char, l+1);
- if (!r)
- return NULL;
-
- if (x) {
- p = stpcpy(r, x);
-
- va_start(ap, x);
-
- for (;;) {
- const char *t;
-
- t = va_arg(ap, const char *);
- if (!t)
- break;
-
- p = stpcpy(p, t);
- }
-
- va_end(ap);
- } else
- r[0] = 0;
-
- return r;
-}
-
-bool is_main_thread(void) {
- static __thread 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;
- unsigned n, m;
-
- assert(ret);
-
- /* If it has a queue this is good enough for us */
- if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
- return -ENOMEM;
-
- r = access(p, F_OK);
- free(p);
-
- if (r >= 0) {
- *ret = d;
- return 0;
- }
-
- /* If it is a partition find the originating device */
- if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
- return -ENOMEM;
-
- r = access(p, F_OK);
- free(p);
-
- if (r < 0)
- return -ENOENT;
-
- /* Get parent dev_t */
- if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
- return -ENOMEM;
-
- r = read_one_line_file(p, &s);
- free(p);
-
- if (r < 0)
- return r;
-
- r = sscanf(s, "%u:%u", &m, &n);
- free(s);
-
- if (r != 2)
- return -EINVAL;
-
- /* Only return this if it is really good enough for us. */
- if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
- return -ENOMEM;
-
- r = access(p, F_OK);
- free(p);
-
- if (r >= 0) {
- *ret = makedev(m, n);
- return 0;
- }
-
- return -ENOENT;
-}
-
-int file_is_priv_sticky(const char *p) {
- struct stat st;
-
- assert(p);
-
- if (lstat(p, &st) < 0)
- return -errno;
-
- return
- (st.st_uid == 0 || st.st_uid == getuid()) &&
- (st.st_mode & S_ISVTX);
-}
-
-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));
-
-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);
-
-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_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);
-
-static const char* const ip_tos_table[] = {
- [IPTOS_LOWDELAY] = "low-delay",
- [IPTOS_THROUGHPUT] = "throughput",
- [IPTOS_RELIABILITY] = "reliability",
- [IPTOS_LOWCOST] = "low-cost",
-};
-
-DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
-
-static const char *const __signal_table[] = {
- [SIGHUP] = "HUP",
- [SIGINT] = "INT",
- [SIGQUIT] = "QUIT",
- [SIGILL] = "ILL",
- [SIGTRAP] = "TRAP",
- [SIGABRT] = "ABRT",
- [SIGBUS] = "BUS",
- [SIGFPE] = "FPE",
- [SIGKILL] = "KILL",
- [SIGUSR1] = "USR1",
- [SIGSEGV] = "SEGV",
- [SIGUSR2] = "USR2",
- [SIGPIPE] = "PIPE",
- [SIGALRM] = "ALRM",
- [SIGTERM] = "TERM",
-#ifdef SIGSTKFLT
- [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
-#endif
- [SIGCHLD] = "CHLD",
- [SIGCONT] = "CONT",
- [SIGSTOP] = "STOP",
- [SIGTSTP] = "TSTP",
- [SIGTTIN] = "TTIN",
- [SIGTTOU] = "TTOU",
- [SIGURG] = "URG",
- [SIGXCPU] = "XCPU",
- [SIGXFSZ] = "XFSZ",
- [SIGVTALRM] = "VTALRM",
- [SIGPROF] = "PROF",
- [SIGWINCH] = "WINCH",
- [SIGIO] = "IO",
- [SIGPWR] = "PWR",
- [SIGSYS] = "SYS"
-};
-
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
-
-const char *signal_to_string(int signo) {
- static __thread char buf[12];
- const char *name;
-
- name = __signal_to_string(signo);
- if (name)
- return name;
-
- if (signo >= SIGRTMIN && signo <= SIGRTMAX)
- snprintf(buf, sizeof(buf) - 1, "RTMIN+%d", signo - SIGRTMIN);
- else
- snprintf(buf, sizeof(buf) - 1, "%d", signo);
- char_array_0(buf);
- return buf;
-}
-
-int signal_from_string(const char *s) {
- int signo;
- int offset = 0;
- unsigned u;
-
- signo = __signal_from_string(s);
- if (signo > 0)
- return signo;
-
- if (startswith(s, "RTMIN+")) {
- s += 6;
- offset = SIGRTMIN;
- }
- if (safe_atou(s, &u) >= 0) {
- signo = (int) u + offset;
- if (signo > 0 && signo < _NSIG)
- return signo;
- }
- return -1;
-}
-
-bool kexec_loaded(void) {
- bool loaded = false;
- char *s;
-
- if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
- if (s[0] == '1')
- loaded = true;
- free(s);
- }
- return loaded;
-}
-
-int strdup_or_null(const char *a, char **b) {
- char *c;
-
- assert(b);
-
- if (!a) {
- *b = NULL;
- return 0;
- }
-
- c = strdup(a);
- if (!c)
- return -ENOMEM;
-
- *b = c;
- return 0;
-}
-
-int prot_from_flags(int flags) {
-
- switch (flags & O_ACCMODE) {
-
- case O_RDONLY:
- return PROT_READ;
-
- case O_WRONLY:
- return PROT_WRITE;
-
- case O_RDWR:
- return PROT_READ|PROT_WRITE;
-
- default:
- return -EINVAL;
- }
-}
-
-char *format_bytes(char *buf, size_t l, off_t t) {
- unsigned i;
-
- static const struct {
- const char *suffix;
- off_t factor;
- } table[] = {
- { "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 },
- };
-
- for (i = 0; i < ELEMENTSOF(table); i++) {
-
- if (t >= table[i].factor) {
- snprintf(buf, l,
- "%llu.%llu%s",
- (unsigned long long) (t / table[i].factor),
- (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
- table[i].suffix);
-
- goto finish;
- }
- }
-
- snprintf(buf, l, "%lluB", (unsigned long long) 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 fd_inc_sndbuf(int fd, size_t n) {
- int r, value;
- socklen_t l = sizeof(value);
-
- r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
- if (r >= 0 &&
- l == sizeof(value) &&
- (size_t) value >= n*2)
- return 0;
-
- value = (int) n;
- r = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value));
- if (r < 0)
- return -errno;
-
- return 1;
-}
-
-int fd_inc_rcvbuf(int fd, size_t n) {
- int r, value;
- socklen_t l = sizeof(value);
-
- r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
- if (r >= 0 &&
- l == sizeof(value) &&
- (size_t) value >= n*2)
- return 0;
-
- value = (int) n;
- r = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value));
- if (r < 0)
- return -errno;
-
- return 1;
-}
-
-int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
- pid_t parent_pid, agent_pid;
- int fd;
- bool stdout_is_tty, stderr_is_tty;
- unsigned n, i;
- va_list ap;
- char **l;
-
- assert(pid);
- assert(path);
-
- parent_pid = getpid();
-
- /* Spawns a temporary TTY agent, making sure it goes away when
- * we go away */
-
- agent_pid = fork();
- if (agent_pid < 0)
- return -errno;
-
- if (agent_pid != 0) {
- *pid = agent_pid;
- return 0;
- }
-
- /* In the child:
- *
- * Make sure the agent goes away when the parent dies */
- if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
- _exit(EXIT_FAILURE);
-
- /* Check whether our parent died before we were able
- * to set the death signal */
- if (getppid() != parent_pid)
- _exit(EXIT_SUCCESS);
-
- /* Don't leak fds to the agent */
- close_all_fds(except, n_except);
-
- stdout_is_tty = isatty(STDOUT_FILENO);
- stderr_is_tty = isatty(STDERR_FILENO);
-
- if (!stdout_is_tty || !stderr_is_tty) {
- /* Detach from stdout/stderr. and reopen
- * /dev/tty for them. This is important to
- * ensure that when systemctl is started via
- * popen() or a similar call that expects to
- * read EOF we actually do generate EOF and
- * not delay this indefinitely by because we
- * keep an unused copy of stdin around. */
- fd = open("/dev/tty", O_WRONLY);
- if (fd < 0) {
- log_error("Failed to open /dev/tty: %m");
- _exit(EXIT_FAILURE);
- }
-
- if (!stdout_is_tty)
- dup2(fd, STDOUT_FILENO);
-
- if (!stderr_is_tty)
- dup2(fd, STDERR_FILENO);
-
- if (fd > 2)
- close(fd);
- }
-
- /* Count arguments */
- va_start(ap, path);
- for (n = 0; va_arg(ap, char*); n++)
- ;
- va_end(ap);
-
- /* Allocate strv */
- l = alloca(sizeof(char *) * (n + 1));
-
- /* Fill in arguments */
- va_start(ap, path);
- for (i = 0; i <= n; i++)
- l[i] = va_arg(ap, char*);
- va_end(ap);
-
- execv(path, l);
- _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;
-}
-
-int getenv_for_pid(pid_t pid, const char *field, char **_value) {
- char path[sizeof("/proc/")-1+10+sizeof("/environ")], *value = NULL;
- int r;
- FILE *f;
- bool done = false;
- size_t l;
-
- assert(field);
- assert(_value);
-
- if (pid == 0)
- pid = getpid();
-
- snprintf(path, sizeof(path), "/proc/%lu/environ", (unsigned long) pid);
- char_array_0(path);
-
- f = fopen(path, "re");
- if (!f)
- return -errno;
-
- l = strlen(field);
- r = 0;
-
- do {
- char line[LINE_MAX];
- unsigned i;
-
- for (i = 0; i < sizeof(line)-1; i++) {
- int c;
-
- c = getc(f);
- if (_unlikely_(c == EOF)) {
- done = true;
- break;
- } else if (c == 0)
- break;
-
- line[i] = c;
- }
- line[i] = 0;
-
- if (memcmp(line, field, l) == 0 && line[l] == '=') {
- value = strdup(line + l + 1);
- if (!value) {
- r = -ENOMEM;
- break;
- }
-
- r = 1;
- break;
- }
-
- } while (!done);
-
- fclose(f);
-
- if (r >= 0)
- *_value = value;
-
- return r;
-}
-
-int can_sleep(const char *type) {
- char *w, *state;
- size_t l, k;
- int r;
- _cleanup_free_ char *p = NULL;
-
- assert(type);
-
- r = read_one_line_file("/sys/power/state", &p);
- if (r < 0)
- return r == -ENOENT ? 0 : r;
-
- k = strlen(type);
- FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state)
- if (l == k && memcmp(w, type, l) == 0)
- return true;
-
- return false;
-}
-
-int can_sleep_disk(const char *type) {
- char *w, *state;
- size_t l, k;
- int r;
- _cleanup_free_ char *p = NULL;
-
- assert(type);
-
- r = read_one_line_file("/sys/power/disk", &p);
- if (r < 0)
- return r == -ENOENT ? 0 : r;
-
- k = strlen(type);
- FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state) {
- if (l == k && memcmp(w, type, l) == 0)
- return true;
-
- if (l == k + 2 && w[0] == '[' && memcmp(w + 1, type, l - 2) == 0 && w[l-1] == ']')
- return true;
- }
-
- return false;
-}
-
-bool is_valid_documentation_url(const char *url) {
- assert(url);
-
- if (startswith(url, "http://") && url[7])
- return true;
-
- if (startswith(url, "https://") && url[8])
- return true;
-
- if (startswith(url, "file:") && url[5])
- return true;
-
- if (startswith(url, "info:") && url[5])
- return true;
-
- if (startswith(url, "man:") && url[4])
- return true;
-
- return false;
-}
-
-bool in_initrd(void) {
- static __thread int saved = -1;
- struct statfs s;
-
- if (saved >= 0)
- return saved;
-
- /* We make two checks here:
- *
- * 1. the flag file /etc/initrd-release must exist
- * 2. the root file system must be a memory file system
- *
- * The second check is extra paranoia, since misdetecting an
- * initrd can have bad bad consequences due the initrd
- * emptying when transititioning to the main systemd.
- */
-
- saved = access("/etc/initrd-release", F_OK) >= 0 &&
- statfs("/", &s) >= 0 &&
- (s.f_type == TMPFS_MAGIC || s.f_type == RAMFS_MAGIC);
-
- return saved;
-}
-
-void warn_melody(void) {
- _cleanup_close_ int fd = -1;
-
- fd = open("/dev/console", O_WRONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0)
- return;
-
- /* Yeah, this is synchronous. Kinda sucks. But well... */
-
- ioctl(fd, KIOCSOUND, (int)(1193180/440));
- usleep(125*USEC_PER_MSEC);
-
- ioctl(fd, KIOCSOUND, (int)(1193180/220));
- usleep(125*USEC_PER_MSEC);
-
- ioctl(fd, KIOCSOUND, (int)(1193180/220));
- usleep(125*USEC_PER_MSEC);
-
- ioctl(fd, KIOCSOUND, 0);
-}
-
-int make_console_stdio(void) {
- int fd, r;
-
- /* Make /dev/console the controlling terminal and stdin/stdout/stderr */
-
- fd = acquire_terminal("/dev/console", false, true, true, (usec_t) -1);
- if (fd < 0) {
- log_error("Failed to acquire terminal: %s", strerror(-fd));
- return fd;
- }
-
- r = make_stdio(fd);
- if (r < 0) {
- log_error("Failed to duplicate terminal fd: %s", strerror(-r));
- return r;
- }
-
- return 0;
-}
-
-int get_home_dir(char **_h) {
- char *h;
- const char *e;
- uid_t u;
- struct passwd *p;
-
- assert(_h);
-
- /* Take the user specified one */
- e = getenv("HOME");
- if (e) {
- h = strdup(e);
- if (!h)
- return -ENOMEM;
-
- *_h = h;
- return 0;
- }
-
- /* Hardcode home directory for root to avoid NSS */
- u = getuid();
- if (u == 0) {
- h = strdup("/root");
- if (!h)
- return -ENOMEM;
-
- *_h = h;
- return 0;
- }
-
- /* Check the database... */
- errno = 0;
- p = getpwuid(u);
- if (!p)
- return errno ? -errno : -ESRCH;
-
- if (!path_is_absolute(p->pw_dir))
- return -EINVAL;
-
- h = strdup(p->pw_dir);
- if (!h)
- return -ENOMEM;
-
- *_h = h;
- return 0;
-}
-
-int get_shell(char **_sh) {
- char *sh;
- const char *e;
- uid_t u;
- struct passwd *p;
-
- assert(_sh);
-
- /* Take the user specified one */
- e = getenv("SHELL");
- if (e) {
- sh = strdup(e);
- if (!sh)
- return -ENOMEM;
-
- *_sh = sh;
- return 0;
- }
-
- /* Hardcode home directory for root to avoid NSS */
- u = getuid();
- if (u == 0) {
- sh = strdup("/bin/sh");
- if (!sh)
- return -ENOMEM;
-
- *_sh = sh;
- return 0;
- }
-
- /* Check the database... */
- errno = 0;
- p = getpwuid(u);
- if (!p)
- return errno ? -errno : -ESRCH;
-
- if (!path_is_absolute(p->pw_shell))
- return -EINVAL;
-
- sh = strdup(p->pw_shell);
- if (!sh)
- return -ENOMEM;
-
- *_sh = sh;
- return 0;
-}
-
-void freep(void *p) {
- free(*(void**) p);
-}
-
-void fclosep(FILE **f) {
- if (*f)
- fclose(*f);
-}
-
-void closep(int *fd) {
- if (*fd >= 0)
- close_nointr_nofail(*fd);
-}
-
-void closedirp(DIR **d) {
- if (*d)
- closedir(*d);
-}
-
-void umaskp(mode_t *u) {
- umask(*u);
-}
-
-bool filename_is_safe(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;
-
- assert(p);
-
- for (t = p; *t; t++) {
- if (*t > 0 && *t < ' ')
- return false;
-
- if (strchr("\\\"\'", *t))
- return false;
- }
-
- return true;
-}
-
-int parse_timestamp(const char *t, usec_t *usec) {
- const char *k;
- struct tm tm, copy;
- time_t x;
- usec_t plus = 0, minus = 0, ret;
- int r;
-
- /*
- * Allowed syntaxes:
- *
- * 2012-09-22 16:34:22
- * 2012-09-22 16:34 (seconds will be set to 0)
- * 2012-09-22 (time will be set to 00:00:00)
- * 16:34:22 (date will be set to today)
- * 16:34 (date will be set to today, seconds to 0)
- * now
- * yesterday (time is set to 00:00:00)
- * today (time is set to 00:00:00)
- * tomorrow (time is set to 00:00:00)
- * +5min
- * -5days
- *
- */
-
- assert(t);
- assert(usec);
-
- x = time(NULL);
- assert_se(localtime_r(&x, &tm));
-
- if (streq(t, "now"))
- goto finish;
-
- else if (streq(t, "today")) {
- tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto finish;
-
- } else if (streq(t, "yesterday")) {
- tm.tm_mday --;
- tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto finish;
-
- } else if (streq(t, "tomorrow")) {
- tm.tm_mday ++;
- tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto finish;
-
- } else if (t[0] == '+') {
-
- r = parse_usec(t+1, &plus);
- if (r < 0)
- return r;
-
- goto finish;
- } else if (t[0] == '-') {
-
- r = parse_usec(t+1, &minus);
- if (r < 0)
- return r;
-
- goto finish;
- }
-
- copy = tm;
- k = strptime(t, "%y-%m-%d %H:%M:%S", &tm);
- if (k && *k == 0)
- goto finish;
-
- tm = copy;
- k = strptime(t, "%Y-%m-%d %H:%M:%S", &tm);
- if (k && *k == 0)
- goto finish;
-
- tm = copy;
- k = strptime(t, "%y-%m-%d %H:%M", &tm);
- if (k && *k == 0) {
- tm.tm_sec = 0;
- goto finish;
- }
-
- tm = copy;
- k = strptime(t, "%Y-%m-%d %H:%M", &tm);
- if (k && *k == 0) {
- tm.tm_sec = 0;
- goto finish;
- }
-
- tm = copy;
- k = strptime(t, "%y-%m-%d", &tm);
- if (k && *k == 0) {
- tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto finish;
- }
-
- tm = copy;
- k = strptime(t, "%Y-%m-%d", &tm);
- if (k && *k == 0) {
- tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto finish;
- }
-
- tm = copy;
- k = strptime(t, "%H:%M:%S", &tm);
- if (k && *k == 0)
- goto finish;
-
- tm = copy;
- k = strptime(t, "%H:%M", &tm);
- if (k && *k == 0) {
- tm.tm_sec = 0;
- goto finish;
- }
-
- return -EINVAL;
-
-finish:
- x = mktime(&tm);
- if (x == (time_t) -1)
- return -EINVAL;
-
- ret = (usec_t) x * USEC_PER_SEC;
-
- ret += plus;
- if (ret > minus)
- ret -= minus;
- else
- ret = 0;
-
- *usec = ret;
-
- return 0;
-}
-
-/* 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) {
- size_t l, u, idx;
- const void *p;
- int comparison;
-
- l = 0;
- u = nmemb;
- while (l < u) {
- idx = (l + u) / 2;
- p = (void *)(((const char *) base) + (idx * size));
- comparison = compar(key, p, arg);
- if (comparison < 0)
- u = idx;
- else if (comparison > 0)
- l = idx + 1;
- else
- return (void *)p;
- }
- return NULL;
-}
-
-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;
- }
-
- cached_answer = streq(set, "UTF-8");
-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_VERT] = "\342\224\202 ", /* │ */
- [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */
- [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */
- [DRAW_TRIANGULAR_BULLET] = "\342\200\243 ", /* ‣ */
- },
- /* ASCII fallback */ {
- [DRAW_TREE_VERT] = "| ",
- [DRAW_TREE_BRANCH] = "|-",
- [DRAW_TREE_RIGHT] = "`-",
- [DRAW_TRIANGULAR_BULLET] = "> ",
- }
- };
-
- return draw_table[!is_locale_utf8()][ch];
-}
-
-char *strreplace(const char *text, const char *old_string, const char *new_string) {
- const char *f;
- char *t, *r;
- size_t l, old_len, new_len;
-
- assert(text);
- assert(old_string);
- assert(new_string);
-
- old_len = strlen(old_string);
- new_len = strlen(new_string);
-
- l = strlen(text);
- r = new(char, l+1);
- if (!r)
- return NULL;
-
- f = text;
- t = r;
- while (*f) {
- char *a;
- size_t d, nl;
-
- if (!startswith(f, old_string)) {
- *(t++) = *(f++);
- continue;
- }
-
- d = t - r;
- nl = l - old_len + new_len;
- a = realloc(r, nl + 1);
- if (!a)
- goto oom;
-
- l = nl;
- r = a;
- t = r + d;
-
- t = stpcpy(t, new_string);
- f += old_len;
- }
-
- *t = 0;
- return r;
-
-oom:
- free(r);
- return NULL;
-}
diff --git a/src/shared/util.h b/src/shared/util.h
deleted file mode 100644
index a148ebbc58..0000000000
--- a/src/shared/util.h
+++ /dev/null
@@ -1,615 +0,0 @@
-/*-*- 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 <time.h>
-#include <sys/time.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <signal.h>
-#include <sched.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#include <sys/resource.h>
-#include <stddef.h>
-
-#include "macro.h"
-
-typedef uint64_t usec_t;
-typedef uint64_t nsec_t;
-
-typedef struct dual_timestamp {
- usec_t realtime;
- usec_t monotonic;
-} dual_timestamp;
-
-union dirent_storage {
- struct dirent de;
- uint8_t storage[offsetof(struct dirent, d_name) +
- ((NAME_MAX + 1 + sizeof(long)) & ~(sizeof(long) - 1))];
-};
-
-#define MSEC_PER_SEC 1000ULL
-#define USEC_PER_SEC 1000000ULL
-#define USEC_PER_MSEC 1000ULL
-#define NSEC_PER_SEC 1000000000ULL
-#define NSEC_PER_MSEC 1000000ULL
-#define NSEC_PER_USEC 1000ULL
-
-#define USEC_PER_MINUTE (60ULL*USEC_PER_SEC)
-#define NSEC_PER_MINUTE (60ULL*NSEC_PER_SEC)
-#define USEC_PER_HOUR (60ULL*USEC_PER_MINUTE)
-#define NSEC_PER_HOUR (60ULL*NSEC_PER_MINUTE)
-#define USEC_PER_DAY (24ULL*USEC_PER_HOUR)
-#define NSEC_PER_DAY (24ULL*NSEC_PER_HOUR)
-#define USEC_PER_WEEK (7ULL*USEC_PER_DAY)
-#define NSEC_PER_WEEK (7ULL*NSEC_PER_DAY)
-#define USEC_PER_MONTH (2629800ULL*USEC_PER_SEC)
-#define NSEC_PER_MONTH (2629800ULL*NSEC_PER_SEC)
-#define USEC_PER_YEAR (31557600ULL*USEC_PER_SEC)
-#define NSEC_PER_YEAR (31557600ULL*NSEC_PER_SEC)
-
-/* What is interpreted as whitespace? */
-#define WHITESPACE " \t\n\r"
-#define NEWLINE "\n\r"
-#define QUOTES "\"\'"
-#define COMMENTS "#;\n"
-
-#define FORMAT_TIMESTAMP_MAX (5+11+9+4+1)
-#define FORMAT_TIMESTAMP_PRETTY_MAX 256
-#define FORMAT_TIMESPAN_MAX 64
-#define FORMAT_BYTES_MAX 8
-
-#define ANSI_HIGHLIGHT_ON "\x1B[1;39m"
-#define ANSI_HIGHLIGHT_RED_ON "\x1B[1;31m"
-#define ANSI_HIGHLIGHT_GREEN_ON "\x1B[1;32m"
-#define ANSI_HIGHLIGHT_YELLOW_ON "\x1B[1;33m"
-#define ANSI_HIGHLIGHT_OFF "\x1B[0m"
-
-bool is_efiboot(void);
-
-usec_t now(clockid_t clock);
-
-dual_timestamp* dual_timestamp_get(dual_timestamp *ts);
-dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u);
-
-#define dual_timestamp_is_set(ts) ((ts)->realtime > 0)
-
-usec_t timespec_load(const struct timespec *ts);
-struct timespec *timespec_store(struct timespec *ts, usec_t u);
-
-usec_t timeval_load(const struct timeval *tv);
-struct timeval *timeval_store(struct timeval *tv, usec_t u);
-
-size_t page_size(void);
-#define PAGE_ALIGN(l) ALIGN_TO((l), page_size())
-
-#define streq(a,b) (strcmp((a),(b)) == 0)
-#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
-
-bool streq_ptr(const char *a, const char *b);
-
-#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 newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n)))
-
-#define malloc0(n) (calloc((n), 1))
-
-static inline const char* yes_no(bool b) {
- return b ? "yes" : "no";
-}
-
-static inline const char* strempty(const char *s) {
- return s ? s : "";
-}
-
-static inline const char* strnull(const char *s) {
- return s ? s : "(null)";
-}
-
-static inline const char *strna(const char *s) {
- return s ? s : "n/a";
-}
-
-static inline bool isempty(const char *p) {
- return !p || !p[0];
-}
-
-char *endswith(const char *s, const char *postfix);
-char *startswith(const char *s, const char *prefix);
-char *startswith_no_case(const char *s, const char *prefix);
-
-bool first_word(const char *s, const char *word);
-
-int close_nointr(int fd);
-void close_nointr_nofail(int fd);
-void close_many(const int fds[], unsigned n_fd);
-
-int parse_boolean(const char *v);
-int parse_usec(const char *t, usec_t *usec);
-int parse_nsec(const char *t, nsec_t *nsec);
-int parse_bytes(const char *t, off_t *bytes);
-int parse_pid(const char *s, pid_t* ret_pid);
-int parse_uid(const char *s, uid_t* ret_uid);
-#define parse_gid(s, ret_uid) parse_uid(s, ret_uid)
-
-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);
-
-#if __WORDSIZE == 32
-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);
-}
-
-char *split(const char *c, size_t *l, const char *separator, char **state);
-char *split_quoted(const char *c, size_t *l, char **state);
-
-#define FOREACH_WORD(word, length, s, state) \
- for ((state) = NULL, (word) = split((s), &(length), WHITESPACE, &(state)); (word); (word) = split((s), &(length), WHITESPACE, &(state)))
-
-#define FOREACH_WORD_SEPARATOR(word, length, s, separator, state) \
- for ((state) = NULL, (word) = split((s), &(length), (separator), &(state)); (word); (word) = split((s), &(length), (separator), &(state)))
-
-#define FOREACH_WORD_QUOTED(word, length, s, state) \
- for ((state) = NULL, (word) = split_quoted((s), &(length), &(state)); (word); (word) = split_quoted((s), &(length), &(state)))
-
-pid_t get_parent_of_pid(pid_t pid, pid_t *ppid);
-int get_starttime_of_pid(pid_t pid, unsigned long long *st);
-
-int write_one_line_file(const char *fn, const char *line);
-int write_one_line_file_atomic(const char *fn, const char *line);
-int read_one_line_file(const char *fn, char **line);
-int read_full_file(const char *fn, char **contents, size_t *size);
-
-int parse_env_file(const char *fname, const char *separator, ...) _sentinel_;
-int load_env_file(const char *fname, char ***l);
-int write_env_file(const char *fname, char **l);
-
-char *strappend(const char *s, const char *suffix);
-char *strnappend(const char *s, const char *suffix, size_t length);
-
-char *replace_env(const char *format, char **env);
-char **replace_env_argv(char **argv, char **env);
-
-int readlink_malloc(const char *p, char **r);
-int readlink_and_make_absolute(const char *p, char **r);
-int readlink_and_canonicalize(const char *p, char **r);
-
-int reset_all_signal_handlers(void);
-
-char *strstrip(char *s);
-char *delete_chars(char *s, const char *bad);
-char *truncate_nl(char *s);
-
-char *file_in_same_dir(const char *path, const char *filename);
-
-int rmdir_parents(const char *path, const char *stop);
-
-int get_process_comm(pid_t pid, char **name);
-int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line);
-int get_process_exe(pid_t pid, char **name);
-int get_process_uid(pid_t pid, uid_t *uid);
-int get_process_gid(pid_t pid, gid_t *gid);
-
-char hexchar(int x);
-int unhexchar(char c);
-char octchar(int x);
-int unoctchar(char c);
-char decchar(int x);
-int undecchar(char c);
-
-char *cescape(const char *s);
-char *cunescape(const char *s);
-char *cunescape_length(const char *s, size_t length);
-char *cunescape_length_with_prefix(const char *s, size_t length, const char *prefix);
-
-char *xescape(const char *s, const char *bad);
-
-char *bus_path_escape(const char *s);
-char *bus_path_unescape(const char *s);
-
-char *ascii_strlower(char *path);
-
-bool dirent_is_file(const struct dirent *de);
-bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix);
-
-bool ignore_file(const char *filename);
-
-bool chars_intersect(const char *a, const char *b);
-
-char *format_timestamp(char *buf, size_t l, usec_t t);
-char *format_timestamp_pretty(char *buf, size_t l, usec_t t);
-char *format_timespan(char *buf, size_t l, usec_t t);
-
-int make_stdio(int fd);
-int make_null_stdio(void);
-int make_console_stdio(void);
-
-unsigned long long random_ull(void);
-
-/* For basic lookup tables with strictly enumerated entries */
-#define __DEFINE_STRING_TABLE_LOOKUP(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]; \
- } \
- scope type name##_from_string(const char *s) { \
- type i; \
- assert(s); \
- for (i = 0; i < (type)ELEMENTSOF(name##_table); i++) \
- if (name##_table[i] && \
- streq(name##_table[i], s)) \
- return i; \
- return (type) -1; \
- } \
- 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)
-
-/* 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; \
- int r; \
- if (i < 0 || i > max) \
- return -ERANGE; \
- if (i < (type) ELEMENTSOF(name##_table)) { \
- s = strdup(name##_table[i]); \
- if (!s) \
- return log_oom(); \
- } else { \
- r = asprintf(&s, "%u", i); \
- if (r < 0) \
- return log_oom(); \
- } \
- *str = s; \
- return 0; \
- } \
- type name##_from_string(const char *s) { \
- type i; \
- unsigned u = 0; \
- assert(s); \
- for (i = 0; i < (type)ELEMENTSOF(name##_table); i++) \
- if (name##_table[i] && \
- streq(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__
-
-int fd_nonblock(int fd, bool nonblock);
-int fd_cloexec(int fd, bool cloexec);
-
-int close_all_fds(const int except[], unsigned n_except);
-
-bool fstype_is_network(const char *fstype);
-
-int chvt(int vt);
-
-int read_one_char(FILE *f, char *ret, usec_t timeout, bool *need_nl);
-int ask(char *ret, const char *replies, const char *text, ...);
-
-int reset_terminal_fd(int fd, bool switch_to_text);
-int reset_terminal(const char *name);
-
-int open_terminal(const char *name, int mode);
-int acquire_terminal(const char *name, bool fail, bool force, bool ignore_tiocstty_eperm, usec_t timeout);
-int release_terminal(void);
-
-int flush_fd(int fd);
-
-int ignore_signals(int sig, ...);
-int default_signals(int sig, ...);
-int sigaction_many(const struct sigaction *sa, ...);
-
-int close_pipe(int p[]);
-int fopen_temporary(const char *path, FILE **_f, char **_temp_path);
-
-ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll);
-ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll);
-
-bool is_device_path(const char *path);
-
-int dir_is_empty(const char *path);
-
-void rename_process(const char name[8]);
-
-void sigset_add_many(sigset_t *ss, ...);
-
-bool hostname_is_set(void);
-
-char* gethostname_malloc(void);
-char* getlogname_malloc(void);
-char* getusername_malloc(void);
-
-int getttyname_malloc(int fd, char **r);
-int getttyname_harder(int fd, char **r);
-
-int get_ctty_devnr(pid_t pid, dev_t *d);
-int get_ctty(pid_t, dev_t *_devnr, 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 rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev);
-int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev);
-int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky);
-int rm_rf_dangerous(const char *path, bool only_dirs, bool delete_root, bool honour_sticky);
-
-int pipe_eof(int fd);
-
-cpu_set_t* cpu_set_malloc(unsigned *ncpus);
-
-int status_vprintf(const char *status, bool ellipse, const char *format, va_list ap);
-int status_printf(const char *status, bool ellipse, const char *format, ...);
-int status_welcome(void);
-
-int fd_columns(int fd);
-unsigned columns(void);
-int fd_lines(int fd);
-unsigned lines(void);
-void columns_lines_cache_reset(int _unused_ signum);
-
-bool on_tty(void);
-
-int running_in_chroot(void);
-
-char *ellipsize(const char *s, size_t length, unsigned percent);
-char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent);
-
-int touch(const char *path);
-
-char *unquote(const char *s, const char *quotes);
-char *normalize_env_assignment(const char *s);
-
-int wait_for_terminate(pid_t pid, siginfo_t *status);
-int wait_for_terminate_and_warn(const char *name, pid_t pid);
-
-_noreturn_ void freeze(void);
-
-bool null_or_empty(struct stat *st);
-int null_or_empty_path(const char *fn);
-
-DIR *xopendirat(int dirfd, const char *name, int flags);
-
-void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t);
-void dual_timestamp_deserialize(const char *value, dual_timestamp *t);
-
-char *fstab_node_to_udev_node(const char *p);
-
-bool tty_is_vc(const char *tty);
-bool tty_is_vc_resolve(const char *tty);
-bool tty_is_console(const char *tty);
-int vtnr_from_tty(const char *tty);
-const char *default_term_for_tty(const char *tty);
-
-void execute_directory(const char *directory, DIR *_d, char *argv[]);
-
-int kill_and_sigcont(pid_t pid, int sig);
-
-bool nulstr_contains(const char*nulstr, const char *needle);
-
-bool plymouth_running(void);
-
-bool hostname_is_valid(const char *s);
-char* hostname_cleanup(char *s);
-
-char* strshorten(char *s, size_t l);
-
-int terminal_vhangup_fd(int fd);
-int terminal_vhangup(const char *name);
-
-int vt_disallocate(const char *name);
-
-int copy_file(const char *from, const char *to);
-
-int symlink_atomic(const char *from, const char *to);
-
-int fchmod_umask(int fd, mode_t mode);
-
-bool display_is_local(const char *display);
-int socket_from_display(const char *display, char **path);
-
-int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **home, const char **shell);
-int get_group_creds(const char **groupname, gid_t *gid);
-
-int in_group(const char *name);
-
-int glob_exists(const char *path);
-
-int dirent_ensure_type(DIR *d, struct dirent *de);
-
-int in_search_path(const char *path, char **search);
-int get_files_in_directory(const char *path, char ***list);
-
-char *strjoin(const char *x, ...) _sentinel_;
-
-bool is_main_thread(void);
-
-bool in_charset(const char *s, const char* charset);
-
-int block_get_whole_disk(dev_t d, dev_t *ret);
-
-int file_is_priv_sticky(const char *p);
-
-int strdup_or_null(const char *a, char **b);
-
-#define NULSTR_FOREACH(i, l) \
- for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
-
-#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);
-int sigchld_code_from_string(const char *s);
-
-int log_facility_unshifted_to_string_alloc(int i, char **s);
-int log_facility_unshifted_from_string(const char *s);
-
-int log_level_to_string_alloc(int i, char **s);
-int log_level_from_string(const char *s);
-
-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);
-int rlimit_from_string(const char *s);
-
-int ip_tos_to_string_alloc(int i, char **s);
-int ip_tos_from_string(const char *s);
-
-const char *signal_to_string(int i);
-int signal_from_string(const char *s);
-
-int signal_from_string_try_harder(const char *s);
-
-extern int saved_argc;
-extern char **saved_argv;
-
-bool kexec_loaded(void);
-
-int prot_from_flags(int flags);
-
-char *format_bytes(char *buf, size_t l, off_t t);
-
-int fd_wait_for_event(int fd, int event, usec_t timeout);
-
-void* memdup(const void *p, size_t l) _malloc_;
-
-int is_kernel_thread(pid_t pid);
-
-int fd_inc_sndbuf(int fd, size_t n);
-int fd_inc_rcvbuf(int fd, size_t n);
-
-int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...);
-
-int setrlimit_closest(int resource, const struct rlimit *rlim);
-
-int getenv_for_pid(pid_t pid, const char *field, char **_value);
-
-int can_sleep(const char *type);
-int can_sleep_disk(const char *type);
-
-bool is_valid_documentation_url(const char *url);
-
-bool in_initrd(void);
-
-void warn_melody(void);
-
-int get_shell(char **ret);
-int get_home_dir(char **ret);
-
-void freep(void *p);
-void fclosep(FILE **f);
-void closep(int *fd);
-void closedirp(DIR **d);
-void umaskp(mode_t *u);
-
-_malloc_ 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);
-}
-
-_malloc_ 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_safe(const char *p);
-bool string_is_safe(const char *p);
-
-int parse_timestamp(const char *t, usec_t *usec);
-
-void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
- int (*compar) (const void *, const void *, void *),
- void *arg);
-
-bool is_locale_utf8(void);
-
-typedef enum DrawSpecialChar {
- DRAW_TREE_VERT,
- DRAW_TREE_BRANCH,
- DRAW_TREE_RIGHT,
- DRAW_TRIANGULAR_BULLET,
- _DRAW_SPECIAL_CHAR_MAX
-} DrawSpecialChar;
-const char *draw_special_char(DrawSpecialChar ch);
-
-char *strreplace(const char *text, const char *old_string, const char *new_string);
diff --git a/src/shared/utmp-wtmp.c b/src/shared/utmp-wtmp.c
deleted file mode 100644
index 046fb584fb..0000000000
--- a/src/shared/utmp-wtmp.c
+++ /dev/null
@@ -1,431 +0,0 @@
-/*-*- 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 <utmpx.h>
-#include <errno.h>
-#include <assert.h>
-#include <string.h>
-#include <sys/utsname.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/poll.h>
-
-#include "macro.h"
-#include "path-util.h"
-#include "utmp-wtmp.h"
-
-int utmp_get_runlevel(int *runlevel, int *previous) {
- struct utmpx lookup, *found;
- int r;
- const char *e;
-
- assert(runlevel);
-
- /* If these values are set in the environment this takes
- * precedence. Presumably, sysvinit does this to work around a
- * race condition that would otherwise exist where we'd always
- * go to disk and hence might read runlevel data that might be
- * very new and does not apply to the current script being
- * executed. */
-
- if ((e = getenv("RUNLEVEL")) && e[0] > 0) {
- *runlevel = e[0];
-
- if (previous) {
- /* $PREVLEVEL seems to be an Upstart thing */
-
- if ((e = getenv("PREVLEVEL")) && e[0] > 0)
- *previous = e[0];
- else
- *previous = 0;
- }
-
- return 0;
- }
-
- if (utmpxname(_PATH_UTMPX) < 0)
- return -errno;
-
- setutxent();
-
- zero(lookup);
- lookup.ut_type = RUN_LVL;
-
- if (!(found = getutxid(&lookup)))
- r = -errno;
- else {
- int a, b;
-
- a = found->ut_pid & 0xFF;
- b = (found->ut_pid >> 8) & 0xFF;
-
- if (a < 0 || b < 0)
- r = -EIO;
- else {
- *runlevel = a;
-
- if (previous)
- *previous = b;
- r = 0;
- }
- }
-
- endutxent();
-
- return r;
-}
-
-static void init_timestamp(struct utmpx *store, usec_t t) {
- assert(store);
-
- zero(*store);
-
- if (t <= 0)
- t = now(CLOCK_REALTIME);
-
- store->ut_tv.tv_sec = t / USEC_PER_SEC;
- store->ut_tv.tv_usec = t % USEC_PER_SEC;
-}
-
-static void init_entry(struct utmpx *store, usec_t t) {
- struct utsname uts;
-
- assert(store);
-
- init_timestamp(store, t);
-
- zero(uts);
-
- if (uname(&uts) >= 0)
- strncpy(store->ut_host, uts.release, sizeof(store->ut_host));
-
- strncpy(store->ut_line, "~", sizeof(store->ut_line)); /* or ~~ ? */
- strncpy(store->ut_id, "~~", sizeof(store->ut_id));
-}
-
-static int write_entry_utmp(const struct utmpx *store) {
- int r;
-
- assert(store);
-
- /* utmp is similar to wtmp, but there is only one entry for
- * each entry type resp. user; i.e. basically a key/value
- * table. */
-
- if (utmpxname(_PATH_UTMPX) < 0)
- return -errno;
-
- setutxent();
-
- if (!pututxline(store))
- r = -errno;
- else
- r = 0;
-
- endutxent();
-
- return r;
-}
-
-static int write_entry_wtmp(const struct utmpx *store) {
- assert(store);
-
- /* wtmp is a simple append-only file where each entry is
- simply appended to * the end; i.e. basically a log. */
-
- errno = 0;
- updwtmpx(_PATH_WTMPX, store);
- return -errno;
-}
-
-static int write_utmp_wtmp(const struct utmpx *store_utmp, const struct utmpx *store_wtmp) {
- int r, s;
-
- r = write_entry_utmp(store_utmp);
- s = write_entry_wtmp(store_wtmp);
-
- if (r >= 0)
- r = s;
-
- /* If utmp/wtmp have been disabled, that's a good thing, hence
- * ignore the errors */
- if (r == -ENOENT)
- r = 0;
-
- return r;
-}
-
-static int write_entry_both(const struct utmpx *store) {
- return write_utmp_wtmp(store, store);
-}
-
-int utmp_put_shutdown(void) {
- struct utmpx store;
-
- init_entry(&store, 0);
-
- store.ut_type = RUN_LVL;
- strncpy(store.ut_user, "shutdown", sizeof(store.ut_user));
-
- return write_entry_both(&store);
-}
-
-int utmp_put_reboot(usec_t t) {
- struct utmpx store;
-
- init_entry(&store, t);
-
- store.ut_type = BOOT_TIME;
- strncpy(store.ut_user, "reboot", sizeof(store.ut_user));
-
- return write_entry_both(&store);
-}
-
-static const char *sanitize_id(const char *id) {
- size_t l;
-
- assert(id);
- l = strlen(id);
-
- if (l <= sizeof(((struct utmpx*) NULL)->ut_id))
- return id;
-
- return id + l - sizeof(((struct utmpx*) NULL)->ut_id);
-}
-
-int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line) {
- struct utmpx store;
-
- assert(id);
-
- init_timestamp(&store, 0);
-
- store.ut_type = INIT_PROCESS;
- store.ut_pid = pid;
- store.ut_session = sid;
-
- strncpy(store.ut_id, sanitize_id(id), sizeof(store.ut_id));
-
- if (line)
- strncpy(store.ut_line, path_get_file_name(line), sizeof(store.ut_line));
-
- return write_entry_both(&store);
-}
-
-int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) {
- struct utmpx lookup, store, store_wtmp, *found;
-
- assert(id);
-
- setutxent();
-
- zero(lookup);
- lookup.ut_type = INIT_PROCESS; /* looks for DEAD_PROCESS, LOGIN_PROCESS, USER_PROCESS, too */
- strncpy(lookup.ut_id, sanitize_id(id), sizeof(lookup.ut_id));
-
- if (!(found = getutxid(&lookup)))
- return 0;
-
- if (found->ut_pid != pid)
- return 0;
-
- memcpy(&store, found, sizeof(store));
- store.ut_type = DEAD_PROCESS;
- store.ut_exit.e_termination = code;
- store.ut_exit.e_exit = status;
-
- zero(store.ut_user);
- zero(store.ut_host);
- zero(store.ut_tv);
-
- memcpy(&store_wtmp, &store, sizeof(store_wtmp));
- /* wtmp wants the current time */
- init_timestamp(&store_wtmp, 0);
-
- return write_utmp_wtmp(&store, &store_wtmp);
-}
-
-
-int utmp_put_runlevel(int runlevel, int previous) {
- struct utmpx store;
- int r;
-
- assert(runlevel > 0);
-
- if (previous <= 0) {
- /* Find the old runlevel automatically */
-
- if ((r = utmp_get_runlevel(&previous, NULL)) < 0) {
- if (r != -ESRCH)
- return r;
-
- previous = 0;
- }
- }
-
- if (previous == runlevel)
- return 0;
-
- init_entry(&store, 0);
-
- store.ut_type = RUN_LVL;
- store.ut_pid = (runlevel & 0xFF) | ((previous & 0xFF) << 8);
- strncpy(store.ut_user, "runlevel", sizeof(store.ut_user));
-
- return write_entry_both(&store);
-}
-
-#define TIMEOUT_MSEC 50
-
-static int write_to_terminal(const char *tty, const char *message) {
- int fd, r;
- const char *p;
- size_t left;
- usec_t end;
-
- assert(tty);
- assert(message);
-
- if ((fd = open(tty, O_WRONLY|O_NDELAY|O_NOCTTY|O_CLOEXEC)) < 0)
- return -errno;
-
- if (!isatty(fd)) {
- r = -errno;
- goto finish;
- }
-
- p = message;
- left = strlen(message);
-
- end = now(CLOCK_MONOTONIC) + TIMEOUT_MSEC*USEC_PER_MSEC;
-
- while (left > 0) {
- ssize_t n;
- struct pollfd pollfd;
- usec_t t;
- int k;
-
- t = now(CLOCK_MONOTONIC);
-
- if (t >= end) {
- r = -ETIME;
- goto finish;
- }
-
- zero(pollfd);
- pollfd.fd = fd;
- pollfd.events = POLLOUT;
-
- if ((k = poll(&pollfd, 1, (end - t) / USEC_PER_MSEC)) < 0)
- return -errno;
-
- if (k <= 0) {
- r = -ETIME;
- goto finish;
- }
-
- if ((n = write(fd, p, left)) < 0) {
-
- if (errno == EAGAIN)
- continue;
-
- r = -errno;
- goto finish;
- }
-
- assert((size_t) n <= left);
-
- p += n;
- left -= n;
- }
-
- r = 0;
-
-finish:
- close_nointr_nofail(fd);
-
- return r;
-}
-
-int utmp_wall(const char *message, bool (*match_tty)(const char *tty)) {
- struct utmpx *u;
- char date[FORMAT_TIMESTAMP_MAX];
- char *text = NULL, *hn = NULL, *un = NULL, *tty = NULL;
- int r;
-
- if (!(hn = gethostname_malloc()) ||
- !(un = getlogname_malloc())) {
- r = -ENOMEM;
- goto finish;
- }
-
- getttyname_harder(STDIN_FILENO, &tty);
-
- if (asprintf(&text,
- "\a\r\n"
- "Broadcast message from %s@%s%s%s (%s):\r\n\r\n"
- "%s\r\n\r\n",
- un, hn,
- tty ? " on " : "", strempty(tty),
- format_timestamp(date, sizeof(date), now(CLOCK_REALTIME)),
- message) < 0) {
- r = -ENOMEM;
- goto finish;
- }
-
- setutxent();
-
- r = 0;
-
- while ((u = getutxent())) {
- int q;
- const char *path;
- char *buf = NULL;
-
- if (u->ut_type != USER_PROCESS || u->ut_user[0] == 0)
- continue;
-
- if (path_startswith(u->ut_line, "/dev/"))
- path = u->ut_line;
- else {
- if (asprintf(&buf, "/dev/%s", u->ut_line) < 0) {
- r = -ENOMEM;
- goto finish;
- }
-
- path = buf;
- }
-
- if (!match_tty || match_tty(path))
- if ((q = write_to_terminal(path, text)) < 0)
- r = q;
-
- free(buf);
- }
-
-finish:
- free(hn);
- free(un);
- free(tty);
- free(text);
-
- return r;
-}
diff --git a/src/shared/utmp-wtmp.h b/src/shared/utmp-wtmp.h
deleted file mode 100644
index 5924023203..0000000000
--- a/src/shared/utmp-wtmp.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*-*- 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 "util.h"
-
-int utmp_get_runlevel(int *runlevel, int *previous);
-
-int utmp_put_shutdown(void);
-int utmp_put_reboot(usec_t timestamp);
-int utmp_put_runlevel(int runlevel, int previous);
-
-int utmp_put_dead_process(const char *id, pid_t pid, int code, int status);
-int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line);
-
-int utmp_wall(const char *message, bool (*match_tty)(const char *tty));
diff --git a/src/shared/virt.c b/src/shared/virt.c
deleted file mode 100644
index fc62c72328..0000000000
--- a/src/shared/virt.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <errno.h>
-#include <unistd.h>
-
-#include "util.h"
-#include "virt.h"
-
-/* Returns a short identifier for the various VM implementations */
-int detect_vm(const char **id) {
-
-#if defined(__i386__) || defined(__x86_64__)
-
- /* Both CPUID and DMI are x86 specific interfaces... */
-
- static const char *const dmi_vendors[] = {
- "/sys/class/dmi/id/sys_vendor",
- "/sys/class/dmi/id/board_vendor",
- "/sys/class/dmi/id/bios_vendor"
- };
-
- static const char dmi_vendor_table[] =
- "QEMU\0" "qemu\0"
- /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
- "VMware\0" "vmware\0"
- "VMW\0" "vmware\0"
- "Microsoft Corporation\0" "microsoft\0"
- "innotek GmbH\0" "oracle\0"
- "Xen\0" "xen\0"
- "Bochs\0" "bochs\0";
-
- static const char cpuid_vendor_table[] =
- "XenVMMXenVMM\0" "xen\0"
- "KVMKVMKVM\0" "kvm\0"
- /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
- "VMwareVMware\0" "vmware\0"
- /* http://msdn.microsoft.com/en-us/library/ff542428.aspx */
- "Microsoft Hv\0" "microsoft\0";
-
- uint32_t eax, ecx;
- union {
- uint32_t sig32[3];
- char text[13];
- } sig;
- unsigned i;
- const char *j, *k;
- bool hypervisor;
-
- /* http://lwn.net/Articles/301888/ */
- zero(sig);
-
-#if defined (__i386__)
-#define REG_a "eax"
-#define REG_b "ebx"
-#elif defined (__amd64__)
-#define REG_a "rax"
-#define REG_b "rbx"
-#endif
-
- /* First detect whether there is a hypervisor */
- eax = 1;
- __asm__ __volatile__ (
- /* ebx/rbx is being used for PIC! */
- " push %%"REG_b" \n\t"
- " cpuid \n\t"
- " pop %%"REG_b" \n\t"
-
- : "=a" (eax), "=c" (ecx)
- : "0" (eax)
- );
-
- hypervisor = !!(ecx & 0x80000000U);
-
- if (hypervisor) {
-
- /* There is a hypervisor, see what it is */
- eax = 0x40000000U;
- __asm__ __volatile__ (
- /* ebx/rbx is being used for PIC! */
- " push %%"REG_b" \n\t"
- " cpuid \n\t"
- " mov %%ebx, %1 \n\t"
- " pop %%"REG_b" \n\t"
-
- : "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2])
- : "0" (eax)
- );
-
- NULSTR_FOREACH_PAIR(j, k, cpuid_vendor_table)
- if (streq(sig.text, j)) {
-
- if (id)
- *id = k;
-
- return 1;
- }
- }
-
- for (i = 0; i < ELEMENTSOF(dmi_vendors); i++) {
- char *s;
- int r;
- const char *found = NULL;
-
- if ((r = read_one_line_file(dmi_vendors[i], &s)) < 0) {
- if (r != -ENOENT)
- return r;
-
- continue;
- }
-
- NULSTR_FOREACH_PAIR(j, k, dmi_vendor_table)
- if (startswith(s, j))
- found = k;
- free(s);
-
- if (found) {
- if (id)
- *id = found;
-
- return 1;
- }
- }
-
- if (hypervisor) {
- if (id)
- *id = "other";
-
- return 1;
- }
-
-#endif
- return 0;
-}
-
-int detect_container(const char **id) {
- char *e = NULL;
- int r;
-
- /* Unfortunately many of these operations require root access
- * in one way or another */
-
- r = running_in_chroot();
- if (r < 0)
- return r;
- if (r > 0) {
-
- if (id)
- *id = "chroot";
-
- return 1;
- }
-
- /* /proc/vz exists in container and outside of the container,
- * /proc/bc only outside of the container. */
- if (access("/proc/vz", F_OK) >= 0 &&
- access("/proc/bc", F_OK) < 0) {
-
- if (id)
- *id = "openvz";
-
- return 1;
- }
-
- r = getenv_for_pid(1, "container", &e);
- if (r <= 0)
- return r;
-
- /* We only recognize a selected few here, since we want to
- * enforce a redacted namespace */
- if (streq(e, "lxc")) {
- if (id)
- *id = "lxc";
- } else if (streq(e, "lxc-libvirt")) {
- if (id)
- *id = "lxc-libvirt";
- } else if (streq(e, "systemd-nspawn")) {
- if (id)
- *id = "systemd-nspawn";
- } else {
- if (id)
- *id = "other";
- }
-
- free(e);
-
- return r;
-}
-
-/* Returns a short identifier for the various VM/container implementations */
-Virtualization detect_virtualization(const char **id) {
-
- static __thread Virtualization cached_virt = _VIRTUALIZATION_INVALID;
- static __thread const char *cached_id = NULL;
-
- const char *_id;
- int r;
- Virtualization v;
-
- if (_likely_(cached_virt >= 0)) {
-
- if (id && cached_virt > 0)
- *id = cached_id;
-
- return cached_virt;
- }
-
- r = detect_container(&_id);
- if (r < 0) {
- v = r;
- goto finish;
- } else if (r > 0) {
- v = VIRTUALIZATION_CONTAINER;
- goto finish;
- }
-
- r = detect_vm(&_id);
- if (r < 0) {
- v = r;
- goto finish;
- } else if (r > 0) {
- v = VIRTUALIZATION_VM;
- goto finish;
- }
-
- v = VIRTUALIZATION_NONE;
-
-finish:
- if (v > 0) {
- cached_id = _id;
-
- if (id)
- *id = _id;
- }
-
- if (v >= 0)
- cached_virt = v;
-
- return v;
-}
diff --git a/src/shared/virt.h b/src/shared/virt.h
deleted file mode 100644
index aa6ad35ba9..0000000000
--- a/src/shared/virt.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 detect_vm(const char **id);
-int detect_container(const char **id);
-
-typedef enum Virtualization {
- VIRTUALIZATION_NONE = 0,
- VIRTUALIZATION_VM,
- VIRTUALIZATION_CONTAINER,
- _VIRTUALIZATION_MAX,
- _VIRTUALIZATION_INVALID = -1
-} Virtualization;
-
-Virtualization detect_virtualization(const char **id);
diff --git a/src/shared/watchdog.c b/src/shared/watchdog.c
deleted file mode 100644
index 13265e7692..0000000000
--- a/src/shared/watchdog.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <linux/watchdog.h>
-
-#include "watchdog.h"
-#include "log.h"
-
-static int watchdog_fd = -1;
-static usec_t watchdog_timeout = (usec_t) -1;
-
-static int update_timeout(void) {
- int r;
-
- if (watchdog_fd < 0)
- return 0;
-
- if (watchdog_timeout == (usec_t) -1)
- return 0;
- else if (watchdog_timeout == 0) {
- int flags;
-
- flags = WDIOS_DISABLECARD;
- r = ioctl(watchdog_fd, WDIOC_SETOPTIONS, &flags);
- if (r < 0) {
- log_warning("Failed to disable hardware watchdog: %m");
- return -errno;
- }
- } else {
- int sec, flags;
- char buf[FORMAT_TIMESPAN_MAX];
-
- sec = (int) ((watchdog_timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
- r = ioctl(watchdog_fd, WDIOC_SETTIMEOUT, &sec);
- if (r < 0) {
- log_warning("Failed to set timeout to %is: %m", sec);
- return -errno;
- }
-
- watchdog_timeout = (usec_t) sec * USEC_PER_SEC;
- log_info("Set hardware watchdog to %s.", format_timespan(buf, sizeof(buf), watchdog_timeout));
-
- flags = WDIOS_ENABLECARD;
- r = ioctl(watchdog_fd, WDIOC_SETOPTIONS, &flags);
- if (r < 0) {
- log_warning("Failed to enable hardware watchdog: %m");
- return -errno;
- }
-
- r = ioctl(watchdog_fd, WDIOC_KEEPALIVE, 0);
- if (r < 0) {
- log_warning("Failed to ping hardware watchdog: %m");
- return -errno;
- }
- }
-
- return 0;
-}
-
-static int open_watchdog(void) {
- struct watchdog_info ident;
-
- if (watchdog_fd >= 0)
- return 0;
-
- watchdog_fd = open("/dev/watchdog", O_WRONLY|O_CLOEXEC);
- if (watchdog_fd < 0)
- return -errno;
-
- if (ioctl(watchdog_fd, WDIOC_GETSUPPORT, &ident) >= 0)
- log_info("Hardware watchdog '%s', version %x",
- ident.identity,
- ident.firmware_version);
-
- return update_timeout();
-}
-
-int watchdog_set_timeout(usec_t *usec) {
- int r;
-
- watchdog_timeout = *usec;
-
- /* If we didn't open the watchdog yet and didn't get any
- * explicit timeout value set, don't do anything */
- if (watchdog_fd < 0 && watchdog_timeout == (usec_t) -1)
- return 0;
-
- if (watchdog_fd < 0)
- r = open_watchdog();
- else
- r = update_timeout();
-
- *usec = watchdog_timeout;
-
- return r;
-}
-
-int watchdog_ping(void) {
- int r;
-
- if (watchdog_fd < 0) {
- r = open_watchdog();
- if (r < 0)
- return r;
- }
-
- r = ioctl(watchdog_fd, WDIOC_KEEPALIVE, 0);
- if (r < 0) {
- log_warning("Failed to ping hardware watchdog: %m");
- return -errno;
- }
-
- return 0;
-}
-
-void watchdog_close(bool disarm) {
- int r;
-
- if (watchdog_fd < 0)
- return;
-
- if (disarm) {
- int flags;
-
- /* Explicitly disarm it */
- flags = WDIOS_DISABLECARD;
- r = ioctl(watchdog_fd, WDIOC_SETOPTIONS, &flags);
- if (r < 0)
- log_warning("Failed to disable hardware watchdog: %m");
-
- /* To be sure, use magic close logic, too */
- for (;;) {
- static const char v = 'V';
-
- if (write(watchdog_fd, &v, 1) > 0)
- break;
-
- if (errno != EINTR) {
- log_error("Failed to disarm watchdog timer: %m");
- break;
- }
- }
- }
-
- close_nointr_nofail(watchdog_fd);
- watchdog_fd = -1;
-}
diff --git a/src/shared/watchdog.h b/src/shared/watchdog.h
deleted file mode 100644
index b748b15857..0000000000
--- a/src/shared/watchdog.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "util.h"
-
-int watchdog_set_timeout(usec_t *usec);
-int watchdog_ping(void);
-void watchdog_close(bool disarm);
diff --git a/src/shutdownd/Makefile b/src/shutdownd/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/shutdownd/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/shutdownd/shutdownd.c b/src/shutdownd/shutdownd.c
deleted file mode 100644
index c0747415fd..0000000000
--- a/src/shutdownd/shutdownd.c
+++ /dev/null
@@ -1,478 +0,0 @@
-/*-*- 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/socket.h>
-#include <sys/poll.h>
-#include <sys/types.h>
-#include <sys/timerfd.h>
-#include <assert.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stddef.h>
-
-#include <systemd/sd-daemon.h>
-#include <systemd/sd-shutdown.h>
-
-#include "log.h"
-#include "macro.h"
-#include "util.h"
-#include "utmp-wtmp.h"
-#include "mkdir.h"
-
-union shutdown_buffer {
- struct sd_shutdown_command command;
- char space[offsetof(struct sd_shutdown_command, wall_message) + LINE_MAX];
-};
-
-static int read_packet(int fd, union shutdown_buffer *_b) {
- struct msghdr msghdr;
- struct iovec iovec;
- struct ucred *ucred;
- union {
- struct cmsghdr cmsghdr;
- uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
- } control;
- ssize_t n;
- union shutdown_buffer b; /* We maintain our own copy here, in order not to corrupt the last message */
-
- assert(fd >= 0);
- assert(_b);
-
- zero(iovec);
- iovec.iov_base = &b;
- iovec.iov_len = sizeof(b) - 1;
-
- zero(control);
- zero(msghdr);
- msghdr.msg_iov = &iovec;
- msghdr.msg_iovlen = 1;
- msghdr.msg_control = &control;
- msghdr.msg_controllen = sizeof(control);
-
- n = recvmsg(fd, &msghdr, MSG_DONTWAIT);
- if (n <= 0) {
- if (n == 0) {
- log_error("Short read");
- return -EIO;
- }
-
- if (errno == EAGAIN || errno == EINTR)
- return 0;
-
- log_error("recvmsg(): %m");
- return -errno;
- }
-
- if (msghdr.msg_controllen < CMSG_LEN(sizeof(struct ucred)) ||
- control.cmsghdr.cmsg_level != SOL_SOCKET ||
- control.cmsghdr.cmsg_type != SCM_CREDENTIALS ||
- control.cmsghdr.cmsg_len != CMSG_LEN(sizeof(struct ucred))) {
- log_warning("Received message without credentials. Ignoring.");
- return 0;
- }
-
- ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr);
- if (ucred->uid != 0) {
- log_warning("Got request from unprivileged user. Ignoring.");
- return 0;
- }
-
- if ((size_t) n < offsetof(struct sd_shutdown_command, wall_message)) {
- log_warning("Message has invalid size. Ignoring.");
- return 0;
- }
-
- if (b.command.mode != SD_SHUTDOWN_NONE &&
- b.command.mode != SD_SHUTDOWN_REBOOT &&
- b.command.mode != SD_SHUTDOWN_POWEROFF &&
- b.command.mode != SD_SHUTDOWN_HALT &&
- b.command.mode != SD_SHUTDOWN_KEXEC) {
- log_warning("Message has invalid mode. Ignoring.");
- return 0;
- }
-
- b.space[n] = 0;
-
- *_b = b;
- return 1;
-}
-
-static void warn_wall(usec_t n, struct sd_shutdown_command *c) {
- char date[FORMAT_TIMESTAMP_MAX];
- const char *prefix;
- char *l = NULL;
-
- assert(c);
- assert(c->warn_wall);
-
- if (n >= c->usec)
- return;
-
- if (c->mode == SD_SHUTDOWN_HALT)
- prefix = "The system is going down for system halt at ";
- else if (c->mode == SD_SHUTDOWN_POWEROFF)
- prefix = "The system is going down for power-off at ";
- else if (c->mode == SD_SHUTDOWN_REBOOT)
- prefix = "The system is going down for reboot at ";
- else if (c->mode == SD_SHUTDOWN_KEXEC)
- prefix = "The system is going down for kexec reboot at ";
- else if (c->mode == SD_SHUTDOWN_NONE)
- prefix = "The system shutdown has been cancelled at ";
- else
- assert_not_reached("Unknown mode!");
-
- if (asprintf(&l, "%s%s%s%s!", c->wall_message, c->wall_message[0] ? "\n" : "",
- prefix, format_timestamp(date, sizeof(date), c->usec)) < 0)
- log_error("Failed to allocate wall message");
- else {
- utmp_wall(l, NULL);
- free(l);
- }
-}
-
-static usec_t when_wall(usec_t n, usec_t elapse) {
-
- static const struct {
- usec_t delay;
- usec_t interval;
- } table[] = {
- { 10 * USEC_PER_MINUTE, USEC_PER_MINUTE },
- { USEC_PER_HOUR, 15 * USEC_PER_MINUTE },
- { 3 * USEC_PER_HOUR, 30 * USEC_PER_MINUTE }
- };
-
- usec_t left, sub;
- unsigned i;
-
- /* If the time is already passed, then don't announce */
- if (n >= elapse)
- return 0;
-
- left = elapse - n;
- for (i = 0; i < ELEMENTSOF(table); i++)
- if (n + table[i].delay >= elapse) {
- sub = ((left / table[i].interval) * table[i].interval);
- break;
- }
-
- if (i >= ELEMENTSOF(table))
- sub = ((left / USEC_PER_HOUR) * USEC_PER_HOUR);
-
- return elapse > sub ? elapse - sub : 1;
-}
-
-static usec_t when_nologin(usec_t elapse) {
- return elapse > 5*USEC_PER_MINUTE ? elapse - 5*USEC_PER_MINUTE : 1;
-}
-
-static const char *mode_to_string(enum sd_shutdown_mode m) {
- switch (m) {
- case SD_SHUTDOWN_REBOOT:
- return "reboot";
- case SD_SHUTDOWN_POWEROFF:
- return "poweroff";
- case SD_SHUTDOWN_HALT:
- return "halt";
- case SD_SHUTDOWN_KEXEC:
- return "kexec";
- default:
- return NULL;
- }
-}
-
-static int update_schedule_file(struct sd_shutdown_command *c) {
- int r;
- FILE *f;
- char *temp_path, *t;
-
- assert(c);
-
- r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0);
- if (r < 0) {
- log_error("Failed to create shutdown subdirectory: %s", strerror(-r));
- return r;
- }
-
- t = cescape(c->wall_message);
- if (!t)
- return log_oom();
-
- r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path);
- if (r < 0) {
- log_error("Failed to save information about scheduled shutdowns: %s", strerror(-r));
- free(t);
- return r;
- }
-
- fchmod(fileno(f), 0644);
-
- fprintf(f,
- "USEC=%llu\n"
- "WARN_WALL=%i\n"
- "MODE=%s\n",
- (unsigned long long) c->usec,
- c->warn_wall,
- mode_to_string(c->mode));
-
- if (c->dry_run)
- fputs("DRY_RUN=1\n", f);
-
- if (!isempty(t))
- fprintf(f, "WALL_MESSAGE=%s\n", t);
-
- free(t);
-
- fflush(f);
-
- if (ferror(f) || rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) {
- log_error("Failed to write information about scheduled shutdowns: %m");
- r = -errno;
-
- unlink(temp_path);
- unlink("/run/systemd/shutdown/scheduled");
- }
-
- fclose(f);
- free(temp_path);
-
- return r;
-}
-
-static bool scheduled(struct sd_shutdown_command *c) {
- return c->usec > 0 && c->mode != SD_SHUTDOWN_NONE;
-}
-
-int main(int argc, char *argv[]) {
- enum {
- FD_SOCKET,
- FD_WALL_TIMER,
- FD_NOLOGIN_TIMER,
- FD_SHUTDOWN_TIMER,
- _FD_MAX
- };
-
- int r = EXIT_FAILURE, n_fds;
- union shutdown_buffer b;
- struct pollfd pollfd[_FD_MAX];
- bool exec_shutdown = false, unlink_nologin = false;
- unsigned i;
-
- if (getppid() != 1) {
- log_error("This program should be invoked by init only.");
- return EXIT_FAILURE;
- }
-
- if (argc > 1) {
- log_error("This program does not take arguments.");
- return EXIT_FAILURE;
- }
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- n_fds = sd_listen_fds(true);
- if (n_fds < 0) {
- log_error("Failed to read listening file descriptors from environment: %s", strerror(-r));
- return EXIT_FAILURE;
- }
-
- if (n_fds != 1) {
- log_error("Need exactly one file descriptor.");
- return EXIT_FAILURE;
- }
-
- zero(b);
- zero(pollfd);
-
- pollfd[FD_SOCKET].fd = SD_LISTEN_FDS_START;
- pollfd[FD_SOCKET].events = POLLIN;
-
- for (i = FD_WALL_TIMER; i < _FD_MAX; i++) {
- pollfd[i].events = POLLIN;
- pollfd[i].fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC);
- if (pollfd[i].fd < 0) {
- log_error("timerfd_create(): %m");
- goto finish;
- }
- }
-
- log_debug("systemd-shutdownd running as pid %lu", (unsigned long) getpid());
-
- sd_notify(false,
- "READY=1\n"
- "STATUS=Processing requests...");
-
- for (;;) {
- int k;
- usec_t n;
-
- k = poll(pollfd, _FD_MAX, scheduled(&b.command) ? -1 : 0);
- if (k < 0) {
-
- if (errno == EAGAIN || errno == EINTR)
- continue;
-
- log_error("poll(): %m");
- goto finish;
- }
-
- /* Exit on idle */
- if (k == 0)
- break;
-
- n = now(CLOCK_REALTIME);
-
- if (pollfd[FD_SOCKET].revents) {
-
- k = read_packet(pollfd[FD_SOCKET].fd, &b);
- if (k < 0)
- goto finish;
- else if (k > 0) {
- struct itimerspec its;
- char date[FORMAT_TIMESTAMP_MAX];
-
- if (!scheduled(&b.command)) {
- log_info("Shutdown canceled.");
- if (b.command.warn_wall)
- warn_wall(0, &b.command);
- break;
- }
-
- zero(its);
- if (b.command.warn_wall) {
- /* Send wall messages every so often */
- timespec_store(&its.it_value, when_wall(n, b.command.usec));
-
- /* Warn immediately if less than 15 minutes are left */
- if (n < b.command.usec &&
- n + 15*USEC_PER_MINUTE >= b.command.usec)
- warn_wall(n, &b.command);
- }
- if (timerfd_settime(pollfd[FD_WALL_TIMER].fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
- log_error("timerfd_settime(): %m");
- goto finish;
- }
-
- /* Disallow logins 5 minutes prior to shutdown */
- zero(its);
- timespec_store(&its.it_value, when_nologin(b.command.usec));
- if (timerfd_settime(pollfd[FD_NOLOGIN_TIMER].fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
- log_error("timerfd_settime(): %m");
- goto finish;
- }
-
- /* Shutdown after the specified time is reached */
- zero(its);
- timespec_store(&its.it_value, b.command.usec);
- if (timerfd_settime(pollfd[FD_SHUTDOWN_TIMER].fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
- log_error("timerfd_settime(): %m");
- goto finish;
- }
-
- update_schedule_file(&b.command);
-
- sd_notifyf(false,
- "STATUS=Shutting down at %s (%s)...",
- format_timestamp(date, sizeof(date), b.command.usec),
- mode_to_string(b.command.mode));
-
- log_info("Shutting down at %s (%s)...", date, mode_to_string(b.command.mode));
- }
- }
-
- if (pollfd[FD_WALL_TIMER].revents) {
- struct itimerspec its;
-
- warn_wall(n, &b.command);
- flush_fd(pollfd[FD_WALL_TIMER].fd);
-
- /* Restart timer */
- zero(its);
- timespec_store(&its.it_value, when_wall(n, b.command.usec));
- if (timerfd_settime(pollfd[FD_WALL_TIMER].fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
- log_error("timerfd_settime(): %m");
- goto finish;
- }
- }
-
- if (pollfd[FD_NOLOGIN_TIMER].revents) {
- int e;
-
- log_info("Creating /run/nologin, blocking further logins...");
-
- e = write_one_line_file_atomic("/run/nologin", "System is going down.");
- if (e < 0)
- log_error("Failed to create /run/nologin: %s", strerror(-e));
- else
- unlink_nologin = true;
-
- flush_fd(pollfd[FD_NOLOGIN_TIMER].fd);
- }
-
- if (pollfd[FD_SHUTDOWN_TIMER].revents) {
- exec_shutdown = true;
- goto finish;
- }
- }
-
- r = EXIT_SUCCESS;
-
- log_debug("systemd-shutdownd stopped as pid %lu", (unsigned long) getpid());
-
-finish:
-
- for (i = 0; i < _FD_MAX; i++)
- if (pollfd[i].fd >= 0)
- close_nointr_nofail(pollfd[i].fd);
-
- if (unlink_nologin)
- unlink("/run/nologin");
-
- unlink("/run/systemd/shutdown/scheduled");
-
- if (exec_shutdown && !b.command.dry_run) {
- char sw[3];
-
- sw[0] = '-';
- sw[1] = b.command.mode;
- sw[2] = 0;
-
- execl(SYSTEMCTL_BINARY_PATH,
- "shutdown",
- sw,
- "now",
- (b.command.warn_wall && b.command.wall_message[0]) ? b.command.wall_message :
- (b.command.warn_wall ? NULL : "--no-wall"),
- NULL);
-
- log_error("Failed to execute /sbin/shutdown: %m");
- }
-
- sd_notify(false,
- "STATUS=Exiting...");
-
- return r;
-}
diff --git a/src/sleep/Makefile b/src/sleep/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/sleep/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c
deleted file mode 100644
index 218de3a567..0000000000
--- a/src/sleep/sleep.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-
-#include "log.h"
-#include "util.h"
-#include "systemd/sd-id128.h"
-#include "systemd/sd-messages.h"
-
-int main(int argc, char *argv[]) {
- const char *verb;
- char* arguments[4];
- int r;
- FILE *f;
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- if (argc != 2) {
- log_error("Invalid number of arguments.");
- r = -EINVAL;
- goto finish;
- }
-
- if (streq(argv[1], "suspend"))
- verb = "mem";
- else if (streq(argv[1], "hibernate") || streq(argv[1], "hybrid-sleep"))
- verb = "disk";
- else {
- log_error("Unknown action '%s'.", argv[1]);
- r = -EINVAL;
- goto finish;
- }
-
- /* Configure the hibernation mode */
- if (streq(argv[1], "hibernate")) {
- if (write_one_line_file("/sys/power/disk", "platform") < 0)
- write_one_line_file("/sys/power/disk", "shutdown");
- } else if (streq(argv[1], "hybrid-sleep")) {
- if (write_one_line_file("/sys/power/disk", "suspend") < 0)
- if (write_one_line_file("/sys/power/disk", "platform") < 0)
- write_one_line_file("/sys/power/disk", "shutdown");
- }
-
- f = fopen("/sys/power/state", "we");
- if (!f) {
- log_error("Failed to open /sys/power/state: %m");
- r = -errno;
- goto finish;
- }
-
- arguments[0] = NULL;
- arguments[1] = (char*) "pre";
- arguments[2] = argv[1];
- arguments[3] = NULL;
- execute_directory(SYSTEM_SLEEP_PATH, NULL, arguments);
-
- if (streq(argv[1], "suspend"))
- log_struct(LOG_INFO,
- MESSAGE_ID(SD_MESSAGE_SLEEP_START),
- "MESSAGE=Suspending system...",
- "SLEEP=suspend",
- NULL);
- else if (streq(argv[1], "hibernate"))
- log_struct(LOG_INFO,
- MESSAGE_ID(SD_MESSAGE_SLEEP_START),
- "MESSAGE=Hibernating system...",
- "SLEEP=hibernate",
- NULL);
- else
- log_struct(LOG_INFO,
- MESSAGE_ID(SD_MESSAGE_SLEEP_START),
- "MESSAGE=Hibernating and suspending system...",
- "SLEEP=hybrid-sleep",
- NULL);
-
- fputs(verb, f);
- fputc('\n', f);
- fflush(f);
-
- r = ferror(f) ? -errno : 0;
-
- if (streq(argv[1], "suspend"))
- log_struct(LOG_INFO,
- MESSAGE_ID(SD_MESSAGE_SLEEP_STOP),
- "MESSAGE=System resumed.",
- "SLEEP=suspend",
- NULL);
- else
- log_struct(LOG_INFO,
- MESSAGE_ID(SD_MESSAGE_SLEEP_STOP),
- "MESSAGE=System thawed.",
- "SLEEP=hibernate",
- NULL);
-
- arguments[1] = (char*) "post";
- execute_directory(SYSTEM_SLEEP_PATH, NULL, arguments);
-
- fclose(f);
-
-finish:
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-
-}
diff --git a/src/stdio-bridge/Makefile b/src/stdio-bridge/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/stdio-bridge/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/stdio-bridge/stdio-bridge.c b/src/stdio-bridge/stdio-bridge.c
deleted file mode 100644
index f926fe5538..0000000000
--- a/src/stdio-bridge/stdio-bridge.c
+++ /dev/null
@@ -1,367 +0,0 @@
-/*-*- 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/socket.h>
-#include <sys/un.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/epoll.h>
-#include <stddef.h>
-
-#include "log.h"
-#include "util.h"
-#include "socket-util.h"
-
-#define BUFFER_SIZE (64*1024)
-#define EXTRA_SIZE 16
-
-static bool initial_nul = false;
-static bool auth_over = false;
-
-static void format_uid(char *buf, size_t l) {
- char text[20 + 1]; /* enough space for a 64bit integer plus NUL */
- unsigned j;
-
- assert(l > 0);
-
- snprintf(text, sizeof(text)-1, "%llu", (unsigned long long) geteuid());
- text[sizeof(text)-1] = 0;
-
- memset(buf, 0, l);
-
- for (j = 0; text[j] && j*2+2 < l; j++) {
- buf[j*2] = hexchar(text[j] >> 4);
- buf[j*2+1] = hexchar(text[j] & 0xF);
- }
-
- buf[j*2] = 0;
-}
-
-static size_t patch_in_line(char *line, size_t l, size_t left) {
- size_t r;
-
- if (line[0] == 0 && !initial_nul) {
- initial_nul = true;
- line += 1;
- l -= 1;
- r = 1;
- } else
- r = 0;
-
- if (l == 5 && strncmp(line, "BEGIN", 5) == 0) {
- r += l;
- auth_over = true;
-
- } else if (l == 17 && strncmp(line, "NEGOTIATE_UNIX_FD", 17) == 0) {
- memmove(line + 13, line + 17, left);
- memcpy(line, "NEGOTIATE_NOP", 13);
- r += 13;
-
- } else if (l >= 14 && strncmp(line, "AUTH EXTERNAL ", 14) == 0) {
- char uid[20*2 + 1];
- size_t len;
-
- format_uid(uid, sizeof(uid));
- len = strlen(uid);
- assert(len <= EXTRA_SIZE);
-
- memmove(line + 14 + len, line + l, left);
- memcpy(line + 14, uid, len);
-
- r += 14 + len;
- } else
- r += l;
-
- return r;
-}
-
-static size_t patch_in_buffer(char* in_buffer, size_t *in_buffer_full) {
- size_t i, good = 0;
-
- if (*in_buffer_full <= 0)
- return *in_buffer_full;
-
- /* If authentication is done, we don't touch anything anymore */
- if (auth_over)
- return *in_buffer_full;
-
- if (*in_buffer_full < 2)
- return 0;
-
- for (i = 0; i <= *in_buffer_full - 2; i ++) {
-
- /* Fully lines can be send on */
- if (in_buffer[i] == '\r' && in_buffer[i+1] == '\n') {
- if (i > good) {
- size_t old_length, new_length;
-
- old_length = i - good;
- new_length = patch_in_line(in_buffer+good, old_length, *in_buffer_full - i);
- *in_buffer_full = *in_buffer_full + new_length - old_length;
-
- good += new_length + 2;
-
- } else
- good = i+2;
- }
-
- if (auth_over)
- break;
- }
-
- return good;
-}
-
-int main(int argc, char *argv[]) {
- int r = EXIT_FAILURE, fd = -1, ep = -1;
- union sockaddr_union sa;
- char in_buffer[BUFFER_SIZE+EXTRA_SIZE], out_buffer[BUFFER_SIZE+EXTRA_SIZE];
- size_t in_buffer_full = 0, out_buffer_full = 0;
- struct epoll_event stdin_ev, stdout_ev, fd_ev;
- bool stdin_readable = false, stdout_writable = false, fd_readable = false, fd_writable = false;
- bool stdin_rhup = false, stdout_whup = false, fd_rhup = false, fd_whup = false;
-
- if (argc > 1) {
- log_error("This program takes no argument.");
- return EXIT_FAILURE;
- }
-
- log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
- log_parse_environment();
- log_open();
-
- if ((fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0)) < 0) {
- log_error("Failed to create socket: %s", strerror(errno));
- goto finish;
- }
-
- zero(sa);
- sa.un.sun_family = AF_UNIX;
- strncpy(sa.un.sun_path, "/run/dbus/system_bus_socket", sizeof(sa.un.sun_path));
-
- if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
- log_error("Failed to connect: %m");
- goto finish;
- }
-
- fd_nonblock(STDIN_FILENO, 1);
- fd_nonblock(STDOUT_FILENO, 1);
-
- if ((ep = epoll_create1(EPOLL_CLOEXEC)) < 0) {
- log_error("Failed to create epoll: %m");
- goto finish;
- }
-
- zero(stdin_ev);
- stdin_ev.events = EPOLLIN|EPOLLET;
- stdin_ev.data.fd = STDIN_FILENO;
-
- zero(stdout_ev);
- stdout_ev.events = EPOLLOUT|EPOLLET;
- stdout_ev.data.fd = STDOUT_FILENO;
-
- zero(fd_ev);
- fd_ev.events = EPOLLIN|EPOLLOUT|EPOLLET;
- fd_ev.data.fd = fd;
-
- if (epoll_ctl(ep, EPOLL_CTL_ADD, STDIN_FILENO, &stdin_ev) < 0 ||
- epoll_ctl(ep, EPOLL_CTL_ADD, STDOUT_FILENO, &stdout_ev) < 0 ||
- epoll_ctl(ep, EPOLL_CTL_ADD, fd, &fd_ev) < 0) {
- log_error("Failed to regiser fds in epoll: %m");
- goto finish;
- }
-
- do {
- struct epoll_event ev[16];
- ssize_t k;
- int i, nfds;
-
- if ((nfds = epoll_wait(ep, ev, ELEMENTSOF(ev), -1)) < 0) {
-
- if (errno == EINTR || errno == EAGAIN)
- continue;
-
- log_error("epoll_wait(): %m");
- goto finish;
- }
-
- assert(nfds >= 1);
-
- for (i = 0; i < nfds; i++) {
- if (ev[i].data.fd == STDIN_FILENO) {
-
- if (!stdin_rhup && (ev[i].events & (EPOLLHUP|EPOLLIN)))
- stdin_readable = true;
-
- } else if (ev[i].data.fd == STDOUT_FILENO) {
-
- if (ev[i].events & EPOLLHUP) {
- stdout_writable = false;
- stdout_whup = true;
- }
-
- if (!stdout_whup && (ev[i].events & EPOLLOUT))
- stdout_writable = true;
-
- } else if (ev[i].data.fd == fd) {
-
- if (ev[i].events & EPOLLHUP) {
- fd_writable = false;
- fd_whup = true;
- }
-
- if (!fd_rhup && (ev[i].events & (EPOLLHUP|EPOLLIN)))
- fd_readable = true;
-
- if (!fd_whup && (ev[i].events & EPOLLOUT))
- fd_writable = true;
- }
- }
-
- while ((stdin_readable && in_buffer_full <= 0) ||
- (fd_writable && patch_in_buffer(in_buffer, &in_buffer_full) > 0) ||
- (fd_readable && out_buffer_full <= 0) ||
- (stdout_writable && out_buffer_full > 0)) {
-
- size_t in_buffer_good = 0;
-
- if (stdin_readable && in_buffer_full < BUFFER_SIZE) {
-
- if ((k = read(STDIN_FILENO, in_buffer + in_buffer_full, BUFFER_SIZE - in_buffer_full)) < 0) {
-
- if (errno == EAGAIN)
- stdin_readable = false;
- else if (errno == EPIPE || errno == ECONNRESET)
- k = 0;
- else {
- log_error("read(): %m");
- goto finish;
- }
- } else
- in_buffer_full += (size_t) k;
-
- if (k == 0) {
- stdin_rhup = true;
- stdin_readable = false;
- shutdown(STDIN_FILENO, SHUT_RD);
- close_nointr_nofail(STDIN_FILENO);
- }
- }
-
- in_buffer_good = patch_in_buffer(in_buffer, &in_buffer_full);
-
- if (fd_writable && in_buffer_good > 0) {
-
- if ((k = write(fd, in_buffer, in_buffer_good)) < 0) {
-
- if (errno == EAGAIN)
- fd_writable = false;
- else if (errno == EPIPE || errno == ECONNRESET) {
- fd_whup = true;
- fd_writable = false;
- shutdown(fd, SHUT_WR);
- } else {
- log_error("write(): %m");
- goto finish;
- }
-
- } else {
- assert(in_buffer_full >= (size_t) k);
- memmove(in_buffer, in_buffer + k, in_buffer_full - k);
- in_buffer_full -= k;
- }
- }
-
- if (fd_readable && out_buffer_full < BUFFER_SIZE) {
-
- if ((k = read(fd, out_buffer + out_buffer_full, BUFFER_SIZE - out_buffer_full)) < 0) {
-
- if (errno == EAGAIN)
- fd_readable = false;
- else if (errno == EPIPE || errno == ECONNRESET)
- k = 0;
- else {
- log_error("read(): %m");
- goto finish;
- }
- } else
- out_buffer_full += (size_t) k;
-
- if (k == 0) {
- fd_rhup = true;
- fd_readable = false;
- shutdown(fd, SHUT_RD);
- }
- }
-
- if (stdout_writable && out_buffer_full > 0) {
-
- if ((k = write(STDOUT_FILENO, out_buffer, out_buffer_full)) < 0) {
-
- if (errno == EAGAIN)
- stdout_writable = false;
- else if (errno == EPIPE || errno == ECONNRESET) {
- stdout_whup = true;
- stdout_writable = false;
- shutdown(STDOUT_FILENO, SHUT_WR);
- close_nointr(STDOUT_FILENO);
- } else {
- log_error("write(): %m");
- goto finish;
- }
-
- } else {
- assert(out_buffer_full >= (size_t) k);
- memmove(out_buffer, out_buffer + k, out_buffer_full - k);
- out_buffer_full -= k;
- }
- }
- }
-
- if (stdin_rhup && in_buffer_full <= 0 && !fd_whup) {
- fd_whup = true;
- fd_writable = false;
- shutdown(fd, SHUT_WR);
- }
-
- if (fd_rhup && out_buffer_full <= 0 && !stdout_whup) {
- stdout_whup = true;
- stdout_writable = false;
- shutdown(STDOUT_FILENO, SHUT_WR);
- close_nointr(STDOUT_FILENO);
- }
-
- } while (!stdout_whup || !fd_whup);
-
- r = EXIT_SUCCESS;
-
-finish:
- if (fd >= 0)
- close_nointr_nofail(fd);
-
- if (ep >= 0)
- close_nointr_nofail(ep);
-
- return r;
-}
diff --git a/src/sysctl/Makefile b/src/sysctl/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/sysctl/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c
deleted file mode 100644
index 035e0ec321..0000000000
--- a/src/sysctl/sysctl.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/*-*- 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 <stdlib.h>
-#include <stdbool.h>
-#include <errno.h>
-#include <string.h>
-#include <stdio.h>
-#include <limits.h>
-#include <getopt.h>
-
-#include "log.h"
-#include "strv.h"
-#include "util.h"
-#include "strv.h"
-#include "hashmap.h"
-#include "path-util.h"
-#include "conf-files.h"
-
-#define PROC_SYS_PREFIX "/proc/sys/"
-
-static char **arg_prefixes;
-static Hashmap *sysctl_options;
-
-static int apply_sysctl(const char *property, const char *value) {
- char *p, *n;
- int r = 0, k;
-
- log_debug("Setting '%s' to '%s'", property, value);
-
- p = new(char, sizeof(PROC_SYS_PREFIX) + strlen(property));
- if (!p)
- return log_oom();
-
- n = stpcpy(p, PROC_SYS_PREFIX);
- strcpy(n, property);
-
- for (; *n; n++)
- if (*n == '.')
- *n = '/';
-
- if (!strv_isempty(arg_prefixes)) {
- char **i;
- bool good = false;
-
- STRV_FOREACH(i, arg_prefixes)
- if (path_startswith(p, *i)) {
- good = true;
- break;
- }
-
- if (!good) {
- log_debug("Skipping %s", p);
- free(p);
- return 0;
- }
- }
-
- k = write_one_line_file(p, value);
- if (k < 0) {
-
- log_full(k == -ENOENT ? LOG_DEBUG : LOG_WARNING,
- "Failed to write '%s' to '%s': %s", value, p, strerror(-k));
-
- if (k != -ENOENT && r == 0)
- r = k;
- }
-
- free(p);
-
- return r;
-}
-
-static int apply_all(void) {
- int r = 0;
- char *property, *value;
- Iterator i;
-
- HASHMAP_FOREACH_KEY(value, property, sysctl_options, i) {
- int k;
-
- k = apply_sysctl(property, value);
- if (k < 0 && r == 0)
- r = k;
- }
- return r;
-}
-
-static int parse_file(const char *path, bool ignore_enoent) {
- FILE *f;
- int r = 0;
-
- assert(path);
-
- f = fopen(path, "re");
- if (!f) {
- if (ignore_enoent && errno == ENOENT)
- return 0;
-
- log_error("Failed to open file '%s', ignoring: %m", path);
- return -errno;
- }
-
- log_debug("parse: %s\n", path);
- while (!feof(f)) {
- char l[LINE_MAX], *p, *value, *new_value, *property;
-
- if (!fgets(l, sizeof(l), f)) {
- if (feof(f))
- break;
-
- log_error("Failed to read file '%s', ignoring: %m", path);
- r = -errno;
- goto finish;
- }
-
- p = strstrip(l);
-
- if (!*p)
- continue;
-
- if (strchr(COMMENTS, *p))
- continue;
-
- value = strchr(p, '=');
- if (!value) {
- log_error("Line is not an assignment in file '%s': %s", path, value);
-
- if (r == 0)
- r = -EINVAL;
- continue;
- }
-
- *value = 0;
- value++;
-
- property = strdup(strstrip(p));
- if (!property) {
- r = log_oom();
- goto finish;
- }
-
- new_value = strdup(strstrip(value));
- if (!new_value) {
- free(property);
- r = log_oom();
- goto finish;
- }
-
- r = hashmap_put(sysctl_options, property, new_value);
- if (r < 0) {
- if (r == -EEXIST) {
- /* ignore this "error" to avoid returning it
- * for the function when this is the last key
- * in the file being parsed. */
- r = 0;
- log_debug("Skipping previously assigned sysctl variable %s", property);
- } else
- log_error("Failed to add sysctl variable %s to hashmap: %s", property, strerror(-r));
-
- free(property);
- free(new_value);
- if (r != 0)
- goto finish;
- }
- }
-
-finish:
- fclose(f);
-
- return r;
-}
-
-static int help(void) {
-
- printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
- "Applies kernel sysctl settings.\n\n"
- " -h --help Show this help\n"
- " --prefix=PATH Only apply rules that apply to paths with the specified prefix\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_PREFIX
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "prefix", required_argument, NULL, ARG_PREFIX },
- { NULL, 0, NULL, 0 }
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_PREFIX: {
- char *p;
- char **l;
-
- for (p = optarg; *p; p++)
- if (*p == '.')
- *p = '/';
-
- l = strv_append(arg_prefixes, optarg);
- if (!l)
- return log_oom();
-
- strv_free(arg_prefixes);
- arg_prefixes = l;
-
- break;
- }
-
- case '?':
- return -EINVAL;
-
- default:
- log_error("Unknown option code %c", c);
- return -EINVAL;
- }
- }
-
- return 1;
-}
-
-int main(int argc, char *argv[]) {
- int r = 0, k;
- char *property, *value;
- Iterator it;
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- sysctl_options = hashmap_new(string_hash_func, string_compare_func);
- if (!sysctl_options) {
- r = log_oom();
- goto finish;
- }
-
- r = 0;
-
- if (argc > optind) {
- int i;
-
- for (i = optind; i < argc; i++) {
- k = parse_file(argv[i], false);
- if (k < 0)
- r = k;
- }
- } else {
- char **files, **f;
-
- r = conf_files_list(&files, ".conf",
- "/etc/sysctl.d",
- "/run/sysctl.d",
- "/usr/local/lib/sysctl.d",
- "/usr/lib/sysctl.d",
-#ifdef HAVE_SPLIT_USR
- "/lib/sysctl.d",
-#endif
- NULL);
- if (r < 0) {
- log_error("Failed to enumerate sysctl.d files: %s", strerror(-r));
- goto finish;
- }
-
- /* We parse the files in decreasing order of precedence.
- * parse_file() will skip keys that were already assigned. */
-
- r = parse_file("/etc/sysctl.conf", true);
-
- f = files + strv_length(files) - 1;
- STRV_FOREACH_BACKWARDS(f, files) {
- k = parse_file(*f, true);
- if (k < 0)
- r = k;
- }
-
- strv_free(files);
- }
-
- k = apply_all();
- if (k < 0)
- r = k;
-
-finish:
- HASHMAP_FOREACH_KEY(value, property, sysctl_options, it) {
- hashmap_remove(sysctl_options, property);
- free(property);
- free(value);
- }
- hashmap_free(sysctl_options);
-
- strv_free(arg_prefixes);
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/system-update-generator/Makefile b/src/system-update-generator/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/system-update-generator/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/system-update-generator/system-update-generator.c b/src/system-update-generator/system-update-generator.c
deleted file mode 100644
index 6660192f5e..0000000000
--- a/src/system-update-generator/system-update-generator.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <unistd.h>
-
-#include "log.h"
-#include "util.h"
-#include "unit-name.h"
-#include "path-util.h"
-
-/*
- * Implements the logic described in
- * http://freedesktop.org/wiki/Software/systemd/SystemUpdates
- */
-
-static const char *arg_dest = "/tmp";
-
-static int generate_symlink(void) {
- struct stat st;
- char *p;
-
- if (lstat("/system-update", &st) < 0) {
- if (errno == ENOENT)
- return 0;
-
- log_error("Failed to check for system update: %m");
- return -EINVAL;
- }
-
- p = strappend(arg_dest, "/default.target");
- if (!p)
- return log_oom();
-
- if (symlink(SYSTEM_DATA_UNIT_PATH "/system-update.target", p) < 0) {
- free(p);
- log_error("Failed to create symlink: %m");
- return -errno;
- }
-
- free(p);
-
- return 0;
-}
-
-int main(int argc, char *argv[]) {
- int r;
-
- if (argc > 1 && argc != 4) {
- log_error("This program takes three or no arguments.");
- return EXIT_FAILURE;
- }
-
- if (argc > 1)
- arg_dest = argv[2];
-
- log_set_target(LOG_TARGET_SAFE);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- r = generate_symlink();
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/systemctl/Makefile b/src/systemctl/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/systemctl/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
deleted file mode 100644
index b82c79435d..0000000000
--- a/src/systemctl/systemctl.c
+++ /dev/null
@@ -1,5354 +0,0 @@
-/*-*- 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/reboot.h>
-#include <stdio.h>
-#include <getopt.h>
-#include <locale.h>
-#include <stdbool.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <termios.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <stddef.h>
-#include <sys/prctl.h>
-#include <dbus/dbus.h>
-
-#include <systemd/sd-daemon.h>
-#include <systemd/sd-shutdown.h>
-
-#include "log.h"
-#include "util.h"
-#include "macro.h"
-#include "set.h"
-#include "utmp-wtmp.h"
-#include "special.h"
-#include "initreq.h"
-#include "path-util.h"
-#include "strv.h"
-#include "dbus-common.h"
-#include "cgroup-show.h"
-#include "cgroup-util.h"
-#include "list.h"
-#include "path-lookup.h"
-#include "conf-parser.h"
-#include "exit-status.h"
-#include "bus-errors.h"
-#include "build.h"
-#include "unit-name.h"
-#include "pager.h"
-#include "spawn-ask-password-agent.h"
-#include "spawn-polkit-agent.h"
-#include "install.h"
-#include "logs-show.h"
-#include "path-util.h"
-#include "socket-util.h"
-
-static const char *arg_type = NULL;
-static const char *arg_load_state = NULL;
-static char **arg_property = NULL;
-static bool arg_all = false;
-static const char *arg_job_mode = "replace";
-static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
-static bool arg_no_block = false;
-static bool arg_no_legend = false;
-static bool arg_no_pager = false;
-static bool arg_no_wtmp = false;
-static bool arg_no_wall = false;
-static bool arg_no_reload = false;
-static bool arg_dry = false;
-static bool arg_quiet = false;
-static bool arg_full = false;
-static int arg_force = 0;
-static bool arg_ask_password = true;
-static bool arg_failed = false;
-static bool arg_runtime = false;
-static char **arg_wall = NULL;
-static const char *arg_kill_who = NULL;
-static int arg_signal = SIGTERM;
-static const char *arg_root = NULL;
-static usec_t arg_when = 0;
-static enum action {
- ACTION_INVALID,
- ACTION_SYSTEMCTL,
- ACTION_HALT,
- ACTION_POWEROFF,
- ACTION_REBOOT,
- ACTION_KEXEC,
- ACTION_EXIT,
- ACTION_SUSPEND,
- ACTION_HIBERNATE,
- ACTION_HYBRID_SLEEP,
- ACTION_RUNLEVEL2,
- ACTION_RUNLEVEL3,
- ACTION_RUNLEVEL4,
- ACTION_RUNLEVEL5,
- ACTION_RESCUE,
- ACTION_EMERGENCY,
- ACTION_DEFAULT,
- ACTION_RELOAD,
- ACTION_REEXEC,
- ACTION_RUNLEVEL,
- ACTION_CANCEL_SHUTDOWN,
- _ACTION_MAX
-} arg_action = ACTION_SYSTEMCTL;
-static enum dot {
- DOT_ALL,
- DOT_ORDER,
- DOT_REQUIRE
-} arg_dot = DOT_ALL;
-static enum transport {
- TRANSPORT_NORMAL,
- TRANSPORT_SSH,
- TRANSPORT_POLKIT
-} arg_transport = TRANSPORT_NORMAL;
-static const char *arg_host = NULL;
-static unsigned arg_lines = 10;
-static OutputMode arg_output = OUTPUT_SHORT;
-
-static bool private_bus = false;
-
-static int daemon_reload(DBusConnection *bus, char **args);
-static void halt_now(enum action a);
-
-static void pager_open_if_enabled(void) {
-
- if (arg_no_pager)
- return;
-
- pager_open();
-}
-
-static void ask_password_agent_open_if_enabled(void) {
-
- /* Open the password agent as a child process if necessary */
-
- if (!arg_ask_password)
- return;
-
- if (arg_scope != UNIT_FILE_SYSTEM)
- return;
-
- ask_password_agent_open();
-}
-
-#ifdef HAVE_LOGIND
-static void polkit_agent_open_if_enabled(void) {
-
- /* Open the polkit agent as a child process if necessary */
-
- if (!arg_ask_password)
- return;
-
- if (arg_scope != UNIT_FILE_SYSTEM)
- return;
-
- polkit_agent_open();
-}
-#endif
-
-static const char *ansi_highlight(bool b) {
-
- if (!on_tty())
- return "";
-
- return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
-}
-
-static const char *ansi_highlight_red(bool b) {
-
- if (!on_tty())
- return "";
-
- return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
-}
-
-static const char *ansi_highlight_green(bool b) {
-
- if (!on_tty())
- return "";
-
- return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
-}
-
-static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
- assert(error);
-
- if (!dbus_error_is_set(error))
- return r;
-
- if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
- dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
- dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
- dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
- return EXIT_NOPERMISSION;
-
- if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
- return EXIT_NOTINSTALLED;
-
- if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
- dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
- return EXIT_NOTIMPLEMENTED;
-
- if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
- return EXIT_NOTCONFIGURED;
-
- if (r != 0)
- return r;
-
- return EXIT_FAILURE;
-}
-
-static void warn_wall(enum action a) {
- static const char *table[_ACTION_MAX] = {
- [ACTION_HALT] = "The system is going down for system halt NOW!",
- [ACTION_REBOOT] = "The system is going down for reboot NOW!",
- [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
- [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
- [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
- [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
- [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
- };
-
- if (arg_no_wall)
- return;
-
- if (arg_wall) {
- char *p;
-
- p = strv_join(arg_wall, " ");
- if (!p) {
- log_error("Failed to join strings.");
- return;
- }
-
- if (*p) {
- utmp_wall(p, NULL);
- free(p);
- return;
- }
-
- free(p);
- }
-
- if (!table[a])
- return;
-
- utmp_wall(table[a], NULL);
-}
-
-static bool avoid_bus(void) {
-
- if (running_in_chroot() > 0)
- return true;
-
- if (sd_booted() <= 0)
- return true;
-
- if (!isempty(arg_root))
- return true;
-
- if (arg_scope == UNIT_FILE_GLOBAL)
- return true;
-
- return false;
-}
-
-struct unit_info {
- const char *id;
- const char *description;
- const char *load_state;
- const char *active_state;
- const char *sub_state;
- const char *following;
- const char *unit_path;
- uint32_t job_id;
- const char *job_type;
- const char *job_path;
-};
-
-static int compare_unit_info(const void *a, const void *b) {
- const char *d1, *d2;
- const struct unit_info *u = a, *v = b;
-
- d1 = strrchr(u->id, '.');
- d2 = strrchr(v->id, '.');
-
- if (d1 && d2) {
- int r;
-
- if ((r = strcasecmp(d1, d2)) != 0)
- return r;
- }
-
- return strcasecmp(u->id, v->id);
-}
-
-static bool output_show_unit(const struct unit_info *u) {
- const char *dot;
-
- if (arg_failed)
- return streq(u->active_state, "failed");
-
- return (!arg_type || ((dot = strrchr(u->id, '.')) &&
- streq(dot+1, arg_type))) &&
- (!arg_load_state || streq(u->load_state, arg_load_state)) &&
- (arg_all || !(streq(u->active_state, "inactive")
- || u->following[0]) || u->job_id > 0);
-}
-
-static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
- unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
- const struct unit_info *u;
- int job_count = 0;
-
- max_id_len = sizeof("UNIT")-1;
- active_len = sizeof("ACTIVE")-1;
- sub_len = sizeof("SUB")-1;
- job_len = sizeof("JOB")-1;
- desc_len = 0;
-
- for (u = unit_infos; u < unit_infos + c; u++) {
- if (!output_show_unit(u))
- continue;
-
- max_id_len = MAX(max_id_len, strlen(u->id));
- active_len = MAX(active_len, strlen(u->active_state));
- sub_len = MAX(sub_len, strlen(u->sub_state));
- if (u->job_id != 0) {
- job_len = MAX(job_len, strlen(u->job_type));
- job_count++;
- }
- }
-
- if (!arg_full) {
- unsigned basic_len;
- id_len = MIN(max_id_len, 25);
- basic_len = 5 + id_len + 5 + active_len + sub_len;
- if (job_count)
- basic_len += job_len + 1;
- if (basic_len < (unsigned) columns()) {
- unsigned extra_len, incr;
- extra_len = columns() - basic_len;
- /* Either UNIT already got 25, or is fully satisfied.
- * Grant up to 25 to DESC now. */
- incr = MIN(extra_len, 25);
- desc_len += incr;
- extra_len -= incr;
- /* split the remaining space between UNIT and DESC,
- * but do not give UNIT more than it needs. */
- if (extra_len > 0) {
- incr = MIN(extra_len / 2, max_id_len - id_len);
- id_len += incr;
- desc_len += extra_len - incr;
- }
- }
- } else
- id_len = max_id_len;
-
- for (u = unit_infos; u < unit_infos + c; u++) {
- char *e;
- const char *on_loaded, *off_loaded;
- const char *on_active, *off_active;
-
- if (!output_show_unit(u))
- continue;
-
- if (!n_shown && !arg_no_legend) {
- printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
- active_len, "ACTIVE", sub_len, "SUB");
- if (job_count)
- printf("%-*s ", job_len, "JOB");
- if (!arg_full && arg_no_pager)
- printf("%.*s\n", desc_len, "DESCRIPTION");
- else
- printf("%s\n", "DESCRIPTION");
- }
-
- n_shown++;
-
- if (streq(u->load_state, "error")) {
- on_loaded = ansi_highlight_red(true);
- off_loaded = ansi_highlight_red(false);
- } else
- on_loaded = off_loaded = "";
-
- if (streq(u->active_state, "failed")) {
- on_active = ansi_highlight_red(true);
- off_active = ansi_highlight_red(false);
- } else
- on_active = off_active = "";
-
- e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
-
- printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s",
- id_len, e ? e : u->id,
- on_loaded, u->load_state, off_loaded,
- on_active, active_len, u->active_state,
- sub_len, u->sub_state, off_active,
- job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
- if (!arg_full && arg_no_pager)
- printf("%.*s\n", desc_len, u->description);
- else
- printf("%s\n", u->description);
-
- free(e);
- }
-
- if (!arg_no_legend) {
- const char *on, *off;
-
- if (n_shown) {
- printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
- "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
- "SUB = The low-level unit activation state, values depend on unit type.\n");
- if (job_count)
- printf("JOB = Pending job for the unit.\n");
- on = ansi_highlight(true);
- off = ansi_highlight(false);
- } else {
- on = ansi_highlight_red(true);
- off = ansi_highlight_red(false);
- }
-
- if (arg_all)
- printf("\n%s%u loaded units listed.%s\n"
- "To show all installed unit files use 'systemctl list-unit-files'.\n",
- on, n_shown, off);
- else
- printf("\n%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
- "To show all installed unit files use 'systemctl list-unit-files'.\n",
- on, n_shown, off);
- }
-}
-
-static int list_units(DBusConnection *bus, char **args) {
- DBusMessage *reply = NULL;
- int r;
- DBusMessageIter iter, sub, sub2;
- unsigned c = 0, n_units = 0;
- struct unit_info *unit_infos = NULL;
-
- pager_open_if_enabled();
-
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "ListUnits",
- &reply,
- NULL,
- DBUS_TYPE_INVALID);
- if (r)
- goto finish;
-
- if (!dbus_message_iter_init(reply, &iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&iter, &sub);
-
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- struct unit_info *u;
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- if (c >= n_units) {
- struct unit_info *w;
-
- n_units = MAX(2*c, 16);
- w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
-
- if (!w) {
- log_error("Failed to allocate unit array.");
- r = -ENOMEM;
- goto finish;
- }
-
- unit_infos = w;
- }
-
- u = unit_infos+c;
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_next(&sub);
- c++;
- }
-
- if (c > 0) {
- qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
- output_units_list(unit_infos, c);
- }
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- free(unit_infos);
-
- return r;
-}
-
-static int compare_unit_file_list(const void *a, const void *b) {
- const char *d1, *d2;
- const UnitFileList *u = a, *v = b;
-
- d1 = strrchr(u->path, '.');
- d2 = strrchr(v->path, '.');
-
- if (d1 && d2) {
- int r;
-
- r = strcasecmp(d1, d2);
- if (r != 0)
- return r;
- }
-
- return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
-}
-
-static bool output_show_unit_file(const UnitFileList *u) {
- const char *dot;
-
- return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
-}
-
-static void output_unit_file_list(const UnitFileList *units, unsigned c) {
- unsigned max_id_len, id_cols, state_cols, n_shown = 0;
- const UnitFileList *u;
-
- max_id_len = sizeof("UNIT FILE")-1;
- state_cols = sizeof("STATE")-1;
- for (u = units; u < units + c; u++) {
- if (!output_show_unit_file(u))
- continue;
-
- max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
- state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
- }
-
- if (!arg_full) {
- unsigned basic_cols;
- id_cols = MIN(max_id_len, 25);
- basic_cols = 1 + id_cols + state_cols;
- if (basic_cols < (unsigned) columns())
- id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
- } else
- id_cols = max_id_len;
-
- if (!arg_no_legend)
- printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
-
- for (u = units; u < units + c; u++) {
- char *e;
- const char *on, *off;
- const char *id;
-
- if (!output_show_unit_file(u))
- continue;
-
- n_shown++;
-
- if (u->state == UNIT_FILE_MASKED ||
- u->state == UNIT_FILE_MASKED_RUNTIME ||
- u->state == UNIT_FILE_DISABLED ||
- u->state == UNIT_FILE_INVALID) {
- on = ansi_highlight_red(true);
- off = ansi_highlight_red(false);
- } else if (u->state == UNIT_FILE_ENABLED) {
- on = ansi_highlight_green(true);
- off = ansi_highlight_green(false);
- } else
- on = off = "";
-
- id = path_get_file_name(u->path);
-
- e = arg_full ? NULL : ellipsize(id, id_cols, 33);
-
- printf("%-*s %s%-*s%s\n",
- id_cols, e ? e : id,
- on, state_cols, unit_file_state_to_string(u->state), off);
-
- free(e);
- }
-
- if (!arg_no_legend)
- printf("\n%u unit files listed.\n", n_shown);
-}
-
-static int list_unit_files(DBusConnection *bus, char **args) {
- DBusMessage *reply = NULL;
- int r;
- DBusMessageIter iter, sub, sub2;
- unsigned c = 0, n_units = 0;
- UnitFileList *units = NULL;
-
- pager_open_if_enabled();
-
- if (avoid_bus()) {
- Hashmap *h;
- UnitFileList *u;
- Iterator i;
-
- h = hashmap_new(string_hash_func, string_compare_func);
- if (!h)
- return log_oom();
-
- r = unit_file_get_list(arg_scope, arg_root, h);
- if (r < 0) {
- unit_file_list_free(h);
- log_error("Failed to get unit file list: %s", strerror(-r));
- return r;
- }
-
- n_units = hashmap_size(h);
- units = new(UnitFileList, n_units);
- if (!units) {
- unit_file_list_free(h);
- return log_oom();
- }
-
- HASHMAP_FOREACH(u, h, i) {
- memcpy(units + c++, u, sizeof(UnitFileList));
- free(u);
- }
-
- hashmap_free(h);
- } else {
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "ListUnitFiles",
- &reply,
- NULL,
- DBUS_TYPE_INVALID);
- if (r)
- goto finish;
-
- if (!dbus_message_iter_init(reply, &iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&iter, &sub);
-
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- UnitFileList *u;
- const char *state;
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- if (c >= n_units) {
- UnitFileList *w;
-
- n_units = MAX(2*c, 16);
- w = realloc(units, sizeof(struct UnitFileList) * n_units);
-
- if (!w) {
- log_error("Failed to allocate unit array.");
- r = -ENOMEM;
- goto finish;
- }
-
- units = w;
- }
-
- u = units+c;
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- u->state = unit_file_state_from_string(state);
-
- dbus_message_iter_next(&sub);
- c++;
- }
- }
-
- if (c > 0) {
- qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
- output_unit_file_list(units, c);
- }
-
- r = 0;
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- free(units);
-
- return r;
-}
-
-static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
- static const char * const colors[] = {
- "Requires", "[color=\"black\"]",
- "RequiresOverridable", "[color=\"black\"]",
- "Requisite", "[color=\"darkblue\"]",
- "RequisiteOverridable", "[color=\"darkblue\"]",
- "Wants", "[color=\"grey66\"]",
- "Conflicts", "[color=\"red\"]",
- "ConflictedBy", "[color=\"red\"]",
- "After", "[color=\"green\"]"
- };
-
- const char *c = NULL;
- unsigned i;
-
- assert(name);
- assert(prop);
- assert(iter);
-
- for (i = 0; i < ELEMENTSOF(colors); i += 2)
- if (streq(colors[i], prop)) {
- c = colors[i+1];
- break;
- }
-
- if (!c)
- return 0;
-
- if (arg_dot != DOT_ALL)
- if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
- return 0;
-
- switch (dbus_message_iter_get_arg_type(iter)) {
-
- case DBUS_TYPE_ARRAY:
-
- if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
- DBusMessageIter sub;
-
- dbus_message_iter_recurse(iter, &sub);
-
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- const char *s;
-
- assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
- dbus_message_iter_get_basic(&sub, &s);
- printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
-
- dbus_message_iter_next(&sub);
- }
-
- return 0;
- }
- }
-
- return 0;
-}
-
-static int dot_one(DBusConnection *bus, const char *name, const char *path) {
- DBusMessage *reply = NULL;
- const char *interface = "org.freedesktop.systemd1.Unit";
- int r;
- DBusMessageIter iter, sub, sub2, sub3;
-
- assert(path);
-
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- path,
- "org.freedesktop.DBus.Properties",
- "GetAll",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &interface,
- DBUS_TYPE_INVALID);
- if (r)
- goto finish;
-
- if (!dbus_message_iter_init(reply, &iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&iter, &sub);
-
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- const char *prop;
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&sub2, &sub3);
-
- if (dot_one_property(name, prop, &sub3)) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_next(&sub);
- }
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- return r;
-}
-
-static int dot(DBusConnection *bus, char **args) {
- DBusMessage *reply = NULL;
- int r;
- DBusMessageIter iter, sub, sub2;
-
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "ListUnits",
- &reply,
- NULL,
- DBUS_TYPE_INVALID);
- if (r)
- goto finish;
-
- if (!dbus_message_iter_init(reply, &iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- printf("digraph systemd {\n");
-
- dbus_message_iter_recurse(&iter, &sub);
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- if ((r = dot_one(bus, id, unit_path)) < 0)
- goto finish;
-
- /* printf("\t\"%s\";\n", id); */
- dbus_message_iter_next(&sub);
- }
-
- printf("}\n");
-
- log_info(" Color legend: black = Requires\n"
- " dark blue = Requisite\n"
- " dark grey = Wants\n"
- " red = Conflicts\n"
- " green = After\n");
-
- if (on_tty())
- log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
- "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
-
- r = 0;
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- return r;
-}
-
-static int list_jobs(DBusConnection *bus, char **args) {
- DBusMessage *reply = NULL;
- int r;
- DBusMessageIter iter, sub, sub2;
- unsigned k = 0;
-
- pager_open_if_enabled();
-
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "ListJobs",
- &reply,
- NULL,
- DBUS_TYPE_INVALID);
- if (r)
- goto finish;
-
- if (!dbus_message_iter_init(reply, &iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&iter, &sub);
-
- if (on_tty())
- printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
-
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- const char *name, *type, *state, *job_path, *unit_path;
- uint32_t id;
- char *e;
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- e = arg_full ? NULL : ellipsize(name, 25, 33);
- printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
- free(e);
-
- k++;
-
- dbus_message_iter_next(&sub);
- }
-
- if (on_tty())
- printf("\n%u jobs listed.\n", k);
-
- r = 0;
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- return r;
-}
-
-static int load_unit(DBusConnection *bus, char **args) {
- int r = 0;
- char **name, *n;
-
- assert(args);
-
- STRV_FOREACH(name, args+1) {
- n = unit_name_mangle(*name);
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "LoadUnit",
- NULL,
- NULL,
- DBUS_TYPE_STRING, n ? &n : name,
- DBUS_TYPE_INVALID);
- free(n);
- if (r)
- goto finish;
- }
-
-finish:
- return r;
-}
-
-static int cancel_job(DBusConnection *bus, char **args) {
- DBusMessage *reply = NULL;
- int r = 0;
- char **name;
-
- assert(args);
-
- if (strv_length(args) <= 1)
- return daemon_reload(bus, args);
-
- STRV_FOREACH(name, args+1) {
- unsigned id;
- const char *path;
-
- r = safe_atou(*name, &id);
- if (r < 0) {
- log_error("Failed to parse job id: %s", strerror(-r));
- goto finish;
- }
- assert_cc(sizeof(uint32_t) == sizeof(id));
-
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "GetJob",
- &reply,
- NULL,
- DBUS_TYPE_UINT32, &id,
- DBUS_TYPE_INVALID);
- if (r)
- goto finish;
-
- if (!dbus_message_get_args(reply, NULL,
- DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID)) {
- log_error("Failed to parse reply");
- dbus_message_unref(reply);
- r = -EIO;
- goto finish;
- }
- dbus_message_unref(reply);
-
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- path,
- "org.freedesktop.systemd1.Job",
- "Cancel",
- NULL,
- NULL,
- DBUS_TYPE_INVALID);
- if (r)
- goto finish;
- }
-
-finish:
- return r;
-}
-
-static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
- DBusMessage *reply = NULL;
- dbus_bool_t b = FALSE;
- DBusMessageIter iter, sub;
- const char
- *interface = "org.freedesktop.systemd1.Unit",
- *property = "NeedDaemonReload",
- *path;
- char *n;
- int r;
-
- /* We ignore all errors here, since this is used to show a warning only */
-
- n = unit_name_mangle(unit);
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "GetUnit",
- &reply,
- NULL,
- DBUS_TYPE_STRING, n ? (const char**) &n : &unit,
- DBUS_TYPE_INVALID);
- free(n);
- if (r)
- goto finish;
-
- if (!dbus_message_get_args(reply, NULL,
- DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID))
- goto finish;
-
- dbus_message_unref(reply);
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- path,
- "org.freedesktop.DBus.Properties",
- "Get",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &interface,
- DBUS_TYPE_STRING, &property,
- DBUS_TYPE_INVALID);
- if (r)
- goto finish;
-
- if (!dbus_message_iter_init(reply, &iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
- goto finish;
-
- dbus_message_iter_recurse(&iter, &sub);
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
- goto finish;
-
- dbus_message_iter_get_basic(&sub, &b);
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- return b;
-}
-
-typedef struct WaitData {
- Set *set;
-
- char *name;
- char *result;
-} WaitData;
-
-static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
- DBusError error;
- WaitData *d = data;
-
- assert(connection);
- assert(message);
- assert(d);
-
- dbus_error_init(&error);
-
- log_debug("Got D-Bus request: %s.%s() on %s",
- dbus_message_get_interface(message),
- dbus_message_get_member(message),
- dbus_message_get_path(message));
-
- if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
- log_error("Warning! D-Bus connection terminated.");
- dbus_connection_close(connection);
-
- } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
- uint32_t id;
- const char *path, *result, *unit;
- dbus_bool_t success = true;
-
- if (dbus_message_get_args(message, &error,
- DBUS_TYPE_UINT32, &id,
- DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_STRING, &unit,
- DBUS_TYPE_STRING, &result,
- DBUS_TYPE_INVALID)) {
- char *p;
-
- p = set_remove(d->set, (char*) path);
- free(p);
-
- if (!isempty(result))
- d->result = strdup(result);
-
- if (!isempty(unit))
- d->name = strdup(unit);
-
- goto finish;
- }
-#ifndef LEGACY
- dbus_error_free(&error);
- if (dbus_message_get_args(message, &error,
- DBUS_TYPE_UINT32, &id,
- DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_STRING, &result,
- DBUS_TYPE_INVALID)) {
- char *p;
-
- /* Compatibility with older systemd versions <
- * 183 during upgrades. This should be dropped
- * one day. */
- p = set_remove(d->set, (char*) path);
- free(p);
-
- if (*result)
- d->result = strdup(result);
-
- goto finish;
- }
-
- dbus_error_free(&error);
- if (dbus_message_get_args(message, &error,
- DBUS_TYPE_UINT32, &id,
- DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_BOOLEAN, &success,
- DBUS_TYPE_INVALID)) {
- char *p;
-
- /* Compatibility with older systemd versions <
- * 19 during upgrades. This should be dropped
- * one day */
-
- p = set_remove(d->set, (char*) path);
- free(p);
-
- if (!success)
- d->result = strdup("failed");
-
- goto finish;
- }
-#endif
-
- log_error("Failed to parse message: %s", bus_error_message(&error));
- }
-
-finish:
- dbus_error_free(&error);
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-static int enable_wait_for_jobs(DBusConnection *bus) {
- DBusError error;
-
- assert(bus);
-
- if (private_bus)
- return 0;
-
- dbus_error_init(&error);
- dbus_bus_add_match(bus,
- "type='signal',"
- "sender='org.freedesktop.systemd1',"
- "interface='org.freedesktop.systemd1.Manager',"
- "member='JobRemoved',"
- "path='/org/freedesktop/systemd1'",
- &error);
-
- if (dbus_error_is_set(&error)) {
- log_error("Failed to add match: %s", bus_error_message(&error));
- dbus_error_free(&error);
- return -EIO;
- }
-
- /* This is slightly dirty, since we don't undo the match registrations. */
- return 0;
-}
-
-static int wait_for_jobs(DBusConnection *bus, Set *s) {
- int r = 0;
- WaitData d;
-
- assert(bus);
- assert(s);
-
- zero(d);
- d.set = s;
-
- if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
- return log_oom();
-
- while (!set_isempty(s)) {
-
- if (!dbus_connection_read_write_dispatch(bus, -1)) {
- log_error("Disconnected from bus.");
- return -ECONNREFUSED;
- }
-
- if (!d.result)
- goto free_name;
-
- if (!arg_quiet) {
- if (streq(d.result, "timeout"))
- log_error("Job for %s timed out.", strna(d.name));
- else if (streq(d.result, "canceled"))
- log_error("Job for %s canceled.", strna(d.name));
- else if (streq(d.result, "dependency"))
- log_error("A dependency job for %s failed. See 'journalctl -n' for details.", strna(d.name));
- else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
- log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -n' for details.", strna(d.name), strna(d.name));
- }
-
- if (streq_ptr(d.result, "timeout"))
- r = -ETIME;
- else if (streq_ptr(d.result, "canceled"))
- r = -ECANCELED;
- else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
- r = -EIO;
-
- free(d.result);
- d.result = NULL;
-
- free_name:
- free(d.name);
- d.name = NULL;
- }
-
- dbus_connection_remove_filter(bus, wait_filter, &d);
- return r;
-}
-
-static int check_one_unit(DBusConnection *bus, char *name, bool quiet) {
- DBusMessage *reply = NULL;
- DBusMessageIter iter, sub;
- const char
- *interface = "org.freedesktop.systemd1.Unit",
- *property = "ActiveState";
- const char *path = NULL;
- const char *state;
- int r;
- char *n;
-
- assert(name);
-
- n = unit_name_mangle(name);
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "GetUnit",
- &reply,
- NULL,
- DBUS_TYPE_STRING, n ? &n : &name,
- DBUS_TYPE_INVALID);
- free(n);
- if (r) {
- if ((r != -ENOMEM) && (!quiet))
- puts("unknown");
- goto finish;
- }
-
- if (!dbus_message_get_args(reply, NULL,
- DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID)) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_unref(reply);
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- path,
- "org.freedesktop.DBus.Properties",
- "Get",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &interface,
- DBUS_TYPE_STRING, &property,
- DBUS_TYPE_INVALID);
- if (r)
- goto finish;
-
- if (!dbus_message_iter_init(reply, &iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&iter, &sub);
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_get_basic(&sub, &state);
-
- if (!quiet)
- puts(state);
-
- if (streq(state, "active") || streq(state, "reloading"))
- r = 0;
- else
- r = 3; /* According to LSB: "program is not running" */
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- return r;
-}
-
-static void check_triggering_units(
- DBusConnection *bus,
- const char *unit_name) {
-
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- DBusMessageIter iter, sub;
- char *service_trigger = NULL;
- const char *interface = "org.freedesktop.systemd1.Unit",
- *triggered_by_property = "TriggeredBy";
-
- char _cleanup_free_ *unit_path = NULL, *n = NULL;
- bool print_warning_label = true;
- int r;
-
- n = unit_name_mangle(unit_name);
- if (!n) {
- log_oom();
- return;
- }
-
- unit_path = unit_dbus_path_from_name(n);
- if (!unit_path) {
- log_oom();
- return;
- }
-
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- unit_path,
- "org.freedesktop.DBus.Properties",
- "Get",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &interface,
- DBUS_TYPE_STRING, &triggered_by_property,
- DBUS_TYPE_INVALID);
- if (r)
- return;
-
- if (!dbus_message_iter_init(reply, &iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
- log_error("Failed to parse reply.");
- return;
- }
-
- dbus_message_iter_recurse(&iter, &sub);
- dbus_message_iter_recurse(&sub, &iter);
- sub = iter;
-
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
- log_error("Failed to parse reply.");
- return;
- }
-
- dbus_message_iter_get_basic(&sub, &service_trigger);
-
- r = check_one_unit(bus, service_trigger, true);
- if (r < 0)
- return;
- if (r == 0) {
- if (print_warning_label) {
- log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
- print_warning_label = false;
- }
- log_warning(" %s", service_trigger);
- }
-
- dbus_message_iter_next(&sub);
- }
-}
-
-static int start_unit_one(
- DBusConnection *bus,
- const char *method,
- const char *name,
- const char *mode,
- DBusError *error,
- Set *s) {
-
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- const char *path;
- int r;
- _cleanup_free_ char *n, *p = NULL;
-
- assert(method);
- assert(name);
- assert(mode);
- assert(error);
-
- n = unit_name_mangle(name);
- if (!n)
- return log_oom();
-
- r = bus_method_call_with_reply(
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- method,
- &reply,
- error,
- DBUS_TYPE_STRING, &n,
- DBUS_TYPE_STRING, &mode,
- DBUS_TYPE_INVALID);
- if (r) {
- if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
- /* There's always a fallback possible for
- * legacy actions. */
- r = -EADDRNOTAVAIL;
- else
- log_error("Failed to issue method call: %s", bus_error_message(error));
-
- return r;
- }
-
- if (!dbus_message_get_args(reply, error,
- DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID)) {
- log_error("Failed to parse reply: %s", bus_error_message(error));
- return -EIO;
- }
-
- if (need_daemon_reload(bus, n))
- log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
- n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
-
- if (s) {
- p = strdup(path);
- if (!p)
- return log_oom();
-
- r = set_put(s, p);
- if (r < 0) {
- log_error("Failed to add path to set.");
- return r;
- }
-
- p = NULL;
- }
-
- return 0;
-}
-
-static enum action verb_to_action(const char *verb) {
- if (streq(verb, "halt"))
- return ACTION_HALT;
- else if (streq(verb, "poweroff"))
- return ACTION_POWEROFF;
- else if (streq(verb, "reboot"))
- return ACTION_REBOOT;
- else if (streq(verb, "kexec"))
- return ACTION_KEXEC;
- else if (streq(verb, "rescue"))
- return ACTION_RESCUE;
- else if (streq(verb, "emergency"))
- return ACTION_EMERGENCY;
- else if (streq(verb, "default"))
- return ACTION_DEFAULT;
- else if (streq(verb, "exit"))
- return ACTION_EXIT;
- else if (streq(verb, "suspend"))
- return ACTION_SUSPEND;
- else if (streq(verb, "hibernate"))
- return ACTION_HIBERNATE;
- else if (streq(verb, "hybrid-sleep"))
- return ACTION_HYBRID_SLEEP;
- else
- return ACTION_INVALID;
-}
-
-static int start_unit(DBusConnection *bus, char **args) {
-
- static const char * const table[_ACTION_MAX] = {
- [ACTION_HALT] = SPECIAL_HALT_TARGET,
- [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
- [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
- [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
- [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
- [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
- [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
- [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
- [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
- [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
- [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
- [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
- [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
- [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
- [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
- };
-
- int r, ret = 0;
- const char *method, *mode, *one_name;
- Set *s = NULL;
- DBusError error;
- char **name;
-
- dbus_error_init(&error);
-
- assert(bus);
-
- ask_password_agent_open_if_enabled();
-
- if (arg_action == ACTION_SYSTEMCTL) {
- method =
- streq(args[0], "stop") ||
- streq(args[0], "condstop") ? "StopUnit" :
- streq(args[0], "reload") ? "ReloadUnit" :
- streq(args[0], "restart") ? "RestartUnit" :
-
- streq(args[0], "try-restart") ||
- streq(args[0], "condrestart") ? "TryRestartUnit" :
-
- streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
-
- streq(args[0], "reload-or-try-restart") ||
- streq(args[0], "condreload") ||
-
- streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
- "StartUnit";
-
- mode =
- (streq(args[0], "isolate") ||
- streq(args[0], "rescue") ||
- streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
-
- one_name = table[verb_to_action(args[0])];
-
- } else {
- assert(arg_action < ELEMENTSOF(table));
- assert(table[arg_action]);
-
- method = "StartUnit";
-
- mode = (arg_action == ACTION_EMERGENCY ||
- arg_action == ACTION_RESCUE ||
- arg_action == ACTION_RUNLEVEL2 ||
- arg_action == ACTION_RUNLEVEL3 ||
- arg_action == ACTION_RUNLEVEL4 ||
- arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
-
- one_name = table[arg_action];
- }
-
- if (!arg_no_block) {
- ret = enable_wait_for_jobs(bus);
- if (ret < 0) {
- log_error("Could not watch jobs: %s", strerror(-ret));
- goto finish;
- }
-
- s = set_new(string_hash_func, string_compare_func);
- if (!s) {
- ret = log_oom();
- goto finish;
- }
- }
-
- if (one_name) {
- ret = start_unit_one(bus, method, one_name, mode, &error, s);
- if (ret < 0)
- ret = translate_bus_error_to_exit_status(ret, &error);
- } else {
- STRV_FOREACH(name, args+1) {
- r = start_unit_one(bus, method, *name, mode, &error, s);
- if (r < 0) {
- ret = translate_bus_error_to_exit_status(r, &error);
- dbus_error_free(&error);
- }
- }
- }
-
- if (!arg_no_block) {
- r = wait_for_jobs(bus, s);
- if (r < 0) {
- ret = r;
- goto finish;
- }
-
- /* When stopping units, warn if they can still be triggered by
- * another active unit (socket, path, timer) */
- if (!arg_quiet && streq(method, "StopUnit")) {
- if (one_name)
- check_triggering_units(bus, one_name);
- else
- STRV_FOREACH(name, args+1)
- check_triggering_units(bus, *name);
- }
- }
-
-finish:
- set_free_free(s);
- dbus_error_free(&error);
-
- return ret;
-}
-
-/* Ask systemd-logind, which might grant access to unprivileged users
- * through PolicyKit */
-static int reboot_with_logind(DBusConnection *bus, enum action a) {
-#ifdef HAVE_LOGIND
- const char *method;
- dbus_bool_t interactive = true;
-
- polkit_agent_open_if_enabled();
-
- switch (a) {
-
- case ACTION_REBOOT:
- method = "Reboot";
- break;
-
- case ACTION_POWEROFF:
- method = "PowerOff";
- break;
-
- case ACTION_SUSPEND:
- method = "Suspend";
- break;
-
- case ACTION_HIBERNATE:
- method = "Hibernate";
- break;
-
- case ACTION_HYBRID_SLEEP:
- method = "HybridSleep";
- break;
-
- default:
- return -EINVAL;
- }
-
- return bus_method_call_with_reply (
- bus,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- method,
- NULL,
- NULL,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID);
-#else
- return -ENOSYS;
-#endif
-}
-
-static int start_special(DBusConnection *bus, char **args) {
- enum action a;
- int r;
-
- assert(args);
-
- a = verb_to_action(args[0]);
-
- if (arg_force >= 2 && geteuid() != 0) {
- log_error("Must be root.");
- return -EPERM;
- }
-
- if (arg_force >= 2 &&
- (a == ACTION_HALT ||
- a == ACTION_POWEROFF ||
- a == ACTION_REBOOT))
- halt_now(a);
-
- if (arg_force >= 1 &&
- (a == ACTION_HALT ||
- a == ACTION_POWEROFF ||
- a == ACTION_REBOOT ||
- a == ACTION_KEXEC ||
- a == ACTION_EXIT))
- return daemon_reload(bus, args);
-
- /* first try logind, to allow authentication with polkit */
- if (geteuid() != 0 &&
- (a == ACTION_POWEROFF ||
- a == ACTION_REBOOT ||
- a == ACTION_SUSPEND ||
- a == ACTION_HIBERNATE ||
- a == ACTION_HYBRID_SLEEP)) {
- r = reboot_with_logind(bus, a);
- if (r >= 0)
- return r;
- }
-
- r = start_unit(bus, args);
- if (r >= 0)
- warn_wall(a);
-
- return r;
-}
-
-static int check_unit(DBusConnection *bus, char **args) {
- char **name;
- int r = 3; /* According to LSB: "program is not running" */
-
- assert(bus);
- assert(args);
-
- STRV_FOREACH(name, args+1) {
- int state = check_one_unit(bus, *name, arg_quiet);
- if (state < 0)
- return state;
- if (state == 0)
- r = 0;
- }
-
- return r;
-}
-
-static int kill_unit(DBusConnection *bus, char **args) {
- int r = 0;
- char **name, *n;
-
- assert(args);
-
- if (!arg_kill_who)
- arg_kill_who = "all";
-
- STRV_FOREACH(name, args+1) {
- n = unit_name_mangle(*name);
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "KillUnit",
- NULL,
- NULL,
- DBUS_TYPE_STRING, n ? &n : name,
- DBUS_TYPE_STRING, &arg_kill_who,
- DBUS_TYPE_INT32, &arg_signal,
- DBUS_TYPE_INVALID);
- free(n);
- if (r)
- return r;
- }
- return 0;
-}
-
-typedef struct ExecStatusInfo {
- char *name;
-
- char *path;
- char **argv;
-
- bool ignore;
-
- usec_t start_timestamp;
- usec_t exit_timestamp;
- pid_t pid;
- int code;
- int status;
-
- LIST_FIELDS(struct ExecStatusInfo, exec);
-} ExecStatusInfo;
-
-static void exec_status_info_free(ExecStatusInfo *i) {
- assert(i);
-
- free(i->name);
- free(i->path);
- strv_free(i->argv);
- free(i);
-}
-
-static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
- uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
- DBusMessageIter sub2, sub3;
- const char*path;
- unsigned n;
- uint32_t pid;
- int32_t code, status;
- dbus_bool_t ignore;
-
- assert(i);
- assert(i);
-
- if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
- return -EIO;
-
- dbus_message_iter_recurse(sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
- return -EIO;
-
- if (!(i->path = strdup(path)))
- return -ENOMEM;
-
- if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
- return -EIO;
-
- n = 0;
- dbus_message_iter_recurse(&sub2, &sub3);
- while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
- assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
- dbus_message_iter_next(&sub3);
- n++;
- }
-
-
- if (!(i->argv = new0(char*, n+1)))
- return -ENOMEM;
-
- n = 0;
- dbus_message_iter_recurse(&sub2, &sub3);
- while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
- const char *s;
-
- assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
- dbus_message_iter_get_basic(&sub3, &s);
- dbus_message_iter_next(&sub3);
-
- if (!(i->argv[n++] = strdup(s)))
- return -ENOMEM;
- }
-
- if (!dbus_message_iter_next(&sub2) ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
- return -EIO;
-
- i->ignore = ignore;
- i->start_timestamp = (usec_t) start_timestamp;
- i->exit_timestamp = (usec_t) exit_timestamp;
- i->pid = (pid_t) pid;
- i->code = code;
- i->status = status;
-
- return 0;
-}
-
-typedef struct UnitStatusInfo {
- const char *id;
- const char *load_state;
- const char *active_state;
- const char *sub_state;
- const char *unit_file_state;
-
- const char *description;
- const char *following;
-
- char **documentation;
-
- const char *fragment_path;
- const char *source_path;
- const char *default_control_group;
-
- const char *load_error;
- const char *result;
-
- usec_t inactive_exit_timestamp;
- usec_t inactive_exit_timestamp_monotonic;
- usec_t active_enter_timestamp;
- usec_t active_exit_timestamp;
- usec_t inactive_enter_timestamp;
-
- bool need_daemon_reload;
-
- /* Service */
- pid_t main_pid;
- pid_t control_pid;
- const char *status_text;
- bool running:1;
-
- usec_t start_timestamp;
- usec_t exit_timestamp;
-
- int exit_code, exit_status;
-
- usec_t condition_timestamp;
- bool condition_result;
-
- /* Socket */
- unsigned n_accepted;
- unsigned n_connections;
- bool accept;
-
- /* Device */
- const char *sysfs_path;
-
- /* Mount, Automount */
- const char *where;
-
- /* Swap */
- const char *what;
-
- LIST_HEAD(ExecStatusInfo, exec);
-} UnitStatusInfo;
-
-static void print_status_info(UnitStatusInfo *i) {
- ExecStatusInfo *p;
- const char *on, *off, *ss;
- usec_t timestamp;
- char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
- char since2[FORMAT_TIMESTAMP_MAX], *s2;
- const char *path;
-
- assert(i);
-
- /* This shows pretty information about a unit. See
- * print_property() for a low-level property printer */
-
- printf("%s", strna(i->id));
-
- if (i->description && !streq_ptr(i->id, i->description))
- printf(" - %s", i->description);
-
- printf("\n");
-
- if (i->following)
- printf("\t Follow: unit currently follows state of %s\n", i->following);
-
- if (streq_ptr(i->load_state, "error")) {
- on = ansi_highlight_red(true);
- off = ansi_highlight_red(false);
- } else
- on = off = "";
-
- path = i->source_path ? i->source_path : i->fragment_path;
-
- if (i->load_error)
- printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
- else if (path && i->unit_file_state)
- printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
- else if (path)
- printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
- else
- printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
-
- ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
-
- if (streq_ptr(i->active_state, "failed")) {
- on = ansi_highlight_red(true);
- off = ansi_highlight_red(false);
- } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
- on = ansi_highlight_green(true);
- off = ansi_highlight_green(false);
- } else
- on = off = "";
-
- if (ss)
- printf("\t Active: %s%s (%s)%s",
- on,
- strna(i->active_state),
- ss,
- off);
- else
- printf("\t Active: %s%s%s",
- on,
- strna(i->active_state),
- off);
-
- if (!isempty(i->result) && !streq(i->result, "success"))
- printf(" (Result: %s)", i->result);
-
- timestamp = (streq_ptr(i->active_state, "active") ||
- streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
- (streq_ptr(i->active_state, "inactive") ||
- streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
- streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
- i->active_exit_timestamp;
-
- s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
- s2 = format_timestamp(since2, sizeof(since2), timestamp);
-
- if (s1)
- printf(" since %s; %s\n", s2, s1);
- else if (s2)
- printf(" since %s\n", s2);
- else
- printf("\n");
-
- if (!i->condition_result && i->condition_timestamp > 0) {
- s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
- s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
-
- if (s1)
- printf("\t start condition failed at %s; %s\n", s2, s1);
- else if (s2)
- printf("\t start condition failed at %s\n", s2);
- }
-
- if (i->sysfs_path)
- printf("\t Device: %s\n", i->sysfs_path);
- if (i->where)
- printf("\t Where: %s\n", i->where);
- if (i->what)
- printf("\t What: %s\n", i->what);
-
- if (!strv_isempty(i->documentation)) {
- char **t;
- bool first = true;
-
- STRV_FOREACH(t, i->documentation) {
- if (first) {
- printf("\t Docs: %s\n", *t);
- first = false;
- } else
- printf("\t %s\n", *t);
- }
- }
-
- if (i->accept)
- printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
-
- LIST_FOREACH(exec, p, i->exec) {
- char *t;
- bool good;
-
- /* Only show exited processes here */
- if (p->code == 0)
- continue;
-
- t = strv_join(p->argv, " ");
- printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
- free(t);
-
- good = is_clean_exit_lsb(p->code, p->status, NULL);
- if (!good) {
- on = ansi_highlight_red(true);
- off = ansi_highlight_red(false);
- } else
- on = off = "";
-
- printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
-
- if (p->code == CLD_EXITED) {
- const char *c;
-
- printf("status=%i", p->status);
-
- c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
- if (c)
- printf("/%s", c);
-
- } else
- printf("signal=%s", signal_to_string(p->status));
-
- printf(")%s\n", off);
-
- if (i->main_pid == p->pid &&
- i->start_timestamp == p->start_timestamp &&
- i->exit_timestamp == p->start_timestamp)
- /* Let's not show this twice */
- i->main_pid = 0;
-
- if (p->pid == i->control_pid)
- i->control_pid = 0;
- }
-
- if (i->main_pid > 0 || i->control_pid > 0) {
- printf("\t");
-
- if (i->main_pid > 0) {
- printf("Main PID: %u", (unsigned) i->main_pid);
-
- if (i->running) {
- char *t = NULL;
- get_process_comm(i->main_pid, &t);
- if (t) {
- printf(" (%s)", t);
- free(t);
- }
- } else if (i->exit_code > 0) {
- printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
-
- if (i->exit_code == CLD_EXITED) {
- const char *c;
-
- printf("status=%i", i->exit_status);
-
- c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
- if (c)
- printf("/%s", c);
-
- } else
- printf("signal=%s", signal_to_string(i->exit_status));
- printf(")");
- }
- }
-
- if (i->main_pid > 0 && i->control_pid > 0)
- printf(";");
-
- if (i->control_pid > 0) {
- char *t = NULL;
-
- printf(" Control: %u", (unsigned) i->control_pid);
-
- get_process_comm(i->control_pid, &t);
- if (t) {
- printf(" (%s)", t);
- free(t);
- }
- }
-
- printf("\n");
- }
-
- if (i->status_text)
- printf("\t Status: \"%s\"\n", i->status_text);
-
- if (i->default_control_group) {
- unsigned c;
-
- printf("\t CGroup: %s\n", i->default_control_group);
-
- if (arg_transport != TRANSPORT_SSH) {
- unsigned k = 0;
- pid_t extra[2];
-
- c = columns();
- if (c > 18)
- c -= 18;
- else
- c = 0;
-
- if (i->main_pid > 0)
- extra[k++] = i->main_pid;
-
- if (i->control_pid > 0)
- extra[k++] = i->control_pid;
-
- show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
- }
- }
-
- if (i->id && arg_transport != TRANSPORT_SSH) {
- int flags =
- arg_all * OUTPUT_SHOW_ALL |
- (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
- on_tty() * OUTPUT_COLOR |
- !arg_quiet * OUTPUT_WARN_CUTOFF;
-
- printf("\n");
- show_journal_by_unit(stdout,
- i->id,
- arg_output,
- 0,
- i->inactive_exit_timestamp_monotonic,
- arg_lines,
- flags);
- }
-
- if (i->need_daemon_reload)
- printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
- ansi_highlight_red(true),
- ansi_highlight_red(false),
- arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
-}
-
-static void show_unit_help(UnitStatusInfo *i) {
- char **p;
-
- assert(i);
-
- if (!i->documentation) {
- log_info("Documentation for %s not known.", i->id);
- return;
- }
-
- STRV_FOREACH(p, i->documentation) {
-
- if (startswith(*p, "man:")) {
- size_t k;
- char *e = NULL;
- char *page = NULL, *section = NULL;
- const char *args[4] = { "man", NULL, NULL, NULL };
- pid_t pid;
-
- k = strlen(*p);
-
- if ((*p)[k-1] == ')')
- e = strrchr(*p, '(');
-
- if (e) {
- page = strndup((*p) + 4, e - *p - 4);
- if (!page) {
- log_oom();
- return;
- }
-
- section = strndup(e + 1, *p + k - e - 2);
- if (!section) {
- free(page);
- log_oom();
- return;
- }
-
- args[1] = section;
- args[2] = page;
- } else
- args[1] = *p + 4;
-
- pid = fork();
- if (pid < 0) {
- log_error("Failed to fork: %m");
- free(page);
- free(section);
- continue;
- }
-
- if (pid == 0) {
- /* Child */
- execvp(args[0], (char**) args);
- log_error("Failed to execute man: %m");
- _exit(EXIT_FAILURE);
- }
-
- free(page);
- free(section);
-
- wait_for_terminate(pid, NULL);
- } else
- log_info("Can't show: %s", *p);
- }
-}
-
-static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
-
- assert(name);
- assert(iter);
- assert(i);
-
- switch (dbus_message_iter_get_arg_type(iter)) {
-
- case DBUS_TYPE_STRING: {
- const char *s;
-
- dbus_message_iter_get_basic(iter, &s);
-
- if (!isempty(s)) {
- if (streq(name, "Id"))
- i->id = s;
- else if (streq(name, "LoadState"))
- i->load_state = s;
- else if (streq(name, "ActiveState"))
- i->active_state = s;
- else if (streq(name, "SubState"))
- i->sub_state = s;
- else if (streq(name, "Description"))
- i->description = s;
- else if (streq(name, "FragmentPath"))
- i->fragment_path = s;
- else if (streq(name, "SourcePath"))
- i->source_path = s;
- else if (streq(name, "DefaultControlGroup"))
- i->default_control_group = s;
- else if (streq(name, "StatusText"))
- i->status_text = s;
- else if (streq(name, "SysFSPath"))
- i->sysfs_path = s;
- else if (streq(name, "Where"))
- i->where = s;
- else if (streq(name, "What"))
- i->what = s;
- else if (streq(name, "Following"))
- i->following = s;
- else if (streq(name, "UnitFileState"))
- i->unit_file_state = s;
- else if (streq(name, "Result"))
- i->result = s;
- }
-
- break;
- }
-
- case DBUS_TYPE_BOOLEAN: {
- dbus_bool_t b;
-
- dbus_message_iter_get_basic(iter, &b);
-
- if (streq(name, "Accept"))
- i->accept = b;
- else if (streq(name, "NeedDaemonReload"))
- i->need_daemon_reload = b;
- else if (streq(name, "ConditionResult"))
- i->condition_result = b;
-
- break;
- }
-
- case DBUS_TYPE_UINT32: {
- uint32_t u;
-
- dbus_message_iter_get_basic(iter, &u);
-
- if (streq(name, "MainPID")) {
- if (u > 0) {
- i->main_pid = (pid_t) u;
- i->running = true;
- }
- } else if (streq(name, "ControlPID"))
- i->control_pid = (pid_t) u;
- else if (streq(name, "ExecMainPID")) {
- if (u > 0)
- i->main_pid = (pid_t) u;
- } else if (streq(name, "NAccepted"))
- i->n_accepted = u;
- else if (streq(name, "NConnections"))
- i->n_connections = u;
-
- break;
- }
-
- case DBUS_TYPE_INT32: {
- int32_t j;
-
- dbus_message_iter_get_basic(iter, &j);
-
- if (streq(name, "ExecMainCode"))
- i->exit_code = (int) j;
- else if (streq(name, "ExecMainStatus"))
- i->exit_status = (int) j;
-
- break;
- }
-
- case DBUS_TYPE_UINT64: {
- uint64_t u;
-
- dbus_message_iter_get_basic(iter, &u);
-
- if (streq(name, "ExecMainStartTimestamp"))
- i->start_timestamp = (usec_t) u;
- else if (streq(name, "ExecMainExitTimestamp"))
- i->exit_timestamp = (usec_t) u;
- else if (streq(name, "ActiveEnterTimestamp"))
- i->active_enter_timestamp = (usec_t) u;
- else if (streq(name, "InactiveEnterTimestamp"))
- i->inactive_enter_timestamp = (usec_t) u;
- else if (streq(name, "InactiveExitTimestamp"))
- i->inactive_exit_timestamp = (usec_t) u;
- else if (streq(name, "InactiveExitTimestampMonotonic"))
- i->inactive_exit_timestamp_monotonic = (usec_t) u;
- else if (streq(name, "ActiveExitTimestamp"))
- i->active_exit_timestamp = (usec_t) u;
- else if (streq(name, "ConditionTimestamp"))
- i->condition_timestamp = (usec_t) u;
-
- break;
- }
-
- case DBUS_TYPE_ARRAY: {
-
- if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
- startswith(name, "Exec")) {
- DBusMessageIter sub;
-
- dbus_message_iter_recurse(iter, &sub);
- while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
- ExecStatusInfo *info;
- int r;
-
- if (!(info = new0(ExecStatusInfo, 1)))
- return -ENOMEM;
-
- if (!(info->name = strdup(name))) {
- free(info);
- return -ENOMEM;
- }
-
- if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
- free(info);
- return r;
- }
-
- LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
-
- dbus_message_iter_next(&sub);
- }
- } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
- streq(name, "Documentation")) {
-
- DBusMessageIter sub;
-
- dbus_message_iter_recurse(iter, &sub);
- while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
- const char *s;
- char **l;
-
- dbus_message_iter_get_basic(&sub, &s);
-
- l = strv_append(i->documentation, s);
- if (!l)
- return -ENOMEM;
-
- strv_free(i->documentation);
- i->documentation = l;
-
- dbus_message_iter_next(&sub);
- }
- }
-
- break;
- }
-
- case DBUS_TYPE_STRUCT: {
-
- if (streq(name, "LoadError")) {
- DBusMessageIter sub;
- const char *n, *message;
- int r;
-
- dbus_message_iter_recurse(iter, &sub);
-
- r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
- if (r < 0)
- return r;
-
- r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
- if (r < 0)
- return r;
-
- if (!isempty(message))
- i->load_error = message;
- }
-
- break;
- }
- }
-
- return 0;
-}
-
-static int print_property(const char *name, DBusMessageIter *iter) {
- assert(name);
- assert(iter);
-
- /* This is a low-level property printer, see
- * print_status_info() for the nicer output */
-
- if (arg_property && !strv_find(arg_property, name))
- return 0;
-
- switch (dbus_message_iter_get_arg_type(iter)) {
-
- case DBUS_TYPE_STRUCT: {
- DBusMessageIter sub;
- dbus_message_iter_recurse(iter, &sub);
-
- if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
- uint32_t u;
-
- dbus_message_iter_get_basic(&sub, &u);
-
- if (u)
- printf("%s=%u\n", name, (unsigned) u);
- else if (arg_all)
- printf("%s=\n", name);
-
- return 0;
- } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
- const char *s;
-
- dbus_message_iter_get_basic(&sub, &s);
-
- if (arg_all || s[0])
- printf("%s=%s\n", name, s);
-
- return 0;
- } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
- const char *a = NULL, *b = NULL;
-
- if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
- bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
-
- if (arg_all || !isempty(a) || !isempty(b))
- printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
-
- return 0;
- }
-
- break;
- }
-
- case DBUS_TYPE_ARRAY:
-
- if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
- DBusMessageIter sub, sub2;
-
- dbus_message_iter_recurse(iter, &sub);
- while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
- const char *path;
- dbus_bool_t ignore;
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
- printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
-
- dbus_message_iter_next(&sub);
- }
-
- return 0;
-
- } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
- DBusMessageIter sub, sub2;
-
- dbus_message_iter_recurse(iter, &sub);
- while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
- const char *type, *path;
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
- printf("%s=%s\n", type, path);
-
- dbus_message_iter_next(&sub);
- }
-
- return 0;
-
- } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
- DBusMessageIter sub, sub2;
-
- dbus_message_iter_recurse(iter, &sub);
- while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
- const char *base;
- uint64_t value, next_elapse;
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
- char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
-
- printf("%s={ value=%s ; next_elapse=%s }\n",
- base,
- format_timespan(timespan1, sizeof(timespan1), value),
- format_timespan(timespan2, sizeof(timespan2), next_elapse));
- }
-
- dbus_message_iter_next(&sub);
- }
-
- return 0;
-
- } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
- DBusMessageIter sub, sub2;
-
- dbus_message_iter_recurse(iter, &sub);
- while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
- const char *controller, *attr, *value;
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
-
- printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
- controller,
- attr,
- value);
- }
-
- dbus_message_iter_next(&sub);
- }
-
- return 0;
-
- } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
- DBusMessageIter sub;
-
- dbus_message_iter_recurse(iter, &sub);
- while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
- ExecStatusInfo info;
-
- zero(info);
- if (exec_status_info_deserialize(&sub, &info) >= 0) {
- char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
- char *t;
-
- t = strv_join(info.argv, " ");
-
- printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
- name,
- strna(info.path),
- strna(t),
- yes_no(info.ignore),
- strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
- strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
- (unsigned) info. pid,
- sigchld_code_to_string(info.code),
- info.status,
- info.code == CLD_EXITED ? "" : "/",
- strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
-
- free(t);
- }
-
- free(info.path);
- strv_free(info.argv);
-
- dbus_message_iter_next(&sub);
- }
-
- return 0;
- }
-
- break;
- }
-
- if (generic_print_property(name, iter, arg_all) > 0)
- return 0;
-
- if (arg_all)
- printf("%s=[unprintable]\n", name);
-
- return 0;
-}
-
-static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
- DBusMessage *reply = NULL;
- const char *interface = "";
- int r;
- DBusMessageIter iter, sub, sub2, sub3;
- UnitStatusInfo info;
- ExecStatusInfo *p;
-
- assert(path);
- assert(new_line);
-
- zero(info);
-
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- path,
- "org.freedesktop.DBus.Properties",
- "GetAll",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &interface,
- DBUS_TYPE_INVALID);
- if (r)
- goto finish;
-
- if (!dbus_message_iter_init(reply, &iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&iter, &sub);
-
- if (*new_line)
- printf("\n");
-
- *new_line = true;
-
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- const char *name;
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&sub2, &sub3);
-
- if (show_properties)
- r = print_property(name, &sub3);
- else
- r = status_property(name, &sub3, &info);
-
- if (r < 0) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_next(&sub);
- }
-
- r = 0;
-
- if (!show_properties) {
- if (streq(verb, "help"))
- show_unit_help(&info);
- else
- print_status_info(&info);
- }
-
- strv_free(info.documentation);
-
- if (!streq_ptr(info.active_state, "active") &&
- !streq_ptr(info.active_state, "reloading") &&
- streq(verb, "status"))
- /* According to LSB: "program not running" */
- r = 3;
-
- while ((p = info.exec)) {
- LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
- exec_status_info_free(p);
- }
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- return r;
-}
-
-static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
- DBusMessage *reply = NULL;
- const char *path = NULL;
- DBusError error;
- int r;
-
- dbus_error_init(&error);
-
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "GetUnitByPID",
- &reply,
- NULL,
- DBUS_TYPE_UINT32, &pid,
- DBUS_TYPE_INVALID);
- if (r)
- goto finish;
-
- if (!dbus_message_get_args(reply, &error,
- DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID)) {
- log_error("Failed to parse reply: %s", bus_error_message(&error));
- r = -EIO;
- goto finish;
- }
-
- r = show_one(verb, bus, path, false, new_line);
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- dbus_error_free(&error);
-
- return r;
-}
-
-static int show(DBusConnection *bus, char **args) {
- int r, ret = 0;
- bool show_properties, new_line = false;
- char **name;
-
- assert(bus);
- assert(args);
-
- show_properties = streq(args[0], "show");
-
- if (show_properties)
- pager_open_if_enabled();
-
- if (show_properties && strv_length(args) <= 1) {
- /* If not argument is specified inspect the manager
- * itself */
-
- return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
- }
-
- STRV_FOREACH(name, args+1) {
- uint32_t id;
-
- if (safe_atou32(*name, &id) < 0) {
- char *p, *n;
- /* Interpret as unit name */
-
- n = unit_name_mangle(*name);
- p = unit_dbus_path_from_name(n ? n : *name);
- free(n);
- if (!p)
- return log_oom();
-
- r = show_one(args[0], bus, p, show_properties, &new_line);
- free(p);
-
- if (r != 0)
- ret = r;
-
- } else if (show_properties) {
-
- /* Interpret as job id */
-
- char *p;
- if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
- return log_oom();
-
- r = show_one(args[0], bus, p, show_properties, &new_line);
- free(p);
-
- if (r != 0)
- ret = r;
-
- } else {
-
- /* Interpret as PID */
-
- r = show_one_by_pid(args[0], bus, id, &new_line);
- if (r != 0)
- ret = r;
- }
- }
-
- return ret;
-}
-
-static int dump(DBusConnection *bus, char **args) {
- DBusMessage *reply = NULL;
- DBusError error;
- int r;
- const char *text;
-
- dbus_error_init(&error);
-
- pager_open_if_enabled();
-
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "Dump",
- &reply,
- NULL,
- DBUS_TYPE_INVALID);
- if (r)
- goto finish;
-
- if (!dbus_message_get_args(reply, &error,
- DBUS_TYPE_STRING, &text,
- DBUS_TYPE_INVALID)) {
- log_error("Failed to parse reply: %s", bus_error_message(&error));
- r = -EIO;
- goto finish;
- }
-
- fputs(text, stdout);
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- dbus_error_free(&error);
-
- return r;
-}
-
-static int snapshot(DBusConnection *bus, char **args) {
- DBusMessage *reply = NULL;
- DBusError error;
- int r;
- dbus_bool_t cleanup = FALSE;
- DBusMessageIter iter, sub;
- const char
- *name = "", *path, *id,
- *interface = "org.freedesktop.systemd1.Unit",
- *property = "Id";
- char *n;
-
- dbus_error_init(&error);
-
- if (strv_length(args) > 1)
- name = args[1];
-
- n = unit_name_mangle(name);
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "CreateSnapshot",
- &reply,
- NULL,
- DBUS_TYPE_STRING, n ? (const char**) &n : &name,
- DBUS_TYPE_BOOLEAN, &cleanup,
- DBUS_TYPE_INVALID);
- free(n);
- if (r)
- goto finish;
-
- if (!dbus_message_get_args(reply, &error,
- DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID)) {
- log_error("Failed to parse reply: %s", bus_error_message(&error));
- r = -EIO;
- goto finish;
- }
-
- dbus_message_unref(reply);
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- path,
- "org.freedesktop.DBus.Properties",
- "Get",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &interface,
- DBUS_TYPE_STRING, &property,
- DBUS_TYPE_INVALID);
- if (r)
- goto finish;
-
- if (!dbus_message_iter_init(reply, &iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&iter, &sub);
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_get_basic(&sub, &id);
-
- if (!arg_quiet)
- puts(id);
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- dbus_error_free(&error);
-
- return r;
-}
-
-static int delete_snapshot(DBusConnection *bus, char **args) {
- DBusMessage *reply = NULL;
- int r = 0;
- DBusError error;
- char **name;
-
- assert(args);
-
- dbus_error_init(&error);
-
- STRV_FOREACH(name, args+1) {
- const char *path = NULL;
- char *n;
-
- n = unit_name_mangle(*name);
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "GetUnit",
- &reply,
- NULL,
- DBUS_TYPE_STRING, n ? &n : name,
- DBUS_TYPE_INVALID);
- free(n);
- if (r)
- goto finish;
-
- if (!dbus_message_get_args(reply, &error,
- DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID)) {
- log_error("Failed to parse reply: %s", bus_error_message(&error));
- r = -EIO;
- dbus_message_unref(reply);
- dbus_error_free(&error);
- goto finish;
- }
- dbus_message_unref(reply);
-
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- path,
- "org.freedesktop.systemd1.Snapshot",
- "Remove",
- NULL,
- NULL,
- DBUS_TYPE_INVALID);
- if (r)
- goto finish;
- }
-
-finish:
- return r;
-}
-
-static int daemon_reload(DBusConnection *bus, char **args) {
- int r;
- const char *method;
- DBusError error;
-
- if (arg_action == ACTION_RELOAD)
- method = "Reload";
- else if (arg_action == ACTION_REEXEC)
- method = "Reexecute";
- else {
- assert(arg_action == ACTION_SYSTEMCTL);
-
- method =
- streq(args[0], "clear-jobs") ||
- streq(args[0], "cancel") ? "ClearJobs" :
- streq(args[0], "daemon-reexec") ? "Reexecute" :
- streq(args[0], "reset-failed") ? "ResetFailed" :
- streq(args[0], "halt") ? "Halt" :
- streq(args[0], "poweroff") ? "PowerOff" :
- streq(args[0], "reboot") ? "Reboot" :
- streq(args[0], "kexec") ? "KExec" :
- streq(args[0], "exit") ? "Exit" :
- /* "daemon-reload" */ "Reload";
- }
-
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- method,
- NULL,
- &error,
- DBUS_TYPE_INVALID);
-
- if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
- /* There's always a fallback possible for
- * legacy actions. */
- r = -EADDRNOTAVAIL;
- else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
- /* On reexecution, we expect a disconnect, not
- * a reply */
- r = 0;
- else if (r)
- log_error("Failed to issue method call: %s", bus_error_message(&error));
- dbus_error_free(&error);
-
- return r;
-}
-
-static int reset_failed(DBusConnection *bus, char **args) {
- int r = 0;
- char **name, *n;
-
- if (strv_length(args) <= 1)
- return daemon_reload(bus, args);
-
- STRV_FOREACH(name, args+1) {
- n = unit_name_mangle(*name);
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "ResetFailedUnit",
- NULL,
- NULL,
- DBUS_TYPE_STRING, n ? &n : name,
- DBUS_TYPE_INVALID);
- free(n);
- if (r)
- goto finish;
- }
-
-finish:
- return r;
-}
-
-static int show_enviroment(DBusConnection *bus, char **args) {
- DBusMessage *reply = NULL;
- DBusMessageIter iter, sub, sub2;
- int r;
- const char
- *interface = "org.freedesktop.systemd1.Manager",
- *property = "Environment";
-
- pager_open_if_enabled();
-
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.DBus.Properties",
- "Get",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &interface,
- DBUS_TYPE_STRING, &property,
- DBUS_TYPE_INVALID);
- if (r)
- goto finish;
-
- if (!dbus_message_iter_init(reply, &iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&iter, &sub);
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
- const char *text;
-
- if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_get_basic(&sub2, &text);
- printf("%s\n", text);
-
- dbus_message_iter_next(&sub2);
- }
-
- r = 0;
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- return r;
-}
-
-static int switch_root(DBusConnection *bus, char **args) {
- unsigned l;
- const char *root, *init;
-
- l = strv_length(args);
- if (l < 2 || l > 3) {
- log_error("Wrong number of arguments.");
- return -EINVAL;
- }
-
- root = args[1];
- init = l >= 3 ? args[2] : "";
-
- return bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "SwitchRoot",
- NULL,
- NULL,
- DBUS_TYPE_STRING, &root,
- DBUS_TYPE_STRING, &init,
- DBUS_TYPE_INVALID);
-}
-
-static int set_environment(DBusConnection *bus, char **args) {
- _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
- DBusError error;
- const char *method;
- DBusMessageIter iter;
- int r;
-
- assert(bus);
-
- dbus_error_init(&error);
-
- method = streq(args[0], "set-environment")
- ? "SetEnvironment"
- : "UnsetEnvironment";
-
- m = dbus_message_new_method_call(
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- method);
- if (!m)
- return log_oom();
-
- dbus_message_iter_init_append(m, &iter);
-
- r = bus_append_strv_iter(&iter, args + 1);
- if (r < 0)
- return log_oom();
-
- reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
- if (!reply) {
- log_error("Failed to issue method call: %s", bus_error_message(&error));
- r = -EIO;
- goto finish;
- }
-
- r = 0;
-
-finish:
- dbus_error_free(&error);
- return r;
-}
-
-static int enable_sysv_units(char **args) {
- int r = 0;
-
-#if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
- const char *verb = args[0];
- unsigned f = 1, t = 1;
- LookupPaths paths;
-
- if (arg_scope != UNIT_FILE_SYSTEM)
- return 0;
-
- if (!streq(verb, "enable") &&
- !streq(verb, "disable") &&
- !streq(verb, "is-enabled"))
- return 0;
-
- /* Processes all SysV units, and reshuffles the array so that
- * afterwards only the native units remain */
-
- zero(paths);
- r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
- if (r < 0)
- return r;
-
- r = 0;
- for (f = 1; args[f]; f++) {
- const char *name;
- char *p;
- bool found_native = false, found_sysv;
- unsigned c = 1;
- const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
- char **k, *l, *q = NULL;
- int j;
- pid_t pid;
- siginfo_t status;
-
- name = args[f];
-
- if (!endswith(name, ".service"))
- continue;
-
- if (path_is_absolute(name))
- continue;
-
- STRV_FOREACH(k, paths.unit_path) {
- p = NULL;
-
- if (!isempty(arg_root))
- asprintf(&p, "%s/%s/%s", arg_root, *k, name);
- else
- asprintf(&p, "%s/%s", *k, name);
-
- if (!p) {
- r = log_oom();
- goto finish;
- }
-
- found_native = access(p, F_OK) >= 0;
- free(p);
-
- if (found_native)
- break;
- }
-
- if (found_native)
- continue;
-
- p = NULL;
- if (!isempty(arg_root))
- asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
- else
- asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
- if (!p) {
- r = log_oom();
- goto finish;
- }
-
- p[strlen(p) - sizeof(".service") + 1] = 0;
- found_sysv = access(p, F_OK) >= 0;
-
- if (!found_sysv) {
- free(p);
- continue;
- }
-
- /* Mark this entry, so that we don't try enabling it as native unit */
- args[f] = (char*) "";
-
- log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
-
- if (!isempty(arg_root))
- argv[c++] = q = strappend("--root=", arg_root);
-
- argv[c++] = path_get_file_name(p);
- argv[c++] =
- streq(verb, "enable") ? "on" :
- streq(verb, "disable") ? "off" : "--level=5";
- argv[c] = NULL;
-
- l = strv_join((char**)argv, " ");
- if (!l) {
- free(q);
- free(p);
- r = log_oom();
- goto finish;
- }
-
- log_info("Executing %s", l);
- free(l);
-
- pid = fork();
- if (pid < 0) {
- log_error("Failed to fork: %m");
- free(p);
- free(q);
- r = -errno;
- goto finish;
- } else if (pid == 0) {
- /* Child */
-
- execv(argv[0], (char**) argv);
- _exit(EXIT_FAILURE);
- }
-
- free(p);
- free(q);
-
- j = wait_for_terminate(pid, &status);
- if (j < 0) {
- log_error("Failed to wait for child: %s", strerror(-r));
- r = j;
- goto finish;
- }
-
- if (status.si_code == CLD_EXITED) {
- if (streq(verb, "is-enabled")) {
- if (status.si_status == 0) {
- if (!arg_quiet)
- puts("enabled");
- r = 1;
- } else {
- if (!arg_quiet)
- puts("disabled");
- }
-
- } else if (status.si_status != 0) {
- r = -EINVAL;
- goto finish;
- }
- } else {
- r = -EPROTO;
- goto finish;
- }
- }
-
-finish:
- lookup_paths_free(&paths);
-
- /* Drop all SysV units */
- for (f = 1, t = 1; args[f]; f++) {
-
- if (isempty(args[f]))
- continue;
-
- args[t++] = args[f];
- }
-
- args[t] = NULL;
-
-#endif
- return r;
-}
-
-static int mangle_names(char **original_names, char ***mangled_names) {
- char **i, **l, **name;
-
- l = new(char*, strv_length(original_names) + 1);
- if (!l)
- return log_oom();
-
- i = l;
- STRV_FOREACH(name, original_names) {
-
- /* When enabling units qualified path names are OK,
- * too, hence allow them explicitly. */
-
- if (is_path(*name))
- *i = strdup(*name);
- else
- *i = unit_name_mangle(*name);
-
- if (!*i) {
- strv_free(l);
- return log_oom();
- }
-
- i++;
- }
-
- *i = NULL;
- *mangled_names = l;
-
- return 0;
-}
-
-static int enable_unit(DBusConnection *bus, char **args) {
- const char *verb = args[0];
- UnitFileChange *changes = NULL;
- unsigned n_changes = 0, i;
- int carries_install_info = -1;
- DBusMessage *m = NULL, *reply = NULL;
- int r;
- DBusError error;
- char **mangled_names = NULL;
-
- r = enable_sysv_units(args);
- if (r < 0)
- return r;
-
- if (!args[1])
- return 0;
-
- dbus_error_init(&error);
-
- if (!bus || avoid_bus()) {
- if (streq(verb, "enable")) {
- r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
- carries_install_info = r;
- } else if (streq(verb, "disable"))
- r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
- else if (streq(verb, "reenable")) {
- r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
- carries_install_info = r;
- } else if (streq(verb, "link"))
- r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
- else if (streq(verb, "preset")) {
- r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
- carries_install_info = r;
- } else if (streq(verb, "mask"))
- r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
- else if (streq(verb, "unmask"))
- r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
- else
- assert_not_reached("Unknown verb");
-
- if (r < 0) {
- log_error("Operation failed: %s", strerror(-r));
- goto finish;
- }
-
- if (!arg_quiet) {
- for (i = 0; i < n_changes; i++) {
- if (changes[i].type == UNIT_FILE_SYMLINK)
- log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
- else
- log_info("rm '%s'", changes[i].path);
- }
- }
-
- r = 0;
- } else {
- const char *method;
- bool send_force = true, expect_carries_install_info = false;
- dbus_bool_t a, b;
- DBusMessageIter iter, sub, sub2;
-
- if (streq(verb, "enable")) {
- method = "EnableUnitFiles";
- expect_carries_install_info = true;
- } else if (streq(verb, "disable")) {
- method = "DisableUnitFiles";
- send_force = false;
- } else if (streq(verb, "reenable")) {
- method = "ReenableUnitFiles";
- expect_carries_install_info = true;
- } else if (streq(verb, "link"))
- method = "LinkUnitFiles";
- else if (streq(verb, "preset")) {
- method = "PresetUnitFiles";
- expect_carries_install_info = true;
- } else if (streq(verb, "mask"))
- method = "MaskUnitFiles";
- else if (streq(verb, "unmask")) {
- method = "UnmaskUnitFiles";
- send_force = false;
- } else
- assert_not_reached("Unknown verb");
-
- m = dbus_message_new_method_call(
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- method);
- if (!m) {
- r = log_oom();
- goto finish;
- }
-
- dbus_message_iter_init_append(m, &iter);
-
- r = mangle_names(args+1, &mangled_names);
- if(r < 0)
- goto finish;
-
- r = bus_append_strv_iter(&iter, mangled_names);
- if (r < 0) {
- log_error("Failed to append unit files.");
- goto finish;
- }
-
- a = arg_runtime;
- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
- log_error("Failed to append runtime boolean.");
- r = -ENOMEM;
- goto finish;
- }
-
- if (send_force) {
- b = arg_force;
-
- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
- log_error("Failed to append force boolean.");
- r = -ENOMEM;
- goto finish;
- }
- }
-
- reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
- if (!reply) {
- log_error("Failed to issue method call: %s", bus_error_message(&error));
- r = -EIO;
- goto finish;
- }
-
- if (!dbus_message_iter_init(reply, &iter)) {
- log_error("Failed to initialize iterator.");
- goto finish;
- }
-
- if (expect_carries_install_info) {
- r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
- if (r < 0) {
- log_error("Failed to parse reply.");
- goto finish;
- }
-
- carries_install_info = b;
- }
-
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&iter, &sub);
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- const char *type, *path, *source;
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- if (!arg_quiet) {
- if (streq(type, "symlink"))
- log_info("ln -s '%s' '%s'", source, path);
- else
- log_info("rm '%s'", path);
- }
-
- dbus_message_iter_next(&sub);
- }
-
- /* Try to reload if enabeld */
- if (!arg_no_reload)
- r = daemon_reload(bus, args);
- }
-
- if (carries_install_info == 0)
- log_warning("The unit files have no [Install] section. They are not meant to be enabled using systemctl.");
-
-finish:
- if (m)
- dbus_message_unref(m);
-
- if (reply)
- dbus_message_unref(reply);
-
- unit_file_changes_free(changes, n_changes);
-
- dbus_error_free(&error);
-
- strv_free(mangled_names);
-
- return r;
-}
-
-static int unit_is_enabled(DBusConnection *bus, char **args) {
- DBusError error;
- int r;
- DBusMessage *reply = NULL;
- bool enabled;
- char **name;
-
- dbus_error_init(&error);
-
- r = enable_sysv_units(args);
- if (r < 0)
- return r;
-
- enabled = r > 0;
-
- if (!bus || avoid_bus()) {
-
- STRV_FOREACH(name, args+1) {
- UnitFileState state;
-
- state = unit_file_get_state(arg_scope, arg_root, *name);
- if (state < 0) {
- r = state;
- goto finish;
- }
-
- if (state == UNIT_FILE_ENABLED ||
- state == UNIT_FILE_ENABLED_RUNTIME ||
- state == UNIT_FILE_STATIC)
- enabled = true;
-
- if (!arg_quiet)
- puts(unit_file_state_to_string(state));
- }
-
- } else {
- STRV_FOREACH(name, args+1) {
- const char *s;
-
- r = bus_method_call_with_reply (
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "GetUnitFileState",
- &reply,
- NULL,
- DBUS_TYPE_STRING, name,
- DBUS_TYPE_INVALID);
- if (r)
- goto finish;
-
- if (!dbus_message_get_args(reply, &error,
- DBUS_TYPE_STRING, &s,
- DBUS_TYPE_INVALID)) {
- log_error("Failed to parse reply: %s", bus_error_message(&error));
- r = -EIO;
- goto finish;
- }
-
- dbus_message_unref(reply);
- reply = NULL;
-
- if (streq(s, "enabled") ||
- streq(s, "enabled-runtime") ||
- streq(s, "static"))
- enabled = true;
-
- if (!arg_quiet)
- puts(s);
- }
- }
-
- r = enabled ? 0 : 1;
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- dbus_error_free(&error);
- return r;
-}
-
-static int systemctl_help(void) {
-
- pager_open_if_enabled();
-
- printf("%s [OPTIONS...] {COMMAND} ...\n\n"
- "Query or send control commands to the systemd manager.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " -t --type=TYPE List only units of a particular type\n"
- " -p --property=NAME Show only properties by this name\n"
- " -a --all Show all units/properties, including dead/empty ones\n"
- " --failed Show only failed units\n"
- " --full Don't ellipsize unit names on output\n"
- " --fail When queueing a new job, fail if conflicting jobs are\n"
- " pending\n"
- " --ignore-dependencies\n"
- " When queueing a new job, ignore all its dependencies\n"
- " --kill-who=WHO Who to send signal to\n"
- " -s --signal=SIGNAL Which signal to send\n"
- " -H --host=[USER@]HOST\n"
- " Show information for remote host\n"
- " -P --privileged Acquire privileges before execution\n"
- " -q --quiet Suppress output\n"
- " --no-block Do not wait until operation finished\n"
- " --no-wall Don't send wall message before halt/power-off/reboot\n"
- " --no-reload When enabling/disabling unit files, don't reload daemon\n"
- " configuration\n"
- " --no-legend Do not print a legend (column headers and hints)\n"
- " --no-pager Do not pipe output into a pager\n"
- " --no-ask-password\n"
- " Do not ask for system passwords\n"
- " --order When generating graph for dot, show only order\n"
- " --require When generating graph for dot, show only requirement\n"
- " --system Connect to system manager\n"
- " --user Connect to user service manager\n"
- " --global Enable/disable unit files globally\n"
- " -f --force When enabling unit files, override existing symlinks\n"
- " When shutting down, execute action immediately\n"
- " --root=PATH Enable unit files in the specified root directory\n"
- " --runtime Enable unit files only temporarily until next reboot\n"
- " -n --lines=INTEGER Journal entries to show\n"
- " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
- " verbose, export, json, json-pretty, json-sse, cat)\n\n"
- "Unit Commands:\n"
- " list-units List loaded units\n"
- " start [NAME...] Start (activate) one or more units\n"
- " stop [NAME...] Stop (deactivate) one or more units\n"
- " reload [NAME...] Reload one or more units\n"
- " restart [NAME...] Start or restart one or more units\n"
- " try-restart [NAME...] Restart one or more units if active\n"
- " reload-or-restart [NAME...] Reload one or more units is possible,\n"
- " otherwise start or restart\n"
- " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
- " otherwise restart if active\n"
- " isolate [NAME] Start one unit and stop all others\n"
- " kill [NAME...] Send signal to processes of a unit\n"
- " is-active [NAME...] Check whether units are active\n"
- " status [NAME...|PID...] Show runtime status of one or more units\n"
- " show [NAME...|JOB...] Show properties of one or more\n"
- " units/jobs or the manager\n"
- " help [NAME...|PID...] Show manual for one or more units\n"
- " reset-failed [NAME...] Reset failed state for all, one, or more\n"
- " units\n"
- " load [NAME...] Load one or more units\n\n"
- "Unit File Commands:\n"
- " list-unit-files List installed unit files\n"
- " enable [NAME...] Enable one or more unit files\n"
- " disable [NAME...] Disable one or more unit files\n"
- " reenable [NAME...] Reenable one or more unit files\n"
- " preset [NAME...] Enable/disable one or more unit files\n"
- " based on preset configuration\n"
- " mask [NAME...] Mask one or more units\n"
- " unmask [NAME...] Unmask one or more units\n"
- " link [PATH...] Link one or more units files into\n"
- " the search path\n"
- " is-enabled [NAME...] Check whether unit files are enabled\n\n"
- "Job Commands:\n"
- " list-jobs List jobs\n"
- " cancel [JOB...] Cancel all, one, or more jobs\n\n"
- "Status Commands:\n"
- " dump Dump server status\n"
- " dot Dump dependency graph for dot(1)\n\n"
- "Snapshot Commands:\n"
- " snapshot [NAME] Create a snapshot\n"
- " delete [NAME...] Remove one or more snapshots\n\n"
- "Environment Commands:\n"
- " show-environment Dump environment\n"
- " set-environment [NAME=VALUE...] Set one or more environment variables\n"
- " unset-environment [NAME...] Unset one or more environment variables\n\n"
- "Manager Lifecycle Commands:\n"
- " daemon-reload Reload systemd manager configuration\n"
- " daemon-reexec Reexecute systemd manager\n\n"
- "System Commands:\n"
- " default Enter system default mode\n"
- " rescue Enter system rescue mode\n"
- " emergency Enter system emergency mode\n"
- " halt Shut down and halt the system\n"
- " poweroff Shut down and power-off the system\n"
- " reboot Shut down and reboot the system\n"
- " kexec Shut down and reboot the system with kexec\n"
- " exit Request user instance exit\n"
- " switch-root [ROOT] [INIT] Change to a different root file system\n"
- " suspend Suspend the system\n"
- " hibernate Hibernate the system\n"
- " hybrid-sleep Hibernate and suspend the system\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static int halt_help(void) {
-
- printf("%s [OPTIONS...]\n\n"
- "%s the system.\n\n"
- " --help Show this help\n"
- " --halt Halt the machine\n"
- " -p --poweroff Switch off the machine\n"
- " --reboot Reboot the machine\n"
- " -f --force Force immediate halt/power-off/reboot\n"
- " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
- " -d --no-wtmp Don't write wtmp record\n"
- " --no-wall Don't send wall message before halt/power-off/reboot\n",
- program_invocation_short_name,
- arg_action == ACTION_REBOOT ? "Reboot" :
- arg_action == ACTION_POWEROFF ? "Power off" :
- "Halt");
-
- return 0;
-}
-
-static int shutdown_help(void) {
-
- printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
- "Shut down the system.\n\n"
- " --help Show this help\n"
- " -H --halt Halt the machine\n"
- " -P --poweroff Power-off the machine\n"
- " -r --reboot Reboot the machine\n"
- " -h Equivalent to --poweroff, overridden by --halt\n"
- " -k Don't halt/power-off/reboot, just send warnings\n"
- " --no-wall Don't send wall message before halt/power-off/reboot\n"
- " -c Cancel a pending shutdown\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static int telinit_help(void) {
-
- printf("%s [OPTIONS...] {COMMAND}\n\n"
- "Send control commands to the init daemon.\n\n"
- " --help Show this help\n"
- " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
- "Commands:\n"
- " 0 Power-off the machine\n"
- " 6 Reboot the machine\n"
- " 2, 3, 4, 5 Start runlevelX.target unit\n"
- " 1, s, S Enter rescue mode\n"
- " q, Q Reload init daemon configuration\n"
- " u, U Reexecute init daemon\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static int runlevel_help(void) {
-
- printf("%s [OPTIONS...]\n\n"
- "Prints the previous and current runlevel of the init system.\n\n"
- " --help Show this help\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static int systemctl_parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_FAIL = 0x100,
- ARG_IGNORE_DEPENDENCIES,
- ARG_VERSION,
- ARG_USER,
- ARG_SYSTEM,
- ARG_GLOBAL,
- ARG_NO_BLOCK,
- ARG_NO_LEGEND,
- ARG_NO_PAGER,
- ARG_NO_WALL,
- ARG_ORDER,
- ARG_REQUIRE,
- ARG_ROOT,
- ARG_FULL,
- ARG_NO_RELOAD,
- ARG_KILL_WHO,
- ARG_NO_ASK_PASSWORD,
- ARG_FAILED,
- ARG_RUNTIME,
- ARG_FORCE
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "type", required_argument, NULL, 't' },
- { "property", required_argument, NULL, 'p' },
- { "all", no_argument, NULL, 'a' },
- { "failed", no_argument, NULL, ARG_FAILED },
- { "full", no_argument, NULL, ARG_FULL },
- { "fail", no_argument, NULL, ARG_FAIL },
- { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
- { "user", no_argument, NULL, ARG_USER },
- { "system", no_argument, NULL, ARG_SYSTEM },
- { "global", no_argument, NULL, ARG_GLOBAL },
- { "no-block", no_argument, NULL, ARG_NO_BLOCK },
- { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
- { "no-pager", no_argument, NULL, ARG_NO_PAGER },
- { "no-wall", no_argument, NULL, ARG_NO_WALL },
- { "quiet", no_argument, NULL, 'q' },
- { "order", no_argument, NULL, ARG_ORDER },
- { "require", no_argument, NULL, ARG_REQUIRE },
- { "root", required_argument, NULL, ARG_ROOT },
- { "force", no_argument, NULL, ARG_FORCE },
- { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
- { "kill-who", required_argument, NULL, ARG_KILL_WHO },
- { "signal", required_argument, NULL, 's' },
- { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
- { "host", required_argument, NULL, 'H' },
- { "privileged",no_argument, NULL, 'P' },
- { "runtime", no_argument, NULL, ARG_RUNTIME },
- { "lines", required_argument, NULL, 'n' },
- { "output", required_argument, NULL, 'o' },
- { NULL, 0, NULL, 0 }
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
-
- switch (c) {
-
- case 'h':
- systemctl_help();
- return 0;
-
- case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(DISTRIBUTION);
- puts(SYSTEMD_FEATURES);
- return 0;
-
- case 't':
- if (unit_type_from_string(optarg) >= 0) {
- arg_type = optarg;
- break;
- }
- if (unit_load_state_from_string(optarg) >= 0) {
- arg_load_state = optarg;
- break;
- }
- log_error("Unkown unit type or load state '%s'.",
- optarg);
- return -EINVAL;
- case 'p': {
- char **l;
-
- if (!(l = strv_append(arg_property, optarg)))
- return -ENOMEM;
-
- strv_free(arg_property);
- arg_property = l;
-
- /* If the user asked for a particular
- * property, show it to him, even if it is
- * empty. */
- arg_all = true;
- break;
- }
-
- case 'a':
- arg_all = true;
- break;
-
- case ARG_FAIL:
- arg_job_mode = "fail";
- break;
-
- case ARG_IGNORE_DEPENDENCIES:
- arg_job_mode = "ignore-dependencies";
- break;
-
- case ARG_USER:
- arg_scope = UNIT_FILE_USER;
- break;
-
- case ARG_SYSTEM:
- arg_scope = UNIT_FILE_SYSTEM;
- break;
-
- case ARG_GLOBAL:
- arg_scope = UNIT_FILE_GLOBAL;
- break;
-
- case ARG_NO_BLOCK:
- arg_no_block = true;
- break;
-
- case ARG_NO_LEGEND:
- arg_no_legend = true;
- break;
-
- case ARG_NO_PAGER:
- arg_no_pager = true;
- break;
-
- case ARG_NO_WALL:
- arg_no_wall = true;
- break;
-
- case ARG_ORDER:
- arg_dot = DOT_ORDER;
- break;
-
- case ARG_REQUIRE:
- arg_dot = DOT_REQUIRE;
- break;
-
- case ARG_ROOT:
- arg_root = optarg;
- break;
-
- case ARG_FULL:
- arg_full = true;
- break;
-
- case ARG_FAILED:
- arg_failed = true;
- break;
-
- case 'q':
- arg_quiet = true;
- break;
-
- case ARG_FORCE:
- arg_force ++;
- break;
-
- case 'f':
- arg_force ++;
- break;
-
- case ARG_NO_RELOAD:
- arg_no_reload = true;
- break;
-
- case ARG_KILL_WHO:
- arg_kill_who = optarg;
- break;
-
- case 's':
- if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
- log_error("Failed to parse signal string %s.", optarg);
- return -EINVAL;
- }
- break;
-
- case ARG_NO_ASK_PASSWORD:
- arg_ask_password = false;
- break;
-
- case 'P':
- arg_transport = TRANSPORT_POLKIT;
- break;
-
- case 'H':
- arg_transport = TRANSPORT_SSH;
- arg_host = optarg;
- break;
-
- case ARG_RUNTIME:
- arg_runtime = true;
- break;
-
- case 'n':
- if (safe_atou(optarg, &arg_lines) < 0) {
- log_error("Failed to parse lines '%s'", optarg);
- return -EINVAL;
- }
- break;
-
- case 'o':
- arg_output = output_mode_from_string(optarg);
- if (arg_output < 0) {
- log_error("Unknown output '%s'.", optarg);
- return -EINVAL;
- }
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- log_error("Unknown option code '%c'.", c);
- return -EINVAL;
- }
- }
-
- if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
- log_error("Cannot access user instance remotely.");
- return -EINVAL;
- }
-
- return 1;
-}
-
-static int halt_parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_HELP = 0x100,
- ARG_HALT,
- ARG_REBOOT,
- ARG_NO_WALL
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, ARG_HELP },
- { "halt", no_argument, NULL, ARG_HALT },
- { "poweroff", no_argument, NULL, 'p' },
- { "reboot", no_argument, NULL, ARG_REBOOT },
- { "force", no_argument, NULL, 'f' },
- { "wtmp-only", no_argument, NULL, 'w' },
- { "no-wtmp", no_argument, NULL, 'd' },
- { "no-wall", no_argument, NULL, ARG_NO_WALL },
- { NULL, 0, NULL, 0 }
- };
-
- int c, runlevel;
-
- assert(argc >= 0);
- assert(argv);
-
- if (utmp_get_runlevel(&runlevel, NULL) >= 0)
- if (runlevel == '0' || runlevel == '6')
- arg_force = 2;
-
- while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
- switch (c) {
-
- case ARG_HELP:
- halt_help();
- return 0;
-
- case ARG_HALT:
- arg_action = ACTION_HALT;
- break;
-
- case 'p':
- if (arg_action != ACTION_REBOOT)
- arg_action = ACTION_POWEROFF;
- break;
-
- case ARG_REBOOT:
- arg_action = ACTION_REBOOT;
- break;
-
- case 'f':
- arg_force = 2;
- break;
-
- case 'w':
- arg_dry = true;
- break;
-
- case 'd':
- arg_no_wtmp = true;
- break;
-
- case ARG_NO_WALL:
- arg_no_wall = true;
- break;
-
- case 'i':
- case 'h':
- case 'n':
- /* Compatibility nops */
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- log_error("Unknown option code '%c'.", c);
- return -EINVAL;
- }
- }
-
- if (optind < argc) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
- return 1;
-}
-
-static int parse_time_spec(const char *t, usec_t *_u) {
- assert(t);
- assert(_u);
-
- if (streq(t, "now"))
- *_u = 0;
- else if (!strchr(t, ':')) {
- uint64_t u;
-
- if (safe_atou64(t, &u) < 0)
- return -EINVAL;
-
- *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
- } else {
- char *e = NULL;
- long hour, minute;
- struct tm tm;
- time_t s;
- usec_t n;
-
- errno = 0;
- hour = strtol(t, &e, 10);
- if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
- return -EINVAL;
-
- minute = strtol(e+1, &e, 10);
- if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
- return -EINVAL;
-
- n = now(CLOCK_REALTIME);
- s = (time_t) (n / USEC_PER_SEC);
-
- zero(tm);
- assert_se(localtime_r(&s, &tm));
-
- tm.tm_hour = (int) hour;
- tm.tm_min = (int) minute;
- tm.tm_sec = 0;
-
- assert_se(s = mktime(&tm));
-
- *_u = (usec_t) s * USEC_PER_SEC;
-
- while (*_u <= n)
- *_u += USEC_PER_DAY;
- }
-
- return 0;
-}
-
-static int shutdown_parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_HELP = 0x100,
- ARG_NO_WALL
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, ARG_HELP },
- { "halt", no_argument, NULL, 'H' },
- { "poweroff", no_argument, NULL, 'P' },
- { "reboot", no_argument, NULL, 'r' },
- { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
- { "no-wall", no_argument, NULL, ARG_NO_WALL },
- { NULL, 0, NULL, 0 }
- };
-
- int c, r;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
- switch (c) {
-
- case ARG_HELP:
- shutdown_help();
- return 0;
-
- case 'H':
- arg_action = ACTION_HALT;
- break;
-
- case 'P':
- arg_action = ACTION_POWEROFF;
- break;
-
- case 'r':
- if (kexec_loaded())
- arg_action = ACTION_KEXEC;
- else
- arg_action = ACTION_REBOOT;
- break;
-
- case 'K':
- arg_action = ACTION_KEXEC;
- break;
-
- case 'h':
- if (arg_action != ACTION_HALT)
- arg_action = ACTION_POWEROFF;
- break;
-
- case 'k':
- arg_dry = true;
- break;
-
- case ARG_NO_WALL:
- arg_no_wall = true;
- break;
-
- case 't':
- case 'a':
- /* Compatibility nops */
- break;
-
- case 'c':
- arg_action = ACTION_CANCEL_SHUTDOWN;
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- log_error("Unknown option code '%c'.", c);
- return -EINVAL;
- }
- }
-
- if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
- r = parse_time_spec(argv[optind], &arg_when);
- if (r < 0) {
- log_error("Failed to parse time specification: %s", argv[optind]);
- return r;
- }
- } else
- arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
-
- if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
- /* No time argument for shutdown cancel */
- arg_wall = argv + optind;
- else if (argc > optind + 1)
- /* We skip the time argument */
- arg_wall = argv + optind + 1;
-
- optind = argc;
-
- return 1;
-}
-
-static int telinit_parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_HELP = 0x100,
- ARG_NO_WALL
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, ARG_HELP },
- { "no-wall", no_argument, NULL, ARG_NO_WALL },
- { NULL, 0, NULL, 0 }
- };
-
- static const struct {
- char from;
- enum action to;
- } table[] = {
- { '0', ACTION_POWEROFF },
- { '6', ACTION_REBOOT },
- { '1', ACTION_RESCUE },
- { '2', ACTION_RUNLEVEL2 },
- { '3', ACTION_RUNLEVEL3 },
- { '4', ACTION_RUNLEVEL4 },
- { '5', ACTION_RUNLEVEL5 },
- { 's', ACTION_RESCUE },
- { 'S', ACTION_RESCUE },
- { 'q', ACTION_RELOAD },
- { 'Q', ACTION_RELOAD },
- { 'u', ACTION_REEXEC },
- { 'U', ACTION_REEXEC }
- };
-
- unsigned i;
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
- switch (c) {
-
- case ARG_HELP:
- telinit_help();
- return 0;
-
- case ARG_NO_WALL:
- arg_no_wall = true;
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- log_error("Unknown option code '%c'.", c);
- return -EINVAL;
- }
- }
-
- if (optind >= argc) {
- telinit_help();
- return -EINVAL;
- }
-
- if (optind + 1 < argc) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
- if (strlen(argv[optind]) != 1) {
- log_error("Expected single character argument.");
- return -EINVAL;
- }
-
- for (i = 0; i < ELEMENTSOF(table); i++)
- if (table[i].from == argv[optind][0])
- break;
-
- if (i >= ELEMENTSOF(table)) {
- log_error("Unknown command '%s'.", argv[optind]);
- return -EINVAL;
- }
-
- arg_action = table[i].to;
-
- optind ++;
-
- return 1;
-}
-
-static int runlevel_parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_HELP = 0x100,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, ARG_HELP },
- { NULL, 0, NULL, 0 }
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
- switch (c) {
-
- case ARG_HELP:
- runlevel_help();
- return 0;
-
- case '?':
- return -EINVAL;
-
- default:
- log_error("Unknown option code '%c'.", c);
- return -EINVAL;
- }
- }
-
- if (optind < argc) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
- return 1;
-}
-
-static int parse_argv(int argc, char *argv[]) {
- assert(argc >= 0);
- assert(argv);
-
- if (program_invocation_short_name) {
-
- if (strstr(program_invocation_short_name, "halt")) {
- arg_action = ACTION_HALT;
- return halt_parse_argv(argc, argv);
- } else if (strstr(program_invocation_short_name, "poweroff")) {
- arg_action = ACTION_POWEROFF;
- return halt_parse_argv(argc, argv);
- } else if (strstr(program_invocation_short_name, "reboot")) {
- if (kexec_loaded())
- arg_action = ACTION_KEXEC;
- else
- arg_action = ACTION_REBOOT;
- return halt_parse_argv(argc, argv);
- } else if (strstr(program_invocation_short_name, "shutdown")) {
- arg_action = ACTION_POWEROFF;
- return shutdown_parse_argv(argc, argv);
- } else if (strstr(program_invocation_short_name, "init")) {
-
- if (sd_booted() > 0) {
- arg_action = ACTION_INVALID;
- return telinit_parse_argv(argc, argv);
- } else {
- /* Hmm, so some other init system is
- * running, we need to forward this
- * request to it. For now we simply
- * guess that it is Upstart. */
-
- execv("/lib/upstart/telinit", argv);
-
- log_error("Couldn't find an alternative telinit implementation to spawn.");
- return -EIO;
- }
-
- } else if (strstr(program_invocation_short_name, "runlevel")) {
- arg_action = ACTION_RUNLEVEL;
- return runlevel_parse_argv(argc, argv);
- }
- }
-
- arg_action = ACTION_SYSTEMCTL;
- return systemctl_parse_argv(argc, argv);
-}
-
-static int action_to_runlevel(void) {
-
- static const char table[_ACTION_MAX] = {
- [ACTION_HALT] = '0',
- [ACTION_POWEROFF] = '0',
- [ACTION_REBOOT] = '6',
- [ACTION_RUNLEVEL2] = '2',
- [ACTION_RUNLEVEL3] = '3',
- [ACTION_RUNLEVEL4] = '4',
- [ACTION_RUNLEVEL5] = '5',
- [ACTION_RESCUE] = '1'
- };
-
- assert(arg_action < _ACTION_MAX);
-
- return table[arg_action];
-}
-
-static int talk_upstart(void) {
- DBusMessage *m = NULL, *reply = NULL;
- DBusError error;
- int previous, rl, r;
- char
- env1_buf[] = "RUNLEVEL=X",
- env2_buf[] = "PREVLEVEL=X";
- char *env1 = env1_buf, *env2 = env2_buf;
- const char *emit = "runlevel";
- dbus_bool_t b_false = FALSE;
- DBusMessageIter iter, sub;
- DBusConnection *bus;
-
- dbus_error_init(&error);
-
- if (!(rl = action_to_runlevel()))
- return 0;
-
- if (utmp_get_runlevel(&previous, NULL) < 0)
- previous = 'N';
-
- if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
- if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
- r = 0;
- goto finish;
- }
-
- log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
- r = -EIO;
- goto finish;
- }
-
- if ((r = bus_check_peercred(bus)) < 0) {
- log_error("Failed to verify owner of bus.");
- goto finish;
- }
-
- if (!(m = dbus_message_new_method_call(
- "com.ubuntu.Upstart",
- "/com/ubuntu/Upstart",
- "com.ubuntu.Upstart0_6",
- "EmitEvent"))) {
-
- log_error("Could not allocate message.");
- r = -ENOMEM;
- goto finish;
- }
-
- dbus_message_iter_init_append(m, &iter);
-
- env1_buf[sizeof(env1_buf)-2] = rl;
- env2_buf[sizeof(env2_buf)-2] = previous;
-
- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
- !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
- !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
- !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
- !dbus_message_iter_close_container(&iter, &sub) ||
- !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
- log_error("Could not append arguments to message.");
- r = -ENOMEM;
- goto finish;
- }
-
- if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-
- if (bus_error_is_no_service(&error)) {
- r = -EADDRNOTAVAIL;
- goto finish;
- }
-
- log_error("Failed to issue method call: %s", bus_error_message(&error));
- r = -EIO;
- goto finish;
- }
-
- r = 1;
-
-finish:
- if (m)
- dbus_message_unref(m);
-
- if (reply)
- dbus_message_unref(reply);
-
- if (bus) {
- dbus_connection_flush(bus);
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
- }
-
- dbus_error_free(&error);
-
- return r;
-}
-
-static int talk_initctl(void) {
- struct init_request request;
- int r, fd;
- char rl;
-
- if (!(rl = action_to_runlevel()))
- return 0;
-
- zero(request);
- request.magic = INIT_MAGIC;
- request.sleeptime = 0;
- request.cmd = INIT_CMD_RUNLVL;
- request.runlevel = rl;
-
- if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
-
- if (errno == ENOENT)
- return 0;
-
- log_error("Failed to open "INIT_FIFO": %m");
- return -errno;
- }
-
- errno = 0;
- r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
- close_nointr_nofail(fd);
-
- if (r < 0) {
- log_error("Failed to write to "INIT_FIFO": %m");
- return errno ? -errno : -EIO;
- }
-
- return 1;
-}
-
-static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
-
- static const struct {
- const char* verb;
- const enum {
- MORE,
- LESS,
- EQUAL
- } argc_cmp;
- const int argc;
- int (* const dispatch)(DBusConnection *bus, char **args);
- } verbs[] = {
- { "list-units", LESS, 1, list_units },
- { "list-unit-files", EQUAL, 1, list_unit_files },
- { "list-jobs", EQUAL, 1, list_jobs },
- { "clear-jobs", EQUAL, 1, daemon_reload },
- { "load", MORE, 2, load_unit },
- { "cancel", MORE, 2, cancel_job },
- { "start", MORE, 2, start_unit },
- { "stop", MORE, 2, start_unit },
- { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
- { "reload", MORE, 2, start_unit },
- { "restart", MORE, 2, start_unit },
- { "try-restart", MORE, 2, start_unit },
- { "reload-or-restart", MORE, 2, start_unit },
- { "reload-or-try-restart", MORE, 2, start_unit },
- { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
- { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
- { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
- { "isolate", EQUAL, 2, start_unit },
- { "kill", MORE, 2, kill_unit },
- { "is-active", MORE, 2, check_unit },
- { "check", MORE, 2, check_unit },
- { "show", MORE, 1, show },
- { "status", MORE, 2, show },
- { "help", MORE, 2, show },
- { "dump", EQUAL, 1, dump },
- { "dot", EQUAL, 1, dot },
- { "snapshot", LESS, 2, snapshot },
- { "delete", MORE, 2, delete_snapshot },
- { "daemon-reload", EQUAL, 1, daemon_reload },
- { "daemon-reexec", EQUAL, 1, daemon_reload },
- { "show-environment", EQUAL, 1, show_enviroment },
- { "set-environment", MORE, 2, set_environment },
- { "unset-environment", MORE, 2, set_environment },
- { "halt", EQUAL, 1, start_special },
- { "poweroff", EQUAL, 1, start_special },
- { "reboot", EQUAL, 1, start_special },
- { "kexec", EQUAL, 1, start_special },
- { "suspend", EQUAL, 1, start_special },
- { "hibernate", EQUAL, 1, start_special },
- { "hybrid-sleep", EQUAL, 1, start_special },
- { "default", EQUAL, 1, start_special },
- { "rescue", EQUAL, 1, start_special },
- { "emergency", EQUAL, 1, start_special },
- { "exit", EQUAL, 1, start_special },
- { "reset-failed", MORE, 1, reset_failed },
- { "enable", MORE, 2, enable_unit },
- { "disable", MORE, 2, enable_unit },
- { "is-enabled", MORE, 2, unit_is_enabled },
- { "reenable", MORE, 2, enable_unit },
- { "preset", MORE, 2, enable_unit },
- { "mask", MORE, 2, enable_unit },
- { "unmask", MORE, 2, enable_unit },
- { "link", MORE, 2, enable_unit },
- { "switch-root", MORE, 2, switch_root },
- };
-
- int left;
- unsigned i;
-
- assert(argc >= 0);
- assert(argv);
- assert(error);
-
- left = argc - optind;
-
- if (left <= 0)
- /* Special rule: no arguments means "list-units" */
- i = 0;
- else {
- if (streq(argv[optind], "help") && !argv[optind+1]) {
- log_error("This command expects one or more "
- "unit names. Did you mean --help?");
- return -EINVAL;
- }
-
- for (i = 0; i < ELEMENTSOF(verbs); i++)
- if (streq(argv[optind], verbs[i].verb))
- break;
-
- if (i >= ELEMENTSOF(verbs)) {
- log_error("Unknown operation '%s'.", argv[optind]);
- return -EINVAL;
- }
- }
-
- switch (verbs[i].argc_cmp) {
-
- case EQUAL:
- if (left != verbs[i].argc) {
- log_error("Invalid number of arguments.");
- return -EINVAL;
- }
-
- break;
-
- case MORE:
- if (left < verbs[i].argc) {
- log_error("Too few arguments.");
- return -EINVAL;
- }
-
- break;
-
- case LESS:
- if (left > verbs[i].argc) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
- break;
-
- default:
- assert_not_reached("Unknown comparison operator.");
- }
-
- /* Require a bus connection for all operations but
- * enable/disable */
- if (!streq(verbs[i].verb, "enable") &&
- !streq(verbs[i].verb, "disable") &&
- !streq(verbs[i].verb, "is-enabled") &&
- !streq(verbs[i].verb, "list-unit-files") &&
- !streq(verbs[i].verb, "reenable") &&
- !streq(verbs[i].verb, "preset") &&
- !streq(verbs[i].verb, "mask") &&
- !streq(verbs[i].verb, "unmask") &&
- !streq(verbs[i].verb, "link")) {
-
- if (running_in_chroot() > 0) {
- log_info("Running in chroot, ignoring request.");
- return 0;
- }
-
- if (((!streq(verbs[i].verb, "reboot") &&
- !streq(verbs[i].verb, "halt") &&
- !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
- log_error("Failed to get D-Bus connection: %s",
- dbus_error_is_set(error) ? error->message : "No connection to service manager.");
- return -EIO;
- }
-
- } else {
-
- if (!bus && !avoid_bus()) {
- log_error("Failed to get D-Bus connection: %s",
- dbus_error_is_set(error) ? error->message : "No connection to service manager.");
- return -EIO;
- }
- }
-
- return verbs[i].dispatch(bus, argv + optind);
-}
-
-static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
- int fd;
- struct msghdr msghdr;
- struct iovec iovec[2];
- union sockaddr_union sockaddr;
- struct sd_shutdown_command c;
-
- fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
- if (fd < 0)
- return -errno;
-
- zero(c);
- c.usec = t;
- c.mode = mode;
- c.dry_run = dry_run;
- c.warn_wall = warn;
-
- zero(sockaddr);
- sockaddr.sa.sa_family = AF_UNIX;
- strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
-
- zero(msghdr);
- msghdr.msg_name = &sockaddr;
- msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
-
- zero(iovec);
- iovec[0].iov_base = (char*) &c;
- iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
-
- if (isempty(message))
- msghdr.msg_iovlen = 1;
- else {
- iovec[1].iov_base = (char*) message;
- iovec[1].iov_len = strlen(message);
- msghdr.msg_iovlen = 2;
- }
- msghdr.msg_iov = iovec;
-
- if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
- close_nointr_nofail(fd);
- return -errno;
- }
-
- close_nointr_nofail(fd);
- return 0;
-}
-
-static int reload_with_fallback(DBusConnection *bus) {
-
- if (bus) {
- /* First, try systemd via D-Bus. */
- if (daemon_reload(bus, NULL) >= 0)
- return 0;
- }
-
- /* Nothing else worked, so let's try signals */
- assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
-
- if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
- log_error("kill() failed: %m");
- return -errno;
- }
-
- return 0;
-}
-
-static int start_with_fallback(DBusConnection *bus) {
-
- if (bus) {
- /* First, try systemd via D-Bus. */
- if (start_unit(bus, NULL) >= 0)
- goto done;
- }
-
- /* Hmm, talking to systemd via D-Bus didn't work. Then
- * let's try to talk to Upstart via D-Bus. */
- if (talk_upstart() > 0)
- goto done;
-
- /* Nothing else worked, so let's try
- * /dev/initctl */
- if (talk_initctl() > 0)
- goto done;
-
- log_error("Failed to talk to init daemon.");
- return -EIO;
-
-done:
- warn_wall(arg_action);
- return 0;
-}
-
-static _noreturn_ void halt_now(enum action a) {
-
- /* Make sure C-A-D is handled by the kernel from this
- * point on... */
- reboot(RB_ENABLE_CAD);
-
- switch (a) {
-
- case ACTION_HALT:
- log_info("Halting.");
- reboot(RB_HALT_SYSTEM);
- break;
-
- case ACTION_POWEROFF:
- log_info("Powering off.");
- reboot(RB_POWER_OFF);
- break;
-
- case ACTION_REBOOT:
- log_info("Rebooting.");
- reboot(RB_AUTOBOOT);
- break;
-
- default:
- assert_not_reached("Unknown halt action.");
- }
-
- assert_not_reached("Uh? This shouldn't happen.");
-}
-
-static int halt_main(DBusConnection *bus) {
- int r;
-
- if (geteuid() != 0) {
- /* Try logind if we are a normal user and no special
- * mode applies. Maybe PolicyKit allows us to shutdown
- * the machine. */
-
- if (arg_when <= 0 &&
- !arg_dry &&
- !arg_force &&
- (arg_action == ACTION_POWEROFF ||
- arg_action == ACTION_REBOOT)) {
- r = reboot_with_logind(bus, arg_action);
- if (r >= 0)
- return r;
- }
-
- log_error("Must be root.");
- return -EPERM;
- }
-
- if (arg_when > 0) {
- char *m;
-
- m = strv_join(arg_wall, " ");
- r = send_shutdownd(arg_when,
- arg_action == ACTION_HALT ? 'H' :
- arg_action == ACTION_POWEROFF ? 'P' :
- arg_action == ACTION_KEXEC ? 'K' :
- 'r',
- arg_dry,
- !arg_no_wall,
- m);
- free(m);
-
- if (r < 0)
- log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
- else {
- char date[FORMAT_TIMESTAMP_MAX];
-
- log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
- format_timestamp(date, sizeof(date), arg_when));
- return 0;
- }
- }
-
- if (!arg_dry && !arg_force)
- return start_with_fallback(bus);
-
- if (!arg_no_wtmp) {
- if (sd_booted() > 0)
- log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
- else {
- r = utmp_put_shutdown();
- if (r < 0)
- log_warning("Failed to write utmp record: %s", strerror(-r));
- }
- }
-
- if (arg_dry)
- return 0;
-
- halt_now(arg_action);
- /* We should never reach this. */
- return -ENOSYS;
-}
-
-static int runlevel_main(void) {
- int r, runlevel, previous;
-
- r = utmp_get_runlevel(&runlevel, &previous);
- if (r < 0) {
- puts("unknown");
- return r;
- }
-
- printf("%c %c\n",
- previous <= 0 ? 'N' : previous,
- runlevel <= 0 ? 'N' : runlevel);
-
- return 0;
-}
-
-int main(int argc, char*argv[]) {
- int r, retval = EXIT_FAILURE;
- DBusConnection *bus = NULL;
- DBusError error;
-
- dbus_error_init(&error);
-
- setlocale(LC_ALL, "");
- log_parse_environment();
- log_open();
-
- r = parse_argv(argc, argv);
- if (r < 0)
- goto finish;
- else if (r == 0) {
- retval = EXIT_SUCCESS;
- goto finish;
- }
-
- /* /sbin/runlevel doesn't need to communicate via D-Bus, so
- * let's shortcut this */
- if (arg_action == ACTION_RUNLEVEL) {
- r = runlevel_main();
- retval = r < 0 ? EXIT_FAILURE : r;
- goto finish;
- }
-
- if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
- log_info("Running in chroot, ignoring request.");
- retval = 0;
- goto finish;
- }
-
- if (!avoid_bus()) {
- if (arg_transport == TRANSPORT_NORMAL)
- bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
- else if (arg_transport == TRANSPORT_POLKIT) {
- bus_connect_system_polkit(&bus, &error);
- private_bus = false;
- } else if (arg_transport == TRANSPORT_SSH) {
- bus_connect_system_ssh(NULL, arg_host, &bus, &error);
- private_bus = false;
- } else
- assert_not_reached("Uh, invalid transport...");
- }
-
- switch (arg_action) {
-
- case ACTION_SYSTEMCTL:
- r = systemctl_main(bus, argc, argv, &error);
- break;
-
- case ACTION_HALT:
- case ACTION_POWEROFF:
- case ACTION_REBOOT:
- case ACTION_KEXEC:
- r = halt_main(bus);
- break;
-
- case ACTION_RUNLEVEL2:
- case ACTION_RUNLEVEL3:
- case ACTION_RUNLEVEL4:
- case ACTION_RUNLEVEL5:
- case ACTION_RESCUE:
- case ACTION_EMERGENCY:
- case ACTION_DEFAULT:
- r = start_with_fallback(bus);
- break;
-
- case ACTION_RELOAD:
- case ACTION_REEXEC:
- r = reload_with_fallback(bus);
- break;
-
- case ACTION_CANCEL_SHUTDOWN: {
- char *m = NULL;
-
- if (arg_wall) {
- m = strv_join(arg_wall, " ");
- if (!m) {
- retval = EXIT_FAILURE;
- goto finish;
- }
- }
- r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
- if (r < 0)
- log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
- free(m);
- break;
- }
-
- case ACTION_INVALID:
- case ACTION_RUNLEVEL:
- default:
- assert_not_reached("Unknown action");
- }
-
- retval = r < 0 ? EXIT_FAILURE : r;
-
-finish:
- if (bus) {
- dbus_connection_flush(bus);
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
- }
-
- dbus_error_free(&error);
-
- dbus_shutdown();
-
- strv_free(arg_property);
-
- pager_close();
- ask_password_agent_close();
- polkit_agent_close();
-
- return retval;
-}
diff --git a/src/systemd/Makefile b/src/systemd/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/systemd/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/systemd/sd-daemon.h b/src/systemd/sd-daemon.h
deleted file mode 100644
index fb7456d50f..0000000000
--- a/src/systemd/sd-daemon.h
+++ /dev/null
@@ -1,282 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef foosddaemonhfoo
-#define foosddaemonhfoo
-
-/***
- Copyright 2010 Lennart Poettering
-
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation files
- (the "Software"), to deal in the Software without restriction,
- including without limitation the rights to use, copy, modify, merge,
- publish, distribute, sublicense, and/or sell copies of the Software,
- and to permit persons to whom the Software is furnished to do so,
- subject to the following conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
-***/
-
-#include <sys/types.h>
-#include <inttypes.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- Reference implementation of a few systemd related interfaces for
- writing daemons. These interfaces are trivial to implement. To
- simplify porting we provide this reference implementation.
- Applications are welcome to reimplement the algorithms described
- here if they do not want to include these two source files.
-
- The following functionality is provided:
-
- - Support for logging with log levels on stderr
- - File descriptor passing for socket-based activation
- - Daemon startup and status notification
- - Detection of systemd boots
-
- You may compile this with -DDISABLE_SYSTEMD to disable systemd
- support. This makes all those calls NOPs that are directly related to
- systemd (i.e. only sd_is_xxx() will stay useful).
-
- Since this is drop-in code we don't want any of our symbols to be
- exported in any case. Hence we declare hidden visibility for all of
- them.
-
- You may find an up-to-date version of these source files online:
-
- http://cgit.freedesktop.org/systemd/systemd/plain/src/systemd/sd-daemon.h
- http://cgit.freedesktop.org/systemd/systemd/plain/src/libsystemd-daemon/sd-daemon.c
-
- This should compile on non-Linux systems, too, but with the
- exception of the sd_is_xxx() calls all functions will become NOPs.
-
- See sd-daemon(3) for more information.
-*/
-
-#ifndef _sd_printf_attr_
-#if __GNUC__ >= 4
-#define _sd_printf_attr_(a,b) __attribute__ ((format (printf, a, b)))
-#else
-#define _sd_printf_attr_(a,b)
-#endif
-#endif
-
-/*
- Log levels for usage on stderr:
-
- fprintf(stderr, SD_NOTICE "Hello World!\n");
-
- This is similar to printk() usage in the kernel.
-*/
-#define SD_EMERG "<0>" /* system is unusable */
-#define SD_ALERT "<1>" /* action must be taken immediately */
-#define SD_CRIT "<2>" /* critical conditions */
-#define SD_ERR "<3>" /* error conditions */
-#define SD_WARNING "<4>" /* warning conditions */
-#define SD_NOTICE "<5>" /* normal but significant condition */
-#define SD_INFO "<6>" /* informational */
-#define SD_DEBUG "<7>" /* debug-level messages */
-
-/* The first passed file descriptor is fd 3 */
-#define SD_LISTEN_FDS_START 3
-
-/*
- Returns how many file descriptors have been passed, or a negative
- errno code on failure. Optionally, removes the $LISTEN_FDS and
- $LISTEN_PID file descriptors from the environment (recommended, but
- problematic in threaded environments). If r is the return value of
- this function you'll find the file descriptors passed as fds
- SD_LISTEN_FDS_START to SD_LISTEN_FDS_START+r-1. Returns a negative
- errno style error code on failure. This function call ensures that
- the FD_CLOEXEC flag is set for the passed file descriptors, to make
- sure they are not passed on to child processes. If FD_CLOEXEC shall
- not be set, the caller needs to unset it after this call for all file
- descriptors that are used.
-
- See sd_listen_fds(3) for more information.
-*/
-int sd_listen_fds(int unset_environment);
-
-/*
- Helper call for identifying a passed file descriptor. Returns 1 if
- the file descriptor is a FIFO in the file system stored under the
- specified path, 0 otherwise. If path is NULL a path name check will
- not be done and the call only verifies if the file descriptor
- refers to a FIFO. Returns a negative errno style error code on
- failure.
-
- See sd_is_fifo(3) for more information.
-*/
-int sd_is_fifo(int fd, const char *path);
-
-/*
- Helper call for identifying a passed file descriptor. Returns 1 if
- the file descriptor is a special character device on the file
- system stored under the specified path, 0 otherwise.
- If path is NULL a path name check will not be done and the call
- only verifies if the file descriptor refers to a special character.
- Returns a negative errno style error code on failure.
-
- See sd_is_special(3) for more information.
-*/
-int sd_is_special(int fd, const char *path);
-
-/*
- Helper call for identifying a passed file descriptor. Returns 1 if
- the file descriptor is a socket of the specified family (AF_INET,
- ...) and type (SOCK_DGRAM, SOCK_STREAM, ...), 0 otherwise. If
- family is 0 a socket family check will not be done. If type is 0 a
- socket type check will not be done and the call only verifies if
- the file descriptor refers to a socket. If listening is > 0 it is
- verified that the socket is in listening mode. (i.e. listen() has
- been called) If listening is == 0 it is verified that the socket is
- not in listening mode. If listening is < 0 no listening mode check
- is done. Returns a negative errno style error code on failure.
-
- See sd_is_socket(3) for more information.
-*/
-int sd_is_socket(int fd, int family, int type, int listening);
-
-/*
- Helper call for identifying a passed file descriptor. Returns 1 if
- the file descriptor is an Internet socket, of the specified family
- (either AF_INET or AF_INET6) and the specified type (SOCK_DGRAM,
- SOCK_STREAM, ...), 0 otherwise. If version is 0 a protocol version
- check is not done. If type is 0 a socket type check will not be
- done. If port is 0 a socket port check will not be done. The
- listening flag is used the same way as in sd_is_socket(). Returns a
- negative errno style error code on failure.
-
- See sd_is_socket_inet(3) for more information.
-*/
-int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port);
-
-/*
- Helper call for identifying a passed file descriptor. Returns 1 if
- the file descriptor is an AF_UNIX socket of the specified type
- (SOCK_DGRAM, SOCK_STREAM, ...) and path, 0 otherwise. If type is 0
- a socket type check will not be done. If path is NULL a socket path
- check will not be done. For normal AF_UNIX sockets set length to
- 0. For abstract namespace sockets set length to the length of the
- socket name (including the initial 0 byte), and pass the full
- socket path in path (including the initial 0 byte). The listening
- flag is used the same way as in sd_is_socket(). Returns a negative
- errno style error code on failure.
-
- See sd_is_socket_unix(3) for more information.
-*/
-int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length);
-
-/*
- Helper call for identifying a passed file descriptor. Returns 1 if
- the file descriptor is a POSIX Message Queue of the specified name,
- 0 otherwise. If path is NULL a message queue name check is not
- done. Returns a negative errno style error code on failure.
-*/
-int sd_is_mq(int fd, const char *path);
-
-/*
- Informs systemd about changed daemon state. This takes a number of
- newline separated environment-style variable assignments in a
- string. The following variables are known:
-
- READY=1 Tells systemd that daemon startup is finished (only
- relevant for services of Type=notify). The passed
- argument is a boolean "1" or "0". Since there is
- little value in signaling non-readiness the only
- value daemons should send is "READY=1".
-
- STATUS=... Passes a single-line status string back to systemd
- that describes the daemon state. This is free-from
- and can be used for various purposes: general state
- feedback, fsck-like programs could pass completion
- percentages and failing programs could pass a human
- readable error message. Example: "STATUS=Completed
- 66% of file system check..."
-
- ERRNO=... If a daemon fails, the errno-style error code,
- formatted as string. Example: "ERRNO=2" for ENOENT.
-
- BUSERROR=... If a daemon fails, the D-Bus error-style error
- code. Example: "BUSERROR=org.freedesktop.DBus.Error.TimedOut"
-
- MAINPID=... The main pid of a daemon, in case systemd did not
- fork off the process itself. Example: "MAINPID=4711"
-
- WATCHDOG=1 Tells systemd to update the watchdog timestamp.
- Services using this feature should do this in
- regular intervals. A watchdog framework can use the
- timestamps to detect failed services.
-
- Daemons can choose to send additional variables. However, it is
- recommended to prefix variable names not listed above with X_.
-
- Returns a negative errno-style error code on failure. Returns > 0
- if systemd could be notified, 0 if it couldn't possibly because
- systemd is not running.
-
- Example: When a daemon finished starting up, it could issue this
- call to notify systemd about it:
-
- sd_notify(0, "READY=1");
-
- See sd_notifyf() for more complete examples.
-
- See sd_notify(3) for more information.
-*/
-int sd_notify(int unset_environment, const char *state);
-
-/*
- Similar to sd_notify() but takes a format string.
-
- Example 1: A daemon could send the following after initialization:
-
- sd_notifyf(0, "READY=1\n"
- "STATUS=Processing requests...\n"
- "MAINPID=%lu",
- (unsigned long) getpid());
-
- Example 2: A daemon could send the following shortly before
- exiting, on failure:
-
- sd_notifyf(0, "STATUS=Failed to start up: %s\n"
- "ERRNO=%i",
- strerror(errno),
- errno);
-
- See sd_notifyf(3) for more information.
-*/
-int sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_attr_(2,3);
-
-/*
- Returns > 0 if the system was booted with systemd. Returns < 0 on
- error. Returns 0 if the system was not booted with systemd. Note
- that all of the functions above handle non-systemd boots just
- fine. You should NOT protect them with a call to this function. Also
- note that this function checks whether the system, not the user
- session is controlled by systemd. However the functions above work
- for both user and system services.
-
- See sd_booted(3) for more information.
-*/
-int sd_booted(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/systemd/sd-id128.h b/src/systemd/sd-id128.h
deleted file mode 100644
index 79bb8b3c99..0000000000
--- a/src/systemd/sd-id128.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef fooid128hfoo
-#define fooid128hfoo
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <string.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* 128 Bit ID APIs. See sd-id128(3) for more information. */
-
-typedef union sd_id128 sd_id128_t;
-
-union sd_id128 {
- uint8_t bytes[16];
- uint64_t qwords[2];
-};
-
-char *sd_id128_to_string(sd_id128_t id, char s[33]);
-
-int sd_id128_from_string(const char s[33], sd_id128_t *ret);
-
-int sd_id128_randomize(sd_id128_t *ret);
-
-int sd_id128_get_machine(sd_id128_t *ret);
-
-int sd_id128_get_boot(sd_id128_t *ret);
-
-#define SD_ID128_MAKE(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) \
- ((sd_id128_t) { .bytes = { 0x##v0, 0x##v1, 0x##v2, 0x##v3, 0x##v4, 0x##v5, 0x##v6, 0x##v7, \
- 0x##v8, 0x##v9, 0x##v10, 0x##v11, 0x##v12, 0x##v13, 0x##v14, 0x##v15 }})
-
-/* Note that SD_ID128_FORMAT_VAL will evaluate the passed argument 16
- * times. It is hence not a good idea to call this macro with an
- * expensive function as paramater or an expression with side
- * effects */
-
-#define SD_ID128_FORMAT_STR "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
-#define SD_ID128_FORMAT_VAL(x) (x).bytes[0], (x).bytes[1], (x).bytes[2], (x).bytes[3], (x).bytes[4], (x).bytes[5], (x).bytes[6], (x).bytes[7], (x).bytes[8], (x).bytes[9], (x).bytes[10], (x).bytes[11], (x).bytes[12], (x).bytes[13], (x).bytes[14], (x).bytes[15]
-
-#define SD_ID128_CONST_STR(x) \
- ((char[33]) { \
- ((x).bytes[0] >> 4) >= 10 ? 'a' + ((x).bytes[0] >> 4) - 10 : '0' + ((x).bytes[0] >> 4), \
- ((x).bytes[0] & 15) >= 10 ? 'a' + ((x).bytes[0] & 15) - 10 : '0' + ((x).bytes[0] & 15), \
- ((x).bytes[1] >> 4) >= 10 ? 'a' + ((x).bytes[1] >> 4) - 10 : '0' + ((x).bytes[1] >> 4), \
- ((x).bytes[1] & 15) >= 10 ? 'a' + ((x).bytes[1] & 15) - 10 : '0' + ((x).bytes[1] & 15), \
- ((x).bytes[2] >> 4) >= 10 ? 'a' + ((x).bytes[2] >> 4) - 10 : '0' + ((x).bytes[2] >> 4), \
- ((x).bytes[2] & 15) >= 10 ? 'a' + ((x).bytes[2] & 15) - 10 : '0' + ((x).bytes[2] & 15), \
- ((x).bytes[3] >> 4) >= 10 ? 'a' + ((x).bytes[3] >> 4) - 10 : '0' + ((x).bytes[3] >> 4), \
- ((x).bytes[3] & 15) >= 10 ? 'a' + ((x).bytes[3] & 15) - 10 : '0' + ((x).bytes[3] & 15), \
- ((x).bytes[4] >> 4) >= 10 ? 'a' + ((x).bytes[4] >> 4) - 10 : '0' + ((x).bytes[4] >> 4), \
- ((x).bytes[4] & 15) >= 10 ? 'a' + ((x).bytes[4] & 15) - 10 : '0' + ((x).bytes[4] & 15), \
- ((x).bytes[5] >> 4) >= 10 ? 'a' + ((x).bytes[5] >> 4) - 10 : '0' + ((x).bytes[5] >> 4), \
- ((x).bytes[5] & 15) >= 10 ? 'a' + ((x).bytes[5] & 15) - 10 : '0' + ((x).bytes[5] & 15), \
- ((x).bytes[6] >> 4) >= 10 ? 'a' + ((x).bytes[6] >> 4) - 10 : '0' + ((x).bytes[6] >> 4), \
- ((x).bytes[6] & 15) >= 10 ? 'a' + ((x).bytes[6] & 15) - 10 : '0' + ((x).bytes[6] & 15), \
- ((x).bytes[7] >> 4) >= 10 ? 'a' + ((x).bytes[7] >> 4) - 10 : '0' + ((x).bytes[7] >> 4), \
- ((x).bytes[7] & 15) >= 10 ? 'a' + ((x).bytes[7] & 15) - 10 : '0' + ((x).bytes[7] & 15), \
- ((x).bytes[8] >> 4) >= 10 ? 'a' + ((x).bytes[8] >> 4) - 10 : '0' + ((x).bytes[8] >> 4), \
- ((x).bytes[8] & 15) >= 10 ? 'a' + ((x).bytes[8] & 15) - 10 : '0' + ((x).bytes[8] & 15), \
- ((x).bytes[9] >> 4) >= 10 ? 'a' + ((x).bytes[9] >> 4) - 10 : '0' + ((x).bytes[9] >> 4), \
- ((x).bytes[9] & 15) >= 10 ? 'a' + ((x).bytes[9] & 15) - 10 : '0' + ((x).bytes[9] & 15), \
- ((x).bytes[10] >> 4) >= 10 ? 'a' + ((x).bytes[10] >> 4) - 10 : '0' + ((x).bytes[10] >> 4), \
- ((x).bytes[10] & 15) >= 10 ? 'a' + ((x).bytes[10] & 15) - 10 : '0' + ((x).bytes[10] & 15), \
- ((x).bytes[11] >> 4) >= 10 ? 'a' + ((x).bytes[11] >> 4) - 10 : '0' + ((x).bytes[11] >> 4), \
- ((x).bytes[11] & 15) >= 10 ? 'a' + ((x).bytes[11] & 15) - 10 : '0' + ((x).bytes[11] & 15), \
- ((x).bytes[12] >> 4) >= 10 ? 'a' + ((x).bytes[12] >> 4) - 10 : '0' + ((x).bytes[12] >> 4), \
- ((x).bytes[12] & 15) >= 10 ? 'a' + ((x).bytes[12] & 15) - 10 : '0' + ((x).bytes[12] & 15), \
- ((x).bytes[13] >> 4) >= 10 ? 'a' + ((x).bytes[13] >> 4) - 10 : '0' + ((x).bytes[13] >> 4), \
- ((x).bytes[13] & 15) >= 10 ? 'a' + ((x).bytes[13] & 15) - 10 : '0' + ((x).bytes[13] & 15), \
- ((x).bytes[14] >> 4) >= 10 ? 'a' + ((x).bytes[14] >> 4) - 10 : '0' + ((x).bytes[14] >> 4), \
- ((x).bytes[14] & 15) >= 10 ? 'a' + ((x).bytes[14] & 15) - 10 : '0' + ((x).bytes[14] & 15), \
- ((x).bytes[15] >> 4) >= 10 ? 'a' + ((x).bytes[15] >> 4) - 10 : '0' + ((x).bytes[15] >> 4), \
- ((x).bytes[15] & 15) >= 10 ? 'a' + ((x).bytes[15] & 15) - 10 : '0' + ((x).bytes[15] & 15), \
- 0 })
-
-static inline int sd_id128_equal(sd_id128_t a, sd_id128_t b) {
- return memcmp(&a, &b, 16) == 0;
-}
-
-#define SD_ID128_NULL ((sd_id128_t) { .qwords = { 0, 0 }})
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h
deleted file mode 100644
index 7241173035..0000000000
--- a/src/systemd/sd-journal.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef foojournalhfoo
-#define foojournalhfoo
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <stdarg.h>
-#include <sys/uio.h>
-#include <syslog.h>
-
-#include <systemd/sd-id128.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Journal APIs. See sd-journal(3) for more information. */
-
-/* Write to daemon */
-int sd_journal_print(int priority, const char *format, ...) __attribute__ ((format (printf, 2, 3)));
-int sd_journal_printv(int priority, const char *format, va_list ap);
-int sd_journal_send(const char *format, ...) __attribute__((sentinel));
-int sd_journal_sendv(const struct iovec *iov, int n);
-int sd_journal_perror(const char *message);
-
-/* Used by the macros below. Don't call this directly. */
-int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) __attribute__ ((format (printf, 5, 6)));
-int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap);
-int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) __attribute__((sentinel));
-int sd_journal_sendv_with_location(const char *file, const char *line, const char *func, const struct iovec *iov, int n);
-int sd_journal_perror_with_location(const char *file, const char *line, const char *func, const char *message);
-
-/* implicitly add code location to messages sent, if this is enabled */
-#ifndef SD_JOURNAL_SUPPRESS_LOCATION
-
-#define _sd_XSTRINGIFY(x) #x
-#define _sd_STRINGIFY(x) _sd_XSTRINGIFY(x)
-
-#define sd_journal_print(priority, ...) sd_journal_print_with_location(priority, "CODE_FILE=" __FILE__, "CODE_LINE=" _sd_STRINGIFY(__LINE__), __func__, __VA_ARGS__)
-#define sd_journal_printv(priority, format, ap) sd_journal_printv_with_location(priority, "CODE_FILE=" __FILE__, "CODE_LINE=" _sd_STRINGIFY(__LINE__), __func__, format, ap)
-#define sd_journal_send(...) sd_journal_send_with_location("CODE_FILE=" __FILE__, "CODE_LINE=" _sd_STRINGIFY(__LINE__), __func__, __VA_ARGS__)
-#define sd_journal_sendv(iovec, n) sd_journal_sendv_with_location("CODE_FILE=" __FILE__, "CODE_LINE=" _sd_STRINGIFY(__LINE__), __func__, iovec, n)
-#define sd_journal_perror(message) sd_journal_perror_with_location("CODE_FILE=" __FILE__, "CODE_LINE=" _sd_STRINGIFY(__LINE__), __func__, message)
-
-#endif
-
-int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix);
-
-/* Browse journal stream */
-
-typedef struct sd_journal sd_journal;
-
-/* Open flags */
-enum {
- SD_JOURNAL_LOCAL_ONLY = 1,
- SD_JOURNAL_RUNTIME_ONLY = 2,
- SD_JOURNAL_SYSTEM_ONLY = 4
-};
-
-/* Wakeup event types */
-enum {
- SD_JOURNAL_NOP,
- SD_JOURNAL_APPEND,
- SD_JOURNAL_INVALIDATE
-};
-
-int sd_journal_open(sd_journal **ret, int flags);
-int sd_journal_open_directory(sd_journal **ret, const char *path, int flags);
-void sd_journal_close(sd_journal *j);
-
-int sd_journal_previous(sd_journal *j);
-int sd_journal_next(sd_journal *j);
-
-int sd_journal_previous_skip(sd_journal *j, uint64_t skip);
-int sd_journal_next_skip(sd_journal *j, uint64_t skip);
-
-int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret);
-int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id128_t *ret_boot_id);
-
-int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *l);
-int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *l);
-void sd_journal_restart_data(sd_journal *j);
-
-int sd_journal_add_match(sd_journal *j, const void *data, size_t size);
-int sd_journal_add_disjunction(sd_journal *j);
-void sd_journal_flush_matches(sd_journal *j);
-
-int sd_journal_seek_head(sd_journal *j);
-int sd_journal_seek_tail(sd_journal *j);
-int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t usec);
-int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec);
-int sd_journal_seek_cursor(sd_journal *j, const char *cursor);
-
-int sd_journal_get_cursor(sd_journal *j, char **cursor);
-int sd_journal_test_cursor(sd_journal *j, const char *cursor);
-
-int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, uint64_t *to);
-int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, const sd_id128_t boot_id, uint64_t *from, uint64_t *to);
-
-int sd_journal_get_usage(sd_journal *j, uint64_t *bytes);
-
-int sd_journal_query_unique(sd_journal *j, const char *field);
-int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l);
-void sd_journal_restart_unique(sd_journal *j);
-
-int sd_journal_get_fd(sd_journal *j);
-int sd_journal_reliable_fd(sd_journal *j);
-int sd_journal_process(sd_journal *j);
-int sd_journal_wait(sd_journal *j, uint64_t timeout_usec);
-
-#define SD_JOURNAL_FOREACH(j) \
- if (sd_journal_seek_head(j) >= 0) \
- while (sd_journal_next(j) > 0)
-
-#define SD_JOURNAL_FOREACH_BACKWARDS(j) \
- if (sd_journal_seek_tail(j) >= 0) \
- while (sd_journal_previous(j) > 0)
-
-#define SD_JOURNAL_FOREACH_DATA(j, data, l) \
- for (sd_journal_restart_data(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; )
-
-#define SD_JOURNAL_FOREACH_UNIQUE(j, data, l) \
- for (sd_journal_restart_unique(j); sd_journal_enumerate_unique((j), &(data), &(l)) > 0; )
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/systemd/sd-login.h b/src/systemd/sd-login.h
deleted file mode 100644
index 6bd1f2da4a..0000000000
--- a/src/systemd/sd-login.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef foosdloginhfoo
-#define foosdloginhfoo
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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/types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * A few points:
- *
- * Instead of returning an empty string array or empty uid array, we
- * may return NULL.
- *
- * Free the data the library returns with libc free(). String arrays
- * are NULL terminated and you need to free the array itself in
- * addition to the strings contained.
- *
- * We return error codes as negative errno, kernel-style. 0 or
- * positive on success.
- *
- * These functions access data in /proc, /sys/fs/cgroup and /run. All
- * of these are virtual file systems, hence the accesses are
- * relatively cheap.
- *
- * See sd-login(3) for more information.
- */
-
-/* Get session from PID. Note that 'shared' processes of a user are
- * not attached to a session, but only attached to a user. This will
- * return an error for system processes and 'shared' processes of a
- * user. */
-int sd_pid_get_session(pid_t pid, char **session);
-
-/* Get UID of the owner of the session of the PID (or in case the
- * process is a 'shared' user process the UID of that user is
- * returned). This will not return the UID of the process, but rather
- * the UID of the owner of the cgroup the process is in. This will
- * return an error for system processes. */
-int sd_pid_get_owner_uid(pid_t pid, uid_t *uid);
-
-/* Get systemd unit (i.e. service) name from PID. This will return an
- * error for non-service processes. */
-int sd_pid_get_unit(pid_t, char **unit);
-
-/* Get state from uid. Possible states: offline, lingering, online, active, closing */
-int sd_uid_get_state(uid_t uid, char**state);
-
-/* Return 1 if uid has session on seat. If require_active is true will
- * look for active sessions only. */
-int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat);
-
-/* Return sessions of user. If require_active is true will look for
- * active sessions only. Returns number of sessions as return
- * value. If sessions is NULL will just return number of sessions. */
-int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions);
-
-/* Return seats of user is on. If require_active is true will look for
- * active seats only. Returns number of seats. If seats is NULL will
- * just return number of seats.*/
-int sd_uid_get_seats(uid_t uid, int require_active, char ***seats);
-
-/* Return 1 if the session is a active. */
-int sd_session_is_active(const char *session);
-
-/* Get state from session. Possible states: online, active, closing
- * (This function is a more generic version of
- * sd_session_is_active().) */
-int sd_session_get_state(const char *sessio, char **state);
-
-/* Determine user id of session */
-int sd_session_get_uid(const char *session, uid_t *uid);
-
-/* Determine seat of session */
-int sd_session_get_seat(const char *session, char **seat);
-
-/* Determine the (PAM) service name this session was registered by. */
-int sd_session_get_service(const char *session, char **service);
-
-/* Determine the type of this session, i.e. one of "tty", "x11" or "unspecified". */
-int sd_session_get_type(const char *session, char **type);
-
-/* Determine the class of this session, i.e. one of "user", "greeter" or "lock-screen". */
-int sd_session_get_class(const char *session, char **clazz);
-
-/* Determine the X11 display of this session. */
-int sd_session_get_display(const char *session, char **display);
-
-/* Return active session and user of seat */
-int sd_seat_get_active(const char *seat, char **session, uid_t *uid);
-
-/* Return sessions and users on seat. Returns number of sessions as
- * return value. If sessions is NULL returns only the number of
- * sessions. */
-int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uid, unsigned *n_uids);
-
-/* Return whether the seat is multi-session capable */
-int sd_seat_can_multi_session(const char *seat);
-
-/* Return whether the seat is TTY capable, i.e. suitable for showing console UIs */
-int sd_seat_can_tty(const char *seat);
-
-/* Return whether the seat is graphics capable, i.e. suitable for showing graphical UIs */
-int sd_seat_can_graphical(const char *seat);
-
-/* Get all seats, store in *seats. Returns the number of seats. If
- * seats is NULL only returns number of seats. */
-int sd_get_seats(char ***seats);
-
-/* Get all sessions, store in *sessions. Returns the number of
- * sessions. If sessions is NULL only returns number of sessions. */
-int sd_get_sessions(char ***sessions);
-
-/* Get all logged in users, store in *users. Returns the number of
- * users. If users is NULL only returns the number of users. */
-int sd_get_uids(uid_t **users);
-
-/* Monitor object */
-typedef struct sd_login_monitor sd_login_monitor;
-
-/* Create a new monitor. Category must be NULL, "seat", "session",
- * "uid" to get monitor events for the specific category (or all). */
-int sd_login_monitor_new(const char *category, sd_login_monitor** ret);
-
-/* Destroys the passed monitor. Returns NULL. */
-sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m);
-
-/* Flushes the monitor */
-int sd_login_monitor_flush(sd_login_monitor *m);
-
-/* Get FD from monitor */
-int sd_login_monitor_get_fd(sd_login_monitor *m);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/systemd/sd-messages.h b/src/systemd/sd-messages.h
deleted file mode 100644
index 5099a36e6a..0000000000
--- a/src/systemd/sd-messages.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef foosdmessageshfoo
-#define foosdmessageshfoo
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <systemd/sd-id128.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define SD_MESSAGE_JOURNAL_START SD_ID128_MAKE(f7,73,79,a8,49,0b,40,8b,be,5f,69,40,50,5a,77,7b)
-#define SD_MESSAGE_JOURNAL_STOP SD_ID128_MAKE(d9,3f,b3,c9,c2,4d,45,1a,97,ce,a6,15,ce,59,c0,0b)
-#define SD_MESSAGE_JOURNAL_DROPPED SD_ID128_MAKE(a5,96,d6,fe,7b,fa,49,94,82,8e,72,30,9e,95,d6,1e)
-#define SD_MESSAGE_JOURNAL_MISSED SD_ID128_MAKE(e9,bf,28,e6,e8,34,48,1b,b6,f4,8f,54,8a,d1,36,06)
-
-#define SD_MESSAGE_COREDUMP SD_ID128_MAKE(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1)
-
-#define SD_MESSAGE_SESSION_START SD_ID128_MAKE(8d,45,62,0c,1a,43,48,db,b1,74,10,da,57,c6,0c,66)
-#define SD_MESSAGE_SESSION_STOP SD_ID128_MAKE(33,54,93,94,24,b4,45,6d,98,02,ca,83,33,ed,42,4a)
-#define SD_MESSAGE_SEAT_START SD_ID128_MAKE(fc,be,fc,5d,a2,3d,42,80,93,f9,7c,82,a9,29,0f,7b)
-#define SD_MESSAGE_SEAT_STOP SD_ID128_MAKE(e7,85,2b,fe,46,78,4e,d0,ac,cd,e0,4b,c8,64,c2,d5)
-
-#define SD_MESSAGE_TIME_CHANGE SD_ID128_MAKE(c7,a7,87,07,9b,35,4e,aa,a9,e7,7b,37,18,93,cd,27)
-#define SD_MESSAGE_TIMEZONE_CHANGE SD_ID128_MAKE(45,f8,2f,4a,ef,7a,4b,bf,94,2c,e8,61,d1,f2,09,90)
-
-#define SD_MESSAGE_STARTUP_FINISHED SD_ID128_MAKE(b0,7a,24,9c,d0,24,41,4a,82,dd,00,cd,18,13,78,ff)
-
-#define SD_MESSAGE_SLEEP_START SD_ID128_MAKE(6b,bd,95,ee,97,79,41,e4,97,c4,8b,e2,7c,25,41,28)
-#define SD_MESSAGE_SLEEP_STOP SD_ID128_MAKE(88,11,e6,df,2a,8e,40,f5,8a,94,ce,a2,6f,8e,bf,14)
-
-#define SD_MESSAGE_SHUTDOWN SD_ID128_MAKE(98,26,88,66,d1,d5,4a,49,9c,4e,98,92,1d,93,bc,40)
-
-#define SD_MESSAGE_UNIT_STARTING SD_ID128_MAKE(7d,49,58,e8,42,da,4a,75,8f,6c,1c,dc,7b,36,dc,c5)
-#define SD_MESSAGE_UNIT_STARTED SD_ID128_MAKE(39,f5,34,79,d3,a0,45,ac,8e,11,78,62,48,23,1f,bf)
-#define SD_MESSAGE_UNIT_STOPPING SD_ID128_MAKE(de,5b,42,6a,63,be,47,a7,b6,ac,3e,aa,c8,2e,2f,6f)
-#define SD_MESSAGE_UNIT_STOPPED SD_ID128_MAKE(9d,1a,aa,27,d6,01,40,bd,96,36,54,38,aa,d2,02,86)
-#define SD_MESSAGE_UNIT_FAILED SD_ID128_MAKE(be,02,cf,68,55,d2,42,8b,a4,0d,f7,e9,d0,22,f0,3d)
-#define SD_MESSAGE_UNIT_RELOADING SD_ID128_MAKE(d3,4d,03,7f,ff,18,47,e6,ae,66,9a,37,0e,69,47,25)
-#define SD_MESSAGE_UNIT_RELOADED SD_ID128_MAKE(7b,05,eb,c6,68,38,42,22,ba,a8,88,11,79,cf,da,54)
-
-#define SD_MESSAGE_SPAWN_FAILED SD_ID128_MAKE(64,12,57,65,1c,1b,4e,c9,a8,62,4d,7a,40,a9,e1,e7)
-
-#define SD_MESSAGE_FORWARD_SYSLOG_MISSED SD_ID128_MAKE(00,27,22,9c,a0,64,41,81,a7,6c,4e,92,45,8a,fa,2e)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/systemd/sd-readahead.h b/src/systemd/sd-readahead.h
deleted file mode 100644
index 2dac104f7a..0000000000
--- a/src/systemd/sd-readahead.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef foosdreadaheadhfoo
-#define foosdreadaheadhfoo
-
-/***
- Copyright 2010 Lennart Poettering
-
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation files
- (the "Software"), to deal in the Software without restriction,
- including without limitation the rights to use, copy, modify, merge,
- publish, distribute, sublicense, and/or sell copies of the Software,
- and to permit persons to whom the Software is furnished to do so,
- subject to the following conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
-***/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- Reference implementation of a few boot readahead related
- interfaces. These interfaces are trivial to implement. To simplify
- porting we provide this reference implementation. Applications are
- welcome to reimplement the algorithms described here if they do not
- want to include these two source files.
-
- You may compile this with -DDISABLE_SYSTEMD to disable systemd
- support. This makes all calls NOPs.
-
- Since this is drop-in code we don't want any of our symbols to be
- exported in any case. Hence we declare hidden visibility for all of
- them.
-
- You may find an up-to-date version of these source files online:
-
- http://cgit.freedesktop.org/systemd/systemd/plain/src/systemd/sd-readahead.h
- http://cgit.freedesktop.org/systemd/systemd/plain/src/readahead/sd-readahead.c
-
- This should compile on non-Linux systems, too, but all functions
- will become NOPs.
-
- See sd-readahead(3) for more information.
-*/
-
-/*
- Controls ongoing disk read-ahead operations during boot-up. The argument
- must be a string, and either "cancel", "done" or "noreplay".
-
- cancel = terminate read-ahead data collection, drop collected information
- done = terminate read-ahead data collection, keep collected information
- noreplay = terminate read-ahead replay
-*/
-int sd_readahead(const char *action);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/systemd/sd-shutdown.h b/src/systemd/sd-shutdown.h
deleted file mode 100644
index cee4350173..0000000000
--- a/src/systemd/sd-shutdown.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef foosdshutdownhfoo
-#define foosdshutdownhfoo
-
-/***
- 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/>.
-***/
-
-/* Interface for scheduling and cancelling timed shutdowns. */
-
-#include <inttypes.h>
-
-typedef enum sd_shutdown_mode {
- SD_SHUTDOWN_NONE = 0,
- SD_SHUTDOWN_REBOOT = 'r',
- SD_SHUTDOWN_POWEROFF = 'P',
- SD_SHUTDOWN_HALT = 'H',
- SD_SHUTDOWN_KEXEC = 'K'
-} sd_shutdown_mode_t;
-
-/* Calculate the size of the message as "offsetof(struct
- * sd_shutdown_command, wall_message) +
- * strlen(command.wall_message)" */
-__attribute__((packed)) struct sd_shutdown_command {
- /* Microseconds after the epoch 1970 UTC */
- uint64_t usec;
-
- /* H, P, r, i.e. the switches usually passed to
- * /usr/bin/shutdown to select whether to halt, power-off or
- * reboot the machine */
- sd_shutdown_mode_t mode:8;
-
- /* If non-zero, don't actually shut down, just pretend */
- unsigned dry_run:1;
-
- /* If non-zero, send our wall message */
- unsigned warn_wall:1;
-
- /* The wall message to send around. Leave empty for the
- * default wall message */
- char wall_message[];
-};
-
-/* The scheme is very simple:
- *
- * To schedule a shutdown, simply fill in and send a single
- * AF_UNIX/SOCK_DGRAM datagram with the structure above suffixed with
- * the wall message to the socket /run/systemd/shutdownd (leave an
- * empty wall message for the default shutdown message). To calculate
- * the size of the message use "offsetof(struct sd_shutdown_command,
- * wall_message) + strlen(command.wall_message)".
- *
- * To cancel a shutdown, do the same, but send an fully zeroed out
- * structure.
- *
- * To be notified about scheduled shutdowns, create an inotify watch
- * on /run/shutdown/. Whenever a file called "scheduled" appears a
- * shutdown is scheduled. If it is removed it is canceled. It is
- * replaced the scheduled shutdown has been changed. The file contains
- * a simple environment-like block, that contains information about
- * the scheduled shutdown:
- *
- * USEC=
- * encodes the time for the shutdown in usecs since the epoch UTC,
- * formatted as numeric string.
- *
- * WARN_WALL=
- * is 1 if a wall message shall be sent
- *
- * DRY_RUN=
- * is 1 if a dry run shutdown is scheduled
- *
- * MODE=
- * is the shutdown mode, one of "poweroff", "reboot", "halt", "kexec"
- *
- * WALL_MESSAGE=
- * is the wall message to use, with all special characters escape in C style.
- *
- * Note that some fields might be missing if they do not apply.
- *
- * Note that the file is first written to a temporary file and then
- * renamed, in order to provide atomic properties for readers: if the
- * file exists under the name "scheduled" it is guaranteed to be fully
- * written. A reader should ignore all files in that directory by any
- * other name.
- *
- * Scheduled shutdowns are only accepted from privileged processes,
- * but the directory may be watched and the file in it read by
- * anybody.
- */
-
-#endif
diff --git a/src/test/Makefile b/src/test/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/test/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/test/test-cgroup.c b/src/test/test-cgroup.c
deleted file mode 100644
index 6d64a4e47f..0000000000
--- a/src/test/test-cgroup.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*-*- 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 <unistd.h>
-#include <string.h>
-
-#include "cgroup-util.h"
-#include "path-util.h"
-#include "util.h"
-#include "log.h"
-
-int main(int argc, char*argv[]) {
- char *path;
- char *c, *p;
-
- assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-a") == 0);
- assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-a") == 0);
- assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-b") == 0);
- assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-b/test-c") == 0);
- assert_se(cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0) == 0);
-
- assert_se(cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, getpid(), &path) == 0);
- assert_se(streq(path, "/test-b"));
- free(path);
-
- assert_se(cg_attach(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0) == 0);
-
- assert_se(cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, getpid(), &path) == 0);
- assert_se(path_equal(path, "/test-a"));
- free(path);
-
- assert_se(cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, "/test-b/test-d", 0) == 0);
-
- assert_se(cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, getpid(), &path) == 0);
- assert_se(path_equal(path, "/test-b/test-d"));
- free(path);
-
- assert_se(cg_get_path(SYSTEMD_CGROUP_CONTROLLER, "/test-b/test-d", NULL, &path) == 0);
- assert_se(path_equal(path, "/sys/fs/cgroup/systemd/test-b/test-d"));
- free(path);
-
- assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, "/test-a", false) > 0);
- assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, "/test-b", false) > 0);
- assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", false) > 0);
- assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", false) == 0);
-
- assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, false, false, false, NULL) == 0);
- assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, false, false, false, NULL) > 0);
-
- assert_se(cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", "/test-a", false, false) > 0);
-
- assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", false) == 0);
- assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", false) > 0);
-
- assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, false, false, false, NULL) > 0);
- assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, false, false, false, NULL) == 0);
-
- cg_trim(SYSTEMD_CGROUP_CONTROLLER, "/", false);
-
- assert_se(cg_delete(SYSTEMD_CGROUP_CONTROLLER, "/test-b") < 0);
- assert_se(cg_delete(SYSTEMD_CGROUP_CONTROLLER, "/test-a") >= 0);
-
- assert_se(cg_split_spec("foobar:/", &c, &p) == 0);
- assert(streq(c, "foobar"));
- assert(streq(p, "/"));
- free(c);
- free(p);
-
- assert_se(cg_split_spec("foobar:", &c, &p) < 0);
- assert_se(cg_split_spec("foobar:asdfd", &c, &p) < 0);
- assert_se(cg_split_spec(":///", &c, &p) < 0);
- assert_se(cg_split_spec(":", &c, &p) < 0);
- assert_se(cg_split_spec("", &c, &p) < 0);
- assert_se(cg_split_spec("fo/obar:/", &c, &p) < 0);
-
- assert_se(cg_split_spec("/", &c, &p) >= 0);
- assert(c == NULL);
- assert(streq(p, "/"));
- free(p);
-
- assert_se(cg_split_spec("foo", &c, &p) >= 0);
- assert(streq(c, "foo"));
- assert(p == NULL);
- free(c);
-
- return 0;
-}
diff --git a/src/test/test-daemon.c b/src/test/test-daemon.c
deleted file mode 100644
index 3215f0c560..0000000000
--- a/src/test/test-daemon.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/*-*- 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 <unistd.h>
-
-#include <systemd/sd-daemon.h>
-
-int main(int argc, char*argv[]) {
-
- sd_notify(0, "STATUS=Starting up");
- sleep(5);
- sd_notify(0,
- "STATUS=Running\n"
- "READY=1");
- sleep(10);
- sd_notify(0, "STATUS=Quitting");
-
- return 0;
-}
diff --git a/src/test/test-date.c b/src/test/test-date.c
deleted file mode 100644
index 57f8b371d3..0000000000
--- a/src/test/test-date.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "util.h"
-
-int main(int argc, char *argv[]) {
-
- usec_t t;
- char buf[FORMAT_TIMESTAMP_MAX];
-
- assert_se(parse_timestamp("17:41", &t) >= 0);
- log_info("%s", format_timestamp(buf, sizeof(buf), t));
-
- assert_se(parse_timestamp("18:42:44", &t) >= 0);
- log_info("%s", format_timestamp(buf, sizeof(buf), t));
-
- assert_se(parse_timestamp("12-10-02 12:13:14", &t) >= 0);
- log_info("%s", format_timestamp(buf, sizeof(buf), t));
-
- assert_se(parse_timestamp("12-10-2 12:13:14", &t) >= 0);
- log_info("%s", format_timestamp(buf, sizeof(buf), t));
-
- assert_se(parse_timestamp("12-10-03 12:13", &t) >= 0);
- log_info("%s", format_timestamp(buf, sizeof(buf), t));
-
- assert_se(parse_timestamp("2012-12-30 18:42", &t) >= 0);
- log_info("%s", format_timestamp(buf, sizeof(buf), t));
-
- assert_se(parse_timestamp("2012-10-02", &t) >= 0);
- log_info("%s", format_timestamp(buf, sizeof(buf), t));
-
- assert_se(parse_timestamp("now", &t) >= 0);
- log_info("%s", format_timestamp(buf, sizeof(buf), t));
-
- assert_se(parse_timestamp("yesterday", &t) >= 0);
- log_info("%s", format_timestamp(buf, sizeof(buf), t));
-
- assert_se(parse_timestamp("today", &t) >= 0);
- log_info("%s", format_timestamp(buf, sizeof(buf), t));
-
- assert_se(parse_timestamp("tomorrow", &t) >= 0);
- log_info("%s", format_timestamp(buf, sizeof(buf), t));
-
- assert_se(parse_timestamp("+2d", &t) >= 0);
- log_info("%s", format_timestamp(buf, sizeof(buf), t));
-
- assert_se(parse_timestamp("+2y 4d", &t) >= 0);
- log_info("%s", format_timestamp(buf, sizeof(buf), t));
-
- return 0;
-}
diff --git a/src/test/test-engine.c b/src/test/test-engine.c
deleted file mode 100644
index 0f3862226a..0000000000
--- a/src/test/test-engine.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*-*- 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 <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "manager.h"
-
-int main(int argc, char *argv[]) {
- Manager *m = NULL;
- Unit *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *g = NULL, *h = NULL;
- Job *j;
-
- assert_se(set_unit_path("test") >= 0);
-
- assert_se(manager_new(SYSTEMD_SYSTEM, &m) >= 0);
-
- printf("Load1:\n");
- assert_se(manager_load_unit(m, "a.service", NULL, NULL, &a) >= 0);
- assert_se(manager_load_unit(m, "b.service", NULL, NULL, &b) >= 0);
- assert_se(manager_load_unit(m, "c.service", NULL, NULL, &c) >= 0);
- manager_dump_units(m, stdout, "\t");
-
- printf("Test1: (Trivial)\n");
- assert_se(manager_add_job(m, JOB_START, c, JOB_REPLACE, false, NULL, &j) == 0);
- manager_dump_jobs(m, stdout, "\t");
-
- printf("Load2:\n");
- manager_clear_jobs(m);
- assert_se(manager_load_unit(m, "d.service", NULL, NULL, &d) >= 0);
- assert_se(manager_load_unit(m, "e.service", NULL, NULL, &e) >= 0);
- manager_dump_units(m, stdout, "\t");
-
- printf("Test2: (Cyclic Order, Unfixable)\n");
- assert_se(manager_add_job(m, JOB_START, d, JOB_REPLACE, false, NULL, &j) == -ENOEXEC);
- manager_dump_jobs(m, stdout, "\t");
-
- printf("Test3: (Cyclic Order, Fixable, Garbage Collector)\n");
- assert_se(manager_add_job(m, JOB_START, e, JOB_REPLACE, false, NULL, &j) == 0);
- manager_dump_jobs(m, stdout, "\t");
-
- printf("Test4: (Identical transaction)\n");
- assert_se(manager_add_job(m, JOB_START, e, JOB_FAIL, false, NULL, &j) == 0);
- manager_dump_jobs(m, stdout, "\t");
-
- printf("Load3:\n");
- assert_se(manager_load_unit(m, "g.service", NULL, NULL, &g) >= 0);
- manager_dump_units(m, stdout, "\t");
-
- printf("Test5: (Colliding transaction, fail)\n");
- assert_se(manager_add_job(m, JOB_START, g, JOB_FAIL, false, NULL, &j) == -EEXIST);
-
- printf("Test6: (Colliding transaction, replace)\n");
- assert_se(manager_add_job(m, JOB_START, g, JOB_REPLACE, false, NULL, &j) == 0);
- manager_dump_jobs(m, stdout, "\t");
-
- printf("Test7: (Unmergeable job type, fail)\n");
- assert_se(manager_add_job(m, JOB_STOP, g, JOB_FAIL, false, NULL, &j) == -EEXIST);
-
- printf("Test8: (Mergeable job type, fail)\n");
- assert_se(manager_add_job(m, JOB_RESTART, g, JOB_FAIL, false, NULL, &j) == 0);
- manager_dump_jobs(m, stdout, "\t");
-
- printf("Test9: (Unmergeable job type, replace)\n");
- assert_se(manager_add_job(m, JOB_STOP, g, JOB_REPLACE, false, NULL, &j) == 0);
- manager_dump_jobs(m, stdout, "\t");
-
- printf("Load4:\n");
- assert_se(manager_load_unit(m, "h.service", NULL, NULL, &h) >= 0);
- manager_dump_units(m, stdout, "\t");
-
- printf("Test10: (Unmergeable job type of auxiliary job, fail)\n");
- assert_se(manager_add_job(m, JOB_START, h, JOB_FAIL, false, NULL, &j) == 0);
- manager_dump_jobs(m, stdout, "\t");
-
- manager_free(m);
-
- return 0;
-}
diff --git a/src/test/test-env-replace.c b/src/test/test-env-replace.c
deleted file mode 100644
index cd596a6e16..0000000000
--- a/src/test/test-env-replace.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*-*- 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 <unistd.h>
-#include <string.h>
-
-#include "util.h"
-#include "log.h"
-#include "strv.h"
-
-int main(int argc, char *argv[]) {
-
- const char *env[] = {
- "FOO=BAR BAR",
- "BAR=waldo",
- NULL
- };
-
- const char *line[] = {
- "FOO$FOO",
- "FOO$FOOFOO",
- "FOO${FOO}$FOO",
- "FOO${FOO}",
- "${FOO}",
- "$FOO",
- "$FOO$FOO",
- "${FOO}${BAR}",
- "${FOO",
- NULL
- };
-
- char **i, **r, *t, **a, **b;
- const char nulstr[] = "fuck\0fuck2\0fuck3\0\0fuck5\0\0xxx";
-
- a = strv_parse_nulstr(nulstr, sizeof(nulstr)-1);
-
- STRV_FOREACH(i, a)
- printf("nulstr--%s\n", *i);
-
- strv_free(a);
-
- r = replace_env_argv((char**) line, (char**) env);
-
- STRV_FOREACH(i, r)
- printf("%s\n", *i);
-
- strv_free(r);
-
- t = normalize_env_assignment("foo=bar");
- printf("%s\n", t);
- free(t);
-
- t = normalize_env_assignment("=bar");
- printf("%s\n", t);
- free(t);
-
- t = normalize_env_assignment("foo=");
- printf("%s\n", t);
- free(t);
-
- t = normalize_env_assignment("=");
- printf("%s\n", t);
- free(t);
-
- t = normalize_env_assignment("");
- printf("%s\n", t);
- free(t);
-
- t = normalize_env_assignment("a=\"waldo\"");
- printf("%s\n", t);
- free(t);
-
- t = normalize_env_assignment("a=\"waldo");
- printf("%s\n", t);
- free(t);
-
- t = normalize_env_assignment("a=waldo\"");
- printf("%s\n", t);
- free(t);
-
- t = normalize_env_assignment("a=\'");
- printf("%s\n", t);
- free(t);
-
- t = normalize_env_assignment("a=\'\'");
- printf("%s\n", t);
- free(t);
-
- t = normalize_env_assignment(" xyz ");
- printf("<%s>\n", t);
- free(t);
-
- t = normalize_env_assignment(" xyz = bar ");
- printf("<%s>\n", t);
- free(t);
-
- t = normalize_env_assignment(" xyz = 'bar ' ");
- printf("<%s>\n", t);
- free(t);
-
- t = normalize_env_assignment(" ' xyz' = 'bar ' ");
- printf("<%s>\n", t);
- free(t);
-
- a = strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF", NULL);
- b = strv_new("FOO=KKK", "FOO=", "PIEP=", "SCHLUMPF=SMURFF", "NANANANA=YES", NULL);
-
- r = strv_env_merge(2, a, b);
- strv_free(a);
- strv_free(b);
-
- STRV_FOREACH(i, r)
- printf("%s\n", *i);
-
- printf("CLEANED UP:\n");
-
- r = strv_env_clean(r);
-
- STRV_FOREACH(i, r)
- printf("%s\n", *i);
-
- strv_free(r);
-
- return 0;
-}
diff --git a/src/test/test-hostname.c b/src/test/test-hostname.c
deleted file mode 100644
index ad4f285619..0000000000
--- a/src/test/test-hostname.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*-*- 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 <errno.h>
-#include <string.h>
-#include <stdio.h>
-#include <fcntl.h>
-
-#include "hostname-setup.h"
-#include "util.h"
-
-int main(int argc, char* argv[]) {
- int r;
-
- r = hostname_setup();
- if (r < 0)
- fprintf(stderr, "hostname: %s\n", strerror(-r));
-
- return 0;
-}
diff --git a/src/test/test-id128.c b/src/test/test-id128.c
deleted file mode 100644
index bfd743eca3..0000000000
--- a/src/test/test-id128.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <systemd/sd-id128.h>
-
-#include "util.h"
-#include "macro.h"
-
-#define ID128_WALDI SD_ID128_MAKE(01, 02, 03, 04, 05, 06, 07, 08, 09, 0a, 0b, 0c, 0d, 0e, 0f, 10)
-
-int main(int argc, char *argv[]) {
- sd_id128_t id, id2;
- char t[33];
-
- assert_se(sd_id128_randomize(&id) == 0);
- printf("random: %s\n", sd_id128_to_string(id, t));
-
- assert_se(sd_id128_from_string(t, &id2) == 0);
- assert_se(sd_id128_equal(id, id2));
-
- assert_se(sd_id128_get_machine(&id) == 0);
- printf("machine: %s\n", sd_id128_to_string(id, t));
-
- assert_se(sd_id128_get_boot(&id) == 0);
- printf("boot: %s\n", sd_id128_to_string(id, t));
-
- printf("waldi: %s\n", sd_id128_to_string(ID128_WALDI, t));
-
- printf("waldi2: " SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(ID128_WALDI));
-
- return 0;
-}
diff --git a/src/test/test-install.c b/src/test/test-install.c
deleted file mode 100644
index 2c1b9efcb8..0000000000
--- a/src/test/test-install.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <errno.h>
-#include <string.h>
-#include <stdio.h>
-#include <fcntl.h>
-
-#include "util.h"
-#include "path-util.h"
-#include "install.h"
-
-static void dump_changes(UnitFileChange *c, unsigned n) {
- unsigned i;
-
- assert(n == 0 || c);
-
- for (i = 0; i < n; i++) {
- if (c[i].type == UNIT_FILE_UNLINK)
- printf("rm '%s'\n", c[i].path);
- else if (c[i].type == UNIT_FILE_SYMLINK)
- printf("ln -s '%s' '%s'\n", c[i].source, c[i].path);
- }
-}
-
-int main(int argc, char* argv[]) {
- Hashmap *h;
- UnitFileList *p;
- Iterator i;
- int r;
- const char *const files[] = { "avahi-daemon.service", NULL };
- const char *const files2[] = { "/home/lennart/test.service", NULL };
- UnitFileChange *changes = NULL;
- unsigned n_changes = 0;
-
- h = hashmap_new(string_hash_func, string_compare_func);
- r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h);
- assert_se(r == 0);
-
- HASHMAP_FOREACH(p, h, i) {
- UnitFileState s;
-
- s = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, path_get_file_name(p->path));
-
- assert_se(p->state == s);
-
- fprintf(stderr, "%s (%s)\n",
- p->path,
- unit_file_state_to_string(p->state));
- }
-
- unit_file_list_free(h);
-
- log_error("enable");
-
- r = unit_file_enable(UNIT_FILE_SYSTEM, false, NULL, (char**) files, false, &changes, &n_changes);
- assert_se(r >= 0);
-
- log_error("enable2");
-
- r = unit_file_enable(UNIT_FILE_SYSTEM, false, NULL, (char**) files, false, &changes, &n_changes);
- assert_se(r >= 0);
-
- dump_changes(changes, n_changes);
- unit_file_changes_free(changes, n_changes);
-
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_ENABLED);
-
- log_error("disable");
-
- changes = NULL;
- n_changes = 0;
-
- r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**) files, &changes, &n_changes);
- assert_se(r >= 0);
-
- dump_changes(changes, n_changes);
- unit_file_changes_free(changes, n_changes);
-
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_DISABLED);
-
- log_error("mask");
- changes = NULL;
- n_changes = 0;
-
- r = unit_file_mask(UNIT_FILE_SYSTEM, false, NULL, (char**) files, false, &changes, &n_changes);
- assert_se(r >= 0);
- log_error("mask2");
- r = unit_file_mask(UNIT_FILE_SYSTEM, false, NULL, (char**) files, false, &changes, &n_changes);
- assert_se(r >= 0);
-
- dump_changes(changes, n_changes);
- unit_file_changes_free(changes, n_changes);
-
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_MASKED);
-
- log_error("unmask");
- changes = NULL;
- n_changes = 0;
-
- r = unit_file_unmask(UNIT_FILE_SYSTEM, false, NULL, (char**) files, &changes, &n_changes);
- assert_se(r >= 0);
- log_error("unmask2");
- r = unit_file_unmask(UNIT_FILE_SYSTEM, false, NULL, (char**) files, &changes, &n_changes);
- assert_se(r >= 0);
-
- dump_changes(changes, n_changes);
- unit_file_changes_free(changes, n_changes);
-
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_DISABLED);
-
- log_error("mask");
- changes = NULL;
- n_changes = 0;
-
- r = unit_file_mask(UNIT_FILE_SYSTEM, false, NULL, (char**) files, false, &changes, &n_changes);
- assert_se(r >= 0);
-
- dump_changes(changes, n_changes);
- unit_file_changes_free(changes, n_changes);
-
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_MASKED);
-
- log_error("disable");
- changes = NULL;
- n_changes = 0;
-
- r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**) files, &changes, &n_changes);
- assert_se(r >= 0);
- log_error("disable2");
- r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**) files, &changes, &n_changes);
- assert_se(r >= 0);
-
- dump_changes(changes, n_changes);
- unit_file_changes_free(changes, n_changes);
-
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_MASKED);
-
- log_error("umask");
- changes = NULL;
- n_changes = 0;
-
- r = unit_file_unmask(UNIT_FILE_SYSTEM, false, NULL, (char**) files, &changes, &n_changes);
- assert_se(r >= 0);
-
- dump_changes(changes, n_changes);
- unit_file_changes_free(changes, n_changes);
-
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0]) == UNIT_FILE_DISABLED);
-
- log_error("enable files2");
- changes = NULL;
- n_changes = 0;
-
- r = unit_file_enable(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, false, &changes, &n_changes);
- assert_se(r >= 0);
-
- dump_changes(changes, n_changes);
- unit_file_changes_free(changes, n_changes);
-
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, path_get_file_name(files2[0])) == UNIT_FILE_ENABLED);
-
- log_error("disable files2");
- changes = NULL;
- n_changes = 0;
-
- r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, &changes, &n_changes);
- assert_se(r >= 0);
-
- dump_changes(changes, n_changes);
- unit_file_changes_free(changes, n_changes);
-
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, path_get_file_name(files2[0])) == _UNIT_FILE_STATE_INVALID);
-
- log_error("link files2");
- changes = NULL;
- n_changes = 0;
-
- r = unit_file_link(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, false, &changes, &n_changes);
- assert_se(r >= 0);
-
- dump_changes(changes, n_changes);
- unit_file_changes_free(changes, n_changes);
-
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, path_get_file_name(files2[0])) == UNIT_FILE_LINKED);
-
- log_error("disable files2");
- changes = NULL;
- n_changes = 0;
-
- r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, &changes, &n_changes);
- assert_se(r >= 0);
-
- dump_changes(changes, n_changes);
- unit_file_changes_free(changes, n_changes);
-
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, path_get_file_name(files2[0])) == _UNIT_FILE_STATE_INVALID);
-
- log_error("link files2");
- changes = NULL;
- n_changes = 0;
-
- r = unit_file_link(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, false, &changes, &n_changes);
- assert_se(r >= 0);
-
- dump_changes(changes, n_changes);
- unit_file_changes_free(changes, n_changes);
-
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, path_get_file_name(files2[0])) == UNIT_FILE_LINKED);
-
- log_error("reenable files2");
- changes = NULL;
- n_changes = 0;
-
- r = unit_file_reenable(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, false, &changes, &n_changes);
- assert_se(r >= 0);
-
- dump_changes(changes, n_changes);
- unit_file_changes_free(changes, n_changes);
-
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, path_get_file_name(files2[0])) == UNIT_FILE_ENABLED);
-
- log_error("disable files2");
- changes = NULL;
- n_changes = 0;
-
- r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, &changes, &n_changes);
- assert_se(r >= 0);
-
- dump_changes(changes, n_changes);
- unit_file_changes_free(changes, n_changes);
-
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, path_get_file_name(files2[0])) == _UNIT_FILE_STATE_INVALID);
- log_error("preset files");
- changes = NULL;
- n_changes = 0;
-
- r = unit_file_preset(UNIT_FILE_SYSTEM, false, NULL, (char**) files, false, &changes, &n_changes);
- assert_se(r >= 0);
-
- dump_changes(changes, n_changes);
- unit_file_changes_free(changes, n_changes);
-
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL, path_get_file_name(files[0])) == UNIT_FILE_ENABLED);
-
- return 0;
-}
diff --git a/src/test/test-job-type.c b/src/test/test-job-type.c
deleted file mode 100644
index 1066374436..0000000000
--- a/src/test/test-job-type.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*-*- 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 <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "job.h"
-#include "unit.h"
-#include "service.h"
-
-int main(int argc, char*argv[]) {
- JobType a, b, c, ab, bc, ab_c, bc_a, a_bc;
- const ServiceState test_states[] = { SERVICE_DEAD, SERVICE_RUNNING };
- unsigned i;
- bool merged_ab;
-
- /* fake a unit */
- static Service s = {
- .meta.load_state = UNIT_LOADED,
- .type = SERVICE_SIMPLE,
- };
- Unit *u = UNIT(&s);
-
- for (i = 0; i < ELEMENTSOF(test_states); i++) {
- s.state = test_states[i];
- printf("\nWith collapsing for service state %s\n"
- "=========================================\n", service_state_to_string(s.state));
- for (a = 0; a < _JOB_TYPE_MAX_MERGING; a++) {
- for (b = 0; b < _JOB_TYPE_MAX_MERGING; b++) {
-
- ab = a;
- merged_ab = (job_type_merge_and_collapse(&ab, b, u) >= 0);
-
- if (!job_type_is_mergeable(a, b)) {
- assert(!merged_ab);
- printf("Not mergeable: %s + %s\n", job_type_to_string(a), job_type_to_string(b));
- continue;
- }
-
- assert(merged_ab);
- printf("%s + %s = %s\n", job_type_to_string(a), job_type_to_string(b), job_type_to_string(ab));
-
- for (c = 0; c < _JOB_TYPE_MAX_MERGING; c++) {
-
- /* Verify transitivity of mergeability of job types */
- assert(!job_type_is_mergeable(a, b) ||
- !job_type_is_mergeable(b, c) ||
- job_type_is_mergeable(a, c));
-
- /* Verify that merged entries can be merged with the same entries
- * they can be merged with separately */
- assert(!job_type_is_mergeable(a, c) || job_type_is_mergeable(ab, c));
- assert(!job_type_is_mergeable(b, c) || job_type_is_mergeable(ab, c));
-
- /* Verify that if a merged with b is not mergeable with c, then
- * either a or b is not mergeable with c either. */
- assert(job_type_is_mergeable(ab, c) || !job_type_is_mergeable(a, c) || !job_type_is_mergeable(b, c));
-
- bc = b;
- if (job_type_merge_and_collapse(&bc, c, u) >= 0) {
-
- /* Verify associativity */
-
- ab_c = ab;
- assert(job_type_merge_and_collapse(&ab_c, c, u) == 0);
-
- bc_a = bc;
- assert(job_type_merge_and_collapse(&bc_a, a, u) == 0);
-
- a_bc = a;
- assert(job_type_merge_and_collapse(&a_bc, bc, u) == 0);
-
- assert(ab_c == bc_a);
- assert(ab_c == a_bc);
-
- printf("%s + %s + %s = %s\n", job_type_to_string(a), job_type_to_string(b), job_type_to_string(c), job_type_to_string(ab_c));
- }
- }
- }
- }
- }
-
-
- return 0;
-}
diff --git a/src/test/test-log.c b/src/test/test-log.c
deleted file mode 100644
index 8dc3d5383f..0000000000
--- a/src/test/test-log.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stddef.h>
-#include <unistd.h>
-
-#include "log.h"
-
-int main(int argc, char* argv[]) {
-
- log_set_target(LOG_TARGET_CONSOLE);
- log_open();
-
- log_struct(LOG_INFO,
- "MESSAGE=Waldo PID=%lu", (unsigned long) getpid(),
- "SERVICE=piepapo",
- NULL);
-
- log_set_target(LOG_TARGET_JOURNAL);
- log_open();
-
- log_struct(LOG_INFO,
- "MESSAGE=Foobar PID=%lu", (unsigned long) getpid(),
- "SERVICE=foobar",
- NULL);
-
- log_struct(LOG_INFO,
- "MESSAGE=Foobar PID=%lu", (unsigned long) getpid(),
- "FORMAT_STR_TEST=1=%i A=%c 2=%hi 3=%li 4=%lli 1=%p foo=%s 2.5=%g 3.5=%g 4.5=%Lg",
- (int) 1, 'A', (short) 2, (long int) 3, (long long int) 4, (void*) 1, "foo", (float) 2.5f, (double) 3.5, (long double) 4.5,
- "SUFFIX=GOT IT",
- NULL);
-
- return 0;
-}
diff --git a/src/test/test-loopback.c b/src/test/test-loopback.c
deleted file mode 100644
index ab330ac840..0000000000
--- a/src/test/test-loopback.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/*-*- 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 <errno.h>
-#include <string.h>
-#include <stdio.h>
-#include <fcntl.h>
-
-#include "loopback-setup.h"
-#include "util.h"
-
-int main(int argc, char* argv[]) {
- int r;
-
- if ((r = loopback_setup()) < 0)
- fprintf(stderr, "loopback: %s\n", strerror(-r));
-
- return 0;
-}
diff --git a/src/test/test-ns.c b/src/test/test-ns.c
deleted file mode 100644
index b1c759fc20..0000000000
--- a/src/test/test-ns.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*-*- 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 <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/mount.h>
-#include <linux/fs.h>
-
-#include "namespace.h"
-#include "log.h"
-
-int main(int argc, char *argv[]) {
- const char * const writable[] = {
- "/home",
- NULL
- };
-
- const char * const readonly[] = {
- "/",
- "/usr",
- "/boot",
- NULL
- };
-
- const char * const inaccessible[] = {
- "/home/lennart/projects",
- NULL
- };
-
- int r;
-
- r = setup_namespace((char**) writable, (char**) readonly, (char**) inaccessible, true, 0);
- if (r < 0) {
- log_error("Failed to setup namespace: %s", strerror(-r));
- return 1;
- }
-
- execl("/bin/sh", "/bin/sh", NULL);
- log_error("execl(): %m");
-
- return 1;
-}
diff --git a/src/test/test-replace-var.c b/src/test/test-replace-var.c
deleted file mode 100644
index b1d42d77fd..0000000000
--- a/src/test/test-replace-var.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <string.h>
-
-#include "util.h"
-#include "macro.h"
-#include "replace-var.h"
-
-static char *lookup(const char *variable, void *userdata) {
- return strjoin("<<<", variable, ">>>", NULL);
-}
-
-int main(int argc, char *argv[]) {
- char *r;
-
- assert_se(r = replace_var("@@@foobar@xyz@HALLO@foobar@test@@testtest@TEST@...@@@", lookup, NULL));
- puts(r);
- assert_se(streq(r, "@@@foobar@xyz<<<HALLO>>>foobar@test@@testtest<<<TEST>>>...@@@"));
- free(r);
-
- assert_se(r = strreplace("XYZFFFFXYZFFFFXYZ", "XYZ", "ABC"));
- puts(r);
- assert_se(streq(r, "ABCFFFFABCFFFFABC"));
- free(r);
-
- return 0;
-}
diff --git a/src/test/test-sleep.c b/src/test/test-sleep.c
deleted file mode 100644
index 5a98ecda2f..0000000000
--- a/src/test/test-sleep.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <string.h>
-#include <stdio.h>
-#include <fcntl.h>
-
-#include "util.h"
-#include "log.h"
-
-int main(int argc, char* argv[]) {
- log_info("Can Suspend: %s", yes_no(can_sleep("mem") > 0));
- log_info("Can Hibernate: %s", yes_no(can_sleep("disk") > 0));
- log_info("Can Hibernate+Suspend (Hybrid-Sleep): %s", yes_no(can_sleep_disk("suspend") > 0));
- log_info("Can Hibernate+Reboot: %s", yes_no(can_sleep_disk("reboot") > 0));
- log_info("Can Hibernate+Platform: %s", yes_no(can_sleep_disk("platform") > 0));
- log_info("Can Hibernate+Shutdown: %s", yes_no(can_sleep_disk("shutdown") > 0));
-
- return 0;
-}
diff --git a/src/test/test-strv.c b/src/test/test-strv.c
deleted file mode 100644
index 5ee4447669..0000000000
--- a/src/test/test-strv.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*-*- 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 "util.h"
-#include "specifier.h"
-
-int main(int argc, char *argv[]) {
- const Specifier table[] = {
- { 'a', specifier_string, (char*) "AAAA" },
- { 'b', specifier_string, (char*) "BBBB" },
- { 0, NULL, NULL }
- };
-
- char *w, *state;
- size_t l;
- const char test[] = "test a b c 'd' e '' '' hhh '' ''";
-
- printf("<%s>\n", test);
-
- FOREACH_WORD_QUOTED(w, l, test, state) {
- char *t;
-
- assert_se(t = strndup(w, l));
- printf("<%s>\n", t);
- free(t);
- }
-
- printf("%s\n", default_term_for_tty("/dev/tty23"));
- printf("%s\n", default_term_for_tty("/dev/ttyS23"));
- printf("%s\n", default_term_for_tty("/dev/tty0"));
- printf("%s\n", default_term_for_tty("/dev/pty0"));
- printf("%s\n", default_term_for_tty("/dev/pts/0"));
- printf("%s\n", default_term_for_tty("/dev/console"));
- printf("%s\n", default_term_for_tty("tty23"));
- printf("%s\n", default_term_for_tty("ttyS23"));
- printf("%s\n", default_term_for_tty("tty0"));
- printf("%s\n", default_term_for_tty("pty0"));
- printf("%s\n", default_term_for_tty("pts/0"));
- printf("%s\n", default_term_for_tty("console"));
-
- w = specifier_printf("xxx a=%a b=%b yyy", table, NULL);
- printf("<%s>\n", w);
- free(w);
-
- return 0;
-}
diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
deleted file mode 100644
index 95e2b68015..0000000000
--- a/src/test/test-unit-file.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <assert.h>
-#include <stdio.h>
-#include <stddef.h>
-#include <string.h>
-
-#include "install.h"
-#include "util.h"
-#include "macro.h"
-#include "hashmap.h"
-
-int main(int argc, char *argv[]) {
-
- int r;
- Hashmap *h;
- Iterator i;
- UnitFileList *p;
-
- h = hashmap_new(string_hash_func, string_compare_func);
- assert(h);
-
- r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h);
- log_info("unit_file_get_list: %s", strerror(-r));
- assert(r >= 0);
-
- HASHMAP_FOREACH(p, h, i)
- printf("%s = %s\n", p->path, unit_file_state_to_string(p->state));
-
- unit_file_list_free(h);
-
- return 0;
-}
diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c
deleted file mode 100644
index 50187e1129..0000000000
--- a/src/test/test-unit-name.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "unit-name.h"
-#include "util.h"
-
-int main(int argc, char* argv[]) {
- char *t, *k;
-
- t = unit_name_replace_instance("foo@.service", "waldo");
- puts(t);
- free(t);
-
- t = unit_name_replace_instance("foo@xyz.service", "waldo");
- puts(t);
- free(t);
-
- t = unit_name_replace_instance("xyz", "waldo");
- puts(t);
- free(t);
-
- t = unit_name_replace_instance("", "waldo");
- puts(t);
- free(t);
-
- t = unit_name_replace_instance("", "");
- puts(t);
- free(t);
-
- t = unit_name_replace_instance("foo.service", "waldo");
- puts(t);
- free(t);
-
- t = unit_name_replace_instance(".service", "waldo");
- puts(t);
- free(t);
-
- t = unit_name_replace_instance("foo@bar", "waldo");
- puts(t);
- free(t);
-
- t = unit_name_replace_instance("foo@", "waldo");
- puts(t);
- free(t);
-
- t = unit_name_replace_instance("@", "waldo");
- puts(t);
- free(t);
-
- t = unit_name_replace_instance("@bar", "waldo");
- puts(t);
- free(t);
-
- t = unit_name_from_path("/waldo", ".mount");
- puts(t);
- k = unit_name_to_path(t);
- puts(k);
- free(k);
- free(t);
-
- t = unit_name_from_path("/waldo/quuix", ".mount");
- puts(t);
- k = unit_name_to_path(t);
- puts(k);
- free(k);
- free(t);
-
- t = unit_name_from_path("/waldo/quuix/", ".mount");
- puts(t);
- k = unit_name_to_path(t);
- puts(k);
- free(k);
- free(t);
-
- t = unit_name_from_path("/", ".mount");
- puts(t);
- k = unit_name_to_path(t);
- puts(k);
- free(k);
- free(t);
-
- t = unit_name_from_path("///", ".mount");
- puts(t);
- k = unit_name_to_path(t);
- puts(k);
- free(k);
- free(t);
-
- t = unit_name_from_path_instance("waldo", "/waldo", ".mount");
- puts(t);
- free(t);
-
- t = unit_name_from_path_instance("waldo", "/waldo////quuix////", ".mount");
- puts(t);
- free(t);
-
- t = unit_name_from_path_instance("waldo", "/", ".mount");
- puts(t);
- free(t);
-
- t = unit_name_from_path_instance("wa--ldo", "/--", ".mount");
- puts(t);
- free(t);
-
- assert_se(t = unit_name_mangle("/home"));
- assert_se(k = unit_name_mangle(t));
- puts(t);
- assert_se(streq(t, k));
- free(t);
- free(k);
-
- assert_se(t = unit_name_mangle("/dev/sda"));
- assert_se(k = unit_name_mangle(t));
- puts(t);
- assert_se(streq(t, k));
- free(t);
- free(k);
-
- assert_se(t = unit_name_mangle("üxknürz.service"));
- assert_se(k = unit_name_mangle(t));
- puts(t);
- assert_se(streq(t, k));
- free(t);
- free(k);
-
- assert_se(t = unit_name_mangle("foobar-meh...waldi.service"));
- assert_se(k = unit_name_mangle(t));
- puts(t);
- assert_se(streq(t, k));
- free(t);
- free(k);
-
- assert_se(t = unit_name_mangle("_____####----.....service"));
- assert_se(k = unit_name_mangle(t));
- puts(t);
- assert_se(streq(t, k));
- free(t);
- free(k);
-
- assert_se(t = unit_name_mangle("_____##@;;;,,,##----.....service"));
- assert_se(k = unit_name_mangle(t));
- puts(t);
- assert_se(streq(t, k));
- free(t);
- free(k);
-
- assert_se(t = unit_name_mangle("xxx@@@@/////\\\\\\\\\\yyy.service"));
- assert_se(k = unit_name_mangle(t));
- puts(t);
- assert_se(streq(t, k));
- free(t);
- free(k);
-
- return 0;
-}
diff --git a/src/test/test-watchdog.c b/src/test/test-watchdog.c
deleted file mode 100644
index ccb1854708..0000000000
--- a/src/test/test-watchdog.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <unistd.h>
-#include <string.h>
-
-#include "watchdog.h"
-#include "log.h"
-
-int main(int argc, char *argv[]) {
- usec_t t = 10 * USEC_PER_SEC;
- unsigned i;
- int r;
-
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
-
- r = watchdog_set_timeout(&t);
- if (r < 0)
- log_warning("Failed to open watchdog: %s", strerror(-r));
-
- for (i = 0; i < 5; i++) {
- log_info("Pinging...");
- r = watchdog_ping();
- if (r < 0)
- log_warning("Failed to ping watchdog: %s", strerror(-r));
-
- usleep(t/2);
- }
-
- watchdog_close(true);
- return 0;
-}
diff --git a/src/timedate/.gitignore b/src/timedate/.gitignore
deleted file mode 100644
index 48757f0968..0000000000
--- a/src/timedate/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-org.freedesktop.timedate1.policy
diff --git a/src/timedate/Makefile b/src/timedate/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/timedate/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/timedate/org.freedesktop.timedate1.conf b/src/timedate/org.freedesktop.timedate1.conf
deleted file mode 100644
index 36557d5841..0000000000
--- a/src/timedate/org.freedesktop.timedate1.conf
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0"?> <!--*-nxml-*-->
-<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
-
-<!--
- This file is part of systemd.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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.
--->
-
-<busconfig>
-
- <policy user="root">
- <allow own="org.freedesktop.timedate1"/>
- <allow send_destination="org.freedesktop.timedate1"/>
- <allow receive_sender="org.freedesktop.timedate1"/>
- </policy>
-
- <policy context="default">
- <allow send_destination="org.freedesktop.timedate1"/>
- <allow receive_sender="org.freedesktop.timedate1"/>
- </policy>
-
-</busconfig>
diff --git a/src/timedate/org.freedesktop.timedate1.policy.in b/src/timedate/org.freedesktop.timedate1.policy.in
deleted file mode 100644
index dd0a54d81a..0000000000
--- a/src/timedate/org.freedesktop.timedate1.policy.in
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?> <!--*-nxml-*-->
-<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
-
-<!--
- This file is part of systemd.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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.
--->
-
-<policyconfig>
-
- <vendor>The systemd Project</vendor>
- <vendor_url>http://www.freedesktop.org/wiki/Software/systemd</vendor_url>
-
- <action id="org.freedesktop.timedate1.set-time">
- <_description>Set system time</_description>
- <_message>Authentication is required to set the system time.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.timedate1.set-timezone">
- <_description>Set system timezone</_description>
- <_message>Authentication is required to set the system timezone.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.timedate1.set-local-rtc">
- <_description>Set RTC to local timezone or UTC</_description>
- <_message>Authentication is required to control whether
- the RTC stores the local or UTC time.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
- </defaults>
- </action>
-
- <action id="org.freedesktop.timedate1.set-ntp">
- <_description>Turn network time synchronization on or off</_description>
- <_message>Authentication is required to control whether
- network time synchronization shall be enabled.</_message>
- <defaults>
- <allow_any>auth_admin_keep</allow_any>
- <allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
- </defaults>
- </action>
-
-</policyconfig>
diff --git a/src/timedate/org.freedesktop.timedate1.service b/src/timedate/org.freedesktop.timedate1.service
deleted file mode 100644
index 875f4bec78..0000000000
--- a/src/timedate/org.freedesktop.timedate1.service
+++ /dev/null
@@ -1,12 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-
-[D-BUS Service]
-Name=org.freedesktop.timedate1
-Exec=/bin/false
-User=root
-SystemdService=dbus-org.freedesktop.timedate1.service
diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c
deleted file mode 100644
index c96377f829..0000000000
--- a/src/timedate/timedatectl.c
+++ /dev/null
@@ -1,719 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdlib.h>
-#include <stdbool.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <locale.h>
-#include <string.h>
-#include <sys/timex.h>
-
-#include "dbus-common.h"
-#include "util.h"
-#include "spawn-polkit-agent.h"
-#include "build.h"
-#include "hwclock.h"
-#include "strv.h"
-#include "pager.h"
-#include "time-dst.h"
-
-static bool arg_adjust_system_clock = false;
-static bool arg_no_pager = false;
-static enum transport {
- TRANSPORT_NORMAL,
- TRANSPORT_SSH,
- TRANSPORT_POLKIT
-} arg_transport = TRANSPORT_NORMAL;
-static bool arg_ask_password = true;
-static const char *arg_host = NULL;
-
-static void pager_open_if_enabled(void) {
-
- if (arg_no_pager)
- return;
-
- pager_open();
-}
-
-static void polkit_agent_open_if_enabled(void) {
-
- /* Open the polkit agent as a child process if necessary */
-
- if (!arg_ask_password)
- return;
-
- polkit_agent_open();
-}
-
-typedef struct StatusInfo {
- const char *timezone;
- bool local_rtc;
- bool ntp;
-} StatusInfo;
-
-static bool ntp_synced(void) {
- struct timex txc;
-
- zero(txc);
- if (adjtimex(&txc) < 0)
- return false;
-
- if (txc.status & STA_UNSYNC)
- return false;
-
- return true;
-}
-
-static const char *jump_str(int delta_minutes, char *s, size_t size) {
- if (delta_minutes == 60)
- return "one hour forward";
- if (delta_minutes == -60)
- return "one hour backwards";
- if (delta_minutes < 0) {
- snprintf(s, size, "%i minutes backwards", -delta_minutes);
- return s;
- }
- if (delta_minutes > 0) {
- snprintf(s, size, "%i minutes forward", delta_minutes);
- return s;
- }
- return "";
-}
-
-static void print_status_info(StatusInfo *i) {
- usec_t n;
- char a[FORMAT_TIMESTAMP_MAX];
- char b[FORMAT_TIMESTAMP_MAX];
- char s[32];
- struct tm tm;
- time_t sec;
- char *zc, *zn;
- time_t t, tc, tn;
- int dn;
- bool is_dstc, is_dstn;
- int r;
-
- assert(i);
-
- /* enforce the values of /etc/localtime */
- if (getenv("TZ")) {
- fprintf(stderr, "Warning: ignoring the TZ variable, reading the system's timezone setting only.\n\n");
- unsetenv("TZ");
- }
-
- n = now(CLOCK_REALTIME);
- sec = (time_t) (n / USEC_PER_SEC);
-
- zero(tm);
- assert_se(strftime(a, sizeof(a), "%a, %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm)) > 0);
- char_array_0(a);
- printf(" Local time: %s\n", a);
-
- zero(tm);
- assert_se(strftime(a, sizeof(a), "%a, %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm)) > 0);
- char_array_0(a);
- printf(" Universal time: %s\n", a);
-
- zero(tm);
- r = hwclock_get_time(&tm);
- if (r >= 0) {
- /* Calculcate the week-day */
- mktime(&tm);
-
- assert_se(strftime(a, sizeof(a), "%a, %Y-%m-%d %H:%M:%S", &tm) > 0);
- char_array_0(a);
- printf(" RTC time: %s\n", a);
- }
-
- zero(tm);
- assert_se(strftime(a, sizeof(a), "%z", localtime_r(&sec, &tm)) > 0);
- char_array_0(a);
- printf(" Timezone: %s\n"
- " UTC offset: %s\n"
- " NTP enabled: %s\n"
- "NTP synchronized: %s\n"
- " RTC in local TZ: %s\n",
- strna(i->timezone),
- a,
- yes_no(i->ntp),
- yes_no(ntp_synced()),
- yes_no(i->local_rtc));
-
- r = time_get_dst(sec, "/etc/localtime",
- &tc, &zc, &is_dstc,
- &tn, &dn, &zn, &is_dstn);
- if (r < 0)
- printf(" DST active: n/a\n");
- else {
- printf(" DST active: %s\n", yes_no(is_dstc));
-
- t = tc - 1;
- zero(tm);
- assert_se(strftime(a, sizeof(a), "%a, %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm)) > 0);
- char_array_0(a);
-
- zero(tm);
- assert_se(strftime(b, sizeof(b), "%a, %Y-%m-%d %H:%M:%S %Z", localtime_r(&tc, &tm)) > 0);
- char_array_0(b);
- printf(" Last DST change: %s → %s, DST became %s\n"
- " %s\n"
- " %s\n",
- strna(zn), strna(zc), is_dstc ? "active" : "inactive", a, b);
-
- t = tn - 1;
- zero(tm);
- assert_se(strftime(a, sizeof(a), "%a, %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm)) > 0);
- char_array_0(a);
-
- zero(tm);
- assert_se(strftime(b, sizeof(b), "%a, %Y-%m-%d %H:%M:%S %Z", localtime_r(&tn, &tm)) > 0);
- char_array_0(b);
- printf(" Next DST change: %s → %s, DST will become %s\n"
- " the clock will jump %s\n"
- " %s\n"
- " %s\n",
- strna(zc), strna(zn), is_dstn ? "active" : "inactive", jump_str(dn, s, sizeof(s)), a, b);
-
- free(zc);
- free(zn);
- }
-
- if (i->local_rtc)
- fputs("\n" ANSI_HIGHLIGHT_ON
- "Warning: The RTC is configured to maintain time in the local time zone. This\n"
- " mode is not fully supported and will create various problems with time\n"
- " zone changes and daylight saving adjustments. If at all possible use\n"
- " RTC in UTC, by calling 'timedatectl set-local-rtc 0'" ANSI_HIGHLIGHT_OFF ".\n", stdout);
-}
-
-static int status_property(const char *name, DBusMessageIter *iter, StatusInfo *i) {
- assert(name);
- assert(iter);
-
- switch (dbus_message_iter_get_arg_type(iter)) {
-
- case DBUS_TYPE_STRING: {
- const char *s;
-
- dbus_message_iter_get_basic(iter, &s);
- if (!isempty(s)) {
- if (streq(name, "Timezone"))
- i->timezone = s;
- }
- break;
- }
-
- case DBUS_TYPE_BOOLEAN: {
- dbus_bool_t b;
-
- dbus_message_iter_get_basic(iter, &b);
- if (streq(name, "LocalRTC"))
- i->local_rtc = b;
- else if (streq(name, "NTP"))
- i->ntp = b;
- }
- }
-
- return 0;
-}
-
-static int show_status(DBusConnection *bus, char **args, unsigned n) {
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- const char *interface = "";
- int r;
- DBusMessageIter iter, sub, sub2, sub3;
- StatusInfo info;
-
- assert(args);
-
- r = bus_method_call_with_reply(
- bus,
- "org.freedesktop.timedate1",
- "/org/freedesktop/timedate1",
- "org.freedesktop.DBus.Properties",
- "GetAll",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &interface,
- DBUS_TYPE_INVALID);
- if (r < 0)
- return r;
-
- if (!dbus_message_iter_init(reply, &iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
- log_error("Failed to parse reply.");
- return -EIO;
- }
-
- zero(info);
- dbus_message_iter_recurse(&iter, &sub);
-
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- const char *name;
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
- log_error("Failed to parse reply.");
- return -EIO;
- }
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
- log_error("Failed to parse reply.");
- return -EIO;
- }
-
- if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
- log_error("Failed to parse reply.");
- return -EIO;
- }
-
- dbus_message_iter_recurse(&sub2, &sub3);
-
- r = status_property(name, &sub3, &info);
- if (r < 0) {
- log_error("Failed to parse reply.");
- return r;
- }
-
- dbus_message_iter_next(&sub);
- }
-
- print_status_info(&info);
- return 0;
-}
-
-static int set_time(DBusConnection *bus, char **args, unsigned n) {
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- dbus_bool_t relative = false, interactive = true;
- usec_t t;
- dbus_int64_t u;
- int r;
-
- assert(args);
- assert(n == 2);
-
- polkit_agent_open_if_enabled();
-
- r = parse_timestamp(args[1], &t);
- if (r < 0) {
- log_error("Failed to parse time specification: %s", args[1]);
- return r;
- }
-
- u = (dbus_uint64_t) t;
-
- return bus_method_call_with_reply(
- bus,
- "org.freedesktop.timedate1",
- "/org/freedesktop/timedate1",
- "org.freedesktop.timedate1",
- "SetTime",
- &reply,
- NULL,
- DBUS_TYPE_INT64, &u,
- DBUS_TYPE_BOOLEAN, &relative,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID);
-}
-
-static int set_timezone(DBusConnection *bus, char **args, unsigned n) {
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- dbus_bool_t interactive = true;
-
- assert(args);
- assert(n == 2);
-
- polkit_agent_open_if_enabled();
-
- return bus_method_call_with_reply(
- bus,
- "org.freedesktop.timedate1",
- "/org/freedesktop/timedate1",
- "org.freedesktop.timedate1",
- "SetTimezone",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &args[1],
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID);
-}
-
-static int set_local_rtc(DBusConnection *bus, char **args, unsigned n) {
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- dbus_bool_t interactive = true, b, q;
- int r;
-
- assert(args);
- assert(n == 2);
-
- polkit_agent_open_if_enabled();
-
- r = parse_boolean(args[1]);
- if (r < 0) {
- log_error("Failed to parse local RTC setting: %s", args[1]);
- return r;
- }
-
- b = r;
- q = arg_adjust_system_clock;
-
- return bus_method_call_with_reply(
- bus,
- "org.freedesktop.timedate1",
- "/org/freedesktop/timedate1",
- "org.freedesktop.timedate1",
- "SetLocalRTC",
- &reply,
- NULL,
- DBUS_TYPE_BOOLEAN, &b,
- DBUS_TYPE_BOOLEAN, &q,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID);
-}
-
-static int set_ntp(DBusConnection *bus, char **args, unsigned n) {
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- dbus_bool_t interactive = true, b;
- int r;
-
- assert(args);
- assert(n == 2);
-
- polkit_agent_open_if_enabled();
-
- r = parse_boolean(args[1]);
- if (r < 0) {
- log_error("Failed to parse NTP setting: %s", args[1]);
- return r;
- }
-
- b = r;
-
- return bus_method_call_with_reply(
- bus,
- "org.freedesktop.timedate1",
- "/org/freedesktop/timedate1",
- "org.freedesktop.timedate1",
- "SetNTP",
- &reply,
- NULL,
- DBUS_TYPE_BOOLEAN, &b,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID);
-}
-
-static int list_timezones(DBusConnection *bus, char **args, unsigned n) {
- _cleanup_fclose_ FILE *f = NULL;
- _cleanup_strv_free_ char **zones = NULL;
- size_t n_zones = 0;
- char **i;
-
- assert(args);
- assert(n == 1);
-
- f = fopen("/usr/share/zoneinfo/zone.tab", "re");
- if (!f) {
- log_error("Failed to open timezone database: %m");
- return -errno;
- }
-
- for (;;) {
- char l[LINE_MAX], *p, **z, *w;
- size_t k;
-
- if (!fgets(l, sizeof(l), f)) {
- if (feof(f))
- break;
-
- log_error("Failed to read timezone database: %m");
- return -errno;
- }
-
- p = strstrip(l);
-
- if (isempty(p) || *p == '#')
- continue;
-
-
- /* Skip over country code */
- p += strcspn(p, WHITESPACE);
- p += strspn(p, WHITESPACE);
-
- /* Skip over coordinates */
- p += strcspn(p, WHITESPACE);
- p += strspn(p, WHITESPACE);
-
- /* Found timezone name */
- k = strcspn(p, WHITESPACE);
- if (k <= 0)
- continue;
-
- w = strndup(p, k);
- if (!w)
- return log_oom();
-
- z = realloc(zones, sizeof(char*) * (n_zones + 2));
- if (!z) {
- free(w);
- return log_oom();
- }
-
- zones = z;
- zones[n_zones++] = w;
- }
-
- if (zones)
- zones[n_zones] = NULL;
-
- pager_open_if_enabled();
-
- strv_sort(zones);
- STRV_FOREACH(i, zones)
- puts(*i);
-
- return 0;
-}
-
-static int help(void) {
-
- printf("%s [OPTIONS...] COMMAND ...\n\n"
- "Query or change system time and date settings.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --adjust-system-clock\n"
- " Adjust system clock when changing local RTC mode\n"
- " --no-pager Do not pipe output into a pager\n"
- " --no-ask-password Do not prompt for password\n"
- " -H --host=[USER@]HOST Operate on remote host\n\n"
- "Commands:\n"
- " status Show current time settings\n"
- " set-time TIME Set system time\n"
- " set-timezone ZONE Set system timezone\n"
- " list-timezones Show known timezones\n"
- " set-local-rtc BOOL Control whether RTC is in local time\n"
- " set-ntp BOOL Control whether NTP is enabled\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100,
- ARG_NO_PAGER,
- ARG_ADJUST_SYSTEM_CLOCK,
- ARG_NO_ASK_PASSWORD
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "no-pager", no_argument, NULL, ARG_NO_PAGER },
- { "host", required_argument, NULL, 'H' },
- { "privileged", no_argument, NULL, 'P' },
- { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
- { "adjust-system-clock", no_argument, NULL, ARG_ADJUST_SYSTEM_CLOCK },
- { NULL, 0, NULL, 0 }
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "+hH:P", options, NULL)) >= 0) {
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(DISTRIBUTION);
- puts(SYSTEMD_FEATURES);
- return 0;
-
- case 'P':
- arg_transport = TRANSPORT_POLKIT;
- break;
-
- case 'H':
- arg_transport = TRANSPORT_SSH;
- arg_host = optarg;
- break;
-
- case ARG_ADJUST_SYSTEM_CLOCK:
- arg_adjust_system_clock = true;
- break;
-
- case ARG_NO_PAGER:
- arg_no_pager = true;
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- log_error("Unknown option code %c", c);
- return -EINVAL;
- }
- }
-
- return 1;
-}
-
-static int timedatectl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
-
- static const struct {
- const char* verb;
- const enum {
- MORE,
- LESS,
- EQUAL
- } argc_cmp;
- const int argc;
- int (* const dispatch)(DBusConnection *bus, char **args, unsigned n);
- } verbs[] = {
- { "status", LESS, 1, show_status },
- { "set-time", EQUAL, 2, set_time },
- { "set-timezone", EQUAL, 2, set_timezone },
- { "list-timezones", EQUAL, 1, list_timezones },
- { "set-local-rtc", EQUAL, 2, set_local_rtc },
- { "set-ntp", EQUAL, 2, set_ntp, },
- };
-
- int left;
- unsigned i;
-
- assert(argc >= 0);
- assert(argv);
- assert(error);
-
- left = argc - optind;
-
- if (left <= 0)
- /* Special rule: no arguments means "status" */
- i = 0;
- else {
- if (streq(argv[optind], "help")) {
- help();
- return 0;
- }
-
- for (i = 0; i < ELEMENTSOF(verbs); i++)
- if (streq(argv[optind], verbs[i].verb))
- break;
-
- if (i >= ELEMENTSOF(verbs)) {
- log_error("Unknown operation %s", argv[optind]);
- return -EINVAL;
- }
- }
-
- switch (verbs[i].argc_cmp) {
-
- case EQUAL:
- if (left != verbs[i].argc) {
- log_error("Invalid number of arguments.");
- return -EINVAL;
- }
-
- break;
-
- case MORE:
- if (left < verbs[i].argc) {
- log_error("Too few arguments.");
- return -EINVAL;
- }
-
- break;
-
- case LESS:
- if (left > verbs[i].argc) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
- break;
-
- default:
- assert_not_reached("Unknown comparison operator.");
- }
-
- if (!bus) {
- log_error("Failed to get D-Bus connection: %s", error->message);
- return -EIO;
- }
-
- return verbs[i].dispatch(bus, argv + optind, left);
-}
-
-int main(int argc, char *argv[]) {
- int r, retval = EXIT_FAILURE;
- DBusConnection *bus = NULL;
- DBusError error;
-
- dbus_error_init(&error);
-
- setlocale(LC_ALL, "");
- log_parse_environment();
- log_open();
-
- r = parse_argv(argc, argv);
- if (r < 0)
- goto finish;
- else if (r == 0) {
- retval = EXIT_SUCCESS;
- goto finish;
- }
-
- if (arg_transport == TRANSPORT_NORMAL)
- bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
- else if (arg_transport == TRANSPORT_POLKIT)
- bus_connect_system_polkit(&bus, &error);
- else if (arg_transport == TRANSPORT_SSH)
- bus_connect_system_ssh(NULL, arg_host, &bus, &error);
- else
- assert_not_reached("Uh, invalid transport...");
-
- r = timedatectl_main(bus, argc, argv, &error);
- retval = r < 0 ? EXIT_FAILURE : r;
-
-finish:
- if (bus) {
- dbus_connection_flush(bus);
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
- }
-
- dbus_error_free(&error);
- dbus_shutdown();
-
- pager_close();
-
- return retval;
-}
diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
deleted file mode 100644
index 40ba255090..0000000000
--- a/src/timedate/timedated.c
+++ /dev/null
@@ -1,1042 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU 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 <dbus/dbus.h>
-
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "systemd/sd-id128.h"
-#include "systemd/sd-messages.h"
-#include "util.h"
-#include "strv.h"
-#include "dbus-common.h"
-#include "polkit.h"
-#include "def.h"
-#include "hwclock.h"
-#include "conf-files.h"
-#include "path-util.h"
-
-#define NULL_ADJTIME_UTC "0.0 0 0\n0\nUTC\n"
-#define NULL_ADJTIME_LOCAL "0.0 0 0\n0\nLOCAL\n"
-
-#define INTERFACE \
- " <interface name=\"org.freedesktop.timedate1\">\n" \
- " <property name=\"Timezone\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"LocalRTC\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"NTP\" type=\"b\" access=\"read\"/>\n" \
- " <method name=\"SetTime\">\n" \
- " <arg name=\"usec_utc\" type=\"x\" direction=\"in\"/>\n" \
- " <arg name=\"relative\" type=\"b\" direction=\"in\"/>\n" \
- " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"SetTimezone\">\n" \
- " <arg name=\"timezone\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"SetLocalRTC\">\n" \
- " <arg name=\"local_rtc\" type=\"b\" direction=\"in\"/>\n" \
- " <arg name=\"fix_system\" type=\"b\" direction=\"in\"/>\n" \
- " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"SetNTP\">\n" \
- " <arg name=\"use_ntp\" type=\"b\" direction=\"in\"/>\n" \
- " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
- " </method>\n" \
- " </interface>\n"
-
-#define INTROSPECTION \
- DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
- "<node>\n" \
- INTERFACE \
- BUS_PROPERTIES_INTERFACE \
- BUS_INTROSPECTABLE_INTERFACE \
- BUS_PEER_INTERFACE \
- "</node>\n"
-
-#define INTERFACES_LIST \
- BUS_GENERIC_INTERFACES_LIST \
- "org.freedesktop.timedate1\0"
-
-const char timedate_interface[] _introspect_("timedate1") = INTERFACE;
-
-typedef struct TZ {
- char *zone;
- bool local_rtc;
- int use_ntp;
-} TZ;
-
-static TZ tz = {
- .use_ntp = -1,
-};
-
-static usec_t remain_until;
-
-static void free_data(void) {
- free(tz.zone);
- tz.zone = NULL;
-
- tz.local_rtc = false;
-}
-
-static bool valid_timezone(const char *name) {
- const char *p;
- char *t;
- bool slash = false;
- int r;
- struct stat st;
-
- assert(name);
-
- if (*name == '/' || *name == 0)
- return false;
-
- for (p = name; *p; p++) {
- if (!(*p >= '0' && *p <= '9') &&
- !(*p >= 'a' && *p <= 'z') &&
- !(*p >= 'A' && *p <= 'Z') &&
- !(*p == '-' || *p == '_' || *p == '+' || *p == '/'))
- return false;
-
- if (*p == '/') {
-
- if (slash)
- return false;
-
- slash = true;
- } else
- slash = false;
- }
-
- if (slash)
- return false;
-
- t = strappend("/usr/share/zoneinfo/", name);
- if (!t)
- return false;
-
- r = stat(t, &st);
- free(t);
-
- if (r < 0)
- return false;
-
- if (!S_ISREG(st.st_mode))
- return false;
-
- return true;
-}
-
-static int read_data(void) {
- int r;
- _cleanup_free_ char *t = NULL;
-
- free_data();
-
- r = readlink_malloc("/etc/localtime", &t);
- if (r < 0) {
- if (r == -EINVAL)
- log_warning("/etc/localtime should be a symbolic link to a timezone data file in /usr/share/zoneinfo/.");
- else
- log_warning("Failed to get target of /etc/localtime: %s", strerror(-r));
- } else {
- const char *e;
-
- e = path_startswith(t, "/usr/share/zoneinfo/");
- if (!e)
- e = path_startswith(t, "../usr/share/zoneinfo/");
-
- if (!e)
- log_warning("/etc/localtime should be a symbolic link to a timezone data file in /usr/share/zoneinfo/.");
- else {
- tz.zone = strdup(e);
- if (!tz.zone)
- return log_oom();
-
- goto have_timezone;
- }
- }
-
-#ifdef HAVE_DEBIAN
- r = read_one_line_file("/etc/timezone", &tz.zone);
- if (r < 0) {
- if (r != -ENOENT)
- log_warning("Failed to read /etc/timezone: %s", strerror(-r));
- }
-#endif
-
-have_timezone:
- if (isempty(tz.zone)) {
- free(tz.zone);
- tz.zone = NULL;
- }
-
- tz.local_rtc = hwclock_is_localtime() > 0;
-
- return 0;
-}
-
-static int write_data_timezone(void) {
- int r = 0;
- _cleanup_free_ char *p = NULL;
-
-#ifdef TARGET_DEBIAN
- struct stat st;
-#endif
-
- if (!tz.zone) {
- if (unlink("/etc/localtime") < 0 && errno != ENOENT)
- r = -errno;
-
-#ifdef TARGET_DEBIAN
- if (unlink("/etc/timezone") < 0 && errno != ENOENT)
- r = -errno;
-#endif
-
- return r;
- }
-
- p = strappend("../usr/share/zoneinfo/", tz.zone);
- if (!p)
- return log_oom();
-
- r = symlink_atomic(p, "/etc/localtime");
- if (r < 0)
- return r;
-
-#ifdef TARGET_DEBIAN
- if (stat("/etc/timezone", &st) == 0 && S_ISREG(st.st_mode)) {
- r = write_one_line_file_atomic("/etc/timezone", tz.zone);
- if (r < 0)
- return r;
- }
-#endif
-
- return 0;
-}
-
-static int write_data_local_rtc(void) {
- int r;
- char *s, *w;
-
- r = read_full_file("/etc/adjtime", &s, NULL);
- if (r < 0) {
- if (r != -ENOENT)
- return r;
-
- if (!tz.local_rtc)
- return 0;
-
- w = strdup(NULL_ADJTIME_LOCAL);
- if (!w)
- return -ENOMEM;
- } else {
- char *p, *e;
- size_t a, b;
-
- p = strchr(s, '\n');
- if (!p) {
- free(s);
- return -EIO;
- }
-
- p = strchr(p+1, '\n');
- if (!p) {
- free(s);
- return -EIO;
- }
-
- p++;
- e = strchr(p, '\n');
- if (!e) {
- free(s);
- return -EIO;
- }
-
- a = p - s;
- b = strlen(e);
-
- w = new(char, a + (tz.local_rtc ? 5 : 3) + b + 1);
- if (!w) {
- free(s);
- return -ENOMEM;
- }
-
- *(char*) mempcpy(stpcpy(mempcpy(w, s, a), tz.local_rtc ? "LOCAL" : "UTC"), e, b) = 0;
-
- if (streq(w, NULL_ADJTIME_UTC)) {
- free(w);
-
- if (unlink("/etc/adjtime") < 0) {
- if (errno != ENOENT)
- return -errno;
- }
-
- return 0;
- }
- }
-
- r = write_one_line_file_atomic("/etc/adjtime", w);
- free(w);
-
- return r;
-}
-
-static char** get_ntp_services(void) {
- char **r = NULL, **files, **i;
- int k;
-
- k = conf_files_list(&files, ".list",
- "/etc/systemd/ntp-units.d",
- "/run/systemd/ntp-units.d",
- "/usr/local/lib/systemd/ntp-units.d",
- "/usr/lib/systemd/ntp-units.d",
- NULL);
- if (k < 0)
- return NULL;
-
- STRV_FOREACH(i, files) {
- FILE *f;
-
- f = fopen(*i, "re");
- if (!f)
- continue;
-
- for (;;) {
- char line[PATH_MAX], *l, **q;
-
- if (!fgets(line, sizeof(line), f)) {
-
- if (ferror(f))
- log_error("Failed to read NTP units file: %m");
-
- break;
- }
-
- l = strstrip(line);
- if (l[0] == 0 || l[0] == '#')
- continue;
-
- q = strv_append(r, l);
- if (!q) {
- log_oom();
- break;
- }
-
- strv_free(r);
- r = q;
- }
-
- fclose(f);
- }
-
- strv_free(files);
-
- return strv_uniq(r);
-}
-
-static int read_ntp(DBusConnection *bus) {
- DBusMessage *m = NULL, *reply = NULL;
- DBusError error;
- int r;
- char **i, **l;
-
- assert(bus);
-
- dbus_error_init(&error);
-
- l = get_ntp_services();
- STRV_FOREACH(i, l) {
- const char *s;
-
- if (m)
- dbus_message_unref(m);
- m = dbus_message_new_method_call(
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "GetUnitFileState");
- if (!m) {
- r = log_oom();
- goto finish;
- }
-
- if (!dbus_message_append_args(m,
- DBUS_TYPE_STRING, i,
- DBUS_TYPE_INVALID)) {
- r = log_oom();
- goto finish;
- }
-
- if (reply)
- dbus_message_unref(reply);
- reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
- if (!reply) {
- if (streq(error.name, "org.freedesktop.DBus.Error.FileNotFound")) {
- /* This implementation does not exist, try next one */
- dbus_error_free(&error);
- continue;
- }
-
- log_error("Failed to issue method call: %s", bus_error_message(&error));
- r = -EIO;
- goto finish;
- }
-
- if (!dbus_message_get_args(reply, &error,
- DBUS_TYPE_STRING, &s,
- DBUS_TYPE_INVALID)) {
- log_error("Failed to parse reply: %s", bus_error_message(&error));
- r = -EIO;
- goto finish;
- }
-
- tz.use_ntp =
- streq(s, "enabled") ||
- streq(s, "enabled-runtime");
- r = 0;
- goto finish;
- }
-
- /* NTP is not installed. */
- tz.use_ntp = 0;
- r = 0;
-
-finish:
- if (m)
- dbus_message_unref(m);
-
- if (reply)
- dbus_message_unref(reply);
-
- strv_free(l);
-
- dbus_error_free(&error);
-
- return r;
-}
-
-static int start_ntp(DBusConnection *bus, DBusError *error) {
- DBusMessage *m = NULL, *reply = NULL;
- const char *mode = "replace";
- char **i, **l;
- int r;
-
- assert(bus);
- assert(error);
-
- l = get_ntp_services();
- STRV_FOREACH(i, l) {
- if (m)
- dbus_message_unref(m);
- m = dbus_message_new_method_call(
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- tz.use_ntp ? "StartUnit" : "StopUnit");
- if (!m) {
- log_error("Could not allocate message.");
- r = -ENOMEM;
- goto finish;
- }
-
- if (!dbus_message_append_args(m,
- DBUS_TYPE_STRING, i,
- DBUS_TYPE_STRING, &mode,
- DBUS_TYPE_INVALID)) {
- log_error("Could not append arguments to message.");
- r = -ENOMEM;
- goto finish;
- }
-
- if (reply)
- dbus_message_unref(reply);
- reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error);
- if (!reply) {
- if (streq(error->name, "org.freedesktop.DBus.Error.FileNotFound") ||
- streq(error->name, "org.freedesktop.systemd1.LoadFailed") ||
- streq(error->name, "org.freedesktop.systemd1.NoSuchUnit")) {
- /* This implementation does not exist, try next one */
- dbus_error_free(error);
- continue;
- }
-
- log_error("Failed to issue method call: %s", bus_error_message(error));
- r = -EIO;
- goto finish;
- }
-
- r = 0;
- goto finish;
- }
-
- /* No implementaiton available... */
- r = -ENOENT;
-
-finish:
- if (m)
- dbus_message_unref(m);
-
- if (reply)
- dbus_message_unref(reply);
-
- strv_free(l);
-
- return r;
-}
-
-static int enable_ntp(DBusConnection *bus, DBusError *error) {
- DBusMessage *m = NULL, *reply = NULL;
- int r;
- DBusMessageIter iter;
- dbus_bool_t f = FALSE, t = TRUE;
- char **i, **l;
-
- assert(bus);
- assert(error);
-
- l = get_ntp_services();
- STRV_FOREACH(i, l) {
- char* k[2];
-
- if (m)
- dbus_message_unref(m);
- m = dbus_message_new_method_call(
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- tz.use_ntp ? "EnableUnitFiles" : "DisableUnitFiles");
- if (!m) {
- log_error("Could not allocate message.");
- r = -ENOMEM;
- goto finish;
- }
-
- dbus_message_iter_init_append(m, &iter);
-
- k[0] = *i;
- k[1] = NULL;
-
- r = bus_append_strv_iter(&iter, k);
- if (r < 0) {
- log_error("Failed to append unit files.");
- goto finish;
- }
-
- /* send runtime bool */
- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &f)) {
- log_error("Failed to append runtime boolean.");
- r = -ENOMEM;
- goto finish;
- }
-
- if (tz.use_ntp) {
- /* send force bool */
- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &t)) {
- log_error("Failed to append force boolean.");
- r = -ENOMEM;
- goto finish;
- }
- }
-
- if (reply)
- dbus_message_unref(reply);
- reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error);
- if (!reply) {
- if (streq(error->name, "org.freedesktop.DBus.Error.FileNotFound")) {
- /* This implementation does not exist, try next one */
- dbus_error_free(error);
- continue;
- }
-
- log_error("Failed to issue method call: %s", bus_error_message(error));
- r = -EIO;
- goto finish;
- }
-
- dbus_message_unref(m);
- m = dbus_message_new_method_call(
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "Reload");
- if (!m) {
- log_error("Could not allocate message.");
- r = -ENOMEM;
- goto finish;
- }
-
- dbus_message_unref(reply);
- reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error);
- if (!reply) {
- log_error("Failed to issue method call: %s", bus_error_message(error));
- r = -EIO;
- goto finish;
- }
-
- r = 0;
- goto finish;
- }
-
- r = -ENOENT;
-
-finish:
- if (m)
- dbus_message_unref(m);
-
- if (reply)
- dbus_message_unref(reply);
-
- strv_free(l);
-
- return r;
-}
-
-static int property_append_ntp(DBusMessageIter *i, const char *property, void *data) {
- dbus_bool_t db;
-
- assert(i);
- assert(property);
-
- db = tz.use_ntp > 0;
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &db))
- return -ENOMEM;
-
- return 0;
-}
-
-static const BusProperty bus_timedate_properties[] = {
- { "Timezone", bus_property_append_string, "s", offsetof(TZ, zone), true },
- { "LocalRTC", bus_property_append_bool, "b", offsetof(TZ, local_rtc) },
- { "NTP", property_append_ntp, "b", offsetof(TZ, use_ntp) },
- { NULL, }
-};
-
-static const BusBoundProperties bps[] = {
- { "org.freedesktop.timedate1", bus_timedate_properties, &tz },
- { NULL, }
-};
-
-static DBusHandlerResult timedate_message_handler(
- DBusConnection *connection,
- DBusMessage *message,
- void *userdata) {
-
- DBusMessage *reply = NULL, *changed = NULL;
- DBusError error;
- int r;
-
- assert(connection);
- assert(message);
-
- dbus_error_init(&error);
-
- if (dbus_message_is_method_call(message, "org.freedesktop.timedate1", "SetTimezone")) {
- const char *z;
- dbus_bool_t interactive;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &z,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- if (!valid_timezone(z))
- return bus_send_error_reply(connection, message, NULL, -EINVAL);
-
- if (!streq_ptr(z, tz.zone)) {
- char *t;
-
- r = verify_polkit(connection, message, "org.freedesktop.timedate1.set-timezone", interactive, NULL, &error);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- t = strdup(z);
- if (!t)
- goto oom;
-
- free(tz.zone);
- tz.zone = t;
-
- /* 1. Write new configuration file */
- r = write_data_timezone();
- if (r < 0) {
- log_error("Failed to set timezone: %s", strerror(-r));
- return bus_send_error_reply(connection, message, NULL, r);
- }
-
- /* 2. Tell the kernel our time zone */
- hwclock_set_timezone(NULL);
-
- if (tz.local_rtc) {
- struct timespec ts;
- struct tm *tm;
-
- /* 3. Sync RTC from system clock, with the new delta */
- assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
- assert_se(tm = localtime(&ts.tv_sec));
- hwclock_set_time(tm);
- }
-
- log_struct(LOG_INFO,
- MESSAGE_ID(SD_MESSAGE_TIMEZONE_CHANGE),
- "TIMEZONE=%s", tz.zone,
- "MESSAGE=Changed timezone to '%s'.", tz.zone,
- NULL);
-
- changed = bus_properties_changed_new(
- "/org/freedesktop/timedate1",
- "org.freedesktop.timedate1",
- "Timezone\0");
- if (!changed)
- goto oom;
- }
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.timedate1", "SetLocalRTC")) {
- dbus_bool_t lrtc;
- dbus_bool_t fix_system;
- dbus_bool_t interactive;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_BOOLEAN, &lrtc,
- DBUS_TYPE_BOOLEAN, &fix_system,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- if (lrtc != tz.local_rtc) {
- struct timespec ts;
-
- r = verify_polkit(connection, message, "org.freedesktop.timedate1.set-local-rtc", interactive, NULL, &error);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- tz.local_rtc = lrtc;
-
- /* 1. Write new configuration file */
- r = write_data_local_rtc();
- if (r < 0) {
- log_error("Failed to set RTC to local/UTC: %s", strerror(-r));
- return bus_send_error_reply(connection, message, NULL, r);
- }
-
- /* 2. Tell the kernel our time zone */
- hwclock_set_timezone(NULL);
-
- /* 3. Synchronize clocks */
- assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
-
- if (fix_system) {
- struct tm tm;
-
- /* Sync system clock from RTC; first,
- * initialize the timezone fields of
- * struct tm. */
- if (tz.local_rtc)
- tm = *localtime(&ts.tv_sec);
- else
- tm = *gmtime(&ts.tv_sec);
-
- /* Override the main fields of
- * struct tm, but not the timezone
- * fields */
- if (hwclock_get_time(&tm) >= 0) {
-
- /* And set the system clock
- * with this */
- if (tz.local_rtc)
- ts.tv_sec = mktime(&tm);
- else
- ts.tv_sec = timegm(&tm);
-
- clock_settime(CLOCK_REALTIME, &ts);
- }
-
- } else {
- struct tm *tm;
-
- /* Sync RTC from system clock */
- if (tz.local_rtc)
- tm = localtime(&ts.tv_sec);
- else
- tm = gmtime(&ts.tv_sec);
-
- hwclock_set_time(tm);
- }
-
- log_info("RTC configured to %s time.", tz.local_rtc ? "local" : "UTC");
-
- changed = bus_properties_changed_new(
- "/org/freedesktop/timedate1",
- "org.freedesktop.timedate1",
- "LocalRTC\0");
- if (!changed)
- goto oom;
- }
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.timedate1", "SetTime")) {
- int64_t utc;
- dbus_bool_t relative;
- dbus_bool_t interactive;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_INT64, &utc,
- DBUS_TYPE_BOOLEAN, &relative,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- if (!relative && utc <= 0)
- return bus_send_error_reply(connection, message, NULL, -EINVAL);
-
- if (!relative || utc != 0) {
- struct timespec ts;
- struct tm* tm;
-
- r = verify_polkit(connection, message, "org.freedesktop.timedate1.set-time", interactive, NULL, &error);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- if (relative)
- timespec_store(&ts, now(CLOCK_REALTIME) + utc);
- else
- timespec_store(&ts, utc);
-
- /* Set system clock */
- if (clock_settime(CLOCK_REALTIME, &ts) < 0) {
- log_error("Failed to set local time: %m");
- return bus_send_error_reply(connection, message, NULL, -errno);
- }
-
- /* Sync down to RTC */
- if (tz.local_rtc)
- tm = localtime(&ts.tv_sec);
- else
- tm = gmtime(&ts.tv_sec);
-
- hwclock_set_time(tm);
-
- log_struct(LOG_INFO,
- MESSAGE_ID(SD_MESSAGE_TIME_CHANGE),
- "REALTIME=%llu", (unsigned long long) timespec_load(&ts),
- "MESSAGE=Changed local time to %s", ctime(&ts.tv_sec),
- NULL);
- }
- } else if (dbus_message_is_method_call(message, "org.freedesktop.timedate1", "SetNTP")) {
- dbus_bool_t ntp;
- dbus_bool_t interactive;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_BOOLEAN, &ntp,
- DBUS_TYPE_BOOLEAN, &interactive,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(connection, message, &error, -EINVAL);
-
- if (ntp != !!tz.use_ntp) {
-
- r = verify_polkit(connection, message, "org.freedesktop.timedate1.set-ntp", interactive, NULL, &error);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- tz.use_ntp = !!ntp;
-
- r = enable_ntp(connection, &error);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- r = start_ntp(connection, &error);
- if (r < 0)
- return bus_send_error_reply(connection, message, &error, r);
-
- log_info("Set NTP to %s", tz.use_ntp ? "enabled" : "disabled");
-
- changed = bus_properties_changed_new(
- "/org/freedesktop/timedate1",
- "org.freedesktop.timedate1",
- "NTP\0");
- if (!changed)
- goto oom;
- }
-
- } else
- return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps);
-
- if (!(reply = dbus_message_new_method_return(message)))
- goto oom;
-
- if (!dbus_connection_send(connection, reply, NULL))
- goto oom;
-
- dbus_message_unref(reply);
- reply = NULL;
-
- if (changed) {
-
- if (!dbus_connection_send(connection, changed, NULL))
- goto oom;
-
- dbus_message_unref(changed);
- }
-
- return DBUS_HANDLER_RESULT_HANDLED;
-
-oom:
- if (reply)
- dbus_message_unref(reply);
-
- if (changed)
- dbus_message_unref(changed);
-
- dbus_error_free(&error);
-
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-}
-
-static int connect_bus(DBusConnection **_bus) {
- static const DBusObjectPathVTable timedate_vtable = {
- .message_function = timedate_message_handler
- };
- DBusError error;
- DBusConnection *bus = NULL;
- int r;
-
- assert(_bus);
-
- dbus_error_init(&error);
-
- bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
- if (!bus) {
- log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
- r = -ECONNREFUSED;
- goto fail;
- }
-
- dbus_connection_set_exit_on_disconnect(bus, FALSE);
-
- if (!dbus_connection_register_object_path(bus, "/org/freedesktop/timedate1", &timedate_vtable, NULL) ||
- !dbus_connection_add_filter(bus, bus_exit_idle_filter, &remain_until, NULL)) {
- r = log_oom();
- goto fail;
- }
-
- r = dbus_bus_request_name(bus, "org.freedesktop.timedate1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
- if (dbus_error_is_set(&error)) {
- log_error("Failed to register name on bus: %s", bus_error_message(&error));
- r = -EEXIST;
- goto fail;
- }
-
- if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
- log_error("Failed to acquire name.");
- r = -EEXIST;
- goto fail;
- }
-
- if (_bus)
- *_bus = bus;
-
- return 0;
-
-fail:
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
-
- dbus_error_free(&error);
-
- return r;
-}
-
-int main(int argc, char *argv[]) {
- int r;
- DBusConnection *bus = NULL;
- bool exiting = false;
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- if (argc == 2 && streq(argv[1], "--introspect")) {
- fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
- "<node>\n", stdout);
- fputs(timedate_interface, stdout);
- fputs("</node>\n", stdout);
- return 0;
- }
-
- if (argc != 1) {
- log_error("This program takes no arguments.");
- r = -EINVAL;
- goto finish;
- }
-
- r = read_data();
- if (r < 0) {
- log_error("Failed to read timezone data: %s", strerror(-r));
- goto finish;
- }
-
- r = connect_bus(&bus);
- if (r < 0)
- goto finish;
-
- r = read_ntp(bus);
- if (r < 0) {
- log_error("Failed to determine whether NTP is enabled: %s", strerror(-r));
- goto finish;
- }
-
- remain_until = now(CLOCK_MONOTONIC) + DEFAULT_EXIT_USEC;
- for (;;) {
-
- if (!dbus_connection_read_write_dispatch(bus, exiting ? -1 : (int) (DEFAULT_EXIT_USEC/USEC_PER_MSEC)))
- break;
-
- if (!exiting && remain_until < now(CLOCK_MONOTONIC)) {
- exiting = true;
- bus_async_unregister_and_exit(bus, "org.freedesktop.timedated1");
- }
- }
-
- r = 0;
-
-finish:
- free_data();
-
- if (bus) {
- dbus_connection_flush(bus);
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
- }
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/timestamp/Makefile b/src/timestamp/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/timestamp/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/timestamp/timestamp.c b/src/timestamp/timestamp.c
deleted file mode 100644
index 1152f1b52e..0000000000
--- a/src/timestamp/timestamp.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*-*- 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 <stdio.h>
-
-#include "util.h"
-
-int main(int argc, char *argv[]) {
- struct dual_timestamp t;
-
- /* This is mostly useful for stuff like init ram disk scripts
- * which want to take a proper timestamp to do minimal bootup
- * profiling. */
-
- dual_timestamp_get(&t);
- printf("%llu %llu\n",
- (unsigned long long) t.realtime,
- (unsigned long long) t.monotonic);
-
- return 0;
-}
diff --git a/src/tmpfiles/Makefile b/src/tmpfiles/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/tmpfiles/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
deleted file mode 100644
index c27d0112f9..0000000000
--- a/src/tmpfiles/tmpfiles.c
+++ /dev/null
@@ -1,1418 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering, Kay Sievers
-
- 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 <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <limits.h>
-#include <dirent.h>
-#include <grp.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <getopt.h>
-#include <stdbool.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <glob.h>
-#include <fnmatch.h>
-#include <sys/capability.h>
-
-#include "log.h"
-#include "util.h"
-#include "macro.h"
-#include "mkdir.h"
-#include "path-util.h"
-#include "strv.h"
-#include "label.h"
-#include "set.h"
-#include "conf-files.h"
-#include "capability.h"
-
-/* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
- * them in the file system. This is intended to be used to create
- * properly owned directories beneath /tmp, /var/tmp, /run, which are
- * volatile and hence need to be recreated on bootup. */
-
-typedef enum ItemType {
- /* These ones take file names */
- CREATE_FILE = 'f',
- TRUNCATE_FILE = 'F',
- WRITE_FILE = 'w',
- CREATE_DIRECTORY = 'd',
- TRUNCATE_DIRECTORY = 'D',
- CREATE_FIFO = 'p',
- CREATE_SYMLINK = 'L',
- CREATE_CHAR_DEVICE = 'c',
- CREATE_BLOCK_DEVICE = 'b',
-
- /* These ones take globs */
- IGNORE_PATH = 'x',
- REMOVE_PATH = 'r',
- RECURSIVE_REMOVE_PATH = 'R',
- RELABEL_PATH = 'z',
- RECURSIVE_RELABEL_PATH = 'Z'
-} ItemType;
-
-typedef struct Item {
- ItemType type;
-
- char *path;
- char *argument;
- uid_t uid;
- gid_t gid;
- mode_t mode;
- usec_t age;
-
- dev_t major_minor;
-
- bool uid_set:1;
- bool gid_set:1;
- bool mode_set:1;
- bool age_set:1;
-
- bool keep_first_level:1;
-} Item;
-
-static Hashmap *items = NULL, *globs = NULL;
-static Set *unix_sockets = NULL;
-
-static bool arg_create = false;
-static bool arg_clean = false;
-static bool arg_remove = false;
-
-static const char *arg_prefix = NULL;
-
-static const char * const conf_file_dirs[] = {
- "/etc/tmpfiles.d",
- "/run/tmpfiles.d",
- "/usr/local/lib/tmpfiles.d",
- "/usr/lib/tmpfiles.d",
-#ifdef HAVE_SPLIT_USR
- "/lib/tmpfiles.d",
-#endif
- NULL
-};
-
-#define MAX_DEPTH 256
-
-static bool needs_glob(ItemType t) {
- return t == IGNORE_PATH || t == REMOVE_PATH || t == RECURSIVE_REMOVE_PATH || t == RELABEL_PATH || t == RECURSIVE_RELABEL_PATH;
-}
-
-static struct Item* find_glob(Hashmap *h, const char *match) {
- Item *j;
- Iterator i;
-
- HASHMAP_FOREACH(j, h, i)
- if (fnmatch(j->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
- return j;
-
- return NULL;
-}
-
-static void load_unix_sockets(void) {
- FILE *f = NULL;
- char line[LINE_MAX];
-
- if (unix_sockets)
- return;
-
- /* We maintain a cache of the sockets we found in
- * /proc/net/unix to speed things up a little. */
-
- unix_sockets = set_new(string_hash_func, string_compare_func);
- if (!unix_sockets)
- return;
-
- f = fopen("/proc/net/unix", "re");
- if (!f)
- return;
-
- /* Skip header */
- if (!fgets(line, sizeof(line), f))
- goto fail;
-
- for (;;) {
- char *p, *s;
- int k;
-
- if (!fgets(line, sizeof(line), f))
- break;
-
- truncate_nl(line);
-
- p = strchr(line, ':');
- if (!p)
- continue;
-
- if (strlen(p) < 37)
- continue;
-
- p += 37;
- p += strspn(p, WHITESPACE);
- p += strcspn(p, WHITESPACE); /* skip one more word */
- p += strspn(p, WHITESPACE);
-
- if (*p != '/')
- continue;
-
- s = strdup(p);
- if (!s)
- goto fail;
-
- path_kill_slashes(s);
-
- k = set_put(unix_sockets, s);
- if (k < 0) {
- free(s);
-
- if (k != -EEXIST)
- goto fail;
- }
- }
-
- fclose(f);
- return;
-
-fail:
- set_free_free(unix_sockets);
- unix_sockets = NULL;
-
- if (f)
- fclose(f);
-}
-
-static bool unix_socket_alive(const char *fn) {
- assert(fn);
-
- load_unix_sockets();
-
- if (unix_sockets)
- return !!set_get(unix_sockets, (char*) fn);
-
- /* We don't know, so assume yes */
- return true;
-}
-
-static int dir_cleanup(
- const char *p,
- DIR *d,
- const struct stat *ds,
- usec_t cutoff,
- dev_t rootdev,
- bool mountpoint,
- int maxdepth,
- bool keep_this_level)
-{
- struct dirent *dent;
- struct timespec times[2];
- bool deleted = false;
- char *sub_path = NULL;
- int r = 0;
-
- while ((dent = readdir(d))) {
- struct stat s;
- usec_t age;
-
- if (streq(dent->d_name, ".") ||
- streq(dent->d_name, ".."))
- continue;
-
- if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
-
- if (errno != ENOENT) {
- log_error("stat(%s/%s) failed: %m", p, dent->d_name);
- r = -errno;
- }
-
- continue;
- }
-
- /* Stay on the same filesystem */
- if (s.st_dev != rootdev)
- continue;
-
- /* Do not delete read-only files owned by root */
- if (s.st_uid == 0 && !(s.st_mode & S_IWUSR))
- continue;
-
- free(sub_path);
- sub_path = NULL;
-
- if (asprintf(&sub_path, "%s/%s", p, dent->d_name) < 0) {
- r = log_oom();
- goto finish;
- }
-
- /* Is there an item configured for this path? */
- if (hashmap_get(items, sub_path))
- continue;
-
- if (find_glob(globs, sub_path))
- continue;
-
- if (S_ISDIR(s.st_mode)) {
-
- if (mountpoint &&
- streq(dent->d_name, "lost+found") &&
- s.st_uid == 0)
- continue;
-
- if (maxdepth <= 0)
- log_warning("Reached max depth on %s.", sub_path);
- else {
- DIR *sub_dir;
- int q;
-
- sub_dir = xopendirat(dirfd(d), dent->d_name, O_NOFOLLOW|O_NOATIME);
- if (sub_dir == NULL) {
- if (errno != ENOENT) {
- log_error("opendir(%s/%s) failed: %m", p, dent->d_name);
- r = -errno;
- }
-
- continue;
- }
-
- q = dir_cleanup(sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false);
- closedir(sub_dir);
-
- if (q < 0)
- r = q;
- }
-
- /* Note: if you are wondering why we don't
- * support the sticky bit for excluding
- * directories from cleaning like we do it for
- * other file system objects: well, the sticky
- * bit already has a meaning for directories,
- * so we don't want to overload that. */
-
- if (keep_this_level)
- continue;
-
- /* Ignore ctime, we change it when deleting */
- age = MAX(timespec_load(&s.st_mtim),
- timespec_load(&s.st_atim));
- if (age >= cutoff)
- continue;
-
- log_debug("rmdir '%s'\n", sub_path);
-
- if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) {
- if (errno != ENOENT && errno != ENOTEMPTY) {
- log_error("rmdir(%s): %m", sub_path);
- r = -errno;
- }
- }
-
- } else {
- /* Skip files for which the sticky bit is
- * set. These are semantics we define, and are
- * unknown elsewhere. See XDG_RUNTIME_DIR
- * specification for details. */
- if (s.st_mode & S_ISVTX)
- continue;
-
- if (mountpoint && S_ISREG(s.st_mode)) {
- if (streq(dent->d_name, ".journal") &&
- s.st_uid == 0)
- continue;
-
- if (streq(dent->d_name, "aquota.user") ||
- streq(dent->d_name, "aquota.group"))
- continue;
- }
-
- /* Ignore sockets that are listed in /proc/net/unix */
- if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path))
- continue;
-
- /* Ignore device nodes */
- if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode))
- continue;
-
- /* Keep files on this level around if this is
- * requested */
- if (keep_this_level)
- continue;
-
- age = MAX3(timespec_load(&s.st_mtim),
- timespec_load(&s.st_atim),
- timespec_load(&s.st_ctim));
-
- if (age >= cutoff)
- continue;
-
- log_debug("unlink '%s'\n", sub_path);
-
- if (unlinkat(dirfd(d), dent->d_name, 0) < 0) {
- if (errno != ENOENT) {
- log_error("unlink(%s): %m", sub_path);
- r = -errno;
- }
- }
-
- deleted = true;
- }
- }
-
-finish:
- if (deleted) {
- /* Restore original directory timestamps */
- times[0] = ds->st_atim;
- times[1] = ds->st_mtim;
-
- if (futimens(dirfd(d), times) < 0)
- log_error("utimensat(%s): %m", p);
- }
-
- free(sub_path);
-
- return r;
-}
-
-static int clean_item(Item *i) {
- DIR *d;
- struct stat s, ps;
- bool mountpoint;
- int r;
- usec_t cutoff, n;
-
- assert(i);
-
- if (i->type != CREATE_DIRECTORY &&
- i->type != TRUNCATE_DIRECTORY &&
- i->type != IGNORE_PATH)
- return 0;
-
- if (!i->age_set)
- return 0;
-
- n = now(CLOCK_REALTIME);
- if (n < i->age)
- return 0;
-
- cutoff = n - i->age;
-
- d = opendir(i->path);
- if (!d) {
- if (errno == ENOENT)
- return 0;
-
- log_error("Failed to open directory %s: %m", i->path);
- return -errno;
- }
-
- if (fstat(dirfd(d), &s) < 0) {
- log_error("stat(%s) failed: %m", i->path);
- r = -errno;
- goto finish;
- }
-
- if (!S_ISDIR(s.st_mode)) {
- log_error("%s is not a directory.", i->path);
- r = -ENOTDIR;
- goto finish;
- }
-
- if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0) {
- log_error("stat(%s/..) failed: %m", i->path);
- r = -errno;
- goto finish;
- }
-
- mountpoint = s.st_dev != ps.st_dev ||
- (s.st_dev == ps.st_dev && s.st_ino == ps.st_ino);
-
- r = dir_cleanup(i->path, d, &s, cutoff, s.st_dev, mountpoint, MAX_DEPTH, i->keep_first_level);
-
-finish:
- if (d)
- closedir(d);
-
- return r;
-}
-
-static int item_set_perms(Item *i, const char *path) {
- /* not using i->path directly because it may be a glob */
- if (i->mode_set)
- if (chmod(path, i->mode) < 0) {
- log_error("chmod(%s) failed: %m", path);
- return -errno;
- }
-
- if (i->uid_set || i->gid_set)
- if (chown(path,
- i->uid_set ? i->uid : (uid_t) -1,
- i->gid_set ? i->gid : (gid_t) -1) < 0) {
-
- log_error("chown(%s) failed: %m", path);
- return -errno;
- }
-
- return label_fix(path, false, false);
-}
-
-static int write_one_file(Item *i, const char *path) {
- int r, e, fd, flags;
- struct stat st;
- mode_t u;
-
- flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND :
- i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC : 0;
-
- u = umask(0);
- label_context_set(path, S_IFREG);
- fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY|O_NOFOLLOW, i->mode);
- e = errno;
- label_context_clear();
- umask(u);
- errno = e;
-
- if (fd < 0) {
- if (i->type == WRITE_FILE && errno == ENOENT)
- return 0;
-
- log_error("Failed to create file %s: %m", path);
- return -errno;
- }
-
- if (i->argument) {
- ssize_t n;
- size_t l;
- _cleanup_free_ char *unescaped;
-
- unescaped = cunescape(i->argument);
- if (unescaped == NULL)
- return log_oom();
-
- l = strlen(unescaped);
- n = write(fd, unescaped, l);
-
- if (n < 0 || (size_t) n < l) {
- log_error("Failed to write file %s: %s", path, n < 0 ? strerror(-n) : "Short write");
- close_nointr_nofail(fd);
- return n < 0 ? n : -EIO;
- }
- }
-
- close_nointr_nofail(fd);
-
- if (stat(path, &st) < 0) {
- log_error("stat(%s) failed: %m", path);
- return -errno;
- }
-
- if (!S_ISREG(st.st_mode)) {
- log_error("%s is not a file.", path);
- return -EEXIST;
- }
-
- r = item_set_perms(i, path);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static int recursive_relabel_children(Item *i, const char *path) {
- DIR *d;
- int ret = 0;
-
- /* This returns the first error we run into, but nevertheless
- * tries to go on */
-
- d = opendir(path);
- if (!d)
- return errno == ENOENT ? 0 : -errno;
-
- for (;;) {
- struct dirent *de;
- union dirent_storage buf;
- bool is_dir;
- int r;
- char *entry_path;
-
- r = readdir_r(d, &buf.de, &de);
- if (r != 0) {
- if (ret == 0)
- ret = -r;
- break;
- }
-
- if (!de)
- break;
-
- if (streq(de->d_name, ".") || streq(de->d_name, ".."))
- continue;
-
- if (asprintf(&entry_path, "%s/%s", path, de->d_name) < 0) {
- if (ret == 0)
- ret = -ENOMEM;
- continue;
- }
-
- if (de->d_type == DT_UNKNOWN) {
- struct stat st;
-
- if (lstat(entry_path, &st) < 0) {
- if (ret == 0 && errno != ENOENT)
- ret = -errno;
- free(entry_path);
- continue;
- }
-
- is_dir = S_ISDIR(st.st_mode);
-
- } else
- is_dir = de->d_type == DT_DIR;
-
- r = item_set_perms(i, entry_path);
- if (r < 0) {
- if (ret == 0 && r != -ENOENT)
- ret = r;
- free(entry_path);
- continue;
- }
-
- if (is_dir) {
- r = recursive_relabel_children(i, entry_path);
- if (r < 0 && ret == 0)
- ret = r;
- }
-
- free(entry_path);
- }
-
- closedir(d);
-
- return ret;
-}
-
-static int recursive_relabel(Item *i, const char *path) {
- int r;
- struct stat st;
-
- r = item_set_perms(i, path);
- if (r < 0)
- return r;
-
- if (lstat(path, &st) < 0)
- return -errno;
-
- if (S_ISDIR(st.st_mode))
- r = recursive_relabel_children(i, path);
-
- return r;
-}
-
-static int glob_item(Item *i, int (*action)(Item *, const char *)) {
- int r = 0, k;
- glob_t g;
- char **fn;
-
- zero(g);
-
- errno = 0;
- if ((k = glob(i->path, GLOB_NOSORT|GLOB_BRACE, NULL, &g)) != 0) {
-
- if (k != GLOB_NOMATCH) {
- if (errno != 0)
- errno = EIO;
-
- log_error("glob(%s) failed: %m", i->path);
- return -errno;
- }
- }
-
- STRV_FOREACH(fn, g.gl_pathv)
- if ((k = action(i, *fn)) < 0)
- r = k;
-
- globfree(&g);
- return r;
-}
-
-static int create_item(Item *i) {
- int r, e;
- mode_t u;
- struct stat st;
-
- assert(i);
-
- switch (i->type) {
-
- case IGNORE_PATH:
- case REMOVE_PATH:
- case RECURSIVE_REMOVE_PATH:
- return 0;
-
- case CREATE_FILE:
- case TRUNCATE_FILE:
- r = write_one_file(i, i->path);
- if (r < 0)
- return r;
- break;
- case WRITE_FILE:
- r = glob_item(i, write_one_file);
- if (r < 0)
- return r;
-
- break;
-
- case TRUNCATE_DIRECTORY:
- case CREATE_DIRECTORY:
-
- u = umask(0);
- mkdir_parents_label(i->path, 0755);
- r = mkdir(i->path, i->mode);
- umask(u);
-
- if (r < 0 && errno != EEXIST) {
- log_error("Failed to create directory %s: %m", i->path);
- return -errno;
- }
-
- if (stat(i->path, &st) < 0) {
- log_error("stat(%s) failed: %m", i->path);
- return -errno;
- }
-
- if (!S_ISDIR(st.st_mode)) {
- log_error("%s is not a directory.", i->path);
- return -EEXIST;
- }
-
- r = item_set_perms(i, i->path);
- if (r < 0)
- return r;
-
- break;
-
- case CREATE_FIFO:
-
- u = umask(0);
- r = mkfifo(i->path, i->mode);
- umask(u);
-
- if (r < 0 && errno != EEXIST) {
- log_error("Failed to create fifo %s: %m", i->path);
- return -errno;
- }
-
- if (stat(i->path, &st) < 0) {
- log_error("stat(%s) failed: %m", i->path);
- return -errno;
- }
-
- if (!S_ISFIFO(st.st_mode)) {
- log_error("%s is not a fifo.", i->path);
- return -EEXIST;
- }
-
- r = item_set_perms(i, i->path);
- if (r < 0)
- return r;
-
- break;
-
- case CREATE_SYMLINK: {
- char *x;
-
- label_context_set(i->path, S_IFLNK);
- r = symlink(i->argument, i->path);
- e = errno;
- label_context_clear();
- errno = e;
-
- if (r < 0 && errno != EEXIST) {
- log_error("symlink(%s, %s) failed: %m", i->argument, i->path);
- return -errno;
- }
-
- r = readlink_malloc(i->path, &x);
- if (r < 0) {
- log_error("readlink(%s) failed: %s", i->path, strerror(-r));
- return -errno;
- }
-
- if (!streq(i->argument, x)) {
- free(x);
- log_error("%s is not the right symlinks.", i->path);
- return -EEXIST;
- }
-
- free(x);
- break;
- }
-
- case CREATE_BLOCK_DEVICE:
- case CREATE_CHAR_DEVICE: {
- mode_t file_type;
-
- if (have_effective_cap(CAP_MKNOD) == 0) {
- /* In a container we lack CAP_MKNOD. We
- shouldnt attempt to create the device node in
- that case to avoid noise, and we don't support
- virtualized devices in containers anyway. */
-
- log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
- return 0;
- }
-
- file_type = (i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR);
-
- u = umask(0);
- label_context_set(i->path, file_type);
- r = mknod(i->path, i->mode | file_type, i->major_minor);
- e = errno;
- label_context_clear();
- umask(u);
- errno = e;
-
- if (r < 0 && errno != EEXIST) {
- log_error("Failed to create device node %s: %m", i->path);
- return -errno;
- }
-
- if (stat(i->path, &st) < 0) {
- log_error("stat(%s) failed: %m", i->path);
- return -errno;
- }
-
- if ((st.st_mode & S_IFMT) != file_type) {
- log_error("%s is not a device node.", i->path);
- return -EEXIST;
- }
-
- r = item_set_perms(i, i->path);
- if (r < 0)
- return r;
-
- break;
- }
-
- case RELABEL_PATH:
-
- r = glob_item(i, item_set_perms);
- if (r < 0)
- return 0;
- break;
-
- case RECURSIVE_RELABEL_PATH:
-
- r = glob_item(i, recursive_relabel);
- if (r < 0)
- return r;
- }
-
- log_debug("%s created successfully.", i->path);
-
- return 0;
-}
-
-static int remove_item_instance(Item *i, const char *instance) {
- int r;
-
- assert(i);
-
- switch (i->type) {
-
- case CREATE_FILE:
- case TRUNCATE_FILE:
- case CREATE_DIRECTORY:
- case CREATE_FIFO:
- case CREATE_SYMLINK:
- case CREATE_BLOCK_DEVICE:
- case CREATE_CHAR_DEVICE:
- case IGNORE_PATH:
- case RELABEL_PATH:
- case RECURSIVE_RELABEL_PATH:
- case WRITE_FILE:
- break;
-
- case REMOVE_PATH:
- if (remove(instance) < 0 && errno != ENOENT) {
- log_error("remove(%s): %m", instance);
- return -errno;
- }
-
- break;
-
- case TRUNCATE_DIRECTORY:
- case RECURSIVE_REMOVE_PATH:
- /* FIXME: we probably should use dir_cleanup() here
- * instead of rm_rf() so that 'x' is honoured. */
- r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
- if (r < 0 && r != -ENOENT) {
- log_error("rm_rf(%s): %s", instance, strerror(-r));
- return r;
- }
-
- break;
- }
-
- return 0;
-}
-
-static int remove_item(Item *i) {
- int r = 0;
-
- assert(i);
-
- switch (i->type) {
-
- case CREATE_FILE:
- case TRUNCATE_FILE:
- case CREATE_DIRECTORY:
- case CREATE_FIFO:
- case CREATE_SYMLINK:
- case CREATE_CHAR_DEVICE:
- case CREATE_BLOCK_DEVICE:
- case IGNORE_PATH:
- case RELABEL_PATH:
- case RECURSIVE_RELABEL_PATH:
- case WRITE_FILE:
- break;
-
- case REMOVE_PATH:
- case TRUNCATE_DIRECTORY:
- case RECURSIVE_REMOVE_PATH:
- r = glob_item(i, remove_item_instance);
- break;
- }
-
- return r;
-}
-
-static int process_item(Item *i) {
- int r, q, p;
-
- assert(i);
-
- r = arg_create ? create_item(i) : 0;
- q = arg_remove ? remove_item(i) : 0;
- p = arg_clean ? clean_item(i) : 0;
-
- if (r < 0)
- return r;
-
- if (q < 0)
- return q;
-
- return p;
-}
-
-static void item_free(Item *i) {
- assert(i);
-
- free(i->path);
- free(i->argument);
- free(i);
-}
-
-static bool item_equal(Item *a, Item *b) {
- assert(a);
- assert(b);
-
- if (!streq_ptr(a->path, b->path))
- return false;
-
- if (a->type != b->type)
- return false;
-
- if (a->uid_set != b->uid_set ||
- (a->uid_set && a->uid != b->uid))
- return false;
-
- if (a->gid_set != b->gid_set ||
- (a->gid_set && a->gid != b->gid))
- return false;
-
- if (a->mode_set != b->mode_set ||
- (a->mode_set && a->mode != b->mode))
- return false;
-
- if (a->age_set != b->age_set ||
- (a->age_set && a->age != b->age))
- return false;
-
- if ((a->type == CREATE_FILE ||
- a->type == TRUNCATE_FILE ||
- a->type == WRITE_FILE ||
- a->type == CREATE_SYMLINK) &&
- !streq_ptr(a->argument, b->argument))
- return false;
-
- if ((a->type == CREATE_CHAR_DEVICE ||
- a->type == CREATE_BLOCK_DEVICE) &&
- a->major_minor != b->major_minor)
- return false;
-
- return true;
-}
-
-static int parse_line(const char *fname, unsigned line, const char *buffer) {
- Item *i, *existing;
- char *mode = NULL, *user = NULL, *group = NULL, *age = NULL;
- char type;
- Hashmap *h;
- int r, n = -1;
-
- assert(fname);
- assert(line >= 1);
- assert(buffer);
-
- i = new0(Item, 1);
- if (!i)
- return log_oom();
-
- if (sscanf(buffer,
- "%c "
- "%ms "
- "%ms "
- "%ms "
- "%ms "
- "%ms "
- "%n",
- &type,
- &i->path,
- &mode,
- &user,
- &group,
- &age,
- &n) < 2) {
- log_error("[%s:%u] Syntax error.", fname, line);
- r = -EIO;
- goto finish;
- }
-
- if (n >= 0) {
- n += strspn(buffer+n, WHITESPACE);
- if (buffer[n] != 0 && (buffer[n] != '-' || buffer[n+1] != 0)) {
- i->argument = unquote(buffer+n, "\"");
- if (!i->argument)
- return log_oom();
- }
- }
-
- switch(type) {
-
- case CREATE_FILE:
- case TRUNCATE_FILE:
- case CREATE_DIRECTORY:
- case TRUNCATE_DIRECTORY:
- case CREATE_FIFO:
- case IGNORE_PATH:
- case REMOVE_PATH:
- case RECURSIVE_REMOVE_PATH:
- case RELABEL_PATH:
- case RECURSIVE_RELABEL_PATH:
- break;
-
- case CREATE_SYMLINK:
- if (!i->argument) {
- log_error("[%s:%u] Symlink file requires argument.", fname, line);
- r = -EBADMSG;
- goto finish;
- }
- break;
-
- case WRITE_FILE:
- if (!i->argument) {
- log_error("[%s:%u] Write file requires argument.", fname, line);
- r = -EBADMSG;
- goto finish;
- }
- break;
-
- case CREATE_CHAR_DEVICE:
- case CREATE_BLOCK_DEVICE: {
- unsigned major, minor;
-
- if (!i->argument) {
- log_error("[%s:%u] Device file requires argument.", fname, line);
- r = -EBADMSG;
- goto finish;
- }
-
- if (sscanf(i->argument, "%u:%u", &major, &minor) != 2) {
- log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i->argument);
- r = -EBADMSG;
- goto finish;
- }
-
- i->major_minor = makedev(major, minor);
- break;
- }
-
- default:
- log_error("[%s:%u] Unknown file type '%c'.", fname, line, type);
- r = -EBADMSG;
- goto finish;
- }
-
- i->type = type;
-
- if (!path_is_absolute(i->path)) {
- log_error("[%s:%u] Path '%s' not absolute.", fname, line, i->path);
- r = -EBADMSG;
- goto finish;
- }
-
- path_kill_slashes(i->path);
-
- if (arg_prefix && !path_startswith(i->path, arg_prefix)) {
- r = 0;
- goto finish;
- }
-
- if (user && !streq(user, "-")) {
- const char *u = user;
-
- r = get_user_creds(&u, &i->uid, NULL, NULL, NULL);
- if (r < 0) {
- log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
- goto finish;
- }
-
- i->uid_set = true;
- }
-
- if (group && !streq(group, "-")) {
- const char *g = group;
-
- r = get_group_creds(&g, &i->gid);
- if (r < 0) {
- log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
- goto finish;
- }
-
- i->gid_set = true;
- }
-
- if (mode && !streq(mode, "-")) {
- unsigned m;
-
- if (sscanf(mode, "%o", &m) != 1) {
- log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
- r = -ENOENT;
- goto finish;
- }
-
- i->mode = m;
- i->mode_set = true;
- } else
- i->mode =
- i->type == CREATE_DIRECTORY ||
- i->type == TRUNCATE_DIRECTORY ? 0755 : 0644;
-
- if (age && !streq(age, "-")) {
- const char *a = age;
-
- if (*a == '~') {
- i->keep_first_level = true;
- a++;
- }
-
- if (parse_usec(a, &i->age) < 0) {
- log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
- r = -EBADMSG;
- goto finish;
- }
-
- i->age_set = true;
- }
-
- h = needs_glob(i->type) ? globs : items;
-
- existing = hashmap_get(h, i->path);
- if (existing) {
-
- /* Two identical items are fine */
- if (!item_equal(existing, i))
- log_warning("Two or more conflicting lines for %s configured, ignoring.", i->path);
-
- r = 0;
- goto finish;
- }
-
- r = hashmap_put(h, i->path, i);
- if (r < 0) {
- log_error("Failed to insert item %s: %s", i->path, strerror(-r));
- goto finish;
- }
-
- i = NULL;
- r = 0;
-
-finish:
- free(user);
- free(group);
- free(mode);
- free(age);
-
- if (i)
- item_free(i);
-
- return r;
-}
-
-static int help(void) {
-
- printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
- "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
- " -h --help Show this help\n"
- " --create Create marked files/directories\n"
- " --clean Clean up marked directories\n"
- " --remove Remove marked files/directories\n"
- " --prefix=PATH Only apply rules that apply to paths with the specified prefix\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_CREATE,
- ARG_CLEAN,
- ARG_REMOVE,
- ARG_PREFIX
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "create", no_argument, NULL, ARG_CREATE },
- { "clean", no_argument, NULL, ARG_CLEAN },
- { "remove", no_argument, NULL, ARG_REMOVE },
- { "prefix", required_argument, NULL, ARG_PREFIX },
- { NULL, 0, NULL, 0 }
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_CREATE:
- arg_create = true;
- break;
-
- case ARG_CLEAN:
- arg_clean = true;
- break;
-
- case ARG_REMOVE:
- arg_remove = true;
- break;
-
- case ARG_PREFIX:
- arg_prefix = optarg;
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- log_error("Unknown option code %c", c);
- return -EINVAL;
- }
- }
-
- if (!arg_clean && !arg_create && !arg_remove) {
- log_error("You need to specify at least one of --clean, --create or --remove.");
- return -EINVAL;
- }
-
- return 1;
-}
-
-static int read_config_file(const char *fn, bool ignore_enoent) {
- FILE *f;
- unsigned v = 0;
- int r = 0;
-
- assert(fn);
-
- f = fopen(fn, "re");
- if (!f) {
-
- if (ignore_enoent && errno == ENOENT)
- return 0;
-
- log_error("Failed to open %s: %m", fn);
- return -errno;
- }
-
- log_debug("apply: %s\n", fn);
- for (;;) {
- char line[LINE_MAX], *l;
- int k;
-
- if (!(fgets(line, sizeof(line), f)))
- break;
-
- v++;
-
- l = strstrip(line);
- if (*l == '#' || *l == 0)
- continue;
-
- if ((k = parse_line(fn, v, l)) < 0)
- if (r == 0)
- r = k;
- }
-
- if (ferror(f)) {
- log_error("Failed to read from file %s: %m", fn);
- if (r == 0)
- r = -EIO;
- }
-
- fclose(f);
-
- return r;
-}
-
-static char *resolve_fragment(const char *fragment, const char **search_paths) {
- const char **p;
- char *resolved_path;
-
- if (is_path(fragment))
- return strdup(fragment);
-
- STRV_FOREACH(p, search_paths) {
- resolved_path = strjoin(*p, "/", fragment, NULL);
- if (resolved_path == NULL) {
- log_oom();
- return NULL;
- }
-
- if (access(resolved_path, F_OK) == 0)
- return resolved_path;
-
- free(resolved_path);
- }
-
- errno = ENOENT;
- return NULL;
-}
-
-int main(int argc, char *argv[]) {
- int r;
- Item *i;
- Iterator iterator;
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- label_init(NULL);
-
- items = hashmap_new(string_hash_func, string_compare_func);
- globs = hashmap_new(string_hash_func, string_compare_func);
-
- if (!items || !globs) {
- log_oom();
- r = EXIT_FAILURE;
- goto finish;
- }
-
- r = EXIT_SUCCESS;
-
- if (optind < argc) {
- int j;
-
- for (j = optind; j < argc; j++) {
- char *fragment;
-
- fragment = resolve_fragment(argv[j], (const char **)conf_file_dirs);
- if (!fragment) {
- log_error("Failed to find a %s file: %m", argv[j]);
- r = EXIT_FAILURE;
- goto finish;
- }
- if (read_config_file(fragment, false) < 0)
- r = EXIT_FAILURE;
- free(fragment);
- }
-
- } else {
- char **files, **f;
-
- r = conf_files_list_strv(&files, ".conf", (const char **)conf_file_dirs);
- if (r < 0) {
- log_error("Failed to enumerate tmpfiles.d files: %s", strerror(-r));
- r = EXIT_FAILURE;
- goto finish;
- }
-
- STRV_FOREACH(f, files) {
- if (read_config_file(*f, true) < 0)
- r = EXIT_FAILURE;
- }
-
- strv_free(files);
- }
-
- HASHMAP_FOREACH(i, globs, iterator)
- process_item(i);
-
- HASHMAP_FOREACH(i, items, iterator)
- process_item(i);
-
-finish:
- while ((i = hashmap_steal_first(items)))
- item_free(i);
-
- while ((i = hashmap_steal_first(globs)))
- item_free(i);
-
- hashmap_free(items);
- hashmap_free(globs);
-
- set_free_free(unix_sockets);
-
- label_finish();
-
- return r;
-}
diff --git a/src/tty-ask-password-agent/Makefile b/src/tty-ask-password-agent/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/tty-ask-password-agent/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c
deleted file mode 100644
index 052c10e7d5..0000000000
--- a/src/tty-ask-password-agent/tty-ask-password-agent.c
+++ /dev/null
@@ -1,764 +0,0 @@
-/*-*- 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 <errno.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <stddef.h>
-#include <sys/poll.h>
-#include <sys/inotify.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <sys/signalfd.h>
-#include <fcntl.h>
-
-#include "util.h"
-#include "mkdir.h"
-#include "path-util.h"
-#include "conf-parser.h"
-#include "utmp-wtmp.h"
-#include "socket-util.h"
-#include "ask-password-api.h"
-#include "strv.h"
-#include "build.h"
-
-static enum {
- ACTION_LIST,
- ACTION_QUERY,
- ACTION_WATCH,
- ACTION_WALL
-} arg_action = ACTION_QUERY;
-
-static bool arg_plymouth = false;
-static bool arg_console = false;
-
-static int ask_password_plymouth(
- const char *message,
- usec_t until,
- const char *flag_file,
- bool accept_cached,
- char ***_passphrases) {
-
- int fd = -1, notify = -1;
- union sockaddr_union sa;
- char *packet = NULL;
- ssize_t k;
- int r, n;
- struct pollfd pollfd[2];
- char buffer[LINE_MAX];
- size_t p = 0;
- enum {
- POLL_SOCKET,
- POLL_INOTIFY
- };
-
- assert(_passphrases);
-
- if (flag_file) {
- if ((notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK)) < 0) {
- r = -errno;
- goto finish;
- }
-
- if (inotify_add_watch(notify, flag_file, IN_ATTRIB /* for the link count */) < 0) {
- r = -errno;
- goto finish;
- }
- }
-
- if ((fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0)) < 0) {
- r = -errno;
- goto finish;
- }
-
- zero(sa);
- sa.sa.sa_family = AF_UNIX;
- strncpy(sa.un.sun_path+1, "/org/freedesktop/plymouthd", sizeof(sa.un.sun_path)-1);
- if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) {
- log_error("Failed to connect to Plymouth: %m");
- r = -errno;
- goto finish;
- }
-
- if (accept_cached) {
- packet = strdup("c");
- n = 1;
- } else
- asprintf(&packet, "*\002%c%s%n", (int) (strlen(message) + 1), message, &n);
-
- if (!packet) {
- r = -ENOMEM;
- goto finish;
- }
-
- if ((k = loop_write(fd, packet, n+1, true)) != n+1) {
- r = k < 0 ? (int) k : -EIO;
- goto finish;
- }
-
- zero(pollfd);
- pollfd[POLL_SOCKET].fd = fd;
- pollfd[POLL_SOCKET].events = POLLIN;
- pollfd[POLL_INOTIFY].fd = notify;
- pollfd[POLL_INOTIFY].events = POLLIN;
-
- for (;;) {
- int sleep_for = -1, j;
-
- if (until > 0) {
- usec_t y;
-
- y = now(CLOCK_MONOTONIC);
-
- if (y > until) {
- r = -ETIME;
- goto finish;
- }
-
- sleep_for = (int) ((until - y) / USEC_PER_MSEC);
- }
-
- if (flag_file)
- if (access(flag_file, F_OK) < 0) {
- r = -errno;
- goto finish;
- }
-
- if ((j = poll(pollfd, notify > 0 ? 2 : 1, sleep_for)) < 0) {
-
- if (errno == EINTR)
- continue;
-
- r = -errno;
- goto finish;
- } else if (j == 0) {
- r = -ETIME;
- goto finish;
- }
-
- if (notify > 0 && pollfd[POLL_INOTIFY].revents != 0)
- flush_fd(notify);
-
- if (pollfd[POLL_SOCKET].revents == 0)
- continue;
-
- if ((k = read(fd, buffer + p, sizeof(buffer) - p)) <= 0) {
- r = k < 0 ? -errno : -EIO;
- goto finish;
- }
-
- p += k;
-
- if (p < 1)
- continue;
-
- if (buffer[0] == 5) {
-
- if (accept_cached) {
- /* Hmm, first try with cached
- * passwords failed, so let's retry
- * with a normal password request */
- free(packet);
- packet = NULL;
-
- if (asprintf(&packet, "*\002%c%s%n", (int) (strlen(message) + 1), message, &n) < 0) {
- r = -ENOMEM;
- goto finish;
- }
-
- if ((k = loop_write(fd, packet, n+1, true)) != n+1) {
- r = k < 0 ? (int) k : -EIO;
- goto finish;
- }
-
- accept_cached = false;
- p = 0;
- continue;
- }
-
- /* No password, because UI not shown */
- r = -ENOENT;
- goto finish;
-
- } else if (buffer[0] == 2 || buffer[0] == 9) {
- uint32_t size;
- char **l;
-
- /* One ore more answers */
- if (p < 5)
- continue;
-
- memcpy(&size, buffer+1, sizeof(size));
- size = le32toh(size);
- if (size+5 > sizeof(buffer)) {
- r = -EIO;
- goto finish;
- }
-
- if (p-5 < size)
- continue;
-
- if (!(l = strv_parse_nulstr(buffer + 5, size))) {
- r = -ENOMEM;
- goto finish;
- }
-
- *_passphrases = l;
- break;
-
- } else {
- /* Unknown packet */
- r = -EIO;
- goto finish;
- }
- }
-
- r = 0;
-
-finish:
- if (notify >= 0)
- close_nointr_nofail(notify);
-
- if (fd >= 0)
- close_nointr_nofail(fd);
-
- free(packet);
-
- return r;
-}
-
-static int parse_password(const char *filename, char **wall) {
- char *socket_name = NULL, *message = NULL, *packet = NULL;
- uint64_t not_after = 0;
- unsigned pid = 0;
- int socket_fd = -1;
- bool accept_cached = false;
-
- const ConfigTableItem items[] = {
- { "Ask", "Socket", config_parse_string, 0, &socket_name },
- { "Ask", "NotAfter", config_parse_uint64, 0, &not_after },
- { "Ask", "Message", config_parse_string, 0, &message },
- { "Ask", "PID", config_parse_unsigned, 0, &pid },
- { "Ask", "AcceptCached", config_parse_bool, 0, &accept_cached },
- { NULL, NULL, NULL, 0, NULL }
- };
-
- FILE *f;
- int r;
-
- assert(filename);
-
- f = fopen(filename, "re");
- if (!f) {
- if (errno == ENOENT)
- return 0;
-
- log_error("open(%s): %m", filename);
- return -errno;
- }
-
- r = config_parse(filename, f, NULL, config_item_table_lookup, (void*) items, true, NULL);
- if (r < 0) {
- log_error("Failed to parse password file %s: %s", filename, strerror(-r));
- goto finish;
- }
-
- if (!socket_name) {
- log_error("Invalid password file %s", filename);
- r = -EBADMSG;
- goto finish;
- }
-
- if (not_after > 0) {
- if (now(CLOCK_MONOTONIC) > not_after) {
- r = 0;
- goto finish;
- }
- }
-
- if (pid > 0 &&
- kill(pid, 0) < 0 &&
- errno == ESRCH) {
- r = 0;
- goto finish;
- }
-
- if (arg_action == ACTION_LIST)
- printf("'%s' (PID %u)\n", message, pid);
- else if (arg_action == ACTION_WALL) {
- char *_wall;
-
- if (asprintf(&_wall,
- "%s%sPassword entry required for \'%s\' (PID %u).\r\n"
- "Please enter password with the systemd-tty-ask-password-agent tool!",
- *wall ? *wall : "",
- *wall ? "\r\n\r\n" : "",
- message,
- pid) < 0) {
- r = log_oom();
- goto finish;
- }
-
- free(*wall);
- *wall = _wall;
- } else {
- union {
- struct sockaddr sa;
- struct sockaddr_un un;
- } sa;
- size_t packet_length = 0;
-
- assert(arg_action == ACTION_QUERY ||
- arg_action == ACTION_WATCH);
-
- if (access(socket_name, W_OK) < 0) {
-
- if (arg_action == ACTION_QUERY)
- log_info("Not querying '%s' (PID %u), lacking privileges.", message, pid);
-
- r = 0;
- goto finish;
- }
-
- if (arg_plymouth) {
- char **passwords = NULL;
-
- if ((r = ask_password_plymouth(message, not_after, filename, accept_cached, &passwords)) >= 0) {
- char **p;
-
- packet_length = 1;
- STRV_FOREACH(p, passwords)
- packet_length += strlen(*p) + 1;
-
- if (!(packet = new(char, packet_length)))
- r = -ENOMEM;
- else {
- char *d;
-
- packet[0] = '+';
- d = packet+1;
-
- STRV_FOREACH(p, passwords)
- d = stpcpy(d, *p) + 1;
- }
- }
-
- } else {
- int tty_fd = -1;
- char *password;
-
- if (arg_console)
- if ((tty_fd = acquire_terminal("/dev/console", false, false, false, (usec_t) -1)) < 0) {
- r = tty_fd;
- goto finish;
- }
-
- r = ask_password_tty(message, not_after, filename, &password);
-
- if (arg_console) {
- close_nointr_nofail(tty_fd);
- release_terminal();
- }
-
- if (r >= 0) {
- packet_length = 1+strlen(password)+1;
- if (!(packet = new(char, packet_length)))
- r = -ENOMEM;
- else {
- packet[0] = '+';
- strcpy(packet+1, password);
- }
-
- free(password);
- }
- }
-
- if (r == -ETIME || r == -ENOENT) {
- /* If the query went away, that's OK */
- r = 0;
- goto finish;
- }
-
- if (r < 0) {
- log_error("Failed to query password: %s", strerror(-r));
- goto finish;
- }
-
- if ((socket_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) {
- log_error("socket(): %m");
- r = -errno;
- goto finish;
- }
-
- zero(sa);
- sa.un.sun_family = AF_UNIX;
- strncpy(sa.un.sun_path, socket_name, sizeof(sa.un.sun_path));
-
- if (sendto(socket_fd, packet, packet_length, MSG_NOSIGNAL, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(socket_name)) < 0) {
- log_error("Failed to send: %m");
- r = -errno;
- goto finish;
- }
- }
-
-finish:
- fclose(f);
-
- if (socket_fd >= 0)
- close_nointr_nofail(socket_fd);
-
- free(packet);
- free(socket_name);
- free(message);
-
- return r;
-}
-
-static int wall_tty_block(void) {
- char *p;
- int fd, r;
- dev_t devnr;
-
- r = get_ctty_devnr(0, &devnr);
- if (r < 0)
- return -r;
-
- if (asprintf(&p, "/run/systemd/ask-password-block/%u:%u", major(devnr), minor(devnr)) < 0)
- return -ENOMEM;
-
- mkdir_parents_label(p, 0700);
- mkfifo(p, 0600);
-
- fd = open(p, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
- free(p);
-
- if (fd < 0)
- return -errno;
-
- return fd;
-}
-
-static bool wall_tty_match(const char *path) {
- int fd, k;
- char *p;
- struct stat st;
-
- if (path_is_absolute(path))
- k = lstat(path, &st);
- else {
- if (asprintf(&p, "/dev/%s", path) < 0)
- return true;
-
- k = lstat(p, &st);
- free(p);
- }
-
- if (k < 0)
- return true;
-
- if (!S_ISCHR(st.st_mode))
- return true;
-
- /* We use named pipes to ensure that wall messages suggesting
- * password entry are not printed over password prompts
- * already shown. We use the fact here that opening a pipe in
- * non-blocking mode for write-only will succeed only if
- * there's some writer behind it. Using pipes has the
- * advantage that the block will automatically go away if the
- * process dies. */
-
- if (asprintf(&p, "/run/systemd/ask-password-block/%u:%u", major(st.st_rdev), minor(st.st_rdev)) < 0)
- return true;
-
- fd = open(p, O_WRONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
- free(p);
-
- if (fd < 0)
- return true;
-
- /* What, we managed to open the pipe? Then this tty is filtered. */
- close_nointr_nofail(fd);
- return false;
-}
-
-static int show_passwords(void) {
- DIR *d;
- struct dirent *de;
- int r = 0;
-
- if (!(d = opendir("/run/systemd/ask-password"))) {
- if (errno == ENOENT)
- return 0;
-
- log_error("opendir(): %m");
- return -errno;
- }
-
- while ((de = readdir(d))) {
- char *p;
- int q;
- char *wall;
-
- /* We only support /dev on tmpfs, hence we can rely on
- * d_type to be reliable */
-
- if (de->d_type != DT_REG)
- continue;
-
- if (ignore_file(de->d_name))
- continue;
-
- if (!startswith(de->d_name, "ask."))
- continue;
-
- if (!(p = strappend("/run/systemd/ask-password/", de->d_name))) {
- r = log_oom();
- goto finish;
- }
-
- wall = NULL;
- if ((q = parse_password(p, &wall)) < 0)
- r = q;
-
- free(p);
-
- if (wall) {
- utmp_wall(wall, wall_tty_match);
- free(wall);
- }
- }
-
-finish:
- if (d)
- closedir(d);
-
- return r;
-}
-
-static int watch_passwords(void) {
- enum {
- FD_INOTIFY,
- FD_SIGNAL,
- _FD_MAX
- };
-
- int notify = -1, signal_fd = -1, tty_block_fd = -1;
- struct pollfd pollfd[_FD_MAX];
- sigset_t mask;
- int r;
-
- tty_block_fd = wall_tty_block();
-
- mkdir_p_label("/run/systemd/ask-password", 0755);
-
- if ((notify = inotify_init1(IN_CLOEXEC)) < 0) {
- r = -errno;
- goto finish;
- }
-
- if (inotify_add_watch(notify, "/run/systemd/ask-password", IN_CLOSE_WRITE|IN_MOVED_TO) < 0) {
- r = -errno;
- goto finish;
- }
-
- assert_se(sigemptyset(&mask) == 0);
- sigset_add_many(&mask, SIGINT, SIGTERM, -1);
- assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
-
- if ((signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC)) < 0) {
- log_error("signalfd(): %m");
- r = -errno;
- goto finish;
- }
-
- zero(pollfd);
- pollfd[FD_INOTIFY].fd = notify;
- pollfd[FD_INOTIFY].events = POLLIN;
- pollfd[FD_SIGNAL].fd = signal_fd;
- pollfd[FD_SIGNAL].events = POLLIN;
-
- for (;;) {
- if ((r = show_passwords()) < 0)
- log_error("Failed to show password: %s", strerror(-r));
-
- if (poll(pollfd, _FD_MAX, -1) < 0) {
-
- if (errno == EINTR)
- continue;
-
- r = -errno;
- goto finish;
- }
-
- if (pollfd[FD_INOTIFY].revents != 0)
- flush_fd(notify);
-
- if (pollfd[FD_SIGNAL].revents != 0)
- break;
- }
-
- r = 0;
-
-finish:
- if (notify >= 0)
- close_nointr_nofail(notify);
-
- if (signal_fd >= 0)
- close_nointr_nofail(signal_fd);
-
- if (tty_block_fd >= 0)
- close_nointr_nofail(tty_block_fd);
-
- return r;
-}
-
-static int help(void) {
-
- printf("%s [OPTIONS...]\n\n"
- "Process system password requests.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --list Show pending password requests\n"
- " --query Process pending password requests\n"
- " --watch Continuously process password requests\n"
- " --wall Continuously forward password requests to wall\n"
- " --plymouth Ask question with Plymouth instead of on TTY\n"
- " --console Ask question on /dev/console instead of current TTY\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_LIST = 0x100,
- ARG_QUERY,
- ARG_WATCH,
- ARG_WALL,
- ARG_PLYMOUTH,
- ARG_CONSOLE,
- ARG_VERSION
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "list", no_argument, NULL, ARG_LIST },
- { "query", no_argument, NULL, ARG_QUERY },
- { "watch", no_argument, NULL, ARG_WATCH },
- { "wall", no_argument, NULL, ARG_WALL },
- { "plymouth", no_argument, NULL, ARG_PLYMOUTH },
- { "console", no_argument, NULL, ARG_CONSOLE },
- { NULL, 0, NULL, 0 }
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(DISTRIBUTION);
- puts(SYSTEMD_FEATURES);
- return 0;
-
- case ARG_LIST:
- arg_action = ACTION_LIST;
- break;
-
- case ARG_QUERY:
- arg_action = ACTION_QUERY;
- break;
-
- case ARG_WATCH:
- arg_action = ACTION_WATCH;
- break;
-
- case ARG_WALL:
- arg_action = ACTION_WALL;
- break;
-
- case ARG_PLYMOUTH:
- arg_plymouth = true;
- break;
-
- case ARG_CONSOLE:
- arg_console = true;
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- log_error("Unknown option code %c", c);
- return -EINVAL;
- }
- }
-
- if (optind != argc) {
- help();
- return -EINVAL;
- }
-
- return 1;
-}
-
-int main(int argc, char *argv[]) {
- int r;
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- if ((r = parse_argv(argc, argv)) <= 0)
- goto finish;
-
- if (arg_console) {
- setsid();
- release_terminal();
- }
-
- if (arg_action == ACTION_WATCH ||
- arg_action == ACTION_WALL)
- r = watch_passwords();
- else
- r = show_passwords();
-
- if (r < 0)
- log_error("Error: %s", strerror(-r));
-
-finish:
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/udev/.gitignore b/src/udev/.gitignore
deleted file mode 100644
index 3e375a7726..0000000000
--- a/src/udev/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/udev.pc
diff --git a/src/udev/.vimrc b/src/udev/.vimrc
deleted file mode 100644
index 366fbdca4b..0000000000
--- a/src/udev/.vimrc
+++ /dev/null
@@ -1,4 +0,0 @@
-" 'set exrc' in ~/.vimrc will read .vimrc from the current directory
-set tabstop=8
-set shiftwidth=8
-set expandtab
diff --git a/src/udev/Makefile b/src/udev/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/udev/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/udev/keymap/.gitignore b/src/udev/keymap/.gitignore
deleted file mode 100644
index 4567584f4e..0000000000
--- a/src/udev/keymap/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-keyboard-force-release.sh
-keys-from-name.gperf
-keys-from-name.h
-keys-to-name.h
-keys.txt
diff --git a/src/udev/scsi_id/.gitignore b/src/udev/scsi_id/.gitignore
deleted file mode 100644
index 6aebddd809..0000000000
--- a/src/udev/scsi_id/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-scsi_id_version.h
diff --git a/src/update-utmp/Makefile b/src/update-utmp/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/update-utmp/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/update-utmp/update-utmp.c b/src/update-utmp/update-utmp.c
deleted file mode 100644
index a311280c27..0000000000
--- a/src/update-utmp/update-utmp.c
+++ /dev/null
@@ -1,386 +0,0 @@
-/*-*- 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 <assert.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <dbus/dbus.h>
-
-#ifdef HAVE_AUDIT
-#include <libaudit.h>
-#endif
-
-#include "log.h"
-#include "macro.h"
-#include "util.h"
-#include "special.h"
-#include "utmp-wtmp.h"
-#include "dbus-common.h"
-
-typedef struct Context {
- DBusConnection *bus;
-#ifdef HAVE_AUDIT
- int audit_fd;
-#endif
-} Context;
-
-static usec_t get_startup_time(Context *c) {
- const char
- *interface = "org.freedesktop.systemd1.Manager",
- *property = "UserspaceTimestamp";
-
- usec_t t = 0;
- DBusMessage *reply = NULL;
- DBusMessageIter iter, sub;
-
- assert(c);
-
- if (bus_method_call_with_reply (
- c->bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.DBus.Properties",
- "Get",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &interface,
- DBUS_TYPE_STRING, &property,
- DBUS_TYPE_INVALID))
- goto finish;
-
- if (!dbus_message_iter_init(reply, &iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
- log_error("Failed to parse reply.");
- goto finish;
- }
-
- dbus_message_iter_recurse(&iter, &sub);
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_UINT64) {
- log_error("Failed to parse reply.");
- goto finish;
- }
-
- dbus_message_iter_get_basic(&sub, &t);
-
-finish:
- if (reply)
- dbus_message_unref(reply);
- return t;
-}
-
-static int get_current_runlevel(Context *c) {
- static const struct {
- const int runlevel;
- const char *special;
- } table[] = {
- /* The first target of this list that is active or has
- * a job scheduled wins. We prefer runlevels 5 and 3
- * here over the others, since these are the main
- * runlevels used on Fedora. It might make sense to
- * change the order on some distributions. */
- { '5', SPECIAL_RUNLEVEL5_TARGET },
- { '3', SPECIAL_RUNLEVEL3_TARGET },
- { '4', SPECIAL_RUNLEVEL4_TARGET },
- { '2', SPECIAL_RUNLEVEL2_TARGET },
- { 'S', SPECIAL_RESCUE_TARGET },
- };
- const char
- *interface = "org.freedesktop.systemd1.Unit",
- *property = "ActiveState";
-
- DBusMessage *reply = NULL;
- int r = 0;
- unsigned i;
- DBusError error;
-
- assert(c);
-
- dbus_error_init(&error);
-
- for (i = 0; i < ELEMENTSOF(table); i++) {
- const char *path = NULL, *state;
- DBusMessageIter iter, sub;
-
- r = bus_method_call_with_reply (
- c->bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "GetUnit",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &table[i].special,
- DBUS_TYPE_INVALID);
- if (r == -ENOMEM)
- goto finish;
- if (r)
- continue;
-
- if (!dbus_message_get_args(reply, &error,
- DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID)) {
- log_error("Failed to parse reply: %s", bus_error_message(&error));
- r = -EIO;
- goto finish;
- }
-
- dbus_message_unref(reply);
- r = bus_method_call_with_reply (
- c->bus,
- "org.freedesktop.systemd1",
- path,
- "org.freedesktop.DBus.Properties",
- "Get",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &interface,
- DBUS_TYPE_STRING, &property,
- DBUS_TYPE_INVALID);
- if (r)
- goto finish;
-
- if (!dbus_message_iter_init(reply, &iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_recurse(&iter, &sub);
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
- log_error("Failed to parse reply.");
- r = -EIO;
- goto finish;
- }
-
- dbus_message_iter_get_basic(&sub, &state);
-
- if (streq(state, "active") || streq(state, "reloading"))
- r = table[i].runlevel;
-
- dbus_message_unref(reply);
- reply = NULL;
-
- if (r)
- break;
- }
-
-finish:
- if (reply)
- dbus_message_unref(reply);
-
- dbus_error_free(&error);
-
- return r;
-}
-
-static int on_reboot(Context *c) {
- int r = 0, q;
- usec_t t;
-
- assert(c);
-
- /* We finished start-up, so let's write the utmp
- * record and send the audit msg */
-
-#ifdef HAVE_AUDIT
- if (c->audit_fd >= 0)
- if (audit_log_user_message(c->audit_fd, AUDIT_SYSTEM_BOOT, "init", NULL, NULL, NULL, 1) < 0 &&
- errno != EPERM) {
- log_error("Failed to send audit message: %m");
- r = -errno;
- }
-#endif
-
- /* If this call fails it will return 0, which
- * utmp_put_reboot() will then fix to the current time */
- t = get_startup_time(c);
-
- if ((q = utmp_put_reboot(t)) < 0) {
- log_error("Failed to write utmp record: %s", strerror(-q));
- r = q;
- }
-
- return r;
-}
-
-static int on_shutdown(Context *c) {
- int r = 0, q;
-
- assert(c);
-
- /* We started shut-down, so let's write the utmp
- * record and send the audit msg */
-
-#ifdef HAVE_AUDIT
- if (c->audit_fd >= 0)
- if (audit_log_user_message(c->audit_fd, AUDIT_SYSTEM_SHUTDOWN, "init", NULL, NULL, NULL, 1) < 0 &&
- errno != EPERM) {
- log_error("Failed to send audit message: %m");
- r = -errno;
- }
-#endif
-
- if ((q = utmp_put_shutdown()) < 0) {
- log_error("Failed to write utmp record: %s", strerror(-q));
- r = q;
- }
-
- return r;
-}
-
-static int on_runlevel(Context *c) {
- int r = 0, q, previous, runlevel;
-
- assert(c);
-
- /* We finished changing runlevel, so let's write the
- * utmp record and send the audit msg */
-
- /* First, get last runlevel */
- if ((q = utmp_get_runlevel(&previous, NULL)) < 0) {
-
- if (q != -ESRCH && q != -ENOENT) {
- log_error("Failed to get current runlevel: %s", strerror(-q));
- return q;
- }
-
- /* Hmm, we didn't find any runlevel, that means we
- * have been rebooted */
- r = on_reboot(c);
- previous = 0;
- }
-
- /* Secondly, get new runlevel */
- if ((runlevel = get_current_runlevel(c)) < 0)
- return runlevel;
-
- if (previous == runlevel)
- return 0;
-
-#ifdef HAVE_AUDIT
- if (c->audit_fd >= 0) {
- char *s = NULL;
-
- if (asprintf(&s, "old-level=%c new-level=%c",
- previous > 0 ? previous : 'N',
- runlevel > 0 ? runlevel : 'N') < 0)
- return -ENOMEM;
-
- if (audit_log_user_message(c->audit_fd, AUDIT_SYSTEM_RUNLEVEL, s, NULL, NULL, NULL, 1) < 0 &&
- errno != EPERM) {
- log_error("Failed to send audit message: %m");
- r = -errno;
- }
-
- free(s);
- }
-#endif
-
- if ((q = utmp_put_runlevel(runlevel, previous)) < 0) {
- if (q != -ESRCH && q != -ENOENT) {
- log_error("Failed to write utmp record: %s", strerror(-q));
- r = q;
- }
- }
-
- return r;
-}
-
-int main(int argc, char *argv[]) {
- int r;
- DBusError error;
- Context c;
-
- dbus_error_init(&error);
-
- zero(c);
-#ifdef HAVE_AUDIT
- c.audit_fd = -1;
-#endif
-
- if (getppid() != 1) {
- log_error("This program should be invoked by init only.");
- return EXIT_FAILURE;
- }
-
- if (argc != 2) {
- log_error("This program requires one argument.");
- return EXIT_FAILURE;
- }
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
-#ifdef HAVE_AUDIT
- if ((c.audit_fd = audit_open()) < 0 &&
- /* If the kernel lacks netlink or audit support,
- * don't worry about it. */
- errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT)
- log_error("Failed to connect to audit log: %m");
-#endif
-
- if (bus_connect(DBUS_BUS_SYSTEM, &c.bus, NULL, &error) < 0) {
- log_error("Failed to get D-Bus connection: %s", bus_error_message(&error));
- r = -EIO;
- goto finish;
- }
-
- log_debug("systemd-update-utmp running as pid %lu", (unsigned long) getpid());
-
- if (streq(argv[1], "reboot"))
- r = on_reboot(&c);
- else if (streq(argv[1], "shutdown"))
- r = on_shutdown(&c);
- else if (streq(argv[1], "runlevel"))
- r = on_runlevel(&c);
- else {
- log_error("Unknown command %s", argv[1]);
- r = -EINVAL;
- }
-
- log_debug("systemd-update-utmp stopped as pid %lu", (unsigned long) getpid());
-
-finish:
-#ifdef HAVE_AUDIT
- if (c.audit_fd >= 0)
- audit_close(c.audit_fd);
-#endif
-
- if (c.bus) {
- dbus_connection_flush(c.bus);
- dbus_connection_close(c.bus);
- dbus_connection_unref(c.bus);
- }
-
- dbus_error_free(&error);
- dbus_shutdown();
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/vconsole/Makefile b/src/vconsole/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/vconsole/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c
deleted file mode 100644
index ca208497c3..0000000000
--- a/src/vconsole/vconsole-setup.c
+++ /dev/null
@@ -1,392 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Kay Sievers
-
- 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 <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <stdbool.h>
-#include <stdarg.h>
-#include <limits.h>
-#include <sys/ioctl.h>
-#include <sys/wait.h>
-#include <linux/tiocl.h>
-#include <linux/kd.h>
-
-#include "util.h"
-#include "log.h"
-#include "macro.h"
-#include "virt.h"
-
-static bool is_vconsole(int fd) {
- unsigned char data[1];
-
- data[0] = TIOCL_GETFGCONSOLE;
- return ioctl(fd, TIOCLINUX, data) >= 0;
-}
-
-static int disable_utf8(int fd) {
- int r = 0, k;
-
- if (ioctl(fd, KDSKBMODE, K_XLATE) < 0)
- r = -errno;
-
- if (loop_write(fd, "\033%@", 3, false) < 0)
- r = -errno;
-
- k = write_one_line_file("/sys/module/vt/parameters/default_utf8", "0");
- if (k < 0)
- r = k;
-
- if (r < 0)
- log_warning("Failed to disable UTF-8: %s", strerror(-r));
-
- return r;
-}
-
-static int enable_utf8(int fd) {
- int r = 0, k;
-
- if (ioctl(fd, KDSKBMODE, K_UNICODE) < 0)
- r = -errno;
-
- if (loop_write(fd, "\033%G", 3, false) < 0)
- r = -errno;
-
- k = write_one_line_file("/sys/module/vt/parameters/default_utf8", "1");
- if (k < 0)
- r = k;
-
- if (r < 0)
- log_warning("Failed to enable UTF-8: %s", strerror(-r));
-
- return r;
-}
-
-static int load_keymap(const char *vc, const char *map, const char *map_toggle, bool utf8, pid_t *_pid) {
- const char *args[8];
- int i = 0;
- pid_t pid;
-
- if (isempty(map)) {
- /* An empty map means kernel map */
- *_pid = 0;
- return 0;
- }
-
- args[i++] = KBD_LOADKEYS;
- args[i++] = "-q";
- args[i++] = "-C";
- args[i++] = vc;
- if (utf8)
- args[i++] = "-u";
- args[i++] = map;
- if (map_toggle)
- args[i++] = map_toggle;
- args[i++] = NULL;
-
- pid = fork();
- if (pid < 0) {
- log_error("Failed to fork: %m");
- return -errno;
- } else if (pid == 0) {
- execv(args[0], (char **) args);
- _exit(EXIT_FAILURE);
- }
-
- *_pid = pid;
- return 0;
-}
-
-static int load_font(const char *vc, const char *font, const char *map, const char *unimap, pid_t *_pid) {
- const char *args[9];
- int i = 0;
- pid_t pid;
-
- if (isempty(font)) {
- /* An empty font means kernel font */
- *_pid = 0;
- return 0;
- }
-
- args[i++] = KBD_SETFONT;
- args[i++] = "-C";
- args[i++] = vc;
- args[i++] = font;
- if (map) {
- args[i++] = "-m";
- args[i++] = map;
- }
- if (unimap) {
- args[i++] = "-u";
- args[i++] = unimap;
- }
- args[i++] = NULL;
-
- pid = fork();
- if (pid < 0) {
- log_error("Failed to fork: %m");
- return -errno;
- } else if (pid == 0) {
- execv(args[0], (char **) args);
- _exit(EXIT_FAILURE);
- }
-
- *_pid = pid;
- return 0;
-}
-
-int main(int argc, char **argv) {
- const char *vc;
- char *vc_keymap = NULL;
- char *vc_keymap_toggle = NULL;
- char *vc_font = NULL;
- char *vc_font_map = NULL;
- char *vc_font_unimap = NULL;
-#ifdef TARGET_GENTOO
- char *vc_unicode = NULL;
-#endif
-#if defined(TARGET_MANDRIVA) || defined(TARGET_MAGEIA)
- char *vc_keytable = NULL;
-#endif
- int fd = -1;
- bool utf8;
- int r = EXIT_FAILURE;
- pid_t font_pid = 0, keymap_pid = 0;
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- if (argv[1])
- vc = argv[1];
- else
- vc = "/dev/tty0";
-
- fd = open_terminal(vc, O_RDWR|O_CLOEXEC);
- if (fd < 0) {
- log_error("Failed to open %s: %m", vc);
- goto finish;
- }
-
- if (!is_vconsole(fd)) {
- log_error("Device %s is not a virtual console.", vc);
- goto finish;
- }
-
- utf8 = is_locale_utf8();
-
- r = 0;
-
- if (detect_container(NULL) <= 0) {
- r = parse_env_file("/proc/cmdline", WHITESPACE,
- "vconsole.keymap", &vc_keymap,
- "vconsole.keymap.toggle", &vc_keymap_toggle,
- "vconsole.font", &vc_font,
- "vconsole.font.map", &vc_font_map,
- "vconsole.font.unimap", &vc_font_unimap,
- NULL);
-
- if (r < 0 && r != -ENOENT)
- log_warning("Failed to read /proc/cmdline: %s", strerror(-r));
- }
-
- /* Hmm, nothing set on the kernel cmd line? Then let's
- * try /etc/vconsole.conf */
- if (r <= 0) {
- r = parse_env_file("/etc/vconsole.conf", NEWLINE,
- "KEYMAP", &vc_keymap,
- "KEYMAP_TOGGLE", &vc_keymap_toggle,
- "FONT", &vc_font,
- "FONT_MAP", &vc_font_map,
- "FONT_UNIMAP", &vc_font_unimap,
- NULL);
-
- if (r < 0 && r != -ENOENT)
- log_warning("Failed to read /etc/vconsole.conf: %s", strerror(-r));
- }
-
- if (r <= 0) {
-#if defined(TARGET_SUSE)
- r = parse_env_file("/etc/sysconfig/keyboard", NEWLINE,
- "KEYTABLE", &vc_keymap,
- NULL);
- if (r < 0 && r != -ENOENT)
- log_warning("Failed to read /etc/sysconfig/keyboard: %s", strerror(-r));
-
- r = parse_env_file("/etc/sysconfig/console", NEWLINE,
- "CONSOLE_FONT", &vc_font,
- "CONSOLE_SCREENMAP", &vc_font_map,
- "CONSOLE_UNICODEMAP", &vc_font_unimap,
- NULL);
- if (r < 0 && r != -ENOENT)
- log_warning("Failed to read /etc/sysconfig/console: %s", strerror(-r));
-
-#elif defined(TARGET_ALTLINUX)
- r = parse_env_file("/etc/sysconfig/keyboard", NEWLINE,
- "KEYTABLE", &vc_keymap,
- NULL)
- if (r < 0 && r != -ENOENT)
- log_warning("Failed to read /etc/sysconfig/keyboard: %s", strerror(-r));
-
- r = parse_env_file("/etc/sysconfig/consolefont", NEWLINE,
- "SYSFONT", &vc_font,
- NULL);
- if (r < 0 && r != -ENOENT)
- log_warning("Failed to read /etc/sysconfig/consolefont: %s", strerror(-r));
-
-#elif defined(TARGET_GENTOO)
- r = parse_env_file("/etc/rc.conf", NEWLINE,
- "unicode", &vc_unicode,
- NULL);
- if (r < 0 && r != -ENOENT)
- log_warning("Failed to read /etc/rc.conf: %s", strerror(-r));
-
- if (vc_unicode) {
- int rc_unicode;
-
- rc_unicode = parse_boolean(vc_unicode);
- if (rc_unicode < 0)
- log_warning("Unknown value for /etc/rc.conf unicode=%s", vc_unicode);
- else {
- if (rc_unicode && !utf8)
- log_warning("/etc/rc.conf wants unicode, but current locale is not UTF-8 capable!");
- else if (!rc_unicode && utf8) {
- log_debug("/etc/rc.conf does not want unicode, leave it on in kernel but does not apply to vconsole.");
- utf8 = false;
- }
- }
- }
-
- /* /etc/conf.d/consolefont comments and gentoo
- * documentation mention uppercase, but the actual
- * contents are lowercase. the existing
- * /etc/init.d/consolefont tries both
- */
- r = parse_env_file("/etc/conf.d/consolefont", NEWLINE,
- "CONSOLEFONT", &vc_font,
- "consolefont", &vc_font,
- "consoletranslation", &vc_font_map,
- "CONSOLETRANSLATION", &vc_font_map,
- "unicodemap", &vc_font_unimap,
- "UNICODEMAP", &vc_font_unimap,
- NULL);
- if (r < 0 && r != -ENOENT)
- log_warning("Failed to read /etc/conf.d/consolefont: %s", strerror(-r));
-
- r = parse_env_file("/etc/conf.d/keymaps", NEWLINE,
- "keymap", &vc_keymap,
- "KEYMAP", &vc_keymap,
- NULL);
- if (r < 0 && r != -ENOENT)
- log_warning("Failed to read /etc/conf.d/keymaps: %s", strerror(-r));
-
-#elif defined(TARGET_MANDRIVA) || defined (TARGET_MAGEIA)
-
- r = parse_env_file("/etc/sysconfig/i18n", NEWLINE,
- "SYSFONT", &vc_font,
- "SYSFONTACM", &vc_font_map,
- "UNIMAP", &vc_font_unimap,
- NULL);
- if (r < 0 && r != -ENOENT)
- log_warning("Failed to read /etc/sysconfig/i18n: %s", strerror(-r));
-
- r = parse_env_file("/etc/sysconfig/keyboard", NEWLINE,
- "KEYTABLE", &vc_keytable,
- "KEYMAP", &vc_keymap,
- "UNIKEYTABLE", &vc_keymap,
- "GRP_TOGGLE", &vc_keymap_toggle,
- NULL);
- if (r < 0 && r != -ENOENT)
- log_warning("Failed to read /etc/sysconfig/keyboard: %s", strerror(-r));
-
- if (vc_keytable) {
- free(vc_keymap);
- if (utf8) {
- if (endswith(vc_keytable, ".uni") || strstr(vc_keytable, ".uni."))
- vc_keymap = strdup(vc_keytable);
- else {
- char *s;
- s = strstr(vc_keytable, ".map");
- if (s)
- vc_keytable[s-vc_keytable+1] = '\0';
- vc_keymap = strappend(vc_keytable, ".uni");
- }
- } else
- vc_keymap = strdup(vc_keytable);
-
- free(vc_keytable);
-
- if (!vc_keymap) {
- log_oom();
- goto finish;
- }
- }
-
- if (access("/etc/sysconfig/console/default.kmap", F_OK) >= 0) {
- char *t;
-
- t = strdup("/etc/sysconfig/console/default.kmap");
- if (!t) {
- log_oom();
- goto finish;
- }
-
- free(vc_keymap);
- vc_keymap = t;
- }
-#endif
- }
-
- r = EXIT_FAILURE;
-
- if (utf8)
- enable_utf8(fd);
- else
- disable_utf8(fd);
-
-
- if (load_keymap(vc, vc_keymap, vc_keymap_toggle, utf8, &keymap_pid) >= 0 &&
- load_font(vc, vc_font, vc_font_map, vc_font_unimap, &font_pid) >= 0)
- r = EXIT_SUCCESS;
-
-finish:
- if (keymap_pid > 0)
- wait_for_terminate_and_warn(KBD_LOADKEYS, keymap_pid);
-
- if (font_pid > 0)
- wait_for_terminate_and_warn(KBD_SETFONT, font_pid);
-
- free(vc_keymap);
- free(vc_font);
- free(vc_font_map);
- free(vc_font_unimap);
-
- if (fd >= 0)
- close_nointr_nofail(fd);
-
- return r;
-}