summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore318
-rw-r--r--.gitmodules3
-rw-r--r--.mailmap38
-rw-r--r--.vimrc20
-rw-r--r--.ycm_extra_conf.py67
-rw-r--r--LICENSE.MIT19
-rw-r--r--Makefile16
-rw-r--r--Makefile-man.am1136
-rw-r--r--Makefile.am1663
-rw-r--r--NEWS1242
-rw-r--r--README65
-rw-r--r--TODO360
-rwxr-xr-xautogen.sh56
-rw-r--r--cb/elogind.cbp538
-rwxr-xr-xconfigure21
-rw-r--r--configure.ac906
-rw-r--r--doc/CODING_STYLE (renamed from CODING_STYLE)26
-rw-r--r--docs/.gitignore1
l---------docs/Makefile1
-rw-r--r--m4/.gitignore6
-rw-r--r--m4/arch.m413
-rw-r--r--m4/attributes.m4292
-rw-r--r--m4/ax_normalize_path.m4115
-rw-r--r--man/.gitignore5
l---------man/Makefile1
-rw-r--r--man/custom-entities.ent.in12
-rw-r--r--man/custom-html.xsl28
-rw-r--r--man/custom-man.xsl17
-rw-r--r--man/elogind-inhibit.xml157
-rw-r--r--man/elogind.syntax.xml98
-rw-r--r--man/elogind.xml1272
-rw-r--r--man/glib-event-glue.c64
-rw-r--r--man/less-variables.xml4
-rw-r--r--man/libelogind-pkgconfig.xml4
-rw-r--r--man/loginctl.xml208
-rw-r--r--man/logind.conf.xml481
-rw-r--r--man/meson.build225
-rw-r--r--man/pam_elogind.xml83
-rw-r--r--man/rules/meson.build349
-rw-r--r--man/sd-bus.xml26
-rw-r--r--man/sd-event.xml32
-rw-r--r--man/sd-login.xml251
-rw-r--r--man/sd_booted.xml26
-rw-r--r--man/sd_bus_add_match.xml158
-rw-r--r--man/sd_bus_creds_get_pid.xml56
-rw-r--r--man/sd_bus_creds_new_from_pid.xml39
-rw-r--r--man/sd_bus_default.xml92
-rw-r--r--man/sd_bus_error.xml38
-rw-r--r--man/sd_bus_error_add_map.xml26
-rw-r--r--man/sd_bus_get_fd.xml25
-rw-r--r--man/sd_bus_is_open.xml111
-rw-r--r--man/sd_bus_message_append.xml36
-rw-r--r--man/sd_bus_message_append_array.xml36
-rw-r--r--man/sd_bus_message_append_basic.xml38
-rw-r--r--man/sd_bus_message_append_string_memfd.xml39
-rw-r--r--man/sd_bus_message_append_strv.xml36
-rw-r--r--man/sd_bus_message_get_cookie.xml44
-rw-r--r--man/sd_bus_message_get_monotonic_usec.xml46
-rw-r--r--man/sd_bus_message_read_basic.xml25
-rw-r--r--man/sd_bus_negotiate_fds.xml55
-rw-r--r--man/sd_bus_new.xml38
-rw-r--r--man/sd_bus_path_encode.xml34
-rw-r--r--man/sd_bus_process.xml25
-rw-r--r--man/sd_bus_request_name.xml166
-rw-r--r--man/sd_bus_set_connected_signal.xml117
-rw-r--r--man/sd_bus_set_sender.xml110
-rw-r--r--man/sd_bus_set_watch_bind.xml126
-rw-r--r--man/sd_bus_slot_set_destroy_callback.xml131
-rw-r--r--man/sd_bus_slot_set_floating.xml118
-rw-r--r--man/sd_bus_track_add_name.xml36
-rw-r--r--man/sd_bus_track_new.xml36
-rw-r--r--man/sd_event_add_child.xml27
-rw-r--r--man/sd_event_add_defer.xml29
-rw-r--r--man/sd_event_add_inotify.xml193
-rw-r--r--man/sd_event_add_io.xml55
-rw-r--r--man/sd_event_add_signal.xml27
-rw-r--r--man/sd_event_add_time.xml27
-rw-r--r--man/sd_event_exit.xml30
-rw-r--r--man/sd_event_get_fd.xml26
-rw-r--r--man/sd_event_new.xml26
-rw-r--r--man/sd_event_now.xml30
-rw-r--r--man/sd_event_run.xml26
-rw-r--r--man/sd_event_set_watchdog.xml30
-rw-r--r--man/sd_event_source_get_event.xml26
-rw-r--r--man/sd_event_source_get_pending.xml26
-rw-r--r--man/sd_event_source_set_description.xml26
-rw-r--r--man/sd_event_source_set_destroy_callback.xml112
-rw-r--r--man/sd_event_source_set_enabled.xml26
-rw-r--r--man/sd_event_source_set_prepare.xml26
-rw-r--r--man/sd_event_source_set_priority.xml32
-rw-r--r--man/sd_event_source_set_userdata.xml26
-rw-r--r--man/sd_event_source_unref.xml26
-rw-r--r--man/sd_event_wait.xml26
-rw-r--r--man/sd_get_seats.xml47
-rw-r--r--man/sd_id128_get_machine.xml46
-rw-r--r--man/sd_id128_randomize.xml47
-rw-r--r--man/sd_id128_to_string.xml43
-rw-r--r--man/sd_is_fifo.xml28
-rw-r--r--man/sd_listen_fds.xml26
-rw-r--r--man/sd_login_monitor_new.xml44
-rw-r--r--man/sd_machine_get_class.xml45
-rw-r--r--man/sd_notify.xml95
-rw-r--r--man/sd_pid_get_owner_uid.xml (renamed from man/sd_pid_get_session.xml)167
-rw-r--r--man/sd_seat_get_active.xml47
-rw-r--r--man/sd_session_is_active.xml53
-rw-r--r--man/sd_uid_get_state.xml38
-rw-r--r--man/sd_watchdog_enabled.xml26
-rw-r--r--man/standard-conf.xml73
-rw-r--r--man/standard-options.xml13
-rw-r--r--man/user-system-options.xml10
-rw-r--r--meson.build3412
-rw-r--r--meson_options.txt385
-rw-r--r--modprobe.d/elogind.conf18
-rw-r--r--po/.gitignore9
-rw-r--r--po/LINGUAS1
-rw-r--r--po/POTFILES.in7
-rw-r--r--po/be.po120
-rw-r--r--po/be@latin.po120
-rw-r--r--po/bg.po120
-rw-r--r--po/ca.po138
-rw-r--r--po/cs.po332
-rw-r--r--po/da.po140
-rw-r--r--po/de.po134
-rw-r--r--po/el.po120
-rw-r--r--po/es.po138
-rw-r--r--po/fr.po228
-rw-r--r--po/gl.po120
-rw-r--r--po/hr.po122
-rw-r--r--po/hu.po120
-rw-r--r--po/id.po122
-rw-r--r--po/it.po122
-rw-r--r--po/its/polkit.its8
-rw-r--r--po/its/polkit.loc6
-rw-r--r--po/ko.po122
-rw-r--r--po/meson.build21
-rw-r--r--po/pl.po244
-rw-r--r--po/pt_BR.po124
-rw-r--r--po/ro.po626
-rw-r--r--po/ru.po284
-rw-r--r--po/sk.po120
-rw-r--r--po/sr.po120
-rw-r--r--po/sv.po184
-rw-r--r--po/tr.po226
-rw-r--r--po/uk.po120
-rw-r--r--po/zh_CN.po128
-rw-r--r--po/zh_TW.po120
m---------pwx0
l---------shell-completion/Makefile1
-rw-r--r--shell-completion/bash/.gitignore1
l---------shell-completion/bash/Makefile1
-rw-r--r--shell-completion/bash/loginctl14
-rw-r--r--shell-completion/bash/meson.build58
-rw-r--r--shell-completion/bash/resolvectl182
-rw-r--r--shell-completion/zsh/.gitignore1
l---------shell-completion/zsh/Makefile1
-rw-r--r--shell-completion/zsh/_elogind-inhibit1
-rw-r--r--shell-completion/zsh/_loginctl1
-rw-r--r--shell-completion/zsh/meson.build53
-rw-r--r--src/.gitignore76
-rw-r--r--src/Makefile28
-rw-r--r--src/basic/.gitignore16
l---------src/basic/Makefile1
-rw-r--r--src/basic/alloc-util.c46
-rw-r--r--src/basic/alloc-util.h55
-rw-r--r--src/basic/audit-util.c30
-rw-r--r--src/basic/audit-util.h24
-rw-r--r--src/basic/build.h161
-rw-r--r--src/basic/bus-label.c19
-rw-r--r--src/basic/bus-label.h24
-rw-r--r--src/basic/cap-list.c119
-rw-r--r--src/basic/cap-list.h9
-rw-r--r--src/basic/cap-to-name.awk9
-rw-r--r--src/basic/capability-util.c143
-rw-r--r--src/basic/capability-util.h26
-rw-r--r--src/basic/cgroup-util.c536
-rw-r--r--src/basic/cgroup-util.h58
-rw-r--r--src/basic/conf-files.c300
-rw-r--r--src/basic/conf-files.h43
-rw-r--r--src/basic/copy.c352
-rw-r--r--src/basic/copy.h32
-rw-r--r--src/basic/def.h62
-rw-r--r--src/basic/dirent-util.c19
-rw-r--r--src/basic/dirent-util.h20
-rw-r--r--src/basic/env-util.c95
-rw-r--r--src/basic/env-util.h29
-rw-r--r--src/basic/errno-list.c24
-rw-r--r--src/basic/errno-list.h32
-rw-r--r--src/basic/errno-to-name.awk9
-rw-r--r--src/basic/escape.c33
-rw-r--r--src/basic/escape.h22
-rw-r--r--src/basic/exec-util.c80
-rw-r--r--src/basic/exec-util.h19
-rw-r--r--src/basic/extract-word.c24
-rw-r--r--src/basic/extract-word.h20
-rw-r--r--src/basic/fd-util.c671
-rw-r--r--src/basic/fd-util.h72
-rw-r--r--src/basic/fileio-label.c35
-rw-r--r--src/basic/fileio-label.h28
-rw-r--r--src/basic/fileio.c457
-rw-r--r--src/basic/fileio.h51
-rw-r--r--src/basic/format-table.c1255
-rw-r--r--src/basic/format-table.h68
-rw-r--r--src/basic/format-util.h19
-rw-r--r--src/basic/fs-util.c632
-rw-r--r--src/basic/fs-util.h61
-rwxr-xr-xsrc/basic/generate-cap-list.sh12
-rwxr-xr-xsrc/basic/generate-errno-list.sh5
-rwxr-xr-xsrc/basic/generate-gperfs.py22
-rw-r--r--src/basic/generate-socket-protocol-list.sh6
-rw-r--r--src/basic/gunicode.c4
-rw-r--r--src/basic/gunicode.h2
-rw-r--r--src/basic/hash-funcs.c69
-rw-r--r--src/basic/hash-funcs.h43
-rw-r--r--src/basic/hashmap.c208
-rw-r--r--src/basic/hashmap.h64
-rw-r--r--src/basic/hexdecoct.c304
-rw-r--r--src/basic/hexdecoct.h20
-rw-r--r--src/basic/hostname-util.c130
-rw-r--r--src/basic/hostname-util.h26
-rw-r--r--src/basic/io-util.c31
-rw-r--r--src/basic/io-util.h42
-rw-r--r--src/basic/khash.c93
-rw-r--r--src/basic/khash.h22
-rw-r--r--src/basic/label.c53
-rw-r--r--src/basic/label.h29
-rw-r--r--src/basic/list.h23
-rw-r--r--src/basic/locale-util.c129
-rw-r--r--src/basic/locale-util.h32
-rw-r--r--src/basic/log.c498
-rw-r--r--src/basic/log.h120
-rw-r--r--src/basic/login-util.c19
-rw-r--r--src/basic/login-util.h20
-rw-r--r--src/basic/macro.h80
-rw-r--r--src/basic/memfd-util.c26
-rw-r--r--src/basic/memfd-util.h20
-rw-r--r--src/basic/mempool.c31
-rw-r--r--src/basic/mempool.h23
-rw-r--r--src/basic/meson.build494
-rw-r--r--src/basic/missing.h287
-rw-r--r--src/basic/missing_syscall.h208
-rw-r--r--src/basic/mkdir-label.c45
-rw-r--r--src/basic/mkdir.c104
-rw-r--r--src/basic/mkdir.h32
-rw-r--r--src/basic/mount-util.c401
-rw-r--r--src/basic/mount-util.h43
-rw-r--r--src/basic/pager.c (renamed from src/shared/pager.c)96
-rw-r--r--src/basic/pager.h14
-rw-r--r--src/basic/parse-util.c225
-rw-r--r--src/basic/parse-util.h46
-rw-r--r--src/basic/path-util.c334
-rw-r--r--src/basic/path-util.h86
-rw-r--r--src/basic/prioq.c21
-rw-r--r--src/basic/prioq.h20
-rw-r--r--src/basic/proc-cmdline.c39
-rw-r--r--src/basic/proc-cmdline.h20
-rw-r--r--src/basic/process-util.c743
-rw-r--r--src/basic/process-util.h133
-rw-r--r--src/basic/procfs-util.c269
-rw-r--r--src/basic/procfs-util.h16
-rw-r--r--src/basic/random-util.c39
-rw-r--r--src/basic/random-util.h20
-rw-r--r--src/basic/raw-clone.h79
-rw-r--r--src/basic/refcnt.h20
-rw-r--r--src/basic/rm-rf.c47
-rw-r--r--src/basic/rm-rf.h31
-rw-r--r--src/basic/selinux-util.c134
-rw-r--r--src/basic/selinux-util.h23
-rw-r--r--src/basic/set.h33
-rw-r--r--src/basic/sigbus.c135
-rw-r--r--src/basic/sigbus.h7
-rw-r--r--src/basic/signal-util.c95
-rw-r--r--src/basic/signal-util.h39
-rw-r--r--src/basic/siphash24.c16
-rw-r--r--src/basic/smack-util.c112
-rw-r--r--src/basic/smack-util.h33
-rw-r--r--src/basic/socket-protocol-to-name.awk9
-rw-r--r--src/basic/socket-util.c189
-rw-r--r--src/basic/socket-util.h65
-rw-r--r--src/basic/sparse-endian.h4
-rw-r--r--src/basic/special.h105
-rw-r--r--src/basic/stat-util.c126
-rw-r--r--src/basic/stat-util.h34
-rw-r--r--src/basic/stdio-util.h25
-rw-r--r--src/basic/string-table.c19
-rw-r--r--src/basic/string-table.h45
-rw-r--r--src/basic/string-util.c438
-rw-r--r--src/basic/string-util.h90
-rw-r--r--src/basic/strv.c112
-rw-r--r--src/basic/strv.h41
-rw-r--r--src/basic/syslog-util.c19
-rw-r--r--src/basic/syslog-util.h20
-rw-r--r--src/basic/terminal-util.c664
-rw-r--r--src/basic/terminal-util.h133
-rw-r--r--src/basic/time-util.c307
-rw-r--r--src/basic/time-util.h36
-rw-r--r--src/basic/umask-util.h20
-rw-r--r--src/basic/unaligned.h79
-rw-r--r--src/basic/unit-def.c273
-rw-r--r--src/basic/unit-def.h284
-rw-r--r--src/basic/unit-name.c413
-rw-r--r--src/basic/unit-name.h332
-rw-r--r--src/basic/user-util.c263
-rw-r--r--src/basic/user-util.h72
-rw-r--r--src/basic/utf8.c80
-rw-r--r--src/basic/utf8.h24
-rw-r--r--src/basic/util.c379
-rw-r--r--src/basic/util.h67
-rw-r--r--src/basic/verbs.c71
-rw-r--r--src/basic/verbs.h32
-rw-r--r--src/basic/virt.c198
-rw-r--r--src/basic/virt.h21
-rw-r--r--src/basic/xattr-util.c148
-rw-r--r--src/basic/xattr-util.h28
l---------src/cgroups-agent/Makefile1
-rw-r--r--src/cgroups-agent/cgroups-agent.c19
l---------src/core/Makefile1
-rw-r--r--src/core/cgroup.c1099
-rw-r--r--src/core/cgroup.h77
-rw-r--r--src/core/meson.build234
-rw-r--r--src/core/mount-setup.c172
-rw-r--r--src/core/mount-setup.h20
-rw-r--r--src/libelogind/.gitignore1
l---------src/libelogind/Makefile1
-rw-r--r--src/libelogind/libelogind.pc.in6
-rw-r--r--src/libelogind/libelogind.sym94
-rw-r--r--src/libelogind/meson.build153
l---------src/libelogind/sd-bus/Makefile1
-rw-r--r--src/libelogind/sd-bus/bus-bloom.c156
-rw-r--r--src/libelogind/sd-bus/bus-bloom.h43
-rw-r--r--src/libelogind/sd-bus/bus-common-errors.c21
-rw-r--r--src/libelogind/sd-bus/bus-common-errors.h27
-rw-r--r--src/libelogind/sd-bus/bus-container.c190
-rw-r--r--src/libelogind/sd-bus/bus-container.h18
-rw-r--r--src/libelogind/sd-bus/bus-control.c1424
-rw-r--r--src/libelogind/sd-bus/bus-control.h28
-rw-r--r--src/libelogind/sd-bus/bus-convenience.c108
-rw-r--r--src/libelogind/sd-bus/bus-creds.c58
-rw-r--r--src/libelogind/sd-bus/bus-creds.h17
-rw-r--r--src/libelogind/sd-bus/bus-error.c21
-rw-r--r--src/libelogind/sd-bus/bus-error.h17
-rw-r--r--src/libelogind/sd-bus/bus-gvariant.c20
-rw-r--r--src/libelogind/sd-bus/bus-gvariant.h17
-rw-r--r--src/libelogind/sd-bus/bus-internal.c34
-rw-r--r--src/libelogind/sd-bus/bus-internal.h99
-rw-r--r--src/libelogind/sd-bus/bus-introspect.c29
-rw-r--r--src/libelogind/sd-bus/bus-introspect.h17
-rw-r--r--src/libelogind/sd-bus/bus-kernel.c1738
-rw-r--r--src/libelogind/sd-bus/bus-kernel.h72
-rw-r--r--src/libelogind/sd-bus/bus-match.c33
-rw-r--r--src/libelogind/sd-bus/bus-match.h17
-rw-r--r--src/libelogind/sd-bus/bus-message.c394
-rw-r--r--src/libelogind/sd-bus/bus-message.h30
-rw-r--r--src/libelogind/sd-bus/bus-objects.c64
-rw-r--r--src/libelogind/sd-bus/bus-objects.h17
-rw-r--r--src/libelogind/sd-bus/bus-protocol.h17
-rw-r--r--src/libelogind/sd-bus/bus-signature.c20
-rw-r--r--src/libelogind/sd-bus/bus-signature.h17
-rw-r--r--src/libelogind/sd-bus/bus-slot.c91
-rw-r--r--src/libelogind/sd-bus/bus-slot.h17
-rw-r--r--src/libelogind/sd-bus/bus-socket.c407
-rw-r--r--src/libelogind/sd-bus/bus-socket.h18
-rw-r--r--src/libelogind/sd-bus/bus-track.c88
-rw-r--r--src/libelogind/sd-bus/bus-track.h17
-rw-r--r--src/libelogind/sd-bus/bus-type.c19
-rw-r--r--src/libelogind/sd-bus/bus-type.h19
-rw-r--r--src/libelogind/sd-bus/kdbus.h980
-rw-r--r--src/libelogind/sd-bus/sd-bus.c1646
-rw-r--r--src/libelogind/sd-bus/test-bus-error.c17
-rw-r--r--src/libelogind/sd-bus/test-bus-introspect.c17
-rw-r--r--src/libelogind/sd-bus/test-bus-match.c21
-rw-r--r--src/libelogind/sd-bus/test-bus-server.c20
-rw-r--r--src/libelogind/sd-bus/test-bus-signature.c17
-rw-r--r--src/libelogind/sd-bus/test-bus-vtable.c8
l---------src/libelogind/sd-daemon/Makefile1
-rw-r--r--src/libelogind/sd-daemon/sd-daemon.c81
l---------src/libelogind/sd-event/Makefile1
-rw-r--r--src/libelogind/sd-event/sd-event.c1080
-rw-r--r--src/libelogind/sd-event/test-event.c180
l---------src/libelogind/sd-id128/Makefile1
-rw-r--r--src/libelogind/sd-id128/id128-util.c31
-rw-r--r--src/libelogind/sd-id128/id128-util.h17
-rw-r--r--src/libelogind/sd-id128/sd-id128.c22
l---------src/libelogind/sd-login/Makefile1
-rw-r--r--src/libelogind/sd-login/sd-login.c161
-rw-r--r--src/libelogind/sd-login/test-login.c36
-rw-r--r--src/login/70-power-switch.rules7
-rw-r--r--src/login/70-uaccess.rules9
-rw-r--r--src/login/71-seat.rules.in2
-rw-r--r--src/login/73-seat-late.rules.in11
l---------src/login/Makefile1
-rw-r--r--src/login/eloginctl.c105
-rw-r--r--src/login/eloginctl.h2
-rw-r--r--src/login/elogind-dbus.c308
-rw-r--r--src/login/elogind-dbus.h18
-rw-r--r--src/login/elogind.c84
-rw-r--r--src/login/inhibit.c54
-rw-r--r--src/login/loginctl.c534
-rw-r--r--src/login/logind-acl.c25
-rw-r--r--src/login/logind-acl.h22
-rw-r--r--src/login/logind-action.c75
-rw-r--r--src/login/logind-action.h27
-rw-r--r--src/login/logind-button.c46
-rw-r--r--src/login/logind-button.h20
-rw-r--r--src/login/logind-core.c205
-rw-r--r--src/login/logind-dbus.c897
-rw-r--r--src/login/logind-device.c19
-rw-r--r--src/login/logind-device.h20
-rw-r--r--src/login/logind-gperf.gperf53
-rw-r--r--src/login/logind-inhibit.c31
-rw-r--r--src/login/logind-inhibit.h21
-rw-r--r--src/login/logind-seat-dbus.c100
-rw-r--r--src/login/logind-seat.c45
-rw-r--r--src/login/logind-seat.h22
-rw-r--r--src/login/logind-session-dbus.c77
-rw-r--r--src/login/logind-session-device.c204
-rw-r--r--src/login/logind-session-device.h24
-rw-r--r--src/login/logind-session.c105
-rw-r--r--src/login/logind-session.h24
-rw-r--r--src/login/logind-user-dbus.c59
-rw-r--r--src/login/logind-user.c283
-rw-r--r--src/login/logind-user.h25
-rw-r--r--src/login/logind-utmp.c30
-rw-r--r--src/login/logind.c386
-rw-r--r--src/login/logind.conf.in5
-rw-r--r--src/login/logind.h40
-rw-r--r--src/login/meson.build169
-rw-r--r--src/login/org.freedesktop.login1.conf18
-rw-r--r--src/login/org.freedesktop.login1.policy (renamed from src/login/org.freedesktop.login1.policy.in)159
-rw-r--r--src/login/pam_elogind.c220
-rw-r--r--src/login/pam_elogind.sym2
-rw-r--r--src/login/sysfs-show.c54
-rw-r--r--src/login/sysfs-show.h22
-rw-r--r--src/login/test-inhibit.c19
-rw-r--r--src/login/test-login-shared.c19
-rw-r--r--src/login/test-login-tables.c19
-rw-r--r--src/login/user-runtime-dir.c196
-rw-r--r--src/login/user-runtime-dir.h28
l---------src/shared/Makefile1
-rw-r--r--src/shared/acl-util.c36
-rw-r--r--src/shared/acl-util.h22
-rw-r--r--src/shared/bus-util.c669
-rw-r--r--src/shared/bus-util.h93
-rw-r--r--src/shared/clean-ipc.c185
-rw-r--r--src/shared/clean-ipc.h29
-rw-r--r--src/shared/conf-parser.c665
-rw-r--r--src/shared/conf-parser.h244
-rw-r--r--src/shared/libshared.sym3
-rw-r--r--src/shared/meson.build202
-rw-r--r--src/shared/musl_missing.c40
-rw-r--r--src/shared/musl_missing.h52
-rw-r--r--src/shared/nsflags.c70
-rw-r--r--src/shared/nsflags.h28
-rw-r--r--src/shared/output-mode.c23
-rw-r--r--src/shared/output-mode.h42
-rw-r--r--src/shared/pager.h32
-rw-r--r--src/shared/sleep-config.c267
-rw-r--r--src/shared/sleep-config.h29
-rw-r--r--src/shared/spawn-polkit-agent.c37
-rw-r--r--src/shared/spawn-polkit-agent.h31
-rw-r--r--src/shared/test-tables.h20
-rw-r--r--src/shared/tests.c73
-rw-r--r--src/shared/tests.h23
-rw-r--r--src/shared/udev-util.c57
-rw-r--r--src/shared/udev-util.h34
-rw-r--r--src/shared/utmp-wtmp.c26
-rw-r--r--src/shared/utmp-wtmp.h26
-rw-r--r--src/shared/wireguard-netlink.h179
l---------src/sleep/Makefile1
-rw-r--r--src/sleep/meson.build4
-rw-r--r--src/sleep/sleep.c252
-rw-r--r--src/sleep/sleep.h4
l---------src/systemd/Makefile1
-rw-r--r--src/systemd/_sd-common.h4
-rw-r--r--src/systemd/meson.build96
-rw-r--r--src/systemd/sd-bus-protocol.h4
-rw-r--r--src/systemd/sd-bus-vtable.h7
-rw-r--r--src/systemd/sd-bus.h47
-rw-r--r--src/systemd/sd-daemon.h47
-rw-r--r--src/systemd/sd-event.h16
-rw-r--r--src/systemd/sd-id128.h4
-rw-r--r--src/systemd/sd-login.h4
-rw-r--r--src/systemd/sd-messages.h13
-rw-r--r--src/test/.gitignore1
l---------src/test/Makefile1
-rwxr-xr-xsrc/test/generate-sym-test.py23
-rw-r--r--src/test/meson.build1062
-rw-r--r--src/test/test-alloc-util.c70
-rw-r--r--src/test/test-bus-util.c90
-rw-r--r--src/test/test-cgroup.c32
-rw-r--r--src/test/test-conf-files.c46
-rw-r--r--src/test/test-conf-parser.c227
-rw-r--r--src/test/test-copy.c80
-rw-r--r--src/test/test-dlopen.c15
-rw-r--r--src/test/test-ellipsize.c136
-rw-r--r--src/test/test-escape.c19
-rw-r--r--src/test/test-exec-util.c46
-rw-r--r--src/test/test-extract-word.c21
-rw-r--r--src/test/test-fd-util.c265
-rw-r--r--src/test/test-format-table.c139
-rw-r--r--src/test/test-fs-util.c345
-rw-r--r--src/test/test-hash.c29
-rw-r--r--src/test/test-hashmap-ordered.awk11
-rw-r--r--src/test/test-hashmap-plain.c95
-rw-r--r--src/test/test-hashmap.c131
-rw-r--r--src/test/test-helper.h20
-rw-r--r--src/test/test-hexdecoct.c312
-rw-r--r--src/test/test-id128.c23
-rw-r--r--src/test/test-io-util.c19
-rw-r--r--src/test/test-ipcrm.c19
-rw-r--r--src/test/test-list.c18
-rw-r--r--src/test/test-locale-util.c73
-rw-r--r--src/test/test-log.c77
-rw-r--r--src/test/test-os-util.c22
-rw-r--r--src/test/test-parse-util.c264
-rw-r--r--src/test/test-path-util.c253
-rw-r--r--src/test/test-prioq.c19
-rw-r--r--src/test/test-proc-cmdline.c19
-rw-r--r--src/test/test-process-util.c355
-rw-r--r--src/test/test-procfs-util.c55
-rw-r--r--src/test/test-random-util.c19
-rw-r--r--src/test/test-selinux.c19
-rw-r--r--src/test/test-set.c43
-rw-r--r--src/test/test-signal-util.c131
-rw-r--r--src/test/test-siphash24.c19
-rw-r--r--src/test/test-sizeof.c49
-rw-r--r--src/test/test-stat-util.c43
-rw-r--r--src/test/test-string-util.c223
-rw-r--r--src/test/test-strip-tab-ansi.c55
-rw-r--r--src/test/test-unaligned.c19
-rw-r--r--src/test/test-user-util.c101
-rw-r--r--src/test/test-utf8.c51
-rw-r--r--src/test/test-util.c34
-rw-r--r--src/test/test-verbs.c19
-rw-r--r--src/uaccess-command/uaccess-command.c98
l---------src/update-utmp/Makefile1
-rw-r--r--src/update-utmp/meson.build4
-rw-r--r--src/update-utmp/update-utmp.c55
-rw-r--r--src/update-utmp/update-utmp.h2
-rwxr-xr-xtools/add-git-hook.sh12
-rwxr-xr-xtools/check-includes.pl37
-rw-r--r--tools/find-double-newline.sh42
-rwxr-xr-x[-rw-r--r--]tools/gdb-sd_dump_hashmaps.py34
-rwxr-xr-xtools/make-directive-index.py94
-rwxr-xr-xtools/make-man-index.py32
-rwxr-xr-xtools/make-man-rules.py91
-rw-r--r--tools/meson-apply-m4.sh24
-rwxr-xr-xtools/meson-build.sh18
-rwxr-xr-xtools/meson-check-api-docs.sh11
-rwxr-xr-xtools/meson-check-compilation.sh4
-rwxr-xr-xtools/meson-check-help.sh23
-rwxr-xr-xtools/meson-get-cg-controller.sh18
-rwxr-xr-xtools/meson-git-contrib.sh9
-rw-r--r--tools/meson-link-test.c1
-rwxr-xr-xtools/meson-symlink_headers.sh9
-rwxr-xr-xtools/xml_helper.py20
555 files changed, 39746 insertions, 27075 deletions
diff --git a/.gitignore b/.gitignore
index 792cf2674..0c45e459f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,329 +1,37 @@
*.a
*.cache
*.gch
-*.la
-*.lo
*.log
*.o
*.plist
+*.py[co]
*.stamp
*.swp
*.trs
*~
.config.args
.deps/
-.dirstamp
-.libs/
/*.gcda
/*.gcno
/*.tar.bz2
/*.tar.gz
/*.tar.xz
-/30-systemd-environment-d-generator
/GPATH
/GRTAGS
/GSYMS
/GTAGS
-/Makefile
/TAGS
-/ata_id
-/bootctl
+/ID
/build*
-/busctl
-/cdrom_id
-/collect
-/coredumpctl
/coverage/
-/defined
-/exported
-/exported-*
-/hostnamectl
/image.raw
+/image.raw.cache-pre-dev
+/image.raw.cache-pre-inst
/install-tree
-/journalctl
-/libtool
-/linuxx64.efi.stub
-/localectl
-/loginctl
-/machinectl
-/mtd_probe
-/networkctl
-/scsi_id
-/systemctl
-/systemd
-/systemd-ac-power
-/systemd-analyze
-/systemd-ask-password
-/systemd-backlight
-/systemd-binfmt
-/systemd-bootx64.efi
-/systemd-cat
-/systemd-cgls
-/systemd-cgroups-agent
-/systemd-cgtop
-/systemd-coredump
-/systemd-cryptsetup
-/systemd-cryptsetup-generator
-/systemd-dbus1-generator
-/systemd-debug-generator
-/systemd-delta
-/systemd-detect-virt
-/systemd-dissect
-/systemd-escape
-/systemd-export
-/systemd-firstboot
-/systemd-fsck
-/systemd-fstab-generator
-/systemd-getty-generator
-/systemd-gpt-auto-generator
-/systemd-hibernate-resume
-/systemd-hibernate-resume-generator
-/systemd-hostnamed
-/systemd-hwdb
-/systemd-import
-/systemd-importd
-/systemd-inhibit
-/systemd-initctl
-/systemd-journal-gatewayd
-/systemd-journal-remote
-/systemd-journal-upload
-/systemd-journald
-/systemd-localed
-/systemd-logind
-/systemd-machine-id-setup
-/systemd-machined
-/systemd-modules-load
-/systemd-mount
-/systemd-networkd
-/systemd-networkd-wait-online
-/systemd-notify
-/systemd-nspawn
-/systemd-path
-/systemd-pull
-/systemd-quotacheck
-/systemd-random-seed
-/systemd-rc-local-generator
-/systemd-remount-fs
-/systemd-reply-password
-/systemd-resolve
-/systemd-resolved
-/systemd-rfkill
-/systemd-run
-/systemd-shutdown
-/systemd-sleep
-/systemd-socket-activate
-/systemd-socket-proxyd
-/systemd-stdio-bridge
-/systemd-sysctl
-/systemd-system-update-generator
-/systemd-sysusers
-/systemd-sysv-generator
-/systemd-timedated
-/systemd-timesyncd
-/systemd-tmpfiles
-/systemd-tty-ask-password-agent
-/systemd-udevd
-/systemd-update-done
-/systemd-update-utmp
-/systemd-user-sessions
-/systemd-vconsole-setup
-/systemd-veritysetup
-/systemd-veritysetup-generator
-/systemd-volatile-root
+/mkosi.builddir/
+/mkosi.output/
/tags
-/test-acd
-/test-acl-util
-/test-af-list
-/test-alloc-util
-/test-architecture
-/test-arphrd-list
-/test-ask-password-api
-/test-async
-/test-audit-type
-/test-barrier
-/test-bitmap
-/test-boot-timestamps
-/test-btrfs
-/test-bus-benchmark
-/test-bus-chat
-/test-bus-cleanup
-/test-bus-creds
-/test-bus-error
-/test-bus-gvariant
-/test-bus-introspect
-/test-bus-kernel
-/test-bus-kernel-bloom
-/test-bus-marshal
-/test-bus-match
-/test-bus-objects
-/test-bus-policy
-/test-bus-server
-/test-bus-signature
-/test-bus-track
-/test-bus-vtable
-/test-bus-vtable-cc
-/test-bus-zero-copy
-/test-calendarspec
-/test-cap-list
-/test-capability
-/test-catalog
-/test-cgroup
-/test-cgroup-mask
-/test-cgroup-util
-/test-clock
-/test-compress
-/test-compress-benchmark
-/test-condition
-/test-conf-files
-/test-conf-parser
-/test-copy
-/test-coredump-vacuum
-/test-cpu-set-util
-/test-daemon
-/test-date
-/test-device-nodes
-/test-dnssec-complex
-/test-dhcp-client
-/test-dhcp-option
-/test-dhcp-server
-/test-dhcp6-client
-/test-dissect-image
-/test-dns-domain
-/test-dns-packet
-/test-dnssec
-/test-efi-disk.img
-/test-ellipsize
-/test-engine
-/test-env-util
-/test-escape
-/test-event
-/test-exec-util
-/test-execute
-/test-extract-word
-/test-fd-util
-/test-fdset
-/test-fileio
-/test-firewall-util
-/test-fs-util
-/test-fstab-util
-/test-glob-util
-/test-hash
-/test-hashmap
-/test-hexdecoct
-/test-hostname
-/test-hostname-util
-/test-id128
-/test-inhibit
-/test-install
-/test-install-root
-/test-io-util
-/test-ipcrm
-/test-ipv4ll
-/test-ipv4ll-manual
-/test-job-type
-/test-journal
-/test-journal-enum
-/test-journal-flush
-/test-journal-importer
-/test-journal-init
-/test-journal-interleaving
-/test-journal-match
-/test-journal-send
-/test-journal-stream
-/test-journal-syslog
-/test-journal-verify
-/test-keymap-util
-/test-libsystemd-sym*
-/test-libudev
-/test-libudev-sym*
-/test-list
-/test-lldp
-/test-local-addresses
-/test-locale-util
-/test-log
-/test-login
-/test-login-shared
-/test-login-tables
-/test-loopback
-/test-machine-tables
-/test-mmap-cache
-/test-mount-util
-/test-namespace
-/test-ndisc-rs
-/test-netlink
-/test-netlink-manual
-/test-networkd-conf
-/test-network
-/test-network-tables
-/test-ns
-/test-nss
-/test-parse-util
-/test-patch-uid
-/test-path
-/test-path-lookup
-/test-path-util
-/test-prioq
-/test-proc-cmdline
-/test-process-util
-/test-pty
-/test-qcow2
-/test-random-util
-/test-ratelimit
-/test-replace-var
-/test-resolve
-/test-resolve-tables
-/test-resolved-packet
-/test-ring
-/test-rlimit-util
-/test-sched-prio
-/test-sd-dhcp-lease
-/test-seccomp
-/test-selinux
-/test-set
-/test-sizeof
-/test-sigbus
-/test-signal-util
-/test-siphash24
-/test-sleep
-/test-socket-util
-/test-stat-util
-/test-strbuf
-/test-string-util
-/test-strip-tab-ansi
-/test-strv
-/test-strxcpyx
-/test-tables
-/test-terminal-util
-/test-time
-/test-timesync
-/test-tmpfiles
-/test-udev
-/test-uid-range
-/test-unaligned
-/test-unit-file
-/test-unit-name
-/test-user-util
-/test-utf8
-/test-util
-/test-verbs
-/test-watchdog
-/test-web-util
-/test-xattr-util
-/test-xml
-/timedatectl
-/udevadm
-/undefined
-/v4l_id
-Makefile.in
__pycache__/
-*.py[co]
-aclocal.m4
-config.h
-config.h.in
-config.log
-config.status
-configure
-stamp-*
# elogind specific
/elogind
@@ -332,14 +40,10 @@ stamp-*
/test-libelogind*
# Local Helper Scripts and Tools - Not for distribution
-patches/
-patches_port/
-/check_*.*
-/cleanup*.sh
-/elogind.*
-/get_build_file_diff.sh
-/pwx_*.*
-/rebuild_all.sh
+pwx/patches/*
+!pwx/patches/.keep_dir
+pwx/patches_port/*
+!pwx/patches_port/.keep_dir
*.orig
*.rej
*.remote
@@ -364,3 +68,5 @@ mask_po_files.sh
cccc
*.v234
*.v234.diff
+.project
+patches_port/
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 000000000..d9427f25e
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "pwx"]
+ path = pwx
+ url = https://github.com/Yamakuzure/pwx-elogind-migration-tools.git
diff --git a/.mailmap b/.mailmap
index e2a390bbe..83b17bfb2 100644
--- a/.mailmap
+++ b/.mailmap
@@ -123,3 +123,41 @@ Federico Di Pierro <nierro92@gmail.com>
Josef Andersson <josef.andersson@fripost.org>
Josef Andersson <l10nl18nsweja@gmail.com>
Hendrik Westerberg <hendrik@gestorf.com>
+Stefan Pietsch <mail.ipv4v6@gmail.com>
+Jérémy Rosen <jeremy.rosen@enst-bretagne.fr>
+Vasilis Liaskovitis <vliaskov@gmail.com>
+Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Tomasz Pala <gotar@polanet.pl>
+Dmitriy Geels <dmitriy.geels@gmail.com>
+Beniamino Galvani <bgalvani@redhat.com> <bengal@users.noreply.github.com>
+Justin Capella <justincapella@gmail.com> <b1tninja@users.noreply.github.com>
+Daniel Șerbănescu <dasj19@users.noreply.github.com>
+Stanislav Angelovič <angelovic.s@gmail.com>
+Torsten Hilbrich <torsten.hilbrich@gmx.net>
+Tinu Weber <takeya@bluewin.ch>
+Gwendal Grignou <gwendal@chromium.org>
+José Bollo <jose.bollo@iot.bzh> <jobol@nonadev.net>
+Patryk Kocielnik <longer44@gmail.com>
+Lukáš Říha <cedel@centrum.cz>
+Alan Robertson <aroberts@zen.iomart.com> <alanjrobertson@gmail.com>
+Martin Steuer <martinsteuer@gmx.de>
+Matthias-Christian Ott <ott@mirix.org> <ott@users.noreply.github.com>
+Larry Bernstone <lbernstone@gmail.com>
+Michał Szczepański <skrzatu@hotmail.com> <skrzatu@gmail.com>
+Tomasz Bachorski <tomasz.bachorski@x7f.io> <34866781+nulsoh@users.noreply.github.com>
+Zachary Winnerman <33329648+winnerman-pythian@users.noreply.github.com>
+Vladislav Vishnyakov <split7fire@yandex.ru>
+Robert Kolchmeyer <rkolchmeyer@google.com> <rkolchmeyer@users.noreply.github.com>
+George Gaydarov <git@gg7.io> <gg7@users.noreply.github.com>
+Bill Yodlowsky <bill@redhat.com> <itsbill@users.noreply.github.com>
+Mao Huang <littlecvr@gmail.com>
+Pavel Hrdina <phrdina@redhat.com>
+Jürg Billeter <j@bitron.ch>
+Leonard König <leonard.r.koenig@googlemail.com>
+Milan Pässler <me@petabyteboy.de>
+Wim van Mourik <wvanmourik@computest.nl> <githubw@use.startmail.com>
+Rubén Suárez Alvarez <rubensa@tluportatil082> <rubensa@gmail.com>
+Salvo Tomaselli <ltworf@users.noreply.github.com>
+Matthew McGinn <mamcgi@gmail.com> <xginn8@users.noreply.github.com>
+Evgeny Vereshchagin <evvers@ya.ru>
+Peter D'Hoye <peter.dhoye@gmail.com>
diff --git a/.vimrc b/.vimrc
deleted file mode 100644
index 284bf8849..000000000
--- a/.vimrc
+++ /dev/null
@@ -1,20 +0,0 @@
-" 'set exrc' in ~/.vimrc will read .vimrc from the current directory
-" Warning: Enabling exrc is dangerous! You can do nearly everything from a
-" vimrc configuration file, including write operations and shell execution.
-" You should consider setting 'set secure' as well, which is highly
-" recommended!
-
-" Note that we set a line width of 119 for .c and XML files, but for everything
-" else (such as journal catalog files, unit files, README files) we stick to a
-" more conservative 79 characters.
-
-" NOTE: If you update this file make sure to update .dir-locals.el and
-" .editorconfig, too.
-
-set tabstop=8
-set shiftwidth=8
-set expandtab
-set makeprg=GCC_COLORS=\ make
-set tw=79
-au BufRead,BufNewFile *.xml set tw=119 shiftwidth=2 smarttab
-au FileType c set tw=119
diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py
deleted file mode 100644
index 4edd3c8a7..000000000
--- a/.ycm_extra_conf.py
+++ /dev/null
@@ -1,67 +0,0 @@
-import itertools
-import os
-import subprocess
-
-def GetFlagsFromMakefile(varname):
- return subprocess.check_output([
- "make", "-s", "print-%s" % varname]).decode().split()
-
-
-def Flatten(lists):
- return list(itertools.chain.from_iterable(lists))
-
-
-def DirectoryOfThisScript():
- return os.path.dirname(os.path.abspath(__file__))
-
-
-def MakeRelativePathsInFlagsAbsolute(flags, working_directory):
- if not working_directory:
- return flags
- new_flags = []
- make_next_absolute = False
- path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ]
- for flag in flags:
- new_flag = flag
-
- if make_next_absolute:
- make_next_absolute = False
- if not flag.startswith('/'):
- new_flag = os.path.join(working_directory, flag)
-
- for path_flag in path_flags:
- if flag == path_flag:
- make_next_absolute = True
- break
-
- if flag.startswith(path_flag):
- path = flag[ len(path_flag): ]
- new_flag = path_flag + os.path.join(working_directory, path)
- break
-
- if new_flag:
- new_flags.append(new_flag)
- return new_flags
-
-
-def FlagsForFile(filename):
- relative_to = DirectoryOfThisScript()
-
- return {
- 'flags': MakeRelativePathsInFlagsAbsolute(flags, relative_to),
- 'do_cache': True
- }
-
-flags = Flatten(map(GetFlagsFromMakefile, [
- 'AM_CPPFLAGS',
- 'CPPFLAGS',
- 'AM_CFLAGS',
- 'CFLAGS',
-]))
-
-# these flags cause crashes in libclang, so remove them
-flags.remove('-Wlogical-op')
-flags.remove('-Wsuggest-attribute=noreturn')
-flags.remove('-Wdate-time')
-
-# vim: set et ts=2 sw=2:
diff --git a/LICENSE.MIT b/LICENSE.MIT
deleted file mode 100644
index fd44f736e..000000000
--- a/LICENSE.MIT
+++ /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:
-
-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.
diff --git a/Makefile b/Makefile
new file mode 100644
index 000000000..4de99579a
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,16 @@
+.PHONY: all install loginctl test test-login
+
+all:
+ ninja -C build
+
+install:
+ DESTDIR=$(DESTDIR) ninja -C build install
+
+loginctl:
+ ninja -C build loginctl
+
+test:
+ ninja -C build test
+
+test-login:
+ ninja -C build test-login
diff --git a/Makefile-man.am b/Makefile-man.am
deleted file mode 100644
index c4e00d7cb..000000000
--- a/Makefile-man.am
+++ /dev/null
@@ -1,1136 +0,0 @@
-# Do not edit. Generated by make-man-rules.py.
-# To regenerate:
-# 1. Create, update, or remove source .xml files in man/
-# 2. Run 'make update-man-list'
-# 3. Run 'make man' to generate manpages
-#
-# To make a man page conditional on a configure switch add
-# attribute conditional="ENABLE_WHAT" or conditional="WITH_WHAT"
-# to <refentry> element.
-MANPAGES += \
- man/elogind.8 \
- man/loginctl.1 \
- man/logind.conf.5 \
- man/sd-bus.3 \
- man/sd-event.3 \
- man/sd_booted.3 \
- man/sd_bus_add_match.3 \
- man/sd_bus_creds_get_pid.3 \
- man/sd_bus_creds_new_from_pid.3 \
- man/sd_bus_default.3 \
- man/sd_bus_error.3 \
- man/sd_bus_error_add_map.3 \
- man/sd_bus_get_fd.3 \
- man/sd_bus_message_append.3 \
- man/sd_bus_message_append_array.3 \
- man/sd_bus_message_append_basic.3 \
- man/sd_bus_message_append_string_memfd.3 \
- man/sd_bus_message_append_strv.3 \
- man/sd_bus_message_get_cookie.3 \
- man/sd_bus_message_get_monotonic_usec.3 \
- man/sd_bus_message_read_basic.3 \
- man/sd_bus_negotiate_fds.3 \
- man/sd_bus_new.3 \
- man/sd_bus_path_encode.3 \
- man/sd_bus_process.3 \
- man/sd_bus_request_name.3 \
- man/sd_bus_track_add_name.3 \
- man/sd_bus_track_new.3 \
- man/sd_event_add_child.3 \
- man/sd_event_add_defer.3 \
- man/sd_event_add_io.3 \
- man/sd_event_add_signal.3 \
- man/sd_event_add_time.3 \
- man/sd_event_exit.3 \
- man/sd_event_get_fd.3 \
- man/sd_event_new.3 \
- man/sd_event_now.3 \
- man/sd_event_run.3 \
- man/sd_event_set_watchdog.3 \
- man/sd_event_source_get_event.3 \
- man/sd_event_source_get_pending.3 \
- man/sd_event_source_set_description.3 \
- man/sd_event_source_set_enabled.3 \
- man/sd_event_source_set_prepare.3 \
- man/sd_event_source_set_priority.3 \
- man/sd_event_source_set_userdata.3 \
- man/sd_event_source_unref.3 \
- man/sd_event_wait.3 \
- man/sd_id128_get_machine.3 \
- man/sd_id128_randomize.3 \
- man/sd_id128_to_string.3 \
- man/sd_is_fifo.3 \
- man/sd_listen_fds.3 \
- man/sd_machine_get_class.3 \
- man/sd_notify.3 \
- man/sd_watchdog_enabled.3
-MANPAGES_ALIAS += \
- man/SD_BUS_ERROR_END.3 \
- man/SD_BUS_ERROR_MAKE_CONST.3 \
- man/SD_BUS_ERROR_MAP.3 \
- man/SD_BUS_ERROR_NULL.3 \
- man/SD_EVENT_ARMED.3 \
- man/SD_EVENT_EXITING.3 \
- man/SD_EVENT_FINISHED.3 \
- man/SD_EVENT_INITIAL.3 \
- man/SD_EVENT_OFF.3 \
- man/SD_EVENT_ON.3 \
- man/SD_EVENT_ONESHOT.3 \
- man/SD_EVENT_PENDING.3 \
- man/SD_EVENT_PREPARING.3 \
- man/SD_EVENT_PRIORITY_IDLE.3 \
- man/SD_EVENT_PRIORITY_IMPORTANT.3 \
- man/SD_EVENT_PRIORITY_NORMAL.3 \
- man/SD_EVENT_RUNNING.3 \
- man/SD_LISTEN_FDS_START.3 \
- man/sd_bus_creds_get_audit_login_uid.3 \
- man/sd_bus_creds_get_audit_session_id.3 \
- man/sd_bus_creds_get_augmented_mask.3 \
- man/sd_bus_creds_get_cgroup.3 \
- man/sd_bus_creds_get_cmdline.3 \
- man/sd_bus_creds_get_comm.3 \
- man/sd_bus_creds_get_description.3 \
- man/sd_bus_creds_get_egid.3 \
- man/sd_bus_creds_get_euid.3 \
- man/sd_bus_creds_get_exe.3 \
- man/sd_bus_creds_get_fsgid.3 \
- man/sd_bus_creds_get_fsuid.3 \
- man/sd_bus_creds_get_gid.3 \
- man/sd_bus_creds_get_mask.3 \
- man/sd_bus_creds_get_owner_uid.3 \
- man/sd_bus_creds_get_ppid.3 \
- man/sd_bus_creds_get_selinux_context.3 \
- man/sd_bus_creds_get_session.3 \
- man/sd_bus_creds_get_sgid.3 \
- man/sd_bus_creds_get_suid.3 \
- man/sd_bus_creds_get_supplementary_gids.3 \
- man/sd_bus_creds_get_tid.3 \
- man/sd_bus_creds_get_tid_comm.3 \
- man/sd_bus_creds_get_tty.3 \
- man/sd_bus_creds_get_uid.3 \
- man/sd_bus_creds_get_unique_name.3 \
- man/sd_bus_creds_get_well_known_names.3 \
- man/sd_bus_creds_has_bounding_cap.3 \
- man/sd_bus_creds_has_effective_cap.3 \
- man/sd_bus_creds_has_inheritable_cap.3 \
- man/sd_bus_creds_has_permitted_cap.3 \
- man/sd_bus_creds_ref.3 \
- man/sd_bus_creds_unref.3 \
- man/sd_bus_creds_unrefp.3 \
- man/sd_bus_default_system.3 \
- man/sd_bus_default_user.3 \
- man/sd_bus_error_copy.3 \
- man/sd_bus_error_free.3 \
- man/sd_bus_error_get_errno.3 \
- man/sd_bus_error_has_name.3 \
- man/sd_bus_error_is_set.3 \
- man/sd_bus_error_map.3 \
- man/sd_bus_error_set.3 \
- man/sd_bus_error_set_const.3 \
- man/sd_bus_error_set_errno.3 \
- man/sd_bus_error_set_errnof.3 \
- man/sd_bus_error_set_errnofv.3 \
- man/sd_bus_error_setf.3 \
- man/sd_bus_message_append_array_iovec.3 \
- man/sd_bus_message_append_array_memfd.3 \
- man/sd_bus_message_append_array_space.3 \
- man/sd_bus_message_append_string_iovec.3 \
- man/sd_bus_message_append_string_space.3 \
- man/sd_bus_message_get_realtime_usec.3 \
- man/sd_bus_message_get_reply_cookie.3 \
- man/sd_bus_message_get_seqnum.3 \
- man/sd_bus_negotiate_creds.3 \
- man/sd_bus_negotiate_timestamp.3 \
- man/sd_bus_open.3 \
- man/sd_bus_open_system.3 \
- man/sd_bus_open_system_machine.3 \
- man/sd_bus_open_system_remote.3 \
- man/sd_bus_open_user.3 \
- man/sd_bus_path_decode.3 \
- man/sd_bus_path_decode_many.3 \
- man/sd_bus_path_encode_many.3 \
- man/sd_bus_ref.3 \
- man/sd_bus_release_name.3 \
- man/sd_bus_track_add_sender.3 \
- man/sd_bus_track_contains.3 \
- man/sd_bus_track_count.3 \
- man/sd_bus_track_count_name.3 \
- man/sd_bus_track_count_sender.3 \
- man/sd_bus_track_first.3 \
- man/sd_bus_track_get_bus.3 \
- man/sd_bus_track_get_recursive.3 \
- man/sd_bus_track_get_userdata.3 \
- man/sd_bus_track_next.3 \
- man/sd_bus_track_ref.3 \
- man/sd_bus_track_remove_name.3 \
- man/sd_bus_track_remove_sender.3 \
- man/sd_bus_track_set_recursive.3 \
- man/sd_bus_track_set_userdata.3 \
- man/sd_bus_track_unref.3 \
- man/sd_bus_track_unrefp.3 \
- man/sd_bus_unref.3 \
- man/sd_bus_unrefp.3 \
- man/sd_event.3 \
- man/sd_event_add_exit.3 \
- man/sd_event_add_post.3 \
- man/sd_event_child_handler_t.3 \
- man/sd_event_default.3 \
- man/sd_event_dispatch.3 \
- man/sd_event_get_exit_code.3 \
- man/sd_event_get_state.3 \
- man/sd_event_get_tid.3 \
- man/sd_event_get_watchdog.3 \
- man/sd_event_handler_t.3 \
- man/sd_event_io_handler_t.3 \
- man/sd_event_loop.3 \
- man/sd_event_prepare.3 \
- man/sd_event_ref.3 \
- man/sd_event_signal_handler_t.3 \
- man/sd_event_source.3 \
- man/sd_event_source_get_child_pid.3 \
- man/sd_event_source_get_description.3 \
- man/sd_event_source_get_enabled.3 \
- man/sd_event_source_get_io_events.3 \
- man/sd_event_source_get_io_fd.3 \
- man/sd_event_source_get_io_revents.3 \
- man/sd_event_source_get_priority.3 \
- man/sd_event_source_get_signal.3 \
- man/sd_event_source_get_time.3 \
- man/sd_event_source_get_time_accuracy.3 \
- man/sd_event_source_get_time_clock.3 \
- man/sd_event_source_get_userdata.3 \
- man/sd_event_source_ref.3 \
- man/sd_event_source_set_io_events.3 \
- man/sd_event_source_set_io_fd.3 \
- man/sd_event_source_set_time.3 \
- man/sd_event_source_set_time_accuracy.3 \
- man/sd_event_source_unrefp.3 \
- man/sd_event_time_handler_t.3 \
- man/sd_event_unref.3 \
- man/sd_event_unrefp.3 \
- man/sd_id128_from_string.3 \
- man/sd_id128_get_boot.3 \
- man/sd_id128_get_invocation.3 \
- man/sd_id128_get_machine_app_specific.3 \
- man/sd_is_socket.3 \
- man/sd_is_socket_inet.3 \
- man/sd_is_socket_unix.3 \
- man/sd_is_special.3 \
- man/sd_listen_fds_with_names.3 \
- man/sd_machine_get_ifindices.3 \
- man/sd_notifyf.3 \
- man/sd_pid_notify.3 \
- man/sd_pid_notify_with_fds.3 \
- man/sd_pid_notifyf.3
-man/SD_BUS_ERROR_END.3: man/sd_bus_error_add_map.3
-man/SD_BUS_ERROR_MAKE_CONST.3: man/sd_bus_error.3
-man/SD_BUS_ERROR_MAP.3: man/sd_bus_error_add_map.3
-man/SD_BUS_ERROR_NULL.3: man/sd_bus_error.3
-man/SD_EVENT_ARMED.3: man/sd_event_wait.3
-man/SD_EVENT_EXITING.3: man/sd_event_wait.3
-man/SD_EVENT_FINISHED.3: man/sd_event_wait.3
-man/SD_EVENT_INITIAL.3: man/sd_event_wait.3
-man/SD_EVENT_OFF.3: man/sd_event_source_set_enabled.3
-man/SD_EVENT_ON.3: man/sd_event_source_set_enabled.3
-man/SD_EVENT_ONESHOT.3: man/sd_event_source_set_enabled.3
-man/SD_EVENT_PENDING.3: man/sd_event_wait.3
-man/SD_EVENT_PREPARING.3: man/sd_event_wait.3
-man/SD_EVENT_PRIORITY_IDLE.3: man/sd_event_source_set_priority.3
-man/SD_EVENT_PRIORITY_IMPORTANT.3: man/sd_event_source_set_priority.3
-man/SD_EVENT_PRIORITY_NORMAL.3: man/sd_event_source_set_priority.3
-man/SD_EVENT_RUNNING.3: man/sd_event_wait.3
-man/SD_LISTEN_FDS_START.3: man/sd_listen_fds.3
-man/sd_bus_creds_get_audit_login_uid.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_audit_session_id.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_augmented_mask.3: man/sd_bus_creds_new_from_pid.3
-man/sd_bus_creds_get_cgroup.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_cmdline.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_comm.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_description.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_egid.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_euid.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_exe.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_fsgid.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_fsuid.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_gid.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_mask.3: man/sd_bus_creds_new_from_pid.3
-man/sd_bus_creds_get_owner_uid.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_ppid.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_selinux_context.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_session.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_sgid.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_suid.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_supplementary_gids.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_tid.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_tid_comm.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_tty.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_uid.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_unique_name.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_get_well_known_names.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_has_bounding_cap.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_has_effective_cap.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_has_inheritable_cap.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_has_permitted_cap.3: man/sd_bus_creds_get_pid.3
-man/sd_bus_creds_ref.3: man/sd_bus_creds_new_from_pid.3
-man/sd_bus_creds_unref.3: man/sd_bus_creds_new_from_pid.3
-man/sd_bus_creds_unrefp.3: man/sd_bus_creds_new_from_pid.3
-man/sd_bus_default_system.3: man/sd_bus_default.3
-man/sd_bus_default_user.3: man/sd_bus_default.3
-man/sd_bus_error_copy.3: man/sd_bus_error.3
-man/sd_bus_error_free.3: man/sd_bus_error.3
-man/sd_bus_error_get_errno.3: man/sd_bus_error.3
-man/sd_bus_error_has_name.3: man/sd_bus_error.3
-man/sd_bus_error_is_set.3: man/sd_bus_error.3
-man/sd_bus_error_map.3: man/sd_bus_error_add_map.3
-man/sd_bus_error_set.3: man/sd_bus_error.3
-man/sd_bus_error_set_const.3: man/sd_bus_error.3
-man/sd_bus_error_set_errno.3: man/sd_bus_error.3
-man/sd_bus_error_set_errnof.3: man/sd_bus_error.3
-man/sd_bus_error_set_errnofv.3: man/sd_bus_error.3
-man/sd_bus_error_setf.3: man/sd_bus_error.3
-man/sd_bus_message_append_array_iovec.3: man/sd_bus_message_append_array.3
-man/sd_bus_message_append_array_memfd.3: man/sd_bus_message_append_array.3
-man/sd_bus_message_append_array_space.3: man/sd_bus_message_append_array.3
-man/sd_bus_message_append_string_iovec.3: man/sd_bus_message_append_string_memfd.3
-man/sd_bus_message_append_string_space.3: man/sd_bus_message_append_string_memfd.3
-man/sd_bus_message_get_realtime_usec.3: man/sd_bus_message_get_monotonic_usec.3
-man/sd_bus_message_get_reply_cookie.3: man/sd_bus_message_get_cookie.3
-man/sd_bus_message_get_seqnum.3: man/sd_bus_message_get_monotonic_usec.3
-man/sd_bus_negotiate_creds.3: man/sd_bus_negotiate_fds.3
-man/sd_bus_negotiate_timestamp.3: man/sd_bus_negotiate_fds.3
-man/sd_bus_open.3: man/sd_bus_default.3
-man/sd_bus_open_system.3: man/sd_bus_default.3
-man/sd_bus_open_system_machine.3: man/sd_bus_default.3
-man/sd_bus_open_system_remote.3: man/sd_bus_default.3
-man/sd_bus_open_user.3: man/sd_bus_default.3
-man/sd_bus_path_decode.3: man/sd_bus_path_encode.3
-man/sd_bus_path_decode_many.3: man/sd_bus_path_encode.3
-man/sd_bus_path_encode_many.3: man/sd_bus_path_encode.3
-man/sd_bus_ref.3: man/sd_bus_new.3
-man/sd_bus_release_name.3: man/sd_bus_request_name.3
-man/sd_bus_track_add_sender.3: man/sd_bus_track_add_name.3
-man/sd_bus_track_contains.3: man/sd_bus_track_add_name.3
-man/sd_bus_track_count.3: man/sd_bus_track_add_name.3
-man/sd_bus_track_count_name.3: man/sd_bus_track_add_name.3
-man/sd_bus_track_count_sender.3: man/sd_bus_track_add_name.3
-man/sd_bus_track_first.3: man/sd_bus_track_add_name.3
-man/sd_bus_track_get_bus.3: man/sd_bus_track_new.3
-man/sd_bus_track_get_recursive.3: man/sd_bus_track_new.3
-man/sd_bus_track_get_userdata.3: man/sd_bus_track_new.3
-man/sd_bus_track_next.3: man/sd_bus_track_add_name.3
-man/sd_bus_track_ref.3: man/sd_bus_track_new.3
-man/sd_bus_track_remove_name.3: man/sd_bus_track_add_name.3
-man/sd_bus_track_remove_sender.3: man/sd_bus_track_add_name.3
-man/sd_bus_track_set_recursive.3: man/sd_bus_track_new.3
-man/sd_bus_track_set_userdata.3: man/sd_bus_track_new.3
-man/sd_bus_track_unref.3: man/sd_bus_track_new.3
-man/sd_bus_track_unrefp.3: man/sd_bus_track_new.3
-man/sd_bus_unref.3: man/sd_bus_new.3
-man/sd_bus_unrefp.3: man/sd_bus_new.3
-man/sd_event.3: man/sd_event_new.3
-man/sd_event_add_exit.3: man/sd_event_add_defer.3
-man/sd_event_add_post.3: man/sd_event_add_defer.3
-man/sd_event_child_handler_t.3: man/sd_event_add_child.3
-man/sd_event_default.3: man/sd_event_new.3
-man/sd_event_dispatch.3: man/sd_event_wait.3
-man/sd_event_get_exit_code.3: man/sd_event_exit.3
-man/sd_event_get_state.3: man/sd_event_wait.3
-man/sd_event_get_tid.3: man/sd_event_new.3
-man/sd_event_get_watchdog.3: man/sd_event_set_watchdog.3
-man/sd_event_handler_t.3: man/sd_event_add_defer.3
-man/sd_event_io_handler_t.3: man/sd_event_add_io.3
-man/sd_event_loop.3: man/sd_event_run.3
-man/sd_event_prepare.3: man/sd_event_wait.3
-man/sd_event_ref.3: man/sd_event_new.3
-man/sd_event_signal_handler_t.3: man/sd_event_add_signal.3
-man/sd_event_source.3: man/sd_event_add_io.3
-man/sd_event_source_get_child_pid.3: man/sd_event_add_child.3
-man/sd_event_source_get_description.3: man/sd_event_source_set_description.3
-man/sd_event_source_get_enabled.3: man/sd_event_source_set_enabled.3
-man/sd_event_source_get_io_events.3: man/sd_event_add_io.3
-man/sd_event_source_get_io_fd.3: man/sd_event_add_io.3
-man/sd_event_source_get_io_revents.3: man/sd_event_add_io.3
-man/sd_event_source_get_priority.3: man/sd_event_source_set_priority.3
-man/sd_event_source_get_signal.3: man/sd_event_add_signal.3
-man/sd_event_source_get_time.3: man/sd_event_add_time.3
-man/sd_event_source_get_time_accuracy.3: man/sd_event_add_time.3
-man/sd_event_source_get_time_clock.3: man/sd_event_add_time.3
-man/sd_event_source_get_userdata.3: man/sd_event_source_set_userdata.3
-man/sd_event_source_ref.3: man/sd_event_source_unref.3
-man/sd_event_source_set_io_events.3: man/sd_event_add_io.3
-man/sd_event_source_set_io_fd.3: man/sd_event_add_io.3
-man/sd_event_source_set_time.3: man/sd_event_add_time.3
-man/sd_event_source_set_time_accuracy.3: man/sd_event_add_time.3
-man/sd_event_source_unrefp.3: man/sd_event_source_unref.3
-man/sd_event_time_handler_t.3: man/sd_event_add_time.3
-man/sd_event_unref.3: man/sd_event_new.3
-man/sd_event_unrefp.3: man/sd_event_new.3
-man/sd_id128_from_string.3: man/sd_id128_to_string.3
-man/sd_id128_get_boot.3: man/sd_id128_get_machine.3
-man/sd_id128_get_invocation.3: man/sd_id128_get_machine.3
-man/sd_id128_get_machine_app_specific.3: man/sd_id128_get_machine.3
-man/sd_is_socket.3: man/sd_is_fifo.3
-man/sd_is_socket_inet.3: man/sd_is_fifo.3
-man/sd_is_socket_unix.3: man/sd_is_fifo.3
-man/sd_is_special.3: man/sd_is_fifo.3
-man/sd_listen_fds_with_names.3: man/sd_listen_fds.3
-man/sd_machine_get_ifindices.3: man/sd_machine_get_class.3
-man/sd_notifyf.3: man/sd_notify.3
-man/sd_pid_notify.3: man/sd_notify.3
-man/sd_pid_notify_with_fds.3: man/sd_notify.3
-man/sd_pid_notifyf.3: man/sd_notify.3
-man/SD_BUS_ERROR_END.html: man/sd_bus_error_add_map.html
- $(html-alias)
-
-man/SD_BUS_ERROR_MAKE_CONST.html: man/sd_bus_error.html
- $(html-alias)
-
-man/SD_BUS_ERROR_MAP.html: man/sd_bus_error_add_map.html
- $(html-alias)
-
-man/SD_BUS_ERROR_NULL.html: man/sd_bus_error.html
- $(html-alias)
-
-man/SD_EVENT_ARMED.html: man/sd_event_wait.html
- $(html-alias)
-
-man/SD_EVENT_EXITING.html: man/sd_event_wait.html
- $(html-alias)
-
-man/SD_EVENT_FINISHED.html: man/sd_event_wait.html
- $(html-alias)
-
-man/SD_EVENT_INITIAL.html: man/sd_event_wait.html
- $(html-alias)
-
-man/SD_EVENT_OFF.html: man/sd_event_source_set_enabled.html
- $(html-alias)
-
-man/SD_EVENT_ON.html: man/sd_event_source_set_enabled.html
- $(html-alias)
-
-man/SD_EVENT_ONESHOT.html: man/sd_event_source_set_enabled.html
- $(html-alias)
-
-man/SD_EVENT_PENDING.html: man/sd_event_wait.html
- $(html-alias)
-
-man/SD_EVENT_PREPARING.html: man/sd_event_wait.html
- $(html-alias)
-
-man/SD_EVENT_PRIORITY_IDLE.html: man/sd_event_source_set_priority.html
- $(html-alias)
-
-man/SD_EVENT_PRIORITY_IMPORTANT.html: man/sd_event_source_set_priority.html
- $(html-alias)
-
-man/SD_EVENT_PRIORITY_NORMAL.html: man/sd_event_source_set_priority.html
- $(html-alias)
-
-man/SD_EVENT_RUNNING.html: man/sd_event_wait.html
- $(html-alias)
-
-man/SD_LISTEN_FDS_START.html: man/sd_listen_fds.html
- $(html-alias)
-
-man/sd_bus_creds_get_audit_login_uid.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_audit_session_id.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_augmented_mask.html: man/sd_bus_creds_new_from_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_cgroup.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_cmdline.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_comm.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_description.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_egid.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_euid.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_exe.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_fsgid.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_fsuid.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_gid.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_mask.html: man/sd_bus_creds_new_from_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_owner_uid.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_ppid.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_selinux_context.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_session.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_sgid.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_suid.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_supplementary_gids.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_tid.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_tid_comm.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_tty.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_uid.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_unique_name.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_get_well_known_names.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_has_bounding_cap.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_has_effective_cap.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_has_inheritable_cap.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_has_permitted_cap.html: man/sd_bus_creds_get_pid.html
- $(html-alias)
-
-man/sd_bus_creds_ref.html: man/sd_bus_creds_new_from_pid.html
- $(html-alias)
-
-man/sd_bus_creds_unref.html: man/sd_bus_creds_new_from_pid.html
- $(html-alias)
-
-man/sd_bus_creds_unrefp.html: man/sd_bus_creds_new_from_pid.html
- $(html-alias)
-
-man/sd_bus_default_system.html: man/sd_bus_default.html
- $(html-alias)
-
-man/sd_bus_default_user.html: man/sd_bus_default.html
- $(html-alias)
-
-man/sd_bus_error_copy.html: man/sd_bus_error.html
- $(html-alias)
-
-man/sd_bus_error_free.html: man/sd_bus_error.html
- $(html-alias)
-
-man/sd_bus_error_get_errno.html: man/sd_bus_error.html
- $(html-alias)
-
-man/sd_bus_error_has_name.html: man/sd_bus_error.html
- $(html-alias)
-
-man/sd_bus_error_is_set.html: man/sd_bus_error.html
- $(html-alias)
-
-man/sd_bus_error_map.html: man/sd_bus_error_add_map.html
- $(html-alias)
-
-man/sd_bus_error_set.html: man/sd_bus_error.html
- $(html-alias)
-
-man/sd_bus_error_set_const.html: man/sd_bus_error.html
- $(html-alias)
-
-man/sd_bus_error_set_errno.html: man/sd_bus_error.html
- $(html-alias)
-
-man/sd_bus_error_set_errnof.html: man/sd_bus_error.html
- $(html-alias)
-
-man/sd_bus_error_set_errnofv.html: man/sd_bus_error.html
- $(html-alias)
-
-man/sd_bus_error_setf.html: man/sd_bus_error.html
- $(html-alias)
-
-man/sd_bus_message_append_array_iovec.html: man/sd_bus_message_append_array.html
- $(html-alias)
-
-man/sd_bus_message_append_array_memfd.html: man/sd_bus_message_append_array.html
- $(html-alias)
-
-man/sd_bus_message_append_array_space.html: man/sd_bus_message_append_array.html
- $(html-alias)
-
-man/sd_bus_message_append_string_iovec.html: man/sd_bus_message_append_string_memfd.html
- $(html-alias)
-
-man/sd_bus_message_append_string_space.html: man/sd_bus_message_append_string_memfd.html
- $(html-alias)
-
-man/sd_bus_message_get_realtime_usec.html: man/sd_bus_message_get_monotonic_usec.html
- $(html-alias)
-
-man/sd_bus_message_get_reply_cookie.html: man/sd_bus_message_get_cookie.html
- $(html-alias)
-
-man/sd_bus_message_get_seqnum.html: man/sd_bus_message_get_monotonic_usec.html
- $(html-alias)
-
-man/sd_bus_negotiate_creds.html: man/sd_bus_negotiate_fds.html
- $(html-alias)
-
-man/sd_bus_negotiate_timestamp.html: man/sd_bus_negotiate_fds.html
- $(html-alias)
-
-man/sd_bus_open.html: man/sd_bus_default.html
- $(html-alias)
-
-man/sd_bus_open_system.html: man/sd_bus_default.html
- $(html-alias)
-
-man/sd_bus_open_system_machine.html: man/sd_bus_default.html
- $(html-alias)
-
-man/sd_bus_open_system_remote.html: man/sd_bus_default.html
- $(html-alias)
-
-man/sd_bus_open_user.html: man/sd_bus_default.html
- $(html-alias)
-
-man/sd_bus_path_decode.html: man/sd_bus_path_encode.html
- $(html-alias)
-
-man/sd_bus_path_decode_many.html: man/sd_bus_path_encode.html
- $(html-alias)
-
-man/sd_bus_path_encode_many.html: man/sd_bus_path_encode.html
- $(html-alias)
-
-man/sd_bus_ref.html: man/sd_bus_new.html
- $(html-alias)
-
-man/sd_bus_release_name.html: man/sd_bus_request_name.html
- $(html-alias)
-
-man/sd_bus_track_add_sender.html: man/sd_bus_track_add_name.html
- $(html-alias)
-
-man/sd_bus_track_contains.html: man/sd_bus_track_add_name.html
- $(html-alias)
-
-man/sd_bus_track_count.html: man/sd_bus_track_add_name.html
- $(html-alias)
-
-man/sd_bus_track_count_name.html: man/sd_bus_track_add_name.html
- $(html-alias)
-
-man/sd_bus_track_count_sender.html: man/sd_bus_track_add_name.html
- $(html-alias)
-
-man/sd_bus_track_first.html: man/sd_bus_track_add_name.html
- $(html-alias)
-
-man/sd_bus_track_get_bus.html: man/sd_bus_track_new.html
- $(html-alias)
-
-man/sd_bus_track_get_recursive.html: man/sd_bus_track_new.html
- $(html-alias)
-
-man/sd_bus_track_get_userdata.html: man/sd_bus_track_new.html
- $(html-alias)
-
-man/sd_bus_track_next.html: man/sd_bus_track_add_name.html
- $(html-alias)
-
-man/sd_bus_track_ref.html: man/sd_bus_track_new.html
- $(html-alias)
-
-man/sd_bus_track_remove_name.html: man/sd_bus_track_add_name.html
- $(html-alias)
-
-man/sd_bus_track_remove_sender.html: man/sd_bus_track_add_name.html
- $(html-alias)
-
-man/sd_bus_track_set_recursive.html: man/sd_bus_track_new.html
- $(html-alias)
-
-man/sd_bus_track_set_userdata.html: man/sd_bus_track_new.html
- $(html-alias)
-
-man/sd_bus_track_unref.html: man/sd_bus_track_new.html
- $(html-alias)
-
-man/sd_bus_track_unrefp.html: man/sd_bus_track_new.html
- $(html-alias)
-
-man/sd_bus_unref.html: man/sd_bus_new.html
- $(html-alias)
-
-man/sd_bus_unrefp.html: man/sd_bus_new.html
- $(html-alias)
-
-man/sd_event.html: man/sd_event_new.html
- $(html-alias)
-
-man/sd_event_add_exit.html: man/sd_event_add_defer.html
- $(html-alias)
-
-man/sd_event_add_post.html: man/sd_event_add_defer.html
- $(html-alias)
-
-man/sd_event_child_handler_t.html: man/sd_event_add_child.html
- $(html-alias)
-
-man/sd_event_default.html: man/sd_event_new.html
- $(html-alias)
-
-man/sd_event_dispatch.html: man/sd_event_wait.html
- $(html-alias)
-
-man/sd_event_get_exit_code.html: man/sd_event_exit.html
- $(html-alias)
-
-man/sd_event_get_state.html: man/sd_event_wait.html
- $(html-alias)
-
-man/sd_event_get_tid.html: man/sd_event_new.html
- $(html-alias)
-
-man/sd_event_get_watchdog.html: man/sd_event_set_watchdog.html
- $(html-alias)
-
-man/sd_event_handler_t.html: man/sd_event_add_defer.html
- $(html-alias)
-
-man/sd_event_io_handler_t.html: man/sd_event_add_io.html
- $(html-alias)
-
-man/sd_event_loop.html: man/sd_event_run.html
- $(html-alias)
-
-man/sd_event_prepare.html: man/sd_event_wait.html
- $(html-alias)
-
-man/sd_event_ref.html: man/sd_event_new.html
- $(html-alias)
-
-man/sd_event_signal_handler_t.html: man/sd_event_add_signal.html
- $(html-alias)
-
-man/sd_event_source.html: man/sd_event_add_io.html
- $(html-alias)
-
-man/sd_event_source_get_child_pid.html: man/sd_event_add_child.html
- $(html-alias)
-
-man/sd_event_source_get_description.html: man/sd_event_source_set_description.html
- $(html-alias)
-
-man/sd_event_source_get_enabled.html: man/sd_event_source_set_enabled.html
- $(html-alias)
-
-man/sd_event_source_get_io_events.html: man/sd_event_add_io.html
- $(html-alias)
-
-man/sd_event_source_get_io_fd.html: man/sd_event_add_io.html
- $(html-alias)
-
-man/sd_event_source_get_io_revents.html: man/sd_event_add_io.html
- $(html-alias)
-
-man/sd_event_source_get_priority.html: man/sd_event_source_set_priority.html
- $(html-alias)
-
-man/sd_event_source_get_signal.html: man/sd_event_add_signal.html
- $(html-alias)
-
-man/sd_event_source_get_time.html: man/sd_event_add_time.html
- $(html-alias)
-
-man/sd_event_source_get_time_accuracy.html: man/sd_event_add_time.html
- $(html-alias)
-
-man/sd_event_source_get_time_clock.html: man/sd_event_add_time.html
- $(html-alias)
-
-man/sd_event_source_get_userdata.html: man/sd_event_source_set_userdata.html
- $(html-alias)
-
-man/sd_event_source_ref.html: man/sd_event_source_unref.html
- $(html-alias)
-
-man/sd_event_source_set_io_events.html: man/sd_event_add_io.html
- $(html-alias)
-
-man/sd_event_source_set_io_fd.html: man/sd_event_add_io.html
- $(html-alias)
-
-man/sd_event_source_set_time.html: man/sd_event_add_time.html
- $(html-alias)
-
-man/sd_event_source_set_time_accuracy.html: man/sd_event_add_time.html
- $(html-alias)
-
-man/sd_event_source_unrefp.html: man/sd_event_source_unref.html
- $(html-alias)
-
-man/sd_event_time_handler_t.html: man/sd_event_add_time.html
- $(html-alias)
-
-man/sd_event_unref.html: man/sd_event_new.html
- $(html-alias)
-
-man/sd_event_unrefp.html: man/sd_event_new.html
- $(html-alias)
-
-man/sd_id128_from_string.html: man/sd_id128_to_string.html
- $(html-alias)
-
-man/sd_id128_get_boot.html: man/sd_id128_get_machine.html
- $(html-alias)
-
-man/sd_id128_get_invocation.html: man/sd_id128_get_machine.html
- $(html-alias)
-
-man/sd_id128_get_machine_app_specific.html: man/sd_id128_get_machine.html
- $(html-alias)
-
-man/sd_is_socket.html: man/sd_is_fifo.html
- $(html-alias)
-
-man/sd_is_socket_inet.html: man/sd_is_fifo.html
- $(html-alias)
-
-man/sd_is_socket_unix.html: man/sd_is_fifo.html
- $(html-alias)
-
-man/sd_is_special.html: man/sd_is_fifo.html
- $(html-alias)
-
-man/sd_listen_fds_with_names.html: man/sd_listen_fds.html
- $(html-alias)
-
-man/sd_machine_get_ifindices.html: man/sd_machine_get_class.html
- $(html-alias)
-
-man/sd_notifyf.html: man/sd_notify.html
- $(html-alias)
-
-man/sd_pid_notify.html: man/sd_notify.html
- $(html-alias)
-
-man/sd_pid_notify_with_fds.html: man/sd_notify.html
- $(html-alias)
-
-man/sd_pid_notifyf.html: man/sd_notify.html
- $(html-alias)
-
-
-if HAVE_PAM
-MANPAGES += \
- man/pam_elogind.8 \
- man/sd_get_seats.3 \
- man/sd_login_monitor_new.3 \
- man/sd_pid_get_session.3 \
- man/sd_seat_get_active.3 \
- man/sd_session_is_active.3 \
- man/sd_uid_get_state.3
-MANPAGES_ALIAS += \
- man/sd_get_machine_names.3 \
- man/sd_get_sessions.3 \
- man/sd_get_uids.3 \
- man/sd_login_monitor.3 \
- man/sd_login_monitor_flush.3 \
- man/sd_login_monitor_get_events.3 \
- man/sd_login_monitor_get_fd.3 \
- man/sd_login_monitor_get_timeout.3 \
- man/sd_login_monitor_unref.3 \
- man/sd_login_monitor_unrefp.3 \
- man/sd_peer_get_cgroup.3 \
- man/sd_peer_get_machine_name.3 \
- man/sd_peer_get_owner_uid.3 \
- man/sd_peer_get_session.3 \
- man/sd_pid_get_cgroup.3 \
- man/sd_pid_get_machine_name.3 \
- man/sd_pid_get_owner_uid.3 \
- man/sd_seat_can_graphical.3 \
- man/sd_seat_can_multi_session.3 \
- man/sd_seat_can_tty.3 \
- man/sd_seat_get_sessions.3 \
- man/sd_session_get_class.3 \
- man/sd_session_get_desktop.3 \
- man/sd_session_get_display.3 \
- man/sd_session_get_remote_host.3 \
- man/sd_session_get_remote_user.3 \
- man/sd_session_get_seat.3 \
- man/sd_session_get_service.3 \
- man/sd_session_get_state.3 \
- man/sd_session_get_tty.3 \
- man/sd_session_get_type.3 \
- man/sd_session_get_uid.3 \
- man/sd_session_get_vt.3 \
- man/sd_session_is_remote.3 \
- man/sd_uid_get_display.3 \
- man/sd_uid_get_seats.3 \
- man/sd_uid_get_sessions.3 \
- man/sd_uid_is_on_seat.3
-man/sd_get_machine_names.3: man/sd_get_seats.3
-man/sd_get_sessions.3: man/sd_get_seats.3
-man/sd_get_uids.3: man/sd_get_seats.3
-man/sd_login_monitor.3: man/sd_login_monitor_new.3
-man/sd_login_monitor_flush.3: man/sd_login_monitor_new.3
-man/sd_login_monitor_get_events.3: man/sd_login_monitor_new.3
-man/sd_login_monitor_get_fd.3: man/sd_login_monitor_new.3
-man/sd_login_monitor_get_timeout.3: man/sd_login_monitor_new.3
-man/sd_login_monitor_unref.3: man/sd_login_monitor_new.3
-man/sd_login_monitor_unrefp.3: man/sd_login_monitor_new.3
-man/sd_peer_get_cgroup.3: man/sd_pid_get_session.3
-man/sd_peer_get_machine_name.3: man/sd_pid_get_session.3
-man/sd_peer_get_owner_uid.3: man/sd_pid_get_session.3
-man/sd_peer_get_session.3: man/sd_pid_get_session.3
-man/sd_pid_get_cgroup.3: man/sd_pid_get_session.3
-man/sd_pid_get_machine_name.3: man/sd_pid_get_session.3
-man/sd_pid_get_owner_uid.3: man/sd_pid_get_session.3
-man/sd_seat_can_graphical.3: man/sd_seat_get_active.3
-man/sd_seat_can_multi_session.3: man/sd_seat_get_active.3
-man/sd_seat_can_tty.3: man/sd_seat_get_active.3
-man/sd_seat_get_sessions.3: man/sd_seat_get_active.3
-man/sd_session_get_class.3: man/sd_session_is_active.3
-man/sd_session_get_desktop.3: man/sd_session_is_active.3
-man/sd_session_get_display.3: man/sd_session_is_active.3
-man/sd_session_get_remote_host.3: man/sd_session_is_active.3
-man/sd_session_get_remote_user.3: man/sd_session_is_active.3
-man/sd_session_get_seat.3: man/sd_session_is_active.3
-man/sd_session_get_service.3: man/sd_session_is_active.3
-man/sd_session_get_state.3: man/sd_session_is_active.3
-man/sd_session_get_tty.3: man/sd_session_is_active.3
-man/sd_session_get_type.3: man/sd_session_is_active.3
-man/sd_session_get_uid.3: man/sd_session_is_active.3
-man/sd_session_get_vt.3: man/sd_session_is_active.3
-man/sd_session_is_remote.3: man/sd_session_is_active.3
-man/sd_uid_get_display.3: man/sd_uid_get_state.3
-man/sd_uid_get_seats.3: man/sd_uid_get_state.3
-man/sd_uid_get_sessions.3: man/sd_uid_get_state.3
-man/sd_uid_is_on_seat.3: man/sd_uid_get_state.3
-man/sd_get_machine_names.html: man/sd_get_seats.html
- $(html-alias)
-
-man/sd_get_sessions.html: man/sd_get_seats.html
- $(html-alias)
-
-man/sd_get_uids.html: man/sd_get_seats.html
- $(html-alias)
-
-man/sd_login_monitor.html: man/sd_login_monitor_new.html
- $(html-alias)
-
-man/sd_login_monitor_flush.html: man/sd_login_monitor_new.html
- $(html-alias)
-
-man/sd_login_monitor_get_events.html: man/sd_login_monitor_new.html
- $(html-alias)
-
-man/sd_login_monitor_get_fd.html: man/sd_login_monitor_new.html
- $(html-alias)
-
-man/sd_login_monitor_get_timeout.html: man/sd_login_monitor_new.html
- $(html-alias)
-
-man/sd_login_monitor_unref.html: man/sd_login_monitor_new.html
- $(html-alias)
-
-man/sd_login_monitor_unrefp.html: man/sd_login_monitor_new.html
- $(html-alias)
-
-man/sd_peer_get_cgroup.html: man/sd_pid_get_session.html
- $(html-alias)
-
-man/sd_peer_get_machine_name.html: man/sd_pid_get_session.html
- $(html-alias)
-
-man/sd_peer_get_owner_uid.html: man/sd_pid_get_session.html
- $(html-alias)
-
-man/sd_peer_get_session.html: man/sd_pid_get_session.html
- $(html-alias)
-
-man/sd_pid_get_cgroup.html: man/sd_pid_get_session.html
- $(html-alias)
-
-man/sd_pid_get_machine_name.html: man/sd_pid_get_session.html
- $(html-alias)
-
-man/sd_pid_get_owner_uid.html: man/sd_pid_get_session.html
- $(html-alias)
-
-man/sd_seat_can_graphical.html: man/sd_seat_get_active.html
- $(html-alias)
-
-man/sd_seat_can_multi_session.html: man/sd_seat_get_active.html
- $(html-alias)
-
-man/sd_seat_can_tty.html: man/sd_seat_get_active.html
- $(html-alias)
-
-man/sd_seat_get_sessions.html: man/sd_seat_get_active.html
- $(html-alias)
-
-man/sd_session_get_class.html: man/sd_session_is_active.html
- $(html-alias)
-
-man/sd_session_get_desktop.html: man/sd_session_is_active.html
- $(html-alias)
-
-man/sd_session_get_display.html: man/sd_session_is_active.html
- $(html-alias)
-
-man/sd_session_get_remote_host.html: man/sd_session_is_active.html
- $(html-alias)
-
-man/sd_session_get_remote_user.html: man/sd_session_is_active.html
- $(html-alias)
-
-man/sd_session_get_seat.html: man/sd_session_is_active.html
- $(html-alias)
-
-man/sd_session_get_service.html: man/sd_session_is_active.html
- $(html-alias)
-
-man/sd_session_get_state.html: man/sd_session_is_active.html
- $(html-alias)
-
-man/sd_session_get_tty.html: man/sd_session_is_active.html
- $(html-alias)
-
-man/sd_session_get_type.html: man/sd_session_is_active.html
- $(html-alias)
-
-man/sd_session_get_uid.html: man/sd_session_is_active.html
- $(html-alias)
-
-man/sd_session_get_vt.html: man/sd_session_is_active.html
- $(html-alias)
-
-man/sd_session_is_remote.html: man/sd_session_is_active.html
- $(html-alias)
-
-man/sd_uid_get_display.html: man/sd_uid_get_state.html
- $(html-alias)
-
-man/sd_uid_get_seats.html: man/sd_uid_get_state.html
- $(html-alias)
-
-man/sd_uid_get_sessions.html: man/sd_uid_get_state.html
- $(html-alias)
-
-man/sd_uid_is_on_seat.html: man/sd_uid_get_state.html
- $(html-alias)
-
-endif
-
-if HAVE_PYTHON
-MANPAGES += \
- man/elogind.directives.7 \
- man/elogind.index.7
-MANPAGES_ALIAS += \
- #
-
-
-endif
-
-# Really, do not edit this file.
-
-EXTRA_DIST += \
- man/elogind.xml \
- man/less-variables.xml \
- man/libelogind-pkgconfig.xml \
- man/loginctl.xml \
- man/logind.conf.xml \
- man/pam_elogind.xml \
- man/sd-bus.xml \
- man/sd-event.xml \
- man/sd_booted.xml \
- man/sd_bus_add_match.xml \
- man/sd_bus_creds_get_pid.xml \
- man/sd_bus_creds_new_from_pid.xml \
- man/sd_bus_default.xml \
- man/sd_bus_error.xml \
- man/sd_bus_error_add_map.xml \
- man/sd_bus_get_fd.xml \
- man/sd_bus_message_append.xml \
- man/sd_bus_message_append_array.xml \
- man/sd_bus_message_append_basic.xml \
- man/sd_bus_message_append_string_memfd.xml \
- man/sd_bus_message_append_strv.xml \
- man/sd_bus_message_get_cookie.xml \
- man/sd_bus_message_get_monotonic_usec.xml \
- man/sd_bus_message_read_basic.xml \
- man/sd_bus_negotiate_fds.xml \
- man/sd_bus_new.xml \
- man/sd_bus_path_encode.xml \
- man/sd_bus_process.xml \
- man/sd_bus_request_name.xml \
- man/sd_bus_track_add_name.xml \
- man/sd_bus_track_new.xml \
- man/sd_event_add_child.xml \
- man/sd_event_add_defer.xml \
- man/sd_event_add_io.xml \
- man/sd_event_add_signal.xml \
- man/sd_event_add_time.xml \
- man/sd_event_exit.xml \
- man/sd_event_get_fd.xml \
- man/sd_event_new.xml \
- man/sd_event_now.xml \
- man/sd_event_run.xml \
- man/sd_event_set_watchdog.xml \
- man/sd_event_source_get_event.xml \
- man/sd_event_source_get_pending.xml \
- man/sd_event_source_set_description.xml \
- man/sd_event_source_set_enabled.xml \
- man/sd_event_source_set_prepare.xml \
- man/sd_event_source_set_priority.xml \
- man/sd_event_source_set_userdata.xml \
- man/sd_event_source_unref.xml \
- man/sd_event_wait.xml \
- man/sd_get_seats.xml \
- man/sd_id128_get_machine.xml \
- man/sd_id128_randomize.xml \
- man/sd_id128_to_string.xml \
- man/sd_is_fifo.xml \
- man/sd_listen_fds.xml \
- man/sd_login_monitor_new.xml \
- man/sd_machine_get_class.xml \
- man/sd_notify.xml \
- man/sd_pid_get_session.xml \
- man/sd_seat_get_active.xml \
- man/sd_session_is_active.xml \
- man/sd_uid_get_state.xml \
- man/sd_watchdog_enabled.xml \
- man/standard-conf.xml \
- man/standard-options.xml \
- man/user-system-options.xml
diff --git a/Makefile.am b/Makefile.am
deleted file mode 100644
index 8cd0b6c72..000000000
--- a/Makefile.am
+++ /dev/null
@@ -1,1663 +0,0 @@
-# -*- Mode: makefile; indent-tabs-mode: t -*-
-#
-# This file is part of elogind.
-#
-# Copyright 2010-2012 Lennart Poettering
-# Copyright 2010-2012 Kay Sievers
-# Copyright 2013 Zbigniew Jędrzejewski-Szmek
-# Copyright 2013 David Strauss
-#
-# elogind is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# elogind is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with elogind; If not, see <http://www.gnu.org/licenses/>.
-
-ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
-AM_MAKEFLAGS = --no-print-directory
-AUTOMAKE_OPTIONS = color-tests parallel-tests
-
-GCC_COLORS ?= 'ooh, shiny!'
-export GCC_COLORS
-
-SUBDIRS = . po
-
-# remove targets if the command fails
-.DELETE_ON_ERROR:
-
-# keep intermediate files
-.SECONDARY:
-
-# Keep the test-suite.log
-.PRECIOUS: $(TEST_SUITE_LOG) Makefile
-
-LIBELOGIND_CURRENT=19
-LIBELOGIND_REVISION=4
-LIBELOGIND_AGE=19
-
-# Dirs of external packages
-dbuspolicydir=@dbuspolicydir@
-dbussystemservicedir=@dbussystemservicedir@
-pamlibdir=@pamlibdir@
-pamconfdir=@pamconfdir@
-pkgconfigdatadir=$(datadir)/pkgconfig
-pkgconfiglibdir=$(libdir)/pkgconfig
-polkitpolicydir=$(datadir)/polkit-1/actions
-polkitrulesdir=$(datadir)/polkit-1/rules.d
-polkitpkladir=$(localstatedir)/lib/polkit-1/localauthority/10-vendor.d
-bashcompletiondir=@bashcompletiondir@
-zshcompletiondir=@zshcompletiondir@
-
-CGROUP_CONTROLLER=@cgroup_controller@
-PKTTYAGENT=$(bindir)/pkttyagent
-
-# Our own, non-special dirs
-pkgsysconfdir=$(sysconfdir)/elogind
-pkgincludedir=$(includedir)/elogind/systemd
-udevrulesdir=@udevrulesdir@
-udevbindir=@udevbindir@
-udevlibexecdir=$(udevbindir)
-udevhomedir=$(udevlibexecdir)
-factory_pamdir = $(datadir)/factory/etc/pam.d
-
-# And these are the special ones for /
-
-rootprefix=@rootprefix@
-rootbindir=$(rootprefix)/bin
-rootlibdir=@rootlibdir@
-rootlibexecdir=@rootlibexecdir@
-systemshutdowndir=$(rootlibexecdir)/system-shutdown
-systemsleepdir=$(rootlibexecdir)/system-sleep
-
-EXTRA_DIST =
-BUILT_SOURCES =
-INSTALL_EXEC_HOOKS =
-UNINSTALL_EXEC_HOOKS =
-DISTCLEAN_LOCAL_HOOKS =
-CLEAN_LOCAL_HOOKS =
-pkginclude_HEADERS =
-noinst_LTLIBRARIES =
-lib_LTLIBRARIES =
-noinst_DATA =
-pkgconfiglib_DATA =
-polkitpolicy_in_files =
-polkitpolicy_files =
-polkitrules_files =
-polkitpkla_files =
-dist_udevrules_DATA =
-nodist_udevrules_DATA =
-dist_pkgsysconf_DATA =
-nodist_pkgsysconf_DATA =
-dist_dbuspolicy_DATA =
-dist_dbussystemservice_DATA =
-check_PROGRAMS =
-check_DATA =
-dist_rootlibexec_DATA =
-rootlib_LTLIBRARIES =
-tests=
-manual_tests =
-TEST_DATA_FILES =
-if ENABLE_TESTS
-noinst_PROGRAMS = $(manual_tests) $(tests) $(unsafe_tests)
-TESTS = $(tests)
-if ENABLE_UNSAFE_TESTS
-TESTS += \
- $(unsafe_tests)
-endif
-else
-noinst_PROGRAMS =
-TESTS =
-endif
-
-if ENABLE_BASH_COMPLETION
-dist_bashcompletion_DATA = $(dist_bashcompletion_data)
-endif
-if ENABLE_ZSH_COMPLETION
-dist_zshcompletion_DATA = $(dist_zshcompletion_data)
-endif
-
-in_files = $(filter %.in,$(EXTRA_DIST))
-in_in_files = $(filter %.in.in, $(in_files))
-m4_files = $(filter %.m4,$(EXTRA_DIST) $(in_files:.m4.in=.m4))
-
-CLEANFILES = $(BUILT_SOURCES) \
- $(pkgconfiglib_DATA) \
- $(in_files:.in=) $(in_in_files:.in.in=) \
- $(m4_files:.m4=)
-
-.PHONY: $(INSTALL_EXEC_HOOKS) $(UNINSTALL_EXEC_HOOKS) \
- $(DISTCLEAN_LOCAL_HOOKS) $(CLEAN_LOCAL_HOOKS)
-
-AM_CPPFLAGS = \
- -include $(top_builddir)/config.h \
- -DPKGSYSCONFDIR=\"$(pkgsysconfdir)\" \
- -DSYSTEMD_CGROUP_CONTROLLER=\"_$(CGROUP_CONTROLLER)\" \
- -DSYSTEMD_CGROUP_CONTROLLER_LEGACY=\"name=$(CGROUP_CONTROLLER)\" \
- -DSYSTEMD_CGROUP_CONTROLLER_HYBRID=\"name=$(CGROUP_CONTROLLER)\" \
- -DSYSTEMD_CGROUP_AGENT_PATH=\"$(rootlibexecdir)/elogind-cgroups-agent\" \
- -DSYSTEMD_BINARY_PATH=\"$(rootlibexecdir)/elogind\" \
- -DUDEVLIBEXECDIR=\"$(udevlibexecdir)\" \
- -DPOLKIT_AGENT_BINARY_PATH=\"$(PKTTYAGENT)\" \
- -DSYSTEM_SLEEP_PATH=\"$(systemsleepdir)\" \
- -DSYSTEM_SHUTDOWN_PATH=\"$(systemshutdowndir)\" \
- -DHALT=\"$(HALT)\" \
- -DREBOOT=\"$(REBOOT)\" \
- -DKEXEC=\"$(KEXEC)\" \
- -DLIBDIR=\"$(libdir)\" \
- -DROOTLIBDIR=\"$(rootlibdir)\" \
- -DROOTLIBEXECDIR=\"$(rootlibexecdir)\" \
- -DTEST_DIR=\"$(abs_top_srcdir)/test\" \
- -I $(top_srcdir)/src \
- -I $(top_builddir)/src/basic \
- -I $(top_srcdir)/src/basic \
- -I $(top_srcdir)/src/core \
- -I $(top_srcdir)/src/shared \
- -I $(top_builddir)/src/shared \
- -I $(top_srcdir)/src/login \
- -I $(top_srcdir)/src/systemd \
- -I $(top_srcdir)/src/libelogind/sd-bus \
- -I $(top_srcdir)/src/libelogind/sd-event \
- -I $(top_srcdir)/src/libelogind/sd-login \
- -I $(top_srcdir)/src/libelogind/sd-id128 \
- -I $(top_srcdir)/src/update-utmp \
- -I $(top_srcdir)/src/sleep \
- -DABS_SRC_DIR=\"$(abs_top_srcdir)\" \
- -DABS_BUILD_DIR=\"$(abs_top_builddir)\" \
- $(OUR_CPPFLAGS)
-
-AM_CFLAGS = $(OUR_CFLAGS)
-AM_LDFLAGS = $(OUR_LDFLAGS)
-
-# ------------------------------------------------------------------------------
-install-touch-usr-hook:
- touch -c $(DESTDIR)/$(prefix)
-
-INSTALL_EXEC_HOOKS += \
- install-touch-usr-hook
-
-
-# ------------------------------------------------------------------------------
-AM_V_M4 = $(AM_V_M4_$(V))
-AM_V_M4_ = $(AM_V_M4_$(AM_DEFAULT_VERBOSITY))
-AM_V_M4_0 = @echo " M4 " $@;
-
-AM_V_XSLT = $(AM_V_XSLT_$(V))
-AM_V_XSLT_ = $(AM_V_XSLT_$(AM_DEFAULT_VERBOSITY))
-AM_V_XSLT_0 = @echo " XSLT " $@;
-
-AM_V_GPERF = $(AM_V_GPERF_$(V))
-AM_V_GPERF_ = $(AM_V_GPERF_$(AM_DEFAULT_VERBOSITY))
-AM_V_GPERF_0 = @echo " GPERF " $@;
-
-AM_V_LN = $(AM_V_LN_$(V))
-AM_V_LN_ = $(AM_V_LN_$(AM_DEFAULT_VERBOSITY))
-AM_V_LN_0 = @echo " LN " $@;
-
-AM_V_RM = $(AM_V_RM_$(V))
-AM_V_RM_ = $(AM_V_RM_$(AM_DEFAULT_VERBOSITY))
-AM_V_RM_0 = @echo " RM " $@;
-
-# ------------------------------------------------------------------------------
-rootbin_PROGRAMS =
-rootlibexec_PROGRAMS =
-
-dist_doc_DATA = \
- README \
- NEWS \
- LICENSE.LGPL2.1 \
- LICENSE.GPL2
-
-@INTLTOOL_POLICY_RULE@
-
-# ------------------------------------------------------------------------------
-
-MANPAGES =
-MANPAGES_ALIAS =
-
-include Makefile-man.am
-
-.PHONY: man update-man-list
-man: $(MANPAGES) $(MANPAGES_ALIAS) $(HTML_FILES) $(HTML_ALIAS)
-
-XML_FILES = \
- ${patsubst %.1,%.xml,${patsubst %.3,%.xml,${patsubst %.5,%.xml,${patsubst %.7,%.xml,${patsubst %.8,%.xml,$(MANPAGES)}}}}}
-HTML_FILES = \
- ${XML_FILES:.xml=.html}
-HTML_ALIAS = \
- ${patsubst %.1,%.html,${patsubst %.3,%.html,${patsubst %.5,%.html,${patsubst %.7,%.html,${patsubst %.8,%.html,$(MANPAGES_ALIAS)}}}}}
-
-if ENABLE_MANPAGES
-man_MANS = \
- $(MANPAGES) \
- $(MANPAGES_ALIAS)
-
-noinst_DATA += \
- $(HTML_FILES) \
- $(HTML_ALIAS) \
- docs/html/man
-endif
-
-CLEANFILES += \
- $(man_MANS) \
- $(HTML_FILES) \
- $(HTML_ALIAS) \
- docs/html/man
-
-docs/html/man:
- $(AM_V_at)$(MKDIR_P) $(dir $@)
- $(AM_V_LN)$(LN_S) -f ../../man $@
-
-man/index.html: man/elogind.index.html
- $(AM_V_LN)$(LN_S) -f elogind.index.html $@
-
-if HAVE_PYTHON
-if ENABLE_MANPAGES
-noinst_DATA += \
- man/index.html
-endif
-endif
-
-CLEANFILES += \
- man/index.html
-
-XML_GLOB := $(wildcard $(top_srcdir)/man/*.xml)
-DIRECTIVE_FILE := man/elogind.directives.xml
-INDEX_XML_FILE := man/elogind.index.xml
-NON_INDEX_XML_FILES := $(DIRECTIVE_FILE) $(filter-out $(INDEX_XML_FILE) $(DIRECTIVE_FILE),$(XML_FILES))
-ALL_XML_FILES := $(INDEX_XML_FILE) $(DIRECTIVE_FILE) $(filter-out $(INDEX_XML_FILE) $(DIRECTIVE_FILE),$(XML_GLOB))
-SOURCE_XML_FILES := ${patsubst %,$(top_srcdir)/%,$(filter-out $(DIRECTIVE_FILE),$(NON_INDEX_XML_FILES))}
-
-# This target should only be run manually. It recreates Makefile-man.am
-# file in the source directory based on all man/*.xml files. Run it after
-# adding, removing, or changing the conditional in a man page.
-update-man-list: $(top_srcdir)/tools/make-man-rules.py $(ALL_XML_FILES) man/custom-entities.ent
- $(AM_V_GEN)$(PYTHON) $< $(ALL_XML_FILES) > $(top_srcdir)/Makefile-man.tmp
- $(AM_V_at)mv $(top_srcdir)/Makefile-man.tmp $(top_srcdir)/Makefile-man.am
- @echo "Makefile-man.am has been regenerated"
-
-$(INDEX_XML_FILE): $(top_srcdir)/tools/make-man-index.py $(NON_INDEX_XML_FILES)
- $(AM_V_at)$(MKDIR_P) $(dir $@)
- $(AM_V_GEN)$(PYTHON) $< $@ $(filter-out $<,$^)
-
-$(DIRECTIVE_FILE): $(top_srcdir)/tools/make-directive-index.py man/custom-entities.ent $(SOURCE_XML_FILES)
- $(AM_V_at)$(MKDIR_P) $(dir $@)
- $(AM_V_GEN)$(PYTHON) $< $@ $(SOURCE_XML_FILES)
-
-CLEANFILES += \
- $(INDEX_XML_FILE) \
- $(DIRECTIVE_FILE)
-
-EXTRA_DIST += \
- $(filter-out $(DIRECTIVE_FILE) $(INDEX_XML_FILE),$(XML_FILES)) \
- tools/make-man-index.py \
- tools/make-man-rules.py \
- tools/make-directive-index.py \
- tools/xml_helper.py \
- man/glib-event-glue.c
-
-# ------------------------------------------------------------------------------
-noinst_LTLIBRARIES += \
- libbasic.la
-
-libbasic_la_SOURCES = \
- src/basic/missing.h \
- src/basic/capability-util.c \
- src/basic/capability-util.h \
- src/basic/conf-files.c \
- src/basic/conf-files.h \
- src/basic/stdio-util.h \
- src/basic/hostname-util.h \
- src/basic/hostname-util.c \
- src/basic/unit-name.c \
- src/basic/unit-name.h \
- src/basic/unaligned.h \
- src/basic/util.c \
- src/basic/util.h \
- src/basic/io-util.c \
- src/basic/io-util.h \
- src/basic/string-util.c \
- src/basic/string-util.h \
- src/basic/parse-util.c \
- src/basic/parse-util.h \
- src/basic/fd-util.c \
- src/basic/fd-util.h \
- src/basic/user-util.c \
- src/basic/user-util.h \
- src/basic/dirent-util.c \
- src/basic/dirent-util.h \
- src/basic/xattr-util.c \
- src/basic/xattr-util.h \
- src/basic/proc-cmdline.c \
- src/basic/proc-cmdline.h \
- src/basic/fs-util.c \
- src/basic/fs-util.h \
- src/basic/syslog-util.c \
- src/basic/syslog-util.h \
- src/basic/stat-util.c \
- src/basic/stat-util.h \
- src/basic/mount-util.c \
- src/basic/mount-util.h \
- src/basic/hexdecoct.c \
- src/basic/hexdecoct.h \
- src/basic/extract-word.c \
- src/basic/extract-word.h \
- src/basic/escape.c \
- src/basic/escape.h \
- src/basic/path-util.c \
- src/basic/path-util.h \
- src/basic/parse-printf-format.c \
- src/basic/parse-printf-format.h \
- src/basic/time-util.c \
- src/basic/time-util.h \
- src/basic/locale-util.c \
- src/basic/locale-util.h \
- src/basic/umask-util.h \
- src/basic/signal-util.c \
- src/basic/signal-util.h \
- src/basic/string-table.c \
- src/basic/string-table.h \
- src/basic/mempool.c \
- src/basic/mempool.h \
- src/basic/hashmap.c \
- src/basic/hashmap.h \
- src/basic/hash-funcs.c \
- src/basic/hash-funcs.h \
- src/basic/siphash24.c \
- src/basic/siphash24.h \
- src/basic/prioq.c \
- src/basic/prioq.h \
- src/basic/strv.c \
- src/basic/strv.h \
- src/basic/env-util.c \
- src/basic/env-util.h \
- src/basic/log.c \
- src/basic/log.h \
- src/basic/bus-label.c \
- src/basic/bus-label.h \
- src/basic/exec-util.c \
- src/basic/exec-util.h \
- src/basic/virt.c \
- src/basic/virt.h \
- src/basic/smack-util.c \
- src/basic/smack-util.h \
- src/basic/utf8.c \
- src/basic/utf8.h \
- src/basic/gunicode.c \
- src/basic/gunicode.h \
- src/basic/socket-util.c \
- src/basic/socket-util.h \
- src/basic/fileio.c \
- src/basic/fileio.h \
- src/basic/mkdir.c \
- src/basic/mkdir.h \
- src/basic/cgroup-util.c \
- src/basic/cgroup-util.h \
- src/basic/errno-list.c \
- src/basic/errno-list.h \
- src/basic/terminal-util.c \
- src/basic/terminal-util.h \
- src/basic/login-util.h \
- src/basic/login-util.c \
- src/basic/audit-util.c \
- src/basic/audit-util.h \
- src/basic/memfd-util.c \
- src/basic/memfd-util.h \
- src/basic/process-util.c \
- src/basic/process-util.h \
- src/basic/random-util.c \
- src/basic/random-util.h \
- src/basic/verbs.c \
- src/basic/verbs.h \
- src/basic/label.c \
- src/basic/label.h \
- src/basic/selinux-util.c \
- src/basic/selinux-util.h \
- src/basic/mkdir-label.c \
- src/basic/fileio-label.c \
- src/basic/fileio-label.h \
- src/basic/rm-rf.c \
- src/basic/rm-rf.h \
- src/basic/copy.c \
- src/basic/copy.h \
- src/basic/alloc-util.h \
- src/basic/alloc-util.c \
- src/basic/format-util.h \
- src/basic/khash.h \
- src/basic/khash.c
-
-nodist_libbasic_la_SOURCES = \
- src/basic/errno-from-name.h \
- src/basic/errno-to-name.h
-
-libbasic_la_CFLAGS = \
- $(AM_CFLAGS) \
- $(SELINUX_CFLAGS) \
- $(CAP_CFLAGS) \
- -pthread
-
-libbasic_la_LDFLAGS = \
- $(CAP_LDFLAGS)
-
-libbasic_la_LIBADD = \
- $(SELINUX_LIBS) \
- $(CAP_LIBS) \
- -ldl \
- -lm
-
-# -----------------------------------------------------------------------------
-noinst_LTLIBRARIES += \
- libshared.la
-
-libshared_la_SOURCES = \
- src/shared/udev-util.h \
- src/shared/udev-util.c \
- src/shared/bus-util.c \
- src/shared/bus-util.h \
- src/shared/clean-ipc.c \
- src/shared/clean-ipc.h \
- src/shared/conf-parser.c \
- src/shared/conf-parser.h \
- src/shared/musl_missing.h \
- src/shared/musl_missing.c \
- src/shared/pager.c \
- src/shared/pager.h \
- src/shared/sleep-config.c \
- src/shared/sleep-config.h \
- src/shared/spawn-polkit-agent.c \
- src/shared/spawn-polkit-agent.h \
- src/shared/tests.h \
- src/shared/tests.c \
- src/shared/nsflags.h \
- src/shared/nsflags.c
-
-if HAVE_ACL
-libshared_la_SOURCES += \
- src/shared/acl-util.c \
- src/shared/acl-util.h
-endif
-
-libshared_la_CFLAGS = \
- $(AM_CFLAGS) \
- $(ACL_CFLAGS)
-
-libshared_la_LIBADD = \
- libelogind-internal.la \
- libbasic.la \
- $(UDEV_LIBS) \
- $(ACL_LIBS)
-
-noinst_LTLIBRARIES += \
- libelogind-shared.la
-
-libelogind_shared_la_SOURCES = \
- $(libbasic_la_SOURCES) \
- $(libshared_la_SOURCES) \
- $(libelogind_internal_la_SOURCES)
-
-libelogind_shared_la_CFLAGS = \
- $(AM_CFLAGS) \
- $(libbasic_la_CFLAGS) \
- $(libshared_la_CFLAGS) \
- $(libelogind_internal_la_CFLAGS) \
- $(libelogind_journal_internal_la_CFLAGS) \
- $(libudev_internal_la_CFLAGS) \
- $(ACL_CFLAGS) \
- $(SECCOMP_CFLAGS) \
- -fvisibility=default
-
-# We can't use libshared_la_LIBADD here because it would
-# pull in libelogind*-internal.la
-libelogind_shared_la_LIBADD = \
- $(libbasic_la_LIBADD) \
- $(libelogind_internal_la_LIBADD) \
- $(UDEV_LIBS) \
- $(ACL_LIBS) \
- $(SECCOMP_LIBS)
-
-libelogind_shared_la_LDFLAGS = \
- $(AM_LDFLAGS)
- # -----------------------------------------------------------------------------
-gperf_txt_sources = \
- src/basic/errno-list.txt
-
-BUILT_SOURCES += \
- $(gperf_gperf_m4_sources:-gperf.gperf.m4=-gperf.c) \
- $(gperf_gperf_sources:-gperf.gperf=-gperf.c) \
- $(gperf_txt_sources:-list.txt=-from-name.h) \
- $(gperf_txt_sources:-list.txt=-to-name.h)
-
-CLEANFILES += \
- $(gperf_txt_sources:-list.txt=-from-name.gperf)
-DISTCLEANFILES = \
- $(gperf_txt_sources)
-
-EXTRA_DIST += \
- $(gperf_gperf_m4_sources) \
- $(gperf_gperf_sources)
-
-CLEANFILES += \
- $(gperf_txt_sources)
-
-%-from-name.gperf: %-list.txt
- $(AM_V_at)$(MKDIR_P) $(dir $@)
- $(AM_V_GEN)$(AWK) 'BEGIN{ print "struct $(notdir $*)_name { const char* name; int id; };"; print "%null-strings"; print "%%";} { printf "%s, %s\n", $$1, $$1 }' <$< >$@
-
-%-from-name.h: %-from-name.gperf
- $(AM_V_at)$(MKDIR_P) $(dir $@)
- $(AM_V_GPERF)$(GPERF) -L ANSI-C -t --ignore-case -N lookup_$(notdir $*) -H hash_$(notdir $*)_name -p -C <$< >$@
-
-
-src/basic/errno-list.txt:
- $(AM_V_at)$(MKDIR_P) $(dir $@)
- $(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM -include errno.h - </dev/null | $(AWK) '/^#define[ \t]+E[^ _]+[ \t]+/ { print $$2; }' >$@
-
-src/basic/errno-to-name.h: src/basic/errno-list.txt
- $(AM_V_at)$(MKDIR_P) $(dir $@)
- $(AM_V_GEN)$(AWK) 'BEGIN{ print "static const char* const errno_names[] = { "} !/EDEADLOCK/ && !/EWOULDBLOCK/ && !/ENOTSUP/ { printf "[%s] = \"%s\",\n", $$1, $$1 } END{print "};"}' <$< >$@
-
-# ------------------------------------------------------------------------------
-
-manual_tests += \
- test-cgroup
-
-unsafe_tests = \
- test-ipcrm
-
-tests += \
- test-log \
- test-path-util \
- test-siphash24 \
- test-utf8 \
- test-ellipsize \
- test-util \
- test-exec-util \
- test-hexdecoct \
- test-escape \
- test-alloc-util \
- test-proc-cmdline \
- test-io-util \
- test-fs-util \
- test-stat-util \
- test-fd-util \
- test-string-util \
- test-extract-word \
- test-parse-util \
- test-user-util \
- test-process-util \
- test-strip-tab-ansi \
- test-prioq \
- test-hashmap \
- test-set \
- test-list \
- test-unaligned \
- test-conf-files \
- test-random-util \
- test-conf-parser \
- test-locale-util \
- test-copy \
- test-verbs \
- test-signal-util \
- test-selinux \
- test-sizeof
-
-TEST_DATA_FILES += \
- test/bus-policy/hello.conf \
- test/bus-policy/methods.conf \
- test/bus-policy/ownerships.conf \
- test/bus-policy/signals.conf \
- test/bus-policy/check-own-rules.conf \
- test/bus-policy/many-rules.conf \
- test/bus-policy/test.conf
-
-
-EXTRA_DIST += \
- src/test/test-helper.h
-
-test_utf8_SOURCES = \
- src/test/test-utf8.c
-
-test_utf8_LDADD = \
- libelogind-shared.la
-
-test_locale_util_SOURCES = \
- src/test/test-locale-util.c
-
-test_locale_util_LDADD = \
- libelogind-shared.la
-
-test_copy_SOURCES = \
- src/test/test-copy.c
-
-# Link statically to ensure file is large
-test_copy_LDADD = \
- libshared.la
-
-test_random_util_SOURCES = \
- src/test/test-random-util.c
-
-test_random_util_LDADD = \
- libelogind-shared.la
-
-test_util_SOURCES = \
- src/test/test-util.c
-
-test_util_LDADD = \
- libelogind-shared.la
-
-test_exec_util_SOURCES = \
- src/test/test-exec-util.c
-
-test_exec_util_LDADD = \
- libelogind-shared.la
-
-test_hexdecoct_SOURCES = \
- src/test/test-hexdecoct.c
-
-test_hexdecoct_LDADD = \
- libelogind-shared.la
-
-test_alloc_util_SOURCES = \
- src/test/test-alloc-util.c
-
-test_alloc_util_LDADD = \
- libelogind-shared.la
-
-test_io_util_SOURCES = \
- src/test/test-io-util.c
-
-test_io_util_LDADD = \
- libelogind-shared.la
-
-test_fs_util_SOURCES = \
- src/test/test-fs-util.c
-
-test_fs_util_LDADD = \
- libelogind-shared.la
-
-test_proc_cmdline_SOURCES = \
- src/test/test-proc-cmdline.c
-
-test_proc_cmdline_LDADD = \
- libelogind-shared.la
-
-test_fd_util_SOURCES = \
- src/test/test-fd-util.c
-
-test_fd_util_LDADD = \
- libelogind-shared.la
-
-test_stat_util_SOURCES = \
- src/test/test-stat-util.c
-
-test_stat_util_LDADD = \
- libelogind-shared.la
-
-test_escape_SOURCES = \
- src/test/test-escape.c
-
-test_escape_LDADD = \
- libelogind-shared.la
-
-test_string_util_SOURCES = \
- src/test/test-string-util.c
-
-test_string_util_LDADD = \
- libelogind-shared.la
-
-test_extract_word_SOURCES = \
- src/test/test-extract-word.c
-
-test_extract_word_LDADD = \
- libelogind-shared.la
-
-test_parse_util_SOURCES = \
- src/test/test-parse-util.c
-
-test_parse_util_LDADD = \
- libelogind-shared.la
-
-test_user_util_SOURCES = \
- src/test/test-user-util.c
-
-test_user_util_LDADD = \
- libelogind-shared.la
-
-test_process_util_SOURCES = \
- src/test/test-process-util.c
-
-test_process_util_LDADD = \
- libelogind-shared.la
-
-test_verbs_SOURCES = \
- src/test/test-verbs.c
-
-test_verbs_LDADD = \
- libelogind-shared.la
-
-test_signal_util_SOURCES = \
- src/test/test-signal-util.c
-
-test_signal_util_LDADD = \
- libelogind-shared.la
-
-test_selinux_SOURCES = \
- src/test/test-selinux.c
-
-test_selinux_LDADD = \
- libelogind-shared.la
-
-test_sizeof_SOURCES = \
- src/test/test-sizeof.c
-
-BUILT_SOURCES += \
- src/test/test-hashmap-ordered.c
-
-src/test/test-hashmap-ordered.c: src/test/test-hashmap-plain.c
- $(AM_V_at)$(MKDIR_P) $(dir $@)
- $(AM_V_GEN)$(AWK) 'BEGIN { print "/* GENERATED FILE */\n#define ORDERED" } \
- { if (!match($$0, "^#include")) \
- gsub(/hashmap/, "ordered_hashmap"); \
- gsub(/HASHMAP/, "ORDERED_HASHMAP"); \
- gsub(/Hashmap/, "OrderedHashmap"); \
- print }' <$< >$@
-
-nodist_test_hashmap_SOURCES = \
- src/test/test-hashmap-ordered.c
-
-test_hashmap_SOURCES = \
- src/test/test-hashmap.c \
- src/test/test-hashmap-plain.c
-
-test_hashmap_LDADD = \
- libelogind-shared.la
-
-test_set_SOURCES = \
- src/test/test-set.c
-
-test_set_LDADD = \
- libelogind-shared.la
-
-test_list_SOURCES = \
- src/test/test-list.c
-
-test_list_LDADD = \
- libelogind-shared.la
-
-test_unaligned_LDADD = \
- libelogind-shared.la
-
-test_unaligned_SOURCES = \
- src/test/test-unaligned.c
-
-test_prioq_SOURCES = \
- src/test/test-prioq.c
-
-test_prioq_LDADD = \
- libelogind-shared.la
-
-test_log_SOURCES = \
- src/test/test-log.c
-
-test_log_LDADD = \
- libelogind-shared.la
-
-test_ipcrm_SOURCES = \
- src/test/test-ipcrm.c
-
-test_ipcrm_LDADD = \
- libelogind-shared.la
-
-test_ellipsize_SOURCES = \
- src/test/test-ellipsize.c
-
-test_ellipsize_LDADD = \
- libelogind-shared.la
-
-test_strip_tab_ansi_SOURCES = \
- src/test/test-strip-tab-ansi.c
-
-test_strip_tab_ansi_LDADD = \
- libelogind-shared.la
-
-test_cgroup_SOURCES = \
- src/test/test-cgroup.c
-
-test_cgroup_LDADD = \
- libelogind-shared.la
-
-test_path_util_SOURCES = \
- src/test/test-path-util.c
-
-test_path_util_LDADD = \
- libelogind-shared.la
-
-test_siphash24_SOURCES = \
- src/test/test-siphash24.c
-
-test_siphash24_LDADD = \
- libelogind-shared.la
-
-test_conf_files_SOURCES = \
- src/test/test-conf-files.c
-
-test_conf_files_LDADD = \
- libelogind-shared.la
-
-test_conf_parser_SOURCES = \
- src/test/test-conf-parser.c
-
-test_conf_parser_LDADD = \
- libelogind-shared.la
-
-# ------------------------------------------------------------------------------
-## .PHONY so it always rebuilds it
-.PHONY: coverage lcov-run lcov-report coverage-sync
-
-# run lcov from scratch, always
-coverage: all
- $(MAKE) lcov-run
- $(MAKE) lcov-report
-
-coverage_dir = coverage
-coverage_opts = --base-directory $(srcdir) --directory $(builddir) --rc 'geninfo_adjust_src_path=$(abspath $(srcdir))=>$(abspath $(builddir))'
-
-if ENABLE_COVERAGE
-# reset run coverage tests
-lcov-run:
- @rm -rf $(coverage_dir)
- lcov $(coverage_opts) --zerocounters
- -$(MAKE) check
-
-# generate report based on current coverage data
-lcov-report:
- $(MKDIR_P) $(coverage_dir)
- lcov $(coverage_opts) --compat-libtool --capture --no-external \
- | sed 's|$(abspath $(builddir))|$(abspath $(srcdir))|' > $(coverage_dir)/.lcov.info
- lcov --remove $(coverage_dir)/.lcov.info --output-file $(coverage_dir)/.lcov-clean.info 'test-*'
- genhtml -t "systemd test coverage" -o $(coverage_dir) $(coverage_dir)/.lcov-clean.info
- @echo "Coverage report generated in $(abs_builddir)/$(coverage_dir)/index.html"
-
-# lcov doesn't work properly with vpath builds, make sure that bad
-# output is not uploaded by mistake.
-coverage-sync: coverage
- test "$(builddir)" = "$(srcdir)"
- rsync -rlv --delete --omit-dir-times coverage/ $(www_target)/coverage
-
-else
-lcov-run lcov-report:
- echo "Need to reconfigure with --enable-coverage"
-endif
-
-# ------------------------------------------------------------------------------
-
-if HAVE_PAM
-dist_factory_pam_DATA = \
- factory/etc/pam.d/system-auth \
- factory/etc/pam.d/other
-endif
-
-# ------------------------------------------------------------------------------
-rootlibexec_PROGRAMS += \
- elogind-cgroups-agent
-
-elogind_cgroups_agent_SOURCES = \
- src/cgroups-agent/cgroups-agent.c
-
-elogind_cgroups_agent_LDADD = \
- libelogind-shared.la
-
-# ------------------------------------------------------------------------------
-libelogind_internal_la_SOURCES = \
- src/systemd/sd-bus.h \
- src/systemd/sd-bus-protocol.h \
- src/systemd/sd-bus-vtable.h \
- src/systemd/sd-event.h \
- src/systemd/sd-login.h \
- src/systemd/sd-id128.h \
- src/systemd/sd-daemon.h \
- src/libelogind/libelogind.sym \
- src/libelogind/sd-bus/sd-bus.c \
- src/libelogind/sd-bus/bus-control.c \
- src/libelogind/sd-bus/bus-control.h \
- src/libelogind/sd-bus/bus-error.c \
- src/libelogind/sd-bus/bus-error.h \
- src/libelogind/sd-bus/bus-common-errors.h \
- src/libelogind/sd-bus/bus-common-errors.c \
- src/libelogind/sd-bus/bus-internal.c \
- src/libelogind/sd-bus/bus-internal.h \
- src/libelogind/sd-bus/bus-socket.c \
- src/libelogind/sd-bus/bus-socket.h \
- src/libelogind/sd-bus/bus-kernel.c \
- src/libelogind/sd-bus/bus-kernel.h \
- src/libelogind/sd-bus/bus-container.c \
- src/libelogind/sd-bus/bus-container.h \
- src/libelogind/sd-bus/bus-message.c \
- src/libelogind/sd-bus/bus-message.h \
- src/libelogind/sd-bus/bus-creds.c \
- src/libelogind/sd-bus/bus-creds.h \
- src/libelogind/sd-bus/bus-signature.c \
- src/libelogind/sd-bus/bus-signature.h \
- src/libelogind/sd-bus/bus-type.c \
- src/libelogind/sd-bus/bus-type.h \
- src/libelogind/sd-bus/bus-match.c \
- src/libelogind/sd-bus/bus-match.h \
- src/libelogind/sd-bus/bus-bloom.c \
- src/libelogind/sd-bus/bus-bloom.h \
- src/libelogind/sd-bus/bus-introspect.c \
- src/libelogind/sd-bus/bus-introspect.h \
- src/libelogind/sd-bus/bus-objects.c \
- src/libelogind/sd-bus/bus-objects.h \
- src/libelogind/sd-bus/bus-gvariant.c \
- src/libelogind/sd-bus/bus-gvariant.h \
- src/libelogind/sd-bus/bus-convenience.c \
- src/libelogind/sd-bus/bus-track.c \
- src/libelogind/sd-bus/bus-track.h \
- src/libelogind/sd-bus/bus-slot.c \
- src/libelogind/sd-bus/bus-slot.h \
- src/libelogind/sd-bus/bus-protocol.h \
- src/libelogind/sd-event/sd-event.c \
- src/libelogind/sd-id128/sd-id128.c \
- src/libelogind/sd-id128/id128-util.h \
- src/libelogind/sd-id128/id128-util.c \
- src/libelogind/sd-daemon/sd-daemon.c \
- src/libelogind/sd-login/sd-login.c
-
-noinst_LTLIBRARIES += \
- libelogind-internal.la
-
-EXTRA_DIST += \
- src/libelogind/libelogind.pc.in \
- src/libelogind/sd-bus/GVARIANT-SERIALIZATION
-
-libelogind_la_SOURCES =
-
-libelogind_la_LDFLAGS = \
- $(AM_LDFLAGS) \
- -version-info $(LIBELOGIND_CURRENT):$(LIBELOGIND_REVISION):$(LIBELOGIND_AGE) \
- -Wl,--version-script=$(top_srcdir)/src/libelogind/libelogind.sym
-
-libelogind_la_LIBADD = \
- libelogind-internal.la \
- libbasic.la
-
-pkgconfiglib_DATA += \
- src/libelogind/libelogind.pc
-
-pkginclude_HEADERS += \
- src/systemd/sd-bus.h \
- src/systemd/sd-bus-protocol.h \
- src/systemd/sd-bus-vtable.h \
- src/systemd/_sd-common.h \
- src/systemd/sd-daemon.h \
- src/systemd/sd-event.h \
- src/systemd/sd-id128.h \
- src/systemd/sd-login.h \
- src/systemd/sd-messages.h
-
-header-install-hook:
- $(MKDIR_P) $(DESTDIR)/$(pkgincludedir)
- cd $(DESTDIR)/$(includedir)/elogind && \
- for hdr in $(notdir $(pkginclude_HEADERS)) ; do \
- rm -f $$hdr ; \
- $(LN_S) systemd/$$hdr $$hdr ; \
- done
-
-header-uninstall-hook:
- m -f $(DESTDIR)/$(includedir)/elogind/*.h
-
-INSTALL_EXEC_HOOKS += header-install-hook
-UNINSTALL_EXEC_HOOKS += header-uninstall-hook
-
-rootlib_LTLIBRARIES += \
- libelogind.la
-
-tests += \
- test-bus-signature \
- test-bus-server \
- test-bus-match \
- test-bus-introspect \
- test-bus-vtable \
- test-bus-error \
- test-event
-
-test_bus_signature_SOURCES = \
- src/libelogind/sd-bus/test-bus-signature.c
-
-test_bus_signature_LDADD = \
- libelogind-shared.la
-
-test_bus_server_SOURCES = \
- src/libelogind/sd-bus/test-bus-server.c
-
-test_bus_server_LDADD = \
- libelogind-shared.la
-
-test_bus_vtable_SOURCES = \
- src/libelogind/sd-bus/test-bus-vtable.c
-
-test_bus_vtable_LDADD = \
- libelogind-shared.la
-
-test_bus_error_SOURCES = \
- src/libelogind/sd-bus/test-bus-error.c
-
-# Link statically because this test uses BUS_ERROR_MAP_ELF_REGISTER
-test_bus_error_LDADD = \
- libshared.la
-
-test_bus_match_SOURCES = \
- src/libelogind/sd-bus/test-bus-match.c
-
-test_bus_match_LDADD = \
- libelogind-shared.la
-
-test_bus_introspect_SOURCES = \
- src/libelogind/sd-bus/test-bus-introspect.c
-
-test_bus_introspect_LDADD = \
- libelogind-shared.la
-
-test_event_SOURCES = \
- src/libelogind/sd-event/test-event.c
-
-test_event_LDADD = \
- libelogind-shared.la
-
-# ------------------------------------------------------------------------------
-test_id128_SOURCES = \
- src/test/test-id128.c
-
-test_id128_LDADD = \
- libelogind-shared.la
-
-tests += \
- test-id128
-
-# ------------------------------------------------------------------------------
-test_hash_SOURCES = \
- src/test/test-hash.c
-
-test_hash_LDADD = \
- libelogind-shared.la
-
-tests += \
- test-hash
-
-# ------------------------------------------------------------------------------
-elogind_SOURCES = \
- src/login/logind.c \
- src/login/logind.h
-
-nodist_elogind_SOURCES = \
- src/login/logind-gperf.c
-
-elogind_LDADD = \
- libelogind-core.la
-
-libelogind_core_la_SOURCES = \
- src/core/cgroup.h \
- src/core/cgroup.c \
- src/core/mount-setup.h \
- src/core/mount-setup.c \
- src/login/elogind.c \
- src/login/elogind.h \
- src/login/elogind-dbus.c \
- src/login/elogind-dbus.h \
- src/login/logind-core.c \
- src/login/logind-device.c \
- src/login/logind-device.h \
- src/login/logind-button.c \
- src/login/logind-button.h \
- src/login/logind-action.c \
- src/login/logind-action.h \
- src/login/logind-seat.c \
- src/login/logind-seat.h \
- src/login/logind-session.c \
- src/login/logind-session.h \
- src/login/logind-session-device.c \
- src/login/logind-session-device.h \
- src/login/logind-user.c \
- src/login/logind-user.h \
- src/login/logind-inhibit.c \
- src/login/logind-inhibit.h \
- src/login/logind-dbus.c \
- src/login/logind-session-dbus.c \
- src/login/logind-seat-dbus.c \
- src/login/logind-user-dbus.c \
- src/login/logind-utmp.c \
- src/login/logind-acl.h \
- src/sleep/sleep.c \
- src/sleep/sleep.h
-
-if HAVE_UTMP
-libelogind_core_la_SOURCES += \
- src/shared/utmp-wtmp.c \
- src/update-utmp/update-utmp.c
-endif
-
-libelogind_core_la_LIBADD = \
- libelogind-shared.la
-
-if HAVE_ACL
-libelogind_core_la_SOURCES += \
- src/login/logind-acl.c
-endif
-
-noinst_LTLIBRARIES += \
- libelogind-core.la
-
-rootlibexec_PROGRAMS += \
- elogind
-
-loginctl_SOURCES = \
- src/login/eloginctl.c \
- src/login/eloginctl.h \
- src/login/loginctl.c \
- src/login/sysfs-show.h \
- src/login/sysfs-show.c
-
-loginctl_LDADD = \
- libelogind-shared.la
-
-rootbin_PROGRAMS += \
- loginctl
-
-dist_bashcompletion_data = \
- shell-completion/bash/loginctl
-
-dist_zshcompletion_data = \
- shell-completion/zsh/_loginctl \
- shell-completion/zsh/_elogind-inhibit
-
-elogind_inhibit_SOURCES = \
- src/login/inhibit.c
-
-elogind_inhibit_LDADD = \
- libelogind-shared.la
-
-rootbin_PROGRAMS += \
- elogind-inhibit
-
-test_login_SOURCES = \
- src/libelogind/sd-login/test-login.c
-
-test_login_LDADD = \
- libelogind-shared.la
-
-test_login_shared_SOURCES = \
- src/login/test-login-shared.c
-
-test_login_shared_LDADD = \
- libelogind-shared.la
-
-test_inhibit_SOURCES = \
- src/login/test-inhibit.c
-
-test_inhibit_LDADD = \
- libelogind-shared.la
-
-test_login_tables_SOURCES = \
- src/login/test-login-tables.c
-
-test_login_tables_LDADD = \
- libelogind-core.la
-
-manual_tests += \
- test-inhibit
-
-tests += \
- test-login \
- test-login-tables \
- test-login-shared
-
-if HAVE_PAM
-pam_elogind_la_SOURCES = \
- src/login/pam_elogind.sym \
- src/login/pam_elogind.c
-
-pam_elogind_la_CFLAGS = \
- $(AM_CFLAGS) \
- $(PAM_CFLAGS)
-
-pam_elogind_la_LDFLAGS = \
- $(AM_LDFLAGS) \
- -module \
- -export-dynamic \
- -avoid-version \
- -shared \
- -Wl,--version-script=$(top_srcdir)/src/login/pam_elogind.sym
-
-pam_elogind_la_LIBADD = \
- libshared.la \
- $(PAM_LIBS)
-
-pamlib_LTLIBRARIES = \
- pam_elogind.la
-
-if ENABLE_PAM_CONFIG
-dist_pamconf_DATA = \
- src/login/elogind-user
-endif
-
-EXTRA_DIST += \
- src/login/elogind-user.m4
-endif
-
-dist_dbussystemservice_DATA += \
- src/login/org.freedesktop.login1.service
-
-dist_dbuspolicy_DATA += \
- src/login/org.freedesktop.login1.conf
-
-nodist_pkgsysconf_DATA += \
- src/login/logind.conf
-
-polkitpolicy_files += \
- src/login/org.freedesktop.login1.policy
-
-dist_udevrules_DATA += \
- src/login/70-uaccess.rules \
- src/login/70-power-switch.rules
-
-nodist_udevrules_DATA += \
- src/login/71-seat.rules \
- src/login/73-seat-late.rules
-
-polkitpolicy_in_files += \
- src/login/org.freedesktop.login1.policy.in
-
-gperf_gperf_sources = \
- src/login/logind-gperf.gperf
-
-EXTRA_DIST += \
- src/login/71-seat.rules.in \
- src/login/73-seat-late.rules.in \
- src/login/logind.conf.in \
- src/login/org.freedesktop.login1.service.in
-
-# ------------------------------------------------------------------------------
-substitutions = \
- '|rootlibdir=$(rootlibdir)|' \
- '|rootlibexecdir=$(rootlibexecdir)|' \
- '|rootbindir=$(rootbindir)|' \
- '|bindir=$(bindir)|' \
- '|pkgsysconfdir=$(pkgsysconfdir)|' \
- '|pkgdatadir=$(pkgdatadir)|' \
- '|udevrulesdir=$(udevrulesdir)|' \
- '|PACKAGE_VERSION=$(PACKAGE_VERSION)|' \
- '|PACKAGE_NAME=$(PACKAGE_NAME)|' \
- '|PACKAGE_URL=$(PACKAGE_URL)|' \
- '|prefix=$(prefix)|' \
- '|exec_prefix=$(exec_prefix)|' \
- '|libdir=$(libdir)|' \
- '|includedir=$(includedir)|' \
- '|rootprefix=$(rootprefix)|' \
- '|udevlibexecdir=$(udevlibexecdir)|' \
- '|KILL=$(KILL)|' \
- '|MKDIR_P=$(MKDIR_P)|' \
- '|KILL_USER_PROCESSES=$(KILL_USER_PROCESSES)|' \
- '|systemuidmax=$(SYSTEM_UID_MAX)|' \
- '|systemgidmax=$(SYSTEM_GID_MAX)|'
-
-SED_PROCESS = \
- $(AM_V_GEN)$(MKDIR_P) $(dir $@) && \
- $(SED) $(subst '|,-e 's|@,$(subst =,\@|,$(subst |',|g',$(substitutions)))) \
- -e '/^\#\# /d' \
- < $< > $@
-
-man/%: man/%.in
- $(SED_PROCESS)
-
-sysctl.d/%: sysctl.d/%.in
- $(SED_PROCESS)
-
-%.pc: %.pc.in
- $(SED_PROCESS)
-
-shell-completion/%: shell-completion/%.in
- $(SED_PROCESS)
-
-%.rules: %.rules.in
- $(SED_PROCESS)
-
-%.conf: %.conf.in
- $(SED_PROCESS)
-
-%.login1.service: %.login1.service.in
- $(SED_PROCESS)
-
-%.sh: %.sh.in
- $(SED_PROCESS)
- $(AM_V_GEN)chmod +x $@
-
-src/%.c: src/%.gperf
- $(AM_V_at)$(MKDIR_P) $(dir $@)
- $(AM_V_GPERF)$(GPERF) < $< > $@
-
-src/%: src/%.m4
- $(AM_V_at)$(MKDIR_P) $(dir $@)
- $(AM_V_M4)$(M4) -P $(M4_DEFINES) < $< > $@
-
-sysusers.d/%: sysusers.d/%.m4
- $(AM_V_at)$(MKDIR_P) $(dir $@)
- $(AM_V_M4)$(M4) -P $(M4_DEFINES) < $< > $@
-
-tmpfiles.d/%: tmpfiles.d/%.m4
- $(AM_V_at)$(MKDIR_P) $(dir $@)
- $(AM_V_M4)$(M4) -P $(M4_DEFINES) < $< > $@
-
-
-units/%: units/%.m4
- $(AM_V_at)$(MKDIR_P) $(dir $@)
- $(AM_V_M4)$(M4) -P $(M4_DEFINES) -DFOR_SYSTEM=1 < $< > $@
-
-units/user/%: units/user/%.m4
- $(AM_V_at)$(MKDIR_P) $(dir $@)
- $(AM_V_M4)$(M4) -P $(M4_DEFINES) -DFOR_USER=1 < $< > $@
-
-if ENABLE_POLKIT
-nodist_polkitpolicy_DATA = \
- $(polkitpolicy_files)
-polkitrules_DATA = $(polkitrules_files)
-if ENABLE_POLKIT_PKLA
-polkitpkla_DATA = $(polkitpkla_files)
-endif
-endif
-
-EXTRA_DIST += \
- $(polkitpolicy_in_files)
-
-# ------------------------------------------------------------------------------
-if ENABLE_MANPAGES
-man/custom-entities.ent: configure.ac
- $(AM_V_GEN)$(MKDIR_P) $(dir $@)
- $(AM_V_GEN)(echo '<?xml version="1.0" encoding="utf-8" ?>' && \
- printf '$(subst '|,<!ENTITY ,$(subst =, ",$(subst |',">\n,$(substitutions))))') \
- > $@ # '
-
-CLEANFILES += \
- man/custom-entities.ent
-
-XSLTPROC_FLAGS = \
- --nonet \
- --xinclude \
- --stringparam man.output.quietly 1 \
- --stringparam funcsynopsis.style ansi \
- --stringparam man.authors.section.enabled 0 \
- --stringparam man.copyright.section.enabled 0 \
- --stringparam elogind.version $(PACKAGE_VERSION) \
- --path '$(builddir)/man:$(srcdir)/man'
-
-XSLTPROC_PROCESS_MAN = \
- $(AM_V_XSLT)$(XSLTPROC) -o $@ $(XSLTPROC_FLAGS) $(srcdir)/man/custom-man.xsl $<
-
-XSLTPROC_PROCESS_HTML = \
- $(AM_V_XSLT)$(XSLTPROC) -o $@ $(XSLTPROC_FLAGS) $(srcdir)/man/custom-html.xsl $<
-
-man/%.1: man/%.xml man/custom-man.xsl man/custom-entities.ent
- $(XSLTPROC_PROCESS_MAN)
-
-man/%.3: man/%.xml man/custom-man.xsl man/custom-entities.ent
- $(XSLTPROC_PROCESS_MAN)
-
-man/%.5: man/%.xml man/custom-man.xsl man/custom-entities.ent
- $(XSLTPROC_PROCESS_MAN)
-
-man/%.7: man/%.xml man/custom-man.xsl man/custom-entities.ent
- $(XSLTPROC_PROCESS_MAN)
-
-man/%.8: man/%.xml man/custom-man.xsl man/custom-entities.ent
- $(XSLTPROC_PROCESS_MAN)
-
-man/%.html: man/%.xml man/custom-html.xsl man/custom-entities.ent
- $(XSLTPROC_PROCESS_HTML)
-
-define html-alias
- $(AM_V_LN)$(LN_S) -f $(notdir $<) $@
-endef
-
-endif
-
-EXTRA_DIST += \
- man/custom-html.xsl \
- man/custom-man.xsl
-
-install-exec-hook: $(INSTALL_EXEC_HOOKS)
-
-uninstall-hook: $(UNINSTALL_EXEC_HOOKS)
-
-distclean-local: $(DISTCLEAN_LOCAL_HOOKS)
-
-clean-local: $(CLEAN_LOCAL_HOOKS)
- rm -rf $(abs_srcdir)/install-tree
- rm -f $(abs_srcdir)/hwdb/usb.ids $(abs_srcdir)/hwdb/pci.ids $(abs_srcdir)/hwdb/oui.txt \
- $(abs_srcdir)/hwdb/iab.txt
-
-DISTCHECK_CONFIGURE_FLAGS = \
- --with-dbuspolicydir=$$dc_install_base/$(dbuspolicydir) \
- --with-dbussystemservicedir=$$dc_install_base/$(dbussystemservicedir) \
- --with-bashcompletiondir=$$dc_install_base/$(bashcompletiondir) \
- --with-zshcompletiondir=$$dc_install_base/$(zshcompletiondir) \
- --with-pamlibdir=$$dc_install_base/$(pamlibdir) \
- --with-pamconfdir=$$dc_install_base/$(pamconfdir) \
- --with-rootprefix=$$dc_install_base
-
-if ENABLE_SPLIT_USR
-DISTCHECK_CONFIGURE_FLAGS += \
- --enable-split-usr
-else
-DISTCHECK_CONFIGURE_FLAGS += \
- --disable-split-usr
-endif
-
-.PHONY: dist-check-help
-dist-check-help: $(rootbin_PROGRAMS)
- for i in $(abspath $^); do \
- if $$i --help | grep -v 'default:' | grep -E -q '.{80}.' ; then \
- echo "$(basename $$i) --help output is too wide:"; \
- $$i --help | awk 'length > 80' | grep -E --color=yes '.{80}'; \
- exit 1; \
- fi; done
-
-include_compilers = "$(CC)" "$(CC) -ansi" "$(CC) -std=iso9899:1990"
-public_headers = $(filter-out src/systemd/_sd-common.h, $(pkginclude_HEADERS) $(include_HEADERS))
-.PHONY: dist-check-includes
-dist-check-includes: $(public_headers)
- @res=0; \
- for i in $(abspath $^); do \
- for cc in $(include_compilers); do \
- echo "$$cc -o/dev/null -c -x c -include "$$i" - </dev/null"; \
- $$cc -o/dev/null -c -x c -include "$$i" - </dev/null || res=1; \
- done; \
- done; exit $$res
-
-dist:
-
-.PHONY: git-tag
-git-tag:
- git tag -s "v$(PACKAGE_VERSION)" -m "elogind $(PACKAGE_VERSION)"
-
-.PHONY: git-tar
-git-tar:
- $(AM_V_at)git archive --format=tar --prefix=elogind-$(PACKAGE_VERSION)-raw/ HEAD | \
- (cd /var/tmp/ && tar xf -)
- $(AM_V_GEN)(cd /var/tmp && \
- rm -rf elogind-$(PACKAGE_VERSION) && \
- $(MKDIR_P) elogind-$(PACKAGE_VERSION) && \
- for f in `find elogind-$(PACKAGE_VERSION)-raw/ -type f | \
- cut -d '/' -f 2-` ; do \
- $(MKDIR_P) elogind-$(PACKAGE_VERSION)/`dirname $$f` ; \
- $(AWK) 'BEGIN { i=0;e=0 } \
- /^#if\s+0.*elogind.*$$/ { i=1;next } \
- /^#else\s*$$/ { \
- { if ( i==1 ) e=1; else print }{next} \
- } \
- /^#endif\s*\/\/\s*0\s*$$/ { \
- { if ( i==1 ) { i=0;e=0 } else print }{next} \
- } \
- /^\s*\/\/\/.*elogind.*$$/{ next } \
- /^\s*\/\/\s*#include.+$$/{ next } \
- { if ( (i==0) || (e==1) ) print }' \
- elogind-$(PACKAGE_VERSION)-raw/$$f \
- > elogind-$(PACKAGE_VERSION)/$$f ; \
- chmod `stat -c '%a' elogind-$(PACKAGE_VERSION)-raw/$$f` \
- elogind-$(PACKAGE_VERSION)/$$f ; \
- done ; \
- for l in `find elogind-$(PACKAGE_VERSION)-raw/ -type l | \
- cut -d '/' -f 2-` ; do \
- $(MKDIR_P) elogind-$(PACKAGE_VERSION)/`dirname $$l` ; \
- cp -P elogind-$(PACKAGE_VERSION)-raw/$$l \
- elogind-$(PACKAGE_VERSION)/$$l ; \
- done ; \
- tar czf elogind-$(PACKAGE_VERSION).tar.gz elogind-$(PACKAGE_VERSION) ; \
- rm -rf elogind-$(PACKAGE_VERSION) elogind-$(PACKAGE_VERSION)-raw) ; \
- $(AM_V_at)mv /var/tmp/elogind-$(PACKAGE_VERSION).tar.gz ./
-
-.PHONY: install-tree
-install-tree: all
- rm -rf $(abs_srcdir)/install-tree
- $(MAKE) install DESTDIR=$(abs_srcdir)/install-tree
- tree $(abs_srcdir)/install-tree
-
-# Let's run all tests of the test suite, but under valgrind. Let's
-# exclude perl/python/shell scripts we have in there
-.PHONY: valgrind-tests
-valgrind-tests: $(TESTS)
- $(AM_V_GEN)for f in $(filter-out %.pl %.py, $^); do \
- if $(LIBTOOL) --mode=execute file $$f | grep -q shell; then \
- echo -e "$${x}Skipping non-binary $$f"; else \
- echo -e "$${x}Running $$f"; \
- $(AM_TESTS_ENVIRONMENT) $(LIBTOOL) --mode=execute valgrind -q --leak-check=full --max-stackframe=5242880 --error-exitcode=55 $(builddir)/$$f ; fi; \
- x="\n\n"; \
- done
-
-exported-%: %
- $(AM_V_GEN)$(NM) -g --defined-only $(builddir)/.libs/$(<:.la=.so) 2>&1 /dev/null | grep " T " | cut -d" " -f3 > $@
-
-exported: $(addprefix exported-, $(rootlib_LTLIBRARIES))
- $(AM_V_GEN)cat $^ > $@
-
-.PHONY: check-api-docs
-check-api-docs: exported man
- $(AM_V_GEN)for symbol in `cat exported` ; do \
- if test -f $(builddir)/man/$$symbol.html ; then \
- echo " Symbol $$symbol() is documented." ; \
- else \
- echo "‣ Symbol $$symbol() lacks documentation." ; \
- fi ; \
- done
-
-OBJECT_VARIABLES:=$(filter %_OBJECTS,$(.VARIABLES))
-ALL_OBJECTS:=$(foreach v,$(OBJECT_VARIABLES),$($(v)))
-
-undefined defined: $(ALL_OBJECTS)
- $(AM_V_GEN)for f in $(ALL_OBJECTS) ; do \
- $(NM) -g --$@-only `echo $(builddir)/"$$f" | sed -e 's,\([^/]*\).lo$$,.libs/\1.o,'` ; \
- done | cut -c 20- | cut -d @ -f 1 | sort -u > $@
-
-CLEANFILES += \
- defined \
- undefined
-
-.PHONY: check-api-unused
-check-api-unused: defined undefined exported
- ( cat exported undefined ) | sort -u | diff -u - defined | grep ^+ | grep -v ^+++ | cut -c2-
-
-.PHONY: check-includes
-check-includes: $(top_srcdir)/tools/check-includes.pl
- $(AM_V_GEN) find * -name '*.[hcS]' -type f -print | sort -u \
- | xargs $(top_srcdir)/tools/check-includes.pl
-
-EXTRA_DIST += \
- $(top_srcdir)/tools/check-includes.pl
-
-# Stupid test that everything purported to be exported really is
-define generate-sym-test
- $(AM_V_at)$(MKDIR_P) $(dir $@)
- $(AM_V_at)printf '#include <stdio.h>\n' > $@
- $(AM_V_at)printf '#include "%s"\n' $(notdir $(filter %.h, $^)) >> $@
- $(AM_V_at)printf 'void* functions[] = {\n' >> $@
- $(AM_V_GEN)sed -r -n 's/^ +([a-zA-Z0-9_]+);/\1,/p' $< >> $@
- $(AM_V_at)printf '};\nint main(void) {\n' >> $@
- $(AM_V_at)printf 'unsigned i; for (i=0;i<sizeof(functions)/sizeof(void*);i++) printf("%%p\\n", functions[i]);\n' >> $@
- $(AM_V_at)printf 'return 0; }\n' >> $@
-endef
-
-test-libelogind-sym.c: \
- $(top_builddir)/src/libelogind/libelogind.sym \
- src/systemd/sd-daemon.h \
- src/systemd/sd-login.h \
- src/systemd/sd-bus.h \
- src/systemd/sd-event.h
- $(generate-sym-test)
-
-test_libelogind_sym_SOURCES = \
- test-libelogind-sym.c
-test_libelogind_sym_LDADD = \
- libelogind.la
-
-BUILT_SOURCES += \
- $(test_libelogind_sym_SOURCES)
-
-tests += \
- test-libelogind-sym
-
-.PHONY: install-tests
-install-tests: $(tests) $(TEST_DATA_FILES)
- for f in $(tests); do \
- if [ -x $(top_builddir)/.libs/$$f ]; then \
- install -D -m 755 $(top_builddir)/.libs/$$f $(DESTDIR)/$(testsdir)/$$f; \
- else \
- install -D -m 755 $(top_builddir)/$$f $(DESTDIR)/$(testsdir)/$$f; \
- fi; \
- done
- for f in $(TEST_DATA_FILES); do \
- install -D -m 644 $(top_srcdir)/$$f $(DESTDIR)/$(testsdir)/testdata/$${f#test/}; \
- done
-
-.PHONY: cccc cppcheck
-cccc: all
- cccc --outdir=$(top_builddir)/cccc \
- `find $(top_srcdir)/src/ -name '*.h' -or -name '*.c'`
-
-cppcheck:
- cppcheck --enable=all -q \
- -I $(top_srcdir)/src \
- -I $(top_builddir)/src/basic \
- -I $(top_srcdir)/src/basic \
- -I $(top_srcdir)/src/core \
- -I $(top_srcdir)/src/shared \
- -I $(top_builddir)/src/shared \
- -I $(top_srcdir)/src/login \
- -I $(top_srcdir)/src/systemd \
- -I $(top_srcdir)/src/libelogind/sd-bus \
- -I $(top_srcdir)/src/libelogind/sd-event \
- -I $(top_srcdir)/src/libelogind/sd-login \
- -I $(top_srcdir)/src/libelogind/sd-id128 \
- -I $(top_srcdir)/src/update-utmp \
- -I $(top_srcdir)/src/sleep \
- --force \
- $(top_srcdir)
-
-# Used to extract compile flags for YCM.
-print-%:
- @echo $($*)
-
-git-contrib:
- @git shortlog -s `git describe --abbrev=0`.. | cut -c8- | sed 's/ / /g' | awk '{ print $$0 "," }' | sort -u
-
-EXTRA_DIST += \
- tools/gdb-sd_dump_hashmaps.py
-
-list-keys:
- gpg --verbose --no-options --no-default-keyring --no-auto-key-locate --batch --trust-model=always --keyring=$(srcdir)/src/import/import-pubring.gpg --list-keys
-
-add-key:
- gpg --verbose --no-options --no-default-keyring --no-auto-key-locate --batch --trust-model=always --keyring=$(srcdir)/src/import/import-pubring.gpg --import -
diff --git a/NEWS b/NEWS
index d56b7a6f2..3bd24d7ad 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,1225 @@
systemd System and Service Manager
+CHANGES WITH 239:
+
+ * NETWORK INTERFACE DEVICE NAMING CHANGES: elogind-udevd's "net_id"
+ builtin will name network interfaces differently than in previous
+ versions for virtual network interfaces created with SR-IOV and NPAR
+ and for devices where the PCI network controller device does not have
+ a slot number associated.
+
+ SR-IOV virtual devices are now named based on the name of the parent
+ interface, with a suffix of "v<N>", where <N> is the virtual device
+ number. Previously those virtual devices were named as if completely
+ independent.
+
+ The ninth and later NPAR virtual devices will be named following the
+ scheme used for the first eight NPAR partitions. Previously those
+ devices were not renamed and the kernel default (eth<n>) was used.
+
+ "net_id" will also generate names for PCI devices where the PCI
+ network controller device does not have an associated slot number
+ itself, but one of its parents does. Previously those devices were
+ not renamed and the kernel default (eth<n>) was used.
+
+ * AF_INET and AF_INET6 are dropped from RestrictAddressFamilies= in
+ elogind.service. Since v235, IPAddressDeny=any has been set to
+ the unit. So, it is expected that the default behavior of
+ elogind is not changed. However, if distribution packagers or
+ administrators disabled or modified IPAddressDeny= setting by a
+ drop-in config file, then it may be necessary to update the file to
+ re-enable AF_INET and AF_INET6 to support network user name services,
+ e.g. NIS.
+
+ * When the RestrictNamespaces= unit property is specified multiple
+ times, then the specified types are merged now. Previously, only the
+ last assignment was used. So, if distribution packagers or
+ administrators modified the setting by a drop-in config file, then it
+ may be necessary to update the file.
+
+ * When OnFailure= is used in combination with Restart= on a service
+ unit, then the specified units will no longer be triggered on
+ failures that result in restarting. Previously, the specified units
+ would be activated each time the unit failed, even when the unit was
+ going to be restarted automatically. This behaviour contradicted the
+ documentation. With this release the code is adjusted to match the
+ documentation.
+
+ * elogind-tmpfiles will now print a notice whenever it encounters
+ tmpfiles.d/ lines referencing the /var/run/ directory. It will
+ recommend reworking them to use the /run/ directory instead (for
+ which /var/run/ is simply a symlinked compatibility alias). This way
+ elogind-tmpfiles can properly detect line conflicts and merge lines
+ referencing the same file by two paths, without having to access
+ them.
+
+ * systemctl disable/unmask/preset/preset-all cannot be used with
+ --runtime. Previously this was allowed, but resulted in unintuitive
+ behaviour that wasn't useful. systemctl disable/unmask will now undo
+ both runtime and persistent enablement/masking, i.e. it will remove
+ any relevant symlinks both in /run and /etc.
+
+ * Note that all long-running system services shipped with elogind will
+ now default to a system call whitelist (rather than a blacklist, as
+ before). In particular, elogind-udevd will now enforce one too. For
+ most cases this should be safe, however downstream distributions
+ which disabled sandboxing of elogind-udevd (specifically the
+ MountFlags= setting), might want to disable this security feature
+ too, as the default whitelisting will prohibit all mount, swap,
+ reboot and clock changing operations from udev rules.
+
+ * sd-boot acquired new loader configuration settings to optionally turn
+ off Windows and MacOS boot partition discovery as well as
+ reboot-into-firmware menu items. It is also able to pick a better
+ screen resolution for HiDPI systems, and now provides loader
+ configuration settings to change the resolution explicitly.
+
+ * The elogind-resolve tool has been renamed to resolvectl (it also
+ * elogind-resolved now supports DNS-over-TLS. It's still
+ turned off by default, use DNSOverTLS=opportunistic to turn it on in
+ resolved.conf. We intend to make this the default as soon as couple
+ of additional techniques for optimizing the initial latency caused by
+ establishing a TLS/TCP connection are implemented.
+
+ * elogind-resolved.service and elogind-networkd.service now set
+ DynamicUser=yes. The users elogind-resolve and elogind-network are
+ not created by elogind-sysusers.
+
+ remains available under the old name, for compatibility), and its
+ interface is now verb-based, similar in style to the other <xyz>ctl
+ tools, such as systemctl or loginctl.
+
+ * The resolvectl/elogind-resolve tool also provides 'resolvconf'
+ compatibility. It may be symlinked under the 'resolvconf' name, in
+ which case it will take arguments and input compatible with the
+ Debian and FreeBSD resolvconf tool.
+
+ * Support for suspend-then-hibernate has been added, i.e. a sleep mode
+ where the system initially suspends, and after a time-out resumes and
+ hibernates again.
+
+ * networkd's ClientIdentifier= now accepts a new option "duid-only". If
+ set the client will only send a DUID as client identifier.
+
+ * The nss-elogind glibc NSS module will now enumerate dynamic users and
+ groups in effect. Previously, it could resolve UIDs/GIDs to user
+ names/groups and vice versa, but did not support enumeration.
+
+ * journald's Compress= configuration setting now optionally accepts a
+ byte threshold value. All journal objects larger than this threshold
+ will be compressed, smaller ones will not. Previously this threshold
+ was not configurable and set to 512.
+
+ * A new system.conf setting NoNewPrivileges= is now available which may
+ be used to turn off acquisition of new privileges system-wide
+ (i.e. set Linux' PR_SET_NO_NEW_PRIVS for PID 1 itself, and thus also
+ for all its children). Note that turning this option on means setuid
+ binaries and file system capabilities lose their special powers.
+ While turning on this option is a big step towards a more secure
+ system, doing so is likely to break numerous pre-existing UNIX tools,
+ in particular su and sudo.
+
+ * A new service elogind-time-sync-wait.service has been added. If
+ enabled it will delay the time-sync.target unit at boot until time
+ synchronization has been received from the network. This
+ functionality is useful on systems lacking a local RTC or where it is
+ acceptable that the boot process shall be delayed by external network
+ services.
+
+ * When hibernating, elogind will now inform the kernel of the image
+ write offset, on kernels new enough to support this. This means swap
+ files should work for hibernation now.
+
+ * When loading unit files, elogind will now look for drop-in unit files
+ extensions in additional places. Previously, for a unit file name
+ "foo-bar-baz.service" it would look for dropin files in
+ "foo-bar-baz.service.d/*.conf". Now, it will also look in
+ "foo-bar-.service.d/*.conf" and "foo-.service.d/", i.e. at the
+ service name truncated after all inner dashes. This scheme allows
+ writing drop-ins easily that apply to a whole set of unit files at
+ once. It's particularly useful for mount and slice units (as their
+ naming is prefix based), but is also useful for service and other
+ units, for packages that install multiple unit files at once,
+ following a strict naming regime of beginning the unit file name with
+ the package's name. Two new specifiers are now supported in unit
+ files to match this: %j and %J are replaced by the part of the unit
+ name following the last dash.
+
+ * Unit files and other configuration files that support specifier
+ expansion now understand another three new specifiers: %T and %V will
+ resolve to /tmp and /var/tmp respectively, or whatever temporary
+ directory has been set for the calling user. %E will expand to either
+ /etc (for system units) or $XDG_CONFIG_HOME (for user units).
+
+ * The ExecStart= lines of unit files are no longer required to
+ reference absolute paths. If non-absolute paths are specified the
+ specified binary name is searched within the service manager's
+ built-in $PATH, which may be queried with 'elogind-path
+ search-binaries-default'. It's generally recommended to continue to
+ use absolute paths for all binaries specified in unit files.
+
+ * Units gained a new load state "bad-setting", which is used when a
+ unit file was loaded, but contained fatal errors which prevent it
+ from being started (for example, a service unit has been defined
+ lacking both ExecStart= and ExecStop= lines).
+
+ * coredumpctl's "gdb" verb has been renamed to "debug", in order to
+ support alternative debuggers, for example lldb. The old name
+ continues to be available however, for compatibility reasons. Use the
+ new --debugger= switch or the $SYSTEMD_DEBUGGER environment variable
+ to pick an alternative debugger instead of the default gdb.
+
+ * systemctl and the other tools will now output escape sequences that
+ generate proper clickable hyperlinks in various terminal emulators
+ where useful (for example, in the "systemctl status" output you can
+ now click on the unit file name to quickly open it in the
+ editor/viewer of your choice). Note that not all terminal emulators
+ support this functionality yet, but many do. Unfortunately, the
+ "less" pager doesn't support this yet, hence this functionality is
+ currently automatically turned off when a pager is started (which
+ happens quite often due to auto-paging). We hope to remove this
+ limitation as soon as "less" learns these escape sequences. This new
+ behaviour may also be turned off explicitly with the $SYSTEMD_URLIFY
+ environment variable. For details on these escape sequences see:
+ https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
+
+ * networkd's .network files now support a new IPv6MTUBytes= option for
+ setting the MTU used by IPv6 explicitly as well as a new MTUBytes=
+ option in the [Route] section to configure the MTU to use for
+ specific routes. It also gained support for configuration of the DHCP
+ "UserClass" option through the new UserClass= setting. It gained
+ three new options in the new [CAN] section for configuring CAN
+ networks. The MULTICAST and ALLMULTI interface flags may now be
+ controlled explicitly with the new Multicast= and AllMulticast=
+ settings.
+
+ * networkd will now automatically make use of the kernel's route
+ expiration feature, if it is available.
+
+ * udevd's .link files now support setting the number of receive and
+ transmit channels, using the RxChannels=, TxChannels=,
+ OtherChannels=, CombinedChannels= settings.
+
+ * Support for UDPSegmentationOffload= has been removed, given its
+ limited support in hardware, and waning software support.
+
+ * networkd's .netdev files now support creating "netdevsim" interfaces.
+
+ * PID 1 learnt a new bus call GetUnitByControlGroup() which may be used
+ to query the unit belonging to a specific kernel control group.
+
+ * elogind-analyze gained a new verb "cat-config", which may be used to
+ dump the contents of any configuration file, with all its matching
+ drop-in files added in, and honouring the usual search and masking
+ logic applied to elogind configuration files. For example use
+ "elogind-analyze cat-config elogind/system.conf" to get the complete
+ system configuration file of elogind how it would be loaded by PID 1
+ itself. Similar to this, various tools such as elogind-tmpfiles or
+ elogind-sysusers, gained a new option "--cat-config", which does the
+ corresponding operation for their own configuration settings. For
+ example, "elogind-tmpfiles --cat-config" will now output the full
+ list of tmpfiles.d/ lines in place.
+
+ * timedatectl gained three new verbs: "show" shows bus properties of
+ elogind-timedated, "timesync-status" shows the current NTP
+ synchronization state of elogind-timesyncd, and "show-timesync"
+ shows bus properties of elogind-timesyncd.
+
+ * elogind-timesyncd gained a bus interface on which it exposes details
+ about its state.
+
+ * elogind-nspawn gained a new --rlimit= switch for setting initial
+ * A new environment variable $SYSTEMD_TIMEDATED_NTP_SERVICES is now
+ understood by elogind-timedated. It takes a colon-separated list of
+ unit names of NTP client services. The list is used by
+ "timedatectl set-ntp".
+
+ resource limits for the container payload. There's a new switch
+ --hostname= to explicitly override the container's hostname. A new
+ --no-new-privileges= switch may be used to control the
+ PR_SET_NO_NEW_PRIVS flag for the container payload. A new
+ --oom-score-adjust= switch controls the OOM scoring adjustment value
+ for the payload. The new --cpu-affinity= switch controls the CPU
+ affinity of the container payload. The new --resolv-conf= switch
+ allows more detailed control of /etc/resolv.conf handling of the
+ container. Similarly, the new --timezone= switch allows more detailed
+ control of /etc/localtime handling of the container.
+
+ * elogind-detect-virt gained a new --list switch, which will print a
+ list of all currently known VM and container environments.
+
+ * Support for "Portable Services" has been added, see
+ doc/PORTABLE_SERVICES.md for details. Currently, the support is still
+ experimental, but this is expected to change soon. Reflecting this
+ experimental state, the "portablectl" binary is not installed into
+ /usr/bin yet. The binary has to be called with the full path
+ /usr/lib/elogind/portablectl instead.
+
+ * journalctl's and systemctl's -o switch now knows a new log output
+ mode "with-unit". The output it generates is very similar to the
+ regular "short" mode, but displays the unit name instead of the
+ syslog tag for each log line. Also, the date is shown with timezone
+ information. This mode is probably more useful than the classic
+ "short" output mode for most purposes, except where pixel-perfect
+ compatibility with classic /var/log/messages formatting is required.
+
+ * A new --dump-bus-properties switch has been added to the elogind
+ binary, which may be used to dump all supported D-Bus properties.
+ (Options which are still supported, but are deprecated, are *not*
+ shown.)
+
+ * sd-bus gained a set of new calls:
+ sd_bus_slot_set_floating()/sd_bus_slot_get_floating() may be used to
+ enable/disable the "floating" state of a bus slot object,
+ i.e. whether the slot object pins the bus it is allocated for into
+ memory or if the bus slot object gets disconnected when the bus goes
+ away. sd_bus_open_with_description(),
+ sd_bus_open_user_with_description(),
+ sd_bus_open_system_with_description() may be used to allocate bus
+ objects and set their description string already during allocation.
+
+ * sd-event gained support for watching inotify events from the event
+ loop, in an efficient way, sharing inotify handles between multiple
+ users. For this a new function sd_event_add_inotify() has been added.
+
+ * sd-event and sd-bus gained support for calling special user-supplied
+ destructor functions for userdata pointers associated with
+ sd_event_source, sd_bus_slot, and sd_bus_track objects. For this new
+ functions sd_bus_slot_set_destroy_callback,
+ sd_bus_slot_get_destroy_callback, sd_bus_track_set_destroy_callback,
+ sd_bus_track_get_destroy_callback,
+ sd_event_source_set_destroy_callback,
+ sd_event_source_get_destroy_callback have been added.
+
+ * The "net.ipv4.tcp_ecn" sysctl will now be turned on by default.
+
+ * PID 1 will now automatically reschedule .timer units whenever the
+ local timezone changes. (They previously got rescheduled
+ automatically when the system clock changed.)
+
+ * New documentation has been added to document cgroups delegation,
+ portable services and the various code quality tools we have set up:
+
+ https://github.com/systemd/systemd/blob/master/doc/CGROUP_DELEGATION.md
+ https://github.com/systemd/systemd/blob/master/doc/PORTABLE_SERVICES.md
+ https://github.com/systemd/systemd/blob/master/doc/CODE_QUALITY.md
+
+ * The Boot Loader Specification has been added to the source tree.
+
+ https://github.com/systemd/systemd/blob/master/doc/BOOT_LOADER_SPECIFICATION.md
+
+ While moving it into our source tree we have updated it and further
+ changes are now accepted through the usual github PR workflow.
+
+ * pam_elogind will now look for PAM userdata fields elogind.memory_max,
+ elogind.tasks_max, elogind.cpu_weight, elogind.io_weight set by
+ earlier PAM modules. The data in these fields is used to initialize
+ the session scope's resource properties. Thus external PAM modules
+ may now configure per-session limits, for example sourced from
+ external user databases.
+
+ * socket units with Accept=yes will now maintain a "refused" counter in
+ addition to the existing "accepted" counter, counting connections
+ refused due to the enforced limits.
+
+ * The "elogind-path search-binaries-default" command may now be use to
+ query the default, built-in $PATH PID 1 will pass to the services it
+ manages.
+
+ * A new unit file setting PrivateMounts= has been added. It's a boolean
+ option. If enabled the unit's processes are invoked in their own file
+ system namespace. Note that this behaviour is also implied if any
+ other file system namespacing options (such as PrivateTmp=,
+ PrivateDevices=, ProtectSystem=, …) are used. This option is hence
+ primarily useful for services that do not use any of the other file
+ system namespacing options. One such service is elogind-udevd.service
+ wher this is now used by default.
+
+ * ConditionSecurity= gained a new value "uefi-secureboot" that is true
+ when the system is booted in UEFI "secure mode".
+
+ * A new unit "system-update-pre.target" is added, which defines an
+ optional synchronization point for offline system updates, as
+ implemented by the pre-existing "system-update.target" unit. It
+ allows ordering services before the service that executes the actual
+ update process in a generic way.
+
+ Contributions from: Adam Duskett, Alan Jenkins, Alessandro Casale,
+ Alexander Kurtz, Alex Gartrell, Anssi Hannula, Arnaud Rebillout, Brian
+ J. Murrell, Bruno Vernay, Chris Lamb, Chris Lesiak, Christian Brauner,
+ Christian Hesse, Christian Rebischke, Colin Guthrie, Daniel Dao, Daniel
+ Lin, Danylo Korostil, Davide Cavalca, David Tardon, Dimitri John
+ Ledkov, Dmitriy Geels, Douglas Christman, Elia Geretto, emelenas, Emil
+ Velikov, Evgeny Vereshchagin, Felipe Sateler, Feng Sun, Filipe
+ Brandenburger, Franck Bui, futpib, Giuseppe Scrivano, Guillem Jover,
+ guixxx, Hannes Reinecke, Hans de Goede, Harald Hoyer, Henrique Dante de
+ Almeida, Hiram van Paassen, Ian Miell, Igor Gnatenko, Ivan Shapovalov,
+ Iwan Timmer, James Cowgill, Jan Janssen, Jan Synacek, Jared Kazimir,
+ Jérémy Rosen, João Paulo Rechi Vita, Joost Heitbrink, Jui-Chi Ricky
+ Liang, Jürg Billeter, Kai-Heng Feng, Karol Augustin, Kay Sievers,
+ Krzysztof Nowicki, Lauri Tirkkonen, Lennart Poettering, Leonard König,
+ Long Li, Luca Boccassi, Lucas Werkmeister, Marcel Hoppe, Marc
+ Kleine-Budde, Mario Limonciello, Martin Jansa, Martin Wilck, Mathieu
+ Malaterre, Matteo F. Vescovi, Matthew McGinn, Matthias-Christian Ott,
+ Michael Biebl, Michael Olbrich, Michael Prokop, Michal Koutný, Michal
+ Sekletar, Mike Gilbert, Mikhail Kasimov, Milan Broz, Milan Pässler,
+ Mladen Pejaković, Muhammet Kara, Nicolas Boichat, Omer Katz, Paride
+ Legovini, Paul Menzel, Paul Milliken, Pavel Hrdina, Peter A. Bigot,
+ Peter D'Hoye, Peter Hutterer, Peter Jones, Philip Sequeira, Philip
+ Withnall, Piotr Drąg, Radostin Stoyanov, Ricardo Salveti de Araujo,
+ Ronny Chevalier, Rosen Penev, Rubén Suárez Alvarez, Ryan Gonzalez,
+ Salvo Tomaselli, Sebastian Reichel, Sergey Ptashnick, Sergio Lindo
+ Mansilla, Stefan Schweter, Stephen Hemminger, Stuart Hayes, Susant
+ Sahani, Sylvain Plantefève, Thomas H. P. Andersen, Tobias Jungel,
+ Tomasz Torcz, Vito Caputo, Will Dietz, Will Thompson, Wim van Mourik,
+ Yu Watanabe, Zbigniew Jędrzejewski-Szmek
+
+ — Berlin, 2018-06-22
+
+CHANGES WITH 238:
+
+ * The MemoryAccounting= unit property now defaults to on. After
+ discussions with the upstream control group maintainers we learnt
+ that the negative impact of cgroup memory accounting on current
+ kernels is finally relatively minimal, so that it should be safe to
+ enable this by default without affecting system performance. Besides
+ memory accounting only task accounting is turned on by default, all
+ other forms of resource accounting (CPU, IO, IP) remain off for now,
+ because it's not clear yet that their impact is small enough to move
+ from opt-in to opt-out. We recommend downstreams to leave memory
+ accounting on by default if kernel 4.14 or higher is primarily
+ used. On very resource constrained systems or when support for old
+ kernels is a necessity, -Dmemory-accounting-default=false can be used
+ to revert this change.
+
+ * rpm scriptlets to update the udev hwdb and rules (%udev_hwdb_update,
+ %udev_rules_update) and the journal catalog (%journal_catalog_update)
+ from the upgrade scriptlets of individual packages now do nothing.
+ Transfiletriggers have been added which will perform those updates
+ once at the end of the transaction.
+
+ Similar transfiletriggers have been added to execute any sysctl.d
+ and binfmt.d rules. Thus, it should be unnecessary to provide any
+ scriptlets to execute this configuration from package installation
+ scripts.
+
+ * elogind-sysusers gained a mode where the configuration to execute is
+ specified on the command line, but this configuration is not executed
+ directly, but instead it is merged with the configuration on disk,
+ and the result is executed. This is useful for package installation
+ scripts which want to create the user before installing any files on
+ disk (in case some of those files are owned by that user), while
+ still allowing local admin overrides.
+
+ This functionality is exposed to rpm scriptlets through a new
+ %sysusers_create_package macro. Old %sysusers_create and
+ %sysusers_create_inline macros are deprecated.
+
+ A transfiletrigger for sysusers.d configuration is now installed,
+ which means that it should be unnecessary to call elogind-sysusers from
+ package installation scripts, unless the package installs any files
+ owned by those newly-created users, in which case
+ %sysusers_create_package should be used.
+
+ * Analogous change has been done for elogind-tmpfiles: it gained a mode
+ where the command-line configuration is merged with the configuration
+ on disk. This is exposed as the new %tmpfiles_create_package macro,
+ and %tmpfiles_create is deprecated. A transfiletrigger is installed
+ for tmpfiles.d, hence it should be unnecessary to call elogind-tmpfiles
+ from package installation scripts.
+
+ * sysusers.d configuration for a user may now also specify the group
+ number, in addition to the user number ("u username 123:456"), or
+ without the user number ("u username -:456").
+
+ * Configution items for elogind-sysusers can now be specified as
+ positional arguments when the new --inline switch is used.
+
+ * The login shell of users created through sysusers.d may now be
+ specified (previously, it was always /bin/sh for root and
+ /sbin/nologin for other users).
+
+ * elogind-analyze gained a new --global switch to look at global user
+ configuration. It also gained a unit-paths verb to list the unit load
+ paths that are compiled into elogind (which can be used with
+ --elogind, --user, or --global).
+
+ * udevadm trigger gained a new --settle/-w option to wait for any
+ triggered events to finish (but just those, and not any other events
+ which are triggered meanwhile).
+
+ * The action that elogind takes when the lid is closed and the
+ machine is connected to external power can now be configured using
+ HandleLidSwitchExternalPower= in logind.conf. Previously, this action
+ was determined by HandleLidSwitch=, and, for backwards compatibility,
+ is still is, if HandleLidSwitchExternalPower= is not explicitly set.
+
+ * journalctl will periodically call sd_journal_process() to make it
+ resilient against inotify queue overruns when journal files are
+ rotated very quickly.
+
+ * Two new functions in libelogind — sd_bus_get_n_queued_read and
+ sd_bus_get_n_queued_write — may be used to check the number of
+ pending bus messages.
+
+ * elogind gained a new
+ org.freedesktop.elogind1.Manager.AttachProcessesToUnit dbus call
+ which can be used to migrate foreign processes to scope and service
+ units. The primary user for this new API is elogind itself: the
+ elogind --user instance uses this call of the elogind --system
+ instance to migrate processes if it itself gets the request to
+ migrate processes and the kernel refuses this due to access
+ restrictions. Thanks to this "elogind-run --scope --user …" works
+ again in pure cgroups v2 environments when invoked from the user
+ session scope.
+
+ * A new TemporaryFileSystem= setting can be used to mask out part of
+ the real file system tree with tmpfs mounts. This may be combined
+ with BindPaths= and BindReadOnlyPaths= to hide files or directories
+ not relevant to the unit, while still allowing some paths lower in
+ the tree to be accessed.
+
+ ProtectHome=tmpfs may now be used to hide user home and runtime
+ directories from units, in a way that is mostly equivalent to
+ "TemporaryFileSystem=/home /run/user /root".
+
+ * Non-service units are now started with KeyringMode=shared by default.
+ This means that mount and swapon and other mount tools have access
+ to keys in the main keyring.
+
+ * /sys/fs/bpf is now mounted automatically.
+
+ * QNX virtualization is now detected by elogind-detect-virt and may
+ be used in ConditionVirtualization=.
+
+ * IPAccounting= may now be enabled also for slice units.
+
+ * A new -Dsplit-bin= build configuration switch may be used to specify
+ whether bin and sbin directories are merged, or if they should be
+ included separately in $PATH and various listings of executable
+ directories. The build configuration scripts will try to autodetect
+ the proper values of -Dsplit-usr= and -Dsplit-bin= based on build
+ system, but distributions are encouraged to configure this
+ explicitly.
+
+ * A new -Dok-color= build configuration switch may be used to change
+ the colour of "OK" status messages.
+
+ * UPGRADE ISSUE: serialization of units using JoinsNamespaceOf= with
+ PrivateNetwork=yes was buggy in previous versions of elogind. This
+ means that after the upgrade and daemon-reexec, any such units must
+ be restarted.
+
+ * INCOMPATIBILITY: as announced in the NEWS for 237, elogind-tmpfiles
+ will not exclude read-only files owned by root from cleanup.
+
+ Contributions from: Alan Jenkins, Alexander F Rødseth, Alexis Jeandet,
+ Andika Triwidada, Andrei Gherzan, Ansgar Burchardt, antizealot1337,
+ Batuhan Osman Taşkaya, Beniamino Galvani, Bill Yodlowsky, Caio Marcelo
+ de Oliveira Filho, CuBiC, Daniele Medri, Daniel Mouritzen, Daniel
+ Rusek, Davide Cavalca, Dimitri John Ledkov, Douglas Christman, Evgeny
+ Vereshchagin, Faalagorn, Filipe Brandenburger, Franck Bui, futpib,
+ Giacomo Longo, Gunnar Hjalmarsson, Hans de Goede, Hermann Gausterer,
+ Iago López Galeiras, Jakub Filak, Jan Synacek, Jason A. Donenfeld,
+ Javier Martinez Canillas, Jérémy Rosen, Lennart Poettering, Lucas
+ Werkmeister, Mao Huang, Marco Gulino, Michael Biebl, Michael Vogt,
+ MilhouseVH, Neal Gompa (ニール・ゴンパ), Oleander Reis, Olof Mogren,
+ Patrick Uiterwijk, Peter Hutterer, Peter Portante, Piotr Drąg, Robert
+ Antoni Buj Gelonch, Sergey Ptashnick, Shawn Landden, Shuang Liu, Simon
+ Fowler, SjonHortensius, snorreflorre, Susant Sahani, Sylvain
+ Plantefève, Thomas Blume, Thomas Haller, Vito Caputo, Yu Watanabe,
+ Zbigniew Jędrzejewski-Szmek, Марко М. Костић (Marko M. Kostić)
+
+ — Warsaw, 2018-03-05
+
+CHANGES WITH 237:
+
+ * Some keyboards come with a zoom see-saw or rocker which until now got
+ mapped to the Linux "zoomin/out" keys in hwdb. However, these
+ keycodes are not recognized by any major desktop. They now produce
+ Up/Down key events so that they can be used for scrolling.
+
+ * INCOMPATIBILITY: elogind-tmpfiles' "f" lines changed behaviour
+ slightly: previously, if an argument was specified for lines of this
+ type (i.e. the right-most column was set) this string was appended to
+ existing files each time elogind-tmpfiles was run. This behaviour was
+ different from what the documentation said, and not particularly
+ useful, as repeated elogind-tmpfiles invocations would not be
+ idempotent and grow such files without bounds. With this release
+ behaviour has been altered slightly, to match what the documentation
+ says: lines of this type only have an effect if the indicated files
+ don't exist yet, and only then the argument string is written to the
+ file.
+
+ * FUTURE INCOMPATIBILITY: In elogind v238 we intend to slightly change
+ elogind-tmpfiles behaviour: previously, read-only files owned by root
+ were always excluded from the file "aging" algorithm (i.e. the
+ automatic clean-up of directories like /tmp based on
+ atime/mtime/ctime). We intend to drop this restriction, and age files
+ by default even when owned by root and read-only. This behaviour was
+ inherited from older tools, but there have been requests to remove
+ it, and it's not obvious why this restriction was made in the first
+ place. Please speak up now, if you are aware of software that reqires
+ this behaviour, otherwise we'll remove the restriction in v238.
+
+ * A new environment variable $SYSTEMD_OFFLINE is now understood by
+ systemctl. It takes a boolean argument. If on, systemctl assumes it
+ operates on an "offline" OS tree, and will not attempt to talk to the
+ service manager. Previously, this mode was implicitly enabled if a
+ chroot() environment was detected, and this new environment variable
+ now provides explicit control.
+
+ * .path and .socket units may now be created transiently, too.
+ Previously only service, mount, automount and timer units were
+ supported as transient units. The elogind-run tool has been updated
+ to expose this new functionality, you may hence use it now to bind
+ arbitrary commands to path or socket activation on-the-fly from the
+ command line. Moreover, almost all properties are now exposed for the
+ unit types that already supported transient operation.
+
+ * The elogind-mount command gained support for a new --owner= parameter
+ which takes a user name, which is then resolved and included in uid=
+ and gid= mount options string of the file system to mount.
+
+ * A new unit condition ConditionControlGroupController= has been added
+ that checks whether a specific cgroup controller is available.
+
+ * Unit files, udev's .link files, and elogind-networkd's .netdev and
+ .network files all gained support for a new condition
+ ConditionKernelVersion= for checking against specific kernel
+ versions.
+
+ * In elogind-networkd, the [IPVLAN] section in .netdev files gained
+ support for configuring device flags in the Flags= setting. In the
+ same files, the [Tunnel] section gained support for configuring
+ AllowLocalRemote=. The [Route] section in .network files gained
+ support for configuring InitialCongestionWindow=,
+ InitialAdvertisedReceiveWindow= and QuickAck=. The [DHCP] section now
+ understands RapidCommit=.
+
+ * elogind-networkd's DHCPv6 support gained support for Prefix
+ Delegation.
+
+ * sd-bus gained support for a new "watch-bind" feature. When this
+ feature is enabled, an sd_bus connection may be set up to connect to
+ an AF_UNIX socket in the file system as soon as it is created. This
+ functionality is useful for writing early-boot services that
+ automatically connect to the system bus as soon as it is started,
+ without ugly time-based polling. elogind-networkd and
+ elogind-resolved have been updated to make use of this
+ functionality. busctl exposes this functionality in a new
+ --watch-bind= command line switch.
+
+ * sd-bus will now optionally synthesize a local "Connected" signal as
+ soon as a D-Bus connection is set up fully. This message mirrors the
+ already existing "Disconnected" signal which is synthesized when the
+ connection is terminated. This signal is generally useful but
+ particularly handy in combination with the "watch-bind" feature
+ described above. Synthesizing of this message has to be requested
+ explicitly through the new API call sd_bus_set_connected_signal(). In
+ addition a new call sd_bus_is_ready() has been added that checks
+ whether a connection is fully set up (i.e. between the "Connected" and
+ "Disconnected" signals).
+
+ * sd-bus gained two new calls sd_bus_request_name_async() and
+ sd_bus_release_name_async() for asynchronously registering bus
+ names. Similar, there is now sd_bus_add_match_async() for installing
+ a signal match asynchronously. All of elogind's own services have
+ been updated to make use of these calls. Doing these operations
+ asynchronously has two benefits: it reduces the risk of deadlocks in
+ case of cyclic dependencies between bus services, and it speeds up
+ service initialization since synchronization points for bus
+ round-trips are removed.
+
+ * sd-bus gained two new calls sd_bus_match_signal() and
+ sd_bus_match_signal_async(), which are similar to sd_bus_add_match()
+ and sd_bus_add_match_async() but instead of taking a D-Bus match
+ string take match fields as normal function parameters.
+
+ * sd-bus gained two new calls sd_bus_set_sender() and
+ sd_bus_message_set_sender() for setting the sender name of outgoing
+ messages (either for all outgoing messages or for just one specific
+ one). These calls are only useful in direct connections as on
+ brokered connections the broker fills in the sender anyway,
+ overwriting whatever the client filled in.
+
+ * sd-event gained a new pseudo-handle that may be specified on all API
+ calls where an "sd_event*" object is expected: SD_EVENT_DEFAULT. When
+ used this refers to the default event loop object of the calling
+ thread. Note however that this does not implicitly allocate one —
+ which has to be done prior by using sd_event_default(). Similarly
+ sd-bus gained three new pseudo-handles SD_BUS_DEFAULT,
+ SD_BUS_DEFAULT_USER, SD_BUS_DEFAULT_SYSTEM that may be used to refer
+ to the default bus of the specified type of the calling thread. Here
+ too this does not implicitly allocate bus connection objects, this
+ has to be done prior with sd_bus_default() and friends.
+
+ * sd-event gained a new call pair
+ sd_event_source_{get|set}_io_fd_own(). This may be used to request
+ automatic closure of the file descriptor an IO event source watches
+ when the event source is destroyed.
+
+ * elogind-networkd gained support for natively configuring WireGuard
+ connections.
+
+ * In previous versions elogind synthesized user records both for the
+ "nobody" (UID 65534) and "root" (UID 0) users in nss-elogind and
+ internally. In order to simplify distribution-wide renames of the
+ "nobody" user (like it is planned in Fedora: nfsnobody → nobody), a
+ new transitional flag file has been added: if
+ /etc/elogind/dont-synthesize-nobody exists synthesizing of the 65534
+ user and group record within the elogind codebase is disabled.
+
+ * elogind-notify gained a new --uid= option for selecting the source
+ user/UID to use for notification messages sent to the service
+ manager.
+
+ * journalctl gained a new --grep= option to list only entries in which
+ the message matches a certain pattern. By default matching is case
+ insensitive if the pattern is lowercase, and case sensitive
+ otherwise. Option --case-sensitive=yes|no can be used to override
+ this an specify case sensitivity or case insensitivity.
+
+ * There's now a "elogind-analyze service-watchdogs" command for printing
+ the current state of the service runtime watchdog, and optionally
+ enabling or disabling the per-service watchdogs system-wide if given a
+ boolean argument (i.e. the concept you configure in WatchdogSec=), for
+ debugging purposes. There's also a kernel command line option
+ elogind.service_watchdogs= for controlling the same.
+
+ * Two new "log-level" and "log-target" options for elogind-analyze were
+ added that merge the now deprecated get-log-level, set-log-level and
+ get-log-target, set-log-target pairs. The deprecated options are still
+ understood for backwards compatibility. The two new options print the
+ current value when no arguments are given, and set them when a
+ level/target is given as an argument.
+
+ * sysusers.d's "u" lines now optionally accept both a UID and a GID
+ specification, separated by a ":" character, in order to create users
+ where UID and GID do not match.
+
+ Contributions from: Adam Duskett, Alan Jenkins, Alexander Kuleshov,
+ Alexis Deruelle, Andrew Jeddeloh, Armin Widegreen, Batuhan Osman
+ Taşkaya, Björn Esser, bleep_blop, Bruce A. Johnson, Chris Down, Clinton
+ Roy, Colin Walters, Daniel Rusek, Dimitri John Ledkov, Dmitry Rozhkov,
+ Evgeny Vereshchagin, Ewout van Mansom, Felipe Sateler, Franck Bui,
+ Frantisek Sumsal, George Gaydarov, Gianluca Boiano, Hans-Christian
+ Noren Egtvedt, Hans de Goede, Henrik Grindal Bakken, Jan Alexander
+ Steffens, Jan Klötzke, Jason A. Donenfeld, jdkbx, Jérémy Rosen,
+ Jerónimo Borque, John Lin, John Paul Herold, Jonathan Rudenberg, Jörg
+ Thalheim, Ken (Bitsko) MacLeod, Larry Bernstone, Lennart Poettering,
+ Lucas Werkmeister, Maciej S. Szmigiero, Marek Čermák, Martin Pitt,
+ Mathieu Malaterre, Matthew Thode, Matthias-Christian Ott, Max Harmathy,
+ Michael Biebl, Michael Vogt, Michal Koutný, Michal Sekletar, Michał
+ Szczepański, Mike Gilbert, Nathaniel McCallum, Nicolas Chauvet, Olaf
+ Hering, Olivier Schwander, Patrik Flykt, Paul Cercueil, Peter Hutterer,
+ Piotr Drąg, Raphael Vogelgsang, Reverend Homer, Robert Kolchmeyer,
+ Samuel Dionne-Riel, Sergey Ptashnick, Shawn Landden, Susant Sahani,
+ Sylvain Plantefève, Thomas H. P. Andersen, Thomas Huth, Tomasz
+ Bachorski, Vladislav Vishnyakov, Wieland Hoffmann, Yu Watanabe, Zachary
+ Winnerman, Zbigniew Jędrzejewski-Szmek, Дамјан Георгиевски, Дилян
+ Палаузов
+
+ — Brno, 2018-01-28
+
+CHANGES WITH 236:
+
+ * The modprobe.d/ drop-in for the bonding.ko kernel module introduced
+ in v235 has been extended to also set the dummy.ko module option
+ numdummies=0, preventing the kernel from automatically creating
+ dummy0. All dummy interfaces must now be explicitly created.
+
+ * Unknown '%' specifiers in configuration files are now rejected. This
+ applies to units and tmpfiles.d configuration. Any percent characters
+ that are followed by a letter or digit that are not supposed to be
+ interpreted as the beginning of a specifier should be escaped by
+ doubling ("%%"). (So "size=5%" is still accepted, as well as
+ "size=5%,foo=bar", but not "LABEL=x%y%z" since %y and %z are not
+ valid specifiers today.)
+
+ * systemd-resolved now maintains a new dynamic
+ /run/systemd/resolve/stub-resolv.conf compatibility file. It is
+ recommended to make /etc/resolv.conf a symlink to it. This file
+ points at the systemd-resolved stub DNS 127.0.0.53 resolver and
+ includes dynamically acquired search domains, achieving more correct
+ DNS resolution by software that bypasses local DNS APIs such as NSS.
+
+ * The "uaccess" udev tag has been dropped from /dev/kvm and
+ /dev/dri/renderD*. These devices now have the 0666 permissions by
+ default (but this may be changed at build-time). /dev/dri/renderD*
+ will now be owned by the "render" group along with /dev/kfd.
+
+ * "DynamicUser=yes" has been enabled for systemd-timesyncd.service,
+ systemd-journal-gatewayd.service and
+ systemd-journal-upload.service. This means "nss-systemd" must be
+ enabled in /etc/nsswitch.conf to ensure the UIDs assigned to these
+ services are resolved properly.
+
+ * In /etc/fstab two new mount options are now understood:
+ x-systemd.makefs and x-systemd.growfs. The former has the effect that
+ the configured file system is formatted before it is mounted, the
+ latter that the file system is resized to the full block device size
+ after it is mounted (i.e. if the file system is smaller than the
+ partition it resides on, it's grown). This is similar to the fsck
+ logic in /etc/fstab, and pulls in systemd-makefs@.service and
+ systemd-growfs@.service as necessary, similar to
+ systemd-fsck@.service. Resizing is currently only supported on ext4
+ and btrfs.
+
+ * In systemd-networkd, the IPv6 RA logic now optionally may announce
+ DNS server and domain information.
+
+ * Support for the LUKS2 on-disk format for encrypted partitions has
+ been added. This requires libcryptsetup2 during compilation and
+ runtime.
+
+ * The systemd --user instance will now signal "readiness" when its
+ basic.target unit has been reached, instead of when the run queue ran
+ empty for the first time.
+
+ * Tmpfiles.d with user configuration are now also supported.
+ systemd-tmpfiles gained a new --user switch, and snippets placed in
+ ~/.config/user-tmpfiles.d/ and corresponding directories will be
+ executed by systemd-tmpfiles --user running in the new
+ systemd-tmpfiles-setup.service and systemd-tmpfiles-clean.service
+ running in the user session.
+
+ * Unit files and tmpfiles.d snippets learnt three new % specifiers:
+ %S resolves to the top-level state directory (/var/lib for the system
+ instance, $XDG_CONFIG_HOME for the user instance), %C resolves to the
+ top-level cache directory (/var/cache for the system instance,
+ $XDG_CACHE_HOME for the user instance), %L resolves to the top-level
+ logs directory (/var/log for the system instance,
+ $XDG_CONFIG_HOME/log/ for the user instance). This matches the
+ existing %t specifier, that resolves to the top-level runtime
+ directory (/run for the system instance, and $XDG_RUNTIME_DIR for the
+ user instance).
+
+ * journalctl learnt a new parameter --output-fields= for limiting the
+ set of journal fields to output in verbose and JSON output modes.
+
+ * systemd-timesyncd's configuration file gained a new option
+ RootDistanceMaxSec= for setting the maximum root distance of servers
+ it'll use, as well as the new options PollIntervalMinSec= and
+ PollIntervalMaxSec= to tweak the minimum and maximum poll interval.
+
+ * bootctl gained a new command "list" for listing all available boot
+ menu items on systems that follow the boot loader specification.
+
+ * systemctl gained a new --dry-run switch that shows what would be done
+ instead of doing it, and is currently supported by the shutdown and
+ sleep verbs.
+
+ * ConditionSecurity= can now detect the TOMOYO security module.
+
+ * Unit file [Install] sections are now also respected in unit drop-in
+ files. This is intended to be used by drop-ins under /usr/lib/.
+
+ * systemd-firstboot may now also set the initial keyboard mapping.
+
+ * Udev "changed" events for devices which are exposed as systemd
+ .device units are now propagated to units specified in
+ ReloadPropagatedFrom= as reload requests.
+
+ * If a udev device has a SYSTEMD_WANTS= property containing a systemd
+ unit template name (i.e. a name in the form of 'foobar@.service',
+ without the instance component between the '@' and - the '.'), then
+ the escaped sysfs path of the device is automatically used as the
+ instance.
+
+ * SystemCallFilter= in unit files has been extended so that an "errno"
+ can be specified individually for each system call. Example:
+ SystemCallFilter=~uname:EILSEQ.
+
+ * The cgroup delegation logic has been substantially updated. Delegate=
+ now optionally takes a list of controllers (instead of a boolean, as
+ before), which lists the controllers to delegate at least.
+
+ * The networkd DHCPv6 client now implements the FQDN option (RFC 4704).
+
+ * A new LogLevelMax= setting configures the maximum log level any
+ process of the service may log at (i.e. anything with a lesser
+ priority than what is specified is automatically dropped). A new
+ LogExtraFields= setting allows configuration of additional journal
+ fields to attach to all log records generated by any of the unit's
+ processes.
+
+ * New StandardInputData= and StandardInputText= settings along with the
+ new option StandardInput=data may be used to configure textual or
+ binary data that shall be passed to the executed service process via
+ standard input, encoded in-line in the unit file.
+
+ * StandardInput=, StandardOutput= and StandardError= may now be used to
+ connect stdin/stdout/stderr of executed processes directly with a
+ file or AF_UNIX socket in the file system, using the new "file:" option.
+
+ * A new unit file option CollectMode= has been added, that allows
+ tweaking the garbage collection logic for units. It may be used to
+ tell systemd to garbage collect units that have failed automatically
+ (normally it only GCs units that exited successfully). systemd-run
+ and systemd-mount expose this new functionality with a new -G option.
+
+ * "machinectl bind" may now be used to bind mount non-directories
+ (i.e. regularfiles, devices, fifos, sockets).
+
+ * systemd-analyze gained a new verb "calendar" for validating and
+ testing calendar time specifications to use for OnCalendar= in timer
+ units. Besides validating the expression it will calculate the next
+ time the specified expression would elapse.
+
+ * In addition to the pre-existing FailureAction= unit file setting
+ there's now SuccessAction=, for configuring a shutdown action to
+ execute when a unit completes successfully. This is useful in
+ particular inside containers that shall terminate after some workload
+ has been completed. Also, both options are now supported for all unit
+ types, not just services.
+
+ * networkds's IP rule support gained two new options
+ IncomingInterface= and OutgoingInterface= for configuring the incoming
+ and outgoing interfaces of configured rules. systemd-networkd also
+ gained support for "vxcan" network devices.
+
+ * networkd gained a new setting RequiredForOnline=, taking a
+ boolean. If set, systemd-wait-online will take it into consideration
+ when determining that the system is up, otherwise it will ignore the
+ interface for this purpose.
+
+ * The sd_notify() protocol gained support for a new operation: with
+ FDSTOREREMOVE=1 file descriptors may be removed from the per-service
+ store again, ahead of POLLHUP or POLLERR when they are removed
+ anyway.
+
+ * A new document doc/UIDS-GIDS.md has been added to the source tree,
+ that documents the UID/GID range and assignment assumptions and
+ requirements of systemd.
+
+ * The watchdog device PID 1 will ping may now be configured through the
+ WatchdogDevice= configuration file setting, or by setting the
+ systemd.watchdog_service= kernel commandline option.
+
+ * systemd-resolved's gained support for registering DNS-SD services on
+ the local network using MulticastDNS. Services may either be
+ registered by dropping in a .dnssd file in /etc/systemd/dnssd/ (or
+ the same dir below /run, /usr/lib), or through its D-Bus API.
+
+ * The sd_notify() protocol can now with EXTEND_TIMEOUT_USEC=microsecond
+ extend the effective start, runtime, and stop time. The service must
+ continue to send EXTEND_TIMEOUT_USEC within the period specified to
+ prevent the service manager from making the service as timedout.
+
+ * elogind-resolved's DNSSEC support gained support for RFC 8080
+ (Ed25519 keys and signatures).
+
+ * The elogind-resolve command line tool gained a new set of options
+ --set-dns=, --set-domain=, --set-llmnr=, --set-mdns=, --set-dnssec=,
+ --set-nta= and --revert to configure per-interface DNS configuration
+ dynamically during runtime. It's useful for pushing DNS information
+ into elogind-resolved from DNS hook scripts that various interface
+ managing software supports (such as pppd).
+
+ * elogind-nspawn gained a new --network-namespace-path= command line
+ option, which may be used to make a container join an existing
+ network namespace, by specifying a path to a "netns" file.
+
+ Contributions from: Alan Jenkins, Alan Robertson, Alessandro Ghedini,
+ Andrew Jeddeloh, Antonio Rojas, Ari, asavah, bleep_blop, Carsten
+ Strotmann, Christian Brauner, Christian Hesse, Clinton Roy, Collin
+ Eggert, Cong Wang, Daniel Black, Daniel Lockyer, Daniel Rusek, Dimitri
+ John Ledkov, Dmitry Rozhkov, Dongsu Park, Edward A. James, Evgeny
+ Vereshchagin, Florian Klink, Franck Bui, Gwendal Grignou, Hans de
+ Goede, Harald Hoyer, Hristo Venev, Iago López Galeiras, Ikey Doherty,
+ Jakub Wilk, Jérémy Rosen, Jiahui Xie, John Lin, José Bollo, Josef
+ Andersson, juga0, Krzysztof Nowicki, Kyle Walker, Lars Karlitski, Lars
+ Kellogg-Stedman, Lauri Tirkkonen, Lennart Poettering, Lubomir Rintel,
+ Luca Bruno, Lucas Werkmeister, Lukáš Nykrýn, Lukáš Říha, Lukasz
+ Rubaszewski, Maciej S. Szmigiero, Mantas Mikulėnas, Marcus Folkesson,
+ Martin Steuer, Mathieu Trudel-Lapierre, Matija Skala,
+ Matthias-Christian Ott, Max Resch, Michael Biebl, Michael Vogt, Michal
+ Koutný, Michal Sekletar, Mike Gilbert, Muhammet Kara, Neil Brown, Olaf
+ Hering, Ondrej Kozina, Patrik Flykt, Patryk Kocielnik, Peter Hutterer,
+ Piotr Drąg, Razvan Cojocaru, Robin McCorkell, Roland Hieber, Saran
+ Tunyasuvunakool, Sergey Ptashnick, Shawn Landden, Shuang Liu, Simon
+ Arlott, Simon Peeters, Stanislav Angelovič, Stefan Agner, Susant
+ Sahani, Sylvain Plantefève, Thomas Blume, Thomas Haller, Tiago Salem
+ Herrmann, Tinu Weber, Tom Stellard, Topi Miettinen, Torsten Hilbrich,
+ Vito Caputo, Vladislav Vishnyakov, WaLyong Cho, Yu Watanabe, Zbigniew
+ Jędrzejewski-Szmek, Zeal Jagannatha
+
+ — Berlin, 2017-12-14
+
+CHANGES WITH 235:
+
+ * INCOMPATIBILITY: systemd-logind.service and other long-running
+ services now run inside an IPv4/IPv6 sandbox, prohibiting them any IP
+ communication with the outside. This generally improves security of
+ the system, and is in almost all cases a safe and good choice, as
+ these services do not and should not provide any network-facing
+ functionality. However, systemd-logind uses the glibc NSS API to
+ query the user database. This creates problems on systems where NSS
+ is set up to directly consult network services for user database
+ lookups. In particular, this creates incompatibilities with the
+ "nss-nis" module, which attempts to directly contact the NIS/YP
+ network servers it is configured for, and will now consistently
+ fail. In such cases, it is possible to turn off IP sandboxing for
+ systemd-logind.service (set IPAddressDeny= in its [Service] section
+ to the empty string, via a .d/ unit file drop-in). Downstream
+ distributions might want to update their nss-nis packaging to include
+ such a drop-in snippet, accordingly, to hide this incompatibility
+ from the user. Another option is to make use of glibc's nscd service
+ to proxy such network requests through a privilege-separated, minimal
+ local caching daemon, or to switch to more modern technologies such
+ sssd, whose NSS hook-ups generally do not involve direct network
+ access. In general, we think it's definitely time to question the
+ implementation choices of nss-nis, i.e. whether it's a good idea
+ today to embed a network-facing loadable module into all local
+ processes that need to query the user database, including the most
+ trivial and benign ones, such as "ls". For more details about
+ IPAddressDeny= see below.
+
+ * A new modprobe.d drop-in is now shipped by default that sets the
+ bonding module option max_bonds=0. This overrides the kernel default,
+ to avoid conflicts and ambiguity as to whether or not bond0 should be
+ managed by systemd-networkd or not. This resolves multiple issues
+ with bond0 properties not being applied, when bond0 is configured
+ with systemd-networkd. Distributors may choose to not package this,
+ however in that case users will be prevented from correctly managing
+ bond0 interface using systemd-networkd.
+
+ * systemd-analyze gained new verbs "get-log-level" and "get-log-target"
+ which print the logging level and target of the system manager. They
+ complement the existing "set-log-level" and "set-log-target" verbs
+ used to change those values.
+
+ * journald.conf gained a new boolean setting ReadKMsg= which defaults
+ to on. If turned off kernel log messages will not be read by
+ systemd-journald or included in the logs. It also gained a new
+ setting LineMax= for configuring the maximum line length in
+ STDOUT/STDERR log streams. The new default for this value is 48K, up
+ from the previous hardcoded 2048.
+
+ * A new unit setting RuntimeDirectoryPreserve= has been added, which
+ allows more detailed control of what to do with a runtime directory
+ configured with RuntimeDirectory= (i.e. a directory below /run or
+ $XDG_RUNTIME_DIR) after a unit is stopped.
+
+ * The RuntimeDirectory= setting for units gained support for creating
+ deeper subdirectories below /run or $XDG_RUNTIME_DIR, instead of just
+ one top-level directory.
+
+ * Units gained new options StateDirectory=, CacheDirectory=,
+ LogsDirectory= and ConfigurationDirectory= which are closely related
+ to RuntimeDirectory= but manage per-service directories below
+ /var/lib, /var/cache, /var/log and /etc. By making use of them it is
+ possible to write unit files which when activated automatically gain
+ properly owned service specific directories in these locations, thus
+ making unit files self-contained and increasing compatibility with
+ stateless systems and factory reset where /etc or /var are
+ unpopulated at boot. Matching these new settings there's also
+ StateDirectoryMode=, CacheDirectoryMode=, LogsDirectoryMode=,
+ ConfigurationDirectoryMode= for configuring the access mode of these
+ directories. These settings are particularly useful in combination
+ with DynamicUser=yes as they provide secure, properly-owned,
+ writable, and stateful locations for storage, excluded from the
+ sandbox that such services live in otherwise.
+
+ * Automake support has been removed from this release. systemd is now
+ Meson-only.
+
+ * systemd-journald will now aggressively cache client metadata during
+ runtime, speeding up log write performance under pressure. This comes
+ at a small price though: as much of the metadata is read
+ asynchronously from /proc/ (and isn't implicitly attached to log
+ datagrams by the kernel, like UID/GID/PID/SELinux are) this means the
+ metadata stored alongside a log entry might be slightly
+ out-of-date. Previously it could only be slightly newer than the log
+ message. The time window is small however, and given that the kernel
+ is unlikely to be improved anytime soon in this regard, this appears
+ acceptable to us.
+
+ * nss-myhostname/systemd-resolved will now by default synthesize an
+ A/AAAA resource record for the "_gateway" hostname, pointing to the
+ current default IP gateway. Previously it did that for the "gateway"
+ name, hampering adoption, as some distributions wanted to leave that
+ host name open for local use. The old behaviour may still be
+ requested at build time.
+
+ * systemd-networkd's [Address] section in .network files gained a new
+ Scope= setting for configuring the IP address scope. The [Network]
+ section gained a new boolean setting ConfigureWithoutCarrier= that
+ tells systemd-networkd to ignore link sensing when configuring the
+ device. The [DHCP] section gained a new Anonymize= boolean option for
+ turning on a number of options suggested in RFC 7844. A new
+ [RoutingPolicyRule] section has been added for configuring the IP
+ routing policy. The [Route] section has gained support for a new
+ Type= setting which permits configuring
+ blackhole/unreachable/prohibit routes.
+
+ * The [VRF] section in .netdev files gained a new Table= setting for
+ configuring the routing table to use. The [Tunnel] section gained a
+ new Independent= boolean field for configuring tunnels independent of
+ an underlying network interface. The [Bridge] section gained a new
+ GroupForwardMask= option for configuration of propagation of link
+ local frames between bridge ports.
+
+ * The WakeOnLan= setting in .link files gained support for a number of
+ new modes. A new TCP6SegmentationOffload= setting has been added for
+ configuring TCP/IPv6 hardware segmentation offload.
+
+ * The IPv6 RA sender implementation may now optionally send out RDNSS
+ and RDNSSL records to supply DNS configuration to peers.
+
+ * systemd-nspawn gained support for a new --system-call-filter= command
+ line option for adding and removing entries in the default system
+ call filter it applies. Moreover systemd-nspawn has been changed to
+ implement a system call whitelist instead of a blacklist.
+
+ * systemd-run gained support for a new --pipe command line option. If
+ used the STDIN/STDOUT/STDERR file descriptors passed to systemd-run
+ are directly passed on to the activated transient service
+ executable. This allows invoking arbitrary processes as systemd
+ services (for example to take benefit of dependency management,
+ accounting management, resource management or log management that is
+ done automatically for services) — while still allowing them to be
+ integrated in a classic UNIX shell pipeline.
+
+ * When a service sends RELOAD=1 via sd_notify() and reload propagation
+ using ReloadPropagationTo= is configured, a reload is now propagated
+ to configured units. (Previously this was only done on explicitly
+ requested reloads, using "systemctl reload" or an equivalent
+ command.)
+
+ * For each service unit a restart counter is now kept: it is increased
+ each time the service is restarted due to Restart=, and may be
+ queried using "systemctl show -p NRestarts …".
+
+ * New system call filter groups @aio, @sync, @chown, @setuid, @memlock,
+ @signal and @timer have been added, for usage with SystemCallFilter=
+ in unit files and the new --system-call-filter= command line option
+ of systemd-nspawn (see above).
+
+ * ExecStart= lines in unit files gained two new modifiers: when a
+ command line is prefixed with "!" the command will be executed as
+ configured, except for the credentials applied by
+ setuid()/setgid()/setgroups(). It is very similar to the pre-existing
+ "+", but does still apply namespacing options unlike "+". There's
+ also "!!" now, which is mostly identical, but becomes a NOP on
+ systems that support ambient capabilities. This is useful to write
+ unit files that work with ambient capabilities where possible but
+ automatically fall back to traditional privilege dropping mechanisms
+ on systems where this is not supported.
+
+ * ListenNetlink= settings in socket units now support RDMA netlink
+ sockets.
+
+ * A new unit file setting LockPersonality= has been added which permits
+ locking down the chosen execution domain ("personality") of a service
+ during runtime.
+
+ * A new special target "getty-pre.target" has been added, which is
+ ordered before all text logins, and may be used to order services
+ before textual logins acquire access to the console.
+
+ * systemd will now attempt to load the virtio-rng.ko kernel module very
+ early on if a VM environment supporting this is detected. This should
+ improve entropy during early boot in virtualized environments.
+
+ * A _netdev option is now supported in /etc/crypttab that operates in a
+ similar way as the same option in /etc/fstab: it permits configuring
+ encrypted devices that need to be ordered after the network is up.
+ Following this logic, two new special targets
+ remote-cryptsetup-pre.target and remote-cryptsetup.target have been
+ added that are to cryptsetup.target what remote-fs.target and
+ remote-fs-pre.target are to local-fs.target.
+
+ * Service units gained a new UnsetEnvironment= setting which permits
+ unsetting specific environment variables for services that are
+ normally passed to it (for example in order to mask out locale
+ settings for specific services that can't deal with it).
+
+ * Units acquired a new boolean option IPAccounting=. When turned on, IP
+ traffic accounting (packet count as well as byte count) is done for
+ the service, and shown as part of "systemctl status" or "systemd-run
+ --wait".
+
+ * Service units acquired two new options IPAddressAllow= and
+ IPAddressDeny=, taking a list of IPv4 or IPv6 addresses and masks,
+ for configuring a simple IP access control list for all sockets of
+ the unit. These options are available also on .slice and .socket
+ units, permitting flexible access list configuration for individual
+ services as well as groups of services (as defined by a slice unit),
+ including system-wide. Note that IP ACLs configured this way are
+ enforced on every single IPv4 and IPv6 socket created by any process
+ of the service unit, and apply to ingress as well as egress traffic.
+
+ * If CPUAccounting= or IPAccounting= is turned on for a unit a new
+ structured log message is generated each time the unit is stopped,
+ containing information about the consumed resources of this
+ invocation.
+
+ * A new setting KeyringMode= has been added to unit files, which may be
+ used to control how the kernel keyring is set up for executed
+ processes.
+
+ * "systemctl poweroff", "systemctl reboot", "systemctl halt",
+ "systemctl kexec" and "systemctl exit" are now always asynchronous in
+ behaviour (that is: these commands return immediately after the
+ operation was enqueued instead of waiting for the operation to
+ complete). Previously, "systemctl poweroff" and "systemctl reboot"
+ were asynchronous on systems using systemd-logind (i.e. almost
+ always, and like they were on sysvinit), and the other three commands
+ were unconditionally synchronous. With this release this is cleaned
+ up, and callers will see the same asynchronous behaviour on all
+ systems for all five operations.
+
+ * systemd-logind gained new Halt() and CanHalt() bus calls for halting
+ the system.
+
+ * .timer units now accept calendar specifications in other timezones
+ than UTC or the local timezone.
+
+ * The tmpfiles snippet var.conf has been changed to create
+ /var/log/btmp with access mode 0660 instead of 0600. It was owned by
+ the "utmp" group already, and it appears to be generally understood
+ that members of "utmp" can modify/flush the utmp/wtmp/lastlog/btmp
+ databases. Previously this was implemented correctly for all these
+ databases excepts btmp, which has been opened up like this now
+ too. Note that while the other databases are world-readable
+ (i.e. 0644), btmp is not and remains more restrictive.
+
+ * The systemd-resolve tool gained a new --reset-server-features
+ switch. When invoked like this systemd-resolved will forget
+ everything it learnt about the features supported by the configured
+ upstream DNS servers, and restarts the feature probing logic on the
+ next resolver look-up for them at the highest feature level
+ again.
+
+ * The status dump systemd-resolved sends to the logs upon receiving
+ SIGUSR1 now also includes information about all DNS servers it is
+ configured to use, and the features levels it probed for them.
+
+ Contributions from: Abdó Roig-Maranges, Alan Jenkins, Alexander
+ Kuleshov, Andreas Rammhold, Andrew Jeddeloh, Andrew Soutar, Ansgar
+ Burchardt, Beniamino Galvani, Benjamin Berg, Benjamin Robin, Charles
+ Huber, Christian Hesse, Daniel Berrange, Daniel Kahn Gillmor, Daniel
+ Mack, Daniel Rusek, Daniel Șerbănescu, Davide Cavalca, Dimitri John
+ Ledkov, Diogo Pereira, Djalal Harouni, Dmitriy Geels, Dmitry Torokhov,
+ ettavolt, Evgeny Vereshchagin, Fabio Kung, Felipe Sateler, Franck Bui,
+ Hans de Goede, Harald Hoyer, Insun Pyo, Ivan Kurnosov, Ivan Shapovalov,
+ Jakub Wilk, Jan Synacek, Jason Gunthorpe, Jeremy Bicha, Jérémy Rosen,
+ John Lin, jonasBoss, Jonathan Lebon, Jonathan Teh, Jon Ringle, Jörg
+ Thalheim, Jouke Witteveen, juga0, Justin Capella, Justin Michaud,
+ Kai-Heng Feng, Lennart Poettering, Lion Yang, Luca Bruno, Lucas
+ Werkmeister, Lukáš Nykrýn, Marcel Hollerbach, Marcus Lundblad, Martin
+ Pitt, Michael Biebl, Michael Grzeschik, Michal Sekletar, Mike Gilbert,
+ Neil Brown, Nicolas Iooss, Patrik Flykt, pEJipE, Piotr Drąg, Russell
+ Stuart, S. Fan, Shengyao Xue, Stefan Pietsch, Susant Sahani, Tejun Heo,
+ Thomas Miller, Thomas Sailer, Tobias Hunger, Tomasz Pala, Tom
+ Gundersen, Tommi Rantala, Topi Miettinen, Torstein Husebø, userwithuid,
+ Vasilis Liaskovitis, Vito Caputo, WaLyong Cho, William Douglas, Xiang
+ Fan, Yu Watanabe, Zbigniew Jędrzejewski-Szmek
+
+ — Berlin, 2017-10-06
+
CHANGES WITH 234:
* Meson is now supported as build system in addition to Automake. It is
@@ -37,7 +1257,7 @@ CHANGES WITH 234:
(domain search list).
* systemd-networkd gained support for serving IPv6 address ranges using
- the Router Advertisment protocol. The new .network configuration
+ the Router Advertisement protocol. The new .network configuration
section [IPv6Prefix] may be used to configure the ranges to
serve. This is implemented based on a new, minimal, native server
implementation of RA.
@@ -132,9 +1352,6 @@ CHANGES WITH 234:
CHANGES WITH 233:
- * This version requires at least gperf 3.1 for building, 3.0 is not
- sufficient.
-
* The "hybrid" control group mode has been modified to improve
compatibility with "legacy" cgroups-v1 setups. Specifically, the
"hybrid" setup of /sys/fs/cgroup is now pretty much identical to
@@ -405,7 +1622,7 @@ CHANGES WITH 233:
* Documentation has been added that lists all of systemd's low-level
environment variables:
- https://github.com/systemd/systemd/blob/master/ENVIRONMENT.md
+ https://github.com/systemd/systemd/blob/master/doc/ENVIRONMENT.md
* sd-daemon gained a new API sd_is_socket_sockaddr() for determining
whether a specific socket file descriptor matches a specified socket
@@ -771,7 +1988,7 @@ CHANGES WITH 232:
counted multiple times, if it takes multiple references.
* sd-bus gained new API calls sd_bus_set_exit_on_disconnect() and
- sd_bus_get_exit_on_disconnect(). They may be used to to make a
+ sd_bus_get_exit_on_disconnect(). They may be used to make a
process using sd-bus automatically exit if the bus connection is
severed.
@@ -1102,7 +2319,7 @@ CHANGES WITH 231:
with future releases) that the components link to. This should
decrease systemd footprint both in memory during runtime and on
disk. Note that the shared library is not for public use, and is
- neither API not ABI stable, but is likely to change with every new
+ neither API nor ABI stable, but is likely to change with every new
released update. Packagers need to make sure that binaries
linking to libsystemd-shared.so are updated in step with the
library.
@@ -1116,7 +2333,7 @@ CHANGES WITH 231:
booted up with "systemd-nspawn -b -i", qemu-kvm or on any physical
UEFI PC. This functionality is particularly useful to easily test
local changes made to systemd in a pristine, defined environment. See
- HACKING for details.
+ doc/HACKING for details.
* configure learned the --with-support-url= option to specify the
distribution's bugtracker.
@@ -1579,6 +2796,13 @@ CHANGES WITH 229:
d /run/lock/lockdev 0775 root lock -
+ * The settings StartLimitBurst=, StartLimitInterval=, StartLimitAction=
+ and RebootArgument= have been moved from the [Service] section of
+ unit files to [Unit], and they are now supported on all unit types,
+ not just service units. Of course, elogind will continue to
+ understand these settings also at the old location, in order to
+ maintain compatibility.
+
Contributions from: Abdo Roig-Maranges, Alban Crequy, Aleksander
Adamowski, Alexander Kuleshov, Andreas Pokorny, Andrei Borzenkov,
Andrew Wilcox, Arthur Clement, Beniamino Galvani, Casey Schaufler,
@@ -4819,7 +6043,7 @@ CHANGES WITH 209:
option as supported by Debian is added. It allows indicating
which LUKS slot to use on disk, speeding up key loading.
- * The sd_journald_sendv() API call has been checked and
+ * The sd_journal_sendv() API call has been checked and
officially declared to be async-signal-safe so that it may
be invoked from signal handlers for logging purposes.
diff --git a/README b/README
index 0cd868ade..ced8cc164 100644
--- a/README
+++ b/README
@@ -54,16 +54,11 @@ interface, which is currently only provided by systemd. That is the
origin of this project: to take the excellent logind functionality
from systemd and provide it as a standalone package.
-We like systemd. We realize that there are people out there that hate
-it. You're welcome to use elogind for whatever purpose you like --
+You're welcome to use elogind for whatever purpose you like --
as-is, or as a jumping-off point for other things -- but please don't
-use it as part of some anti-systemd vendetta. Systemd hackers are
-smart folks that are trying to solve interesting problems on the free
-desktop, and their large adoption is largely because they solve
-problems that users and developers of user-focused applications care
-about. We are appreciative of their logind effort and think that
-everyone deserves to run it if they like, even if they use a different
-PID 1.
+use it as part of some anti-systemd vendetta. We are appreciative of
+the systemd developers logind effort and think that everyone deserves
+to run it if they like. Not matter what kind of PID1 they use.
Differences relative to systemd
-------------------------------
@@ -147,37 +142,53 @@ License
LGPLv2.1+ for all code
- - except src/shared/MurmurHash2.c which is Public Domain
- - except src/shared/siphash24.c which is CC0 Public Domain
- - except src/journal/lookup3.c which is Public Domain
+ - except src/basic/siphash24.c which is CC0 Public Domain
Dependencies
------------
- glibc >= 2.14
+ glibc >= 2.16
libcap
- libmount >= 2.20 (from util-linux)
- libseccomp >= 1.0.0 (optional)
+ libmount >= 2.27.1 (from util-linux)
+ (util-linux < 2.29 *must* be built with --enable-libmount-force-mountinfo,
+ and later versions without --enable-libmount-support-mtab.)
+ libseccomp >= 2.3.1 (optional)
libblkid >= 2.24 (from util-linux) (optional)
PAM >= 1.1.2 (optional)
libacl (optional)
libselinux (optional)
- make, gcc, and similar tools
+ libpython (optional)
+ pkg-config
+ gperf >= 3.1
+ docbook-xsl (optional, required for documentation)
+ xsltproc (optional, required for documentation)
+ python-lxml (optional, required to build the indices)
+ python, meson, ninja
+ gcc, awk, sed, grep, m4, and similar tools
During runtime, you need the following additional dependencies:
+ util-linux >= v2.27.1 required
dbus >= 1.4.0 (strictly speaking optional, but recommended)
+ NOTE: If using dbus < 1.9.18, you should override the default
+ policy directory (--with-dbuspolicydir=/etc/dbus-1/system.d).
PolicyKit (optional)
-When building from git, you need the following additional
-dependencies:
+ To build in directory build/:
+ meson build/ && ninja -C build
- pkg-config
- docbook-xsl
- xsltproc
- automake
- autoconf
- libtool
- intltool
- gperf
- gtkdocize (optional)
+ Any configuration options can be specified as -Darg=value... arguments
+ to meson. After the build directory is initially configured, the configuration
+ can be changed with:
+ meson configure -Darg=value... build/
+ 'meson configure' without any arguments will print out available options and
+ their current values.
+
+ Useful commands:
+ ninja -v some/target
+ ninja test
+ sudo ninja install
+ DESTDIR=... ninja install
+
+ A tarball can be created with:
+ git archive --format=tar --prefix=elogind-238/ v238 | xz > elogind-238.tar.xz
diff --git a/TODO b/TODO
index 61efa5e9f..829cc2e2a 100644
--- a/TODO
+++ b/TODO
@@ -1,16 +1,8 @@
Bugfixes:
-* Should systemctl status \* work on all unit types, not just .service?
+* the error paths in usbffs_dispatch_ep() leak memory
-* Dangling symlinks of .automount unit files in .wants/ directories, set up
- automount points even when the original .automount file did not exist
- anymore. Only the .mount unit was still around.
-
-* ExecStart with unicode characters fails in strv_split_extract:
-
- [Service]
- Environment=ONE='one' "TWO='two two' too" THREE=
- ExecStart=/bin/python3 -c 'import sys;print(sys.argv)' $ONE $TWO $THREE
+* copy.c: set the right chattrs before copying files and others after
External:
@@ -22,8 +14,222 @@ Janitorial Clean-ups:
* Rearrange tests so that the various test-xyz.c match a specific src/basic/xyz.c again
+* copy.c: set the right chattrs before copying files and others after
+
+* rework mount.c and swap.c to follow proper state enumeration/deserialization
+ semantics, like we do for device.c now
+
Features:
+* the stop-when-unneded feature should be reworked: there should be a queue of
+ units, and we should only enqeueu stop jobs from a defer event that processes
+ queue instead of right-away when we assume that a unit is now unneeded.
+
+* When reloading configuration PID 1 should reset all its properties to the
+ original defaults before calling parse_config()
+
+* Add OnTimezoneChange= and OnTimeChange= stanzas to .timer units in order to
+ schedule events based on time and timezone changes.
+
+* nspawn: greater control over selinux label?
+
+* cgroups: figure out if we can somehow communicate in a cleaner way whether a
+ elogind instance not running in the cgroup root shall or shall not manage the
+ attributes of its top-level cgroup. Currently it assumes it manages all, but
+ then might get EPERM due to permission porblems/userns, which is OK, but this
+ should be revisited to make clearer and also work if the payload elogind runs
+ with full privs and without userns.
+
+* portables: introduce a new unit file directory /etc/elogind/system.attached/
+ or so, where we attach portable services to
+
+* cgroups: use inotify to get notified when somebody else modifies cgroups
+ owned by us, then log a friendly warning.
+
+* beef up log.c with support for stripping ANSI sequences from strings, so that
+ it is OK to include them in log strings. This would be particularly useful so
+ that our log messages could contain clickable links for example for unit
+ files and suchlike we operate on.
+
+* introduce a new SystemCallFilters= group called "@system-service" with a
+ sensible default set for system services, then make use of them in portable
+ profiles
+
+* add support for "portablectl attach http://foobar.com/waaa.raw (i.e. importd integration)
+
+* add attach --enable and attach --now (for attach+enable+start)
+
+* sync dynamic uids/gids between host+portable srvice (i.e. if DynamicUser=1 is set for a service, make sure that the
+ selected user is resolvable in the service even if it ships its own /etc/passwd)
+
+* Fix DECIMAL_STR_MAX or DECIMAL_STR_WIDTH. One includes a trailing NUL, the
+ other doesn't. What a desaster. Probably to exclude it. Also
+ DECIMAL_STR_WIDTH should probably add an extra "-" into account for negative
+ numbers.
+
+* port systemctl, elogind-inhibit, busctl, … over to format-table.[ch]'s table formatters
+* Check that users of inotify's IN_DELETE_SELF flag are using it properly, as
+ usually IN_ATTRIB is the right way to watch deleted files, as the former only
+ fires when a file is actually removed from disk, i.e. the link count drops to
+ zero and is not open anymore, while the latter happens when a file is
+ unlinked from any dir.
+
+
+* pid1: lock image configured with RootDirectory=/RootImage= using the usual nspawn semantics while the unit is up
+
+* add --vacuum-xyz options to coredumpctl, matching those journalctl already has.
+
+* SuccessExitStatus= and friends should probably also accept symbolic exit
+ codes names, i.e. error codes from the list maintained in exit-codes.[ch]
+
+* introduce Ephemeral= unit file switch, that creates an ephemeral copy of all
+ files and directories that are left writable for a unit, and which are
+ removed after the unit goes down again. A bit like --ephemeral for
+ elogind-nspawn but for system services. If used together with RootImage= this
+ should reflink the image file itself.
+
+ Related: add Ephemeral=<path1> <path2> … which would allow marking
+ specific paths only like this.
+
+* add CopyFile= or so as unit file setting that may be used to copy files or
+ directory trees from the host to te services RootImage= and RootDirectory=
+ environment. Which we can use for /etc/machine-id and in particular
+ /etc/resolv.conf. Should be smart and do something useful on read-only
+ images, for example fallback to read-only bind mounting the file instead.
+
+* nspawn's console TTY should be allocated from within the container, not
+ mounted in from the outside
+
+* show invocation ID in elogind-run output
+
+* bypass SIGTERM state in unit files if KillSignal is SIGKILL
+
+* tree-wide: ensure we always block the signals we hook into with
+ sd_event_add_signal() first
+
+* add proper dbus APIs for the various sd_notify() commands, such as MAINPID=1
+ and so on, which would mean we could report errors and such.
+
+* teach tmpfiles.d q/Q logic something sensible in the context of XFS/ext4
+ project quota
+
+* introduce DefaultSlice= or so in system.conf that allows changing where we
+ place our units by default, i.e. change system.slice to something
+ else. Similar, ManagerSlice= should exist so that PID1's own scope unit could
+ be moved somewhere else too. Finally machined and logind should get similar
+ options so that it is possible to move user session scopes and machines to a
+ different slice too by default. Usecase: people who want to put resources on
+ the entire system, with the exception of one specific service. See:
+ https://lists.freedesktop.org/archives/elogind-devel/2018-February/040369.html
+
+* maybe rework get_user_creds() to query the user database if $SHELL is used
+ for root, but only then.
+
+* be stricter with fds we receive for the fdstore: close them asynchronously
+
+* calenderspec: add support for week numbers and day numbers within a
+ year. This would allow us to define "bi-weekly" triggers safely.
+
+* add bpf-based implementation of devices cgroup controller logic for compat
+ with cgroupsv2 as supported by newest kernel
+
+* introduce sd_id128_get_boot_app_specific() which is like
+ sd_id128_get_machine_app_specific(). After all on long-running systems both
+ IDs have similar properties.
+
+* sd-bus: add vtable flag, that may be used to request client creds implicitly
+ and asynchronously before dispatching the operation
+
+* make use of ethtool veth peer info in machined, for automatically finding out
+ host-side interface pointing to the container.
+
+* add some special mode to LogsDirectory=/StateDirectory=… that allows
+ declaring these directories without necessarily pulling in deps for them, or
+ creating them when starting up. That way, we could declare that
+ systemd-journald writes to /var/log/journal, which could be useful when we
+ doing disk usage calculations and so on.
+
+* taint elogind if there are fewer than 65536 users assigned (userns) to the system.
+
+* deprecate PermissionsStartOnly= and RootDirectoryStartOnly= in favour of the ExecStart= prefix chars
+
+* add a new RuntimeDirectoryPreserve= mode that defines a similar lifecycle for
+ the runtime dir as we maintain for the fdstore: i.e. keep it around as long
+ as the unit is running or has a job queued.
+
+* support projid-based quota in machinectl for containers, and then drop
+ implicit btrfs loopback magic in machined
+
+* Add NetworkNamespacePath= to specify a path to a network namespace
+
+* maybe use SOURCE_DATE_EPOCH (i.e. the env var the reproducible builds folks
+ introduced) as the RTC epoch, instead of the mtime of NEWS.
+
+* add a way to lock down cgroup migration: a boolean, which when set for a unit
+ makes sure the processes in it can never migrate out of it
+
+* blog about fd store and restartable services
+
+* document Environment=SYSTEMD_LOG_LEVEL=debug drop-in in debugging document
+
+* rework ExecOutput and ExecInput enums so that EXEC_OUTPUT_NULL loses its
+ magic meaning and is no longer upgraded to something else if set explicitly.
+
+* in the long run: permit a system with /etc/machine-id linked to /dev/null, to
+ make it lose its identity, i.e. be anonymous. For this we'd have to patch
+ through the whole tree to make all code deal with the case where no machine
+ ID is available.
+
+* optionally, collect cgroup resource data, and store it in per-unit RRD files,
+ suitable for processing with rrdtool. Add bus API to access this data, and
+ possibly implement a CPULoad property based on it.
+
+* beef up pam_systemd to take unit file settings such as cgroups properties as
+ parameters
+
+* a new "systemd-analyze security" tool outputting a checklist of security
+ features a service does and does not implement
+
+* maybe hook of xfs/ext4 quotactl() with services? i.e. automatically manage
+ the quota of a the user indicated in User= via unit file settings, like the
+ other resource management concepts. Would mix nicely with DynamicUser=1. Or
+ alternatively, do this with projids, so that we can also cover services
+ running as root. Quota should probably cover all the special dirs such as
+ StateDirectory=, LogsDirectory=, CacheDirectory=, as well as RootDirectory= if it
+ is set, plus the whole disk space any image configured with RootImage=.
+
+* Introduce "exit" as an EmergencyAction value, and allow to configure a
+ per-unit success/failure exit code to configure. This would be useful for
+ running commands inside of services inside of containers, which could then
+ propagate their failure state all the way up.
+
+* In DynamicUser= mode: before selecting a UID, use disk quota APIs on relevant
+ disks to see if the UID is already in use.
+
+* add "systemctl wait" or so, which does what "systemd-run --wait" does, but
+ for all units. It should be both a way to pin units into memory as well as a
+ wait to retrieve their exit data.
+
+* maybe set a new set of env vars for services, based on RuntimeDirectory=,
+ StateDirectory=, LogsDirectory=, CacheDirectory= and ConfigurationDirectory=
+ automatically. For example, there could be $RUNTIME_DIRECTORY,
+ $STATE_DIRECTORY, $LOGS_DIRECTORY=, $CACHE_DIRECTORY and
+ $CONFIGURATION_DIRECTORY or so. This could be useful to write services that
+ can adapt to varying directories for these purposes. Special care has to be
+ taken if multiple dirs are configured. Maybe avoid setting the env vars in
+ that case?
+
+* expose IO accounting data on the bus, show it in systemd-run --wait and log
+ about it in the resource log message
+
+* add "systemctl purge" for flushing out configuration, state, logs, ... of a
+ unit when it is stopped
+
+* show whether a service has out-of-date configuration in "systemctl status" by
+ using mtime data of ConfigurationDirectory=.
+
+* replace all uses of fgets() + LINE_MAX by read_line()
+
* Add AddUser= setting to unit files, similar to DynamicUser=1 which however
creates a static, persistent user rather than a dynamic, transient user. We
can leverage code from sysusers.d for this.
@@ -33,27 +239,11 @@ Features:
ReadWritePaths=:/var/lib/foobar
-* sort generated hwdb files alphabetically when we import them, so that git
- diffs remain minimal (in particular: the OUI databases we import are not
- sorted, and not stable)
-
-* set SystemCallArchitectures=native on all our services
-
* maybe add call sd_journal_set_block_timeout() or so to set SO_SNDTIMEO for
the sd-journal logging socket, and, if the timeout is set to 0, sets
O_NONBLOCK on it. That way people can control if and when to block for
logging.
-* tighten sd_notify() MAINPID= checks a bit: don't accept foreign PIDs (i.e.
- PIDs not managed by the service manager)
-
-* journald: when we recv a log datagram via the native or syslog transports,
- search for the PID in the active stream connections, and let's make sure to
- always process the datagrams before the streams. Then, cache client metadata
- per stream in the stream object. This way we can somewhat fix the race with
- quickly exiting processes which log as long as they had their own stream
- connection...
-
* hostnamed: populate form factor data from a new hwdb database, so that old
yogas can be recognized as "convertible" too, even if they predate the DMI
"convertible" form factor
@@ -67,15 +257,6 @@ Features:
--as-pid2 switch, and sanely proxy sd_notify() messages dropping stuff such
as MAINPID.
-* change the dependency Set* objects in Unit structures to become Hashmap*, and
- then store a bit mask who created a specific dependency: the source unit via
- fragment configuration, the destination unit via fragment configuration, or
- the source unit via udev rules (in case of .device units), or any combination
- thereof. This information can then be used to flush out old udev-created
- dependencies when the udev properties change, and eventually to implement a
- "systemctl refresh" operation for reloading the configuration of individual
- units without reloading the whole set.
-
* Add ExecMonitor= setting. May be used multiple times. Forks off a process in
the service cgroup, which is supposed to monitor the service, and when it
exits the service is considered failed by its monitor.
@@ -89,16 +270,8 @@ Features:
"systemd-gdb" for attaching to the start-up of any system service in its
natural habitat.
-* replace all canonicalize_file_name() invocations by chase_symlinks(), in
- particulr those where a rootdir is relevant.
-
* maybe introduce gpt auto discovery for /var/tmp?
-* set ProtectSystem=strict for all our usual services.
-
-* fix PrivateNetwork= so that we fall back gracefully on kernels lacking
- namespacing support (similar for the other namespacing options)
-
* maybe add gpt-partition-based user management: each user gets his own
LUKS-encrypted GPT partition with a new GPT type. A small nss module
enumerates users via udev partition enumeration. UIDs are assigned in a fixed
@@ -119,33 +292,20 @@ Features:
partition, that is mounted to / and is writable, and where the actual root's
/usr is mounted into.
-* machined: add apis to query /etc/machine-info data of a container
-
-* .mount and .swap units: add Format=yes|no option that formats the partition before mounting/enabling it, implicitly
-
* gpt-auto logic: support encrypted swap, add kernel cmdline option to force it, and honour a gpt bit about it, plus maybe a configuration file
* drop nss-myhostname in favour of nss-resolve?
-* drop internal dlopen() based nss-dns fallback in nss-resolve, and rely on the
- external nsswitch.conf based one
-
* add a percentage syntax for TimeoutStopSec=, e.g. TimeoutStopSec=150%, and
then use that for the setting used in user@.service. It should be understood
relative to the configured default value.
-* on cgroupsv2 add DelegateControllers=, to pick the precise cgroup controllers to delegate
-
* in networkd, when matching device types, fix up DEVTYPE rubbish the kernel passes to us
* enable LockMLOCK to take a percentage value relative to physical memory
-* switch to ProtectSystem=strict for all our long-running services where that's possible
-
* Permit masking specific netlink APIs with RestrictAddressFamily=
-* nspawn: start UID allocation loop from hash of container name
-
* nspawn: support that /proc, /sys/, /dev are pre-mounted
* define gpt header bits to select volatility mode
@@ -168,9 +328,6 @@ Features:
* DeviceAllow= should also generate seccomp filters for mknod()
-* Add DataDirectory=, CacheDirectory= and LogDirectory= to match
- RuntimeDirectory=, and create it as necessary when starting a service, owned by the right user.
-
* make sure the ratelimit object can deal with USEC_INFINITY as way to turn off things
* journalctl: make sure -f ends when the container indicated by -M terminates
@@ -186,8 +343,6 @@ Features:
a user/group for a service only has to exist on the host for the right
mapping to work.
-* allow attaching additional journald log fields to cgroups
-
* add bus API for creating unit files in /etc, reusing the code for transient units
* add bus API to remove unit files from /etc
@@ -197,8 +352,6 @@ Features:
* rework fopen_temporary() to make use of open_tmpfile_linkable() (problem: the
kernel doesn't support linkat() that replaces existing files, currently)
-* check if DeviceAllow= should split first, resolve specifiers later
-
* transient units: don't bother with actually setting unit properties, we
reload the unit file anyway
@@ -223,8 +376,6 @@ Features:
the specified range and generates sane error messages for incorrect
specifications.
-* do something about "/control" subcgroups in the unified cgroup hierarchy
-
* when we detect that there are waiting jobs but no running jobs, do something
* push CPUAffinity= also into the "cpuset" cgroup controller (only after the cpuset controller got ported to the unified hierarchy)
@@ -236,16 +387,10 @@ Features:
prefixed with /sys generally special.
http://lists.freedesktop.org/archives/systemd-devel/2015-June/032962.html
-* man: document that unless you use StandardError=null the shell >/dev/stderr won't work in shell scripts in services
-
* fstab-generator: default to tmpfs-as-root if only usr= is specified on the kernel cmdline
* docs: bring http://www.freedesktop.org/wiki/Software/systemd/MyServiceCantGetRealtime up to date
-* mounting and unmounting mount points manually with different source
- devices will result in collected on all devices used.
- http://lists.freedesktop.org/archives/systemd-devel/2015-April/030225.html
-
* add a job mode that will fail if a transaction would mean stopping
running units. Use this in timedated to manage the NTP service
state.
@@ -263,13 +408,6 @@ Features:
* networkd/udev: implement SR_IOV configuration in .link files:
http://lists.freedesktop.org/archives/systemd-devel/2015-January/027451.html
-* Rework systemctl's GetAll property parsing to use the generic bus_map_all_properties() API
-
-* implement a per-service firewall based on net_cls
-
-* Port various tools to make use of verbs.[ch], where applicable: busctl,
- coredumpctl, hostnamectl, localectl, systemd-analyze, timedatectl
-
* hostnamectl: show root image uuid
* sysfs set api in libudev is not const
@@ -303,8 +441,6 @@ Features:
* introduce systemd-timesync-wait.service or so to sync on an NTP fix?
-* systemd --user should issue sd_notify() upon reaching basic.target, not on becoming idle
-
* consider showing the unit names during boot up in the status output, not just the unit descriptions
* maybe allow timer units with an empty Units= setting, so that they
@@ -312,8 +448,6 @@ Features:
* what to do about udev db binary stability for apps? (raw access is not an option)
-* maybe provide an API to allow migration of foreign PIDs into existing scopes.
-
* man: maybe use the word "inspect" rather than "introspect"?
* systemctl: if some operation fails, show log output?
@@ -360,8 +494,6 @@ Features:
* figure out a nice way how we can let the admin know what child/sibling unit causes cgroup membership for a specific unit
-* mount_cgroup_controllers(): symlinks need to get the label applied
-
* For timer units: add some mechanisms so that timer units that trigger immediately on boot do not have the services
they run added to the initial transaction and thus confuse Type=idle.
@@ -405,7 +537,6 @@ Features:
* transient units:
- add field to transient units that indicate whether systemd or somebody else saves/restores its settings, for integration with libvirt
- - ensure scope units may be started only a single time
* Automatically configure swap partition to use for hibernation by looking for largest swap partition on the root disk?
@@ -435,32 +566,23 @@ Features:
* sd-bus:
- EBADSLT handling
- GetAllProperties() on a non-existing object does not result in a failure currently
- - kdbus: process fd=-1 for incoming msgs
- port to sd-resolve for connecting to TCP dbus servers
- - kdbus: maybe add controlling tty metadata fields
- see if we can introduce a new sd_bus_get_owner_machine_id() call to retrieve the machine ID of the machine of the bus itself
- - when kdbus does not take our message without memfds, try again with memfds
- see if we can drop more message validation on the sending side
- add API to clone sd_bus_message objects
- - make AddMatch calls on dbus1 transports async?
- - kdbus: matches against source or destination pids for an "strace -p"-like feel. Problem: The PID info needs to be available in userspace too...
- longer term: priority inheritance
- dbus spec updates:
- - kdbus mapping
- NameLost/NameAcquired obsolete
- GVariant
- path escaping
- update systemd.special(7) to mention that dbus.socket is only about the compatibility socket now
- - test bloom filter generation indexes
- - kdbus: introduce a concept of "send-only" connections
- - kdbus: add counter for refused unicast messages that is passed out via the RECV ioctl. SImilar to the counter for dropped multicast messages we already have.
* sd-event
- allow multiple signal handlers per signal?
- document chaining of signal handler for SIGCHLD and child handlers
- define more intervals where we will shift wakeup intervals around in, 1h, 6h, 24h, ...
- generate a failure of a default event loop is executed out-of-thread
- - maybe add support for inotify events
+ - maybe add support for inotify events (which we can do safely now, with O_PATH)
* investigate endianness issues of UUID vs. GUID
@@ -473,11 +595,8 @@ Features:
* maybe add a generator that looks for "systemd.run=" on the kernel cmdline for container usercases...
-* cgtop: make cgtop useful in a container
-
* test/:
- - add 'set -e' to scripts in test/
- - make stuff in test/ work with separate output dir
+ - add unit tests for config_parse_device_allow()
* seems that when we follow symlinks to units we prefer the symlink
destination path over /etc and /usr. We should not do that. Instead
@@ -505,8 +624,6 @@ Features:
* shutdown logging: store to EFI var, and store to USB stick?
-* think about window-manager-run-as-user-service problem: exit 0 → activate shutdown.target; exit != 0 → restart service
-
* merge unit_kill_common() and unit_kill_context()
* introduce ExecCondition= in services
@@ -528,7 +645,6 @@ Features:
- logind: wakelock/opportunistic suspend support
- Add pretty name for seats in logind
- logind: allow showing logout dialog from system?
- - we should probably handle SIGTERM/SIGINT to not leave dot files around, just in case
- session scopes/user unit: add RequiresMountsFor for the home directory of the user
- add Suspend() bus calls which take timestamps to fix double suspend issues when somebody hits suspend and closes laptop quickly.
- if pam_systemd is invoked by su from a process that is outside of a
@@ -543,10 +659,6 @@ Features:
logout dialog. If it is pressed for 1s, do the usual
shutdown. Inspiration are Macs here.
- expose "Locked" property on logind sesison objects
- - given that logind now lets PID 1 do all nasty work, we can
- probably reduce the capability set it retains substantially.
- (we need CAP_SYS_ADMIN for drmSetMaster(), so maybe not worth it)
- - expose orientation sensors and tablet mode through logind
- maybe allow configuration of the StopTimeout for session scopes
- rename session scope so that it includes the UID. THat way
the session scope can be arranged freely in slices and we don't have
@@ -556,8 +668,6 @@ Features:
* exec: when deinitializating a tty device fix the perms and group, too, not only when initializing. Set access mode/gid to 0620/tty.
-* service: watchdog logic: for testing purposes allow ping, but do not require pong
-
* journal:
- consider introducing implicit _TTY= + _PPID= + _EUID= + _EGID= + _FSUID= + _FSGID= fields
- import and delete pstore filesystem content at startup
@@ -592,7 +702,6 @@ Features:
- journald: when we drop syslog messages because the syslog socket is
full, make sure to write how many messages are lost as first thing
to syslog when it works again.
- - journald: make sure ratelimit is actually really per-service with the new cgroup changes
- change systemd-journal-flush into a service that stays around during
boot, and causes the journal to be moved back to /run on shutdown,
so that we do not keep /var busy. This needs to happen synchronously,
@@ -606,8 +715,6 @@ Features:
lazily. Encode just enough information in the file name, so that we
do not have to open it to know that it is not interesting for us, for
the most common operations.
- - journal-or-kmsg is currently broken? See reverted
- commit 4a01181e460686d8b4a543b1dfa7f77c9e3c5ab8.
- man: document that corrupted journal files is nothing to act on
- rework journald sigbus stuff to use mutex
- Set RLIMIT_NPROC for systemd-journal-xyz, and all other of our
@@ -621,19 +728,21 @@ Features:
- add journalctl -H that talks via ssh to a remote peer and passes through
binary logs data
- add a version of --merge which also merges /var/log/journal/remote
- - log accumulated resource usage after each service invocation
- journalctl: -m should access container journals directly by enumerating
them via machined, and also watch containers coming and going.
Benefit: nspawn --ephemeral would start working nicely with the journal.
- assign MESSAGE_ID to log messages about failed services
+* add a test if all entries in the catalog are properly formatted.
+ (Adding dashes in a catalog entry currently results in the catalog entry
+ being silently skipped. journalctl --update-catalog must warn about this,
+ and we should also have a unit test to check that all our message are OK.)
+
* document:
- document that deps in [Unit] sections ignore Alias= fields in
[Install] units of other units, unless those units are disabled
- man: clarify that time-sync.target is not only sysv compat but also useful otherwise. Same for similar targets
- - document the exit codes when services fail before they are exec()ed
- document that service reload may be implemented as service reexec
- - document in wiki how to map ical recurrence events to systemd timer unit calendar specifications
- add a man page containing packaging guidelines and recommending usage of things like Documentation=, PrivateTmp=, PrivateNetwork= and ReadOnlyDirectories=/etc /usr.
- document systemd-journal-flush.service properly
- documentation: recommend to connect the timer units of a service to the service via Also= in [Install]
@@ -651,7 +760,6 @@ Features:
- add new command to systemctl: "systemctl system-reexec" which reexecs as many daemons as virtually possible
- systemctl enable: fail if target to alias into does not exist? maybe show how many units are enabled afterwards?
- systemctl: "Journal has been rotated since unit was started." message is misleading
- - better error message if you run systemctl without systemd running
- systemctl status output should include list of triggering units and their status
* unit install:
@@ -662,6 +770,7 @@ Features:
- timer units should get the ability to trigger when:
o CLOCK_REALTIME makes jumps (TFD_TIMER_CANCEL_ON_SET)
o DST changes
+ o timezone changes
- Modulate timer frequency based on battery state
* add libsystemd-password or so to query passwords during boot using the password agent logic
@@ -691,11 +800,8 @@ Features:
https://github.com/systemd/systemd/pull/272#issuecomment-113153176
- should optionally support receiving WATCHDOG=1 messages from its payload
PID 1...
- - should send out sd_notify("WATCHDOG=1") messages
- optionally automatically add FORWARD rules to iptables whenever nspawn is
running, remove them when shut down.
- - Improve error message when --bind= is used on a non-existing source
- directory
- maybe make copying of /etc/resolv.conf optional, and skip it if --read-only
is used
@@ -724,14 +830,12 @@ Features:
* cryptsetup:
- cryptsetup-generator: allow specification of passwords in crypttab itself
- - move cryptsetup key caching into kernel keyctl?
- https://bugs.freedesktop.org/show_bug.cgi?id=54982
- support rd.luks.allow-discards= kernel cmdline params in cryptsetup generator
* hw watchdog: optionally try to use the preset watchdog timeout instead of always overriding it
https://bugs.freedesktop.org/show_bug.cgi?id=54712
-* create /sbin/init symlinks from the build system
+* add a dependency on standard-conf.xml and other included files to man pages
* MountFlags=shared acts as MountFlags=slave right now.
@@ -745,8 +849,6 @@ Features:
- add trigger --subsystem-match=usb/usb_device device
- reimport udev db after MOVE events for devices without dev_t
-* when a service has the same env var set twice we actually store it twice and return that in systemctl show -p... We should only show the last setting
-
* There's currently no way to cancel fsck (used to be possible via C-c or c on the console)
* add option to sockets to avoid activation. Instead just drop packets/connections, see http://cyberelk.net/tim/2012/02/15/portreserve-systemd-solution/
@@ -784,7 +886,6 @@ Features:
* write blog stories about:
- hwdb: what belongs into it, lsusb
- enabling dbus services
- - status update
- how to make changes to sysctl and sysfs attributes
- remote access
- how to pass throw-away units to systemd, or dynamically change properties of existing units
@@ -805,10 +906,7 @@ Features:
* dot output for --test showing the 'initial transaction'
-* fingerprint.target, wireless.target, gps.target, netdevice.target
-
* pid1:
- - .timer units should optionally support CLOCK_BOOTTIME in addition to CLOCK_MONOTONIC
- When logging about multiple units (stopping BoundTo units, conflicts, etc.),
log both units as UNIT=, so that journalctl -u triggers on both.
- generate better errors when people try to set transient properties
@@ -844,12 +942,9 @@ Features:
- load-fragment: when loading a unit file via a chain of symlinks
verify that it is not masked via any of the names traversed.
- introduce Type=pid-file
- - ExecOnFailure=/usr/bin/foo
- introduce mix of BindTo and Requisite
- add a concept of RemainAfterExit= to scope units
- - Set NoNewPrivileges= on all of our own services, where that makes sense
- Allow multiple ExecStart= for all Type= settings, so that we can cover rescue.service nicely
- - consider adding RuntimeDirectoryUser= + RuntimeDirectoryGroup=
* udev-link-config:
- Make sure ID_PATH is always exported and complete for
@@ -891,7 +986,6 @@ Features:
* dhcp:
- figure out how much we can increase Maximum Message Size
- - support RFC4702 (pass FQDN)
* dhcp6:
- add functions to set previously stored IPv6 addresses on startup and get
@@ -923,8 +1017,6 @@ External:
* drop accountsservice's StandardOutput=syslog and Type=dbus fields
-* dbus: in fedora, make /var/lib/dbus/machine-id a symlink to /etc/machine-id
-
* /usr/bin/service should actually show the new command line
* fedora: suggest auto-restart on failure, but not on success and not on coredump. also, ask people to think about changing the start limit logic. Also point people to RestartPreventExitStatus=, SuccessExitStatus=
@@ -948,8 +1040,6 @@ Regularly:
* check for strerror(r) instead of strerror(-r)
-* Use PR_SET_PROCTITLE_AREA if it becomes available in the kernel
-
* pahole
* set_put(), hashmap_put() return values check. i.e. == 0 does not free()!
diff --git a/autogen.sh b/autogen.sh
deleted file mode 100755
index 7f9bbfc16..000000000
--- a/autogen.sh
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/bin/sh
-
-# This file is part of elogind
-#
-# elogind is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# elogind is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with elogind; If not, see <http://www.gnu.org/licenses/>.
-
-set -e
-
-oldpwd=$(pwd)
-topdir=$(dirname $0)
-cd $topdir
-
-intltoolize --force --automake
-autoreconf --force --install --symlink
-
-libdir() {
- echo $(cd "$1/$(gcc -print-multi-os-directory)"; pwd)
-}
-
-args="\
---sysconfdir=/etc \
---localstatedir=/var \
---libdir=$(libdir /usr/lib) \
-"
-
-if [ -f "$topdir/.config.args" ]; then
- args="$args $(cat $topdir/.config.args)"
-fi
-
-if [ ! -L /bin ]; then
-args="$args \
---with-rootprefix=/ \
---with-rootlibdir=$(libdir /lib) \
-"
-fi
-
-cd $oldpwd
-
-echo
-echo "----------------------------------------------------------------"
-echo "Initialized build system. For a common configuration please run:"
-echo "----------------------------------------------------------------"
-echo
-echo "$topdir/configure CFLAGS='-g -O0 -ftrapv' --enable-kdbus $args"
-echo
diff --git a/cb/elogind.cbp b/cb/elogind.cbp
index 818c48570..f612e9176 100644
--- a/cb/elogind.cbp
+++ b/cb/elogind.cbp
@@ -29,14 +29,123 @@
<Add option="-s" />
</Linker>
</Target>
+ <Target title="test">
+ <Option output="../build/test-login" prefix_auto="1" extension_auto="1" />
+ <Option working_dir="../../elogind" />
+ <Option type="1" />
+ <Option compiler="gcc" />
+ <Option parameters="-m" />
+ </Target>
+ <Target title="test-login">
+ <Option output="../build/test-login" prefix_auto="1" extension_auto="1" />
+ <Option working_dir="../../elogind" />
+ <Option type="1" />
+ <Option compiler="gcc" />
+ <Option parameters="-m" />
+ </Target>
+ <Target title="loginctl">
+ <Option output="../build/loginctl" prefix_auto="1" extension_auto="1" />
+ <Option working_dir="../../elogind" />
+ <Option type="1" />
+ <Option compiler="gcc" />
+ <Option parameters="enable-linger sed" />
+ </Target>
</Build>
<Compiler>
<Add option="-Wall" />
</Compiler>
- <Unit filename="../Makefile.am" />
- <Unit filename="../config.h.in" />
- <Unit filename="../configure.ac" />
- <Unit filename="../po/Makefile.in.in" />
+ <Unit filename="../man/custom-entities.ent.in" />
+ <Unit filename="../man/custom-html.xsl" />
+ <Unit filename="../man/custom-man.xsl" />
+ <Unit filename="../man/elogind.syntax.xml" />
+ <Unit filename="../man/elogind.xml" />
+ <Unit filename="../man/glib-event-glue.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="../man/less-variables.xml" />
+ <Unit filename="../man/libelogind-pkgconfig.xml" />
+ <Unit filename="../man/loginctl.xml" />
+ <Unit filename="../man/logind.conf.xml" />
+ <Unit filename="../man/meson.build" />
+ <Unit filename="../man/pam_elogind.xml" />
+ <Unit filename="../man/sd-bus.xml" />
+ <Unit filename="../man/sd-event.xml" />
+ <Unit filename="../man/sd-login.xml" />
+ <Unit filename="../man/sd_booted.xml" />
+ <Unit filename="../man/sd_bus_add_match.xml" />
+ <Unit filename="../man/sd_bus_creds_get_pid.xml" />
+ <Unit filename="../man/sd_bus_creds_new_from_pid.xml" />
+ <Unit filename="../man/sd_bus_default.xml" />
+ <Unit filename="../man/sd_bus_error.xml" />
+ <Unit filename="../man/sd_bus_error_add_map.xml" />
+ <Unit filename="../man/sd_bus_get_fd.xml" />
+ <Unit filename="../man/sd_bus_is_open.xml" />
+ <Unit filename="../man/sd_bus_message_append.xml" />
+ <Unit filename="../man/sd_bus_message_append_array.xml" />
+ <Unit filename="../man/sd_bus_message_append_basic.xml" />
+ <Unit filename="../man/sd_bus_message_append_string_memfd.xml" />
+ <Unit filename="../man/sd_bus_message_append_strv.xml" />
+ <Unit filename="../man/sd_bus_message_get_cookie.xml" />
+ <Unit filename="../man/sd_bus_message_get_monotonic_usec.xml" />
+ <Unit filename="../man/sd_bus_message_read_basic.xml" />
+ <Unit filename="../man/sd_bus_negotiate_fds.xml" />
+ <Unit filename="../man/sd_bus_new.xml" />
+ <Unit filename="../man/sd_bus_path_encode.xml" />
+ <Unit filename="../man/sd_bus_process.xml" />
+ <Unit filename="../man/sd_bus_request_name.xml" />
+ <Unit filename="../man/sd_bus_set_connected_signal.xml" />
+ <Unit filename="../man/sd_bus_set_sender.xml" />
+ <Unit filename="../man/sd_bus_set_watch_bind.xml" />
+ <Unit filename="../man/sd_bus_slot_set_destroy_callback.xml" />
+ <Unit filename="../man/sd_bus_slot_set_floating.xml" />
+ <Unit filename="../man/sd_bus_track_add_name.xml" />
+ <Unit filename="../man/sd_bus_track_new.xml" />
+ <Unit filename="../man/sd_event_add_child.xml" />
+ <Unit filename="../man/sd_event_add_defer.xml" />
+ <Unit filename="../man/sd_event_add_inotify.xml" />
+ <Unit filename="../man/sd_event_add_io.xml" />
+ <Unit filename="../man/sd_event_add_signal.xml" />
+ <Unit filename="../man/sd_event_add_time.xml" />
+ <Unit filename="../man/sd_event_exit.xml" />
+ <Unit filename="../man/sd_event_get_fd.xml" />
+ <Unit filename="../man/sd_event_new.xml" />
+ <Unit filename="../man/sd_event_now.xml" />
+ <Unit filename="../man/sd_event_run.xml" />
+ <Unit filename="../man/sd_event_set_watchdog.xml" />
+ <Unit filename="../man/sd_event_source_get_event.xml" />
+ <Unit filename="../man/sd_event_source_get_pending.xml" />
+ <Unit filename="../man/sd_event_source_set_description.xml" />
+ <Unit filename="../man/sd_event_source_set_destroy_callback.xml" />
+ <Unit filename="../man/sd_event_source_set_enabled.xml" />
+ <Unit filename="../man/sd_event_source_set_prepare.xml" />
+ <Unit filename="../man/sd_event_source_set_priority.xml" />
+ <Unit filename="../man/sd_event_source_set_userdata.xml" />
+ <Unit filename="../man/sd_event_source_unref.xml" />
+ <Unit filename="../man/sd_event_wait.xml" />
+ <Unit filename="../man/sd_get_seats.xml" />
+ <Unit filename="../man/sd_id128_get_machine.xml" />
+ <Unit filename="../man/sd_id128_randomize.xml" />
+ <Unit filename="../man/sd_id128_to_string.xml" />
+ <Unit filename="../man/sd_is_fifo.xml" />
+ <Unit filename="../man/sd_listen_fds.xml" />
+ <Unit filename="../man/sd_login_monitor_new.xml" />
+ <Unit filename="../man/sd_machine_get_class.xml" />
+ <Unit filename="../man/sd_notify.xml" />
+ <Unit filename="../man/sd_pid_get_owner_uid.xml" />
+ <Unit filename="../man/sd_seat_get_active.xml" />
+ <Unit filename="../man/sd_session_is_active.xml" />
+ <Unit filename="../man/sd_uid_get_state.xml" />
+ <Unit filename="../man/sd_watchdog_enabled.xml" />
+ <Unit filename="../man/standard-options.xml" />
+ <Unit filename="../man/user-system-options.xml" />
+ <Unit filename="../meson.build">
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../meson_options.txt">
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
<Unit filename="../src/basic/alloc-util.c">
<Option compilerVar="CC" />
</Unit>
@@ -50,6 +159,10 @@
<Option compilerVar="CC" />
</Unit>
<Unit filename="../src/basic/bus-label.h" />
+ <Unit filename="../src/basic/cap-list.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="../src/basic/cap-list.h" />
<Unit filename="../src/basic/capability-util.c">
<Option compilerVar="CC" />
</Unit>
@@ -103,6 +216,10 @@
<Option compilerVar="CC" />
</Unit>
<Unit filename="../src/basic/fileio.h" />
+ <Unit filename="../src/basic/format-table.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="../src/basic/format-table.h" />
<Unit filename="../src/basic/format-util.h" />
<Unit filename="../src/basic/fs-util.c">
<Option compilerVar="CC" />
@@ -162,6 +279,10 @@
<Option compilerVar="CC" />
</Unit>
<Unit filename="../src/basic/mempool.h" />
+ <Unit filename="../src/basic/meson.build">
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
<Unit filename="../src/basic/missing.h" />
<Unit filename="../src/basic/missing_syscall.h" />
<Unit filename="../src/basic/mkdir-label.c">
@@ -175,6 +296,14 @@
<Option compilerVar="CC" />
</Unit>
<Unit filename="../src/basic/mount-util.h" />
+ <Unit filename="../src/basic/os-util.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="../src/basic/os-util.h" />
+ <Unit filename="../src/basic/pager.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="../src/basic/pager.h" />
<Unit filename="../src/basic/parse-printf-format.c">
<Option compilerVar="CC" />
</Unit>
@@ -199,10 +328,15 @@
<Option compilerVar="CC" />
</Unit>
<Unit filename="../src/basic/process-util.h" />
+ <Unit filename="../src/basic/procfs-util.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="../src/basic/procfs-util.h" />
<Unit filename="../src/basic/random-util.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="../src/basic/random-util.h" />
+ <Unit filename="../src/basic/raw-clone.h" />
<Unit filename="../src/basic/refcnt.h" />
<Unit filename="../src/basic/rm-rf.c">
<Option compilerVar="CC" />
@@ -213,6 +347,10 @@
</Unit>
<Unit filename="../src/basic/selinux-util.h" />
<Unit filename="../src/basic/set.h" />
+ <Unit filename="../src/basic/sigbus.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="../src/basic/sigbus.h" />
<Unit filename="../src/basic/signal-util.c">
<Option compilerVar="CC" />
</Unit>
@@ -230,6 +368,7 @@
</Unit>
<Unit filename="../src/basic/socket-util.h" />
<Unit filename="../src/basic/sparse-endian.h" />
+ <Unit filename="../src/basic/special.h" />
<Unit filename="../src/basic/stat-util.c">
<Option compilerVar="CC" />
</Unit>
@@ -261,6 +400,10 @@
<Unit filename="../src/basic/time-util.h" />
<Unit filename="../src/basic/umask-util.h" />
<Unit filename="../src/basic/unaligned.h" />
+ <Unit filename="../src/basic/unit-def.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="../src/basic/unit-def.h" />
<Unit filename="../src/basic/unit-name.c">
<Option compilerVar="CC" />
</Unit>
@@ -291,136 +434,276 @@
<Unit filename="../src/basic/xattr-util.h" />
<Unit filename="../src/cgroups-agent/cgroups-agent.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
<Unit filename="../src/core/cgroup.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/core/cgroup.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/core/cgroup.h" />
+ <Unit filename="../src/core/meson.build" />
<Unit filename="../src/core/mount-setup.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/core/mount-setup.h" />
- <Unit filename="../src/libelogind/libelogind.sym" />
- <Unit filename="../src/libelogind/sd-bus/bus-bloom.c">
- <Option compilerVar="CC" />
+ <Unit filename="../src/core/mount-setup.h">
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/libelogind/libelogind.sym">
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/libelogind/meson.build">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/libelogind/sd-bus/bus-bloom.h" />
<Unit filename="../src/libelogind/sd-bus/bus-common-errors.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/libelogind/sd-bus/bus-common-errors.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/libelogind/sd-bus/bus-common-errors.h" />
<Unit filename="../src/libelogind/sd-bus/bus-container.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/libelogind/sd-bus/bus-container.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/libelogind/sd-bus/bus-container.h" />
<Unit filename="../src/libelogind/sd-bus/bus-control.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/libelogind/sd-bus/bus-control.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/libelogind/sd-bus/bus-control.h" />
<Unit filename="../src/libelogind/sd-bus/bus-convenience.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
<Unit filename="../src/libelogind/sd-bus/bus-creds.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/libelogind/sd-bus/bus-creds.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/libelogind/sd-bus/bus-creds.h" />
<Unit filename="../src/libelogind/sd-bus/bus-error.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/libelogind/sd-bus/bus-error.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/libelogind/sd-bus/bus-error.h" />
<Unit filename="../src/libelogind/sd-bus/bus-gvariant.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/libelogind/sd-bus/bus-gvariant.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/libelogind/sd-bus/bus-gvariant.h" />
<Unit filename="../src/libelogind/sd-bus/bus-internal.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/libelogind/sd-bus/bus-internal.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/libelogind/sd-bus/bus-internal.h" />
<Unit filename="../src/libelogind/sd-bus/bus-introspect.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/libelogind/sd-bus/bus-introspect.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/libelogind/sd-bus/bus-introspect.h" />
<Unit filename="../src/libelogind/sd-bus/bus-kernel.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/libelogind/sd-bus/bus-kernel.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/libelogind/sd-bus/bus-kernel.h" />
<Unit filename="../src/libelogind/sd-bus/bus-match.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/libelogind/sd-bus/bus-match.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/libelogind/sd-bus/bus-match.h" />
<Unit filename="../src/libelogind/sd-bus/bus-message.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/libelogind/sd-bus/bus-message.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/libelogind/sd-bus/bus-message.h" />
<Unit filename="../src/libelogind/sd-bus/bus-objects.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/libelogind/sd-bus/bus-objects.h">
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/libelogind/sd-bus/bus-protocol.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/libelogind/sd-bus/bus-objects.h" />
- <Unit filename="../src/libelogind/sd-bus/bus-protocol.h" />
<Unit filename="../src/libelogind/sd-bus/bus-signature.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/libelogind/sd-bus/bus-signature.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/libelogind/sd-bus/bus-signature.h" />
<Unit filename="../src/libelogind/sd-bus/bus-slot.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/libelogind/sd-bus/bus-slot.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/libelogind/sd-bus/bus-slot.h" />
<Unit filename="../src/libelogind/sd-bus/bus-socket.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/libelogind/sd-bus/bus-socket.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/libelogind/sd-bus/bus-socket.h" />
<Unit filename="../src/libelogind/sd-bus/bus-track.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/libelogind/sd-bus/bus-track.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/libelogind/sd-bus/bus-track.h" />
<Unit filename="../src/libelogind/sd-bus/bus-type.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/libelogind/sd-bus/bus-type.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/libelogind/sd-bus/bus-type.h" />
- <Unit filename="../src/libelogind/sd-bus/kdbus.h" />
<Unit filename="../src/libelogind/sd-bus/sd-bus.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
<Unit filename="../src/libelogind/sd-bus/test-bus-error.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
<Unit filename="../src/libelogind/sd-bus/test-bus-introspect.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
<Unit filename="../src/libelogind/sd-bus/test-bus-match.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
<Unit filename="../src/libelogind/sd-bus/test-bus-server.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
<Unit filename="../src/libelogind/sd-bus/test-bus-signature.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
<Unit filename="../src/libelogind/sd-bus/test-bus-vtable.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
<Unit filename="../src/libelogind/sd-daemon/sd-daemon.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
<Unit filename="../src/libelogind/sd-event/sd-event.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
<Unit filename="../src/libelogind/sd-event/test-event.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
<Unit filename="../src/libelogind/sd-id128/id128-util.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/libelogind/sd-id128/id128-util.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/libelogind/sd-id128/id128-util.h" />
<Unit filename="../src/libelogind/sd-id128/sd-id128.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
<Unit filename="../src/libelogind/sd-login/sd-login.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
<Unit filename="../src/libelogind/sd-login/test-login.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
+ <Unit filename="../src/login/70-power-switch.rules" />
+ <Unit filename="../src/login/70-uaccess.rules" />
+ <Unit filename="../src/login/71-seat.rules.in" />
+ <Unit filename="../src/login/73-seat-late.rules.in" />
<Unit filename="../src/login/eloginctl.c">
<Option compilerVar="CC" />
</Unit>
@@ -461,10 +744,10 @@
<Option compilerVar="CC" />
</Unit>
<Unit filename="../src/login/logind-device.h" />
- <Unit filename="../src/login/logind-gperf.c">
- <Option compilerVar="CC" />
+ <Unit filename="../src/login/logind-gperf.gperf">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/login/logind-gperf.gperf" />
<Unit filename="../src/login/logind-inhibit.c">
<Option compilerVar="CC" />
</Unit>
@@ -500,8 +783,17 @@
<Unit filename="../src/login/logind.c">
<Option compilerVar="CC" />
</Unit>
- <Unit filename="../src/login/logind.conf.in" />
+ <Unit filename="../src/login/logind.conf.in">
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
<Unit filename="../src/login/logind.h" />
+ <Unit filename="../src/login/meson.build">
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/login/org.freedesktop.login1.conf" />
+ <Unit filename="../src/login/org.freedesktop.login1.policy" />
<Unit filename="../src/login/pam_elogind.c">
<Option compilerVar="CC" />
</Unit>
@@ -518,71 +810,166 @@
<Unit filename="../src/login/test-login-tables.c">
<Option compilerVar="CC" />
</Unit>
+ <Unit filename="../src/login/user-runtime-dir.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="../src/login/user-runtime-dir.h" />
<Unit filename="../src/shared/acl-util.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/shared/acl-util.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/shared/acl-util.h" />
<Unit filename="../src/shared/bus-util.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/shared/bus-util.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/shared/bus-util.h" />
<Unit filename="../src/shared/clean-ipc.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/shared/clean-ipc.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/shared/clean-ipc.h" />
<Unit filename="../src/shared/conf-parser.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/shared/conf-parser.h">
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/shared/libshared.sym">
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/shared/meson.build">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/shared/conf-parser.h" />
<Unit filename="../src/shared/musl_missing.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/shared/musl_missing.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/shared/musl_missing.h" />
<Unit filename="../src/shared/nsflags.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/shared/nsflags.h" />
- <Unit filename="../src/shared/pager.c">
- <Option compilerVar="CC" />
+ <Unit filename="../src/shared/nsflags.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/shared/pager.h" />
<Unit filename="../src/shared/sleep-config.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/shared/sleep-config.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/shared/sleep-config.h" />
<Unit filename="../src/shared/spawn-polkit-agent.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/shared/spawn-polkit-agent.h" />
- <Unit filename="../src/shared/test-tables.h" />
- <Unit filename="../src/shared/tests.c">
- <Option compilerVar="CC" />
+ <Unit filename="../src/shared/spawn-polkit-agent.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/shared/tests.h" />
- <Unit filename="../src/shared/udev-util.c">
- <Option compilerVar="CC" />
+ <Unit filename="../src/shared/test-tables.h">
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/shared/udev-util.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/shared/udev-util.h" />
<Unit filename="../src/shared/utmp-wtmp.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/shared/utmp-wtmp.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/shared/utmp-wtmp.h" />
<Unit filename="../src/sleep/sleep.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/sleep/sleep.h">
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/systemd/_sd-common.h">
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/systemd/meson.build">
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/systemd/sd-bus-protocol.h">
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/systemd/sd-bus-vtable.h">
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/systemd/sd-bus.h">
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/systemd/sd-daemon.h">
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/systemd/sd-event.h">
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/systemd/sd-id128.h">
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/systemd/sd-login.h">
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/systemd/sd-messages.h">
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/test/meson.build">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/sleep/sleep.h" />
- <Unit filename="../src/systemd/_sd-common.h" />
- <Unit filename="../src/systemd/sd-bus-protocol.h" />
- <Unit filename="../src/systemd/sd-bus-vtable.h" />
- <Unit filename="../src/systemd/sd-bus.h" />
- <Unit filename="../src/systemd/sd-daemon.h" />
- <Unit filename="../src/systemd/sd-event.h" />
- <Unit filename="../src/systemd/sd-id128.h" />
- <Unit filename="../src/systemd/sd-login.h" />
- <Unit filename="../src/systemd/sd-messages.h" />
<Unit filename="../src/test/test-alloc-util.c">
<Option compilerVar="CC" />
</Unit>
+ <Unit filename="../src/test/test-bus-util.c">
+ <Option compilerVar="CC" />
+ </Unit>
<Unit filename="../src/test/test-cgroup.c">
<Option compilerVar="CC" />
</Unit>
@@ -595,6 +982,9 @@
<Unit filename="../src/test/test-copy.c">
<Option compilerVar="CC" />
</Unit>
+ <Unit filename="../src/test/test-dlopen.c">
+ <Option compilerVar="CC" />
+ </Unit>
<Unit filename="../src/test/test-ellipsize.c">
<Option compilerVar="CC" />
</Unit>
@@ -610,6 +1000,9 @@
<Unit filename="../src/test/test-fd-util.c">
<Option compilerVar="CC" />
</Unit>
+ <Unit filename="../src/test/test-format-table.c">
+ <Option compilerVar="CC" />
+ </Unit>
<Unit filename="../src/test/test-fs-util.c">
<Option compilerVar="CC" />
</Unit>
@@ -618,6 +1011,8 @@
</Unit>
<Unit filename="../src/test/test-hashmap-ordered.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
<Unit filename="../src/test/test-hashmap-plain.c">
<Option compilerVar="CC" />
@@ -647,6 +1042,9 @@
<Unit filename="../src/test/test-log.c">
<Option compilerVar="CC" />
</Unit>
+ <Unit filename="../src/test/test-os-util.c">
+ <Option compilerVar="CC" />
+ </Unit>
<Unit filename="../src/test/test-parse-util.c">
<Option compilerVar="CC" />
</Unit>
@@ -662,6 +1060,9 @@
<Unit filename="../src/test/test-process-util.c">
<Option compilerVar="CC" />
</Unit>
+ <Unit filename="../src/test/test-procfs-util.c">
+ <Option compilerVar="CC" />
+ </Unit>
<Unit filename="../src/test/test-random-util.c">
<Option compilerVar="CC" />
</Unit>
@@ -704,10 +1105,19 @@
<Unit filename="../src/test/test-verbs.c">
<Option compilerVar="CC" />
</Unit>
+ <Unit filename="../src/update-utmp/meson.build">
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
<Unit filename="../src/update-utmp/update-utmp.c">
<Option compilerVar="CC" />
+ <Option target="all" />
+ <Option target="clean" />
+ </Unit>
+ <Unit filename="../src/update-utmp/update-utmp.h">
+ <Option target="all" />
+ <Option target="clean" />
</Unit>
- <Unit filename="../src/update-utmp/update-utmp.h" />
<Extensions>
<envvars />
<code_completion />
diff --git a/configure b/configure
new file mode 100755
index 000000000..a9db8a1cf
--- /dev/null
+++ b/configure
@@ -0,0 +1,21 @@
+#!/bin/bash -e
+
+cflags=CFLAGS="$CFLAGS"
+cxxflags=CXXFLAGS="$CXXFLAGS"
+declare -a args
+j=0
+for i in "$@"; do
+ case "$i" in
+ CFLAGS=*)
+ cflags="$i";;
+ CXXFLAGS=*)
+ cxxflags="$i";;
+ *)
+ args[$j]="$i"
+ j=$((j+1))
+ esac
+done
+
+export "$cflags" "$cxxflags"
+set -x
+exec meson build "${args[@]}"
diff --git a/configure.ac b/configure.ac
deleted file mode 100644
index c0ad243d2..000000000
--- a/configure.ac
+++ /dev/null
@@ -1,906 +0,0 @@
-#
-# This file is part of elogind.
-#
-# Copyright 2010-2012 Lennart Poettering
-# Copyright 2010-2012 Kay Sievers
-#
-# elogind is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# elogind is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-
-AC_PREREQ([2.64])
-
-AC_INIT([elogind],
- [234.4],
- [https://github.com/elogind/elogind/issues],
- [elogind],
- [https://github.com/elogind/elogind])
-
-AC_CONFIG_SRCDIR([src/login/logind.c])
-AC_CONFIG_MACRO_DIR([m4])
-AC_CONFIG_HEADERS([config.h])
-AC_CONFIG_AUX_DIR([build-aux])
-
-AC_USE_SYSTEM_EXTENSIONS
-AC_SYS_LARGEFILE
-AC_PREFIX_DEFAULT([/usr])
-AM_MAINTAINER_MODE([enable])
-AM_INIT_AUTOMAKE([foreign 1.11 -Wall -Wno-portability silent-rules tar-pax no-dist-gzip dist-xz subdir-objects parallel-tests])
-AM_SILENT_RULES([yes])
-AC_CANONICAL_HOST
-AC_DEFINE_UNQUOTED([CANONICAL_HOST], "$host", [Canonical host string.])
-
-AC_PROG_CC_C99
-
-AX_COMPILER_VENDOR
-AS_IF([test "x$ax_cv_c_compiler_vendor" = "xgnu"], [
- AC_CHECK_TOOLS([AR], [gcc-ar ar], [:])
- AC_CHECK_TOOLS([NM], [gcc-nm nm], [:])
- AC_CHECK_TOOLS([RANLIB], [gcc-ranlib ranlib], [:])
-])
-
-LT_PREREQ(2.2)
-LT_INIT([disable-static])
-
-AS_IF([test "x$enable_static" = "xyes"], [AC_MSG_ERROR([--enable-static is not supported by elogind])])
-AS_IF([test "x$enable_largefile" = "xno"], [AC_MSG_ERROR([--disable-largefile is not supported by elogind])])
-
-SET_ARCH(X86_64, x86_64*)
-SET_ARCH(IA32, i*86*)
-SET_ARCH(MIPS, mips*)
-SET_ARCH(AARCH64, aarch64*)
-
-# i18n stuff for the PolicyKit policy files, check whether intltool can be found, disable NLS otherwise
-AC_CHECK_PROG(intltool_found, [intltool-merge], [yes], [no])
-AS_IF([test x"$intltool_found" != xyes],
- [AS_IF([test x"$enable_nls" = xyes],
- [AC_MSG_ERROR([--enable-nls requested but intltool not found])],
- [AS_IF([test x"$enable_nls" != xno],
- [AC_MSG_WARN([*** Disabling NLS support because intltool was not found])
- enable_nls=no])
- ])
- ])
-
-AM_NLS
-AS_IF([test x"$enable_nls" != xno -o "x$enable_polkit" != xno], [
- # intltoolize greps for '^(AC|IT)_PROG_INTLTOOL', so it needs to be on its own line
-IT_PROG_INTLTOOL([0.40.0])
-])
-
-AS_IF([test -z "$INTLTOOL_POLICY_RULE"], [
- # If intltool is not available, provide a dummy rule to fail generation of %.policy files with a meaningful error message
- INTLTOOL_POLICY_RULE='%.policy: %.policy.in ; @echo " ITMRG " $@ && echo "*** intltool support required to build target $@" && false'
- AC_SUBST(INTLTOOL_POLICY_RULE)
-])
-
-GETTEXT_PACKAGE=elogind
-AC_SUBST(GETTEXT_PACKAGE)
-AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [elogind])
-
-AC_PROG_MKDIR_P
-AC_PROG_LN_S
-AC_PROG_SED
-AC_PROG_GREP
-AC_PROG_AWK
-
-AC_PATH_PROG([M4], [m4])
-AC_PATH_PROG([XSLTPROC], [xsltproc])
-
-AC_PATH_PROG([HALT], [halt], [halt])
-AC_PATH_PROG([REBOOT], [reboot], [reboot])
-AC_PATH_PROG([KEXEC], [kexec], [/usr/sbin/kexec], [$PATH:/usr/sbin:/sbin])
-
-AS_IF([! ln --relative --help > /dev/null 2>&1], [AC_MSG_ERROR([*** ln doesn't support --relative ***])])
-
-M4_DEFINES=
-
-AC_CHECK_TOOL(OBJCOPY, objcopy)
-AC_CHECK_TOOL(GPERF, gperf)
-if test -z "$GPERF" ; then
- AC_MSG_ERROR([*** gperf not found])
-fi
-
-
-# ------------------------------------------------------------------------------
-# Let users set the cgroup controller to use, in case the target controller
-# isn't currently running the show.
-# Example: Gentoo Linux, user wants to switch from systemd to openrc+elogind,
-# and emerges elogind before having booted the machine with openrc.
-# See: https://github.com/elogind/elogind/issues/18
-with_cgroupctrl=
-AC_ARG_WITH([cgroup-controller],
- AS_HELP_STRING([--with-cgroup-controller=name],
- [Set the name of the cgroup controller to use.
- Use this when the autodetection fails, or you plan to use your system with a different controller than the one in place now.
- The value 'auto' (default) detects the running controller.
- The values 'none' and 'elogind' will cause elogind to be its own (very limited) controller.
- When elogind shall be its own controller, there *MUST NOT* be any other controller running!
- Another popular controller would be 'openrc'.]),
- [with_cgroupctrl=$withval],
- [with_cgroupctrl=auto])
-
-# ------------------------------------------------------------------------------
-# Find running cgroup controller, if none was set
-AS_IF( [test "x$with_cgroupctrl" = "xauto"], [
- AS_IF([test -f /proc/self/cgroup], [
- # If the init system is a cgroup controler, it will be position 1.
- # Secondary controllers, like cgmanager, do not work.
- with_cgroupctrl=`grep "^1:name=" /proc/self/cgroup | \
- sed -n 's/.*=//p' | sed -e 's/:.*$//'`
- AS_IF( [test -z "$with_cgroupctrl"], [
- # Try to be our own cgroup controller
- with_cgroupctrl="elogind"
- ])
- ], [
- # 'auto' but no cgroup fs is a problem.
- with_cgroupctrl=""
- ])
-])
-
-# If the user specified 'none', switch to 'elogind'.
-# 'none' is allowed, as this means "there is no controller now"
-AS_IF( [test "x$with_cgroupctrl" = "xnone"], [with_cgroupctrl=elogind])
-
-# If this was not possible, /proc/self/cgroup not mounted yet, and 'auto'
-# chosen, error out.
-AS_IF( [test -z "$with_cgroupctrl"],
- AC_MSG_ERROR([No running cgroup controller found]))
-
-# ------------------------------------------------------------------------------
-address_sanitizer_cflags=
-address_sanitizer_cppflags=
-address_sanitizer_ldflags=
-AC_ARG_ENABLE(address-sanitizer, AS_HELP_STRING([--enable-address-sanitizer], [enable -fsanitize=address]))
-AS_IF([test "x$enable_address_sanitizer" = "xyes"], [
- CC_CHECK_FLAG_APPEND([with_as_cflags], [CFLAGS], [-fsanitize=address])
- AS_IF([test -z "$with_as_cflags"],
- [AC_MSG_ERROR([*** -fsanitize=address is not supported])])
- address_sanitizer_cflags="$with_as_cflags -fno-omit-frame-pointer -DVALGRIND=1"
- address_sanitizer_cppflags="-DVALGRIND=1"
- address_sanitizer_ldflags="-Wc,-fsanitize=address"
- ])
-
-undefined_sanitizer_cflags=
-undefined_sanitizer_cppflags=
-undefined_sanitizer_ldflags=
-AC_ARG_ENABLE(undefined-sanitizer, AS_HELP_STRING([--enable-undefined-sanitizer], [enable -fsanitize=undefined]))
-AS_IF([test "x$enable_undefined_sanitizer" = "xyes"], [
- CC_CHECK_FLAG_APPEND([with_us_cflags], [CFLAGS], [-fsanitize=undefined])
- AS_IF([test -z "$with_us_cflags"],
- [AC_MSG_ERROR([*** -fsanitize=undefined is not supported])])
- undefined_sanitizer_cflags="$with_us_cflags -fno-omit-frame-pointer -DVALGRIND=1"
- undefined_sanitizer_cppflags="-DVALGRIND=1"
- undefined_sanitizer_ldflags="-Wc,-fsanitize=undefined"
- ])
-
-sanitizer_cflags="$address_sanitizer_cflags $undefined_sanitizer_cflags"
-sanitizer_cppflags="$address_sanitizer_cppflags $undefined_sanitizer_cppflags"
-sanitizer_ldflags="$address_sanitizer_ldflags $undefined_sanitizer_ldflags"
-
-CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\
- -pipe \
- -Wall \
- -Wextra \
- -Wundef \
- -Wlogical-op \
- -Wmissing-include-dirs \
- -Wold-style-definition \
- -Wpointer-arith \
- -Winit-self \
- -Wdeclaration-after-statement \
- -Wfloat-equal \
- -Wsuggest-attribute=noreturn \
- -Werror=missing-prototypes \
- -Werror=implicit-function-declaration \
- -Werror=missing-declarations \
- -Werror=return-type \
- -Werror=incompatible-pointer-types \
- -Werror=format=2 \
- -Wstrict-prototypes \
- -Wredundant-decls \
- -Wmissing-noreturn \
- -Wshadow \
- -Wendif-labels \
- -Wstrict-aliasing=2 \
- -Wwrite-strings \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -Wno-unused-result \
- -Wno-format-signedness \
- -Werror=overflow \
- -Wdate-time \
- -Wnested-externs \
- -ffast-math \
- -fno-common \
- -fdiagnostics-show-option \
- -fno-strict-aliasing \
- -fvisibility=hidden \
- -fstack-protector \
- -fstack-protector-strong \
- -fPIE \
- --param=ssp-buffer-size=4])
-
-CC_CHECK_FLAG_APPEND([with_cflags], [CFLAGS], [-Werror=shadow], [
-#include <time.h>
-#include <inttypes.h>
-typedef uint64_t usec_t;
-usec_t now(clockid_t clock);
-int main(void) {
- struct timespec now;
- return 0;
-}
-])
-
-AS_CASE([$CC], [*clang*],
- [CC_CHECK_FLAGS_APPEND([with_cppflags], [CPPFLAGS], [\
- -Wno-typedef-redefinition \
- -Wno-gnu-variable-sized-type-not-at-end \
- ])])
-
-# ------------------------------------------------------------------------------
-have_lto=no
-AC_ARG_ENABLE([lto], [AS_HELP_STRING([--disable-lto], [disable -flto])],
- [], [enable_lto=yes])
-AS_CASE([$CFLAGS], [*-O[[12345sz\ ]]*],
- [AS_IF([test "x$enable_lto" = "xyes"], [have_lto=yes],
- [AC_MSG_RESULT([disabling -flto as requested])])],
- [AC_MSG_RESULT([skipping -flto, optimization not enabled])])
-
-AS_IF([test "x$have_lto" = "xyes"],
- [CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS],
- [-flto -fuse-linker-plugin])])
-
-AS_CASE([$with_cflags], [*-flto*], [], [have_lto=no])
-
-# ------------------------------------------------------------------------------
-AS_CASE([$CFLAGS], [*-O[[12345sz\ ]]*],
- [CC_CHECK_FLAGS_APPEND([with_cppflags], [CPPFLAGS], [\
- -Wp,-D_FORTIFY_SOURCE=2])],
- [AC_MSG_RESULT([skipping -D_FORTIFY_SOURCE, optimization not enabled])])
-
-# ------------------------------------------------------------------------------
-AS_CASE([$CFLAGS], [*-O[[12345sz\ ]]*],
- [CC_CHECK_FLAGS_APPEND([with_ldflags], [LDFLAGS], [\
- -Wl,--gc-sections])],
- [AC_MSG_RESULT([skipping --gc-sections, optimization not enabled])])
-
-# ------------------------------------------------------------------------------
-AS_CASE([$CFLAGS], [*-O[[12345sz\ ]]*],
- [CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\
- -ffunction-sections -fdata-sections])],
- [AC_MSG_RESULT([skipping -ffunction/data-section, optimization not enabled])])
-
-# ------------------------------------------------------------------------------
-CC_CHECK_FLAGS_APPEND([with_ldflags], [LDFLAGS], [\
- -Wl,--as-needed \
- -Wl,--no-undefined \
- -Wl,-z,relro \
- -Wl,-z,now \
- -pie])
-AS_IF([test "x$have_lto" = "xyes"],
- [CC_CHECK_FLAGS_APPEND([with_ldflags], [LDFLAGS], [-Wl,-fuse-ld=gold])])
-
-# ------------------------------------------------------------------------------
-AC_SUBST([OUR_CPPFLAGS], "$with_cppflags $sanitizer_cppflags")
-AC_SUBST([OUR_CFLAGS], "-D__SANE_USERSPACE_TYPES__ $with_cflags $sanitizer_cflags")
-AC_SUBST([OUR_LDFLAGS], "$with_ldflags $sanitizer_ldflags")
-
-# ------------------------------------------------------------------------------
-AC_CHECK_SIZEOF(pid_t)
-AC_CHECK_SIZEOF(uid_t)
-AC_CHECK_SIZEOF(gid_t)
-AC_CHECK_SIZEOF(time_t)
-AC_CHECK_SIZEOF(dev_t)
-AC_CHECK_SIZEOF(ino_t)
-AC_CHECK_SIZEOF(rlim_t,,[
- #include <sys/time.h>
- #include <sys/resource.h>
-])
-
-GPERF_TEST="$(echo foo,bar | ${GPERF} -L ANSI-C)"
-save_CFLAGS="$CFLAGS"
-CFLAGS="$CFLAGS -Wno-error"
-AC_COMPILE_IFELSE(
- [AC_LANG_PROGRAM([
- #include <string.h>
- const char * in_word_set(const char *, size_t);
- $GPERF_TEST]
- )],
- [GPERF_LEN_TYPE=size_t],
- [AC_COMPILE_IFELSE(
- [AC_LANG_PROGRAM([
- #include <string.h>
- const char * in_word_set(const char *, unsigned);
- $GPERF_TEST]
- )],
- [GPERF_LEN_TYPE=unsigned],
- [AC_MSG_ERROR([** unable to determine gperf len type])]
- )]
-)
-CFLAGS="$save_CFLAGS"
-
-AC_DEFINE_UNQUOTED([GPERF_LEN_TYPE], [$GPERF_LEN_TYPE], [gperf len type])
-
-# ------------------------------------------------------------------------------
-# we use python to build the man page index
-have_python=no
-AC_ARG_WITH([python],
- [AS_HELP_STRING([--without-python], [disable building the man page index and systemd-python (default: test)])])
-
-have_lxml=no
-AS_IF([test "x$with_python" != "xno"], [
- AM_PATH_PYTHON([3],, [:])
- AS_IF([test "x$PYTHON" != "x:"], [
- AC_MSG_CHECKING([for python lxml module])
- AS_IF(["$PYTHON" -c 'import lxml' 2>/dev/null], [have_lxml=yes])
- AC_MSG_RESULT([$have_lxml])
- AS_IF([test "x$have_lxml" = "xyes"], [have_python=yes],
- [AC_MSG_WARN([*** python support requires python-lxml module installed])])
- ])
-])
-AS_IF([test "$have_python" != "yes"], [
- AS_IF([test "$with_python" = "yes"],
- [AC_MSG_ERROR([*** python support requested but python support not found])])
- AS_IF([test "$with_python" != "no"],
- [AC_MSG_WARN([*** python support not found, some documentation cannot be built])])
-])
-AM_CONDITIONAL([HAVE_PYTHON], [test "x$have_python" = "xyes"])
-
-# ------------------------------------------------------------------------------
-
-AC_CHECK_HEADERS([sys/capability.h], [], [AC_MSG_ERROR([*** POSIX caps headers not found])])
-AC_CHECK_HEADERS([linux/memfd.h], [], [])
-AC_CHECK_HEADERS([linux/vm_sockets.h], [], [], [#include <sys/socket.h>])
-
-AC_CHECK_HEADERS([printf.h], [have_printf_h=yes], [have_printf_h=no])
-AS_IF([test x$have_printf_h = xyes], [
- AC_DEFINE(HAVE_PRINTF_H, 1, [Define if printf.h was found])
-])
-
-
-
-# unconditionally pull-in librt with old glibc versions
-dnl AC_SEARCH_LIBS([clock_gettime], [rt], [], [])
-dnl AC_SEARCH_LIBS([mq_unlink], [rt], [], [])
-
-save_LIBS="$LIBS"
-LIBS=
-AC_SEARCH_LIBS([cap_init], [cap], [], [AC_MSG_ERROR([*** POSIX caps library not found])])
-CAP_LIBS="$LIBS"
-AC_SUBST(CAP_LIBS)
-
-AC_CHECK_FUNCS([__secure_getenv secure_getenv])
-AC_CHECK_DECLS([
- memfd_create,
- gettid,
- pivot_root,
- name_to_handle_at,
- setns,
- renameat2,
- kcmp,
- keyctl,
- LO_FLAGS_PARTSCAN,
- copy_file_range,
- explicit_bzero],
- [], [], [[
-#include <sys/types.h>
-#include <unistd.h>
-#include <sys/mount.h>
-#include <fcntl.h>
-#include <sched.h>
-#include <string.h>
-#include <linux/loop.h>
-]])
-
-AC_CHECK_DECLS([getrandom],
- [AC_DEFINE([USE_SYS_RANDOM_H], [], [sys/random.h is usable])],
- [AC_CHECK_DECLS([getrandom], [], [], [[
-#include <sys/random.h>
-]])], [[
-#include <linux/random.h>
-]])
-
-AC_CHECK_TYPES([char16_t, char32_t, key_serial_t],
- [], [], [[
-#include <uchar.h>
-]])
-
-AC_CHECK_DECLS([IFLA_INET6_ADDR_GEN_MODE,
- IN6_ADDR_GEN_MODE_STABLE_PRIVACY,
- IFLA_VRF_TABLE,
- IFLA_MACVLAN_FLAGS,
- IFLA_IPVLAN_MODE,
- IFLA_VTI_REMOTE,
- IFLA_PHYS_PORT_ID,
- IFLA_BOND_AD_INFO,
- IFLA_VLAN_PROTOCOL,
- IFLA_VXLAN_GPE,
- IFLA_GENEVE_LABEL,
- IFLA_IPTUN_ENCAP_DPORT,
- IFLA_GRE_ENCAP_DPORT,
- IFLA_BRIDGE_VLAN_INFO,
- IFLA_BRPORT_PROXYARP,
- IFLA_BRPORT_LEARNING_SYNC,
- IFLA_BR_VLAN_DEFAULT_PVID,
- NDA_IFINDEX,
- IFA_FLAGS],
-[], [], [[
-#include <inttypes.h>
-#include <netinet/in.h>
-#include <netinet/ether.h>
-#include <linux/rtnetlink.h>
-#include <net/if.h>
-#include <linux/ip.h>
-#include <linux/if_tunnel.h>
-#include <linux/if_link.h>
-#include <linux/if_bridge.h>
-#include <linux/if_addr.h>
-#include <linux/neighbour.h>
-]])
-
-# This makes sure pkg.m4 is available.
-m4_pattern_forbid([^_?PKG_[A-Z_]+$],[*** pkg.m4 missing, please install pkg-config])
-
-
-# ------------------------------------------------------------------------------
-PKG_CHECK_MODULES(UDEV, [libudev])
-dnl
-AC_ARG_WITH([udevrulesdir],
- AS_HELP_STRING([--with-udevrulesdir=DIR], [Directory for udev rules files]),
- [],
- [with_udevrulesdir=$($PKG_CONFIG --variable=udevdir udev)/rules.d])
-AC_SUBST([udevrulesdir], [$with_udevrulesdir])
-
-AC_ARG_WITH([udevbindir],
- AS_HELP_STRING([--with-udevbindir=DIR], [Directory for udev binary files]),
- [],
- [with_udevbindir=$($PKG_CONFIG --variable=udevdir udev)])
-AC_SUBST([udevbindir], [$with_udevbindir])
-
-# ------------------------------------------------------------------------------
-have_glib=no
-AC_ARG_ENABLE(glib, AS_HELP_STRING([--disable-glib], [disable usage of glib,gobject,gio in tests]))
-AS_IF([test "x$enable_glib" != "xno"], [
- PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.22.0 gobject-2.0 >= 2.22.0 gio-2.0],
- [AC_DEFINE(HAVE_GLIB, 1, [Define if glib,gobject,gio are available]) have_glib=yes],
- [have_glib=no])
- AS_IF([test "x$have_glib" = "xno" -a "x$enable_glib" = "xyes"],
- [AC_MSG_ERROR([*** glib support requested but libraries not found])])])
-
-# ------------------------------------------------------------------------------
-have_utmp=yes
-AC_ARG_ENABLE([utmp], AS_HELP_STRING([--disable-utmp], [disable utmp/wtmp log handling]),
- AS_CASE("x${enableval}",
- [xyes], [have_utmp=yes],
- [xno], [have_utmp=no],
- AC_MSG_ERROR(bad value ${enableval} for --enable-utmp)))
-AS_IF([test "x$have_utmp" = "xyes"], [
- AC_DEFINE(HAVE_UTMP, 1, [Define if utmp/wtmp support is enabled])
- have_utmp=yes
- M4_DEFINES="$M4_DEFINES -DHAVE_UTMP"],
- [have_utmp=no])
-AM_CONDITIONAL([HAVE_UTMP], [test "x$have_utmp" = "xyes"])
-
-# ------------------------------------------------------------------------------
-have_coverage=no
-AC_ARG_ENABLE(coverage, AS_HELP_STRING([--enable-coverage], [enable test coverage]))
-if test "x$enable_coverage" = "xyes" ; then
- AC_CHECK_PROG(lcov_found, [lcov], [yes], [no])
- if test "x$lcov_found" = xno ; then
- AC_MSG_ERROR([*** lcov support requested but the program was not found])
- else
- lcov_version_major="`lcov --version | cut -d ' ' -f 4 | cut -d '.' -f 1`"
- lcov_version_minor="`lcov --version | cut -d ' ' -f 4 | cut -d '.' -f 2`"
- if test "$lcov_version_major" -eq 1 -a "$lcov_version_minor" -lt 10; then
- AC_MSG_ERROR([*** lcov version is too old. 1.10 required])
- else
- have_coverage=yes
- CC_CHECK_FLAGS_APPEND([with_coverage_cflags], [CFLAGS], [\
- -fprofile-arcs \
- -ftest-coverage])
- AC_SUBST([OUR_CFLAGS], "$with_cflags $with_coverage_cflags")
- fi
- fi
-fi
-AM_CONDITIONAL(ENABLE_COVERAGE, [test "$have_coverage" = "yes"])
-
-# ------------------------------------------------------------------------------
-have_selinux=no
-AC_ARG_ENABLE(selinux, AS_HELP_STRING([--disable-selinux], [disable optional SELINUX support]))
-if test "x$enable_selinux" != "xno"; then
- PKG_CHECK_MODULES([SELINUX], [libselinux >= 2.1.9],
- [AC_DEFINE(HAVE_SELINUX, 1, [Define if SELinux is available])
- have_selinux=yes
- M4_DEFINES="$M4_DEFINES -DHAVE_SELINUX"],
- [have_selinux=no])
- if test "x$have_selinux" = xno -a "x$enable_selinux" = xyes; then
- AC_MSG_ERROR([*** SELinux support requested but libraries not found])
- fi
-fi
-AM_CONDITIONAL(HAVE_SELINUX, [test "$have_selinux" = "yes"])
-
-# ------------------------------------------------------------------------------
-AC_ARG_WITH([kill-user-processes],
- [AS_HELP_STRING([--without-kill-user-processes], [Set elogind's KillUserProcesses=no by default])])
-AS_IF([test "$with_kill_user_processes" != "no"],
- [kill_user_processes=true
- KILL_USER_PROCESSES=yes],
- [kill_user_processes=false
- KILL_USER_PROCESSES=no])
-AC_DEFINE_UNQUOTED(KILL_USER_PROCESSES, [$kill_user_processes], [Default KillUserProcesses setting])
-AC_SUBST(KILL_USER_PROCESSES)
-
-# ------------------------------------------------------------------------------
-# We do not really support systemd hybrid or unified mode, but set the default
-# to 'legacy' here. That is currently the only cgroup mode supported by elogind.
-#AC_ARG_WITH(default-hierarchy,
-# AS_HELP_STRING([--with-default-hierarchy=MODE],
-# [default cgroup hierarchy, defaults to "hybrid"]),
-# [DEFAULT_HIERARCHY="$withval"],
-# [DEFAULT_HIERARCHY="hybrid"])
-DEFAULT_HIERARCHY=legacy
-
-AS_CASE("$DEFAULT_HIERARCHY",
- [legacy], [mode=CGROUP_UNIFIED_NONE],
- [hybrid], [mode=CGROUP_UNIFIED_SYSTEMD],
- [unified], [mode=CGROUP_UNIFIED_ALL],
- AC_MSG_ERROR(Bad default hierarchy mode ${DEFAULT_HIERARCHY}))
-AC_DEFINE_UNQUOTED(DEFAULT_HIERARCHY, [$mode], [Default cgroup hierarchy])
-AC_DEFINE_UNQUOTED(DEFAULT_HIERARCHY_NAME, ["$DEFAULT_HIERARCHY"],
- [Default cgroup hierarchy as string])
-
-# ------------------------------------------------------------------------------
-AC_ARG_ENABLE([pam],
- AS_HELP_STRING([--disable-pam],[disable optional PAM support]),
- [case "${enableval}" in
- yes) have_pam=yes ;;
- no) have_pam=no ;;
- *) AC_MSG_ERROR(bad value ${enableval} for --disable-pam) ;;
- esac],
- [have_pam=auto])
-
-if test "x${have_pam}" != xno ; then
- AC_CHECK_HEADERS(
- [security/pam_modules.h security/pam_modutil.h security/pam_ext.h],
- [have_pam=yes],
- [if test "x$have_pam" = xyes ; then
- AC_MSG_ERROR([*** PAM headers not found.])
- fi])
-
- AC_CHECK_LIB(
- [pam],
- [pam_syslog],
- [have_pam=yes],
- [if test "x$have_pam" = xyes ; then
- AC_MSG_ERROR([*** libpam not found.])
- fi])
-
- if test "x$have_pam" = xyes ; then
- PAM_LIBS="-lpam -lpam_misc"
- AC_DEFINE(HAVE_PAM, 1, [PAM available])
- M4_DEFINES="$M4_DEFINES -DHAVE_PAM"
- else
- have_pam=no
- fi
-else
- PAM_LIBS=
-fi
-AC_SUBST(PAM_LIBS)
-AM_CONDITIONAL([HAVE_PAM], [test "x$have_pam" != xno])
-
-# ------------------------------------------------------------------------------
-AC_ARG_ENABLE([acl],
- AS_HELP_STRING([--disable-acl],[disable optional ACL support]),
- [case "${enableval}" in
- yes) have_acl=yes ;;
- no) have_acl=no ;;
- *) AC_MSG_ERROR(bad value ${enableval} for --disable-acl) ;;
- esac],
- [have_acl=auto])
-
-if test "x${have_acl}" != xno ; then
- AC_CHECK_HEADERS(
- [sys/acl.h acl/libacl.h],
- [have_acl=yes],
- [if test "x$have_acl" = xyes ; then
- AC_MSG_ERROR([*** ACL headers not found.])
- fi])
-
- AC_CHECK_LIB(
- [acl],
- [acl_get_file],
- [have_acl=yes],
- [if test "x$have_acl" = xyes ; then
- AC_MSG_ERROR([*** libacl not found.])
- fi])
-
- if test "x$have_acl" = xyes ; then
- ACL_LIBS="-lacl"
- AC_DEFINE(HAVE_ACL, 1, [ACL available])
- M4_DEFINES="$M4_DEFINES -DHAVE_ACL"
- else
- have_acl=no
- fi
-else
- ACL_LIBS=
-fi
-AC_SUBST(ACL_LIBS)
-AM_CONDITIONAL([HAVE_ACL], [test "x$have_acl" != xno])
-
-# ------------------------------------------------------------------------------
-AC_ARG_ENABLE([smack], AS_HELP_STRING([--disable-smack],[disable optional SMACK support]),
- [case "${enableval}" in
- yes) have_smack=yes ;;
- no) have_smack=no ;;
- *) AC_MSG_ERROR(bad value ${enableval} for --disable-smack) ;;
- esac],
- [have_smack=auto])
-
-if test "x${have_smack}" != xno; then
- AC_DEFINE(HAVE_SMACK, 1, [Define if SMACK is available])
- M4_DEFINES="$M4_DEFINES -DHAVE_SMACK"
- have_smack=yes
-fi
-
-AM_CONDITIONAL([HAVE_SMACK], [test "x$have_smack" = "xyes"])
-
-have_smack_run_label=no
-AC_ARG_WITH(smack-run-label,
-AS_HELP_STRING([--with-smack-run-label=STRING],
- [run systemd --system itself with a specific SMACK label]),
- [AC_DEFINE_UNQUOTED(SMACK_RUN_LABEL, ["$withval"], [Run systemd itself with SMACK label]) have_smack_run_label=yes],
- [])
-
-if test "x${have_smack_run_label}" = xyes; then
- M4_DEFINES="$M4_DEFINES -DHAVE_SMACK_RUN_LABEL"
-fi
-
-AC_ARG_WITH(smack-default-process-label,
-AS_HELP_STRING([--with-smack-default-process-label=STRING],
- [default SMACK label for executed processes]),
- [AC_DEFINE_UNQUOTED(SMACK_DEFAULT_PROCESS_LABEL, ["$withval"], [Default SMACK label for executed processes])],
- [])
-
-# ------------------------------------------------------------------------------
-AC_ARG_WITH(system-uid-max,
- AS_HELP_STRING([--with-system-uid-max=UID]
- [Maximum UID for system users]),
- [SYSTEM_UID_MAX="$withval"],
- [SYSTEM_UID_MAX="`awk 'BEGIN { uid=999 } /^\s*SYS_UID_MAX\s+/ { uid=$2 } END { print uid }' /etc/login.defs 2>/dev/null || echo 999`"])
-
-AC_DEFINE_UNQUOTED(SYSTEM_UID_MAX, [$SYSTEM_UID_MAX], [Maximum System UID])
-AC_SUBST(SYSTEM_UID_MAX)
-
-# ------------------------------------------------------------------------------
-AC_ARG_WITH(system-gid-max,
- AS_HELP_STRING([--with-system-gid-max=GID]
- [Maximum GID for system groups]),
- [SYSTEM_GID_MAX="$withval"],
- [SYSTEM_GID_MAX="`awk 'BEGIN { gid=999 } /^\s*SYS_GID_MAX\s+/ { gid=$2 } END { print gid }' /etc/login.defs 2>/dev/null || echo 999`"])
-
-AC_DEFINE_UNQUOTED(SYSTEM_GID_MAX, [$SYSTEM_GID_MAX], [Maximum System GID])
-AC_SUBST(SYSTEM_GID_MAX)
-
-# ------------------------------------------------------------------------------
-have_polkit=no
-AC_ARG_ENABLE(polkit, AS_HELP_STRING([--disable-polkit], [disable PolicyKit support]))
-if test "x$enable_polkit" != "xno"; then
- AC_DEFINE(ENABLE_POLKIT, 1, [Define if PolicyKit support is to be enabled])
- have_polkit=yes
-
- # also enable support for *.pkla files on old polkit
- PKG_CHECK_MODULES(POLKIT, [ polkit-gobject-1 < 0.106 ],
- [polkit_pkla=yes],
- [polkit_pkla=no])
-fi
-AM_CONDITIONAL(ENABLE_POLKIT, [test "x$have_polkit" = "xyes"])
-AM_CONDITIONAL(ENABLE_POLKIT_PKLA, [test "x$polkit_pkla" = "xyes"])
-
-# ------------------------------------------------------------------------------
-AC_CHECK_HEADERS_ONCE([valgrind/memcheck.h valgrind/valgrind.h])
-
-# ------------------------------------------------------------------------------
-have_manpages=no
-AC_ARG_ENABLE(manpages, AS_HELP_STRING([--disable-manpages], [disable manpages]))
-AC_PATH_PROG([XSLTPROC], [xsltproc])
-AS_IF([test "x$enable_manpages" != xno], [have_manpages=yes])
-AM_CONDITIONAL(ENABLE_MANPAGES, [test "x$have_manpages" = "xyes"])
-
-# ------------------------------------------------------------------------------
-AC_SUBST(M4_DEFINES)
-
-AC_ARG_WITH([dbuspolicydir],
- AS_HELP_STRING([--with-dbuspolicydir=DIR], [D-Bus policy directory]),
- [],
- [with_dbuspolicydir=${datadir}/dbus-1/system.d])
-AX_NORMALIZE_PATH([with_dbuspolicydir])
-
-AC_ARG_WITH([dbussystemservicedir],
- AS_HELP_STRING([--with-dbussystemservicedir=DIR], [D-Bus system service directory]),
- [],
- [with_dbussystemservicedir=${datadir}/dbus-1/system-services])
-AX_NORMALIZE_PATH([with_dbussystemservicedir])
-
-AC_ARG_WITH([bashcompletiondir],
- AS_HELP_STRING([--with-bashcompletiondir=DIR], [bash completions directory]),
- [],
- [AS_IF([$($PKG_CONFIG --exists bash-completion)], [
- with_bashcompletiondir=$($PKG_CONFIG --variable=completionsdir bash-completion)
- ] , [
- with_bashcompletiondir=${datadir}/bash-completion/completions
- ])])
-AM_CONDITIONAL(ENABLE_BASH_COMPLETION, [test "$with_bashcompletiondir" != "no"])
-AX_NORMALIZE_PATH([with_bashcompletiondir])
-
-AC_ARG_WITH([zshcompletiondir],
- AS_HELP_STRING([--with-zshcompletiondir=DIR], [zsh completions directory]),
- [], [with_zshcompletiondir=${datadir}/zsh/site-functions])
-AM_CONDITIONAL(ENABLE_ZSH_COMPLETION, [test "$with_zshcompletiondir" != "no"])
-AX_NORMALIZE_PATH([with_zshcompletiondir])
-
-AC_ARG_WITH([rootprefix],
- AS_HELP_STRING([--with-rootprefix=DIR], [rootfs directory prefix for config files and kernel modules]),
- [], [with_rootprefix=${ac_default_prefix}])
-# --with-rootprefix= (empty) should default to "/" but AX_NORMALIZE_PATH
-# defaults those to ".", solve that here for now until we can find a suitable
-# fix for AX_NORMALIZE_PATH upstream at autoconf-archive.
-# See: https://github.com/systemd/systemd/issues/54
-if test "x${with_rootprefix}" = "x"; then
- with_rootprefix="/"
-fi
-AX_NORMALIZE_PATH([with_rootprefix])
-
-AC_ARG_WITH([rootlibdir],
- AS_HELP_STRING([--with-rootlibdir=DIR], [root directory for libraries necessary for boot]),
- [],
- [with_rootlibdir=${libdir}])
-AX_NORMALIZE_PATH([with_rootlibdir])
-
-AC_ARG_WITH([rootlibexecdir],
- AS_HELP_STRING([--with-rootlibexecdir=DIR], [Root directory for executables necessary for boot]),
- [],
- [with_rootlibexecdir=${with_rootprefix}/lib/elogind])
-AX_NORMALIZE_PATH([with_rootlibexecdir])
-
-AC_ARG_WITH([pamlibdir],
- AS_HELP_STRING([--with-pamlibdir=DIR], [directory for PAM modules]),
- [],
- [with_pamlibdir=${with_rootlibdir}/security])
-AX_NORMALIZE_PATH([with_pamlibdir])
-
-AC_ARG_WITH([pamconfdir],
- AS_HELP_STRING([--with-pamconfdir=DIR], [directory for PAM configuration (pass no to disable installing)]),
- [],
- [with_pamconfdir=${sysconfdir}/pam.d])
-AM_CONDITIONAL(ENABLE_PAM_CONFIG, [test "$with_pamconfdir" != "no"])
-AX_NORMALIZE_PATH([with_pamconfdir])
-
-AC_ARG_ENABLE([split-usr],
- AS_HELP_STRING([--enable-split-usr], [assume that /bin, /sbin aren\'t symlinks into /usr]),
- [],
- [AS_IF([test "x${ac_default_prefix}" != "x${with_rootprefix}"], [
- enable_split_usr=yes
- ], [
- enable_split_usr=no
- ])])
-
-AS_IF([test "x${enable_split_usr}" = "xyes"], [
- AC_DEFINE(HAVE_SPLIT_USR, 1, [Define if /bin, /sbin aren't symlinks into /usr])
-])
-AM_CONDITIONAL(ENABLE_SPLIT_USR, [test "x${enable_split_usr}" = "xyes"])
-
-# work around intltool-update issues during 'make distcheck'
-AS_IF([test "x$0" != "x./configure"], [
- AC_SUBST([INTLTOOL_UPDATE], [/usr/bin/env true])
-])
-
-AC_ARG_ENABLE(tests,
- [AC_HELP_STRING([--disable-tests], [disable tests, or enable extra tests with =unsafe])],
- enable_tests=$enableval, enable_tests=yes)
-AM_CONDITIONAL(ENABLE_TESTS, [test x$enable_tests = xyes -o x$enable_tests = xunsafe])
-AM_CONDITIONAL(ENABLE_UNSAFE_TESTS, [test x$enable_tests = xunsafe])
-
-AC_ARG_ENABLE(debug,
- [AC_HELP_STRING([--enable-debug@<:@=LIST@:>@], [enable extra debugging (elogind,hashmap,mmap-cache)])],
- [if test "x$enableval" = "xyes"; then
- enableval="elogind,hashmap,mmap-cache"
- fi
- saved_ifs="$IFS"
- IFS="$IFS$PATH_SEPARATOR,"
- for name in $enableval; do
- case $name in
- elogind)
- enable_debug_elogind=yes
- ;;
- hashmap)
- enable_debug_hashmap=yes
- ;;
- mmap-cache)
- enable_debug_mmap_cache=yes
- ;;
- esac
- done
- IFS="$saved_ifs"],[])
-
-enable_debug=""
-AS_IF([test x$enable_debug_elogind = xyes], [
- AC_DEFINE(ENABLE_DEBUG_ELOGIND, 1, [Define if elogind debugging is to be enabled])
- enable_debug="elogind $enable_debug"
-])
-AS_IF([test x$enable_debug_hashmap = xyes], [
- AC_DEFINE(ENABLE_DEBUG_HASHMAP, 1, [Define if hashmap debugging is to be enabled])
- enable_debug="hashmap $enable_debug"
-])
-AS_IF([test x$enable_debug_mmap_cache = xyes], [
- AC_DEFINE(ENABLE_DEBUG_MMAP_CACHE, 1, [Define if mmap cache debugging is to be enabled])
- enable_debug="mmap-cache $enable_debug"
-])
-test -z "$enable_debug" && enable_debug="none"
-
-AC_SUBST([dbuspolicydir], [$with_dbuspolicydir])
-AC_SUBST([dbussystemservicedir], [$with_dbussystemservicedir])
-AC_SUBST([bashcompletiondir], [$with_bashcompletiondir])
-AC_SUBST([zshcompletiondir], [$with_zshcompletiondir])
-AC_SUBST([pamlibdir], [$with_pamlibdir])
-AC_SUBST([pamconfdir], [$with_pamconfdir])
-AC_SUBST([rootprefix], [$with_rootprefix])
-AC_SUBST([rootlibdir], [$with_rootlibdir])
-AC_SUBST([rootlibexecdir], [$with_rootlibexecdir])
-AC_SUBST([cgroup_controller], [$with_cgroupctrl])
-
-AC_CONFIG_FILES([
- Makefile
- po/Makefile.in
-])
-
-AC_OUTPUT
-AC_MSG_RESULT([
- $PACKAGE_NAME $PACKAGE_VERSION
-
- PAM: . . . . . . . . . . . . . . . ${have_pam}
- SELinux: . . . . . . . . . . . . . ${have_selinux}
- SMACK: . . . . . . . . . . . . . . ${have_smack}
- ACL: . . . . . . . . . . . . . . . ${have_acl}
- default cgroup hierarchy: . . . . ${DEFAULT_HIERARCHY}
- default KillUserProcesses setting: ${KILL_USER_PROCESSES}
- polkit: . . . . . . . . . . . . . ${have_polkit} (legacy pkla support: ${polkit_pkla})
- glib: . . . . . . . . . . . . . . ${have_glib}
- Python: . . . . . . . . . . . . . ${have_python}
- man pages: . . . . . . . . . . . . ${have_manpages}
- test coverage: . . . . . . . . . . ${have_coverage}
- Split /usr: . . . . . . . . . . . ${enable_split_usr}
- utmp/wtmp support: . . . . . . . . ${have_utmp}
- Link time optimization: . . . . . ${have_lto}
- extra debugging: . . . . . . . . . ${enable_debug}
- cgroup controller: . . . . . . . . ${with_cgroupctrl}
-
- prefix: . . . . . . . . . . . . . ${prefix}
- rootprefix: . . . . . . . . . . . ${with_rootprefix}
- sysconf dir: . . . . . . . . . . . ${sysconfdir}
- datarootdir: . . . . . . . . . . . ${datarootdir}
- includedir: . . . . . . . . . . . ${includedir}
- lib dir: . . . . . . . . . . . . . ${libdir}
- rootlib dir: . . . . . . . . . . . ${with_rootlibdir}
- rootlibexec dir: . . . . . . . . . ${with_rootlibexecdir}
- PAM modules dir: . . . . . . . . . ${with_pamlibdir}
- PAM configuration dir: . . . . . . ${with_pamconfdir}
- D-Bus policy dir: . . . . . . . . ${with_dbuspolicydir}
- D-Bus system dir: . . . . . . . . ${with_dbussystemservicedir}
- bash completions dir: . . . . . . ${with_bashcompletiondir}
- zsh completions dir: . . . . . . . ${with_zshcompletiondir}
- maximum system UID: . . . . . . . ${SYSTEM_UID_MAX}
- maximum system GID: . . . . . . . ${SYSTEM_GID_MAX}
-
- CFLAGS: . . . . . . . . . . . . . ${OUR_CFLAGS} ${CFLAGS}
- CPPFLAGS: . . . . . . . . . . . . ${OUR_CPPFLAGS} ${CPPFLAGS}
- LDFLAGS: . . . . . . . . . . . . . ${OUR_LDFLAGS} ${LDFLAGS}
-])
diff --git a/CODING_STYLE b/doc/CODING_STYLE
index ed61ea9d2..ae818126c 100644
--- a/CODING_STYLE
+++ b/doc/CODING_STYLE
@@ -1,9 +1,11 @@
- 8ch indent, no tabs, except for files in man/ which are 2ch indent,
and still no tabs
-- We prefer /* comments */ over // comments, please. This is not C++, after
- all. (Yes we know that C99 supports both kinds of comments, but still,
- please!)
+- We prefer /* comments */ over // comments in code you commit, please. This
+ way // comments are left for developers to use for local, temporary
+ commenting of code for debug purposes (i.e. uncommittable stuff), making such
+ comments easily discernable from explanatory, documenting code comments
+ (i.e. committable stuff).
- Don't break code lines too eagerly. We do *not* force line breaks at
80ch, all of today's screens should be much larger than that. But
@@ -218,7 +220,7 @@
- We never use the POSIX version of basename() (which glibc defines it in
libgen.h), only the GNU version (which glibc defines in string.h).
The only reason to include libgen.h is because dirname()
- is needed. Everytime you need that please immediately undefine
+ is needed. Every time you need that please immediately undefine
basename(), and add a comment about it, so that no code ever ends up
using the POSIX version!
@@ -350,8 +352,7 @@
proper event, instead of doing time-based poll loops.
- To determine the length of a constant string "foo", don't bother
- with sizeof("foo")-1, please use strlen("foo") directly. gcc knows
- strlen() anyway and turns it into a constant expression if possible.
+ with sizeof("foo")-1, please use STRLEN() instead.
- If you want to concatenate two or more strings, consider using
strjoin() rather than asprintf(), as the latter is a lot
@@ -363,7 +364,7 @@
global variables. Why are global variables bad? They usually hinder
generic reusability of code (since they break in threaded programs,
and usually would require locking there), and as the code using them
- has side-effects make programs intransparent. That said, there are
+ has side-effects make programs non-transparent. That said, there are
many cases where they explicitly make a lot of sense, and are OK to
use. For example, the log level and target in log.c is stored in a
global variable, and that's OK and probably expected by most. Also
@@ -385,7 +386,7 @@
- When exposing public C APIs, be careful what function parameters you make
"const". For example, a parameter taking a context object should probably not
- be "const", even if you are writing an other-wise read-only accessor function
+ be "const", even if you are writing an otherwise read-only accessor function
for it. The reason is that making it "const" fixates the contract that your
call won't alter the object ever, as part of the API. However, that's often
quite a promise, given that this even prohibits object-internal caching or
@@ -395,14 +396,14 @@
- Make sure to enforce limits on every user controllable resource. If the user
can allocate resources in your code, your code must enforce some form of
- limits after which it will refuse operation. It's fine if it is hardcoded (at
+ limits after which it will refuse operation. It's fine if it is hard-coded (at
least initially), but it needs to be there. This is particularly important
for objects that unprivileged users may allocate, but also matters for
everything else any user may allocated.
- htonl()/ntohl() and htons()/ntohs() are weird. Please use htobe32() and
htobe16() instead, it's much more descriptive, and actually says what really
- is happening, after all htonl() and htons() don't operation on longs and
+ is happening, after all htonl() and htons() don't operate on longs and
shorts as their name would suggest, but on uint32_t and uint16_t. Also,
"network byte order" is just a weird name for "big endian", hence we might
want to call it "big endian" right-away.
@@ -434,3 +435,8 @@
that interrupted system calls are automatically restarted, and we minimize
hassles with handling EINTR (in particular as EINTR handling is pretty broken
on Linux).
+
+- When applying C-style unescaping as well as specifier expansion on the same
+ string, always apply the C-style unescaping fist, followed by the specifier
+ expansion. When doing the reverse, make sure to escape '%' in specifier-style
+ first (i.e. '%' → '%%'), and then do C-style escaping where necessary.
diff --git a/docs/.gitignore b/docs/.gitignore
deleted file mode 100644
index 35b5e99ae..000000000
--- a/docs/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/html
diff --git a/docs/Makefile b/docs/Makefile
deleted file mode 120000
index bd1047548..000000000
--- a/docs/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../src/Makefile \ No newline at end of file
diff --git a/m4/.gitignore b/m4/.gitignore
deleted file mode 100644
index 55eaa803a..000000000
--- a/m4/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-intltool.m4
-libtool.m4
-ltoptions.m4
-ltsugar.m4
-ltversion.m4
-lt~obsolete.m4
diff --git a/m4/arch.m4 b/m4/arch.m4
deleted file mode 100644
index f17b4278e..000000000
--- a/m4/arch.m4
+++ /dev/null
@@ -1,13 +0,0 @@
-
-dnl SET_ARCH(ARCHNAME, PATTERN)
-dnl
-dnl Define ARCH_<archname> condition if the pattern match with the current
-dnl architecture
-dnl
-AC_DEFUN([SET_ARCH], [
- cpu_$1=false
- case "$host" in
- $2) cpu_$1=true ;;
- esac
- AM_CONDITIONAL(AS_TR_CPP(ARCH_$1), [test "x$cpu_$1" = xtrue])
-])
diff --git a/m4/attributes.m4 b/m4/attributes.m4
deleted file mode 100644
index 51ac88be6..000000000
--- a/m4/attributes.m4
+++ /dev/null
@@ -1,292 +0,0 @@
-dnl Macros to check the presence of generic (non-typed) symbols.
-dnl Copyright (c) 2006-2008 Diego Pettenò <flameeyes@gmail.com>
-dnl Copyright (c) 2006-2008 xine project
-dnl Copyright (c) 2012 Lucas De Marchi <lucas.de.marchi@gmail.com>
-dnl
-dnl This program is free software; you can redistribute it and/or modify
-dnl it under the terms of the GNU General Public License as published by
-dnl the Free Software Foundation; either version 2, or (at your option)
-dnl any later version.
-dnl
-dnl This program is distributed in the hope that it will be useful,
-dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
-dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-dnl GNU General Public License for more details.
-dnl
-dnl You should have received a copy of the GNU General Public License
-dnl along with this program; if not, write to the Free Software
-dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-dnl 02110-1301, USA.
-dnl
-dnl As a special exception, the copyright owners of the
-dnl macro gives unlimited permission to copy, distribute and modify the
-dnl configure scripts that are the output of Autoconf when processing the
-dnl Macro. You need not follow the terms of the GNU General Public
-dnl License when using or distributing such scripts, even though portions
-dnl of the text of the Macro appear in them. The GNU General Public
-dnl License (GPL) does govern all other use of the material that
-dnl constitutes the Autoconf Macro.
-dnl
-dnl This special exception to the GPL applies to versions of the
-dnl Autoconf Macro released by this project. When you make and
-dnl distribute a modified version of the Autoconf Macro, you may extend
-dnl this special exception to the GPL to apply to your modified version as
-dnl well.
-
-dnl Check if FLAG in ENV-VAR is supported by compiler and append it
-dnl to WHERE-TO-APPEND variable. Note that we invert -Wno-* checks to
-dnl -W* as gcc cannot test for negated warnings. If a C snippet is passed,
-dnl use it, otherwise use a simple main() definition that just returns 0.
-dnl CC_CHECK_FLAG_APPEND([WHERE-TO-APPEND], [ENV-VAR], [FLAG], [C-SNIPPET])
-
-AC_DEFUN([CC_CHECK_FLAG_APPEND], [
- AC_CACHE_CHECK([if $CC supports flag $3 in envvar $2],
- AS_TR_SH([cc_cv_$2_$3]),
- [eval "AS_TR_SH([cc_save_$2])='${$2}'"
- eval "AS_TR_SH([$2])='${cc_save_$2} -Werror `echo "$3" | sed 's/^-Wno-/-W/'`'"
- AC_LINK_IFELSE([AC_LANG_SOURCE(ifelse([$4], [],
- [int main(void) { return 0; } ],
- [$4]))],
- [eval "AS_TR_SH([cc_cv_$2_$3])='yes'"],
- [eval "AS_TR_SH([cc_cv_$2_$3])='no'"])
- eval "AS_TR_SH([$2])='$cc_save_$2'"])
-
- AS_IF([eval test x$]AS_TR_SH([cc_cv_$2_$3])[ = xyes],
- [eval "$1='${$1} $3'"])
-])
-
-dnl CC_CHECK_FLAGS_APPEND([WHERE-TO-APPEND], [ENV-VAR], [FLAG1 FLAG2], [C-SNIPPET])
-AC_DEFUN([CC_CHECK_FLAGS_APPEND], [
- for flag in [$3]; do
- CC_CHECK_FLAG_APPEND([$1], [$2], $flag, [$4])
- done
-])
-
-dnl Check if the flag is supported by linker (cacheable)
-dnl CC_CHECK_LDFLAGS([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND])
-
-AC_DEFUN([CC_CHECK_LDFLAGS], [
- AC_CACHE_CHECK([if $CC supports $1 flag],
- AS_TR_SH([cc_cv_ldflags_$1]),
- [ac_save_LDFLAGS="$LDFLAGS"
- LDFLAGS="$LDFLAGS $1"
- AC_LINK_IFELSE([int main() { return 1; }],
- [eval "AS_TR_SH([cc_cv_ldflags_$1])='yes'"],
- [eval "AS_TR_SH([cc_cv_ldflags_$1])="])
- LDFLAGS="$ac_save_LDFLAGS"
- ])
-
- AS_IF([eval test x$]AS_TR_SH([cc_cv_ldflags_$1])[ = xyes],
- [$2], [$3])
-])
-
-dnl define the LDFLAGS_NOUNDEFINED variable with the correct value for
-dnl the current linker to avoid undefined references in a shared object.
-AC_DEFUN([CC_NOUNDEFINED], [
- dnl We check $host for which systems to enable this for.
- AC_REQUIRE([AC_CANONICAL_HOST])
-
- case $host in
- dnl FreeBSD (et al.) does not complete linking for shared objects when pthreads
- dnl are requested, as different implementations are present; to avoid problems
- dnl use -Wl,-z,defs only for those platform not behaving this way.
- *-freebsd* | *-openbsd*) ;;
- *)
- dnl First of all check for the --no-undefined variant of GNU ld. This allows
- dnl for a much more readable command line, so that people can understand what
- dnl it does without going to look for what the heck -z defs does.
- for possible_flags in "-Wl,--no-undefined" "-Wl,-z,defs"; do
- CC_CHECK_LDFLAGS([$possible_flags], [LDFLAGS_NOUNDEFINED="$possible_flags"])
- break
- done
- ;;
- esac
-
- AC_SUBST([LDFLAGS_NOUNDEFINED])
-])
-
-dnl Check for a -Werror flag or equivalent. -Werror is the GCC
-dnl and ICC flag that tells the compiler to treat all the warnings
-dnl as fatal. We usually need this option to make sure that some
-dnl constructs (like attributes) are not simply ignored.
-dnl
-dnl Other compilers don't support -Werror per se, but they support
-dnl an equivalent flag:
-dnl - Sun Studio compiler supports -errwarn=%all
-AC_DEFUN([CC_CHECK_WERROR], [
- AC_CACHE_CHECK(
- [for $CC way to treat warnings as errors],
- [cc_cv_werror],
- [CC_CHECK_CFLAGS_SILENT([-Werror], [cc_cv_werror=-Werror],
- [CC_CHECK_CFLAGS_SILENT([-errwarn=%all], [cc_cv_werror=-errwarn=%all])])
- ])
-])
-
-AC_DEFUN([CC_CHECK_ATTRIBUTE], [
- AC_REQUIRE([CC_CHECK_WERROR])
- AC_CACHE_CHECK([if $CC supports __attribute__(( ifelse([$2], , [$1], [$2]) ))],
- AS_TR_SH([cc_cv_attribute_$1]),
- [ac_save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $cc_cv_werror"
- AC_COMPILE_IFELSE([AC_LANG_SOURCE([$3])],
- [eval "AS_TR_SH([cc_cv_attribute_$1])='yes'"],
- [eval "AS_TR_SH([cc_cv_attribute_$1])='no'"])
- CFLAGS="$ac_save_CFLAGS"
- ])
-
- AS_IF([eval test x$]AS_TR_SH([cc_cv_attribute_$1])[ = xyes],
- [AC_DEFINE(
- AS_TR_CPP([SUPPORT_ATTRIBUTE_$1]), 1,
- [Define this if the compiler supports __attribute__(( ifelse([$2], , [$1], [$2]) ))]
- )
- $4],
- [$5])
-])
-
-AC_DEFUN([CC_ATTRIBUTE_CONSTRUCTOR], [
- CC_CHECK_ATTRIBUTE(
- [constructor],,
- [void __attribute__((constructor)) ctor() { int a; }],
- [$1], [$2])
-])
-
-AC_DEFUN([CC_ATTRIBUTE_FORMAT], [
- CC_CHECK_ATTRIBUTE(
- [format], [format(printf, n, n)],
- [void __attribute__((format(printf, 1, 2))) printflike(const char *fmt, ...) { fmt = (void *)0; }],
- [$1], [$2])
-])
-
-AC_DEFUN([CC_ATTRIBUTE_FORMAT_ARG], [
- CC_CHECK_ATTRIBUTE(
- [format_arg], [format_arg(printf)],
- [char *__attribute__((format_arg(1))) gettextlike(const char *fmt) { fmt = (void *)0; }],
- [$1], [$2])
-])
-
-AC_DEFUN([CC_ATTRIBUTE_VISIBILITY], [
- CC_CHECK_ATTRIBUTE(
- [visibility_$1], [visibility("$1")],
- [void __attribute__((visibility("$1"))) $1_function() { }],
- [$2], [$3])
-])
-
-AC_DEFUN([CC_ATTRIBUTE_NONNULL], [
- CC_CHECK_ATTRIBUTE(
- [nonnull], [nonnull()],
- [void __attribute__((nonnull())) some_function(void *foo, void *bar) { foo = (void*)0; bar = (void*)0; }],
- [$1], [$2])
-])
-
-AC_DEFUN([CC_ATTRIBUTE_UNUSED], [
- CC_CHECK_ATTRIBUTE(
- [unused], ,
- [void some_function(void *foo, __attribute__((unused)) void *bar);],
- [$1], [$2])
-])
-
-AC_DEFUN([CC_ATTRIBUTE_SENTINEL], [
- CC_CHECK_ATTRIBUTE(
- [sentinel], ,
- [void some_function(void *foo, ...) __attribute__((sentinel));],
- [$1], [$2])
-])
-
-AC_DEFUN([CC_ATTRIBUTE_DEPRECATED], [
- CC_CHECK_ATTRIBUTE(
- [deprecated], ,
- [void some_function(void *foo, ...) __attribute__((deprecated));],
- [$1], [$2])
-])
-
-AC_DEFUN([CC_ATTRIBUTE_ALIAS], [
- CC_CHECK_ATTRIBUTE(
- [alias], [weak, alias],
- [void other_function(void *foo) { }
- void some_function(void *foo) __attribute__((weak, alias("other_function")));],
- [$1], [$2])
-])
-
-AC_DEFUN([CC_ATTRIBUTE_MALLOC], [
- CC_CHECK_ATTRIBUTE(
- [malloc], ,
- [void * __attribute__((malloc)) my_alloc(int n);],
- [$1], [$2])
-])
-
-AC_DEFUN([CC_ATTRIBUTE_PACKED], [
- CC_CHECK_ATTRIBUTE(
- [packed], ,
- [struct astructure { char a; int b; long c; void *d; } __attribute__((packed));],
- [$1], [$2])
-])
-
-AC_DEFUN([CC_ATTRIBUTE_CONST], [
- CC_CHECK_ATTRIBUTE(
- [const], ,
- [int __attribute__((const)) twopow(int n) { return 1 << n; } ],
- [$1], [$2])
-])
-
-AC_DEFUN([CC_FLAG_VISIBILITY], [
- AC_REQUIRE([CC_CHECK_WERROR])
- AC_CACHE_CHECK([if $CC supports -fvisibility=hidden],
- [cc_cv_flag_visibility],
- [cc_flag_visibility_save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $cc_cv_werror"
- CC_CHECK_CFLAGS_SILENT([-fvisibility=hidden],
- cc_cv_flag_visibility='yes',
- cc_cv_flag_visibility='no')
- CFLAGS="$cc_flag_visibility_save_CFLAGS"])
-
- AS_IF([test "x$cc_cv_flag_visibility" = "xyes"],
- [AC_DEFINE([SUPPORT_FLAG_VISIBILITY], 1,
- [Define this if the compiler supports the -fvisibility flag])
- $1],
- [$2])
-])
-
-AC_DEFUN([CC_FUNC_EXPECT], [
- AC_REQUIRE([CC_CHECK_WERROR])
- AC_CACHE_CHECK([if compiler has __builtin_expect function],
- [cc_cv_func_expect],
- [ac_save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $cc_cv_werror"
- AC_COMPILE_IFELSE([AC_LANG_SOURCE(
- [int some_function() {
- int a = 3;
- return (int)__builtin_expect(a, 3);
- }])],
- [cc_cv_func_expect=yes],
- [cc_cv_func_expect=no])
- CFLAGS="$ac_save_CFLAGS"
- ])
-
- AS_IF([test "x$cc_cv_func_expect" = "xyes"],
- [AC_DEFINE([SUPPORT__BUILTIN_EXPECT], 1,
- [Define this if the compiler supports __builtin_expect() function])
- $1],
- [$2])
-])
-
-AC_DEFUN([CC_ATTRIBUTE_ALIGNED], [
- AC_REQUIRE([CC_CHECK_WERROR])
- AC_CACHE_CHECK([highest __attribute__ ((aligned ())) supported],
- [cc_cv_attribute_aligned],
- [ac_save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $cc_cv_werror"
- for cc_attribute_align_try in 64 32 16 8 4 2; do
- AC_COMPILE_IFELSE([AC_LANG_SOURCE([
- int main() {
- static char c __attribute__ ((aligned($cc_attribute_align_try))) = 0;
- return c;
- }])], [cc_cv_attribute_aligned=$cc_attribute_align_try; break])
- done
- CFLAGS="$ac_save_CFLAGS"
- ])
-
- if test "x$cc_cv_attribute_aligned" != "x"; then
- AC_DEFINE_UNQUOTED([ATTRIBUTE_ALIGNED_MAX], [$cc_cv_attribute_aligned],
- [Define the highest alignment supported])
- fi
-])
diff --git a/m4/ax_normalize_path.m4 b/m4/ax_normalize_path.m4
deleted file mode 100644
index e8f9973e3..000000000
--- a/m4/ax_normalize_path.m4
+++ /dev/null
@@ -1,115 +0,0 @@
-# ===========================================================================
-# http://www.gnu.org/software/autoconf-archive/ax_normalize_path.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-# AX_NORMALIZE_PATH(VARNAME, [REFERENCE_STRING])
-#
-# DESCRIPTION
-#
-# Perform some cleanups on the value of $VARNAME (interpreted as a path):
-#
-# - empty paths are changed to '.'
-# - trailing slashes are removed
-# - repeated slashes are squeezed except a leading doubled slash '//'
-# (which might indicate a networked disk on some OS).
-#
-# REFERENCE_STRING is used to turn '/' into '\' and vice-versa: if
-# REFERENCE_STRING contains some backslashes, all slashes and backslashes
-# are turned into backslashes, otherwise they are all turned into slashes.
-#
-# This makes processing of DOS filenames quite easier, because you can
-# turn a filename to the Unix notation, make your processing, and turn it
-# back to original notation.
-#
-# filename='A:\FOO\\BAR\'
-# old_filename="$filename"
-# # Switch to the unix notation
-# AX_NORMALIZE_PATH([filename], ["/"])
-# # now we have $filename = 'A:/FOO/BAR' and we can process it as if
-# # it was a Unix path. For instance let's say that you want
-# # to append '/subpath':
-# filename="$filename/subpath"
-# # finally switch back to the original notation
-# AX_NORMALIZE_PATH([filename], ["$old_filename"])
-# # now $filename equals to 'A:\FOO\BAR\subpath'
-#
-# One good reason to make all path processing with the unix convention is
-# that backslashes have a special meaning in many cases. For instance
-#
-# expr 'A:\FOO' : 'A:\Foo'
-#
-# will return 0 because the second argument is a regex in which
-# backslashes have to be backslashed. In other words, to have the two
-# strings to match you should write this instead:
-#
-# expr 'A:\Foo' : 'A:\\Foo'
-#
-# Such behavior makes DOS filenames extremely unpleasant to work with. So
-# temporary turn your paths to the Unix notation, and revert them to the
-# original notation after the processing. See the macro
-# AX_COMPUTE_RELATIVE_PATHS for a concrete example of this.
-#
-# REFERENCE_STRING defaults to $VARIABLE, this means that slashes will be
-# converted to backslashes if $VARIABLE already contains some backslashes
-# (see $thirddir below).
-#
-# firstdir='/usr/local//share'
-# seconddir='C:\Program Files\\'
-# thirddir='C:\home/usr/'
-# AX_NORMALIZE_PATH([firstdir])
-# AX_NORMALIZE_PATH([seconddir])
-# AX_NORMALIZE_PATH([thirddir])
-# # $firstdir = '/usr/local/share'
-# # $seconddir = 'C:\Program Files'
-# # $thirddir = 'C:\home\usr'
-#
-# LICENSE
-#
-# Copyright (c) 2008 Alexandre Duret-Lutz <adl@gnu.org>
-#
-# This program 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.
-#
-# This program is distributed in the hope that 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 this program. If not, see <http://www.gnu.org/licenses/>.
-#
-# As a special exception, the respective Autoconf Macro's copyright owner
-# gives unlimited permission to copy, distribute and modify the configure
-# scripts that are the output of Autoconf when processing the Macro. You
-# need not follow the terms of the GNU General Public License when using
-# or distributing such scripts, even though portions of the text of the
-# Macro appear in them. The GNU General Public License (GPL) does govern
-# all other use of the material that constitutes the Autoconf Macro.
-#
-# This special exception to the GPL applies to versions of the Autoconf
-# Macro released by the Autoconf Archive. When you make and distribute a
-# modified version of the Autoconf Macro, you may extend this special
-# exception to the GPL to apply to your modified version as well.
-
-#serial 5
-
-AU_ALIAS([ADL_NORMALIZE_PATH], [AX_NORMALIZE_PATH])
-AC_DEFUN([AX_NORMALIZE_PATH],
-[case ":[$]$1:" in
-# change empty paths to '.'
- ::) $1='.' ;;
-# strip trailing slashes
- :*[[\\/]]:) $1=`echo "[$]$1" | sed 's,[[\\/]]*[$],,'` ;;
- :*:) ;;
-esac
-# squeze repeated slashes
-case ifelse($2,,"[$]$1",$2) in
-# if the path contains any backslashes, turn slashes into backslashes
- *\\*) $1=`echo "[$]$1" | sed 's,\(.\)[[\\/]][[\\/]]*,\1\\\\,g'` ;;
-# if the path contains slashes, also turn backslashes into slashes
- *) $1=`echo "[$]$1" | sed 's,\(.\)[[\\/]][[\\/]]*,\1/,g'` ;;
-esac])
diff --git a/man/.gitignore b/man/.gitignore
deleted file mode 100644
index 4b5f0a489..000000000
--- a/man/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-/elogind.directives.xml
-/elogind.index.xml
-/*.[13578]
-/*.html
-/custom-entities.ent
diff --git a/man/Makefile b/man/Makefile
deleted file mode 120000
index bd1047548..000000000
--- a/man/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../src/Makefile \ No newline at end of file
diff --git a/man/custom-entities.ent.in b/man/custom-entities.ent.in
new file mode 100644
index 000000000..9c70fecb2
--- /dev/null
+++ b/man/custom-entities.ent.in
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!-- 0 /// elogind does not has any of these but KILL_USER_PROCESSES.
+# <!ENTITY MOUNT_PATH @MOUNT_PATH@>
+# <!ENTITY UMOUNT_PATH @UMOUNT_PATH@>
+# <!ENTITY systemgeneratordir @SYSTEM_GENERATOR_PATH@>
+# <!ENTITY usergeneratordir @USER_GENERATOR_PATH@>
+# <!ENTITY systemenvgeneratordir @SYSTEM_ENV_GENERATOR_PATH@>
+# <!ENTITY userenvgeneratordir @USER_ENV_GENERATOR_PATH@>
+# <!ENTITY CERTIFICATE_ROOT @CERTIFICATE_ROOT@>
+# <!ENTITY MEMORY_ACCOUNTING_DEFAULT @MEMORY_ACCOUNTING_DEFAULT_YES_NO@>
+// 0 -->
+<!ENTITY KILL_USER_PROCESSES @KILL_USER_PROCESSES_YES_NO@>
diff --git a/man/custom-html.xsl b/man/custom-html.xsl
index f1271dcb1..ca0326cfa 100644
--- a/man/custom-html.xsl
+++ b/man/custom-html.xsl
@@ -1,22 +1,8 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!--
- This file is part of elogind.
+ SPDX-License-Identifier: LGPL-2.1+
- Copyright 2011 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
@@ -71,6 +57,18 @@
</a>
</xsl:template>
+<xsl:template match="citerefentry[@project='wireguard']">
+ <a>
+ <xsl:attribute name="href">
+ <xsl:text>https://git.zx2c4.com/WireGuard/about/src/tools/</xsl:text>
+ <xsl:value-of select="refentrytitle"/>
+ <xsl:text>.</xsl:text>
+ <xsl:value-of select="manvolnum"/>
+ </xsl:attribute>
+ <xsl:call-template name="inline.charseq"/>
+ </a>
+</xsl:template>
+
<xsl:template match="citerefentry[@project='mankier']">
<a>
<xsl:attribute name="href">
diff --git a/man/custom-man.xsl b/man/custom-man.xsl
index 853e214d1..5cd94834a 100644
--- a/man/custom-man.xsl
+++ b/man/custom-man.xsl
@@ -1,22 +1,7 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!--
- This file is part of elogind.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
diff --git a/man/elogind-inhibit.xml b/man/elogind-inhibit.xml
new file mode 100644
index 000000000..d095e1b05
--- /dev/null
+++ b/man/elogind-inhibit.xml
@@ -0,0 +1,157 @@
+<?xml version='1.0'?> <!--*-nxml-*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ SPDX-License-Identifier: LGPL-2.1+
+-->
+
+<refentry id="elogind-inhibit"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>elogind-inhibit</title>
+ <productname>elogind</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>elogind-inhibit</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>elogind-inhibit</refname>
+ <refpurpose>Execute a program with an inhibition lock taken</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>elogind-inhibit <arg choice="opt" rep="repeat">OPTIONS</arg> <arg>COMMAND</arg> <arg choice="opt" rep="repeat">ARGUMENTS</arg></command>
+ </cmdsynopsis>
+ <cmdsynopsis>
+ <command>elogind-inhibit <arg choice="opt" rep="repeat">OPTIONS</arg> --list</command>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><command>elogind-inhibit</command> may be used to execute a
+ program with a shutdown, sleep, or idle inhibitor lock taken. The
+ lock will be acquired before the specified command line is
+ executed and released afterwards.</para>
+
+ <para>Inhibitor locks may be used to block or delay system sleep
+ and shutdown requests from the user, as well as automatic idle
+ handling of the OS. This is useful to avoid system suspends while
+ an optical disc is being recorded, or similar operations that
+ should not be interrupted.</para>
+
+ <para>For more information see the <ulink
+ url="https://www.freedesktop.org/wiki/Software/systemd/inhibit">Inhibitor
+ Lock Developer Documentation</ulink>.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Options</title>
+
+ <para>The following options are understood:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>--what=</option></term>
+
+ <listitem><para>Takes a colon-separated list of one or more
+ operations to inhibit:
+ <literal>shutdown</literal>,
+ <literal>sleep</literal>,
+ <literal>idle</literal>,
+ <literal>handle-power-key</literal>,
+ <literal>handle-suspend-key</literal>,
+ <literal>handle-hibernate-key</literal>,
+ <literal>handle-lid-switch</literal>,
+ for inhibiting reboot/power-off/halt/kexec,
+ suspending/hibernating, the automatic idle detection, or the
+ low-level handling of the power/sleep key and the lid switch,
+ respectively. If omitted, defaults to
+ <literal>idle:sleep:shutdown</literal>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--who=</option></term>
+
+ <listitem><para>Takes a short, human-readable descriptive
+ string for the program taking the lock. If not passed,
+ defaults to the command line string.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--why=</option></term>
+
+ <listitem><para>Takes a short, human-readable descriptive
+ string for the reason for taking the lock. Defaults to
+ "Unknown reason".</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--mode=</option></term>
+
+ <listitem><para>Takes either <literal>block</literal> or
+ <literal>delay</literal> and describes how the lock is
+ applied. If <literal>block</literal> is used (the default),
+ the lock prohibits any of the requested operations without
+ time limit, and only privileged users may override it. If
+ <literal>delay</literal> is used, the lock can only delay the
+ requested operations for a limited time. If the time elapses,
+ the lock is ignored and the operation executed. The time limit
+ may be specified in
+ <citerefentry><refentrytitle>logind.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ Note that <literal>delay</literal> is only available for
+ <literal>sleep</literal> and
+ <literal>shutdown</literal>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--list</option></term>
+
+ <listitem><para>Lists all active inhibition locks instead of
+ acquiring one.</para></listitem>
+ </varlistentry>
+
+ <xi:include href="standard-options.xml" xpointer="no-pager" />
+ <xi:include href="standard-options.xml" xpointer="no-legend" />
+ <xi:include href="standard-options.xml" xpointer="help" />
+ <xi:include href="standard-options.xml" xpointer="version" />
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1>
+ <title>Exit status</title>
+
+ <para>Returns the exit status of the executed program.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Example</title>
+
+ <programlisting># elogind-inhibit wodim foobar.iso</programlisting>
+
+ <para>This burns the ISO image
+ <filename>foobar.iso</filename> on a CD using
+ <citerefentry project='man-pages'><refentrytitle>wodim</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ and inhibits system sleeping, shutdown and idle while
+ doing so.</para>
+ </refsect1>
+
+ <xi:include href="less-variables.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>logind.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/elogind.syntax.xml b/man/elogind.syntax.xml
new file mode 100644
index 000000000..9b39b45c9
--- /dev/null
+++ b/man/elogind.syntax.xml
@@ -0,0 +1,98 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
+<!ENTITY % entities SYSTEM "custom-entities.ent" >
+%entities;
+]>
+
+<!-- SPDX-License-Identifier: LGPL-2.1+ -->
+
+<refentry id="elogind.syntax">
+
+ <refentryinfo>
+ <title>elogind.syntax</title>
+ <productname>elogind</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>elogind.syntax</refentrytitle>
+ <manvolnum>7</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>elogind.syntax</refname>
+ <refpurpose>General syntax of elogind configuration files</refpurpose>
+ </refnamediv>
+
+ <refsect1>
+ <title>Introduction</title>
+
+ <para>This page describes the basic principles of configuration files used by
+ <citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ and related programs for:
+ <itemizedlist>
+ <listitem><para>elogind unit files, see
+ <citerefentry><refentrytitle>elogind.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>elogind.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>elogind.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>elogind.device</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>elogind.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>elogind.automount</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>elogind.swap</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>elogind.target</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>elogind.path</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>elogind.timer</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>elogind.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>elogind.scope</refentrytitle><manvolnum>5</manvolnum></citerefentry></para></listitem>
+
+ <listitem><para>daemon config files, see
+ <citerefentry><refentrytitle>elogind-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>elogind-user.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>logind.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>journal-remote.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>journal-upload.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>elogind-sleep.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>timesyncd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ </para></listitem>
+ </itemizedlist>
+ </para>
+
+ <para>The syntax is inspired by
+ <ulink url="http://standards.freedesktop.org/desktop-entry-spec/latest/">XDG Desktop Entry Specification</ulink>
+ <filename>.desktop</filename> files, which are in turn inspired by Microsoft Windows
+ <filename>.ini</filename> files.
+ </para>
+
+ <para>Each file is a plain text file divided into sections, with configuration entries in the
+ style <replaceable>key</replaceable>=<replaceable>value</replaceable>.
+ Empty lines and lines starting with <literal>#</literal> or <literal>;</literal> are
+ ignored, which may be used for commenting.</para>
+
+ <para>Lines ending in a backslash are concatenated with the following line while reading and the
+ backslash is replaced by a space character. This may be used to wrap long lines. The limit on
+ line length is very large (currently 1 MB), but it is recommended to avoid such long lines and
+ use multiple directives, variable substitution, or other mechanism as appropriate for the given
+ file type.</para>
+
+ <example><programlisting>[Section A]
+KeyOne=value 1
+KeyTwo=value 2
+
+# a comment
+
+[Section B]
+Setting="something" "some thing" "…"
+KeyTwo=value 2 \
+ value 2 continued
+</programlisting></example>
+
+ <para>Various settings are allowed to be specified more than once, in which case the
+ interpretation depends on the setting. Often, multiple settings form a list, and setting to an
+ empty value "resets", which means that previous assignments are ignored. When this is allowed,
+ it is mentioned in the description of the setting. Note that using multiple assignments to the
+ same value makes the file incompatible with parsers for the XDG <filename>.desktop</filename>
+ file format.</para>
+ </refsect1>
+
+</refentry>
diff --git a/man/elogind.xml b/man/elogind.xml
index 19dbd477e..e84bfd226 100644
--- a/man/elogind.xml
+++ b/man/elogind.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2010 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="elogind"
@@ -27,34 +12,75 @@
<refentryinfo>
<title>elogind</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>elogind</refentrytitle>
+ <!-- 0 /// elogind is in section 8
+ <manvolnum>1</manvolnum>
+ --><!-- else -->
<manvolnum>8</manvolnum>
+ <!-- // 0 -->
</refmeta>
<refnamediv>
+ <!-- 0 /// Well, elogind isn't that much...
+ <refname>systemd</refname>
+ <refname>init</refname>
+ <refpurpose>systemd system and service manager</refpurpose>
+ --><!-- else -->
<refname>elogind</refname>
<refpurpose>Login manager</refpurpose>
+ <!-- // 0 -->
</refnamediv>
<refsynopsisdiv>
- <para><filename>/usr/libexec/elogind/elogind</filename></para>
+ <!-- 0 /// elogind has a different synopsis of course...
+ <cmdsynopsis>
+ <command>/usr/lib/systemd/systemd</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+ <command>init</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="req">COMMAND</arg>
+ </cmdsynopsis>
+ --><!-- else -->
+ <cmdsynopsis>
+ <command>elogind</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="req">COMMAND</arg>
+ </cmdsynopsis>
+ <!-- // 0 -->
</refsynopsisdiv>
<refsect1>
<title>Description</title>
+ <!-- 0 /// elogind does not need that much explanation.
+ <para>systemd is a system and service manager for Linux operating
+ systems. When run as first process on boot (as PID 1), it acts as
+ init system that brings up and maintains userspace
+ services.</para>
+
+ <para>For compatibility with SysV, if systemd is called as
+ <command>init</command> and a PID that is not 1, it will execute
+ <command>telinit</command> and pass all command line arguments
+ unmodified. That means <command>init</command> and
+ <command>telinit</command> are mostly equivalent when invoked from
+ normal login sessions. See
+ <citerefentry><refentrytitle>telinit</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ for more information.</para>
+
+ <para>When run as a system instance, systemd interprets the
+ configuration file <filename>system.conf</filename> and the files
+ in <filename>system.conf.d</filename> directories; when run as a
+ user instance, systemd interprets the configuration file
+ <filename>user.conf</filename> and the files in
+ <filename>user.conf.d</filename> directories. See
+ <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for more information.</para>
+ --><!-- else -->
<para><command>elogind</command> is a system service that
manages user logins. It is responsible for:</para>
@@ -101,14 +127,1208 @@
<para>For more information on the inhibition logic see the <ulink
url="http://www.freedesktop.org/wiki/Software/systemd/inhibit">Inhibitor
Lock Developer Documentation</ulink>.</para>
+ <!-- // 0 -->
+ </refsect1>
+
+ <refsect1>
+ <title>Options</title>
+
+ <para>The following options are understood:</para>
+
+ <variablelist>
+ <!-- 0 /// This list is much shorter with elogind of course.
+ <varlistentry>
+ <term><option>&#x2D;&#x2D;test</option></term>
+
+ <listitem><para>Determine startup sequence, dump it and exit.
+ This is an option useful for debugging only.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>&#x2D;&#x2D;dump-configuration-items</option></term>
+
+ <listitem><para>Dump understood unit configuration items. This
+ outputs a terse but complete list of configuration items
+ understood in unit definition files.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>&#x2D;&#x2D;dump-bus-properties</option></term>
+
+ <listitem><para>Dump exposed bus properties. This outputs
+ a terse but complete list of properties exposed to dbus.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>&#x2D;&#x2D;unit=</option></term>
+
+ <listitem><para>Set default unit to activate on startup. If
+ not specified, defaults to
+ <filename>default.target</filename>.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>&#x2D;&#x2D;system</option></term>
+ <term><option>&#x2D;&#x2D;user</option></term>
+
+ <listitem><para>For <option>&#x2D;&#x2D;system</option>, tell systemd to
+ run a system instance, even if the process ID is not 1, i.e.
+ systemd is not run as init process. <option>&#x2D;&#x2D;user</option>
+ does the opposite, running a user instance even if the process
+ ID is 1. Normally, it should not be necessary to pass these
+ options, as systemd automatically detects the mode it is
+ started in. These options are hence of little use except for
+ debugging. Note that it is not supported booting and
+ maintaining a full system with systemd running in
+ <option>&#x2D;&#x2D;system</option> mode, but PID not 1. In practice,
+ passing <option>&#x2D;&#x2D;system</option> explicitly is only useful in
+ conjunction with <option>&#x2D;&#x2D;test</option>.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>&#x2D;&#x2D;dump-core</option></term>
+
+ <listitem><para>Enable core dumping on crash. This switch has
+ no effect when running as user instance. This setting may also
+ be enabled during boot on the kernel command line via the
+ <varname>systemd.dump_core=</varname> option, see
+ below.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>&#x2D;&#x2D;crash-vt=</option><replaceable>VT</replaceable></term>
+
+ <listitem><para>Switch to a specific virtual console (VT) on
+ crash. Takes a positive integer in the range 1–63, or a
+ boolean argument. If an integer is passed, selects which VT to
+ switch to. If <constant>yes</constant>, the VT kernel messages
+ are written to is selected. If <constant>no</constant>, no VT
+ switch is attempted. This switch has no effect when running as
+ user instance. This setting may also be enabled during boot,
+ on the kernel command line via the
+ <varname>systemd.crash_vt=</varname> option, see
+ // 0 -->
+ <!-- FIXME: there is no crash_vt command line option? -->
+ <!-- 0 /// elogind check_tree.pl can not mangle closed comments.
+ below.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>&#x2D;&#x2D;crash-shell</option></term>
+
+ <listitem><para>Run a shell on crash. This switch has no
+ effect when running as user instance. This setting may also be
+ enabled during boot, on the kernel command line via the
+ <varname>systemd.crash_shell=</varname> option, see
+ below.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>&#x2D;&#x2D;crash-reboot</option></term>
+
+ <listitem><para>Automatically reboot the system on crash. This
+ switch has no effect when running as user instance. This
+ setting may also be enabled during boot, on the kernel command
+ line via the <varname>systemd.crash_reboot=</varname> option,
+ see below.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>&#x2D;&#x2D;confirm-spawn</option></term>
+
+ <listitem><para>Ask for confirmation when spawning processes.
+ This switch has no effect when run as user
+ instance.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>&#x2D;&#x2D;show-status=</option></term>
+
+ <listitem><para>Takes a boolean argument or the special value <constant>auto</constant>. If on, terse unit
+ status information is shown on the console during boot-up and shutdown. If off, no such status information is
+ shown. If set to <constant>auto</constant> behavior is similar to off, except that it is automatically switched
+ to on, as soon as the first unit failure or significant boot delay is encountered. This switch has no effect
+ when invoked as user instance. If specified, overrides both the kernel command line setting
+ <varname>systemd.show_status=</varname> (see below) and the configuration file option
+ <option>ShowStatus=</option>, see
+ <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>&#x2D;&#x2D;log-target=</option></term>
+
+ <listitem><para>Set log target. Argument must be one of
+ <option>console</option>,
+ <option>journal</option>,
+ <option>kmsg</option>,
+ <option>journal-or-kmsg</option>,
+ <option>null</option>.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>&#x2D;&#x2D;log-level=</option></term>
+
+ <listitem><para>Set log level. As
+ argument this accepts a numerical log
+ level or the well-known <citerefentry project='man-pages'><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ symbolic names (lowercase):
+ <option>emerg</option>,
+ <option>alert</option>,
+ <option>crit</option>,
+ <option>err</option>,
+ <option>warning</option>,
+ <option>notice</option>,
+ <option>info</option>,
+ <option>debug</option>.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>&#x2D;&#x2D;log-color=</option></term>
+
+ <listitem><para>Highlight important log messages. Argument is
+ a boolean value. If the argument is omitted, it defaults to
+ <option>true</option>.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>&#x2D;&#x2D;log-location=</option></term>
+
+ <listitem><para>Include code location in log messages. This is
+ mostly relevant for debugging purposes. Argument is a boolean
+ value. If the argument is omitted it defaults to
+ <option>true</option>.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>&#x2D;&#x2D;default-standard-output=</option></term>
+ <term><option>&#x2D;&#x2D;default-standard-error=</option></term>
+
+ <listitem><para>Sets the default output or error output for
+ all services and sockets, respectively. That is, controls the
+ default for <option>StandardOutput=</option> and
+ <option>StandardError=</option> (see
+ <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for details). Takes one of
+ <option>inherit</option>,
+ <option>null</option>,
+ <option>tty</option>,
+ <option>journal</option>,
+ <option>journal+console</option>,
+ <option>syslog</option>,
+ <option>syslog+console</option>,
+ <option>kmsg</option>,
+ <option>kmsg+console</option>. If the
+ argument is omitted
+ <option>&#x2D;&#x2D;default-standard-output=</option> defaults to
+ <option>journal</option> and
+ <option>&#x2D;&#x2D;default-standard-error=</option> to
+ <option>inherit</option>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>&#x2D;&#x2D;machine-id=</option></term>
+
+ <listitem><para>Override the machine-id set on the hard drive,
+ useful for network booting or for containers. May not be set
+ to all zeros.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>&#x2D;&#x2D;service-watchdogs=</option></term>
+
+ <listitem><para>Globally enable/disable all service watchdog timeouts and emergency
+ actions. This setting may also be specified during boot, on the kernel
+ command line via the <varname>systemd.service_watchdogs=</varname>
+ option, see below. Defaults to enabled.</para></listitem>
+ </varlistentry>
+
+ <xi:include href="standard-options.xml" xpointer="help" />
+ <xi:include href="standard-options.xml" xpointer="version" />
+ else -->
+ <varlistentry>
+ <term><option>-D</option></term>
+ <term><option>--daemon</option></term>
+
+ <listitem><para>Daemonize elogind by double-forking
+ into background.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-h</option></term>
+ <term><option>--help</option></term>
+
+ <listitem><para>Show the helpt text and exit.</para></listitem>
+ </varlistentry>
+ <!-- // 0 -->
+ </variablelist>
+ </refsect1>
+
+ <!-- 0 /// The whole concpets section is unneeded in elogind
+ <refsect1>
+ <title>Concepts</title>
+
+ <para>systemd provides a dependency system between various
+ entities called "units" of 11 different types. Units encapsulate
+ various objects that are relevant for system boot-up and
+ maintenance. The majority of units are configured in unit
+ configuration files, whose syntax and basic set of options is
+ described in
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ however some are created automatically from other configuration,
+ dynamically from system state or programmatically at runtime.
+ Units may be "active" (meaning started, bound, plugged in, …,
+ depending on the unit type, see below), or "inactive" (meaning
+ stopped, unbound, unplugged, …), as well as in the process of
+ being activated or deactivated, i.e. between the two states (these
+ states are called "activating", "deactivating"). A special
+ "failed" state is available as well, which is very similar to
+ "inactive" and is entered when the service failed in some way
+ (process returned error code on exit, or crashed, an operation
+ timed out, or after too many restarts). If this state is entered,
+ the cause will be logged, for later reference. Note that the
+ various unit types may have a number of additional substates,
+ which are mapped to the five generalized unit states described
+ here.</para>
+
+ <para>The following unit types are available:</para>
+
+ <orderedlist>
+ <listitem><para>Service units, which start and control daemons
+ and the processes they consist of. For details, see
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para></listitem>
+
+ <listitem><para>Socket units, which encapsulate local IPC or
+ network sockets in the system, useful for socket-based
+ activation. For details about socket units, see
+ <citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ for details on socket-based activation and other forms of
+ activation, see
+ <citerefentry><refentrytitle>daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para></listitem>
+
+ <listitem><para>Target units are useful to group units, or
+ provide well-known synchronization points during boot-up, see
+ <citerefentry><refentrytitle>systemd.target</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para></listitem>
+
+ <listitem><para>Device units expose kernel devices in systemd
+ and may be used to implement device-based activation. For
+ details, see
+ <citerefentry><refentrytitle>systemd.device</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para></listitem>
+
+ <listitem><para>Mount units control mount points in the file
+ system, for details see
+ <citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para></listitem>
+
+ <listitem><para>Automount units provide automount capabilities,
+ for on-demand mounting of file systems as well as parallelized
+ boot-up. See
+ <citerefentry><refentrytitle>systemd.automount</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para></listitem>
+
+ <listitem><para>Timer units are useful for triggering activation
+ of other units based on timers. You may find details in
+ <citerefentry><refentrytitle>systemd.timer</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para></listitem>
+
+ <listitem><para>Swap units are very similar to mount units and
+ encapsulate memory swap partitions or files of the operating
+ system. They are described in
+ <citerefentry><refentrytitle>systemd.swap</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para></listitem>
+
+ <listitem><para>Path units may be used to activate other
+ services when file system objects change or are modified. See
+ <citerefentry><refentrytitle>systemd.path</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para></listitem>
+
+ <listitem><para>Slice units may be used to group units which
+ manage system processes (such as service and scope units) in a
+ hierarchical tree for resource management purposes. See
+ <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para></listitem>
+
+ <listitem><para>Scope units are similar to service units, but
+ manage foreign processes instead of starting them as well. See
+ <citerefentry><refentrytitle>systemd.scope</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para></listitem>
+
+ </orderedlist>
+
+ <para>Units are named as their configuration files. Some units
+ have special semantics. A detailed list is available in
+ <citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
+
+ <para>systemd knows various kinds of dependencies, including
+ positive and negative requirement dependencies (i.e.
+ <varname>Requires=</varname> and <varname>Conflicts=</varname>) as
+ well as ordering dependencies (<varname>After=</varname> and
+ <varname>Before=</varname>). NB: ordering and requirement
+ dependencies are orthogonal. If only a requirement dependency
+ exists between two units (e.g. <filename>foo.service</filename>
+ requires <filename>bar.service</filename>), but no ordering
+ dependency (e.g. <filename>foo.service</filename> after
+ <filename>bar.service</filename>) and both are requested to start,
+ they will be started in parallel. It is a common pattern that both
+ requirement and ordering dependencies are placed between two
+ units. Also note that the majority of dependencies are implicitly
+ created and maintained by systemd. In most cases, it should be
+ unnecessary to declare additional dependencies manually, however
+ it is possible to do this.</para>
+
+ <para>Application programs and units (via dependencies) may
+ request state changes of units. In systemd, these requests are
+ encapsulated as 'jobs' and maintained in a job queue. Jobs may
+ succeed or can fail, their execution is ordered based on the
+ ordering dependencies of the units they have been scheduled
+ for.</para>
+
+ <para>On boot systemd activates the target unit
+ <filename>default.target</filename> whose job is to activate
+ on-boot services and other on-boot units by pulling them in via
+ dependencies. Usually, the unit name is just an alias (symlink) for
+ either <filename>graphical.target</filename> (for fully-featured
+ boots into the UI) or <filename>multi-user.target</filename> (for
+ limited console-only boots for use in embedded or server
+ environments, or similar; a subset of graphical.target). However,
+ it is at the discretion of the administrator to configure it as an
+ alias to any other target unit. See
+ <citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ for details about these target units.</para>
+
+ <para>Processes systemd spawns are placed in individual Linux
+ control groups named after the unit which they belong to in the
+ private systemd hierarchy. (see <ulink
+ url="https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt">cgroups.txt</ulink>
+ for more information about control groups, or short "cgroups").
+ systemd uses this to effectively keep track of processes. Control
+ group information is maintained in the kernel, and is accessible
+ via the file system hierarchy (beneath
+ <filename>/sys/fs/cgroup/systemd/</filename>), or in tools such as
+ <citerefentry project='man-pages'><refentrytitle>systemd-cgls</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ or
+ <citerefentry project='man-pages'><refentrytitle>ps</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ (<command>ps xawf -eo pid,user,cgroup,args</command> is
+ particularly useful to list all processes and the systemd units
+ they belong to.).</para>
+
+ <para>systemd is compatible with the SysV init system to a large
+ degree: SysV init scripts are supported and simply read as an
+ alternative (though limited) configuration file format. The SysV
+ <filename>/dev/initctl</filename> interface is provided, and
+ compatibility implementations of the various SysV client tools are
+ available. In addition to that, various established Unix
+ functionality such as <filename>/etc/fstab</filename> or the
+ <filename>utmp</filename> database are supported.</para>
+
+ <para>systemd has a minimal transaction system: if a unit is
+ requested to start up or shut down it will add it and all its
+ dependencies to a temporary transaction. Then, it will verify if
+ the transaction is consistent (i.e. whether the ordering of all
+ units is cycle-free). If it is not, systemd will try to fix it up,
+ and removes non-essential jobs from the transaction that might
+ remove the loop. Also, systemd tries to suppress non-essential
+ jobs in the transaction that would stop a running service. Finally
+ it is checked whether the jobs of the transaction contradict jobs
+ that have already been queued, and optionally the transaction is
+ aborted then. If all worked out and the transaction is consistent
+ and minimized in its impact it is merged with all already
+ outstanding jobs and added to the run queue. Effectively this
+ means that before executing a requested operation, systemd will
+ verify that it makes sense, fixing it if possible, and only
+ failing if it really cannot work.</para>
+
+ <para>systemd contains native implementations of various tasks
+ that need to be executed as part of the boot process. For example,
+ it sets the hostname or configures the loopback network device. It
+ also sets up and mounts various API file systems, such as
+ <filename>/sys</filename> or <filename>/proc</filename>.</para>
+
+ <para>For more information about the concepts and
+ ideas behind systemd, please refer to the
+ <ulink url="http://0pointer.de/blog/projects/systemd.html">Original Design Document</ulink>.</para>
+
+ <para>Note that some but not all interfaces provided
+ by systemd are covered by the
+ <ulink url="https://www.freedesktop.org/wiki/Software/systemd/InterfaceStabilityPromise">Interface
+ Stability Promise</ulink>.</para>
+
+ <para>Units may be generated dynamically at boot and system
+ manager reload time, for example based on other configuration
+ files or parameters passed on the kernel command line. For details, see
+ <citerefentry><refentrytitle>systemd.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
+
+ <para>Systems which invoke systemd in a container or initrd
+ environment should implement the
+ <ulink url="https://www.freedesktop.org/wiki/Software/systemd/ContainerInterface">Container Interface</ulink> or
+ <ulink url="https://www.freedesktop.org/wiki/Software/systemd/InitrdInterface">initrd Interface</ulink>
+ specifications, respectively.</para>
+ </refsect1>
+ // 0 -->
+
+ <!-- 0 /// The whole directories section is unneeded in elogind
+ <refsect1>
+ <title>Directories</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>System unit directories</term>
+
+ <listitem><para>The systemd system manager reads unit
+ configuration from various directories. Packages that want to
+ install unit files shall place them in the directory returned
+ by <command>pkg-config systemd
+ &#x2D;&#x2D;variable=systemdsystemunitdir</command>. Other directories
+ checked are <filename>/usr/local/lib/systemd/system</filename>
+ and <filename>/usr/lib/systemd/system</filename>. User
+ configuration always takes precedence. <command>pkg-config
+ systemd &#x2D;&#x2D;variable=systemdsystemconfdir</command> returns the
+ path of the system configuration directory. Packages should
+ alter the content of these directories only with the
+ <command>enable</command> and <command>disable</command>
+ commands of the
+ <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ tool. Full list of directories is provided in
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ </para></listitem>
+ </varlistentry>
+ </variablelist>
+
+ <variablelist>
+ <varlistentry>
+ <term>User unit directories</term>
+
+ <listitem><para>Similar rules apply for the user unit
+ directories. However, here the
+ <ulink url="http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html">XDG
+ Base Directory specification</ulink> is followed to find
+ units. Applications should place their unit files in the
+ directory returned by <command>pkg-config systemd
+ &#x2D;&#x2D;variable=systemduserunitdir</command>. Global configuration
+ is done in the directory reported by <command>pkg-config
+ systemd &#x2D;&#x2D;variable=systemduserconfdir</command>. The
+ <command>enable</command> and <command>disable</command>
+ commands of the
+ <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ tool can handle both global (i.e. for all users) and private
+ (for one user) enabling/disabling of units. Full list of
+ directories is provided in
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ </para></listitem>
+ </varlistentry>
+ </variablelist>
+
+ <variablelist>
+ <varlistentry>
+ <term>SysV init scripts directory</term>
+
+ <listitem><para>The location of the SysV init script directory
+ varies between distributions. If systemd cannot find a native
+ unit file for a requested service, it will look for a SysV
+ init script of the same name (with the
+ <filename>.service</filename> suffix
+ removed).</para></listitem>
+ </varlistentry>
+ </variablelist>
+
+ <variablelist>
+ <varlistentry>
+ <term>SysV runlevel link farm directory</term>
+
+ <listitem><para>The location of the SysV runlevel link farm
+ directory varies between distributions. systemd will take the
+ link farm into account when figuring out whether a service
+ shall be enabled. Note that a service unit with a native unit
+ configuration file cannot be started by activating it in the
+ SysV runlevel link farm.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+ // 0 -->
+
+ <!-- 0 /// The whole Signals section is unneeded in elogind
+ <refsect1>
+ <title>Signals</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>SIGTERM</constant></term>
+
+ <listitem><para>Upon receiving this signal the systemd system
+ manager serializes its state, reexecutes itself and
+ deserializes the saved state again. This is mostly equivalent
+ to <command>systemctl daemon-reexec</command>.</para>
+
+ <para>systemd user managers will start the
+ <filename>exit.target</filename> unit when this signal is
+ received. This is mostly equivalent to <command>systemctl
+ &#x2D;&#x2D;user start exit.target
+ &#x2D;&#x2D;job-mode=replace-irreversible</command>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGINT</constant></term>
+
+ <listitem><para>Upon receiving this signal the systemd system
+ manager will start the
+ <filename>ctrl-alt-del.target</filename> unit. This is mostly
+ equivalent to <command>systemctl start ctrl-alt-del.target
+ &#x2D;&#x2D;job-mode=replace-irreversible</command>. If this signal is
+ received more than 7 times per 2s, an immediate reboot is
+ triggered. Note that pressing Ctrl-Alt-Del on the console
+ will trigger this signal. Hence, if a reboot is hanging,
+ pressing Ctrl-Alt-Del more than 7 times in 2s is a relatively
+ safe way to trigger an immediate reboot.</para>
+
+ <para>systemd user managers treat this signal the same way as
+ <constant>SIGTERM</constant>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGWINCH</constant></term>
+
+ <listitem><para>When this signal is received the systemd
+ system manager will start the
+ <filename>kbrequest.target</filename> unit. This is mostly
+ equivalent to <command>systemctl start
+ kbrequest.target</command>.</para>
+
+ <para>This signal is ignored by systemd user
+ managers.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGPWR</constant></term>
+
+ <listitem><para>When this signal is received the systemd
+ manager will start the <filename>sigpwr.target</filename>
+ unit. This is mostly equivalent to <command>systemctl start
+ sigpwr.target</command>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGUSR1</constant></term>
+
+ <listitem><para>When this signal is received the systemd
+ manager will try to reconnect to the D-Bus
+ bus.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGUSR2</constant></term>
+
+ <listitem><para>When this signal is received the systemd
+ manager will log its complete state in human-readable form.
+ The data logged is the same as printed by
+ <command>systemd-analyze dump</command>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGHUP</constant></term>
+
+ <listitem><para>Reloads the complete daemon configuration.
+ This is mostly equivalent to <command>systemctl
+ daemon-reload</command>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGRTMIN+0</constant></term>
+
+ <listitem><para>Enters default mode, starts the
+ <filename>default.target</filename> unit. This is mostly
+ equivalent to <command>systemctl isolate
+ default.target</command>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGRTMIN+1</constant></term>
+
+ <listitem><para>Enters rescue mode, starts the
+ <filename>rescue.target</filename> unit. This is mostly
+ equivalent to <command>systemctl isolate
+ rescue.target</command>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGRTMIN+2</constant></term>
+
+ <listitem><para>Enters emergency mode, starts the
+ <filename>emergency.service</filename> unit. This is mostly
+ equivalent to <command>systemctl isolate
+ emergency.service</command>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGRTMIN+3</constant></term>
+
+ <listitem><para>Halts the machine, starts the
+ <filename>halt.target</filename> unit. This is mostly
+ equivalent to <command>systemctl start halt.target
+ &#x2D;&#x2D;job-mode=replace-irreversible</command>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGRTMIN+4</constant></term>
+
+ <listitem><para>Powers off the machine, starts the
+ <filename>poweroff.target</filename> unit. This is mostly
+ equivalent to <command>systemctl start poweroff.target
+ &#x2D;&#x2D;job-mode=replace-irreversible</command>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGRTMIN+5</constant></term>
+
+ <listitem><para>Reboots the machine, starts the
+ <filename>reboot.target</filename> unit. This is mostly
+ equivalent to <command>systemctl start reboot.target
+ &#x2D;&#x2D;job-mode=replace-irreversible</command>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGRTMIN+6</constant></term>
+
+ <listitem><para>Reboots the machine via kexec, starts the
+ <filename>kexec.target</filename> unit. This is mostly
+ equivalent to <command>systemctl start kexec.target
+ &#x2D;&#x2D;job-mode=replace-irreversible</command>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGRTMIN+13</constant></term>
+
+ <listitem><para>Immediately halts the machine.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGRTMIN+14</constant></term>
+
+ <listitem><para>Immediately powers off the machine.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGRTMIN+15</constant></term>
+
+ <listitem><para>Immediately reboots the machine.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGRTMIN+16</constant></term>
+
+ <listitem><para>Immediately reboots the machine with kexec.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGRTMIN+20</constant></term>
+
+ <listitem><para>Enables display of status messages on the
+ console, as controlled via
+ <varname>systemd.show_status=1</varname> on the kernel command
+ line.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGRTMIN+21</constant></term>
+
+ <listitem><para>Disables display of
+ status messages on the console, as
+ controlled via
+ <varname>systemd.show_status=0</varname>
+ on the kernel command
+ line.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGRTMIN+22</constant></term>
+
+ <listitem><para>Sets the service manager's log level to <literal>debug</literal>, in a fashion equivalent to
+ <varname>systemd.log_level=debug</varname> on the kernel command line.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGRTMIN+23</constant></term>
+
+ <listitem><para>Restores the log level to its configured value. The configured value is derived from – in order
+ of priority – the value specified with <varname>systemd.log-level=</varname> on the kernel command line, or the
+ value specified with <option>LogLevel=</option> in the configuration file, or the built-in default of
+ <literal>info</literal>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGRTMIN+24</constant></term>
+
+ <listitem><para>Immediately exits the manager (only available
+ for &#x2D;&#x2D;user instances).</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGRTMIN+26</constant></term>
+
+ <listitem><para>Restores the log target to its configured value. The configured value is derived from – in
+ order of priority – the value specified with <varname>systemd.log-target=</varname> on the kernel command line,
+ or the value specified with <option>LogTarget=</option> in the configuration file, or the built-in
+ default.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SIGRTMIN+27</constant></term>
+ <term><constant>SIGRTMIN+28</constant></term>
+
+ <listitem><para>Sets the log target to <literal>console</literal> on <constant>SIGRTMIN+27</constant> (or
+ <literal>kmsg</literal> on <constant>SIGRTMIN+28</constant>), in a fashion equivalent to
+ <varname>systemd.log_target=console</varname> (or <varname>systemd.log_target=kmsg</varname> on
+ <constant>SIGRTMIN+28</constant>) on the kernel command line.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+ // 0 -->
+
+ <!-- 0 /// The whole environment section is unneeded in elogind
+ <refsect1>
+ <title>Environment</title>
+
+ <variablelist class='environment-variables'>
+ <varlistentry>
+ <term><varname>$SYSTEMD_LOG_LEVEL</varname></term>
+ <listitem><para>systemd reads the log level from this
+ environment variable. This can be overridden with
+ <option>&#x2D;&#x2D;log-level=</option>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>$SYSTEMD_LOG_TARGET</varname></term>
+ <listitem><para>systemd reads the log target from this
+ environment variable. This can be overridden with
+ <option>&#x2D;&#x2D;log-target=</option>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>$SYSTEMD_LOG_COLOR</varname></term>
+ <listitem><para>Controls whether systemd highlights important
+ log messages. This can be overridden with
+ <option>&#x2D;&#x2D;log-color=</option>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>$SYSTEMD_LOG_LOCATION</varname></term>
+ <listitem><para>Controls whether systemd prints the code
+ location along with log messages. This can be overridden with
+ <option>&#x2D;&#x2D;log-location=</option>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>$XDG_CONFIG_HOME</varname></term>
+ <term><varname>$XDG_CONFIG_DIRS</varname></term>
+ <term><varname>$XDG_DATA_HOME</varname></term>
+ <term><varname>$XDG_DATA_DIRS</varname></term>
+
+ <listitem><para>The systemd user manager uses these variables
+ in accordance to the <ulink
+ url="http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html">XDG
+ Base Directory specification</ulink> to find its
+ configuration.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>$SYSTEMD_UNIT_PATH</varname></term>
+
+ <listitem><para>Controls where systemd looks for unit
+ files.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>$SYSTEMD_SYSVINIT_PATH</varname></term>
+
+ <listitem><para>Controls where systemd looks for SysV init
+ scripts.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>$SYSTEMD_SYSVRCND_PATH</varname></term>
+
+ <listitem><para>Controls where systemd looks for SysV init
+ script runlevel link farms.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>$SYSTEMD_COLORS</varname></term>
+
+ <listitem><para>The value must be a boolean. Controls whether colorized output should be
+ generated. This can be specified to override the decision that <command>systemd</command>
+ makes based on <varname>$TERM</varname> and what the console is connected to.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>$SYSTEMD_URLIFY</varname></term>
+
+ <listitem><para>The value must be a boolean. Controls whether clickable links should be generated in the output
+ for terminal emulators supporting this. This can be specified to override the decision that
+ <command>systemd</command> makes based on <varname>$TERM</varname> and other conditions.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>$LISTEN_PID</varname></term>
+ <term><varname>$LISTEN_FDS</varname></term>
+ <term><varname>$LISTEN_FDNAMES</varname></term>
+
+ <listitem><para>Set by systemd for supervised processes during
+ socket-based activation. See
+ <citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ for more information.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>$NOTIFY_SOCKET</varname></term>
+
+ <listitem><para>Set by systemd for supervised processes for
+ status and start-up completion notification. See
+ <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ for more information.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+ // 0 -->
+
+ <!-- 0 /// The whole kernel section is unneeded in elogind
+ <refsect1>
+ <title>Kernel Command Line</title>
+
+ <para>When run as system instance systemd parses a number of
+ kernel command line arguments<footnote><para>If run inside a Linux
+ container these arguments may be passed as command line arguments
+ to systemd itself, next to any of the command line options listed
+ in the Options section above. If run outside of Linux containers,
+ these arguments are parsed from <filename>/proc/cmdline</filename>
+ instead.</para></footnote>:</para>
+
+ <variablelist class='kernel-commandline-options'>
+ <varlistentry>
+ <term><varname>systemd.unit=</varname></term>
+ <term><varname>rd.systemd.unit=</varname></term>
+
+ <listitem><para>Overrides the unit to activate on boot.
+ Defaults to <filename>default.target</filename>. This may be
+ used to temporarily boot into a different boot unit, for
+ example <filename>rescue.target</filename> or
+ <filename>emergency.service</filename>. See
+ <citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ for details about these units. The option prefixed with
+ <literal>rd.</literal> is honored only in the initial RAM disk
+ (initrd), while the one that is not prefixed only in the main
+ system.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>systemd.dump_core</varname></term>
+
+ <listitem><para>Takes a boolean argument or enables the option if specified
+ without an argument. If enabled, the systemd manager (PID 1) dumps core when
+ it crashes. Otherwise, no core dump is created. Defaults to enabled.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>systemd.crash_chvt</varname></term>
+
+ <listitem><para>Takes a positive integer, or a boolean argument. Can be also
+ specified without an argument, with the same effect as a positive boolean. If
+ a positive integer (in the range 1–63) is specified, the system manager (PID
+ 1) will activate the specified virtual terminal (VT) when it
+ crashes. Defaults to disabled, meaning that no such switch is attempted. If
+ set to enabled, the VT the kernel messages are written to is selected.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>systemd.crash_shell</varname></term>
+
+ <listitem><para>Takes a boolean argument or enables the option if specified
+ without an argument. If enabled, the system manager (PID 1) spawns a shell
+ when it crashes, after a 10s delay. Otherwise, no shell is spawned. Defaults
+ to disabled, for security reasons, as the shell is not protected by password
+ authentication.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>systemd.crash_reboot</varname></term>
+
+ <listitem><para>Takes a boolean argument or enables the option if specified
+ without an argument. If enabled, the system manager (PID 1) will reboot the
+ machine automatically when it crashes, after a 10s delay. Otherwise, the
+ system will hang indefinitely. Defaults to disabled, in order to avoid a
+ reboot loop. If combined with <varname>systemd.crash_shell</varname>, the
+ system is rebooted after the shell exits.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>systemd.confirm_spawn</varname></term>
+
+ <listitem><para>Takes a boolean argument or a path to the virtual console
+ where the confirmation messages should be emitted. Can be also specified
+ without an argument, with the same effect as a positive boolean. If enabled,
+ the system manager (PID 1) asks for confirmation when spawning processes
+ using <option>/dev/console</option>. If a path or a console name (such as
+ <literal>ttyS0</literal>) is provided, the virtual console pointed to by this
+ path or described by the give name will be used instead. Defaults to disabled.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>systemd.service_watchdogs=</varname></term>
+
+ <listitem><para>Takes a boolean argument. If disabled, all service runtime
+ watchdogs (<option>WatchdogSec=</option>) and emergency actions (e.g.
+ <option>OnFailure=</option> or <option>StartLimitAction=</option>) are
+ ignored by the system manager (PID 1); see
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ Defaults to enabled, i.e. watchdogs and failure actions are processed
+ normally. The hardware watchdog is not affected by this
+ option.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>systemd.show_status</varname></term>
+
+ <listitem><para>Takes a boolean argument or the constant
+ <constant>auto</constant>. Can be also specified without an argument, with
+ the same effect as a positive boolean. If enabled, the systemd manager (PID
+ 1) shows terse service status updates on the console during bootup.
+ <constant>auto</constant> behaves like <option>false</option> until a unit
+ fails or there is a significant delay in boot. Defaults to enabled, unless
+ <option>quiet</option> is passed as kernel command line option, in which case
+ it defaults to <constant>auto</constant>. If specified overrides the system
+ manager configuration file option <option>ShowStatus=</option>, see
+ <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ However, the process command line option <option>&#x2D;&#x2D;show-status=</option>
+ takes precedence over both this kernel command line option and the
+ configuration file option.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>systemd.log_target=</varname></term>
+ <term><varname>systemd.log_level=</varname></term>
+ <term><varname>systemd.log_location=</varname></term>
+ <term><varname>systemd.log_color</varname></term>
+
+ <listitem><para>Controls log output, with the same effect as the
+ <varname>$SYSTEMD_LOG_TARGET</varname>,
+ <varname>$SYSTEMD_LOG_LEVEL</varname>,
+ <varname>$SYSTEMD_LOG_LOCATION</varname>,
+ <varname>$SYSTEMD_LOG_COLOR</varname> environment variables described above.
+ <varname>systemd.log_color</varname> can be specified without an argument,
+ with the same effect as a positive boolean.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>systemd.default_standard_output=</varname></term>
+ <term><varname>systemd.default_standard_error=</varname></term>
+ <listitem><para>Controls default standard output and error
+ output for services, with the same effect as the
+ <option>&#x2D;&#x2D;default-standard-output=</option> and
+ <option>&#x2D;&#x2D;default-standard-error=</option> command line
+ arguments described above, respectively.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>systemd.setenv=</varname></term>
+
+ <listitem><para>Takes a string argument in the form
+ VARIABLE=VALUE. May be used to set default environment
+ variables to add to forked child processes. May be used more
+ than once to set multiple variables.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>systemd.machine_id=</varname></term>
+
+ <listitem><para>Takes a 32 character hex value to be
+ used for setting the machine-id. Intended mostly for
+ network booting where the same machine-id is desired
+ for every boot.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>systemd.unified_cgroup_hierarchy</varname></term>
+
+ <listitem><para>When specified without an argument or with a true argument,
+ enables the usage of
+ <ulink url="https://www.kernel.org/doc/Documentation/cgroup-v2.txt">unified cgroup hierarchy</ulink>
+ (a.k.a. cgroups-v2). When specified with a false argument, fall back to
+ hybrid or full legacy cgroup hierarchy.</para>
+
+ <para>If this option is not specified, the default behaviour is determined
+ during compilation (the <option>&#x2D;&#x2D;with-default-hierarchy=</option>
+ option). If the kernel does not support unified cgroup hierarchy, the legacy
+ hierarchy will be used even if this option is specified.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>systemd.legacy_systemd_cgroup_controller</varname></term>
+
+ <listitem><para>Takes effect if the full unified cgroup hierarchy is not used
+ (see previous option). When specified without an argument or with a true
+ argument, disables the use of "hybrid" cgroup hierarchy (i.e. a cgroups-v2
+ tree used for systemd, and
+ <ulink url="https://www.kernel.org/doc/Documentation/cgroup-v1/">legacy
+ cgroup hierarchy</ulink>, a.k.a. cgroups-v1, for other controllers), and
+ forces a full "legacy" mode. When specified with a false argument, enables
+ the use of "hybrid" hierarchy.</para>
+
+ <para>If this option is not specified, the default behaviour is determined
+ during compilation (the <option>&#x2D;&#x2D;with-default-hierarchy=</option>
+ option). If the kernel does not support unified cgroup hierarchy, the legacy
+ hierarchy will be used even if this option is specified.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>quiet</varname></term>
+
+ <listitem><para>Turn off status output at boot, much like
+ <varname>systemd.show_status=false</varname> would. Note that
+ this option is also read by the kernel itself and disables
+ kernel log output. Passing this option hence turns off the
+ usual output from both the system manager and the kernel.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>debug</varname></term>
+
+ <listitem><para>Turn on debugging output. This is equivalent
+ to <varname>systemd.log_level=debug</varname>. Note that this
+ option is also read by the kernel itself and enables kernel
+ debug output. Passing this option hence turns on the debug
+ output from both the system manager and the
+ kernel.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>emergency</varname></term>
+ <term><varname>rd.emergency</varname></term>
+ <term><varname>-b</varname></term>
+
+ <listitem><para>Boot into emergency mode. This is equivalent
+ to <varname>systemd.unit=emergency.target</varname> or
+ <varname>rd.systemd.unit=emergency.target</varname>, respectively, and
+ provided for compatibility reasons and to be easier to type.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>rescue</varname></term>
+ <term><varname>rd.rescue</varname></term>
+ <term><varname>single</varname></term>
+ <term><varname>s</varname></term>
+ <term><varname>S</varname></term>
+ <term><varname>1</varname></term>
+
+ <listitem><para>Boot into rescue mode. This is equivalent to
+ <varname>systemd.unit=rescue.target</varname> or
+ <varname>rd.systemd.unit=rescue.target</varname>, respectively, and
+ provided for compatibility reasons and to be easier to type.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>2</varname></term>
+ <term><varname>3</varname></term>
+ <term><varname>4</varname></term>
+ <term><varname>5</varname></term>
+
+ <listitem><para>Boot into the specified legacy SysV runlevel.
+ These are equivalent to
+ <varname>systemd.unit=runlevel2.target</varname>,
+ <varname>systemd.unit=runlevel3.target</varname>,
+ <varname>systemd.unit=runlevel4.target</varname>, and
+ <varname>systemd.unit=runlevel5.target</varname>,
+ respectively, and provided for compatibility reasons and to be
+ easier to type.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>locale.LANG=</varname></term>
+ <term><varname>locale.LANGUAGE=</varname></term>
+ <term><varname>locale.LC_CTYPE=</varname></term>
+ <term><varname>locale.LC_NUMERIC=</varname></term>
+ <term><varname>locale.LC_TIME=</varname></term>
+ <term><varname>locale.LC_COLLATE=</varname></term>
+ <term><varname>locale.LC_MONETARY=</varname></term>
+ <term><varname>locale.LC_MESSAGES=</varname></term>
+ <term><varname>locale.LC_PAPER=</varname></term>
+ <term><varname>locale.LC_NAME=</varname></term>
+ <term><varname>locale.LC_ADDRESS=</varname></term>
+ <term><varname>locale.LC_TELEPHONE=</varname></term>
+ <term><varname>locale.LC_MEASUREMENT=</varname></term>
+ <term><varname>locale.LC_IDENTIFICATION=</varname></term>
+
+ <listitem><para>Set the system locale to use. This overrides
+ the settings in <filename>/etc/locale.conf</filename>. For
+ more information, see
+ <citerefentry project='man-pages'><refentrytitle>locale.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ and
+ <citerefentry project='man-pages'><refentrytitle>locale</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
+ </para></listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>For other kernel command line parameters understood by
+ components of the core OS, please refer to
+ <citerefentry><refentrytitle>kernel-command-line</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
+ </refsect1>
+ // 0 -->
+
+ <!-- 0 /// The whole sockets section is unneeded in elogind
+ <refsect1>
+ <title>Sockets and FIFOs</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><filename>/run/systemd/notify</filename></term>
+
+ <listitem><para>Daemon status notification socket. This is an
+ <constant>AF_UNIX</constant> datagram socket and is used to
+ implement the daemon notification logic as implemented by
+ <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term><filename>/run/systemd/private</filename></term>
+
+ <listitem><para>Used internally as communication channel
+ between
+ <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ and the systemd process. This is an
+ <constant>AF_UNIX</constant> stream socket. This interface is
+ private to systemd and should not be used in external
+ projects.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><filename>/dev/initctl</filename></term>
+
+ <listitem><para>Limited compatibility support for the SysV
+ client interface, as implemented by the
+ <filename>systemd-initctl.service</filename> unit. This is a
+ named pipe in the file system. This interface is obsolete and
+ should not be used in new applications.</para></listitem>
+ </varlistentry>
+ </variablelist>
</refsect1>
+ // 0 -->
<refsect1>
<title>See Also</title>
<para>
+ <!-- 0 /// elogind does not have that much to see also...
+ The <ulink url="https://www.freedesktop.org/wiki/Software/systemd/">systemd Homepage</ulink>,
+ <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>locale.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-notify</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>kernel-command-line</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>bootup</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ else -->
+ The <ulink url="https://github.com/elogind/elogind/">elogind Homepage</ulink>,
<citerefentry><refentrytitle>loginctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>logind.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>pam_elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ <!-- // 0 -->
</para>
</refsect1>
diff --git a/man/glib-event-glue.c b/man/glib-event-glue.c
index 8f3168d0e..15e2bdb6a 100644
--- a/man/glib-event-glue.c
+++ b/man/glib-event-glue.c
@@ -1,68 +1,50 @@
-/***
- Copyright 2014 Tom Gundersen
-
- 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.
-***/
+/* SPDX-License-Identifier: MIT */
#include <stdlib.h>
+//#include <elogind/sd-event.h>
+//#include <glib.h>
+#include <glib.h>
+#include <systemd/sd-event.h>
typedef struct SDEventSource {
- GSource source;
- GPollFD pollfd;
- sd_event *event;
+ GSource source;
+ GPollFD pollfd;
+ sd_event *event;
} SDEventSource;
static gboolean event_prepare(GSource *source, gint *timeout_) {
- return sd_event_prepare(((SDEventSource *)source)->event) > 0;
+ return sd_event_prepare(((SDEventSource *)source)->event) > 0;
}
static gboolean event_check(GSource *source) {
- return sd_event_wait(((SDEventSource *)source)->event, 0) > 0;
+ return sd_event_wait(((SDEventSource *)source)->event, 0) > 0;
}
static gboolean event_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) {
- return sd_event_dispatch(((SDEventSource *)source)->event) > 0;
+ return sd_event_dispatch(((SDEventSource *)source)->event) > 0;
}
static void event_finalize(GSource *source) {
- sd_event_unref(((SDEventSource *)source)->event);
+ sd_event_unref(((SDEventSource *)source)->event);
}
static GSourceFuncs event_funcs = {
- .prepare = event_prepare,
- .check = event_check,
- .dispatch = event_dispatch,
- .finalize = event_finalize,
+ .prepare = event_prepare,
+ .check = event_check,
+ .dispatch = event_dispatch,
+ .finalize = event_finalize,
};
GSource *g_sd_event_create_source(sd_event *event) {
- SDEventSource *source;
+ SDEventSource *source;
- source = (SDEventSource *)g_source_new(&event_funcs, sizeof(SDEventSource));
+ source = (SDEventSource *)g_source_new(&event_funcs, sizeof(SDEventSource));
- source->event = sd_event_ref(event);
- source->pollfd.fd = sd_event_get_fd(event);
- source->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
+ source->event = sd_event_ref(event);
+ source->pollfd.fd = sd_event_get_fd(event);
+ source->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
- g_source_add_poll((GSource *)source, &source->pollfd);
+ g_source_add_poll((GSource *)source, &source->pollfd);
- return (GSource *)source;
+ return (GSource *)source;
}
diff --git a/man/less-variables.xml b/man/less-variables.xml
index 396481c93..a3faa3899 100644
--- a/man/less-variables.xml
+++ b/man/less-variables.xml
@@ -2,6 +2,10 @@
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<!--
+ SPDX-License-Identifier: LGPL-2.1+
+-->
+
<refsect1>
<title>Environment</title>
diff --git a/man/libelogind-pkgconfig.xml b/man/libelogind-pkgconfig.xml
index c940b15b3..5c83e11f8 100644
--- a/man/libelogind-pkgconfig.xml
+++ b/man/libelogind-pkgconfig.xml
@@ -2,6 +2,10 @@
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<!--
+ SPDX-License-Identifier: LGPL-2.1+
+-->
+
<refsect1>
<title>Notes</title>
diff --git a/man/loginctl.xml b/man/loginctl.xml
index 39534f115..e96f0e999 100644
--- a/man/loginctl.xml
+++ b/man/loginctl.xml
@@ -3,39 +3,19 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2010 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
-<refentry id="loginctl"
+<!-- 0 /// elogind does not need to activate loginctl in configure
+<refentry id="loginctl" conditional='ENABLE_LOGIND'
xmlns:xi="http://www.w3.org/2001/XInclude">
+else -->
+<refentry id="loginctl" xmlns:xi="http://www.w3.org/2001/XInclude">
+<!-- // 0 -->
<refentryinfo>
<title>loginctl</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -62,8 +42,14 @@
<para><command>loginctl</command> may be used to introspect and
control the state of the
+ <!-- 0 /// elogind has no services and is in section 8
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ login manager
+ <citerefentry><refentrytitle>systemd-logind.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+ --><!-- else -->
<citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>
login manager</para>
+ <!-- // 0 -->
</refsect1>
<refsect1>
@@ -95,11 +81,9 @@
<varlistentry>
<term><option>--value</option></term>
- <listitem>
- <para>When printing properties with <command>show</command>,
- only print the value, and skip the property name and
- <literal>=</literal>.</para>
- </listitem>
+ <listitem><para>When showing session/user/seat properties,
+ only print the value, and skip the property name and
+ <literal>=</literal>.</para></listitem>
</varlistentry>
<varlistentry>
@@ -143,6 +127,31 @@
<constant>SIGTERM</constant>.</para></listitem>
</varlistentry>
+ <!-- 0 /// elogind does not support systemd-journal
+ <varlistentry>
+ <term><option>-n</option></term>
+ <term><option>&#x2D;&#x2D;lines=</option></term>
+
+ <listitem><para>When used with <command>user-status</command>
+ and <command>session-status</command>, controls the number of
+ journal lines to show, counting from the most recent ones.
+ Takes a positive integer argument. Defaults to 10.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-o</option></term>
+ <term><option>&#x2D;&#x2D;output=</option></term>
+
+ <listitem><para>When used with <command>user-status</command>
+ and <command>session-status</command>, controls the formatting
+ of the journal entries that are shown. For the available
+ choices, see
+ <citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
+ Defaults to <literal>short</literal>.</para></listitem>
+ </varlistentry>
+ // 0 -->
+
<xi:include href="user-system-options.xml" xpointer="host" />
<xi:include href="user-system-options.xml" xpointer="machine" />
@@ -256,11 +265,10 @@
one or more logged in users, followed by the most recent log
data from the journal. Takes one or more user names or numeric
user IDs as parameters. If no parameters are passed, the status
- of the caller's user is shown. This function is intended to
- generate human-readable output. If you are looking for
- computer-parsable output, use <command>show-user</command>
- instead. Users may be specified by their usernames or numeric
- user IDs. </para></listitem>
+ is shown for the user of the session of the caller. This
+ function is intended to generate human-readable output. If you
+ are looking for computer-parsable output, use
+ <command>show-user</command> instead.</para></listitem>
</varlistentry>
<varlistentry>
@@ -278,6 +286,7 @@
formatted human-readable output.</para></listitem>
</varlistentry>
+ <!-- 0 /// elogind does not spawn a user manager. Mask until lingeringin elogind is clarified.
<varlistentry>
<term><command>enable-linger</command> <optional><replaceable>USER</replaceable>…</optional></term>
<term><command>disable-linger</command> <optional><replaceable>USER</replaceable>…</optional></term>
@@ -294,6 +303,7 @@
<citerefentry><refentrytitle>logind.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</para></listitem>
</varlistentry>
+ // 0 -->
<varlistentry>
<term><command>terminate-user</command> <replaceable>USER</replaceable>…</term>
@@ -380,61 +390,64 @@
</varlistentry>
</variablelist></refsect2>
+ <!-- 1 /// elogind additionally supports a few systemctl commands. -->
<refsect2><title>System Commands</title><variablelist>
+ <varlistentry>
+ <term><command>poweroff</command></term>
+
+ <listitem>
+ <para>Print a wall message to all users, shut down and
+ power-off the system.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>reboot <optional><replaceable>arg</replaceable></optional></command></term>
+
+ <listitem>
+ <para>Print a wall message to all users, shut down and
+ reboot the system.</para>
+
+ <para>If the optional argument
+ <replaceable>arg</replaceable> is given, it will be passed
+ as the optional argument to the
+ <citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+ system call. The value is architecture and firmware
+ specific. As an example, <literal>recovery</literal> might
+ be used to trigger system recovery, and
+ <literal>fota</literal> might be used to trigger a
+ <quote>firmware over the air</quote> update.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>suspend</command></term>
+
+ <listitem>
+ <para>Suspend the system.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>hibernate</command></term>
+
+ <listitem>
+ <para>Hibernate the system.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>hybrid-sleep</command></term>
+
+ <listitem>
+ <para>Hibernate and suspend the system.</para>
+ </listitem>
+ </varlistentry>
</variablelist></refsect2>
- <varlistentry>
- <term><command>poweroff</command></term>
-
- <listitem>
- <para>Print a wall message to all users, shut down and
- power-off the system.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>reboot <optional><replaceable>arg</replaceable></optional></command></term>
-
- <listitem>
- <para>Print a wall message to all users, shut down and
- reboot the system.</para>
-
- <para>If the optional argument
- <replaceable>arg</replaceable> is given, it will be passed
- as the optional argument to the
- <citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry>
- system call. The value is architecture and firmware
- specific. As an example, <literal>recovery</literal> might
- be used to trigger system recovery, and
- <literal>fota</literal> might be used to trigger a
- <quote>firmware over the air</quote> update.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>suspend</command></term>
-
- <listitem>
- <para>Suspend the system.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>hibernate</command></term>
-
- <listitem>
- <para>Hibernate the system.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>hybrid-sleep</command></term>
-
- <listitem>
- <para>Hibernate and suspend the system.</para>
- </listitem>
- </varlistentry>
+ <!-- // 1 -->
</refsect1>
+
<refsect1>
<title>Exit status</title>
@@ -448,6 +461,7 @@
<example>
<title>Querying user status</title>
+ <!-- 0 /// With elogind no Unit and jurnald output is generated
<programlisting>$ loginctl user-status
fatima (1005)
Since: Sat 2016-04-09 14:23:31 EDT; 54min ago
@@ -459,13 +473,22 @@ fatima (1005)
├─session-3.scope
└─session-5.scope
- ├─3473 login -- fatima
+ ├─3473 login &#x2D;&#x2D; fatima
└─3515 -zsh
Apr 09 14:40:30 laptop login[2325]: pam_unix(login:session):
session opened for user fatima by LOGIN(uid=0)
Apr 09 14:40:30 laptop login[2325]: LOGIN ON tty3 BY fatima
</programlisting>
+ --><!-- else -->
+ <programlisting>$ loginctl user-status
+fatima (1005)
+ Since: Sat 2016-04-09 14:23:31 EDT; 54min ago
+ State: active
+ Sessions: 5 *3
+ Unit: user-1005.slice
+</programlisting>
+ <!-- // 0 -->
<para>There are two sessions, 3 and 5. Session 3 is a graphical session,
marked with a star. The tree of processing including the two corresponding
@@ -478,8 +501,13 @@ Apr 09 14:40:30 laptop login[2325]: LOGIN ON tty3 BY fatima
<refsect1>
<title>See Also</title>
<para>
- <citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <!-- 0 /// elogind is in section 8
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-logind.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ --><!-- else -->
+ <citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <!-- // 0 -->
<citerefentry><refentrytitle>logind.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/logind.conf.xml b/man/logind.conf.xml
index 4641bbb83..abc97b356 100644
--- a/man/logind.conf.xml
+++ b/man/logind.conf.xml
@@ -1,39 +1,26 @@
-<?xml version='1.0'?> <!--*-nxml-*-->
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
+<!ENTITY % entities SYSTEM "custom-entities.ent" >
+%entities;
+]>
<!--
- This file is part of elogind.
-
- Copyright 2010 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
+<!-- 0 /// elogind does not have to enable itself in configure
+<refentry id="logind.conf" conditional='ENABLE_LOGIND'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <refentryinfo>
+ <title>logind.conf</title>
+ <productname>systemd</productname>
+--><!-- else -->
<refentry id="logind.conf" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>logind.conf</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
+<!-- // 0 -->
</refentryinfo>
<refmeta>
@@ -43,221 +30,344 @@
<refnamediv>
<refname>logind.conf</refname>
+ <!-- 0 /// not supported by elogind
+ <refname>logind.conf.d</refname>
+ // 0 -->
<refpurpose>Login manager configuration files</refpurpose>
</refnamediv>
<refsynopsisdiv>
<para><filename>/etc/elogind/logind.conf</filename></para>
+ <!-- 0 /// not supported by elogind
+ <para><filename>/etc/systemd/logind.conf.d/*.conf</filename></para>
+ <para><filename>/run/systemd/logind.conf.d/*.conf</filename></para>
+ <para><filename>/usr/lib/systemd/logind.conf.d/*.conf</filename></para>
+ // 0 -->
</refsynopsisdiv>
<refsect1>
<title>Description</title>
- <para>These files configure various parameters of the elogind
- login manager.</para>
+ <!-- 0 /// elogind does not need a service file.
+ <para>These files configure various parameters of the systemd login manager,
+ <citerefentry><refentrytitle>systemd-logind.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>. See
+ <citerefentry><refentrytitle>systemd.syntax</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for a general description of the syntax.</para>
+ --><!-- else -->
+ <para>This file configures various parameters of elogind.</para>
+ <!-- // 0 -->
</refsect1>
+ <!-- 0 /// elogind has only this configuration
<xi:include href="standard-conf.xml" xpointer="main-conf" />
+ // 0 -->
<refsect1>
<title>Options</title>
+ <!-- 0 /// elogind also supports a few system commands
+ <para>All options are configured in the
+ <literal>[Login]</literal> section:</para>
+ --><!-- else -->
<para>All login options are configured in the
<literal>[Login]</literal> section, system sleep options are
configured in the <literal>[Sleep]</literal> section.</para>
+ <!-- // 0 -->
+ <!-- 1 /// elogind needs a second level, as we use two sections. -->
<refsect2><title>[Login] section:</title>
- <variablelist>
-
- <varlistentry>
- <term><varname>KillUserProcesses=</varname></term>
-
- <listitem><para>Takes a boolean argument. Configures whether
- the processes of a user should be killed when the user
- completely logs out (i.e. after the user's last session
- ended). Defaults to <literal>no</literal>.</para>
+ <!-- // 1 -->
+
+ <variablelist>
+ <!-- 0 /// elogind has no support for AutoVT
+
+ <varlistentry>
+ <term><varname>NAutoVTs=</varname></term>
+
+ <listitem><para>Takes a positive integer. Configures how many
+ virtual terminals (VTs) to allocate by default that, when
+ switched to and are previously unused,
+ <literal>autovt</literal> services are automatically spawned
+ on. These services are instantiated from the template unit
+ <filename>autovt@.service</filename> for the respective VT TTY
+ name, for example, <filename>autovt@tty4.service</filename>.
+ By default, <filename>autovt@.service</filename> is linked to
+ <filename>getty@.service</filename>. In other words, login
+ prompts are started dynamically as the user switches to unused
+ virtual terminals. Hence, this parameter controls how many
+ login <literal>gettys</literal> are available on the VTs. If a
+ VT is already used by some other subsystem (for example, a
+ graphical login), this kind of activation will not be
+ attempted. Note that the VT configured in
+ <varname>ReserveVT=</varname> is always subject to this kind
+ of activation, even if it is not one of the VTs configured
+ with the <varname>NAutoVTs=</varname> directive. Defaults to
+ 6. When set to 0, automatic spawning of
+ <literal>autovt</literal> services is
+ disabled.</para></listitem>
+ </varlistentry>
- <para>Note that setting <varname>KillUserProcesses=1</varname>
- will break tools like
- <citerefentry project='die-net'><refentrytitle>screen</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para></listitem>
- </varlistentry>
+ <varlistentry>
+ <term><varname>ReserveVT=</varname></term>
+
+ <listitem><para>Takes a positive integer. Identifies one
+ virtual terminal that shall unconditionally be reserved for
+ <filename>autovt@.service</filename> activation (see above).
+ The VT selected with this option will be marked busy
+ unconditionally, so that no other subsystem will allocate it.
+ This functionality is useful to ensure that, regardless of how
+ many VTs are allocated by other subsystems, one login
+ <literal>getty</literal> is always available. Defaults to 6
+ (in other words, there will always be a
+ <literal>getty</literal> available on Alt-F6.). When set to 0,
+ VT reservation is disabled.</para></listitem>
+ </varlistentry>
+ // 0 -->
+
+ <varlistentry>
+ <term><varname>KillUserProcesses=</varname></term>
+
+ <listitem><para>Takes a boolean argument. Configures whether the processes of a
+ <!-- 0 /// elogind has no scope unit, and goes for cgroups only
+ user should be killed when the user logs out. If true, the scope unit
+ corresponding to the session and all processes inside that scope will be
+ terminated. If false, the scope is "abandoned", see
+ <citerefentry><refentrytitle>systemd.scope</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ and processes are not killed. Defaults to <literal>&KILL_USER_PROCESSES;</literal>,
+ --><!-- else -->
+ user should be killed when the user logs out. If true, the processes
+ listed in their session cgroup will be terminated. If false, the session cgroup
+ is ignored
+ <!-- // 0 -->
+ but see the options <varname>KillOnlyUsers=</varname> and
+ <varname>KillExcludeUsers=</varname> below.</para>
+
+ <!-- 0 /// elogind has no user manager unit, and lingering isn't clarified, yet.
+ <para>In addition to session processes, user process may run under the user
+ manager unit <filename>user@.service</filename>. Depending on the linger
+ settings, this may allow users to run processes independent of their login
+ sessions. See the description of <command>enable-linger</command> in
+ <citerefentry><refentrytitle>loginctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
+ </para>
+ // 0 -->
+
+ <para>Note that setting <varname>KillUserProcesses=yes</varname>
+ will break tools like
+ <citerefentry project='die-net'><refentrytitle>screen</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ and
+ <citerefentry project='die-net'><refentrytitle>tmux</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <!-- 0 /// elogind does not provide systemd-run or any equivalent, yet.
+ unless they are moved out of the session scope. See example in
+ <citerefentry><refentrytitle>systemd-run</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
+ --><!-- else -->
+ unless they are moved out of the session scope.
+ <!-- // 0 -->
+ </para></listitem>
+ </varlistentry>
- <varlistentry>
- <term><varname>KillOnlyUsers=</varname></term>
- <term><varname>KillExcludeUsers=</varname></term>
-
- <listitem><para>These settings take space-separated lists of
- usernames that influence the effect of
- <varname>KillUserProcesses=</varname>. If not empty, only
- processes of users listed in <varname>KillOnlyUsers=</varname>
- will be killed when they log out entirely. Processes of users
- listed in <varname>KillExcludeUsers=</varname> are excluded
- from being killed. <varname>KillExcludeUsers=</varname>
- defaults to <literal>root</literal> and takes precedence over
- <varname>KillOnlyUsers=</varname>, which defaults to the empty
- list.</para></listitem>
- </varlistentry>
+ <varlistentry>
+ <term><varname>KillOnlyUsers=</varname></term>
+ <term><varname>KillExcludeUsers=</varname></term>
+
+ <listitem><para>These settings take space-separated lists of usernames that override
+ the <varname>KillUserProcesses=</varname> setting. A user name may be added to
+ <varname>KillExcludeUsers=</varname> to exclude the processes in the session scopes of
+ that user from being killed even if <varname>KillUserProcesses=yes</varname> is set. If
+ <varname>KillExcludeUsers=</varname> is not set, the <literal>root</literal> user is
+ excluded by default. <varname>KillExcludeUsers=</varname> may be set to an empty value
+ to override this default. If a user is not excluded, <varname>KillOnlyUsers=</varname>
+ is checked next. If this setting is specified, only the session scopes of those users
+ will be killed. Otherwise, users are subject to the
+ <varname>KillUserProcesses=yes</varname> setting.</para></listitem>
+ </varlistentry>
- <varlistentry>
- <term><varname>IdleAction=</varname></term>
-
- <listitem><para>Configures the action to take when the system
- is idle. Takes one of
- <literal>ignore</literal>,
- <literal>poweroff</literal>,
- <literal>reboot</literal>,
- <literal>halt</literal>,
- <literal>kexec</literal>,
- <literal>suspend</literal>,
- <literal>hibernate</literal>,
- <literal>hybrid-sleep</literal>, and
- <literal>lock</literal>.
- Defaults to <literal>ignore</literal>.</para>
-
- <para>Note that this requires that user sessions correctly
- report the idle status to the system. The system will execute
- the action after all sessions report that they are idle, no
- idle inhibitor lock is active, and subsequently, the time
- configured with <varname>IdleActionSec=</varname> (see below)
- has expired.</para>
- </listitem>
- </varlistentry>
+ <varlistentry>
+ <term><varname>IdleAction=</varname></term>
+
+ <listitem><para>Configures the action to take when the system
+ is idle. Takes one of
+ <literal>ignore</literal>,
+ <literal>poweroff</literal>,
+ <literal>reboot</literal>,
+ <literal>halt</literal>,
+ <literal>kexec</literal>,
+ <literal>suspend</literal>,
+ <literal>hibernate</literal>,
+ <literal>hybrid-sleep</literal>,
+ <literal>suspend-then-hibernate</literal>, and
+ <literal>lock</literal>.
+ Defaults to <literal>ignore</literal>.</para>
+
+ <para>Note that this requires that user sessions correctly
+ report the idle status to the system. The system will execute
+ the action after all sessions report that they are idle, no
+ idle inhibitor lock is active, and subsequently, the time
+ configured with <varname>IdleActionSec=</varname> (see below)
+ has expired.</para>
+ </listitem>
+ </varlistentry>
- <varlistentry>
- <term><varname>IdleActionSec=</varname></term>
+ <varlistentry>
+ <term><varname>IdleActionSec=</varname></term>
- <listitem><para>Configures the delay after which the action
- configured in <varname>IdleAction=</varname> (see above) is
- taken after the system is idle.</para></listitem>
- </varlistentry>
+ <listitem><para>Configures the delay after which the action
+ configured in <varname>IdleAction=</varname> (see above) is
+ taken after the system is idle.</para></listitem>
+ </varlistentry>
- <varlistentry>
- <term><varname>InhibitDelayMaxSec=</varname></term>
+ <varlistentry>
+ <term><varname>InhibitDelayMaxSec=</varname></term>
- <listitem><para>Specifies the maximum time a system shutdown
- or sleep request is delayed due to an inhibitor lock of type
- <literal>delay</literal> being active before the inhibitor is
- ignored and the operation executes anyway. Defaults to
- 5.</para></listitem>
- </varlistentry>
+ <listitem><para>Specifies the maximum time a system shutdown
+ or sleep request is delayed due to an inhibitor lock of type
+ <literal>delay</literal> being active before the inhibitor is
+ ignored and the operation executes anyway. Defaults to
+ 5.</para></listitem>
+ </varlistentry>
- <varlistentry>
- <term><varname>HandlePowerKey=</varname></term>
- <term><varname>HandleSuspendKey=</varname></term>
- <term><varname>HandleHibernateKey=</varname></term>
- <term><varname>HandleLidSwitch=</varname></term>
- <term><varname>HandleLidSwitchDocked=</varname></term>
-
- <listitem><para>Controls how logind shall handle the
- system power and sleep keys and the lid switch to trigger
- actions such as system power-off or suspend. Can be one of
- <literal>ignore</literal>,
- <literal>poweroff</literal>,
- <literal>reboot</literal>,
- <literal>halt</literal>,
- <literal>kexec</literal>,
- <literal>suspend</literal>,
- <literal>hibernate</literal>,
- <literal>hybrid-sleep</literal>, and
- <literal>lock</literal>.
- If <literal>ignore</literal>, logind will never handle these
- keys. If <literal>lock</literal>, all running sessions will be
- screen-locked; otherwise, the specified action will be taken
- in the respective event. Only input devices with the
- <literal>power-switch</literal> udev tag will be watched for
- key/lid switch events. <varname>HandlePowerKey=</varname>
- defaults to <literal>poweroff</literal>.
- <varname>HandleSuspendKey=</varname> and
- <varname>HandleLidSwitch=</varname> default to
- <literal>suspend</literal>.
- <varname>HandleLidSwitchDocked=</varname> defaults to
- <literal>ignore</literal>.
- <varname>HandleHibernateKey=</varname> defaults to
- <literal>hibernate</literal>. If the system is inserted in a
- docking station, or if more than one display is connected, the
- action specified by <varname>HandleLidSwitchDocked=</varname>
- occurs; otherwise the <varname>HandleLidSwitch=</varname>
+ <varlistentry>
+ <term><varname>HandlePowerKey=</varname></term>
+ <term><varname>HandleSuspendKey=</varname></term>
+ <term><varname>HandleHibernateKey=</varname></term>
+ <term><varname>HandleLidSwitch=</varname></term>
+ <term><varname>HandleLidSwitchExternalPower=</varname></term>
+ <term><varname>HandleLidSwitchDocked=</varname></term>
+
+ <listitem><para>Controls how logind shall handle the
+ system power and sleep keys and the lid switch to trigger
+ actions such as system power-off or suspend. Can be one of
+ <literal>ignore</literal>,
+ <literal>poweroff</literal>,
+ <literal>reboot</literal>,
+ <literal>halt</literal>,
+ <literal>kexec</literal>,
+ <literal>suspend</literal>,
+ <literal>hibernate</literal>,
+ <literal>hybrid-sleep</literal>,
+ <literal>suspend-then-hibernate</literal>, and
+ <literal>lock</literal>.
+ If <literal>ignore</literal>, logind will never handle these
+ keys. If <literal>lock</literal>, all running sessions will be
+ screen-locked; otherwise, the specified action will be taken
+ in the respective event. Only input devices with the
+ <literal>power-switch</literal> udev tag will be watched for
+ key/lid switch events. <varname>HandlePowerKey=</varname>
+ defaults to <literal>poweroff</literal>.
+ <varname>HandleSuspendKey=</varname> and
+ <varname>HandleLidSwitch=</varname> default to
+ <literal>suspend</literal>.
+ <varname>HandleLidSwitchExternalPower=</varname> is completely
+ ignored by default (for backwards compatibility) — an explicit
+ value must be set before it will be used to determine
+ behaviour. <varname>HandleLidSwitchDocked=</varname> defaults
+ to <literal>ignore</literal>.
+ <varname>HandleHibernateKey=</varname> defaults to
+ <literal>hibernate</literal>. If the system is inserted in a
+ docking station, or if more than one display is connected, the
+ action specified by <varname>HandleLidSwitchDocked=</varname>
+ occurs; if the system is on external power the action (if any)
+ specified by <varname>HandleLidSwitchExternalPower=</varname>
+ occurs; otherwise the <varname>HandleLidSwitch=</varname>
action occurs.</para>
<para>A different application may disable logind's handling of system power and
sleep keys and the lid switch by taking a low-level inhibitor lock
- ("handle-power-key", "handle-suspend-key", "handle-hibernate-key",
- "handle-lid-switch"). This is most commonly used by graphical desktop environments
+ (<literal>handle-power-key</literal>, <literal>handle-suspend-key</literal>,
+ <literal>handle-hibernate-key</literal>, <literal>handle-lid-switch</literal>).
+ This is most commonly used by graphical desktop environments
to take over suspend and hibernation handling, and to use their own configuration
mechanisms. If a low-level inhibitor lock is taken, logind will not take any
action when that key or switch is triggered and the <varname>Handle*=</varname>
settings are irrelevant.</para></listitem>
</varlistentry>
- <varlistentry>
- <term><varname>PowerKeyIgnoreInhibited=</varname></term>
- <term><varname>SuspendKeyIgnoreInhibited=</varname></term>
- <term><varname>HibernateKeyIgnoreInhibited=</varname></term>
- <term><varname>LidSwitchIgnoreInhibited=</varname></term>
+ <varlistentry>
+ <term><varname>PowerKeyIgnoreInhibited=</varname></term>
+ <term><varname>SuspendKeyIgnoreInhibited=</varname></term>
+ <term><varname>HibernateKeyIgnoreInhibited=</varname></term>
+ <term><varname>LidSwitchIgnoreInhibited=</varname></term>
- <listitem><para>Controls whether actions that <command>systemd-logind</command>
+ <listitem><para>Controls whether actions that <command>elogind</command>
takes when the power and sleep keys and the lid switch are triggered are subject
to high-level inhibitor locks ("shutdown", "sleep", "idle"). Low level inhibitor
- locks ("handle-*-key"), are always honoured, irrespective of this setting.</para>
+ locks (<literal>handle-power-key</literal>, <literal>handle-suspend-key</literal>,
+ <literal>handle-hibernate-key</literal>, <literal>handle-lid-switch</literal>),
+ are always honored, irrespective of this setting.</para>
<para>These settings take boolean arguments. If <literal>no</literal>, the
inhibitor locks taken by applications are respected. If <literal>yes</literal>,
"shutdown", "sleep", and "idle" inhibitor locks are ignored.
- <varname>PowerKeyIgnoreInhibited=</varname>,
+ <varname>PowerKeyIgnoreInhibited=</varname>,
<varname>SuspendKeyIgnoreInhibited=</varname>, and
<varname>HibernateKeyIgnoreInhibited=</varname> default to <literal>no</literal>.
<varname>LidSwitchIgnoreInhibited=</varname> defaults to <literal>yes</literal>.
- This means that when <command>systemd-logind</command> is handling events by
+ This means that when <command>elogind</command> is handling events by
itself (no low level inhibitor locks are taken by another application), the lid
switch does not respect suspend blockers by default, but the power and sleep keys
do.</para></listitem>
- </varlistentry>
+ </varlistentry>
- <varlistentry>
- <term><varname>HoldoffTimeoutSec=</varname></term>
-
- <listitem><para>Specifies the timeout after system startup or
- system resume in which elogind will hold off on reacting to
- LID events. This is required for the system to properly
- detect any hotplugged devices so elogind can ignore LID events
- if external monitors, or docks, are connected. If set to 0,
- elogind will always react immediately, possibly before the
- kernel fully probed all hotplugged devices. This is safe, as
- long as you do not care for elogind to account for devices
- that have been plugged or unplugged while the system was off.
- Defaults to 30s.</para></listitem>
- </varlistentry>
+ <varlistentry>
+ <term><varname>HoldoffTimeoutSec=</varname></term>
+
+ <listitem><para>Specifies the timeout after system startup or
+ system resume in which systemd will hold off on reacting to
+ lid events. This is required for the system to properly
+ detect any hotplugged devices so systemd can ignore lid events
+ if external monitors, or docks, are connected. If set to 0,
+ systemd will always react immediately, possibly before the
+ kernel fully probed all hotplugged devices. This is safe, as
+ long as you do not care for systemd to account for devices
+ that have been plugged or unplugged while the system was off.
+ Defaults to 30s.</para></listitem>
+ </varlistentry>
- <varlistentry>
- <term><varname>RuntimeDirectorySize=</varname></term>
-
- <listitem><para>Sets the size limit on the
- <varname>$XDG_RUNTIME_DIR</varname> runtime directory for each
- user who logs in. Takes a size in bytes, optionally suffixed
- with the usual K, G, M, and T suffixes, to the base 1024
- (IEC). Alternatively, a numerical percentage suffixed by
- <literal>%</literal> may be specified, which sets the size
- limit relative to the amount of physical RAM. Defaults to 10%.
- Note that this size is a safety limit only. As each runtime
- directory is a tmpfs file system, it will only consume as much
- memory as is needed. </para></listitem>
- </varlistentry>
+ <varlistentry>
+ <term><varname>RuntimeDirectorySize=</varname></term>
+
+ <listitem><para>Sets the size limit on the
+ <varname>$XDG_RUNTIME_DIR</varname> runtime directory for each
+ user who logs in. Takes a size in bytes, optionally suffixed
+ with the usual K, G, M, and T suffixes, to the base 1024
+ (IEC). Alternatively, a numerical percentage suffixed by
+ <literal>%</literal> may be specified, which sets the size
+ limit relative to the amount of physical RAM. Defaults to 10%.
+ Note that this size is a safety limit only. As each runtime
+ directory is a tmpfs file system, it will only consume as much
+ memory as is needed.</para></listitem>
+ </varlistentry>
- <varlistentry>
- <term><varname>RemoveIPC=</varname></term>
+ <varlistentry>
+ <term><varname>InhibitorsMax=</varname></term>
- <listitem><para>Controls whether System V and POSIX IPC objects belonging to the user shall be removed when the
- user fully logs out. Takes a boolean argument. If enabled, the user may not consume IPC resources after the
- last of the user's sessions terminated. This covers System V semaphores, shared memory and message queues, as
- well as POSIX shared memory and message queues. Note that IPC objects of the root user and other system users
- are excluded from the effect of this setting. Defaults to <literal>yes</literal>.</para></listitem>
- </varlistentry>
+ <listitem><para>Controls the maximum number of concurrent inhibitors to permit. Defaults to 8192
+ (8K).</para></listitem>
+ </varlistentry>
- </variablelist>
+ <varlistentry>
+ <term><varname>SessionsMax=</varname></term>
+
+ <listitem><para>Controls the maximum number of concurrent user sessions to manage. Defaults to 8192
+ (8K). Depending on how the <filename>pam_systemd.so</filename> module is included in the PAM stack
+ configuration, further login sessions will either be refused, or permitted but not tracked by
+ <filename>elogind</filename>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>RemoveIPC=</varname></term>
+
+ <listitem><para>Controls whether System V and POSIX IPC objects belonging to the user shall be removed when the
+ user fully logs out. Takes a boolean argument. If enabled, the user may not consume IPC resources after the
+ last of the user's sessions terminated. This covers System V semaphores, shared memory and message queues, as
+ well as POSIX shared memory and message queues. Note that IPC objects of the root user and other system users
+ are excluded from the effect of this setting. Defaults to <literal>yes</literal>.</para></listitem>
+ </varlistentry>
+
+ </variablelist>
+ <!-- 1 /// elogind has an additional section for system commands. -->
</refsect2>
<refsect2><title>[Sleep] section:</title>
-
<para><command>elogind</command> supports three general
power-saving modes:</para>
@@ -331,13 +441,22 @@
</variablelist>
</refsect2>
+ <!-- // 1 -->
</refsect1>
<refsect1>
<title>See Also</title>
<para>
+ <!-- 0 /// elogind is in section 8
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-logind.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ --><!-- else -->
<citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <!-- // 0 -->
<citerefentry><refentrytitle>loginctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <!-- 0 /// UNNEEDED by elogind
+ <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ // 0 -->
</para>
</refsect1>
diff --git a/man/meson.build b/man/meson.build
new file mode 100644
index 000000000..d5895eb2f
--- /dev/null
+++ b/man/meson.build
@@ -0,0 +1,225 @@
+# SPDX-License-Identifier: LGPL-2.1+
+
+# This is lame, I know, but meson has no other include mechanism
+subdir('rules')
+
+want_man = get_option('man')
+want_html = get_option('html')
+xsltproc = find_program('xsltproc',
+ required : want_man == 'true' or want_html == 'true')
+want_man = want_man != 'false' and xsltproc.found()
+want_html = want_html != 'false' and xsltproc.found()
+
+xsltproc_flags = [
+ '--nonet',
+ '--xinclude',
+ '--maxdepth', '9000',
+ '--stringparam', 'man.output.quietly', '1',
+ '--stringparam', 'funcsynopsis.style', 'ansi',
+ '--stringparam', 'man.authors.section.enabled', '0',
+ '--stringparam', 'man.copyright.section.enabled', '0',
+ '--stringparam', 'elogind.version', '@0@'.format(meson.project_version()),
+ '--path',
+ '@0@:@1@'.format(meson.current_build_dir(), meson.current_source_dir())]
+
+custom_man_xsl = files('custom-man.xsl')
+custom_html_xsl = files('custom-html.xsl')
+xslt_cmd = [xsltproc, '-o', '@OUTPUT0@'] + xsltproc_flags
+
+custom_entities_ent = configure_file(
+ input : 'custom-entities.ent.in',
+ output : 'custom-entities.ent',
+ configuration : conf)
+
+man_pages = []
+html_pages = []
+source_xml_files = []
+foreach tuple : xsltproc.found() ? manpages : []
+ stem = tuple[0]
+ section = tuple[1]
+ aliases = tuple[2]
+ condition = tuple[3]
+
+ xml = stem + '.xml'
+ html = stem + '.html'
+ man = stem + '.' + section
+
+ manaliases = []
+ htmlaliases = []
+ foreach alias : aliases
+ manaliases += [alias + '.' + section]
+ htmlaliases += [alias + '.html']
+ endforeach
+
+ mandirn = join_paths(get_option('mandir'), 'man' + section)
+
+ if condition == '' or conf.get(condition) == 1
+ p1 = custom_target(
+ man,
+ input : xml,
+ output : [man] + manaliases,
+ command : xslt_cmd + [custom_man_xsl, '@INPUT@'],
+#if 0 /// UNNEEDED by elogind
+# depend_files : custom_entities_ent,
+#endif // 0
+ install : want_man,
+ install_dir : mandirn)
+ man_pages += [p1]
+
+ p2 = []
+ foreach htmlalias : htmlaliases
+ link = custom_target(
+ htmlalias,
+ input : p2,
+ output : htmlalias,
+ command : ['ln', '-fs', html, '@OUTPUT@'])
+ if want_html
+#if 0 /// This must be configurable in elogind
+# dst = join_paths(docdir, 'html', htmlalias)
+#else
+ dst = get_option('htmldir')
+ dst = dst != '' ? dst: join_paths(docdir, 'html', htmlalias)
+#endif // 0
+ cmd = 'ln -fs @0@ $DESTDIR@1@'.format(html, dst)
+ meson.add_install_script('sh', '-c', cmd)
+ p2 += [link]
+ endif
+ html_pages += [link]
+ endforeach
+
+ p3 = custom_target(
+ html,
+ input : xml,
+ output : html,
+ command : xslt_cmd + [custom_html_xsl, '@INPUT@'],
+#if 0 /// UNNEEDED by elogind
+# depend_files : custom_entities_ent,
+#endif // 0
+ depends : p2,
+ install : want_html,
+ install_dir : join_paths(docdir, 'html'))
+ html_pages += [p3]
+
+ source_xml_files += files(tuple[0] + '.xml')
+ else
+ message('Skipping @0@.@1@ because @2@ is false'.format(stem, section, condition))
+ endif
+endforeach
+
+############################################################
+
+have_lxml = run_command(xml_helper_py).returncode() == 0
+if not have_lxml
+ message('python-lxml not available, not making man page indices')
+endif
+
+elogind_directives_xml = custom_target(
+ 'elogind.directives.xml',
+ input : source_xml_files,
+ output : 'elogind.directives.xml',
+ command : [make_directive_index_py, '@OUTPUT@'] + source_xml_files)
+
+nonindex_xml_files = source_xml_files + [elogind_directives_xml]
+elogind_index_xml = custom_target(
+ 'elogind.index.xml',
+ input : nonindex_xml_files,
+ output : 'elogind.index.xml',
+ command : [make_man_index_py, '@OUTPUT@'] + nonindex_xml_files)
+
+foreach tuple : want_man or want_html ? [['elogind.directives', '7', elogind_directives_xml],
+ ['elogind.index', '7', elogind_index_xml]] : []
+ stem = tuple[0]
+ section = tuple[1]
+ xml = tuple[2]
+
+ html = stem + '.html'
+ man = stem + '.' + section
+
+ mandirn = join_paths(get_option('mandir'), 'man' + section)
+
+ p1 = custom_target(
+ man,
+ input : xml,
+ output : man,
+ command : xslt_cmd + [custom_man_xsl, '@INPUT@'],
+ install : want_man and have_lxml,
+ install_dir : mandirn)
+ man_pages += [p1]
+
+ p2 = []
+ if html == 'elogind.index.html'
+ htmlalias = 'index.html'
+ link = custom_target(
+ htmlalias,
+ input : p2,
+ output : htmlalias,
+ command : ['ln', '-fs', html, '@OUTPUT@'])
+ if want_html
+ dst = join_paths(docdir, 'html', htmlalias)
+ cmd = 'ln -fs @0@ $DESTDIR@1@'.format(html, dst)
+ meson.add_install_script('sh', '-c', cmd)
+ p2 += [link]
+ endif
+ html_pages += [link]
+ endif
+
+ p3 = custom_target(
+ html,
+ input : xml,
+ output : html,
+ command : xslt_cmd + [custom_html_xsl, '@INPUT@'],
+#if 0 /// UNNEEDED by elogind
+# depend_files : custom_entities_ent,
+#endif // 0
+ depends : p2,
+ install : want_html and have_lxml,
+ install_dir : join_paths(docdir, 'html'))
+ html_pages += [p3]
+endforeach
+
+# cannot use run_target until https://github.com/mesonbuild/meson/issues/1644 is resolved
+man = custom_target(
+ 'man',
+ output : 'man',
+ depends : man_pages,
+ command : ['echo'])
+
+html = custom_target(
+ 'html',
+ output : 'html',
+ depends : html_pages,
+ command : ['echo'])
+
+#if 0 /// UNNEEDED in elogind
+# run_target(
+# 'doc-sync',
+# depends : man_pages + html_pages,
+# command : ['rsync', '-rlv',
+# '--delete-excluded',
+# '--include=man',
+# '--include=*.html',
+# '--exclude=*',
+# '--omit-dir-times',
+# meson.current_build_dir(),
+# get_option('www-target')])
+#endif // 0
+
+############################################################
+
+if git.found()
+ custom_target(
+ 'update-man-rules',
+ output : 'update-man-rules',
+ # slightly strange syntax because of
+ # https://github.com/mesonbuild/meson/issues/1643
+ # and https://github.com/mesonbuild/meson/issues/1512
+ command : ['sh', '-c',
+ 'cd @0@ && '.format(meson.build_root()) +
+ 'python3 @0@/tools/make-man-rules.py `git ls-files ":/man/*.xml"` >t && '.format(meson.source_root()) +
+ 'mv t @0@/rules/meson.build'.format(meson.current_source_dir())],
+#if 0 /// UNNEEDED by elogind
+# depend_files : custom_entities_ent)
+#else
+ )
+#endif // 0
+endif
diff --git a/man/pam_elogind.xml b/man/pam_elogind.xml
index c707b0307..51b285d3a 100644
--- a/man/pam_elogind.xml
+++ b/man/pam_elogind.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2010 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="pam_elogind" conditional='HAVE_PAM'>
@@ -26,15 +11,6 @@
<refentryinfo>
<title>pam_elogind</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -253,8 +229,65 @@
for, if any. (Only applies to seats with a VT available, such
as <literal>seat0</literal>)</para></listitem>
</varlistentry>
+ </variablelist>
+
+ <para>If not set, <command>pam_elogind</command> will determine the
+ values for <varname>$XDG_SEAT</varname> and <varname>$XDG_VTNR</varname>
+ based on the <varname>$DISPLAY</varname> variable.</para>
+ </refsect1>
+ <refsect1>
+ <title>Session limits</title>
+
+ <para>PAM modules earlier in the stack, that is those that come before <command>pam_elogind.so</command>,
+ can set session scope limits using the PAM context objects. The data for these objects is provided as NUL-terminated C strings
+ and maps directly to the respective unit resource control directives. Note that these limits apply to individual sessions of the user,
+ they do not apply to all user processes as a combined whole. In particular, the per-user <command>user@.service</command> unit instance,
+ which runs the <command>elogind --user</command> manager process and its children, and is tracked outside of any session, being shared
+ by all the user's sessions, is not covered by these limits.
+ </para>
+
+ <para> See
+ <citerefentry><refentrytitle>elogind.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry> for more information about the resources.
+ Also, see <citerefentry><refentrytitle>pam_set_data</refentrytitle><manvolnum>3</manvolnum></citerefentry> for additional information about how to set
+ the context objects.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term><varname>elogind.memory_max</varname></term>
+
+ <listitem><para>Sets unit <varname>MemoryMax=</varname>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>elogind.tasks_max</varname></term>
+
+ <listitem><para>Sets unit <varname>TasksMax=</varname>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>elogind.cpu_weight</varname></term>
+
+ <listitem><para>Sets unit <varname>CPUWeight=</varname>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>elogind.io_weight</varname></term>
+
+ <listitem><para>Sets unit <varname>IOWeight=</varname>.</para></listitem>
+ </varlistentry>
</variablelist>
+
+ <para>Example data as can be provided from an another PAM module:
+ <programlisting>
+pam_set_data(handle, "elogind.memory_max", (void *)"200M", cleanup);
+pam_set_data(handle, "elogind.tasks_max", (void *)"50", cleanup);
+pam_set_data(handle, "elogind.cpu_weight", (void *)"100", cleanup);
+pam_set_data(handle, "elogind.io_weight", (void *)"340", cleanup);
+ </programlisting>
+ </para>
+
</refsect1>
<refsect1>
diff --git a/man/rules/meson.build b/man/rules/meson.build
new file mode 100644
index 000000000..74191d00b
--- /dev/null
+++ b/man/rules/meson.build
@@ -0,0 +1,349 @@
+# Do not edit. Generated by make-man-rules.py.
+manpages = [
+['elogind-inhibit', '1', [], ''],
+ ['elogind', '8', [], ''],
+ ['elogind.syntax', '7', [], ''],
+ ['loginctl', '1', [], ''],
+ ['logind.conf', '5', [], ''],
+ ['pam_elogind', '8', [], 'HAVE_PAM'],
+ ['sd-bus', '3', [], ''],
+ ['sd-event', '3', [], ''],
+ ['sd-login', '3', [], 'HAVE_PAM'],
+ ['sd_booted', '3', [], ''],
+ ['sd_bus_add_match',
+ '3',
+ ['sd_bus_add_match_async',
+ 'sd_bus_match_signal',
+ 'sd_bus_match_signal_async'],
+ ''],
+ ['sd_bus_creds_get_pid',
+ '3',
+ ['sd_bus_creds_get_audit_login_uid',
+ 'sd_bus_creds_get_audit_session_id',
+ 'sd_bus_creds_get_cgroup',
+ 'sd_bus_creds_get_cmdline',
+ 'sd_bus_creds_get_comm',
+ 'sd_bus_creds_get_description',
+ 'sd_bus_creds_get_egid',
+ 'sd_bus_creds_get_euid',
+ 'sd_bus_creds_get_exe',
+ 'sd_bus_creds_get_fsgid',
+ 'sd_bus_creds_get_fsuid',
+ 'sd_bus_creds_get_gid',
+ 'sd_bus_creds_get_owner_uid',
+ 'sd_bus_creds_get_ppid',
+ 'sd_bus_creds_get_selinux_context',
+ 'sd_bus_creds_get_session',
+ 'sd_bus_creds_get_sgid',
+ 'sd_bus_creds_get_slice',
+ 'sd_bus_creds_get_suid',
+ 'sd_bus_creds_get_supplementary_gids',
+ 'sd_bus_creds_get_tid',
+ 'sd_bus_creds_get_tid_comm',
+ 'sd_bus_creds_get_tty',
+ 'sd_bus_creds_get_uid',
+ 'sd_bus_creds_get_unique_name',
+ 'sd_bus_creds_get_unit',
+ 'sd_bus_creds_get_user_slice',
+ 'sd_bus_creds_get_user_unit',
+ 'sd_bus_creds_get_well_known_names',
+ 'sd_bus_creds_has_bounding_cap',
+ 'sd_bus_creds_has_effective_cap',
+ 'sd_bus_creds_has_inheritable_cap',
+ 'sd_bus_creds_has_permitted_cap'],
+ ''],
+ ['sd_bus_creds_new_from_pid',
+ '3',
+ ['sd_bus_creds_get_augmented_mask',
+ 'sd_bus_creds_get_mask',
+ 'sd_bus_creds_ref',
+ 'sd_bus_creds_unref',
+ 'sd_bus_creds_unrefp'],
+ ''],
+ ['sd_bus_default',
+ '3',
+ ['sd_bus_default_system',
+ 'sd_bus_default_user',
+ 'sd_bus_open',
+ 'sd_bus_open_system',
+ 'sd_bus_open_system_machine',
+ 'sd_bus_open_system_remote',
+ 'sd_bus_open_user'],
+ ''],
+ ['sd_bus_error',
+ '3',
+ ['SD_BUS_ERROR_MAKE_CONST',
+ 'SD_BUS_ERROR_NULL',
+ 'sd_bus_error_copy',
+ 'sd_bus_error_free',
+ 'sd_bus_error_get_errno',
+ 'sd_bus_error_has_name',
+ 'sd_bus_error_is_set',
+ 'sd_bus_error_set',
+ 'sd_bus_error_set_const',
+ 'sd_bus_error_set_errno',
+ 'sd_bus_error_set_errnof',
+ 'sd_bus_error_set_errnofv',
+ 'sd_bus_error_setf'],
+ ''],
+ ['sd_bus_error_add_map',
+ '3',
+ ['SD_BUS_ERROR_END', 'SD_BUS_ERROR_MAP', 'sd_bus_error_map'],
+ ''],
+ ['sd_bus_get_fd', '3', [], ''],
+ ['sd_bus_is_open', '3', ['sd_bus_is_ready'], ''],
+ ['sd_bus_message_append', '3', ['sd_bus_message_appendv'], ''],
+ ['sd_bus_message_append_array',
+ '3',
+ ['sd_bus_message_append_array_iovec',
+ 'sd_bus_message_append_array_memfd',
+ 'sd_bus_message_append_array_space'],
+ ''],
+ ['sd_bus_message_append_basic', '3', [], ''],
+ ['sd_bus_message_append_string_memfd',
+ '3',
+ ['sd_bus_message_append_string_iovec', 'sd_bus_message_append_string_space'],
+ ''],
+ ['sd_bus_message_append_strv', '3', [], ''],
+ ['sd_bus_message_get_cookie', '3', ['sd_bus_message_get_reply_cookie'], ''],
+ ['sd_bus_message_get_monotonic_usec',
+ '3',
+ ['sd_bus_message_get_realtime_usec', 'sd_bus_message_get_seqnum'],
+ ''],
+ ['sd_bus_message_read_basic', '3', [], ''],
+ ['sd_bus_negotiate_fds',
+ '3',
+ ['sd_bus_negotiate_creds', 'sd_bus_negotiate_timestamp'],
+ ''],
+ ['sd_bus_new', '3', ['sd_bus_ref', 'sd_bus_unref', 'sd_bus_unrefp'], ''],
+ ['sd_bus_path_encode',
+ '3',
+ ['sd_bus_path_decode', 'sd_bus_path_decode_many', 'sd_bus_path_encode_many'],
+ ''],
+ ['sd_bus_process', '3', [], ''],
+ ['sd_bus_request_name',
+ '3',
+ ['sd_bus_release_name',
+ 'sd_bus_release_name_async',
+ 'sd_bus_request_name_async'],
+ ''],
+ ['sd_bus_set_connected_signal', '3', ['sd_bus_get_connected_signal'], ''],
+ ['sd_bus_set_sender', '3', ['sd_bus_get_sender'], ''],
+ ['sd_bus_set_watch_bind', '3', ['sd_bus_get_watch_bind'], ''],
+ ['sd_bus_slot_set_destroy_callback',
+ '3',
+ ['sd_bus_destroy_t',
+ 'sd_bus_slot_get_destroy_callback',
+ 'sd_bus_track_get_destroy_callback',
+ 'sd_bus_track_set_destroy_callback'],
+ ''],
+ ['sd_bus_slot_set_floating', '3', ['sd_bus_slot_get_floating'], ''],
+ ['sd_bus_track_add_name',
+ '3',
+ ['sd_bus_track_add_sender',
+ 'sd_bus_track_contains',
+ 'sd_bus_track_count',
+ 'sd_bus_track_count_name',
+ 'sd_bus_track_count_sender',
+ 'sd_bus_track_first',
+ 'sd_bus_track_next',
+ 'sd_bus_track_remove_name',
+ 'sd_bus_track_remove_sender'],
+ ''],
+ ['sd_bus_track_new',
+ '3',
+ ['sd_bus_track_get_bus',
+ 'sd_bus_track_get_recursive',
+ 'sd_bus_track_get_userdata',
+ 'sd_bus_track_ref',
+ 'sd_bus_track_set_recursive',
+ 'sd_bus_track_set_userdata',
+ 'sd_bus_track_unref',
+ 'sd_bus_track_unrefp'],
+ ''],
+ ['sd_event_add_child',
+ '3',
+ ['sd_event_child_handler_t', 'sd_event_source_get_child_pid'],
+ ''],
+ ['sd_event_add_defer',
+ '3',
+ ['sd_event_add_exit', 'sd_event_add_post', 'sd_event_handler_t'],
+ ''],
+ ['sd_event_add_inotify',
+ '3',
+ ['sd_event_inotify_handler_t', 'sd_event_source_get_inotify_mask'],
+ ''],
+ ['sd_event_add_io',
+ '3',
+ ['sd_event_io_handler_t',
+ 'sd_event_source',
+ 'sd_event_source_get_io_events',
+ 'sd_event_source_get_io_fd',
+ 'sd_event_source_get_io_fd_own',
+ 'sd_event_source_get_io_revents',
+ 'sd_event_source_set_io_events',
+ 'sd_event_source_set_io_fd',
+ 'sd_event_source_set_io_fd_own'],
+ ''],
+ ['sd_event_add_signal',
+ '3',
+ ['sd_event_signal_handler_t', 'sd_event_source_get_signal'],
+ ''],
+ ['sd_event_add_time',
+ '3',
+ ['sd_event_source_get_time',
+ 'sd_event_source_get_time_accuracy',
+ 'sd_event_source_get_time_clock',
+ 'sd_event_source_set_time',
+ 'sd_event_source_set_time_accuracy',
+ 'sd_event_time_handler_t'],
+ ''],
+ ['sd_event_exit', '3', ['sd_event_get_exit_code'], ''],
+ ['sd_event_get_fd', '3', [], ''],
+ ['sd_event_new',
+ '3',
+ ['sd_event',
+ 'sd_event_default',
+ 'sd_event_get_tid',
+ 'sd_event_ref',
+ 'sd_event_unref',
+ 'sd_event_unrefp'],
+ ''],
+ ['sd_event_now', '3', [], ''],
+ ['sd_event_run', '3', ['sd_event_loop'], ''],
+ ['sd_event_set_watchdog', '3', ['sd_event_get_watchdog'], ''],
+ ['sd_event_source_get_event', '3', [], ''],
+ ['sd_event_source_get_pending', '3', [], ''],
+ ['sd_event_source_set_description',
+ '3',
+ ['sd_event_source_get_description'],
+ ''],
+ ['sd_event_source_set_destroy_callback',
+ '3',
+ ['sd_event_destroy_t', 'sd_event_source_get_destroy_callback'],
+ ''],
+ ['sd_event_source_set_enabled',
+ '3',
+ ['SD_EVENT_OFF',
+ 'SD_EVENT_ON',
+ 'SD_EVENT_ONESHOT',
+ 'sd_event_source_get_enabled'],
+ ''],
+ ['sd_event_source_set_prepare', '3', [], ''],
+ ['sd_event_source_set_priority',
+ '3',
+ ['SD_EVENT_PRIORITY_IDLE',
+ 'SD_EVENT_PRIORITY_IMPORTANT',
+ 'SD_EVENT_PRIORITY_NORMAL',
+ 'sd_event_source_get_priority'],
+ ''],
+ ['sd_event_source_set_userdata', '3', ['sd_event_source_get_userdata'], ''],
+ ['sd_event_source_unref',
+ '3',
+ ['sd_event_source_ref', 'sd_event_source_unrefp'],
+ ''],
+ ['sd_event_wait',
+ '3',
+ ['SD_EVENT_ARMED',
+ 'SD_EVENT_EXITING',
+ 'SD_EVENT_FINISHED',
+ 'SD_EVENT_INITIAL',
+ 'SD_EVENT_PENDING',
+ 'SD_EVENT_PREPARING',
+ 'SD_EVENT_RUNNING',
+ 'sd_event_dispatch',
+ 'sd_event_get_iteration',
+ 'sd_event_get_state',
+ 'sd_event_prepare'],
+ ''],
+ ['sd_get_seats',
+ '3',
+ ['sd_get_machine_names', 'sd_get_sessions', 'sd_get_uids'],
+ 'HAVE_PAM'],
+ ['sd_id128_get_machine',
+ '3',
+ ['sd_id128_get_boot',
+ 'sd_id128_get_invocation',
+ 'sd_id128_get_machine_app_specific'],
+ ''],
+ ['sd_id128_randomize', '3', [], ''],
+ ['sd_id128_to_string', '3', ['sd_id128_from_string'], ''],
+ ['sd_is_fifo',
+ '3',
+ ['sd_is_mq',
+ 'sd_is_socket',
+ 'sd_is_socket_inet',
+ 'sd_is_socket_sockaddr',
+ 'sd_is_socket_unix',
+ 'sd_is_special'],
+ ''],
+ ['sd_listen_fds',
+ '3',
+ ['SD_LISTEN_FDS_START', 'sd_listen_fds_with_names'],
+ ''],
+ ['sd_login_monitor_new',
+ '3',
+ ['sd_login_monitor',
+ 'sd_login_monitor_flush',
+ 'sd_login_monitor_get_events',
+ 'sd_login_monitor_get_fd',
+ 'sd_login_monitor_get_timeout',
+ 'sd_login_monitor_unref',
+ 'sd_login_monitor_unrefp'],
+ 'HAVE_PAM'],
+ ['sd_machine_get_class', '3', ['sd_machine_get_ifindices'], ''],
+ ['sd_notify',
+ '3',
+ ['sd_notifyf', 'sd_pid_notify', 'sd_pid_notify_with_fds', 'sd_pid_notifyf'],
+ ''],
+ ['sd_pid_get_owner_uid',
+ '3',
+ ['sd_peer_get_cgroup',
+ 'sd_peer_get_machine_name',
+ 'sd_peer_get_owner_uid',
+ 'sd_peer_get_session',
+ 'sd_peer_get_slice',
+ 'sd_peer_get_unit',
+ 'sd_peer_get_user_slice',
+ 'sd_peer_get_user_unit',
+ 'sd_pid_get_cgroup',
+ 'sd_pid_get_machine_name',
+ 'sd_pid_get_session',
+ 'sd_pid_get_slice',
+ 'sd_pid_get_unit',
+ 'sd_pid_get_user_slice',
+ 'sd_pid_get_user_unit'],
+ 'HAVE_PAM'],
+ ['sd_seat_get_active',
+ '3',
+ ['sd_seat_can_graphical',
+ 'sd_seat_can_multi_session',
+ 'sd_seat_can_tty',
+ 'sd_seat_get_sessions'],
+ 'HAVE_PAM'],
+ ['sd_session_is_active',
+ '3',
+ ['sd_session_get_class',
+ 'sd_session_get_desktop',
+ 'sd_session_get_display',
+ 'sd_session_get_remote_host',
+ 'sd_session_get_remote_user',
+ 'sd_session_get_seat',
+ 'sd_session_get_service',
+ 'sd_session_get_state',
+ 'sd_session_get_tty',
+ 'sd_session_get_type',
+ 'sd_session_get_uid',
+ 'sd_session_get_vt',
+ 'sd_session_is_remote'],
+ 'HAVE_PAM'],
+ ['sd_uid_get_state',
+ '3',
+ ['sd_uid_get_display',
+ 'sd_uid_get_seats',
+ 'sd_uid_get_sessions',
+ 'sd_uid_is_on_seat'],
+ 'HAVE_PAM'],
+ ['sd_watchdog_enabled', '3', [], '']
+]
+# Really, do not edit.
diff --git a/man/sd-bus.xml b/man/sd-bus.xml
index 0ecabab11..95e0e227b 100644
--- a/man/sd-bus.xml
+++ b/man/sd-bus.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of systemd.
-
- Copyright 2016 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/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd-bus" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd-bus</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Documentation</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd-event.xml b/man/sd-event.xml
index 4fcd35685..d1fae5f15 100644
--- a/man/sd-event.xml
+++ b/man/sd-event.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2015 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd-event" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd-event</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -73,6 +49,7 @@
<citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
@@ -156,7 +133,12 @@
<refsect1>
<title>See Also</title>
<para>
+ <!-- 0 /// elogind is in section 8
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ --><!-- else -->
<citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <!-- // 0 -->
<citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_run</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
diff --git a/man/sd-login.xml b/man/sd-login.xml
new file mode 100644
index 000000000..5651e0485
--- /dev/null
+++ b/man/sd-login.xml
@@ -0,0 +1,251 @@
+<?xml version='1.0'?> <!--*-nxml-*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ SPDX-License-Identifier: LGPL-2.1+
+-->
+
+<refentry id="sd-login" conditional='HAVE_PAM'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd-login</title>
+ <productname>systemd</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd-login</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd-login</refname>
+ <refpurpose>APIs for
+ tracking logins</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include &lt;systemd/sd-login.h&gt;</funcsynopsisinfo>
+ </funcsynopsis>
+
+ <cmdsynopsis>
+ <command>pkg-config --cflags --libs libelogind</command>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><filename>sd-login.h</filename> provides APIs to introspect
+ and monitor seat, login session and user status information on the
+ local system. </para>
+
+ <para>Note that these APIs only allow purely passive access and
+ monitoring of seats, sessions and users. To actively make changes
+ to the seat configuration, terminate login sessions, or switch
+ session on a seat you need to utilize the D-Bus API of
+ systemd-logind, instead.</para>
+
+ <para>These functions synchronously access data in
+ <filename>/proc</filename>, <filename>/sys/fs/cgroup</filename>
+ and <filename>/run</filename>. All of these are virtual file
+ systems, hence the runtime cost of the accesses is relatively
+ cheap.</para>
+
+ <para>It is possible (and often a very good choice) to mix calls
+ to the synchronous interface of <filename>sd-login.h</filename>
+ with the asynchronous D-Bus interface of systemd-logind. However,
+ if this is done you need to think a bit about possible races since
+ the stream of events from D-Bus and from
+ <filename>sd-login.h</filename> interfaces such as the login
+ monitor are asynchronous and not ordered against each
+ other.</para>
+
+ <para>If the functions return string arrays, these are generally
+ <constant>NULL</constant> terminated and need to be freed by the
+ caller with the libc
+ <citerefentry project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ call after use, including the strings referenced therein.
+ Similarly, individual strings returned need to be freed, as
+ well.</para>
+
+ <para>As a special exception, instead of an empty string array
+ <constant>NULL</constant> may be returned, which should be treated
+ equivalent to an empty string array.</para>
+
+ <para>See
+ <citerefentry><refentrytitle>sd_pid_get_session</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_uid_get_state</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_session_is_active</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_seat_get_active</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_get_seats</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_login_monitor_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ for more information about the functions
+ implemented.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Definition of Terms</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>seat</term>
+
+ <listitem><para>A seat consists of all hardware devices assigned to a specific
+ workplace. It consists of at least one graphics device, and usually also includes
+ keyboard, mouse. It can also include video cameras, sound cards and more. Seats
+ are identified by seat names, which are strings (&lt;= 255 characters), that start
+ with the four characters <literal>seat</literal> followed by at least one
+ character from the range [a-zA-Z0-9], <literal>_</literal> and
+ <literal>-</literal>. They are suitable for use as file names. Seat names may or
+ may not be stable and may be reused if a seat becomes available again.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>session</term>
+
+ <listitem><para>A session is defined by the time a user is logged in until they
+ log out. A session is bound to one or no seats (the latter for 'virtual' ssh
+ logins). Multiple sessions can be attached to the same seat, but only one of them
+ can be active, the others are in the background. A session is identified by a
+ short string.</para>
+
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ ensures that audit sessions are identical to systemd sessions, and uses the audit
+ session ID as session ID in systemd (if auditing is enabled). In general the
+ session identifier is a short string consisting only of [a-zA-Z0-9],
+ <literal>_</literal> and <literal>-</literal>, suitable for use as a file name.
+ Session IDs are unique on the local machine and are
+ never reused as long as the machine is online. A user (the way we know it on UNIX)
+ corresponds to the person using a computer. A single user can have multiple
+ sessions open at the same time. A user is identified by a numeric user id (UID) or
+ a user name (a string). A multi-session system allows multiple user sessions on
+ the same seat at the same time. A multi-seat system allows multiple independent
+ seats that can be individually and simultaneously used by different users.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>All hardware devices that are eligible to being assigned to a seat, are assigned
+ to one. A device can be assigned to only one seat at a time. If a device is not
+ assigned to any particular other seat it is implicitly assigned to the special default
+ seat called <literal>seat0</literal>.</para>
+
+ <para>Note that hardware like printers, hard disks or network cards is generally not
+ assigned to a specific seat. They are available to all seats equally. (Well, with one
+ exception: USB sticks can be assigned to a seat.)</para>
+
+ <para><literal>seat0</literal> always exists.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>udev Rules</title>
+
+ <para>Assignment of hardware devices to seats is managed inside the udev database, via
+ settings on the devices:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term>Tag <literal>seat</literal></term>
+
+ <listitem><para>When set, a device is eligible to be assigned to a seat. This tag
+ is set for graphics devices, mice, keyboards, video cards, sound cards and
+ more. Note that some devices like sound cards consist of multiple subdevices
+ (i.e. a PCM for input and another one for output). This tag will be set only for
+ the originating device, not for the individual subdevices. A UI for configuring
+ assignment of devices to seats should enumerate and subscribe to all devices with
+ this tag set and show them in the UI. Note that USB hubs can be assigned to a seat
+ as well, in which case all (current and future) devices plugged into it will also
+ be assigned to the same seat (unless they are explicitly assigned to another
+ seat).
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Tag <literal>master-of-seat</literal></term>
+
+ <listitem><para>When set, this device is enough for a seat to be considered
+ existent. This tag is usually set for the framebuffer device of graphics cards. A
+ seat hence consists of an arbitrary number of devices marked with the
+ <literal>seat</literal> tag, but (at least) one of these devices needs to be
+ tagged with <literal>master-of-seat</literal> before the seat is actually
+ considered to be around.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Property <varname>ID_SEAT</varname></term>
+
+ <listitem><para>This property specifies the name of the seat a specific device is
+ assigned to. If not set the device is assigned to <literal>seat0</literal>. Also,
+ to speed up enumeration of hardware belonging to a specific seat, the seat is also
+ set as tag on the device. I.e. if the property
+ <varname>ID_SEAT=seat-waldo</varname> is set for a device, the tag
+ <literal>seat-waldo</literal> will be set as well. Note that if a device is
+ assigned to <literal>seat0</literal>, it will usually not carry such a tag and you
+ need to enumerate all devices and check the <varname>ID_SEAT</varname> property
+ manually. Again, if a device is assigned to seat0 this is visible on the device in
+ two ways: with a property <varname>ID_SEAT=seat0</varname> and with no property
+ <varname>ID_SEAT</varname> set for it at all.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Property <varname>ID_AUTOSEAT</varname></term>
+
+ <listitem><para>When set to <literal>1</literal>, this device automatically
+ generates a new and independent seat, which is named after the path of the
+ device. This is set for specialized USB hubs like the Plugable devices, which when
+ plugged in should create a hotplug seat without further configuration.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Property <varname>ID_FOR_SEAT</varname></term>
+
+ <listitem><para>When creating additional (manual) seats starting from a graphics
+ device this is a good choice to name the seat after. It is created from the path
+ of the device. This is useful in UIs for configuring seats: as soon as you create
+ a new seat from a graphics device, read this property and prefix it with
+ <literal>seat-</literal> and use it as name for the seat.</para></listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>A seat exists only and exclusively because a properly tagged device with the
+ right <varname>ID_SEAT</varname> property exists. Besides udev rules there is no
+ persistent data about seats stored on disk.</para>
+
+ <para>Note that
+ <citerefentry><refentrytitle>systemd-logind</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ manages ACLs on a number of device classes, to allow user code to access the device
+ nodes attached to a seat as long as the user has an active session on it. This is
+ mostly transparent to applications. As mentioned above, for certain user software it
+ might be a good idea to watch whether they can access device nodes instead of thinking
+ about seats.</para>
+ </refsect1>
+
+ <xi:include href="libelogind-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_pid_get_session</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_uid_get_state</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_session_is_active</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_seat_get_active</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_get_seats</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_login_monitor_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ </para>
+
+ <para>
+ <ulink url="https://www.freedesktop.org/wiki/Software/systemd/multiseat">Multi-Seat on Linux</ulink>
+ for an introduction to multi-seat support on Linux and the background for this set of APIs.
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/sd_booted.xml b/man/sd_booted.xml
index d6e9be16e..1dc519602 100644
--- a/man/sd_booted.xml
+++ b/man/sd_booted.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2017 Sven Eden
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_booted"
@@ -27,15 +12,6 @@
<refentryinfo>
<title>sd_booted</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Sven</firstname>
- <surname>Eden</surname>
- <email>sven.eden@gmx.de.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_bus_add_match.xml b/man/sd_bus_add_match.xml
index cac662f8d..db250a0cd 100644
--- a/man/sd_bus_add_match.xml
+++ b/man/sd_bus_add_match.xml
@@ -3,22 +3,9 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
+ SPDX-License-Identifier: LGPL-2.1+
- Copyright 2016 Julian Orth
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2016 Julian Orth
-->
<refentry id="sd_bus_add_match">
@@ -26,14 +13,6 @@
<refentryinfo>
<title>sd_bus_add_match</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <firstname>Julian</firstname>
- <surname>Orth</surname>
- <email>ju.orth@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -43,8 +22,11 @@
<refnamediv>
<refname>sd_bus_add_match</refname>
+ <refname>sd_bus_add_match_async</refname>
+ <refname>sd_bus_match_signal</refname>
+ <refname>sd_bus_match_signal_async</refname>
- <refpurpose>Add a match rule for message dispatching</refpurpose>
+ <refpurpose>Add a match rule for incoming message dispatching</refpurpose>
</refnamediv>
<refsynopsisdiv>
@@ -52,6 +34,13 @@
<funcsynopsisinfo>#include &lt;elogind/sd-bus.h&gt;</funcsynopsisinfo>
<funcprototype>
+ <funcdef>typedef int (*<function>sd_bus_message_handler_t</function>)</funcdef>
+ <paramdef>sd_bus_message *<parameter>m</parameter></paramdef>
+ <paramdef>void *<parameter>userdata</parameter></paramdef>
+ <paramdef>sd_bus_error *<parameter>ret_error</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
<funcdef>int <function>sd_bus_add_match</function></funcdef>
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
<paramdef>sd_bus_slot **<parameter>slot</parameter></paramdef>
@@ -61,58 +50,125 @@
</funcprototype>
<funcprototype>
- <funcdef>typedef int (*<function>sd_bus_message_handler_t</function>)</funcdef>
- <paramdef>sd_bus_message *<parameter>m</parameter></paramdef>
+ <funcdef>int <function>sd_bus_add_match_async</function></funcdef>
+ <paramdef>sd_bus *<parameter>bus</parameter></paramdef>
+ <paramdef>sd_bus_slot **<parameter>slot</parameter></paramdef>
+ <paramdef>const char *<parameter>match</parameter></paramdef>
+ <paramdef>sd_bus_message_handler_t <parameter>callback</parameter></paramdef>
+ <paramdef>sd_bus_message_handler_t <parameter>install_callback</parameter></paramdef>
<paramdef>void *<parameter>userdata</parameter></paramdef>
- <paramdef>sd_bus_error *<parameter>ret_error</parameter></paramdef>
</funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_match_signal</function></funcdef>
+ <paramdef>sd_bus *<parameter>bus</parameter></paramdef>
+ <paramdef>sd_bus_slot **<parameter>slot</parameter></paramdef>
+ <paramdef>const char *<parameter>sender</parameter></paramdef>
+ <paramdef>const char *<parameter>path</parameter></paramdef>
+ <paramdef>const char *<parameter>interface</parameter></paramdef>
+ <paramdef>const char *<parameter>member</parameter></paramdef>
+ <paramdef>sd_bus_message_handler_t <parameter>callback</parameter></paramdef>
+ <paramdef>void *<parameter>userdata</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_match_signal_async</function></funcdef>
+ <paramdef>sd_bus *<parameter>bus</parameter></paramdef>
+ <paramdef>sd_bus_slot **<parameter>slot</parameter></paramdef>
+ <paramdef>const char *<parameter>sender</parameter></paramdef>
+ <paramdef>const char *<parameter>path</parameter></paramdef>
+ <paramdef>const char *<parameter>interface</parameter></paramdef>
+ <paramdef>const char *<parameter>member</parameter></paramdef>
+ <paramdef>sd_bus_message_handler_t <parameter>callback</parameter></paramdef>
+ <paramdef>sd_bus_message_handler_t <parameter>install_callback</parameter></paramdef>
+ <paramdef>void *<parameter>userdata</parameter></paramdef>
+ </funcprototype>
+
</funcsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
- <para>
- <function>sd_bus_add_match()</function> adds a match rule used to dispatch
- incoming messages. The syntax of the rule passed in
- <parameter>match</parameter> is described in the
- <ulink url="https://dbus.freedesktop.org/doc/dbus-specification.html">D-Bus Specification</ulink>.
+ <para><function>sd_bus_add_match()</function> installs a match rule for messages received on the specified bus
+ connection object <parameter>bus</parameter>. The syntax of the match rule expression passed in
+ <parameter>match</parameter> is described in the <ulink
+ url="https://dbus.freedesktop.org/doc/dbus-specification.html">D-Bus Specification</ulink>. The specified handler
+ function <parameter>callback</parameter> is called for eaching incoming message matching the specified expression,
+ the <parameter>userdata</parameter> parameter is passed as-is to the callback function. The match is installed
+ synchronously when connected to a bus broker, i.e. the call sends a control message requested the match to be added
+ to the broker and waits until the broker confirms the match has been installed successfully.</para>
+
+ <para><function>sd_bus_add_match_async()</function> operates very similar to
+ <function>sd_bus_match_signal()</function>, however it installs the match asynchronously, in a non-blocking
+ fashion: a request is sent to the broker, but the call does not wait for a response. The
+ <parameter>install_callback</parameter> function is called when the response is later received, with the response
+ message from the broker as parameter. If this function is specified as <constant>NULL</constant> a default
+ implementation is used that terminates the bus connection should installing the match fail.</para>
+
+ <para><function>sd_bus_match_signal()</function> is very similar to <function>sd_bus_add_match()</function>, but
+ only matches signals, and instead of a match expression accepts four parameters: <parameter>sender</parameter> (the
+ service name of the sender), <parameter>path</parameter> (the object path of the emitting object),
+ <parameter>interface</parameter> (the interface the signal belongs to), <parameter>member</parameter> (the signal
+ name), from which the match string is internally generated. Optionally, these parameters may be specified as
+ <constant>NULL</constant> in which case the relevant field of incoming signals is not tested.</para>
+
+ <para><function>sd_bus_match_signal_async()</function> combines the signal matching logic of
+ <function>sd_bus_match_signal()</function> with the asynchronous behaviour of
+ <function>sd_bus_add_match_async()</function>.</para>
+
+ <para>On success, and if non-<constant>NULL</constant>, the <parameter>slot</parameter> return parameter will be
+ set to a slot object that may be used as a reference to the installed match, and may be utilized to remove it again
+ at a later time with
+ <citerefentry><refentrytitle>sd_bus_slot_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>. If specified
+ as <constant>NULL</constant> the lifetime of the match is bound to the lifetime of the bus object itself, and the
+ match is generally not removed independently. See
+ <citerefentry><refentrytitle>sd_bus_slot_set_floating</refentrytitle><manvolnum>3</manvolnum></citerefentry> for
+ details.</para>
+
+ <para>The message <parameter>m</parameter> passed to the callback is only borrowed, that is, the callback should
+ not call <citerefentry><refentrytitle>sd_bus_message_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ on it. If the callback wants to hold on to the message beyond the lifetime of the callback, it needs to call
+ <citerefentry><refentrytitle>sd_bus_message_ref</refentrytitle><manvolnum>3</manvolnum></citerefentry> to create a
+ new reference.</para>
+
+ <para>If an error occurs during the callback invocation, the callback should return a negative error number
+ (optionally, a more precise error may be returned in <parameter>ret_error</parameter>, as well). If it wants other
+ callbacks that match the same rule to be called, it should return 0. Otherwise it should return a positive integer.
</para>
- <para>
- The message <parameter>m</parameter> passed to the callback is only
- borrowed, that is, the callback should not call
- <citerefentry><refentrytitle>sd_bus_message_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>
- on it. If the callback wants to hold on to the message beyond the lifetime
- of the callback, it needs to call
- <citerefentry><refentrytitle>sd_bus_message_ref</refentrytitle><manvolnum>3</manvolnum></citerefentry>
- to create a new reference.
- </para>
-
- <para>
- If an error occurs during the callback invocation, the callback should
- return a negative error number. If it wants other callbacks that match the
- same rule to be called, it should return 0. Otherwise it should return a
- positive integer.
- </para>
+ <para>If the <parameter>bus</parameter> refers to a direct connection (i.e. not a bus connection, as set with
+ <citerefentry><refentrytitle>sd_bus_set_bus_client</refentrytitle><manvolnum>3</manvolnum></citerefentry>) the
+ match is only installed on the client side, and the synchronous and asynchronous functions operate the same.</para>
</refsect1>
<refsect1>
<title>Return Value</title>
<para>
- On success, <function>sd_bus_add_match()</function> returns 0 or a
- positive integer. On failure, it returns a negative errno-style error
- code.
+ On success, <function>sd_bus_add_match()</function> and the other calls return 0 or a positive integer. On
+ failure, they return a negative errno-style error code.
</para>
</refsect1>
<refsect1>
+ <title>Notes</title>
+
+ <para><function>sd_bus_add_match()</function> and the other functions described here are available as a shared
+ library, which can be compiled and linked to with the <constant>libelogind</constant> <citerefentry
+ project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry> file.</para>
+ </refsect1>
+
+ <refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_slot_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_message_ref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_set_bus_client</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_slot_set_floating</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/sd_bus_creds_get_pid.xml b/man/sd_bus_creds_get_pid.xml
index ffc526ea6..eec510f08 100644
--- a/man/sd_bus_creds_get_pid.xml
+++ b/man/sd_bus_creds_get_pid.xml
@@ -3,38 +3,14 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
-<refentry id="sd_bus_creds_get_pid">
+<refentry id="sd_bus_creds_get_pid" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_creds_get_pid</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>A monkey with a typewriter</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -338,8 +314,8 @@
-ENXIO is returned.</para>
<para><function>sd_bus_creds_get_cgroup()</function> will retrieve
- the cgroup path. See <ulink
- url="https://www.kernel.org/doc/Documentation/cgroups/cgroups.txt">cgroups.txt</ulink>.
+ the control group path. See <ulink
+ url="https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt">cgroups.txt</ulink>.
</para>
<para><function>sd_bus_creds_get_session()</function> will
@@ -454,11 +430,16 @@
<listitem><para>The given field is not specified for the described
process or peer. This will be returned by
- <function>sd_bus_get_session()</function>, and
- <function>sd_bus_get_owner_uid()</function> if the process is
+ <function>sd_bus_creds_get_unit()</function>,
+ <function>sd_bus_creds_get_slice()</function>,
+ <function>sd_bus_creds_get_user_unit()</function>,
+ <function>sd_bus_creds_get_user_slice()</function>, and
+ <function>sd_bus_creds_get_session()</function> if the process is
not part of a elogind system unit, systemd user unit, systemd
- slice, or logind session. It will also be returned by
- <function>sd_bus_creds_get_exe()</function> and
+ slice, or logind session. It will be returned by
+ <function>sd_bus_creds_get_owner_uid()</function> if the process is
+ not part of a elogind user unit or logind session. It will also be
+ returned by <function>sd_bus_creds_get_exe()</function> and
<function>sd_bus_creds_get_cmdline()</function> for kernel
threads (since these are not started from an executable binary,
nor have a command line), and by
@@ -486,16 +467,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para><function>sd_bus_creds_get_pid()</function> and the other
- functions described here are available as a shared library, which
- can be compiled and linked to with the
- <constant>libelogind</constant> <citerefentry
- project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_creds_new_from_pid.xml b/man/sd_bus_creds_new_from_pid.xml
index 1a507cf91..a3782440d 100644
--- a/man/sd_bus_creds_new_from_pid.xml
+++ b/man/sd_bus_creds_new_from_pid.xml
@@ -3,38 +3,14 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
-<refentry id="sd_bus_creds_new_from_pid">
+<refentry id="sd_bus_creds_new_from_pid" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_creds_new_from_pid</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>A monkey with a typewriter</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -318,16 +294,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para><function>sd_bus_creds_new_from_pid()</function> and the
- other calls described here are available as a shared library,
- which can be compiled and linked to with the
- <constant>libelogind</constant> <citerefentry
- project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_default.xml b/man/sd_bus_default.xml
index 13033a52e..f8b5cf0f1 100644
--- a/man/sd_bus_default.xml
+++ b/man/sd_bus_default.xml
@@ -3,38 +3,14 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
-<refentry id="sd_bus_default">
+<refentry id="sd_bus_default" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_default</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>A monkey with a typewriter</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -165,13 +141,17 @@
not set, a suitable default for the default system D-Bus instance
will be used.</para>
- <para><function>sd_bus_open_system_remote()</function> connects to
- the system bus on the specified <parameter>host</parameter> using
- <citerefentry
- project='die-net'><refentrytitle>ssh</refentrytitle><manvolnum>1</manvolnum></citerefentry>. <parameter>host</parameter>
- consists of an optional user name followed by the
- <literal>@</literal> symbol, and the hostname.
- </para>
+ <para><function>sd_bus_open_system_remote()</function> connects to the system bus on
+ the specified host using
+ <citerefentry project='die-net'><refentrytitle>ssh</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
+ <parameter>host</parameter> consists of an optional user name followed by the
+ <literal>@</literal> symbol, and the hostname, optionally followed by a
+ <literal>:</literal> and a machine name. If the machine name is given, a connection
+ is created to the system bus in the specified container on the remote machine, and
+ otherwise a connection to the system bus on the specified host is created.</para>
+
+ <para>Note that entering a container is a privileged operation, and will likely only
+ work for the root user on the remote machine.</para>
<para><function>sd_bus_open_system_machine()</function> connects
to the system bus in the specified <parameter>machine</parameter>,
@@ -213,21 +193,26 @@
<citerefentry><refentrytitle>sd_bus_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>
to drop the reference.</para>
- <para>Queued but unwritten/unread messages also keep a reference
- to their bus connection object. For this reason, even if an
- application dropped all references to a bus connection, it might
- not get destroyed right away. Until all incoming queued
- messages are read, and until all outgoing unwritten messages are
- written, the bus object will stay
- alive. <function>sd_bus_flush()</function> may be used to write
- all outgoing queued messages so they drop their references. To
- flush the unread incoming messages, use
- <function>sd_bus_close()</function>, which will also close the bus
- connection. When using the default bus logic, it is a good idea to
- first invoke <function>sd_bus_flush()</function> followed by
- <function>sd_bus_close()</function> when a thread or process
- terminates, and thus its bus connection object should be
- freed.</para>
+ <para>Queued but unwritten/unread messages keep a reference to their bus connection object. For this reason, even
+ if an application dropped all references to a bus connection, it might not get destroyed right away. Until all
+ incoming queued messages are read, and until all outgoing unwritten messages are written, the bus object will stay
+ alive. <function>sd_bus_flush()</function> may be used to write all outgoing queued messages so they drop their
+ references. To flush the unread incoming messages, use <function>sd_bus_close()</function>, which will also close
+ the bus connection. When using the default bus logic, it is a good idea to first invoke
+ <function>sd_bus_flush()</function> followed by <function>sd_bus_close()</function> when a thread or process
+ terminates, and thus its bus connection object should be freed.</para>
+
+ <para>Normally, slot objects (as created by
+ <citerefentry><refentrytitle>sd_bus_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry> and similar
+ calls) keep a reference to their bus connection object, too. Thus, as long as a bus slot object remains referenced
+ its bus object will remain allocated too. Optionally, bus slot objects may be placed in "floating" mode. When in
+ floating mode the life cycle of the bus slot object is bound to the bus object, i.e. when the bus object is freed
+ the bus slot object is automatically unreferenced too. The floating state of a slot object may be controlled
+ explicitly with
+ <citerefentry><refentrytitle>sd_bus_slot_set_floating</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ though usually floating bus slot objects are created by passing <constant>NULL</constant> as the
+ <parameter>slot</parameter> parameter of <function>sd_bus_add_match()</function> and related calls, thus indicating
+ that the caller is not directly interested in referencing and managing the bus slot object.</para>
<para>The life cycle of the default bus connection should be the
responsibility of the code that creates/owns the thread the
@@ -283,16 +268,7 @@
by returned. See <citerefentry><refentrytitle>sd_bus_send</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para><function>sd_bus_open_user()</function> and the other
- functions described here are available as a shared library, which
- can be compiled and linked to with the
- <constant>libelogind</constant> <citerefentry
- project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_error.xml b/man/sd_bus_error.xml
index 23e463602..070032bfe 100644
--- a/man/sd_bus_error.xml
+++ b/man/sd_bus_error.xml
@@ -3,38 +3,14 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
-<refentry id="sd_bus_error">
+<refentry id="sd_bus_error" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_error</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>A monkey with a typewriter</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -363,15 +339,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para><function>sd_bus_set_error()</function> and other functions
- described here are available as a shared library, which can be
- compiled and linked to with the
- <constant>libelogind</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_error_add_map.xml b/man/sd_bus_error_add_map.xml
index 93c8d7f48..1c6cddd55 100644
--- a/man/sd_bus_error_add_map.xml
+++ b/man/sd_bus_error_add_map.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2015 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_bus_error_add_map">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd_bus_error_add_map</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_bus_get_fd.xml b/man/sd_bus_get_fd.xml
index 7617eaff2..b0b546fb3 100644
--- a/man/sd_bus_get_fd.xml
+++ b/man/sd_bus_get_fd.xml
@@ -3,22 +3,9 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
+ SPDX-License-Identifier: LGPL-2.1+
- Copyright 2016 Julian Orth
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2016 Julian Orth
-->
<refentry id="sd_bus_get_fd">
@@ -26,14 +13,6 @@
<refentryinfo>
<title>sd_bus_get_fd</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <firstname>Julian</firstname>
- <surname>Orth</surname>
- <email>ju.orth@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_bus_is_open.xml b/man/sd_bus_is_open.xml
new file mode 100644
index 000000000..b9f2f5cab
--- /dev/null
+++ b/man/sd_bus_is_open.xml
@@ -0,0 +1,111 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ SPDX-License-Identifier: LGPL-2.1+
+-->
+
+<refentry id="sd_bus_is_open">
+
+ <refentryinfo>
+ <title>sd_bus_is_open</title>
+ <productname>elogind</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_bus_is_open</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_bus_is_open</refname>
+ <refname>sd_bus_is_ready</refname>
+
+ <refpurpose>Check whether the a bus connection is open or ready.</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include &lt;elogind/sd-bus.h&gt;</funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_is_open</function></funcdef>
+ <paramdef>sd_bus *<parameter>bus</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_is_ready</function></funcdef>
+ <paramdef>sd_bus *<parameter>bus</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_bus_is_open()</function> checks whether the specified bus connection is open, i.e. in the
+ process of being established, already established or in the process of being torn down. It returns zero when the
+ connection has not been started yet
+ (i.e. <citerefentry><refentrytitle>sd_bus_start</refentrytitle><manvolnum>3</manvolnum></citerefentry> or some
+ equivalent call has not been invoked yet), or is fully terminated again (for example after
+ <citerefentry><refentrytitle>sd_bus_close</refentrytitle><manvolnum>3</manvolnum></citerefentry>), it returns
+ positive otherwise.</para>
+
+ <para><function>sd_bus_is_ready()</function> checks whether the specified connection is fully established,
+ i.e. completed the connection and authentication phases of the protocol and received the
+ <function>Hello()</function> method call response, and is not in the process of being torn down again. It returns
+ zero outside of this state, and positive otherwise. Effectively, this function returns positive while regular
+ messages can be sent or received on the connection.</para>
+
+ <para>To be notified when the connection is fully established, use
+ <citerefentry><refentrytitle>sd_bus_set_connected_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry> and
+ install a match for the <function>Connected()</function> signal on the
+ <literal>org.freedesktop.DBus.Local</literal> interface. To be notified when the connection is torn down again,
+ install a match for the <function>Disconnected()</function> signal on the
+ <literal>org.freedesktop.DBus.Local</literal> interface.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success, these functions return 0 or a positive integer. On failure, they return a negative errno-style
+ error code.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>-ECHILD</constant></term>
+
+ <listitem><para>The bus connection has been created in a different process.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Notes</title>
+
+ <para><function>sd_bus_is_open()</function> and <function>sd_bus_is_ready()</function> are available as
+ a shared library, which can be compiled and linked to with the <constant>libelogind</constant> <citerefentry
+ project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry> file.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_start</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_close</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_set_connected_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/sd_bus_message_append.xml b/man/sd_bus_message_append.xml
index ba86f7afb..5a26d10de 100644
--- a/man/sd_bus_message_append.xml
+++ b/man/sd_bus_message_append.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_bus_message_append"
@@ -27,15 +12,6 @@
<refentryinfo>
<title>sd_bus_message_append</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>A monkey with a typewriter</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -240,15 +216,7 @@ sd_bus_message_append(m, "ynqiuxtd", y, n, q, i, u, x, t, d);</programlisting>
<xi:include href="sd_bus_message_append_basic.xml" xpointer="errors" />
- <refsect1>
- <title>Notes</title>
-
- <para><function>sd_bus_open_user()</function> and other functions
- described here are available as a shared library, which can be
- compiled and linked to with the
- <constant>libelogind-bus</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_message_append_array.xml b/man/sd_bus_message_append_array.xml
index 9a893035e..9ed5860f5 100644
--- a/man/sd_bus_message_append_array.xml
+++ b/man/sd_bus_message_append_array.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_bus_message_append_array"
@@ -27,15 +12,6 @@
<refentryinfo>
<title>sd_bus_message_append_array</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>A monkey with a typewriter</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -187,15 +163,7 @@
<xi:include href="sd_bus_message_append_basic.xml" xpointer="errors" />
- <refsect1>
- <title>Notes</title>
-
- <para><function>sd_bus_append_array()</function> and other
- functions described here are available as a shared library, which
- can be compiled and linked to with the
- <constant>libelogind</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_message_append_basic.xml b/man/sd_bus_message_append_basic.xml
index a49a18bba..49eb6d2f8 100644
--- a/man/sd_bus_message_append_basic.xml
+++ b/man/sd_bus_message_append_basic.xml
@@ -3,38 +3,14 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
-<refentry id="sd_bus_message_append_basic">
+<refentry id="sd_bus_message_append_basic" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_message_append_basic</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>A monkey with a typewriter</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -271,15 +247,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_bus_append_basic()</function> function
- described here is available as a shared library, which can be
- compiled and linked to with the
- <constant>libelogind</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_message_append_string_memfd.xml b/man/sd_bus_message_append_string_memfd.xml
index 08f1fd001..f2de80abf 100644
--- a/man/sd_bus_message_append_string_memfd.xml
+++ b/man/sd_bus_message_append_string_memfd.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_bus_message_append_string_memfd"
@@ -27,15 +12,6 @@
<refentryinfo>
<title>sd_bus_message_append_string_memfd</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>A monkey with a typewriter</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -130,20 +106,17 @@
<xi:include href="sd_bus_message_append_basic.xml" xpointer="errors" />
- <refsect1>
- <title>Notes</title>
-
- <para>The functions described here are available as a shared library,
- which can be compiled and linked to with the
- <constant>libelogind</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
<para>
+ <!-- 0 /// elogind is in section 8
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ --><!-- else -->
<citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <!-- // 0 -->
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_append_basic</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<ulink url="http://dbus.freedesktop.org/doc/dbus-specification.html">The D-Bus specification</ulink>
diff --git a/man/sd_bus_message_append_strv.xml b/man/sd_bus_message_append_strv.xml
index 458e21dcb..de21dd7c6 100644
--- a/man/sd_bus_message_append_strv.xml
+++ b/man/sd_bus_message_append_strv.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_bus_message_append_strv"
@@ -27,15 +12,6 @@
<refentryinfo>
<title>sd_bus_message_append_strv</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>A monkey with a typewriter</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -91,15 +67,7 @@
<xi:include href="sd_bus_message_append_basic.xml" xpointer="errors" />
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_bus_append_append_strv()</function> function
- described here is available as a shared library, which can be
- compiled and linked to with the
- <constant>libelogind</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_message_get_cookie.xml b/man/sd_bus_message_get_cookie.xml
index 7994d72aa..db3c64b5d 100644
--- a/man/sd_bus_message_get_cookie.xml
+++ b/man/sd_bus_message_get_cookie.xml
@@ -3,38 +3,15 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2013 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
-<refentry id="sd_bus_message_get_cookie">
+<refentry id="sd_bus_message_get_cookie"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_message_get_cookie</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -122,22 +99,17 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_bus_message_get_cookie()</function> and
- <function>sd_bus_message_get_reply_cookie()</function> interfaces
- are available as a shared library, which can be compiled and
- linked to with the
- <constant>libelogind</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
<para>
+ <!-- 0 /// elogind is in section 8
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ --><!-- else -->
<citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <!-- // 0 -->
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
diff --git a/man/sd_bus_message_get_monotonic_usec.xml b/man/sd_bus_message_get_monotonic_usec.xml
index 4fb50252a..559a997ae 100644
--- a/man/sd_bus_message_get_monotonic_usec.xml
+++ b/man/sd_bus_message_get_monotonic_usec.xml
@@ -3,38 +3,15 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2013 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
-<refentry id="sd_bus_message_get_monotonic_usec">
+<refentry id="sd_bus_message_get_monotonic_usec"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_message_get_monotonic_usec</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -152,24 +129,17 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The
- <function>sd_bus_message_get_monotonic_usec()</function>,
- <function>sd_bus_message_get_realtime_usec()</function>, and
- <function>sd_bus_message_get_seqnum()</function> interfaces are
- available as a shared library, which can be compiled and linked to
- with the
- <constant>libelogind</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
<para>
+ <!-- 0 /// elogind is in section 8
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ --><!-- else -->
<citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <!-- // 0 -->
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_negotiate_timestamp</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
diff --git a/man/sd_bus_message_read_basic.xml b/man/sd_bus_message_read_basic.xml
index bc5de5299..fb4df08e1 100644
--- a/man/sd_bus_message_read_basic.xml
+++ b/man/sd_bus_message_read_basic.xml
@@ -3,22 +3,9 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
+ SPDX-License-Identifier: LGPL-2.1+
- Copyright 2016 Julian Orth
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2016 Julian Orth
-->
<refentry id="sd_bus_message_read_basic">
@@ -26,14 +13,6 @@
<refentryinfo>
<title>sd_bus_message_read_basic</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <firstname>Julian</firstname>
- <surname>Orth</surname>
- <email>ju.orth@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_bus_negotiate_fds.xml b/man/sd_bus_negotiate_fds.xml
index 90404d2f2..0522bd549 100644
--- a/man/sd_bus_negotiate_fds.xml
+++ b/man/sd_bus_negotiate_fds.xml
@@ -3,38 +3,14 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2014 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
-<refentry id="sd_bus_negotiate_fds">
+<refentry id="sd_bus_negotiate_fds" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_negotiate_fds</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -93,17 +69,9 @@
default, file descriptor passing is negotiated for all
connections.</para>
- <para>Note that when bus activation is used, it is highly
- recommended to set the <option>AcceptFileDescriptors=</option>
- setting in the <filename>.busname</filename> unit file to the same
- setting as negotiated by the program ultimately activated. By
- default, file descriptor passing is enabled for both.</para>
-
- <para><function>sd_bus_negotiate_timestamps()</function> controls
- whether implicit sender timestamps shall be attached automatically
- to all incoming messages. Takes a bus object and a boolean, which,
- when true, enables timestamping, and, when false, disables it.
- Use
+ <para><function>sd_bus_negotiate_timestamp()</function> controls whether implicit sender
+ timestamps shall be attached automatically to all incoming messages. Takes a bus object and a
+ boolean, which, when true, enables timestamping, and, when false, disables it. Use
<citerefentry><refentrytitle>sd_bus_message_get_monotonic_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_get_realtime_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_get_seqnum</refentrytitle><manvolnum>3</manvolnum></citerefentry>
@@ -171,15 +139,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para><function>sd_bus_negotiate_fds()</function> and the other
- functions described here are available as a shared library, which
- can be compiled and linked to with the
- <constant>libelogind</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
@@ -192,8 +152,7 @@
<citerefentry><refentrytitle>sd_bus_message_get_monotonic_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_get_realtime_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_get_seqnum</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_message_get_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>elogind.busname</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>sd_bus_message_get_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/sd_bus_new.xml b/man/sd_bus_new.xml
index 6be915ac9..938228018 100644
--- a/man/sd_bus_new.xml
+++ b/man/sd_bus_new.xml
@@ -3,38 +3,14 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
-<refentry id="sd_bus_new">
+<refentry id="sd_bus_new" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_new</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>A monkey with a typewriter</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -163,15 +139,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para><function>sd_bus_new()</function> and other functions
- described here are available as a shared library, which can be
- compiled and linked to with the
- <constant>libelogind</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_path_encode.xml b/man/sd_bus_path_encode.xml
index 3fbb37cea..d0a16ebfc 100644
--- a/man/sd_bus_path_encode.xml
+++ b/man/sd_bus_path_encode.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_bus_path_encode">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd_bus_path_encode</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>A monkey with a typewriter</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -66,7 +42,7 @@
<funcdef>int <function>sd_bus_path_encode_many</function></funcdef>
<paramdef>char **<parameter>out</parameter></paramdef>
<paramdef>const char *<parameter>path_template</parameter></paramdef>
- <paramdef>...</paramdef>
+ <paramdef>…</paramdef>
</funcprototype>
<funcprototype>
@@ -80,7 +56,7 @@
<funcdef>int <function>sd_bus_path_decode_many</function></funcdef>
<paramdef>const char *<parameter>path</parameter></paramdef>
<paramdef>const char *<parameter>path_template</parameter></paramdef>
- <paramdef>...</paramdef>
+ <paramdef>…</paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
@@ -179,7 +155,11 @@
<title>See Also</title>
<para>
+ <!-- 0 /// elogind is in section 8
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ --><!-- else -->
<citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <!-- // 0 -->
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
diff --git a/man/sd_bus_process.xml b/man/sd_bus_process.xml
index 2b7b47766..2f2075197 100644
--- a/man/sd_bus_process.xml
+++ b/man/sd_bus_process.xml
@@ -3,22 +3,9 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
+ SPDX-License-Identifier: LGPL-2.1+
- Copyright 2016 Julian Orth
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2016 Julian Orth
-->
<refentry id="sd_bus_process">
@@ -26,14 +13,6 @@
<refentryinfo>
<title>sd_bus_process</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <firstname>Julian</firstname>
- <surname>Orth</surname>
- <email>ju.orth@gmail.com</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_bus_request_name.xml b/man/sd_bus_request_name.xml
index d627eded1..ec71f610b 100644
--- a/man/sd_bus_request_name.xml
+++ b/man/sd_bus_request_name.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2013 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_bus_request_name">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd_bus_request_name</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -44,7 +20,9 @@
<refnamediv>
<refname>sd_bus_request_name</refname>
+ <refname>sd_bus_request_name_async</refname>
<refname>sd_bus_release_name</refname>
+ <refname>sd_bus_release_name_async</refname>
<refpurpose>Request or release a well-known service name on a bus</refpurpose>
</refnamediv>
@@ -60,70 +38,102 @@
</funcprototype>
<funcprototype>
+ <funcdef>int <function>sd_bus_request_name_async</function></funcdef>
+ <paramdef>sd_bus *<parameter>bus</parameter></paramdef>
+ <paramdef>sd_bus_slot **<parameter>slot</parameter></paramdef>
+ <paramdef>const char *<parameter>name</parameter></paramdef>
+ <paramdef>uint64_t <parameter>flags</parameter></paramdef>
+ <paramdef>sd_bus_message_handler_t <parameter>callback</parameter></paramdef>
+ <paramdef>void *<parameter>userdata</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
<funcdef>int <function>sd_bus_release_name</function></funcdef>
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
<paramdef>const char *<parameter>name</parameter></paramdef>
</funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_release_name_async</function></funcdef>
+ <paramdef>sd_bus *<parameter>bus</parameter></paramdef>
+ <paramdef>sd_bus_slot **<parameter>slot</parameter></paramdef>
+ <paramdef>const char *<parameter>name</parameter></paramdef>
+ <paramdef>sd_bus_message_handler_t <parameter>callback</parameter></paramdef>
+ <paramdef>void *<parameter>userdata</parameter></paramdef>
+ </funcprototype>
</funcsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
- <para><function>sd_bus_request_name()</function> requests a
- well-known service name on a bus. It takes a bus connection, a
- valid bus name and a flags parameter. The flags parameter is a
- combination of the following flags:</para>
+ <para><function>sd_bus_request_name()</function> requests a well-known service name on a bus. It takes a bus
+ connection, a valid bus name and a flags parameter. The flags parameter is a combination of the following
+ flags:</para>
<variablelist>
<varlistentry>
<term><varname>SD_BUS_NAME_ALLOW_REPLACEMENT</varname></term>
- <listitem><para>After acquiring the name successfully, permit
- other peers to take over the name when they try to acquire it
- with the <varname>SD_BUS_NAME_REPLACE_EXISTING</varname> flag
- set. If <varname>SD_BUS_NAME_ALLOW_REPLACEMENT</varname> is
- not set on the original request, such a request by other peers
- will be denied.</para></listitem>
+ <listitem><para>After acquiring the name successfully, permit other peers to take over the name when they try
+ to acquire it with the <varname>SD_BUS_NAME_REPLACE_EXISTING</varname> flag set. If
+ <varname>SD_BUS_NAME_ALLOW_REPLACEMENT</varname> is not set on the original request, such a request by other
+ peers will be denied.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>SD_BUS_NAME_REPLACE_EXISTING</varname></term>
- <listitem><para>Take over the name if it is already acquired
- by another peer, and that other peer has permitted takeover by
- setting <varname>SD_BUS_NAME_ALLOW_REPLACEMENT</varname> while
- acquiring it.</para></listitem>
+ <listitem><para>Take over the name if it is already acquired by another peer, and that other peer has permitted
+ takeover by setting <varname>SD_BUS_NAME_ALLOW_REPLACEMENT</varname> while acquiring it.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>SD_BUS_NAME_QUEUE</varname></term>
- <listitem><para>Queue the acquisition of the name when the
- name is already taken.</para></listitem>
+ <listitem><para>Queue the acquisition of the name when the name is already taken.</para></listitem>
</varlistentry>
</variablelist>
- <para><function>sd_bus_release_name()</function> releases an
- acquired well-known name. It takes a bus connection and a valid
- bus name as parameters.</para>
+ <para><function>sd_bus_request_name()</function> operates in a synchronous fashion: a message requesting the name
+ is sent to the bus broker, and the call waits until the broker responds.</para>
+
+ <para><function>sd_bus_request_name_async()</function> is an asynchronous version of
+ <function>sd_bus_release_name()</function>. Instead of waiting for the request to complete, the request message is
+ enqueued. The specified <parameter>callback</parameter> will be called when the broker's response is received. If
+ the parameter is specified as <constant>NULL</constant> a default implementation is used instead which will
+ terminate the connection when the name cannot be acquired. The function returns a slot object in its
+ <parameter>slot</parameter> parameter — if it is passed as non-<constant>NULL</constant> — which may be used as a
+ reference to the name request operation. Use
+ <citerefentry><refentrytitle>sd_bus_slot_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry> to destroy
+ this reference. Note that destroying the reference will not unregister the name, but simply ensure the specified
+ callback is no longer called.</para>
+
+ <para><function>sd_bus_release_name()</function> releases an acquired well-known name. It takes a bus connection
+ and a valid bus name as parameters. This function operates synchronously, sending a release request message to the
+ bus broker and waiting for it to reply.</para>
+
+ <para><function>sd_bus_release_name_async()</function> is an asynchronous version of
+ <function>sd_bus_release_name()</function>. The specified <parameter>callback</parameter> function is called when
+ the name has been released successfully. If specified as <constant>NULL</constant> a generic implementation is used
+ that ignores the result of the operation. As above, the <parameter>slot</parameter> (if
+ non-<constant>NULL</constant>) is set to an object that may be used to reference the operation.</para>
+
+ <para>These functions are supported only on bus connections, i.e. connections to a bus broker and not on direct
+ connections.</para>
</refsect1>
<refsect1>
<title>Return Value</title>
- <para>On success, these calls return 0 or a positive integer. On
- failure, these calls return a negative errno-style error
- code.</para>
-
- <para>If <varname>SD_BUS_NAME_QUEUE</varname> is specified,
- <function>sd_bus_request_name()</function> will return 0 when the
- name is already taken by another peer and the client has been
- added to the queue for the name. In that case, the caller can
- subscribe to <literal>NameOwnerChanged</literal> signals to be
- notified when the name is successfully acquired.
- <function>sd_bus_request_name()</function> returns &gt; 0 when the
- name has immediately been acquired successfully.</para>
+ <para>On success, these calls return 0 or a positive integer. On failure, these calls return a negative errno-style
+ error code.</para>
+
+ <para>If <varname>SD_BUS_NAME_QUEUE</varname> is specified, <function>sd_bus_request_name()</function> will return
+ 0 when the name is already taken by another peer and the client has been added to the queue for the name. In that
+ case, the caller can subscribe to <literal>NameOwnerChanged</literal> signals to be notified when the name is
+ successfully acquired. <function>sd_bus_request_name()</function> returns &gt; 0 when the name has immediately
+ been acquired successfully.</para>
</refsect1>
<refsect1>
@@ -135,56 +145,50 @@
<varlistentry>
<term><constant>-EALREADY</constant></term>
- <listitem><para>The caller already is the owner of the
- specified name.</para></listitem>
+ <listitem><para>The caller already is the owner of the specified name.</para></listitem>
</varlistentry>
<varlistentry>
<term><constant>-EEXIST</constant></term>
- <listitem><para>The name has already been acquired by a
- different peer, and SD_BUS_NAME_REPLACE_EXISTING was not
- specified or the other peer did not specify
- SD_BUS_NAME_ALLOW_REPLACEMENT while acquiring the
+ <listitem><para>The name has already been acquired by a different peer, and SD_BUS_NAME_REPLACE_EXISTING was
+ not specified or the other peer did not specify SD_BUS_NAME_ALLOW_REPLACEMENT while acquiring the
name.</para></listitem>
</varlistentry>
<varlistentry>
<term><constant>-ESRCH</constant></term>
- <listitem><para>It was attempted to release a name that is
- currently not registered on the bus.</para></listitem>
+ <listitem><para>It was attempted to release a name that is currently not registered on the
+ bus.</para></listitem>
</varlistentry>
<varlistentry>
<term><constant>-EADDRINUSE</constant></term>
- <listitem><para>It was attempted to release a name that is
- owned by a different peer on the bus.</para></listitem>
+ <listitem><para>It was attempted to release a name that is owned by a different peer on the
+ bus.</para></listitem>
</varlistentry>
<varlistentry>
<term><constant>-EINVAL</constant></term>
- <listitem><para>A specified parameter is invalid. This is also
- generated when the requested name is a special service name
- reserved by the D-Bus specification, or when the operation is
- requested on a connection that does not refer to a
- bus.</para></listitem>
+ <listitem><para>A specified parameter is invalid. This is also generated when the requested name is a special
+ service name reserved by the D-Bus specification, or when the operation is requested on a connection that does
+ not refer to a bus.</para></listitem>
</varlistentry>
<varlistentry>
<term><constant>-ENOTCONN</constant></term>
- <listitem><para>The bus connection has been
- disconnected.</para></listitem>
+ <listitem><para>The bus connection has been disconnected.</para></listitem>
</varlistentry>
<varlistentry>
<term><constant>-ECHILD</constant></term>
- <listitem><para>The bus connection has been created in a
- different process than the current one.</para></listitem>
+ <listitem><para>The bus connection has been created in a different process than the current
+ one.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
@@ -192,12 +196,9 @@
<refsect1>
<title>Notes</title>
- <para>The <function>sd_bus_acquire_name()</function> and
- <function>sd_bus_release_name()</function> interfaces are
- available as a shared library, which can be compiled and linked to
- with the
- <constant>libelogind</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
+ <para>The <function>sd_bus_acquire_name()</function> and the other interfaces described here are available as a
+ shared library, which can be compiled and linked to with the <constant>libelogind</constant> <citerefentry
+ project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry> file.</para>
</refsect1>
<refsect1>
@@ -206,7 +207,8 @@
<para>
<citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>sd_bus_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_slot_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/sd_bus_set_connected_signal.xml b/man/sd_bus_set_connected_signal.xml
new file mode 100644
index 000000000..a439c2e60
--- /dev/null
+++ b/man/sd_bus_set_connected_signal.xml
@@ -0,0 +1,117 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ SPDX-License-Identifier: LGPL-2.1+
+-->
+
+<refentry id="sd_bus_set_connected_signal">
+
+ <refentryinfo>
+ <title>sd_bus_set_connected_signal</title>
+ <productname>elogind</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_bus_set_connected_signal</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_bus_set_connected_signal</refname>
+ <refname>sd_bus_get_connected_signal</refname>
+
+ <refpurpose>Control emmission of local connection establishment signal on bus connections</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include &lt;elogind/sd-bus.h&gt;</funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_set_connected_signal</function></funcdef>
+ <paramdef>sd_bus *<parameter>bus</parameter></paramdef>
+ <paramdef>int <parameter>b</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_get_connected_signal</function></funcdef>
+ <paramdef>sd_bus *<parameter>bus</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_bus_set_connected_signal()</function> may be used to control whether a local, synthetic
+ <function>Connected()</function> signal message shall be generated and enqueued for dispatching when the connection
+ is fully established. If the <parameter>b</parameter> parameter is zero the message is not generated (the default),
+ otherwise it is generated.</para>
+
+ <para><function>sd_bus_get_connected_signal()</function> may be used to query whether this feature is enabled. It
+ returns zero if not, positive otherwise.</para>
+
+ <para>The <function>Connected()</function> signal message is generated from the
+ <literal>org.freedesktop.DBus.Local</literal> service and interface, and
+ <literal>/org/freedesktop/DBus/Local</literal> object path. Use
+ <citerefentry><refentrytitle>sd_bus_match_signal_async</refentrytitle><manvolnum>3</manvolnum></citerefentry> to
+ match on this signal.</para>
+
+ <para>This message is particularly useful on slow transports where connections take a long time to be
+ established. This is especially the case when
+ <citerefentry><refentrytitle>sd_bus_set_watch_bind</refentrytitle><manvolnum>3</manvolnum></citerefentry> is
+ used. The signal is generated when the
+ <citerefentry><refentrytitle>sd_bus_is_ready</refentrytitle><manvolnum>3</manvolnum></citerefentry> returns
+ positive for the first time.</para>
+
+ <para>The <function>Connected()</function> signal corresponds with the <function>Disconnected()</function> signal
+ that is synthesized locally when the connection is terminated. The latter is generated unconditionally however,
+ unlike the former which needs to be enabled explicitly before it is generated, with
+ <function>sd_bus_set_connected_signal()</function>.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success, these functions return 0 or a positive integer. On failure, they return a negative errno-style
+ error code.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>-ECHILD</constant></term>
+
+ <listitem><para>The bus connection has been created in a different process.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Notes</title>
+
+ <para><function>sd_bus_set_connected_signal()</function> and <function>sd_bus_get_connected_signal()</function> are available as
+ a shared library, which can be compiled and linked to with the <constant>libelogind</constant> <citerefentry
+ project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry> file.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_match_signal_async</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_set_watch_bind</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_is_ready</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/sd_bus_set_sender.xml b/man/sd_bus_set_sender.xml
new file mode 100644
index 000000000..463f17bae
--- /dev/null
+++ b/man/sd_bus_set_sender.xml
@@ -0,0 +1,110 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ SPDX-License-Identifier: LGPL-2.1+
+-->
+
+<refentry id="sd_bus_set_sender">
+
+ <refentryinfo>
+ <title>sd_bus_set_sender</title>
+ <productname>elogind</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_bus_set_sender</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_bus_set_sender</refname>
+ <refname>sd_bus_get_sender</refname>
+
+ <refpurpose>Configure default sender for outgoing messages</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include &lt;elogind/sd-bus.h&gt;</funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_set_sender</function></funcdef>
+ <paramdef>sd_bus *<parameter>bus</parameter></paramdef>
+ <paramdef>const char* <parameter>name</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_get_sender</function></funcdef>
+ <paramdef>sd_bus *<parameter>bus</parameter></paramdef>
+ <paramdef>const char** <parameter>name</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_bus_set_sender()</function> configures the default sender service name to use for outgoing
+ messages. The service name specified in the <parameter>name</parameter> parameter is set on all outgoing messages
+ that are sent on the connection and have no sender set yet, for example through
+ <citerefentry><refentrytitle>sd_bus_message_set_sender</refentrytitle><manvolnum>3</manvolnum></citerefentry>. Note
+ that this function is only supported on direct connections, i.e. not on connections to a bus broker as the broker
+ will fill in the sender service name automatically anyway. By default no sender name is configured, and hence
+ messages are sent without sender field set. If the <parameter>name</parameter> parameter is specified as
+ <constant>NULL</constant> the default sender service name is cleared, returning to the default state if a default
+ sender service name was set before. If passed as non-<constant>NULL</constant> the specified name must be a valid
+ unique or well-known service name.</para>
+
+ <para><function>sd_bus_get_sender()</function> may be used to query the current default service name for outgoing
+ messages.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success, these functions return 0 or a positive integer. On failure, they return a negative errno-style
+ error code.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>-ECHILD</constant></term>
+
+ <listitem><para>The bus connection has been created in a different process.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-EPERM</constant></term>
+
+ <listitem><para>The specified bus connection object is a not a direct but a brokered connection.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Notes</title>
+
+ <para><function>sd_bus_set_sender()</function> and <function>sd_bus_get_sender()</function> are available as
+ a shared library, which can be compiled and linked to with the <constant>libelogind</constant> <citerefentry
+ project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry> file.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_message_set_sender</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/sd_bus_set_watch_bind.xml b/man/sd_bus_set_watch_bind.xml
new file mode 100644
index 000000000..927ed88f4
--- /dev/null
+++ b/man/sd_bus_set_watch_bind.xml
@@ -0,0 +1,126 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ SPDX-License-Identifier: LGPL-2.1+
+-->
+
+<refentry id="sd_bus_set_watch_bind">
+
+ <refentryinfo>
+ <title>sd_bus_set_watch_bind</title>
+ <productname>elogind</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_bus_set_watch_bind</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_bus_set_watch_bind</refname>
+ <refname>sd_bus_get_watch_bind</refname>
+
+ <refpurpose>Control socket binding watching on bus connections</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include &lt;elogind/sd-bus.h&gt;</funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_set_watch_bind</function></funcdef>
+ <paramdef>sd_bus *<parameter>bus</parameter></paramdef>
+ <paramdef>int <parameter>b</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_get_watch_bind</function></funcdef>
+ <paramdef>sd_bus *<parameter>bus</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_bus_set_watch_bind()</function> may be used to enable or disable client-side watching of server
+ socket binding for a bus connection object. If the <parameter>b</parameter> is true, the feature is enabled,
+ otherwise disabled (which is the default). When enabled, and the selected bus address refers to an
+ <filename>AF_UNIX</filename> socket in the file system which does not exist while the connection attempt is made an
+ <citerefentry><refentrytitle>inotify</refentrytitle><manvolnum>7</manvolnum></citerefentry> watch is installed on
+ it, waiting for the socket to appear. As soon as the socket appears the connection is made. This functionality is
+ useful in particular in early-boot programs that need to run before the system bus is available, but want to
+ connect to it the instant it may be connected to.</para>
+
+ <para><function>sd_bus_get_watch_bind()</function> may be used to query the current setting of this feature. It
+ returns zero when the feature is disabled, and positive if enabled.</para>
+
+ <para>Note that no timeout is applied while it is waited for the socket to appear. This means that any synchronous
+ remote operation (such as
+ <citerefentry><refentrytitle>sd_bus_call</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry> or
+ <citerefentry><refentrytitle>sd_bus_request_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>), that is
+ used on a connection with this feature enabled that is not established yet might block unbounded if the socket is
+ never created. However, asynchronous remote operations (such as
+ <citerefentry><refentrytitle>sd_bus_send</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_add_match_async</refentrytitle><manvolnum>3</manvolnum></citerefentry> or
+ <citerefentry><refentrytitle>sd_bus_request_match_async</refentrytitle><manvolnum>3</manvolnum></citerefentry>) do
+ not block in this case, and safely enqueue the requested operations to be dispatched the instant the connection is
+ set up.</para>
+
+ <para>Use <citerefentry><refentrytitle>sd_bus_is_ready</refentrytitle><manvolnum>3</manvolnum></citerefentry> to
+ determine whether the connection is fully established, i.e. whether the peer socket has been bound, connected to
+ and authenticated. Use
+ <citerefentry><refentrytitle>sd_bus_set_connected_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry> to
+ be notified when the connection is fully established.</para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success, these functions return 0 or a positive integer. On failure, they return a negative errno-style
+ error code.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>-ECHILD</constant></term>
+
+ <listitem><para>The bus connection has been created in a different process.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Notes</title>
+
+ <para><function>sd_bus_set_watch_bind()</function> and <function>sd_bus_get_watch_bind()</function> are available as
+ a shared library, which can be compiled and linked to with the <constant>libelogind</constant> <citerefentry
+ project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry> file.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>inotify</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_call</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_request_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_is_ready</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_set_connected_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/sd_bus_slot_set_destroy_callback.xml b/man/sd_bus_slot_set_destroy_callback.xml
new file mode 100644
index 000000000..c1ce4b92c
--- /dev/null
+++ b/man/sd_bus_slot_set_destroy_callback.xml
@@ -0,0 +1,131 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!-- SPDX-License-Identifier: LGPL-2.1+ -->
+
+<refentry id="sd_bus_slot_set_destroy_callback"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd_bus_slot_set_destroy_callback</title>
+ <productname>elogind</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_bus_slot_set_destroy_callback</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_bus_slot_set_destroy_callback</refname>
+ <refname>sd_bus_slot_get_destroy_callback</refname>
+ <refname>sd_bus_track_set_destroy_callback</refname>
+ <refname>sd_bus_track_get_destroy_callback</refname>
+ <refname>sd_bus_destroy_t</refname>
+
+ <refpurpose>Define the callback function for resource cleanup.</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include &lt;elogind/sd-bus.h&gt;</funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>typedef int (*<function>sd_bus_destroy_t</function>)</funcdef>
+ <paramdef>void *<parameter>userdata</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_slot_set_destroy_callback</function></funcdef>
+ <paramdef>sd_bus_slot *<parameter>slot</parameter></paramdef>
+ <paramdef>sd_bus_destroy_t <parameter>callback</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_slot_get_destroy_callback</function></funcdef>
+ <paramdef>sd_bus_slot *<parameter>slot</parameter></paramdef>
+ <paramdef>sd_bus_destroy_t *<parameter>callback</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_track_set_destroy_callback</function></funcdef>
+ <paramdef>sd_bus_track *<parameter>track</parameter></paramdef>
+ <paramdef>sd_bus_destroy_t <parameter>callback</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_track_get_destroy_callback</function></funcdef>
+ <paramdef>sd_bus_track *<parameter>track</parameter></paramdef>
+ <paramdef>sd_bus_destroy_t *<parameter>callback</parameter></paramdef>
+ </funcprototype>
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_bus_slot_set_destroy_callback()</function> sets <parameter>callback</parameter> as the callback
+ function to be called right before the bus slot object <parameter>slot</parameter> is deallocated. The
+ <parameter>userdata</parameter> pointer from the slot object will be passed as the <parameter>userdata</parameter>
+ parameter. This pointer can be set by an argument to the constructor functions, see
+ <citerefentry><refentrytitle>sd_bus_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>, or directly,
+ see <citerefentry><refentrytitle>sd_bus_slot_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+ This callback function is called even if <parameter>userdata</parameter> is <constant>NULL</constant>. Note that
+ this callback is invoked at a time where the bus slot object itself is already invalidated, and executing
+ operations or taking new references to the bus slot object is not permissible.</para>
+
+ <para><function>sd_bus_slot_get_destroy_callback()</function> returns the current callback
+ for <parameter>slot</parameter> in the <parameter>callback</parameter> parameter.</para>
+
+ <para><function>sd_bus_track_set_destroy_callback()</function> and
+ <function>sd_bus_track_get_destroy_callback</function> provide equivalent functionality for the
+ <parameter>userdata</parameter> pointer associated with bus peer tracking objects. For details about bus peer
+ tracking objects, see
+ <citerefentry><refentrytitle>sd_bus_track_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success, <function>sd_bus_slot_set_destroy_callback()</function> and
+ <function>sd_bus_track_set_destroy_callback()</function> return 0 or a positive integer. On failure, they return a
+ negative errno-style error code.</para>
+
+ <para><function>sd_bus_slot_get_destroy_callback()</function> and
+ <function>sd_bus_track_get_destroy_callback</function> return positive if the destroy callback function is set, 0
+ if not. On failure, they return a negative errno-style error code.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>-EINVAL</constant></term>
+
+ <listitem><para>The <parameter>slot</parameter> or <parameter>track</parameter> parameter is
+ <constant>NULL</constant>.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <xi:include href="libelogind-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_slot_set_floating</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_track_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_slot_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_track_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/sd_bus_slot_set_floating.xml b/man/sd_bus_slot_set_floating.xml
new file mode 100644
index 000000000..a2a134e9f
--- /dev/null
+++ b/man/sd_bus_slot_set_floating.xml
@@ -0,0 +1,118 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!-- SPDX-License-Identifier: LGPL-2.1+ -->
+
+<refentry id="sd_bus_slot_set_floating" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd_bus_slot_set_floating</title>
+ <productname>elogind</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_bus_slot_set_floating</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_bus_slot_set_floating</refname>
+ <refname>sd_bus_slot_get_floating</refname>
+
+ <refpurpose>Control whether a bus slot object is "floating".</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include &lt;elogind/sd-bus.h&gt;</funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_slot_set_floating</function></funcdef>
+ <paramdef>sd_bus_slot *<parameter>slot</parameter></paramdef>
+ <paramdef>int <parameter>b</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_slot_get_floating</function></funcdef>
+ <paramdef>sd_bus_slot *<parameter>slot</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_bus_slot_set_floating()</function> controls whether the specified bus slot object
+ <parameter>slot</parameter> shall be "floating" or not. A floating bus slot object's lifetime is bound to the
+ lifetime of the bus object it is associated with, meaning that it remains allocated as long as the bus object
+ itself and is freed automatically when the bus object is freed. Regular (i.e. non-floating) bus slot objects keep
+ the bus referenced, hence the bus object remains allocated at least as long as there remains at least one
+ referenced bus slot object around. The floating state hence controls the direction of referencing between the bus
+ object and the bus slot objects: if floating the bus pins the bus slot, and otherwise the bus slot pins the bus
+ objects. Use <function>sd_bus_slot_set_floating()</function> to switch between both modes: if the
+ <parameter>b</parameter> parameter is zero, the slot object is considered floating, otherwise it is made a regular
+ (non-floating) slot object.</para>
+
+ <para>Bus slot objects may be allocated with calls such as
+ <citerefentry><refentrytitle>sd_bus_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>. If the
+ <parameter>slot</parameter> of these functions is non-<constant>NULL</constant> the slot object will be of the
+ regular kind (i.e. non-floating), otherwise it will be created floating. With
+ <function>sd_bus_slot_set_floating()</function> a bus slot object allocated as regular can be converted into a
+ floating object and back. This is particularly useful for creating a bus slot object, then changing parameters of
+ it, and then turning it into a floating object, whose lifecycle is managed by the bus object.</para>
+
+ <para><function>sd_bus_slot_get_floating()</function> returns the current floating state of the specified bus slot
+ object. It returns negative on error, zero if the bus slot object is a regular (non-floating) object and positive
+ otherwise.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success, these functions return 0 or a positive integer. On failure, they return a negative errno-style
+ error code.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>-EINVAL</constant></term>
+
+ <listitem><para>The <parameter>slot</parameter> parameter is <constant>NULL</constant>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ECHILD</constant></term>
+
+ <listitem><para>The bus connection has been created in a different process.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ESTALE</constant></term>
+
+ <listitem><para>The bus object the specified bus slot object is associated with has already been freed, and
+ hence no change in the floating state can be made anymore.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <xi:include href="libelogind-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_slot_set_destroy_callback</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/sd_bus_track_add_name.xml b/man/sd_bus_track_add_name.xml
index 8496ee881..e40bb0063 100644
--- a/man/sd_bus_track_add_name.xml
+++ b/man/sd_bus_track_add_name.xml
@@ -3,38 +3,14 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2016 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
-<refentry id="sd_bus_track_add_name">
+<refentry id="sd_bus_track_add_name" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_track_add_name</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -240,13 +216,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para><function>sd_bus_track_add_name()</function> and the other calls described here are available as a shared library,
- which can be compiled and linked to with the <constant>libelogind</constant> <citerefentry
- project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry> file.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_bus_track_new.xml b/man/sd_bus_track_new.xml
index e8a252125..c290fb32b 100644
--- a/man/sd_bus_track_new.xml
+++ b/man/sd_bus_track_new.xml
@@ -3,38 +3,14 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2016 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
-<refentry id="sd_bus_track_new">
+<refentry id="sd_bus_track_new" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_track_new</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -242,13 +218,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para><function>sd_bus_track_new()</function> and the other calls described here are available as a shared library,
- which can be compiled and linked to with the <constant>libelogind</constant> <citerefentry
- project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry> file.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_event_add_child.xml b/man/sd_event_add_child.xml
index 9925cec33..447e797db 100644
--- a/man/sd_event_add_child.xml
+++ b/man/sd_event_add_child.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_event_add_child" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd_event_add_child</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>More text</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -234,6 +210,7 @@
<citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
diff --git a/man/sd_event_add_defer.xml b/man/sd_event_add_defer.xml
index dd88b0982..326579691 100644
--- a/man/sd_event_add_defer.xml
+++ b/man/sd_event_add_defer.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_event_add_defer" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -26,16 +11,7 @@
<refentryinfo>
<title>sd_event_add_defer</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>More text</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
- </refentryinfo>
+ </refentryinfo>
<refmeta>
<refentrytitle>sd_event_add_defer</refentrytitle>
@@ -205,6 +181,7 @@
<citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
diff --git a/man/sd_event_add_inotify.xml b/man/sd_event_add_inotify.xml
new file mode 100644
index 000000000..b28847f92
--- /dev/null
+++ b/man/sd_event_add_inotify.xml
@@ -0,0 +1,193 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!-- SPDX-License-Identifier: LGPL-2.1+ -->
+
+<refentry id="sd_event_add_inotify" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd_event_add_inotify</title>
+ <productname>elogind</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_event_add_inotify</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_event_add_inotify</refname>
+ <refname>sd_event_source_get_inotify_mask</refname>
+ <refname>sd_event_inotify_handler_t</refname>
+
+ <refpurpose>Add an "inotify" file system inode event source to an event loop</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include &lt;elogind/sd-event.h&gt;</funcsynopsisinfo>
+
+ <funcsynopsisinfo><token>typedef</token> struct sd_event_source sd_event_source;</funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>typedef int (*<function>sd_event_inotify_handler_t</function>)</funcdef>
+ <paramdef>sd_event_source *<parameter>s</parameter></paramdef>
+ <paramdef>const struct inotify_event *<parameter>event</parameter></paramdef>
+ <paramdef>void *<parameter>userdata</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_add_inotify</function></funcdef>
+ <paramdef>sd_event *<parameter>event</parameter></paramdef>
+ <paramdef>sd_event_source **<parameter>source</parameter></paramdef>
+ <paramdef>const char *<parameter>path</parameter></paramdef>
+ <paramdef>uint32_t <parameter>mask</parameter></paramdef>
+ <paramdef>sd_event_inotify_handler_t <parameter>handler</parameter></paramdef>
+ <paramdef>void *<parameter>userdata</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_get_inotify_mask</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ <paramdef>uint32_t *<parameter>mask</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_event_add_inotify()</function> adds a new <citerefentry
+ project='man-pages'><refentrytitle>inotify</refentrytitle><manvolnum>7</manvolnum></citerefentry> file system inode
+ event source to an event loop. The event loop object is specified in the <parameter>event</parameter> parameter,
+ the event source object is returned in the <parameter>source</parameter> parameter. The <parameter>path</parameter>
+ parameter specifies the path of the file system inode to watch. The <parameter>handler</parameter> must reference a
+ function to call when the inode changes. The handler function will be passed the <parameter>userdata</parameter>
+ pointer, which may be chosen freely by the caller. The handler also receives a pointer to a <structname>struct
+ inotify_event</structname> structure containing information about the inode event. The <parameter>mask</parameter>
+ parameter specifie which types of inode events to watch specifically. It must contain an OR-ed combination of
+ <constant>IN_ACCESS</constant>, <constant>IN_ATTRIB</constant>, <constant>IN_CLOSE_WRITE</constant>, … flags. See
+ <citerefentry project='man-pages'><refentrytitle>inotify</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
+ further information.</para>
+
+ <para>If multiple event sources are installed for the same inode the backing inotify watch descriptor is
+ automatically shared. The mask parameter may contain any flag defined by the inotify API, with the exception of
+ <constant>IN_MASK_ADD</constant>.</para>
+
+ <para>The handler is enabled continuously (<constant>SD_EVENT_ON</constant>), but this may be changed with
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>. Alternatively,
+ the <constant>IN_ONESHOT</constant> mask flag may be used to request <constant>SD_EVENT_ONESHOT</constant> mode.
+ If the handler function returns a negative error code, it will be disabled after the invocation, even if the
+ <constant>SD_EVENT_ON</constant> mode was requested before.
+ </para>
+
+ <para>As a special limitation the priority of inotify event sources may only be altered (see
+ <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>)
+ in the time between creation of the event source object with <function>sd_event_add_inotify()</function> and the
+ beginning of the next event loop iteration. Attempts of changing the priority any later will be refused. Consider
+ freeing and allocating a new inotify event source to change the priority at that point.</para>
+
+ <para>To destroy an event source object use
+ <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>, but note
+ that the event source is only removed from the event loop when all references to the event source are dropped. To
+ make sure an event source does not fire anymore, even when there's still a reference to it kept, consider disabling
+ it with
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+
+ <para>If the second parameter of <function>sd_event_add_inotify()</function> is passed as NULL no reference to the
+ event source object is returned. In this case the event source is considered "floating", and will be destroyed
+ implicitly when the event loop itself is destroyed.</para>
+
+ <para><function>sd_event_source_get_inotify_mask()</function> retrieves the configured inotify watch mask of an
+ event source created previously with <function>sd_event_add_inotify()</function>. It takes the event source object
+ as the <parameter>source</parameter> parameter and a pointer to a <type>uint32_t</type> variable to return the mask
+ in.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success, these functions return 0 or a positive integer. On failure, they return a negative errno-style
+ error code.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>-ENOMEM</constant></term>
+
+ <listitem><para>Not enough memory to allocate an object.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-EINVAL</constant></term>
+
+ <listitem><para>An invalid argument has been passed. This includes specifying a mask with
+ <constant>IN_MASK_ADD</constant> set.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ESTALE</constant></term>
+
+ <listitem><para>The event loop is already terminated.</para></listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ECHILD</constant></term>
+
+ <listitem><para>The event loop has been created in a different process.</para></listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-EDOM</constant></term>
+
+ <listitem><para>The passed event source is not an inotify process event source.</para></listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <!-- 0 /// elogind has no inotify test program.
+ <refsect1>
+ <title>Examples</title>
+
+ <example>
+ <title>A simple program that uses inotify to monitor one or two directories</title>
+
+ <programlisting><xi:include href="inotify-watch-tmp.c" parse="text" /></programlisting>
+ </example>
+ </refsect1>
+ // 0 -->
+
+ <xi:include href="libelogind-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_now</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>waitid</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/sd_event_add_io.xml b/man/sd_event_add_io.xml
index 3ba7c3bd3..07a0591a4 100644
--- a/man/sd_event_add_io.xml
+++ b/man/sd_event_add_io.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2015 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_event_add_io" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd_event_add_io</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -49,6 +25,8 @@
<refname>sd_event_source_get_io_revents</refname>
<refname>sd_event_source_get_io_fd</refname>
<refname>sd_event_source_set_io_fd</refname>
+ <refname>sd_event_source_get_io_fd_own</refname>
+ <refname>sd_event_source_set_io_fd_own</refname>
<refname>sd_event_source</refname>
<refname>sd_event_io_handler_t</refname>
@@ -108,6 +86,17 @@
<paramdef>int <parameter>fd</parameter></paramdef>
</funcprototype>
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_get_io_fd_own</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_set_io_fd_own</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ <paramdef>int <parameter>b</parameter></paramdef>
+ </funcprototype>
+
</funcsynopsis>
</refsynopsisdiv>
@@ -223,6 +212,17 @@
changes the UNIX file descriptor of an I/O event source created
previously with <function>sd_event_add_io()</function>. It takes
the event source object and the new file descriptor.</para>
+
+ <para><function>sd_event_source_set_io_fd_own()</function> controls whether the file descriptor of the event source
+ shall be closed automatically when the event source is freed, i.e. whether it shall be considered 'owned' by the
+ event source object. By default it is not closed automatically, and the application has to do this on its own. The
+ <parameter>b</parameter> parameter is a boolean parameter: if zero, the file descriptor is not closed automatically
+ when the event source is freed, otherwise it is closed.</para>
+
+ <para><function>sd_event_source_get_io_fd_own()</function> may be used to query the current setting of the file
+ descriptor ownership boolean flag as set with <function>sd_event_source_set_io_fd_own()</function>. It returns
+ positive if the file descriptor is closed automatically when the event source is destroyed, zero if not, and
+ negative on error.</para>
</refsect1>
<refsect1>
@@ -279,7 +279,12 @@
<title>See Also</title>
<para>
+ <!-- 0 /// elogind is in section 8
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ --><!-- else -->
<citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <!-- // 0 -->
<citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_now</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
diff --git a/man/sd_event_add_signal.xml b/man/sd_event_add_signal.xml
index dec185a97..22c4399f8 100644
--- a/man/sd_event_add_signal.xml
+++ b/man/sd_event_add_signal.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_event_add_signal" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd_event_add_signal</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>More text</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -209,6 +185,7 @@
<citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
diff --git a/man/sd_event_add_time.xml b/man/sd_event_add_time.xml
index 426dff1c5..80d19f260 100644
--- a/man/sd_event_add_time.xml
+++ b/man/sd_event_add_time.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2014 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_event_add_time" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd_event_add_time</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -299,6 +275,7 @@
<citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_source_set_priority</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
diff --git a/man/sd_event_exit.xml b/man/sd_event_exit.xml
index 7ac12ae5b..91d0bbf09 100644
--- a/man/sd_event_exit.xml
+++ b/man/sd_event_exit.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2015 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_event_exit" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd_event_exit</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -153,7 +129,11 @@
<title>See Also</title>
<para>
+ <!-- 0 /// elogind is in section 8
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ --><!-- else -->
<citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <!-- // 0 -->
<citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>
diff --git a/man/sd_event_get_fd.xml b/man/sd_event_get_fd.xml
index 88671a2b9..61fb83ce6 100644
--- a/man/sd_event_get_fd.xml
+++ b/man/sd_event_get_fd.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_event_get_fd" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd_event_get_fd</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>More text</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_event_new.xml b/man/sd_event_new.xml
index 40a686b14..79449b938 100644
--- a/man/sd_event_new.xml
+++ b/man/sd_event_new.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2014 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_event_new" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd_event_new</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_event_now.xml b/man/sd_event_now.xml
index b419e7d82..c746a9ff8 100644
--- a/man/sd_event_now.xml
+++ b/man/sd_event_now.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2015 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_event_now" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd_event_now</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -135,7 +111,11 @@
<title>See Also</title>
<para>
+ <!-- 0 /// elogind is in section 8
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ --><!-- else -->
<citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <!-- // 0 -->
<citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
diff --git a/man/sd_event_run.xml b/man/sd_event_run.xml
index d37febef4..16b900250 100644
--- a/man/sd_event_run.xml
+++ b/man/sd_event_run.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2015 Zbigniew Jędrzejewski-Szmek
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_event_run" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd_event_run</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Tom</firstname>
- <surname>Gundersen</surname>
- <email>teg@jklm.no</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_event_set_watchdog.xml b/man/sd_event_set_watchdog.xml
index 230668c42..e1bca3815 100644
--- a/man/sd_event_set_watchdog.xml
+++ b/man/sd_event_set_watchdog.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2015 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_event_set_watchdog" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd_event_set_watchdog</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -158,7 +134,11 @@
<title>See Also</title>
<para>
+ <!-- 0 /// elogind is in section 8
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ --><!-- else -->
<citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <!-- // 0 -->
<citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
diff --git a/man/sd_event_source_get_event.xml b/man/sd_event_source_get_event.xml
index c9a52af68..33d0d481c 100644
--- a/man/sd_event_source_get_event.xml
+++ b/man/sd_event_source_get_event.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2015 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_event_source_get_event" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd_event_source_get_event</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_event_source_get_pending.xml b/man/sd_event_source_get_pending.xml
index ea3c21db8..f9043354a 100644
--- a/man/sd_event_source_get_pending.xml
+++ b/man/sd_event_source_get_pending.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2015 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_event_source_get_pending" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd_event_source_get_pending</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_event_source_set_description.xml b/man/sd_event_source_set_description.xml
index 9e8a1d6d9..c83396cca 100644
--- a/man/sd_event_source_set_description.xml
+++ b/man/sd_event_source_set_description.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_event_source_set_description" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd_event_source_set_description</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>More text</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_event_source_set_destroy_callback.xml b/man/sd_event_source_set_destroy_callback.xml
new file mode 100644
index 000000000..aa6d0e1b3
--- /dev/null
+++ b/man/sd_event_source_set_destroy_callback.xml
@@ -0,0 +1,112 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!-- SPDX-License-Identifier: LGPL-2.1+ -->
+
+<refentry id="sd_event_source_set_destroy_callback"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <refentryinfo>
+ <title>sd_event_source_set_destroy_callback</title>
+ <productname>elogind</productname>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_event_source_set_destroy_callback</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_event_source_set_destroy_callback</refname>
+ <refname>sd_event_source_get_destroy_callback</refname>
+ <refname>sd_event_destroy_t</refname>
+
+ <refpurpose>Define the callback function for resource cleanup.</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include &lt;elogind/sd-event.h&gt;</funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>typedef int (*<function>sd_event_destroy_t</function>)</funcdef>
+ <paramdef>void *<parameter>userdata</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_set_destroy_callback</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ <paramdef>sd_event_destroy_t <parameter>callback</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_event_source_get_destroy_callback</function></funcdef>
+ <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+ <paramdef>sd_event_destroy_t *<parameter>callback</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_event_source_set_destroy_callback()</function> sets <parameter>callback</parameter> as the
+ callback function to be called right before the event source object <parameter>source</parameter> is
+ deallocated. The <parameter>userdata</parameter> pointer from the event source object will be passed as the
+ <parameter>userdata</parameter> parameter. This pointer can be set by an argument to the constructor functions, see
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>, or directly,
+ see
+ <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+ This callback function is called even if <parameter>userdata</parameter> is <constant>NULL</constant>. Note that
+ this callback is invoked at a time where the event source object itself is already invalidated, and executing
+ operations or taking new references to the event source object is not permissible.</para>
+
+ <para><function>sd_event_source_get_destroy_callback()</function> returns the current callback
+ for <parameter>source</parameter> in the <parameter>callback</parameter> parameter.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success, <function>sd_event_source_set_destroy_callback()</function> returns 0 or a positive integer. On
+ failure, it returns a negative errno-style error code.</para>
+
+ <para><function>sd_event_source_get_destroy_callback()</function> returns positive if the destroy callback function
+ is set, 0 if not. On failure, returns a negative errno-style error code.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>-EINVAL</constant></term>
+
+ <listitem><para>The <parameter>source</parameter> parameter is <constant>NULL</constant>.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <xi:include href="libelogind-pkgconfig.xml" />
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_io</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_time</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_child</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_add_defer</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_event_source_set_userdata</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/sd_event_source_set_enabled.xml b/man/sd_event_source_set_enabled.xml
index dd7fa9932..ac6dcd74d 100644
--- a/man/sd_event_source_set_enabled.xml
+++ b/man/sd_event_source_set_enabled.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2015 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_event_source_set_enabled" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd_event_source_set_enabled</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_event_source_set_prepare.xml b/man/sd_event_source_set_prepare.xml
index f0c8e6c42..28bb3e874 100644
--- a/man/sd_event_source_set_prepare.xml
+++ b/man/sd_event_source_set_prepare.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2015 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_event_source_set_prepare" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd_event_source_set_prepare</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_event_source_set_priority.xml b/man/sd_event_source_set_priority.xml
index 3e325502e..faa9325b7 100644
--- a/man/sd_event_source_set_priority.xml
+++ b/man/sd_event_source_set_priority.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2015 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_event_source_set_priority" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd_event_source_set_priority</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -119,6 +95,12 @@
particular event sources do not starve or dominate the event
loop.</para>
+ <para>The priority of event sources may be changed at any time of their lifetime, with the exception of inotify
+ event sources (i.e. those created with
+ <citerefentry><refentrytitle>sd_event_add_inotify</refentrytitle><manvolnum>3</manvolnum></citerefentry>) whose
+ priority may only be changed in the time between their initial creation and the first subsequent event loop
+ iteration.</para>
+
<para><function>sd_event_source_get_priority()</function> may be
used to query the current priority assigned to the event source
object <parameter>source</parameter>.</para>
diff --git a/man/sd_event_source_set_userdata.xml b/man/sd_event_source_set_userdata.xml
index 697539662..5d66c0582 100644
--- a/man/sd_event_source_set_userdata.xml
+++ b/man/sd_event_source_set_userdata.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2015 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_event_source_set_userdata" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd_event_source_set_userdata</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_event_source_unref.xml b/man/sd_event_source_unref.xml
index 6bc122e1c..91bae59ab 100644
--- a/man/sd_event_source_unref.xml
+++ b/man/sd_event_source_unref.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2015 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_event_source_unref" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd_event_source_unref</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_event_wait.xml b/man/sd_event_wait.xml
index 5d675ecea..c8721777a 100644
--- a/man/sd_event_wait.xml
+++ b/man/sd_event_wait.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2015 Zbigniew Jędrzejewski-Szmek
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_event_wait" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -26,15 +11,6 @@
<refentryinfo>
<title>sd_event_wait</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Tom</firstname>
- <surname>Gundersen</surname>
- <email>teg@jklm.no</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_get_seats.xml b/man/sd_get_seats.xml
index 95e8b362b..05173b0b7 100644
--- a/man/sd_get_seats.xml
+++ b/man/sd_get_seats.xml
@@ -3,38 +3,15 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2010 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
-<refentry id="sd_get_seats" conditional='HAVE_PAM'>
+<refentry id="sd_get_seats" conditional='HAVE_PAM'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_get_seats</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -117,7 +94,6 @@
errno-style error code.</para>
</refsect1>
-
<refsect1>
<title>Errors</title>
@@ -133,24 +109,17 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_get_seats()</function>,
- <function>sd_get_sessions()</function>,
- <function>sd_get_uids()</function> and
- <function>sd_get_machine_names()</function> interfaces are
- available as a shared library, which can be compiled and linked to
- with the
- <constant>libelogind</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
<para>
+ <!-- 0 /// elogind is in section 8
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ --><!-- else -->
<citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <!-- // 0 -->
<citerefentry><refentrytitle>sd-login</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_session_get_seat</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
diff --git a/man/sd_id128_get_machine.xml b/man/sd_id128_get_machine.xml
index cc1f2b30c..8ed5dfcb1 100644
--- a/man/sd_id128_get_machine.xml
+++ b/man/sd_id128_get_machine.xml
@@ -3,38 +3,14 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2012 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
-<refentry id="sd_id128_get_machine">
+<refentry id="sd_id128_get_machine" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_id128_get_machine</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -127,20 +103,14 @@
<refsect1>
<title>Return Value</title>
- <para>The two calls return 0 on success (in which case
- <parameter>ret</parameter> is filled in), or a negative
- errno-style error code.</para>
+ <para>Those calls return 0 on success (in which case <parameter>ret</parameter> is filled in),
+ or a negative errno-style error code. In particular, <function>sd_id128_get_machine()</function>
+ and <function>sd_id128_get_machine_app_specific()</function> return <constant>-ENOENT</constant>
+ if <filename>/etc/machine-id</filename> is missing, and <constant>-ENOMEDIUM</constant> if is
+ empty or all zeros.</para>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_id128_get_machine()</function>, <function>sd_id128_get_machine_app_specific()</function>
- <function>sd_id128_get_boot()</function> and <function>sd_id128_get_invocation()</function> interfaces are
- available as a shared library, which can be compiled and linked to with the
- <literal>libelogind</literal> <citerefentry
- project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry> file.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>Examples</title>
diff --git a/man/sd_id128_randomize.xml b/man/sd_id128_randomize.xml
index f99d88e55..e968b199f 100644
--- a/man/sd_id128_randomize.xml
+++ b/man/sd_id128_randomize.xml
@@ -3,38 +3,14 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2012 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
-<refentry id="sd_id128_randomize">
+<refentry id="sd_id128_randomize" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_id128_randomize</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -76,8 +52,11 @@
type, see
<citerefentry><refentrytitle>sd-id128</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
- <para><option>--new-id</option> option may be used as a command line
+<!-- 0 /// elogind does not support journalctl
+ <para><citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
+ <option>&#x2D;&#x2D;new-id128</option> option may be used as a command line
front-end for <function>sd_id128_randomize()</function>.</para>
+// 0 -->
</refsect1>
<refsect1>
@@ -88,21 +67,17 @@
errno-style error code.</para>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_id128_randomize()</function> interface is
- available as a shared library, which can be compiled and linked to
- with the
- <literal>libelogind</literal> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
<para>
+ <!-- 0 /// elogind is in section 8
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ --><!-- else -->
<citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <!-- // 0 -->
<citerefentry><refentrytitle>sd-id128</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>random</refentrytitle><manvolnum>4</manvolnum></citerefentry>,
diff --git a/man/sd_id128_to_string.xml b/man/sd_id128_to_string.xml
index 11bee6919..02a3758c0 100644
--- a/man/sd_id128_to_string.xml
+++ b/man/sd_id128_to_string.xml
@@ -3,38 +3,14 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2012 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
-<refentry id="sd_id128_to_string">
+<refentry id="sd_id128_to_string" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_id128_to_string</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -106,22 +82,17 @@
errno-style error code.</para>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_id128_to_string()</function> and
- <function>sd_id128_from_string()</function> interfaces are
- available as a shared library, which can be compiled and linked to
- with the
- <literal>libelogind</literal> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
<para>
+ <!-- 0 /// elogind is in section 8
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ --><!-- else -->
<citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <!-- // 0 -->
<citerefentry><refentrytitle>sd-id128</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>printf</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
diff --git a/man/sd_is_fifo.xml b/man/sd_is_fifo.xml
index 3dac5a900..11021d541 100644
--- a/man/sd_is_fifo.xml
+++ b/man/sd_is_fifo.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2010 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_is_fifo"
@@ -27,15 +12,6 @@
<refentryinfo>
<title>sd_is_fifo</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -148,7 +124,7 @@
whether the specified file descriptor refers to a special file. If
the <parameter>path</parameter> parameter is not
<constant>NULL</constant>, it is checked whether the file
- descriptor is bound to the specified file name. Special files in
+ descriptor is bound to the specified filename. Special files in
this context are character device nodes and files in
<filename>/proc</filename> or <filename>/sys</filename>.</para>
</refsect1>
diff --git a/man/sd_listen_fds.xml b/man/sd_listen_fds.xml
index 0d3479efb..ba03836d0 100644
--- a/man/sd_listen_fds.xml
+++ b/man/sd_listen_fds.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- 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/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_listen_fds"
@@ -27,15 +12,6 @@
<refentryinfo>
<title>sd_listen_fds</title>
<productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/sd_login_monitor_new.xml b/man/sd_login_monitor_new.xml
index 0b5b474a5..8f9c218d2 100644
--- a/man/sd_login_monitor_new.xml
+++ b/man/sd_login_monitor_new.xml
@@ -3,38 +3,15 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2010 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
-<refentry id="sd_login_monitor_new" conditional='HAVE_PAM'>
+<refentry id="sd_login_monitor_new" conditional='HAVE_PAM'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_login_monitor_new</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -257,20 +234,7 @@ else {
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_login_monitor_new()</function>,
- <function>sd_login_monitor_unref()</function>,
- <function>sd_login_monitor_flush()</function>,
- <function>sd_login_monitor_get_fd()</function>,
- <function>sd_login_monitor_get_events()</function> and
- <function>sd_login_monitor_get_timeout()</function>
- interfaces are available as a shared library, which can be
- compiled and linked to with the
- <constant>libelogind</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
diff --git a/man/sd_machine_get_class.xml b/man/sd_machine_get_class.xml
index be872eac8..d848686b1 100644
--- a/man/sd_machine_get_class.xml
+++ b/man/sd_machine_get_class.xml
@@ -3,38 +3,14 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2014 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
-<refentry id="sd_machine_get_class">
+<refentry id="sd_machine_get_class" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_machine_get_class</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -127,24 +103,19 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_machine_get_class()</function> and
- <function>sd_machine_get_ifindices()</function> interfaces are
- available as a shared library, which can be compiled and linked to
- with the
- <constant>libelogind</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
<para>
+ <!-- 0 /// elogind is in section 8
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-machined.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ --><!-- else -->
<citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <!-- // 0 -->
<citerefentry><refentrytitle>sd-login</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>elogind-machined.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_pid_get_machine_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/sd_notify.xml b/man/sd_notify.xml
index a15426c1d..4efb2733c 100644
--- a/man/sd_notify.xml
+++ b/man/sd_notify.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2010 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_notify"
@@ -27,15 +12,6 @@
<refentryinfo>
<title>sd_notify</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -122,12 +98,10 @@
<varlistentry>
<term>READY=1</term>
- <listitem><para>Tells the service manager that service startup
- is finished. This is only used by elogind if the service
- definition file has Type=notify set. Since there is little
- value in signaling non-readiness, the only value services
- should send is <literal>READY=1</literal> (i.e.
- <literal>READY=0</literal> is not defined).</para></listitem>
+ <listitem><para>Tells the service manager that service startup is finished, or the service finished loading its
+ configuration. This is only used by elogind if the service definition file has <varname>Type=notify</varname>
+ set. Since there is little value in signaling non-readiness, the only value services should send is
+ <literal>READY=1</literal> (i.e. <literal>READY=0</literal> is not defined).</para></listitem>
</varlistentry>
<varlistentry>
@@ -139,7 +113,8 @@
present it to the user. Note that a service that sends this
notification must also send a <literal>READY=1</literal>
notification when it completed reloading its
- configuration.</para></listitem>
+ configuration. Reloads are propagated in the same way as they
+ are when initiated by the user.</para></listitem>
</varlistentry>
<varlistentry>
@@ -201,6 +176,26 @@
watchdog is enabled. </para></listitem>
</varlistentry>
+ <varlistentry>
+ <term>WATCHDOG_USEC=…</term>
+
+ <listitem><para>Reset <varname>watchdog_usec</varname> value during runtime.
+ Notice that this is not available when using <function>sd_event_set_watchdog()</function>
+ or <function>sd_watchdog_enabled()</function>.
+ Example : <literal>WATCHDOG_USEC=20000000</literal></para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>EXTEND_TIMEOUT_USEC=…</term>
+
+ <listitem><para>Tells the service manager to extend the startup, runtime or shutdown service timeout
+ corresponding the current state. The value specified is a time in microseconds during which the service must
+ send a new message. A service timeout will occur if the message isn't received, but only if the runtime of the
+ current state is beyond the original maximium times of <varname>TimeoutStartSec=</varname>, <varname>RuntimeMaxSec=</varname>,
+ and <varname>TimeoutStopSec=</varname>.
+ See <citerefentry><refentrytitle>elogind.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for effects on the service timeouts.</para></listitem>
+ </varlistentry>
<varlistentry>
<term>FDSTORE=1</term>
@@ -227,33 +222,25 @@
</varlistentry>
<varlistentry>
- <term>FDNAME=…</term>
+ <term>FDSTOREREMOVE=1</term>
- <listitem><para>When used in combination with
- <varname>FDSTORE=1</varname>, specifies a name for the
- submitted file descriptors. This name is passed to the service
- during activation, and may be queried using
- <citerefentry><refentrytitle>sd_listen_fds_with_names</refentrytitle><manvolnum>3</manvolnum></citerefentry>. File
- descriptors submitted without this field set, will implicitly
- get the name <literal>stored</literal> assigned. Note that, if
- multiple file descriptors are submitted at once, the specified
- name will be assigned to all of them. In order to assign
- different names to submitted file descriptors, submit them in
- separate invocations of
- <function>sd_pid_notify_with_fds()</function>. The name may
- consist of any ASCII character, but must not contain control
- characters or <literal>:</literal>. It may not be longer than
- 255 characters. If a submitted name does not follow these
- restrictions, it is ignored.</para></listitem>
+ <listitem><para>Removes file descriptors from the file descriptor store. This field needs to be combined with
+ <varname>FDNAME=</varname> to specify the name of the file descriptors to remove.</para></listitem>
</varlistentry>
<varlistentry>
- <term>WATCHDOG_USEC=…</term>
+ <term>FDNAME=…</term>
- <listitem><para>Reset <varname>watchdog_usec</varname> value during runtime.
- Notice that this is not available when using <function>sd_event_set_watchdog()</function>
- or <function>sd_watchdog_enabled()</function>.
- Example : <literal>WATCHDOG_USEC=20000000</literal></para></listitem>
+ <listitem><para>When used in combination with <varname>FDSTORE=1</varname>, specifies a name for the submitted
+ file descriptors. When used with <varname>FDSTOREREMOVE=1</varname>, specifies the name for the file
+ descriptors to remove. This name is passed to the service during activation, and may be queried using
+ <citerefentry><refentrytitle>sd_listen_fds_with_names</refentrytitle><manvolnum>3</manvolnum></citerefentry>. File
+ descriptors submitted without this field set, will implicitly get the name <literal>stored</literal>
+ assigned. Note that, if multiple file descriptors are submitted at once, the specified name will be assigned to
+ all of them. In order to assign different names to submitted file descriptors, submit them in separate
+ invocations of <function>sd_pid_notify_with_fds()</function>. The name may consist of arbitrary ASCII
+ characters except control characters or <literal>:</literal>. It may not be longer than 255 characters. If a
+ submitted name does not follow these restrictions, it is ignored.</para></listitem>
</varlistentry>
</variablelist>
diff --git a/man/sd_pid_get_session.xml b/man/sd_pid_get_owner_uid.xml
index f85b413f0..573e3fece 100644
--- a/man/sd_pid_get_session.xml
+++ b/man/sd_pid_get_owner_uid.xml
@@ -3,57 +3,38 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2010 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
-<refentry id="sd_pid_get_session" conditional='HAVE_PAM'>
+<refentry id="sd_pid_get_owner_uid" conditional='HAVE_PAM'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
- <title>sd_pid_get_session</title>
+ <title>sd_pid_get_owner_uid</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
- <refentrytitle>sd_pid_get_session</refentrytitle>
+ <refentrytitle>sd_pid_get_owner_uid</refentrytitle>
<manvolnum>3</manvolnum>
</refmeta>
<refnamediv>
- <refname>sd_pid_get_session</refname>
<refname>sd_pid_get_owner_uid</refname>
+ <refname>sd_pid_get_session</refname>
+ <refname>sd_pid_get_user_unit</refname>
+ <refname>sd_pid_get_unit</refname>
<refname>sd_pid_get_machine_name</refname>
<refname>sd_pid_get_cgroup</refname>
- <refname>sd_peer_get_session</refname>
<refname>sd_peer_get_owner_uid</refname>
+ <refname>sd_peer_get_session</refname>
+ <refname>sd_peer_get_user_unit</refname>
+ <refname>sd_peer_get_unit</refname>
<refname>sd_peer_get_machine_name</refname>
<refname>sd_peer_get_cgroup</refname>
- <refpurpose>Determine session, unit, owner of a session,
- container/VM or slice of a specific PID or socket
- peer</refpurpose>
+ <refpurpose>Determine the owner uid of the user unit or session,
+ or the session, user unit, system unit, container/VM or slice that
+ a specific PID or socket peer belongs to.</refpurpose>
</refnamediv>
<refsynopsisdiv>
@@ -61,15 +42,27 @@
<funcsynopsisinfo>#include &lt;elogind/sd-login.h&gt;</funcsynopsisinfo>
<funcprototype>
+ <funcdef>int <function>sd_pid_get_owner_uid</function></funcdef>
+ <paramdef>pid_t <parameter>pid</parameter></paramdef>
+ <paramdef>uid_t *<parameter>uid</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
<funcdef>int <function>sd_pid_get_session</function></funcdef>
<paramdef>pid_t <parameter>pid</parameter></paramdef>
<paramdef>char **<parameter>session</parameter></paramdef>
</funcprototype>
<funcprototype>
- <funcdef>int <function>sd_pid_get_owner_uid</function></funcdef>
+ <funcdef>int <function>sd_pid_get_user_unit</function></funcdef>
<paramdef>pid_t <parameter>pid</parameter></paramdef>
- <paramdef>uid_t *<parameter>uid</parameter></paramdef>
+ <paramdef>char **<parameter>unit</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_pid_get_unit</function></funcdef>
+ <paramdef>pid_t <parameter>pid</parameter></paramdef>
+ <paramdef>char **<parameter>unit</parameter></paramdef>
</funcprototype>
<funcprototype>
@@ -85,15 +78,27 @@
</funcprototype>
<funcprototype>
+ <funcdef>int <function>sd_peer_get_owner_uid</function></funcdef>
+ <paramdef>int <parameter>fd</parameter></paramdef>
+ <paramdef>uid_t *<parameter>uid</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
<funcdef>int <function>sd_peer_get_session</function></funcdef>
<paramdef>int <parameter>fd</parameter></paramdef>
<paramdef>char **<parameter>session</parameter></paramdef>
</funcprototype>
<funcprototype>
- <funcdef>int <function>sd_peer_get_owner_uid</function></funcdef>
+ <funcdef>int <function>sd_peer_get_user_unit</function></funcdef>
<paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>uid_t *<parameter>uid</parameter></paramdef>
+ <paramdef>char **<parameter>unit</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_peer_get_unit</function></funcdef>
+ <paramdef>int <parameter>fd</parameter></paramdef>
+ <paramdef>char **<parameter>unit</parameter></paramdef>
</funcprototype>
<funcprototype>
@@ -113,27 +118,48 @@
<refsect1>
<title>Description</title>
+ <para><function>sd_pid_get_owner_uid()</function> may be used to
+ determine the Unix UID (user identifier) which owns the login
+ session or systemd user unit of a process identified by the
+ specified PID. For processes which are not part of a login session
+ and not managed by a user manager, this function will fail with
+ <constant>-ENODATA</constant>.</para>
+
<para><function>sd_pid_get_session()</function> may be used to
determine the login session identifier of a process identified by
the specified process identifier. The session identifier is a
- short string, suitable for usage in file system paths. Note that
- not all processes are part of a login session (e.g. system service
- processes, user processes that are shared between multiple
- sessions of the same user, or kernel threads). For processes not
- being part of a login session, this function will fail with
- -ENODATA. The returned string needs to be freed with the libc
- <citerefentry
+ short string, suitable for usage in file system paths. Please
+ note the login session may be limited to a stub process or two.
+ User processes may instead be started from their systemd user
+ manager, e.g. GUI applications started using DBus activation, as
+ well as service processes which are shared between multiple logins
+ of the same user. For processes which are not part of a login
+ session, this function will fail with <constant>-ENODATA</constant>.
+ The returned string needs to be freed with the libc <citerefentry
project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use.</para>
- <para><function>sd_pid_get_owner_uid()</function> may be used to
- determine the Unix UID (user identifier) of the owner of the
- session of a process identified the specified PID. Note that this
- function will succeed for user processes which are shared between
- multiple login sessions of the same user, whereas
- <function>sd_pid_get_session()</function> will fail. For processes
- not being part of a login session and not being a shared process
- of a user, this function will fail with -ENODATA.</para>
+ <para><function>sd_pid_get_user_unit()</function> may be used to
+ determine the systemd user unit (i.e. user service or scope unit)
+ identifier of a process identified by the specified PID. The
+ unit name is a short string, suitable for usage in file system
+ paths. For processes which are not managed by a user manager, this
+ function will fail with <constant>-ENODATA</constant>. The
+ returned string needs to be freed with the libc <citerefentry
+ project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ call after use.</para>
+
+ <para><function>sd_pid_get_unit()</function> may be used to
+ determine the systemd system unit (i.e. system service or scope
+ unit) identifier of a process identified by the specified PID. The
+ unit name is a short string, suitable for usage in file system
+ paths. Note that not all processes are part of a system
+ unit/service. For processes not being part of a systemd system
+ unit, this function will fail with <constant>-ENODATA</constant>.
+ (More specifically, this call will not work for kernel threads.)
+ The returned string needs to be freed with the libc <citerefentry
+ project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ call after use.</para>
<para><function>sd_pid_get_machine_name()</function> may be used
to determine the name of the VM or container is a member of. The
@@ -141,8 +167,20 @@
paths. The returned string needs to be freed with the libc
<citerefentry
project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
- call after use. For processes not part of a VM or containers, this
- function fails with -ENODATA.</para>
+ call after use. For processes not part of a VM or container, this
+ function fails with <constant>-ENODATA</constant>.</para>
+
+ <para><function>sd_pid_get_slice()</function> may be used to
+ determine the slice unit the process is a member of. See
+ <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for details about slices. The returned string needs to be freed
+ with the libc
+ <citerefentry project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ call after use.</para>
+
+ <para>Similarly, <function>sd_pid_get_user_slice()</function>
+ returns the user slice (as managed by the user's systemd instance)
+ of a process.</para>
<para><function>sd_pid_get_cgroup()</function> returns the control
group path of the specified process, relative to the root of the
@@ -159,9 +197,13 @@
functions is passed as 0, the operation is executed for the
calling process.</para>
- <para>The <function>sd_peer_get_session()</function>,
- <function>sd_peer_get_owner_uid()</function>,
- <function>sd_peer_get_machine_name()</function> and
+ <para>The <function>sd_peer_get_owner_uid()</function>,
+ <function>sd_peer_get_session()</function>,
+ <function>sd_peer_get_user_unit()</function>,
+ <function>sd_peer_get_unit()</function>,
+ <function>sd_peer_get_machine_name()</function>,
+ <function>sd_peer_get_slice()</function>,
+ <function>sd_peer_get_user_slice()</function> and
<function>sd_peer_get_cgroup()</function> calls operate similar to
their PID counterparts, but operate on a connected AF_UNIX socket
and retrieve information about the connected peer process. Note
@@ -226,16 +268,7 @@
<refsect1>
<title>Notes</title>
- <para>The <function>sd_pid_get_session()</function>,
- <function>sd_pid_get_owner_uid()</function>,
- <function>sd_pid_get_machine_name()</function>,
- <function>sd_peer_get_session()</function>,
- <function>sd_peer_get_owner_uid()</function>,
- <function>sd_peer_get_machine_name()</function>,
- available as a shared library, which can be compiled and linked to
- with the <constant>libelogind</constant> <citerefentry
- project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
+ <xi:include href="libelogind-pkgconfig.xml" xpointer="pkgconfig-text"/>
<para>Note that the login session identifier as
returned by <function>sd_pid_get_session()</function>
diff --git a/man/sd_seat_get_active.xml b/man/sd_seat_get_active.xml
index 33a8697ff..fb0ed5527 100644
--- a/man/sd_seat_get_active.xml
+++ b/man/sd_seat_get_active.xml
@@ -3,38 +3,15 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2010 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
-<refentry id="sd_seat_get_active" conditional='HAVE_PAM'>
+<refentry id="sd_seat_get_active" conditional='HAVE_PAM'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_seat_get_active</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -186,25 +163,17 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_seat_get_active()</function>,
- <function>sd_seat_get_sessions()</function>,
- <function>sd_seat_can_multi_session()</function>,
- <function>sd_seat_can_tty()</function> and
- <function>sd_seat_can_graphical()</function> interfaces are
- available as a shared library, which can be compiled and linked to
- with the
- <constant>libelogind</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
<para>
+ <!-- 0 /// elogind is in section 8
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ --><!-- else -->
<citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <!-- // 0 -->
<citerefentry><refentrytitle>sd-login</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_session_get_seat</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
diff --git a/man/sd_session_is_active.xml b/man/sd_session_is_active.xml
index d457010b8..22b869729 100644
--- a/man/sd_session_is_active.xml
+++ b/man/sd_session_is_active.xml
@@ -3,38 +3,15 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2010 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
-<refentry id="sd_session_is_active" conditional='HAVE_PAM'>
+<refentry id="sd_session_is_active" conditional='HAVE_PAM'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_session_is_active</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -327,31 +304,17 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>The <function>sd_session_is_active()</function>,
- <function>sd_session_get_state()</function>,
- <function>sd_session_get_uid()</function>,
- <function>sd_session_get_seat()</function>,
- <function>sd_session_get_service()</function>,
- <function>sd_session_get_type()</function>,
- <function>sd_session_get_class()</function>,
- <function>sd_session_get_display()</function>,
- <function>sd_session_get_remote_host()</function>,
- <function>sd_session_get_remote_user()</function> and
- <function>sd_session_get_tty()</function>
- interfaces are available as a shared library, which can
- be compiled and linked to with the
- <constant>libelogind</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
<para>
+ <!-- 0 /// elogind is in section 8
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ --><!-- else -->
<citerefentry><refentrytitle>elogind</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <!-- // 0 -->
<citerefentry><refentrytitle>sd-login</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_pid_get_session</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
diff --git a/man/sd_uid_get_state.xml b/man/sd_uid_get_state.xml
index 20aa92b96..ae670ff57 100644
--- a/man/sd_uid_get_state.xml
+++ b/man/sd_uid_get_state.xml
@@ -3,38 +3,15 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2010 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
-<refentry id="sd_uid_get_state" conditional='HAVE_PAM'>
+<refentry id="sd_uid_get_state" conditional='HAVE_PAM'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_uid_get_state</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -208,14 +185,7 @@
</variablelist>
</refsect1>
- <refsect1>
- <title>Notes</title>
-
- <para>Functions described here are available as a shared library,
- and can be compiled and linked to using the
- <constant>libelogind</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- entry.</para>
- </refsect1>
+ <xi:include href="libelogind-pkgconfig.xml" />
<refsect1>
<title>History</title>
diff --git a/man/sd_watchdog_enabled.xml b/man/sd_watchdog_enabled.xml
index 9ba70dd5c..b3c67d83d 100644
--- a/man/sd_watchdog_enabled.xml
+++ b/man/sd_watchdog_enabled.xml
@@ -3,22 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
- This file is part of elogind.
-
- Copyright 2013 Lennart Poettering
-
- elogind is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- elogind is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: LGPL-2.1+
-->
<refentry id="sd_watchdog_enabled"
@@ -27,15 +12,6 @@
<refentryinfo>
<title>sd_watchdog_enabled</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
diff --git a/man/standard-conf.xml b/man/standard-conf.xml
deleted file mode 100644
index 807702493..000000000
--- a/man/standard-conf.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-<?xml version="1.0"?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
-<!DOCTYPE refsection PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
- "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-
-<refsection>
- <refsection id='confd'>
- <title>Configuration Directories and Precedence</title>
-
- <para>Configuration files are read from directories in
- <filename>/etc/</filename>, <filename>/run/</filename>, and
- <filename>/usr/lib/</filename>, in order of precedence.
- Each configuration file in these configuration directories shall be named in
- the style of <filename><replaceable>filename</replaceable>.conf</filename>.
- Files in <filename>/etc/</filename> override files with the same name in
- <filename>/run/</filename> and <filename>/usr/lib/</filename>. Files in
- <filename>/run/</filename> override files with the same name in
- <filename>/usr/lib/</filename>.</para>
-
- <para>Packages should install their configuration files in
- <filename>/usr/lib/</filename>. Files in <filename>/etc/</filename> are
- reserved for the local administrator, who may use this logic to override the
- configuration files installed by vendor packages. All configuration files
- are sorted by their filename in lexicographic order, regardless of which of
- the directories they reside in. If multiple files specify the same option,
- the entry in the file with the lexicographically latest name will take
- precedence. It is recommended to prefix all filenames with a two-digit number
- and a dash, to simplify the ordering of the files.</para>
-
- <para>If the administrator wants to disable a configuration file supplied by
- the vendor, the recommended way is to place a symlink to
- <filename>/dev/null</filename> in the configuration directory in
- <filename>/etc/</filename>, with the same filename as the vendor
- configuration file. If the vendor configuration file is included in
- the initrd image, the image has to be regenerated.</para>
-
- </refsection>
-
- <refsection id='main-conf'>
- <title>Configuration Directories and Precedence</title>
-
- <para>The default configuration is defined during compilation, so a
- configuration file is only needed when it is necessary to deviate
- from those defaults. By default, the configuration file in
- <filename>/etc/elogind/</filename> contains commented out entries
- showing the defaults as a guide to the administrator. This file
- can be edited to create local overrides.
- </para>
-
- <para>When packages need to customize the configuration, they can
- install configuration snippets in
- <filename>/usr/lib/elogind/*.conf.d/</filename>. Files in
- <filename>/etc/</filename> are reserved for the local
- administrator, who may use this logic to override the
- configuration files installed by vendor packages. The main
- configuration file is read before any of the configuration
- directories, and has the lowest precedence; entries in a file in
- any configuration directory override entries in the single
- configuration file. Files in the
- <filename>*.conf.d/</filename> configuration subdirectories
- are sorted by their filename in lexicographic order, regardless of
- which of the subdirectories they reside in. If multiple files
- specify the same option, the entry in the file with the
- lexicographically latest name takes precedence. It is recommended
- to prefix all filenames in those subdirectories with a two-digit
- number and a dash, to simplify the ordering of the files.</para>
-
- <para>To disable a configuration file supplied by the vendor, the
- recommended way is to place a symlink to
- <filename>/dev/null</filename> in the configuration directory in
- <filename>/etc/</filename>, with the same filename as the vendor
- configuration file.</para>
- </refsection>
-</refsection>
diff --git a/man/standard-options.xml b/man/standard-options.xml
index f718451a1..bea92e89f 100644
--- a/man/standard-options.xml
+++ b/man/standard-options.xml
@@ -2,6 +2,10 @@
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<!--
+ SPDX-License-Identifier: LGPL-2.1+
+-->
+
<variablelist>
<varlistentry id='help'>
<term><option>-h</option></term>
@@ -42,4 +46,13 @@
footer with hints.</para>
</listitem>
</varlistentry>
+
+ <varlistentry id='cat-config'>
+ <term><option>--cat-config</option></term>
+
+ <listitem>
+ <para>Copy the contents of config files to standard output.
+ Before each file, the filename is printed as a comment.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
diff --git a/man/user-system-options.xml b/man/user-system-options.xml
index 8616c5424..a2624787a 100644
--- a/man/user-system-options.xml
+++ b/man/user-system-options.xml
@@ -2,9 +2,14 @@
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<!--
+ SPDX-License-Identifier: LGPL-2.1+
+-->
+
<variablelist>
+ <!-- 0 /// With elogind there is no calling user systemd instance.
<varlistentry id='user'>
- <term><option>--user</option></term>
+ <term><option>&#x2D;&#x2D;user</option></term>
<listitem id='user-text'>
<para>Talk to the service manager of the calling user,
@@ -13,13 +18,14 @@
</varlistentry>
<varlistentry id='system'>
- <term><option>--system</option></term>
+ <term><option>&#x2D;&#x2D;system</option></term>
<listitem id='system-text'>
<para>Talk to the service manager of the system. This is the
implied default.</para>
</listitem>
</varlistentry>
+ // 0 -->
<varlistentry id='host'>
<term><option>-H</option></term>
diff --git a/meson.build b/meson.build
new file mode 100644
index 000000000..550d7a674
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,3412 @@
+# SPDX-License-Identifier: LGPL-2.1+
+
+project('elogind', 'c',
+ version : '239',
+ license : 'LGPLv2+',
+ default_options: [
+ 'c_std=gnu99',
+ 'prefix=/usr',
+ 'sysconfdir=/etc',
+ 'localstatedir=/var',
+ ],
+ meson_version : '>= 0.44',
+ )
+
+#if 0 /// UNNEEDED by elogind - libudev is external
+# libsystemd_version = '0.23.0'
+# libudev_version = '1.6.11'
+#else
+libelogind_version = '0.23.0'
+#endif // 0
+
+# We need the same data in two different formats, ugh!
+# Also, for hysterical reasons, we use different variable
+# names, sometimes. Not all variables are included in every
+# set. Ugh, ugh, ugh!
+conf = configuration_data()
+conf.set_quoted('PACKAGE_STRING', meson.project_name() + ' ' + meson.project_version())
+conf.set_quoted('PACKAGE_VERSION', meson.project_version())
+
+substs = configuration_data()
+#if 0 /// Set elogind Package PACKAGE_URL
+# substs.set('PACKAGE_URL', 'https://www.freedesktop.org/wiki/Software/systemd')
+#else
+substs.set('PACKAGE_URL', 'https://github.com/elogind/elogind')
+#endif // 0
+substs.set('PACKAGE_VERSION', meson.project_version())
+
+#####################################################################
+#if 0 /// elogind does not need this
+#
+# # Try to install the git pre-commit hook
+# git_hook = run_command(join_paths(meson.source_root(), 'tools/add-git-hook.sh'))
+# if git_hook.returncode() == 0
+# message(git_hook.stdout().strip())
+# endif
+#else
+# elogind Note: We use precompiler masks for two reasons:
+# 1) The masking is consistent with the sources
+# 2) The git patch creator we use for preparing upstream patches
+# manipulates commits to not take those masks out. Therefore
+# it can be used to add commits updating the meson files, too.
+#endif // 0
+
+#####################################################################
+
+if get_option('split-usr') == 'auto'
+ split_usr = run_command('test', '-L', '/bin').returncode() != 0
+else
+ split_usr = get_option('split-usr') == 'true'
+endif
+conf.set10('HAVE_SPLIT_USR', split_usr,
+ description : '/usr/bin and /bin directories are separate')
+
+if get_option('split-bin') == 'auto'
+ split_bin = run_command('test', '-L', '/usr/sbin').returncode() != 0
+else
+ split_bin = get_option('split-bin') == 'true'
+endif
+conf.set10('HAVE_SPLIT_BIN', split_bin,
+ description : 'bin and sbin directories are separate')
+
+rootprefixdir = get_option('rootprefix')
+# Unusual rootprefixdir values are used by some distros
+# (see https://github.com/systemd/systemd/pull/7461).
+rootprefix_default = split_usr ? '/' : '/usr'
+if rootprefixdir == ''
+ rootprefixdir = rootprefix_default
+endif
+
+#if 0 /// UNNEEDED by elogind
+# sysvinit_path = get_option('sysvinit-path')
+# sysvrcnd_path = get_option('sysvrcnd-path')
+# conf.set10('HAVE_SYSV_COMPAT', sysvinit_path != '' and sysvrcnd_path != '',
+# description : 'SysV init scripts and rcN.d links are supported')
+#endif // 0
+
+# join_paths ignore the preceding arguments if an absolute component is
+# encountered, so this should canonicalize various paths when they are
+# absolute or relative.
+prefixdir = get_option('prefix')
+if not prefixdir.startswith('/')
+ error('Prefix is not absolute: "@0@"'.format(prefixdir))
+endif
+bindir = join_paths(prefixdir, get_option('bindir'))
+libdir = join_paths(prefixdir, get_option('libdir'))
+sysconfdir = join_paths(prefixdir, get_option('sysconfdir'))
+includedir = join_paths(prefixdir, get_option('includedir'))
+datadir = join_paths(prefixdir, get_option('datadir'))
+localstatedir = join_paths('/', get_option('localstatedir'))
+
+rootbindir = join_paths(rootprefixdir, 'bin')
+rootsbindir = join_paths(rootprefixdir, split_bin ? 'sbin' : 'bin')
+#if 0 /// elogind has a different default
+# rootlibexecdir = join_paths(rootprefixdir, 'lib/systemd')
+#else
+rootlibexecdir = get_option('rootlibexecdir')
+rootlibexecdir = rootlibexecdir != '' ? rootlibexecdir : join_paths(rootprefixdir, 'lib/elogind')
+#endif // 0
+
+rootlibdir = get_option('rootlibdir')
+if rootlibdir == ''
+ rootlibdir = join_paths(rootprefixdir, libdir.split('/')[-1])
+endif
+
+# Dirs of external packages
+pkgconfigdatadir = join_paths(datadir, 'pkgconfig')
+pkgconfiglibdir = join_paths(libdir, 'pkgconfig')
+polkitpolicydir = join_paths(datadir, 'polkit-1/actions')
+polkitrulesdir = join_paths(datadir, 'polkit-1/rules.d')
+polkitpkladir = join_paths(localstatedir, 'lib/polkit-1/localauthority/10-vendor.d')
+varlogdir = join_paths(localstatedir, 'log')
+#if 0 /// UNNEEDED by elogind
+# xinitrcdir = join_paths(sysconfdir, 'X11/xinit/xinitrc.d')
+# rpmmacrosdir = get_option('rpmmacrosdir')
+# if rpmmacrosdir != 'no'
+# rpmmacrosdir = join_paths(prefixdir, rpmmacrosdir)
+# endif
+#endif // 0
+modprobedir = join_paths(rootprefixdir, 'lib/modprobe.d')
+
+# Our own paths
+#if 0 /// elogind has a bit different layout and does not need all of theses
+# pkgdatadir = join_paths(datadir, 'systemd')
+# environmentdir = join_paths(prefixdir, 'lib/environment.d')
+# pkgsysconfdir = join_paths(sysconfdir, 'systemd')
+# userunitdir = join_paths(prefixdir, 'lib/systemd/user')
+# userpresetdir = join_paths(prefixdir, 'lib/systemd/user-preset')
+# tmpfilesdir = join_paths(prefixdir, 'lib/tmpfiles.d')
+# sysusersdir = join_paths(prefixdir, 'lib/sysusers.d')
+# sysctldir = join_paths(prefixdir, 'lib/sysctl.d')
+# binfmtdir = join_paths(prefixdir, 'lib/binfmt.d')
+# modulesloaddir = join_paths(prefixdir, 'lib/modules-load.d')
+# networkdir = join_paths(rootprefixdir, 'lib/systemd/network')
+# pkgincludedir = join_paths(includedir, 'systemd')
+# systemgeneratordir = join_paths(rootlibexecdir, 'system-generators')
+# usergeneratordir = join_paths(prefixdir, 'lib/systemd/user-generators')
+# systemenvgeneratordir = join_paths(prefixdir, 'lib/systemd/system-environment-generators')
+# userenvgeneratordir = join_paths(prefixdir, 'lib/systemd/user-environment-generators')
+# systemshutdowndir = join_paths(rootlibexecdir, 'system-shutdown')
+# systemsleepdir = join_paths(rootlibexecdir, 'system-sleep')
+# systemunitdir = join_paths(rootprefixdir, 'lib/systemd/system')
+# systempresetdir = join_paths(rootprefixdir, 'lib/systemd/system-preset')
+# udevlibexecdir = join_paths(rootprefixdir, 'lib/udev')
+# udevhomedir = udevlibexecdir
+# udevrulesdir = join_paths(udevlibexecdir, 'rules.d')
+# udevhwdbdir = join_paths(udevlibexecdir, 'hwdb.d')
+# catalogdir = join_paths(prefixdir, 'lib/systemd/catalog')
+# kernelinstalldir = join_paths(prefixdir, 'lib/kernel/install.d')
+# factorydir = join_paths(datadir, 'factory')
+# bootlibdir = join_paths(prefixdir, 'lib/systemd/boot/efi')
+# testsdir = join_paths(prefixdir, 'lib/systemd/tests')
+# systemdstatedir = join_paths(localstatedir, 'lib/systemd')
+# catalogstatedir = join_paths(systemdstatedir, 'catalog')
+# randomseeddir = join_paths(localstatedir, 'lib/systemd')
+# profiledir = join_paths(rootlibexecdir, 'portable', 'profile')
+#
+# docdir = get_option('docdir')
+# if docdir == ''
+# docdir = join_paths(datadir, 'doc/systemd')
+# endif
+#else
+pkgdatadir = join_paths(datadir, 'elogind')
+pkgsysconfdir = join_paths(sysconfdir, 'elogind')
+pkgincludedir = join_paths(includedir, 'elogind/systemd')
+systemshutdowndir = join_paths(rootlibexecdir, 'system-shutdown')
+systemsleepdir = join_paths(rootlibexecdir, 'system-sleep')
+
+# in elogind, udev is external and thus configurable
+udevlibexecdir = get_option('udevbindir')
+udevlibexecdir = udevlibexecdir != '' ? udevlibexecdir : join_paths(rootprefixdir, 'lib/udev')
+udevrulesdir = get_option('udevrulesdir')
+udevrulesdir = udevrulesdir != '' ? udevrulesdir : join_paths(udevlibexecdir, 'rules.d')
+udevhomedir = udevlibexecdir
+factorydir = join_paths(datadir, 'factory')
+docdir = get_option('docdir')
+docdir = docdir != '' ? docdir: '-'.join([join_paths(datadir, 'doc/elogind'),
+ meson.project_version()])
+testsdir = join_paths(prefixdir, 'lib/elogind/tests')
+randomseeddir = join_paths(localstatedir, 'lib/elogind')
+#endif // 0
+
+dbuspolicydir = get_option('dbuspolicydir')
+if dbuspolicydir == ''
+ dbuspolicydir = join_paths(datadir, 'dbus-1/system.d')
+endif
+
+dbussessionservicedir = get_option('dbussessionservicedir')
+if dbussessionservicedir == ''
+ dbussessionservicedir = join_paths(datadir, 'dbus-1/services')
+endif
+
+dbussystemservicedir = get_option('dbussystemservicedir')
+if dbussystemservicedir == ''
+ dbussystemservicedir = join_paths(datadir, 'dbus-1/system-services')
+endif
+
+#if 1 /// Will elogind find system_bus_socket in /run/dbus or /var/run/dbus ?
+varrunissymllink = run_command('test', '-L', '/var/run').returncode() == 0
+message('Setting VARRUN_IS_SYMLINK to: @0@'.format(varrunissymllink))
+conf.set10('VARRUN_IS_SYMLINK', varrunissymllink)
+#endif // 1
+
+pamlibdir = get_option('pamlibdir')
+if pamlibdir == ''
+ pamlibdir = join_paths(rootlibdir, 'security')
+endif
+
+pamconfdir = get_option('pamconfdir')
+if pamconfdir == ''
+ pamconfdir = join_paths(sysconfdir, 'pam.d')
+endif
+
+#if 0 /// UNNEEDED by elogind
+# memory_accounting_default = get_option('memory-accounting-default')
+#endif // 0
+
+conf.set_quoted('PKGSYSCONFDIR', pkgsysconfdir)
+conf.set_quoted('SYSTEM_CONFIG_UNIT_PATH', join_paths(pkgsysconfdir, 'system'))
+#if 0 /// UNNEEDED by elogind
+# conf.set_quoted('SYSTEM_DATA_UNIT_PATH', systemunitdir)
+# conf.set_quoted('SYSTEM_SYSVINIT_PATH', sysvinit_path)
+# conf.set_quoted('SYSTEM_SYSVRCND_PATH', sysvrcnd_path)
+# conf.set_quoted('RC_LOCAL_SCRIPT_PATH_START', get_option('rc-local'))
+# conf.set_quoted('RC_LOCAL_SCRIPT_PATH_STOP', get_option('halt-local'))
+#
+# conf.set('ANSI_OK_COLOR', 'ANSI_' + get_option('ok-color').underscorify().to_upper())
+#
+# conf.set_quoted('USER_CONFIG_UNIT_PATH', join_paths(pkgsysconfdir, 'user'))
+# conf.set_quoted('USER_DATA_UNIT_PATH', userunitdir)
+# conf.set_quoted('CERTIFICATE_ROOT', get_option('certificate-root'))
+# conf.set_quoted('CATALOG_DATABASE', join_paths(catalogstatedir, 'database'))
+# conf.set_quoted('SYSTEMD_CGROUP_AGENT_PATH', join_paths(rootlibexecdir, 'systemd-cgroups-agent'))
+# conf.set_quoted('SYSTEMD_BINARY_PATH', join_paths(rootlibexecdir, 'systemd'))
+# conf.set_quoted('SYSTEMD_FSCK_PATH', join_paths(rootlibexecdir, 'systemd-fsck'))
+# conf.set_quoted('SYSTEMD_MAKEFS_PATH', join_paths(rootlibexecdir, 'systemd-makefs'))
+# conf.set_quoted('SYSTEMD_GROWFS_PATH', join_paths(rootlibexecdir, 'systemd-growfs'))
+# conf.set_quoted('SYSTEMD_SHUTDOWN_BINARY_PATH', join_paths(rootlibexecdir, 'systemd-shutdown'))
+# conf.set_quoted('SYSTEMD_SLEEP_BINARY_PATH', join_paths(rootlibexecdir, 'systemd-sleep'))
+# conf.set_quoted('SYSTEMCTL_BINARY_PATH', join_paths(rootbindir, 'systemctl'))
+# conf.set_quoted('SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH', join_paths(rootbindir, 'systemd-tty-ask-password-agent'))
+# conf.set_quoted('SYSTEMD_STDIO_BRIDGE_BINARY_PATH', join_paths(bindir, 'systemd-stdio-bridge'))
+#else
+conf.set_quoted('SYSTEMD_CGROUP_AGENT_PATH', join_paths(rootlibexecdir, 'elogind-cgroups-agent'))
+conf.set_quoted('ELOGIND_UACCESS_COMMAND_PATH', join_paths(rootlibexecdir, 'elogind-uaccess-command'))
+conf.set_quoted('SYSTEMD_BINARY_PATH', join_paths(rootlibexecdir, 'elogind'))
+#endif // 0
+conf.set_quoted('ROOTPREFIX', rootprefixdir)
+#if 0 /// UNNEEDED by elogind
+# conf.set_quoted('RANDOM_SEED_DIR', randomseeddir)
+# conf.set_quoted('RANDOM_SEED', join_paths(randomseeddir, 'random-seed'))
+# conf.set_quoted('SYSTEMD_CRYPTSETUP_PATH', join_paths(rootlibexecdir, 'systemd-cryptsetup'))
+# conf.set_quoted('SYSTEM_GENERATOR_PATH', systemgeneratordir)
+# conf.set_quoted('USER_GENERATOR_PATH', usergeneratordir)
+# conf.set_quoted('SYSTEM_ENV_GENERATOR_PATH', systemenvgeneratordir)
+# conf.set_quoted('USER_ENV_GENERATOR_PATH', userenvgeneratordir)
+#endif // 0
+conf.set_quoted('SYSTEM_SHUTDOWN_PATH', systemshutdowndir)
+conf.set_quoted('SYSTEM_SLEEP_PATH', systemsleepdir)
+#if 0 /// UNNEEDED by elogind
+# conf.set_quoted('SYSTEMD_KBD_MODEL_MAP', join_paths(pkgdatadir, 'kbd-model-map'))
+# conf.set_quoted('SYSTEMD_LANGUAGE_FALLBACK_MAP', join_paths(pkgdatadir, 'language-fallback-map'))
+#endif // 0
+conf.set_quoted('UDEVLIBEXECDIR', udevlibexecdir)
+conf.set_quoted('POLKIT_AGENT_BINARY_PATH', join_paths(bindir, 'pkttyagent'))
+conf.set_quoted('LIBDIR', libdir)
+conf.set_quoted('ROOTLIBDIR', rootlibdir)
+conf.set_quoted('ROOTLIBEXECDIR', rootlibexecdir)
+#if 0 /// UNNEEDED by elogind
+# conf.set_quoted('BOOTLIBDIR', bootlibdir)
+# conf.set_quoted('SYSTEMD_PULL_PATH', join_paths(rootlibexecdir, 'systemd-pull'))
+# conf.set_quoted('SYSTEMD_IMPORT_PATH', join_paths(rootlibexecdir, 'systemd-import'))
+# conf.set_quoted('SYSTEMD_EXPORT_PATH', join_paths(rootlibexecdir, 'systemd-export'))
+# conf.set_quoted('VENDOR_KEYRING_PATH', join_paths(rootlibexecdir, 'import-pubring.gpg'))
+# conf.set_quoted('USER_KEYRING_PATH', join_paths(pkgsysconfdir, 'import-pubring.gpg'))
+# conf.set_quoted('DOCUMENT_ROOT', join_paths(pkgdatadir, 'gatewayd'))
+# conf.set('MEMORY_ACCOUNTING_DEFAULT', memory_accounting_default ? 'true' : 'false')
+# conf.set_quoted('MEMORY_ACCOUNTING_DEFAULT_YES_NO', memory_accounting_default ? 'yes' : 'no')
+#endif // 0
+
+conf.set_quoted('ABS_BUILD_DIR', meson.build_root())
+conf.set_quoted('ABS_SRC_DIR', meson.source_root())
+
+substs.set('prefix', prefixdir)
+substs.set('exec_prefix', prefixdir)
+substs.set('libdir', libdir)
+substs.set('rootlibdir', rootlibdir)
+substs.set('includedir', includedir)
+substs.set('pkgsysconfdir', pkgsysconfdir)
+substs.set('bindir', bindir)
+substs.set('rootbindir', rootbindir)
+substs.set('rootlibexecdir', rootlibexecdir)
+#if 0 /// UNNEEDED by elogind
+# substs.set('systemunitdir', systemunitdir)
+# substs.set('userunitdir', userunitdir)
+# substs.set('systempresetdir', systempresetdir)
+# substs.set('userpresetdir', userpresetdir)
+# substs.set('udevhwdbdir', udevhwdbdir)
+#endif // 0
+substs.set('udevrulesdir', udevrulesdir)
+substs.set('udevlibexecdir', udevlibexecdir)
+#if 0 /// UNNEEDED by elogind
+# substs.set('environmentdir', environmentdir)
+# substs.set('catalogdir', catalogdir)
+# substs.set('tmpfilesdir', tmpfilesdir)
+# substs.set('sysusersdir', sysusersdir)
+# substs.set('sysctldir', sysctldir)
+# substs.set('binfmtdir', binfmtdir)
+# substs.set('modulesloaddir', modulesloaddir)
+# substs.set('modprobedir', modprobedir)
+# substs.set('systemgeneratordir', systemgeneratordir)
+# substs.set('usergeneratordir', usergeneratordir)
+# substs.set('systemenvgeneratordir', systemenvgeneratordir)
+# substs.set('userenvgeneratordir', userenvgeneratordir)
+#endif // 0
+substs.set('systemshutdowndir', systemshutdowndir)
+substs.set('systemsleepdir', systemsleepdir)
+substs.set('VARLOGDIR', varlogdir)
+#if 0 /// UNNEEDED by elogind
+# substs.set('CERTIFICATEROOT', get_option('certificate-root'))
+# substs.set('SYSTEMCTL', join_paths(rootbindir, 'systemctl'))
+# substs.set('RANDOM_SEED', join_paths(randomseeddir, 'random-seed'))
+# substs.set('SYSTEM_SYSVINIT_PATH', sysvinit_path)
+# substs.set('SYSTEM_SYSVRCND_PATH', sysvrcnd_path)
+# substs.set('RC_LOCAL_SCRIPT_PATH_START', get_option('rc-local'))
+# substs.set('RC_LOCAL_SCRIPT_PATH_STOP', get_option('halt-local'))
+# substs.set('MEMORY_ACCOUNTING_DEFAULT', memory_accounting_default ? 'yes' : 'no')
+#endif // 0
+
+#####################################################################
+
+cc = meson.get_compiler('c')
+pkgconfig = import('pkgconfig')
+check_compilation_sh = find_program('tools/meson-check-compilation.sh')
+meson_build_sh = find_program('tools/meson-build.sh')
+
+if get_option('tests') != 'false'
+ cxx = find_program('c++', required : false)
+ if cxx.found()
+ # Used only for tests
+ add_languages('cpp')
+ endif
+endif
+
+#if 0 /// elogind does not support fuzz stress testing (, yet).
+# want_ossfuzz = get_option('oss-fuzz')
+# want_libfuzzer = get_option('llvm-fuzz')
+# fuzzer_build = want_ossfuzz or want_libfuzzer
+# if want_ossfuzz and want_libfuzzer
+# error('only one of oss-fuzz and llvm-fuzz can be specified')
+# endif
+# if want_libfuzzer
+# fuzzing_engine = meson.get_compiler('cpp').find_library('Fuzzer')
+# endif
+# if want_ossfuzz
+# fuzzing_engine = meson.get_compiler('cpp').find_library('FuzzingEngine')
+# endif
+#else
+fuzzer_build = false
+#endif // 0
+
+possible_cc_flags = [
+ '-Wextra',
+ '-Werror=undef',
+ '-Wlogical-op',
+ '-Wmissing-include-dirs',
+ '-Wold-style-definition',
+ '-Wpointer-arith',
+ '-Winit-self',
+ '-Wfloat-equal',
+ '-Wsuggest-attribute=noreturn',
+ '-Werror=missing-prototypes',
+ '-Werror=implicit-function-declaration',
+ '-Werror=missing-declarations',
+ '-Werror=return-type',
+ '-Werror=incompatible-pointer-types',
+ '-Werror=format=2',
+ '-Wstrict-prototypes',
+ '-Wredundant-decls',
+ '-Wmissing-noreturn',
+ '-Wimplicit-fallthrough=5',
+ '-Wshadow',
+ '-Wendif-labels',
+ '-Wstrict-aliasing=2',
+ '-Wwrite-strings',
+ '-Werror=overflow',
+ '-Werror=shift-count-overflow',
+ '-Werror=shift-overflow=2',
+ '-Wdate-time',
+ '-Wnested-externs',
+ '-ffast-math',
+ '-fno-common',
+ '-fdiagnostics-show-option',
+ '-fno-strict-aliasing',
+ '-fvisibility=hidden',
+ '-fstack-protector',
+ '-fstack-protector-strong',
+ '--param=ssp-buffer-size=4',
+]
+
+# --as-needed and --no-undefined are provided by meson by default,
+# run mesonconf to see what is enabled
+possible_link_flags = [
+ '-Wl,-z,relro',
+ '-Wl,-z,now',
+]
+
+# the oss-fuzz fuzzers are not built with -fPIE, so don't
+# enable it when we are linking against them
+if not fuzzer_build
+ possible_cc_flags += '-fPIE'
+ possible_link_flags += '-pie'
+endif
+
+if cc.get_id() == 'clang'
+ possible_cc_flags += [
+ '-Wno-typedef-redefinition',
+ '-Wno-gnu-variable-sized-type-not-at-end',
+ ]
+endif
+
+if get_option('buildtype') != 'debug'
+ possible_cc_flags += [
+ '-ffunction-sections',
+ '-fdata-sections',
+ ]
+
+ possible_link_flags += '-Wl,--gc-sections'
+endif
+
+add_project_arguments(cc.get_supported_arguments(possible_cc_flags), language : 'c')
+
+# "negative" arguments: gcc on purpose does not return an error for "-Wno-"
+# arguments, just emits a warning. So test for the "positive" version instead.
+foreach arg : ['unused-parameter',
+ 'missing-field-initializers',
+ 'unused-result',
+ 'format-signedness',
+ 'error=nonnull', # work-around for gcc 7.1 turning this on on its own
+ ]
+ if cc.has_argument('-W' + arg)
+ add_project_arguments('-Wno-' + arg, language : 'c')
+ endif
+endforeach
+
+if cc.compiles('''
+ #include <time.h>
+ #include <inttypes.h>
+ typedef uint64_t usec_t;
+ usec_t now(clockid_t clock);
+ int main(void) {
+ struct timespec now;
+ return 0;
+ }
+''', name : '-Werror=shadow with local shadowing')
+ add_project_arguments('-Werror=shadow', language : 'c')
+endif
+
+link_test_c = files('tools/meson-link-test.c')
+
+foreach arg : possible_link_flags
+ have = run_command(check_compilation_sh,
+ cc.cmd_array(), '-x', 'c', arg,
+ '-include', link_test_c).returncode() == 0
+ message('Linking with @0@ supported: @1@'.format(arg, have ? 'yes' : 'no'))
+ if have
+ add_project_link_arguments(arg, language : 'c')
+ endif
+endforeach
+
+cpp = ' '.join(cc.cmd_array()) + ' -E'
+
+#####################################################################
+# compilation result tests
+
+conf.set('_GNU_SOURCE', true)
+conf.set('__SANE_USERSPACE_TYPES__', true)
+
+conf.set('SIZEOF_PID_T', cc.sizeof('pid_t', prefix : '#include <sys/types.h>'))
+conf.set('SIZEOF_UID_T', cc.sizeof('uid_t', prefix : '#include <sys/types.h>'))
+conf.set('SIZEOF_GID_T', cc.sizeof('gid_t', prefix : '#include <sys/types.h>'))
+conf.set('SIZEOF_DEV_T', cc.sizeof('dev_t', prefix : '#include <sys/types.h>'))
+conf.set('SIZEOF_INO_T', cc.sizeof('ino_t', prefix : '#include <sys/types.h>'))
+conf.set('SIZEOF_TIME_T', cc.sizeof('time_t', prefix : '#include <sys/time.h>'))
+conf.set('SIZEOF_RLIM_T', cc.sizeof('rlim_t', prefix : '#include <sys/resource.h>'))
+
+decl_headers = '''
+#include <uchar.h>
+#include <linux/ethtool.h>
+#include <linux/fib_rules.h>
+#include <linux/stat.h>
+#include <sys/stat.h>
+'''
+# FIXME: key_serial_t is only defined in keyutils.h, this is bound to fail
+
+foreach decl : ['char16_t',
+ 'char32_t',
+ 'key_serial_t',
+ 'struct ethtool_link_settings',
+ 'struct fib_rule_uid_range',
+ 'struct statx',
+ ]
+
+ # We get -1 if the size cannot be determined
+ have = cc.sizeof(decl, prefix : decl_headers) > 0
+ conf.set10('HAVE_' + decl.underscorify().to_upper(), have)
+endforeach
+
+foreach decl : [['IFLA_INET6_ADDR_GEN_MODE', 'linux/if_link.h'],
+ ['IN6_ADDR_GEN_MODE_STABLE_PRIVACY', 'linux/if_link.h'],
+ ['IFLA_VRF_TABLE', 'linux/if_link.h'],
+ ['IFLA_MACVLAN_FLAGS', 'linux/if_link.h'],
+ ['IFLA_IPVLAN_FLAGS', 'linux/if_link.h'],
+ ['IFLA_PHYS_PORT_ID', 'linux/if_link.h'],
+ ['IFLA_BOND_AD_INFO', 'linux/if_link.h'],
+ ['IFLA_VLAN_PROTOCOL', 'linux/if_link.h'],
+ ['IFLA_VXLAN_REMCSUM_NOPARTIAL', 'linux/if_link.h'],
+ ['IFLA_VXLAN_GPE', 'linux/if_link.h'],
+ ['IFLA_GENEVE_LABEL', 'linux/if_link.h'],
+ # if_tunnel.h is buggy and cannot be included on its own
+ ['IFLA_VTI_REMOTE', 'linux/if_tunnel.h', '#include <net/if.h>'],
+ ['IFLA_IPTUN_ENCAP_DPORT', 'linux/if_tunnel.h', '#include <net/if.h>'],
+ ['IFLA_GRE_ENCAP_DPORT', 'linux/if_tunnel.h', '#include <net/if.h>'],
+ ['IFLA_BRIDGE_VLAN_INFO', 'linux/if_bridge.h'],
+ ['IFLA_BRPORT_PROXYARP', 'linux/if_link.h'],
+ ['IFLA_BRPORT_LEARNING_SYNC', 'linux/if_link.h'],
+ ['IFLA_BR_VLAN_DEFAULT_PVID', 'linux/if_link.h'],
+ ['IPVLAN_F_PRIVATE', 'linux/if_link.h'],
+ ['NDA_IFINDEX', 'linux/neighbour.h'],
+ ['IFA_FLAGS', 'linux/if_addr.h'],
+ ['FRA_UID_RANGE', 'linux/fib_rules.h'],
+ ['LO_FLAGS_PARTSCAN', 'linux/loop.h'],
+ ['VXCAN_INFO_PEER', 'linux/can/vxcan.h'],
+ ]
+ prefix = decl.length() > 2 ? decl[2] : ''
+ have = cc.has_header_symbol(decl[1], decl[0], prefix : prefix)
+ conf.set10('HAVE_' + decl[0], have)
+endforeach
+
+foreach ident : ['secure_getenv', '__secure_getenv']
+ conf.set10('HAVE_' + ident.to_upper(), cc.has_function(ident))
+endforeach
+
+foreach ident : [
+ ['memfd_create', '''#include <sys/mman.h>'''],
+ ['gettid', '''#include <sys/types.h>
+ #include <unistd.h>'''],
+ ['pivot_root', '''#include <stdlib.h>
+ #include <unistd.h>'''], # no known header declares pivot_root
+ ['name_to_handle_at', '''#include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>'''],
+ ['setns', '''#include <sched.h>'''],
+ ['renameat2', '''#include <stdio.h>
+// #include <fcntl.h>'''],
+ ['kcmp', '''#include <linux/kcmp.h>'''],
+ ['keyctl', '''#include <sys/types.h>
+ #include <keyutils.h>'''],
+ ['copy_file_range', '''#include <sys/syscall.h>
+ #include <unistd.h>'''],
+ ['bpf', '''#include <sys/syscall.h>
+ #include <unistd.h>'''],
+ ['statx', '''#include <sys/types.h>
+ #include <sys/stat.h>
+// #include <unistd.h>'''],
+ ['explicit_bzero' , '''#include <string.h>'''],
+ ['reallocarray', '''#include <malloc.h>'''],
+]
+
+ have = cc.has_function(ident[0], prefix : ident[1], args : '-D_GNU_SOURCE')
+ conf.set10('HAVE_' + ident[0].to_upper(), have)
+endforeach
+
+if cc.has_function('getrandom', prefix : '''#include <sys/random.h>''', args : '-D_GNU_SOURCE')
+ conf.set10('USE_SYS_RANDOM_H', true)
+ conf.set10('HAVE_GETRANDOM', true)
+else
+ have = cc.has_function('getrandom', prefix : '''#include <linux/random.h>''')
+ conf.set10('USE_SYS_RANDOM_H', false)
+ conf.set10('HAVE_GETRANDOM', have)
+endif
+
+#####################################################################
+
+sed = find_program('sed')
+awk = find_program('awk')
+m4 = find_program('m4')
+stat = find_program('stat')
+git = find_program('git', required : false)
+env = find_program('env')
+perl = find_program('perl', required : false)
+
+#if 0 /// elogind does not use this but needs a tool to symlink its installed headers.
+# meson_make_symlink = meson.source_root() + '/tools/meson-make-symlink.sh'
+#else /// Needed by elogind
+meson_symlink_headers = meson.source_root() + '/tools/meson-symlink_headers.sh'
+#endif // 0
+mkdir_p = 'mkdir -p $DESTDIR/@0@'
+#if 0 /// unneeded by elogind
+# test_efi_create_disk_sh = find_program('test/test-efi-create-disk.sh')
+# splash_bmp = files('test/splash.bmp')
+#endif // 0
+
+# if -Dxxx-path option is found, use that. Otherwise, check in $PATH,
+# /usr/sbin, /sbin, and fall back to the default from middle column.
+#if 0 /// elogind has a bit different list and some adaptions
+# progs = [['quotaon', '/usr/sbin/quotaon' ],
+# ['quotacheck', '/usr/sbin/quotacheck' ],
+# ['kmod', '/usr/bin/kmod' ],
+# ['kexec', '/usr/sbin/kexec' ],
+# ['sulogin', '/usr/sbin/sulogin' ],
+# ['mount', '/usr/bin/mount', 'MOUNT_PATH'],
+# ['umount', '/usr/bin/umount', 'UMOUNT_PATH'],
+# ['loadkeys', '/usr/bin/loadkeys', 'KBD_LOADKEYS'],
+# ['setfont', '/usr/bin/setfont', 'KBD_SETFONT'],
+# ]
+#else
+progs = [['halt', '/sbin/halt', 'HALT'],
+ ['kexec', '/usr/sbin/kexec', 'KEXEC'],
+ ['poweroff', '/sbin/poweroff', 'POWEROFF'],
+ ['reboot', '/sbin/reboot', 'REBOOT'],
+ ]
+#endif // 0
+foreach prog : progs
+ path = get_option(prog[0] + '-path')
+ if path != ''
+ message('Using @1@ for @0@'.format(prog[0], path))
+ else
+ exe = find_program(prog[0],
+ '/usr/sbin/' + prog[0],
+ '/sbin/' + prog[0],
+ required: false)
+ path = exe.found() ? exe.path() : prog[1]
+ endif
+ name = prog.length() > 2 ? prog[2] : prog[0].to_upper()
+ conf.set_quoted(name, path)
+ substs.set(name, path)
+endforeach
+
+#if 0 /// unneeded by elogind
+# conf.set_quoted('TELINIT', get_option('telinit-path'))
+#
+# if run_command('ln', '--relative', '--help').returncode() != 0
+# error('ln does not support --relative (added in coreutils 8.16)')
+# endif
+#endif // 0
+
+############################################################
+
+gperf = find_program('gperf')
+
+gperf_test_format = '''
+#include <string.h>
+const char * in_word_set(const char *, @0@);
+@1@
+'''
+gperf_snippet_format = 'echo foo,bar | @0@ -L ANSI-C'
+gperf_snippet = run_command('sh', '-c', gperf_snippet_format.format(gperf.path()))
+gperf_test = gperf_test_format.format('size_t', gperf_snippet.stdout())
+if cc.compiles(gperf_test)
+ gperf_len_type = 'size_t'
+else
+ gperf_test = gperf_test_format.format('unsigned', gperf_snippet.stdout())
+ if cc.compiles(gperf_test)
+ gperf_len_type = 'unsigned'
+ else
+ error('unable to determine gperf len type')
+ endif
+endif
+message('gperf len type is @0@'.format(gperf_len_type))
+conf.set('GPERF_LEN_TYPE', gperf_len_type,
+ description : 'The type of gperf "len" parameter')
+
+############################################################
+
+if not cc.has_header('sys/capability.h')
+ error('POSIX caps headers not found')
+endif
+foreach header : ['crypt.h',
+ 'linux/btrfs.h',
+ 'linux/memfd.h',
+ 'linux/vm_sockets.h',
+ 'sys/auxv.h',
+ 'valgrind/memcheck.h',
+ 'valgrind/valgrind.h',
+ ]
+
+ conf.set10('HAVE_' + header.underscorify().to_upper(),
+ cc.has_header(header))
+endforeach
+
+############################################################
+
+conf.set_quoted('FALLBACK_HOSTNAME', get_option('fallback-hostname'))
+#if 0 /// UNNEEDED by elogind
+# conf.set10('ENABLE_COMPAT_GATEWAY_HOSTNAME', get_option('compat-gateway-hostname'))
+# gateway_hostnames = ['_gateway'] + (conf.get('ENABLE_COMPAT_GATEWAY_HOSTNAME') == 1 ? ['gateway'] : [])
+#endif // 0
+
+default_hierarchy = get_option('default-hierarchy')
+conf.set_quoted('DEFAULT_HIERARCHY_NAME', default_hierarchy,
+ description : 'default cgroup hierarchy as string')
+if default_hierarchy == 'legacy'
+ conf.set('DEFAULT_HIERARCHY', 'CGROUP_UNIFIED_NONE')
+elif default_hierarchy == 'hybrid'
+ conf.set('DEFAULT_HIERARCHY', 'CGROUP_UNIFIED_SYSTEMD')
+else
+ conf.set('DEFAULT_HIERARCHY', 'CGROUP_UNIFIED_ALL')
+endif
+
+#if 0 /// UNNEEDED by elogind
+# time_epoch = get_option('time-epoch')
+# if time_epoch == ''
+# NEWS = files('NEWS')
+# time_epoch = run_command(stat, '-c', '%Y', NEWS).stdout()
+# endif
+# time_epoch = time_epoch.to_int()
+# conf.set('TIME_EPOCH', time_epoch)
+#else
+############################################################
+# elogind needs to know which cgroups controller to follow.
+get_cg_ctrl_sh = find_program('tools/meson-get-cg-controller.sh')
+with_cgroupctrl = get_option('cgroup-controller')
+if with_cgroupctrl == '' or with_cgroupctrl == 'auto'
+ with_cgroupctrl = run_command(get_cg_ctrl_sh, []).stdout().strip()
+elif with_cgroupctrl == 'none'
+ with_cgroupctrl = 'elogind'
+endif
+
+# No controller now is a problem:
+if with_cgroupctrl == ''
+ error('Unable to determine cgroup controller, but cgroups support is mandatory!')
+endif
+
+conf.set_quoted('SYSTEMD_CGROUP_CONTROLLER', '_'.join(['',with_cgroupctrl]),
+ description : 'name of the cgroup controller to use')
+conf.set_quoted('SYSTEMD_CGROUP_CONTROLLER_LEGACY',
+ '='.join(['name', with_cgroupctrl]))
+conf.set_quoted('SYSTEMD_CGROUP_CONTROLLER_HYBRID',
+ '='.join(['name', with_cgroupctrl]))
+############################################################
+#endif // 0
+
+system_uid_max = get_option('system-uid-max')
+if system_uid_max == ''
+ system_uid_max = run_command(
+ awk,
+ '/^\s*SYS_UID_MAX\s+/ { uid=$2 } END { print uid }',
+ '/etc/login.defs').stdout().strip()
+ if system_uid_max == ''
+ system_uid_max = '999'
+ endif
+endif
+system_uid_max = system_uid_max.to_int()
+conf.set('SYSTEM_UID_MAX', system_uid_max)
+substs.set('systemuidmax', system_uid_max)
+message('maximum system UID is @0@'.format(system_uid_max))
+
+system_gid_max = get_option('system-gid-max')
+if system_gid_max == ''
+ system_gid_max = run_command(
+ awk,
+ '/^\s*SYS_GID_MAX\s+/ { gid=$2 } END { print gid }',
+ '/etc/login.defs').stdout().strip()
+ if system_gid_max == ''
+ system_gid_max = '999'
+ endif
+endif
+system_gid_max = system_gid_max.to_int()
+conf.set('SYSTEM_GID_MAX', system_gid_max)
+substs.set('systemgidmax', system_gid_max)
+message('maximum system GID is @0@'.format(system_gid_max))
+
+#if 0 /// UNNEEDED by elogind
+# dynamic_uid_min = get_option('dynamic-uid-min').to_int()
+# dynamic_uid_max = get_option('dynamic-uid-max').to_int()
+# conf.set('DYNAMIC_UID_MIN', dynamic_uid_min)
+# conf.set('DYNAMIC_UID_MAX', dynamic_uid_max)
+# substs.set('dynamicuidmin', dynamic_uid_min)
+# substs.set('dynamicuidmax', dynamic_uid_max)
+#
+# container_uid_base_min = get_option('container-uid-base-min').to_int()
+# container_uid_base_max = get_option('container-uid-base-max').to_int()
+# conf.set('CONTAINER_UID_BASE_MIN', container_uid_base_min)
+# conf.set('CONTAINER_UID_BASE_MAX', container_uid_base_max)
+# substs.set('containeruidbasemin', container_uid_base_min)
+# substs.set('containeruidbasemax', container_uid_base_max)
+#endif // 0
+
+nobody_user = get_option('nobody-user')
+nobody_group = get_option('nobody-group')
+
+getent_result = run_command('getent', 'passwd', '65534')
+if getent_result.returncode() == 0
+ name = getent_result.stdout().split(':')[0]
+ if name != nobody_user
+ warning('\n' +
+ 'The local user with the UID 65534 does not match the configured user name "@0@" of the nobody user (its name is @1@).\n'.format(nobody_user, name) +
+ 'Your build will result in an user table setup that is incompatible with the local system.')
+ endif
+endif
+id_result = run_command('id', '-u', nobody_user)
+if id_result.returncode() == 0
+ id = id_result.stdout().to_int()
+ if id != 65534
+ warning('\n' +
+ 'The local user with the configured user name "@0@" of the nobody user does not have UID 65534 (it has @1@).\n'.format(nobody_user, id) +
+ 'Your build will result in an user table setup that is incompatible with the local system.')
+ endif
+endif
+
+getent_result = run_command('getent', 'group', '65534')
+if getent_result.returncode() == 0
+ name = getent_result.stdout().split(':')[0]
+ if name != nobody_group
+ warning('\n' +
+ 'The local group with the GID 65534 does not match the configured group name "@0@" of the nobody group (its name is @1@).\n'.format(nobody_group, name) +
+ 'Your build will result in an group table setup that is incompatible with the local system.')
+ endif
+endif
+id_result = run_command('id', '-g', nobody_group)
+if id_result.returncode() == 0
+ id = id_result.stdout().to_int()
+ if id != 65534
+ warning('\n' +
+ 'The local group with the configured group name "@0@" of the nobody group does not have UID 65534 (it has @1@).\n'.format(nobody_group, id) +
+ 'Your build will result in an group table setup that is incompatible with the local system.')
+ endif
+endif
+if nobody_user != nobody_group and not (nobody_user == 'nobody' and nobody_group == 'nogroup')
+ warning('\n' +
+ 'The configured user name "@0@" and group name "@0@" of the nobody user/group are not equivalent.\n'.format(nobody_user, nobody_group) +
+ 'Please re-check that both "nobody-user" and "nobody-group" options are correctly set.')
+endif
+
+conf.set_quoted('NOBODY_USER_NAME', nobody_user)
+conf.set_quoted('NOBODY_GROUP_NAME', nobody_group)
+substs.set('NOBODY_USER_NAME', nobody_user)
+substs.set('NOBODY_GROUP_NAME', nobody_group)
+
+tty_gid = get_option('tty-gid')
+conf.set('TTY_GID', tty_gid)
+substs.set('TTY_GID', tty_gid)
+
+#if 0 /// UNNEEDED by elogind
+# # Ensure provided GID argument is numeric, otherwise fallback to default assignment
+# if get_option('users-gid') != ''
+# users_gid = get_option('users-gid').to_int()
+# else
+# users_gid = '-'
+# endif
+# substs.set('USERS_GID', users_gid)
+#
+# conf.set10('ENABLE_ADM_GROUP', get_option('adm-group'))
+# conf.set10('ENABLE_WHEEL_GROUP', get_option('wheel-group'))
+#
+# substs.set('DEV_KVM_MODE', get_option('dev-kvm-mode'))
+# substs.set('GROUP_RENDER_MODE', get_option('group-render-mode'))
+#endif // 0
+
+kill_user_processes = get_option('default-kill-user-processes')
+conf.set10('KILL_USER_PROCESSES', kill_user_processes)
+conf.set_quoted('KILL_USER_PROCESSES_YES_NO', kill_user_processes ? 'yes' : 'no')
+substs.set('KILL_USER_PROCESSES', kill_user_processes ? 'yes' : 'no')
+
+#if 0 /// UNNEEDED by elogind
+# dns_servers = get_option('dns-servers')
+# conf.set_quoted('DNS_SERVERS', dns_servers)
+# substs.set('DNS_SERVERS', dns_servers)
+#
+# ntp_servers = get_option('ntp-servers')
+# conf.set_quoted('NTP_SERVERS', ntp_servers)
+# substs.set('NTP_SERVERS', ntp_servers)
+#endif // 0
+
+conf.set_quoted('GETTEXT_PACKAGE', meson.project_name())
+
+#if 0 /// UNNEEDED by elogind
+# substs.set('SUSHELL', get_option('debug-shell'))
+# substs.set('DEBUGTTY', get_option('debug-tty'))
+#endif // 0
+
+enable_debug_hashmap = false
+enable_debug_mmap_cache = false
+#if 1 /// additional elogind debug mode
+enable_debug_elogind = false
+#endif // 1
+foreach name : get_option('debug-extra')
+ if name == 'hashmap'
+ enable_debug_hashmap = true
+ elif name == 'mmap-cache'
+ enable_debug_mmap_cache = true
+#if 1 /// additional elogind debug mode
+ elif name == 'elogind'
+ enable_debug_elogind = true
+#endif // 1
+ else
+ message('unknown debug option "@0@", ignoring'.format(name))
+ endif
+endforeach
+conf.set10('ENABLE_DEBUG_HASHMAP', enable_debug_hashmap)
+conf.set10('ENABLE_DEBUG_MMAP_CACHE', enable_debug_mmap_cache)
+#if 1 /// additional elogind debug mode
+conf.set10('ENABLE_DEBUG_ELOGIND', enable_debug_elogind)
+#endif // 1
+
+conf.set10('VALGRIND', get_option('valgrind'))
+
+#####################################################################
+
+threads = dependency('threads')
+librt = cc.find_library('rt')
+libm = cc.find_library('m')
+libdl = cc.find_library('dl')
+libcrypt = cc.find_library('crypt')
+
+libcap = dependency('libcap', required : false)
+if not libcap.found()
+ # Compat with Ubuntu 14.04 which ships libcap w/o .pc file
+ libcap = cc.find_library('cap')
+endif
+
+#if 0 /// UNNEEDED by elogind
+# libmount = dependency('mount',
+# version : fuzzer_build ? '>= 0' : '>= 2.30')
+#
+# want_seccomp = get_option('seccomp')
+# if want_seccomp != 'false' and not fuzzer_build
+# libseccomp = dependency('libseccomp',
+# version : '>= 2.3.1',
+# required : want_seccomp == 'true')
+# have = libseccomp.found()
+# else
+# have = false
+# libseccomp = []
+# endif
+#else
+libseccomp = []
+#endif // 0
+conf.set10('HAVE_SECCOMP', have)
+
+want_selinux = get_option('selinux')
+if want_selinux != 'false' and not fuzzer_build
+ libselinux = dependency('libselinux',
+ version : '>= 2.1.9',
+ required : want_selinux == 'true')
+ have = libselinux.found()
+else
+ have = false
+ libselinux = []
+endif
+conf.set10('HAVE_SELINUX', have)
+
+#if 0 /// UNNEEDED by elogind
+# want_apparmor = get_option('apparmor')
+# if want_apparmor != 'false' and not fuzzer_build
+# libapparmor = dependency('libapparmor',
+# required : want_apparmor == 'true')
+# have = libapparmor.found()
+# else
+# have = false
+# libapparmor = []
+# endif
+#else
+libapparmor = []
+#endif // 0
+conf.set10('HAVE_APPARMOR', have)
+
+smack_run_label = get_option('smack-run-label')
+if smack_run_label != ''
+ conf.set_quoted('SMACK_RUN_LABEL', smack_run_label)
+endif
+
+want_polkit = get_option('polkit')
+install_polkit = false
+install_polkit_pkla = false
+if want_polkit != 'false' and not fuzzer_build
+ install_polkit = true
+
+ libpolkit = dependency('polkit-gobject-1',
+ required : false)
+ if libpolkit.found() and libpolkit.version().version_compare('< 0.106')
+ message('Old polkit detected, will install pkla files')
+ install_polkit_pkla = true
+ endif
+endif
+conf.set10('ENABLE_POLKIT', install_polkit)
+
+want_acl = get_option('acl')
+if want_acl != 'false' and not fuzzer_build
+ libacl = cc.find_library('acl', required : want_acl == 'true')
+ have = libacl.found()
+else
+ have = false
+ libacl = []
+endif
+conf.set10('HAVE_ACL', have)
+
+want_audit = get_option('audit')
+if want_audit != 'false' and not fuzzer_build
+ libaudit = dependency('audit', required : want_audit == 'true')
+ have = libaudit.found()
+else
+ have = false
+ libaudit = []
+endif
+conf.set10('HAVE_AUDIT', have)
+
+#if 0 /// UNNEEDED by elogind
+# want_blkid = get_option('blkid')
+# if want_blkid != 'false' and not fuzzer_build
+# libblkid = dependency('blkid', required : want_blkid == 'true')
+# have = libblkid.found()
+# else
+# have = false
+# libblkid = []
+# endif
+# conf.set10('HAVE_BLKID', have)
+#
+# want_kmod = get_option('kmod')
+# if want_kmod != 'false' and not fuzzer_build
+# libkmod = dependency('libkmod',
+# version : '>= 15',
+# required : want_kmod == 'true')
+# have = libkmod.found()
+# else
+# have = false
+# libkmod = []
+# endif
+# conf.set10('HAVE_KMOD', have)
+#else
+libblkid = []
+libkmod = []
+#endif // 0
+
+want_pam = get_option('pam')
+if want_pam != 'false' and not fuzzer_build
+ libpam = cc.find_library('pam', required : want_pam == 'true')
+ libpam_misc = cc.find_library('pam_misc', required : want_pam == 'true')
+ have = libpam.found() and libpam_misc.found()
+else
+ have = false
+ libpam = []
+ libpam_misc = []
+endif
+conf.set10('HAVE_PAM', have)
+
+#if 0 /// UNNEEDED by elogind
+# want_microhttpd = get_option('microhttpd')
+# if want_microhttpd != 'false' and not fuzzer_build
+# libmicrohttpd = dependency('libmicrohttpd',
+# version : '>= 0.9.33',
+# required : want_microhttpd == 'true')
+# have = libmicrohttpd.found()
+# else
+# have = false
+# libmicrohttpd = []
+# endif
+# conf.set10('HAVE_MICROHTTPD', have)
+#
+# want_libcryptsetup = get_option('libcryptsetup')
+# if want_libcryptsetup != 'false' and not fuzzer_build
+# libcryptsetup = dependency('libcryptsetup',
+# version : '>= 1.6.0',
+# required : want_libcryptsetup == 'true')
+# have = libcryptsetup.found()
+# else
+# have = false
+# libcryptsetup = []
+# endif
+# conf.set10('HAVE_LIBCRYPTSETUP', have)
+#
+# want_libcurl = get_option('libcurl')
+# if want_libcurl != 'false' and not fuzzer_build
+# libcurl = dependency('libcurl',
+# version : '>= 7.32.0',
+# required : want_libcurl == 'true')
+# have = libcurl.found()
+# else
+# have = false
+# libcurl = []
+# endif
+# conf.set10('HAVE_LIBCURL', have)
+#
+# want_libidn = get_option('libidn')
+# want_libidn2 = get_option('libidn2')
+# if want_libidn == 'true' and want_libidn2 == 'true'
+# error('libidn and libidn2 cannot be requested simultaneously')
+# endif
+#
+# if want_libidn != 'false' and want_libidn2 != 'true' and not fuzzer_build
+# libidn = dependency('libidn',
+# required : want_libidn == 'true')
+# have = libidn.found()
+# else
+# have = false
+# libidn = []
+# endif
+# conf.set10('HAVE_LIBIDN', have)
+# if not have and want_libidn2 != 'false' and not fuzzer_build
+# # libidn is used for both libidn and libidn2 objects
+# libidn = dependency('libidn2',
+# required : want_libidn2 == 'true')
+# have = libidn.found()
+# else
+# have = false
+# endif
+# conf.set10('HAVE_LIBIDN2', have)
+#
+# want_libiptc = get_option('libiptc')
+# if want_libiptc != 'false' and not fuzzer_build
+# libiptc = dependency('libiptc',
+# required : want_libiptc == 'true')
+# have = libiptc.found()
+# else
+# have = false
+# libiptc = []
+# endif
+# conf.set10('HAVE_LIBIPTC', have)
+#
+# want_qrencode = get_option('qrencode')
+# if want_qrencode != 'false' and not fuzzer_build
+# libqrencode = dependency('libqrencode',
+# required : want_qrencode == 'true')
+# have = libqrencode.found()
+# else
+# have = false
+# libqrencode = []
+# endif
+# conf.set10('HAVE_QRENCODE', have)
+#
+# want_gcrypt = get_option('gcrypt')
+# if want_gcrypt != 'false' and not fuzzer_build
+# libgcrypt = cc.find_library('gcrypt', required : want_gcrypt == 'true')
+# libgpg_error = cc.find_library('gpg-error', required : want_gcrypt == 'true')
+# have = libgcrypt.found() and libgpg_error.found()
+# else
+# have = false
+# endif
+# if not have
+# # link to neither of the libs if one is not found
+# libgcrypt = []
+# libgpg_error = []
+# endif
+# conf.set10('HAVE_GCRYPT', have)
+#
+# want_gnutls = get_option('gnutls')
+# if want_gnutls != 'false' and not fuzzer_build
+# libgnutls = dependency('gnutls',
+# version : '>= 3.1.4',
+# required : want_gnutls == 'true')
+# have = libgnutls.found()
+# else
+# have = false
+# libgnutls = []
+# endif
+# conf.set10('HAVE_GNUTLS', have)
+#
+# want_elfutils = get_option('elfutils')
+# if want_elfutils != 'false' and not fuzzer_build
+# libdw = dependency('libdw',
+# required : want_elfutils == 'true')
+# have = libdw.found()
+# else
+# have = false
+# libdw = []
+# endif
+# conf.set10('HAVE_ELFUTILS', have)
+#
+# want_zlib = get_option('zlib')
+# if want_zlib != 'false' and not fuzzer_build
+# libz = dependency('zlib',
+# required : want_zlib == 'true')
+# have = libz.found()
+# else
+# have = false
+# libz = []
+# endif
+# conf.set10('HAVE_ZLIB', have)
+#
+# want_bzip2 = get_option('bzip2')
+# if want_bzip2 != 'false' and not fuzzer_build
+# libbzip2 = cc.find_library('bz2',
+# required : want_bzip2 == 'true')
+# have = libbzip2.found()
+# else
+# have = false
+# libbzip2 = []
+# endif
+# conf.set10('HAVE_BZIP2', have)
+#
+# want_xz = get_option('xz')
+# if want_xz != 'false' and not fuzzer_build
+# libxz = dependency('liblzma',
+# required : want_xz == 'true')
+# have = libxz.found()
+# else
+# have = false
+# libxz = []
+# endif
+# conf.set10('HAVE_XZ', have)
+#
+# want_lz4 = get_option('lz4')
+# if want_lz4 != 'false' and not fuzzer_build
+# liblz4 = dependency('liblz4',
+# required : want_lz4 == 'true')
+# have = liblz4.found()
+# else
+# have = false
+# liblz4 = []
+# endif
+# conf.set10('HAVE_LZ4', have)
+#
+# want_xkbcommon = get_option('xkbcommon')
+# if want_xkbcommon != 'false' and not fuzzer_build
+# libxkbcommon = dependency('xkbcommon',
+# version : '>= 0.3.0',
+# required : want_xkbcommon == 'true')
+# have = libxkbcommon.found()
+# else
+# have = false
+# libxkbcommon = []
+# endif
+#else
+libmicrohttpd = []
+libcryptsetup = []
+libcurl = []
+libidn = []
+libiptc = []
+libqrencode = []
+libgcrypt = []
+libgpg_error = []
+libgnutls = []
+libdw = []
+libz = []
+libbzip2 = []
+libxz = []
+liblz4 = []
+libxkbcommon = []
+#endif // 0
+conf.set10('HAVE_XKBCOMMON', have)
+
+want_pcre2 = get_option('pcre2')
+if want_pcre2 != 'false'
+ libpcre2 = dependency('libpcre2-8',
+ required : want_pcre2 == 'true')
+ have = libpcre2.found()
+else
+ have = false
+ libpcre2 = []
+endif
+conf.set10('HAVE_PCRE2', have)
+
+want_glib = get_option('glib')
+if want_glib != 'false' and not fuzzer_build
+ libglib = dependency('glib-2.0',
+ version : '>= 2.22.0',
+ required : want_glib == 'true')
+ libgobject = dependency('gobject-2.0',
+ version : '>= 2.22.0',
+ required : want_glib == 'true')
+ libgio = dependency('gio-2.0',
+ required : want_glib == 'true')
+ have = libglib.found() and libgobject.found() and libgio.found()
+else
+ have = false
+ libglib = []
+ libgobject = []
+ libgio = []
+endif
+conf.set10('HAVE_GLIB', have)
+
+want_dbus = get_option('dbus')
+if want_dbus != 'false' and not fuzzer_build
+ libdbus = dependency('dbus-1',
+ version : '>= 1.3.2',
+ required : want_dbus == 'true')
+ have = libdbus.found()
+else
+ have = false
+ libdbus = []
+endif
+conf.set10('HAVE_DBUS', have)
+
+#if 0 /// UNNEEDED by elogind
+# default_dnssec = get_option('default-dnssec')
+# if fuzzer_build
+# default_dnssec = 'no'
+# endif
+# if default_dnssec != 'no' and conf.get('HAVE_GCRYPT') == 0
+# message('default-dnssec cannot be set to yes or allow-downgrade when gcrypt is disabled. Setting default-dnssec to no.')
+# default_dnssec = 'no'
+# endif
+# conf.set('DEFAULT_DNSSEC_MODE',
+# 'DNSSEC_' + default_dnssec.underscorify().to_upper())
+# substs.set('DEFAULT_DNSSEC_MODE', default_dnssec)
+#
+# dns_over_tls = get_option('dns-over-tls')
+# if dns_over_tls != 'false'
+# have = conf.get('HAVE_GNUTLS') == 1
+# if dns_over_tls == 'true' and not have
+# error('DNS-over-TLS support was requested, but dependencies are not available')
+# endif
+# else
+# have = false
+# endif
+# conf.set10('ENABLE_DNS_OVER_TLS', have)
+#
+# default_dns_over_tls = get_option('default-dns-over-tls')
+# if fuzzer_build
+# default_dns_over_tls = 'no'
+# endif
+# if default_dns_over_tls != 'no' and conf.get('ENABLE_DNS_OVER_TLS') == 0
+# message('default-dns-over-tls cannot be set to opportunistic when DNS-over-TLS support is disabled. Setting default-dns-over-tls to no.')
+# default_dns_over_tls = 'no'
+# endif
+# conf.set('DEFAULT_DNS_OVER_TLS_MODE',
+# 'DNS_OVER_TLS_' + default_dns_over_tls.underscorify().to_upper())
+# substs.set('DEFAULT_DNS_OVER_TLS_MODE', default_dns_over_tls)
+#
+# want_importd = get_option('importd')
+# if want_importd != 'false'
+# have = (conf.get('HAVE_LIBCURL') == 1 and
+# conf.get('HAVE_ZLIB') == 1 and
+# conf.get('HAVE_BZIP2') == 1 and
+# conf.get('HAVE_XZ') == 1 and
+# conf.get('HAVE_GCRYPT') == 1)
+# if want_importd == 'true' and not have
+# error('importd support was requested, but dependencies are not available')
+# endif
+# else
+# have = false
+# endif
+# conf.set10('ENABLE_IMPORTD', have)
+#
+# want_remote = get_option('remote')
+# if want_remote != 'false'
+# have_deps = [conf.get('HAVE_MICROHTTPD') == 1,
+# conf.get('HAVE_LIBCURL') == 1]
+# # sd-j-remote requires µhttpd, and sd-j-upload requires libcurl, so
+# # it's possible to build one without the other. Complain only if
+# # support was explictly requested. The auxiliary files like sysusers
+# # config should be installed when any of the programs are built.
+# if want_remote == 'true' and not (have_deps[0] and have_deps[1])
+# error('remote support was requested, but dependencies are not available')
+# endif
+# have = have_deps[0] or have_deps[1]
+# else
+# have = false
+# endif
+#endif // 0
+conf.set10('ENABLE_REMOTE', have)
+
+foreach term : ['utmp',
+#if 0 /// UNNEEDED by elogind
+# 'hibernate',
+# 'environment-d',
+# 'binfmt',
+# 'coredump',
+# 'resolve',
+# 'logind',
+# 'hostnamed',
+# 'localed',
+# 'machined',
+# 'portabled',
+# 'networkd',
+# 'timedated',
+# 'timesyncd',
+# 'myhostname',
+# 'firstboot',
+# 'randomseed',
+# 'backlight',
+# 'vconsole',
+# 'quotacheck',
+# 'sysusers',
+# 'tmpfiles',
+# 'hwdb',
+# 'rfkill',
+# 'ldconfig',
+# 'efi',
+# 'tpm',
+# 'ima',
+# 'smack',
+# 'gshadow',
+# 'idn',
+# 'nss-systemd']
+#else
+ 'smack']
+#endif // 0
+ have = get_option(term)
+ name = 'ENABLE_' + term.underscorify().to_upper()
+ conf.set10(name, have)
+endforeach
+
+#if 0 /// UNNEEDED by elogind
+# conf.set10('ENABLE_TIMEDATECTL', get_option('timedated') or get_option('timesyncd'))
+#endif // 0
+
+want_tests = get_option('tests')
+install_tests = get_option('install-tests')
+slow_tests = get_option('slow-tests')
+tests = []
+fuzzers = []
+
+conf.set10('SYSTEMD_SLOW_TESTS_DEFAULT', slow_tests)
+
+#####################################################################
+
+#if 0 /// UNNEEDED by elogind
+# if get_option('efi')
+# efi_arch = host_machine.cpu_family()
+#
+# if efi_arch == 'x86'
+# EFI_MACHINE_TYPE_NAME = 'ia32'
+# gnu_efi_arch = 'ia32'
+# elif efi_arch == 'x86_64'
+# EFI_MACHINE_TYPE_NAME = 'x64'
+# gnu_efi_arch = 'x86_64'
+# elif efi_arch == 'arm'
+# EFI_MACHINE_TYPE_NAME = 'arm'
+# gnu_efi_arch = 'arm'
+# elif efi_arch == 'aarch64'
+# EFI_MACHINE_TYPE_NAME = 'aa64'
+# gnu_efi_arch = 'aarch64'
+# else
+# EFI_MACHINE_TYPE_NAME = ''
+# gnu_efi_arch = ''
+# endif
+#
+# have = true
+# conf.set_quoted('EFI_MACHINE_TYPE_NAME', EFI_MACHINE_TYPE_NAME)
+#
+# conf.set('SD_TPM_PCR', get_option('tpm-pcrindex').to_int())
+# else
+# have = false
+# endif
+#endif // 0
+conf.set10('ENABLE_EFI', have)
+
+#####################################################################
+
+#if 1 /// These are not needed by elogind, but meson wants them although they are commented out.
+conf.set_quoted('CERTIFICATE_ROOT', '/dev/null')
+conf.set_quoted('MEMORY_ACCOUNTING_DEFAULT_YES_NO', 'N/A')
+conf.set_quoted('MOUNT_PATH', '/dev/null')
+conf.set_quoted('SYSTEM_ENV_GENERATOR_PATH', '/dev/null')
+conf.set_quoted('SYSTEM_GENERATOR_PATH', '/dev/null')
+conf.set_quoted('UMOUNT_PATH', '/dev/null')
+conf.set_quoted('USER_ENV_GENERATOR_PATH', '/dev/null')
+conf.set_quoted('USER_GENERATOR_PATH', '/dev/null')
+#####################################################################
+
+#endif // 1
+
+config_h = configure_file(
+ output : 'config.h',
+ configuration : conf)
+
+meson_apply_m4 = find_program('tools/meson-apply-m4.sh')
+
+includes = include_directories('src/basic',
+ 'src/shared',
+ 'src/systemd',
+#if 0 /// UNNEEDED by elogind
+# 'src/journal',
+# 'src/journal-remote',
+# 'src/nspawn',
+# 'src/resolve',
+# 'src/timesync',
+# 'src/time-wait-sync',
+#endif // 0
+ 'src/login',
+#if 0 /// UNNEEDED by elogind
+# 'src/udev',
+# 'src/libudev',
+#endif // 0
+ 'src/core',
+#if 0 /// elogind has a different list
+# 'src/libsystemd/sd-bus',
+# 'src/libsystemd/sd-device',
+# 'src/libsystemd/sd-hwdb',
+# 'src/libsystemd/sd-id128',
+# 'src/libsystemd/sd-netlink',
+# 'src/libsystemd/sd-network',
+# 'src/libsystemd-network',
+#else
+ 'src/libelogind/sd-bus',
+ 'src/libelogind/sd-id128',
+ 'src/sleep',
+ 'src/update-utmp',
+#endif // 0
+ '.')
+
+add_project_arguments('-include', 'config.h', language : 'c')
+
+subdir('po')
+#if 0 /// UNNEEDED by elogind
+# subdir('catalog')
+#endif // 0
+subdir('src/systemd')
+subdir('src/basic')
+#if 0 /// UNNEEDED by elogind
+# subdir('src/libsystemd')
+# subdir('src/libsystemd-network')
+# subdir('src/journal')
+#else
+subdir('src/core')
+subdir('src/libelogind')
+subdir('src/sleep')
+subdir('src/update-utmp')
+#endif // 0
+subdir('src/login')
+
+#if 0 /// UNNEEDED by elogind
+# libjournal_core = static_library(
+# 'journal-core',
+# libjournal_core_sources,
+# journald_gperf_c,
+# include_directories : includes,
+# install : false)
+#endif // 0
+
+libelogind_sym_path = '@0@/@1@'.format(meson.current_source_dir(), libelogind_sym)
+libelogind = shared_library(
+ 'elogind',
+ 'src/systemd/sd-id128.h', # pick a header file at random to work around old meson bug
+ version : libelogind_version,
+ include_directories : includes,
+ link_args : ['-shared',
+ '-Wl,--version-script=' + libelogind_sym_path],
+#if 0 /// elogind does not need gcrypt or libjournal_client, only threads.
+# link_with : [libbasic,
+# libbasic_gcrypt],
+# link_whole : [libsystemd_static,
+# libjournal_client],
+# dependencies : [threads,
+# librt,
+# libxz,
+# liblz4],
+# link_depends : libsystemd_sym,
+#else
+ link_with : [libbasic],
+ link_whole : [libelogind_static],
+ dependencies : [threads],
+ link_depends : libelogind_sym,
+#endif // 0
+ install : true,
+ install_dir : rootlibdir)
+
+static_libelogind = get_option('static-libelogind')
+static_libelogind_pic = static_libelogind == 'true' or static_libelogind == 'pic'
+
+install_libelogind_static = static_library(
+ 'elogind',
+ libelogind_sources,
+#if 0 /// No journald with elogind (And before you ask: NO!)
+# journal_client_sources,
+#endif // 0
+ basic_sources,
+#if 0 /// No gcrypt with elogind
+# basic_gcrypt_sources,
+#endif // 0
+ include_directories : includes,
+ build_by_default : static_libelogind != 'false',
+ install : static_libelogind != 'false',
+ install_dir : rootlibdir,
+ pic : static_libelogind == 'true' or static_libelogind == 'pic',
+ dependencies : [threads,
+ librt,
+ libxz,
+ liblz4,
+ libcap,
+ libblkid,
+#if 0 /// libmount isn't built with elogind (and absolutely not needed anyway.)
+# libmount,
+#endif // 0
+ libselinux,
+#if 0 /// No grypt with elogind
+# libgcrypt],
+#else
+ ],
+#endif // 0
+ c_args : libelogind_c_args + (static_libelogind_pic ? [] : ['-fno-PIC']))
+
+############################################################
+
+# binaries that have --help and are intended for use by humans,
+# usually, but not always, installed in /bin.
+public_programs = []
+
+#if 0 /// UNNEEDED by elogind
+# subdir('src/libudev')
+#else
+# elogind depends on external libudev:
+libudev = dependency('libudev', required : true)
+#endif // 0
+subdir('src/shared')
+#if 0 /// UNNEEDED by elogind
+# subdir('src/core')
+# subdir('src/udev')
+# subdir('src/network')
+#
+# subdir('src/analyze')
+# subdir('src/journal-remote')
+# subdir('src/coredump')
+# subdir('src/hostname')
+# subdir('src/import')
+# subdir('src/kernel-install')
+# subdir('src/locale')
+# subdir('src/machine')
+# subdir('src/portable')
+# subdir('src/nspawn')
+# subdir('src/resolve')
+# subdir('src/timedate')
+# subdir('src/timesync')
+# subdir('src/vconsole')
+# subdir('src/boot/efi')
+#endif // 0
+
+subdir('src/test')
+#if 0 /// UNNEEDED by elogind
+# subdir('src/fuzz')
+# subdir('rules')
+# subdir('test')
+#endif // 0
+
+############################################################
+
+# only static linking apart from libdl, to make sure that the
+# module is linked to all libraries that it uses.
+test_dlopen = executable(
+ 'test-dlopen',
+ test_dlopen_c,
+ include_directories : includes,
+ link_with : [libbasic],
+ dependencies : [libdl])
+
+#if 0 /// UNNEEDED by elogind
+# foreach tuple : [['myhostname', 'ENABLE_MYHOSTNAME'],
+# ['systemd', 'ENABLE_NSS_SYSTEMD'],
+# ['mymachines', 'ENABLE_MACHINED'],
+# ['resolve', 'ENABLE_RESOLVE']]
+#
+# condition = tuple[1] == '' or conf.get(tuple[1]) == 1
+# if condition
+# module = tuple[0]
+#
+# sym = 'src/nss-@0@/nss-@0@.sym'.format(module)
+# version_script_arg = join_paths(meson.current_source_dir(), sym)
+#
+# nss = shared_library(
+# 'nss_' + module,
+# 'src/nss-@0@/nss-@0@.c'.format(module),
+# version : '2',
+# include_directories : includes,
+# # Note that we link NSS modules with '-z nodelete' so that mempools never get orphaned
+# link_args : ['-Wl,-z,nodelete',
+# '-shared',
+# '-Wl,--version-script=' + version_script_arg,
+# '-Wl,--undefined'],
+# link_with : [libsystemd_static,
+# libbasic],
+# dependencies : [threads,
+# librt],
+# link_depends : sym,
+# install : true,
+# install_dir : rootlibdir)
+#
+# # We cannot use shared_module because it does not support version suffix.
+# # Unfortunately shared_library insists on creating the symlink…
+# meson.add_install_script('sh', '-c',
+# 'rm $DESTDIR@0@/libnss_@1@.so'
+# .format(rootlibdir, module))
+#
+# test('dlopen-nss_' + module,
+# test_dlopen,
+# args : [nss.full_path()]) # path to dlopen must include a slash
+# endif
+# endforeach
+#endif // 0
+
+############################################################
+
+#if 0 /// UNNEEDED by elogind
+# executable('systemd',
+# systemd_sources,
+# include_directories : includes,
+# link_with : [libcore,
+# libshared],
+# dependencies : [threads,
+# librt,
+# libseccomp,
+# libselinux,
+# libmount,
+# libblkid],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# meson.add_install_script(meson_make_symlink,
+# join_paths(rootlibexecdir, 'systemd'),
+# join_paths(rootsbindir, 'init'))
+#
+# exe = executable('systemd-analyze',
+# systemd_analyze_sources,
+# include_directories : includes,
+# link_with : [libcore,
+# libshared],
+# dependencies : [threads,
+# librt,
+# libseccomp,
+# libselinux,
+# libmount,
+# libblkid],
+# install_rpath : rootlibexecdir,
+# install : true)
+# public_programs += [exe]
+#
+# executable('systemd-journald',
+# systemd_journald_sources,
+# include_directories : includes,
+# link_with : [libjournal_core,
+# libshared],
+# dependencies : [threads,
+# libxz,
+# liblz4,
+# libselinux],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# exe = executable('systemd-cat',
+# systemd_cat_sources,
+# include_directories : includes,
+# link_with : [libjournal_core,
+# libshared],
+# dependencies : [threads],
+# install_rpath : rootlibexecdir,
+# install : true)
+# public_programs += [exe]
+#
+# exe = executable('journalctl',
+# journalctl_sources,
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [threads,
+# libqrencode,
+# libxz,
+# liblz4,
+# libpcre2],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootbindir)
+# public_programs += [exe]
+#
+# executable('systemd-getty-generator',
+# 'src/getty-generator/getty-generator.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : systemgeneratordir)
+#
+# executable('systemd-debug-generator',
+# 'src/debug-generator/debug-generator.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : systemgeneratordir)
+#
+# executable('systemd-fstab-generator',
+# 'src/fstab-generator/fstab-generator.c',
+# 'src/core/mount-setup.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : systemgeneratordir)
+#
+# if conf.get('ENABLE_ENVIRONMENT_D') == 1
+# executable('30-systemd-environment-d-generator',
+# 'src/environment-d-generator/environment-d-generator.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : userenvgeneratordir)
+#
+# meson.add_install_script(meson_make_symlink,
+# join_paths(sysconfdir, 'environment'),
+# join_paths(environmentdir, '99-environment.conf'))
+# endif
+#
+# if conf.get('ENABLE_HIBERNATE') == 1
+# executable('systemd-hibernate-resume-generator',
+# 'src/hibernate-resume/hibernate-resume-generator.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : systemgeneratordir)
+#
+# executable('systemd-hibernate-resume',
+# 'src/hibernate-resume/hibernate-resume.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+# endif
+#
+# if conf.get('HAVE_BLKID') == 1
+# executable('systemd-gpt-auto-generator',
+# 'src/gpt-auto-generator/gpt-auto-generator.c',
+# 'src/basic/blkid-util.h',
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : libblkid,
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : systemgeneratordir)
+#
+# exe = executable('systemd-dissect',
+# 'src/dissect/dissect.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+# public_programs += [exe]
+# endif
+#
+# if conf.get('ENABLE_RESOLVE') == 1
+# executable('systemd-resolved',
+# systemd_resolved_sources,
+# include_directories : includes,
+# link_with : [libshared,
+# libbasic_gcrypt,
+# libsystemd_resolve_core],
+# dependencies : systemd_resolved_dependencies,
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# exe = executable('resolvectl',
+# resolvectl_sources,
+# include_directories : includes,
+# link_with : [libshared,
+# libbasic_gcrypt,
+# libsystemd_resolve_core],
+# dependencies : [threads,
+# libgpg_error,
+# libm,
+# libidn],
+# install_rpath : rootlibexecdir,
+# install : true)
+# public_programs += [exe]
+#
+# meson.add_install_script(meson_make_symlink,
+# join_paths(bindir, 'resolvectl'),
+# join_paths(rootsbindir, 'resolvconf'))
+#
+# meson.add_install_script(meson_make_symlink,
+# join_paths(bindir, 'resolvectl'),
+# join_paths(bindir, 'systemd-resolve'))
+# endif
+#
+# if conf.get('ENABLE_LOGIND') == 1
+# executable('systemd-logind',
+# systemd_logind_sources,
+# include_directories : includes,
+# link_with : [liblogind_core,
+# libshared],
+# dependencies : [threads,
+# libacl],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# exe = executable('loginctl',
+# loginctl_sources,
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [threads,
+# liblz4,
+# libxz],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootbindir)
+# public_programs += [exe]
+#
+# exe = executable('systemd-inhibit',
+# 'src/login/inhibit.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootbindir)
+# public_programs += [exe]
+#
+# if conf.get('HAVE_PAM') == 1
+# version_script_arg = join_paths(meson.current_source_dir(), pam_systemd_sym)
+# pam_systemd = shared_library(
+# 'pam_systemd',
+# pam_systemd_c,
+# name_prefix : '',
+# include_directories : includes,
+# link_args : ['-shared',
+# '-Wl,--version-script=' + version_script_arg],
+# link_with : [libsystemd_static,
+# libshared_static],
+# dependencies : [threads,
+# libpam,
+# libpam_misc],
+# link_depends : pam_systemd_sym,
+# install : true,
+# install_dir : pamlibdir)
+#
+# test('dlopen-pam_systemd',
+# test_dlopen,
+# args : [pam_systemd.full_path()]) # path to dlopen must include a slash
+# endif
+# endif
+#
+# executable('systemd-user-runtime-dir',
+# user_runtime_dir_sources,
+# include_directories : includes,
+# link_with : [libshared, liblogind_core],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+#else
+
+executable('elogind',
+ elogind_sources,
+ include_directories : includes,
+ link_with : [liblogind_core,
+ libshared],
+ dependencies : [threads,
+ libacl,
+ libudev],
+ install_rpath : rootlibexecdir,
+ install : true,
+ install_dir : rootlibexecdir)
+
+exe = executable('loginctl',
+ loginctl_sources,
+ include_directories : includes,
+ link_with : [libshared],
+ dependencies : [threads,
+ libudev],
+ install_rpath : rootlibexecdir,
+ install : true,
+ install_dir : rootbindir)
+public_programs += [exe]
+
+exe = executable('elogind-inhibit',
+ 'src/login/inhibit.c',
+ include_directories : includes,
+ link_with : [libshared],
+ dependencies : [threads],
+ install_rpath : rootlibexecdir,
+ install : true,
+ install_dir : rootbindir)
+public_programs += [exe]
+
+if conf.get('HAVE_PAM') == 1
+ version_script_arg = join_paths(meson.current_source_dir(), pam_elogind_sym)
+ pam_elogind = shared_library(
+ 'pam_elogind',
+ pam_elogind_c,
+ name_prefix : '',
+ include_directories : includes,
+ link_args : ['-shared',
+ '-Wl,--version-script=' + version_script_arg],
+ link_with : [libelogind_static,
+ libshared_static],
+ dependencies : [threads,
+ libpam,
+ libpam_misc],
+ link_depends : pam_elogind_sym,
+ install : true,
+ install_dir : pamlibdir)
+
+ test('dlopen-pam_elogind',
+ test_dlopen,
+ args : [pam_elogind.full_path()]) # path to dlopen must include a slash
+endif
+#endif // 0
+#if 0 /// UNNEEDED by elogind
+# executable('systemd-user-sessions',
+# 'src/user-sessions/user-sessions.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+# endif
+#
+# if conf.get('ENABLE_EFI') == 1 and conf.get('HAVE_BLKID') == 1
+# exe = executable('bootctl',
+# 'src/boot/bootctl.c',
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [libblkid],
+# install_rpath : rootlibexecdir,
+# install : true)
+# public_programs += [exe]
+# endif
+#
+# exe = executable('systemd-socket-activate', 'src/activate/activate.c',
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [threads],
+# install_rpath : rootlibexecdir,
+# install : true)
+# public_programs += [exe]
+#
+#
+# if get_option('link-systemctl-shared')
+# systemctl_link_with = [libshared]
+# else
+# systemctl_link_with = [libsystemd_static,
+# libshared_static,
+# libjournal_client,
+# libbasic_gcrypt]
+# endif
+#
+# exe = executable('systemctl', 'src/systemctl/systemctl.c',
+# include_directories : includes,
+# link_with : systemctl_link_with,
+# dependencies : [threads,
+# libcap,
+# libselinux,
+# libxz,
+# liblz4],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootbindir)
+# public_programs += [exe]
+#
+# if conf.get('ENABLE_PORTABLED') == 1
+# executable('systemd-portabled',
+# systemd_portabled_sources,
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [threads],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# exe = executable('portablectl', 'src/portable/portablectl.c',
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [threads],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+# public_programs += [exe]
+# endif
+#
+# foreach alias : ['halt', 'poweroff', 'reboot', 'runlevel', 'shutdown', 'telinit']
+# meson.add_install_script(meson_make_symlink,
+# join_paths(rootbindir, 'systemctl'),
+# join_paths(rootsbindir, alias))
+# endforeach
+#
+# if conf.get('ENABLE_BACKLIGHT') == 1
+# executable('systemd-backlight',
+# 'src/backlight/backlight.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+# endif
+#
+# if conf.get('ENABLE_RFKILL') == 1
+# executable('systemd-rfkill',
+# 'src/rfkill/rfkill.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+# endif
+#
+# executable('systemd-system-update-generator',
+# 'src/system-update-generator/system-update-generator.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : systemgeneratordir)
+#
+# if conf.get('HAVE_LIBCRYPTSETUP') == 1
+# executable('systemd-cryptsetup',
+# 'src/cryptsetup/cryptsetup.c',
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [libcryptsetup],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# executable('systemd-cryptsetup-generator',
+# 'src/cryptsetup/cryptsetup-generator.c',
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [libcryptsetup],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : systemgeneratordir)
+#
+# executable('systemd-veritysetup',
+# 'src/veritysetup/veritysetup.c',
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [libcryptsetup],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# executable('systemd-veritysetup-generator',
+# 'src/veritysetup/veritysetup-generator.c',
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [libcryptsetup],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : systemgeneratordir)
+# endif
+#
+# if conf.get('HAVE_SYSV_COMPAT') == 1
+# executable('systemd-sysv-generator',
+# 'src/sysv-generator/sysv-generator.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : systemgeneratordir)
+#
+# executable('systemd-rc-local-generator',
+# 'src/rc-local-generator/rc-local-generator.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : systemgeneratordir)
+# endif
+#
+# if conf.get('ENABLE_HOSTNAMED') == 1
+# executable('systemd-hostnamed',
+# 'src/hostname/hostnamed.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# exe = executable('hostnamectl',
+# 'src/hostname/hostnamectl.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true)
+# public_programs += [exe]
+# endif
+#
+# if conf.get('ENABLE_LOCALED') == 1
+# if conf.get('HAVE_XKBCOMMON') == 1
+# # logind will load libxkbcommon.so dynamically on its own
+# deps = [libdl]
+# else
+# deps = []
+# endif
+#
+# executable('systemd-localed',
+# systemd_localed_sources,
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : deps,
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# exe = executable('localectl',
+# localectl_sources,
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true)
+# public_programs += [exe]
+# endif
+#
+# if conf.get('ENABLE_TIMEDATED') == 1
+# executable('systemd-timedated',
+# 'src/timedate/timedated.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+# endif
+#
+# if conf.get('ENABLE_TIMEDATECTL') == 1
+# exe = executable('timedatectl',
+# 'src/timedate/timedatectl.c',
+# include_directories : includes,
+# install_rpath : rootlibexecdir,
+# link_with : [libshared],
+# dependencies : [libm],
+# install : true)
+# public_programs += [exe]
+# endif
+#
+# if conf.get('ENABLE_TIMESYNCD') == 1
+# executable('systemd-timesyncd',
+# systemd_timesyncd_sources,
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [threads,
+# libm],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# executable('systemd-time-wait-sync',
+# 'src/time-wait-sync/time-wait-sync.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+# endif
+#
+# if conf.get('ENABLE_MACHINED') == 1
+# executable('systemd-machined',
+# systemd_machined_sources,
+# include_directories : includes,
+# link_with : [libmachine_core,
+# libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# exe = executable('machinectl',
+# 'src/machine/machinectl.c',
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [threads,
+# libxz,
+# liblz4],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootbindir)
+# public_programs += [exe]
+# endif
+#
+# if conf.get('ENABLE_IMPORTD') == 1
+# executable('systemd-importd',
+# systemd_importd_sources,
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [threads],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# systemd_pull = executable('systemd-pull',
+# systemd_pull_sources,
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [libcurl,
+# libz,
+# libbzip2,
+# libxz,
+# libgcrypt],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# systemd_import = executable('systemd-import',
+# systemd_import_sources,
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [libcurl,
+# libz,
+# libbzip2,
+# libxz],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# systemd_export = executable('systemd-export',
+# systemd_export_sources,
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [libcurl,
+# libz,
+# libbzip2,
+# libxz],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+# public_programs += [systemd_pull, systemd_import, systemd_export]
+# endif
+#
+# if conf.get('ENABLE_REMOTE') == 1 and conf.get('HAVE_LIBCURL') == 1
+# exe = executable('systemd-journal-upload',
+# systemd_journal_upload_sources,
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [threads,
+# libcurl,
+# libgnutls,
+# libxz,
+# liblz4],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+# public_programs += [exe]
+# endif
+#
+# if conf.get('ENABLE_REMOTE') == 1 and conf.get('HAVE_MICROHTTPD') == 1
+# s_j_remote = executable('systemd-journal-remote',
+# systemd_journal_remote_sources,
+# include_directories : includes,
+# link_with : [libshared,
+# libsystemd_journal_remote],
+# dependencies : [threads,
+# libmicrohttpd,
+# libgnutls,
+# libxz,
+# liblz4],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# s_j_gatewayd = executable('systemd-journal-gatewayd',
+# systemd_journal_gatewayd_sources,
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [threads,
+# libmicrohttpd,
+# libgnutls,
+# libxz,
+# liblz4],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+# public_programs += [s_j_remote, s_j_gatewayd]
+# endif
+#
+# if conf.get('ENABLE_COREDUMP') == 1
+# executable('systemd-coredump',
+# systemd_coredump_sources,
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [threads,
+# libacl,
+# libdw,
+# libxz,
+# liblz4],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# exe = executable('coredumpctl',
+# coredumpctl_sources,
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [threads,
+# libxz,
+# liblz4],
+# install_rpath : rootlibexecdir,
+# install : true)
+# public_programs += [exe]
+# endif
+#
+# if conf.get('ENABLE_BINFMT') == 1
+# exe = executable('systemd-binfmt',
+# 'src/binfmt/binfmt.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+# public_programs += [exe]
+#
+# meson.add_install_script('sh', '-c',
+# mkdir_p.format(binfmtdir))
+# meson.add_install_script('sh', '-c',
+# mkdir_p.format(join_paths(sysconfdir, 'binfmt.d')))
+# endif
+#
+# if conf.get('ENABLE_VCONSOLE') == 1
+# executable('systemd-vconsole-setup',
+# 'src/vconsole/vconsole-setup.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+# endif
+#
+# if conf.get('ENABLE_RANDOMSEED') == 1
+# executable('systemd-random-seed',
+# 'src/random-seed/random-seed.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+# endif
+#
+# if conf.get('ENABLE_FIRSTBOOT') == 1
+# executable('systemd-firstboot',
+# 'src/firstboot/firstboot.c',
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [libcrypt],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootbindir)
+# endif
+#
+# executable('systemd-remount-fs',
+# 'src/remount-fs/remount-fs.c',
+# 'src/core/mount-setup.c',
+# 'src/core/mount-setup.h',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# executable('systemd-machine-id-setup',
+# 'src/machine-id-setup/machine-id-setup-main.c',
+# 'src/core/machine-id-setup.c',
+# 'src/core/machine-id-setup.h',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootbindir)
+#
+# executable('systemd-fsck',
+# 'src/fsck/fsck.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# executable('elogind-growfs',
+# 'src/partition/growfs.c',
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [libcryptsetup],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# executable('elogind-makefs',
+# 'src/partition/makefs.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# executable('systemd-sleep',
+# 'src/sleep/sleep.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# exe = executable('systemd-sysctl',
+# 'src/sysctl/sysctl.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+# public_programs += [exe]
+#
+# executable('systemd-ac-power',
+# 'src/ac-power/ac-power.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# exe = executable('systemd-detect-virt',
+# 'src/detect-virt/detect-virt.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true)
+# public_programs += [exe]
+#
+# exe = executable('systemd-delta',
+# 'src/delta/delta.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true)
+# public_programs += [exe]
+#
+# exe = executable('systemd-escape',
+# 'src/escape/escape.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootbindir)
+# public_programs += [exe]
+#
+# exe = executable('systemd-notify',
+# 'src/notify/notify.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootbindir)
+# public_programs += [exe]
+#
+# executable('systemd-volatile-root',
+# 'src/volatile-root/volatile-root.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# executable('systemd-cgroups-agent',
+# 'src/cgroups-agent/cgroups-agent.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#else
+executable('elogind-cgroups-agent',
+ 'src/cgroups-agent/cgroups-agent.c',
+ include_directories : includes,
+ link_with : [libshared],
+ install_rpath : rootlibexecdir,
+ install : true,
+ install_dir : rootlibexecdir)
+#endif // 0
+
+#if 0 /// UNNEEDED by elogind
+# exe = executable('systemd-path',
+# 'src/path/path.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true)
+# public_programs += [exe]
+#
+# exe = executable('systemd-ask-password',
+# 'src/ask-password/ask-password.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootbindir)
+# public_programs += [exe]
+#
+# executable('systemd-reply-password',
+# 'src/reply-password/reply-password.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# exe = executable('systemd-tty-ask-password-agent',
+# 'src/tty-ask-password-agent/tty-ask-password-agent.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootbindir)
+# public_programs += [exe]
+#
+# exe = executable('systemd-cgls',
+# 'src/cgls/cgls.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true)
+# public_programs += [exe]
+#
+# exe = executable('systemd-cgtop',
+# 'src/cgtop/cgtop.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true)
+# public_programs += [exe]
+#
+# executable('systemd-initctl',
+# 'src/initctl/initctl.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# exe = executable('systemd-mount',
+# 'src/mount/mount-tool.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true)
+# public_programs += [exe]
+#
+# meson.add_install_script(meson_make_symlink,
+# 'systemd-mount', join_paths(bindir, 'systemd-umount'))
+#
+# exe = executable('systemd-run',
+# 'src/run/run.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true)
+# public_programs += [exe]
+#
+# exe = executable('systemd-stdio-bridge',
+# 'src/stdio-bridge/stdio-bridge.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true)
+# public_programs += [exe]
+#
+# exe = executable('busctl',
+# 'src/busctl/busctl.c',
+# 'src/busctl/busctl-introspect.c',
+# 'src/busctl/busctl-introspect.h',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true)
+# public_programs += [exe]
+#
+# if conf.get('ENABLE_SYSUSERS') == 1
+# exe = executable('systemd-sysusers',
+# 'src/sysusers/sysusers.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootbindir)
+# public_programs += [exe]
+# endif
+#
+# if conf.get('ENABLE_TMPFILES') == 1
+# exe = executable('systemd-tmpfiles',
+# 'src/tmpfiles/tmpfiles.c',
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [libacl],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootbindir)
+# public_programs += [exe]
+#
+# test('test-systemd-tmpfiles',
+# test_systemd_tmpfiles_py,
+# args : exe.full_path())
+# # https://github.com/mesonbuild/meson/issues/2681
+# endif
+#
+# if conf.get('ENABLE_HWDB') == 1
+# exe = executable('systemd-hwdb',
+# 'src/hwdb/hwdb.c',
+# 'src/libsystemd/sd-hwdb/hwdb-internal.h',
+# include_directories : includes,
+# link_with : [libudev_static],
+# install_rpath : udev_rpath,
+# install : true,
+# install_dir : rootbindir)
+# public_programs += [exe]
+# endif
+#
+# if conf.get('ENABLE_QUOTACHECK') == 1
+# executable('systemd-quotacheck',
+# 'src/quotacheck/quotacheck.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+# endif
+#
+# exe = executable('systemd-socket-proxyd',
+# 'src/socket-proxy/socket-proxyd.c',
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [threads],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+# public_programs += [exe]
+#
+# exe = executable('systemd-udevd',
+# systemd_udevd_sources,
+# include_directories : includes,
+# c_args : ['-DLOG_REALM=LOG_REALM_UDEV'],
+# link_with : [libudev_core,
+# libsystemd_network,
+# libudev_static],
+# dependencies : [threads,
+# libkmod,
+# libidn,
+# libacl,
+# libblkid],
+# install_rpath : udev_rpath,
+# install : true,
+# install_dir : rootlibexecdir)
+# public_programs += [exe]
+#
+# exe = executable('udevadm',
+# udevadm_sources,
+# c_args : ['-DLOG_REALM=LOG_REALM_UDEV'],
+# include_directories : includes,
+# link_with : [libudev_core,
+# libsystemd_network,
+# libudev_static],
+# dependencies : [threads,
+# libkmod,
+# libidn,
+# libacl,
+# libblkid],
+# install_rpath : udev_rpath,
+# install : true,
+# install_dir : rootbindir)
+# public_programs += [exe]
+#
+# executable('systemd-shutdown',
+# systemd_shutdown_sources,
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [libmount],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# executable('systemd-update-done',
+# 'src/update-done/update-done.c',
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# executable('systemd-update-utmp',
+# 'src/update-utmp/update-utmp.c',
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [libaudit],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# if conf.get('HAVE_KMOD') == 1
+# executable('systemd-modules-load',
+# 'src/modules-load/modules-load.c',
+# include_directories : includes,
+# link_with : [libshared],
+# dependencies : [libkmod],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# meson.add_install_script('sh', '-c',
+# mkdir_p.format(modulesloaddir))
+# meson.add_install_script('sh', '-c',
+# mkdir_p.format(join_paths(sysconfdir, 'modules-load.d')))
+# endif
+#
+# exe = executable('systemd-nspawn',
+# systemd_nspawn_sources,
+# 'src/core/mount-setup.c', # FIXME: use a variable?
+# 'src/core/mount-setup.h',
+# 'src/core/loopback-setup.c',
+# 'src/core/loopback-setup.h',
+# include_directories : includes,
+# link_with : [libnspawn_core,
+# libshared],
+# dependencies : [libblkid],
+# install_rpath : rootlibexecdir,
+# install : true)
+# public_programs += [exe]
+#
+# if conf.get('ENABLE_NETWORKD') == 1
+# executable('systemd-networkd',
+# systemd_networkd_sources,
+# include_directories : includes,
+# link_with : [libnetworkd_core,
+# libsystemd_network,
+# libudev_static,
+# libshared],
+# dependencies : [threads],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# executable('systemd-networkd-wait-online',
+# systemd_networkd_wait_online_sources,
+# include_directories : includes,
+# link_with : [libnetworkd_core,
+# libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#
+# exe = executable('networkctl',
+# networkctl_sources,
+# include_directories : includes,
+# link_with : [libsystemd_network,
+# libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootbindir)
+# public_programs += [exe]
+# endif
+#
+# executable('systemd-sulogin-shell',
+# ['src/sulogin-shell/sulogin-shell.c'],
+# include_directories : includes,
+# link_with : [libshared],
+# install_rpath : rootlibexecdir,
+# install : true,
+# install_dir : rootlibexecdir)
+#else
+executable('elogind-uaccess-command',
+ 'src/uaccess-command/uaccess-command.c',
+ include_directories : includes,
+ link_with : [liblogind_core,
+ libshared],
+ dependencies: [libacl,
+ libudev],
+ install_rpath : rootlibexecdir,
+ install : true,
+ install_dir : rootlibexecdir)
+#endif // 0
+
+############################################################
+
+foreach tuple : tests
+ sources = tuple[0]
+ link_with = tuple[1].length() > 0 ? tuple[1] : [libshared]
+ dependencies = tuple[2]
+ condition = tuple.length() >= 4 ? tuple[3] : ''
+ type = tuple.length() >= 5 ? tuple[4] : ''
+ defs = tuple.length() >= 6 ? tuple[5] : []
+ incs = tuple.length() >= 7 ? tuple[6] : includes
+ timeout = 30
+
+ name = sources[0].split('/')[-1].split('.')[0]
+ if type.startswith('timeout=')
+ timeout = type.split('=')[1].to_int()
+ type = ''
+ endif
+ if want_tests == 'false'
+ message('Not compiling @0@ because tests is set to false'.format(name))
+ elif condition == '' or conf.get(condition) == 1
+ exe = executable(
+ name,
+ sources,
+ include_directories : incs,
+ link_with : link_with,
+ dependencies : dependencies,
+ c_args : defs,
+ install_rpath : rootlibexecdir,
+ install : install_tests,
+ install_dir : join_paths(testsdir, type))
+
+ if type == 'manual'
+ message('@0@ is a manual test'.format(name))
+ elif type == 'unsafe' and want_tests != 'unsafe'
+ message('@0@ is an unsafe test'.format(name))
+ else
+ test(name, exe,
+ env : test_env,
+ timeout : timeout)
+ endif
+ else
+ message('Not compiling @0@ because @1@ is not true'.format(name, condition))
+ endif
+endforeach
+
+#if 0 /// UNNEEDED by elogind
+# exe = executable(
+# 'test-libsystemd-sym',
+# test_libsystemd_sym_c,
+# include_directories : includes,
+# link_with : [libsystemd],
+# install : install_tests,
+# install_dir : testsdir)
+# test('test-libsystemd-sym', exe)
+#
+# exe = executable(
+# 'test-libsystemd-static-sym',
+# test_libsystemd_sym_c,
+# include_directories : includes,
+# link_with : [install_libsystemd_static],
+# dependencies : [threads], # threads is already included in dependencies on the library,
+# # but does not seem to get propagated. Add here as a work-around.
+# build_by_default : static_libsystemd_pic,
+# install : install_tests and static_libsystemd_pic,
+# install_dir : testsdir)
+# if static_libsystemd_pic
+# test('test-libsystemd-static-sym', exe)
+# endif
+#
+# exe = executable(
+# 'test-libudev-sym',
+# test_libudev_sym_c,
+# include_directories : includes,
+# c_args : ['-Wno-deprecated-declarations'],
+# link_with : [libudev],
+# install : install_tests,
+# install_dir : testsdir)
+# test('test-libudev-sym', exe)
+#
+# exe = executable(
+# 'test-libudev-static-sym',
+# test_libudev_sym_c,
+# include_directories : includes,
+# c_args : ['-Wno-deprecated-declarations'],
+# link_with : [install_libudev_static],
+# build_by_default : static_libudev_pic,
+# install : install_tests and static_libudev_pic,
+# install_dir : testsdir)
+# if static_libudev_pic
+# test('test-libudev-static-sym', exe)
+# endif
+#
+# ############################################################
+#
+# fuzzer_exes = []
+#
+# foreach tuple : fuzzers
+# sources = tuple[0]
+# link_with = tuple[1].length() > 0 ? tuple[1] : [libshared]
+# dependencies = tuple[2]
+# defs = tuple.length() >= 4 ? tuple[3] : []
+# incs = tuple.length() >= 5 ? tuple[4] : includes
+#
+# if fuzzer_build
+# dependencies += fuzzing_engine
+# else
+# sources += 'src/fuzz/fuzz-main.c'
+# endif
+#
+# name = sources[0].split('/')[-1].split('.')[0]
+#
+# fuzzer_exes += executable(
+# name,
+# sources,
+# include_directories : [incs, include_directories('src/fuzz')],
+# link_with : link_with,
+# dependencies : dependencies,
+# c_args : defs,
+# install : false)
+# endforeach
+#
+# run_target('fuzzers',
+# depends : fuzzer_exes,
+# command : ['true'])
+#
+# ############################################################
+#
+#else
+test_libelogind_sym = executable(
+ 'test-libelogind-sym',
+ test_libelogind_sym_c,
+ include_directories : includes,
+ link_with : [libelogind],
+ install : install_tests,
+ install_dir : testsdir)
+test('test-libelogind-sym',
+ test_libelogind_sym)
+#endif // 0
+make_directive_index_py = find_program('tools/make-directive-index.py')
+make_man_index_py = find_program('tools/make-man-index.py')
+xml_helper_py = find_program('tools/xml_helper.py')
+#if 0 /// UNNEEDED by elogind
+# hwdb_update_sh = find_program('tools/meson-hwdb-update.sh')
+#
+# subdir('units')
+# subdir('sysctl.d')
+# subdir('sysusers.d')
+# subdir('tmpfiles.d')
+# subdir('presets')
+# subdir('hwdb')
+# subdir('network')
+#endif // 0
+subdir('man')
+subdir('shell-completion/bash')
+subdir('shell-completion/zsh')
+#if 0 /// UNNEEDED by elogind
+# subdir('doc/sysvinit')
+# subdir('doc/var-log')
+#endif // 0
+
+# FIXME: figure out if the warning is true:
+# https://github.com/mesonbuild/meson/wiki/Reference-manual#install_subdir
+install_subdir('factory/etc',
+ install_dir : factorydir)
+
+
+#if 0 /// UNNEEDED by elogind
+# install_data('xorg/50-systemd-user.sh',
+# install_dir : xinitrcdir)
+# install_data('modprobe.d/systemd.conf',
+# install_dir : modprobedir)
+#endif // 0
+install_data('LICENSE.GPL2',
+ 'LICENSE.LGPL2.1',
+ 'NEWS',
+ 'README',
+ 'doc/CODING_STYLE',
+#if 0 /// irrelevant for elogind
+# 'doc/DISTRO_PORTING',
+# 'doc/ENVIRONMENT.md',
+# 'doc/HACKING',
+# 'doc/TRANSIENT-SETTINGS.md',
+# 'doc/TRANSLATORS',
+# 'doc/UIDS-GIDS.md',
+#endif // 0
+ 'src/libelogind/sd-bus/GVARIANT-SERIALIZATION',
+ install_dir : docdir)
+
+#if 0 /// UNNEEDED by elogind
+# meson.add_install_script('sh', '-c', mkdir_p.format(systemdstatedir))
+#endif // 0
+meson.add_install_script('sh', '-c', 'touch $DESTDIR@0@'.format(prefixdir))
+
+############################################################
+
+meson_check_help = find_program('tools/meson-check-help.sh')
+
+foreach exec : public_programs
+ name = exec.full_path().split('/')[-1]
+ test('check-help-' + name,
+ meson_check_help,
+ args : [exec.full_path()])
+endforeach
+
+############################################################
+
+#if 0 /// fuzz regression tests are not supported by elogind
+# # Enable tests for all supported sanitizers
+# foreach tuple : sanitizers
+# sanitizer = tuple[0]
+# build = tuple[1]
+#
+# have = run_command(check_compilation_sh,
+# cc.cmd_array(), '-x', 'c',
+# '-fsanitize=@0@'.format(sanitizer),
+# '-include', link_test_c).returncode() == 0
+# message('@0@ sanitizer supported: @1@'.format(sanitizer, have ? 'yes' : 'no'))
+#
+# if have
+# prev = ''
+# foreach p : fuzz_regression_tests
+# b = p.split('/')[-2]
+# c = p.split('/')[-1]
+#
+# name = '@0@:@1@'.format(b, sanitizer)
+#
+# if name != prev
+# if want_tests == 'false'
+# message('Not compiling @0@ because tests is set to false'.format(name))
+# elif slow_tests
+# exe = custom_target(
+# name,
+# output : name,
+# depends : build,
+# command : [env, 'ln', '-fs',
+# join_paths(build.full_path(), b),
+# '@OUTPUT@'],
+# build_by_default : true)
+# else
+# message('Not compiling @0@ because slow-tests is set to false'.format(name))
+# endif
+# endif
+# prev = name
+#
+# if want_tests != 'false' and slow_tests
+# test('@0@:@1@:@2@'.format(b, c, sanitizer),
+# env,
+# args : [exe.full_path(),
+# join_paths(meson.source_root(),
+# 'test/fuzz-regressions',
+# p)])
+# endif
+# endforeach
+# endif
+# endforeach
+#endif // 0
+
+
+############################################################
+
+if git.found()
+ all_files = run_command(
+ git,
+ ['--git-dir=@0@/.git'.format(meson.current_source_dir()),
+ 'ls-files',
+ ':/*.[ch]'])
+ all_files = files(all_files.stdout().split())
+
+ custom_target(
+ 'tags',
+ output : 'tags',
+ command : [env, 'etags', '-o', '@0@/TAGS'.format(meson.current_source_dir())] + all_files)
+ run_target(
+ 'ctags',
+ command : [env, 'ctags', '-o', '@0@/tags'.format(meson.current_source_dir())] + all_files)
+endif
+
+#if 0 /// UNNEEDED by elogind
+# if git.found()
+# meson_git_contrib_sh = find_program('tools/meson-git-contrib.sh')
+# run_target(
+# 'git-contrib',
+# command : [meson_git_contrib_sh])
+# endif
+#endif // 0
+
+if git.found()
+ git_head = run_command(
+ git,
+ ['--git-dir=@0@/.git'.format(meson.current_source_dir()),
+ 'rev-parse', 'HEAD']).stdout().strip()
+ git_head_short = run_command(
+ git,
+ ['--git-dir=@0@/.git'.format(meson.current_source_dir()),
+ 'rev-parse', '--short=7', 'HEAD']).stdout().strip()
+
+ run_target(
+ 'git-snapshot',
+ command : ['git', 'archive',
+ '-o', '@0@/systemd-@1@.tar.gz'.format(meson.current_source_dir(),
+ git_head_short),
+ '--prefix', 'systemd-@0@/'.format(git_head),
+ 'HEAD'])
+endif
+
+############################################################
+
+meson_check_api_docs_sh = find_program('tools/meson-check-api-docs.sh')
+run_target(
+ 'check-api-docs',
+#if 0 /// libudev is external, elogind does not need to document it.
+# depends : [man, libsystemd, libudev],
+# command : [meson_check_api_docs_sh, libsystemd.full_path(), libudev.full_path()])
+#else
+ depends : [man, libelogind],
+ command : [meson_check_api_docs_sh, libelogind.full_path()])
+#endif // 0
+
+############################################################
+
+status = [
+ '@0@ @1@'.format(meson.project_name(), meson.project_version()),
+
+ 'split /usr: @0@'.format(split_usr),
+ 'split bin-sbin: @0@'.format(split_bin),
+ 'prefix directory: @0@'.format(prefixdir),
+ 'rootprefix directory: @0@'.format(rootprefixdir),
+ 'sysconf directory: @0@'.format(sysconfdir),
+ 'include directory: @0@'.format(includedir),
+ 'lib directory: @0@'.format(libdir),
+ 'rootlib directory: @0@'.format(rootlibdir),
+#if 1 /// Needed by elogind
+ 'rootexeclib dir: @0@'.format(rootlibexecdir),
+#endif // 1
+#if 0 /// UNNEEDED by elogind
+# 'SysV init scripts: @0@'.format(sysvinit_path),
+# 'SysV rc?.d directories: @0@'.format(sysvrcnd_path),
+#endif // 0
+ 'PAM modules directory: @0@'.format(pamlibdir),
+ 'PAM configuration directory: @0@'.format(pamconfdir),
+#if 0 /// UNNEEDED by elogind
+# 'RPM macros directory: @0@'.format(rpmmacrosdir),
+#endif // 0
+ 'modprobe.d directory: @0@'.format(modprobedir),
+ 'D-Bus policy directory: @0@'.format(dbuspolicydir),
+ 'D-Bus session directory: @0@'.format(dbussessionservicedir),
+ 'D-Bus system directory: @0@'.format(dbussystemservicedir),
+ 'bash completions directory: @0@'.format(bashcompletiondir),
+ 'zsh completions directory: @0@'.format(zshcompletiondir),
+#if 0 /// UNSUPPORTED by elogind
+# 'extra start script: @0@'.format(get_option('rc-local')),
+# 'extra stop script: @0@'.format(get_option('halt-local')),
+# 'debug shell: @0@ @ @1@'.format(get_option('debug-shell'),
+# get_option('debug-tty')),
+#endif // 0
+ 'TTY GID: @0@'.format(tty_gid),
+#if 0 /// UNSUPPORTED by elogind
+# 'users GID: @0@'.format(users_gid),
+#endif // 0
+ 'maximum system UID: @0@'.format(system_uid_max),
+ 'maximum system GID: @0@'.format(system_gid_max),
+#if 0 /// UNSUPPORTED by elogind
+# 'minimum dynamic UID: @0@'.format(dynamic_uid_min),
+# 'maximum dynamic UID: @0@'.format(dynamic_uid_max),
+# 'minimum container UID base: @0@'.format(container_uid_base_min),
+# 'maximum container UID base: @0@'.format(container_uid_base_max),
+# '/dev/kvm access mode: @0@'.format(get_option('dev-kvm-mode')),
+# 'render group access mode: @0@'.format(get_option('group-render-mode')),
+# 'certificate root directory: @0@'.format(get_option('certificate-root')),
+# 'support URL: @0@'.format(support_url),
+#endif // 0
+ 'nobody user name: @0@'.format(nobody_user),
+ 'nobody group name: @0@'.format(nobody_group),
+#if 0 /// UNSUPPORTED by elogind
+# 'fallback hostname: @0@'.format(get_option('fallback-hostname')),
+# 'symbolic gateway hostnames: @0@'.format(', '.join(gateway_hostnames)),
+#
+# 'default DNSSEC mode: @0@'.format(default_dnssec),
+# 'default DNS-over-TLS mode: @0@'.format(default_dns_over_tls),
+# 'default cgroup hierarchy: @0@'.format(default_hierarchy),
+#endif // 0
+ 'default KillUserProcesses setting: @0@'.format(kill_user_processes)]
+
+#if 0 /// UNSUPPORTED by elogind
+# alt_dns_servers = '\n '.join(dns_servers.split(' '))
+# alt_ntp_servers = '\n '.join(ntp_servers.split(' '))
+# status += [
+# 'default DNS servers: @0@'.format(alt_dns_servers),
+# 'default NTP servers: @0@'.format(alt_ntp_servers)]
+#
+# alt_time_epoch = run_command('date', '-Is', '-u', '-d',
+# '@@0@'.format(time_epoch)).stdout().strip()
+# status += [
+# 'time epoch: @0@ (@1@)'.format(time_epoch, alt_time_epoch)]
+#endif // 0
+
+# TODO:
+# CFLAGS: ${OUR_CFLAGS} ${CFLAGS}
+# CPPFLAGS: ${OUR_CPPFLAGS} ${CPPFLAGS}
+# LDFLAGS: ${OUR_LDFLAGS} ${LDFLAGS}
+
+#if 0 /// UNNEEDED by elogind
+# if conf.get('ENABLE_EFI') == 1
+# status += [
+# 'efi arch: @0@'.format(efi_arch)]
+#
+# if have_gnu_efi
+# status += [
+# 'EFI machine type: @0@'.format(EFI_MACHINE_TYPE_NAME),
+# 'EFI CC @0@'.format(efi_cc),
+# 'EFI lib directory: @0@'.format(efi_libdir),
+# 'EFI lds directory: @0@'.format(efi_ldsdir),
+# 'EFI include directory: @0@'.format(efi_incdir)]
+# endif
+# endif
+#endif // 0
+
+found = []
+missing = []
+
+foreach tuple : [
+#if 0 /// UNNEEDED by elogind
+# ['libcryptsetup'],
+#endif // 0
+ ['PAM'],
+ ['AUDIT'],
+#if 0 /// UNNEEDED by elogind
+# ['IMA'],
+# ['AppArmor'],
+#endif // 0
+ ['SELinux'],
+#if 0 /// UNNEEDED by elogind
+# ['SECCOMP'],
+#endif // 0
+ ['SMACK'],
+#if 0 /// UNNEEDED by elogind
+# ['zlib'],
+# ['xz'],
+# ['lz4'],
+# ['bzip2'],
+#endif // 0
+ ['ACL'],
+#if 0 /// UNNEEDED by elogind
+# ['gcrypt'],
+# ['qrencode'],
+# ['microhttpd'],
+# ['gnutls'],
+# ['libcurl'],
+# ['idn'],
+# ['libidn2'],
+# ['libidn'],
+# ['nss-systemd'],
+# ['libiptc'],
+# ['elfutils'],
+# ['binfmt'],
+# ['vconsole'],
+# ['quotacheck'],
+# ['tmpfiles'],
+# ['environment.d'],
+# ['sysusers'],
+# ['firstboot'],
+# ['randomseed'],
+# ['backlight'],
+# ['rfkill'],
+# ['logind'],
+# ['machined'],
+# ['portabled'],
+# ['importd'],
+# ['hostnamed'],
+# ['timedated'],
+# ['timesyncd'],
+# ['localed'],
+# ['networkd'],
+# ['resolve'],
+# ['DNS-over-TLS'],
+# ['coredump'],
+#endif // 0
+ ['polkit'],
+ ['legacy pkla', install_polkit_pkla],
+#if 0 /// UNNEEDED by elogind
+# ['efi'],
+# ['gnu-efi', have_gnu_efi],
+# ['kmod'],
+# ['xkbcommon'],
+# ['pcre2'],
+# ['blkid'],
+#endif // 0
+ ['dbus'],
+ ['glib'],
+#if 0 /// UNNEEDED by elogind
+# ['nss-myhostname', conf.get('ENABLE_MYHOSTNAME') == 1],
+# ['hwdb'],
+# ['tpm'],
+#endif // 0
+ ['man pages', want_man],
+ ['html pages', want_html],
+ ['man page indices', want_man and have_lxml],
+#if 0 /// UNNEEDED by elogind
+# ['SysV compat'],
+#endif // 0
+ ['utmp'],
+#if 0 /// UNNEEDED by elogind
+# ['ldconfig'],
+# ['hibernate'],
+# ['adm group', get_option('adm-group')],
+# ['wheel group', get_option('wheel-group')],
+# ['gshadow'],
+#endif // 0
+ ['valgrind', conf.get('VALGRIND') == 1],
+#if 1 /// Extra debugging for elogind
+ ['debug elogind'],
+#endif // 1
+ ['debug hashmap'],
+ ['debug mmap cache'],
+]
+
+ if tuple.length() >= 2
+ cond = tuple[1]
+ else
+ ident1 = 'HAVE_' + tuple[0].underscorify().to_upper()
+ ident2 = 'ENABLE_' + tuple[0].underscorify().to_upper()
+ cond = conf.get(ident1, 0) == 1 or conf.get(ident2, 0) == 1
+ endif
+ if cond
+ found += [tuple[0]]
+ else
+ missing += [tuple[0]]
+ endif
+endforeach
+
+status += [
+ '',
+ 'enabled features: @0@'.format(', '.join(found)),
+ '',
+ 'disabled features: @0@'.format(', '.join(missing)),
+ '']
+message('\n '.join(status))
+
+#if 0 /// Nicely enough this isn't true for elogind. :-)
+# if rootprefixdir != rootprefix_default
+# warning('\n' +
+# 'Note that the installation prefix was changed to "@0@".\n'.format(rootprefixdir) +
+# 'systemd used fixed names for unit file directories and other paths, so anything\n' +
+# 'except the default ("@0@") is strongly discouraged.'.format(rootprefix_default))
+# endif
+#endif // 0
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 000000000..05f80ba1a
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,385 @@
+# -*- mode: meson -*-
+# SPDX-License-Identifier: LGPL-2.1+
+
+option('split-usr', type : 'combo', choices : ['auto', 'true', 'false'],
+ description : '''/bin, /sbin aren't symlinks into /usr''')
+option('split-bin', type : 'combo', choices : ['auto', 'true', 'false'],
+ description : '''sbin is not a symlink to bin''')
+option('rootlibdir', type : 'string',
+ description : '''[/usr]/lib/x86_64-linux-gnu or such''')
+option('rootprefix', type : 'string',
+ description : '''override the root prefix''')
+#if 0 /// UNNEEDED by elogind
+# option('link-udev-shared', type : 'boolean',
+# description : 'link systemd-udev and its helpers to libsystemd-shared.so')
+# option('link-systemctl-shared', type: 'boolean',
+# description : 'link systemctl against libsystemd-shared.so')
+#endif // 0
+option('static-libelogind', type : 'combo',
+ choices : ['false', 'true', 'pic', 'no-pic'],
+ description : '''install a static library for libelogind''')
+#if 0 /// UNNEEDED by elogind
+# option('static-libudev', type : 'combo',
+# choices : ['false', 'true', 'pic', 'no-pic'],
+# description : '''install a static library for libudev''')
+#
+# option('sysvinit-path', type : 'string', value : '/etc/init.d',
+# description : 'the directory where the SysV init scripts are located')
+# option('sysvrcnd-path', type : 'string', value : '/etc/rc.d',
+# description : 'the base directory for SysV rcN.d directories')
+# option('telinit-path', type : 'string', value : '/lib/sysvinit/telinit',
+# description : 'path to telinit')
+# option('rc-local', type : 'string',
+# value : '/etc/rc.local')
+# option('halt-local', type : 'string',
+# value : '/usr/sbin/halt.local')
+#
+# option('quotaon-path', type : 'string', description : 'path to quotaon')
+# option('quotacheck-path', type : 'string', description : 'path to quotacheck')
+# option('kill-path', type : 'string', description : 'path to kill')
+# option('kmod-path', type : 'string', description : 'path to kmod')
+#else
+# elogind must have a configurable rootlibexecdir
+option('rootlibexecdir', type : 'string',
+ description : '''override the root libexec directory path''')
+
+# And because elogind depends on external udev, it must be
+# configurable as well.
+option('udevrulesdir', type : 'string',
+ description : '''directory for udev rules files''')
+
+option('udevbindir', type : 'string',
+ description : '''directory for udev binary files''')
+
+# We are nice and make the documentation paths configurable
+option('docdir', type : 'string', description : 'path where to install the documentation.')
+option('htmldir', type : 'string', description : 'path where to install the HTML documentation.')
+
+# We have no systemd-shutdown binary, so we need 'halt', 'reboot' and 'poweroff'
+option('halt-path', type : 'string', description : 'path to halt')
+option('poweroff-path', type : 'string', description : 'path to poweroff')
+option('reboot-path', type : 'string', description : 'path to reboot')
+#endif // 0
+option('kexec-path', type : 'string', description : 'path to kexec')
+#if 0 /// UNNEEDED by elogind
+# option('sulogin-path', type : 'string', description : 'path to sulogin')
+# option('mount-path', type : 'string', description : 'path to mount')
+# option('umount-path', type : 'string', description : 'path to umount')
+# option('loadkeys-path', type : 'string', description : 'path to loadkeys')
+# option('setfont-path', type : 'string', description : 'path to setfont')
+#
+# option('debug-shell', type : 'string', value : '/bin/sh',
+# description : 'path to debug shell binary')
+# option('debug-tty', type : 'string', value : '/dev/tty9',
+# description : 'specify the tty device for debug shell')
+# option('debug-extra', type : 'array', choices : ['hashmap', 'mmap-cache'], value : [],
+# description : 'enable extra debugging')
+# option('memory-accounting-default', type : 'boolean',
+# description : 'enable MemoryAccounting= by default')
+#endif // 0
+option('valgrind', type : 'boolean', value : false,
+ description : 'do extra operations to avoid valgrind warnings')
+#if 1 /// Add an extra debugging option for elogind
+option('debug-extra', type : 'array', choices : ['elogind', 'hashmap', 'mmap-cache'], value : [],
+ description : 'enable extra debugging')
+#endif // 1
+
+option('utmp', type : 'boolean',
+ description : 'support for utmp/wtmp log handling')
+#if 0 /// UNNEEDED by elogind
+# option('hibernate', type : 'boolean',
+# description : 'support for hibernation')
+# option('ldconfig', type : 'boolean',
+# description : 'support for dynamic linker cache creation')
+# option('resolve', type : 'boolean',
+# description : 'systemd-resolved stack')
+# option('efi', type : 'boolean',
+# description : 'enable systemd-boot and bootctl')
+# option('tpm', type : 'boolean',
+# description : 'TPM should be used to log events and extend the registers')
+# option('environment-d', type : 'boolean',
+# description : 'support for environment.d')
+# option('binfmt', type : 'boolean',
+# description : 'support for custom binary formats')
+# option('coredump', type : 'boolean',
+# description : 'install the coredump handler')
+# option('logind', type : 'boolean',
+# description : 'install the systemd-logind stack')
+# option('hostnamed', type : 'boolean',
+# description : 'install the systemd-hostnamed stack')
+# option('localed', type : 'boolean',
+# description : 'install the systemd-localed stack')
+# option('machined', type : 'boolean',
+# description : 'install the systemd-machined stack')
+# option('portabled', type : 'boolean',
+# description : 'install the systemd-portabled stack')
+# option('networkd', type : 'boolean',
+# description : 'install the systemd-networkd stack')
+# option('timedated', type : 'boolean',
+# description : 'install the systemd-timedated daemon')
+# option('timesyncd', type : 'boolean',
+# description : 'install the systemd-timesyncd daemon')
+# option('remote', type : 'combo', choices : ['auto', 'true', 'false'],
+# description : 'support for "journal over the network"')
+# option('myhostname', type : 'boolean',
+# description : 'nss-myhostname support')
+# option('firstboot', type : 'boolean',
+# description : 'support for firstboot mechanism')
+# option('randomseed', type : 'boolean',
+# description : 'support for restoring random seed')
+# option('backlight', type : 'boolean',
+# description : 'support for restoring backlight state')
+# option('vconsole', type : 'boolean',
+# description : 'support for vconsole configuration')
+# option('quotacheck', type : 'boolean',
+# description : 'support for the quotacheck tools')
+# option('sysusers', type : 'boolean',
+# description : 'support for the sysusers configuration')
+# option('tmpfiles', type : 'boolean',
+# description : 'support for tmpfiles.d')
+# option('importd', type : 'combo', choices : ['auto', 'true', 'false'],
+# description : 'install the systemd-importd daemon')
+# option('hwdb', type : 'boolean',
+# description : 'support for the hardware database')
+# option('rfkill', type : 'boolean',
+# description : 'support for the rfkill tools')
+#endif // 0
+option('man', type : 'combo', choices : ['auto', 'true', 'false'],
+ description : 'build and install man pages')
+option('html', type : 'combo', choices : ['auto', 'true', 'false'],
+ value : 'false',
+ description : 'build and install html pages')
+
+#if 0 /// UNNEEDED by elogind
+# option('certificate-root', type : 'string', value : '/etc/ssl',
+# description : 'the prefix for TLS certificates')
+#endif // 0
+option('dbuspolicydir', type : 'string',
+ description : 'D-Bus policy directory')
+option('dbussessionservicedir', type : 'string',
+ description : 'D-Bus session service directory')
+option('dbussystemservicedir', type : 'string',
+ description : 'D-Bus system service directory')
+option('pkgconfigdatadir', type : 'string', value : 'share/pkgconfig',
+ description : 'directory for ')
+option('pkgconfiglibdir', type : 'string', value : '',
+ description : 'directory for ')
+#if 0 /// UNNEEDED by elogind
+# option('rpmmacrosdir', type : 'string', value : 'lib/rpm/macros.d',
+# description : 'directory for rpm macros ["no" disables]')
+#endif // 0
+option('pamlibdir', type : 'string',
+ description : 'directory for PAM modules')
+option('pamconfdir', type : 'string',
+ description : 'directory for PAM configuration ["no" disables]')
+option('docdir', type : 'string',
+ description : 'documentation directory')
+
+option('fallback-hostname', type : 'string', value : 'localhost',
+ description : 'the hostname used if none configured')
+#if 0 /// UNNEEDED by elogind
+# option('compat-gateway-hostname', type : 'boolean', value : 'false',
+# description : 'allow "gateway" as the symbolic name for default gateway')
+#endif // 0
+option('default-hierarchy', type : 'combo',
+ choices : ['legacy', 'hybrid', 'unified'], value : 'hybrid',
+#if 0 /// elogind interprets this a bit different
+# description : 'default cgroup hierarchy')
+# option('time-epoch', type : 'string',
+# description : 'time epoch for time clients')
+#else
+ description : '''Wanted cgroup hierarchy if elogind has to be a cgroup controller:
+ "legacy" assumes tmpfs mounted on /sys/fs/cgroup and cgroup on its
+ subfolders.
+ "hybrid" assumes cgroups version 2 mounted on /sys/fs/cgroup/unified.
+ /sys/fs/cgroup is legacy, then.
+ "unified" assumes cgroups version 2 on /sys/fs/cgroup''')
+option('cgroup-controller', type : 'string',
+ description : 'Name of the cgroup controller to use')
+#endif // 0
+option('system-uid-max', type : 'string',
+ description : 'maximum system UID')
+option('system-gid-max', type : 'string',
+ description : 'maximum system GID')
+#if 0 /// UNNEEDED by elogind
+# option('dynamic-uid-min', type : 'string',
+# description : 'minimum dynamic UID',
+# value : '61184') # That's → 0x0000EF00 in hex
+# option('dynamic-uid-max', type : 'string',
+# description : 'maximum dynamic UID',
+# value : '65519') # That's → 0x0000FFEF in hex
+# option('container-uid-base-min', type : 'string',
+# description : 'minimum container UID base',
+# value : '524288') # That's → 0x00080000 in hex
+# option('container-uid-base-max', type : 'string',
+# description : 'maximum container UID base',
+# value : '1878982656') # That's → 0x6FFF0000 in hex
+#endif // 0
+option('tty-gid', type : 'string',
+ description : 'the numeric GID of the "tty" group',
+ value : '5')
+#if 0 /// UNNEEDED by elogind
+# option('users-gid', type : 'string',
+# description : 'the numeric GID of the "users" group')
+# option('adm-group', type : 'boolean',
+# description : 'the ACL for adm group should be added')
+# option('wheel-group', type : 'boolean',
+# description : 'the ACL for wheel group should be added')
+#endif // 0
+option('nobody-user', type : 'string',
+ description : 'The name of the nobody user (the one with UID 65534)',
+ value : 'nobody')
+option('nobody-group', type : 'string',
+ description : 'The name of the nobody group (the one with GID 65534)',
+ value : 'nobody')
+#if 0 /// UNNEEDED by elogind
+# option('dev-kvm-mode', type : 'string', value : '0666',
+# description : '/dev/kvm access mode')
+# option('group-render-mode', type : 'string', value : '0666',
+# description : 'Access mode for devices owned by render group (e.g. /dev/dri/renderD*, /dev/kfd).')
+#endif // 0
+option('default-kill-user-processes', type : 'boolean',
+ description : 'the default value for KillUserProcesses= setting')
+option('gshadow', type : 'boolean',
+ description : 'support for shadow group')
+
+#if 0 /// UNNEEDED by elogind
+# option('default-dnssec', type : 'combo',
+# description : 'default DNSSEC mode',
+# choices : ['yes', 'allow-downgrade', 'no'],
+# value : 'allow-downgrade')
+# option('default-dns-over-tls', type : 'combo',
+# description : 'default DNS-over-TLS mode',
+# choices : ['opportunistic', 'no'],
+# value : 'no')
+# option('dns-over-tls', type : 'combo', choices : ['auto', 'true', 'false'],
+# description : 'DNS-over-TLS support')
+# option('dns-servers', type : 'string',
+# description : 'space-separated list of default DNS servers',
+# value : '8.8.8.8 8.8.4.4 2001:4860:4860::8888 2001:4860:4860::8844')
+# option('ntp-servers', type : 'string',
+# description : 'space-separated list of default NTP servers',
+# value : 'time1.google.com time2.google.com time3.google.com time4.google.com')
+# option('support-url', type : 'string',
+# description : 'the support URL to show in catalog entries included in systemd',
+# value : 'https://lists.freedesktop.org/mailman/listinfo/systemd-devel')
+# option('www-target', type : 'string',
+# description : 'the address and dir to upload docs too',
+# value : 'www.freedesktop.org:/srv/www.freedesktop.org/www/software/systemd')
+#
+# option('seccomp', type : 'combo', choices : ['auto', 'true', 'false'],
+# description : 'SECCOMP support')
+#endif // 0
+option('selinux', type : 'combo', choices : ['auto', 'true', 'false'],
+ description : 'SELinux support')
+#if 0 /// UNNEEDED by elogind
+# option('apparmor', type : 'combo', choices : ['auto', 'true', 'false'],
+# description : 'AppArmor support')
+#endif // 0
+option('smack', type : 'boolean',
+ description : 'SMACK support')
+option('smack-run-label', type : 'string',
+ description : 'run systemd --system itself with a specific SMACK label')
+option('polkit', type : 'combo', choices : ['auto', 'true', 'false'],
+ description : 'PolicyKit support')
+option('ima', type : 'boolean',
+ description : 'IMA support')
+
+option('acl', type : 'combo', choices : ['auto', 'true', 'false'],
+ description : 'libacl support')
+option('audit', type : 'combo', choices : ['auto', 'true', 'false'],
+ description : 'libaudit support')
+#if 0 /// UNNEEDED by elogind
+# option('blkid', type : 'combo', choices : ['auto', 'true', 'false'],
+# description : 'libblkid support')
+# option('kmod', type : 'combo', choices : ['auto', 'true', 'false'],
+# description : 'support for loadable modules')
+#endif // 0
+option('pam', type : 'combo', choices : ['auto', 'true', 'false'],
+ description : 'PAM support')
+#if 0 /// UNNEEDED by elogind
+# option('microhttpd', type : 'combo', choices : ['auto', 'true', 'false'],
+# description : 'libµhttpd support')
+# option('libcryptsetup', type : 'combo', choices : ['auto', 'true', 'false'],
+# description : 'libcryptsetup support')
+# option('libcurl', type : 'combo', choices : ['auto', 'true', 'false'],
+# description : 'libcurl support')
+# option('idn', type : 'boolean',
+# description : 'use IDN when printing host names')
+# option('libidn2', type : 'combo', choices : ['auto', 'true', 'false'],
+# description : 'libidn2 support')
+# option('libidn', type : 'combo', choices : ['auto', 'true', 'false'],
+# description : 'libidn support')
+# option('nss-systemd', type : 'boolean',
+# description : 'enable nss-systemd')
+# option('libiptc', type : 'combo', choices : ['auto', 'true', 'false'],
+# description : 'libiptc support')
+# option('qrencode', type : 'combo', choices : ['auto', 'true', 'false'],
+# description : 'libqrencode support')
+# option('gcrypt', type : 'combo', choices : ['auto', 'true', 'false'],
+# description : 'gcrypt support')
+# option('gnutls', type : 'combo', choices : ['auto', 'true', 'false'],
+# description : 'gnutls support')
+# option('elfutils', type : 'combo', choices : ['auto', 'true', 'false'],
+# description : 'elfutils support')
+# option('zlib', type : 'combo', choices : ['auto', 'true', 'false'],
+# description : 'zlib compression support')
+# option('bzip2', type : 'combo', choices : ['auto', 'true', 'false'],
+# description : 'bzip2 compression support')
+# option('xz', type : 'combo', choices : ['auto', 'true', 'false'],
+# description : 'xz compression support')
+# option('lz4', type : 'combo', choices : ['auto', 'true', 'false'],
+# description : 'lz4 compression support')
+# option('xkbcommon', type : 'combo', choices : ['auto', 'true', 'false'],
+# description : 'xkbcommon keymap support')
+#endif // 0
+option('pcre2', type : 'combo', choices : ['auto', 'true', 'false'],
+ description : 'regexp matching support using pcre2')
+option('glib', type : 'combo', choices : ['auto', 'true', 'false'],
+ description : 'libglib support (for tests only)')
+option('dbus', type : 'combo', choices : ['auto', 'true', 'false'],
+ description : 'libdbus support (for tests only)')
+
+#if 0 /// UNNEEDED BY elogind
+# option('gnu-efi', type : 'combo', choices : ['auto', 'true', 'false'],
+# description : 'gnu-efi support for sd-boot')
+# option('efi-cc', type : 'string', value : 'gcc',
+# description : 'the compiler to use for EFI modules')
+# option('efi-ld', type : 'string', value : 'ld',
+# description : 'the linker to use for EFI modules')
+# option('efi-libdir', type : 'string',
+# description : 'path to the EFI lib directory')
+# option('efi-ldsdir', type : 'string',
+# description : 'path to the EFI lds directory')
+# option('efi-includedir', type : 'string', value : '/usr/include/efi',
+# description : 'path to the EFI header directory')
+# option('tpm-pcrindex', type : 'string', value : '8',
+# description : 'TPM PCR register number to use')
+#endif // 0
+
+option('bashcompletiondir', type : 'string',
+ description : 'directory for bash completion scripts ["no" disables]')
+option('zshcompletiondir', type : 'string',
+ description : 'directory for zsh completion scripts ["no" disables]')
+
+option('tests', type : 'combo', choices : ['true', 'unsafe', 'false'],
+ description : 'enable extra tests with =unsafe')
+option('slow-tests', type : 'boolean', value : 'false',
+ description : 'run the slow tests by default')
+option('install-tests', type : 'boolean', value : 'false',
+ description : 'install test executables')
+
+option('ok-color', type: 'combo',
+ choices : ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan',
+ 'white', 'highlight-black', 'highlight-red', 'highlight-green',
+ 'highlight-yellow', 'highlight-blue', 'highlight-magenta',
+ 'highlight-cyan', 'highlight-white'],
+ value : 'green',
+ description: 'color of the "OK" status message')
+
+#if 0 /// fuzz regression tests are not supported by elogind
+# option('oss-fuzz', type : 'boolean', value : 'false',
+# description : 'build against oss-fuzz')
+# option('llvm-fuzz', type : 'boolean', value : 'false',
+# description : 'build against LLVM libFuzzer')
+#endif // 0
diff --git a/modprobe.d/elogind.conf b/modprobe.d/elogind.conf
new file mode 100644
index 000000000..cd0b9fdfb
--- /dev/null
+++ b/modprobe.d/elogind.conf
@@ -0,0 +1,18 @@
+# This file is part of elogind.
+#
+# elogind is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# When bonding module is loaded, it creates bond0 by default due to max_bonds
+# option default value 1. This interferes with the network configuration
+# management / networkd, as it is not possible to detect whether this bond0 was
+# intentionally configured by the user, or should be managed by
+# networkd/NM/etc. Therefore disable bond0 creation.
+
+options bonding max_bonds=0
+
+# Do the same for dummy0.
+
+options dummy numdummies=0
diff --git a/po/.gitignore b/po/.gitignore
deleted file mode 100644
index 1cdd4b6d3..000000000
--- a/po/.gitignore
+++ /dev/null
@@ -1,9 +0,0 @@
-POTFILES
-Makefile.in.in
-.intltool-merge-cache
-Makefile
-systemd.pot
-/*.gmo
-
-# elogind specific ignores
-elogind.pot
diff --git a/po/LINGUAS b/po/LINGUAS
index cc64eab99..36949b723 100644
--- a/po/LINGUAS
+++ b/po/LINGUAS
@@ -16,6 +16,7 @@ it
ko
pl
pt_BR
+ro
ru
sk
sr
diff --git a/po/POTFILES.in b/po/POTFILES.in
index ffb5c0b5f..f33c53fb4 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1 +1,8 @@
+src/core/org.freedesktop.systemd1.policy.in.in
+src/hostname/org.freedesktop.hostname1.policy.in
+src/import/org.freedesktop.import1.policy.in
+src/locale/org.freedesktop.locale1.policy.in
src/login/org.freedesktop.login1.policy.in
+src/machine/org.freedesktop.machine1.policy.in
+src/timedate/org.freedesktop.timedate1.policy.in
+src/core/dbus-unit.c
diff --git a/po/be.po b/po/be.po
index deb386929..2f12d0ca0 100644
--- a/po/be.po
+++ b/po/be.po
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# Belarusian translation for systemd.
# Copyright (C) 2015 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
@@ -20,39 +22,40 @@ msgstr ""
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
"X-Generator: Lokalize 2.0\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "Адправіць пароль назад сістэме"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr "Неабходна аўтэнтыфікацыя для адпраўкі пароля назад сістэме."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "Кіраваць сэрвісамі і іншымі сістэмнымі адзінкамі"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr ""
# "Неабходна аўтэнтыфікацыя для кіравання сэрвісамі і іншымі сістэмнымі "
# "адзінкамі."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "Кіраваць файламі сэрвісаў і іншых сістэмных адзінак"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr ""
# "Неабходна аўтэнтыфікацыя для кіравання файламі сэрвісаў і іншых сістэмных "
# "адзінак."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr "Усталяваць або скінуць зменныя асяроддзя сістэмнага мэнэджэра"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
@@ -60,27 +63,27 @@ msgstr ""
# msgstr ""
# "Неабходна аўтэнтыфікацыя для ўсталявання або скіду зменных асяроддзя "
# "сістэмнага мэнэджэра."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "Перачытаць стан systemd"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr "Неабходна аўтэнтыфікацыя для перачытання стану systemd."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "Усталяваць імя вузла"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "Неабходна аўтэнтыфікацыя для ўсталявання імя вузла."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "Усталяваць статычнае імя вузла"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
@@ -88,55 +91,57 @@ msgstr ""
# msgstr ""
# "Неабходна аўтэнтыфікацыя для ўсталявання як статычнага так і прыгожага імя "
# "вузла."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "Усталяваць інфармацыю аб машыне"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr ""
# "Неабходна аўтэнтыфікацыя для ўсталявання інфармацыі аб лакальнай машыне."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "Імпартаваць вобраз ВМ або кантэйнера"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr "Неабходна аўтэнтыфікацыя для імпарту вобраза ВМ або кантэйнера"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "Экспартаваць вобраз ВМ або кантэйнера"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr "Неабходна аўтэнтыфікацыя для экспарту вобраза ВМ або кантэйнера"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "Спампаваць вобраз ВМ або кантэйнера"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr "Неабходна аўтэнтыфікацыя для спампоўкі вобраза ВМ або кантэйнера"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "Усталяваць сістэмную лакаль"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмнай лакалі."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "Усталяваць сістэмныя налады клавіятуры"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмных налад клавіятуры."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -449,72 +454,73 @@ msgstr "Усталяваць усеагульнае паведамленне"
msgid "Authentication is required to set a wall message"
msgstr "Неабходна аўтэнтыфікацыя для ўсталявання ўсеагульнага паведамлення"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "Увайсці ў лакальны кантэйнер"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr "Неабходна аўтэнтыфікацыя для ўваходу ў лакальны кантэйнер."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "Увайсці ў лакальны вузел"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr "Неабходна аўтэнтыфікацыя для ўваходу ў лакальны вузел."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "Атрымаць абалонку на лакальным кантэйнеры"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr ""
# "Неабходна аўтэнтыфікацыя для атрымання абалонкі на лакальным кантэйнеры."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "Атрымаць абалонку на лакальным вузле"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr "Неабходна аўтэнтыфікацыя для атрымання абалонкі на лакальным вузле."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "Атрымаць псеўда TTY на лакальным кантэйнеры"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr ""
# "Неабходна аўтэнтыфікацыя для атрымання псеўда TTY на лакальным кантэйнеры."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "Атрымаць псеўда TTY на лакальным вузле"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr "Неабходна аўтэнтыфікацыя для атрымання псеўда TTY на лакальным вузле."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "Кіраваць лакальнымі віртуальнымі машынамі або кантэйнерамі"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr ""
# "Неабходна аўтэнтыфікацыя для кіравання лакальнымі віртуальнымі машынамі і "
# "кантэйнерамі."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "Кіраваць вобразамі лакальных віртуальных машын і кантэйнераў"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
@@ -522,27 +528,27 @@ msgstr "Неабходна аўтэнтыфікацыя для ўсталява
# msgstr ""
# "Неабходна аўтэнтыфікацыя для кіравання вобразамі лакальных віртуальных машын "
# "і кантэйнераў."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "Усталяваць сістэмны час"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмнага часу."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "Усталяваць сістэмны часавы пояс"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмнага часавога поясу."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr "Усталяваць часавы пояс (мясцовы або UTC), у якім RTC захоўвае час"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
@@ -550,11 +556,11 @@ msgstr "Неабходна аўтэнтыфікацыя для ўсталява
# msgstr ""
# "Неабходна аўтэнтыфікацыя для ўсталявання часавога поясу (мясцовы або UTC), у "
# "якім захоўваецца час у RTC."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "Уключыць або выключыць сінхранізацыю часу па сетцы"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
@@ -562,31 +568,33 @@ msgstr "Неабходна аўтэнтыфікацыя для ўсталява
# msgstr ""
# "Неабходна аўтэнтыфікацыя для ўключэння або выключэння сінхранізацыі часу па "
# "сетцы."
-
+#
# #: ../src/core/dbus-unit.c:450
# msgid "Authentication is required to start '$(unit)'."
# msgstr "Неабходна аўтэнтыфікацыя для запуску '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:451
# msgid "Authentication is required to stop '$(unit)'."
# msgstr "Неабходна аўтэнтыфікацыя для спынення '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:452
# msgid "Authentication is required to reload '$(unit)'."
# msgstr "Неабходна аўтэнтыфікацыя для перачытання стану '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454
# msgid "Authentication is required to restart '$(unit)'."
# msgstr "Неабходна аўтэнтыфікацыя для перазапуску '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:560
# msgid "Authentication is required to kill '$(unit)'."
# msgstr "Неабходна аўтэнтыфікацыя для забойства '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:590
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
# msgstr "Неабходна аўтэнтыфікацыя для анулявання памылковага стану '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:622
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr "Неабходна аўтэнтыфікацыя для ўсталявання ўласцівасцей '$(unit)'."
+#endif // 0
+
diff --git a/po/be@latin.po b/po/be@latin.po
index daaf8511c..61a59b7b6 100644
--- a/po/be@latin.po
+++ b/po/be@latin.po
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# Belarusian translation for systemd.
# Copyright (C) 2015 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
@@ -20,39 +22,40 @@ msgstr ""
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
"X-Generator: Lokalize 2.0\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "Adpravić paroĺ nazad sistemie"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr "Nieabchodna aŭtentyfikacyja dlia adpraŭki parolia nazad sistemie."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "Kiravać servisami i inšymi sistemnymi adzinkami"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr ""
# "Nieabchodna aŭtentyfikacyja dlia kiravannia servisami i inšymi sistemnymi "
# "adzinkami."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "Kiravać fajlami servisaŭ i inšych sistemnych adzinak"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr ""
# "Nieabchodna aŭtentyfikacyja dlia kiravannia fajlami servisaŭ i inšych "
# "sistemnych adzinak."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr "Ustaliavać abo skinuć zmiennyja asiaroddzia sistemnaha menedžera"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
@@ -60,27 +63,27 @@ msgstr ""
# msgstr ""
# "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia abo skidu zmiennych "
# "asiaroddzia sistemnaha menedžera."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "Pieračytać stan systemd"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr "Nieabchodna aŭtentyfikacyja dlia pieračytannia stanu systemd."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "Ustaliavać imia vuzla"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia imia vuzla."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "Ustaliavać statyčnaje imia vuzla"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
@@ -88,57 +91,59 @@ msgstr ""
# msgstr ""
# "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia jak statyčnaha tak i "
# "pryhožaha imia vuzla."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "Ustaliavać infarmacyju ab mašynie"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr ""
# "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia infarmacyi ab lakaĺnaj "
# "mašynie."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "Impartavać vobraz VM abo kantejniera"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr "Nieabchodna aŭtentyfikacyja dlia impartu vobraza VM abo kantejniera"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "Ekspartavać vobraz VM abo kantejniera"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr "Nieabchodna aŭtentyfikacyja dlia ekspartu vobraza VM abo kantejniera"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "Spampavać vobraz VM abo kantejniera"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr "Nieabchodna aŭtentyfikacyja dlia spampoŭki vobraza VM abo kantejniera"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "Ustaliavać sistemnuju lakaĺ"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia sistemnaj lakali."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "Ustaliavać sistemnyja nalady klavijatury"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr ""
# "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia sistemnych nalad klavijatury."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -456,75 +461,76 @@ msgid "Authentication is required to set a wall message"
msgstr ""
"Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia ŭsieahuĺnaha paviedamliennia"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "Uvajsci ŭ lakaĺny kantejnier"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr "Nieabchodna aŭtentyfikacyja dlia ŭvachodu ŭ lakaĺny kantejnier."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "Uvajsci ŭ lakaĺny vuziel"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr "Nieabchodna aŭtentyfikacyja dlia ŭvachodu ŭ lakaĺny vuziel."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "Atrymać abalonku na lakaĺnym kantejniery"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr ""
# "Nieabchodna aŭtentyfikacyja dlia atrymannia abalonki na lakaĺnym kantejniery."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "Atrymać abalonku na lakaĺnym vuzlie"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr ""
# "Nieabchodna aŭtentyfikacyja dlia atrymannia abalonki na lakaĺnym vuzlie."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "Atrymać psieŭda TTY na lakaĺnym kantejniery"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr ""
# "Nieabchodna aŭtentyfikacyja dlia atrymannia psieŭda TTY na lakaĺnym "
# "kantejniery."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "Atrymać psieŭda TTY na lakaĺnym vuzlie"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr ""
# "Nieabchodna aŭtentyfikacyja dlia atrymannia psieŭda TTY na lakaĺnym vuzlie."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "Kiravać lakaĺnymi virtuaĺnymi mašynami abo kantejnierami"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr ""
# "Nieabchodna aŭtentyfikacyja dlia kiravannia lakaĺnymi virtuaĺnymi mašynami i "
# "kantejnierami."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "Kiravać vobrazami lakaĺnych virtuaĺnych mašyn i kantejnieraŭ"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
@@ -532,28 +538,28 @@ msgstr ""
# msgstr ""
# "Nieabchodna aŭtentyfikacyja dlia kiravannia vobrazami lakaĺnych virtuaĺnych "
# "mašyn i kantejnieraŭ."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "Ustaliavać sistemny čas"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia sistemnaha času."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "Ustaliavać sistemny časavy pojas"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr ""
# "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia sistemnaha časavoha pojasu."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr "Ustaliavać časavy pojas (miascovy abo UTC), u jakim RTC zachoŭvaje čas"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
@@ -561,11 +567,11 @@ msgstr ""
# msgstr ""
# "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia časavoha pojasu (miascovy abo "
# "UTC), u jakim zachoŭvajecca čas u RTC."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "Ukliučyć abo vykliučyć sinchranizacyju času pa sietcy"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
@@ -573,33 +579,35 @@ msgstr ""
# msgstr ""
# "Nieabchodna aŭtentyfikacyja dlia ŭkliučennia abo vykliučennia sinchranizacyi "
# "času pa sietcy."
-
+#
# #: ../src/core/dbus-unit.c:450
# msgid "Authentication is required to start '$(unit)'."
# msgstr "Nieabchodna aŭtentyfikacyja dlia zapusku '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:451
# msgid "Authentication is required to stop '$(unit)'."
# msgstr "Nieabchodna aŭtentyfikacyja dlia spyniennia '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:452
# msgid "Authentication is required to reload '$(unit)'."
# msgstr "Nieabchodna aŭtentyfikacyja dlia pieračytannia stanu '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454
# msgid "Authentication is required to restart '$(unit)'."
# msgstr "Nieabchodna aŭtentyfikacyja dlia pierazapusku '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:560
# msgid "Authentication is required to kill '$(unit)'."
# msgstr "Nieabchodna aŭtentyfikacyja dlia zabojstva '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:590
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
# msgstr ""
# "Nieabchodna aŭtentyfikacyja dlia anuliavannia pamylkovaha stanu '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:622
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr ""
# "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia ŭlascivasciej '$(unit)'."
+#endif // 0
+
diff --git a/po/bg.po b/po/bg.po
index 684876590..db0933e49 100644
--- a/po/bg.po
+++ b/po/bg.po
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# Bulgarian translation of systemd po-file.
# Copyright (C) 2016 Alexander Shopov <ash@kambanaria.org>
# This file is distributed under the same license as the systemd package.
@@ -17,40 +19,41 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "Изпращане на паролата към системата"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr "За изпращане на паролата към системата е необходима идентификация."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "Управление на услугите или другите модули"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr ""
# "За управление на услугите или другите модули е необходима идентификация."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "Управление на файловете за услугите или другите модули"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr ""
# "За управление на файловете за услугите или другите модули е необходима "
# "идентификация."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr ""
# "Задаване или изтриване на променливи на средата за системата и управлението "
# "на услугите"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
@@ -58,88 +61,90 @@ msgstr ""
# msgstr ""
# "За задаване или изтриване на променливи на средата за системата и "
# "управлението на услугите е необходима идентификация."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "Презареждане на състоянието на systemd"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr "За презареждане на състоянието на systemd е необходима идентификация."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "Задаване на име на машината"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "За задаване на име на локалната машина е необходима идентификация."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "Задаване на статично име на машината"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
# "as well as the pretty host name."
# msgstr ""
# "За задаване на статично име на локалната машина е необходима идентификация."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "Задаване на информация за машината"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr ""
# "За задаване на информация за локалната машина е необходима идентификация."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "Внасяне на изображение на виртуална машина или контейнер"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr ""
# "За внасяне на изображение на виртуална машина или контейнер е необходима "
# "идентификация."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "Изнасяне на изображение на виртуална машина или контейнер"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr ""
# "За изнасяне на изображение на виртуална машина или контейнер е необходима "
# "идентификация."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "Изтегляне на изображение на виртуална машина или контейнер"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr ""
# "За изтегляне на изображение на виртуална машина или контейнер е необходима "
# "идентификация."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "Задаване на локала на системата"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr "За задаване на локала на системата е необходима идентификация."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "Задаване на настройките на клавиатурата"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr "За задаване на настройките на клавиатурата е необходима идентификация."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -470,74 +475,75 @@ msgstr "Задаване на системно съобщение „wall“"
msgid "Authentication is required to set a wall message"
msgstr "За задаване на системно съобщение „wall“ е необходима идентификация."
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "Вписване в локален контейнер"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr "За вписване в локален контейнер е необходима идентификация."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "Вписване в локалната машина"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr "За вписване в локалната машина е необходима идентификация."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "Достъп до обвивка в локален контейнер"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr "За достъп до обвивка в локален контейнер е необходима идентификация."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "Достъп до обвивка на локалната машина"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr "За достъп до обвивка на локалната машина е необходима идентификация."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "Получаване на псевдо терминал в локален контейнер"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr ""
# "За получаване на псевдо терминал в локален контейнер е необходима "
# "идентификация."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "Получаване на псевдо терминал на локалната машина"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr ""
# "За получаване на псевдо терминал на локалната машина е необходима "
# "идентификация."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "Управление на локалните виртуални машини и контейнери"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr ""
# "За управление на локалните виртуални машини и контейнери е необходима "
# "идентификация."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "Управление на изображения на виртуални машини или контейнери"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
@@ -545,27 +551,27 @@ msgstr "За задаване на системно съобщение „wall
# msgstr ""
# "За управление на изображения на виртуални машини или е необходима "
# "идентификация."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "Задаване на времето на системата"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "За задаване на времето на системата е необходима идентификация."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "Задаване на часовия пояс на системата"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr "За задаване на часовия пояс на системата е необходима идентификация."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr "Превключване на системния часовник между местния часови пояс и UTC"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
@@ -573,11 +579,11 @@ msgstr "За задаване на системно съобщение „wall
# msgstr ""
# "За превключване на системния часовник между местния часови пояс и UTC е "
# "необходима идентификация."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "Превключване на синхронизацията на времето по мрежата"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
@@ -585,33 +591,35 @@ msgstr "За задаване на системно съобщение „wall
# msgstr ""
# "За превключване на синхронизацията на времето по мрежата е необходима "
# "идентификация."
-
+#
# #: ../src/core/dbus-unit.c:450
# msgid "Authentication is required to start '$(unit)'."
# msgstr "За стартиране на „$(unit)“ е необходима идентификация."
-
+#
# #: ../src/core/dbus-unit.c:451
# msgid "Authentication is required to stop '$(unit)'."
# msgstr "За спиране на „$(unit)“ е необходима идентификация."
-
+#
# #: ../src/core/dbus-unit.c:452
# msgid "Authentication is required to reload '$(unit)'."
# msgstr "За презареждане на „$(unit)“ е необходима идентификация."
-
+#
# #: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454
# msgid "Authentication is required to restart '$(unit)'."
# msgstr "За рестартиране на „$(unit)“ е необходима идентификация."
-
+#
# #: ../src/core/dbus-unit.c:560
# msgid "Authentication is required to kill '$(unit)'."
# msgstr "За убиване на „$(unit)“ е необходима идентификация."
-
+#
# #: ../src/core/dbus-unit.c:590
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
# msgstr ""
# "За премахване на състоянието за неуспех на „$(unit)“ е необходима "
# "идентификация."
-
+#
# #: ../src/core/dbus-unit.c:622
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr "За задаване на свойствата на „$(unit)“ е необходима идентификация."
+#endif // 0
+
diff --git a/po/ca.po b/po/ca.po
index f9c07299b..06aa57f78 100644
--- a/po/ca.po
+++ b/po/ca.po
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# Catalan translation for systemd.
# Copyright (C) 2015 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
@@ -18,114 +20,117 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.8.7.1\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "Retornar la contrasenya al sistema"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr "Es requereix autenticació per retornar la contrasenya entrada al sistema."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "Administrar serveis del sistema o d'altres unitats."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr "Es requereix autenticació per administrar els serveis de sistemes o d'altres unitats."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "Gestiona un servei de sistema o fitxers d'unitat"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr "Cal autenticació per gestionar un servei de sistema o fitxers d'unitat."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr "Administrar variables de entorno del sistema y del gestor de servicios"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
# "environment variables."
# msgstr "Cal autenticació per establir o cancel·lar variables d'entorn de sistema o del gestor de serveis."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "Recarrega l'estat del systemd"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr "Cal autenticació per establir el nom de l'ordinador local."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "Estableix el nom de l'ordinador"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "Cal autenticació per establir el nom de l'ordinador local."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "Estableix el nom estàtic de l'ordinador"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
# "as well as the pretty host name."
# msgstr "Cal autenticació per establir el nom configurat estàticament de l'ordinador local, així com el nom de l'ordinador de nivell superior."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "Estableix la informació de l'ordinador"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr "Cal autenticació per establir la informació de l'ordinador local."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "Importa una màquina virtual o una imatge de contenidor"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr "Cal autenticació per importar una màquina virtual o una imatge de contenidor"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "Exporta una màquina virtual o una imatge de contenidor"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr "Cal autenticació per exportar una màquina virtual o una imatge de contenidor"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "Descarrega una màquina virtual o una imatge de contenidor"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr "Cal autenticació per descarregar una màquina virtual o una imatge de contenidor"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "Estableix la regió del sistema"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr "Cal autenticació per establir la regió del sistema."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "Estableix la configuració del teclat del sistema."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr "Cal autenticació per establir la configuració del teclat del sistema."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -382,144 +387,147 @@ msgstr "Estableix un missatge de mur"
msgid "Authentication is required to set a wall message"
msgstr "Cal autenticació per establir un text de mur"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "Inicia sessió a un contenidor local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr "Cal autenticació per iniciar sessió a un contenidor local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "Inicia sessió a l'ordinador local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr "Cal autenticació per iniciar sessió a l'ordinador local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "Adquireix un intèrpret d'ordres a un contenidor local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr "Cal autenticació per adquirir un intèrpret d'ordres a un contenidor local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "Adquireix un intèrpret d'ordres a l'ordinador local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr "Cal autenticació per adquirir un intèrpret d'ordres a l'ordinador local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "Adquireix un pseudo-terminal al contenidor local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr "Cal autenticació per adquirir una pseudo-terminal al contenidor local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "Adquireix una pseudo-terminal a l'ordinador local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr "Cal autenticació per adquirir una pseudo-terminal a l'ordinador local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "Gestiona les màquines virtuals i els contenidors locals "
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr "Cal autenticació per gestionar les màquines virtuals i els contenidors locals."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "Gestiona les imatges locals de màquines virtuals i contenidors"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
# "images."
# msgstr "Cal autenticació per gestionar les imatges locals de màquines virtuals i contenidors."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "Estableix la data i l'hora del sistema"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "Cal autenticació per establir la data i l'hora del sistema."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "Estableix la zona horària del sistema"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr "Cal autenticació per establir la zona horària del sistema."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr "Estableix el rellotge del sistema a la zona horària local o a UTC"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
# "UTC time."
# msgstr "Cal autenticació per controlar si el rellotge del sistema emmagatzema la data i l'hora locals o UTC."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "Activa o desactiva la sincronització de data i hora de xarxa"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
# "shall be enabled."
# msgstr "Cal autenticació per controlar si s'ha d'activar la sincronització de data i hora de xarxa."
-
+#
# #: ../src/core/dbus-unit.c:428
# msgid "Authentication is required to start '$(unit)'."
# msgstr "Cal autenticació per iniciar «$(unit)»."
-
+#
# #: ../src/core/dbus-unit.c:429
# msgid "Authentication is required to stop '$(unit)'."
# msgstr "Cal autenticació per aturar «$(unit)»."
-
+#
# #: ../src/core/dbus-unit.c:430
# msgid "Authentication is required to reload '$(unit)'."
# msgstr "Cal autenticació per tornar a carregar «$(unit)»."
-
+#
# #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
# msgid "Authentication is required to restart '$(unit)'."
# msgstr "Cal autenticació per tornar a reiniciar «$(unit)»."
-
+#
# #: ../src/core/dbus-unit.c:535
# msgid "Authentication is required to kill '$(unit)'."
# msgstr "Cal autenticació per matar a «$(unit)»."
-
+#
# #: ../src/core/dbus-unit.c:565
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
# msgstr "Cal autenticació per reiniciar l'estat «fallat» de «$(unit)»."
-
+#
# #: ../src/core/dbus-unit.c:597
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr "Cal autenticació per establir propietats a «$(unit)»."
+#
+# #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
+# #~ msgstr ""
+# #~ "Presione Ctrl+C para cancelar todas las comprobaciones del sistema de "
+# #~ "archivos en curso"
+#
+# #~ msgid "Checking in progress on %d disk (%3.1f%% complete)"
+# #~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
+# #~ msgstr[0] "Comprobando progreso en %d disco (%3.1f %% completado)"
+# #~ msgstr[1] "Comprobando progreso en %d discos (%3.1f %% completado)"
+#endif // 0
-#~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
-#~ msgstr ""
-#~ "Presione Ctrl+C para cancelar todas las comprobaciones del sistema de "
-#~ "archivos en curso"
-
-#~ msgid "Checking in progress on %d disk (%3.1f%% complete)"
-#~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
-#~ msgstr[0] "Comprobando progreso en %d disco (%3.1f %% completado)"
-#~ msgstr[1] "Comprobando progreso en %d discos (%3.1f %% completado)"
diff --git a/po/cs.po b/po/cs.po
index 206fde372..e461f46d2 100644
--- a/po/cs.po
+++ b/po/cs.po
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# Czech translation for systemd.
# Copyright (C) 2016-2017 systemd's author and translators.
# This file is distributed under the same license as the systemd package.
@@ -9,128 +11,128 @@ msgstr ""
"Project-Id-Version: systemd master\n"
"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
"POT-Creation-Date: 2016-04-23 14:24+0200\n"
-"PO-Revision-Date: 2017-04-20 23:00+0200\n"
+"PO-Revision-Date: 2017-10-10 19:54+0200\n"
"Last-Translator: Daniel Rusek <mail@asciiwolf.com>\n"
"Language: cs\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n"
-"%100>=20) ? 1 : 2);\n"
+"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? "
+"1 : 2);\n"
"Language-Team: \n"
-"X-Generator: Poedit 1.8.7.1\n"
+"X-Generator: Poedit 2.0.3\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "Odeslat heslo zpět do systému"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid "Authentication is required to send the entered passphrase back to the system."
# msgstr "Pro odeslání zadaného hesla do systému je vyžadováno ověření."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "Spravovat systémové služby nebo další jednotky"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr "Pro správu systémových služeb nebo dalších jednotek je vyžadováno ověření."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "Spravovat systémové služby nebo soubory jednotek"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr "Pro správu systémových služeb nebo souborů jednotek je vyžadováno ověření."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr "Nastavit nebo rušit proměnné správce systému a služeb"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
-# "Authentication is required to set or unset system and service manager environment "
-# "variables."
-# msgstr ""
-# "Pro nastavení nebo rušení proměnných správce systému a služeb je vyžadováno "
-# "ověření."
-
+# "Authentication is required to set or unset system and service manager environment variables."
+# msgstr "Pro nastavení nebo rušení proměnných správce systému a služeb je vyžadováno ověření."
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "Znovu načíst stav systemd"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr "Pro znovu načtení stavu systemd je vyžadováno ověření."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "Nastavit název stroje"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "Pro nastavení lokálního názvu stroje je vyžadováno ověření."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "Nastavit statický název stoje"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
-# "Authentication is required to set the statically configured local host name, as "
-# "well as the pretty host name."
+# "Authentication is required to set the statically configured local host name, as well as the "
+# "pretty host name."
# msgstr ""
-# "Pro nastavení staticky konfigurovaného názvu lokálního stroje, stejně tak pro "
-# "změnu uživatelsky přívětivého jména je vyžadováno ověření."
-
+# "Pro nastavení staticky konfigurovaného názvu lokálního stroje, stejně tak pro změnu "
+# "uživatelsky přívětivého jména je vyžadováno ověření."
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "Nastavit informace o stroji"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr "Pro nastavení informací o stroji je vyžadováno ověření."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "Importovat obraz virtuální stroje nebo kontejneru"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr "Pro import obrazu virtuálního stroje nebo kontejneru je vyžadováno ověření"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "Exportovat obraz virtuálního stroje nebo kontejneru"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr "Pro export obrazu virtuálního stroje nebo kontejneru je vyžadováno ověření"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "Stáhnout obraz virtuálního stroje nebo kontejneru"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr "Pro stažení obrazu virtuálního stroje nebo kontejneru je vyžadováno ověření"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "Nastavit lokalizaci systému"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr "Pro nastavení lokalizace systému je vyžadováno ověření."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "Nastavit systémovou konfiguraci klávesnice"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr "Pro nastavení systémové konfigurace klávesnice je vyžadováno ověření."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -169,10 +171,8 @@ msgid "Allow applications to inhibit automatic system suspend"
msgstr "Povolit aplikacím zakázat automatické vypnutí systému"
#: ../src/login/org.freedesktop.login1.policy.in.h:10
-msgid ""
-"Authentication is required for an application to inhibit automatic system suspend."
-msgstr ""
-"Pro povolení aplikacím zakázat automatické vypnutí systému je vyžadováno ověření."
+msgid "Authentication is required for an application to inhibit automatic system suspend."
+msgstr "Pro povolení aplikacím zakázat automatické vypnutí systému je vyžadováno ověření."
#: ../src/login/org.freedesktop.login1.policy.in.h:11
msgid "Allow applications to inhibit system handling of the power key"
@@ -180,8 +180,7 @@ msgstr "Povolit aplikacím zakázat chovaní systému na stisknutí vypínacího
#: ../src/login/org.freedesktop.login1.policy.in.h:12
msgid ""
-"Authentication is required for an application to inhibit system handling of the "
-"power key."
+"Authentication is required for an application to inhibit system handling of the power key."
msgstr ""
"Pro povolení aplikacím zakázat chovaní systému na stisknutí vypínacího tlačítka je "
"vyžadováno ověření."
@@ -192,8 +191,7 @@ msgstr "Povolit aplikacím zakázat chovaní systému na stisknutí uspávacího
#: ../src/login/org.freedesktop.login1.policy.in.h:14
msgid ""
-"Authentication is required for an application to inhibit system handling of the "
-"suspend key."
+"Authentication is required for an application to inhibit system handling of the suspend key."
msgstr ""
"Pro povolení aplikacím zakázat chovaní systému na stisknutí uspávacího tlačítka je "
"vyžadováno ověření."
@@ -204,11 +202,11 @@ msgstr "Povolit aplikacím zakázat chovaní systému na stisknutí tlačítka h
#: ../src/login/org.freedesktop.login1.policy.in.h:16
msgid ""
-"Authentication is required for an application to inhibit system handling of the "
-"hibernate key."
+"Authentication is required for an application to inhibit system handling of the hibernate "
+"key."
msgstr ""
-"Pro povolení aplikacím zakázat chovaní systému na stisknutí tlačítka hibernace je "
-"vyžadováno ověření."
+"Pro povolení aplikacím zakázat chovaní systému na stisknutí tlačítka hibernace je vyžadováno "
+"ověření."
#: ../src/login/org.freedesktop.login1.policy.in.h:17
msgid "Allow applications to inhibit system handling of the lid switch"
@@ -216,11 +214,8 @@ msgstr "Povolit aplikacím zakázat chovaní systému na zavření víka"
#: ../src/login/org.freedesktop.login1.policy.in.h:18
msgid ""
-"Authentication is required for an application to inhibit system handling of the "
-"lid switch."
-msgstr ""
-"Pro povolení aplikacím zakázat chovaní systému na zavření víka je vyžadováno "
-"ověření."
+"Authentication is required for an application to inhibit system handling of the lid switch."
+msgstr "Pro povolení aplikacím zakázat chovaní systému na zavření víka je vyžadováno ověření."
#: ../src/login/org.freedesktop.login1.policy.in.h:19
msgid "Allow non-logged-in user to run programs"
@@ -228,8 +223,7 @@ msgstr "Povolit nepřihlášenému uživateli spouštět programy"
#: ../src/login/org.freedesktop.login1.policy.in.h:20
msgid "Explicit request is required to run programs as a non-logged-in user."
-msgstr ""
-"Ke spuštění programů jako nepřihlášený uživatel je třeba speciální požadavek."
+msgstr "Ke spuštění programů jako nepřihlášený uživatel je třeba speciální požadavek."
#: ../src/login/org.freedesktop.login1.policy.in.h:21
msgid "Allow non-logged-in users to run programs"
@@ -253,9 +247,7 @@ msgstr "Odstranit přiřazení zařízení ke stanovištím"
#: ../src/login/org.freedesktop.login1.policy.in.h:26
msgid "Authentication is required for resetting how devices are attached to seats."
-msgstr ""
-"Pro reset způsobu jak jsou zařízení přiřazována ke stanovištím je vyžadováno "
-"ověření."
+msgstr "Pro reset způsobu jak jsou zařízení přiřazována ke stanovištím je vyžadováno ověření."
#: ../src/login/org.freedesktop.login1.policy.in.h:27
msgid "Power off the system"
@@ -270,11 +262,8 @@ msgid "Power off the system while other users are logged in"
msgstr "Vypnout systém, i když jsou přihlášeni další uživatelé"
#: ../src/login/org.freedesktop.login1.policy.in.h:30
-msgid ""
-"Authentication is required for powering off the system while other users are "
-"logged in."
-msgstr ""
-"Pro vypnutí systému, když jsou přihlášeni další uživatelé je vyžadováno ověření."
+msgid "Authentication is required for powering off the system while other users are logged in."
+msgstr "Pro vypnutí systému, když jsou přihlášeni další uživatelé je vyžadováno ověření."
#: ../src/login/org.freedesktop.login1.policy.in.h:31
msgid "Power off the system while an application asked to inhibit it"
@@ -282,10 +271,9 @@ msgstr "Vypnout systém, i když aplikace požádala o zákaz vypnutí"
#: ../src/login/org.freedesktop.login1.policy.in.h:32
msgid ""
-"Authentication is required for powering off the system while an application asked "
-"to inhibit it."
-msgstr ""
-"Pro vypnutí systému, když aplikace požádala o zákaz vypnutí je vyžadováno ověření."
+"Authentication is required for powering off the system while an application asked to inhibit "
+"it."
+msgstr "Pro vypnutí systému, když aplikace požádala o zákaz vypnutí je vyžadováno ověření."
#: ../src/login/org.freedesktop.login1.policy.in.h:33
msgid "Reboot the system"
@@ -300,12 +288,8 @@ msgid "Reboot the system while other users are logged in"
msgstr "Restartovat systém, i když jsou přihlášeni další uživatelé"
#: ../src/login/org.freedesktop.login1.policy.in.h:36
-msgid ""
-"Authentication is required for rebooting the system while other users are logged "
-"in."
-msgstr ""
-"Pro restartování systému, když jsou přihlášeni další uživatelé je vyžadováno "
-"ověření."
+msgid "Authentication is required for rebooting the system while other users are logged in."
+msgstr "Pro restartování systému, když jsou přihlášeni další uživatelé je vyžadováno ověření."
#: ../src/login/org.freedesktop.login1.policy.in.h:37
msgid "Reboot the system while an application asked to inhibit it"
@@ -313,234 +297,244 @@ msgstr "Restartovat systém, i když aplikace požádala o zákaz restartu"
#: ../src/login/org.freedesktop.login1.policy.in.h:38
msgid ""
-"Authentication is required for rebooting the system while an application asked to "
-"inhibit it."
+"Authentication is required for rebooting the system while an application asked to inhibit it."
msgstr ""
-"Pro restartování systému, když aplikace požádala o zákaz restartu je vyžadováno "
-"ověření."
+"Pro restartování systému, když aplikace požádala o zákaz restartu je vyžadováno ověření."
#: ../src/login/org.freedesktop.login1.policy.in.h:39
+msgid "Halt the system"
+msgstr "Zastavit systém"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:40
+msgid "Authentication is required for halting the system."
+msgstr "Pro zastavení systému je vyžadováno ověření."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:41
+msgid "Halt the system while other users are logged in"
+msgstr "Zastavit systém, i když jsou přihlášeni další uživatelé"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:42
+msgid "Authentication is required for halting the system while other users are logged in."
+msgstr "Pro zastavení systému, když jsou přihlášeni další uživatelé je vyžadováno ověření."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:43
+msgid "Halt the system while an application asked to inhibit it"
+msgstr "Zastavit systém, i když aplikace požádala o zákaz zastavení"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:44
+msgid ""
+"Authentication is required for halting the system while an application asked to inhibit it."
+msgstr "Pro zastavení systému, když aplikace požádala o zákaz zastavení je vyžadováno ověření."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:45
msgid "Suspend the system"
msgstr "Uspat systém"
-#: ../src/login/org.freedesktop.login1.policy.in.h:40
+#: ../src/login/org.freedesktop.login1.policy.in.h:46
msgid "Authentication is required for suspending the system."
msgstr "Pro uspání systému je vyžadováno ověření."
-#: ../src/login/org.freedesktop.login1.policy.in.h:41
+#: ../src/login/org.freedesktop.login1.policy.in.h:47
msgid "Suspend the system while other users are logged in"
msgstr "Uspat systém, i když jsou přihlášeni další uživatelé"
-#: ../src/login/org.freedesktop.login1.policy.in.h:42
-msgid ""
-"Authentication is required for suspending the system while other users are logged "
-"in."
-msgstr ""
-"Pro uspání systému, když jsou přihlášeni další uživatelé je vyžadováno ověření."
+#: ../src/login/org.freedesktop.login1.policy.in.h:48
+msgid "Authentication is required for suspending the system while other users are logged in."
+msgstr "Pro uspání systému, když jsou přihlášeni další uživatelé je vyžadováno ověření."
-#: ../src/login/org.freedesktop.login1.policy.in.h:43
+#: ../src/login/org.freedesktop.login1.policy.in.h:49
msgid "Suspend the system while an application asked to inhibit it"
msgstr "Uspat systém, i když aplikace požádala o zákaz uspání"
-#: ../src/login/org.freedesktop.login1.policy.in.h:44
+#: ../src/login/org.freedesktop.login1.policy.in.h:50
msgid ""
-"Authentication is required for suspending the system while an application asked to "
-"inhibit it."
-msgstr ""
-"Pro uspání systému, když aplikace požádala o zákaz uspání je vyžadováno ověření."
+"Authentication is required for suspending the system while an application asked to inhibit "
+"it."
+msgstr "Pro uspání systému, když aplikace požádala o zákaz uspání je vyžadováno ověření."
-#: ../src/login/org.freedesktop.login1.policy.in.h:45
+#: ../src/login/org.freedesktop.login1.policy.in.h:51
msgid "Hibernate the system"
msgstr "Hibernovat systém"
-#: ../src/login/org.freedesktop.login1.policy.in.h:46
+#: ../src/login/org.freedesktop.login1.policy.in.h:52
msgid "Authentication is required for hibernating the system."
msgstr "Pro hibernaci systému je vyžadováno ověření."
-#: ../src/login/org.freedesktop.login1.policy.in.h:47
+#: ../src/login/org.freedesktop.login1.policy.in.h:53
msgid "Hibernate the system while other users are logged in"
msgstr "Hibernovat systém, i když jsou přihlášeni další uživatelé"
-#: ../src/login/org.freedesktop.login1.policy.in.h:48
-msgid ""
-"Authentication is required for hibernating the system while other users are logged "
-"in."
-msgstr ""
-"Pro hibernaci systému, když jsou přihlášeni další uživatelé je vyžadováno ověření."
+#: ../src/login/org.freedesktop.login1.policy.in.h:54
+msgid "Authentication is required for hibernating the system while other users are logged in."
+msgstr "Pro hibernaci systému, když jsou přihlášeni další uživatelé je vyžadováno ověření."
-#: ../src/login/org.freedesktop.login1.policy.in.h:49
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
msgid "Hibernate the system while an application asked to inhibit it"
msgstr "Hibernovat systém, i když aplikace požádala o zákaz hibernace"
-#: ../src/login/org.freedesktop.login1.policy.in.h:50
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
msgid ""
-"Authentication is required for hibernating the system while an application asked "
-"to inhibit it."
-msgstr ""
-"Pro hibernaci systému, když aplikace požádala o zákaz hibernace je vyžadováno "
-"ověření."
+"Authentication is required for hibernating the system while an application asked to inhibit "
+"it."
+msgstr "Pro hibernaci systému, když aplikace požádala o zákaz hibernace je vyžadováno ověření."
-#: ../src/login/org.freedesktop.login1.policy.in.h:51
+#: ../src/login/org.freedesktop.login1.policy.in.h:57
msgid "Manage active sessions, users and seats"
msgstr "Spravovat aktivní sezení, uživatele a stanoviště"
-#: ../src/login/org.freedesktop.login1.policy.in.h:52
+#: ../src/login/org.freedesktop.login1.policy.in.h:58
msgid "Authentication is required for managing active sessions, users and seats."
msgstr "Pro správu aktivních sezení, uživatelů a stanovišť je vyžadováno ověření."
-#: ../src/login/org.freedesktop.login1.policy.in.h:53
+#: ../src/login/org.freedesktop.login1.policy.in.h:59
msgid "Lock or unlock active sessions"
msgstr "Zamknout nebo odemknout aktivní sezení"
-#: ../src/login/org.freedesktop.login1.policy.in.h:54
+#: ../src/login/org.freedesktop.login1.policy.in.h:60
msgid "Authentication is required to lock or unlock active sessions."
msgstr "Pro zamčení nebo odemčení aktivních sezení je vyžadováno ověření."
-#: ../src/login/org.freedesktop.login1.policy.in.h:55
+#: ../src/login/org.freedesktop.login1.policy.in.h:61
msgid "Allow indication to the firmware to boot to setup interface"
msgstr "Povolit indikaci firmwaru bootovat instalační prostředí"
-#: ../src/login/org.freedesktop.login1.policy.in.h:56
-msgid ""
-"Authentication is required to indicate to the firmware to boot to setup interface."
-msgstr ""
-"K povolení indikace firmwaru bootovat instalační prostředí je vyžadováno ověření."
+#: ../src/login/org.freedesktop.login1.policy.in.h:62
+msgid "Authentication is required to indicate to the firmware to boot to setup interface."
+msgstr "K povolení indikace firmwaru bootovat instalační prostředí je vyžadováno ověření."
-#: ../src/login/org.freedesktop.login1.policy.in.h:57
+#: ../src/login/org.freedesktop.login1.policy.in.h:63
msgid "Set a wall message"
msgstr "Nastavit zprávu všem uživatelům"
-#: ../src/login/org.freedesktop.login1.policy.in.h:58
+#: ../src/login/org.freedesktop.login1.policy.in.h:64
msgid "Authentication is required to set a wall message"
msgstr "K nastavení zprávy všem uživatelům je vyžadováno ověření"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "Přihlásit se do lokálního kontejneru"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr "Pro přihlášení do lokálního kontejneru je vyžadováno ověření."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "Přihlásit se na lokální stroj"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr "Pro přihlášení k lokálnímu stroji je vyžadováno ověření."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "Získat shell v lokálním kontejneru"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr "Pro získání shellu v lokálním kontejneru je vyžadováno ověření."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "Získat shell na lokálním stroji"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr "Pro získání shellu na lokálním stroji je vyžadováno ověření."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "Získat pseudo TTY v lokálním kontejneru"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr "Pro získání pseudo TTY v lokálním kontejneru je vyžadováno ověření."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "Získat pseudo TTY na lokálním stroji"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr "Pro získání pseudo TTY na lokálním stroji je vyžadováno ověření."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "Spravovat lokální virtuální stroje a kontejnery"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid "Authentication is required to manage local virtual machines and containers."
# msgstr "Pro správu lokálních virtuálních strojů a kontejnerů je vyžadováno ověření."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "Spravovat lokální obrazy virtuálních strojů a kontejnerů"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
-# msgid ""
-# "Authentication is required to manage local virtual machine and container images."
-# msgstr ""
-# "Pro správu obrazů lokálních virtuálních strojů a kontejnerů je vyžadováno ověření."
-
+# msgid "Authentication is required to manage local virtual machine and container images."
+# msgstr "Pro správu obrazů lokálních virtuálních strojů a kontejnerů je vyžadováno ověření."
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "Nastavit systémový čas"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "Pro nastavení systémového času je vyžadováno ověření."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "Nastavit systémovou časovou zónu"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr "Pro nastavení systémové časové zóny je vyžadováno ověření."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr "Nastavit RTC na lokální časovou zónu nebo UTC"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
-# msgid ""
-# "Authentication is required to control whether the RTC stores the local or UTC time."
+# msgid "Authentication is required to control whether the RTC stores the local or UTC time."
# msgstr ""
-# "Pro kontrolu jestli RTC ukládá lokální časovou zónu nebo UTC čas je vyžadováno "
-# "ověření."
-
+# "Pro kontrolu jestli RTC ukládá lokální časovou zónu nebo UTC čas je vyžadováno ověření."
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "Zapnout nebo vypnout synchronizaci s časem ze sítě"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
-# "Authentication is required to control whether network time synchronization shall "
-# "be enabled."
+# "Authentication is required to control whether network time synchronization shall be enabled."
# msgstr "Pro kontrolu synchronizace času ze sítě je vyžadováno ověření."
-
-# #: ../src/core/dbus-unit.c:459
+#
+# #: ../src/core/dbus-unit.c:458
# msgid "Authentication is required to start '$(unit)'."
# msgstr "Pro spuštění „$(unit)” je vyžadováno ověření."
-
-# #: ../src/core/dbus-unit.c:460
+#
+# #: ../src/core/dbus-unit.c:459
# msgid "Authentication is required to stop '$(unit)'."
# msgstr "Pro vypnutí „$(unit)” je vyžadováno ověření."
-
-# #: ../src/core/dbus-unit.c:461
+#
+# #: ../src/core/dbus-unit.c:460
# msgid "Authentication is required to reload '$(unit)'."
# msgstr "Pro znovu načtení „$(unit)” je vyžadováno ověření."
-
-# #: ../src/core/dbus-unit.c:462 ../src/core/dbus-unit.c:463
+#
+# #: ../src/core/dbus-unit.c:461 ../src/core/dbus-unit.c:462
# msgid "Authentication is required to restart '$(unit)'."
# msgstr "Pro restart „$(unit)” je vyžadováno ověření."
-
-# #: ../src/core/dbus-unit.c:570
+#
+# #: ../src/core/dbus-unit.c:569
# msgid "Authentication is required to kill '$(unit)'."
# msgstr "Pro ukončení „$(unit)” je vyžadováno ověření."
-
-# #: ../src/core/dbus-unit.c:601
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
+#
+# #: ../src/core/dbus-unit.c:600
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
# msgstr "Pro resetování chybného stavu „$(unit)” je vyžadováno ověření."
-
-# #: ../src/core/dbus-unit.c:634
+#
+# #: ../src/core/dbus-unit.c:633
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr "Pro nastavení vlastností na „$(unit)” je vyžadováno ověření."
+#endif // 0
+
diff --git a/po/da.po b/po/da.po
index 372a699a1..d96efce71 100644
--- a/po/da.po
+++ b/po/da.po
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# Danish translation for systemd.
# Copyright (C) 2014 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
@@ -17,66 +19,67 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "Send adgangssætning tilbage til systemet"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr ""
# "Autentificering er nødvendig for at sende adgangssætning tilbage til systemet."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "Håndtér system services eller andre enheder"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr ""
# "Autentificering er nødvendig for at håndtere system services og andre enheder."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "Håndtér system services eller enhedsfiler"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr ""
# "Autentificering er nødvendig for at håndtere system service eller enhedsfiler."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr ""
# "Sæt eller fjern system- og service-forvalter miljøvariabler"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
# "environment variables."
# msgstr "Autentificering er nødvendig for at sætte eller fjerne system- "
# "og service-forvalter miljøvariabler."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "Genindlæs systemd tilstand"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr "Autentificering er nødvendig for at genindlæse systemd tilstanden."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "Sæt værtsnavn"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "Autentificering er nødvendig for at sætte værtsnavn."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "Sæt statisk værstnavn"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
@@ -84,60 +87,62 @@ msgstr ""
# msgstr ""
# "Autentificering er nødvendig for at sætte det statisk konfigurerede lokale "
# "værtsnavn, lige så vel som det pæne værtsnavn."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "Sæt maskininformation."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr "Autentificering er nødvendig for at sætte lokal maskininformation."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "Importér en VM eller container billede"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr ""
# "Autentificering er nødvendig for at importére en VM eller "
# "container billeder."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "Exportér en VM eller container billede"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr "Autentificering er nødvendig for at exportére en VM eller container billede"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "Hent en VM eller container billede"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr "Autentificering er nødvendig for at hente en VM eller container billede"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "Sæt sprogindstillinger for systemet"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr ""
# "Autentificering er nødvendig for at sætte sprogindstillinger "
# "for systemet."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "Sæt tastaturindstillinger for systemet."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr ""
# "Autentificering er nødvendig for at sætte tastaturindstillinger "
# "for systemet."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -449,77 +454,78 @@ msgstr "Sæt broadcast-besked"
msgid "Authentication is required to set a wall message"
msgstr "Autentificering er nødvendig for at sætte en broadcast-besked"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "Log på en lokal container"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr "Autentificering er nødvendig for at logge på en lokal container."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "Log på den lokale vært"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr "Auitentificering er nødvendig for at logge på den lokale vært."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "Anskaf en shell i en lokal container"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr ""
# "Autentificering er nødvendig for at anskaffe en shell i en lokal "
# "container."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "Anskaf en shell på den lokale vært"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr ""
# "Autentificering er nødvendig for at anskaffe en shell på den lokale vært."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "Anskaf en pseudo-TTY i en lokal container"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr ""
# "Autentificering er nødvendig for at anskaffe en pseudo-TTY i en lokal "
# "container."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "Anskaf en pseudo-TTY på den lokale vært"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr ""
# "Autentificering er nødvendig for at anskaffe en pseudo-TTY på den "
# "lokale vært."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "Håndtér lokale virtuelle maskiner og containere"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr ""
# "Autentificering er nødvendig for at håndtere lokale virtuelle maskiner og "
# "containere."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "Håndtér lokal virtuel maskine- og container billeder"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
@@ -527,27 +533,27 @@ msgstr "Autentificering er nødvendig for at sætte en broadcast-besked"
# msgstr ""
# "Autentificering er nødvendig for at håndtere lokal virtuel maskine- og "
# "container billeder."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "Sæt tiden for systemet"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "Autentificering er nødvendig for at sætte tiden for systemet."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "Sæt tidszone for systemet"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr "Autentificering er nødvendig for at sætte tidszonen for systemet."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr "Sæt RTC til lokal tidszone eller UTC"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
@@ -555,11 +561,11 @@ msgstr "Autentificering er nødvendig for at sætte en broadcast-besked"
# msgstr ""
# "Autentificering er nødvendig for at kontrollere hvorvidt RTC'en gemmer "
# "den lokale tid eller UTC tid."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "Slå synkronisering af netværkstid til eller fra"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
@@ -567,43 +573,45 @@ msgstr "Autentificering er nødvendig for at sætte en broadcast-besked"
# msgstr ""
# "Autentificering er nødvendig for at kontrollere hvorvidt synkronisering af "
# "netværkstid skal aktiveres"
-
+#
# #: ../src/core/dbus-unit.c:428
# msgid "Authentication is required to start '$(unit)'."
# msgstr "Autentificering er nødvendig for at starte '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:429
# msgid "Authentication is required to stop '$(unit)'."
# msgstr "Autentificering er nødvendig for at stoppe '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:430
# msgid "Authentication is required to reload '$(unit)'."
# msgstr "Autentificering er nødvendig for at genindlæse '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
# msgid "Authentication is required to restart '$(unit)'."
# msgstr "Autentificering at nødvendig for at genstarte '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:535
# msgid "Authentication is required to kill '$(unit)'."
# msgstr "Autentificering er nødvendig for at eliminere '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:565
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
# msgstr ""
-# "Autentificering er nødvendig for at nulstille \"fejl" tilstanden på '$(unit)'."
-
+# "Autentificering er nødvendig for at nulstille \"fejl\" tilstanden på '$(unit)'."
+#
# #: ../src/core/dbus-unit.c:597
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr ""
# "Autentificering er nødvendig for at sætte egenskaber på '$(unit)'."
+#
+# #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
+# #~ msgstr ""
+# #~ "Tryk Ctrl-C for at annulere alle igangværende kontrolleringer af "
+# #~ "filsystemet"
+#
+# #~ msgid "Checking in progress on %d disk (%3.1f%% complete)"
+# #~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
+# #~ msgstr[0] "Igangværende kontrollering på %d disk (%3.1f%% færdig)"
+# #~ msgstr[1] "Igangværende kontrollering på %d diske (%3.1f%% færdig)"
+#endif // 0
-#~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
-#~ msgstr ""
-#~ "Tryk Ctrl-C for at annulere alle igangværende kontrolleringer af "
-#~ "filsystemet"
-
-#~ msgid "Checking in progress on %d disk (%3.1f%% complete)"
-#~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
-#~ msgstr[0] "Igangværende kontrollering på %d disk (%3.1f%% færdig)"
-#~ msgstr[1] "Igangværende kontrollering på %d diske (%3.1f%% færdig)"
diff --git a/po/de.po b/po/de.po
index 8916302fa..72536dbab 100644
--- a/po/de.po
+++ b/po/de.po
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# German translation for systemd.
# Copyright (C) 2014 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
@@ -20,68 +22,69 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Gtranslator 2.91.6\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "Passphrase zurück an das System senden"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr ""
# "Legitimierung ist zum Senden des eingegebenen Kennworts zurück an das System "
# "notwendig."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "Systemdienste und andere Einheiten verwalten"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr ""
# "Legitimierung ist notwendig für die Verwaltung von Systemdiensten und "
# "anderen Einheiten."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "Systemdienste und Einheitendateien verwalten"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr ""
# "Legitimierung ist notwendig für die Verwaltung von Systemdiensten und "
# "Einheitendateien."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr ""
# "Umgebungsvariablen der System- und Dienstverwaltung festlegen oder entfernen"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
# "environment variables."
# msgstr "Legitimierung ist notwendig für die System- und Dienstverwaltung."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "Den systemd-Zustand neu laden"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr "Legitimierung ist zum erneuten Laden des systemd-Zustands notwendig."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "Rechnername festlegen"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "Legitimierung ist zum Festlegen des lokalen Rechnernamens notwendig"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "Statischen Rechnernamen festlegen"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
@@ -89,66 +92,68 @@ msgstr ""
# msgstr ""
# "Authentifizierung ist erforderlich, um den statisch geänderten, lokalen "
# "Rechnernamen, sowie den beschönigten Rechnernamen festzulegen."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "Maschinen-Information festlegen"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr ""
# "Legitimierung ist zum Festlegen der lokalen Maschinen-Information "
# "erforderlich."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "Abbild einer VM oder eines Containers importieren"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr ""
# "Legitimierung ist zum Importieren eines VM- oder Containerabbilds "
# "erforderlich"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "Abbild einer VM oder eines Containers exportieren"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr ""
# "Legitimierung ist zum Exportieren eines VM- oder Containerabbilds "
# "erforderlich"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "Abbild einer VM oder eines Containers herunterladen"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr ""
# "Legitimierung ist zum Herunterladen eines VM- oder Containerabbilds "
# "erforderlich"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "Die lokale Sprachumgebung festlegen"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr ""
# "Legitimierung ist zum Festlegen der systemweiten Spracheinstellungen "
# "erforderlich."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "Tastatureinstellungen des Systems festlegen"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr ""
# "Legitimierung ist zum Festlegen der Tastatureinstellungen des Systems "
# "erforderlich."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -474,77 +479,78 @@ msgstr "Nachricht an alle einstellen"
msgid "Authentication is required to set a wall message"
msgstr "Legitimierung ist zum Einstellen einer Nachricht an alle notwendig"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "In einem lokalen Container anmelden"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr "Legitimierung ist zum Anmelden in einem lokalen Container notwendig."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "Am lokalen Rechner anmelden"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr "Legitimierung ist zum Anmelden am lokalen Rechner notwendig."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "Eine Shell in einem lokalen Container erhalten"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr ""
# "Legitimierung ist zum Erhalten einer Shell in einem lokalen Container "
# "notwendig."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "Eine Shell auf dem lokalen Rechner erhalten"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr ""
# "Legitimierung ist zum Erhalten einer Shell auf dem lokalen Rechner notwendig."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "Ein Pseudo-TTY in einem lokalen Container erhalten"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr ""
# "Legitimierung ist zum Erhalten eines Pseudo-TTY in einem lokalen Container "
# "notwendig."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "Ein Pseudo-TTY auf dem lokalen Rechner erhalten"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr ""
# "Legitimierung ist zum Erhalten eines Pseudo-TTY auf dem lokalen Rechner "
# "notwendig."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "Lokale virtuelle Maschinen und Container verwalten"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr ""
# "Legitimierung ist zum Verwalten lokaler virtueller Maschinen und Container "
# "erforderlich."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "Lokale virtuelle Maschinen und Containerabbilder verwalten"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
@@ -552,27 +558,27 @@ msgstr "Legitimierung ist zum Einstellen einer Nachricht an alle notwendig"
# msgstr ""
# "Legitimierung ist zum Verwalten lokaler virtueller Maschinen und "
# "Containerabbildern erforderlich."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "Die Systemzeit festlegen"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "Legitimierung ist zum Festlegen der Systemzeit notwendig."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "Die Systemzeitzone festlegen"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr "Legitimierung ist zum Festlegen der Systemzeitzone notwendig."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr "Echtzeituhr auf lokale Zeitzone oder UTC setzen"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
@@ -580,11 +586,11 @@ msgstr "Legitimierung ist zum Einstellen einer Nachricht an alle notwendig"
# msgstr ""
# "Legitimierung ist notwendig zum Festlegen, ob die Echtzeituhr auf lokale "
# "Zeitzone oder UTC eingestellt ist."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "Netzwerkzeitabgeich ein- oder ausschalten"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
@@ -592,42 +598,44 @@ msgstr "Legitimierung ist zum Einstellen einer Nachricht an alle notwendig"
# msgstr ""
# "Legitimierung ist zum Festlegen, ob Netzwerkzeitabgeich eingeschaltet sein "
# "soll, erforderlich."
-
+#
# #: ../src/core/dbus-unit.c:428
# msgid "Authentication is required to start '$(unit)'."
# msgstr "Legitimierung ist zum Starten von »$(unit)« notwendig."
-
+#
# #: ../src/core/dbus-unit.c:429
# msgid "Authentication is required to stop '$(unit)'."
# msgstr "Legitimierung ist zum Stoppen von »$(unit)« notwendig."
-
+#
# #: ../src/core/dbus-unit.c:430
# msgid "Authentication is required to reload '$(unit)'."
# msgstr "Legitimierung ist zum erneuten Laden von »$(unit)« notwendig."
-
+#
# #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
# msgid "Authentication is required to restart '$(unit)'."
# msgstr "Legitimierung ist zum Neustarten von »$(unit)« notwendig."
-
+#
# #: ../src/core/dbus-unit.c:535
# msgid "Authentication is required to kill '$(unit)'."
# msgstr "Legitimierung ist zum Eliminieren von »$(unit)« notwendig."
-
+#
# #: ../src/core/dbus-unit.c:565
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
# msgstr ""
# "Legitimierung ist zum Zurücksetzen des Status »fehlgeschlagen« von »$(unit)« "
# "notwendig"
-
+#
# #: ../src/core/dbus-unit.c:597
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr ""
# "Legitimierung ist zum Festlegen der Eigenschaften von »$(unit)« notwendig."
+#
+# #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
+# #~ msgstr "Strl+C drücken um laufende Dateisystem-Prüfungen abzubrechen"
+#
+# #~ msgid "Checking in progress on %d disk (%3.1f%% complete)"
+# #~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
+# #~ msgstr[0] "Prüfe %d Laufwerk (%3.1f%% fertig)"
+# #~ msgstr[1] "Prüfe %d Laufwerke (%3.1f%% fertig)"
+#endif // 0
-#~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
-#~ msgstr "Strl+C drücken um laufende Dateisystem-Prüfungen abzubrechen"
-
-#~ msgid "Checking in progress on %d disk (%3.1f%% complete)"
-#~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
-#~ msgstr[0] "Prüfe %d Laufwerk (%3.1f%% fertig)"
-#~ msgstr[1] "Prüfe %d Laufwerke (%3.1f%% fertig)"
diff --git a/po/el.po b/po/el.po
index 40efcc42a..57f1f680e 100644
--- a/po/el.po
+++ b/po/el.po
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# Greek translation for systemd.
# Copyright (C) 2014 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
@@ -18,44 +20,45 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Virtaal 0.7.0\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "Αποστολή του συνθηματικού πίσω στο σύστημα"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr ""
# "Απαιτείται πιστοποίηση για αποστολή του εισερχόμενου συνθηματικού πίσω στο "
# "σύστημα."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr ""
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# #, fuzzy
# msgid "Authentication is required to manage system services or other units."
# msgstr ""
# "Απαιτείται πιστοποίηση για να προσπελάσετε τον διαχειριστή συστήματος και "
# "υπηρεσιών."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr ""
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# #, fuzzy
# msgid "Authentication is required to manage system service or unit files."
# msgstr ""
# "Απαιτείται πιστοποίηση για να προσπελάσετε τον διαχειριστή συστήματος και "
# "υπηρεσιών."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# #, fuzzy
# msgid "Set or unset system and service manager environment variables"
# msgstr "Προνομιούχος πρόσβαση διαχειριστή συστήματος και υπηρεσίας"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# #, fuzzy
# msgid ""
@@ -64,29 +67,29 @@ msgstr ""
# msgstr ""
# "Απαιτείται πιστοποίηση για να προσπελάσετε τον διαχειριστή συστήματος και "
# "υπηρεσιών."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# #, fuzzy
# msgid "Reload the systemd state"
# msgstr "Επανεκκίνηση του συστήματος"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# #, fuzzy
# msgid "Authentication is required to reload the systemd state."
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "Ορισμός ονόματος οικοδεσπότη"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "Ορισμός στατικού ονόματος οικοδεσπότη"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
@@ -94,60 +97,62 @@ msgstr ""
# msgstr ""
# "Απαιτείται πιστοποίηση για να ορίσετε το στατικά ρυθμισμένο όνομα τοπικού "
# "οικοδεσπότη, καθώς και το pretty όνομα οικοδεσπότη."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "Ορισμός πληροφοριών μηχανής"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε πληροφορίες τοπικής μηχανής."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr ""
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# #, fuzzy
# msgid "Authentication is required to import a VM or container image"
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr ""
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# #, fuzzy
# msgid "Authentication is required to export a VM or container image"
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr ""
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# #, fuzzy
# msgid "Authentication is required to download a VM or container image"
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε πληροφορίες τοπικής μηχανής."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "Ορισμός τοπικών ρυθμίσεων συστήματος"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr ""
# "Απαιτείται πιστοποίηση για να ορίσετε τις τοπικές ρυθμίσεις του συστήματος."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "Ορισμός ρυθμίσεων πληκτρολογίου συστήματος"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr ""
# "Απαιτείται πιστοποίηση για να ορίσετε τις ρυθμίσεις πληκτρολογίου του "
# "συστήματος."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -460,104 +465,105 @@ msgstr ""
msgid "Authentication is required to set a wall message"
msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr ""
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# #, fuzzy
# msgid "Authentication is required to log into a local container."
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr ""
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# #, fuzzy
# msgid "Authentication is required to log into the local host."
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# #, fuzzy
# msgid "Acquire a shell in a local container"
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# #, fuzzy
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr ""
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# #, fuzzy
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# #, fuzzy
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# #, fuzzy
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr ""
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# #, fuzzy
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr ""
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# #, fuzzy
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε πληροφορίες τοπικής μηχανής."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr ""
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# #, fuzzy
# msgid ""
# "Authentication is required to manage local virtual machine and container "
# "images."
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε πληροφορίες τοπικής μηχανής."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "Ορισμός ώρας συστήματος"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "Ορισμός ζώνης ώρας συστήματος"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα ζώνης του συστήματος."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr "Ορισμός RTC στην τοπική ζώνη ώρας ή UTC"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
@@ -565,11 +571,11 @@ msgstr "Απαιτείται πιστοποίηση για να ορίσετε
# msgstr ""
# "Απαιτείται πιστοποίηση για να ελέγξετε αν το RTC αποθηκεύει την τοπική ή την "
# "ώρα UTC."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "Ενεργοποίηση/Απενεργοποίηση συγχρονισμού ώρας δικτύου"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
@@ -577,38 +583,40 @@ msgstr "Απαιτείται πιστοποίηση για να ορίσετε
# msgstr ""
# "Απαιτείται πιστοποίηση για να ελέγξετε αν ο συγχρονισμός ώρας δικτύου θα "
# "ενεργοποιηθεί."
-
+#
# #: ../src/core/dbus-unit.c:428
# #, fuzzy
# msgid "Authentication is required to start '$(unit)'."
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος."
-
+#
# #: ../src/core/dbus-unit.c:429
# #, fuzzy
# msgid "Authentication is required to stop '$(unit)'."
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος."
-
+#
# #: ../src/core/dbus-unit.c:430
# #, fuzzy
# msgid "Authentication is required to reload '$(unit)'."
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος."
-
+#
# #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
# #, fuzzy
# msgid "Authentication is required to restart '$(unit)'."
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος."
-
+#
# #: ../src/core/dbus-unit.c:535
# #, fuzzy
# msgid "Authentication is required to kill '$(unit)'."
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
-
+#
# #: ../src/core/dbus-unit.c:565
# #, fuzzy
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη."
-
+#
# #: ../src/core/dbus-unit.c:597
# #, fuzzy
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος."
+#endif // 0
+
diff --git a/po/es.po b/po/es.po
index 71cedb949..0e4381e50 100644
--- a/po/es.po
+++ b/po/es.po
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# Spanish translation for systemd.
# Copyright (C) 2015 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
@@ -20,40 +22,41 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.8.7.1\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "Devolver contraseña al sistema"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr ""
# "Se requiere autenticación para devolver la contraseña introducida al sistema."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "Administrar servicios del sistema u otras unidades"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr ""
# "Se requiere autenticación para administrar los servicios de sistema u otras "
# "unidades."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "Administrar servicio del sistema o archivos de unidad"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr ""
# "Se requiere autenticación para administrar el servicio de sistema o los "
# "archivos de unidad."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr "Administrar variables de entorno del sistema y del gestor de servicios"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
@@ -61,27 +64,27 @@ msgstr ""
# msgstr ""
# "Se requiere autenticación para administrar las variables de entorno del "
# "sistema y del gestor de servicios."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "Recargar el estado de systemd"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr "Se requiere autenticación para recargar el estado de systemd."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "Establecer el nombre del equipo"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "Se requiere autenticación para establecer el nombre del equipo local."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "Establecer nombre estático del equipo"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
@@ -89,61 +92,63 @@ msgstr ""
# msgstr ""
# "Se requiere autenticación para establecer el nombre estático de equipo "
# "local, así como el nombre visible del equipo."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "Establecer información del sistema"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr ""
# "Se requiere autenticación para establecer la información de sistema local."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "Importar una imagen de máquina virtual o de contenedor"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr ""
# "Se requiere autenticación para importar una imagen de máquina virtual o de "
# "contenedor"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "Exportar imagen de máquina virtual o de contenedor"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr ""
# "Se requiere autenticación para exportar una imagen de máquina virtual o de "
# "contenedor"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "Descargar una imagen de máquina virtual o de contenedor"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr ""
# "Se requiere autenticación para descargar una imagen de máquina virtual o de "
# "contenedor"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "Establecer región del sistema"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr "Se requiere autenticación para establecer la región del sistema."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "Configurar teclado"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr "Se requiere autenticación para configurar el teclado del sistema."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -454,76 +459,77 @@ msgstr "Establecer muro de texto"
msgid "Authentication is required to set a wall message"
msgstr "Se requiere autenticación para establecer un muro de texto"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "Conectarse a un contenedor local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr "Se requiere autenticación para conectarse a un contenedor local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "Conectarse al equipo local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr "Se requiere autenticación para conectarse al equipo local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "Se adquiere un intérprete de órdenes en un contenedor local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr ""
# "Se requiere autenticación para adquirir un intérprete de órdenes en un "
# "contenedor local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "Se adquiere un intérprete de órdenes en el equipo local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr ""
# "Se requiere autenticación para adquirir un intérprete de órdenes del equipo "
# "local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "Se adquiere un seudo-TTY en el contenedor local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr ""
# "Se requiere autenticación para adquirir un seudo-TTY en el contenedor local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "Se adquiere un seudo-TTY en el equipo local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr ""
# "Se requiere autenticación para adquirir un seudo-TTY en el equipo local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "Administrar máquinas virtuales y contenedores locales"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr ""
# "Se requiere autenticación para administrar las máquinas virtuales y los "
# "contenedores locales."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "Administrar imágenes de máquina virtual y de contenedores locales"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
@@ -531,27 +537,27 @@ msgstr "Se requiere autenticación para establecer un muro de texto"
# msgstr ""
# "Se requiere autenticación para administrar las imágenes de máquina virtual y "
# "de contenedores locales."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "Establecer fecha y hora del sistema"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "Se requiere autenticación para establecer la fecha y hora del sistema."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "Establecer la zona horaria del sistema"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr "Se requiere autenticación para establecer la zona horaria del sistema."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr "Establecer reloj del sistema en formato de hora local/tiempo UTC"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
@@ -559,11 +565,11 @@ msgstr "Se requiere autenticación para establecer un muro de texto"
# msgstr ""
# "Se requiere autenticación para establecer el reloj del sistema en formato de "
# "hora local o tiempo UTC."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "Activar/desactivar la sincronización de hora por red"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
@@ -571,42 +577,44 @@ msgstr "Se requiere autenticación para establecer un muro de texto"
# msgstr ""
# "Se requiere autenticación para activar/desactivar la sincronización de hora "
# "por red."
-
+#
# #: ../src/core/dbus-unit.c:428
# msgid "Authentication is required to start '$(unit)'."
# msgstr "Se requiere autenticación para iniciar '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:429
# msgid "Authentication is required to stop '$(unit)'."
# msgstr "Se requiere autenticación para detener '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:430
# msgid "Authentication is required to reload '$(unit)'."
# msgstr "Se requiere autenticación para recargar '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
# msgid "Authentication is required to restart '$(unit)'."
# msgstr "Se requiere autenticación para reiniciar '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:535
# msgid "Authentication is required to kill '$(unit)'."
# msgstr "Se requiere autenticación para matar a '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:565
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
# msgstr "Se requiere autenticación para reiniciar el estado de «fallido» de '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:597
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr ""
# "Se requiere autenticación para establecer las propiedades de '$(unit)'."
+#
+# #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
+# #~ msgstr ""
+# #~ "Presione Ctrl+C para cancelar todas las comprobaciones del sistema de "
+# #~ "archivos en curso"
+#
+# #~ msgid "Checking in progress on %d disk (%3.1f%% complete)"
+# #~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
+# #~ msgstr[0] "Comprobando progreso en %d disco (%3.1f %% completado)"
+# #~ msgstr[1] "Comprobando progreso en %d discos (%3.1f %% completado)"
+#endif // 0
-#~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
-#~ msgstr ""
-#~ "Presione Ctrl+C para cancelar todas las comprobaciones del sistema de "
-#~ "archivos en curso"
-
-#~ msgid "Checking in progress on %d disk (%3.1f%% complete)"
-#~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
-#~ msgstr[0] "Comprobando progreso en %d disco (%3.1f %% completado)"
-#~ msgstr[1] "Comprobando progreso en %d discos (%3.1f %% completado)"
diff --git a/po/fr.po b/po/fr.po
index 852c3e78e..7add4d7f9 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -1,14 +1,16 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# French translations for systemd package
# Traductions françaises du paquet systemd.
# This file is distributed under the same license as the systemd package.
-# Sylvain Plantefève <sylvain.plantefeve@gmail.com>, 2013-2016
+# Sylvain Plantefève <sylvain.plantefeve@gmail.com>, 2013-2017
#
msgid ""
msgstr ""
"Project-Id-Version: systemd\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-04-24 21:13+0200\n"
-"PO-Revision-Date: 2014-12-28 13:04+0100\n"
+"PO-Revision-Date: 2017-10-18 21:30+0200\n"
"Last-Translator: Sylvain Plantefève <sylvain.plantefeve@gmail.com>\n"
"Language-Team: French\n"
"Language: fr\n"
@@ -17,40 +19,41 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "Renvoyer la phrase secrète au système"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr "Authentification requise pour renvoyer la phrase secrète au système."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "Gérer les services système ou les unités"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr ""
# "Authentification requise pour gérer les services système ou les unités."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "Gérer le service système ou ses fichiers unités"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr ""
# "Authentification requise pour gérer le service système ou ses fichiers "
# "unités."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr ""
# "Définir ou supprimer des variables d'environnement du système ou du "
# "gestionnaire de services"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
@@ -58,27 +61,27 @@ msgstr ""
# msgstr ""
# "Authentification requise pour définir ou supprimer des variables "
# "d'environnement du système ou du gestionnaire de services."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "Recharger l'état de systemd"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr "Authentification requise pour recharger l'état de systemd"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "Définir le nom d'hôte"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "Authentification requise pour définir le nom d'hôte local."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "Définir le nom d'hôte statique"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
@@ -86,62 +89,64 @@ msgstr ""
# msgstr ""
# "Authentification requise pour définir le nom d'hôte local de manière "
# "statique, tout comme le nom d'hôte familier."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "Définir les informations sur la machine"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr ""
# "Authentification requise pour définir les informations sur la machine locale."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "Importer une image de machine virtuelle (VM) ou de conteneur"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr ""
# "Authentification requise pour importer une image de machine virtuelle (VM) "
# "ou de conteneur."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "Exporter une image de machine virtuelle (VM) ou de conteneur"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr ""
# "Authentification requise pour exporter une image de machine virtuelle (VM) "
# "ou de conteneur."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "Télécharger une image de machine virtuelle (VM) ou de conteneur"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr ""
# "Authentification requise pour télécharger une image de machine virtuelle "
# "(VM) ou de conteneur."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "Définir la langue du système"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr "Authentification requise pour définir la langue du système."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "Définir les paramètres de clavier du système"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr ""
# "Authentification requise pour définir les paramètres de clavier du système."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -358,19 +363,53 @@ msgstr ""
"a demandé de l'empêcher."
#: ../src/login/org.freedesktop.login1.policy.in.h:39
+msgid "Halt the system"
+msgstr "Arrêter le système"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:40
+msgid "Authentication is required for halting the system."
+msgstr "Authentification requise pour arrêter le système."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:41
+msgid "Halt the system while other users are logged in"
+msgstr ""
+"Arrêter le système alors que d'autres utilisateurs sont connectés"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:42
+msgid ""
+"Authentication is required for halting the system while other users are "
+"logged in."
+msgstr ""
+"Authentification requise pour arrêter le système alors que d'autres "
+"utilisateurs sont connectés."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:43
+msgid "Halt the system while an application asked to inhibit it"
+msgstr ""
+"Arrêter le système alors qu'une application a demandé de l'empêcher"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:44
+msgid ""
+"Authentication is required for halting the system while an application "
+"asked to inhibit it."
+msgstr ""
+"Authentification requise pour arrêter le système alors qu'une "
+"application a demandé de l'empêcher."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:45
msgid "Suspend the system"
msgstr "Mettre le système en veille"
-#: ../src/login/org.freedesktop.login1.policy.in.h:40
+#: ../src/login/org.freedesktop.login1.policy.in.h:46
msgid "Authentication is required for suspending the system."
msgstr "Authentification requise pour mettre le système en veille."
-#: ../src/login/org.freedesktop.login1.policy.in.h:41
+#: ../src/login/org.freedesktop.login1.policy.in.h:47
msgid "Suspend the system while other users are logged in"
msgstr ""
"Mettre le système en veille alors que d'autres utilisateurs sont connectés"
-#: ../src/login/org.freedesktop.login1.policy.in.h:42
+#: ../src/login/org.freedesktop.login1.policy.in.h:48
msgid ""
"Authentication is required for suspending the system while other users are "
"logged in."
@@ -378,12 +417,12 @@ msgstr ""
"Authentification requise pour mettre le système en veille alors que d'autres "
"utilisateurs sont connectés."
-#: ../src/login/org.freedesktop.login1.policy.in.h:43
+#: ../src/login/org.freedesktop.login1.policy.in.h:49
msgid "Suspend the system while an application asked to inhibit it"
msgstr ""
"Mettre le système en veille alors qu'une application a demandé de l'empêcher"
-#: ../src/login/org.freedesktop.login1.policy.in.h:44
+#: ../src/login/org.freedesktop.login1.policy.in.h:50
msgid ""
"Authentication is required for suspending the system while an application "
"asked to inhibit it."
@@ -391,21 +430,21 @@ msgstr ""
"Authentification requise pour mettre le système en veille alors qu'une "
"application a demandé de l'empêcher."
-#: ../src/login/org.freedesktop.login1.policy.in.h:45
+#: ../src/login/org.freedesktop.login1.policy.in.h:51
msgid "Hibernate the system"
msgstr "Mettre le système en hibernation"
-#: ../src/login/org.freedesktop.login1.policy.in.h:46
+#: ../src/login/org.freedesktop.login1.policy.in.h:52
msgid "Authentication is required for hibernating the system."
msgstr "Authentification requise pour mettre le système en hibernation."
-#: ../src/login/org.freedesktop.login1.policy.in.h:47
+#: ../src/login/org.freedesktop.login1.policy.in.h:53
msgid "Hibernate the system while other users are logged in"
msgstr ""
"Mettre le système en hibernation alors que d'autres utilisateurs sont "
"connectés"
-#: ../src/login/org.freedesktop.login1.policy.in.h:48
+#: ../src/login/org.freedesktop.login1.policy.in.h:54
msgid ""
"Authentication is required for hibernating the system while other users are "
"logged in."
@@ -413,13 +452,13 @@ msgstr ""
"Authentification requise pour mettre le système en hibernation alors que "
"d'autres utilisateurs sont connectés."
-#: ../src/login/org.freedesktop.login1.policy.in.h:49
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
msgid "Hibernate the system while an application asked to inhibit it"
msgstr ""
"Mettre le système en hibernation alors qu'une application a demandé de "
"l'empêcher"
-#: ../src/login/org.freedesktop.login1.policy.in.h:50
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
msgid ""
"Authentication is required for hibernating the system while an application "
"asked to inhibit it."
@@ -427,34 +466,34 @@ msgstr ""
"Authentification requise pour mettre le système en hibernation alors qu'une "
"application a demandé de l'empêcher."
-#: ../src/login/org.freedesktop.login1.policy.in.h:51
+#: ../src/login/org.freedesktop.login1.policy.in.h:57
msgid "Manage active sessions, users and seats"
msgstr "Gérer les sessions actives, les utilisateurs et les postes (seats)"
-#: ../src/login/org.freedesktop.login1.policy.in.h:52
+#: ../src/login/org.freedesktop.login1.policy.in.h:58
msgid ""
"Authentication is required for managing active sessions, users and seats."
msgstr ""
"Authentification requise pour gérer les sessions actives, les utilisateurs "
"et les postes (seats)."
-#: ../src/login/org.freedesktop.login1.policy.in.h:53
+#: ../src/login/org.freedesktop.login1.policy.in.h:59
msgid "Lock or unlock active sessions"
msgstr "Verrouiller ou déverrouiller des sessions actives"
-#: ../src/login/org.freedesktop.login1.policy.in.h:54
+#: ../src/login/org.freedesktop.login1.policy.in.h:60
msgid "Authentication is required to lock or unlock active sessions."
msgstr ""
"Authentification requise pour verrouiller ou déverrouiller des sessions "
"actives."
-#: ../src/login/org.freedesktop.login1.policy.in.h:55
+#: ../src/login/org.freedesktop.login1.policy.in.h:61
msgid "Allow indication to the firmware to boot to setup interface"
msgstr ""
"Permet d'indiquer au micrologiciel de démarrer sur l'interface de "
"configuration"
-#: ../src/login/org.freedesktop.login1.policy.in.h:56
+#: ../src/login/org.freedesktop.login1.policy.in.h:62
msgid ""
"Authentication is required to indicate to the firmware to boot to setup "
"interface."
@@ -462,85 +501,86 @@ msgstr ""
"Authentification requise pour indiquer au micrologiciel de démarrer sur "
"l'interface de configuration."
-#: ../src/login/org.freedesktop.login1.policy.in.h:57
+#: ../src/login/org.freedesktop.login1.policy.in.h:63
msgid "Set a wall message"
msgstr "Définir un message wall"
-#: ../src/login/org.freedesktop.login1.policy.in.h:58
+#: ../src/login/org.freedesktop.login1.policy.in.h:64
msgid "Authentication is required to set a wall message"
msgstr "Authentification requise pour définir un message wall."
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "Connexion dans un conteneur local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr ""
# "Authentification requise pour permettre la connexion dans un conteneur local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "Connexion à l'hôte local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr "Authentification requise pour permettre la connexion à l'hôte local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "Obtenir une interface système dans un conteneur local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr ""
# "Authentification requise pour obtenir une interface système dans un "
# "conteneur local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "Obtenir une interface système sur l'hôte local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr ""
# "Authentification requise pour obtenir une interface système sur l'hôte local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "Obtenir un pseudo terminal dans un conteneur local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr ""
# "Authentification requise pour obtenir un pseudo terminal dans un conteneur "
# "local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "Obtenir un pseudo terminal sur l'hôte local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr ""
# "Authentification requise pour obtenir un pseudo terminal sur l'hôte local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "Gérer les machines virtuelles (VM) et conteneurs locaux"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr ""
# "Authentification requise pour gérer les machines virtuelles (VM) et les "
# "conteneurs locaux."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "Gérer les images locales de machines virtuelles (VM) et de conteneurs"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
@@ -548,29 +588,29 @@ msgstr "Authentification requise pour définir un message wall."
# msgstr ""
# "Authentification requise pour gérer les images locales de machines "
# "virtuelles (VM) et de conteneurs."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "Définir l'heure du système"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "Authentification requise pour définir l'heure du système."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "Définir le fuseau horaire du système"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr "Authentification requise pour définir le fuseau horaire du système."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr ""
# "Positionner l'horloge matérielle à l'heure locale ou sur le temps universel "
# "coordonné (UTC)"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
@@ -578,11 +618,11 @@ msgstr "Authentification requise pour définir un message wall."
# msgstr ""
# "Authentification requise pour positionner l'horloge matérielle à l'heure "
# "locale ou sur le temps universel coordonné (UTC)."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "Activer ou désactiver la synchronisation de l'heure avec le réseau"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
@@ -590,43 +630,45 @@ msgstr "Authentification requise pour définir un message wall."
# msgstr ""
# "Authentification requise pour activer ou désactiver la synchronisation de "
# "l'heure avec le réseau."
-
-# #: ../src/core/dbus-unit.c:450
+#
+# #: ../src/core/dbus-unit.c:458
# msgid "Authentication is required to start '$(unit)'."
# msgstr "Authentification requise pour démarrer « $(unit) »."
-
-# #: ../src/core/dbus-unit.c:451
+#
+# #: ../src/core/dbus-unit.c:459
# msgid "Authentication is required to stop '$(unit)'."
# msgstr "Authentification requise pour arrêter « $(unit) »."
-
-# #: ../src/core/dbus-unit.c:452
+#
+# #: ../src/core/dbus-unit.c:460
# msgid "Authentication is required to reload '$(unit)'."
# msgstr "Authentification requise pour recharger « $(unit) »."
-
-# #: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454
+#
+# #: ../src/core/dbus-unit.c:461 ../src/core/dbus-unit.c:462
# msgid "Authentication is required to restart '$(unit)'."
# msgstr "Authentification requise pour redémarrer « $(unit) »."
-
-# #: ../src/core/dbus-unit.c:560
+#
+# #: ../src/core/dbus-unit.c:569
# msgid "Authentication is required to kill '$(unit)'."
# msgstr "Authentification requise pour tuer « $(unit) »."
-
-# #: ../src/core/dbus-unit.c:590
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
+#
+# #: ../src/core/dbus-unit.c:600
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
# msgstr ""
# "Authentification requise pour réinitialiser l'état d'« échec » de "
# "« $(unit) »."
-
-# #: ../src/core/dbus-unit.c:622
+#
+# #: ../src/core/dbus-unit.c:633
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr "Authentification requise pour définir des propriétés de « $(unit) »."
+#
+# #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
+# #~ msgstr ""
+# #~ "Appuyez sur Ctrl+C pour annuler toutes vérifications en cours du système "
+# #~ "de fichiers"
+#
+# #~ msgid "Checking in progress on %d disk (%3.1f%% complete)"
+# #~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
+# #~ msgstr[0] "Vérification en cours sur %d disque (%3.1f%% complété)"
+# #~ msgstr[1] "Vérification en cours sur %d disques (%3.1f%% complété)"
+#endif // 0
-#~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
-#~ msgstr ""
-#~ "Appuyez sur Ctrl+C pour annuler toutes vérifications en cours du système "
-#~ "de fichiers"
-
-#~ msgid "Checking in progress on %d disk (%3.1f%% complete)"
-#~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
-#~ msgstr[0] "Vérification en cours sur %d disque (%3.1f%% complété)"
-#~ msgstr[1] "Vérification en cours sur %d disques (%3.1f%% complété)"
diff --git a/po/gl.po b/po/gl.po
index 2bfebb91c..5de38a741 100644
--- a/po/gl.po
+++ b/po/gl.po
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# Copyright (C) 2015
# This file is distributed under the same license as the systemd package.
# Fran Dieguez <frandieguez@gnome.org>, 2015.
@@ -16,43 +18,44 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Virtaal 0.7.1\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "Enviar frase de paso de volta ao sistema"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr ""
# "Requírese autenticación para enviar a frase de paso escrita de volta ao "
# "sistema."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "Xestionar os servizos do sistema ou outras unidades"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr ""
# "Requírese autenticación para xestionar os servizos do sistema ou outras "
# "unidades"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "Xestionar os servizos do sistema ou outros ficheiros"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr ""
# "Requírese autenticación para xestionar os servizos do sistema ou outros "
# "ficheiros."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr ""
# "Estabelecer ou desestabelecer as variables de ambiente do sistema ou do "
# "xestor de servizos"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
@@ -60,27 +63,27 @@ msgstr ""
# msgstr ""
# "Requírese autenticación para estabelecer ou desestabelecer as variables de "
# "ambiente do sistema ou do xestor de servizos"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "Recargar o estado de systemd"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr "Requírese autenticación para recargar o estado de systemd."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "Estabelecer o nome do equipo"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "Requírese autenticación para estabelecer o nome local do equiupo."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "Estabelecer o nome do equipo estático"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
@@ -89,57 +92,59 @@ msgstr ""
# "Requírese autenticación para estabelecer de forma o nome do equipo local "
# "estabelecido de forma estática, así como o nome do equipo lexíbel por "
# "persoas."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "Estabelecer a información da máquina"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr "Requírese autenticación para estabelecer a información da máquina local"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "Importar unha imaxe de MV ou contenedor"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr "Requírese autenticación para imporar unha imaxe de MV ou contenedor"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "Exportar unha imaxe de MV ou contenedor"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr "Requírese autenticación para exportar unha imaxe de MV ou contenedor"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "Descargar unha imaxe de MV ou contenedor"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr "Requírese autenticación para descargar unha imaxe de MV ou contenedor"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "Estabelecer a configuración rexional do sistema"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr ""
# "Requírese autenticación para estabelecer a configuración rexional do sistema"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "Estabelecer as preferencias do teclado do sistema"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr ""
# "Requírese autenticación para estabelecer as preferencias do teclado do "
# "sistema."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -442,71 +447,72 @@ msgstr "Estabelecer a mensaxe do muro"
msgid "Authentication is required to set a wall message"
msgstr "Requírese autenticación para estabelecer unha mensaxe de muro"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "Iniciar sesión nun contenedor local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr "Requírese autenticación para iniciar sesión nun contenedor local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "Iniciar sesión nun equipo local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr "Requírese autenticación para iniciar sesión nun equipo local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "Adquirir unha shell nun contenedor local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr "Requírese autenticación para adquirir unha shell nun contenedor local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "Adquirir unha shell nun equipo local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr "Requírese autenticación para adquirir unha shell nun equipo local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "Adquirir unha pseudo TTY nun contenedor local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr ""
# "Requírese autenticación para adquirir unha pseudo TTY nun contenedor local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "Adquirir unha pseudo TTY nun equipo local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr "Requírese autenticación para adquirir unha pseudo TTY nun equipo local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "Xestionar máquinas virtuais e contenedores locais"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr ""
# "Requírese autenticación para xestionar máquinas virtuais e contenedores "
# "locais."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "Xestionar imaxes locais virtuais e contenedores locais"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
@@ -514,27 +520,27 @@ msgstr "Requírese autenticación para estabelecer unha mensaxe de muro"
# msgstr ""
# "Requírese autenticación para xestionar imaxes de máquinas virtuais e "
# "contenedores locais."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "Estabelecer a hora do sistema"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "Requírese autenticación para estabelecer a hora do sistema."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "Estabelecer o fuso horario"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr "Requírese autenticación para estabelecer o fuso horario do sistema."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr "Estabelecer o RTC ao fuso horario ou UTC"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
@@ -542,11 +548,11 @@ msgstr "Requírese autenticación para estabelecer unha mensaxe de muro"
# msgstr ""
# "Requírese autenticación para controlar se o RTC almacena a hora local ou a "
# "UTC."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "Activar ou desactivar a sincronización de hora por rede"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
@@ -554,31 +560,33 @@ msgstr "Requírese autenticación para estabelecer unha mensaxe de muro"
# msgstr ""
# "Requírese autenticación para controlar se a sincronización de hora por rede "
# "debería activarse."
-
+#
# #: ../src/core/dbus-unit.c:428
# msgid "Authentication is required to start '$(unit)'."
# msgstr "Requírese autenticación para inciar '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:429
# msgid "Authentication is required to stop '$(unit)'."
# msgstr "Requírese autenticación para deter '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:430
# msgid "Authentication is required to reload '$(unit)'."
# msgstr "Requírese autenticación para recargar '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
# msgid "Authentication is required to restart '$(unit)'."
# msgstr "Requírese autenticación para reiniciar '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:535
# msgid "Authentication is required to kill '$(unit)'."
# msgstr "Requírese autenticación para matar '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:565
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
# msgstr "Requírese autenticación para reinicair o estado «fallido» de '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:597
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr "Requírese autenticación para estabelecer as propiedades en '$(unit)'."
+#endif // 0
+
diff --git a/po/hr.po b/po/hr.po
index 8b1f361d8..39ed79780 100644
--- a/po/hr.po
+++ b/po/hr.po
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
@@ -19,36 +21,37 @@ msgstr ""
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"Language: hr\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "Pošalji lozinku natrag u sustav"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr "Potrebna je ovjera za slanje upisane lozinke natrag u sustav."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "Upravljajte uslugama sustava ili drugim jedinicama"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr "Potrebna je ovjera za upravljanje uslugama sustava ili jedinicama."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "Upravljajte uslugama sustava ili datotekama jedinica"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr ""
# "Potrebna je ovjera za upravljanje uslugama sustava ili datotekama jedinica."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr "Postavite ili uklonite varijable okruženja sustava i usluga"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
@@ -56,27 +59,27 @@ msgstr ""
# msgstr ""
# "Potrebna je ovjera za postavljanje ili uklanjanje varijabla okruženja "
# "sustava i usluga."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "Ponovno učitaj systemd stanje"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr "Potrebna je ovjera za ponovno učitavanje systemd stanja."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "Postavi naziv računala"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "Potrebna je ovjera za postavljanje naziva lokalnog računala."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "Postavi nepromjenjivi naziv račumala"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
@@ -84,54 +87,56 @@ msgstr ""
# msgstr ""
# "Potrebna je ovjera za postavljenje nepromjenjivog naziva lokalnog računala, "
# "kao i prijatnog naziva računala."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "Postavi informacije računala"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr "Potrebna je ovjera za postavljanje informacije lokalnog računala."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "Uvezi VM ili spremnik slike"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr "Potrebna je ovjera za uvoz WM ili spremnika slike"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "Izvezi VM ili spremnik slike"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr "Potrebna je ovjera za izvoz WM ili spremnika slike"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "Preuzmi VM ili spremnik slike"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr "Potrebna je ovjera za preuzimanje VM ili spremnika slike."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "Postavi sustav lokalizacije"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr "Potrebna je ovjera za postavljanje sustava lokalizacije."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "Postavi postavke tipkovnice sustava"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr "Potrebna je ovjera za postavljanje postavki tipkovnice sustava."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -430,70 +435,71 @@ msgstr "Postavljanje zaslonske pruke"
msgid "Authentication is required to set a wall message"
msgstr "Potrebna je ovjera za postavljanje zaslonske pruke."
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "Prijavi se u lokalni spremnik"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr "Potrebna je ovjera za prijavu u lokalni spremnik."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "Prijava na lokalno računalo"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr "Potrebna je ovjera za prijavu na lokalno račuanlo."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "Pokretanje ljuske u lokalnom spremniku"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr "Potrebna je ovjera za pokretanje ljuske u lokalnom spremniku."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "Pokretanje ljuske na lokalnom računalu"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr "Potrebna je ovjera za pokretanje ljuske na lokalnom računalu."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "Pokretanje pseudo TTY na lokalnom spremniku"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr "Potrebna je ovjera za pokretanje pseudo TTY na lokalnom spremniku."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "Pokretanje pseudo TTY na lokalnom računalu"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr "Potrebna je ovjera za pokretanje pseudo TTY na lokalnom računalu."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "Upravljanje lokalnim vurtualnim strojevima i spremnicima"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr ""
# "Potrebna je ovjera za upravljanje lokalnim vurtualnim strojevima i "
# "spremnicima."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "Upravljanje lokalnim vurtualnim strojevima i spremnicima slika"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
@@ -501,38 +507,38 @@ msgstr "Potrebna je ovjera za postavljanje zaslonske pruke."
# msgstr ""
# "Potrebna je ovjera za upravljanje lokalnim vurtualnim strojevima i "
# "spremnicima slika."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "Postavi vrijeme sustava"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "Potrebna je ovjera za postavljanje vremena sustava."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "Postavi vremensku zonu sustava"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr "Potrebna je ovjera za postavljanje vremenske zone sustava."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr "Postavi RTC u lokalnu vremensku zonu ili UTC"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
# "UTC time."
# msgstr ""
# "Potrebna je ovjera za postavljanje RTC-a u lokalnu vremensku zonu ili UTC."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "Uključi ili isključi mrežno uklađivanje vremena"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
@@ -540,31 +546,33 @@ msgstr "Potrebna je ovjera za postavljanje zaslonske pruke."
# msgstr ""
# "Potrebna je ovjera za uključivanje ili isključivanje mrežnog usklađivanja "
# "vremena."
-
+#
# #: ../src/core/dbus-unit.c:428
# msgid "Authentication is required to start '$(unit)'."
# msgstr "Potrebna je ovjera za pokretanje '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:429
# msgid "Authentication is required to stop '$(unit)'."
# msgstr "Potrebna je ovjera za zaustavljanje '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:430
# msgid "Authentication is required to reload '$(unit)'."
# msgstr "Potrebna je ovjera za ponovno učitavnje '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
# msgid "Authentication is required to restart '$(unit)'."
# msgstr "Potrebna je ovjera za ponovno pokretanje'$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:535
# msgid "Authentication is required to kill '$(unit)'."
# msgstr "Potrebna je ovjera za ubijanje '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:565
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
-# msgstr "Potrebna je ovjera za vraćanje \"neuspjelog" stanja '$(unit)'."
-
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+# msgstr "Potrebna je ovjera za vraćanje \"neuspjelog\" stanja '$(unit)'."
+#
# #: ../src/core/dbus-unit.c:597
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr "Potrebna je ovjera za postavljanje svojstava na '$(unit)'."
+#endif // 0
+
diff --git a/po/hu.po b/po/hu.po
index f96f501a4..4918f52e2 100644
--- a/po/hu.po
+++ b/po/hu.po
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# Hungarian translation of systemd
# Copyright (C) 2015, 2016. Free Software Foundation, Inc.
# This file is distributed under the same license as the systemd package.
@@ -19,40 +21,41 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Lokalize 2.0\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "Jelmondat visszaküldése a rendszernek"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr ""
# "Hitelesítés szükséges a bevitt jelmondat visszaküldéséhez a rendszernek."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "Rendszerszolgáltatások vagy más egységek kezelése"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr ""
# "Hitelesítés szükséges a rendszerszolgáltatások vagy más egységek kezeléséhez."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "Rendszerszolgáltatás- vagy egységfájlok kezelése"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr ""
# "Hitelesítés szükséges a rendszerszolgáltatás- vagy egységfájlok kezeléséhez."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr ""
# "Rendszer- és szolgáltatáskezelő környezeti változóinak beállítása vagy "
# "törlése"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
@@ -60,27 +63,27 @@ msgstr ""
# msgstr ""
# "Hitelesítés szükséges a rendszer- és szolgáltatáskezelő környezeti "
# "változóinak beállításához vagy törléséhez."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "A systemd állapotának újratöltése"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr "Hitelesítés szükséges a systemd állapotának újratöltéséhez."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "Gépnév beállítása"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "Hitelesítés szükséges a helyi gépnév beállításához."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "Statikus gépnév beállítása"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
@@ -88,55 +91,57 @@ msgstr ""
# msgstr ""
# "Hitelesítés szükséges a statikusan megadott helyi gépnév, valamint a szép "
# "gépnév beállításához."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "Gépinformációk beállítása"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr "Hitelesítés szükséges a helyi gép információinak beállításához."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "VM vagy konténer lemezkép importálása"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép importálásához."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "VM vagy konténer lemezkép exportálása"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép exportálásához."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "VM vagy konténer lemezkép letöltése"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép letöltéséhez."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "Területi beállítás megadása"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr "Hitelesítés szükséges a rendszer területi beállításainak megadásához."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "Rendszer billentyűzetbeállítások megadása"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr ""
# "Hitelesítés szükséges a rendszer billentyűzetbeállításainak megadásához."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -455,68 +460,69 @@ msgstr "Falüzenet beállítása"
msgid "Authentication is required to set a wall message"
msgstr "Hitelesítés szükséges a falüzenet beállításához"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "Bejelentkezés helyi konténerbe"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr "Hitelesítés szükséges a bejelentkezéshez egy helyi konténerbe."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "Bejelentkezés a helyi gépre"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr "Hitelesítés szükséges a bejelentkezéshez a helyi gépre."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "Parancsértelmező elérése helyi konténerben"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr "Hitelesítés szükséges a parancsértelmező eléréséhez helyi konténerben."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "Parancsértelmező elérése a helyi gépen"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr "Hitelesítés szükséges a parancsértelmező eléréséhez a helyi gépen."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "Pszeudoterminál elérése helyi konténerben"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr "Hitelesítés szükséges a pszeudoterminál eléréséhez helyi konténerben."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "Pszeudoterminál elérése helyi gépen"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr "Hitelesítés szükséges a pszeudoterminál eléréséhez a helyi gépen."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "Virtuális gépek és konténerek kezelése"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr "Hitelesítés szükséges helyi virtuális gépek és konténerek kezeléséhez."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "Helyi virtuális gép és konténer lemezképek kezelése"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
@@ -524,27 +530,27 @@ msgstr "Hitelesítés szükséges a falüzenet beállításához"
# msgstr ""
# "Hitelesítés szükséges a helyi virtuális gép és konténer lemezképek "
# "kezeléséhez."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "Rendszeridő beállítása"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "Hitelesítés szükséges a rendszeridő beállításához."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "Rendszer időzónájának beállítása"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr "Hitelesítés szükséges a rendszer időzónájának beállításához."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr "Az RTC beállítása helyi időzónára vagy UTC-re"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
@@ -552,45 +558,47 @@ msgstr "Hitelesítés szükséges a falüzenet beállításához"
# msgstr ""
# "Hitelesítés szükséges az RTC beállításához a helyi időzóna vagy UTC "
# "tárolására."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "Hálózati időszinkronizáció be- vagy kikapcsolása"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
# "shall be enabled."
# msgstr "Hitelesítés szükséges a hálózati időszinkronizáció engedélyezéséhez."
-
+#
# #: ../src/core/dbus-unit.c:450
# msgid "Authentication is required to start '$(unit)'."
# msgstr "Hitelesítés szükséges a következő elindításához: „$(unit)”."
-
+#
# #: ../src/core/dbus-unit.c:451
# msgid "Authentication is required to stop '$(unit)'."
# msgstr "Hitelesítés szükséges a következő leállításához: „$(unit)”."
-
+#
# #: ../src/core/dbus-unit.c:452
# msgid "Authentication is required to reload '$(unit)'."
# msgstr "Hitelesítés szükséges a következő újratöltéséhez: „$(unit)”."
-
+#
# #: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454
# msgid "Authentication is required to restart '$(unit)'."
# msgstr "Hitelesítés szükséges a következő újraindításához: „$(unit)”."
-
+#
# #: ../src/core/dbus-unit.c:560
# msgid "Authentication is required to kill '$(unit)'."
# msgstr "Hitelesítés szükséges a következő kilövéséhez: „$(unit)”."
-
+#
# #: ../src/core/dbus-unit.c:590
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
# msgstr ""
# "Hitelesítés szükséges a következő „sikertelen” állapotának törléséhez: "
# "„$(unit)”."
-
+#
# #: ../src/core/dbus-unit.c:622
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr ""
# "Hitelesítés szükséges a következő tulajdonságainak beállításához: „$(unit)”."
+#
+#endif // 0
diff --git a/po/id.po b/po/id.po
index 3cdeb052e..1dc13f3ef 100644
--- a/po/id.po
+++ b/po/id.po
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# Indonesian translation for systemd.
# Copyright (C) 2014 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
@@ -17,38 +19,39 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.8\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "Kirim frasa sandi kembali ke sistem"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr ""
# "Otentikasi diperlukan untuk mengirim frasa sandi yang dimasukkan kembali ke "
# "sistem."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "Kelola layanan sistem atau unit lainnya"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr ""
# "Otentikasi diperlukan untuk mengelola layanan sistem atau unit lainnya."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "Kelola layanan sistem atau berkas unit"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr "Otentikasi diperlukan untuk mengelola layanan sistem atau berkas unit."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr "Atur atau hapus variabel lingkungan manajer layanan dan sistem"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
@@ -56,27 +59,27 @@ msgstr ""
# msgstr ""
# "Otentikasi diperlukan untuk menata atau menghapus variabel lingkungan "
# "manajer layanan dan sistem."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "Muat ulang keadaan systemd"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr "Otentikasi diperlukan untuk memuat ulang keadaan systemd."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "Setel nama host"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "Otentikasi diperlukan untuk menata nama host lokal."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "Setel nama host statik"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
@@ -84,54 +87,56 @@ msgstr ""
# msgstr ""
# "Otentikasi diperlukan untuk menata nama host lokal yang dikonfigurasi "
# "statik, maupun nama host cantik."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "Setel informasi mesin"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr "Otentikasi diperlukan untuk menata informasi mesin lokal."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "Impor sebuah image kontainer atau VM"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr "Otentikasi diperlukan untuk mengimpor suatu image kontainer atau VM"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "Ekspor sebuah image kontainer atau VM"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr "Otentikasi diperlukan untuk mengekspor suatu image kontainer atau VM"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "Unduh sebuah image kontainer atau VM"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr "Otentikasi diperlukan untuk mengunduh suatu image kontainer atau VM"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "Setel locale sistem"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr "Otentikasi diperlukan untuk menyetel locale sistem."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "Setel pengaturan papan tik sistem"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr "Otentikasi diperlukan untuk menyetel pengaturan papan tik sistem."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -430,74 +435,75 @@ msgstr "Setel suatu pesan wall"
msgid "Authentication is required to set a wall message"
msgstr "Otentikasi diperlukan untuk menyetel pesan wall"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "Log masuk ke dalam suatu kontainer lokal"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr "Otentikasi diperlukan untuk log masuk ke dalam suatu kontainer lokal."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "Log masuk ke dalam host lokal"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr "Otentikasi diperlukan untuk log masuk ke dalam host lokal."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "Dapatkan sebuah shell dalam kontainer lokal"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr ""
# "Otentikasi diperlukan untuk mendapatkan suatu shell dalam sebuah kontainer "
# "lokal."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "Dapatkan sebuah shell pada host lokal"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr "Otentikasi diperlukan untuk mendapatkan suatu shell pada host lokal."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "Dapatkan sebuah TTY semu dalam suatu kontainer lokal"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr ""
# "Otentikasi diperlukan untuk mendapatkan suatu TTY semu dalam sebuah "
# "kontainer lokal."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "Dapatkan sebuah TTY semu pada host lokal"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr ""
# "Otentikasi diperlukan untuk mendapatkan suatu TTY semu pada host lokal."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "Kelola mesin virtual lokal dan kontainer"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr ""
# "Otentikasi diperlukan untuk mengelola mesin virtual lokal dan kontainer."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "Kelola mesin virtual lokal dan image kontainer"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
@@ -505,27 +511,27 @@ msgstr "Otentikasi diperlukan untuk menyetel pesan wall"
# msgstr ""
# "Otentikasi diperlukan untuk mengelola mesin virtual lokal dan image "
# "kontainer."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "Setel waktu sistem"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "Otentikasi diperlukan untuk menyetel waktu sistem."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "Setel zona waktu sistem"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr "Otentikasi diperlukan untuk menyetel zona waktu sistem."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr "Atur RTC ke zona waktu lokal atau UTC"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
@@ -533,11 +539,11 @@ msgstr "Otentikasi diperlukan untuk menyetel pesan wall"
# msgstr ""
# "Otentikasi diperlukan untuk mengendalikan apakah RTC menyimpan waktu UTC "
# "atau lokal."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "Nyalakan atau matikan penyelarasan waktu jaringan"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
@@ -545,32 +551,34 @@ msgstr "Otentikasi diperlukan untuk menyetel pesan wall"
# msgstr ""
# "Otentikasi diperlukan untuk mengendalikan apakah sinkronisasi waktu jaringan "
# "mesti difungsikan."
-
+#
# #: ../src/core/dbus-unit.c:450
# msgid "Authentication is required to start '$(unit)'."
# msgstr "Otentikasi diperlukan untuk memulai '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:451
# msgid "Authentication is required to stop '$(unit)'."
# msgstr "Otentikasi diperlukan untuk menghentikan '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:452
# msgid "Authentication is required to reload '$(unit)'."
# msgstr "Otentikasi diperlukan untuk memuat ulang '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454
# msgid "Authentication is required to restart '$(unit)'."
# msgstr "Otentikasi diperlukan untuk memulai ulang '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:560
# msgid "Authentication is required to kill '$(unit)'."
# msgstr "Otentikasi diperlukan untuk mematikan '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:590
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
# msgstr ""
-# "Otentikasi diperlukan untuk me-reset keadaan \"failed" dari '$(unit)'."
-
+# "Otentikasi diperlukan untuk me-reset keadaan \"failed\" dari '$(unit)'."
+#
# #: ../src/core/dbus-unit.c:622
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr "Otentikasi diperlukan untuk menata properti pada '$(unit)'."
+#endif // 0
+
diff --git a/po/it.po b/po/it.po
index 48fd2f228..143c425b6 100644
--- a/po/it.po
+++ b/po/it.po
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# Italian translations for systemd package
# Traduzione in italiano per il pacchetto systemd
# This file is distributed under the same license as the systemd package.
@@ -18,41 +20,42 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.8.7.1\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "Invia la frase segreta (passphrase) al sistema"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr ""
# "Autenticazione richiesta per inviare la frase segreta (passphrase) al "
# "sistema."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "Gestisci i servizi o le altre unità di sistema"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr ""
# "Autenticazione richiesta per gestire i servizi o le altre unità di sistema."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "Gestisci i file dei servizi o delle unità di sistema"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr ""
# "Autenticazione richiesta per gestire i file dei servizi o delle unità di "
# "sistema."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr ""
# "Configura le variabili d'ambiente per la gestione dei servizi e del sistema"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
@@ -60,27 +63,27 @@ msgstr ""
# msgstr ""
# "Autenticazione richiesta per configurare le variabili d'ambiente per la "
# "gestione dei servizi e del sistema"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "Ricarica lo stato di systemd"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr "Autenticazione richiesta per riavviare lo stato di sistemd."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "Configura il nome host"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "Autenticazione richiesta per configurare il nome host locale."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "Configura il nome host statico"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
@@ -88,58 +91,60 @@ msgstr ""
# msgstr ""
# "Autenticazione richiesta per configurare staticamente il nome host locale e "
# "il nome host descrittivo."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "Configura le informazioni sulla macchina"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr ""
# "Autenticazione richiesta per configurare le informazioni sulla macchina "
# "locale."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "Importa un'immagine VM o un container"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr "Autenticazione richiesta per importare un'immagine VM o un container"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "Esporta un'immagine VM o un container"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr "Autenticazione richiesta per esportare un'immagine VM o un container"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "Scarica un'immagine VM o un container"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr "Autenticazione richiesta per scaricare un'immagine VM o un container"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "Configura le impostazioni regionali di sistema"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr ""
# "Autenticazione richiesta per configurare le impostazioni regionali di "
# "sistema."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "Configura la tastiera di sistema"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr "Autenticazione richiesta per configurare la tastiera di sistema."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -458,70 +463,71 @@ msgstr "Configura un messaggio per gli utenti"
msgid "Authentication is required to set a wall message"
msgstr "Autenticazione richiesta per configurare un messaggio per gli utenti"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "Accedi in un container locale"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr "Autenticazione richiesta per accedere in un container locale."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "Accedi in un host locale"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr "Autenticazione richiesta per accedere in un host locale."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "Apri una shell in un container locale"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr "Autenticazione richiesta per aprire una shell in un container locale."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "Apri una shell in un host locale"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr "Autenticazione richiesta per aprire una shell in un host locale."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "Apri un pseudo TTY in un container locale"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr ""
# "Autenticazione richiesta per aprire un pseudo TTY in un container locale."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "Apri un pseudo TTY in un host locale"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr "Autenticazione richiesta per aprire un pseudo TTY in un host locale."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "Gestisci le virtual machine e i container locali"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr ""
# "Autenticazione richiesta per gestire le virtual machine e i container locali."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "Gestisci le immagini locali delle virtual machine e dei container"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
@@ -529,29 +535,29 @@ msgstr "Autenticazione richiesta per configurare un messaggio per gli utenti"
# msgstr ""
# "Autenticazione richiesta per gestire le immagini delle virtual machine e dei "
# "container locali."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "Configura l'orario di sistema"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "Autenticazione richiesta per configurare l'orario di sistema."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "Configura il fuso orario di sistema"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr "Autenticazione richiesta per configurare il fuso orario di sistema."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr ""
# "Configura l'orologio di sistema (RTC) al fuso orario locale o al tempo "
# "civile (UTC)"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
@@ -559,11 +565,11 @@ msgstr "Autenticazione richiesta per configurare un messaggio per gli utenti"
# msgstr ""
# "Autenticazione richiesta per verificare se l'orologio di sistema (RTC) è "
# "configurato all'orario locale o al tempo civile (UTC)."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "Abilita o meno la sincronizzazione dell'orario in rete"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
@@ -571,32 +577,34 @@ msgstr "Autenticazione richiesta per configurare un messaggio per gli utenti"
# msgstr ""
# "Autenticazione richiesta per verificare se la sincronizzazione dell'orario "
# "in rete possa essere attivata."
-
+#
# #: ../src/core/dbus-unit.c:450
# msgid "Authentication is required to start '$(unit)'."
# msgstr "Autenticazione richiesta per avviare '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:451
# msgid "Authentication is required to stop '$(unit)'."
# msgstr "Autenticazione richiesta per fermare '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:452
# msgid "Authentication is required to reload '$(unit)'."
# msgstr "Autenticazione richiesta per ricaricare '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454
# msgid "Authentication is required to restart '$(unit)'."
# msgstr "Autenticazione richiesta per riavviare '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:560
# msgid "Authentication is required to kill '$(unit)'."
# msgstr "Autenticazione richiesta per terminare '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:590
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
# msgstr ""
-# "Autenticazione richiesta per riconfigurare lo stato \"fallito" di '$(unit)'."
-
+# "Autenticazione richiesta per riconfigurare lo stato \"fallito\" di '$(unit)'."
+#
# #: ../src/core/dbus-unit.c:622
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr "Autenticazione richiesta per configurare le proprietà di '$(unit)'."
+#endif // 0
+
diff --git a/po/its/polkit.its b/po/its/polkit.its
new file mode 100644
index 000000000..1c37e6bee
--- /dev/null
+++ b/po/its/polkit.its
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<its:rules xmlns:its="http://www.w3.org/2005/11/its"
+ version="2.0">
+ <its:translateRule selector="//*" translate="no"/>
+ <its:translateRule selector="//action/description |
+ //action/message"
+ translate="yes"/>
+</its:rules>
diff --git a/po/its/polkit.loc b/po/its/polkit.loc
new file mode 100644
index 000000000..c7427ec67
--- /dev/null
+++ b/po/its/polkit.loc
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<locatingRules>
+ <locatingRule name="polkit policy" pattern="*.policy">
+ <documentRule localName="policyconfig" target="polkit.its"/>
+ </locatingRule>
+</locatingRules>
diff --git a/po/ko.po b/po/ko.po
index 7d30fd2dc..fb6795b01 100644
--- a/po/ko.po
+++ b/po/ko.po
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# Korean translation for the systemd.
# Copyright (C) 2015 systemd author and translators.
# This file is distributed under the same license as the systemd package.
@@ -20,35 +22,36 @@ msgstr ""
"Language: ko\n"
"X-Poedit-SourceCharset: UTF-8\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "시스템에 암호문 보내기"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr "시스템에 입력한 암호를 보내려면 인증이 필요합니다."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "시스템 서비스 또는 기타 유닛 관리"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr "시스템 서비스 또는 기타 유닛을 관리하려면 인증이 필요합니다."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "시스템 서비스 또는 유닛 파일 관리"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr "시스템 서비스 또는 유닛 파일을 관리하려면 인증이 필요합니다."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr "시스템 및 서비스 관리자 환경 변수 설정 또는 설정 해제"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
@@ -56,27 +59,27 @@ msgstr ""
# msgstr ""
# "시스템 및 서비스 관리자 환경 변수를 설정하거나 설정 해제하려면 인증이 필요합"
# "니다."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "systemd 상태 다시 불러오기"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr "systemd 상태를 다시 불러오려면 인증이 필요합니다."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "호스트 이름 설정"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "로컬 호스트 이름을 설정하려면 인증이 필요합니다."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "정적 호스트 이름 설정"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
@@ -84,54 +87,56 @@ msgstr ""
# msgstr ""
# "로컬 호스트 이름을 모양새를 갖춘 호스트 이름 처럼 정적으로 설정하려면 인증"
# "이 필요합니다."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "머신 정보 설정"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr "로컬 머신 정보를 설정하려면 인증이 필요합니다."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "VM 또는 컨테이너의 이미지 가져오기"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr "VM 또는 컨테이너의 이미지를 가져오려면 인증이 필요합니다"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "가상 머신 또는 컨테이너의 이미지 내보내기"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr "가상 머신 또는 컨테이너의 이미지를 내보내려면 인증이 필요합니다"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "가상머신 또는 컨테이너 이미지 다운로드"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr "가상머신 또는 컨테이너 이미지를 다운로드하려면 인증이 필요합니다"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "시스템 로캘 설정"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr "시스템 로캘을 설정하려면 인증이 필요합니다."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "시스템 키보드 설정"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr "시스템 키보드를 설정하려면 인증이 필요합니다."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -410,94 +415,95 @@ msgstr "wall 메시지 설정"
msgid "Authentication is required to set a wall message"
msgstr "wall 메시지를 설정하려면 인증이 필요합니다"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "로컬 컨테이너 로그인"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr "로컬 컨테이너로 로그인하려면 인증이 필요합니다."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "로컬 호스트 로그인"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr "로컬 호스트로 로그인하려면 인증이 필요합니다."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "로컬 컨테이너의 쉘 획득"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr "로컬 컨테이너에서 쉘을 획득하려면 인증이 필요합니다."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "로컬 호스트 쉘 획득"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr "로컬 호스트의 쉘을 획득하려면 인증이 필요합니다."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "로컬 컨테이너에서 의사 TTY 획득"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr "로컬 컨테이너에서 의사 TTY를 획득하려면 인증이 필요합니다."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "로컬 호스트에서 유사 TTY 획득"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr "로컬 호스트에서 의사 TTY를 획득하려면 인증이 필요합니다."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "로컬 가상 머신 및 컨테이너 관리"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr "로컬 가상 머신 및 컨테이너를 관리하려면 인증이 필요합니다."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "로컬 가상 머신 및 컨테이너 이미지 관리"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
# "images."
# msgstr "로컬 가상 머신 및 컨테이너 이미지를 관리하려면 인증이 필요합니다."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "시스템 시간 설정"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "시스템 시간을 설정하려면 인증이 필요합니다."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "시스템 시간대 설정"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr "시스템 시간대를 설정하려면 인증이 필요합니다."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr "RTC를 로컬 시간대 또는 UTC로 설정"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
@@ -505,41 +511,43 @@ msgstr "wall 메시지를 설정하려면 인증이 필요합니다"
# msgstr ""
# "RTC를 로컬 시간 또는 UTC 시간으로 저장할 지 여부를 제어하려면 인증이 필요합니"
# "다."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "네트워크 시간 동기화 켜거나 끄기"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
# "shall be enabled."
# msgstr "네트워크 시간 동기화의 활성화 여부를 제어하려면 인증이 필요합니다."
-
+#
# #: ../src/core/dbus-unit.c:428
# msgid "Authentication is required to start '$(unit)'."
# msgstr "'$(unit)' 서비스 유닛을 시작하려면 인증이 필요합니다."
-
+#
# #: ../src/core/dbus-unit.c:429
# msgid "Authentication is required to stop '$(unit)'."
# msgstr "'$(unit)' 서비스 유닛을 멈추려면 인증이 필요합니다."
-
+#
# #: ../src/core/dbus-unit.c:430
# msgid "Authentication is required to reload '$(unit)'."
# msgstr "'$(unit)' 서비스 유닛을 다시 불러오려면 인증이 필요합니다."
-
+#
# #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
# msgid "Authentication is required to restart '$(unit)'."
# msgstr "'$(unit)' 서비스 유닛을 다시 시작하려면 인증이 필요합니다."
-
+#
# #: ../src/core/dbus-unit.c:535
# msgid "Authentication is required to kill '$(unit)'."
# msgstr "'$(unit)' 서비스 유닛을 강제로 끝내려면 인증이 필요합니다."
-
+#
# #: ../src/core/dbus-unit.c:565
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
-# msgstr "'$(unit)' 서비스 유닛의 \"실패" 상태를 되돌리려면 인증이 필요합니다."
-
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+# msgstr "'$(unit)' 서비스 유닛의 \"실패\" 상태를 되돌리려면 인증이 필요합니다."
+#
# #: ../src/core/dbus-unit.c:597
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr "'$(unit)' 서비스 유닛 속성을 설정하려면 인증이 필요합니다."
+#endif // 0
+
diff --git a/po/meson.build b/po/meson.build
new file mode 100644
index 000000000..7ba08fba1
--- /dev/null
+++ b/po/meson.build
@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# Copyright 2017 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/>.
+
+i18n = import('i18n')
+i18n.gettext(meson.project_name(), preset: 'glib')
+
+po_dir = meson.current_source_dir()
diff --git a/po/pl.po b/po/pl.po
index d0a80f7db..3f2bdd944 100644
--- a/po/pl.po
+++ b/po/pl.po
@@ -1,15 +1,17 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# Polish translation for systemd.
-# Copyright © 2011-2016 the systemd authors.
+# Copyright © 2011-2017 the systemd authors.
# This file is distributed under the same license as the systemd package.
-# Piotr Drąg <piotrdrag@gmail.com>, 2011, 2013-2016.
+# Piotr Drąg <piotrdrag@gmail.com>, 2011, 2013-2017.
# Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: systemd\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2016-10-05 19:01+0200\n"
-"PO-Revision-Date: 2016-10-05 19:02+0200\n"
+"POT-Creation-Date: 2017-10-06 15:29+0200\n"
+"PO-Revision-Date: 2017-10-05 15:30+0200\n"
"Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n"
"Language-Team: Polish <trans-pl@lists.fedoraproject.org>\n"
"Language: pl\n"
@@ -19,42 +21,43 @@ msgstr ""
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2);\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "Wysłanie hasła z powrotem do systemu"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr ""
# "Wymagane jest uwierzytelnienie, aby wysłać podane hasło z powrotem do "
# "systemu."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "Zarządzanie usługami lub innymi jednostkami systemu"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr ""
# "Wymagane jest uwierzytelnienie, aby zarządzać usługami lub innymi "
# "jednostkami systemu."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "Zarządzanie plikami usług lub jednostek systemu"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr ""
# "Wymagane jest uwierzytelnienie, aby zarządzać plikami usług lub jednostek "
# "systemu."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr ""
# "Ustawienie lub usunięcie zmiennych środowiskowych menedżera systemu i usług"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
@@ -62,89 +65,91 @@ msgstr ""
# msgstr ""
# "Wymagane jest uwierzytelnienie, aby ustawić lub usunąć zmienne środowiskowe "
# "menedżera systemu i usług."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "Ponowne wczytanie stanu systemd"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr "Wymagane jest uwierzytelnienie, aby ponownie wczytać stan systemd."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "Ustawienie nazwy komputera"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "Wymagane jest uwierzytelnienie, aby ustawić nazwę lokalnego komputera."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "Ustawienie statycznej nazwy komputera"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
# "as well as the pretty host name."
# msgstr ""
# "Wymagane jest uwierzytelnienie, aby ustawić statycznie skonfigurowaną nazwę "
-# "lokalnego komputera, a także jego ładną nazwę."
-
+# "lokalnego komputera, a także jego nazwę czytelną dla człowieka."
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "Ustawienie informacji o komputerze"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr ""
# "Wymagane jest uwierzytelnienie, aby ustawić informacje o lokalnym komputerze."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "Import obrazu maszyny wirtualnej lub kontenera"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr ""
# "Wymagane jest uwierzytelnienie, aby zaimportować obraz maszyny wirtualnej "
# "lub kontenera"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "Eksport obrazu maszyny wirtualnej lub kontenera"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr ""
# "Wymagane jest uwierzytelnienie, aby wyeksportować obraz maszyny wirtualnej "
# "lub kontenera"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "Pobranie obrazu maszyny wirtualnej lub kontenera"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr ""
# "Wymagane jest uwierzytelnienie, aby pobrać obraz maszyny wirtualnej lub "
# "kontenera"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "Ustawienie lokalizacji systemu"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr "Wymagane jest uwierzytelnienie, aby ustawić lokalizację systemu."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "Ustawienie klawiatury systemu"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr "Wymagane jest uwierzytelnienie, aby ustawić klawiaturę systemu."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -347,18 +352,50 @@ msgstr ""
"zażądał jego wstrzymania."
#: ../src/login/org.freedesktop.login1.policy.in.h:39
+msgid "Halt the system"
+msgstr "Zatrzymanie systemu"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:40
+msgid "Authentication is required for halting the system."
+msgstr "Wymagane jest uwierzytelnienie, aby zatrzymać system."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:41
+msgid "Halt the system while other users are logged in"
+msgstr "Zatrzymanie systemu, kiedy są zalogowani inni użytkownicy"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:42
+msgid ""
+"Authentication is required for halting the system while other users are "
+"logged in."
+msgstr ""
+"Wymagane jest uwierzytelnienie, aby zatrzymać system, kiedy są zalogowani "
+"inni użytkownicy."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:43
+msgid "Halt the system while an application asked to inhibit it"
+msgstr "Zatrzymanie systemu, kiedy program zażądał jego wstrzymania"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:44
+msgid ""
+"Authentication is required for halting the system while an application asked "
+"to inhibit it."
+msgstr ""
+"Wymagane jest uwierzytelnienie, aby zatrzymać system, kiedy program zażądał "
+"jego wstrzymania."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:45
msgid "Suspend the system"
msgstr "Uśpienie systemu"
-#: ../src/login/org.freedesktop.login1.policy.in.h:40
+#: ../src/login/org.freedesktop.login1.policy.in.h:46
msgid "Authentication is required for suspending the system."
msgstr "Wymagane jest uwierzytelnienie, aby uśpić system."
-#: ../src/login/org.freedesktop.login1.policy.in.h:41
+#: ../src/login/org.freedesktop.login1.policy.in.h:47
msgid "Suspend the system while other users are logged in"
msgstr "Uśpienie systemu, kiedy są zalogowani inni użytkownicy"
-#: ../src/login/org.freedesktop.login1.policy.in.h:42
+#: ../src/login/org.freedesktop.login1.policy.in.h:48
msgid ""
"Authentication is required for suspending the system while other users are "
"logged in."
@@ -366,11 +403,11 @@ msgstr ""
"Wymagane jest uwierzytelnienie, aby uśpić system, kiedy są zalogowani inni "
"użytkownicy."
-#: ../src/login/org.freedesktop.login1.policy.in.h:43
+#: ../src/login/org.freedesktop.login1.policy.in.h:49
msgid "Suspend the system while an application asked to inhibit it"
msgstr "Uśpienie systemu, kiedy program zażądał jego wstrzymania"
-#: ../src/login/org.freedesktop.login1.policy.in.h:44
+#: ../src/login/org.freedesktop.login1.policy.in.h:50
msgid ""
"Authentication is required for suspending the system while an application "
"asked to inhibit it."
@@ -378,19 +415,19 @@ msgstr ""
"Wymagane jest uwierzytelnienie, aby uśpić system, kiedy program zażądał jego "
"wstrzymania."
-#: ../src/login/org.freedesktop.login1.policy.in.h:45
+#: ../src/login/org.freedesktop.login1.policy.in.h:51
msgid "Hibernate the system"
msgstr "Hibernacja systemu"
-#: ../src/login/org.freedesktop.login1.policy.in.h:46
+#: ../src/login/org.freedesktop.login1.policy.in.h:52
msgid "Authentication is required for hibernating the system."
msgstr "Wymagane jest uwierzytelnienie, aby zahibernować system."
-#: ../src/login/org.freedesktop.login1.policy.in.h:47
+#: ../src/login/org.freedesktop.login1.policy.in.h:53
msgid "Hibernate the system while other users are logged in"
msgstr "Hibernacja systemu, kiedy są zalogowani inni użytkownicy"
-#: ../src/login/org.freedesktop.login1.policy.in.h:48
+#: ../src/login/org.freedesktop.login1.policy.in.h:54
msgid ""
"Authentication is required for hibernating the system while other users are "
"logged in."
@@ -398,11 +435,11 @@ msgstr ""
"Wymagane jest uwierzytelnienie, aby zahibernować system, kiedy są zalogowani "
"inni użytkownicy."
-#: ../src/login/org.freedesktop.login1.policy.in.h:49
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
msgid "Hibernate the system while an application asked to inhibit it"
msgstr "Hibernacja systemu, kiedy program zażądał jej wstrzymania"
-#: ../src/login/org.freedesktop.login1.policy.in.h:50
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
msgid ""
"Authentication is required for hibernating the system while an application "
"asked to inhibit it."
@@ -410,31 +447,31 @@ msgstr ""
"Wymagane jest uwierzytelnienie, aby zahibernować system, kiedy program "
"zażądał jej wstrzymania."
-#: ../src/login/org.freedesktop.login1.policy.in.h:51
+#: ../src/login/org.freedesktop.login1.policy.in.h:57
msgid "Manage active sessions, users and seats"
msgstr "Zarządzanie aktywnymi sesjami, użytkownikami i stanowiskami"
-#: ../src/login/org.freedesktop.login1.policy.in.h:52
+#: ../src/login/org.freedesktop.login1.policy.in.h:58
msgid ""
"Authentication is required for managing active sessions, users and seats."
msgstr ""
"Wymagane jest uwierzytelnienie, aby zarządzać aktywnymi sesjami, "
"użytkownikami i stanowiskami."
-#: ../src/login/org.freedesktop.login1.policy.in.h:53
+#: ../src/login/org.freedesktop.login1.policy.in.h:59
msgid "Lock or unlock active sessions"
msgstr "Zablokowanie lub odblokowanie aktywnych sesji"
-#: ../src/login/org.freedesktop.login1.policy.in.h:54
+#: ../src/login/org.freedesktop.login1.policy.in.h:60
msgid "Authentication is required to lock or unlock active sessions."
msgstr ""
"Wymagane jest uwierzytelnienie, aby zablokować lub odblokować aktywne sesje."
-#: ../src/login/org.freedesktop.login1.policy.in.h:55
+#: ../src/login/org.freedesktop.login1.policy.in.h:61
msgid "Allow indication to the firmware to boot to setup interface"
msgstr "Wskazanie oprogramowaniu sprzętowemu, aby uruchomić interfejs ustawień"
-#: ../src/login/org.freedesktop.login1.policy.in.h:56
+#: ../src/login/org.freedesktop.login1.policy.in.h:62
msgid ""
"Authentication is required to indicate to the firmware to boot to setup "
"interface."
@@ -442,85 +479,86 @@ msgstr ""
"Wymagane jest uwierzytelnienie, aby wskazać oprogramowaniu sprzętowemu, że "
"należy uruchomić interfejs ustawień."
-#: ../src/login/org.freedesktop.login1.policy.in.h:57
+#: ../src/login/org.freedesktop.login1.policy.in.h:63
msgid "Set a wall message"
msgstr "Ustawienie komunikatu wall"
-#: ../src/login/org.freedesktop.login1.policy.in.h:58
+#: ../src/login/org.freedesktop.login1.policy.in.h:64
msgid "Authentication is required to set a wall message"
msgstr "Wymagane jest uwierzytelnienie, aby ustawić komunikat wall"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "Logowanie do lokalnego kontenera"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr ""
# "Wymagane jest uwierzytelnienie, aby zalogować się do lokalnego kontenera."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "Logowanie do lokalnego komputera"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr ""
# "Wymagane jest uwierzytelnienie, aby zalogować się do lokalnego komputera."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "Uzyskanie powłoki w lokalnym kontenerze"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr ""
# "Wymagane jest uwierzytelnienie, aby uzyskać powłokę w lokalnym kontenerze."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "Uzyskanie powłoki na lokalnym komputerze"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr ""
# "Wymagane jest uwierzytelnienie, aby uzyskać powłokę na lokalnym komputerze."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "Uzyskanie pseudo-TTY w lokalnym kontenerze"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr ""
# "Wymagane jest uwierzytelnienie, aby uzyskać pseudo-TTY w lokalnym kontenerze."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "Uzyskanie pseudo-TTY na lokalnym komputerze"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr ""
# "Wymagane jest uwierzytelnienie, aby uzyskać pseudo-TTY na lokalnym "
# "komputerze."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "Zarządzanie lokalnymi maszynami wirtualnymi i kontenerami"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr ""
# "Wymagane jest uwierzytelnienie, aby zarządzać lokalnymi maszynami "
# "wirtualnymi i kontenerami."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "Zarządzanie lokalnymi obrazami maszyn wirtualnych i kontenerów"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
@@ -528,27 +566,27 @@ msgstr "Wymagane jest uwierzytelnienie, aby ustawić komunikat wall"
# msgstr ""
# "Wymagane jest uwierzytelnienie, aby zarządzać lokalnymi obrazami maszyn "
# "wirtualnych i kontenerów."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "Ustawienie czasu systemu"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "Wymagane jest uwierzytelnienie, aby ustawić czas systemu."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "Ustawienie strefy czasowej systemu"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr "Wymagane jest uwierzytelnienie, aby ustawić strefę czasową systemu."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr "Ustawienie RTC na lokalną strefę czasową lub strefę UTC"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
@@ -556,11 +594,11 @@ msgstr "Wymagane jest uwierzytelnienie, aby ustawić komunikat wall"
# msgstr ""
# "Wymagane jest uwierzytelnienie, aby kontrolować, czy RTC przechowuje czas "
# "lokalny lub czas UTC."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "Włączenie lub wyłączenie synchronizacji czasu przez sieć"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
@@ -568,48 +606,50 @@ msgstr "Wymagane jest uwierzytelnienie, aby ustawić komunikat wall"
# msgstr ""
# "Wymagane jest uwierzytelnienie, aby kontrolować, czy włączyć synchronizację "
# "czasu przez sieć."
-
-# #: ../src/core/dbus-unit.c:459
+#
+# #: ../src/core/dbus-unit.c:458
# msgid "Authentication is required to start '$(unit)'."
-# msgstr "Wymagane jest uwierzytelnienie, aby uruchomić jednostkę „$(unit)”."
-
-# #: ../src/core/dbus-unit.c:460
+# msgstr "Wymagane jest uwierzytelnienie, aby uruchomić jednostkę „$(unit)”."
+#
+# #: ../src/core/dbus-unit.c:459
# msgid "Authentication is required to stop '$(unit)'."
-# msgstr "Wymagane jest uwierzytelnienie, aby zatrzymać jednostkę „$(unit)”."
-
-# #: ../src/core/dbus-unit.c:461
+# msgstr "Wymagane jest uwierzytelnienie, aby zatrzymać jednostkę „$(unit)”."
+#
+# #: ../src/core/dbus-unit.c:460
# msgid "Authentication is required to reload '$(unit)'."
# msgstr ""
-# "Wymagane jest uwierzytelnienie, aby ponownie wczytać jednostkę „$(unit)”."
-
-# #: ../src/core/dbus-unit.c:462 ../src/core/dbus-unit.c:463
+# "Wymagane jest uwierzytelnienie, aby ponownie wczytać jednostkę „$(unit)”."
+#
+# #: ../src/core/dbus-unit.c:461 ../src/core/dbus-unit.c:462
# msgid "Authentication is required to restart '$(unit)'."
# msgstr ""
-# "Wymagane jest uwierzytelnienie, aby ponownie uruchomić jednostkę „$(unit)”."
-
-# #: ../src/core/dbus-unit.c:570
+# "Wymagane jest uwierzytelnienie, aby ponownie uruchomić jednostkę „$(unit)”."
+#
+# #: ../src/core/dbus-unit.c:569
# msgid "Authentication is required to kill '$(unit)'."
# msgstr ""
-# "Wymagane jest uwierzytelnienie, aby wymusić wyłączenie jednostki „$(unit)”."
-
-# #: ../src/core/dbus-unit.c:601
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
+# "Wymagane jest uwierzytelnienie, aby wymusić wyłączenie jednostki „$(unit)”."
+#
+# #: ../src/core/dbus-unit.c:600
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
# msgstr ""
# "Wymagane jest uwierzytelnienie, aby przywrócić stan „failed” (niepowodzenia) "
# "jednostki „$(unit)”."
-
-# #: ../src/core/dbus-unit.c:634
+#
+# #: ../src/core/dbus-unit.c:633
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr ""
# "Wymagane jest uwierzytelnienie, aby ustawić właściwości jednostki „$(unit)”."
+#
+# #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
+# #~ msgstr ""
+# #~ "Naciśnięcie klawiszy Ctrl+C anuluje wszystkie trwające procesy "
+# #~ "sprawdzania systemów plików"
+#
+# #~ msgid "Checking in progress on %d disk (%3.1f%% complete)"
+# #~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
+# #~ msgstr[0] "Trwa sprawdzanie %d dysku (ukończono %3.1f%%)"
+# #~ msgstr[1] "Trwa sprawdzanie %d dysków (ukończono %3.1f%%)"
+# #~ msgstr[2] "Trwa sprawdzanie %d dysków (ukończono %3.1f%%)"
+#endif // 0
-#~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
-#~ msgstr ""
-#~ "Naciśnięcie klawiszy Ctrl+C anuluje wszystkie trwające procesy "
-#~ "sprawdzania systemów plików"
-
-#~ msgid "Checking in progress on %d disk (%3.1f%% complete)"
-#~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
-#~ msgstr[0] "Trwa sprawdzanie %d dysku (ukończono %3.1f%%)"
-#~ msgstr[1] "Trwa sprawdzanie %d dysków (ukończono %3.1f%%)"
-#~ msgstr[2] "Trwa sprawdzanie %d dysków (ukończono %3.1f%%)"
diff --git a/po/pt_BR.po b/po/pt_BR.po
index 160ea0d80..f8723c898 100644
--- a/po/pt_BR.po
+++ b/po/pt_BR.po
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# Brazilian Portuguese translation for systemd.
# Copyright (C) 2017 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
@@ -18,43 +20,44 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Generator: Virtaal 1.0.0-beta1\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "Enviar frase secreta de volta ao sistema"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr ""
# "É necessária autenticação para enviar a frase secreta informada de volta ao "
# "sistema."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "Gerenciar serviços do sistema e outras unidades"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr ""
# "É necessária autenticação para gerenciar serviços do sistema ou outras "
# "unidades."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "Gerenciar arquivos de unidades e serviços do sistema"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr ""
-# "É necessária autenticação para gerenciar arquivos \"unit" e "service" do "
+# "É necessária autenticação para gerenciar arquivos \"unit\" e \"service\" do "
# "sistema."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr ""
# "Definir ou retirar definição de variáveis de ambiente de gerenciador de "
# "serviço e sistema"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
@@ -62,27 +65,27 @@ msgstr ""
# msgstr ""
# "É necessária autenticação para definir ou retirar definição de variáveis de "
# "ambiente de gerenciador de serviço e sistema."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "Recarregar o estado do sistema"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr "É necessária autenticação para recarregar o estado do sistema."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "Definir nome de máquina"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "É necessária autenticação para definir nome de máquina local."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "Definir nome estático de máquina"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
@@ -90,57 +93,59 @@ msgstr ""
# msgstr ""
# "É necessária autenticação para definir o nome de máquina local configurado "
# "estaticamente, assim como o nome apresentável de máquina."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "Definir informações da máquina"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr "É necessária autenticação para definir informações de máquina local."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "Importar uma VM ou imagem contêiner"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr "É necessária autenticação para importar uma VM ou imagem contêiner"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "Exportar uma VM ou imagem contêiner"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr "É necessária autenticação para exportar uma VM ou imagem contêiner"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "Baixar uma VM ou imagem contêiner"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr "É necessária autenticação para baixar uma VM ou imagem contêiner"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "Definir configurações regionais do sistema"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr ""
# "É necessária autenticação para definir as configurações regionais do sistema."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "Definir configurações de teclado do sistema"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr ""
# "É necessária autenticação para definir as configurações de teclado do "
# "sistema."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -459,74 +464,75 @@ msgstr "Definir uma mensagem de parede"
msgid "Authentication is required to set a wall message"
msgstr "É necessária autenticação para definir uma mensagem de parede"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "Conectar a um contêiner local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr "É necessária autenticação para se conectar a um contêiner local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "Conectar a uma máquina local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr "É necessária autenticação para se conectar a uma máquina local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "Adquirir uma shell em um contêiner local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr ""
# "É necessária autenticação para adquirir uma shell em um contêiner local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "Adquirir uma shell na máquina local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr ""
# "É necessária autenticação para adquirir uma shell em uma máquina local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "Adquirir um pseudo TTY em um contêiner local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr ""
# "É necessária autenticação para adquirir um pseudo TTY em um contêiner local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "Adquiri um pseudo TTY na máquina local"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr ""
# "É necessária autenticação para adquirir um pseudo TTY em um máquina local."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "Gerenciar máquinas virtuais locais e contêineres"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr ""
# "É necessária autenticação para gerenciar máquinas virtuais locais e "
# "contêineres."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "Gerenciar máquinas virtuais locais e imagens contêineres"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
@@ -534,27 +540,27 @@ msgstr "É necessária autenticação para definir uma mensagem de parede"
# msgstr ""
# "É necessária autenticação para gerenciar máquinas virtuais locais e imagens "
# "contêineres."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "Definir horário do sistema"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "É necessária autenticação para definir o horário do sistema."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "Definir fuso horário do sistema"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr "É necessária autenticação para definir o fuso horário do sistema."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr "Definir o relógio do sistema (RTC) para fuso horário local ou UTC"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
@@ -562,11 +568,11 @@ msgstr "É necessária autenticação para definir uma mensagem de parede"
# msgstr ""
# "É necessária autenticação para controlar se o RTC deve, ou não, armazenar o "
# "horário local ou de UTC."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "Ligar/desligar a sincronização do horário em rede"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
@@ -574,32 +580,34 @@ msgstr "É necessária autenticação para definir uma mensagem de parede"
# msgstr ""
# "É necessária autenticação para controlar se deve ser habilitada, ou não, a "
# "sincronização de horário através de rede."
-
+#
# #: ../src/core/dbus-unit.c:457
# msgid "Authentication is required to start '$(unit)'."
# msgstr "É necessária autenticação para iniciar '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:458
# msgid "Authentication is required to stop '$(unit)'."
# msgstr "É necessária autenticação para parar '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:459
# msgid "Authentication is required to reload '$(unit)'."
# msgstr "É necessária autenticação para recarregar '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:460 ../src/core/dbus-unit.c:461
# msgid "Authentication is required to restart '$(unit)'."
# msgstr "É necessária autenticação para reiniciar '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:568
# msgid "Authentication is required to kill '$(unit)'."
# msgstr "É necessária autenticação para matar '$(unit)'."
-
+#
# #: ../src/core/dbus-unit.c:599
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
# msgstr ""
-# "É necessária autenticação para reiniciar o estado \"failed" de '$(unit)'."
-
+# "É necessária autenticação para reiniciar o estado \"failed\" de '$(unit)'."
+#
# #: ../src/core/dbus-unit.c:632
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr "É necessária autenticação para definir propriedades em '$(unit)'."
+#endif // 0
+
diff --git a/po/ro.po b/po/ro.po
new file mode 100644
index 000000000..c4c1825c5
--- /dev/null
+++ b/po/ro.po
@@ -0,0 +1,626 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# Romanian translation for systemd.
+# Copyright (C) 2015 systemd's COPYRIGHT HOLDER
+# This file is distributed under the same license as the systemd package.
+# va511e <va511e@yahoo.com>, 2015.
+# Daniel Șerbănescu <daniel [at] serbanescu [dot] dk>, 2015, 2017.
+msgid ""
+msgstr ""
+"Project-Id-Version: systemd master\n"
+"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
+"POT-Creation-Date: 2017-08-13 15:26+0000\n"
+"PO-Revision-Date: 2017-08-13 19:48+0200\n"
+"Last-Translator: Daniel Șerbănescu <daniel [at] serbanescu [dot] dk>\n"
+"Language-Team: Gnome Romanian Translation Team\n"
+"Language: ro\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < "
+"20)) ? 1 : 2);;\n"
+"X-Generator: Virtaal 0.7.1\n"
+
+#if 0 /// UNNEEDED by elgoind
+# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
+# msgid "Send passphrase back to system"
+# msgstr "Trimite fraza secretă înapoi la sistem"
+#
+# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
+# msgid ""
+# "Authentication is required to send the entered passphrase back to the system."
+# msgstr ""
+# "Autentificarea este necesară pentru a trimite fraza secretă introdusă înapoi "
+# "la sistem."
+#
+# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
+# msgid "Manage system services or other units"
+# msgstr "Gestionează serviciile de sistem sau alte unități"
+#
+# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
+# msgid "Authentication is required to manage system services or other units."
+# msgstr ""
+# "Autentificarea este necesară pentru a gestiona serviciile de sistem sau alte "
+# "unități."
+#
+# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
+# msgid "Manage system service or unit files"
+# msgstr "Gestionează serviciul de sistem sau fișiere unitate"
+#
+# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
+# msgid "Authentication is required to manage system service or unit files."
+# msgstr ""
+# "Autentificarea este necesară pentru a gestiona serviciul de sistem sau "
+# "fișierele unitate."
+#
+# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
+# msgid "Set or unset system and service manager environment variables"
+# msgstr ""
+# "Stabilește sau destabilește variabilele de mediu și managerul de servicii "
+# "ale sistemului"
+#
+# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
+# msgid ""
+# "Authentication is required to set or unset system and service manager "
+# "environment variables."
+# msgstr ""
+# "Autentificarea este necesară pentru a stabili sau destabili variabile de "
+# "mediu și managerul de servicii ale sistemului."
+#
+# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
+# msgid "Reload the systemd state"
+# msgstr "Reîncarcă starea systemd"
+#
+# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
+# msgid "Authentication is required to reload the systemd state."
+# msgstr "Autentificarea este necesară pentru a reîncărca starea systemd."
+#
+# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
+# msgid "Set host name"
+# msgstr "Stabilește numele de server"
+#
+# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
+# msgid "Authentication is required to set the local host name."
+# msgstr "Autentificarea este necesară pentru a stabili numele de server local."
+#
+# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
+# msgid "Set static host name"
+# msgstr "Stabilește numele de server static"
+#
+# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
+# msgid ""
+# "Authentication is required to set the statically configured local host name, "
+# "as well as the pretty host name."
+# msgstr ""
+# "Autentificarea este necesara pentru a stabili numele de server static "
+# "configurat local, precum și numele lung de server."
+#
+# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
+# msgid "Set machine information"
+# msgstr "Stabilește informațiile despre mașină"
+#
+# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
+# msgid "Authentication is required to set local machine information."
+# msgstr ""
+# "Autentificarea este necesară pentru stabili informațiile mașinii locale."
+#
+# #: ../src/import/org.freedesktop.import1.policy.in.h:1
+# msgid "Import a VM or container image"
+# msgstr "Importă o VM (mașină virtuală) sau o imagine container"
+#
+# #: ../src/import/org.freedesktop.import1.policy.in.h:2
+# msgid "Authentication is required to import a VM or container image"
+# msgstr ""
+# "Autentificarea este necesară pentru a importa o VM (mașină virtuală) sau o "
+# "imagine container"
+#
+# #: ../src/import/org.freedesktop.import1.policy.in.h:3
+# msgid "Export a VM or container image"
+# msgstr "Exportă o VM (mașină virtuală) sau o imagine container"
+#
+# #: ../src/import/org.freedesktop.import1.policy.in.h:4
+# msgid "Authentication is required to export a VM or container image"
+# msgstr ""
+# "Autentificarea este necesară pentru a exporta o VM (mașină virtuală) sau o "
+# "imagine container"
+#
+# #: ../src/import/org.freedesktop.import1.policy.in.h:5
+# msgid "Download a VM or container image"
+# msgstr "Descarcă o VM (mașină virtuală) sau o imagine container"
+#
+# #: ../src/import/org.freedesktop.import1.policy.in.h:6
+# msgid "Authentication is required to download a VM or container image"
+# msgstr ""
+# "Autentificarea este necesară pentru a descărca o VM (mașină virtuală) sau o "
+# "imagine container"
+#
+# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
+# msgid "Set system locale"
+# msgstr "Stabilește localizarea sistemului"
+#
+# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
+# msgid "Authentication is required to set the system locale."
+# msgstr "Autentificarea este necesară pentru a stabili localizarea sistemului."
+#
+# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
+# msgid "Set system keyboard settings"
+# msgstr "Stabilește configurările tastaturii sistemului"
+#
+# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
+# msgid "Authentication is required to set the system keyboard settings."
+# msgstr ""
+# "Autentificarea este necesară pentru a stabili configurările tastaturii "
+# "sistemului."
+#
+#endif // 0
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:1
+msgid "Allow applications to inhibit system shutdown"
+msgstr "Permite aplicațiilor să împiedice închiderea sistemului"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:2
+msgid ""
+"Authentication is required for an application to inhibit system shutdown."
+msgstr ""
+"Autentificarea este necesară pentru ca o aplicație să împiedice închiderea "
+"sistemului."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:3
+msgid "Allow applications to delay system shutdown"
+msgstr "Permite aplicațiilor să întârzie închiderea sistemului"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:4
+msgid "Authentication is required for an application to delay system shutdown."
+msgstr ""
+"Autentificarea este necesară pentru ca o aplicație să întârzie închiderea "
+"sistemului."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:5
+msgid "Allow applications to inhibit system sleep"
+msgstr "Permite aplicațiilor să împiedice starea de veghe a sistemului"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:6
+msgid "Authentication is required for an application to inhibit system sleep."
+msgstr ""
+"Autentificarea este necesară pentru ca o aplicație să împiedice starea de "
+"veghe a sistemului."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:7
+msgid "Allow applications to delay system sleep"
+msgstr "Permite aplicațiilor să întârzie starea de veghe sistemului"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:8
+msgid "Authentication is required for an application to delay system sleep."
+msgstr ""
+"Autentificarea este necesară pentru ca o aplicație să întârzie starea de "
+"veghe a sistemului."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:9
+msgid "Allow applications to inhibit automatic system suspend"
+msgstr "Permite aplicațiilor să împiedice suspendarea automată a sistemului"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:10
+msgid ""
+"Authentication is required for an application to inhibit automatic system "
+"suspend."
+msgstr ""
+"Autentificarea este necesară pentru ca o aplicație să împiedice suspendarea "
+"automată a sistemului."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:11
+msgid "Allow applications to inhibit system handling of the power key"
+msgstr ""
+"Permite aplicațiilor să împiedice administrarea butonului de pornire a "
+"sistemului"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:12
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the power key."
+msgstr ""
+"Autentificarea este necesară pentru o aplicație să împiedice administrarea "
+"butonului de pornire a sistemului."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:13
+msgid "Allow applications to inhibit system handling of the suspend key"
+msgstr ""
+"Permite aplicațiilor să împiedice administrarea butonului de suspendare al "
+"sistemului"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:14
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the suspend key."
+msgstr ""
+"Autentificarea este necesară pentru o aplicație pentru a împiedica "
+"manipularea butonului de suspendare al sistemului."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:15
+msgid "Allow applications to inhibit system handling of the hibernate key"
+msgstr ""
+"Permite aplicațiilor să împiedice administrarea butonului de hibernare al "
+"sistemului"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:16
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the hibernate key."
+msgstr ""
+"Autentificarea este necesară pentru o aplicație să împiedice administrarea "
+"butonului de hibernare al sistemului."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:17
+msgid "Allow applications to inhibit system handling of the lid switch"
+msgstr ""
+"Permite aplicațiilor să împiedice administrarea comutatorului capacului al "
+"sistemului"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:18
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the lid switch."
+msgstr ""
+"Autentificarea este necesară pentru ca o aplicație să împiedice manipularea "
+"comutatorului capacului al sistemului."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:19
+msgid "Allow non-logged-in user to run programs"
+msgstr "Permite utilizatorilor neautentificați să execute programe"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:20
+msgid "Explicit request is required to run programs as a non-logged-in user."
+msgstr ""
+"Cererea explicită este necesară pentru a rula programe ca utilizator "
+"neautentificat."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:21
+msgid "Allow non-logged-in users to run programs"
+msgstr "Permite utilizatorilor neautentificați să execute programe"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:22
+msgid "Authentication is required to run programs as a non-logged-in user."
+msgstr ""
+"Autentificarea este necesară pentru a rula programe ca utilizator "
+"neautentificat."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:23
+msgid "Allow attaching devices to seats"
+msgstr "Permite atașarea dispozitivelor la locuri"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:24
+msgid "Authentication is required for attaching a device to a seat."
+msgstr "Autentificarea este necesară pentru a atașa un dispozitiv la un loc."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:25
+msgid "Flush device to seat attachments"
+msgstr "Purjează atașamentele dispozitiv-loc"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:26
+msgid ""
+"Authentication is required for resetting how devices are attached to seats."
+msgstr ""
+"Autentificarea este necesară pentru a restabili cum dispozitivele sunt "
+"atașate la locuri."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:27
+msgid "Power off the system"
+msgstr "Oprește sistemul"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:28
+msgid "Authentication is required for powering off the system."
+msgstr "Este necesară autentificarea pentru oprirea sistemului."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:29
+msgid "Power off the system while other users are logged in"
+msgstr "Oprește sistemul în timp ce alți utilizatori sunt autentificați"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:30
+msgid ""
+"Authentication is required for powering off the system while other users are "
+"logged in."
+msgstr ""
+"Autentificarea este necesară pentru oprirea sistemului în timp ce alți "
+"utilizatori sunt autentificați."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:31
+msgid "Power off the system while an application asked to inhibit it"
+msgstr "Oprește sistemul în timp ce o aplicație a cerut să împiedice asta"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:32
+msgid ""
+"Authentication is required for powering off the system while an application "
+"asked to inhibit it."
+msgstr ""
+"Autentificarea este necesară pentru oprirea sistemului în timp ce o "
+"aplicație a cerut să împiedice asta."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:33
+msgid "Reboot the system"
+msgstr "Repornește sistemul"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:34
+msgid "Authentication is required for rebooting the system."
+msgstr "Autentificarea este necesară pentru repornirea sistemului."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:35
+msgid "Reboot the system while other users are logged in"
+msgstr "Repornește sistemul în timp ce alți utilizatori sunt autentificați"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:36
+msgid ""
+"Authentication is required for rebooting the system while other users are "
+"logged in."
+msgstr ""
+"Autentificarea este necesară pentru repornirea sistemului în timp ce alți "
+"utilizatori autentificați."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:37
+msgid "Reboot the system while an application asked to inhibit it"
+msgstr "Repornește sistemul în timp ce o aplicație a cerut să împiedice asta"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:38
+msgid ""
+"Authentication is required for rebooting the system while an application "
+"asked to inhibit it."
+msgstr ""
+"Autentificarea este necesară pentru repornirea sistemului în timp ce o "
+"aplicație a cerut să împiedice asta."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:39
+msgid "Suspend the system"
+msgstr "Suspendă sistemul"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:40
+msgid "Authentication is required for suspending the system."
+msgstr "Este necesară autentificarea pentru suspendarea sistemului."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:41
+msgid "Suspend the system while other users are logged in"
+msgstr "Suspendă sistemul în timp ce alți utilizatori sunt autentificați"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:42
+msgid ""
+"Authentication is required for suspending the system while other users are "
+"logged in."
+msgstr ""
+"Autentificarea este necesară pentru suspendarea sistemului timp ce alți "
+"utilizatori autentificați."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:43
+msgid "Suspend the system while an application asked to inhibit it"
+msgstr "Suspendă sistemul în timp ce o aplicație a cerut să împiedice asta"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:44
+msgid ""
+"Authentication is required for suspending the system while an application "
+"asked to inhibit it."
+msgstr ""
+"Autentificarea este necesară pentru suspendarea sistemului în timp ce o "
+"aplicație a cerut să împiedice asta."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:45
+msgid "Hibernate the system"
+msgstr "Hiberneaza sistemul"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:46
+msgid "Authentication is required for hibernating the system."
+msgstr "Este necesară autentificarea pentru hibernarea sistemului."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:47
+msgid "Hibernate the system while other users are logged in"
+msgstr "Hiberneaza sistemul în timp ce alți utilizatori sunt autentificați"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:48
+msgid ""
+"Authentication is required for hibernating the system while other users are "
+"logged in."
+msgstr ""
+"Autentificarea este necesară pentru hibernare a sistemului în timp ce alți "
+"utilizatori sunt autentificați."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:49
+msgid "Hibernate the system while an application asked to inhibit it"
+msgstr "Hibernează sistemul în timp ce o aplicație a cerut să împiedice asta"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:50
+msgid ""
+"Authentication is required for hibernating the system while an application "
+"asked to inhibit it."
+msgstr ""
+"Autentificarea este necesară pentru hibernarea sistemului în timp ce o "
+"aplicație a cerut să împiedice asta."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:51
+msgid "Manage active sessions, users and seats"
+msgstr "Gestionează sesiuni active, utilizatori și locuri"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:52
+msgid ""
+"Authentication is required for managing active sessions, users and seats."
+msgstr ""
+"Autentificarea este necesară pentru gestionarea sesiunilor active, "
+"utilizatorilor și locurilor."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:53
+msgid "Lock or unlock active sessions"
+msgstr "Blochează sau deblochează sesiuni active"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:54
+msgid "Authentication is required to lock or unlock active sessions."
+msgstr ""
+"Autentificarea este necesară pentru a bloca sau debloca sesiuni active."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Allow indication to the firmware to boot to setup interface"
+msgstr ""
+"Permite semnalizatrea către firmware pentru a porni în interfața de "
+"configurare"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+msgid ""
+"Authentication is required to indicate to the firmware to boot to setup "
+"interface."
+msgstr ""
+"Autentificarea este necesară pentru a semnaliza către firmware să pornească "
+"în interfața de configurare."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:57
+msgid "Set a wall message"
+msgstr "Stabilește un mesaj de perete"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:58
+msgid "Authentication is required to set a wall message"
+msgstr "Autentificarea este necesară pentru a stabili un mesaj de perete"
+
+#if 0 /// UNNEEDED by elgoind
+# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
+# msgid "Log into a local container"
+# msgstr "Conectează la un container local"
+#
+# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
+# msgid "Authentication is required to log into a local container."
+# msgstr ""
+# "Autentificarea este necesară pentru a vă conecta într-un container local."
+#
+# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
+# msgid "Log into the local host"
+# msgstr "Conectează la serverul local"
+#
+# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+# msgid "Authentication is required to log into the local host."
+# msgstr "Autentificarea este necesară pentru a vă conecta la serverul local."
+#
+# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+# msgid "Acquire a shell in a local container"
+# msgstr "Obține un shell într-un container local"
+#
+# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+# msgid "Authentication is required to acquire a shell in a local container."
+# msgstr ""
+# "Autentificarea este necesară pentru a obține un shell într-un container "
+# "local."
+#
+# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
+# msgid "Acquire a shell on the local host"
+# msgstr "Obține un shell pe serverul local"
+#
+# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
+# msgid "Authentication is required to acquire a shell on the local host."
+# msgstr ""
+# "Autentificarea este necesară pentru a obține un shell pe serverul local."
+#
+# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+# msgid "Acquire a pseudo TTY in a local container"
+# msgstr "Obține un pseudo-TTY într-un container local"
+#
+# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+# msgid ""
+# "Authentication is required to acquire a pseudo TTY in a local container."
+# msgstr ""
+# "Autentificarea este necesară pentru a obține un pseudo-TTY într-un container "
+# "local."
+#
+# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
+# msgid "Acquire a pseudo TTY on the local host"
+# msgstr "Obține un pseudo-TTY pe serverul local"
+#
+# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
+# msgid "Authentication is required to acquire a pseudo TTY on the local host."
+# msgstr ""
+# "Autentificarea este necesară pentru a obține un pseudo-TTY pe serverul local."
+#
+# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
+# msgid "Manage local virtual machines and containers"
+# msgstr "Gestioneaza mașini virtuale locale și containere"
+#
+# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
+# msgid ""
+# "Authentication is required to manage local virtual machines and containers."
+# msgstr ""
+# "Autentificarea este necesară pentru a gestiona mașini virtuale locale și "
+# "containere."
+#
+# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
+# msgid "Manage local virtual machine and container images"
+# msgstr "Gestionează imaginile locale de mașină virtuală și containere"
+#
+# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
+# msgid ""
+# "Authentication is required to manage local virtual machine and container "
+# "images."
+# msgstr ""
+# "Autentificarea este necesară pentru a gestiona imagini locale de mașini "
+# "virtuale și de containere."
+#
+# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
+# msgid "Set system time"
+# msgstr "Stabilește ora sistemului"
+#
+# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
+# msgid "Authentication is required to set the system time."
+# msgstr "Autentificarea este necesară pentru a stabili ora sistemului."
+#
+# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
+# msgid "Set system timezone"
+# msgstr "Stabilește fusul orar al sistemului"
+#
+# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
+# msgid "Authentication is required to set the system timezone."
+# msgstr ""
+# "Autentificarea este necesară pentru a stabili fusul orar al sistemului."
+#
+# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
+# msgid "Set RTC to local timezone or UTC"
+# msgstr "Stabilește RTC la ora locală sau UTC"
+#
+# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
+# msgid ""
+# "Authentication is required to control whether the RTC stores the local or "
+# "UTC time."
+# msgstr ""
+# "Autentificarea este necesară pentru a controla dacă RTC stochează ora locală "
+# "sau UTC."
+#
+# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
+# msgid "Turn network time synchronization on or off"
+# msgstr "Comută sincronizarea cu ora rețelei"
+#
+# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
+# msgid ""
+# "Authentication is required to control whether network time synchronization "
+# "shall be enabled."
+# msgstr ""
+# "Autentificarea este necesară pentru a controla dacă sincronizarea cu ora "
+# "rețelei ar trebui activată."
+#
+# #: ../src/core/dbus-unit.c:457
+# msgid "Authentication is required to start '$(unit)'."
+# msgstr "Autentificarea este necesară pentru a porni „$(unit)”."
+#
+# #: ../src/core/dbus-unit.c:458
+# msgid "Authentication is required to stop '$(unit)'."
+# msgstr "Autentificarea este necesară pentru a opri „$(unit)”."
+#
+# #: ../src/core/dbus-unit.c:459
+# msgid "Authentication is required to reload '$(unit)'."
+# msgstr "Autentificarea este necesară pentru a reîncărca „$ (unit)”."
+#
+# #: ../src/core/dbus-unit.c:460 ../src/core/dbus-unit.c:461
+# msgid "Authentication is required to restart '$(unit)'."
+# msgstr "Autentificarea este necesară pentru a reporni „$(unit)”."
+#
+# #: ../src/core/dbus-unit.c:568
+# msgid "Authentication is required to kill '$(unit)'."
+# msgstr "Autentificarea este necesară pentru a omorî „$(unit)”."
+#
+# #: ../src/core/dbus-unit.c:599
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+# msgstr ""
+# "Autentificarea este necesară pentru a restabili starea „eșuată” a „$(unit)”."
+#
+# #: ../src/core/dbus-unit.c:632
+# msgid "Authentication is required to set properties on '$(unit)'."
+# msgstr ""
+# "Autentificarea este necesară pentru a stabili proprietățile pe „$(unit)”."
+#endif // 0
+
diff --git a/po/ru.po b/po/ru.po
index 56088d13f..074ea396c 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -1,13 +1,15 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# translation of ru.po to Rissian
# Julia Dronova <juliette.tux@gmail.com>, 2013.
-# Sergey Ptashnick <0comffdiz@inbox.ru>, 2013-2016.
+# Sergey Ptashnick <0comffdiz@inbox.ru>, 2013-2017.
#
msgid ""
msgstr ""
"Project-Id-Version: systemd\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-11-22 16:37+0100\n"
-"PO-Revision-Date: 2016-02-02 20:22+0300\n"
+"PO-Revision-Date: 2017-10-10 00:28+0300\n"
"Last-Translator: Sergey Ptashnick <0comffdiz@inbox.ru>\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
@@ -16,39 +18,40 @@ msgstr ""
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "Отправить пароль системе"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr "Чтобы отправить пароль системе, необходимо пройти аутентификацию."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "Управление системными службами и юнитами"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr ""
# "Для управления системными службами и юнитами, необходимо пройти "
# "аутентификацию."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "Управление файлами конфигурации системных служб и юнитов"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr ""
# "Для управления файлами конфигурации системных служб и юнитов, необходимо "
# "пройти аутентификацию."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr "Настроить переменные окружения для системного менеджера"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
@@ -56,29 +59,29 @@ msgstr ""
# msgstr ""
# "Чтобы настроить переменные окружения для системного менеджера, необходимо "
# "пройти аутентификацию."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "Перечитать конфигурацию systemd"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr ""
# "Чтобы заставить systemd перечитать конфигурацию, необходимо пройти "
# "аутентификацию."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "Настроить имя компьютера"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "Чтобы настроить имя компьютера, необходимо пройти аутентификацию."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "Настроить статическое имя компьютера"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
@@ -86,62 +89,64 @@ msgstr ""
# msgstr ""
# "Чтобы настроить статическое имя компьютера, а также его «красивое» имя, "
# "необходимо пройти аутентификацию."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "Настроить информацию о компьютере"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr ""
# "Чтобы настроить информацию о компьютере, необходимо пройти аутентификацию."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "Импортировать образ виртуальной машины или контейнера"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr ""
# "Чтобы импортировать образ виртуальной машины или контейнера, необходимо "
# "пройти аутентификацию."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "Экспортировать образ виртуальной машины или контейнера"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr ""
# "Чтобы экспортировать образ виртуальной машины или контейнера, необходимо "
# "пройти аутентификацию."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "Загрузить образ виртуальной машины или контейнера"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr ""
# "Чтобы загрузить образ виртуальной машины или контейнера, необходимо пройти "
# "аутентификацию."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "Настроить системную локаль"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr "Чтобы настроить системную локаль, необходимо пройти аутентификацию."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "Настроить параметры клавиатуры"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr ""
# "Чтобы настроить параметры клавиатуры, необходимо пройти аутентификацию."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -255,52 +260,63 @@ msgstr ""
"крышки ноутбука, необходимо пройти аутентификацию."
#: ../src/login/org.freedesktop.login1.policy.in.h:19
+msgid "Allow non-logged-in user to run programs"
+msgstr ""
+"Разрешить работу программ в фоновом режиме после завершения сеанса"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:20
+msgid "Explicit request is required to run programs as a non-logged-in user."
+msgstr ""
+"Чтобы разрешить работу программ в фоновом режиме после завершения сеанса, "
+"необходимо явное подтверждение."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:21
msgid "Allow non-logged-in users to run programs"
msgstr ""
"Разрешить пользователям оставлять программы в фоновом режиме после "
"завершения сеанса"
-#: ../src/login/org.freedesktop.login1.policy.in.h:20
+#: ../src/login/org.freedesktop.login1.policy.in.h:22
msgid "Authentication is required to run programs as a non-logged-in user."
msgstr ""
"Чтобы разрешить пользователям оставлять программы в фоновом режиме после "
"завершения сеанса, необходимо пройти аутентификацию."
-#: ../src/login/org.freedesktop.login1.policy.in.h:21
+#: ../src/login/org.freedesktop.login1.policy.in.h:23
msgid "Allow attaching devices to seats"
msgstr "Разрешить подключение устройств к рабочим местам"
-#: ../src/login/org.freedesktop.login1.policy.in.h:22
+#: ../src/login/org.freedesktop.login1.policy.in.h:24
msgid "Authentication is required for attaching a device to a seat."
msgstr ""
"Чтобы разрешить подключение устройств к рабочим местам, необходимо пройти "
"аутентификацию."
-#: ../src/login/org.freedesktop.login1.policy.in.h:23
+#: ../src/login/org.freedesktop.login1.policy.in.h:25
msgid "Flush device to seat attachments"
msgstr "Сбросить привязки устройств к рабочим местам"
-#: ../src/login/org.freedesktop.login1.policy.in.h:24
+#: ../src/login/org.freedesktop.login1.policy.in.h:26
msgid ""
"Authentication is required for resetting how devices are attached to seats."
msgstr ""
"Чтобы сбросить привязки устройств к рабочим местам, необходимо пройти "
"аутентификацию."
-#: ../src/login/org.freedesktop.login1.policy.in.h:25
+#: ../src/login/org.freedesktop.login1.policy.in.h:27
msgid "Power off the system"
msgstr "Выключить систему"
-#: ../src/login/org.freedesktop.login1.policy.in.h:26
+#: ../src/login/org.freedesktop.login1.policy.in.h:28
msgid "Authentication is required for powering off the system."
msgstr "Чтобы выключить систему, необходимо пройти аутентификацию."
-#: ../src/login/org.freedesktop.login1.policy.in.h:27
+#: ../src/login/org.freedesktop.login1.policy.in.h:29
msgid "Power off the system while other users are logged in"
msgstr ""
"Выключить систему, несмотря на то, что в ней работают другие пользователи"
-#: ../src/login/org.freedesktop.login1.policy.in.h:28
+#: ../src/login/org.freedesktop.login1.policy.in.h:30
msgid ""
"Authentication is required for powering off the system while other users are "
"logged in."
@@ -308,13 +324,13 @@ msgstr ""
"Чтобы выключить систему, несмотря на то, что в ней работают другие "
"пользователи, необходимо пройти аутентификацию."
-#: ../src/login/org.freedesktop.login1.policy.in.h:29
+#: ../src/login/org.freedesktop.login1.policy.in.h:31
msgid "Power off the system while an application asked to inhibit it"
msgstr ""
"Выключить систему, несмотря на то, что приложение запросило блокировку "
"выключения"
-#: ../src/login/org.freedesktop.login1.policy.in.h:30
+#: ../src/login/org.freedesktop.login1.policy.in.h:32
msgid ""
"Authentication is required for powering off the system while an application "
"asked to inhibit it."
@@ -322,20 +338,20 @@ msgstr ""
"Чтобы выключить систему, несмотря на то, что приложение запросило блокировку "
"выключения, необходимо пройти аутентификацию."
-#: ../src/login/org.freedesktop.login1.policy.in.h:31
+#: ../src/login/org.freedesktop.login1.policy.in.h:33
msgid "Reboot the system"
msgstr "Перезагрузить систему"
-#: ../src/login/org.freedesktop.login1.policy.in.h:32
+#: ../src/login/org.freedesktop.login1.policy.in.h:34
msgid "Authentication is required for rebooting the system."
msgstr "Чтобы перезагрузить систему, необходимо пройти аутентификацию."
-#: ../src/login/org.freedesktop.login1.policy.in.h:33
+#: ../src/login/org.freedesktop.login1.policy.in.h:35
msgid "Reboot the system while other users are logged in"
msgstr ""
"Перезагрузить систему, несмотря на то, что в ней работают другие пользователи"
-#: ../src/login/org.freedesktop.login1.policy.in.h:34
+#: ../src/login/org.freedesktop.login1.policy.in.h:36
msgid ""
"Authentication is required for rebooting the system while other users are "
"logged in."
@@ -343,13 +359,13 @@ msgstr ""
"Чтобы перезагрузить систему, несмотря на то, что в ней работают другие "
"пользователи, необходимо пройти аутентификацию."
-#: ../src/login/org.freedesktop.login1.policy.in.h:35
+#: ../src/login/org.freedesktop.login1.policy.in.h:37
msgid "Reboot the system while an application asked to inhibit it"
msgstr ""
"Перезагрузить систему, несмотря на то, что приложение запросило блокировку "
"выключения"
-#: ../src/login/org.freedesktop.login1.policy.in.h:36
+#: ../src/login/org.freedesktop.login1.policy.in.h:38
msgid ""
"Authentication is required for rebooting the system while an application "
"asked to inhibit it."
@@ -357,22 +373,57 @@ msgstr ""
"Чтобы перезагрузить систему, несмотря на то, что приложение запросило "
"блокировку выключения, необходимо пройти аутентификацию."
-#: ../src/login/org.freedesktop.login1.policy.in.h:37
+#: ../src/login/org.freedesktop.login1.policy.in.h:39
+msgid "Halt the system"
+msgstr "Остановить систему"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:40
+msgid "Authentication is required for halting the system."
+msgstr "Чтобы остановить систему, необходимо пройти аутентификацию."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:41
+msgid "Halt the system while other users are logged in"
+msgstr ""
+"Остановить систему, несмотря на то, что в ней работают другие пользователи"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:42
+msgid ""
+"Authentication is required for halting the system while other users are "
+"logged in."
+msgstr ""
+"Чтобы остановить систему, несмотря на то, что в ней работают другие "
+"пользователи, необходимо пройти аутентификацию."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:43
+msgid "Halt the system while an application asked to inhibit it"
+msgstr ""
+"Остановить систему, несмотря на то, что приложение запросило блокировку "
+"выключения"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:44
+msgid ""
+"Authentication is required for halting the system while an application asked "
+"to inhibit it."
+msgstr ""
+"Чтобы остановить систему, несмотря на то, что приложение запросило "
+"блокировку выключения, необходимо пройти аутентификацию."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:45
msgid "Suspend the system"
msgstr "Перевести систему в ждущий режим"
-#: ../src/login/org.freedesktop.login1.policy.in.h:38
+#: ../src/login/org.freedesktop.login1.policy.in.h:46
msgid "Authentication is required for suspending the system."
msgstr ""
"Чтобы перевести систему в ждущий режим, необходимо пройти аутентификацию."
-#: ../src/login/org.freedesktop.login1.policy.in.h:39
+#: ../src/login/org.freedesktop.login1.policy.in.h:47
msgid "Suspend the system while other users are logged in"
msgstr ""
"Перевести систему в ждущий режим, несмотря на то, что в ней работают другие "
"пользователи"
-#: ../src/login/org.freedesktop.login1.policy.in.h:40
+#: ../src/login/org.freedesktop.login1.policy.in.h:48
msgid ""
"Authentication is required for suspending the system while other users are "
"logged in."
@@ -380,13 +431,13 @@ msgstr ""
"Чтобы перевести систему в ждущий режим, несмотря на то, что в ней работают "
"другие пользователи, необходимо пройти аутентификацию."
-#: ../src/login/org.freedesktop.login1.policy.in.h:41
+#: ../src/login/org.freedesktop.login1.policy.in.h:49
msgid "Suspend the system while an application asked to inhibit it"
msgstr ""
"Перевести систему в ждущий режим, несмотря на то, что приложение запросило "
"блокировку"
-#: ../src/login/org.freedesktop.login1.policy.in.h:42
+#: ../src/login/org.freedesktop.login1.policy.in.h:50
msgid ""
"Authentication is required for suspending the system while an application "
"asked to inhibit it."
@@ -394,22 +445,22 @@ msgstr ""
"Чтобы перевести систему в ждущий режим, несмотря на то, что приложение "
"запросило блокировку, необходимо пройти аутентификацию."
-#: ../src/login/org.freedesktop.login1.policy.in.h:43
+#: ../src/login/org.freedesktop.login1.policy.in.h:51
msgid "Hibernate the system"
msgstr "Перевести систему в спящий режим"
-#: ../src/login/org.freedesktop.login1.policy.in.h:44
+#: ../src/login/org.freedesktop.login1.policy.in.h:52
msgid "Authentication is required for hibernating the system."
msgstr ""
"Чтобы перевести систему в спящий режим, необходимо пройти аутентификацию."
-#: ../src/login/org.freedesktop.login1.policy.in.h:45
+#: ../src/login/org.freedesktop.login1.policy.in.h:53
msgid "Hibernate the system while other users are logged in"
msgstr ""
"Перевести систему в спящий режим, несмотря на то, что в ней работают другие "
"пользователи"
-#: ../src/login/org.freedesktop.login1.policy.in.h:46
+#: ../src/login/org.freedesktop.login1.policy.in.h:54
msgid ""
"Authentication is required for hibernating the system while other users are "
"logged in."
@@ -417,13 +468,13 @@ msgstr ""
"Чтобы перевести систему в спящий режим, несмотря на то, что в ней работают "
"другие пользователи, необходимо пройти аутентификацию."
-#: ../src/login/org.freedesktop.login1.policy.in.h:47
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
msgid "Hibernate the system while an application asked to inhibit it"
msgstr ""
"Перевести систему в спящий режим, несмотря на то, что приложение запросило "
"блокировку"
-#: ../src/login/org.freedesktop.login1.policy.in.h:48
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
msgid ""
"Authentication is required for hibernating the system while an application "
"asked to inhibit it."
@@ -431,32 +482,32 @@ msgstr ""
"Чтобы перевести систему в спящий режим, несмотря на то, что приложение "
"запросило блокировку, необходимо пройти аутентификацию."
-#: ../src/login/org.freedesktop.login1.policy.in.h:49
+#: ../src/login/org.freedesktop.login1.policy.in.h:57
msgid "Manage active sessions, users and seats"
msgstr "Управление текущими сеансами, пользователями и рабочими местами"
-#: ../src/login/org.freedesktop.login1.policy.in.h:50
+#: ../src/login/org.freedesktop.login1.policy.in.h:58
msgid ""
"Authentication is required for managing active sessions, users and seats."
msgstr ""
"Для управления текущими сеансами, пользователями и рабочими местами, "
"необходимо пройти аутентификацию."
-#: ../src/login/org.freedesktop.login1.policy.in.h:51
+#: ../src/login/org.freedesktop.login1.policy.in.h:59
msgid "Lock or unlock active sessions"
msgstr "Заблокировать или разблокировать текущие сеансы"
-#: ../src/login/org.freedesktop.login1.policy.in.h:52
+#: ../src/login/org.freedesktop.login1.policy.in.h:60
msgid "Authentication is required to lock or unlock active sessions."
msgstr ""
"Чтобы заблокировать или разблокировать текущие сеансы, необходимо пройти "
"аутентификацию."
-#: ../src/login/org.freedesktop.login1.policy.in.h:53
+#: ../src/login/org.freedesktop.login1.policy.in.h:61
msgid "Allow indication to the firmware to boot to setup interface"
msgstr "Разрешить загрузку в режиме настройки прошивки материнской платы"
-#: ../src/login/org.freedesktop.login1.policy.in.h:54
+#: ../src/login/org.freedesktop.login1.policy.in.h:62
msgid ""
"Authentication is required to indicate to the firmware to boot to setup "
"interface."
@@ -464,87 +515,88 @@ msgstr ""
"Чтобы разрешить загрузку в режиме настройки прошивки материнской платы, "
"необходимо пройти аутентификацию."
-#: ../src/login/org.freedesktop.login1.policy.in.h:55
+#: ../src/login/org.freedesktop.login1.policy.in.h:63
msgid "Set a wall message"
msgstr "Отправить сообщение на все терминалы"
-#: ../src/login/org.freedesktop.login1.policy.in.h:56
+#: ../src/login/org.freedesktop.login1.policy.in.h:64
msgid "Authentication is required to set a wall message"
msgstr ""
"Чтобы отправить сообщение на все терминалы, необходимо пройти аутентификацию."
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "Зайти в локальный контейнер"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr "Чтобы зайти в локальный контейнер, необходимо пройти аутентификацию."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "Зайти на этот компьютер"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr "Чтобы зайти на этот компьютер, необходимо пройти аутентификацию."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "Получить командную оболочку в локальном контейнере"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr ""
# "Чтобы получить командную оболочку в локальном контейнере, необходимо пройти "
# "аутентификацию."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "Запустить командную оболочку на этом компьютере"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr ""
# "Чтобы запустить командную оболочку на этом компьютере, необходимо пройти "
# "аутентификацию."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "Получить псевдо-терминал в локальном контейнере"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr ""
# "Чтобы получить псевдо-терминал в локальном контейнере, необходимо пройти "
# "аутентификацию."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "Получить псевдо-терминал на этом компьютере"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr ""
# "Чтобы получить псевдо-терминал на этом компьютере, необходимо пройти "
# "аутентификацию."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "Управление виртуальными машинами и контейнерами"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr ""
# "Для управления виртуальными машинами и контейнерами, необходимо пройти "
# "аутентификацию."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "Управление образами виртуальных машин и контейнеров"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
@@ -552,27 +604,27 @@ msgstr ""
# msgstr ""
# "Для управления образами виртуальных машин и контейнеров, необходимо пройти "
# "аутентификацию."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "Настроить системное время"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "Чтобы настроить системное время, необходимо пройти аутентификацию."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "Настроить часовой пояс"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr "Чтобы настроить часовой пояс, необходимо пройти аутентификацию."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr "Установить аппаратные часы по местному времени или по Гринвичу"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
@@ -580,11 +632,11 @@ msgstr ""
# msgstr ""
# "Чтобы контролировать, установлены аппаратные часы по местному времени или по "
# "Гринвичу, необходимо пройти аутентификацию."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "Включить или выключить синхронизацию времени по сети"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
@@ -592,50 +644,52 @@ msgstr ""
# msgstr ""
# "Чтобы включить или выключить синхронизацию времени по сети, необходимо "
# "пройти аутентификацию."
-
-# #: ../src/core/dbus-unit.c:428
+#
+# #: ../src/core/dbus-unit.c:458
# msgid "Authentication is required to start '$(unit)'."
# msgstr "Чтобы запустить «$(unit)», необходимо пройти аутентификацию."
-
-# #: ../src/core/dbus-unit.c:429
+#
+# #: ../src/core/dbus-unit.c:459
# msgid "Authentication is required to stop '$(unit)'."
# msgstr "Чтобы остановить «$(unit)», необходимо пройти аутентификацию."
-
-# #: ../src/core/dbus-unit.c:430
+#
+# #: ../src/core/dbus-unit.c:460
# msgid "Authentication is required to reload '$(unit)'."
# msgstr ""
# "Чтобы заставить «$(unit)» перечитать конфигурацию, необходимо пройти "
# "аутентификацию."
-
-# #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
+#
+# #: ../src/core/dbus-unit.c:461 ../src/core/dbus-unit.c:462
# msgid "Authentication is required to restart '$(unit)'."
# msgstr "Чтобы перезапустить «$(unit)», необходимо пройти аутентификацию."
-
-# #: ../src/core/dbus-unit.c:535
+#
+# #: ../src/core/dbus-unit.c:569
# msgid "Authentication is required to kill '$(unit)'."
# msgstr "Чтобы убить юнит «$(unit)», необходимо пройти аутентификацию."
-
-# #: ../src/core/dbus-unit.c:565
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
+#
+# #: ../src/core/dbus-unit.c:600
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
# msgstr ""
# "Чтобы сбросить состояние «failed» у юнита «$(unit)», необходимо пройти "
# "аутентификацию."
-
-# #: ../src/core/dbus-unit.c:597
+#
+# #: ../src/core/dbus-unit.c:633
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr "Чтобы изменить параметры юнита «$(unit)», необходимо пройти "
# "аутентификацию."
+#
+# #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
+# #~ msgstr ""
+# #~ "Чтобы прервать все запущенные проверки файловых систем, нажмите Ctrl+C"
+#
+# # There is no difference between "на 2 дисках" (plural==1) and "на 5 дисках" (plural==2)
+# #~ msgid "Checking in progress on %d disk (%3.1f%% complete)"
+# #~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
+# #~ msgstr[0] ""
+# #~ "Проверяется целостность файловой системы на %d диске (выполнено %3.1f%%)"
+# #~ msgstr[1] ""
+# #~ "Проверяется целостность файловых систем на %d дисках (выполнено %3.1f%%)"
+# #~ msgstr[2] ""
+# #~ "Проверяется целостность файловых систем на %d дисках (выполнено %3.1f%%)"
+#endif // 0
-#~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
-#~ msgstr ""
-#~ "Чтобы прервать все запущенные проверки файловых систем, нажмите Ctrl+C"
-
-# There is no difference between "на 2 дисках" (plural==1) and "на 5 дисках" (plural==2)
-#~ msgid "Checking in progress on %d disk (%3.1f%% complete)"
-#~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
-#~ msgstr[0] ""
-#~ "Проверяется целостность файловой системы на %d диске (выполнено %3.1f%%)"
-#~ msgstr[1] ""
-#~ "Проверяется целостность файловых систем на %d дисках (выполнено %3.1f%%)"
-#~ msgstr[2] ""
-#~ "Проверяется целостность файловых систем на %d дисках (выполнено %3.1f%%)"
diff --git a/po/sk.po b/po/sk.po
index e08c0a7ac..112e7f706 100644
--- a/po/sk.po
+++ b/po/sk.po
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# Slovak translation for systemd.
# Copyright (C) 2017 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
@@ -18,42 +20,43 @@ msgstr ""
"Last-Translator: Dušan Kazik <prescott66@gmail.com>\n"
"X-Generator: Poedit 2.0.2\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "Odoslanie hesla späť do systému"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr ""
# "Vyžaduje sa overenie totožnosti na odoslanie zadaného hesla späť do systému."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "Správa systémových služieb alebo iných jednotiek"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr ""
# "Vyžaduje sa overenie totožnosti na správu systémových služieb alebo iných "
# "jednotiek."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "Správa systémovej služby alebo súborov jednotky"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr ""
# "Vyžaduje sa overenie totožnosti na správu systémovej služby alebo súborov "
# "jednotky."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr ""
# "Nastavenie alebo zrušenie nastavenia premenných prostredia systému a správcu "
# "služieb"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
@@ -61,28 +64,28 @@ msgstr ""
# msgstr ""
# "Vyžaduje sa overenie totožnosti na nastavenie alebo zrušenie nastavenia "
# "premenných prostredia systému a správcu služieb."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "Znovu načítanie stavu systému systemd"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr ""
# "Vyžaduje sa overenie totožnosti na znovu načítanie stavu systému systemd."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "Nastavenie názvu hostiteľa"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "Vyžaduje sa overenie totožnosti na nastavenie názvu hostiteľa."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "Nastavenie nemenného názvu hostiteľa"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
@@ -90,57 +93,59 @@ msgstr ""
# msgstr ""
# "Vyžaduje sa overenie totožnosti na nastavenie pevne určeného názvu miestneho "
# "hostiteľa, známeho ako zrozumiteľný názov hostiteľa."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "Nastavenie informácií o počítači"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr ""
# "Vyžaduje sa overenie totožnosti na nastavenie informácií o miestnom počítači."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr ""
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr ""
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr ""
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr ""
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr ""
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr ""
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "Nastavenie miestnych nastavení"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr "Vyžaduje sa overenie totožnosti na nastavenie miestnych nastavení."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "Nastavenie nastavení systémovej klávesnice"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr ""
# "Vyžaduje sa overenie totožnosti na nastavenie nastavení systémovej "
# "klávesnice."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -420,105 +425,106 @@ msgstr ""
msgid "Authentication is required to set a wall message"
msgstr ""
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "Prihlásenie do miestneho kontajneru"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr ""
# "Vyžaduje sa overenie totožnosti na prihlásenie do miestneho kontajneru."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr ""
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr ""
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr ""
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr ""
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr ""
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr ""
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr ""
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr ""
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr ""
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr ""
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr ""
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr ""
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr ""
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
# "images."
# msgstr ""
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr ""
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr ""
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr ""
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr ""
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr ""
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
# "UTC time."
# msgstr ""
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "Zapnutie alebo vypnutie sieťovej synchronizácie času"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
@@ -526,31 +532,33 @@ msgstr ""
# msgstr ""
# "Vyžaduje sa overenie totožnosti na ovládanie, či má byť povolená "
# "synchronizácia času cez sieť."
-
+#
# #: ../src/core/dbus-unit.c:457
# msgid "Authentication is required to start '$(unit)'."
# msgstr ""
-
+#
# #: ../src/core/dbus-unit.c:458
# msgid "Authentication is required to stop '$(unit)'."
# msgstr ""
-
+#
# #: ../src/core/dbus-unit.c:459
# msgid "Authentication is required to reload '$(unit)'."
# msgstr ""
-
+#
# #: ../src/core/dbus-unit.c:460 ../src/core/dbus-unit.c:461
# msgid "Authentication is required to restart '$(unit)'."
# msgstr ""
-
+#
# #: ../src/core/dbus-unit.c:568
# msgid "Authentication is required to kill '$(unit)'."
# msgstr ""
-
+#
# #: ../src/core/dbus-unit.c:599
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
# msgstr ""
-
+#
# #: ../src/core/dbus-unit.c:632
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr ""
+#endif // 0
+
diff --git a/po/sr.po b/po/sr.po
index b0cde7d0f..4c3294ebf 100644
--- a/po/sr.po
+++ b/po/sr.po
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
@@ -20,40 +22,41 @@ msgstr ""
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"Language: sr\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "Пошаљите фразу ка систему"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr ""
# "Потребно је да се идентификујете да бисте послали фразу назад у систем."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "Управљајте системским услугама и другим јединицама"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr ""
# "Потребно је да се идентификујете да бисте управљали системским услугама или "
# "другим јединицама."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "Управљајте системском услугом или јединичним датотекама"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr ""
# "Потребно је да се идентификујете да бисте управљали системском услугом или "
# "јединичним датотекама."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr "Мењајте променљиве окружења на систему и унутар управника услуга"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
@@ -61,28 +64,28 @@ msgstr ""
# msgstr ""
# "Потребно је да се идентификујете да бисте мењали променљиве окружења на "
# "систему и унутар управника услуга."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "Поново учитајте стање систем-деа"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr ""
# "Потребно је да се идентификујете да бисте поново учитали стање систем-деа."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "Поставите назив машине"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "Потребно је да се идентификујете да бисте поставили назив машине."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "Поставите статички назив машине"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
@@ -90,65 +93,67 @@ msgstr ""
# msgstr ""
# "Потребно је да се идентификујете да бисте поставили статички назив машине и "
# "да бисте поставили леп назив машине."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "Поставите податке о машини"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr ""
# "Потребно је да се идентификујете да бисте поставили податке о локалној "
# "машини."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "Увезите ВМ или слику контејнера"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr ""
# "Потребно је да се идентификујете да бисте увезли виртуелну машину или слику "
# "контејнера"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "Извезите ВМ или слику контејнера"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr ""
# "Потребно је да се идентификујете да бисте извезли виртуелну машину или слику "
# "контејнера"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "Преузмите ВМ или слику контејнера"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr ""
# "Потребно је да се идентификујете да бисте преузели виртуелну машину или "
# "слику контејнера"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "Поставите основни језик система"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr ""
# "Потребно је да се идентификујете да бисте поставили основни језик система."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "Поставите подешавање системске тастатуре"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr ""
# "Потребно је да се идентификујете да бисте поставили подешавања системске "
# "тастатуре."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -451,80 +456,81 @@ msgstr "Поставите зидну поруку"
msgid "Authentication is required to set a wall message"
msgstr "Потребно је да се идентификујете да бисте поставили зидну поруку"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "Пријавите се у локални контејнер"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr ""
# "Потребно је да се идентификујете да бисте се пријавили у локални контејнер."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "Пријавите се у локалног домаћина"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr ""
# "Потребно је да се идентификујете да бисте се пријавили у локалног домаћина."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "Добијте приступ шкољци унутар локалног контејнера"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr ""
# "Потребно је да се идентификујете да бисте добили приступ шкољци унутар "
# "локалног контејнера."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "Добијте приступ шкољци на локалном домаћину"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr ""
# "Потребно је да се идентификујете да бисте добили приступ шкољци на локалном "
# "домаћину."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "Добијте приступ псеудо писаћој машини унутар локалног контејнера"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr ""
# "Потребно је да се идентификујете да бисте добили приступ псеудо писаћој "
# "машини унутар локалног контејнера."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "Добијте приступ псеудо писаћој машини на локалном домаћину"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr ""
# "Потребно је да се идентификујете да бисте добили приступ псеудо писаћој "
# "машини на локалном домаћину."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "Управљајте локалним виртуелним машинама и контејнерима"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr ""
# "Потребно је да се идентификујете да бисте управљали локалним виртуелним "
# "машинама и контејнерима."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "Управљајте локалним виртуелним машинама и сликама контејнера"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
@@ -532,28 +538,28 @@ msgstr "Потребно је да се идентификујете да бис
# msgstr ""
# "Потребно је да се идентификујете да бисте управљали локалним виртуелним "
# "машинама и сликама контејнера."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "Поставите системско време"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "Потребно је да се идентификујете да бисте поставили системско време."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "Поставите системску временску зону"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr ""
# "Потребно је да се идентификујете да бисте поставили системску временску зону."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr "Поставите RTC на локалну временску зону или UTC зону"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
@@ -561,11 +567,11 @@ msgstr "Потребно је да се идентификујете да бис
# msgstr ""
# "Потребно је да се идентификујете да бисте подесили да ли RTC чува локално "
# "или UTC време."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "Укључите или искључите усклађивање времена са мреже"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
@@ -573,34 +579,36 @@ msgstr "Потребно је да се идентификујете да бис
# msgstr ""
# "Потребно је да се идентификујете да бисте подесили да ли се време усклађује "
# "са мреже."
-
+#
# #: ../src/core/dbus-unit.c:428
# msgid "Authentication is required to start '$(unit)'."
# msgstr "Потребно је да се идентификујете да бисте покренули „$(unit)“."
-
+#
# #: ../src/core/dbus-unit.c:429
# msgid "Authentication is required to stop '$(unit)'."
# msgstr "Потребно је да се идентификујете да бисте зауставили „$(unit)“."
-
+#
# #: ../src/core/dbus-unit.c:430
# msgid "Authentication is required to reload '$(unit)'."
# msgstr "Потребно је да се идентификујете да бисте поново учитали „$(unit)“."
-
+#
# #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
# msgid "Authentication is required to restart '$(unit)'."
# msgstr "Потребно је да се идентификујете да бисте поново покренули „$(unit)“."
-
+#
# #: ../src/core/dbus-unit.c:535
# msgid "Authentication is required to kill '$(unit)'."
# msgstr "Потребно је да се идентификујете да бисте убили „$(unit)“."
-
+#
# #: ../src/core/dbus-unit.c:565
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
# msgstr ""
# "Потребно је да се идентификујете да бисте поново поставили „неуспешно“ стање "
# "за „$(unit)“."
-
+#
# #: ../src/core/dbus-unit.c:597
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr ""
# "Потребно је да се идентификујете да бисте поставили својства за „$(unit)“."
+#endif // 0
+
diff --git a/po/sv.po b/po/sv.po
index 9c0263637..852e09d8c 100644
--- a/po/sv.po
+++ b/po/sv.po
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# Swedish translation for systemd.
# Copyright © 2015 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
@@ -19,38 +21,39 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.8.9\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "Skicka tillbaka lösenfras till system"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr ""
# "Autentisering krävs för att skicka tillbaka den angivna lösenfrasen till "
# "systemet."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "Hantera systemtjänster eller andra enheter"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr ""
# "Autentisering krävs för att hantera systemtjänster eller andra enheter."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "Hantera systemtjänster eller enhetsfiler"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr "Autentisering krävs för att hantera systemtjänster eller enhetsfiler."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr "Ställ in eller ta bort miljövariabler för system- och servicehanterare"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
@@ -58,27 +61,27 @@ msgstr ""
# msgstr ""
# "Autentisering krävs för att ställa in eller ta bort miljövariabler för "
# "system- och servicehanterare."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "Läs om tillståndet för systemd"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr "Autentisering krävs för att läsa om tillståndet för systemd."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "Ange värdnamn"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "Autentisering krävs för att ställa in lokalt värdnamn."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "Ange statiskt värdnamn"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
@@ -86,55 +89,57 @@ msgstr ""
# msgstr ""
# "Autentisering krävs för att ställa in det statiskt konfigurerade lokala "
# "värdnamnet såväl som det stiliga värdnamnet."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "Ställa in datorinformation"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr "Autentisering krävs för att ställa in lokal datorinformation."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "Importera en VM eller behållaravbildning"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr "Autentisering krävs för att importera en VM eller behållaravbildning"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "Exportera en VM eller behållaravbildning"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr "Autentisering krävs för att exportera en VM eller behållaravbildning"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "Hämta ner en VM eller behållaravbildning"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr "Autentisering krävs för att hämta ner en VM eller behållaravbildning"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "Ange systemlokal"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr "Autentisering krävs för att ställa in systemlokal."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "Ange systeminställningar för tangentbord"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr ""
# "Autentisering krävs för att ställa in systeminställningar för tangentbord."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -336,6 +341,40 @@ msgstr ""
"Autentisering krävs för att starta om systemet även då ett program hindrar "
"det."
+#if 0 /// UNNEEDED by elgoind
+# #: src/login/org.freedesktop.login1.policy.in:224
+# msgid "Halt the system"
+# msgstr "Stoppa systemet"
+#
+# #: src/login/org.freedesktop.login1.policy.in:225
+# msgid "Authentication is required for halting the system."
+# msgstr "Autentisering krävs för att stoppa systemet."
+#
+# #: src/login/org.freedesktop.login1.policy.in:235
+# msgid "Halt the system while other users are logged in"
+# msgstr "Stoppa systemet medan andra användare är inloggade"
+#
+# #: src/login/org.freedesktop.login1.policy.in:236
+# msgid ""
+# "Authentication is required for halting the system while other users are "
+# "logged in."
+# msgstr ""
+# "Autentisering krävs för att stoppa systemet medan andra användare är "
+# "inloggade."
+#
+# #: src/login/org.freedesktop.login1.policy.in:246
+# msgid "Halt the system while an application asked to inhibit it"
+# msgstr "Stoppa systemet även då ett program hindrar det"
+#
+# #: src/login/org.freedesktop.login1.policy.in:247
+# msgid ""
+# "Authentication is required for halting the system while an application asked "
+# "to inhibit it."
+# msgstr ""
+# "Autentisering krävs för att stoppa systemet även då ett program hindrar det."
+#
+#endif // 0
+
#: ../src/login/org.freedesktop.login1.policy.in.h:39
msgid "Suspend the system"
msgstr "Försätt system i vänteläge"
@@ -439,73 +478,74 @@ msgstr "Ange ett väggmeddelande"
msgid "Authentication is required to set a wall message"
msgstr "Autentisering krävs för att ställa in ett väggmeddelande"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "Logga in i en lokal behållare"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr "Autentisering krävs för att logga in i en lokal behållare"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "Logga in på en lokal värd"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr "Autentisering krävs för att logga in på den lokala värden"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "Förvärva en kommandotolk i en lokal behållare"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr ""
# "Autentisering krävs för att förvärva en kommandotolk i en lokal behållare."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "Förvärva en kommandotolk på den lokala värden"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr ""
# "Autentisering krävs för att förvärva en kommandotolk på den lokala värden."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "Förvärva en pseudo TTY i en lokal behållare"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr ""
# "Autentisering krävs för att förvärva en pseudo TTY i en lokal behållare"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "Förvärva en pseudo TTY på den lokala värden"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr ""
# "Autentisering krävs för att förvärva en pseudo TTY på den lokala värden."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "Hantera lokala virtuella maskiner och behållare"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr ""
# "Autentisering krävs för att hantera lokala virtuella maskiner och behållare."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "Hantera lokala virtuella maskin- och behållaravbildningar"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
@@ -513,29 +553,29 @@ msgstr "Autentisering krävs för att ställa in ett väggmeddelande"
# msgstr ""
# "Autentisering krävs för att hantera lokala virtuella maskin- och "
# "behållaravbildningar."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "Ange systemtid"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "Autentisering krävs för ställa in systemtiden."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "Ange systemets tidszon"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr "Autentisering krävs för att ställa in systemets tidszon."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr ""
# "Sätt realtidsklocka (RTC) till lokal tidszon eller koordinerad universell "
# "tid (UTC)"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
@@ -543,11 +583,11 @@ msgstr "Autentisering krävs för att ställa in ett väggmeddelande"
# msgstr ""
# "Autentisering krävs för att kunna kontrollera huruvida realtidsklockan (RTC) "
# "lagrar den lokala eller koordinerade universella tiden (UTC)."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "Växla synkronisering av nätverkstid på och av"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
@@ -555,41 +595,43 @@ msgstr "Autentisering krävs för att ställa in ett väggmeddelande"
# msgstr ""
# "Autentisering krävs för att kontrollera huruvida synkronisering av "
# "nätverkstid ska vara aktiverat."
-
+#
# #: ../src/core/dbus-unit.c:457
# msgid "Authentication is required to start '$(unit)'."
-# msgstr "Autentisering krävs för att starta \"$(unit)"."
-
+# msgstr "Autentisering krävs för att starta \"$(unit)\"."
+#
# #: ../src/core/dbus-unit.c:458
# msgid "Authentication is required to stop '$(unit)'."
-# msgstr "Autentisering krävs för att stoppa \"$(unit)"."
-
+# msgstr "Autentisering krävs för att stoppa \"$(unit)\"."
+#
# #: ../src/core/dbus-unit.c:459
# msgid "Authentication is required to reload '$(unit)'."
-# msgstr "Autentisering krävs för att läsa om tillståndet för \"$(unit)"."
-
+# msgstr "Autentisering krävs för att läsa om tillståndet för \"$(unit)\"."
+#
# #: ../src/core/dbus-unit.c:460 ../src/core/dbus-unit.c:461
# msgid "Authentication is required to restart '$(unit)'."
-# msgstr "Autentisering krävs för att starta om \"$(unit)"."
-
+# msgstr "Autentisering krävs för att starta om \"$(unit)\"."
+#
# #: ../src/core/dbus-unit.c:568
# msgid "Authentication is required to kill '$(unit)'."
-# msgstr "Autentisering krävs för att döda \"$(unit)"."
-
+# msgstr "Autentisering krävs för att döda \"$(unit)\"."
+#
# #: ../src/core/dbus-unit.c:599
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
# msgstr ""
-# "Autentisering krävs för att återställa det \"fallerade" tillståndet för "
-# "\"$(unit)"."
-
+# "Autentisering krävs för att återställa det \"fallerade\" tillståndet för "
+# "\"$(unit)\"."
+#
# #: ../src/core/dbus-unit.c:632
# msgid "Authentication is required to set properties on '$(unit)'."
-# msgstr "Autentisering krävs för att ställa in egenskaper på \"$(unit)"."
-
-#~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
-#~ msgstr "Tryck Ctrl+C för att avbryta alla pågående filsystemskontroller."
+# msgstr "Autentisering krävs för att ställa in egenskaper på \"$(unit)\"."
+#
+# #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
+# #~ msgstr "Tryck Ctrl+C för att avbryta alla pågående filsystemskontroller."
+#
+# #~ msgid "Checking in progress on %d disk (%3.1f%% complete)"
+# #~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
+# #~ msgstr[0] "Kontroll pågår på %d disk (%3.1f%% klart)"
+# #~ msgstr[1] "Kontroll pågår på %d diskar (%3.1f%% klart)"
+#endif // 0
-#~ msgid "Checking in progress on %d disk (%3.1f%% complete)"
-#~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
-#~ msgstr[0] "Kontroll pågår på %d disk (%3.1f%% klart)"
-#~ msgstr[1] "Kontroll pågår på %d diskar (%3.1f%% klart)"
diff --git a/po/tr.po b/po/tr.po
index 41bb0eaea..15d374b13 100644
--- a/po/tr.po
+++ b/po/tr.po
@@ -1,18 +1,20 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# Turkish translation for systemd.
# Copyright (C) 2014-2015 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
# Necdet Yücel <necdetyucel@gmail.com>, 2014.
# Gökhan Gurbetoğlu <ggurbet@gmail.com>, 2015.
-# Muhammet Kara <muhammetk@gmail.com>, 2015, 2016.
+# Muhammet Kara <muhammetk@gmail.com>, 2015, 2016, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: systemd master\n"
"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
-"POT-Creation-Date: 2016-04-24 12:53+0000\n"
-"PO-Revision-Date: 2016-06-09 16:05+0300\n"
+"POT-Creation-Date: 2017-10-06 13:26+0000\n"
+"PO-Revision-Date: 2017-10-06 20:59+0300\n"
"Last-Translator: Muhammet Kara <muhammetk@gmail.com>\n"
-"Language-Team: Turkish <gnome-turk@gnome.org>\n"
+"Language-Team: Türkçe <gnome-turk@gnome.org>\n"
"Language: tr_TR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -20,39 +22,40 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Gtranslator 2.91.7\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "Sisteme parolayı geri gönder"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr "Sisteme parolayı geri göndermek kimlik doğrulaması gerektiriyor."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "Sistem servislerini veya diğer birimlerini yönet"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr ""
# "Sistem servislerini veya diğer birimlerini yönetmek kimlik doğrulaması "
# "gerektiriyor."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "Sistem servislerini veya birim dosyalarını yönet"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr ""
# "Sistem servislerini veya birim dosyalarını yönetmek kimlik doğrulaması "
# "gerektiriyor."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr "Sistem ve servis yöneticisi ortam değişkenlerini ayarla ya da kaldır"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
@@ -60,27 +63,27 @@ msgstr ""
# msgstr ""
# "Sistem ve servis yöneticisi ortam değişkenlerini ayarlamak ya da kaldırmak "
# "kimlik doğrulaması gerektiriyor."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "systemd durumunu yeniden yükle"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr "systemd durumunu yeniden yüklemek kimlik doğrulaması gerektiriyor."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "Makine adını ayarla"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "Yerel makine adını ayarlamak kimlik doğrulaması gerektiriyor."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "Statik makine adı ayarla"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
@@ -88,59 +91,61 @@ msgstr ""
# msgstr ""
# "Statik olarak yapılandırılmış konak makine adını ve yerel makine adını "
# "ayarlamak kimlik doğrulaması gerektiriyor."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "Makine bilgisini ayarla"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr "Yerel makine bilgisini ayarlamak kimlik doğrulaması gerektiriyor."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "Bir SM ya da kapsayıcı kalıbını içe aktar"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr ""
# "Bir SM ya da kapsayıcı kalıbını içe aktarmak için kimlik doğrulaması "
# "gereklidir"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "Bir SM ya da kapsayıcı kalıbını dışa aktar"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr ""
# "Bir SM ya da kapsayıcı kalıbını dışa aktarmak için kimlik doğrulaması "
# "gereklidir"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "Bir SM ya da kapsayıcı kalıbını indir"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr ""
# "Bir SM ya da kapsayıcı kalıbını indirmek için kimlik doğrulaması gereklidir"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "Sistem yerelini ayarla"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr "Sistem yerelini ayarlamak kimlik doğrulaması gerektiriyor."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "Sistem klavye ayarlarını ayarla"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr "Sistem klavye ayarlarını ayarlamak kimlik doğrulaması gerektiriyor."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -249,12 +254,10 @@ msgstr ""
"kimlik doğrulaması gereklidir."
#: ../src/login/org.freedesktop.login1.policy.in.h:19
-#| msgid "Allow non-logged-in users to run programs"
msgid "Allow non-logged-in user to run programs"
msgstr "Oturum açmamış kullanıcının program çalıştırmasına izin ver"
#: ../src/login/org.freedesktop.login1.policy.in.h:20
-#| msgid "Authentication is required to run programs as a non-logged-in user."
msgid "Explicit request is required to run programs as a non-logged-in user."
msgstr ""
"Oturum açmamış bir kullanıcı olarak program çalıştırmak için açıkça istekte "
@@ -355,18 +358,60 @@ msgstr ""
"doğrulaması gerektiriyor."
#: ../src/login/org.freedesktop.login1.policy.in.h:39
+#| msgid "Hibernate the system"
+msgid "Halt the system"
+msgstr "Sistemi durdur"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:40
+#| msgid "Authentication is required for hibernating the system."
+msgid "Authentication is required for halting the system."
+msgstr "Sistemi durdurmak kimlik doğrulaması gerektiriyor."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:41
+#| msgid "Hibernate the system while other users are logged in"
+msgid "Halt the system while other users are logged in"
+msgstr "Diğer kullanıcılar oturum açmışken sistemi durdur"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:42
+#| msgid ""
+#| "Authentication is required for hibernating the system while other users "
+#| "are logged in."
+msgid ""
+"Authentication is required for halting the system while other users are "
+"logged in."
+msgstr ""
+"Diğer kullanıcılar oturum açmışken sistemi durdurmak kimlik doğrulaması "
+"gerektiriyor."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:43
+#| msgid "Hibernate the system while an application asked to inhibit it"
+msgid "Halt the system while an application asked to inhibit it"
+msgstr "Bir uygulama engellenmesini isterken sistemi durdur"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:44
+#| msgid ""
+#| "Authentication is required for hibernating the system while an "
+#| "application asked to inhibit it."
+msgid ""
+"Authentication is required for halting the system while an application asked "
+"to inhibit it."
+msgstr ""
+"Bir uygulama engellenmesini isterken sistemi durdurmak kimlik doğrulaması "
+"gerektiriyor."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:45
msgid "Suspend the system"
msgstr "Sistemi askıya al"
-#: ../src/login/org.freedesktop.login1.policy.in.h:40
+#: ../src/login/org.freedesktop.login1.policy.in.h:46
msgid "Authentication is required for suspending the system."
msgstr "Sistemi askıya almak kimlik doğrulaması gerektiriyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:41
+#: ../src/login/org.freedesktop.login1.policy.in.h:47
msgid "Suspend the system while other users are logged in"
msgstr "Diğer kullanıcılar oturum açmışken sistemi askıya al"
-#: ../src/login/org.freedesktop.login1.policy.in.h:42
+#: ../src/login/org.freedesktop.login1.policy.in.h:48
msgid ""
"Authentication is required for suspending the system while other users are "
"logged in."
@@ -374,11 +419,11 @@ msgstr ""
"Diğer kullanıcılar oturum açmışken sistemi askıya almak kimlik doğrulaması "
"gerektiriyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:43
+#: ../src/login/org.freedesktop.login1.policy.in.h:49
msgid "Suspend the system while an application asked to inhibit it"
msgstr "Bir uygulama engellenmesini isterken sistemi askıya al"
-#: ../src/login/org.freedesktop.login1.policy.in.h:44
+#: ../src/login/org.freedesktop.login1.policy.in.h:50
msgid ""
"Authentication is required for suspending the system while an application "
"asked to inhibit it."
@@ -386,19 +431,19 @@ msgstr ""
"Bir uygulama engellenmesini isterken sistemi askıya almak kimlik doğrulaması "
"gerektiriyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:45
+#: ../src/login/org.freedesktop.login1.policy.in.h:51
msgid "Hibernate the system"
msgstr "Sistemi hazırda beklet"
-#: ../src/login/org.freedesktop.login1.policy.in.h:46
+#: ../src/login/org.freedesktop.login1.policy.in.h:52
msgid "Authentication is required for hibernating the system."
msgstr "Sistemi hazırda bekletmek kimlik doğrulaması gerektiriyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:47
+#: ../src/login/org.freedesktop.login1.policy.in.h:53
msgid "Hibernate the system while other users are logged in"
msgstr "Diğer kullanıcılar oturum açmışken sistemi hazırda beklet"
-#: ../src/login/org.freedesktop.login1.policy.in.h:48
+#: ../src/login/org.freedesktop.login1.policy.in.h:54
msgid ""
"Authentication is required for hibernating the system while other users are "
"logged in."
@@ -406,11 +451,11 @@ msgstr ""
"Diğer kullanıcılar oturum açmışken sistemi hazırda bekletmek kimlik "
"doğrulaması gerektiriyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:49
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
msgid "Hibernate the system while an application asked to inhibit it"
msgstr "Bir uygulama engellenmesini isterken sistemi hazırda beklet"
-#: ../src/login/org.freedesktop.login1.policy.in.h:50
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
msgid ""
"Authentication is required for hibernating the system while an application "
"asked to inhibit it."
@@ -418,33 +463,33 @@ msgstr ""
"Bir uygulama engellenmesini isterken sistemi hazırda bekletmek kimlik "
"doğrulaması gerektiriyor."
-#: ../src/login/org.freedesktop.login1.policy.in.h:51
+#: ../src/login/org.freedesktop.login1.policy.in.h:57
msgid "Manage active sessions, users and seats"
msgstr "Aktif oturumları, kullanıcıları ve yuvaları yönet"
-#: ../src/login/org.freedesktop.login1.policy.in.h:52
+#: ../src/login/org.freedesktop.login1.policy.in.h:58
msgid ""
"Authentication is required for managing active sessions, users and seats."
msgstr ""
"Aktif oturumları, kullanıcıları ve yuvaları yönetmek için kimlik doğrulaması "
"gereklidir."
-#: ../src/login/org.freedesktop.login1.policy.in.h:53
+#: ../src/login/org.freedesktop.login1.policy.in.h:59
msgid "Lock or unlock active sessions"
msgstr "Aktif oturumları kilitle ya da kilidini aç"
-#: ../src/login/org.freedesktop.login1.policy.in.h:54
+#: ../src/login/org.freedesktop.login1.policy.in.h:60
msgid "Authentication is required to lock or unlock active sessions."
msgstr ""
"Aktif oturumları kilitlemek ve bunların kilidini açmak için kimlik "
"doğrulaması gereklidir."
-#: ../src/login/org.freedesktop.login1.policy.in.h:55
+#: ../src/login/org.freedesktop.login1.policy.in.h:61
msgid "Allow indication to the firmware to boot to setup interface"
msgstr ""
"Kurulum arayüzünü önyüklemek için ürün yazılımının belirtilmesine izin ver"
-#: ../src/login/org.freedesktop.login1.policy.in.h:56
+#: ../src/login/org.freedesktop.login1.policy.in.h:62
msgid ""
"Authentication is required to indicate to the firmware to boot to setup "
"interface."
@@ -452,84 +497,85 @@ msgstr ""
"Kurulum arayüzünü önyüklemek için ürün yazılımının belirtilmesi için kimlik "
"doğrulaması gereklidir."
-#: ../src/login/org.freedesktop.login1.policy.in.h:57
+#: ../src/login/org.freedesktop.login1.policy.in.h:63
msgid "Set a wall message"
msgstr "Bir duvar mesajı ayarla"
-#: ../src/login/org.freedesktop.login1.policy.in.h:58
+#: ../src/login/org.freedesktop.login1.policy.in.h:64
msgid "Authentication is required to set a wall message"
msgstr "Duvar mesajı ayarlamak için kimlik doğrulaması gereklidir"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "Yerel kapsayıcıya giriş yap"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr "Yerel kapsayıcıda oturum açmak için kimlik doğrulaması gereklidir."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "Yerel (ana) makineye giriş yap"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr "Yerel (ana) makinede oturum açmak için kimlik doğrulaması gereklidir."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "Yerel kapsayıcıda kabuk (shell) aç"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr ""
# "Yerel kapsayıcıda kabuk (shell) açmak için kimlik doğrulaması gereklidir."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "Yerel (ana) makinede kabuk (shell) aç"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr ""
# "Yerel (ana) makinede kabuk (shell) açmak için kimlik doğrulaması gereklidir."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "Yerel kapsayıcıda sözde (pseudo) TTY al"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr ""
# "Yerel kapsayıcıda sözde (pseudo) TTY almak için kimlik doğrulaması "
# "gereklidir."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "Yerel (ana) makinede sözde (pseudo) TTY al"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr ""
# "Yerel (ana) makinede sözde (pseudo) TTY almak için kimlik doğrulaması "
# "gereklidir."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "Yerel sanal makineleri ve kapsayıcıları yönet"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr ""
# "Yerel sanal makineleri ve kapsayıcıları yönetmek için kimlik doğrulaması "
# "gereklidir."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "Yerel sanal makine ve kapsayıcı kalıplarını yönet"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
@@ -537,27 +583,27 @@ msgstr "Duvar mesajı ayarlamak için kimlik doğrulaması gereklidir"
# msgstr ""
# "Yerel sanal makineler ve kapsayıcı kalıplarını yönetmek için kimlik "
# "doğrulaması gereklidir."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "Sistem zamanını ayarla"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "Sistem zamanını ayarlamak kimlik doğrulaması gerektiriyor."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "Sistem zaman dilimini ayarla"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr "Sistem zaman dilimini ayarlamak kimlik doğrulaması gerektiriyor."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr "Gerçek zamanlı saat olarak yerel zaman dilimini veya UTC'yi ayarla"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
@@ -565,46 +611,48 @@ msgstr "Duvar mesajı ayarlamak için kimlik doğrulaması gereklidir"
# msgstr ""
# "Gerçek zamanlı saat olarak yerel zaman dilimini veya UTC'yi ayarlamak kimlik "
# "doğrulaması gerektiriyor."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "Ağ zaman eş zamanlamasını aç veya kapat"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
# "shall be enabled."
# msgstr ""
# "Ağ zaman eş zamanlamasını kontrol etmek kimlik doğrulaması gerektiriyor."
-
-# #: ../src/core/dbus-unit.c:450
+#
+# #: ../src/core/dbus-unit.c:458
# msgid "Authentication is required to start '$(unit)'."
# msgstr "'$(unit)' başlatmak için kimlik doğrulaması gereklidir."
-
-# #: ../src/core/dbus-unit.c:451
+#
+# #: ../src/core/dbus-unit.c:459
# msgid "Authentication is required to stop '$(unit)'."
# msgstr "'$(unit)' durdurmak için kimlik doğrulaması gereklidir."
-
-# #: ../src/core/dbus-unit.c:452
+#
+# #: ../src/core/dbus-unit.c:460
# msgid "Authentication is required to reload '$(unit)'."
# msgstr "'$(unit)' yeniden yüklemek için kimlik doğrulaması gereklidir."
-
-# #: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454
+#
+# #: ../src/core/dbus-unit.c:461 ../src/core/dbus-unit.c:462
# msgid "Authentication is required to restart '$(unit)'."
# msgstr "'$(unit)' yeniden başlatmak için kimlik doğrulaması gereklidir."
-
-# #: ../src/core/dbus-unit.c:560
+#
+# #: ../src/core/dbus-unit.c:569
# msgid "Authentication is required to kill '$(unit)'."
# msgstr "'$(unit)' sonlandırmak için kimlik doğrulaması gereklidir."
-
-# #: ../src/core/dbus-unit.c:590
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
+#
+# #: ../src/core/dbus-unit.c:600
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
# msgstr ""
-# "'$(unit)'in \"failed" (başarısız) durumunu sıfırlamak için kimlik "
+# "'$(unit)'in \"failed\" (başarısız) durumunu sıfırlamak için kimlik "
# "doğrulaması gereklidir."
-
-# #: ../src/core/dbus-unit.c:622
+#
+# #: ../src/core/dbus-unit.c:633
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr ""
# "'$(unit)' üzerindeki özellikleri ayarlamak için kimlik doğrulaması "
# "gereklidir."
+#endif // 0
+
diff --git a/po/uk.po b/po/uk.po
index ad37ecb08..f0602d224 100644
--- a/po/uk.po
+++ b/po/uk.po
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# Ukrainian translation for systemd.
# Copyright (C) 2014 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
@@ -19,38 +21,39 @@ msgstr ""
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Virtaal 0.7.1\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "Надіслати пароль назад у систему"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr "Засвідчення потрібно, щоб надіслати введений пароль назад у систему."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "Керувати системними службами й іншими одиницями"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr ""
# "Засвідчення потрібно, щоб керувати системними службами й іншими одиницями."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "Керувати системними службами й файлами одиниць"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr ""
# "Засвідчення потрібно, щоб керувати системними службами й файлами одиниць."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr ""
# "Встановити або забрати змінну середовища з керування службами і системою"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
@@ -58,27 +61,27 @@ msgstr ""
# msgstr ""
# "Засвідчення потрібно, щоб установити або забрати змінні середовища з "
# "керування службами і системою."
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "Перезапустити стан системи"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr "Засвідчення потрібно, щоб перезапустити стан системи."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "Встановити назву вузла"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "Засвідчення потрібне, щоб встановити назву локального вузла."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "Встановити статичну назву вузла"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
@@ -86,58 +89,60 @@ msgstr ""
# msgstr ""
# "Засвідчення потрібне, щоб вказати статично налаштовану назву локального "
# "вузла, так само й форматовану."
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "Встановити інформацію про машину"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr "Засвідчення потрібно, щоб вказати локальну інформацію про машини."
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "Імпортувати образ контейнера або віртуальної машини"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr ""
# "Засвідчення потрібно, щоб імпортувати образ контейнера або віртуальної машини"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "Експортувати образ контейнера або віртуальної машини"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr ""
# "Засвідчення потрібно, щоб експортувати образ контейнера або віртуальної "
# "машини"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "Звантажити образ контейнера або віртуальної машини"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr ""
# "Засвідчення потрібно, щоб звантажити образ контейнера або віртуальної машини"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "Вказати системну локаль"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr "Засвідчення потрібно, щоб встановити системну локаль."
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "Вказати налаштування системної клавіатури"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr "Засвідчення потрібно, щоб вказати налаштування системної клавіатури."
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -430,70 +435,71 @@ msgstr "Вказати повідомлення на стіні"
msgid "Authentication is required to set a wall message"
msgstr "Засвідчення потрібне, щоб вказати повідомлення на стіні"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "Увійти в локальний контейнер"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr "Засвідчення потрібне, щоб увійти в локальний контейнер."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "Увійти в локальний вузол"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr "Засвідчення потрібне, щоб увійти в локальний вузол."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "Перейняти оболонку в локальному контейнері"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr "Засвідчення потрібне, щоб перейняти оболонку в локальному контейнері."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "Перейняти оболонку на локальному вузлі"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr "Засвідчення потрібне, щоб перейняти оболонку на локальному вузлі."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "Перейняти псевдо TTY в локальному контейнері"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr "Засвідчення потрібне, щоб перейняти псевдо TTY в локальному контейнері."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "Перейняти псевдо TTY на локальному вузлі"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr "Засвідчення потрібне, щоб перейняти псевдо TTY на локальному вузлі."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "Керувати локальними віртуальними машинами і контейнерами"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr ""
# "Засвідчення потрібно, щоб керувати локальними віртуальними машинами і "
# "контейнерами."
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "Керувати локальними образами віртуальних машин і контейнерів"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
@@ -501,37 +507,37 @@ msgstr "Засвідчення потрібне, щоб вказати пові
# msgstr ""
# "Засвідчення потрібно, щоб керувати локальними образами віртуальних машин і "
# "контейнерів."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "Вказати системний час"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "Засвідчення потрібно, щоб вказати системний час."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "Вказати системний часовий пояс"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr "Засвідчення потрібно, щоб вказати системний часовий пояс."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr "Вкажіть RTC для локального часового поясу або UTC"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
# "UTC time."
# msgstr "Засвідчення потрібно, щоб контролювати, чи RTC зберігає час, чи UTC."
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "Увімкнути або вимкнути синхронізування через мережу"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
@@ -539,31 +545,33 @@ msgstr "Засвідчення потрібне, щоб вказати пові
# msgstr ""
# "Засвідчення потрібно, щоб контролювати, чи синхронізування часу через мережу "
# "запущено."
-
+#
# #: ../src/core/dbus-unit.c:449
# msgid "Authentication is required to start '$(unit)'."
# msgstr "Засвідчення потрібно, щоб запустити «$(unit)»."
-
+#
# #: ../src/core/dbus-unit.c:450
# msgid "Authentication is required to stop '$(unit)'."
# msgstr "Засвідчення потрібно, щоб зупинити «$(unit)»."
-
+#
# #: ../src/core/dbus-unit.c:451
# msgid "Authentication is required to reload '$(unit)'."
# msgstr "Засвідчення потрібно, щоб перезавантажити «$(unit)»."
-
+#
# #: ../src/core/dbus-unit.c:452 ../src/core/dbus-unit.c:453
# msgid "Authentication is required to restart '$(unit)'."
# msgstr "Засвідчення потрібно, щоб перезапустити «$(unit)»."
-
+#
# #: ../src/core/dbus-unit.c:556
# msgid "Authentication is required to kill '$(unit)'."
# msgstr "Засвідчення потрібне, щоб вбити «$(unit)»."
-
+#
# #: ../src/core/dbus-unit.c:586
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
# msgstr "Засвідчення потрібне, щоб скинути «пошкоджений» стан з «$(unit)»."
-
+#
# #: ../src/core/dbus-unit.c:618
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr "Засвідчення потрібно, щоб вказати властивості на «$(unit)»."
+#endif // 0
+
diff --git a/po/zh_CN.po b/po/zh_CN.po
index bfe76a2f5..1984158f3 100644
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# Simplified Chinese translation for systemd.
# Copyright (C) 2015 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
@@ -20,118 +22,121 @@ msgstr ""
"X-Generator: Poedit 1.8.7.1\n"
"Plural-Forms: nplurals=1; plural=0;\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "将密码发回系统"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr "将输入的密码发回系统需要认证。"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "管理系统服务或其它单元"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr "管理系统服务或其它单元需要认证。"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "管理系统服务或单元文件"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr "管理系统服务或单元文件需要认证。"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr "设置或清除系统及服务管理器的环境变量"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
# "environment variables."
# msgstr "设置或清除系统及服务管理器的环境变量需要认证。"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "重新载入 systemd 状态"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr "重新载入 systemd 状态需要认证。"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "设置主机名"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "设置本地主机名需要认证。"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "设置静态主机名"
-
-# For pretty hostname, the zh_CN/zh_TW translation should be discussed again.
-#
-# There were some discussions, like https://lists.fedoraprojects.org/pipermail/trans-zh_cn/2012-December/001347.html
+#
+# # For pretty hostname, the zh_CN/zh_TW translation should be discussed again.
+# #
+# # There were some discussions, like https://lists.fedoraprojects.org/pipermail/trans-zh_cn/2012-December/001347.html
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# #, fuzzy
# msgid ""
# "Authentication is required to set the statically configured local host name, "
# "as well as the pretty host name."
# msgstr "设置静态本地主机名或美观主机名需要认证。"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "设置机器信息"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr "设置本地机器信息需要认证。"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "导入虚拟机或容器镜像"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr "导入虚拟机或容器镜像需要认证"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "导出虚拟机或容器镜像"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr "导出虚拟机或容器镜像需要认证"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "下载虚拟机或容器镜像"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr "下载虚拟机或容器镜像需要认证。"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "设置系统区域和语言"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr "设置系统区域和语言需要认证。"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "设置系统键盘"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr "设置系统键盘需要认证。"
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -391,134 +396,137 @@ msgstr "设置 wall 消息"
msgid "Authentication is required to set a wall message"
msgstr "设置 wall 消息需要认证。"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "登入本地容器"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr "登录一个本地容器需要认证。"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "登入本地主机"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr "登入本地主机需要认证。"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "在本地容器中获取一个 shell"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr "在本地容器中获取 shell 需要认证。"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "在本地主机中获取一个 shell"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr "在本地主机中获取 shell 需要认证。"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "在本地容器中获取一个假 TTY"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr "在本地容器中获取假 TTY 需要认证。"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "在本地主机中获取一个假 TTY"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr "在本地主机中获取假 TTY 需要认证。"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "管理本地虚拟机和容器"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr "管理本地虚拟机和容器需要认证。"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "管理本地虚拟机和容器的镜像"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
# "images."
# msgstr "管理本地的虚拟机和容器镜像需要认证。"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "设置系统时间"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "设置系统时间需要认证。"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "设置系统时区"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr "设置系统时区需要认证。"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr "设置硬件时钟使用本地时间或 UTC"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
# "UTC time."
# msgstr "设置硬件时钟使用本地时间或 UTC 需要认证。"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "打开或关闭网络时间同步"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
# "shall be enabled."
# msgstr "打开或关闭网络时间同步需要认证。"
-
+#
# #: ../src/core/dbus-unit.c:430
# msgid "Authentication is required to start '$(unit)'."
# msgstr "启动“$(unit)”需要认证。"
-
+#
# #: ../src/core/dbus-unit.c:431
# msgid "Authentication is required to stop '$(unit)'."
# msgstr "停止“$(unit)”需要认证。"
-
+#
# #: ../src/core/dbus-unit.c:432
# msgid "Authentication is required to reload '$(unit)'."
# msgstr "重新载入“$(unit)”需要认证。"
-
+#
# #: ../src/core/dbus-unit.c:433 ../src/core/dbus-unit.c:434
# msgid "Authentication is required to restart '$(unit)'."
# msgstr "重新启动“$(unit)”需要认证。"
-
+#
# #: ../src/core/dbus-unit.c:537
# msgid "Authentication is required to kill '$(unit)'."
# msgstr "杀死“$(unit)”需要认证。"
-
+#
# #: ../src/core/dbus-unit.c:567
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
-# msgstr "重置“$(unit)”的失败(\"failed")状态需要认证。"
-
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+# msgstr "重置“$(unit)”的失败(\"failed\")状态需要认证。"
+#
# #: ../src/core/dbus-unit.c:599
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr "设置“$(unit)”的属性需要认证。"
+#endif // 0
+
diff --git a/po/zh_TW.po b/po/zh_TW.po
index 395acd5d8..3409e2de8 100644
--- a/po/zh_TW.po
+++ b/po/zh_TW.po
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# Traditional Chinese translation for systemd.
# Copyright (C) 2015 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
@@ -17,114 +19,117 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Lokalize 2.0\n"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
# msgid "Send passphrase back to system"
# msgstr "傳回密碼片語到系統"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
# msgid ""
# "Authentication is required to send the entered passphrase back to the system."
# msgstr "傳回已輸入的密碼片語到系統需要驗證。"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
# msgid "Manage system services or other units"
# msgstr "管理系統服務或其他單位"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
# msgid "Authentication is required to manage system services or other units."
# msgstr "管理系統服務或其他單位需要驗證。"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
# msgid "Manage system service or unit files"
# msgstr "管理系統服務或單位檔案"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
# msgid "Authentication is required to manage system service or unit files."
# msgstr "管理系統服務或單位檔案需要驗證。"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
# msgid "Set or unset system and service manager environment variables"
# msgstr "設定或取消設定系統及服務管理員環境變量"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
# msgid ""
# "Authentication is required to set or unset system and service manager "
# "environment variables."
# msgstr "設定或取消設定系統及服務管理員環境變量時需要驗證"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
# msgid "Reload the systemd state"
# msgstr "重新載入 systemd 狀態"
-
+#
# #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
# msgid "Authentication is required to reload the systemd state."
# msgstr "重新載入 systemd 狀態需要驗證。"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
# msgid "Set host name"
# msgstr "設定主機名稱"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
# msgid "Authentication is required to set the local host name."
# msgstr "設定主機名稱需要驗證。"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
# msgid "Set static host name"
# msgstr "設定靜態主機名稱"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
# msgid ""
# "Authentication is required to set the statically configured local host name, "
# "as well as the pretty host name."
# msgstr "設定靜態設定的本機主機名稱時需要驗證,同時也需要漂亮的主機名稱"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
# msgid "Set machine information"
# msgstr "設定機器資訊"
-
+#
# #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
# msgid "Authentication is required to set local machine information."
# msgstr "設定機器資訊需要驗證"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:1
# msgid "Import a VM or container image"
# msgstr "匯入虛擬機器或容器映像"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:2
# msgid "Authentication is required to import a VM or container image"
# msgstr "匯入虛擬機器或容器映像需要驗證"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:3
# msgid "Export a VM or container image"
# msgstr "匯出虛擬機器或容器映像"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:4
# msgid "Authentication is required to export a VM or container image"
# msgstr "匯出虛擬機器或容器映像需要驗證"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:5
# msgid "Download a VM or container image"
# msgstr "下載虛擬機器或容器映像"
-
+#
# #: ../src/import/org.freedesktop.import1.policy.in.h:6
# msgid "Authentication is required to download a VM or container image"
# msgstr "下載虛擬機器或容器映像需要驗證"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
# msgid "Set system locale"
# msgstr "設定系統語系"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
# msgid "Authentication is required to set the system locale."
# msgstr "設定系統語系需要驗證。"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
# msgid "Set system keyboard settings"
# msgstr "設定系統鍵盤設定"
-
+#
# #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
# msgid "Authentication is required to set the system keyboard settings."
# msgstr "設定系統鍵盤設定需要驗證。"
+#
+#endif // 0
#: ../src/login/org.freedesktop.login1.policy.in.h:1
msgid "Allow applications to inhibit system shutdown"
@@ -381,135 +386,138 @@ msgstr "設定 wall 訊息"
msgid "Authentication is required to set a wall message"
msgstr "設定 wall 訊息需要驗證。"
+#if 0 /// UNNEEDED by elgoind
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
# msgid "Log into a local container"
# msgstr "登入到本機容器"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
# msgid "Authentication is required to log into a local container."
# msgstr "登入到本機容器需要驗證。"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
# msgid "Log into the local host"
# msgstr "登入到本機主機"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
# msgid "Authentication is required to log into the local host."
# msgstr "登入到本機主機需要驗證。"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
# msgid "Acquire a shell in a local container"
# msgstr "在本機容器中取得一個 shell"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
# msgid "Authentication is required to acquire a shell in a local container."
# msgstr "在本機容器中取得一個 shell 需要驗證。"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
# msgid "Acquire a shell on the local host"
# msgstr "在本機主機中取得一個 shell"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
# msgid "Authentication is required to acquire a shell on the local host."
# msgstr "在本機主機中取得一個 shell 需要驗證。"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
# msgid "Acquire a pseudo TTY in a local container"
# msgstr "取得在本機容器中的偽 TTY"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
# msgid ""
# "Authentication is required to acquire a pseudo TTY in a local container."
# msgstr "取得在本機容器中的偽 TTY 需要驗證。"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
# msgid "Acquire a pseudo TTY on the local host"
# msgstr "取得在本機主機中的偽 TTY"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
# msgid "Authentication is required to acquire a pseudo TTY on the local host."
# msgstr "取得在本機主機中的偽 TTY 需要驗證。"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
# msgid "Manage local virtual machines and containers"
# msgstr "管理本機虛擬機器及容器"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
# msgid ""
# "Authentication is required to manage local virtual machines and containers."
# msgstr "管理本機虛擬機器及容器需要驗證。"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
# msgid "Manage local virtual machine and container images"
# msgstr "管理本機虛擬機器及容器映像"
-
+#
# #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
# msgid ""
# "Authentication is required to manage local virtual machine and container "
# "images."
# msgstr "管理本機虛擬機器及容器映像需要驗證。"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
# msgid "Set system time"
# msgstr "設定系統時間"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
# msgid "Authentication is required to set the system time."
# msgstr "設定系統時間需要驗證。"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
# msgid "Set system timezone"
# msgstr "設定系統時區"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
# msgid "Authentication is required to set the system timezone."
# msgstr "設定系統時區需要驗證。"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
# msgid "Set RTC to local timezone or UTC"
# msgstr "將 RTC 設定為本地時區或 UTC"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
# msgid ""
# "Authentication is required to control whether the RTC stores the local or "
# "UTC time."
# msgstr "控制 RTC 儲存本地或 UTC 時間需要驗證。"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
# msgid "Turn network time synchronization on or off"
# msgstr "打開或關閉網路時間同步"
-
+#
# #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
# msgid ""
# "Authentication is required to control whether network time synchronization "
# "shall be enabled."
# msgstr "控制網路時間同步是否啟用需要驗證。"
-
+#
# #: ../src/core/dbus-unit.c:428
# msgid "Authentication is required to start '$(unit)'."
# msgstr "啟動 '$(unit)' 需要驗證。"
-
+#
# #: ../src/core/dbus-unit.c:429
# msgid "Authentication is required to stop '$(unit)'."
# msgstr "停止 '$(unit)' 需要驗證。"
-
+#
# #: ../src/core/dbus-unit.c:430
# msgid "Authentication is required to reload '$(unit)'."
# msgstr "重新載入 '$(unit)' 需要驗證。"
-
+#
# #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
# msgid "Authentication is required to restart '$(unit)'."
# msgstr "重新啟動 '$(unit)' 需要驗證。"
-
+#
# #: ../src/core/dbus-unit.c:535
# msgid "Authentication is required to kill '$(unit)'."
# msgstr "砍除 '$(unit)' 需要驗證。"
-
+#
# #: ../src/core/dbus-unit.c:565
-# msgid "Authentication is required to reset the \"failed" state of '$(unit)'."
+# msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
# msgstr "重置 '$(unit)' 的「失敗」狀態需要驗證。"
-
+#
# #: ../src/core/dbus-unit.c:597
# msgid "Authentication is required to set properties on '$(unit)'."
# msgstr "在 '$(unit)' 上設定屬性需要驗證。"
+#
+#endif // 0
diff --git a/pwx b/pwx
new file mode 160000
+Subproject a7a0ef894d5b221eeb675cea4f69a7d66922168
diff --git a/shell-completion/Makefile b/shell-completion/Makefile
deleted file mode 120000
index bd1047548..000000000
--- a/shell-completion/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../src/Makefile \ No newline at end of file
diff --git a/shell-completion/bash/.gitignore b/shell-completion/bash/.gitignore
deleted file mode 100644
index 016e09d1e..000000000
--- a/shell-completion/bash/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/systemctl
diff --git a/shell-completion/bash/Makefile b/shell-completion/bash/Makefile
deleted file mode 120000
index d0b0e8e00..000000000
--- a/shell-completion/bash/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/shell-completion/bash/loginctl b/shell-completion/bash/loginctl
index 776eca4e6..1f5b46620 100644
--- a/shell-completion/bash/loginctl
+++ b/shell-completion/bash/loginctl
@@ -1,8 +1,9 @@
# loginctl(1) completion -*- shell-script -*-
+# SPDX-License-Identifier: LGPL-2.1+
#
# This file is part of systemd.
#
-# Copyright 2010 Ran Benita
+# Copyright © 2010 Ran Benita
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
@@ -33,10 +34,11 @@ _loginctl () {
local i verb comps
local -A OPTS=(
- [STANDALONE]='--all -a --help -h --no-pager --privileged -P --version
- --no-legend --no-ask-password -l --full'
- [ARG]='--host -H --kill-who --property -p --signal -s --machine'
- )
+ [STANDALONE]='--all -a --help -h --no-pager --version
+ --no-legend --no-ask-password -l --full --value'
+ [ARG]='--host -H --kill-who --property -p --signal -s -M --machine
+ -n --lines -o --output'
+ )
if __contains_word "$prev" ${OPTS[ARG]}; then
case $prev in
@@ -68,7 +70,7 @@ _loginctl () {
[SESSIONS]='session-status show-session activate lock-session unlock-session terminate-session kill-session'
[USERS]='user-status show-user enable-linger disable-linger terminate-user kill-user'
[SEATS]='seat-status show-seat terminate-seat'
- [STANDALONE]='list-sessions list-users list-seats flush-devices'
+ [STANDALONE]='list-sessions lock-sessions unlock-sessions list-users list-seats flush-devices'
[ATTACH]='attach'
)
diff --git a/shell-completion/bash/meson.build b/shell-completion/bash/meson.build
new file mode 100644
index 000000000..fdc77cc4a
--- /dev/null
+++ b/shell-completion/bash/meson.build
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: LGPL-2.1+
+
+bashcompletiondir = get_option('bashcompletiondir')
+if bashcompletiondir == ''
+ bash_completion = dependency('bash-completion', required : false)
+ if bash_completion.found()
+ bashcompletiondir = bash_completion.get_pkgconfig_variable('completionsdir')
+ else
+ bashcompletiondir = join_paths(datadir, 'bash-completion/completions')
+ endif
+
+ message('bash completions: @0@'.format(bashcompletiondir))
+endif
+
+if bashcompletiondir != 'no'
+#if 0 /// elogind has a *very* short list for this...
+# bash_systemctl = configure_file(
+# input : 'systemctl.in',
+# output : 'systemctl',
+# configuration : substs)
+#
+# items = [['busctl', ''],
+# ['journalctl', ''],
+# ['systemd-analyze', ''],
+# ['systemd-cat', ''],
+# ['systemd-cgls', ''],
+# ['systemd-cgtop', ''],
+# ['systemd-delta', ''],
+# ['systemd-detect-virt', ''],
+# ['systemd-nspawn', ''],
+# ['systemd-path', ''],
+# ['systemd-run', ''],
+# ['udevadm', ''],
+# ['kernel-install', ''],
+# [bash_systemctl, ''],
+# ['bootctl', 'ENABLE_EFI'],
+# ['coredumpctl', 'ENABLE_COREDUMP'],
+# ['hostnamectl', 'ENABLE_HOSTNAMED'],
+# ['localectl', 'ENABLE_LOCALED'],
+# ['loginctl', 'ENABLE_LOGIND'],
+# ['machinectl', 'ENABLE_MACHINED'],
+# ['networkctl', 'ENABLE_NETWORKD'],
+# ['portablectl', 'ENABLE_PORTABLED'],
+# ['resolvectl', 'ENABLE_RESOLVE'],
+# ['systemd-resolve', 'ENABLE_RESOLVE'],
+# ['timedatectl', 'ENABLE_TIMEDATED'],
+#else
+ items = [['loginctl', ''],
+#endif // 0
+ ]
+
+ foreach item : items
+ if item[1] == '' or conf.get(item[1]) == 1
+ install_data(item[0],
+ install_dir : bashcompletiondir)
+ endif
+ endforeach
+endif
diff --git a/shell-completion/bash/resolvectl b/shell-completion/bash/resolvectl
new file mode 100644
index 000000000..367f9c7c8
--- /dev/null
+++ b/shell-completion/bash/resolvectl
@@ -0,0 +1,182 @@
+# resolvectl(1) completion -*- shell-script -*-
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# This file is part of elogind.
+#
+#
+# elogind is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# elogind is distributed in the hope that 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 Lesser General Public License
+# along with elogind; If not, see <http://www.gnu.org/licenses/>.
+
+__contains_word () {
+ local w word=$1; shift
+ for w in "$@"; do
+ [[ $w = "$word" ]] && return
+ done
+}
+
+__get_interfaces(){
+ { cd /sys/class/net && echo *; } | \
+ while read -d' ' -r name; do
+ [[ "$name" != "lo" ]] && echo "$name"
+ done
+}
+
+_resolvectl() {
+ local i comps verb name
+ local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
+ local -A OPTS=(
+ [STANDALONE]='-h --help --version --no-pager -4 -6
+ --service-address=no --service-txt=no
+ --cname=no --search=no --legend=no'
+ [ARG]='-i --interface -p --protocol -t --type -c --class --raw'
+ )
+ local -A VERBS=(
+ [DOMAIN]='query service openpgp'
+ [FAMILY]='tlsa'
+ [STATUS]='status'
+ [LINK]='revert dns domain nta'
+ [RESOLVE]='llmnr mdns'
+ [DNSSEC]='dnssec'
+ [DNSOVERTLS]='dnsovertls'
+ [STANDALONE]='statistics reset-statistics flush-caches reset-server-features'
+ )
+ local -A ARGS=(
+ [FAMILY]='tcp udp sctp'
+ [RESOLVE]='yes no resolve'
+ [DNSSEC]='yes no allow-downgrade'
+ [DNSOVERTLS]='no opportunistic'
+ )
+ local interfaces=$( __get_interfaces )
+
+ if __contains_word "$prev" ${OPTS[ARG]}; then
+ case $prev in
+ --interface|-i)
+ comps="$interfaces"
+ ;;
+ --protocol|-p|--type|-t|--class|-c)
+ comps=$( resolvectl --legend=no "$prev" help; echo help )
+ ;;
+ --raw)
+ comps="payload packet"
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
+ return 0
+ fi
+
+ if [[ "$cur" = -* ]]; then
+ COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") )
+ return 0
+ fi
+
+ for ((i=0; i < COMP_CWORD; i++)); do
+ if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} &&
+ ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then
+ verb=${COMP_WORDS[i]}
+ break
+ fi
+ done
+
+ if [[ -z $verb ]]; then
+ comps="${VERBS[*]}"
+
+ elif __contains_word "$verb" ${VERBS[STANDALONE]} ${VERBS[DOMAIN]}; then
+ comps=''
+
+ elif __contains_word "$verb" ${VERBS[STATUS]}; then
+ comps="$interfaces"
+
+ elif __contains_word "$verb" ${VERBS[FAMILY]}; then
+ for ((i++; i < COMP_CWORD; i++)); do
+ if __contains_word "${COMP_WORDS[i]}" ${ARGS[FAMILY]} &&
+ ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then
+ name=${COMP_WORDS[i]}
+ break;
+ fi
+ done
+ if [[ -z $name ]]; then
+ comps=${ARGS[FAMILY]}
+ else
+ comps=""
+ fi
+
+ elif __contains_word "$verb" ${VERBS[LINK]} ${VERBS[RESOLVE]} ${VERBS[DNSSEC]} ${VERBS[DNSOVERTLS]}; then
+ for ((i++; i < COMP_CWORD; i++)); do
+ if __contains_word "${COMP_WORDS[i]}" $interfaces &&
+ ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then
+ name=${COMP_WORDS[i]}
+ break;
+ fi
+ done
+
+ if [[ -z $name ]]; then
+ comps="$interfaces"
+
+ elif __contains_word "$verb" ${VERBS[RESOLVE]}; then
+ name=
+ for ((i++; i < COMP_CWORD; i++)); do
+ if __contains_word "${COMP_WORDS[i]}" ${ARGS[RESOLVE]} &&
+ ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then
+ name=${COMP_WORDS[i]}
+ break;
+ fi
+ done
+
+ if [[ -z $name ]]; then
+ comps=${ARGS[RESOLVE]}
+ else
+ comps=''
+ fi
+
+ elif __contains_word "$verb" ${VERBS[DNSSEC]}; then
+ name=
+ for ((i++; i < COMP_CWORD; i++)); do
+ if __contains_word "${COMP_WORDS[i]}" ${ARGS[DNSSEC]} &&
+ ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then
+ name=${COMP_WORDS[i]}
+ break;
+ fi
+ done
+
+ if [[ -z $name ]]; then
+ comps=${ARGS[DNSSEC]}
+ else
+ comps=''
+ fi
+
+ elif __contains_word "$verb" ${VERBS[DNSOVERTLS]}; then
+ name=
+ for ((i++; i < COMP_CWORD; i++)); do
+ if __contains_word "${COMP_WORDS[i]}" ${ARGS[DNSOVERTLS]} &&
+ ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then
+ name=${COMP_WORDS[i]}
+ break;
+ fi
+ done
+
+ if [[ -z $name ]]; then
+ comps=${ARGS[DNSOVERTLS]}
+ else
+ comps=''
+ fi
+
+ else
+ comps=''
+ fi
+ fi
+
+ COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
+ return 0
+}
+
+complete -F _resolvectl resolvectl
diff --git a/shell-completion/zsh/.gitignore b/shell-completion/zsh/.gitignore
deleted file mode 100644
index 75f13ad6d..000000000
--- a/shell-completion/zsh/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/_systemctl
diff --git a/shell-completion/zsh/Makefile b/shell-completion/zsh/Makefile
deleted file mode 120000
index d0b0e8e00..000000000
--- a/shell-completion/zsh/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/shell-completion/zsh/_elogind-inhibit b/shell-completion/zsh/_elogind-inhibit
index 1b3247b2c..764713e28 100644
--- a/shell-completion/zsh/_elogind-inhibit
+++ b/shell-completion/zsh/_elogind-inhibit
@@ -1,4 +1,5 @@
#compdef systemd-inhibit
+# SPDX-License-Identifier: LGPL-2.1+
_systemd_inhibit_command(){
if (( CURRENT == 1 )); then
diff --git a/shell-completion/zsh/_loginctl b/shell-completion/zsh/_loginctl
index 6f6ff6e31..03dde9a89 100644
--- a/shell-completion/zsh/_loginctl
+++ b/shell-completion/zsh/_loginctl
@@ -1,4 +1,5 @@
#compdef loginctl
+# SPDX-License-Identifier: LGPL-2.1+
_loginctl_all_sessions() {
local session description
diff --git a/shell-completion/zsh/meson.build b/shell-completion/zsh/meson.build
new file mode 100644
index 000000000..806ea8850
--- /dev/null
+++ b/shell-completion/zsh/meson.build
@@ -0,0 +1,53 @@
+# SPDX-License-Identifier: LGPL-2.1+
+
+zshcompletiondir = get_option('zshcompletiondir')
+if zshcompletiondir == ''
+ zshcompletiondir = join_paths(datadir, 'zsh/site-functions')
+
+ message('zsh completions: @0@'.format(zshcompletiondir))
+endif
+
+if zshcompletiondir != 'no'
+#if 0 /// elogind has a *very* short list for this...
+# zsh_systemctl = configure_file(
+# input : '_systemctl.in',
+# output : '_systemctl',
+# configuration : substs)
+#
+# items = [['_busctl', ''],
+# ['_journalctl', ''],
+# ['_systemd-analyze', ''],
+# ['_systemd-delta', ''],
+# ['_systemd-nspawn', ''],
+# ['_systemd', ''],
+# ['_systemd-run', ''],
+# ['_udevadm', ''],
+# ['_kernel-install', ''],
+# ['_sd_hosts_or_user_at_host', ''],
+# ['_sd_outputmodes', ''],
+# ['_sd_unit_files', ''],
+# ['_sd_machines', ''],
+# [zsh_systemctl, ''],
+# ['_bootctl', 'ENABLE_EFI'],
+# ['_coredumpctl', 'ENABLE_COREDUMP'],
+# ['_hostnamectl', 'ENABLE_HOSTNAMED'],
+# ['_localectl', 'ENABLE_LOCALED'],
+# ['_loginctl', 'ENABLE_LOGIND'],
+# ['_machinectl', 'ENABLE_MACHINED'],
+# ['_networkctl', 'ENABLE_NETWORKD'],
+# ['_systemd-inhibit', 'ENABLE_LOGIND'],
+# ['_systemd-resolve', 'ENABLE_RESOLVE'],
+# ['_systemd-tmpfiles', 'ENABLE_TMPFILES'],
+# ['_timedatectl', 'ENABLE_TIMEDATED'],
+#else
+ items = [['_loginctl', ''],
+#endif // 0
+ ]
+
+ foreach item : items
+ if item[1] == '' or conf.get(item[1]) == 1
+ install_data(item[0],
+ install_dir : zshcompletiondir)
+ endif
+ endforeach
+endif
diff --git a/src/.gitignore b/src/.gitignore
deleted file mode 100644
index ab44b03e0..000000000
--- a/src/.gitignore
+++ /dev/null
@@ -1,76 +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
-*.gcno
-*.gcda
-
-# directories not needed by elogind
-/initctl
-/libudev
-/cgls
-/rfkill
-/resolve
-/firstboot
-/path
-/tmpfiles
-/quotacheck
-/system-update-generator
-/debug-generator
-/sysctl
-/sysv-generator
-/backlight
-/coredump
-/modules-load
-/machine-id-setup
-/getty-generator
-/ac-power
-/gpt-auto-generator
-/journal
-/socket-proxy
-/cgtop
-/locale
-/cryptsetup
-/run
-/binfmt
-/fstab-generator
-/detect-virt
-/timesync
-/journal-remote
-/nss-mymachines
-/nss-resolve
-/hibernate-resume
-/stdio-bridge
-/hostname
-/user-sessions
-/nss-myhostname
-/random-seed
-/vconsole
-/analyze
-/sysusers
-/notify
-/kernel-install
-/rc-local-generator
-/nspawn
-/boot
-/import
-/libsystemd
-/escape
-/systemctl
-/hwdb
-/network
-/udev
-/tty-ask-password-agent
-/remount-fs
-/ask-password
-/timedate
-/delta
-/dbus1-generator
-/fsck
-/machine
-/update-done
-/libsystemd-network
-/reply-password
-/activate
diff --git a/src/Makefile b/src/Makefile
deleted file mode 100644
index 9d0750519..000000000
--- 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/basic/.gitignore b/src/basic/.gitignore
deleted file mode 100644
index e22411e48..000000000
--- a/src/basic/.gitignore
+++ /dev/null
@@ -1,16 +0,0 @@
-/cap-from-name.gperf
-/cap-from-name.h
-/cap-list.txt
-/cap-to-name.h
-/errno-from-name.gperf
-/errno-from-name.h
-/errno-list.txt
-/errno-to-name.h
-/af-from-name.gperf
-/af-from-name.h
-/af-list.txt
-/af-to-name.h
-/arphrd-from-name.gperf
-/arphrd-from-name.h
-/arphrd-list.txt
-/arphrd-to-name.h
diff --git a/src/basic/Makefile b/src/basic/Makefile
deleted file mode 120000
index d0b0e8e00..000000000
--- a/src/basic/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/basic/alloc-util.c b/src/basic/alloc-util.c
index b540dcddf..405445eac 100644
--- a/src/basic/alloc-util.c
+++ b/src/basic/alloc-util.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <stdint.h>
#include <string.h>
@@ -25,16 +8,31 @@
#include "util.h"
void* memdup(const void *p, size_t l) {
- void *r;
+ void *ret;
- assert(p);
+ assert(l == 0 || p);
+
+ ret = malloc(l);
+ if (!ret)
+ return NULL;
+
+ memcpy(ret, p, l);
+ return ret;
+}
+
+void* memdup_suffix0(const void *p, size_t l) {
+ void *ret;
+
+ assert(l == 0 || p);
+
+ /* The same as memdup() but place a safety NUL byte after the allocated memory */
- r = malloc(l);
- if (!r)
+ ret = malloc(l + 1);
+ if (!ret)
return NULL;
- memcpy(r, p, l);
- return r;
+ *((uint8_t*) mempcpy(ret, p, l)) = 0;
+ return ret;
}
void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
diff --git a/src/basic/alloc-util.h b/src/basic/alloc-util.h
index a44dd473c..ebe42889e 100644
--- a/src/basic/alloc-util.h
+++ b/src/basic/alloc-util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <alloca.h>
#include <stddef.h>
#include <stdlib.h>
@@ -30,12 +12,22 @@
#define new0(t, n) ((t*) calloc((n), sizeof(t)))
-#define newa(t, n) ((t*) alloca(sizeof(t)*(n)))
+#define newa(t, n) \
+ ({ \
+ assert(!size_multiply_overflow(sizeof(t), n)); \
+ (t*) alloca(sizeof(t)*(n)); \
+ })
-#define newa0(t, n) ((t*) alloca0(sizeof(t)*(n)))
+#define newa0(t, n) \
+ ({ \
+ assert(!size_multiply_overflow(sizeof(t), n)); \
+ (t*) alloca0(sizeof(t)*(n)); \
+ })
#define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n)))
+#define newdup_suffix0(t, p, n) ((t*) memdup_suffix0_multiply(p, sizeof(t), (n)))
+
#define malloc0(n) (calloc(1, (n)))
static inline void *mfree(void *memory) {
@@ -52,6 +44,7 @@ static inline void *mfree(void *memory) {
})
void* memdup(const void *p, size_t l) _alloc_(2);
+void* memdup_suffix0(const void *p, size_t l) _alloc_(2);
static inline void freep(void *p) {
free(*(void**) p);
@@ -70,12 +63,14 @@ _malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t size, size_t
return malloc(size * need);
}
-_alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t size, size_t need) {
+#if !HAVE_REALLOCARRAY
+_alloc_(2, 3) static inline void *reallocarray(void *p, size_t need, size_t size) {
if (size_multiply_overflow(size, need))
return NULL;
return realloc(p, size * need);
}
+#endif
_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t size, size_t need) {
if (size_multiply_overflow(size, need))
@@ -84,6 +79,13 @@ _alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t size, si
return memdup(p, size * need);
}
+_alloc_(2, 3) static inline void *memdup_suffix0_multiply(const void *p, size_t size, size_t need) {
+ if (size_multiply_overflow(size, need))
+ return NULL;
+
+ return memdup_suffix0(p, size * need);
+}
+
void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size);
void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size);
@@ -117,3 +119,12 @@ void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size);
_new_ = alloca_align(_size_, (align)); \
(void*)memset(_new_, 0, _size_); \
})
+
+/* Takes inspiration from Rusts's Option::take() method: reads and returns a pointer, but at the same time resets it to
+ * NULL. See: https://doc.rust-lang.org/std/option/enum.Option.html#method.take */
+#define TAKE_PTR(ptr) \
+ ({ \
+ typeof(ptr) _ptr_ = (ptr); \
+ (ptr) = NULL; \
+ _ptr_; \
+ })
diff --git a/src/basic/audit-util.c b/src/basic/audit-util.c
index 2b5578394..00bbe2296 100644
--- a/src/basic/audit-util.c
+++ b/src/basic/audit-util.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <linux/netlink.h>
@@ -54,7 +37,7 @@ int audit_session_from_pid(pid_t pid, uint32_t *id) {
if (r < 0)
return r;
- if (u == AUDIT_SESSION_INVALID || u <= 0)
+ if (!audit_session_is_valid(u))
return -ENODATA;
*id = u;
@@ -81,7 +64,7 @@ int audit_loginuid_from_pid(pid_t pid, uid_t *uid) {
if (r < 0)
return r;
- *uid = (uid_t) u;
+ *uid = u;
return 0;
}
@@ -95,10 +78,9 @@ bool use_audit(void) {
fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_AUDIT);
if (fd < 0) {
cached_use = !IN_SET(errno, EAFNOSUPPORT, EPROTONOSUPPORT, EPERM);
- if (errno == EPERM)
- log_debug_errno(errno, "Audit access prohibited, won't talk to audit");
- }
- else {
+ if (!cached_use)
+ log_debug_errno(errno, "Won't talk to audit: %m");
+ } else {
cached_use = true;
safe_close(fd);
}
diff --git a/src/basic/audit-util.h b/src/basic/audit-util.h
index b16ca585b..e57a38425 100644
--- a/src/basic/audit-util.h
+++ b/src/basic/audit-util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 <stdint.h>
#include <sys/types.h>
@@ -31,3 +13,7 @@ int audit_loginuid_from_pid(pid_t pid, uid_t *uid);
#if 0 /// UNNEEDED by elogind
bool use_audit(void);
#endif // 0
+
+static inline bool audit_session_is_valid(uint32_t id) {
+ return id > 0 && id != AUDIT_SESSION_INVALID;
+}
diff --git a/src/basic/build.h b/src/basic/build.h
index 6329a8fc3..44d61e392 100644
--- a/src/basic/build.h
+++ b/src/basic/build.h
@@ -1,60 +1,173 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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
+#if HAVE_PAM
#define _PAM_FEATURE_ "+PAM"
#else
#define _PAM_FEATURE_ "-PAM"
#endif
-#ifdef HAVE_SELINUX
+#if HAVE_AUDIT
+#define _AUDIT_FEATURE_ "+AUDIT"
+#else
+#define _AUDIT_FEATURE_ "-AUDIT"
+#endif
+
+#if HAVE_SELINUX
#define _SELINUX_FEATURE_ "+SELINUX"
#else
#define _SELINUX_FEATURE_ "-SELINUX"
#endif
-#ifdef HAVE_SMACK
+#if 0 /// UNSUPPORTED by elogind
+#if HAVE_APPARMOR
+#define _APPARMOR_FEATURE_ "+APPARMOR"
+#else
+#define _APPARMOR_FEATURE_ "-APPARMOR"
+#endif
+
+#if ENABLE_IMA
+#define _IMA_FEATURE_ "+IMA"
+#else
+#define _IMA_FEATURE_ "-IMA"
+#endif
+#endif // 0
+
+#if ENABLE_SMACK
#define _SMACK_FEATURE_ "+SMACK"
#else
#define _SMACK_FEATURE_ "-SMACK"
#endif
-#ifdef HAVE_UTMP
+#if 0 /// UNSUPPORTED by elogind
+#if HAVE_SYSV_COMPAT
+#define _SYSVINIT_FEATURE_ "+SYSVINIT"
+#else
+#define _SYSVINIT_FEATURE_ "-SYSVINIT"
+#endif
+#endif // 0
+
+#if ENABLE_UTMP
#define _UTMP_FEATURE_ "+UTMP"
#else
#define _UTMP_FEATURE_ "-UTMP"
#endif
-#ifdef HAVE_ACL
+#if 0 /// UNSUPPORTED by elogind
+#if HAVE_LIBCRYPTSETUP
+#define _LIBCRYPTSETUP_FEATURE_ "+LIBCRYPTSETUP"
+#else
+#define _LIBCRYPTSETUP_FEATURE_ "-LIBCRYPTSETUP"
+#endif
+
+#if HAVE_GCRYPT
+#define _GCRYPT_FEATURE_ "+GCRYPT"
+#else
+#define _GCRYPT_FEATURE_ "-GCRYPT"
+#endif
+
+#if HAVE_GNUTLS
+#define _GNUTLS_FEATURE_ "+GNUTLS"
+#else
+#define _GNUTLS_FEATURE_ "-GNUTLS"
+#endif
+#endif // 0
+
+#if HAVE_ACL
#define _ACL_FEATURE_ "+ACL"
#else
#define _ACL_FEATURE_ "-ACL"
#endif
+#if 0 /// UNSUPPORTED by elogind
+#if HAVE_XZ
+#define _XZ_FEATURE_ "+XZ"
+#else
+#define _XZ_FEATURE_ "-XZ"
+#endif
+
+#if HAVE_LZ4
+#define _LZ4_FEATURE_ "+LZ4"
+#else
+#define _LZ4_FEATURE_ "-LZ4"
+#endif
+
+#if HAVE_SECCOMP
+#define _SECCOMP_FEATURE_ "+SECCOMP"
+#else
+#define _SECCOMP_FEATURE_ "-SECCOMP"
+#endif
+
+#if HAVE_BLKID
+#define _BLKID_FEATURE_ "+BLKID"
+#else
+#define _BLKID_FEATURE_ "-BLKID"
+#endif
+
+#if HAVE_ELFUTILS
+#define _ELFUTILS_FEATURE_ "+ELFUTILS"
+#else
+#define _ELFUTILS_FEATURE_ "-ELFUTILS"
+#endif
+
+#if HAVE_KMOD
+#define _KMOD_FEATURE_ "+KMOD"
+#else
+#define _KMOD_FEATURE_ "-KMOD"
+#endif
+
+#if HAVE_LIBIDN2
+#define _IDN2_FEATURE_ "+IDN2"
+#else
+#define _IDN2_FEATURE_ "-IDN2"
+#endif
+
+#if HAVE_LIBIDN
+#define _IDN_FEATURE_ "+IDN"
+#else
+#define _IDN_FEATURE_ "-IDN"
+#endif
+
+#if HAVE_PCRE2
+#define _PCRE2_FEATURE_ "+PCRE2"
+#else
+#define _PCRE2_FEATURE_ "-PCRE2"
+#endif
+#endif // 0
+
#define _CGROUP_HIEARCHY_ "default-hierarchy=" DEFAULT_HIERARCHY_NAME
+#if 0 /// elogind has a much shorter list
+#define SYSTEMD_FEATURES \
+ _PAM_FEATURE_ " " \
+ _AUDIT_FEATURE_ " " \
+ _SELINUX_FEATURE_ " " \
+ _IMA_FEATURE_ " " \
+ _APPARMOR_FEATURE_ " " \
+ _SMACK_FEATURE_ " " \
+ _SYSVINIT_FEATURE_ " " \
+ _UTMP_FEATURE_ " " \
+ _LIBCRYPTSETUP_FEATURE_ " " \
+ _GCRYPT_FEATURE_ " " \
+ _GNUTLS_FEATURE_ " " \
+ _ACL_FEATURE_ " " \
+ _XZ_FEATURE_ " " \
+ _LZ4_FEATURE_ " " \
+ _SECCOMP_FEATURE_ " " \
+ _BLKID_FEATURE_ " " \
+ _ELFUTILS_FEATURE_ " " \
+ _KMOD_FEATURE_ " " \
+ _IDN2_FEATURE_ " " \
+ _IDN_FEATURE_ " " \
+ _PCRE2_FEATURE_ " " \
+ _CGROUP_HIEARCHY_
+#else
#define SYSTEMD_FEATURES \
_PAM_FEATURE_ " " \
+ _AUDIT_FEATURE_ " " \
_SELINUX_FEATURE_ " " \
_SMACK_FEATURE_ " " \
_UTMP_FEATURE_ " " \
_ACL_FEATURE_ " " \
_CGROUP_HIEARCHY_
+#endif // 0
diff --git a/src/basic/bus-label.c b/src/basic/bus-label.c
index d4531c794..1613cf7fd 100644
--- a/src/basic/bus-label.c
+++ b/src/basic/bus-label.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <stdlib.h>
diff --git a/src/basic/bus-label.h b/src/basic/bus-label.h
index 62fb2c450..664cfaf67 100644
--- a/src/basic/bus-label.h
+++ b/src/basic/bus-label.h
@@ -1,31 +1,15 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 <stdlib.h>
#include <string.h>
+#include "string-util.h"
+
char *bus_label_escape(const char *s);
char *bus_label_unescape_n(const char *f, size_t l);
static inline char *bus_label_unescape(const char *f) {
- return bus_label_unescape_n(f, f ? strlen(f) : 0);
+ return bus_label_unescape_n(f, strlen_ptr(f));
}
diff --git a/src/basic/cap-list.c b/src/basic/cap-list.c
new file mode 100644
index 000000000..bfcda3352
--- /dev/null
+++ b/src/basic/cap-list.c
@@ -0,0 +1,119 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <errno.h>
+#include <string.h>
+
+#include "alloc-util.h"
+#include "capability-util.h"
+#include "cap-list.h"
+#include "extract-word.h"
+#include "macro.h"
+#include "missing.h"
+#include "parse-util.h"
+#include "util.h"
+
+static const struct capability_name* lookup_capability(register const char *str, register GPERF_LEN_TYPE len);
+
+#include "cap-from-name.h"
+#include "cap-to-name.h"
+
+const char *capability_to_name(int id) {
+
+ if (id < 0)
+ return NULL;
+
+ if (id >= (int) ELEMENTSOF(capability_names))
+ return NULL;
+
+ return capability_names[id];
+}
+
+int capability_from_name(const char *name) {
+ const struct capability_name *sc;
+ int r, i;
+
+ assert(name);
+
+ /* Try to parse numeric capability */
+ r = safe_atoi(name, &i);
+ if (r >= 0) {
+ if (i >= 0 && i < (int) ELEMENTSOF(capability_names))
+ return i;
+ else
+ return -EINVAL;
+ }
+
+ /* Try to parse string capability */
+ sc = lookup_capability(name, strlen(name));
+ if (!sc)
+ return -EINVAL;
+
+ return sc->id;
+}
+
+int capability_list_length(void) {
+ return (int) ELEMENTSOF(capability_names);
+}
+
+int capability_set_to_string_alloc(uint64_t set, char **s) {
+ _cleanup_free_ char *str = NULL;
+ unsigned long i;
+ size_t allocated = 0, n = 0;
+
+ assert(s);
+
+ for (i = 0; i < cap_last_cap(); i++)
+ if (set & (UINT64_C(1) << i)) {
+ const char *p;
+ size_t add;
+
+ p = capability_to_name(i);
+ if (!p)
+ return -EINVAL;
+
+ add = strlen(p);
+
+ if (!GREEDY_REALLOC(str, allocated, n + add + 2))
+ return -ENOMEM;
+
+ strcpy(mempcpy(str + n, p, add), " ");
+ n += add + 1;
+ }
+
+ if (!GREEDY_REALLOC(str, allocated, n + 1))
+ return -ENOMEM;
+
+ str[n > 0 ? n - 1 : 0] = '\0'; /* truncate the last space, if it's there */
+
+ *s = TAKE_PTR(str);
+
+ return 0;
+}
+
+int capability_set_from_string(const char *s, uint64_t *set) {
+ uint64_t val = 0;
+ const char *p;
+
+ assert(set);
+
+ for (p = s;;) {
+ _cleanup_free_ char *word = NULL;
+ int r;
+
+ r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
+ if (r == -ENOMEM)
+ return r;
+ if (r <= 0)
+ break;
+
+ r = capability_from_name(word);
+ if (r < 0)
+ continue;
+
+ val |= ((uint64_t) UINT64_C(1)) << (uint64_t) r;
+ }
+
+ *set = val;
+
+ return 0;
+}
diff --git a/src/basic/cap-list.h b/src/basic/cap-list.h
new file mode 100644
index 000000000..ab41924d9
--- /dev/null
+++ b/src/basic/cap-list.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+const char *capability_to_name(int id);
+int capability_from_name(const char *name);
+int capability_list_length(void);
+
+int capability_set_to_string_alloc(uint64_t set, char **s);
+int capability_set_from_string(const char *s, uint64_t *set);
diff --git a/src/basic/cap-to-name.awk b/src/basic/cap-to-name.awk
new file mode 100644
index 000000000..402a78202
--- /dev/null
+++ b/src/basic/cap-to-name.awk
@@ -0,0 +1,9 @@
+BEGIN{
+ print "static const char* const capability_names[] = { "
+}
+{
+ printf " [%s] = \"%s\",\n", $1, tolower($1)
+}
+END{
+ print "};"
+}
diff --git a/src/basic/capability-util.c b/src/basic/capability-util.c
index 4a78b14d8..2cc9e158b 100644
--- a/src/basic/capability-util.c
+++ b/src/basic/capability-util.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <grp.h>
@@ -31,6 +14,7 @@
#include "log.h"
#include "macro.h"
#include "parse-util.h"
+#include "user-util.h"
#include "util.h"
#if 0 /// UNNEEDED by elogind
@@ -153,7 +137,7 @@ int capability_ambient_set_apply(uint64_t set, bool also_inherit) {
}
int capability_bounding_set_drop(uint64_t keep, bool right_now) {
- _cleanup_cap_free_ cap_t after_cap = NULL;
+ _cleanup_cap_free_ cap_t before_cap = NULL, after_cap = NULL;
cap_flag_value_t fv;
unsigned long i;
int r;
@@ -163,80 +147,89 @@ int capability_bounding_set_drop(uint64_t keep, bool right_now) {
* executing init!), so get it back temporarily so that we can
* call PR_CAPBSET_DROP. */
- after_cap = cap_get_proc();
- if (!after_cap)
+ before_cap = cap_get_proc();
+ if (!before_cap)
return -errno;
- if (cap_get_flag(after_cap, CAP_SETPCAP, CAP_EFFECTIVE, &fv) < 0)
+ if (cap_get_flag(before_cap, CAP_SETPCAP, CAP_EFFECTIVE, &fv) < 0)
return -errno;
if (fv != CAP_SET) {
_cleanup_cap_free_ cap_t temp_cap = NULL;
static const cap_value_t v = CAP_SETPCAP;
- temp_cap = cap_dup(after_cap);
- if (!temp_cap) {
- r = -errno;
- goto finish;
- }
+ temp_cap = cap_dup(before_cap);
+ if (!temp_cap)
+ return -errno;
- if (cap_set_flag(temp_cap, CAP_EFFECTIVE, 1, &v, CAP_SET) < 0) {
- r = -errno;
- goto finish;
- }
+ if (cap_set_flag(temp_cap, CAP_EFFECTIVE, 1, &v, CAP_SET) < 0)
+ return -errno;
- if (cap_set_proc(temp_cap) < 0) {
- r = -errno;
- goto finish;
- }
+ if (cap_set_proc(temp_cap) < 0)
+ log_debug_errno(errno, "Can't acquire effective CAP_SETPCAP bit, ignoring: %m");
+
+ /* If we didn't manage to acquire the CAP_SETPCAP bit, we continue anyway, after all this just means
+ * we'll fail later, when we actually intend to drop some capabilities. */
}
+ after_cap = cap_dup(before_cap);
+ if (!after_cap)
+ return -errno;
+
for (i = 0; i <= cap_last_cap(); i++) {
+ cap_value_t v;
- if (!(keep & (UINT64_C(1) << i))) {
- cap_value_t v;
+ if ((keep & (UINT64_C(1) << i)))
+ continue;
- /* Drop it from the bounding set */
- if (prctl(PR_CAPBSET_DROP, i) < 0) {
- r = -errno;
+ /* Drop it from the bounding set */
+ if (prctl(PR_CAPBSET_DROP, i) < 0) {
+ r = -errno;
+
+ /* If dropping the capability failed, let's see if we didn't have it in the first place. If so,
+ * continue anyway, as dropping a capability we didn't have in the first place doesn't really
+ * matter anyway. */
+ if (prctl(PR_CAPBSET_READ, i) != 0)
goto finish;
- }
- v = (cap_value_t) i;
+ }
+ v = (cap_value_t) 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) {
+ /* 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;
}
-
- /* 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 (cap_set_proc(after_cap) < 0)
- return -errno;
+ if (cap_set_proc(after_cap) < 0) {
+ /* If there are no actual changes anyway then let's ignore this error. */
+ if (cap_compare(before_cap, after_cap) != 0)
+ r = -errno;
+ }
return r;
}
static int drop_from_file(const char *fn, uint64_t keep) {
- int r, k;
- uint32_t hi, lo;
+ _cleanup_free_ char *p = NULL;
uint64_t current, after;
- char *p;
+ uint32_t hi, lo;
+ int r, k;
r = read_one_line_file(fn, &p);
if (r < 0)
@@ -246,8 +239,6 @@ static int drop_from_file(const char *fn, uint64_t keep) {
assert_cc(sizeof(lo) == sizeof(unsigned));
k = sscanf(p, "%u %u", &lo, &hi);
- free(p);
-
if (k != 2)
return -EIO;
@@ -260,13 +251,7 @@ static int drop_from_file(const char *fn, uint64_t keep) {
lo = (unsigned) (after & 0xFFFFFFFFULL);
hi = (unsigned) ((after >> 32ULL) & 0xFFFFFFFFULL);
- if (asprintf(&p, "%u %u", lo, hi) < 0)
- return -ENOMEM;
-
- r = write_string_file(fn, p, WRITE_STRING_FILE_CREATE);
- free(p);
-
- return r;
+ return write_string_filef(fn, WRITE_STRING_FILE_CREATE, "%u %u", lo, hi);
}
int capability_bounding_set_drop_usermode(uint64_t keep) {
@@ -306,8 +291,7 @@ int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities) {
if (prctl(PR_SET_KEEPCAPS, 1) < 0)
return log_error_errno(errno, "Failed to enable keep capabilities flag: %m");
- r = setresuid(uid, uid, uid);
- if (r < 0)
+ if (setresuid(uid, uid, uid) < 0)
return log_error_errno(errno, "Failed to change user ID: %m");
if (prctl(PR_SET_KEEPCAPS, 0) < 0)
@@ -363,4 +347,19 @@ int drop_capability(cap_value_t cv) {
return 0;
}
+
+bool ambient_capabilities_supported(void) {
+ static int cache = -1;
+
+ if (cache >= 0)
+ return cache;
+
+ /* If PR_CAP_AMBIENT returns something valid, or an unexpected error code we assume that ambient caps are
+ * available. */
+
+ cache = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_KILL, 0, 0) >= 0 ||
+ !IN_SET(errno, EINVAL, EOPNOTSUPP, ENOSYS);
+
+ return cache;
+}
#endif // 0
diff --git a/src/basic/capability-util.h b/src/basic/capability-util.h
index 913048e4c..06ff99157 100644
--- a/src/basic/capability-util.h
+++ b/src/basic/capability-util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 <stdint.h>
#include <sys/capability.h>
@@ -55,5 +37,9 @@ static inline void cap_free_charpp(char **p) {
static inline bool cap_test_all(uint64_t caps) {
uint64_t m;
m = (UINT64_C(1) << (cap_last_cap() + 1)) - 1;
- return (caps & m) == m;
+ return FLAGS_SET(caps, m);
}
+
+#if 0 /// UNNEEDED by elogind
+bool ambient_capabilities_supported(void);
+#endif // 0
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
index 1137e167c..42395aae5 100644
--- a/src/basic/cgroup-util.c
+++ b/src/basic/cgroup-util.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <dirent.h>
#include <errno.h>
@@ -23,6 +6,7 @@
//#include <limits.h>
#include <signal.h>
//#include <stddef.h>
+#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
@@ -103,9 +87,12 @@ int cg_read_pid(FILE *f, pid_t *_pid) {
return 1;
}
-int cg_read_event(const char *controller, const char *path, const char *event,
- char **val)
-{
+int cg_read_event(
+ const char *controller,
+ const char *path,
+ const char *event,
+ char **val) {
+
_cleanup_free_ char *events = NULL, *content = NULL;
char *p, *line;
int r;
@@ -150,7 +137,7 @@ bool cg_ns_supported(void) {
return enabled;
}
-#endif //0
+#endif // 0
int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d) {
_cleanup_free_ char *fs = NULL;
@@ -257,7 +244,7 @@ int cg_kill(
return -ENOMEM;
}
- my_pid = getpid();
+ my_pid = getpid_cached();
do {
_cleanup_fclose_ FILE *f = NULL;
@@ -373,7 +360,7 @@ int cg_kill_recursive(
if (flags & CGROUP_REMOVE) {
r = cg_rmdir(controller, path);
- if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY)
+ if (r < 0 && ret >= 0 && !IN_SET(r, -ENOENT, -EBUSY))
return r;
}
@@ -401,7 +388,7 @@ int cg_migrate(
if (!s)
return -ENOMEM;
- my_pid = getpid();
+ my_pid = getpid_cached();
log_debug_elogind("Migrating \"%s\"/\"%s\" to \"%s\"/\"%s\" (%s)",
cfrom, pfrom, cto, pto,
@@ -435,7 +422,7 @@ int cg_migrate(
* exist in the root cgroup, we only check for
* them there. */
if (cfrom &&
- (isempty(pfrom) || path_equal(pfrom, "/")) &&
+ empty_or_root(pfrom) &&
is_kernel_thread(pid) > 0)
continue;
@@ -512,7 +499,7 @@ int cg_migrate_recursive(
if (flags & CGROUP_REMOVE) {
r = cg_rmdir(cfrom, pfrom);
- if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY)
+ if (r < 0 && ret >= 0 && !IN_SET(r, -ENOENT, -EBUSY))
return r;
}
@@ -642,7 +629,7 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch
if (!t)
return -ENOMEM;
- *fs = path_kill_slashes(t);
+ *fs = path_simplify(t, false);
return 0;
}
@@ -659,7 +646,7 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch
if (r < 0)
return r;
- path_kill_slashes(*fs);
+ path_simplify(*fs, false);
return 0;
}
@@ -768,6 +755,9 @@ int cg_trim(const char *controller, const char *path, bool delete_root) {
return r;
}
+/* Create a cgroup in the hierarchy of controller.
+ * Returns 0 if the group already existed, 1 on success, negative otherwise.
+ */
int cg_create(const char *controller, const char *path) {
_cleanup_free_ char *fs = NULL;
int r;
@@ -780,13 +770,11 @@ int cg_create(const char *controller, const char *path) {
if (r < 0)
return r;
- if (mkdir(fs, 0755) < 0) {
-
- if (errno == EEXIST)
- return 0;
-
- return -errno;
- }
+ r = mkdir_errno_wrapper(fs, 0755);
+ if (r == -EEXIST)
+ return 0;
+ if (r < 0)
+ return r;
r = cg_hybrid_unified();
if (r < 0)
@@ -831,7 +819,7 @@ int cg_attach(const char *controller, const char *path, pid_t pid) {
return r;
if (pid == 0)
- pid = getpid();
+ pid = getpid_cached();
xsprintf(c, PID_FMT "\n", pid);
@@ -879,85 +867,87 @@ int cg_attach_fallback(const char *controller, const char *path, pid_t pid) {
}
#if 0 /// UNNEEDED by elogind
-int cg_set_group_access(
+int cg_set_access(
const char *controller,
const char *path,
- mode_t mode,
uid_t uid,
gid_t gid) {
+ struct Attribute {
+ const char *name;
+ bool fatal;
+ };
+
+ /* cgroupsv1, aka legacy/non-unified */
+ static const struct Attribute legacy_attributes[] = {
+ { "cgroup.procs", true },
+ { "tasks", false },
+ { "cgroup.clone_children", false },
+ {},
+ };
+
+ /* cgroupsv2, aka unified */
+ static const struct Attribute unified_attributes[] = {
+ { "cgroup.procs", true },
+ { "cgroup.subtree_control", true },
+ { "cgroup.threads", false },
+ {},
+ };
+
+ static const struct Attribute* const attributes[] = {
+ [false] = legacy_attributes,
+ [true] = unified_attributes,
+ };
+
_cleanup_free_ char *fs = NULL;
- int r;
+ const struct Attribute *i;
+ int r, unified;
- if (mode == MODE_INVALID && uid == UID_INVALID && gid == GID_INVALID)
+ assert(path);
+
+ if (uid == UID_INVALID && gid == GID_INVALID)
return 0;
- if (mode != MODE_INVALID)
- mode &= 0777;
+ unified = cg_unified_controller(controller);
+ if (unified < 0)
+ return unified;
+ /* Configure access to the cgroup itself */
r = cg_get_path(controller, path, NULL, &fs);
if (r < 0)
return r;
- r = chmod_and_chown(fs, mode, uid, gid);
+ r = chmod_and_chown(fs, 0755, uid, gid);
if (r < 0)
return r;
- r = cg_hybrid_unified();
- if (r < 0)
- return r;
- if (r > 0 && streq(controller, SYSTEMD_CGROUP_CONTROLLER)) {
- r = cg_set_group_access(SYSTEMD_CGROUP_CONTROLLER_LEGACY, path, mode, uid, gid);
- if (r < 0)
- log_warning_errno(r, "Failed to set group access on compat systemd cgroup %s: %m", path);
- }
-
- return 0;
-}
-
-int cg_set_task_access(
- const char *controller,
- const char *path,
- mode_t mode,
- uid_t uid,
- gid_t gid) {
-
- _cleanup_free_ char *fs = NULL, *procs = NULL;
- int r;
-
- assert(path);
-
- if (mode == MODE_INVALID && uid == UID_INVALID && gid == GID_INVALID)
- return 0;
-
- if (mode != MODE_INVALID)
- mode &= 0666;
+ /* Configure access to the cgroup's attributes */
+ for (i = attributes[unified]; i->name; i++) {
+ fs = mfree(fs);
- r = cg_get_path(controller, path, "cgroup.procs", &fs);
- if (r < 0)
- return r;
+ r = cg_get_path(controller, path, i->name, &fs);
+ if (r < 0)
+ return r;
- r = chmod_and_chown(fs, mode, uid, gid);
- if (r < 0)
- return r;
+ r = chmod_and_chown(fs, 0644, uid, gid);
+ if (r < 0) {
+ if (i->fatal)
+ return r;
- r = cg_unified_controller(controller);
- if (r < 0)
- return r;
- if (r == 0) {
- /* Compatibility, Always keep values for "tasks" in sync with
- * "cgroup.procs" */
- if (cg_get_path(controller, path, "tasks", &procs) >= 0)
- (void) chmod_and_chown(procs, mode, uid, gid);
+ log_debug_errno(r, "Failed to set access on cgroup %s, ignoring: %m", fs);
+ }
}
- r = cg_hybrid_unified();
- if (r < 0)
- return r;
- if (r > 0 && streq(controller, SYSTEMD_CGROUP_CONTROLLER)) {
- r = cg_set_task_access(SYSTEMD_CGROUP_CONTROLLER_LEGACY, path, mode, uid, gid);
+ if (streq(controller, SYSTEMD_CGROUP_CONTROLLER)) {
+ r = cg_hybrid_unified();
if (r < 0)
- log_warning_errno(r, "Failed to set task access on compat systemd cgroup %s: %m", path);
+ return r;
+ if (r > 0) {
+ /* Always propagate access mode from unified to legacy controller */
+ r = cg_set_access(SYSTEMD_CGROUP_CONTROLLER_LEGACY, path, uid, gid);
+ if (r < 0)
+ log_debug_errno(r, "Failed to set access on compatibility elogind cgroup %s, ignoring: %m", path);
+ }
}
return 0;
@@ -1004,7 +994,11 @@ int cg_get_xattr(const char *controller, const char *path, const char *name, voi
int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
_cleanup_fclose_ FILE *f = NULL;
char line[LINE_MAX];
+#if 0 /// At elogind we do not want that (false alarm) "maybe uninitialized" warning
+ const char *fs, *controller_str;
+#else
const char *fs, *controller_str = NULL;
+#endif // 0
size_t cs = 0;
int unified;
@@ -1036,6 +1030,8 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
if (!f)
return errno == ENOENT ? -ESRCH : -errno;
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
FOREACH_LINE(line, f, return -errno) {
char *e, *p;
@@ -1065,13 +1061,11 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
continue;
*e = 0;
- FOREACH_WORD_SEPARATOR(word, k, l, ",", state) {
+ FOREACH_WORD_SEPARATOR(word, k, l, ",", state)
if (k == cs && memcmp(word, controller_str, cs) == 0) {
found = true;
break;
}
- }
-
if (!found)
continue;
}
@@ -1081,6 +1075,11 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
if (!p)
return -ENOMEM;
+ /* Truncate suffix indicating the process is a zombie */
+ e = endswith(p, " (deleted)");
+ if (e)
+ *e = 0;
+
*path = p;
return 0;
}
@@ -1201,7 +1200,7 @@ int cg_is_empty_recursive(const char *controller, const char *path) {
assert(path);
/* The root cgroup is always populated */
- if (controller && (isempty(path) || path_equal(path, "/")))
+ if (controller && empty_or_root(path))
return false;
r = cg_unified_controller(controller);
@@ -1258,7 +1257,7 @@ int cg_split_spec(const char *spec, char **controller, char **path) {
assert(spec);
if (*spec == '/') {
- if (!path_is_safe(spec))
+ if (!path_is_normalized(spec))
return -EINVAL;
if (path) {
@@ -1266,7 +1265,7 @@ int cg_split_spec(const char *spec, char **controller, char **path) {
if (!t)
return -ENOMEM;
- *path = path_kill_slashes(t);
+ *path = path_simplify(t, false);
}
if (controller)
@@ -1311,14 +1310,14 @@ int cg_split_spec(const char *spec, char **controller, char **path) {
return -ENOMEM;
}
- if (!path_is_safe(u) ||
+ if (!path_is_normalized(u) ||
!path_is_absolute(u)) {
free(t);
free(u);
return -EINVAL;
}
- path_kill_slashes(u);
+ path_simplify(u, false);
}
if (controller)
@@ -1349,7 +1348,7 @@ int cg_mangle_path(const char *path, char **result) {
if (!t)
return -ENOMEM;
- *result = path_kill_slashes(t);
+ *result = path_simplify(t, false);
return 0;
}
@@ -1438,10 +1437,9 @@ int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) {
if (r < 0)
return r;
- if (c == raw) {
- *cgroup = raw;
- raw = NULL;
- } else {
+ if (c == raw)
+ *cgroup = TAKE_PTR(raw);
+ else {
char *n;
n = strdup(c);
@@ -1455,7 +1453,6 @@ int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) {
return 0;
}
-#if 0 /// UNNEEDED by elogind
int cg_path_decode_unit(const char *cgroup, char **unit) {
char *c, *s;
size_t n;
@@ -1463,15 +1460,21 @@ int cg_path_decode_unit(const char *cgroup, char **unit) {
assert(cgroup);
assert(unit);
+#if 0 /// elogind has a different naming: <controller>:/<session id>. So prefix is always len < 3
n = strcspn(cgroup, "/");
if (n < 3)
return -ENXIO;
+#else
+ n = strspn(cgroup, "/") + 1;
+#endif // 0
c = strndupa(cgroup, n);
c = cg_unescape(c);
+#if 0 /// elogind session ids are never valid unit names.
if (!unit_name_is_valid(c, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
return -ENXIO;
+#endif // 0
s = strdup(c);
if (!s)
@@ -1486,7 +1489,7 @@ static bool valid_slice_name(const char *p, size_t n) {
if (!p)
return false;
- if (n < strlen("x.slice"))
+ if (n < STRLEN("x.slice"))
return false;
if (memcmp(p + n - 6, ".slice", 6) == 0) {
@@ -1558,6 +1561,7 @@ int cg_pid_get_unit(pid_t pid, char **unit) {
return cg_path_get_unit(cgroup, unit);
}
+#if 0 /// UNNEEDED by elogind
/**
* Skip session-*.scope, but require it to be there.
*/
@@ -1570,7 +1574,7 @@ static const char *skip_session(const char *p) {
p += strspn(p, "/");
n = strcspn(p, "/");
- if (n < strlen("session-x.scope"))
+ if (n < STRLEN("session-x.scope"))
return NULL;
if (memcmp(p, "session-", 8) == 0 && memcmp(p + n - 6, ".scope", 6) == 0) {
@@ -1607,7 +1611,7 @@ static const char *skip_user_manager(const char *p) {
p += strspn(p, "/");
n = strcspn(p, "/");
- if (n < strlen("user@x.service"))
+ if (n < STRLEN("user@x.service"))
return NULL;
if (memcmp(p, "user@", 5) == 0 && memcmp(p + n - 8, ".service", 8) == 0) {
@@ -1774,10 +1778,13 @@ int cg_pid_get_session(pid_t pid, char **session) {
return cg_path_get_session(cgroup, session);
}
-#if 0 /// UNNEEDED by elogind
int cg_path_get_owner_uid(const char *path, uid_t *uid) {
+#if 0 /// elogind needs one more value
_cleanup_free_ char *slice = NULL;
char *start, *end;
+#else
+ _cleanup_free_ char *slice = NULL, *p = NULL, *s = NULL;
+#endif // 0
int r;
assert(path);
@@ -1786,6 +1793,7 @@ int cg_path_get_owner_uid(const char *path, uid_t *uid) {
if (r < 0)
return r;
+#if 0 /// elogind does not support systemd slices
start = startswith(slice, "user-");
if (!start)
return -ENXIO;
@@ -1796,6 +1804,20 @@ int cg_path_get_owner_uid(const char *path, uid_t *uid) {
*end = 0;
if (parse_uid(start, uid) < 0)
return -ENXIO;
+#else
+ p = strappend("/run/systemd/sessions/", slice);
+
+ r = parse_env_file(NULL, p, NEWLINE, "UID", &s, NULL);
+ if (r == -ENOENT)
+ return -ENXIO;
+ if (r < 0)
+ return r;
+ if (isempty(s))
+ return -EIO;
+
+ if (parse_uid(s, uid) < 0)
+ return -ENXIO;
+#endif // 0
return 0;
}
@@ -1817,6 +1839,7 @@ int cg_path_get_slice(const char *p, char **slice) {
assert(p);
assert(slice);
+#if 0 /// elogind does not support systemd slices
/* Finds the right-most slice unit from the beginning, but
* stops before we come to the first non-slice unit. */
@@ -1845,6 +1868,23 @@ int cg_path_get_slice(const char *p, char **slice) {
e = p;
p += n;
}
+#else
+ /* In elogind, what is reported here, is the location of
+ * the session. This is derived from /proc/<self|PID>/cgroup.
+ * In there we look at the controller, which will look something
+ * like "1:name=openrc:/3".
+ * The last part gets extracted (and is now p), which is "/3" in
+ * this case. The three is the session id, and that can be mapped.
+ */
+ e = startswith(p, "/");
+
+ if (e)
+ *slice = strdup(e);
+ else
+ *slice = strdup(p);
+
+ return 0;
+#endif // 0
}
int cg_pid_get_slice(pid_t pid, char **slice) {
@@ -1854,6 +1894,8 @@ int cg_pid_get_slice(pid_t pid, char **slice) {
assert(slice);
r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
+ log_debug_elogind("Found cgroup %s for pid %u (result %d)",
+ cgroup, pid, r);
if (r < 0)
return r;
@@ -1861,17 +1903,28 @@ int cg_pid_get_slice(pid_t pid, char **slice) {
}
int cg_path_get_user_slice(const char *p, char **slice) {
+#if 0 /// UNNEEDED by elogind
const char *t;
+#endif // 0
assert(p);
assert(slice);
+#if 0 /// nothing to skip in elogind
t = skip_user_prefix(p);
if (!t)
return -ENXIO;
+#endif // 0
+#if 0 /// UNNEEDED by elogind
/* And now it looks pretty much the same as for a system
* slice, so let's just use the same parser from here on. */
return cg_path_get_slice(t, slice);
+#else
+ /* In elogind there is nothing to skip, we can use the path
+ * directly. Generally speaking this is always a session id
+ * to user mapping. */
+ return cg_path_get_slice(p, slice);
+#endif // 0
}
int cg_pid_get_user_slice(pid_t pid, char **slice) {
@@ -1886,7 +1939,6 @@ int cg_pid_get_user_slice(pid_t pid, char **slice) {
return cg_path_get_user_slice(cgroup, slice);
}
-#endif // 0
char *cg_escape(const char *p) {
bool need_prefix = false;
@@ -1901,9 +1953,7 @@ char *cg_escape(const char *p) {
/* The return value of this function (unlike cg_unescape())
* needs free()! */
- if (p[0] == 0 ||
- p[0] == '_' ||
- p[0] == '.' ||
+ if (IN_SET(p[0], 0, '_', '.') ||
streq(p, "notify_on_release") ||
streq(p, "release_agent") ||
streq(p, "tasks") ||
@@ -1969,7 +2019,7 @@ bool cg_controller_is_valid(const char *p) {
if (s)
p = s;
- if (*p == 0 || *p == '_')
+ if (IN_SET(*p, 0, '_'))
return false;
for (t = p; *t; t++)
@@ -2021,8 +2071,16 @@ int cg_slice_to_path(const char *unit, char **ret) {
_cleanup_free_ char *escaped = NULL;
char n[dash - p + sizeof(".slice")];
+#if HAS_FEATURE_MEMORY_SANITIZER
+ /* msan doesn't instrument stpncpy, so it thinks
+ * n is later used unitialized:
+ * https://github.com/google/sanitizers/issues/926
+ */
+ zero(n);
+#endif
+
/* Don't allow trailing or double dashes */
- if (dash[1] == 0 || dash[1] == '-')
+ if (IN_SET(dash[1], 0, '-'))
return -EINVAL;
strcpy(stpncpy(n, p, dash - p), ".slice");
@@ -2046,8 +2104,7 @@ int cg_slice_to_path(const char *unit, char **ret) {
if (!strextend(&s, e, NULL))
return -ENOMEM;
- *ret = s;
- s = NULL;
+ *ret = TAKE_PTR(s);
return 0;
}
@@ -2076,68 +2133,110 @@ int cg_get_attribute(const char *controller, const char *path, const char *attri
}
#if 0 /// UNNEEDED by elogind
-int cg_get_keyed_attribute(const char *controller, const char *path, const char *attribute, const char **keys, char **values) {
- _cleanup_free_ char *filename = NULL, *content = NULL;
- char *line, *p;
- int i, r;
+int cg_get_keyed_attribute(
+ const char *controller,
+ const char *path,
+ const char *attribute,
+ char **keys,
+ char **ret_values) {
+
+ _cleanup_free_ char *filename = NULL, *contents = NULL;
+ const char *p;
+ size_t n, i, n_done = 0;
+ char **v;
+ int r;
- for (i = 0; keys[i]; i++)
- values[i] = NULL;
+ /* Reads one or more fields of a cgroupsv2 keyed attribute file. The 'keys' parameter should be an strv with
+ * all keys to retrieve. The 'ret_values' parameter should be passed as string size with the same number of
+ * entries as 'keys'. On success each entry will be set to the value of the matching key.
+ *
+ * If the attribute file doesn't exist at all returns ENOENT, if any key is not found returns ENXIO. */
r = cg_get_path(controller, path, attribute, &filename);
if (r < 0)
return r;
- r = read_full_file(filename, &content, NULL);
+ r = read_full_file(filename, &contents, NULL);
if (r < 0)
return r;
- p = content;
- while ((line = strsep(&p, "\n"))) {
- char *key;
+ n = strv_length(keys);
+ if (n == 0) /* No keys to retrieve? That's easy, we are done then */
+ return 0;
- key = strsep(&line, " ");
+ /* Let's build this up in a temporary array for now in order not to clobber the return parameter on failure */
+ v = newa0(char*, n);
- for (i = 0; keys[i]; i++) {
- if (streq(key, keys[i])) {
- values[i] = strdup(line);
- break;
+ for (p = contents; *p;) {
+ const char *w = NULL;
+
+ for (i = 0; i < n; i++)
+ if (!v[i]) {
+ w = first_word(p, keys[i]);
+ if (w)
+ break;
}
- }
- }
- for (i = 0; keys[i]; i++) {
- if (!values[i]) {
- for (i = 0; keys[i]; i++) {
- free(values[i]);
- values[i] = NULL;
+ if (w) {
+ size_t l;
+
+ l = strcspn(w, NEWLINE);
+ v[i] = strndup(w, l);
+ if (!v[i]) {
+ r = -ENOMEM;
+ goto fail;
}
- return -ENOENT;
- }
+
+ n_done++;
+ if (n_done >= n)
+ goto done;
+
+ p = w + l;
+ } else
+ p += strcspn(p, NEWLINE);
+
+ p += strspn(p, NEWLINE);
}
+ r = -ENXIO;
+
+fail:
+ for (i = 0; i < n; i++)
+ free(v[i]);
+
+ return r;
+
+done:
+ memcpy(ret_values, v, sizeof(char*) * n);
return 0;
+
}
int cg_create_everywhere(CGroupMask supported, CGroupMask mask, const char *path) {
CGroupController c;
+ bool created;
int r;
/* This one will create a cgroup in our private tree, but also
* duplicate it in the trees specified in mask, and remove it
- * in all others */
+ * in all others.
+ *
+ * Returns 0 if the group already existed in the systemd hierarchy,
+ * 1 on success, negative otherwise.
+ */
/* First create the cgroup in our own hierarchy. */
r = cg_create(SYSTEMD_CGROUP_CONTROLLER, path);
if (r < 0)
return r;
+ created = !!r;
/* If we are in the unified hierarchy, we are done now */
r = cg_all_unified();
if (r < 0)
return r;
if (r > 0)
- return 0;
+ return created;
/* Otherwise, do the same in the other hierarchies */
for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
@@ -2152,7 +2251,7 @@ int cg_create_everywhere(CGroupMask supported, CGroupMask mask, const char *path
(void) cg_trim(n, path, true);
}
- return 0;
+ return created;
}
int cg_attach_everywhere(CGroupMask supported, const char *path, pid_t pid, cg_migrate_callback_t path_callback, void *userdata) {
@@ -2268,10 +2367,10 @@ int cg_trim_everywhere(CGroupMask supported, const char *path, bool delete_root)
#endif // 0
int cg_mask_to_string(CGroupMask mask, char **ret) {
- const char *controllers[_CGROUP_CONTROLLER_MAX + 1];
+ _cleanup_free_ char *s = NULL;
+ size_t n = 0, allocated = 0;
+ bool space = false;
CGroupController c;
- int i = 0;
- char *s;
assert(ret);
@@ -2281,19 +2380,31 @@ int cg_mask_to_string(CGroupMask mask, char **ret) {
}
for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
+ const char *k;
+ size_t l;
if (!(mask & CGROUP_CONTROLLER_TO_MASK(c)))
continue;
- controllers[i++] = cgroup_controller_to_string(c);
- controllers[i] = NULL;
+ k = cgroup_controller_to_string(c);
+ l = strlen(k);
+
+ if (!GREEDY_REALLOC(s, allocated, n + space + l + 1))
+ return -ENOMEM;
+
+ if (space)
+ s[n] = ' ';
+ memcpy(s + n + space, k, l);
+ n += space + l;
+
+ space = true;
}
- s = strv_join((char **)controllers, NULL);
- if (!s)
- return -ENOMEM;
+ assert(s);
+
+ s[n] = 0;
+ *ret = TAKE_PTR(s);
- *ret = s;
return 0;
}
@@ -2380,27 +2491,36 @@ int cg_mask_supported(CGroupMask *ret) {
}
#if 0 /// UNNEEDED by elogind
-int cg_kernel_controllers(Set *controllers) {
+int cg_kernel_controllers(Set **ret) {
+ _cleanup_set_free_free_ Set *controllers = NULL;
_cleanup_fclose_ FILE *f = NULL;
- char buf[LINE_MAX];
int r;
- assert(controllers);
+ assert(ret);
/* Determines the full list of kernel-known controllers. Might
* include controllers we don't actually support, arbitrary
* named hierarchies and controllers that aren't currently
* accessible (because not mounted). */
+ controllers = set_new(&string_hash_ops);
+ if (!controllers)
+ return -ENOMEM;
+
f = fopen("/proc/cgroups", "re");
if (!f) {
- if (errno == ENOENT)
+ if (errno == ENOENT) {
+ *ret = NULL;
return 0;
+ }
+
return -errno;
}
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
/* Ignore the header line */
- (void) fgets(buf, sizeof(buf), f);
+ (void) read_line(f, (size_t) -1, NULL);
for (;;) {
char *controller;
@@ -2433,6 +2553,8 @@ int cg_kernel_controllers(Set *controllers) {
return r;
}
+ *ret = TAKE_PTR(controllers);
+
return 0;
}
#endif // 0
@@ -2463,37 +2585,48 @@ static int cg_unified_update(void) {
return 0;
if (statfs("/sys/fs/cgroup/", &fs) < 0)
- return -errno;
+ return log_debug_errno(errno, "statfs(\"/sys/fs/cgroup/\") failed: %m");
-#if 0 /// UNNEEDED by elogind
- if (F_TYPE_EQUAL(fs.f_type, CGROUP2_SUPER_MAGIC))
+ if (F_TYPE_EQUAL(fs.f_type, CGROUP2_SUPER_MAGIC)) {
+ log_debug("Found cgroup2 on /sys/fs/cgroup/, full unified hierarchy");
unified_cache = CGROUP_UNIFIED_ALL;
- else if (F_TYPE_EQUAL(fs.f_type, TMPFS_MAGIC)) {
+#if 0 /// The handling of cgroups is a bit different with elogind
+ } else if (F_TYPE_EQUAL(fs.f_type, TMPFS_MAGIC)) {
+ log_debug("Found cgroup2 on /sys/fs/cgroup/unified, unified hierarchy for systemd controller");
+#else
+ } else if (F_TYPE_EQUAL(fs.f_type, CGROUP_SUPER_MAGIC)
+ || F_TYPE_EQUAL(fs.f_type, TMPFS_MAGIC)) {
+#endif // 0
if (statfs("/sys/fs/cgroup/unified/", &fs) == 0 &&
F_TYPE_EQUAL(fs.f_type, CGROUP2_SUPER_MAGIC)) {
unified_cache = CGROUP_UNIFIED_SYSTEMD;
unified_systemd_v232 = false;
- } else if (statfs("/sys/fs/cgroup/systemd/", &fs) == 0 &&
- F_TYPE_EQUAL(fs.f_type, CGROUP2_SUPER_MAGIC)) {
- unified_cache = CGROUP_UNIFIED_SYSTEMD;
- unified_systemd_v232 = true;
} else {
+#if 0 /// There is no sub-grouping within elogind
if (statfs("/sys/fs/cgroup/systemd/", &fs) < 0)
- return -errno;
- if (!F_TYPE_EQUAL(fs.f_type, CGROUP_SUPER_MAGIC))
- return -ENOMEDIUM;
+ return log_debug_errno(errno, "statfs(\"/sys/fs/cgroup/systemd\" failed: %m");
+
+ if (F_TYPE_EQUAL(fs.f_type, CGROUP2_SUPER_MAGIC)) {
+ log_debug("Found cgroup2 on /sys/fs/cgroup/systemd, unified hierarchy for systemd controller (v232 variant)");
+ unified_cache = CGROUP_UNIFIED_SYSTEMD;
+ unified_systemd_v232 = true;
+ } else if (F_TYPE_EQUAL(fs.f_type, CGROUP_SUPER_MAGIC)) {
+ log_debug("Found cgroup on /sys/fs/cgroup/systemd, legacy hierarchy");
+ unified_cache = CGROUP_UNIFIED_NONE;
+ } else {
+ log_debug("Unexpected filesystem type %llx mounted on /sys/fs/cgroup/systemd, assuming legacy hierarchy",
+ (unsigned long long) fs.f_type);
+ unified_cache = CGROUP_UNIFIED_NONE;
+ }
+#else
unified_cache = CGROUP_UNIFIED_NONE;
+#endif // 0
}
- } else
+ } else {
+ log_debug("Unknown filesystem type %llx mounted on /sys/fs/cgroup.",
+ (unsigned long long) fs.f_type);
return -ENOMEDIUM;
-#else
- /* elogind can not support the unified hierarchy as a controller,
- * so always assume a classical hierarchy.
- * If, and only *if*, someone really wants to substitute systemd-login
- * in an environment managed by systemd with elogind, we might have to
- * add such a support. */
- unified_cache = CGROUP_UNIFIED_NONE;
-#endif // 0
+ }
return 0;
}
@@ -2511,7 +2644,11 @@ int cg_unified_controller(const char *controller) {
if (unified_cache >= CGROUP_UNIFIED_ALL)
return true;
+#if 0 /// only if elogind is the controller we can use cgroups2 in hybrid mode
return streq_ptr(controller, SYSTEMD_CGROUP_CONTROLLER);
+#else
+ return streq_ptr(controller, SYSTEMD_CGROUP_CONTROLLER_HYBRID);
+#endif // 0
}
int cg_all_unified(void) {
@@ -2542,6 +2679,7 @@ int cg_unified_flush(void) {
#if 0 /// UNNEEDED by elogind
int cg_enable_everywhere(CGroupMask supported, CGroupMask mask, const char *p) {
+ _cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *fs = NULL;
CGroupController c;
int r;
@@ -2575,19 +2713,32 @@ int cg_enable_everywhere(CGroupMask supported, CGroupMask mask, const char *p) {
s[0] = mask & bit ? '+' : '-';
strcpy(s + 1, n);
- r = write_string_file(fs, s, 0);
- if (r < 0)
+ if (!f) {
+ f = fopen(fs, "we");
+ if (!f) {
+ log_debug_errno(errno, "Failed to open cgroup.subtree_control file of %s: %m", p);
+ break;
+ }
+ }
+
+ r = write_string_stream(f, s, 0);
+ if (r < 0) {
log_debug_errno(r, "Failed to enable controller %s for %s (%s): %m", n, p, fs);
+ clearerr(f);
+ }
}
}
return 0;
}
+#endif // 0
bool cg_is_unified_wanted(void) {
static thread_local int wanted = -1;
+#if 0 /// UNNEEDED by elogind
int r;
bool b;
+#endif // 0
const bool is_default = DEFAULT_HIERARCHY == CGROUP_UNIFIED_ALL;
/* If we have a cached value, return that. */
@@ -2599,11 +2750,15 @@ bool cg_is_unified_wanted(void) {
if (cg_unified_flush() >= 0)
return (wanted = unified_cache >= CGROUP_UNIFIED_ALL);
+#if 0 /// elogind is not init and has no business with kernel command line
/* Otherwise, let's see what the kernel command line has to say.
* Since checking is expensive, cache a non-error result. */
r = proc_cmdline_get_bool("systemd.unified_cgroup_hierarchy", &b);
return (wanted = r > 0 ? b : is_default);
+#else
+ return is_default;
+#endif // 0
}
bool cg_is_legacy_wanted(void) {
@@ -2625,8 +2780,10 @@ bool cg_is_legacy_wanted(void) {
bool cg_is_hybrid_wanted(void) {
static thread_local int wanted = -1;
+#if 0 /// UNNEEDED by elogind
int r;
bool b;
+#endif // 0
const bool is_default = DEFAULT_HIERARCHY >= CGROUP_UNIFIED_SYSTEMD;
/* We default to true if the default is "hybrid", obviously,
* but also when the default is "unified", because if we get
@@ -2642,6 +2799,7 @@ bool cg_is_hybrid_wanted(void) {
unified_cache == CGROUP_UNIFIED_ALL)
return (wanted = false);
+#if 0 /// elogind is not init and has no business with kernel command line
/* Otherwise, let's see what the kernel command line has to say.
* Since checking is expensive, cache a non-error result. */
r = proc_cmdline_get_bool("systemd.legacy_systemd_cgroup_controller", &b);
@@ -2649,20 +2807,11 @@ bool cg_is_hybrid_wanted(void) {
/* The meaning of the kernel option is reversed wrt. to the return value
* of this function, hence the negation. */
return (wanted = r > 0 ? !b : is_default);
-}
#else
-bool cg_is_unified_wanted(void) {
- return false;
-}
-bool cg_is_legacy_wanted(void) {
- return true;
-}
-bool cg_is_hybrid_wanted(void) {
- return false;
-}
+ return is_default;
#endif // 0
+}
-#if 0 /// UNNEEDED by elogind
int cg_weight_parse(const char *s, uint64_t *ret) {
uint64_t u;
int r;
@@ -2683,6 +2832,7 @@ int cg_weight_parse(const char *s, uint64_t *ret) {
return 0;
}
+#if 0 /// UNNEEDED by elogind
const uint64_t cgroup_io_limit_defaults[_CGROUP_IO_LIMIT_TYPE_MAX] = {
[CGROUP_IO_RBPS_MAX] = CGROUP_LIMIT_MAX,
[CGROUP_IO_WBPS_MAX] = CGROUP_LIMIT_MAX,
diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h
index 4c6ab1137..25e634dea 100644
--- a/src/basic/cgroup-util.h
+++ b/src/basic/cgroup-util.h
@@ -1,28 +1,11 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <dirent.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
+#include <sys/statfs.h>
#include <sys/types.h>
#include "def.h"
@@ -30,14 +13,20 @@
//#include "macro.h"
#include "set.h"
+#if 0 /// elogind has them set through config.h
+#define SYSTEMD_CGROUP_CONTROLLER_LEGACY "name=systemd"
+#define SYSTEMD_CGROUP_CONTROLLER_HYBRID "name=unified"
+#define SYSTEMD_CGROUP_CONTROLLER "_systemd"
+#endif // 0
+
/* An enum of well known cgroup controllers */
typedef enum CGroupController {
CGROUP_CONTROLLER_CPU,
- CGROUP_CONTROLLER_CPUACCT,
- CGROUP_CONTROLLER_IO,
- CGROUP_CONTROLLER_BLKIO,
+ CGROUP_CONTROLLER_CPUACCT, /* v1 only */
+ CGROUP_CONTROLLER_IO, /* v2 only */
+ CGROUP_CONTROLLER_BLKIO, /* v1 only */
CGROUP_CONTROLLER_MEMORY,
- CGROUP_CONTROLLER_DEVICES,
+ CGROUP_CONTROLLER_DEVICES, /* v1 only */
CGROUP_CONTROLLER_PIDS,
_CGROUP_CONTROLLER_MAX,
_CGROUP_CONTROLLER_INVALID = -1,
@@ -57,13 +46,11 @@ typedef enum CGroupMask {
_CGROUP_MASK_ALL = CGROUP_CONTROLLER_TO_MASK(_CGROUP_CONTROLLER_MAX) - 1
} CGroupMask;
-#if 0 /// UNNEEDED by elogind
/* Special values for all weight knobs on unified hierarchy */
#define CGROUP_WEIGHT_INVALID ((uint64_t) -1)
#define CGROUP_WEIGHT_MIN UINT64_C(1)
#define CGROUP_WEIGHT_MAX UINT64_C(10000)
#define CGROUP_WEIGHT_DEFAULT UINT64_C(100)
-#endif // 0
#define CGROUP_LIMIT_MIN UINT64_C(0)
#define CGROUP_LIMIT_MAX ((uint64_t) -1)
@@ -90,6 +77,7 @@ extern const uint64_t cgroup_io_limit_defaults[_CGROUP_IO_LIMIT_TYPE_MAX];
const char* cgroup_io_limit_type_to_string(CGroupIOLimitType t) _const_;
CGroupIOLimitType cgroup_io_limit_type_from_string(const char *s) _pure_;
+#endif // 0
/* Special values for the cpu.shares attribute */
#define CGROUP_CPU_SHARES_INVALID ((uint64_t) -1)
@@ -97,11 +85,13 @@ CGroupIOLimitType cgroup_io_limit_type_from_string(const char *s) _pure_;
#define CGROUP_CPU_SHARES_MAX UINT64_C(262144)
#define CGROUP_CPU_SHARES_DEFAULT UINT64_C(1024)
+#if 0 /// UNNEEDED by elogind
static inline bool CGROUP_CPU_SHARES_IS_OK(uint64_t x) {
return
x == CGROUP_CPU_SHARES_INVALID ||
(x >= CGROUP_CPU_SHARES_MIN && x <= CGROUP_CPU_SHARES_MAX);
}
+#endif // 0
/* Special values for the blkio.weight attribute */
#define CGROUP_BLKIO_WEIGHT_INVALID ((uint64_t) -1)
@@ -109,6 +99,7 @@ static inline bool CGROUP_CPU_SHARES_IS_OK(uint64_t x) {
#define CGROUP_BLKIO_WEIGHT_MAX UINT64_C(1000)
#define CGROUP_BLKIO_WEIGHT_DEFAULT UINT64_C(500)
+#if 0 /// UNNEEDED by elogind
static inline bool CGROUP_BLKIO_WEIGHT_IS_OK(uint64_t x) {
return
x == CGROUP_BLKIO_WEIGHT_INVALID ||
@@ -185,10 +176,9 @@ int cg_create_and_attach(const char *controller, const char *path, pid_t pid);
int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value);
int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret);
#if 0 /// UNNEEDED by elogind
-int cg_get_keyed_attribute(const char *controller, const char *path, const char *attribute, const char **keys, char **values);
+int cg_get_keyed_attribute(const char *controller, const char *path, const char *attribute, char **keys, char **values);
-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 cg_set_access(const char *controller, const char *path, uid_t uid, gid_t gid);
int cg_set_xattr(const char *controller, const char *path, const char *name, const void *value, size_t size, int flags);
int cg_get_xattr(const char *controller, const char *path, const char *name, void *value, size_t size);
@@ -203,29 +193,29 @@ int cg_is_empty_recursive(const char *controller, const char *path);
int cg_get_root_path(char **path);
int cg_path_get_session(const char *path, char **session);
-#if 0 /// UNNEEDED by elogind
int cg_path_get_owner_uid(const char *path, uid_t *uid);
int cg_path_get_unit(const char *path, char **unit);
+#if 0 /// UNNEEDED by elogind
int cg_path_get_user_unit(const char *path, char **unit);
int cg_path_get_machine_name(const char *path, char **machine);
+#endif // 0
int cg_path_get_slice(const char *path, char **slice);
int cg_path_get_user_slice(const char *path, char **slice);
-#endif // 0
int cg_shift_path(const char *cgroup, const char *cached_root, const char **shifted);
int cg_pid_get_path_shifted(pid_t pid, const char *cached_root, char **cgroup);
int cg_pid_get_session(pid_t pid, char **session);
-#if 0 /// UNNEEDED by elogind
int cg_pid_get_owner_uid(pid_t pid, uid_t *uid);
int cg_pid_get_unit(pid_t pid, char **unit);
+#if 0 /// UNNEEDED by elogind
int cg_pid_get_user_unit(pid_t pid, char **unit);
int cg_pid_get_machine_name(pid_t pid, char **machine);
+#endif // 0
int cg_pid_get_slice(pid_t pid, char **slice);
int cg_pid_get_user_slice(pid_t pid, char **slice);
int cg_path_decode_unit(const char *cgroup, char **unit);
-#endif // 0
char *cg_escape(const char *p);
char *cg_unescape(const char *p) _pure_;
@@ -250,7 +240,7 @@ int cg_mask_from_string(const char *s, CGroupMask *ret);
int cg_mask_to_string(CGroupMask mask, char **ret);
#if 0 /// UNNEEDED by elogind
-int cg_kernel_controllers(Set *controllers);
+int cg_kernel_controllers(Set **controllers);
bool cg_ns_supported(void);
#endif // 0
@@ -267,8 +257,8 @@ bool cg_is_hybrid_wanted(void);
const char* cgroup_controller_to_string(CGroupController c) _const_;
CGroupController cgroup_controller_from_string(const char *s) _pure_;
-#if 0 /// UNNEEDED by elogind
int cg_weight_parse(const char *s, uint64_t *ret);
+#if 0 /// UNNEEDED by elogind
int cg_cpu_shares_parse(const char *s, uint64_t *ret);
int cg_blkio_weight_parse(const char *s, uint64_t *ret);
#endif // 0
diff --git a/src/basic/conf-files.c b/src/basic/conf-files.c
index b8f0f5d03..6960a0bce 100644
--- a/src/basic/conf-files.c
+++ b/src/basic/conf-files.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <dirent.h>
#include <errno.h>
@@ -25,6 +8,7 @@
#include <string.h>
#include "conf-files.h"
+#include "def.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "hashmap.h"
@@ -32,16 +16,28 @@
#include "macro.h"
#include "missing.h"
#include "path-util.h"
+#include "set.h"
+#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
+//#include "terminal-util.h"
#include "util.h"
-static int files_add(Hashmap *h, const char *root, const char *path, const char *suffix) {
+static int files_add(
+ Hashmap *h,
+ Set *masked,
+ const char *suffix,
+ const char *root,
+ unsigned flags,
+ const char *path) {
+
_cleanup_closedir_ DIR *dir = NULL;
const char *dirpath;
struct dirent *de;
int r;
+ assert(h);
+ assert((flags & CONF_FILES_FILTER_MASKED) == 0 || masked);
assert(path);
dirpath = prefix_roota(root, path);
@@ -50,30 +46,89 @@ static int files_add(Hashmap *h, const char *root, const char *path, const char
if (!dir) {
if (errno == ENOENT)
return 0;
- return -errno;
+
+ return log_debug_errno(errno, "Failed to open directory '%s': %m", dirpath);
}
FOREACH_DIRENT(de, dir, return -errno) {
- char *p;
+ struct stat st;
+ char *p, *key;
- if (!dirent_is_file_with_suffix(de, suffix))
+ /* Does this match the suffix? */
+ if (suffix && !endswith(de->d_name, suffix))
continue;
- p = strjoin(dirpath, "/", de->d_name);
- if (!p)
- return -ENOMEM;
+ /* Has this file already been found in an earlier directory? */
+ if (hashmap_contains(h, de->d_name)) {
+ log_debug("Skipping overridden file '%s/%s'.", dirpath, de->d_name);
+ continue;
+ }
- r = hashmap_put(h, basename(p), p);
- if (r == -EEXIST) {
- log_debug("Skipping overridden file: %s.", p);
- free(p);
- } else if (r < 0) {
- free(p);
- return r;
- } else if (r == 0) {
- log_debug("Duplicate file %s", p);
+ /* Has this been masked in an earlier directory? */
+ if ((flags & CONF_FILES_FILTER_MASKED) && set_contains(masked, de->d_name)) {
+ log_debug("File '%s/%s' is masked by previous entry.", dirpath, de->d_name);
+ continue;
+ }
+
+ /* Read file metadata if we shall validate the check for file masks, for node types or whether the node is marked executable. */
+ if (flags & (CONF_FILES_FILTER_MASKED|CONF_FILES_REGULAR|CONF_FILES_DIRECTORY|CONF_FILES_EXECUTABLE))
+ if (fstatat(dirfd(dir), de->d_name, &st, 0) < 0) {
+ log_debug_errno(errno, "Failed to stat '%s/%s', ignoring: %m", dirpath, de->d_name);
+ continue;
+ }
+
+ /* Is this a masking entry? */
+ if ((flags & CONF_FILES_FILTER_MASKED))
+ if (null_or_empty(&st)) {
+ /* Mark this one as masked */
+ r = set_put_strdup(masked, de->d_name);
+ if (r < 0)
+ return r;
+
+ log_debug("File '%s/%s' is a mask.", dirpath, de->d_name);
+ continue;
+ }
+
+ /* Does this node have the right type? */
+ if (flags & (CONF_FILES_REGULAR|CONF_FILES_DIRECTORY))
+ if (!((flags & CONF_FILES_DIRECTORY) && S_ISDIR(st.st_mode)) &&
+ !((flags & CONF_FILES_REGULAR) && S_ISREG(st.st_mode))) {
+ log_debug("Ignoring '%s/%s', as it is not a of the right type.", dirpath, de->d_name);
+ continue;
+ }
+
+ /* Does this node have the executable bit set? */
+ if (flags & CONF_FILES_EXECUTABLE)
+ /* As requested: check if the file is marked exectuable. Note that we don't check access(X_OK)
+ * here, as we care about whether the file is marked executable at all, and not whether it is
+ * executable for us, because if so, such errors are stuff we should log about. */
+
+ if ((st.st_mode & 0111) == 0) { /* not executable */
+ log_debug("Ignoring '%s/%s', as it is not marked executable.", dirpath, de->d_name);
+ continue;
+ }
+
+ if (flags & CONF_FILES_BASENAME) {
+ p = strdup(de->d_name);
+ if (!p)
+ return -ENOMEM;
+
+ key = p;
+ } else {
+ p = strjoin(dirpath, "/", de->d_name);
+ if (!p)
+ return -ENOMEM;
+
+ key = basename(p);
+ }
+
+ r = hashmap_put(h, key, p);
+ if (r < 0) {
free(p);
+ return log_debug_errno(r, "Failed to add item to hashmap: %m");
}
+
+ assert(r > 0);
}
return 0;
@@ -87,8 +142,9 @@ static int base_cmp(const void *a, const void *b) {
return strcmp(basename(s1), basename(s2));
}
-static int conf_files_list_strv_internal(char ***strv, const char *suffix, const char *root, char **dirs) {
+static int conf_files_list_strv_internal(char ***strv, const char *suffix, const char *root, unsigned flags, char **dirs) {
_cleanup_hashmap_free_ Hashmap *fh = NULL;
+ _cleanup_set_free_free_ Set *masked = NULL;
char **files, **p;
int r;
@@ -98,12 +154,18 @@ static int conf_files_list_strv_internal(char ***strv, const char *suffix, const
if (!path_strv_resolve_uniq(dirs, root))
return -ENOMEM;
- fh = hashmap_new(&string_hash_ops);
+ fh = hashmap_new(&path_hash_ops);
if (!fh)
return -ENOMEM;
+ if (flags & CONF_FILES_FILTER_MASKED) {
+ masked = set_new(&path_hash_ops);
+ if (!masked)
+ return -ENOMEM;
+ }
+
STRV_FOREACH(p, dirs) {
- r = files_add(fh, root, *p, suffix);
+ r = files_add(fh, masked, suffix, root, flags, *p);
if (r == -ENOMEM)
return r;
if (r < 0)
@@ -120,7 +182,83 @@ static int conf_files_list_strv_internal(char ***strv, const char *suffix, const
return 0;
}
-int conf_files_list_strv(char ***strv, const char *suffix, const char *root, const char* const* dirs) {
+int conf_files_insert(char ***strv, const char *root, char **dirs, const char *path) {
+ /* Insert a path into strv, at the place honouring the usual sorting rules:
+ * - we first compare by the basename
+ * - and then we compare by dirname, allowing just one file with the given
+ * basename.
+ * This means that we will
+ * - add a new entry if basename(path) was not on the list,
+ * - do nothing if an entry with higher priority was already present,
+ * - do nothing if our new entry matches the existing entry,
+ * - replace the existing entry if our new entry has higher priority.
+ */
+ size_t i;
+ char *t;
+ int r;
+
+ for (i = 0; i < strv_length(*strv); i++) {
+ int c;
+
+ c = base_cmp(*strv + i, &path);
+ if (c == 0) {
+ char **dir;
+
+ /* Oh, we found our spot and it already contains something. */
+ STRV_FOREACH(dir, dirs) {
+ char *p1, *p2;
+
+ p1 = path_startswith((*strv)[i], root);
+ if (p1)
+ /* Skip "/" in *dir, because p1 is without "/" too */
+ p1 = path_startswith(p1, *dir + 1);
+ if (p1)
+ /* Existing entry with higher priority
+ * or same priority, no need to do anything. */
+ return 0;
+
+ p2 = path_startswith(path, *dir);
+ if (p2) {
+ /* Our new entry has higher priority */
+ t = path_join(root, path, NULL);
+ if (!t)
+ return log_oom();
+
+ return free_and_replace((*strv)[i], t);
+ }
+ }
+
+ } else if (c > 0)
+ /* Following files have lower priority, let's go insert our
+ * new entry. */
+ break;
+
+ /* … we are not there yet, let's continue */
+ }
+
+ t = path_join(root, path, NULL);
+ if (!t)
+ return log_oom();
+
+ r = strv_insert(strv, i, t);
+ if (r < 0)
+ free(t);
+ return r;
+}
+
+int conf_files_insert_nulstr(char ***strv, const char *root, const char *dirs, const char *path) {
+ _cleanup_strv_free_ char **d = NULL;
+
+ assert(strv);
+
+ d = strv_split_nulstr(dirs);
+ if (!d)
+ return -ENOMEM;
+
+ return conf_files_insert(strv, root, d, path);
+}
+
+int conf_files_list_strv(char ***strv, const char *suffix, const char *root, unsigned flags, const char* const* dirs) {
_cleanup_strv_free_ char **copy = NULL;
assert(strv);
@@ -129,10 +267,10 @@ int conf_files_list_strv(char ***strv, const char *suffix, const char *root, con
if (!copy)
return -ENOMEM;
- return conf_files_list_strv_internal(strv, suffix, root, copy);
+ return conf_files_list_strv_internal(strv, suffix, root, flags, copy);
}
-int conf_files_list(char ***strv, const char *suffix, const char *root, const char *dir, ...) {
+int conf_files_list(char ***strv, const char *suffix, const char *root, unsigned flags, const char *dir, ...) {
_cleanup_strv_free_ char **dirs = NULL;
va_list ap;
@@ -145,17 +283,87 @@ int conf_files_list(char ***strv, const char *suffix, const char *root, const ch
if (!dirs)
return -ENOMEM;
- return conf_files_list_strv_internal(strv, suffix, root, dirs);
+ return conf_files_list_strv_internal(strv, suffix, root, flags, dirs);
}
-int conf_files_list_nulstr(char ***strv, const char *suffix, const char *root, const char *d) {
- _cleanup_strv_free_ char **dirs = NULL;
+int conf_files_list_nulstr(char ***strv, const char *suffix, const char *root, unsigned flags, const char *dirs) {
+ _cleanup_strv_free_ char **d = NULL;
assert(strv);
- dirs = strv_split_nulstr(d);
- if (!dirs)
+ d = strv_split_nulstr(dirs);
+ if (!d)
return -ENOMEM;
- return conf_files_list_strv_internal(strv, suffix, root, dirs);
+ return conf_files_list_strv_internal(strv, suffix, root, flags, d);
+}
+
+int conf_files_list_with_replacement(
+ const char *root,
+ char **config_dirs,
+ const char *replacement,
+ char ***files,
+ char **replace_file) {
+
+ _cleanup_strv_free_ char **f = NULL;
+ _cleanup_free_ char *p = NULL;
+ int r;
+
+ assert(config_dirs);
+ assert(files);
+ assert(replace_file || !replacement);
+
+ r = conf_files_list_strv(&f, ".conf", root, 0, (const char* const*) config_dirs);
+ if (r < 0)
+ return log_error_errno(r, "Failed to enumerate config files: %m");
+
+ if (replacement) {
+ r = conf_files_insert(&f, root, config_dirs, replacement);
+ if (r < 0)
+ return log_error_errno(r, "Failed to extend config file list: %m");
+
+ p = path_join(root, replacement, NULL);
+ if (!p)
+ return log_oom();
+ }
+
+ *files = TAKE_PTR(f);
+ if (replace_file)
+ *replace_file = TAKE_PTR(p);
+ return 0;
+}
+
+#if 0 /// UNNEEDED by elogind
+int conf_files_cat(const char *root, const char *name) {
+ _cleanup_strv_free_ char **dirs = NULL, **files = NULL;
+ _cleanup_free_ char *path = NULL;
+ const char *dir;
+ char **t;
+ int r;
+
+ NULSTR_FOREACH(dir, CONF_PATHS_NULSTR("")) {
+ assert(endswith(dir, "/"));
+ r = strv_extendf(&dirs, "%s%s.d", dir, name);
+ if (r < 0)
+ return log_error_errno(r, "Failed to build directory list: %m");
+ }
+
+ r = conf_files_list_strv(&files, ".conf", root, 0, (const char* const*) dirs);
+ if (r < 0)
+ return log_error_errno(r, "Failed to query file list: %m");
+
+ path = path_join(root, "/etc", name);
+ if (!path)
+ return log_oom();
+
+ if (DEBUG_LOGGING) {
+ log_debug("Looking for configuration in:");
+ log_debug(" %s", path);
+ STRV_FOREACH(t, dirs)
+ log_debug(" %s/*.conf", *t);
+ }
+
+ /* show */
+ return cat_files(path, files, CAT_FLAGS_MAIN_FILE_OPTIONAL);
}
+#endif // 0
diff --git a/src/basic/conf-files.h b/src/basic/conf-files.h
index e00e0e81f..16fcc5736 100644
--- a/src/basic/conf-files.h
+++ b/src/basic/conf-files.h
@@ -1,25 +1,26 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
- Copyright 2010-2012 Lennart Poettering
- Copyright 2010-2012 Kay Sievers
+enum {
+ CONF_FILES_EXECUTABLE = 1 << 0,
+ CONF_FILES_REGULAR = 1 << 1,
+ CONF_FILES_DIRECTORY = 1 << 2,
+ CONF_FILES_BASENAME = 1 << 3,
+ CONF_FILES_FILTER_MASKED = 1 << 4,
+};
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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 conf_files_list(char ***ret, const char *suffix, const char *root, const char *dir, ...);
-int conf_files_list_strv(char ***ret, const char *suffix, const char *root, const char* const* dirs);
-int conf_files_list_nulstr(char ***ret, const char *suffix, const char *root, const char *dirs);
+int conf_files_list(char ***ret, const char *suffix, const char *root, unsigned flags, const char *dir, ...);
+int conf_files_list_strv(char ***ret, const char *suffix, const char *root, unsigned flags, const char* const* dirs);
+int conf_files_list_nulstr(char ***ret, const char *suffix, const char *root, unsigned flags, const char *dirs);
+int conf_files_insert(char ***strv, const char *root, char **dirs, const char *path);
+int conf_files_insert_nulstr(char ***strv, const char *root, const char *dirs, const char *path);
+int conf_files_list_with_replacement(
+ const char *root,
+ char **config_dirs,
+ const char *replacement,
+ char ***files,
+ char **replace_file);
+#if 0 /// UNNEEDED by elogind
+int conf_files_cat(const char *root, const char *name);
+#endif // 0
diff --git a/src/basic/copy.c b/src/basic/copy.c
index 37212be22..aaefc3a51 100644
--- a/src/basic/copy.c
+++ b/src/basic/copy.c
@@ -1,26 +1,9 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
//#include <dirent.h>
//#include <errno.h>
//#include <fcntl.h>
-//#include <stddef.h>
+#include <stddef.h>
//#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
@@ -40,64 +23,160 @@
//#include "fs-util.h"
#include "io-util.h"
//#include "macro.h"
+#include "missing.h"
+//#include "mount-util.h"
//#include "string-util.h"
#include "strv.h"
#include "time-util.h"
//#include "umask-util.h"
+#include "user-util.h"
//#include "xattr-util.h"
-#define COPY_BUFFER_SIZE (16*1024u)
+#define COPY_BUFFER_SIZE (16U*1024U)
+
+/* A safety net for descending recursively into file system trees to copy. On Linux PATH_MAX is 4096, which means the
+ * deepest valid path one can build is around 2048, which we hence use as a safety net here, to not spin endlessly in
+ * case of bind mount cycles and suchlike. */
+#define COPY_DEPTH_MAX 2048U
+
+static ssize_t try_copy_file_range(
+ int fd_in, loff_t *off_in,
+ int fd_out, loff_t *off_out,
+ size_t len,
+ unsigned int flags) {
-static ssize_t try_copy_file_range(int fd_in, loff_t *off_in,
- int fd_out, loff_t *off_out,
- size_t len,
- unsigned int flags) {
static int have = -1;
ssize_t r;
- if (have == false)
+ if (have == 0)
return -ENOSYS;
r = copy_file_range(fd_in, off_in, fd_out, off_out, len, flags);
- if (_unlikely_(have < 0))
+ if (have < 0)
have = r >= 0 || errno != ENOSYS;
- if (r >= 0)
- return r;
- else
+ if (r < 0)
+ return -errno;
+
+ return r;
+}
+
+enum {
+ FD_IS_NO_PIPE,
+ FD_IS_BLOCKING_PIPE,
+ FD_IS_NONBLOCKING_PIPE,
+};
+
+static int fd_is_nonblock_pipe(int fd) {
+ struct stat st;
+ int flags;
+
+ /* Checks whether the specified file descriptor refers to a pipe, and if so if O_NONBLOCK is set. */
+
+ if (fstat(fd, &st) < 0)
return -errno;
+
+ if (!S_ISFIFO(st.st_mode))
+ return FD_IS_NO_PIPE;
+
+ flags = fcntl(fd, F_GETFL);
+ if (flags < 0)
+ return -errno;
+
+ return FLAGS_SET(flags, O_NONBLOCK) ? FD_IS_NONBLOCKING_PIPE : FD_IS_BLOCKING_PIPE;
}
-int copy_bytes(int fdf, int fdt, uint64_t max_bytes, CopyFlags copy_flags) {
+int copy_bytes_full(
+ int fdf, int fdt,
+ uint64_t max_bytes,
+ CopyFlags copy_flags,
+ void **ret_remains,
+ size_t *ret_remains_size) {
+
bool try_cfr = true, try_sendfile = true, try_splice = true;
- int r;
+ int r, nonblock_pipe = -1;
size_t m = SSIZE_MAX; /* that is the maximum that sendfile and c_f_r accept */
assert(fdf >= 0);
assert(fdt >= 0);
+ /* Tries to copy bytes from the file descriptor 'fdf' to 'fdt' in the smartest possible way. Copies a maximum
+ * of 'max_bytes', which may be specified as UINT64_MAX, in which no maximum is applied. Returns negative on
+ * error, zero if EOF is hit before the bytes limit is hit and positive otherwise. If the copy fails for some
+ * reason but we read but didn't yet write some data an ret_remains/ret_remains_size is not NULL, then it will
+ * be initialized with an allocated buffer containing this "remaining" data. Note that these two parameters are
+ * initialized with a valid buffer only on failure and only if there's actually data already read. Otherwise
+ * these parameters if non-NULL are set to NULL. */
+
+ if (ret_remains)
+ *ret_remains = NULL;
+ if (ret_remains_size)
+ *ret_remains_size = 0;
+
#if 0 /// UNNEEDED by elogind
- /* Try btrfs reflinks first. */
- if ((copy_flags & COPY_REFLINK) &&
- max_bytes == (uint64_t) -1 &&
- lseek(fdf, 0, SEEK_CUR) == 0 &&
- lseek(fdt, 0, SEEK_CUR) == 0) {
-
- r = btrfs_reflink(fdf, fdt);
- if (r >= 0)
- return 0; /* we copied the whole thing, hence hit EOF, return 0 */
+ /* Try btrfs reflinks first. This only works on regular, seekable files, hence let's check the file offsets of
+ * source and destination first. */
+ if ((copy_flags & COPY_REFLINK)) {
+ off_t foffset;
+
+ foffset = lseek(fdf, 0, SEEK_CUR);
+ if (foffset >= 0) {
+ off_t toffset;
+
+ toffset = lseek(fdt, 0, SEEK_CUR);
+ if (toffset >= 0) {
+
+ if (foffset == 0 && toffset == 0 && max_bytes == UINT64_MAX)
+ r = btrfs_reflink(fdf, fdt); /* full file reflink */
+ else
+ r = btrfs_clone_range(fdf, foffset, fdt, toffset, max_bytes == UINT64_MAX ? 0 : max_bytes); /* partial reflink */
+ if (r >= 0) {
+ off_t t;
+
+ /* This worked, yay! Now — to be fully correct — let's adjust the file pointers */
+ if (max_bytes == UINT64_MAX) {
+
+ /* We cloned to the end of the source file, let's position the read
+ * pointer there, and query it at the same time. */
+ t = lseek(fdf, 0, SEEK_END);
+ if (t < 0)
+ return -errno;
+ if (t < foffset)
+ return -ESPIPE;
+
+ /* Let's adjust the destination file write pointer by the same number
+ * of bytes. */
+ t = lseek(fdt, toffset + (t - foffset), SEEK_SET);
+ if (t < 0)
+ return -errno;
+
+ return 0; /* we copied the whole thing, hence hit EOF, return 0 */
+ } else {
+ t = lseek(fdf, foffset + max_bytes, SEEK_SET);
+ if (t < 0)
+ return -errno;
+
+ t = lseek(fdt, toffset + max_bytes, SEEK_SET);
+ if (t < 0)
+ return -errno;
+
+ return 1; /* we copied only some number of bytes, which worked, but this means we didn't hit EOF, return 1 */
+ }
+ }
+
+ log_debug_errno(r, "Reflinking didn't work, falling back to non-reflink copying: %m");
+ }
+ }
}
#endif // 0
for (;;) {
ssize_t n;
- if (max_bytes != (uint64_t) -1) {
- if (max_bytes <= 0)
- return 1; /* return > 0 if we hit the max_bytes limit */
+ if (max_bytes <= 0)
+ return 1; /* return > 0 if we hit the max_bytes limit */
- if (m > max_bytes)
- m = max_bytes;
- }
+ if (max_bytes != UINT64_MAX && m > max_bytes)
+ m = max_bytes;
/* First try copy_file_range(), unless we already tried */
if (try_cfr) {
@@ -131,9 +210,51 @@ int copy_bytes(int fdf, int fdt, uint64_t max_bytes, CopyFlags copy_flags) {
goto next;
}
- /* Then try splice, unless we already tried */
+ /* Then try splice, unless we already tried. */
+ if (try_splice) {
+
+ /* splice()'s asynchronous I/O support is a bit weird. When it encounters a pipe file
+ * descriptor, then it will ignore its O_NONBLOCK flag and instead only honour the
+ * SPLICE_F_NONBLOCK flag specified in its flag parameter. Let's hide this behaviour here, and
+ * check if either of the specified fds are a pipe, and if so, let's pass the flag
+ * automatically, depending on O_NONBLOCK being set.
+ *
+ * Here's a twist though: when we use it to move data between two pipes of which one has
+ * O_NONBLOCK set and the other has not, then we have no individual control over O_NONBLOCK
+ * behaviour. Hence in that case we can't use splice() and still guarantee systematic
+ * O_NONBLOCK behaviour, hence don't. */
+
+ if (nonblock_pipe < 0) {
+ int a, b;
+
+ /* Check if either of these fds is a pipe, and if so non-blocking or not */
+ a = fd_is_nonblock_pipe(fdf);
+ if (a < 0)
+ return a;
+
+ b = fd_is_nonblock_pipe(fdt);
+ if (b < 0)
+ return b;
+
+ if ((a == FD_IS_NO_PIPE && b == FD_IS_NO_PIPE) ||
+ (a == FD_IS_BLOCKING_PIPE && b == FD_IS_NONBLOCKING_PIPE) ||
+ (a == FD_IS_NONBLOCKING_PIPE && b == FD_IS_BLOCKING_PIPE))
+
+ /* splice() only works if one of the fds is a pipe. If neither is, let's skip
+ * this step right-away. As mentioned above, if one of the two fds refers to a
+ * blocking pipe and the other to a non-blocking pipe, we can't use splice()
+ * either, hence don't try either. This hence means we can only use splice() if
+ * either only one of the two fds is a pipe, or if both are pipes with the same
+ * nonblocking flag setting. */
+
+ try_splice = false;
+ else
+ nonblock_pipe = a == FD_IS_NONBLOCKING_PIPE || b == FD_IS_NONBLOCKING_PIPE;
+ }
+ }
+
if (try_splice) {
- n = splice(fdf, NULL, fdt, NULL, m, 0);
+ n = splice(fdf, NULL, fdt, NULL, m, nonblock_pipe ? SPLICE_F_NONBLOCK : 0);
if (n < 0) {
if (!IN_SET(errno, EINVAL, ENOSYS))
return -errno;
@@ -149,7 +270,8 @@ int copy_bytes(int fdf, int fdt, uint64_t max_bytes, CopyFlags copy_flags) {
/* As a fallback just copy bits by hand */
{
- uint8_t buf[MIN(m, COPY_BUFFER_SIZE)];
+ uint8_t buf[MIN(m, COPY_BUFFER_SIZE)], *p = buf;
+ ssize_t z;
n = read(fdf, buf, sizeof buf);
if (n < 0)
@@ -157,9 +279,34 @@ int copy_bytes(int fdf, int fdt, uint64_t max_bytes, CopyFlags copy_flags) {
if (n == 0) /* EOF */
break;
- r = loop_write(fdt, buf, (size_t) n, false);
- if (r < 0)
- return r;
+ z = (size_t) n;
+ do {
+ ssize_t k;
+
+ k = write(fdt, p, z);
+ if (k < 0) {
+ r = -errno;
+
+ if (ret_remains) {
+ void *copy;
+
+ copy = memdup(p, z);
+ if (!copy)
+ return -ENOMEM;
+
+ *ret_remains = copy;
+ }
+
+ if (ret_remains_size)
+ *ret_remains_size = z;
+
+ return r;
+ }
+
+ assert(k <= z);
+ z -= k;
+ p += k;
+ } while (z > 0);
}
next:
@@ -239,7 +386,7 @@ static int fd_copy_regular(
r = copy_bytes(fdf, fdt, (uint64_t) -1, copy_flags);
if (r < 0) {
- unlinkat(dt, to, 0);
+ (void) unlinkat(dt, to, 0);
return r;
}
@@ -261,7 +408,7 @@ static int fd_copy_regular(
if (q < 0) {
r = -errno;
- unlinkat(dt, to, 0);
+ (void) unlinkat(dt, to, 0);
}
return r;
@@ -336,6 +483,7 @@ static int fd_copy_directory(
int dt,
const char *to,
dev_t original_device,
+ unsigned depth_left,
uid_t override_uid,
gid_t override_gid,
CopyFlags copy_flags) {
@@ -349,6 +497,9 @@ static int fd_copy_directory(
assert(st);
assert(to);
+ if (depth_left == 0)
+ return -ENAMETOOLONG;
+
if (from)
fdf = openat(df, from, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
else
@@ -387,13 +538,40 @@ static int fd_copy_directory(
continue;
}
- if (buf.st_dev != original_device)
- continue;
+ if (S_ISDIR(buf.st_mode)) {
+ /*
+ * Don't descend into directories on other file systems, if this is requested. We do a simple
+ * .st_dev check here, which basically comes for free. Note that we do this check only on
+ * directories, not other kind of file system objects, for two reason:
+ *
+ * • The kernel's overlayfs pseudo file system that overlays multiple real file systems
+ * propagates the .st_dev field of the file system a file originates from all the way up
+ * through the stack to stat(). It doesn't do that for directories however. This means that
+ * comparing .st_dev on non-directories suggests that they all are mount points. To avoid
+ * confusion we hence avoid relying on this check for regular files.
+ *
+ * • The main reason we do this check at all is to protect ourselves from bind mount cycles,
+ * where we really want to avoid descending down in all eternity. However the .st_dev check
+ * is usually not sufficient for this protection anyway, as bind mount cycles from the same
+ * file system onto itself can't be detected that way. (Note we also do a recursion depth
+ * check, which is probably the better protection in this regard, which is why
+ * COPY_SAME_MOUNT is optional).
+ */
+
+ if (FLAGS_SET(copy_flags, COPY_SAME_MOUNT)) {
+ if (buf.st_dev != original_device)
+ continue;
- if (S_ISREG(buf.st_mode))
+ r = fd_is_mount_point(dirfd(d), de->d_name, 0);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ continue;
+ }
+
+ q = fd_copy_directory(dirfd(d), de->d_name, &buf, fdt, de->d_name, original_device, depth_left-1, override_uid, override_gid, copy_flags);
+ } else if (S_ISREG(buf.st_mode))
q = fd_copy_regular(dirfd(d), de->d_name, &buf, fdt, de->d_name, override_uid, override_gid, copy_flags);
- else if (S_ISDIR(buf.st_mode))
- q = fd_copy_directory(dirfd(d), de->d_name, &buf, fdt, de->d_name, original_device, override_uid, override_gid, copy_flags);
else if (S_ISLNK(buf.st_mode))
q = fd_copy_symlink(dirfd(d), de->d_name, &buf, fdt, de->d_name, override_uid, override_gid, copy_flags);
else if (S_ISFIFO(buf.st_mode))
@@ -443,7 +621,7 @@ int copy_tree_at(int fdf, const char *from, int fdt, const char *to, uid_t overr
if (S_ISREG(st.st_mode))
return fd_copy_regular(fdf, from, &st, fdt, to, override_uid, override_gid, copy_flags);
else if (S_ISDIR(st.st_mode))
- return fd_copy_directory(fdf, from, &st, fdt, to, st.st_dev, override_uid, override_gid, copy_flags);
+ return fd_copy_directory(fdf, from, &st, fdt, to, st.st_dev, COPY_DEPTH_MAX, override_uid, override_gid, copy_flags);
else if (S_ISLNK(st.st_mode))
return fd_copy_symlink(fdf, from, &st, fdt, to, override_uid, override_gid, copy_flags);
else if (S_ISFIFO(st.st_mode))
@@ -470,7 +648,7 @@ int copy_directory_fd(int dirfd, const char *to, CopyFlags copy_flags) {
if (!S_ISDIR(st.st_mode))
return -ENOTDIR;
- return fd_copy_directory(dirfd, NULL, &st, AT_FDCWD, to, st.st_dev, UID_INVALID, GID_INVALID, copy_flags);
+ return fd_copy_directory(dirfd, NULL, &st, AT_FDCWD, to, st.st_dev, COPY_DEPTH_MAX, UID_INVALID, GID_INVALID, copy_flags);
}
int copy_directory(const char *from, const char *to, CopyFlags copy_flags) {
@@ -485,7 +663,7 @@ int copy_directory(const char *from, const char *to, CopyFlags copy_flags) {
if (!S_ISDIR(st.st_mode))
return -ENOTDIR;
- return fd_copy_directory(AT_FDCWD, from, &st, AT_FDCWD, to, st.st_dev, UID_INVALID, GID_INVALID, copy_flags);
+ return fd_copy_directory(AT_FDCWD, from, &st, AT_FDCWD, to, st.st_dev, COPY_DEPTH_MAX, UID_INVALID, GID_INVALID, copy_flags);
}
int copy_file_fd(const char *from, int fdt, CopyFlags copy_flags) {
@@ -525,7 +703,7 @@ int copy_file(const char *from, const char *to, int flags, mode_t mode, unsigned
r = copy_file_fd(from, fdt, copy_flags);
if (r < 0) {
close(fdt);
- unlink(to);
+ (void) unlink(to);
return r;
}
@@ -538,31 +716,55 @@ int copy_file(const char *from, const char *to, int flags, mode_t mode, unsigned
}
int copy_file_atomic(const char *from, const char *to, mode_t mode, unsigned chattr_flags, CopyFlags copy_flags) {
- _cleanup_free_ char *t = NULL;
+ _cleanup_(unlink_and_freep) char *t = NULL;
+ _cleanup_close_ int fdt = -1;
int r;
assert(from);
assert(to);
- r = tempfn_random(to, NULL, &t);
- if (r < 0)
- return r;
+ /* We try to use O_TMPFILE here to create the file if we can. Note that that only works if COPY_REPLACE is not
+ * set though as we need to use linkat() for linking the O_TMPFILE file into the file system but that system
+ * call can't replace existing files. Hence, if COPY_REPLACE is set we create a temporary name in the file
+ * system right-away and unconditionally which we then can renameat() to the right name after we completed
+ * writing it. */
- r = copy_file(from, t, O_NOFOLLOW|O_EXCL, mode, chattr_flags, copy_flags);
+ if (copy_flags & COPY_REPLACE) {
+ r = tempfn_random(to, NULL, &t);
+ if (r < 0)
+ return r;
+
+ fdt = open(t, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|O_WRONLY|O_CLOEXEC, 0600);
+ if (fdt < 0) {
+ t = mfree(t);
+ return -errno;
+ }
+ } else {
+ fdt = open_tmpfile_linkable(to, O_WRONLY|O_CLOEXEC, &t);
+ if (fdt < 0)
+ return fdt;
+ }
+
+ if (chattr_flags != 0)
+ (void) chattr_fd(fdt, chattr_flags, (unsigned) -1);
+
+ r = copy_file_fd(from, fdt, copy_flags);
if (r < 0)
return r;
+ if (fchmod(fdt, mode) < 0)
+ return -errno;
+
if (copy_flags & COPY_REPLACE) {
- r = renameat(AT_FDCWD, t, AT_FDCWD, to);
+ if (renameat(AT_FDCWD, t, AT_FDCWD, to) < 0)
+ return -errno;
+ } else {
+ r = link_tmpfile(fdt, t, to);
if (r < 0)
- r = -errno;
- } else
- r = rename_noreplace(AT_FDCWD, t, AT_FDCWD, to);
- if (r < 0) {
- (void) unlink(t);
- return r;
+ return r;
}
+ t = mfree(t);
return 0;
}
diff --git a/src/basic/copy.h b/src/basic/copy.h
index d46f1c92a..e79140593 100644
--- a/src/basic/copy.h
+++ b/src/basic/copy.h
@@ -1,33 +1,16 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 <stdint.h>
#include <sys/types.h>
typedef enum CopyFlags {
- COPY_REFLINK = 0x1, /* try to reflink */
- COPY_MERGE = 0x2, /* merge existing trees with our new one to copy */
- COPY_REPLACE = 0x4, /* replace an existing file if there's one */
+ COPY_REFLINK = 1 << 0, /* Try to reflink */
+ COPY_MERGE = 1 << 1, /* Merge existing trees with our new one to copy */
+ COPY_REPLACE = 1 << 2, /* Replace an existing file if there's one */
+ COPY_SAME_MOUNT = 1 << 3, /* Don't descend recursively into other file systems, across mount point boundaries */
} CopyFlags;
#if 0 /// UNNEEDED by elogind
@@ -39,7 +22,10 @@ int copy_tree_at(int fdf, const char *from, int fdt, const char *to, uid_t overr
int copy_directory_fd(int dirfd, const char *to, CopyFlags copy_flags);
int copy_directory(const char *from, const char *to, CopyFlags copy_flags);
#endif // 0
-int copy_bytes(int fdf, int fdt, uint64_t max_bytes, CopyFlags copy_flags);
+int copy_bytes_full(int fdf, int fdt, uint64_t max_bytes, CopyFlags copy_flags, void **ret_remains, size_t *ret_remains_size);
+static inline int copy_bytes(int fdf, int fdt, uint64_t max_bytes, CopyFlags copy_flags) {
+ return copy_bytes_full(fdf, fdt, max_bytes, copy_flags, NULL, NULL);
+}
#if 0 /// UNNEEDED by elogind
int copy_times(int fdf, int fdt);
int copy_xattr(int fdf, int fdt);
diff --git a/src/basic/def.h b/src/basic/def.h
index cce32da1e..ee4c672ac 100644
--- a/src/basic/def.h
+++ b/src/basic/def.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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)
@@ -37,9 +19,6 @@
#define DEFAULT_UNIX_MAX_DGRAM_QLEN 512UL
#if 0 /// elogind allows foreign cgroup controllers. (Well, needs them, actually)
-#define SYSTEMD_CGROUP_CONTROLLER_LEGACY "name=systemd"
-#define SYSTEMD_CGROUP_CONTROLLER_HYBRID "name=unified"
-#define SYSTEMD_CGROUP_CONTROLLER "_systemd"
#else
#ifndef SYSTEMD_CGROUP_CONTROLLER_LEGACY
# define SYSTEMD_CGROUP_CONTROLLER_LEGACY "name=elogind"
@@ -51,11 +30,10 @@
# define SYSTEMD_CGROUP_CONTROLLER "_elogind"
#endif // SYSTEMD_CGROUP_CONTROLLER
#endif // 0
-
#define SIGNALS_CRASH_HANDLER SIGSEGV,SIGILL,SIGFPE,SIGBUS,SIGQUIT,SIGABRT
#define SIGNALS_IGNORE SIGPIPE
-#ifdef HAVE_SPLIT_USR
+#if HAVE_SPLIT_USR
#define KBD_KEYMAP_DIRS \
"/usr/share/keymaps/\0" \
"/usr/share/kbd/keymaps/\0" \
@@ -68,11 +46,19 @@
"/usr/lib/kbd/keymaps/\0"
#endif
-#define UNIX_SYSTEM_BUS_ADDRESS "unix:path=/var/run/dbus/system_bus_socket"
-#define KERNEL_SYSTEM_BUS_ADDRESS "kernel:path=/sys/fs/kdbus/0-system/bus"
-#define DEFAULT_SYSTEM_BUS_ADDRESS KERNEL_SYSTEM_BUS_ADDRESS ";" UNIX_SYSTEM_BUS_ADDRESS
-#define UNIX_USER_BUS_ADDRESS_FMT "unix:path=%s/bus"
-#define KERNEL_USER_BUS_ADDRESS_FMT "kernel:path=/sys/fs/kdbus/"UID_FMT"-user/bus"
+/* Note that we use the new /run prefix here (instead of /var/run) since we require them to be aliases and that way we
+ * become independent of /var being mounted */
+#if 0 /// elogind should support both /run/dbus & /var/run/dbus (per Linux FHS)
+#define DEFAULT_SYSTEM_BUS_ADDRESS "unix:path=/run/dbus/system_bus_socket"
+#else
+/* Not all systems have dbus hierarchy in /run (as preferred by systemd) */
+#if VARRUN_IS_SYMLINK
+ #define DEFAULT_SYSTEM_BUS_ADDRESS "unix:path=/run/dbus/system_bus_socket"
+#else
+ #define DEFAULT_SYSTEM_BUS_ADDRESS "unix:path=/var/run/dbus/system_bus_socket"
+#endif // VARRUN_IS_SYMLINK
+#endif // 0
+#define DEFAULT_USER_BUS_ADDRESS_FMT "unix:path=%s/bus"
#define PLYMOUTH_SOCKET { \
.un.sun_family = AF_UNIX, \
@@ -82,9 +68,11 @@
#define NOTIFY_FD_MAX 768
#define NOTIFY_BUFFER_MAX PIPE_BUF
-#ifdef HAVE_SPLIT_USR
-# define _CONF_PATHS_SPLIT_USR(n) "/lib/" n "\0"
+#if HAVE_SPLIT_USR
+# define _CONF_PATHS_SPLIT_USR_NULSTR(n) "/lib/" n "\0"
+# define _CONF_PATHS_SPLIT_USR(n) , "/lib/" n
#else
+# define _CONF_PATHS_SPLIT_USR_NULSTR(n)
# define _CONF_PATHS_SPLIT_USR(n)
#endif
@@ -97,4 +85,14 @@
"/run/" n "\0" \
"/usr/local/lib/" n "\0" \
"/usr/lib/" n "\0" \
- _CONF_PATHS_SPLIT_USR(n)
+ _CONF_PATHS_SPLIT_USR_NULSTR(n)
+
+#define CONF_PATHS_STRV(n) \
+ STRV_MAKE( \
+ "/etc/" n, \
+ "/run/" n, \
+ "/usr/local/lib/" n, \
+ "/usr/lib/" n \
+ _CONF_PATHS_SPLIT_USR(n))
+
+#define LONG_LINE_MAX (1U*1024U*1024U)
diff --git a/src/basic/dirent-util.c b/src/basic/dirent-util.c
index 5bf58bcdc..d1d2c0ef4 100644
--- a/src/basic/dirent-util.c
+++ b/src/basic/dirent-util.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <fcntl.h>
#include <sys/stat.h>
diff --git a/src/basic/dirent-util.h b/src/basic/dirent-util.h
index 18b9db9b2..b1b87679d 100644
--- a/src/basic/dirent-util.h
+++ b/src/basic/dirent-util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <dirent.h>
#include <errno.h>
#include <stdbool.h>
diff --git a/src/basic/env-util.c b/src/basic/env-util.c
index 47c1fccd3..adb88c2c5 100644
--- a/src/basic/env-util.c
+++ b/src/basic/env-util.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <limits.h>
@@ -83,9 +66,9 @@ bool env_value_is_valid(const char *e) {
if (!utf8_is_valid(e))
return false;
- /* bash allows tabs in environment variables, and so should
- * we */
- if (string_has_cc(e, "\t"))
+ /* bash allows tabs and newlines in environment variables, and so
+ * should we */
+ if (string_has_cc(e, "\t\n"))
return false;
/* POSIX says the overall size of the environment block cannot
@@ -209,11 +192,11 @@ static int env_append(char **r, char ***k, char **a) {
return 0;
}
-char **strv_env_merge(unsigned n_lists, ...) {
+char **strv_env_merge(size_t n_lists, ...) {
size_t n = 0;
char **l, **k, **r;
va_list ap;
- unsigned i;
+ size_t i;
/* Merges an arbitrary number of environment sets */
@@ -288,7 +271,7 @@ static bool env_entry_has_name(const char *entry, const char *name) {
return *t == '=';
}
-char **strv_env_delete(char **x, unsigned n_lists, ...) {
+char **strv_env_delete(char **x, size_t n_lists, ...) {
size_t n, i = 0;
char **k, **r;
va_list ap;
@@ -303,7 +286,7 @@ char **strv_env_delete(char **x, unsigned n_lists, ...) {
return NULL;
STRV_FOREACH(k, x) {
- unsigned v;
+ size_t v;
va_start(ap, n_lists);
for (v = 0; v < n_lists; v++) {
@@ -430,7 +413,8 @@ int strv_env_replace(char ***l, char *p) {
char **strv_env_set(char **x, const char *p) {
- char **k, **r;
+ char **k;
+ _cleanup_strv_free_ char **r = NULL;
char* m[2] = { (char*) p, NULL };
/* Overrides the env var setting of p, returns a new copy */
@@ -441,18 +425,14 @@ char **strv_env_set(char **x, const char *p) {
k = r;
if (env_append(r, &k, x) < 0)
- goto fail;
+ return NULL;
if (env_append(r, &k, m) < 0)
- goto fail;
+ return NULL;
*k = NULL;
- return r;
-
-fail:
- strv_free(r);
- return NULL;
+ return TAKE_PTR(r);
}
char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) {
@@ -539,8 +519,7 @@ char *replace_env_n(const char *format, size_t n, char **env, unsigned flags) {
assert(format);
- for (e = format, i = 0; *e && i < n; e ++, i ++) {
-
+ for (e = format, i = 0; *e && i < n; e ++, i ++)
switch (state) {
case WORD:
@@ -554,8 +533,7 @@ char *replace_env_n(const char *format, size_t n, char **env, unsigned flags) {
if (!k)
return NULL;
- free(r);
- r = k;
+ free_and_replace(r, k);
word = e-1;
state = VARIABLE;
@@ -565,8 +543,7 @@ char *replace_env_n(const char *format, size_t n, char **env, unsigned flags) {
if (!k)
return NULL;
- free(r);
- r = k;
+ free_and_replace(r, k);
word = e+1;
state = WORD;
@@ -576,8 +553,7 @@ char *replace_env_n(const char *format, size_t n, char **env, unsigned flags) {
if (!k)
return NULL;
- free(r);
- r = k;
+ free_and_replace(r, k);
word = e-1;
state = VARIABLE_RAW;
@@ -596,8 +572,7 @@ char *replace_env_n(const char *format, size_t n, char **env, unsigned flags) {
if (!k)
return NULL;
- free(r);
- r = k;
+ free_and_replace(r, k);
word = e+1;
state = WORD;
@@ -653,8 +628,7 @@ char *replace_env_n(const char *format, size_t n, char **env, unsigned flags) {
if (!k)
return NULL;
- free(r);
- r = k;
+ free_and_replace(r, k);
word = e+1;
state = WORD;
@@ -673,8 +647,7 @@ char *replace_env_n(const char *format, size_t n, char **env, unsigned flags) {
if (!k)
return NULL;
- free(r);
- r = k;
+ free_and_replace(r, k);
word = e--;
i--;
@@ -682,7 +655,6 @@ char *replace_env_n(const char *format, size_t n, char **env, unsigned flags) {
}
break;
}
- }
if (state == VARIABLE_RAW) {
const char *t;
@@ -697,7 +669,7 @@ char *replace_env_n(const char *format, size_t n, char **env, unsigned flags) {
char **replace_env_argv(char **argv, char **env) {
char **ret, **i;
- unsigned k = 0, l = 0;
+ size_t k = 0, l = 0;
l = strv_length(argv);
@@ -708,10 +680,10 @@ char **replace_env_argv(char **argv, char **env) {
STRV_FOREACH(i, argv) {
/* If $FOO appears as single word, replace it by the split up variable */
- if ((*i)[0] == '$' && (*i)[1] != '{' && (*i)[1] != '$') {
+ if ((*i)[0] == '$' && !IN_SET((*i)[1], '{', '$')) {
char *e;
char **w, **m = NULL;
- unsigned q;
+ size_t q;
e = strv_env_get(env, *i+1);
if (e) {
@@ -729,7 +701,7 @@ char **replace_env_argv(char **argv, char **env) {
q = strv_length(m);
l = l + q - 1;
- w = realloc(ret, sizeof(char*) * (l+1));
+ w = reallocarray(ret, l + 1, sizeof(char *));
if (!w) {
ret[k] = NULL;
strv_free(ret);
@@ -759,6 +731,7 @@ char **replace_env_argv(char **argv, char **env) {
ret[k] = NULL;
return ret;
}
+#endif // 0
int getenv_bool(const char *p) {
const char *e;
@@ -770,6 +743,17 @@ int getenv_bool(const char *p) {
return parse_boolean(e);
}
+#if 0 /// UNNEEDED by elogind
+int getenv_bool_secure(const char *p) {
+ const char *e;
+
+ e = secure_getenv(p);
+ if (!e)
+ return -ENXIO;
+
+ return parse_boolean(e);
+}
+
int serialize_environment(FILE *f, char **environment) {
char **e;
@@ -796,15 +780,10 @@ int deserialize_environment(char ***environment, const char *line) {
assert(environment);
assert(startswith(line, "env="));
- r = cunescape(line + 4, UNESCAPE_RELAX, &uce);
+ r = cunescape(line + 4, 0, &uce);
if (r < 0)
return r;
- if (!env_assignment_is_valid(uce)) {
- free(uce);
- return -EINVAL;
- }
-
return strv_env_replace(environment, uce);
}
#endif // 0
diff --git a/src/basic/env-util.h b/src/basic/env-util.h
index d30b87410..da76e60ca 100644
--- a/src/basic/env-util.h
+++ b/src/basic/env-util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 <stddef.h>
#include <stdio.h>
@@ -42,9 +24,7 @@ char **replace_env_argv(char **argv, char **env);
static inline char *replace_env(const char *format, char **env, unsigned flags) {
return replace_env_n(format, strlen(format), env, flags);
}
-#endif // 0
-#if 0 /// UNNEEDED by elogind
bool strv_env_is_valid(char **e);
#define strv_env_clean(l) strv_env_clean_with_callback(l, NULL, NULL)
char **strv_env_clean_with_callback(char **l, void (*invalid_callback)(const char *p, void *userdata), void *userdata);
@@ -52,8 +32,8 @@ char **strv_env_clean_with_callback(char **l, void (*invalid_callback)(const cha
bool strv_env_name_is_valid(char **l);
bool strv_env_name_or_assignment_is_valid(char **l);
-char **strv_env_merge(unsigned n_lists, ...);
-char **strv_env_delete(char **x, unsigned n_lists, ...); /* New copy */
+char **strv_env_merge(size_t n_lists, ...);
+char **strv_env_delete(char **x, size_t n_lists, ...); /* New copy */
char **strv_env_set(char **x, const char *p); /* New copy ... */
char **strv_env_unset(char **l, const char *p); /* In place ... */
@@ -62,8 +42,11 @@ int strv_env_replace(char ***l, char *p); /* In place ... */
char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) _pure_;
char *strv_env_get(char **x, const char *n) _pure_;
+#endif // 0
int getenv_bool(const char *p);
+#if 0 /// UNNEEDED by elogind
+int getenv_bool_secure(const char *p);
int serialize_environment(FILE *f, char **environment);
int deserialize_environment(char ***environment, const char *line);
diff --git a/src/basic/errno-list.c b/src/basic/errno-list.c
index c568629f7..0549fcead 100644
--- a/src/basic/errno-list.c
+++ b/src/basic/errno-list.c
@@ -1,22 +1,6 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#include <errno.h>
#include <string.h>
#include "errno-list.h"
@@ -51,9 +35,5 @@ int errno_from_name(const char *name) {
assert(sc->id > 0);
return sc->id;
}
-
#if 0 /// UNNEEDED by elogind
-int errno_max(void) {
- return ELEMENTSOF(errno_names);
-}
#endif // 0
diff --git a/src/basic/errno-list.h b/src/basic/errno-list.h
index fb3d05e5e..9c639b4f5 100644
--- a/src/basic/errno-list.h
+++ b/src/basic/errno-list.h
@@ -1,27 +1,15 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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>
+/*
+ * MAX_ERRNO is defined as 4095 in linux/err.h
+ * We use the same value here.
+ */
+#define ERRNO_MAX 4095
const char *errno_to_name(int id);
int errno_from_name(const char *name);
-
-#if 0 /// UNNEEDED by elogind
-int errno_max(void);
-#endif // 0
+static inline bool errno_is_valid(int n) {
+ return n > 0 && n <= ERRNO_MAX;
+}
diff --git a/src/basic/errno-to-name.awk b/src/basic/errno-to-name.awk
new file mode 100644
index 000000000..0878abacb
--- /dev/null
+++ b/src/basic/errno-to-name.awk
@@ -0,0 +1,9 @@
+BEGIN{
+ print "static const char* const errno_names[] = { "
+}
+!/EDEADLOCK/ && !/EWOULDBLOCK/ && !/ENOTSUP/ {
+ printf " [%s] = \"%s\",\n", $1, $1
+}
+END{
+ print "};"
+}
diff --git a/src/basic/escape.c b/src/basic/escape.c
index d43bdaebf..05f388ede 100644
--- a/src/basic/escape.c
+++ b/src/basic/escape.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <stdlib.h>
@@ -27,8 +10,10 @@
#include "macro.h"
#include "utf8.h"
-size_t cescape_char(char c, char *buf) {
- char * buf_old = buf;
+int cescape_char(char c, char *buf) {
+ char *buf_old = buf;
+
+ /* Needs space for 4 characters in the buffer */
switch (c) {
@@ -200,7 +185,7 @@ int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit)
/* C++11 style 16bit unicode */
int a[4];
- unsigned i;
+ size_t i;
uint32_t c;
if (length != (size_t) -1 && length < 5)
@@ -227,7 +212,7 @@ int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit)
/* C++11 style 32bit unicode */
int a[8];
- unsigned i;
+ size_t i;
char32_t c;
if (length != (size_t) -1 && length < 9)
@@ -314,7 +299,7 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi
/* Undoes C style string escaping, and optionally prefixes it. */
- pl = prefix ? strlen(prefix) : 0;
+ pl = strlen_ptr(prefix);
r = new(char, pl+length+1);
if (!r)
@@ -427,7 +412,7 @@ char *octescape(const char *s, size_t len) {
for (f = s, t = r; f < s + len; f++) {
- if (*f < ' ' || *f >= 127 || *f == '\\' || *f == '"') {
+ if (*f < ' ' || *f >= 127 || IN_SET(*f, '\\', '"')) {
*(t++) = '\\';
*(t++) = '0' + (*f >> 6);
*(t++) = '0' + ((*f >> 3) & 8);
diff --git a/src/basic/escape.h b/src/basic/escape.h
index 2977145d6..61e9fe1b9 100644
--- a/src/basic/escape.h
+++ b/src/basic/escape.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 <stddef.h>
#include <stdint.h>
@@ -57,7 +39,7 @@ typedef enum EscapeStyle {
char *cescape(const char *s);
char *cescape_length(const char *s, size_t n);
-size_t cescape_char(char c, char *buf);
+int cescape_char(char c, char *buf);
int cunescape(const char *s, UnescapeFlags flags, char **ret);
int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret);
diff --git a/src/basic/exec-util.c b/src/basic/exec-util.c
index c4fea735c..7896f9369 100644
--- a/src/basic/exec-util.c
+++ b/src/basic/exec-util.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <dirent.h>
#include <errno.h>
@@ -47,27 +30,23 @@ assert_cc(EAGAIN == EWOULDBLOCK);
static int do_spawn(const char *path, char *argv[], int stdout_fd, pid_t *pid) {
pid_t _pid;
+ int r;
if (null_or_empty_path(path)) {
log_debug("%s is empty (a mask).", path);
return 0;
}
- _pid = fork();
- if (_pid < 0)
- return log_error_errno(errno, "Failed to fork: %m");
- if (_pid == 0) {
+ r = safe_fork("(direxec)", FORK_DEATHSIG|FORK_LOG, &_pid);
+ if (r < 0)
+ return r;
+ if (r == 0) {
char *_argv[2];
- assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
-
if (stdout_fd >= 0) {
- /* If the fd happens to be in the right place, go along with that */
- if (stdout_fd != STDOUT_FILENO &&
- dup2(stdout_fd, STDOUT_FILENO) < 0)
- return -errno;
-
- fd_cloexec(STDOUT_FILENO, false);
+ r = rearrange_stdio(STDIN_FILENO, stdout_fd, STDERR_FILENO);
+ if (r < 0)
+ _exit(EXIT_FAILURE);
}
if (!argv) {
@@ -82,7 +61,6 @@ static int do_spawn(const char *path, char *argv[], int stdout_fd, pid_t *pid) {
_exit(EXIT_FAILURE);
}
- log_debug("Spawned %s as " PID_FMT ".", path, _pid);
*pid = _pid;
return 1;
}
@@ -106,12 +84,7 @@ static int do_execute(
* If callbacks is nonnull, execution is serial. Otherwise, we default to parallel.
*/
- (void) reset_all_signal_handlers();
- (void) reset_signal_mask();
-
- assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
-
- r = conf_files_list_strv(&paths, NULL, NULL, (const char* const*) directories);
+ r = conf_files_list_strv(&paths, NULL, NULL, CONF_FILES_EXECUTABLE|CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED, (const char* const*) directories);
if (r < 0)
return r;
@@ -125,12 +98,16 @@ static int do_execute(
* default action terminating the process, and turn on alarm(). */
if (timeout != USEC_INFINITY)
- alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
+ alarm(DIV_ROUND_UP(timeout, USEC_PER_SEC));
STRV_FOREACH(path, paths) {
_cleanup_free_ char *t = NULL;
_cleanup_close_ int fd = -1;
+#if 0 /// No "maybe uninitialized" warning in elogind
+ pid_t pid;
+#else
pid_t pid = 0;
+#endif // 0
t = strdup(*path);
if (!t)
@@ -152,7 +129,7 @@ static int do_execute(
return log_oom();
t = NULL;
} else {
- r = wait_for_terminate_and_warn(t, pid, true);
+ r = wait_for_terminate_and_check(t, pid, WAIT_LOG);
if (r < 0)
continue;
@@ -182,7 +159,7 @@ static int do_execute(
t = hashmap_remove(pids, PID_TO_PTR(pid));
assert(t);
- wait_for_terminate_and_warn(t, pid, true);
+ (void) wait_for_terminate_and_check(t, pid, WAIT_LOG);
}
return 0;
@@ -195,10 +172,9 @@ int execute_directories(
void* const callback_args[_STDOUT_CONSUME_MAX],
char *argv[]) {
- pid_t executor_pid;
- char *name;
char **dirs = (char**) directories;
_cleanup_close_ int fd = -1;
+ char *name;
int r;
assert(!strv_isempty(dirs));
@@ -221,24 +197,14 @@ int execute_directories(
* them to finish. Optionally a timeout is applied. If a file with the same name
* exists in more than one directory, the earliest one wins. */
- executor_pid = fork();
- if (executor_pid < 0)
- return log_error_errno(errno, "Failed to fork: %m");
-
- if (executor_pid == 0) {
+ r = safe_fork("(sd-executor)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
+ if (r < 0)
+ return r;
+ if (r == 0) {
r = do_execute(dirs, timeout, callbacks, callback_args, fd, argv);
_exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
}
- r = wait_for_terminate_and_warn(name, executor_pid, true);
- if (r < 0)
- return log_error_errno(r, "Execution failed: %m");
- if (r > 0) {
- /* non-zero return code from child */
- log_error("Forker process failed.");
- return -EREMOTEIO;
- }
-
if (!callbacks)
return 0;
@@ -256,7 +222,7 @@ int execute_directories(
static int gather_environment_generate(int fd, void *arg) {
char ***env = arg, **x, **y;
_cleanup_fclose_ FILE *f = NULL;
- _cleanup_strv_free_ char **new;
+ _cleanup_strv_free_ char **new = NULL;
int r;
/* Read a series of VAR=value assignments from fd, use them to update the list of
diff --git a/src/basic/exec-util.h b/src/basic/exec-util.h
index a89f9bc68..f81019f86 100644
--- a/src/basic/exec-util.h
+++ b/src/basic/exec-util.h
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2017 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <stdbool.h>
diff --git a/src/basic/extract-word.c b/src/basic/extract-word.c
index 6f2959efd..8b97cdb96 100644
--- a/src/basic/extract-word.c
+++ b/src/basic/extract-word.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <stdarg.h>
@@ -152,7 +135,7 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
for (;; (*p)++, c = **p) {
if (c == 0)
goto finish_force_terminate;
- else if ((c == '\'' || c == '"') && (flags & EXTRACT_QUOTES)) {
+ else if (IN_SET(c, '\'', '"') && (flags & EXTRACT_QUOTES)) {
quote = c;
break;
} else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) {
@@ -193,8 +176,7 @@ finish:
finish_force_next:
s[sz] = 0;
- *ret = s;
- s = NULL;
+ *ret = TAKE_PTR(s);
return 1;
}
diff --git a/src/basic/extract-word.h b/src/basic/extract-word.h
index 36006a5b6..346c5731c 100644
--- a/src/basic/extract-word.h
+++ b/src/basic/extract-word.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 "macro.h"
typedef enum ExtractFlags {
diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c
index 9afec9366..122b59a68 100644
--- a/src/basic/fd-util.c
+++ b/src/basic/fd-util.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <fcntl.h>
@@ -24,13 +7,21 @@
#include <sys/stat.h>
#include <unistd.h>
+#include "alloc-util.h"
+#include "copy.h"
#include "dirent-util.h"
#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
+#include "io-util.h"
#include "macro.h"
+#include "memfd-util.h"
#include "missing.h"
#include "parse-util.h"
#include "path-util.h"
+#include "process-util.h"
#include "socket-util.h"
+#include "stdio-util.h"
#include "util.h"
int close_nointr(int fd) {
@@ -92,8 +83,8 @@ void safe_close_pair(int p[]) {
p[1] = safe_close(p[1]);
}
-void close_many(const int fds[], unsigned n_fd) {
- unsigned i;
+void close_many(const int fds[], size_t n_fd) {
+ size_t i;
assert(fds || n_fd <= 0);
@@ -187,14 +178,8 @@ int fd_cloexec(int fd, bool cloexec) {
return 0;
}
-void stdio_unset_cloexec(void) {
- fd_cloexec(STDIN_FILENO, false);
- fd_cloexec(STDOUT_FILENO, false);
- fd_cloexec(STDERR_FILENO, false);
-}
-
-_pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
- unsigned i;
+_pure_ static bool fd_in_set(int fd, const int fdset[], size_t n_fdset) {
+ size_t i;
assert(n_fdset == 0 || fdset);
@@ -205,7 +190,7 @@ _pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
return false;
}
-int close_all_fds(const int except[], unsigned n_except) {
+int close_all_fds(const int except[], size_t n_except) {
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
int r = 0;
@@ -214,29 +199,37 @@ int close_all_fds(const int except[], unsigned n_except) {
d = opendir("/proc/self/fd");
if (!d) {
- int fd;
struct rlimit rl;
+ int fd, max_fd;
- /* When /proc isn't available (for example in chroots)
- * the fallback is brute forcing through the fd
+ /* 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 (rl.rlim_max == 0)
+ return -EINVAL;
+
+ /* Let's take special care if the resource limit is set to unlimited, or actually larger than the range
+ * of 'int'. Let's avoid implicit overflows. */
+ max_fd = (rl.rlim_max == RLIM_INFINITY || rl.rlim_max > INT_MAX) ? INT_MAX : (int) (rl.rlim_max - 1);
+
+ for (fd = 3; fd >= 0; fd = fd < max_fd ? fd + 1 : -1) {
+ int q;
if (fd_in_set(fd, except, n_except))
continue;
- if (close_nointr(fd) < 0)
- if (errno != EBADF && r == 0)
- r = -errno;
+ q = close_nointr(fd);
+ if (q < 0 && q != -EBADF && r >= 0)
+ r = q;
}
return r;
}
FOREACH_DIRENT(de, d, return -errno) {
- int fd = -1;
+ int fd = -1, q;
if (safe_atoi(de->d_name, &fd) < 0)
/* Let's better ignore this, just in case */
@@ -251,11 +244,9 @@ int close_all_fds(const int except[], unsigned n_except) {
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;
- }
+ q = close_nointr(fd);
+ if (q < 0 && q != -EBADF && r >= 0) /* Valgrind has its own FD and doesn't want to have it closed */
+ r = q;
}
return r;
@@ -283,7 +274,7 @@ int same_fd(int a, int b) {
return true;
/* Try to use kcmp() if we have it. */
- pid = getpid();
+ pid = getpid_cached();
r = kcmp(pid, pid, KCMP_FILE, a, b);
if (r == 0)
return true;
@@ -363,18 +354,604 @@ bool fdname_is_valid(const char *s) {
return p - s < 256;
}
+#endif // 0
int fd_get_path(int fd, char **ret) {
- char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+ _cleanup_close_ int dir = -1;
+ char fdname[DECIMAL_STR_MAX(int)];
int r;
- xsprintf(procfs_path, "/proc/self/fd/%i", fd);
+ dir = open("/proc/self/fd/", O_CLOEXEC | O_DIRECTORY | O_PATH);
+ if (dir < 0)
+ /* /proc is not available or not set up properly, we're most likely
+ * in some chroot environment. */
+ return errno == ENOENT ? -EOPNOTSUPP : -errno;
- r = readlink_malloc(procfs_path, ret);
+ xsprintf(fdname, "%i", fd);
- if (r == -ENOENT) /* If the file doesn't exist the fd is invalid */
+ r = readlinkat_malloc(dir, fdname, ret);
+ if (r == -ENOENT)
+ /* If the file doesn't exist the fd is invalid */
return -EBADF;
return r;
}
+
+int move_fd(int from, int to, int cloexec) {
+ int r;
+
+ /* Move fd 'from' to 'to', make sure FD_CLOEXEC remains equal if requested, and release the old fd. If
+ * 'cloexec' is passed as -1, the original FD_CLOEXEC is inherited for the new fd. If it is 0, it is turned
+ * off, if it is > 0 it is turned on. */
+
+ if (from < 0)
+ return -EBADF;
+ if (to < 0)
+ return -EBADF;
+
+ if (from == to) {
+
+ if (cloexec >= 0) {
+ r = fd_cloexec(to, cloexec);
+ if (r < 0)
+ return r;
+ }
+
+ return to;
+ }
+
+ if (cloexec < 0) {
+ int fl;
+
+ fl = fcntl(from, F_GETFD, 0);
+ if (fl < 0)
+ return -errno;
+
+ cloexec = !!(fl & FD_CLOEXEC);
+ }
+
+ r = dup3(from, to, cloexec ? O_CLOEXEC : 0);
+ if (r < 0)
+ return -errno;
+
+ assert(r == to);
+
+ safe_close(from);
+
+ return to;
+}
+
+int acquire_data_fd(const void *data, size_t size, unsigned flags) {
+
+ _cleanup_close_pair_ int pipefds[2] = { -1, -1 };
+ char pattern[] = "/dev/shm/data-fd-XXXXXX";
+ _cleanup_close_ int fd = -1;
+ int isz = 0, r;
+ ssize_t n;
+ off_t f;
+
+ assert(data || size == 0);
+
+ /* Acquire a read-only file descriptor that when read from returns the specified data. This is much more
+ * complex than I wish it was. But here's why:
+ *
+ * a) First we try to use memfds. They are the best option, as we can seal them nicely to make them
+ * read-only. Unfortunately they require kernel 3.17, and – at the time of writing – we still support 3.14.
+ *
+ * b) Then, we try classic pipes. They are the second best options, as we can close the writing side, retaining
+ * a nicely read-only fd in the reading side. However, they are by default quite small, and unprivileged
+ * clients can only bump their size to a system-wide limit, which might be quite low.
+ *
+ * c) Then, we try an O_TMPFILE file in /dev/shm (that dir is the only suitable one known to exist from
+ * earliest boot on). To make it read-only we open the fd a second time with O_RDONLY via
+ * /proc/self/<fd>. Unfortunately O_TMPFILE is not available on older kernels on tmpfs.
+ *
+ * d) Finally, we try creating a regular file in /dev/shm, which we then delete.
+ *
+ * It sucks a bit that depending on the situation we return very different objects here, but that's Linux I
+ * figure. */
+
+ if (size == 0 && ((flags & ACQUIRE_NO_DEV_NULL) == 0)) {
+ /* As a special case, return /dev/null if we have been called for an empty data block */
+ r = open("/dev/null", O_RDONLY|O_CLOEXEC|O_NOCTTY);
+ if (r < 0)
+ return -errno;
+
+ return r;
+ }
+
+ if ((flags & ACQUIRE_NO_MEMFD) == 0) {
+ fd = memfd_new("data-fd");
+ if (fd < 0)
+ goto try_pipe;
+
+ n = write(fd, data, size);
+ if (n < 0)
+ return -errno;
+ if ((size_t) n != size)
+ return -EIO;
+
+ f = lseek(fd, 0, SEEK_SET);
+ if (f != 0)
+ return -errno;
+
+ r = memfd_set_sealed(fd);
+ if (r < 0)
+ return r;
+
+ return TAKE_FD(fd);
+ }
+
+try_pipe:
+ if ((flags & ACQUIRE_NO_PIPE) == 0) {
+ if (pipe2(pipefds, O_CLOEXEC|O_NONBLOCK) < 0)
+ return -errno;
+
+ isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
+ if (isz < 0)
+ return -errno;
+
+ if ((size_t) isz < size) {
+ isz = (int) size;
+ if (isz < 0 || (size_t) isz != size)
+ return -E2BIG;
+
+ /* Try to bump the pipe size */
+ (void) fcntl(pipefds[1], F_SETPIPE_SZ, isz);
+
+ /* See if that worked */
+ isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
+ if (isz < 0)
+ return -errno;
+
+ if ((size_t) isz < size)
+ goto try_dev_shm;
+ }
+
+ n = write(pipefds[1], data, size);
+ if (n < 0)
+ return -errno;
+ if ((size_t) n != size)
+ return -EIO;
+
+ (void) fd_nonblock(pipefds[0], false);
+
+ return TAKE_FD(pipefds[0]);
+ }
+
+try_dev_shm:
+ if ((flags & ACQUIRE_NO_TMPFILE) == 0) {
+ fd = open("/dev/shm", O_RDWR|O_TMPFILE|O_CLOEXEC, 0500);
+ if (fd < 0)
+ goto try_dev_shm_without_o_tmpfile;
+
+ n = write(fd, data, size);
+ if (n < 0)
+ return -errno;
+ if ((size_t) n != size)
+ return -EIO;
+
+ /* Let's reopen the thing, in order to get an O_RDONLY fd for the original O_RDWR one */
+ return fd_reopen(fd, O_RDONLY|O_CLOEXEC);
+ }
+
+try_dev_shm_without_o_tmpfile:
+ if ((flags & ACQUIRE_NO_REGULAR) == 0) {
+ fd = mkostemp_safe(pattern);
+ if (fd < 0)
+ return fd;
+
+ n = write(fd, data, size);
+ if (n < 0) {
+ r = -errno;
+ goto unlink_and_return;
+ }
+ if ((size_t) n != size) {
+ r = -EIO;
+ goto unlink_and_return;
+ }
+
+ /* Let's reopen the thing, in order to get an O_RDONLY fd for the original O_RDWR one */
+ r = open(pattern, O_RDONLY|O_CLOEXEC);
+ if (r < 0)
+ r = -errno;
+
+ unlink_and_return:
+ (void) unlink(pattern);
+ return r;
+ }
+
+ return -EOPNOTSUPP;
+}
+
+/* When the data is smaller or equal to 64K, try to place the copy in a memfd/pipe */
+#define DATA_FD_MEMORY_LIMIT (64U*1024U)
+
+/* If memfd/pipe didn't work out, then let's use a file in /tmp up to a size of 1M. If it's large than that use /var/tmp instead. */
+#define DATA_FD_TMP_LIMIT (1024U*1024U)
+
+#if 0 /// UNNEEDED by elogind
+int fd_duplicate_data_fd(int fd) {
+
+ _cleanup_close_ int copy_fd = -1, tmp_fd = -1;
+ _cleanup_free_ void *remains = NULL;
+ size_t remains_size = 0;
+ const char *td;
+ struct stat st;
+ int r;
+
+ /* Creates a 'data' fd from the specified source fd, containing all the same data in a read-only fashion, but
+ * independent of it (i.e. the source fd can be closed and unmounted after this call succeeded). Tries to be
+ * somewhat smart about where to place the data. In the best case uses a memfd(). If memfd() are not supported
+ * uses a pipe instead. For larger data will use an unlinked file in /tmp, and for even larger data one in
+ * /var/tmp. */
+
+ if (fstat(fd, &st) < 0)
+ return -errno;
+
+ /* For now, let's only accept regular files, sockets, pipes and char devices */
+ if (S_ISDIR(st.st_mode))
+ return -EISDIR;
+ if (S_ISLNK(st.st_mode))
+ return -ELOOP;
+ if (!S_ISREG(st.st_mode) && !S_ISSOCK(st.st_mode) && !S_ISFIFO(st.st_mode) && !S_ISCHR(st.st_mode))
+ return -EBADFD;
+
+ /* If we have reason to believe the data is bounded in size, then let's use memfds or pipes as backing fd. Note
+ * that we use the reported regular file size only as a hint, given that there are plenty special files in
+ * /proc and /sys which report a zero file size but can be read from. */
+
+ if (!S_ISREG(st.st_mode) || st.st_size < DATA_FD_MEMORY_LIMIT) {
+
+ /* Try a memfd first */
+ copy_fd = memfd_new("data-fd");
+ if (copy_fd >= 0) {
+ off_t f;
+
+ r = copy_bytes(fd, copy_fd, DATA_FD_MEMORY_LIMIT, 0);
+ if (r < 0)
+ return r;
+
+ f = lseek(copy_fd, 0, SEEK_SET);
+ if (f != 0)
+ return -errno;
+
+ if (r == 0) {
+ /* Did it fit into the limit? If so, we are done. */
+ r = memfd_set_sealed(copy_fd);
+ if (r < 0)
+ return r;
+
+ return TAKE_FD(copy_fd);
+ }
+
+ /* Hmm, pity, this didn't fit. Let's fall back to /tmp then, see below */
+
+ } else {
+ _cleanup_(close_pairp) int pipefds[2] = { -1, -1 };
+ int isz;
+
+ /* If memfds aren't available, use a pipe. Set O_NONBLOCK so that we will get EAGAIN rather
+ * then block indefinitely when we hit the pipe size limit */
+
+ if (pipe2(pipefds, O_CLOEXEC|O_NONBLOCK) < 0)
+ return -errno;
+
+ isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
+ if (isz < 0)
+ return -errno;
+
+ /* Try to enlarge the pipe size if necessary */
+ if ((size_t) isz < DATA_FD_MEMORY_LIMIT) {
+
+ (void) fcntl(pipefds[1], F_SETPIPE_SZ, DATA_FD_MEMORY_LIMIT);
+
+ isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
+ if (isz < 0)
+ return -errno;
+ }
+
+ if ((size_t) isz >= DATA_FD_MEMORY_LIMIT) {
+
+ r = copy_bytes_full(fd, pipefds[1], DATA_FD_MEMORY_LIMIT, 0, &remains, &remains_size);
+ if (r < 0 && r != -EAGAIN)
+ return r; /* If we get EAGAIN it could be because of the source or because of
+ * the destination fd, we can't know, as sendfile() and friends won't
+ * tell us. Hence, treat this as reason to fall back, just to be
+ * sure. */
+ if (r == 0) {
+ /* Everything fit in, yay! */
+ (void) fd_nonblock(pipefds[0], false);
+
+ return TAKE_FD(pipefds[0]);
+ }
+
+ /* Things didn't fit in. But we read data into the pipe, let's remember that, so that
+ * when writing the new file we incorporate this first. */
+ copy_fd = TAKE_FD(pipefds[0]);
+ }
+ }
+ }
+
+ /* If we have reason to believe this will fit fine in /tmp, then use that as first fallback. */
+ if ((!S_ISREG(st.st_mode) || st.st_size < DATA_FD_TMP_LIMIT) &&
+ (DATA_FD_MEMORY_LIMIT + remains_size) < DATA_FD_TMP_LIMIT) {
+ off_t f;
+
+ tmp_fd = open_tmpfile_unlinkable(NULL /* NULL as directory means /tmp */, O_RDWR|O_CLOEXEC);
+ if (tmp_fd < 0)
+ return tmp_fd;
+
+ if (copy_fd >= 0) {
+ /* If we tried a memfd/pipe first and it ended up being too large, then copy this into the
+ * temporary file first. */
+
+ r = copy_bytes(copy_fd, tmp_fd, UINT64_MAX, 0);
+ if (r < 0)
+ return r;
+
+ assert(r == 0);
+ }
+
+ if (remains_size > 0) {
+ /* If there were remaining bytes (i.e. read into memory, but not written out yet) from the
+ * failed copy operation, let's flush them out next. */
+
+ r = loop_write(tmp_fd, remains, remains_size, false);
+ if (r < 0)
+ return r;
+ }
+
+ r = copy_bytes(fd, tmp_fd, DATA_FD_TMP_LIMIT - DATA_FD_MEMORY_LIMIT - remains_size, COPY_REFLINK);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ goto finish; /* Yay, it fit in */
+
+ /* It didn't fit in. Let's not forget to use what we already used */
+ f = lseek(tmp_fd, 0, SEEK_SET);
+ if (f != 0)
+ return -errno;
+
+ safe_close(copy_fd);
+ copy_fd = TAKE_FD(tmp_fd);
+
+ remains = mfree(remains);
+ remains_size = 0;
+ }
+
+ /* As last fallback use /var/tmp */
+ r = var_tmp_dir(&td);
+ if (r < 0)
+ return r;
+
+ tmp_fd = open_tmpfile_unlinkable(td, O_RDWR|O_CLOEXEC);
+ if (tmp_fd < 0)
+ return tmp_fd;
+
+ if (copy_fd >= 0) {
+ /* If we tried a memfd/pipe first, or a file in /tmp, and it ended up being too large, than copy this
+ * into the temporary file first. */
+ r = copy_bytes(copy_fd, tmp_fd, UINT64_MAX, COPY_REFLINK);
+ if (r < 0)
+ return r;
+
+ assert(r == 0);
+ }
+
+ if (remains_size > 0) {
+ /* Then, copy in any read but not yet written bytes. */
+ r = loop_write(tmp_fd, remains, remains_size, false);
+ if (r < 0)
+ return r;
+ }
+
+ /* Copy in the rest */
+ r = copy_bytes(fd, tmp_fd, UINT64_MAX, COPY_REFLINK);
+ if (r < 0)
+ return r;
+
+ assert(r == 0);
+
+finish:
+ /* Now convert the O_RDWR file descriptor into an O_RDONLY one (and as side effect seek to the beginning of the
+ * file again */
+
+ return fd_reopen(tmp_fd, O_RDONLY|O_CLOEXEC);
+}
#endif // 0
+
+int fd_move_above_stdio(int fd) {
+ int flags, copy;
+ PROTECT_ERRNO;
+
+ /* Moves the specified file descriptor if possible out of the range [0…2], i.e. the range of
+ * stdin/stdout/stderr. If it can't be moved outside of this range the original file descriptor is
+ * returned. This call is supposed to be used for long-lasting file descriptors we allocate in our code that
+ * might get loaded into foreign code, and where we want ensure our fds are unlikely used accidentally as
+ * stdin/stdout/stderr of unrelated code.
+ *
+ * Note that this doesn't fix any real bugs, it just makes it less likely that our code will be affected by
+ * buggy code from others that mindlessly invokes 'fprintf(stderr, …' or similar in places where stderr has
+ * been closed before.
+ *
+ * This function is written in a "best-effort" and "least-impact" style. This means whenever we encounter an
+ * error we simply return the original file descriptor, and we do not touch errno. */
+
+ if (fd < 0 || fd > 2)
+ return fd;
+
+ flags = fcntl(fd, F_GETFD, 0);
+ if (flags < 0)
+ return fd;
+
+ if (flags & FD_CLOEXEC)
+ copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
+ else
+ copy = fcntl(fd, F_DUPFD, 3);
+ if (copy < 0)
+ return fd;
+
+ assert(copy > 2);
+
+ (void) close(fd);
+ return copy;
+}
+
+int rearrange_stdio(int original_input_fd, int original_output_fd, int original_error_fd) {
+
+ int fd[3] = { /* Put together an array of fds we work on */
+ original_input_fd,
+ original_output_fd,
+ original_error_fd
+ };
+
+ int r, i,
+ null_fd = -1, /* if we open /dev/null, we store the fd to it here */
+ copy_fd[3] = { -1, -1, -1 }; /* This contains all fds we duplicate here temporarily, and hence need to close at the end */
+ bool null_readable, null_writable;
+
+ /* Sets up stdin, stdout, stderr with the three file descriptors passed in. If any of the descriptors is
+ * specified as -1 it will be connected with /dev/null instead. If any of the file descriptors is passed as
+ * itself (e.g. stdin as STDIN_FILENO) it is left unmodified, but the O_CLOEXEC bit is turned off should it be
+ * on.
+ *
+ * Note that if any of the passed file descriptors are > 2 they will be closed — both on success and on
+ * failure! Thus, callers should assume that when this function returns the input fds are invalidated.
+ *
+ * Note that when this function fails stdin/stdout/stderr might remain half set up!
+ *
+ * O_CLOEXEC is turned off for all three file descriptors (which is how it should be for
+ * stdin/stdout/stderr). */
+
+ null_readable = original_input_fd < 0;
+ null_writable = original_output_fd < 0 || original_error_fd < 0;
+
+ /* First step, open /dev/null once, if we need it */
+ if (null_readable || null_writable) {
+
+ /* Let's open this with O_CLOEXEC first, and convert it to non-O_CLOEXEC when we move the fd to the final position. */
+ null_fd = open("/dev/null", (null_readable && null_writable ? O_RDWR :
+ null_readable ? O_RDONLY : O_WRONLY) | O_CLOEXEC);
+ if (null_fd < 0) {
+ r = -errno;
+ goto finish;
+ }
+
+ /* If this fd is in the 0…2 range, let's move it out of it */
+ if (null_fd < 3) {
+ int copy;
+
+ copy = fcntl(null_fd, F_DUPFD_CLOEXEC, 3); /* Duplicate this with O_CLOEXEC set */
+ if (copy < 0) {
+ r = -errno;
+ goto finish;
+ }
+
+ safe_close(null_fd);
+ null_fd = copy;
+ }
+ }
+
+ /* Let's assemble fd[] with the fds to install in place of stdin/stdout/stderr */
+ for (i = 0; i < 3; i++) {
+
+ if (fd[i] < 0)
+ fd[i] = null_fd; /* A negative parameter means: connect this one to /dev/null */
+ else if (fd[i] != i && fd[i] < 3) {
+ /* This fd is in the 0…2 territory, but not at its intended place, move it out of there, so that we can work there. */
+ copy_fd[i] = fcntl(fd[i], F_DUPFD_CLOEXEC, 3); /* Duplicate this with O_CLOEXEC set */
+ if (copy_fd[i] < 0) {
+ r = -errno;
+ goto finish;
+ }
+
+ fd[i] = copy_fd[i];
+ }
+ }
+
+ /* At this point we now have the fds to use in fd[], and they are all above the stdio range, so that we
+ * have freedom to move them around. If the fds already were at the right places then the specific fds are
+ * -1. Let's now move them to the right places. This is the point of no return. */
+ for (i = 0; i < 3; i++) {
+
+ if (fd[i] == i) {
+
+ /* fd is already in place, but let's make sure O_CLOEXEC is off */
+ r = fd_cloexec(i, false);
+ if (r < 0)
+ goto finish;
+
+ } else {
+ assert(fd[i] > 2);
+
+ if (dup2(fd[i], i) < 0) { /* Turns off O_CLOEXEC on the new fd. */
+ r = -errno;
+ goto finish;
+ }
+ }
+ }
+
+ r = 0;
+
+finish:
+ /* Close the original fds, but only if they were outside of the stdio range. Also, properly check for the same
+ * fd passed in multiple times. */
+ safe_close_above_stdio(original_input_fd);
+ if (original_output_fd != original_input_fd)
+ safe_close_above_stdio(original_output_fd);
+ if (original_error_fd != original_input_fd && original_error_fd != original_output_fd)
+ safe_close_above_stdio(original_error_fd);
+
+ /* Close the copies we moved > 2 */
+ for (i = 0; i < 3; i++)
+ safe_close(copy_fd[i]);
+
+ /* Close our null fd, if it's > 2 */
+ safe_close_above_stdio(null_fd);
+
+ return r;
+}
+
+int fd_reopen(int fd, int flags) {
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+ int new_fd;
+
+ /* Reopens the specified fd with new flags. This is useful for convert an O_PATH fd into a regular one, or to
+ * turn O_RDWR fds into O_RDONLY fds.
+ *
+ * This doesn't work on sockets (since they cannot be open()ed, ever).
+ *
+ * This implicitly resets the file read index to 0. */
+
+ xsprintf(procfs_path, "/proc/self/fd/%i", fd);
+ new_fd = open(procfs_path, flags);
+ if (new_fd < 0)
+ return -errno;
+
+ return new_fd;
+}
+
+int read_nr_open(void) {
+ _cleanup_free_ char *nr_open = NULL;
+ int r;
+
+ /* Returns the kernel's current fd limit, either by reading it of /proc/sys if that works, or using the
+ * hard-coded default compiled-in value of current kernels (1M) if not. This call will never fail. */
+
+ r = read_one_line_file("/proc/sys/fs/nr_open", &nr_open);
+ if (r < 0)
+ log_debug_errno(r, "Failed to read /proc/sys/fs/nr_open, ignoring: %m");
+ else {
+ int v;
+
+ r = safe_atoi(nr_open, &v);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse /proc/sys/fs/nr_open value '%s', ignoring: %m", nr_open);
+ else
+ return v;
+ }
+
+ /* If we fail, fallback to the hard-coded kernel limit of 1024 * 1024. */
+ return 1024 * 1024;
+}
diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h
index fe92b76c4..2e5616cb7 100644
--- a/src/basic/fd-util.h
+++ b/src/basic/fd-util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <dirent.h>
#include <stdbool.h>
#include <stdio.h>
@@ -34,7 +16,14 @@ int close_nointr(int fd);
int safe_close(int fd);
void safe_close_pair(int p[]);
-void close_many(const int fds[], unsigned n_fd);
+static inline int safe_close_above_stdio(int fd) {
+ if (fd < 3) /* Don't close stdin/stdout/stderr, but still invalidate the fd by returning -1 */
+ return -1;
+
+ return safe_close(fd);
+}
+
+void close_many(const int fds[], size_t n_fd);
int fclose_nointr(FILE *f);
FILE* safe_fclose(FILE *f);
@@ -65,9 +54,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir);
int fd_nonblock(int fd, bool nonblock);
int fd_cloexec(int fd, bool cloexec);
-void stdio_unset_cloexec(void);
-int close_all_fds(const int except[], unsigned n_except);
+int close_all_fds(const int except[], size_t n_except);
#if 0 /// UNNEEDED by elogind
int same_fd(int a, int b);
@@ -75,10 +63,50 @@ int same_fd(int a, int b);
void cmsg_close_all(struct msghdr *mh);
bool fdname_is_valid(const char *s);
+#endif // 0
int fd_get_path(int fd, char **ret);
+
+int move_fd(int from, int to, int cloexec);
+
+enum {
+ ACQUIRE_NO_DEV_NULL = 1 << 0,
+ ACQUIRE_NO_MEMFD = 1 << 1,
+ ACQUIRE_NO_PIPE = 1 << 2,
+ ACQUIRE_NO_TMPFILE = 1 << 3,
+ ACQUIRE_NO_REGULAR = 1 << 4,
+};
+
+int acquire_data_fd(const void *data, size_t size, unsigned flags);
+
+#if 0 /// UNNEEDED by elogind
+int fd_duplicate_data_fd(int fd);
#endif // 0
/* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */
#define ERRNO_IS_DISCONNECT(r) \
IN_SET(r, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, ENETUNREACH)
+
+/* Resource exhaustion, could be our fault or general system trouble */
+#define ERRNO_IS_RESOURCE(r) \
+ IN_SET(r, ENOMEM, EMFILE, ENFILE)
+
+int fd_move_above_stdio(int fd);
+
+int rearrange_stdio(int original_input_fd, int original_output_fd, int original_error_fd);
+
+static inline int make_null_stdio(void) {
+ return rearrange_stdio(-1, -1, -1);
+}
+
+/* Like TAKE_PTR() but for file descriptors, resetting them to -1 */
+#define TAKE_FD(fd) \
+ ({ \
+ int _fd_ = (fd); \
+ (fd) = -1; \
+ _fd_; \
+ })
+
+int fd_reopen(int fd, int flags);
+
+int read_nr_open(void);
diff --git a/src/basic/fileio-label.c b/src/basic/fileio-label.c
index 4cb207742..7ad79cb5c 100644
--- a/src/basic/fileio-label.c
+++ b/src/basic/fileio-label.c
@@ -1,21 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2010 Harald Hoyer
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2010 Harald Hoyer
***/
#include <sys/stat.h>
@@ -68,3 +53,19 @@ int fopen_temporary_label(const char *target,
return r;
}
#endif // 0
+
+int create_shutdown_run_nologin_or_warn(void) {
+ int r;
+
+ /* This is used twice: once in systemd-user-sessions.service, in order to block logins when we actually go
+ * down, and once in systemd-logind.service when shutdowns are scheduled, and logins are to be turned off a bit
+ * in advance. We use the same wording of the message in both cases. */
+
+ r = write_string_file_atomic_label("/run/nologin",
+ "System is going down. Unprivileged users are not permitted to log in anymore. "
+ "For technical details, see pam_nologin(8).");
+ if (r < 0)
+ return log_error_errno(r, "Failed to create /run/nologin: %m");
+
+ return 0;
+}
diff --git a/src/basic/fileio-label.h b/src/basic/fileio-label.h
index d811ca9b8..5ba94366c 100644
--- a/src/basic/fileio-label.h
+++ b/src/basic/fileio-label.h
@@ -1,35 +1,25 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2010 Harald Hoyer
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2010 Harald Hoyer
***/
#include <stdio.h>
#include "fileio.h"
+/* These functions are split out of fileio.h (and not for examplement just as flags to the functions they wrap) in
+ * order to optimize linking: This way, -lselinux is needed only for the callers of these functions that need selinux,
+ * but not for all */
+
int write_string_file_atomic_label_ts(const char *fn, const char *line, struct timespec *ts);
static inline int write_string_file_atomic_label(const char *fn, const char *line) {
return write_string_file_atomic_label_ts(fn, line, NULL);
}
#if 0 /// UNNEEDED by elogind
int write_env_file_label(const char *fname, char **l);
-int fopen_temporary_label(const char *target,
- const char *path, FILE **f, char **temp_path);
#endif // 0
+int fopen_temporary_label(const char *target, const char *path, FILE **f, char **temp_path);
+
+int create_shutdown_run_nologin_or_warn(void);
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
index 7bafe9038..7b1014b1d 100644
--- a/src/basic/fileio.c
+++ b/src/basic/fileio.c
@@ -1,35 +1,22 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdarg.h>
#include <stdint.h>
+#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "alloc-util.h"
#include "ctype.h"
+#include "def.h"
+#include "env-util.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
@@ -40,6 +27,7 @@
#include "missing.h"
#include "parse-util.h"
#include "path-util.h"
+#include "process-util.h"
#include "random-util.h"
#include "stdio-util.h"
#include "string-util.h"
@@ -50,14 +38,44 @@
#define READ_FULL_BYTES_MAX (4U*1024U*1024U)
-int write_string_stream_ts(FILE *f, const char *line, bool enforce_newline, struct timespec *ts) {
+int write_string_stream_ts(
+ FILE *f,
+ const char *line,
+ WriteStringFileFlags flags,
+ struct timespec *ts) {
+
+ bool needs_nl;
+ int r;
assert(f);
assert(line);
- fputs(line, f);
- if (enforce_newline && !endswith(line, "\n"))
- fputc('\n', f);
+ if (ferror(f))
+ return -EIO;
+
+ needs_nl = !(flags & WRITE_STRING_FILE_AVOID_NEWLINE) && !endswith(line, "\n");
+
+ if (needs_nl && (flags & WRITE_STRING_FILE_DISABLE_BUFFER)) {
+ /* If STDIO buffering was disabled, then let's append the newline character to the string itself, so
+ * that the write goes out in one go, instead of two */
+
+ line = strjoina(line, "\n");
+ needs_nl = false;
+ }
+
+ if (fputs(line, f) == EOF)
+ return -errno;
+
+ if (needs_nl)
+ if (fputc('\n', f) == EOF)
+ return -errno;
+
+ if (flags & WRITE_STRING_FILE_SYNC)
+ r = fflush_sync_and_check(f);
+ else
+ r = fflush_and_check(f);
+ if (r < 0)
+ return r;
if (ts) {
struct timespec twice[2] = {*ts, *ts};
@@ -66,10 +84,15 @@ int write_string_stream_ts(FILE *f, const char *line, bool enforce_newline, stru
return -errno;
}
- return fflush_and_check(f);
+ return 0;
}
-static int write_string_file_atomic(const char *fn, const char *line, bool enforce_newline) {
+static int write_string_file_atomic(
+ const char *fn,
+ const char *line,
+ WriteStringFileFlags flags,
+ struct timespec *ts) {
+
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *p = NULL;
int r;
@@ -81,37 +104,50 @@ static int write_string_file_atomic(const char *fn, const char *line, bool enfor
if (r < 0)
return r;
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
(void) fchmod_umask(fileno(f), 0644);
- r = write_string_stream(f, line, enforce_newline);
- if (r >= 0) {
- if (rename(p, fn) < 0)
- r = -errno;
+ r = write_string_stream_ts(f, line, flags, ts);
+ if (r < 0)
+ goto fail;
+
+ if (rename(p, fn) < 0) {
+ r = -errno;
+ goto fail;
}
- if (r < 0)
- (void) unlink(p);
+ return 0;
+fail:
+ (void) unlink(p);
return r;
}
-int write_string_file_ts(const char *fn, const char *line, WriteStringFileFlags flags, struct timespec *ts) {
+int write_string_file_ts(
+ const char *fn,
+ const char *line,
+ WriteStringFileFlags flags,
+ struct timespec *ts) {
+
_cleanup_fclose_ FILE *f = NULL;
int q, r;
assert(fn);
assert(line);
+ /* We don't know how to verify whether the file contents was already on-disk. */
+ assert(!((flags & WRITE_STRING_FILE_VERIFY_ON_FAILURE) && (flags & WRITE_STRING_FILE_SYNC)));
+
if (flags & WRITE_STRING_FILE_ATOMIC) {
assert(flags & WRITE_STRING_FILE_CREATE);
- r = write_string_file_atomic(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
+ r = write_string_file_atomic(fn, line, flags, ts);
if (r < 0)
goto fail;
return r;
} else
- assert(ts == NULL);
+ assert(!ts);
if (flags & WRITE_STRING_FILE_CREATE) {
f = fopen(fn, "we");
@@ -138,7 +174,12 @@ int write_string_file_ts(const char *fn, const char *line, WriteStringFileFlags
}
}
- r = write_string_stream_ts(f, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE), ts);
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
+ if (flags & WRITE_STRING_FILE_DISABLE_BUFFER)
+ setvbuf(f, NULL, _IONBF, 0);
+
+ r = write_string_stream_ts(f, line, flags, ts);
if (r < 0)
goto fail;
@@ -160,9 +201,28 @@ fail:
return 0;
}
+int write_string_filef(
+ const char *fn,
+ WriteStringFileFlags flags,
+ const char *format, ...) {
+
+ _cleanup_free_ char *p = NULL;
+ va_list ap;
+ int r;
+
+ va_start(ap, format);
+ r = vasprintf(&p, format, ap);
+ va_end(ap);
+
+ if (r < 0)
+ return -ENOMEM;
+
+ return write_string_file(fn, p, flags);
+}
+
int read_one_line_file(const char *fn, char **line) {
_cleanup_fclose_ FILE *f = NULL;
- char t[LINE_MAX], *c;
+ int r;
assert(fn);
assert(line);
@@ -171,21 +231,10 @@ int read_one_line_file(const char *fn, char **line) {
if (!f)
return -errno;
- if (!fgets(t, sizeof(t), f)) {
-
- if (ferror(f))
- return errno > 0 ? -errno : -EIO;
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
- t[0] = 0;
- }
-
- c = strdup(t);
- if (!c)
- return -ENOMEM;
- truncate_nl(c);
-
- *line = c;
- return 0;
+ r = read_line(f, LONG_LINE_MAX, line);
+ return r < 0 ? r : 0;
}
int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
@@ -209,6 +258,8 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
if (!f)
return -errno;
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
/* We try to read one byte more than we need, so that we know whether we hit eof */
errno = 0;
k = fread(buf, 1, l + accept_extra_nl + 1, f);
@@ -226,29 +277,35 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
}
int read_full_stream(FILE *f, char **contents, size_t *size) {
- size_t n, l;
_cleanup_free_ char *buf = NULL;
struct stat st;
+ size_t n, l;
+ int fd;
assert(f);
assert(contents);
- if (fstat(fileno(f), &st) < 0)
- return -errno;
-
n = LINE_MAX;
- if (S_ISREG(st.st_mode)) {
+ fd = fileno(f);
+ if (fd >= 0) { /* If the FILE* object is backed by an fd (as opposed to memory or such, see fmemopen(), let's
+ * optimize our buffering) */
- /* Safety check */
- if (st.st_size > READ_FULL_BYTES_MAX)
- return -E2BIG;
+ if (fstat(fileno(f), &st) < 0)
+ return -errno;
+
+ if (S_ISREG(st.st_mode)) {
+
+ /* Safety check */
+ if (st.st_size > READ_FULL_BYTES_MAX)
+ return -E2BIG;
- /* Start with the right file size, but be prepared for
- * files from /proc which generally report a file size
- * of 0 */
- if (st.st_size > 0)
- n = st.st_size;
+ /* Start with the right file size, but be prepared for files from /proc which generally report a file
+ * size of 0. Note that we increase the size to read here by one, so that the first read attempt
+ * already makes us notice the EOF. */
+ if (st.st_size > 0)
+ n = st.st_size + 1;
+ }
}
l = 0;
@@ -261,12 +318,13 @@ int read_full_stream(FILE *f, char **contents, size_t *size) {
return -ENOMEM;
buf = t;
+ errno = 0;
k = fread(buf + l, 1, n - l, f);
if (k > 0)
l += k;
if (ferror(f))
- return -errno;
+ return errno > 0 ? -errno : -EIO;
if (feof(f))
break;
@@ -284,8 +342,7 @@ int read_full_stream(FILE *f, char **contents, size_t *size) {
}
buf[l] = 0;
- *contents = buf;
- buf = NULL; /* do not free */
+ *contents = TAKE_PTR(buf);
if (size)
*size = l;
@@ -303,6 +360,8 @@ int read_full_file(const char *fn, char **contents, size_t *size) {
if (!f)
return -errno;
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
return read_full_stream(f, contents, size);
}
@@ -315,11 +374,11 @@ static int parse_env_file_internal(
void *userdata,
int *n_pushed) {
- _cleanup_free_ char *contents = NULL, *key = NULL;
size_t key_alloc = 0, n_key = 0, value_alloc = 0, n_value = 0, last_value_whitespace = (size_t) -1, last_key_whitespace = (size_t) -1;
- char *p, *value = NULL;
- int r;
+ _cleanup_free_ char *contents = NULL, *key = NULL, *value = NULL;
unsigned line = 1;
+ char *p;
+ int r;
enum {
PRE_KEY,
@@ -356,10 +415,8 @@ static int parse_env_file_internal(
state = KEY;
last_key_whitespace = (size_t) -1;
- if (!GREEDY_REALLOC(key, key_alloc, n_key+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(key, key_alloc, n_key+2))
+ return -ENOMEM;
key[n_key++] = c;
}
@@ -379,10 +436,8 @@ static int parse_env_file_internal(
else if (last_key_whitespace == (size_t) -1)
last_key_whitespace = n_key;
- if (!GREEDY_REALLOC(key, key_alloc, n_key+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(key, key_alloc, n_key+2))
+ return -ENOMEM;
key[n_key++] = c;
}
@@ -404,7 +459,7 @@ static int parse_env_file_internal(
r = push(fname, line, key, value, userdata, n_pushed);
if (r < 0)
- goto fail;
+ return r;
n_key = 0;
value = NULL;
@@ -419,10 +474,8 @@ static int parse_env_file_internal(
else if (!strchr(WHITESPACE, c)) {
state = VALUE;
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
+ return -ENOMEM;
value[n_value++] = c;
}
@@ -449,7 +502,7 @@ static int parse_env_file_internal(
r = push(fname, line, key, value, userdata, n_pushed);
if (r < 0)
- goto fail;
+ return r;
n_key = 0;
value = NULL;
@@ -464,10 +517,8 @@ static int parse_env_file_internal(
else if (last_value_whitespace == (size_t) -1)
last_value_whitespace = n_value;
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
+ return -ENOMEM;
value[n_value++] = c;
}
@@ -479,10 +530,8 @@ static int parse_env_file_internal(
if (!strchr(newline, c)) {
/* Escaped newlines we eat up entirely */
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
+ return -ENOMEM;
value[n_value++] = c;
}
@@ -494,10 +543,8 @@ static int parse_env_file_internal(
else if (c == '\\')
state = SINGLE_QUOTE_VALUE_ESCAPE;
else {
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
+ return -ENOMEM;
value[n_value++] = c;
}
@@ -508,10 +555,8 @@ static int parse_env_file_internal(
state = SINGLE_QUOTE_VALUE;
if (!strchr(newline, c)) {
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
+ return -ENOMEM;
value[n_value++] = c;
}
@@ -523,10 +568,8 @@ static int parse_env_file_internal(
else if (c == '\\')
state = DOUBLE_QUOTE_VALUE_ESCAPE;
else {
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
+ return -ENOMEM;
value[n_value++] = c;
}
@@ -537,10 +580,8 @@ static int parse_env_file_internal(
state = DOUBLE_QUOTE_VALUE;
if (!strchr(newline, c)) {
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
+ return -ENOMEM;
value[n_value++] = c;
}
@@ -585,14 +626,12 @@ static int parse_env_file_internal(
r = push(fname, line, key, value, userdata, n_pushed);
if (r < 0)
- goto fail;
+ return r;
+
+ value = NULL;
}
return 0;
-
-fail:
- free(value);
- return r;
}
static int check_utf8ness_and_warn(
@@ -657,21 +696,41 @@ static int parse_env_file_push(
return 0;
}
-int parse_env_file(
+int parse_env_filev(
+ FILE *f,
const char *fname,
- const char *newline, ...) {
+ const char *newline,
+ va_list ap) {
- va_list ap;
int r, n_pushed = 0;
+ va_list aq;
if (!newline)
newline = NEWLINE;
+ va_copy(aq, ap);
+ r = parse_env_file_internal(f, fname, newline, parse_env_file_push, &aq, &n_pushed);
+ va_end(aq);
+ if (r < 0)
+ return r;
+
+ return n_pushed;
+}
+
+int parse_env_file(
+ FILE *f,
+ const char *fname,
+ const char *newline,
+ ...) {
+
+ va_list ap;
+ int r;
+
va_start(ap, newline);
- r = parse_env_file_internal(NULL, fname, newline, parse_env_file_push, &ap, &n_pushed);
+ r = parse_env_filev(f, fname, newline, ap);
va_end(ap);
- return r < 0 ? r : n_pushed;
+ return r;
}
#if 0 /// UNNEEDED by elogind
@@ -825,29 +884,29 @@ static void write_env_var(FILE *f, const char *v) {
p = strchr(v, '=');
if (!p) {
/* Fallback */
- fputs(v, f);
- fputc('\n', f);
+ fputs_unlocked(v, f);
+ fputc_unlocked('\n', f);
return;
}
p++;
- fwrite(v, 1, p-v, f);
+ fwrite_unlocked(v, 1, p-v, f);
if (string_has_cc(p, NULL) || chars_intersect(p, WHITESPACE SHELL_NEED_QUOTES)) {
- fputc('\"', f);
+ fputc_unlocked('\"', f);
for (; *p; p++) {
if (strchr(SHELL_NEED_ESCAPE, *p))
- fputc('\\', f);
+ fputc_unlocked('\\', f);
- fputc(*p, f);
+ fputc_unlocked(*p, f);
}
- fputc('\"', f);
+ fputc_unlocked('\"', f);
} else
- fputs(p, f);
+ fputs_unlocked(p, f);
- fputc('\n', f);
+ fputc_unlocked('\n', f);
}
int write_env_file(const char *fname, char **l) {
@@ -862,7 +921,8 @@ int write_env_file(const char *fname, char **l) {
if (r < 0)
return r;
- fchmod_umask(fileno(f), 0644);
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+ (void) fchmod_umask(fileno(f), 0644);
STRV_FOREACH(i, l)
write_env_var(f, *i);
@@ -880,14 +940,16 @@ int write_env_file(const char *fname, char **l) {
}
int executable_is_script(const char *path, char **interpreter) {
- int r;
_cleanup_free_ char *line = NULL;
- int len;
+ size_t len;
char *ans;
+ int r;
assert(path);
r = read_one_line_file(path, &line);
+ if (r == -ENOBUFS) /* First line overly long? if so, then it's not a script */
+ return 0;
if (r < 0)
return r;
@@ -1130,6 +1192,25 @@ int fflush_and_check(FILE *f) {
return 0;
}
+int fflush_sync_and_check(FILE *f) {
+ int r;
+
+ assert(f);
+
+ r = fflush_and_check(f);
+ if (r < 0)
+ return r;
+
+ if (fsync(fileno(f)) < 0)
+ return -errno;
+
+ r = fsync_directory_of_file(fileno(f));
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
/* This is much like mkostemp() but is subject to umask(). */
int mkostemp_safe(char *pattern) {
_cleanup_umask_ mode_t u = 0;
@@ -1165,8 +1246,7 @@ int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
if (!filename_is_valid(fn))
return -EINVAL;
- if (extra == NULL)
- extra = "";
+ extra = strempty(extra);
t = new(char, strlen(p) + 2 + strlen(extra) + 6 + 1);
if (!t)
@@ -1174,7 +1254,7 @@ int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
strcpy(stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn), "XXXXXX");
- *ret = path_kill_slashes(t);
+ *ret = path_simplify(t, false);
return 0;
}
@@ -1199,8 +1279,7 @@ int tempfn_random(const char *p, const char *extra, char **ret) {
if (!filename_is_valid(fn))
return -EINVAL;
- if (!extra)
- extra = "";
+ extra = strempty(extra);
t = new(char, strlen(p) + 2 + strlen(extra) + 16 + 1);
if (!t)
@@ -1216,7 +1295,7 @@ int tempfn_random(const char *p, const char *extra, char **ret) {
*x = 0;
- *ret = path_kill_slashes(t);
+ *ret = path_simplify(t, false);
return 0;
}
@@ -1241,8 +1320,7 @@ int tempfn_random_child(const char *p, const char *extra, char **ret) {
return r;
}
- if (!extra)
- extra = "";
+ extra = strempty(extra);
t = new(char, strlen(p) + 3 + strlen(extra) + 16 + 1);
if (!t)
@@ -1258,7 +1336,7 @@ int tempfn_random_child(const char *p, const char *extra, char **ret) {
*x = 0;
- *ret = path_kill_slashes(t);
+ *ret = path_simplify(t, false);
return 0;
}
@@ -1394,8 +1472,7 @@ int open_tmpfile_linkable(const char *target, int flags, char **ret_path) {
if (fd < 0)
return -errno;
- *ret_path = tmp;
- tmp = NULL;
+ *ret_path = TAKE_PTR(tmp);
return fd;
}
@@ -1408,7 +1485,7 @@ int open_serialization_fd(const char *ident) {
if (fd < 0) {
const char *path;
- path = getpid() == 1 ? "/run/systemd" : "/tmp";
+ path = getpid_cached() == 1 ? "/run/systemd" : "/tmp";
fd = open_tmpfile_unlinkable(path, O_RDWR|O_CLOEXEC);
if (fd < 0)
return fd;
@@ -1437,7 +1514,7 @@ int link_tmpfile(int fd, const char *path, const char *target) {
if (rename_noreplace(AT_FDCWD, path, AT_FDCWD, target) < 0)
return -errno;
} else {
- char proc_fd_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
+ char proc_fd_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
xsprintf(proc_fd_path, "/proc/self/fd/%i", fd);
@@ -1483,28 +1560,106 @@ int read_nul_string(FILE *f, char **ret) {
return -ENOMEM;
}
- *ret = x;
- x = NULL;
+ *ret = TAKE_PTR(x);
return 0;
}
+#endif // 0
int mkdtemp_malloc(const char *template, char **ret) {
- char *p;
+ _cleanup_free_ char *p = NULL;
+ int r;
- assert(template);
assert(ret);
- p = strdup(template);
+ if (template)
+ p = strdup(template);
+ else {
+ const char *tmp;
+
+ r = tmp_dir(&tmp);
+ if (r < 0)
+ return r;
+
+ p = strjoin(tmp, "/XXXXXX");
+ }
if (!p)
return -ENOMEM;
- if (!mkdtemp(p)) {
- free(p);
+ if (!mkdtemp(p))
return -errno;
- }
- *ret = p;
+ *ret = TAKE_PTR(p);
return 0;
}
-#endif // 0
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, funlockfile);
+
+int read_line(FILE *f, size_t limit, char **ret) {
+ _cleanup_free_ char *buffer = NULL;
+ size_t n = 0, allocated = 0, count = 0;
+
+ assert(f);
+
+ /* Something like a bounded version of getline().
+ *
+ * Considers EOF, \n and \0 end of line delimiters, and does not include these delimiters in the string
+ * returned.
+ *
+ * Returns the number of bytes read from the files (i.e. including delimiters — this hence usually differs from
+ * the number of characters in the returned string). When EOF is hit, 0 is returned.
+ *
+ * The input parameter limit is the maximum numbers of characters in the returned string, i.e. excluding
+ * delimiters. If the limit is hit we fail and return -ENOBUFS.
+ *
+ * If a line shall be skipped ret may be initialized as NULL. */
+
+ if (ret) {
+ if (!GREEDY_REALLOC(buffer, allocated, 1))
+ return -ENOMEM;
+ }
+
+ {
+ _unused_ _cleanup_(funlockfilep) FILE *flocked = f;
+ flockfile(f);
+
+ for (;;) {
+ int c;
+
+ if (n >= limit)
+ return -ENOBUFS;
+
+ errno = 0;
+ c = fgetc_unlocked(f);
+ if (c == EOF) {
+ /* if we read an error, and have no data to return, then propagate the error */
+ if (ferror_unlocked(f) && n == 0)
+ return errno > 0 ? -errno : -EIO;
+
+ break;
+ }
+
+ count++;
+
+ if (IN_SET(c, '\n', 0)) /* Reached a delimiter */
+ break;
+
+ if (ret) {
+ if (!GREEDY_REALLOC(buffer, allocated, n + 2))
+ return -ENOMEM;
+
+ buffer[n] = (char) c;
+ }
+
+ n++;
+ }
+ }
+
+ if (ret) {
+ buffer[n] = 0;
+
+ *ret = TAKE_PTR(buffer);
+ }
+
+ return (int) count;
+}
diff --git a/src/basic/fileio.h b/src/basic/fileio.h
index fa223fdf5..eac22ff76 100644
--- a/src/basic/fileio.h
+++ b/src/basic/fileio.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <dirent.h>
#include <stdbool.h>
#include <stddef.h>
@@ -29,28 +11,38 @@
#include "time-util.h"
typedef enum {
- WRITE_STRING_FILE_CREATE = 1,
- WRITE_STRING_FILE_ATOMIC = 2,
- WRITE_STRING_FILE_AVOID_NEWLINE = 4,
- WRITE_STRING_FILE_VERIFY_ON_FAILURE = 8,
+ WRITE_STRING_FILE_CREATE = 1 << 0,
+ WRITE_STRING_FILE_ATOMIC = 1 << 1,
+ WRITE_STRING_FILE_AVOID_NEWLINE = 1 << 2,
+ WRITE_STRING_FILE_VERIFY_ON_FAILURE = 1 << 3,
+ WRITE_STRING_FILE_SYNC = 1 << 4,
+ WRITE_STRING_FILE_DISABLE_BUFFER = 1 << 5,
+
+ /* And before you wonder, why write_string_file_atomic_label_ts() is a separate function instead of just one
+ more flag here: it's about linking: we don't want to pull -lselinux into all users of write_string_file()
+ and friends. */
+
} WriteStringFileFlags;
-int write_string_stream_ts(FILE *f, const char *line, bool enforce_newline, struct timespec *ts);
-static inline int write_string_stream(FILE *f, const char *line, bool enforce_newline) {
- return write_string_stream_ts(f, line, enforce_newline, NULL);
+int write_string_stream_ts(FILE *f, const char *line, WriteStringFileFlags flags, struct timespec *ts);
+static inline int write_string_stream(FILE *f, const char *line, WriteStringFileFlags flags) {
+ return write_string_stream_ts(f, line, flags, NULL);
}
int write_string_file_ts(const char *fn, const char *line, WriteStringFileFlags flags, struct timespec *ts);
static inline int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags) {
return write_string_file_ts(fn, line, flags, NULL);
}
+int write_string_filef(const char *fn, WriteStringFileFlags flags, const char *format, ...) _printf_(3, 4);
+
int read_one_line_file(const char *fn, char **line);
int read_full_file(const char *fn, char **contents, size_t *size);
int read_full_stream(FILE *f, char **contents, size_t *size);
int verify_file(const char *fn, const char *blob, bool accept_extra_nl);
-int parse_env_file(const char *fname, const char *separator, ...) _sentinel_;
+int parse_env_filev(FILE *f, const char *fname, const char *separator, va_list ap);
+int parse_env_file(FILE *f, const char *fname, const char *separator, ...) _sentinel_;
#if 0 /// UNNEEDED by elogind
int load_env_file(FILE *f, const char *fname, const char *separator, char ***l);
#endif // 0
@@ -83,6 +75,7 @@ int search_and_fopen_nulstr(const char *path, const char *mode, const char *root
} else
int fflush_and_check(FILE *f);
+int fflush_sync_and_check(FILE *f);
int fopen_temporary(const char *path, FILE **_f, char **_temp_path);
int mkostemp_safe(char *pattern);
@@ -108,6 +101,8 @@ int open_serialization_fd(const char *ident);
int link_tmpfile(int fd, const char *path, const char *target);
int read_nul_string(FILE *f, char **ret);
+#endif // 0
int mkdtemp_malloc(const char *template, char **ret);
-#endif // 0
+
+int read_line(FILE *f, size_t limit, char **ret);
diff --git a/src/basic/format-table.c b/src/basic/format-table.c
new file mode 100644
index 000000000..00473a2e8
--- /dev/null
+++ b/src/basic/format-table.c
@@ -0,0 +1,1255 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <stdio_ext.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "format-table.h"
+#include "gunicode.h"
+#include "pager.h"
+#include "parse-util.h"
+#include "string-util.h"
+#include "terminal-util.h"
+#include "time-util.h"
+#include "utf8.h"
+#include "util.h"
+
+#define DEFAULT_WEIGHT 100
+
+/*
+ A few notes on implementation details:
+
+ - TableCell is a 'fake' structure, it's just used as data type to pass references to specific cell positions in the
+ table. It can be easily converted to an index number and back.
+
+ - TableData is where the actual data is stored: it encapsulates the data and formatting for a specific cell. It's
+ 'pseudo-immutable' and ref-counted. When a cell's data's formatting is to be changed, we duplicate the object if the
+ ref-counting is larger than 1. Note that TableData and its ref-counting is mostly not visible to the outside. The
+ outside only sees Table and TableCell.
+
+ - The Table object stores a simple one-dimensional array of references to TableData objects, one row after the
+ previous one.
+
+ - There's no special concept of a "row" or "column" in the table, and no special concept of the "header" row. It's all
+ derived from the cell index: we know how many cells are to be stored in a row, and can determine the rest from
+ that. The first row is always the header row. If header display is turned off we simply skip outputting the first
+ row. Also, when sorting rows we always leave the first row where it is, as the header shouldn't move.
+
+ - Note because there's no row and no column object some properties that might be approproate as row/column properties
+ are exposed as cell properties instead. For example, the "weight" of a column (which is used to determine where to
+ add/remove space preferable when expanding/compressing tables horizontally) is actually made the "weight" of a
+ cell. Given that we usually need it per-column though we will calculate the average across every cell of the column
+ instead.
+
+ - To make things easy, when cells are added without any explicit configured formatting, then we'll copy the formatting
+ from the same cell in the previous cell. This is particularly useful for the "weight" of the cell (see above), as
+ this means setting the weight of the cells of the header row will nicely propagate to all cells in the other rows.
+*/
+
+typedef struct TableData {
+ unsigned n_ref;
+ TableDataType type;
+
+ size_t minimum_width; /* minimum width for the column */
+ size_t maximum_width; /* maximum width for the column */
+ unsigned weight; /* the horizontal weight for this column, in case the table is expanded/compressed */
+ unsigned ellipsize_percent; /* 0 … 100, where to place the ellipsis when compression is needed */
+ unsigned align_percent; /* 0 … 100, where to pad with spaces when expanding is needed. 0: left-aligned, 100: right-aligned */
+
+ const char *color; /* ANSI color string to use for this cell. When written to terminal should not move cursor. Will automatically be reset after the cell */
+ char *formatted; /* A cached textual representation of the cell data, before ellipsation/alignment */
+
+ union {
+ uint8_t data[0]; /* data is generic array */
+ bool boolean;
+ usec_t timestamp;
+ usec_t timespan;
+ uint64_t size;
+ char string[0];
+ uint32_t uint32;
+ /* … add more here as we start supporting more cell data types … */
+ };
+} TableData;
+
+static size_t TABLE_CELL_TO_INDEX(TableCell *cell) {
+ unsigned i;
+
+ assert(cell);
+
+ i = PTR_TO_UINT(cell);
+ assert(i > 0);
+
+ return i-1;
+}
+
+static TableCell* TABLE_INDEX_TO_CELL(size_t index) {
+ assert(index != (size_t) -1);
+ return UINT_TO_PTR((unsigned) (index + 1));
+}
+
+struct Table {
+ size_t n_columns;
+ size_t n_cells;
+
+ bool header; /* Whether to show the header row? */
+ size_t width; /* If != (size_t) -1 the width to format this table in */
+
+ TableData **data;
+ size_t n_allocated;
+
+ size_t *display_map; /* List of columns to show (by their index). It's fine if columns are listed multiple times or not at all */
+ size_t n_display_map;
+
+ size_t *sort_map; /* The columns to order rows by, in order of preference. */
+ size_t n_sort_map;
+};
+
+Table *table_new_raw(size_t n_columns) {
+ _cleanup_(table_unrefp) Table *t = NULL;
+
+ assert(n_columns > 0);
+
+ t = new(Table, 1);
+ if (!t)
+ return NULL;
+
+ *t = (struct Table) {
+ .n_columns = n_columns,
+ .header = true,
+ .width = (size_t) -1,
+ };
+
+ return TAKE_PTR(t);
+}
+
+Table *table_new_internal(const char *first_header, ...) {
+ _cleanup_(table_unrefp) Table *t = NULL;
+ size_t n_columns = 1;
+ va_list ap;
+ int r;
+
+ assert(first_header);
+
+ va_start(ap, first_header);
+ for (;;) {
+ const char *h;
+
+ h = va_arg(ap, const char*);
+ if (!h)
+ break;
+
+ n_columns++;
+ }
+ va_end(ap);
+
+ t = table_new_raw(n_columns);
+ if (!t)
+ return NULL;
+
+ r = table_add_cell(t, NULL, TABLE_STRING, first_header);
+ if (r < 0)
+ return NULL;
+
+ va_start(ap, first_header);
+ for (;;) {
+ const char *h;
+
+ h = va_arg(ap, const char*);
+ if (!h)
+ break;
+
+ r = table_add_cell(t, NULL, TABLE_STRING, h);
+ if (r < 0) {
+ va_end(ap);
+ return NULL;
+ }
+ }
+ va_end(ap);
+
+ assert(t->n_columns == t->n_cells);
+ return TAKE_PTR(t);
+}
+
+static TableData *table_data_unref(TableData *d) {
+ if (!d)
+ return NULL;
+
+ assert(d->n_ref > 0);
+ d->n_ref--;
+
+ if (d->n_ref > 0)
+ return NULL;
+
+ free(d->formatted);
+ return mfree(d);
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(TableData*, table_data_unref);
+
+static TableData *table_data_ref(TableData *d) {
+ if (!d)
+ return NULL;
+
+ assert(d->n_ref > 0);
+ d->n_ref++;
+
+ return d;
+}
+
+Table *table_unref(Table *t) {
+ size_t i;
+
+ if (!t)
+ return NULL;
+
+ for (i = 0; i < t->n_cells; i++)
+ table_data_unref(t->data[i]);
+
+ free(t->data);
+ free(t->display_map);
+ free(t->sort_map);
+
+ return mfree(t);
+}
+
+static size_t table_data_size(TableDataType type, const void *data) {
+
+ switch (type) {
+
+ case TABLE_EMPTY:
+ return 0;
+
+ case TABLE_STRING:
+ return strlen(data) + 1;
+
+ case TABLE_BOOLEAN:
+ return sizeof(bool);
+
+ case TABLE_TIMESTAMP:
+ case TABLE_TIMESPAN:
+ return sizeof(usec_t);
+
+ case TABLE_SIZE:
+ return sizeof(uint64_t);
+
+ case TABLE_UINT32:
+ return sizeof(uint32_t);
+
+ default:
+ assert_not_reached("Uh? Unexpected cell type");
+ }
+}
+
+static bool table_data_matches(
+ TableData *d,
+ TableDataType type,
+ const void *data,
+ size_t minimum_width,
+ size_t maximum_width,
+ unsigned weight,
+ unsigned align_percent,
+ unsigned ellipsize_percent) {
+
+ size_t k, l;
+ assert(d);
+
+ if (d->type != type)
+ return false;
+
+ if (d->minimum_width != minimum_width)
+ return false;
+
+ if (d->maximum_width != maximum_width)
+ return false;
+
+ if (d->weight != weight)
+ return false;
+
+ if (d->align_percent != align_percent)
+ return false;
+
+ if (d->ellipsize_percent != ellipsize_percent)
+ return false;
+
+ k = table_data_size(type, data);
+ l = table_data_size(d->type, d->data);
+
+ if (k != l)
+ return false;
+
+ return memcmp(data, d->data, l) == 0;
+}
+
+static TableData *table_data_new(
+ TableDataType type,
+ const void *data,
+ size_t minimum_width,
+ size_t maximum_width,
+ unsigned weight,
+ unsigned align_percent,
+ unsigned ellipsize_percent) {
+
+ size_t data_size;
+ TableData *d;
+
+ data_size = table_data_size(type, data);
+
+ d = malloc0(offsetof(TableData, data) + data_size);
+ if (!d)
+ return NULL;
+
+ d->n_ref = 1;
+ d->type = type;
+ d->minimum_width = minimum_width;
+ d->maximum_width = maximum_width;
+ d->weight = weight;
+ d->align_percent = align_percent;
+ d->ellipsize_percent = ellipsize_percent;
+ memcpy_safe(d->data, data, data_size);
+
+ return d;
+}
+
+int table_add_cell_full(
+ Table *t,
+ TableCell **ret_cell,
+ TableDataType type,
+ const void *data,
+ size_t minimum_width,
+ size_t maximum_width,
+ unsigned weight,
+ unsigned align_percent,
+ unsigned ellipsize_percent) {
+
+ _cleanup_(table_data_unrefp) TableData *d = NULL;
+ TableData *p;
+
+ assert(t);
+ assert(type >= 0);
+ assert(type < _TABLE_DATA_TYPE_MAX);
+
+ /* Determine the cell adjacent to the current one, but one row up */
+ if (t->n_cells >= t->n_columns)
+ assert_se(p = t->data[t->n_cells - t->n_columns]);
+ else
+ p = NULL;
+
+ /* If formatting parameters are left unspecified, copy from the previous row */
+ if (minimum_width == (size_t) -1)
+ minimum_width = p ? p->minimum_width : 1;
+
+ if (weight == (unsigned) -1)
+ weight = p ? p->weight : DEFAULT_WEIGHT;
+
+ if (align_percent == (unsigned) -1)
+ align_percent = p ? p->align_percent : 0;
+
+ if (ellipsize_percent == (unsigned) -1)
+ ellipsize_percent = p ? p->ellipsize_percent : 100;
+
+ assert(align_percent <= 100);
+ assert(ellipsize_percent <= 100);
+
+ /* Small optimization: Pretty often adjacent cells in two subsequent lines have the same data and
+ * formatting. Let's see if we can reuse the cell data and ref it once more. */
+
+ if (p && table_data_matches(p, type, data, minimum_width, maximum_width, weight, align_percent, ellipsize_percent))
+ d = table_data_ref(p);
+ else {
+ d = table_data_new(type, data, minimum_width, maximum_width, weight, align_percent, ellipsize_percent);
+ if (!d)
+ return -ENOMEM;
+ }
+
+ if (!GREEDY_REALLOC(t->data, t->n_allocated, MAX(t->n_cells + 1, t->n_columns)))
+ return -ENOMEM;
+
+ if (ret_cell)
+ *ret_cell = TABLE_INDEX_TO_CELL(t->n_cells);
+
+ t->data[t->n_cells++] = TAKE_PTR(d);
+
+ return 0;
+}
+
+#if 0 /// UNNEEDED by elogind
+int table_dup_cell(Table *t, TableCell *cell) {
+ size_t i;
+
+ assert(t);
+
+ /* Add the data of the specified cell a second time as a new cell to the end. */
+
+ i = TABLE_CELL_TO_INDEX(cell);
+ if (i >= t->n_cells)
+ return -ENXIO;
+
+ if (!GREEDY_REALLOC(t->data, t->n_allocated, MAX(t->n_cells + 1, t->n_columns)))
+ return -ENOMEM;
+
+ t->data[t->n_cells++] = table_data_ref(t->data[i]);
+ return 0;
+}
+#endif // 0
+
+static int table_dedup_cell(Table *t, TableCell *cell) {
+ TableData *nd, *od;
+ size_t i;
+
+ assert(t);
+
+ /* Helper call that ensures the specified cell's data object has a ref count of 1, which we can use before
+ * changing a cell's formatting without effecting every other cell's formatting that shares the same data */
+
+ i = TABLE_CELL_TO_INDEX(cell);
+ if (i >= t->n_cells)
+ return -ENXIO;
+
+ assert_se(od = t->data[i]);
+ if (od->n_ref == 1)
+ return 0;
+
+ assert(od->n_ref > 1);
+
+ nd = table_data_new(od->type, od->data, od->minimum_width, od->maximum_width, od->weight, od->align_percent, od->ellipsize_percent);
+ if (!nd)
+ return -ENOMEM;
+
+ table_data_unref(od);
+ t->data[i] = nd;
+
+ assert(nd->n_ref == 1);
+
+ return 1;
+}
+
+static TableData *table_get_data(Table *t, TableCell *cell) {
+ size_t i;
+
+ assert(t);
+ assert(cell);
+
+ /* Get the data object of the specified cell, or NULL if it doesn't exist */
+
+ i = TABLE_CELL_TO_INDEX(cell);
+ if (i >= t->n_cells)
+ return NULL;
+
+ assert(t->data[i]);
+ assert(t->data[i]->n_ref > 0);
+
+ return t->data[i];
+}
+
+#if 0 /// UNNEEDED by elogind
+int table_set_minimum_width(Table *t, TableCell *cell, size_t minimum_width) {
+ int r;
+
+ assert(t);
+ assert(cell);
+
+ if (minimum_width == (size_t) -1)
+ minimum_width = 1;
+
+ r = table_dedup_cell(t, cell);
+ if (r < 0)
+ return r;
+
+ table_get_data(t, cell)->minimum_width = minimum_width;
+ return 0;
+}
+
+int table_set_maximum_width(Table *t, TableCell *cell, size_t maximum_width) {
+ int r;
+
+ assert(t);
+ assert(cell);
+
+ r = table_dedup_cell(t, cell);
+ if (r < 0)
+ return r;
+
+ table_get_data(t, cell)->maximum_width = maximum_width;
+ return 0;
+}
+
+int table_set_weight(Table *t, TableCell *cell, unsigned weight) {
+ int r;
+
+ assert(t);
+ assert(cell);
+
+ if (weight == (unsigned) -1)
+ weight = DEFAULT_WEIGHT;
+
+ r = table_dedup_cell(t, cell);
+ if (r < 0)
+ return r;
+
+ table_get_data(t, cell)->weight = weight;
+ return 0;
+}
+#endif // 0
+
+int table_set_align_percent(Table *t, TableCell *cell, unsigned percent) {
+ int r;
+
+ assert(t);
+ assert(cell);
+
+ if (percent == (unsigned) -1)
+ percent = 0;
+
+ assert(percent <= 100);
+
+ r = table_dedup_cell(t, cell);
+ if (r < 0)
+ return r;
+
+ table_get_data(t, cell)->align_percent = percent;
+ return 0;
+}
+
+#if 0 /// UNNEEDED by elogind
+int table_set_ellipsize_percent(Table *t, TableCell *cell, unsigned percent) {
+ int r;
+
+ assert(t);
+ assert(cell);
+
+ if (percent == (unsigned) -1)
+ percent = 100;
+
+ assert(percent <= 100);
+
+ r = table_dedup_cell(t, cell);
+ if (r < 0)
+ return r;
+
+ table_get_data(t, cell)->ellipsize_percent = percent;
+ return 0;
+}
+
+int table_set_color(Table *t, TableCell *cell, const char *color) {
+ int r;
+
+ assert(t);
+ assert(cell);
+
+ r = table_dedup_cell(t, cell);
+ if (r < 0)
+ return r;
+
+ table_get_data(t, cell)->color = empty_to_null(color);
+ return 0;
+}
+#endif // 0
+
+int table_add_many_internal(Table *t, TableDataType first_type, ...) {
+ TableDataType type;
+ va_list ap;
+ int r;
+
+ assert(t);
+ assert(first_type >= 0);
+ assert(first_type < _TABLE_DATA_TYPE_MAX);
+
+ type = first_type;
+
+ va_start(ap, first_type);
+ for (;;) {
+ const void *data;
+ union {
+ uint64_t size;
+ usec_t usec;
+ uint32_t uint32;
+ bool b;
+ } buffer;
+
+ switch (type) {
+
+ case TABLE_EMPTY:
+ data = NULL;
+ break;
+
+ case TABLE_STRING:
+ data = va_arg(ap, const char *);
+ break;
+
+ case TABLE_BOOLEAN:
+ buffer.b = va_arg(ap, int);
+ data = &buffer.b;
+ break;
+
+ case TABLE_TIMESTAMP:
+ case TABLE_TIMESPAN:
+ buffer.usec = va_arg(ap, usec_t);
+ data = &buffer.usec;
+ break;
+
+ case TABLE_SIZE:
+ buffer.size = va_arg(ap, uint64_t);
+ data = &buffer.size;
+ break;
+
+ case TABLE_UINT32:
+ buffer.uint32 = va_arg(ap, uint32_t);
+ data = &buffer.uint32;
+ break;
+
+ case _TABLE_DATA_TYPE_MAX:
+ /* Used as end marker */
+ va_end(ap);
+ return 0;
+
+ default:
+ assert_not_reached("Uh? Unexpected data type.");
+ }
+
+ r = table_add_cell(t, NULL, type, data);
+ if (r < 0) {
+ va_end(ap);
+ return r;
+ }
+
+ type = va_arg(ap, TableDataType);
+ }
+}
+
+void table_set_header(Table *t, bool b) {
+ assert(t);
+
+ t->header = b;
+}
+
+void table_set_width(Table *t, size_t width) {
+ assert(t);
+
+ t->width = width;
+}
+
+int table_set_display(Table *t, size_t first_column, ...) {
+ size_t allocated, column;
+ va_list ap;
+
+ assert(t);
+
+ allocated = t->n_display_map;
+ column = first_column;
+
+ va_start(ap, first_column);
+ for (;;) {
+ assert(column < t->n_columns);
+
+ if (!GREEDY_REALLOC(t->display_map, allocated, MAX(t->n_columns, t->n_display_map+1))) {
+ va_end(ap);
+ return -ENOMEM;
+ }
+
+ t->display_map[t->n_display_map++] = column;
+
+ column = va_arg(ap, size_t);
+ if (column == (size_t) -1)
+ break;
+
+ }
+ va_end(ap);
+
+ return 0;
+}
+
+int table_set_sort(Table *t, size_t first_column, ...) {
+ size_t allocated, column;
+ va_list ap;
+
+ assert(t);
+
+ allocated = t->n_sort_map;
+ column = first_column;
+
+ va_start(ap, first_column);
+ for (;;) {
+ assert(column < t->n_columns);
+
+ if (!GREEDY_REALLOC(t->sort_map, allocated, MAX(t->n_columns, t->n_sort_map+1))) {
+ va_end(ap);
+ return -ENOMEM;
+ }
+
+ t->sort_map[t->n_sort_map++] = column;
+
+ column = va_arg(ap, size_t);
+ if (column == (size_t) -1)
+ break;
+ }
+ va_end(ap);
+
+ return 0;
+}
+
+static int cell_data_compare(TableData *a, size_t index_a, TableData *b, size_t index_b) {
+ assert(a);
+ assert(b);
+
+ if (a->type == b->type) {
+
+ /* We only define ordering for cells of the same data type. If cells with different data types are
+ * compared we follow the order the cells were originally added in */
+
+ switch (a->type) {
+
+ case TABLE_STRING:
+ return strcmp(a->string, b->string);
+
+ case TABLE_BOOLEAN:
+ if (!a->boolean && b->boolean)
+ return -1;
+ if (a->boolean && !b->boolean)
+ return 1;
+ return 0;
+
+ case TABLE_TIMESTAMP:
+ if (a->timestamp < b->timestamp)
+ return -1;
+ if (a->timestamp > b->timestamp)
+ return 1;
+ return 0;
+
+ case TABLE_TIMESPAN:
+ if (a->timespan < b->timespan)
+ return -1;
+ if (a->timespan > b->timespan)
+ return 1;
+ return 0;
+
+ case TABLE_SIZE:
+ if (a->size < b->size)
+ return -1;
+ if (a->size > b->size)
+ return 1;
+ return 0;
+
+ case TABLE_UINT32:
+ if (a->uint32 < b->uint32)
+ return -1;
+ if (a->uint32 > b->uint32)
+ return 1;
+ return 0;
+
+ default:
+ ;
+ }
+ }
+
+ /* Generic fallback using the orginal order in which the cells where added. */
+ if (index_a < index_b)
+ return -1;
+ if (index_a > index_b)
+ return 1;
+
+ return 0;
+}
+
+static int table_data_compare(const void *x, const void *y, void *userdata) {
+ const size_t *a = x, *b = y;
+ Table *t = userdata;
+ size_t i;
+ int r;
+
+ assert(t);
+ assert(t->sort_map);
+
+ /* Make sure the header stays at the beginning */
+ if (*a < t->n_columns && *b < t->n_columns)
+ return 0;
+ if (*a < t->n_columns)
+ return -1;
+ if (*b < t->n_columns)
+ return 1;
+
+ /* Order other lines by the sorting map */
+ for (i = 0; i < t->n_sort_map; i++) {
+ TableData *d, *dd;
+
+ d = t->data[*a + t->sort_map[i]];
+ dd = t->data[*b + t->sort_map[i]];
+
+ r = cell_data_compare(d, *a, dd, *b);
+ if (r != 0)
+ return r;
+ }
+
+ /* Order identical lines by the order there were originally added in */
+ if (*a < *b)
+ return -1;
+ if (*a > *b)
+ return 1;
+
+ return 0;
+}
+
+static const char *table_data_format(TableData *d) {
+ assert(d);
+
+ if (d->formatted)
+ return d->formatted;
+
+ switch (d->type) {
+ case TABLE_EMPTY:
+ return "";
+
+ case TABLE_STRING:
+ return d->string;
+
+ case TABLE_BOOLEAN:
+ return yes_no(d->boolean);
+
+ case TABLE_TIMESTAMP: {
+ _cleanup_free_ char *p;
+
+ p = new(char, FORMAT_TIMESTAMP_MAX);
+ if (!p)
+ return NULL;
+
+ if (!format_timestamp(p, FORMAT_TIMESTAMP_MAX, d->timestamp))
+ return "n/a";
+
+ d->formatted = TAKE_PTR(p);
+ break;
+ }
+
+ case TABLE_TIMESPAN: {
+ _cleanup_free_ char *p;
+
+ p = new(char, FORMAT_TIMESPAN_MAX);
+ if (!p)
+ return NULL;
+
+ if (!format_timespan(p, FORMAT_TIMESPAN_MAX, d->timestamp, 0))
+ return "n/a";
+
+ d->formatted = TAKE_PTR(p);
+ break;
+ }
+
+ case TABLE_SIZE: {
+ _cleanup_free_ char *p;
+
+ p = new(char, FORMAT_BYTES_MAX);
+ if (!p)
+ return NULL;
+
+ if (!format_bytes(p, FORMAT_BYTES_MAX, d->size))
+ return "n/a";
+
+ d->formatted = TAKE_PTR(p);
+ break;
+ }
+
+ case TABLE_UINT32: {
+ _cleanup_free_ char *p;
+
+ p = new(char, DECIMAL_STR_WIDTH(d->uint32) + 1);
+ if (!p)
+ return NULL;
+
+ sprintf(p, "%" PRIu32, d->uint32);
+ d->formatted = TAKE_PTR(p);
+ break;
+ }
+
+ default:
+ assert_not_reached("Unexpected type?");
+ }
+
+ return d->formatted;
+}
+
+static int table_data_requested_width(TableData *d, size_t *ret) {
+ const char *t;
+ size_t l;
+
+ t = table_data_format(d);
+ if (!t)
+ return -ENOMEM;
+
+ l = utf8_console_width(t);
+ if (l == (size_t) -1)
+ return -EINVAL;
+
+ if (d->maximum_width != (size_t) -1 && l > d->maximum_width)
+ l = d->maximum_width;
+
+ if (l < d->minimum_width)
+ l = d->minimum_width;
+
+ *ret = l;
+ return 0;
+}
+
+static char *align_string_mem(const char *str, size_t new_length, unsigned percent) {
+ size_t w = 0, space, lspace, old_length;
+ const char *p;
+ char *ret;
+ size_t i;
+
+ /* As with ellipsize_mem(), 'old_length' is a byte size while 'new_length' is a width in character cells */
+
+ assert(str);
+ assert(percent <= 100);
+
+ old_length = strlen(str);
+
+ /* Determine current width on screen */
+ p = str;
+ while (p < str + old_length) {
+ char32_t c;
+
+ if (utf8_encoded_to_unichar(p, &c) < 0) {
+ p++, w++; /* count invalid chars as 1 */
+ continue;
+ }
+
+ p = utf8_next_char(p);
+ w += unichar_iswide(c) ? 2 : 1;
+ }
+
+ /* Already wider than the target, if so, don't do anything */
+ if (w >= new_length)
+ return strndup(str, old_length);
+
+ /* How much spaces shall we add? An how much on the left side? */
+ space = new_length - w;
+ lspace = space * percent / 100U;
+
+ ret = new(char, space + old_length + 1);
+ if (!ret)
+ return NULL;
+
+ for (i = 0; i < lspace; i++)
+ ret[i] = ' ';
+ memcpy(ret + lspace, str, old_length);
+ for (i = lspace + old_length; i < space + old_length; i++)
+ ret[i] = ' ';
+
+ ret[space + old_length] = 0;
+ return ret;
+}
+
+int table_print(Table *t, FILE *f) {
+ size_t n_rows, *minimum_width, *maximum_width, display_columns, *requested_width,
+ i, j, table_minimum_width, table_maximum_width, table_requested_width, table_effective_width,
+ *width;
+ _cleanup_free_ size_t *sorted = NULL;
+ uint64_t *column_weight, weight_sum;
+ int r;
+
+ assert(t);
+
+ if (!f)
+ f = stdout;
+
+ /* Ensure we have no incomplete rows */
+ assert(t->n_cells % t->n_columns == 0);
+
+ n_rows = t->n_cells / t->n_columns;
+ assert(n_rows > 0); /* at least the header row must be complete */
+
+ if (t->sort_map) {
+ /* If sorting is requested, let's calculate an index table we use to lookup the actual index to display with. */
+
+ sorted = new(size_t, n_rows);
+ if (!sorted)
+ return -ENOMEM;
+
+ for (i = 0; i < n_rows; i++)
+ sorted[i] = i * t->n_columns;
+
+ qsort_r_safe(sorted, n_rows, sizeof(size_t), table_data_compare, t);
+ }
+
+ if (t->display_map)
+ display_columns = t->n_display_map;
+ else
+ display_columns = t->n_columns;
+
+ assert(display_columns > 0);
+
+ minimum_width = newa(size_t, display_columns);
+ maximum_width = newa(size_t, display_columns);
+ requested_width = newa(size_t, display_columns);
+ width = newa(size_t, display_columns);
+ column_weight = newa0(uint64_t, display_columns);
+
+ for (j = 0; j < display_columns; j++) {
+ minimum_width[j] = 1;
+ maximum_width[j] = (size_t) -1;
+ requested_width[j] = (size_t) -1;
+ }
+
+ /* First pass: determine column sizes */
+ for (i = t->header ? 0 : 1; i < n_rows; i++) {
+ TableData **row;
+
+ /* Note that we don't care about ordering at this time, as we just want to determine column sizes,
+ * hence we don't care for sorted[] during the first pass. */
+ row = t->data + i * t->n_columns;
+
+ for (j = 0; j < display_columns; j++) {
+ TableData *d;
+ size_t req;
+
+ assert_se(d = row[t->display_map ? t->display_map[j] : j]);
+
+ r = table_data_requested_width(d, &req);
+ if (r < 0)
+ return r;
+
+ /* Determine the biggest width that any cell in this column would like to have */
+ if (requested_width[j] == (size_t) -1 ||
+ requested_width[j] < req)
+ requested_width[j] = req;
+
+ /* Determine the minimum width any cell in this column needs */
+ if (minimum_width[j] < d->minimum_width)
+ minimum_width[j] = d->minimum_width;
+
+ /* Determine the maximum width any cell in this column needs */
+ if (d->maximum_width != (size_t) -1 &&
+ (maximum_width[j] == (size_t) -1 ||
+ maximum_width[j] > d->maximum_width))
+ maximum_width[j] = d->maximum_width;
+
+ /* Determine the full columns weight */
+ column_weight[j] += d->weight;
+ }
+ }
+
+ /* One space between each column */
+ table_requested_width = table_minimum_width = table_maximum_width = display_columns - 1;
+
+ /* Calculate the total weight for all columns, plus the minimum, maximum and requested width for the table. */
+ weight_sum = 0;
+ for (j = 0; j < display_columns; j++) {
+ weight_sum += column_weight[j];
+
+ table_minimum_width += minimum_width[j];
+
+ if (maximum_width[j] == (size_t) -1)
+ table_maximum_width = (size_t) -1;
+ else
+ table_maximum_width += maximum_width[j];
+
+ table_requested_width += requested_width[j];
+ }
+
+ /* Calculate effective table width */
+ if (t->width == (size_t) -1)
+ table_effective_width = pager_have() ? table_requested_width : MIN(table_requested_width, columns());
+ else
+ table_effective_width = t->width;
+
+ if (table_maximum_width != (size_t) -1 && table_effective_width > table_maximum_width)
+ table_effective_width = table_maximum_width;
+
+ if (table_effective_width < table_minimum_width)
+ table_effective_width = table_minimum_width;
+
+ if (table_effective_width >= table_requested_width) {
+ size_t extra;
+
+ /* We have extra room, let's distribute it among columns according to their weights. We first provide
+ * each column with what it asked for and the distribute the rest. */
+
+ extra = table_effective_width - table_requested_width;
+
+ for (j = 0; j < display_columns; j++) {
+ size_t delta;
+
+ if (weight_sum == 0)
+ width[j] = requested_width[j] + extra / (display_columns - j); /* Avoid division by zero */
+ else
+ width[j] = requested_width[j] + (extra * column_weight[j]) / weight_sum;
+
+ if (maximum_width[j] != (size_t) -1 && width[j] > maximum_width[j])
+ width[j] = maximum_width[j];
+
+ if (width[j] < minimum_width[j])
+ width[j] = minimum_width[j];
+
+ assert(width[j] >= requested_width[j]);
+ delta = width[j] - requested_width[j];
+
+ /* Subtract what we just added from the rest */
+ if (extra > delta)
+ extra -= delta;
+ else
+ extra = 0;
+
+ assert(weight_sum >= column_weight[j]);
+ weight_sum -= column_weight[j];
+ }
+
+ } else {
+ /* We need to compress the table, columns can't get what they asked for. We first provide each column
+ * with the minimum they need, and then distribute anything left. */
+ bool finalize = false;
+ size_t extra;
+
+ extra = table_effective_width - table_minimum_width;
+
+ for (j = 0; j < display_columns; j++)
+ width[j] = (size_t) -1;
+
+ for (;;) {
+ bool restart = false;
+
+ for (j = 0; j < display_columns; j++) {
+ size_t delta, w;
+
+ /* Did this column already get something assigned? If so, let's skip to the next */
+ if (width[j] != (size_t) -1)
+ continue;
+
+ if (weight_sum == 0)
+ w = minimum_width[j] + extra / (display_columns - j); /* avoid division by zero */
+ else
+ w = minimum_width[j] + (extra * column_weight[j]) / weight_sum;
+
+ if (w >= requested_width[j]) {
+ /* Never give more than requested. If we hit a column like this, there's more
+ * space to allocate to other columns which means we need to restart the
+ * iteration. However, if we hit a column like this, let's assign it the space
+ * it wanted for good early.*/
+
+ w = requested_width[j];
+ restart = true;
+
+ } else if (!finalize)
+ continue;
+
+ width[j] = w;
+
+ assert(w >= minimum_width[j]);
+ delta = w - minimum_width[j];
+
+ assert(delta <= extra);
+ extra -= delta;
+
+ assert(weight_sum >= column_weight[j]);
+ weight_sum -= column_weight[j];
+
+ if (restart)
+ break;
+ }
+
+ if (finalize) {
+ assert(!restart);
+ break;
+ }
+
+ if (!restart)
+ finalize = true;
+ }
+ }
+
+ /* Second pass: show output */
+ for (i = t->header ? 0 : 1; i < n_rows; i++) {
+ TableData **row;
+
+ if (sorted)
+ row = t->data + sorted[i];
+ else
+ row = t->data + i * t->n_columns;
+
+ for (j = 0; j < display_columns; j++) {
+ _cleanup_free_ char *buffer = NULL;
+ const char *field;
+ TableData *d;
+ size_t l;
+
+ assert_se(d = row[t->display_map ? t->display_map[j] : j]);
+
+ field = table_data_format(d);
+ if (!field)
+ return -ENOMEM;
+
+ l = utf8_console_width(field);
+ if (l > width[j]) {
+ /* Field is wider than allocated space. Let's ellipsize */
+
+ buffer = ellipsize(field, width[j], d->ellipsize_percent);
+ if (!buffer)
+ return -ENOMEM;
+
+ field = buffer;
+
+ } else if (l < width[j]) {
+ /* Field is shorter than allocated space. Let's align with spaces */
+
+ buffer = align_string_mem(field, width[j], d->align_percent);
+ if (!buffer)
+ return -ENOMEM;
+
+ field = buffer;
+ }
+
+ if (j > 0)
+ fputc(' ', f); /* column separator */
+
+ if (d->color)
+ fputs(d->color, f);
+
+ fputs(field, f);
+
+ if (d->color)
+ fputs(ansi_normal(), f);
+ }
+
+ fputc('\n', f);
+ }
+
+ return fflush_and_check(f);
+}
+
+int table_format(Table *t, char **ret) {
+ _cleanup_fclose_ FILE *f = NULL;
+ char *buf = NULL;
+ size_t sz = 0;
+ int r;
+
+ f = open_memstream(&buf, &sz);
+ if (!f)
+ return -ENOMEM;
+
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
+ r = table_print(t, f);
+ if (r < 0)
+ return r;
+
+ f = safe_fclose(f);
+
+ *ret = buf;
+
+ return 0;
+}
+
+size_t table_get_rows(Table *t) {
+ if (!t)
+ return 0;
+
+ assert(t->n_columns > 0);
+ return t->n_cells / t->n_columns;
+}
+
+#if 0 /// UNNEEDED by elogind
+size_t table_get_columns(Table *t) {
+ if (!t)
+ return 0;
+
+ assert(t->n_columns > 0);
+ return t->n_columns;
+}
+#endif // 0
diff --git a/src/basic/format-table.h b/src/basic/format-table.h
new file mode 100644
index 000000000..b8f068e99
--- /dev/null
+++ b/src/basic/format-table.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "macro.h"
+
+typedef enum TableDataType {
+ TABLE_EMPTY,
+ TABLE_STRING,
+ TABLE_BOOLEAN,
+ TABLE_TIMESTAMP,
+ TABLE_TIMESPAN,
+ TABLE_SIZE,
+ TABLE_UINT32,
+ _TABLE_DATA_TYPE_MAX,
+ _TABLE_DATA_TYPE_INVALID = -1,
+} TableDataType;
+
+typedef struct Table Table;
+typedef struct TableCell TableCell;
+
+Table *table_new_internal(const char *first_header, ...) _sentinel_;
+#define table_new(...) table_new_internal(__VA_ARGS__, NULL)
+Table *table_new_raw(size_t n_columns);
+Table *table_unref(Table *t);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(Table*, table_unref);
+
+int table_add_cell_full(Table *t, TableCell **ret_cell, TableDataType type, const void *data, size_t minimum_width, size_t maximum_width, unsigned weight, unsigned align_percent, unsigned ellipsize_percent);
+static inline int table_add_cell(Table *t, TableCell **ret_cell, TableDataType type, const void *data) {
+ return table_add_cell_full(t, ret_cell, type, data, (size_t) -1, (size_t) -1, (unsigned) -1, (unsigned) -1, (unsigned) -1);
+}
+
+#if 0 /// UNNEEDED by elogind
+int table_dup_cell(Table *t, TableCell *cell);
+
+int table_set_minimum_width(Table *t, TableCell *cell, size_t minimum_width);
+int table_set_maximum_width(Table *t, TableCell *cell, size_t maximum_width);
+int table_set_weight(Table *t, TableCell *cell, unsigned weight);
+#endif // 0
+int table_set_align_percent(Table *t, TableCell *cell, unsigned percent);
+#if 0 /// UNNEEDED by elogind
+int table_set_ellipsize_percent(Table *t, TableCell *cell, unsigned percent);
+int table_set_color(Table *t, TableCell *cell, const char *color);
+#endif // 0
+
+int table_add_many_internal(Table *t, TableDataType first_type, ...);
+#define table_add_many(t, ...) table_add_many_internal(t, __VA_ARGS__, _TABLE_DATA_TYPE_MAX)
+
+void table_set_header(Table *table, bool b);
+void table_set_width(Table *t, size_t width);
+int table_set_display(Table *t, size_t first_column, ...);
+int table_set_sort(Table *t, size_t first_column, ...);
+
+int table_print(Table *t, FILE *f);
+int table_format(Table *t, char **ret);
+
+static inline TableCell* TABLE_HEADER_CELL(size_t i) {
+ return SIZE_TO_PTR(i + 1);
+}
+
+size_t table_get_rows(Table *t);
+#if 0 /// UNNEEDED by elogind
+size_t table_get_columns(Table *t);
+#endif // 0
diff --git a/src/basic/format-util.h b/src/basic/format-util.h
index ae42a8f89..160550cd6 100644
--- a/src/basic/format-util.h
+++ b/src/basic/format-util.h
@@ -1,23 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Ronny Chevalier
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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>
diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c
index 33624354f..562fe8277 100644
--- a/src/basic/fs-util.c
+++ b/src/basic/fs-util.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <stddef.h>
@@ -23,6 +6,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
+#include <linux/magic.h>
#include <time.h>
#include <unistd.h>
@@ -37,13 +21,18 @@
#include "mkdir.h"
#include "parse-util.h"
#include "path-util.h"
+//#include "process-util.h"
#include "stat-util.h"
+#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
//#include "time-util.h"
#include "user-util.h"
#include "util.h"
+/// Additional includes needed by elogind
+#include "process-util.h"
+
int unlink_noerrno(const char *path) {
PROTECT_ERRNO;
int r;
@@ -103,7 +92,6 @@ int rmdir_parents(const char *path, const char *stop) {
return 0;
}
-
int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) {
struct stat buf;
int ret;
@@ -227,63 +215,36 @@ int readlink_and_make_absolute(const char *p, char **r) {
}
#if 0 /// UNNEEDED by elogind
-int readlink_and_canonicalize(const char *p, const char *root, char **ret) {
- char *t, *s;
- int r;
-
- assert(p);
- assert(ret);
-
- r = readlink_and_make_absolute(p, &t);
- if (r < 0)
- return r;
-
- r = chase_symlinks(t, root, 0, &s);
- if (r < 0)
- /* If we can't follow up, then let's return the original string, slightly cleaned up. */
- *ret = path_kill_slashes(t);
- else {
- *ret = s;
- free(t);
- }
-
- return 0;
-}
-
-int readlink_and_make_absolute_root(const char *root, const char *path, char **ret) {
- _cleanup_free_ char *target = NULL, *t = NULL;
- const char *full;
- int r;
+#endif // 0
+int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
+ assert(path);
- full = prefix_roota(root, path);
- r = readlink_malloc(full, &target);
- if (r < 0)
- return r;
+ /* 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. */
- t = file_in_same_dir(path, target);
- if (!t)
- return -ENOMEM;
+ if (mode != MODE_INVALID)
+ if (chmod(path, mode) < 0)
+ return -errno;
- *ret = t;
- t = NULL;
+ if (uid != UID_INVALID || gid != GID_INVALID)
+ if (chown(path, uid, gid) < 0)
+ return -errno;
return 0;
}
-#endif // 0
-
-int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
- assert(path);
+int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid) {
/* Under the assumption that we are running privileged we
* first change the access mode and only then hand out
* ownership to avoid a window where access is too open. */
if (mode != MODE_INVALID)
- if (chmod(path, mode) < 0)
+ if (fchmod(fd, mode) < 0)
return -errno;
if (uid != UID_INVALID || gid != GID_INVALID)
- if (chown(path, uid, gid) < 0)
+ if (fchown(fd, uid, gid) < 0)
return -errno;
return 0;
@@ -300,6 +261,21 @@ int fchmod_umask(int fd, mode_t m) {
return r;
}
+int fchmod_opath(int fd, mode_t m) {
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+
+ /* This function operates also on fd that might have been opened with
+ * O_PATH. Indeed fchmodat() doesn't have the AT_EMPTY_PATH flag like
+ * fchownat() does. */
+
+ xsprintf(procfs_path, "/proc/self/fd/%i", fd);
+
+ if (chmod(procfs_path, m) < 0)
+ return -errno;
+
+ return 0;
+}
+
int fd_warn_permissions(const char *path, int fd) {
struct stat st;
@@ -312,50 +288,67 @@ int fd_warn_permissions(const char *path, int fd) {
if (st.st_mode & 0002)
log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path);
- if (getpid() == 1 && (st.st_mode & 0044) != 0044)
+ if (getpid_cached() == 1 && (st.st_mode & 0044) != 0044)
log_warning("Configuration file %s is marked world-inaccessible. This has no effect as configuration data is accessible via APIs without restrictions. Proceeding anyway.", path);
return 0;
}
int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) {
- _cleanup_close_ int fd;
- int r;
+ char fdpath[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+ _cleanup_close_ int fd = -1;
+ int r, ret = 0;
assert(path);
- if (parents)
- mkdir_parents(path, 0755);
-
- fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY,
- (mode == 0 || mode == MODE_INVALID) ? 0644 : mode);
- if (fd < 0)
- return -errno;
+ /* Note that touch_file() does not follow symlinks: if invoked on an existing symlink, then it is the symlink
+ * itself which is updated, not its target
+ *
+ * Returns the first error we encounter, but tries to apply as much as possible. */
- if (mode != MODE_INVALID) {
- r = fchmod(fd, mode);
- if (r < 0)
+ if (parents)
+ (void) mkdir_parents(path, 0755);
+
+ /* Initially, we try to open the node with O_PATH, so that we get a reference to the node. This is useful in
+ * case the path refers to an existing device or socket node, as we can open it successfully in all cases, and
+ * won't trigger any driver magic or so. */
+ fd = open(path, O_PATH|O_CLOEXEC|O_NOFOLLOW);
+ if (fd < 0) {
+ if (errno != ENOENT)
return -errno;
- }
- if (uid != UID_INVALID || gid != GID_INVALID) {
- r = fchown(fd, uid, gid);
- if (r < 0)
+ /* if the node doesn't exist yet, we create it, but with O_EXCL, so that we only create a regular file
+ * here, and nothing else */
+ fd = open(path, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, IN_SET(mode, 0, MODE_INVALID) ? 0644 : mode);
+ if (fd < 0)
return -errno;
}
+ /* Let's make a path from the fd, and operate on that. With this logic, we can adjust the access mode,
+ * ownership and time of the file node in all cases, even if the fd refers to an O_PATH object — which is
+ * something fchown(), fchmod(), futimensat() don't allow. */
+ xsprintf(fdpath, "/proc/self/fd/%i", fd);
+
+ if (mode != MODE_INVALID)
+ if (chmod(fdpath, mode) < 0)
+ ret = -errno;
+
+ if (uid_is_valid(uid) || gid_is_valid(gid))
+ if (chown(fdpath, uid, gid) < 0 && ret >= 0)
+ ret = -errno;
+
if (stamp != USEC_INFINITY) {
struct timespec ts[2];
timespec_store(&ts[0], stamp);
ts[1] = ts[0];
- r = futimens(fd, ts);
+ r = utimensat(AT_FDCWD, fdpath, ts, 0);
} else
- r = futimens(fd, NULL);
- if (r < 0)
+ r = utimensat(AT_FDCWD, fdpath, NULL, 0);
+ if (r < 0 && ret >= 0)
return -errno;
- return 0;
+ return ret;
}
int touch(const char *path) {
@@ -364,22 +357,25 @@ int touch(const char *path) {
#if 0 /// UNNEEDED by elogind
int symlink_idempotent(const char *from, const char *to) {
- _cleanup_free_ char *p = NULL;
int r;
assert(from);
assert(to);
if (symlink(from, to) < 0) {
+ _cleanup_free_ char *p = NULL;
+
if (errno != EEXIST)
return -errno;
r = readlink_malloc(to, &p);
- if (r < 0)
+ if (r == -EINVAL) /* Not a symlink? In that case return the original error we encountered: -EEXIST */
+ return -EEXIST;
+ if (r < 0) /* Any other error? In that case propagate it as is */
return r;
- if (!streq(p, from))
- return -EINVAL;
+ if (!streq(p, from)) /* Not the symlink we want it to be? In that case, propagate the original -EEXIST */
+ return -EEXIST;
}
return 0;
@@ -486,10 +482,8 @@ int get_files_in_directory(const char *path, char ***list) {
n++;
}
- if (list) {
- *list = l;
- l = NULL; /* avoid freeing */
- }
+ if (list)
+ *list = TAKE_PTR(l);
return n;
}
@@ -512,7 +506,7 @@ static int getenv_tmp_dir(const char **ret_path) {
r = -ENOTDIR;
goto next;
}
- if (!path_is_safe(e)) {
+ if (!path_is_normalized(e)) {
r = -EPERM;
goto next;
}
@@ -584,9 +578,19 @@ int tmp_dir(const char **ret) {
return tmp_dir_internal("/tmp", ret);
}
-#if 0 /// UNNEEDED by elogind
+int unlink_or_warn(const char *filename) {
+ if (unlink(filename) < 0 && errno != ENOENT)
+ /* If the file doesn't exist and the fs simply was read-only (in which
+ * case unlink() returns EROFS even if the file doesn't exist), don't
+ * complain */
+ if (errno != EROFS || access(filename, F_OK) >= 0)
+ return log_error_errno(errno, "Failed to remove \"%s\": %m", filename);
+
+ return 0;
+}
+
int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
- char path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
+ char path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
int r;
/* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */
@@ -598,18 +602,39 @@ int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
return r;
}
-#endif // 0
+
+static bool safe_transition(const struct stat *a, const struct stat *b) {
+ /* Returns true if the transition from a to b is safe, i.e. that we never transition from unprivileged to
+ * privileged files or directories. Why bother? So that unprivileged code can't symlink to privileged files
+ * making us believe we read something safe even though it isn't safe in the specific context we open it in. */
+
+ if (a->st_uid == 0) /* Transitioning from privileged to unprivileged is always fine */
+ return true;
+
+ return a->st_uid == b->st_uid; /* Otherwise we need to stay within the same UID */
+}
int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret) {
_cleanup_free_ char *buffer = NULL, *done = NULL, *root = NULL;
_cleanup_close_ int fd = -1;
- unsigned max_follow = 32; /* how many symlinks to follow before giving up and returning ELOOP */
+ unsigned max_follow = CHASE_SYMLINKS_MAX; /* how many symlinks to follow before giving up and returning ELOOP */
+ struct stat previous_stat;
bool exists = true;
char *todo;
int r;
assert(path);
+ /* Either the file may be missing, or we return an fd to the final object, but both make no sense */
+ if (FLAGS_SET(flags, CHASE_NONEXISTENT | CHASE_OPEN))
+ return -EINVAL;
+
+ if (FLAGS_SET(flags, CHASE_STEP | CHASE_OPEN))
+ return -EINVAL;
+
+ if (isempty(path))
+ return -EINVAL;
+
/* This is a lot like canonicalize_file_name(), but takes an additional "root" parameter, that allows following
* symlinks relative to a root directory, instead of the root of the host.
*
@@ -630,16 +655,54 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
* function what to do when encountering a symlink with an absolute path as directory: prefix it by the
* specified path.
*
- * Note: there's also chase_symlinks_prefix() (see below), which as first step prefixes the passed path by the
- * passed root. */
+ * There are three ways to invoke this function:
+ *
+ * 1. Without CHASE_STEP or CHASE_OPEN: in this case the path is resolved and the normalized path is returned
+ * in `ret`. The return value is < 0 on error. If CHASE_NONEXISTENT is also set 0 is returned if the file
+ * doesn't exist, > 0 otherwise. If CHASE_NONEXISTENT is not set >= 0 is returned if the destination was
+ * found, -ENOENT if it doesn't.
+ *
+ * 2. With CHASE_OPEN: in this case the destination is opened after chasing it as O_PATH and this file
+ * descriptor is returned as return value. This is useful to open files relative to some root
+ * directory. Note that the returned O_PATH file descriptors must be converted into a regular one (using
+ * fd_reopen() or such) before it can be used for reading/writing. CHASE_OPEN may not be combined with
+ * CHASE_NONEXISTENT.
+ *
+ * 3. With CHASE_STEP: in this case only a single step of the normalization is executed, i.e. only the first
+ * symlink or ".." component of the path is resolved, and the resulting path is returned. This is useful if
+ * a caller wants to trace the a path through the file system verbosely. Returns < 0 on error, > 0 if the
+ * path is fully normalized, and == 0 for each normalization step. This may be combined with
+ * CHASE_NONEXISTENT, in which case 1 is returned when a component is not found.
+ *
+ * */
+
+ /* A root directory of "/" or "" is identical to none */
+ if (empty_or_root(original_root))
+ original_root = NULL;
+
+ if (!original_root && !ret && (flags & (CHASE_NONEXISTENT|CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_OPEN|CHASE_STEP)) == CHASE_OPEN) {
+ /* Shortcut the CHASE_OPEN case if the caller isn't interested in the actual path and has no root set
+ * and doesn't care about any of the other special features we provide either. */
+ r = open(path, O_PATH|O_CLOEXEC);
+ if (r < 0)
+ return -errno;
+
+ return r;
+ }
if (original_root) {
r = path_make_absolute_cwd(original_root, &root);
if (r < 0)
return r;
- if (flags & CHASE_PREFIX_ROOT)
+ if (flags & CHASE_PREFIX_ROOT) {
+
+ /* We don't support relative paths in combination with a root directory */
+ if (!path_is_absolute(path))
+ return -EINVAL;
+
path = prefix_roota(root, path);
+ }
}
r = path_make_absolute_cwd(path, &buffer);
@@ -650,6 +713,11 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
if (fd < 0)
return -errno;
+ if (flags & CHASE_SAFE) {
+ if (fstat(fd, &previous_stat) < 0)
+ return -errno;
+ }
+
todo = buffer;
for (;;) {
_cleanup_free_ char *first = NULL;
@@ -668,9 +736,20 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
todo += m;
+ /* Empty? Then we reached the end. */
+ if (isempty(first))
+ break;
+
/* Just a single slash? Then we reached the end. */
- if (isempty(first) || path_equal(first, "/"))
+ if (path_equal(first, "/")) {
+ /* Preserve the trailing slash */
+
+ if (flags & CHASE_TRAIL_SLASH)
+ if (!strextend(&done, "/", NULL))
+ return -ENOMEM;
+
break;
+ }
/* Just a dot? Then let's eat this up. */
if (path_equal(first, "/."))
@@ -679,11 +758,11 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
/* Two dots? Then chop off the last bit of what we already found out. */
if (path_equal(first, "/..")) {
_cleanup_free_ char *parent = NULL;
- int fd_parent = -1;
+ _cleanup_close_ int fd_parent = -1;
/* If we already are at the top, then going up will not change anything. This is in-line with
* how the kernel handles this. */
- if (isempty(done) || path_equal(done, "/"))
+ if (empty_or_root(done))
continue;
parent = dirname_malloc(done);
@@ -698,12 +777,25 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
free_and_replace(done, parent);
+ if (flags & CHASE_STEP)
+ goto chased_one;
+
fd_parent = openat(fd, "..", O_CLOEXEC|O_NOFOLLOW|O_PATH);
if (fd_parent < 0)
return -errno;
+ if (flags & CHASE_SAFE) {
+ if (fstat(fd_parent, &st) < 0)
+ return -errno;
+
+ if (!safe_transition(&previous_stat, &st))
+ return -EPERM;
+
+ previous_stat = st;
+ }
+
safe_close(fd);
- fd = fd_parent;
+ fd = TAKE_FD(fd_parent);
continue;
}
@@ -714,12 +806,16 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
if (errno == ENOENT &&
(flags & CHASE_NONEXISTENT) &&
- (isempty(todo) || path_is_safe(todo))) {
+ (isempty(todo) || path_is_normalized(todo))) {
/* If CHASE_NONEXISTENT is set, and the path does not exist, then that's OK, return
* what we got so far. But don't allow this if the remaining path contains "../ or "./"
* or something else weird. */
+ /* If done is "/", as first also contains slash at the head, then remove this redundant slash. */
+ if (streq_ptr(done, "/"))
+ *done = '\0';
+
if (!strextend(&done, first, todo, NULL))
return -ENOMEM;
@@ -732,6 +828,15 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
if (fstat(child, &st) < 0)
return -errno;
+ if ((flags & CHASE_SAFE) &&
+ !safe_transition(&previous_stat, &st))
+ return -EPERM;
+
+ previous_stat = st;
+
+ if ((flags & CHASE_NO_AUTOFS) &&
+ fd_is_fs_type(child, AUTOFS_SUPER_MAGIC) > 0)
+ return -EREMOTE;
if (S_ISLNK(st.st_mode)) {
char *joined;
@@ -759,6 +864,16 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
if (fd < 0)
return -errno;
+ if (flags & CHASE_SAFE) {
+ if (fstat(fd, &st) < 0)
+ return -errno;
+
+ if (!safe_transition(&previous_stat, &st))
+ return -EPERM;
+
+ previous_stat = st;
+ }
+
free(done);
/* Note that we do not revalidate the root, we take it as is. */
@@ -770,34 +885,38 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
return -ENOMEM;
}
- }
-
- /* Prefix what's left to do with what we just read, and start the loop again,
- * but remain in the current directory. */
-
- joined = strjoin("/", destination, todo);
+ /* Prefix what's left to do with what we just read, and start the loop again, but
+ * remain in the current directory. */
+ joined = strjoin(destination, todo);
+ } else
+ joined = strjoin("/", destination, todo);
if (!joined)
return -ENOMEM;
free(buffer);
todo = buffer = joined;
+ if (flags & CHASE_STEP)
+ goto chased_one;
+
continue;
}
/* If this is not a symlink, then let's just add the name we read to what we already verified. */
- if (!done) {
- done = first;
- first = NULL;
- } else {
+ if (!done)
+ done = TAKE_PTR(first);
+ else {
+ /* If done is "/", as first also contains slash at the head, then remove this redundant slash. */
+ if (streq(done, "/"))
+ *done = '\0';
+
if (!strextend(&done, first, NULL))
return -ENOMEM;
}
/* And iterate again, but go one directory further down. */
safe_close(fd);
- fd = child;
- child = -1;
+ fd = TAKE_FD(child);
}
if (!done) {
@@ -807,10 +926,287 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
return -ENOMEM;
}
- if (ret) {
- *ret = done;
- done = NULL;
+ if (ret)
+ *ret = TAKE_PTR(done);
+
+ if (flags & CHASE_OPEN) {
+ /* Return the O_PATH fd we currently are looking to the caller. It can translate it to a proper fd by
+ * opening /proc/self/fd/xyz. */
+
+ assert(fd >= 0);
+ return TAKE_FD(fd);
}
+ if (flags & CHASE_STEP)
+ return 1;
+
return exists;
+
+chased_one:
+ if (ret) {
+ char *c;
+
+ c = strjoin(strempty(done), todo);
+ if (!c)
+ return -ENOMEM;
+
+ *ret = c;
+ }
+
+ return 0;
+}
+
+#if 0 /// UNNEEDED by elogind
+int chase_symlinks_and_open(
+ const char *path,
+ const char *root,
+ unsigned chase_flags,
+ int open_flags,
+ char **ret_path) {
+
+ _cleanup_close_ int path_fd = -1;
+ _cleanup_free_ char *p = NULL;
+ int r;
+
+ if (chase_flags & CHASE_NONEXISTENT)
+ return -EINVAL;
+
+ if (empty_or_root(root) && !ret_path && (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE)) == 0) {
+ /* Shortcut this call if none of the special features of this call are requested */
+ r = open(path, open_flags);
+ if (r < 0)
+ return -errno;
+
+ return r;
+ }
+
+ path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL);
+ if (path_fd < 0)
+ return path_fd;
+
+ r = fd_reopen(path_fd, open_flags);
+ if (r < 0)
+ return r;
+
+ if (ret_path)
+ *ret_path = TAKE_PTR(p);
+
+ return r;
+}
+
+int chase_symlinks_and_opendir(
+ const char *path,
+ const char *root,
+ unsigned chase_flags,
+ char **ret_path,
+ DIR **ret_dir) {
+
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+ _cleanup_close_ int path_fd = -1;
+ _cleanup_free_ char *p = NULL;
+ DIR *d;
+
+ if (!ret_dir)
+ return -EINVAL;
+ if (chase_flags & CHASE_NONEXISTENT)
+ return -EINVAL;
+
+ if (empty_or_root(root) && !ret_path && (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE)) == 0) {
+ /* Shortcut this call if none of the special features of this call are requested */
+ d = opendir(path);
+ if (!d)
+ return -errno;
+
+ *ret_dir = d;
+ return 0;
+ }
+
+ path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL);
+ if (path_fd < 0)
+ return path_fd;
+
+ xsprintf(procfs_path, "/proc/self/fd/%i", path_fd);
+ d = opendir(procfs_path);
+ if (!d)
+ return -errno;
+
+ if (ret_path)
+ *ret_path = TAKE_PTR(p);
+
+ *ret_dir = d;
+ return 0;
+}
+
+int chase_symlinks_and_stat(
+ const char *path,
+ const char *root,
+ unsigned chase_flags,
+ char **ret_path,
+ struct stat *ret_stat) {
+
+ _cleanup_close_ int path_fd = -1;
+ _cleanup_free_ char *p = NULL;
+
+ assert(path);
+ assert(ret_stat);
+
+ if (chase_flags & CHASE_NONEXISTENT)
+ return -EINVAL;
+
+ if (empty_or_root(root) && !ret_path && (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE)) == 0) {
+ /* Shortcut this call if none of the special features of this call are requested */
+ if (stat(path, ret_stat) < 0)
+ return -errno;
+
+ return 1;
+ }
+
+ path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL);
+ if (path_fd < 0)
+ return path_fd;
+
+ if (fstat(path_fd, ret_stat) < 0)
+ return -errno;
+
+ if (ret_path)
+ *ret_path = TAKE_PTR(p);
+
+ if (chase_flags & CHASE_OPEN)
+ return TAKE_FD(path_fd);
+
+ return 1;
+}
+#endif // 0
+
+int access_fd(int fd, int mode) {
+ char p[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
+ int r;
+
+ /* Like access() but operates on an already open fd */
+
+ xsprintf(p, "/proc/self/fd/%i", fd);
+ r = access(p, mode);
+ if (r < 0)
+ return -errno;
+
+ return r;
+}
+
+void unlink_tempfilep(char (*p)[]) {
+ /* If the file is created with mkstemp(), it will (almost always)
+ * change the suffix. Treat this as a sign that the file was
+ * successfully created. We ignore both the rare case where the
+ * original suffix is used and unlink failures. */
+ if (!endswith(*p, ".XXXXXX"))
+ (void) unlink_noerrno(*p);
+}
+
+int unlinkat_deallocate(int fd, const char *name, int flags) {
+ _cleanup_close_ int truncate_fd = -1;
+ struct stat st;
+ off_t l, bs;
+
+ /* Operates like unlinkat() but also deallocates the file contents if it is a regular file and there's no other
+ * link to it. This is useful to ensure that other processes that might have the file open for reading won't be
+ * able to keep the data pinned on disk forever. This call is particular useful whenever we execute clean-up
+ * jobs ("vacuuming"), where we want to make sure the data is really gone and the disk space released and
+ * returned to the free pool.
+ *
+ * Deallocation is preferably done by FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE (👊) if supported, which means
+ * the file won't change size. That's a good thing since we shouldn't needlessly trigger SIGBUS in other
+ * programs that have mmap()ed the file. (The assumption here is that changing file contents to all zeroes
+ * underneath those programs is the better choice than simply triggering SIGBUS in them which truncation does.)
+ * However if hole punching is not implemented in the kernel or file system we'll fall back to normal file
+ * truncation (🔪), as our goal of deallocating the data space trumps our goal of being nice to readers (💐).
+ *
+ * Note that we attempt deallocation, but failure to succeed with that is not considered fatal, as long as the
+ * primary job – to delete the file – is accomplished. */
+
+ if ((flags & AT_REMOVEDIR) == 0) {
+ truncate_fd = openat(fd, name, O_WRONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW|O_NONBLOCK);
+ if (truncate_fd < 0) {
+
+ /* If this failed because the file doesn't exist propagate the error right-away. Also,
+ * AT_REMOVEDIR wasn't set, and we tried to open the file for writing, which means EISDIR is
+ * returned when this is a directory but we are not supposed to delete those, hence propagate
+ * the error right-away too. */
+ if (IN_SET(errno, ENOENT, EISDIR))
+ return -errno;
+
+ if (errno != ELOOP) /* don't complain if this is a symlink */
+ log_debug_errno(errno, "Failed to open file '%s' for deallocation, ignoring: %m", name);
+ }
+ }
+
+ if (unlinkat(fd, name, flags) < 0)
+ return -errno;
+
+ if (truncate_fd < 0) /* Don't have a file handle, can't do more ☹️ */
+ return 0;
+
+ if (fstat(truncate_fd, &st) < 0) {
+ log_debug_errno(errno, "Failed to stat file '%s' for deallocation, ignoring.", name);
+ return 0;
+ }
+
+ if (!S_ISREG(st.st_mode) || st.st_blocks == 0 || st.st_nlink > 0)
+ return 0;
+
+ /* If this is a regular file, it actually took up space on disk and there are no other links it's time to
+ * punch-hole/truncate this to release the disk space. */
+
+ bs = MAX(st.st_blksize, 512);
+ l = DIV_ROUND_UP(st.st_size, bs) * bs; /* Round up to next block size */
+
+ if (fallocate(truncate_fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, 0, l) >= 0)
+ return 0; /* Successfully punched a hole! 😊 */
+
+ /* Fall back to truncation */
+ if (ftruncate(truncate_fd, 0) < 0) {
+ log_debug_errno(errno, "Failed to truncate file to 0, ignoring: %m");
+ return 0;
+ }
+
+ return 0;
+}
+
+int fsync_directory_of_file(int fd) {
+ _cleanup_free_ char *path = NULL, *dn = NULL;
+ _cleanup_close_ int dfd = -1;
+ int r;
+
+ r = fd_verify_regular(fd);
+ if (r < 0)
+ return r;
+
+ r = fd_get_path(fd, &path);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to query /proc/self/fd/%d%s: %m",
+ fd,
+ r == -EOPNOTSUPP ? ", ignoring" : "");
+
+ if (r == -EOPNOTSUPP)
+ /* If /proc is not available, we're most likely running in some
+ * chroot environment, and syncing the directory is not very
+ * important in that case. Let's just silently do nothing. */
+ return 0;
+
+ return r;
+ }
+
+ if (!path_is_absolute(path))
+ return -EINVAL;
+
+ dn = dirname_malloc(path);
+ if (!dn)
+ return -ENOMEM;
+
+ dfd = open(dn, O_RDONLY|O_CLOEXEC|O_DIRECTORY);
+ if (dfd < 0)
+ return -errno;
+
+ if (fsync(dfd) < 0)
+ return -errno;
+
+ return 0;
}
diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h
index 4c6bb659a..c7d831f50 100644
--- a/src/basic/fs-util.h
+++ b/src/basic/fs-util.h
@@ -1,24 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
+//#include <dirent.h>
#include <fcntl.h>
#include <limits.h>
#include <stdbool.h>
@@ -28,6 +11,7 @@
#include <unistd.h>
#include "time-util.h"
+#include "util.h"
int unlink_noerrno(const char *path);
@@ -44,13 +28,13 @@ int readlink_value(const char *p, char **ret);
#endif // 0
int readlink_and_make_absolute(const char *p, char **r);
#if 0 /// UNNEEDED by elogind
-int readlink_and_canonicalize(const char *p, const char *root, char **r);
-int readlink_and_make_absolute_root(const char *root, const char *path, char **ret);
#endif // 0
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
+int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid);
int fchmod_umask(int fd, mode_t mode);
+int fchmod_opath(int fd, mode_t m);
int fd_warn_permissions(const char *path, int fd);
@@ -58,8 +42,7 @@ int fd_warn_permissions(const char *path, int fd);
#define laccess(path, mode) faccessat(AT_FDCWD, (path), (mode), AT_SYMLINK_NOFOLLOW)
#else
#define laccess(path, mode) faccessat(AT_FDCWD, (path), (mode), 0)
-#endif
-
+#endif // __GLIBC__
int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode);
int touch(const char *path);
@@ -77,6 +60,9 @@ int get_files_in_directory(const char *path, char ***list);
int tmp_dir(const char **ret);
#if 0 /// UNNEEDED by elogind
int var_tmp_dir(const char **ret);
+#endif // 0
+
+int unlink_or_warn(const char *filename);
#define INOTIFY_EVENT_MAX (sizeof(struct inotify_event) + NAME_MAX + 1)
@@ -92,25 +78,46 @@ union inotify_event_buffer {
int inotify_add_watch_fd(int fd, int what, uint32_t mask);
-#endif // 0
enum {
- CHASE_PREFIX_ROOT = 1, /* If set, the specified path will be prefixed by the specified root before beginning the iteration */
- CHASE_NONEXISTENT = 2, /* If set, it's OK if the path doesn't actually exist. */
+ CHASE_PREFIX_ROOT = 1 << 0, /* If set, the specified path will be prefixed by the specified root before beginning the iteration */
+ CHASE_NONEXISTENT = 1 << 1, /* If set, it's OK if the path doesn't actually exist. */
+ CHASE_NO_AUTOFS = 1 << 2, /* If set, return -EREMOTE if autofs mount point found */
+ CHASE_SAFE = 1 << 3, /* If set, return EPERM if we ever traverse from unprivileged to privileged files or directories */
+ CHASE_OPEN = 1 << 4, /* If set, return an O_PATH object to the final component */
+ CHASE_TRAIL_SLASH = 1 << 5, /* If set, any trailing slash will be preserved */
+ CHASE_STEP = 1 << 6, /* If set, just execute a single step of the normalization */
};
+/* How many iterations to execute before returning -ELOOP */
+#define CHASE_SYMLINKS_MAX 32
+
int chase_symlinks(const char *path_with_prefix, const char *root, unsigned flags, char **ret);
#if 0 /// UNNEEDED by elogind
+int chase_symlinks_and_open(const char *path, const char *root, unsigned chase_flags, int open_flags, char **ret_path);
+int chase_symlinks_and_opendir(const char *path, const char *root, unsigned chase_flags, char **ret_path, DIR **ret_dir);
+int chase_symlinks_and_stat(const char *path, const char *root, unsigned chase_flags, char **ret_path, struct stat *ret_stat);
+#endif // 0
+
/* Useful for usage with _cleanup_(), removes a directory and frees the pointer */
static inline void rmdir_and_free(char *p) {
+ PROTECT_ERRNO;
(void) rmdir(p);
free(p);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(char*, rmdir_and_free);
+#if 0 /// UNNEEDED by elogind
static inline void unlink_and_free(char *p) {
- (void) unlink(p);
+ (void) unlink_noerrno(p);
free(p);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(char*, unlink_and_free);
#endif // 0
+
+int access_fd(int fd, int mode);
+
+void unlink_tempfilep(char (*p)[]);
+int unlinkat_deallocate(int fd, const char *name, int flags);
+
+int fsync_directory_of_file(int fd);
diff --git a/src/basic/generate-cap-list.sh b/src/basic/generate-cap-list.sh
new file mode 100755
index 000000000..c39f1b698
--- /dev/null
+++ b/src/basic/generate-cap-list.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+set -eu
+
+#if 0 /// elogind needs musl_missing.sh, which is in shared.
+# $1 -dM -include linux/capability.h -include "$2" -include "$3" - </dev/null | \
+# awk '/^#define[ \t]+CAP_[A-Z_]+[ \t]+/ { print $2; }' | \
+# grep -v CAP_LAST_CAP
+#else
+$1 -dM -include linux/capability.h -I"$2"/src/shared -include "$3" -include "$4" - </dev/null | \
+ awk '/^#define[ \t]+CAP_[A-Z_]+[ \t]+/ { print $2; }' | \
+ grep -v CAP_LAST_CAP
+#endif // 0
diff --git a/src/basic/generate-errno-list.sh b/src/basic/generate-errno-list.sh
new file mode 100755
index 000000000..953d5e37b
--- /dev/null
+++ b/src/basic/generate-errno-list.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+set -eu
+
+$1 -dM -include errno.h - </dev/null | \
+ awk '/^#define[ \t]+E[^ _]+[ \t]+/ { print $2; }'
diff --git a/src/basic/generate-gperfs.py b/src/basic/generate-gperfs.py
new file mode 100755
index 000000000..aca9ab1fe
--- /dev/null
+++ b/src/basic/generate-gperfs.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python3
+
+"""Generate %-from-name.gperf from %-list.txt
+"""
+
+import sys
+
+name, prefix, input = sys.argv[1:]
+
+print("""\
+%{
+#if __GNUC__ >= 7
+_Pragma("GCC diagnostic ignored \\"-Wimplicit-fallthrough\\"")
+#endif
+%}""")
+print("""\
+struct {}_name {{ const char* name; int id; }};
+%null-strings
+%%""".format(name))
+
+for line in open(input):
+ print("{0}, {1}{0}".format(line.rstrip(), prefix))
diff --git a/src/basic/generate-socket-protocol-list.sh b/src/basic/generate-socket-protocol-list.sh
new file mode 100644
index 000000000..a9b1e0fb5
--- /dev/null
+++ b/src/basic/generate-socket-protocol-list.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+set -eu
+
+$1 -dM -include netinet/in.h - </dev/null | \
+ awk '/^#define[ \t]+IPPROTO_[^ \t]+[ \t]+[^ \t]/ { print $2; }' | \
+ sed -e 's/IPPROTO_//'
diff --git a/src/basic/gunicode.c b/src/basic/gunicode.c
index e6ac0545a..c51b1a7a1 100644
--- a/src/basic/gunicode.c
+++ b/src/basic/gunicode.c
@@ -1,11 +1,9 @@
/* gunicode.c - Unicode manipulation functions
*
* Copyright (C) 1999, 2000 Tom Tromey
- * Copyright 2000, 2005 Red Hat, Inc.
+ * Copyright © 2000, 2005 Red Hat, Inc.
*/
-#include <stdlib.h>
-
#include "gunicode.h"
#define unichar uint32_t
diff --git a/src/basic/gunicode.h b/src/basic/gunicode.h
index 5975bc8fc..a16b7b6ff 100644
--- a/src/basic/gunicode.h
+++ b/src/basic/gunicode.h
@@ -3,7 +3,7 @@
/* gunicode.h - Unicode manipulation functions
*
* Copyright (C) 1999, 2000 Tom Tromey
- * Copyright 2000, 2005 Red Hat, Inc.
+ * Copyright © 2000, 2005 Red Hat, Inc.
*/
#include <stdbool.h>
diff --git a/src/basic/hash-funcs.c b/src/basic/hash-funcs.c
index c3a4a011b..db48437be 100644
--- a/src/basic/hash-funcs.c
+++ b/src/basic/hash-funcs.c
@@ -1,24 +1,9 @@
-/***
- This file is part of systemd.
+/* SPDX-License-Identifier: LGPL-2.1+ */
- Copyright 2010 Lennart Poettering
- Copyright 2014 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 <string.h>
#include "hash-funcs.h"
+#include "path-util.h"
void string_hash_func(const void *p, struct siphash *state) {
siphash24_compress(p, strlen(p) + 1, state);
@@ -33,6 +18,54 @@ const struct hash_ops string_hash_ops = {
.compare = string_compare_func
};
+void path_hash_func(const void *p, struct siphash *state) {
+ const char *q = p;
+ size_t n;
+
+ assert(q);
+ assert(state);
+
+ /* Calculates a hash for a path in a way this duplicate inner slashes don't make a differences, and also
+ * whether there's a trailing slash or not. This fits well with the semantics of path_compare(), which does
+ * similar checks and also doesn't care for trailing slashes. Note that relative and absolute paths (i.e. those
+ * which begin in a slash or not) will hash differently though. */
+
+ n = strspn(q, "/");
+ if (n > 0) { /* Eat up initial slashes, and add one "/" to the hash for all of them */
+ siphash24_compress(q, 1, state);
+ q += n;
+ }
+
+ for (;;) {
+ /* Determine length of next component */
+ n = strcspn(q, "/");
+ if (n == 0) /* Reached the end? */
+ break;
+
+ /* Add this component to the hash and skip over it */
+ siphash24_compress(q, n, state);
+ q += n;
+
+ /* How many slashes follow this component? */
+ n = strspn(q, "/");
+ if (q[n] == 0) /* Is this a trailing slash? If so, we are at the end, and don't care about the slashes anymore */
+ break;
+
+ /* We are not add the end yet. Hash exactly one slash for all of the ones we just encountered. */
+ siphash24_compress(q, 1, state);
+ q += n;
+ }
+}
+
+int path_compare_func(const void *a, const void *b) {
+ return path_compare(a, b);
+}
+
+const struct hash_ops path_hash_ops = {
+ .hash = path_hash_func,
+ .compare = path_compare_func
+};
+
void trivial_hash_func(const void *p, struct siphash *state) {
siphash24_compress(&p, sizeof(p), state);
}
diff --git a/src/basic/hash-funcs.h b/src/basic/hash-funcs.h
index 299189d14..5e5989f02 100644
--- a/src/basic/hash-funcs.h
+++ b/src/basic/hash-funcs.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2014 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 "macro.h"
#include "siphash24.h"
@@ -35,29 +17,28 @@ void string_hash_func(const void *p, struct siphash *state);
int string_compare_func(const void *a, const void *b) _pure_;
extern const struct hash_ops string_hash_ops;
-/* This will compare the passed pointers directly, and will not
- * dereference them. This is hence not useful for strings or
- * suchlike. */
+void path_hash_func(const void *p, struct siphash *state);
+int path_compare_func(const void *a, const void *b) _pure_;
+extern const struct hash_ops path_hash_ops;
+
+/* This will compare the passed pointers directly, and will not dereference them. This is hence not useful for strings
+ * or suchlike. */
void trivial_hash_func(const void *p, struct siphash *state);
int trivial_compare_func(const void *a, const void *b) _const_;
extern const struct hash_ops trivial_hash_ops;
-/* 32bit values we can always just embed in the pointer itself, but
- * in order to support 32bit archs we need store 64bit values
- * indirectly, since they don't fit in a pointer. */
+/* 32bit values we can always just embed in the pointer itself, but in order to support 32bit archs we need store 64bit
+ * values indirectly, since they don't fit in a pointer. */
void uint64_hash_func(const void *p, struct siphash *state);
int uint64_compare_func(const void *a, const void *b) _pure_;
extern const struct hash_ops uint64_hash_ops;
-/* On some archs dev_t is 32bit, and on others 64bit. And sometimes
- * it's 64bit on 32bit archs, and sometimes 32bit on 64bit archs. Yuck! */
+/* On some archs dev_t is 32bit, and on others 64bit. And sometimes it's 64bit on 32bit archs, and sometimes 32bit on
+ * 64bit archs. Yuck! */
#if SIZEOF_DEV_T != 8
void devt_hash_func(const void *p, struct siphash *state) _pure_;
int devt_compare_func(const void *a, const void *b) _pure_;
-extern const struct hash_ops devt_hash_ops = {
- .hash = devt_hash_func,
- .compare = devt_compare_func
-};
+extern const struct hash_ops devt_hash_ops;
#else
#define devt_hash_func uint64_hash_func
#define devt_compare_func uint64_compare_func
diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c
index 86d648df0..15c8c8816 100644
--- a/src/basic/hashmap.c
+++ b/src/basic/hashmap.c
@@ -1,22 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2014 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <stdint.h>
@@ -25,16 +7,18 @@
#include "alloc-util.h"
#include "hashmap.h"
+#include "fileio.h"
#include "macro.h"
#include "mempool.h"
#include "process-util.h"
#include "random-util.h"
#include "set.h"
#include "siphash24.h"
+#include "string-util.h"
#include "strv.h"
#include "util.h"
-#ifdef ENABLE_DEBUG_HASHMAP
+#if ENABLE_DEBUG_HASHMAP
#include <pthread.h>
#include "list.h"
#endif
@@ -142,7 +126,7 @@ typedef uint8_t dib_raw_t;
#define DIB_FREE UINT_MAX
-#ifdef ENABLE_DEBUG_HASHMAP
+#if ENABLE_DEBUG_HASHMAP
struct hashmap_debug_info {
LIST_FIELDS(struct hashmap_debug_info, debug_list);
unsigned max_entries; /* high watermark of n_entries */
@@ -226,6 +210,8 @@ struct HashmapBase {
unsigned n_direct_entries:3; /* Number of entries in direct storage.
* Only valid if !has_indirect. */
bool from_pool:1; /* whether was allocated from mempool */
+ bool dirty:1; /* whether dirtied since last iterated_cache_get() */
+ bool cached:1; /* whether this hashmap is being cached */
HASHMAP_DEBUG_FIELDS /* optional hashmap_debug_info */
};
@@ -245,6 +231,17 @@ struct Set {
struct HashmapBase b;
};
+typedef struct CacheMem {
+ const void **ptr;
+ size_t n_populated, n_allocated;
+ bool active:1;
+} CacheMem;
+
+struct IteratedCache {
+ HashmapBase *hashmap;
+ CacheMem keys, values;
+};
+
DEFINE_MEMPOOL(hashmap_pool, Hashmap, 8);
DEFINE_MEMPOOL(ordered_hashmap_pool, OrderedHashmap, 8);
/* No need for a separate Set pool */
@@ -278,6 +275,28 @@ static const struct hashmap_type_info hashmap_type_info[_HASHMAP_TYPE_MAX] = {
},
};
+#if VALGRIND
+__attribute__((destructor)) static void cleanup_pools(void) {
+ _cleanup_free_ char *t = NULL;
+ int r;
+
+ /* Be nice to valgrind */
+
+ /* The pool is only allocated by the main thread, but the memory can
+ * be passed to other threads. Let's clean up if we are the main thread
+ * and no other threads are live. */
+ if (!is_main_thread())
+ return;
+
+ r = get_proc_field("/proc/self/status", "Threads", WHITESPACE, &t);
+ if (r < 0 || !streq(t, "1"))
+ return;
+
+ mempool_drop(&hashmap_pool);
+ mempool_drop(&ordered_hashmap_pool);
+}
+#endif
+
static unsigned n_buckets(HashmapBase *h) {
return h->has_indirect ? h->indirect.n_buckets
: hashmap_type_info[h->type].n_direct_buckets;
@@ -326,6 +345,11 @@ static unsigned base_bucket_hash(HashmapBase *h, const void *p) {
}
#define bucket_hash(h, p) base_bucket_hash(HASHMAP_BASE(h), p)
+static inline void base_set_dirty(HashmapBase *h) {
+ h->dirty = true;
+}
+#define hashmap_set_dirty(h) base_set_dirty(HASHMAP_BASE(h))
+
static void get_hash_key(uint8_t hash_key[HASH_KEY_SIZE], bool reuse_is_ok) {
static uint8_t current[HASH_KEY_SIZE];
static bool current_initialized = false;
@@ -499,7 +523,7 @@ static void base_remove_entry(HashmapBase *h, unsigned idx) {
dibs = dib_raw_ptr(h);
assert(dibs[idx] != DIB_RAW_FREE);
-#ifdef ENABLE_DEBUG_HASHMAP
+#if ENABLE_DEBUG_HASHMAP
h->debug.rem_count++;
h->debug.last_rem_idx = idx;
#endif
@@ -508,7 +532,7 @@ static void base_remove_entry(HashmapBase *h, unsigned idx) {
/* Find the stop bucket ("right"). It is either free or has DIB == 0. */
for (right = next_idx(h, left); ; right = next_idx(h, right)) {
raw_dib = dibs[right];
- if (raw_dib == 0 || raw_dib == DIB_RAW_FREE)
+ if (IN_SET(raw_dib, 0, DIB_RAW_FREE))
break;
/* The buckets are not supposed to be all occupied and with DIB > 0.
@@ -543,6 +567,7 @@ static void base_remove_entry(HashmapBase *h, unsigned idx) {
bucket_mark_free(h, prev);
n_entries_dec(h);
+ base_set_dirty(h);
}
#define remove_entry(h, idx) base_remove_entry(HASHMAP_BASE(h), idx)
@@ -578,7 +603,7 @@ static unsigned hashmap_iterate_in_insertion_order(OrderedHashmap *h, Iterator *
assert(e->p.b.key == i->next_key);
}
-#ifdef ENABLE_DEBUG_HASHMAP
+#if ENABLE_DEBUG_HASHMAP
i->prev_idx = idx;
#endif
@@ -635,7 +660,7 @@ static unsigned hashmap_iterate_in_internal_order(HashmapBase *h, Iterator *i) {
}
idx = i->idx;
-#ifdef ENABLE_DEBUG_HASHMAP
+#if ENABLE_DEBUG_HASHMAP
i->prev_idx = idx;
#endif
@@ -658,7 +683,7 @@ static unsigned hashmap_iterate_entry(HashmapBase *h, Iterator *i) {
return IDX_NIL;
}
-#ifdef ENABLE_DEBUG_HASHMAP
+#if ENABLE_DEBUG_HASHMAP
if (i->idx == IDX_FIRST) {
i->put_count = h->debug.put_count;
i->rem_count = h->debug.rem_count;
@@ -712,6 +737,25 @@ bool set_iterate(Set *s, Iterator *i, void **value) {
(idx != IDX_NIL); \
(idx) = hashmap_iterate_entry((h), &(i)))
+IteratedCache *internal_hashmap_iterated_cache_new(HashmapBase *h) {
+ IteratedCache *cache;
+
+ assert(h);
+ assert(!h->cached);
+
+ if (h->cached)
+ return NULL;
+
+ cache = new0(IteratedCache, 1);
+ if (!cache)
+ return NULL;
+
+ cache->hashmap = h;
+ h->cached = true;
+
+ return cache;
+}
+
static void reset_direct_storage(HashmapBase *h) {
const struct hashmap_type_info *hi = &hashmap_type_info[h->type];
void *p;
@@ -750,7 +794,7 @@ static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enu
shared_hash_key_initialized= true;
}
-#ifdef ENABLE_DEBUG_HASHMAP
+#if ENABLE_DEBUG_HASHMAP
h->debug.func = func;
h->debug.file = file;
h->debug.line = line;
@@ -807,7 +851,7 @@ static void hashmap_free_no_clear(HashmapBase *h) {
assert(!h->has_indirect);
assert(!h->n_direct_entries);
-#ifdef ENABLE_DEBUG_HASHMAP
+#if ENABLE_DEBUG_HASHMAP
assert_se(pthread_mutex_lock(&hashmap_debug_list_mutex) == 0);
LIST_REMOVE(debug_list, hashmap_debug_list, &h->debug);
assert_se(pthread_mutex_unlock(&hashmap_debug_list_mutex) == 0);
@@ -872,6 +916,8 @@ void internal_hashmap_clear(HashmapBase *h) {
OrderedHashmap *lh = (OrderedHashmap*) h;
lh->iterate_list_head = lh->iterate_list_tail = IDX_NIL;
}
+
+ base_set_dirty(h);
}
void internal_hashmap_clear_free(HashmapBase *h) {
@@ -919,7 +965,7 @@ static bool hashmap_put_robin_hood(HashmapBase *h, unsigned idx,
dib_raw_t raw_dib, *dibs;
unsigned dib, distance;
-#ifdef ENABLE_DEBUG_HASHMAP
+#if ENABLE_DEBUG_HASHMAP
h->debug.put_count++;
#endif
@@ -927,7 +973,7 @@ static bool hashmap_put_robin_hood(HashmapBase *h, unsigned idx,
for (distance = 0; ; distance++) {
raw_dib = dibs[idx];
- if (raw_dib == DIB_RAW_FREE || raw_dib == DIB_RAW_REHASH) {
+ if (IN_SET(raw_dib, DIB_RAW_FREE, DIB_RAW_REHASH)) {
if (raw_dib == DIB_RAW_REHASH)
bucket_move_entry(h, swap, idx, IDX_TMP);
@@ -1012,10 +1058,12 @@ static int hashmap_base_put_boldly(HashmapBase *h, unsigned idx,
assert_se(hashmap_put_robin_hood(h, idx, swap) == false);
n_entries_inc(h);
-#ifdef ENABLE_DEBUG_HASHMAP
+#if ENABLE_DEBUG_HASHMAP
h->debug.max_entries = MAX(h->debug.max_entries, n_entries(h));
#endif
+ base_set_dirty(h);
+
return 1;
}
#define hashmap_put_boldly(h, idx, swap, may_resize) \
@@ -1240,7 +1288,7 @@ int hashmap_replace(Hashmap *h, const void *key, void *value) {
idx = bucket_scan(h, hash, key);
if (idx != IDX_NIL) {
e = plain_bucket_at(h, idx);
-#ifdef ENABLE_DEBUG_HASHMAP
+#if ENABLE_DEBUG_HASHMAP
/* Although the key is equal, the key pointer may have changed,
* and this would break our assumption for iterating. So count
* this operation as incompatible with iteration. */
@@ -1252,6 +1300,8 @@ int hashmap_replace(Hashmap *h, const void *key, void *value) {
#endif
e->b.key = key;
e->value = value;
+ hashmap_set_dirty(h);
+
return 0;
}
@@ -1274,6 +1324,8 @@ int hashmap_update(Hashmap *h, const void *key, void *value) {
e = plain_bucket_at(h, idx);
e->value = value;
+ hashmap_set_dirty(h);
+
return 0;
}
@@ -1830,3 +1882,95 @@ int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags
}
}
#endif // 0
+
+/* expand the cachemem if needed, return true if newly (re)activated. */
+static int cachemem_maintain(CacheMem *mem, unsigned size) {
+ assert(mem);
+
+ if (!GREEDY_REALLOC(mem->ptr, mem->n_allocated, size)) {
+ if (size > 0)
+ return -ENOMEM;
+ }
+
+ if (!mem->active) {
+ mem->active = true;
+ return true;
+ }
+
+ return false;
+}
+
+int iterated_cache_get(IteratedCache *cache, const void ***res_keys, const void ***res_values, unsigned *res_n_entries) {
+ bool sync_keys = false, sync_values = false;
+ unsigned size;
+ int r;
+
+ assert(cache);
+ assert(cache->hashmap);
+
+ size = n_entries(cache->hashmap);
+
+ if (res_keys) {
+ r = cachemem_maintain(&cache->keys, size);
+ if (r < 0)
+ return r;
+
+ sync_keys = r;
+ } else
+ cache->keys.active = false;
+
+ if (res_values) {
+ r = cachemem_maintain(&cache->values, size);
+ if (r < 0)
+ return r;
+
+ sync_values = r;
+ } else
+ cache->values.active = false;
+
+ if (cache->hashmap->dirty) {
+ if (cache->keys.active)
+ sync_keys = true;
+ if (cache->values.active)
+ sync_values = true;
+
+ cache->hashmap->dirty = false;
+ }
+
+ if (sync_keys || sync_values) {
+ unsigned i, idx;
+ Iterator iter;
+
+ i = 0;
+ HASHMAP_FOREACH_IDX(idx, cache->hashmap, iter) {
+ struct hashmap_base_entry *e;
+
+ e = bucket_at(cache->hashmap, idx);
+
+ if (sync_keys)
+ cache->keys.ptr[i] = e->key;
+ if (sync_values)
+ cache->values.ptr[i] = entry_value(cache->hashmap, e);
+ i++;
+ }
+ }
+
+ if (res_keys)
+ *res_keys = cache->keys.ptr;
+ if (res_values)
+ *res_values = cache->values.ptr;
+ if (res_n_entries)
+ *res_n_entries = size;
+
+ return 0;
+}
+
+IteratedCache *iterated_cache_free(IteratedCache *cache) {
+ if (cache) {
+ free(cache->keys.ptr);
+ free(cache->values.ptr);
+ free(cache);
+ }
+
+ return NULL;
+}
diff --git a/src/basic/hashmap.h b/src/basic/hashmap.h
index 6d1ae48b2..5c70c102d 100644
--- a/src/basic/hashmap.h
+++ b/src/basic/hashmap.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2014 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 <limits.h>
#include <stdbool.h>
@@ -52,13 +34,15 @@ typedef struct Hashmap Hashmap; /* Maps keys to values */
typedef struct OrderedHashmap OrderedHashmap; /* Like Hashmap, but also remembers entry insertion order */
typedef struct Set Set; /* Stores just keys */
+typedef struct IteratedCache IteratedCache; /* Caches the iterated order of one of the above */
+
/* Ideally the Iterator would be an opaque struct, but it is instantiated
* by hashmap users, so the definition has to be here. Do not use its fields
* directly. */
typedef struct {
unsigned idx; /* index of an entry to be iterated next */
const void *next_key; /* expected value of that entry's key pointer */
-#ifdef ENABLE_DEBUG_HASHMAP
+#if ENABLE_DEBUG_HASHMAP
unsigned put_count; /* hashmap's put_count recorded at start of iteration */
unsigned rem_count; /* hashmap's rem_count in previous iteration */
unsigned prev_idx; /* idx in previous iteration */
@@ -89,7 +73,7 @@ typedef struct {
(Hashmap*)(h), \
(void)0)
-#ifdef ENABLE_DEBUG_HASHMAP
+#if ENABLE_DEBUG_HASHMAP
# define HASHMAP_DEBUG_PARAMS , const char *func, const char *file, int line
# define HASHMAP_DEBUG_SRC_ARGS , __func__, __FILE__, __LINE__
# define HASHMAP_DEBUG_PASS_ARGS , func, file, line
@@ -125,6 +109,9 @@ static inline OrderedHashmap *ordered_hashmap_free_free_free(OrderedHashmap *h)
return (void*)hashmap_free_free_free(PLAIN_HASHMAP(h));
}
+IteratedCache *iterated_cache_free(IteratedCache *cache);
+int iterated_cache_get(IteratedCache *cache, const void ***res_keys, const void ***res_values, unsigned *res_n_entries);
+
HashmapBase *internal_hashmap_copy(HashmapBase *h);
static inline Hashmap *hashmap_copy(Hashmap *h) {
return (Hashmap*) internal_hashmap_copy(HASHMAP_BASE(h));
@@ -138,6 +125,14 @@ int internal_ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct h
#define hashmap_ensure_allocated(h, ops) internal_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
#define ordered_hashmap_ensure_allocated(h, ops) internal_ordered_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
+IteratedCache *internal_hashmap_iterated_cache_new(HashmapBase *h);
+static inline IteratedCache *hashmap_iterated_cache_new(Hashmap *h) {
+ return (IteratedCache*) internal_hashmap_iterated_cache_new(HASHMAP_BASE(h));
+}
+static inline IteratedCache *ordered_hashmap_iterated_cache_new(OrderedHashmap *h) {
+ return (IteratedCache*) internal_hashmap_iterated_cache_new(HASHMAP_BASE(h));
+}
+
int hashmap_put(Hashmap *h, const void *key, void *value);
static inline int ordered_hashmap_put(OrderedHashmap *h, const void *key, void *value) {
return hashmap_put(PLAIN_HASHMAP(h), key, value);
@@ -328,6 +323,29 @@ static inline void *ordered_hashmap_first(OrderedHashmap *h) {
return internal_hashmap_first(HASHMAP_BASE(h));
}
+#define hashmap_clear_with_destructor(_s, _f) \
+ ({ \
+ void *_item; \
+ while ((_item = hashmap_steal_first(_s))) \
+ _f(_item); \
+ })
+#define hashmap_free_with_destructor(_s, _f) \
+ ({ \
+ hashmap_clear_with_destructor(_s, _f); \
+ hashmap_free(_s); \
+ })
+#define ordered_hashmap_clear_with_destructor(_s, _f) \
+ ({ \
+ void *_item; \
+ while ((_item = ordered_hashmap_steal_first(_s))) \
+ _f(_item); \
+ })
+#define ordered_hashmap_free_with_destructor(_s, _f) \
+ ({ \
+ ordered_hashmap_clear_with_destructor(_s, _f); \
+ ordered_hashmap_free(_s); \
+ })
+
/* no hashmap_next */
void *ordered_hashmap_next(OrderedHashmap *h, const void *key);
@@ -370,3 +388,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free_free_free);
#define _cleanup_ordered_hashmap_free_ _cleanup_(ordered_hashmap_freep)
#define _cleanup_ordered_hashmap_free_free_ _cleanup_(ordered_hashmap_free_freep)
#define _cleanup_ordered_hashmap_free_free_free_ _cleanup_(ordered_hashmap_free_free_freep)
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(IteratedCache*, iterated_cache_free);
+
+#define _cleanup_iterated_cache_free_ _cleanup_(iterated_cache_freep)
diff --git a/src/basic/hexdecoct.c b/src/basic/hexdecoct.c
index 2d6e377f0..7748e8352 100644
--- a/src/basic/hexdecoct.c
+++ b/src/basic/hexdecoct.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <ctype.h>
#include <errno.h>
@@ -25,6 +8,7 @@
#include "alloc-util.h"
#include "hexdecoct.h"
#include "macro.h"
+#include "string-util.h"
#include "util.h"
char octchar(int x) {
@@ -88,30 +72,69 @@ char *hexmem(const void *p, size_t l) {
return r;
}
-int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
- _cleanup_free_ uint8_t *r = NULL;
- uint8_t *z;
- const char *x;
+static int unhex_next(const char **p, size_t *l) {
+ int r;
- assert(mem);
- assert(len);
assert(p);
+ assert(l);
- if (l % 2 != 0)
- return -EINVAL;
+ /* Find the next non-whitespace character, and decode it. We
+ * greedily skip all preceeding and all following whitespace. */
- z = r = malloc((l + 1) / 2 + 1);
- if (!r)
+ for (;;) {
+ if (*l == 0)
+ return -EPIPE;
+
+ if (!strchr(WHITESPACE, **p))
+ break;
+
+ /* Skip leading whitespace */
+ (*p)++, (*l)--;
+ }
+
+ r = unhexchar(**p);
+ if (r < 0)
+ return r;
+
+ for (;;) {
+ (*p)++, (*l)--;
+
+ if (*l == 0 || !strchr(WHITESPACE, **p))
+ break;
+
+ /* Skip following whitespace */
+ }
+
+ return r;
+}
+
+int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) {
+ _cleanup_free_ uint8_t *buf = NULL;
+ const char *x;
+ uint8_t *z;
+
+ assert(ret);
+ assert(ret_len);
+ assert(p || l == 0);
+
+ if (l == (size_t) -1)
+ l = strlen(p);
+
+ /* Note that the calculation of memory size is an upper boundary, as we ignore whitespace while decoding */
+ buf = malloc((l + 1) / 2 + 1);
+ if (!buf)
return -ENOMEM;
- for (x = p; x < p + l; x += 2) {
+ for (x = p, z = buf;;) {
int a, b;
- a = unhexchar(x[0]);
+ a = unhex_next(&x, &l);
+ if (a == -EPIPE) /* End of string */
+ break;
if (a < 0)
return a;
- b = unhexchar(x[1]);
+ b = unhex_next(&x, &l);
if (b < 0)
return b;
@@ -120,9 +143,8 @@ int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
*z = 0;
- *mem = r;
- r = NULL;
- *len = (l + 1) / 2;
+ *ret_len = (size_t) (z - buf);
+ *ret = TAKE_PTR(buf);
return 0;
}
@@ -159,6 +181,8 @@ char *base32hexmem(const void *p, size_t l, bool padding) {
const uint8_t *x;
size_t len;
+ assert(p || l == 0);
+
if (padding)
/* five input bytes makes eight output bytes, padding is added so we must round up */
len = 8 * (l + 4) / 5;
@@ -188,7 +212,7 @@ char *base32hexmem(const void *p, size_t l, bool padding) {
for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) {
/* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ
- x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
+ * x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
*(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
*(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
*(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
@@ -268,7 +292,12 @@ int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_l
size_t len;
unsigned pad = 0;
- assert(p);
+ assert(p || l == 0);
+ assert(mem);
+ assert(_len);
+
+ if (l == (size_t) -1)
+ l = strlen(p);
/* padding ensures any base32hex input has input divisible by 8 */
if (padding && l % 8 != 0)
@@ -283,7 +312,7 @@ int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_l
}
/* a group of eight input bytes needs five output bytes, in case of
- padding we need to add some extra bytes */
+ * padding we need to add some extra bytes */
len = (l / 8) * 5;
switch (l % 8) {
@@ -311,7 +340,7 @@ int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_l
for (x = p; x < p + (l / 8) * 8; x += 8) {
/* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW
- e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
+ * e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
a = unbase32hexchar(x[0]);
if (a < 0)
return -EINVAL;
@@ -470,8 +499,7 @@ int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_l
*z = 0;
- *mem = r;
- r = NULL;
+ *mem = TAKE_PTR(r);
*_len = len;
return 0;
@@ -518,6 +546,9 @@ ssize_t base64mem(const void *p, size_t l, char **out) {
char *r, *z;
const uint8_t *x;
+ assert(p || l == 0);
+ assert(out);
+
/* three input bytes makes four output bytes, padding is added so we must round up */
z = r = malloc(4 * (l + 2) / 3 + 1);
if (!r)
@@ -553,10 +584,11 @@ ssize_t base64mem(const void *p, size_t l, char **out) {
return z - r;
}
-static int base64_append_width(char **prefix, int plen,
- const char *sep, int indent,
- const void *p, size_t l,
- int width) {
+static int base64_append_width(
+ char **prefix, int plen,
+ const char *sep, int indent,
+ const void *p, size_t l,
+ int width) {
_cleanup_free_ char *x = NULL;
char *t, *s;
@@ -567,9 +599,9 @@ static int base64_append_width(char **prefix, int plen,
if (len <= 0)
return len;
- lines = (len + width - 1) / width;
+ lines = DIV_ROUND_UP(len, width);
- slen = sep ? strlen(sep) : 0;
+ slen = strlen_ptr(sep);
t = realloc(*prefix, plen + 1 + slen + (indent + width + 1) * lines);
if (!t)
return -ENOMEM;
@@ -595,118 +627,145 @@ static int base64_append_width(char **prefix, int plen,
return 0;
}
-int base64_append(char **prefix, int plen,
- const void *p, size_t l,
- int indent, int width) {
+int base64_append(
+ char **prefix, int plen,
+ const void *p, size_t l,
+ int indent, int width) {
+
if (plen > width / 2 || plen + indent > width)
/* leave indent on the left, keep last column free */
return base64_append_width(prefix, plen, "\n", indent, p, l, width - indent - 1);
else
/* leave plen on the left, keep last column free */
return base64_append_width(prefix, plen, NULL, plen, p, l, width - plen - 1);
-};
+}
-
-int unbase64mem(const char *p, size_t l, void **mem, size_t *_len) {
- _cleanup_free_ uint8_t *r = NULL;
- int a, b, c, d;
- uint8_t *z;
- const char *x;
- size_t len;
+static int unbase64_next(const char **p, size_t *l) {
+ int ret;
assert(p);
+ assert(l);
- /* padding ensures any base63 input has input divisible by 4 */
- if (l % 4 != 0)
- return -EINVAL;
-
- /* strip the padding */
- if (l > 0 && p[l - 1] == '=')
- l--;
- if (l > 0 && p[l - 1] == '=')
- l--;
+ /* Find the next non-whitespace character, and decode it. If we find padding, we return it as INT_MAX. We
+ * greedily skip all preceeding and all following whitespace. */
- /* a group of four input bytes needs three output bytes, in case of
- padding we need to add two or three extra bytes */
- len = (l / 4) * 3 + (l % 4 ? (l % 4) - 1 : 0);
+ for (;;) {
+ if (*l == 0)
+ return -EPIPE;
- z = r = malloc(len + 1);
- if (!r)
- return -ENOMEM;
+ if (!strchr(WHITESPACE, **p))
+ break;
- for (x = p; x < p + (l / 4) * 4; x += 4) {
- /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */
- a = unbase64char(x[0]);
- if (a < 0)
- return -EINVAL;
+ /* Skip leading whitespace */
+ (*p)++, (*l)--;
+ }
- b = unbase64char(x[1]);
- if (b < 0)
- return -EINVAL;
+ if (**p == '=')
+ ret = INT_MAX; /* return padding as INT_MAX */
+ else {
+ ret = unbase64char(**p);
+ if (ret < 0)
+ return ret;
+ }
- c = unbase64char(x[2]);
- if (c < 0)
- return -EINVAL;
+ for (;;) {
+ (*p)++, (*l)--;
- d = unbase64char(x[3]);
- if (d < 0)
- return -EINVAL;
+ if (*l == 0)
+ break;
+ if (!strchr(WHITESPACE, **p))
+ break;
- *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
- *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
- *(z++) = (uint8_t) c << 6 | (uint8_t) d; /* ZZWWWWWW */
+ /* Skip following whitespace */
}
- switch (l % 4) {
- case 3:
- a = unbase64char(x[0]);
+ return ret;
+}
+
+int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) {
+ _cleanup_free_ uint8_t *buf = NULL;
+ const char *x;
+ uint8_t *z;
+ size_t len;
+
+ assert(p || l == 0);
+ assert(ret);
+ assert(ret_size);
+
+ if (l == (size_t) -1)
+ l = strlen(p);
+
+ /* A group of four input bytes needs three output bytes, in case of padding we need to add two or three extra
+ * bytes. Note that this calculation is an upper boundary, as we ignore whitespace while decoding */
+ len = (l / 4) * 3 + (l % 4 != 0 ? (l % 4) - 1 : 0);
+
+ buf = malloc(len + 1);
+ if (!buf)
+ return -ENOMEM;
+
+ for (x = p, z = buf;;) {
+ int a, b, c, d; /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */
+
+ a = unbase64_next(&x, &l);
+ if (a == -EPIPE) /* End of string */
+ break;
if (a < 0)
+ return a;
+ if (a == INT_MAX) /* Padding is not allowed at the beginning of a 4ch block */
return -EINVAL;
- b = unbase64char(x[1]);
+ b = unbase64_next(&x, &l);
if (b < 0)
+ return b;
+ if (b == INT_MAX) /* Padding is not allowed at the second character of a 4ch block either */
return -EINVAL;
- c = unbase64char(x[2]);
+ c = unbase64_next(&x, &l);
if (c < 0)
- return -EINVAL;
+ return c;
- /* c == 00ZZZZ00 */
- if (c & 3)
- return -EINVAL;
+ d = unbase64_next(&x, &l);
+ if (d < 0)
+ return d;
- *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
- *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
+ if (c == INT_MAX) { /* Padding at the third character */
- break;
- case 2:
- a = unbase64char(x[0]);
- if (a < 0)
- return -EINVAL;
+ if (d != INT_MAX) /* If the third character is padding, the fourth must be too */
+ return -EINVAL;
- b = unbase64char(x[1]);
- if (b < 0)
- return -EINVAL;
+ /* b == 00YY0000 */
+ if (b & 15)
+ return -EINVAL;
- /* b == 00YY0000 */
- if (b & 15)
- return -EINVAL;
+ if (l > 0) /* Trailing rubbish? */
+ return -ENAMETOOLONG;
- *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */
+ *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */
+ break;
+ }
- break;
- case 0:
+ if (d == INT_MAX) {
+ /* c == 00ZZZZ00 */
+ if (c & 3)
+ return -EINVAL;
- break;
- default:
- return -EINVAL;
+ if (l > 0) /* Trailing rubbish? */
+ return -ENAMETOOLONG;
+
+ *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
+ *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
+ break;
+ }
+
+ *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
+ *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
+ *(z++) = (uint8_t) c << 6 | (uint8_t) d; /* ZZWWWWWW */
}
*z = 0;
- *mem = r;
- r = NULL;
- *_len = len;
+ *ret_size = (size_t) (z - buf);
+ *ret = TAKE_PTR(buf);
return 0;
}
@@ -715,7 +774,10 @@ void hexdump(FILE *f, const void *p, size_t s) {
const uint8_t *b = p;
unsigned n = 0;
- assert(s == 0 || b);
+ assert(b || s == 0);
+
+ if (!f)
+ f = stdout;
while (s > 0) {
size_t i;
diff --git a/src/basic/hexdecoct.h b/src/basic/hexdecoct.h
index 1ba2f69eb..9477d16e3 100644
--- a/src/basic/hexdecoct.h
+++ b/src/basic/hexdecoct.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 <stddef.h>
#include <stdio.h>
diff --git a/src/basic/hostname-util.c b/src/basic/hostname-util.c
index 63329d53b..e2b77e51f 100644
--- a/src/basic/hostname-util.c
+++ b/src/basic/hostname-util.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <limits.h>
@@ -24,6 +7,8 @@
#include <sys/utsname.h>
#include <unistd.h>
+//#include "alloc-util.h"
+//#include "def.h"
//#include "fd-util.h"
#include "fileio.h"
#include "hostname-util.h"
@@ -98,9 +83,7 @@ static bool hostname_valid_char(char c) {
(c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9') ||
- c == '-' ||
- c == '_' ||
- c == '.';
+ IN_SET(c, '-', '_', '.');
}
/**
@@ -207,8 +190,11 @@ bool is_gateway_hostname(const char *hostname) {
* synthetic "gateway" host. */
return
- strcaseeq(hostname, "gateway") ||
- strcaseeq(hostname, "gateway.");
+ strcaseeq(hostname, "_gateway") || strcaseeq(hostname, "_gateway.")
+#if ENABLE_COMPAT_GATEWAY_HOSTNAME
+ || strcaseeq(hostname, "gateway") || strcaseeq(hostname, "gateway.")
+#endif
+ ;
}
int sethostname_idempotent(const char *s) {
@@ -228,36 +214,88 @@ int sethostname_idempotent(const char *s) {
return 1;
}
-int read_hostname_config(const char *path, char **hostname) {
- _cleanup_fclose_ FILE *f = NULL;
- char l[LINE_MAX];
- char *name = NULL;
+int shorten_overlong(const char *s, char **ret) {
+ char *h, *p;
- assert(path);
- assert(hostname);
+ /* Shorten an overlong name to HOST_NAME_MAX or to the first dot,
+ * whatever comes earlier. */
- f = fopen(path, "re");
- if (!f)
- return -errno;
+ assert(s);
- /* may have comments, ignore them */
- FOREACH_LINE(l, f, return -errno) {
- truncate_nl(l);
- if (l[0] != '\0' && l[0] != '#') {
- /* found line with value */
- name = hostname_cleanup(l);
- name = strdup(name);
- if (!name)
+ h = strdup(s);
+ if (!h)
+ return -ENOMEM;
+
+ if (hostname_is_valid(h, false)) {
+ *ret = h;
+ return 0;
+ }
+
+ p = strchr(h, '.');
+ if (p)
+ *p = 0;
+
+ strshorten(h, HOST_NAME_MAX);
+
+ if (!hostname_is_valid(h, false)) {
+ free(h);
+ return -EDOM;
+ }
+
+ *ret = h;
+ return 1;
+}
+
+int read_etc_hostname_stream(FILE *f, char **ret) {
+ int r;
+
+ assert(f);
+ assert(ret);
+
+ for (;;) {
+ _cleanup_free_ char *line = NULL;
+ char *p;
+
+ r = read_line(f, LONG_LINE_MAX, &line);
+ if (r < 0)
+ return r;
+ if (r == 0) /* EOF without any hostname? the file is empty, let's treat that exactly like no file at all: ENOENT */
+ return -ENOENT;
+
+ p = strstrip(line);
+
+ /* File may have empty lines or comments, ignore them */
+ if (!IN_SET(*p, '\0', '#')) {
+ char *copy;
+
+ hostname_cleanup(p); /* normalize the hostname */
+
+ if (!hostname_is_valid(p, true)) /* check that the hostname we return is valid */
+ return -EBADMSG;
+
+ copy = strdup(p);
+ if (!copy)
return -ENOMEM;
- break;
+
+ *ret = copy;
+ return 0;
}
}
+}
- if (!name)
- /* no non-empty line found */
- return -ENOENT;
+int read_etc_hostname(const char *path, char **ret) {
+ _cleanup_fclose_ FILE *f = NULL;
+
+ assert(ret);
+
+ if (!path)
+ path = "/etc/hostname";
+
+ f = fopen(path, "re");
+ if (!f)
+ return -errno;
+
+ return read_etc_hostname_stream(f, ret);
- *hostname = name;
- return 0;
}
#endif // 0
diff --git a/src/basic/hostname-util.h b/src/basic/hostname-util.h
index 4282d71ae..779de3ede 100644
--- a/src/basic/hostname-util.h
+++ b/src/basic/hostname-util.h
@@ -1,25 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010-2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
+//#include <stdio.h>
#include "macro.h"
@@ -45,5 +28,8 @@ bool is_gateway_hostname(const char *hostname);
int sethostname_idempotent(const char *s);
-int read_hostname_config(const char *path, char **hostname);
#endif // 0
+int shorten_overlong(const char *s, char **ret);
+
+int read_etc_hostname_stream(FILE *f, char **ret);
+int read_etc_hostname(const char *path, char **ret);
diff --git a/src/basic/io-util.c b/src/basic/io-util.c
index cc6dfa8c1..1f64cc933 100644
--- a/src/basic/io-util.c
+++ b/src/basic/io-util.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <limits.h>
@@ -32,6 +15,7 @@ int flush_fd(int fd) {
.fd = fd,
.events = POLLIN,
};
+ int count = 0;
/* Read from the specified file descriptor, until POLLIN is not set anymore, throwing away everything
* read. Note that some file descriptors (notable IP sockets) will trigger POLLIN even when no data can be read
@@ -51,7 +35,7 @@ int flush_fd(int fd) {
return -errno;
} else if (r == 0)
- return 0;
+ return count;
l = read(fd, buf, sizeof(buf));
if (l < 0) {
@@ -60,11 +44,13 @@ int flush_fd(int fd) {
continue;
if (errno == EAGAIN)
- return 0;
+ return count;
return -errno;
} else if (l == 0)
- return 0;
+ return count;
+
+ count += (int) l;
}
}
@@ -133,7 +119,7 @@ int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
assert(fd >= 0);
assert(buf);
- if (nbytes > (size_t) SSIZE_MAX)
+ if (_unlikely_(nbytes > (size_t) SSIZE_MAX))
return -EINVAL;
do {
@@ -199,7 +185,6 @@ int fd_wait_for_event(int fd, int event, usec_t t) {
r = ppoll(&pollfd, 1, t == USEC_INFINITY ? NULL : timespec_store(&ts, t), NULL);
if (r < 0)
return -errno;
-
if (r == 0)
return 0;
diff --git a/src/basic/io-util.h b/src/basic/io-util.h
index 4684ed3bf..ed189b582 100644
--- a/src/basic/io-util.h
+++ b/src/basic/io-util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 <stddef.h>
#include <stdint.h>
@@ -40,17 +22,8 @@ int fd_wait_for_event(int fd, int event, usec_t timeout);
ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length);
-#define IOVEC_SET_STRING(i, s) \
- do { \
- struct iovec *_i = &(i); \
- char *_s = (char *)(s); \
- _i->iov_base = _s; \
- _i->iov_len = strlen(_s); \
- } while (false)
-
-static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, unsigned n) {
- unsigned j;
- size_t r = 0;
+static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, size_t n) {
+ size_t j, r = 0;
for (j = 0; j < n; j++)
r += i[j].iov_len;
@@ -58,8 +31,8 @@ static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, unsigned n) {
return r;
}
-static inline size_t IOVEC_INCREMENT(struct iovec *i, unsigned n, size_t k) {
- unsigned j;
+static inline size_t IOVEC_INCREMENT(struct iovec *i, size_t n, size_t k) {
+ size_t j;
for (j = 0; j < n; j++) {
size_t sub;
@@ -93,3 +66,8 @@ static inline bool FILE_SIZE_VALID_OR_INFINITY(uint64_t l) {
return FILE_SIZE_VALID(l);
}
+
+#define IOVEC_INIT(base, len) { .iov_base = (base), .iov_len = (len) }
+#define IOVEC_MAKE(base, len) (struct iovec) IOVEC_INIT(base, len)
+#define IOVEC_INIT_STRING(string) IOVEC_INIT((char*) string, strlen(string))
+#define IOVEC_MAKE_STRING(string) (struct iovec) IOVEC_INIT_STRING(string)
diff --git a/src/basic/khash.c b/src/basic/khash.c
index 84648dc1c..847f2572a 100644
--- a/src/basic/khash.c
+++ b/src/basic/khash.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <linux/if_alg.h>
#include <stdbool.h>
@@ -42,6 +25,66 @@ struct khash {
bool digest_valid;
};
+int khash_supported(void) {
+ static const union {
+ struct sockaddr sa;
+ struct sockaddr_alg alg;
+ } sa = {
+ .alg.salg_family = AF_ALG,
+ .alg.salg_type = "hash",
+ .alg.salg_name = "sha256", /* a very common algorithm */
+ };
+
+ static int cached = -1;
+
+ if (cached < 0) {
+ _cleanup_close_ int fd1 = -1, fd2 = -1;
+ uint8_t buf[LONGEST_DIGEST+1];
+
+ fd1 = socket(AF_ALG, SOCK_SEQPACKET|SOCK_CLOEXEC, 0);
+ if (fd1 < 0) {
+ /* The kernel returns EAFNOSUPPORT if AF_ALG is not supported at all */
+ if (IN_SET(errno, EAFNOSUPPORT, EOPNOTSUPP))
+ return (cached = false);
+
+ return -errno;
+ }
+
+ if (bind(fd1, &sa.sa, sizeof(sa)) < 0) {
+ /* The kernel returns ENOENT if the selected algorithm is not supported at all. We use a check
+ * for SHA256 as a proxy for whether the whole API is supported at all. After all it's one of
+ * the most common hash functions, and if it isn't supported, that's ample indication that
+ * something is really off. */
+
+ if (IN_SET(errno, ENOENT, EOPNOTSUPP))
+ return (cached = false);
+
+ return -errno;
+ }
+
+ fd2 = accept4(fd1, NULL, 0, SOCK_CLOEXEC);
+ if (fd2 < 0) {
+ if (errno == EOPNOTSUPP)
+ return (cached = false);
+
+ return -errno;
+ }
+
+ if (recv(fd2, buf, sizeof(buf), 0) < 0) {
+ /* On some kernels we get ENOKEY for non-keyed hash functions (such as sha256), let's refuse
+ * using the API in those cases, since the kernel is
+ * broken. https://github.com/systemd/systemd/issues/8278 */
+
+ if (IN_SET(errno, ENOKEY, EOPNOTSUPP))
+ return (cached = false);
+ }
+
+ cached = true;
+ }
+
+ return cached;
+}
+
int khash_new_with_key(khash **ret, const char *algorithm, const void *key, size_t key_size) {
union {
struct sockaddr sa;
@@ -53,6 +96,7 @@ int khash_new_with_key(khash **ret, const char *algorithm, const void *key, size
_cleanup_(khash_unrefp) khash *h = NULL;
_cleanup_close_ int fd = -1;
+ int supported;
ssize_t n;
assert(ret);
@@ -66,6 +110,12 @@ int khash_new_with_key(khash **ret, const char *algorithm, const void *key, size
if (strlen(algorithm) >= sizeof(sa.alg.salg_name))
return -EOPNOTSUPP;
+ supported = khash_supported();
+ if (supported < 0)
+ return supported;
+ if (supported == 0)
+ return -EOPNOTSUPP;
+
fd = socket(AF_ALG, SOCK_SEQPACKET|SOCK_CLOEXEC, 0);
if (fd < 0)
return -errno;
@@ -126,9 +176,7 @@ khash* khash_unref(khash *h) {
safe_close(h->fd);
free(h->algorithm);
- free(h);
-
- return NULL;
+ return mfree(h);
}
int khash_dup(khash *h, khash **ret) {
@@ -150,8 +198,7 @@ int khash_dup(khash *h, khash **ret) {
if (copy->fd < 0)
return -errno;
- *ret = copy;
- copy = NULL;
+ *ret = TAKE_PTR(copy);
return 0;
}
diff --git a/src/basic/khash.h b/src/basic/khash.h
index 410f3020e..a3013b9d6 100644
--- a/src/basic/khash.h
+++ b/src/basic/khash.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 <sys/uio.h>
@@ -27,6 +9,8 @@
typedef struct khash khash;
+int khash_supported(void);
+
/* For plain hash functions. Hash functions commonly supported on today's kernels are: crc32c, crct10dif, crc32,
* sha224, sha256, sha512, sha384, sha1, md5, md4, sha3-224, sha3-256, sha3-384, sha3-512, and more. */
int khash_new(khash **ret, const char *algorithm);
diff --git a/src/basic/label.c b/src/basic/label.c
index 3556377d2..e4c1170ae 100644
--- a/src/basic/label.c
+++ b/src/basic/label.c
@@ -1,36 +1,20 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
+//#include "btrfs-util.h"
#include "label.h"
#include "macro.h"
#include "selinux-util.h"
#include "smack-util.h"
-int label_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
+int label_fix(const char *path, LabelFixFlags flags) {
int r, q;
- r = mac_selinux_fix(path, ignore_enoent, ignore_erofs);
- q = mac_smack_fix(path, ignore_enoent, ignore_erofs);
+ r = mac_selinux_fix(path, flags);
+ q = mac_smack_fix(path, flags);
if (r < 0)
return r;
@@ -40,16 +24,19 @@ int label_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
return 0;
}
-int mkdir_label(const char *path, mode_t mode) {
+
+#if 0 /// UNNEEDED by elogind
+int symlink_label(const char *old_path, const char *new_path) {
int r;
- assert(path);
+ assert(old_path);
+ assert(new_path);
- r = mac_selinux_create_file_prepare(path, S_IFDIR);
+ r = mac_selinux_create_file_prepare(new_path, S_IFLNK);
if (r < 0)
return r;
- if (mkdir(path, mode) < 0)
+ if (symlink(old_path, new_path) < 0)
r = -errno;
mac_selinux_create_file_clear();
@@ -57,28 +44,24 @@ int mkdir_label(const char *path, mode_t mode) {
if (r < 0)
return r;
- return mac_smack_fix(path, false, false);
+ return mac_smack_fix(new_path, 0);
}
-#if 0 /// UNNEEDED by elogind
-int symlink_label(const char *old_path, const char *new_path) {
+int btrfs_subvol_make_label(const char *path) {
int r;
- assert(old_path);
- assert(new_path);
+ assert(path);
- r = mac_selinux_create_file_prepare(new_path, S_IFLNK);
+ r = mac_selinux_create_file_prepare(path, S_IFDIR);
if (r < 0)
return r;
- if (symlink(old_path, new_path) < 0)
- r = -errno;
-
+ r = btrfs_subvol_make(path);
mac_selinux_create_file_clear();
if (r < 0)
return r;
- return mac_smack_fix(new_path, false, false);
+ return mac_smack_fix(path, 0);
}
#endif // 0
diff --git a/src/basic/label.h b/src/basic/label.h
index dc702f5cb..3cdc14683 100644
--- a/src/basic/label.h
+++ b/src/basic/label.h
@@ -1,30 +1,19 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <sys/types.h>
-int label_fix(const char *path, bool ignore_enoent, bool ignore_erofs);
+typedef enum LabelFixFlags {
+ LABEL_IGNORE_ENOENT = 1 << 0,
+ LABEL_IGNORE_EROFS = 1 << 1,
+} LabelFixFlags;
+
+int label_fix(const char *path, LabelFixFlags flags);
int mkdir_label(const char *path, mode_t mode);
#if 0 /// UNNEEDED by elogind
int symlink_label(const char *old_path, const char *new_path);
+
+int btrfs_subvol_make_label(const char *path);
#endif // 0
diff --git a/src/basic/list.h b/src/basic/list.h
index c3771a177..643e0bea8 100644
--- a/src/basic/list.h
+++ b/src/basic/list.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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) \
@@ -182,3 +164,6 @@
for ((i) = (p)->name##_next ? (p)->name##_next : (head); \
(i) != (p); \
(i) = (i)->name##_next ? (i)->name##_next : (head))
+
+#define LIST_IS_EMPTY(head) \
+ (!(head))
diff --git a/src/basic/locale-util.c b/src/basic/locale-util.c
index ada0a28cd..3ad352f22 100644
--- a/src/basic/locale-util.c
+++ b/src/basic/locale-util.c
@@ -1,25 +1,9 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
+#include <ftw.h>
#include <langinfo.h>
#include <libintl.h>
#include <locale.h>
@@ -30,6 +14,7 @@
#include <sys/mman.h>
#include <sys/stat.h>
+#include "def.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "hashmap.h"
@@ -81,7 +66,7 @@ static int add_locales_from_archive(Set *locales) {
_cleanup_close_ int fd = -1;
size_t sz = 0;
struct stat st;
- unsigned i;
+ size_t i;
int r;
fd = open("/usr/lib/locale/locale-archive", O_RDONLY|O_NOCTTY|O_CLOEXEC);
@@ -193,8 +178,7 @@ int get_locales(char ***ret) {
strv_sort(l);
- *ret = l;
- l = NULL;
+ *ret = TAKE_PTR(l);
return 0;
}
@@ -270,9 +254,108 @@ out:
return (bool) cached_answer;
}
+static thread_local 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(basename(fpath));
+ if (!p)
+ return FTW_STOP;
+
+ e = endswith(p, ".map");
+ if (e)
+ *e = 0;
+
+ e = endswith(p, ".map.gz");
+ if (e)
+ *e = 0;
+
+ r = set_consume(keymaps, p);
+ if (r < 0 && r != -EEXIST)
+ return r;
+
+ return 0;
+}
+
+int get_keymaps(char ***ret) {
+ _cleanup_strv_free_ char **l = NULL;
+ const char *dir;
+ int r;
+
+ keymaps = set_new(&string_hash_ops);
+ if (!keymaps)
+ return -ENOMEM;
+
+ NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS) {
+ r = nftw(dir, nftw_cb, 20, FTW_PHYS|FTW_ACTIONRETVAL);
+
+ if (r == FTW_STOP)
+ log_debug("Directory not found %s", dir);
+ else if (r < 0)
+ log_debug_errno(r, "Can't add keymap: %m");
+ }
+
+ l = set_get_strv(keymaps);
+ if (!l) {
+ set_free_free(keymaps);
+ return -ENOMEM;
+ }
+
+ set_free(keymaps);
+
+ if (strv_isempty(l))
+ return -ENOENT;
+
+ strv_sort(l);
+
+ *ret = TAKE_PTR(l);
+
+ return 0;
+}
+
+bool keymap_is_valid(const char *name) {
+
+ if (isempty(name))
+ return false;
+
+ if (strlen(name) >= 128)
+ return false;
+
+ if (!utf8_is_valid(name))
+ return false;
+
+ if (!filename_is_valid(name))
+ return false;
+
+ if (!string_is_safe(name))
+ return false;
+
+ return true;
+}
const char *special_glyph(SpecialGlyph code) {
+ /* A list of a number of interesting unicode glyphs we can use to decorate our output. It's probably wise to be
+ * conservative here, and primarily stick to the glyphs defined in the eurlatgr font, so that display still
+ * works reasonably well on the Linux console. For details see:
+ *
+ * http://git.altlinux.org/people/legion/packages/kbd.git?p=kbd.git;a=blob;f=data/consolefonts/README.eurlatgr
+ */
+
static const char* const draw_table[2][_SPECIAL_GLYPH_MAX] = {
/* ASCII fallback */
[false] = {
@@ -284,10 +367,11 @@ const char *special_glyph(SpecialGlyph code) {
[BLACK_CIRCLE] = "*",
[ARROW] = "->",
[MDASH] = "-",
+ [ELLIPSIS] = "..."
},
/* UTF-8 */
- [ true ] = {
+ [true] = {
[TREE_VERTICAL] = "\342\224\202 ", /* │ */
[TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */
[TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */
@@ -296,6 +380,7 @@ const char *special_glyph(SpecialGlyph code) {
[BLACK_CIRCLE] = "\342\227\217", /* ● */
[ARROW] = "\342\206\222", /* → */
[MDASH] = "\342\200\223", /* – */
+ [ELLIPSIS] = "\342\200\246", /* … */
},
};
diff --git a/src/basic/locale-util.h b/src/basic/locale-util.h
index 0630a034a..775fe8bc7 100644
--- a/src/basic/locale-util.h
+++ b/src/basic/locale-util.h
@@ -1,26 +1,9 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <libintl.h>
#include <stdbool.h>
+#include <locale.h>
#include "macro.h"
@@ -64,6 +47,7 @@ typedef enum {
BLACK_CIRCLE,
ARROW,
MDASH,
+ ELLIPSIS,
_SPECIAL_GLYPH_MAX
} SpecialGlyph;
@@ -71,3 +55,13 @@ const char *special_glyph(SpecialGlyph code) _const_;
const char* locale_variable_to_string(LocaleVariable i) _const_;
LocaleVariable locale_variable_from_string(const char *s) _pure_;
+
+int get_keymaps(char ***l);
+bool keymap_is_valid(const char *name);
+
+static inline void freelocalep(locale_t *p) {
+ if (*p == (locale_t) 0)
+ return;
+
+ freelocale(*p);
+}
diff --git a/src/basic/log.c b/src/basic/log.c
index 3924ed71f..6524b9e32 100644
--- a/src/basic/log.c
+++ b/src/basic/log.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <fcntl.h>
@@ -53,6 +36,7 @@
#include "syslog-util.h"
#include "terminal-util.h"
#include "time-util.h"
+#include "utf8.h"
#include "util.h"
#define SNDBUF_SIZE (8*1024*1024)
@@ -76,40 +60,46 @@ static bool show_location = false;
static bool upgrade_syslog_to_journal = false;
#endif // 0
static bool always_reopen_console = false;
+static bool open_when_needed = false;
+static bool prohibit_ipc = 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)
- safe_close(console_fd);
-
- console_fd = -1;
- }
+/* An assert to use in logging functions that does not call recursively
+ * into our logging functions (since that might lead to a loop). */
+#define assert_raw(expr) \
+ do { \
+ if (_unlikely_(!(expr))) { \
+ fputs(#expr "\n", stderr); \
+ abort(); \
+ } \
+ } while (false)
+
+static void log_close_console(void) {
+ console_fd = safe_close_above_stdio(console_fd);
}
static int log_open_console(void) {
- if (console_fd >= 0)
+ if (!always_reopen_console) {
+ console_fd = STDERR_FILENO;
return 0;
+ }
- if (always_reopen_console) {
+ if (console_fd < 3) {
console_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
if (console_fd < 0)
return console_fd;
- } else
- console_fd = STDERR_FILENO;
+
+ console_fd = fd_move_above_stdio(console_fd);
+ }
return 0;
}
-void log_close_kmsg(void) {
+static void log_close_kmsg(void) {
kmsg_fd = safe_close(kmsg_fd);
}
@@ -122,10 +112,11 @@ static int log_open_kmsg(void) {
if (kmsg_fd < 0)
return -errno;
+ kmsg_fd = fd_move_above_stdio(kmsg_fd);
return 0;
}
-void log_close_syslog(void) {
+static void log_close_syslog(void) {
syslog_fd = safe_close(syslog_fd);
}
@@ -137,12 +128,12 @@ static int create_log_socket(int type) {
if (fd < 0)
return -errno;
+ fd = fd_move_above_stdio(fd);
(void) fd_inc_sndbuf(fd, SNDBUF_SIZE);
- /* We need a blocking fd here since we'd otherwise lose
- messages way too early. However, let's not hang forever in the
- unlikely case of a deadlock. */
- if (getpid() == 1)
+ /* We need a blocking fd here since we'd otherwise lose messages way too early. However, let's not hang forever
+ * in the unlikely case of a deadlock. */
+ if (getpid_cached() == 1)
timeval_store(&tv, 10 * USEC_PER_MSEC);
else
timeval_store(&tv, 10 * USEC_PER_SEC);
@@ -197,7 +188,7 @@ fail:
return r;
}
-void log_close_journal(void) {
+static void log_close_journal(void) {
#if 0 /// elogind does not support journald
journal_fd = safe_close(journal_fd);
#endif // 0
@@ -243,7 +234,8 @@ int log_open(void) {
/* 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,
+ * the fs, and to make sure we don't use it if prohibit_ipc is
+ * set. 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) {
@@ -253,12 +245,13 @@ int log_open(void) {
return 0;
}
- if (!IN_SET(log_target, LOG_TARGET_AUTO, LOG_TARGET_SAFE) ||
- getpid() == 1 ||
+ if (log_target != LOG_TARGET_AUTO ||
+ getpid_cached() == 1 ||
isatty(STDERR_FILENO) <= 0) {
#if 0 /// elogind does not support logging to systemd-journald
- if (IN_SET(log_target, LOG_TARGET_AUTO,
+ if (!prohibit_ipc &&
+ IN_SET(log_target, LOG_TARGET_AUTO,
LOG_TARGET_JOURNAL_OR_KMSG,
LOG_TARGET_JOURNAL)) {
r = log_open_journal();
@@ -270,7 +263,8 @@ int log_open(void) {
}
#endif // 0
- if (IN_SET(log_target, LOG_TARGET_SYSLOG_OR_KMSG,
+ if (!prohibit_ipc &&
+ IN_SET(log_target, LOG_TARGET_SYSLOG_OR_KMSG,
LOG_TARGET_SYSLOG)) {
r = log_open_syslog();
if (r >= 0) {
@@ -281,7 +275,6 @@ int log_open(void) {
}
if (IN_SET(log_target, LOG_TARGET_AUTO,
- LOG_TARGET_SAFE,
LOG_TARGET_JOURNAL_OR_KMSG,
LOG_TARGET_SYSLOG_OR_KMSG,
LOG_TARGET_KMSG)) {
@@ -355,34 +348,34 @@ static int write_to_console(
char location[256], prefix[1 + DECIMAL_STR_MAX(int) + 2];
struct iovec iovec[6] = {};
- unsigned n = 0;
bool highlight;
+ size_t n = 0;
if (console_fd < 0)
return 0;
if (log_target == LOG_TARGET_CONSOLE_PREFIXED) {
xsprintf(prefix, "<%i>", level);
- IOVEC_SET_STRING(iovec[n++], prefix);
+ iovec[n++] = IOVEC_MAKE_STRING(prefix);
}
highlight = LOG_PRI(level) <= LOG_ERR && show_color;
if (show_location) {
- snprintf(location, sizeof(location), "(%s:%i) ", file, line);
- IOVEC_SET_STRING(iovec[n++], location);
+ (void) snprintf(location, sizeof location, "(%s:%i) ", file, line);
+ iovec[n++] = IOVEC_MAKE_STRING(location);
}
if (highlight)
- IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_RED);
- IOVEC_SET_STRING(iovec[n++], buffer);
+ iovec[n++] = IOVEC_MAKE_STRING(ANSI_HIGHLIGHT_RED);
+ iovec[n++] = IOVEC_MAKE_STRING(buffer);
if (highlight)
- IOVEC_SET_STRING(iovec[n++], ANSI_NORMAL);
- IOVEC_SET_STRING(iovec[n++], "\n");
+ iovec[n++] = IOVEC_MAKE_STRING(ANSI_NORMAL);
+ iovec[n++] = IOVEC_MAKE_STRING("\n");
if (writev(console_fd, iovec, n) < 0) {
- if (errno == EIO && getpid() == 1) {
+ if (errno == EIO && getpid_cached() == 1) {
/* If somebody tried to kick us from our
* console tty (via vhangup() or suchlike),
@@ -435,13 +428,13 @@ static int write_to_syslog(
if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
return -EINVAL;
- xsprintf(header_pid, "["PID_FMT"]: ", getpid());
+ xsprintf(header_pid, "["PID_FMT"]: ", getpid_cached());
- 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);
+ iovec[0] = IOVEC_MAKE_STRING(header_priority);
+ iovec[1] = IOVEC_MAKE_STRING(header_time);
+ iovec[2] = IOVEC_MAKE_STRING(program_invocation_short_name);
+ iovec[3] = IOVEC_MAKE_STRING(header_pid);
+ iovec[4] = IOVEC_MAKE_STRING(buffer);
/* When using syslog via SOCK_STREAM separate the messages by NUL chars */
if (syslog_is_stream)
@@ -480,13 +473,13 @@ static int write_to_kmsg(
return 0;
xsprintf(header_priority, "<%i>", level);
- xsprintf(header_pid, "["PID_FMT"]: ", getpid());
+ xsprintf(header_pid, "["PID_FMT"]: ", getpid_cached());
- 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");
+ iovec[0] = IOVEC_MAKE_STRING(header_priority);
+ iovec[1] = IOVEC_MAKE_STRING(program_invocation_short_name);
+ iovec[2] = IOVEC_MAKE_STRING(header_pid);
+ iovec[3] = IOVEC_MAKE_STRING(buffer);
+ iovec[4] = IOVEC_MAKE_STRING("\n");
if (writev(kmsg_fd, iovec, ELEMENTSOF(iovec)) < 0)
return -errno;
@@ -494,7 +487,6 @@ static int write_to_kmsg(
return 1;
}
-#if 0 /// UNNEEDED by elogind
static int log_do_header(
char *header,
size_t size,
@@ -503,42 +495,45 @@ static int log_do_header(
const char *file, int line, const char *func,
const char *object_field, const char *object,
const char *extra_field, const char *extra) {
+ int r;
- snprintf(header, size,
- "PRIORITY=%i\n"
- "SYSLOG_FACILITY=%i\n"
- "%s%s%s"
- "%s%.*i%s"
- "%s%s%s"
- "%s%.*i%s"
- "%s%s%s"
- "%s%s%s"
- "SYSLOG_IDENTIFIER=%s\n",
- LOG_PRI(level),
- LOG_FAC(level),
- isempty(file) ? "" : "CODE_FILE=",
- isempty(file) ? "" : file,
- isempty(file) ? "" : "\n",
- line ? "CODE_LINE=" : "",
- line ? 1 : 0, line, /* %.0d means no output too, special case for 0 */
- line ? "\n" : "",
- isempty(func) ? "" : "CODE_FUNC=",
- isempty(func) ? "" : func,
- isempty(func) ? "" : "\n",
- error ? "ERRNO=" : "",
- error ? 1 : 0, error,
- error ? "\n" : "",
- isempty(object) ? "" : object_field,
- isempty(object) ? "" : object,
- isempty(object) ? "" : "\n",
- isempty(extra) ? "" : extra_field,
- isempty(extra) ? "" : extra,
- isempty(extra) ? "" : "\n",
- program_invocation_short_name);
+ r = snprintf(header, size,
+ "PRIORITY=%i\n"
+ "SYSLOG_FACILITY=%i\n"
+ "%s%.256s%s" /* CODE_FILE */
+ "%s%.*i%s" /* CODE_LINE */
+ "%s%.256s%s" /* CODE_FUNC */
+ "%s%.*i%s" /* ERRNO */
+ "%s%.256s%s" /* object */
+ "%s%.256s%s" /* extra */
+ "SYSLOG_IDENTIFIER=%.256s\n",
+ LOG_PRI(level),
+ LOG_FAC(level),
+ isempty(file) ? "" : "CODE_FILE=",
+ isempty(file) ? "" : file,
+ isempty(file) ? "" : "\n",
+ line ? "CODE_LINE=" : "",
+ line ? 1 : 0, line, /* %.0d means no output too, special case for 0 */
+ line ? "\n" : "",
+ isempty(func) ? "" : "CODE_FUNC=",
+ isempty(func) ? "" : func,
+ isempty(func) ? "" : "\n",
+ error ? "ERRNO=" : "",
+ error ? 1 : 0, error,
+ error ? "\n" : "",
+ isempty(object) ? "" : object_field,
+ isempty(object) ? "" : object,
+ isempty(object) ? "" : "\n",
+ isempty(extra) ? "" : extra_field,
+ isempty(extra) ? "" : extra,
+ isempty(extra) ? "" : "\n",
+ program_invocation_short_name);
+ assert_raw((size_t) r < size);
return 0;
}
+#if 0 /// UNNEEDED by elogind
static int write_to_journal(
int level,
int error,
@@ -560,10 +555,10 @@ static int write_to_journal(
log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object, extra_field, extra);
- IOVEC_SET_STRING(iovec[0], header);
- IOVEC_SET_STRING(iovec[1], "MESSAGE=");
- IOVEC_SET_STRING(iovec[2], buffer);
- IOVEC_SET_STRING(iovec[3], "\n");
+ iovec[0] = IOVEC_MAKE_STRING(header);
+ iovec[1] = IOVEC_MAKE_STRING("MESSAGE=");
+ iovec[2] = IOVEC_MAKE_STRING(buffer);
+ iovec[3] = IOVEC_MAKE_STRING("\n");
mh.msg_iov = iovec;
mh.msg_iovlen = ELEMENTSOF(iovec);
@@ -583,11 +578,11 @@ int log_dispatch_internal(
const char *func,
const char *object_field,
const char *object,
- const char *extra,
const char *extra_field,
+ const char *extra,
char *buffer) {
- assert(buffer);
+ assert_raw(buffer);
if (error < 0)
error = -error;
@@ -599,6 +594,9 @@ int log_dispatch_internal(
if ((level & LOG_FACMASK) == 0)
level = log_facility | LOG_PRI(level);
+ if (open_when_needed)
+ log_open();
+
do {
char *e;
int k = 0;
@@ -617,11 +615,8 @@ int log_dispatch_internal(
LOG_TARGET_JOURNAL)) {
k = write_to_journal(level, error, file, line, func, object_field, object, extra_field, extra, buffer);
- if (k < 0) {
- if (k != -EAGAIN)
- log_close_journal();
- log_open_kmsg();
- }
+ if (k < 0 && k != -EAGAIN)
+ log_close_journal();
}
#endif // 0
@@ -629,20 +624,19 @@ int log_dispatch_internal(
LOG_TARGET_SYSLOG)) {
k = write_to_syslog(level, error, file, line, func, buffer);
- if (k < 0) {
- if (k != -EAGAIN)
- log_close_syslog();
- log_open_kmsg();
- }
+ if (k < 0 && k != -EAGAIN)
+ log_close_syslog();
}
if (k <= 0 &&
IN_SET(log_target, LOG_TARGET_AUTO,
- LOG_TARGET_SAFE,
LOG_TARGET_SYSLOG_OR_KMSG,
LOG_TARGET_JOURNAL_OR_KMSG,
LOG_TARGET_KMSG)) {
+ if (k < 0)
+ log_open_kmsg();
+
k = write_to_kmsg(level, error, file, line, func, buffer);
if (k < 0) {
log_close_kmsg();
@@ -656,6 +650,9 @@ int log_dispatch_internal(
buffer = e;
} while (buffer);
+ if (open_when_needed)
+ log_close();
+
return -error;
}
@@ -700,11 +697,10 @@ int log_internalv_realm(
if (_likely_(LOG_PRI(level) > log_max_level[realm]))
return -error;
- /* Make sure that %m maps to the specified error */
- if (error != 0)
- errno = error;
+ /* Make sure that %m maps to the specified error (or "Success"). */
+ errno = error;
- vsnprintf(buffer, sizeof(buffer), format, ap);
+ (void) vsnprintf(buffer, sizeof buffer, format, ap);
return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
}
@@ -727,7 +723,8 @@ int log_internal_realm(
return r;
}
-int log_object_internalv(
+_printf_(10,0)
+static int log_object_internalv(
int level,
int error,
const char *file,
@@ -749,9 +746,8 @@ int log_object_internalv(
if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD]))
return -error;
- /* Make sure that %m maps to the specified error */
- if (error != 0)
- errno = error;
+ /* Make sure that %m maps to the specified error (or "Success"). */
+ errno = error;
/* Prepend the object name before the message */
if (object) {
@@ -763,7 +759,7 @@ int log_object_internalv(
} else
b = buffer = newa(char, LINE_MAX);
- vsnprintf(b, LINE_MAX, format, ap);
+ (void) vsnprintf(b, LINE_MAX, format, ap);
return log_dispatch_internal(level, error, file, line, func,
object_field, object, extra_field, extra, buffer);
@@ -806,7 +802,7 @@ static void log_assert(
return;
DISABLE_WARNING_FORMAT_NONLITERAL;
- snprintf(buffer, sizeof buffer, format, text, file, line, func);
+ (void) snprintf(buffer, sizeof buffer, format, text, file, line, func);
REENABLE_WARNING;
log_abort_msg = buffer;
@@ -814,23 +810,25 @@ static void log_assert(
log_dispatch_internal(level, 0, file, line, func, NULL, NULL, NULL, NULL, buffer);
}
-noreturn void log_assert_failed_realm(
+_noreturn_ void log_assert_failed_realm(
LogRealm realm,
const char *text,
const char *file,
int line,
const char *func) {
+ log_open();
log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
"Assertion '%s' failed at %s:%u, function %s(). Aborting.");
abort();
}
-noreturn void log_assert_failed_unreachable_realm(
+_noreturn_ void log_assert_failed_unreachable_realm(
LogRealm realm,
const char *text,
const char *file,
int line,
const char *func) {
+ log_open();
log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
"Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
abort();
@@ -848,15 +846,14 @@ void log_assert_failed_return_realm(
}
int log_oom_internal(LogRealm realm, const char *file, int line, const char *func) {
- log_internal_realm(LOG_REALM_PLUS_LEVEL(realm, LOG_ERR),
- ENOMEM, file, line, func, "Out of memory.");
- return -ENOMEM;
+ return log_internal_realm(LOG_REALM_PLUS_LEVEL(realm, LOG_ERR),
+ ENOMEM, file, line, func, "Out of memory.");
}
int log_format_iovec(
struct iovec *iovec,
- unsigned iovec_len,
- unsigned *n,
+ size_t iovec_len,
+ size_t *n,
bool newline_separator,
int error,
const char *format,
@@ -873,8 +870,7 @@ int log_format_iovec(
* since vasprintf() leaves it afterwards at
* an undefined location */
- if (error != 0)
- errno = error;
+ errno = error;
va_copy(aq, ap);
r = vasprintf(&m, format, aq);
@@ -886,7 +882,7 @@ int log_format_iovec(
* the next format string */
VA_FORMAT_ADVANCE(format, ap);
- IOVEC_SET_STRING(iovec[(*n)++], m);
+ iovec[(*n)++] = IOVEC_MAKE_STRING(m);
if (newline_separator) {
iovec[*n].iov_base = (char*) &nl;
@@ -907,9 +903,9 @@ int log_struct_internal(
const char *func,
const char *format, ...) {
+ LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
char buf[LINE_MAX];
bool found = false;
- LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
PROTECT_ERRNO;
va_list ap;
@@ -926,38 +922,48 @@ int log_struct_internal(
level = log_facility | LOG_PRI(level);
#if 0 /// elogind does not support logging to systemd-journald
- if (IN_SET(log_target, LOG_TARGET_AUTO,
- LOG_TARGET_JOURNAL_OR_KMSG,
- LOG_TARGET_JOURNAL) &&
- journal_fd >= 0) {
- char header[LINE_MAX];
- struct iovec iovec[17] = {};
- unsigned n = 0, i;
- int r;
- struct msghdr mh = {
- .msg_iov = iovec,
- };
- bool fallback = false;
-
- /* If the journal is available do structured logging */
- log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL);
- IOVEC_SET_STRING(iovec[n++], header);
+ if (IN_SET(log_target,
+ LOG_TARGET_AUTO,
+ LOG_TARGET_JOURNAL_OR_KMSG,
+ LOG_TARGET_JOURNAL)) {
+
+ if (open_when_needed)
+ log_open_journal();
+
+ if (journal_fd >= 0) {
+ char header[LINE_MAX];
+ struct iovec iovec[17] = {};
+ size_t n = 0, i;
+ int r;
+ struct msghdr mh = {
+ .msg_iov = iovec,
+ };
+ bool fallback = false;
+
+ /* If the journal is available do structured logging */
+ log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL);
+ iovec[n++] = IOVEC_MAKE_STRING(header);
+
+ va_start(ap, format);
+ r = log_format_iovec(iovec, ELEMENTSOF(iovec), &n, true, error, format, ap);
+ if (r < 0)
+ fallback = true;
+ else {
+ mh.msg_iovlen = n;
+ (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
+ }
- va_start(ap, format);
- r = log_format_iovec(iovec, ELEMENTSOF(iovec), &n, true, error, format, ap);
- if (r < 0)
- fallback = true;
- else {
- mh.msg_iovlen = n;
- (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
- }
+ va_end(ap);
+ for (i = 1; i < n; i += 2)
+ free(iovec[i].iov_base);
- va_end(ap);
- for (i = 1; i < n; i += 2)
- free(iovec[i].iov_base);
+ if (!fallback) {
+ if (open_when_needed)
+ log_close();
- if (!fallback)
- return -error;
+ return -error;
+ }
+ }
}
#endif // 0
@@ -967,11 +973,10 @@ int log_struct_internal(
while (format) {
va_list aq;
- if (error != 0)
- errno = error;
+ errno = error;
va_copy(aq, ap);
- vsnprintf(buf, sizeof(buf), format, aq);
+ (void) vsnprintf(buf, sizeof buf, format, aq);
va_end(aq);
if (startswith(buf, "MESSAGE=")) {
@@ -985,12 +990,79 @@ int log_struct_internal(
}
va_end(ap);
- if (!found)
+ if (!found) {
+ if (open_when_needed)
+ log_close();
+
return -error;
+ }
return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buf + 8);
}
+int log_struct_iovec_internal(
+ int level,
+ int error,
+ const char *file,
+ int line,
+ const char *func,
+ const struct iovec input_iovec[],
+ size_t n_input_iovec) {
+
+ LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
+ PROTECT_ERRNO;
+ size_t i;
+ char *m;
+
+ if (error < 0)
+ error = -error;
+
+ if (_likely_(LOG_PRI(level) > log_max_level[realm]))
+ return -error;
+
+ if (log_target == LOG_TARGET_NULL)
+ return -error;
+
+ if ((level & LOG_FACMASK) == 0)
+ level = log_facility | LOG_PRI(level);
+
+ if (IN_SET(log_target, LOG_TARGET_AUTO,
+ LOG_TARGET_JOURNAL_OR_KMSG,
+ LOG_TARGET_JOURNAL) &&
+ journal_fd >= 0) {
+
+ struct iovec iovec[1 + n_input_iovec*2];
+ char header[LINE_MAX];
+ struct msghdr mh = {
+ .msg_iov = iovec,
+ .msg_iovlen = 1 + n_input_iovec*2,
+ };
+
+ log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL);
+ iovec[0] = IOVEC_MAKE_STRING(header);
+
+ for (i = 0; i < n_input_iovec; i++) {
+ iovec[1+i*2] = input_iovec[i];
+ iovec[1+i*2+1] = IOVEC_MAKE_STRING("\n");
+ }
+
+ if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) >= 0)
+ return -error;
+ }
+
+ for (i = 0; i < n_input_iovec; i++)
+ if (memory_startswith(input_iovec[i].iov_base, input_iovec[i].iov_len, "MESSAGE="))
+ break;
+
+ if (_unlikely_(i >= n_input_iovec)) /* Couldn't find MESSAGE=? */
+ return -error;
+
+ m = strndupa(input_iovec[i].iov_base + STRLEN("MESSAGE="),
+ input_iovec[i].iov_len - STRLEN("MESSAGE="));
+
+ return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, m);
+}
+
int log_set_target_from_string(const char *e) {
LogTarget t;
@@ -1149,18 +1221,19 @@ static const char *const log_target_table[_LOG_TARGET_MAX] = {
[LOG_TARGET_SYSLOG] = "syslog",
[LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg",
[LOG_TARGET_AUTO] = "auto",
- [LOG_TARGET_SAFE] = "safe",
- [LOG_TARGET_NULL] = "null"
+ [LOG_TARGET_NULL] = "null",
};
DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);
#if 0 /// UNNEEDED by elogind
void log_received_signal(int level, const struct signalfd_siginfo *si) {
- if (si->ssi_pid > 0) {
+ assert(si);
+
+ if (pid_is_valid(si->ssi_pid)) {
_cleanup_free_ char *p = NULL;
- get_process_comm(si->ssi_pid, &p);
+ (void) get_process_comm(si->ssi_pid, &p);
log_full(level,
"Received SIG%s from PID %"PRIu32" (%s).",
@@ -1170,14 +1243,9 @@ void log_received_signal(int level, const struct signalfd_siginfo *si) {
log_full(level,
"Received SIG%s.",
signal_to_string(si->ssi_signo));
-
}
-void log_set_upgrade_syslog_to_journal(bool b) {
- upgrade_syslog_to_journal = b;
-}
#endif // 0
-
int log_syntax_internal(
const char *unit,
int level,
@@ -1203,15 +1271,14 @@ int log_syntax_internal(
if (log_target == LOG_TARGET_NULL)
return -error;
- if (error != 0)
- errno = error;
+ errno = error;
va_start(ap, format);
- vsnprintf(buffer, sizeof(buffer), format, ap);
+ (void) vsnprintf(buffer, sizeof buffer, format, ap);
va_end(ap);
if (unit)
- unit_fmt = getpid() == 1 ? "UNIT=%s" : "USER_UNIT=%s";
+ unit_fmt = getpid_cached() == 1 ? "UNIT=%s" : "USER_UNIT=%s";
return log_struct_internal(
LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level),
@@ -1225,8 +1292,73 @@ int log_syntax_internal(
NULL);
}
+int log_syntax_invalid_utf8_internal(
+ const char *unit,
+ int level,
+ const char *config_file,
+ unsigned config_line,
+ const char *file,
+ int line,
+ const char *func,
+ const char *rvalue) {
+
+ _cleanup_free_ char *p = NULL;
+
+ if (rvalue)
+ p = utf8_escape_invalid(rvalue);
+
+ log_syntax_internal(unit, level, config_file, config_line, 0, file, line, func,
+ "String is not UTF-8 clean, ignoring assignment: %s", strna(p));
+
+ return -EINVAL;
+}
+
#if 0 /// UNNEEDED by elogind
+void log_set_upgrade_syslog_to_journal(bool b) {
+ upgrade_syslog_to_journal = b;
+
+ /* Make the change effective immediately */
+ if (b) {
+ if (log_target == LOG_TARGET_SYSLOG)
+ log_target = LOG_TARGET_JOURNAL;
+ else if (log_target == LOG_TARGET_SYSLOG_OR_KMSG)
+ log_target = LOG_TARGET_JOURNAL_OR_KMSG;
+ }
+}
+
void log_set_always_reopen_console(bool b) {
always_reopen_console = b;
}
#endif // 0
+
+void log_set_open_when_needed(bool b) {
+ open_when_needed = b;
+}
+
+void log_set_prohibit_ipc(bool b) {
+ prohibit_ipc = b;
+}
+
+int log_emergency_level(void) {
+ /* Returns the log level to use for log_emergency() logging. We use LOG_EMERG only when we are PID 1, as only
+ * then the system of the whole system is obviously affected. */
+
+ return getpid_cached() == 1 ? LOG_EMERG : LOG_ERR;
+}
+
+int log_dup_console(void) {
+ int copy;
+
+ /* Duplicate the fd we use for fd logging if it's < 3 and use the copy from now on. This call is useful
+ * whenever we want to continue logging through the original fd, but want to rearrange stderr. */
+
+ if (console_fd >= 3)
+ return 0;
+
+ copy = fcntl(console_fd, F_DUPFD_CLOEXEC, 3);
+ if (copy < 0)
+ return -errno;
+
+ console_fd = copy;
+ return 0;
+}
diff --git a/src/basic/log.h b/src/basic/log.h
index 9c796e9f1..e4caece30 100644
--- a/src/basic/log.h
+++ b/src/basic/log.h
@@ -1,36 +1,17 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 <errno.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdlib.h>
-#include <sys/signalfd.h>
-#include <sys/socket.h>
#include <syslog.h>
-#include "sd-id128.h"
-
#include "macro.h"
+/* Some structures we reference but don't want to pull in headers for */
+struct iovec;
+struct signalfd_siginfo;
+
typedef enum LogRealm {
LOG_REALM_SYSTEMD,
LOG_REALM_UDEV,
@@ -50,7 +31,6 @@ typedef enum LogTarget{
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
@@ -97,11 +77,6 @@ void log_close(void);
void log_forget_fds(void);
#endif // 0
-void log_close_syslog(void);
-void log_close_journal(void);
-void log_close_kmsg(void);
-void log_close_console(void);
-
void log_parse_environment_realm(LogRealm realm);
#define log_parse_environment() \
log_parse_environment_realm(LOG_REALM)
@@ -152,19 +127,6 @@ int log_object_internal(
const char *extra,
const char *format, ...) _printf_(10,11);
-int log_object_internalv(
- int level,
- int error,
- const char *file,
- int line,
- const char *func,
- const char *object_field,
- const char *object,
- const char *extra_field,
- const char *extra,
- const char *format,
- va_list ap) _printf_(10,0);
-
int log_struct_internal(
int level,
int error,
@@ -181,13 +143,22 @@ int log_oom_internal(
int log_format_iovec(
struct iovec *iovec,
- unsigned iovec_len,
- unsigned *n,
+ size_t iovec_len,
+ size_t *n,
bool newline_separator,
int error,
const char *format,
va_list ap) _printf_(6, 0);
+int log_struct_iovec_internal(
+ int level,
+ int error,
+ const char *file,
+ int line,
+ const char *func,
+ const struct iovec *input_iovec,
+ size_t n_input_iovec);
+
/* This modifies the buffer passed! */
int log_dump_internal(
int level,
@@ -198,7 +169,7 @@ int log_dump_internal(
char *buffer);
/* Logging for various assertions */
-noreturn void log_assert_failed_realm(
+_noreturn_ void log_assert_failed_realm(
LogRealm realm,
const char *text,
const char *file,
@@ -207,7 +178,7 @@ noreturn void log_assert_failed_realm(
#define log_assert_failed(text, ...) \
log_assert_failed_realm(LOG_REALM, (text), __VA_ARGS__)
-noreturn void log_assert_failed_unreachable_realm(
+_noreturn_ void log_assert_failed_unreachable_realm(
LogRealm realm,
const char *text,
const char *file,
@@ -231,9 +202,9 @@ void log_assert_failed_return_realm(
/* Logging with level */
#define log_full_errno_realm(realm, level, error, ...) \
({ \
- int _level = (level), _e = (error); \
- (log_get_max_level_realm((realm)) >= LOG_PRI(_level)) \
- ? log_internal_realm(LOG_REALM_PLUS_LEVEL((realm), _level), _e, \
+ int _level = (level), _e = (error), _realm = (realm); \
+ (log_get_max_level_realm(_realm) >= LOG_PRI(_level)) \
+ ? log_internal_realm(LOG_REALM_PLUS_LEVEL(_realm, _level), _e, \
__FILE__, __LINE__, __func__, __VA_ARGS__) \
: -abs(_e); \
})
@@ -243,13 +214,15 @@ void log_assert_failed_return_realm(
#define log_full(level, ...) log_full_errno((level), 0, __VA_ARGS__)
+int log_emergency_level(void);
+
/* Normal logging */
#define log_debug(...) log_full(LOG_DEBUG, __VA_ARGS__)
#define log_info(...) log_full(LOG_INFO, __VA_ARGS__)
#define log_notice(...) log_full(LOG_NOTICE, __VA_ARGS__)
#define log_warning(...) log_full(LOG_WARNING, __VA_ARGS__)
#define log_error(...) log_full(LOG_ERR, __VA_ARGS__)
-#define log_emergency(...) log_full(getpid() == 1 ? LOG_EMERG : LOG_ERR, __VA_ARGS__)
+#define log_emergency(...) log_full(log_emergency_level(), __VA_ARGS__)
/* Logging triggered by an errno-like error */
#define log_debug_errno(error, ...) log_full_errno(LOG_DEBUG, error, __VA_ARGS__)
@@ -257,7 +230,7 @@ void log_assert_failed_return_realm(
#define log_notice_errno(error, ...) log_full_errno(LOG_NOTICE, error, __VA_ARGS__)
#define log_warning_errno(error, ...) log_full_errno(LOG_WARNING, error, __VA_ARGS__)
#define log_error_errno(error, ...) log_full_errno(LOG_ERR, error, __VA_ARGS__)
-#define log_emergency_errno(error, ...) log_full_errno(getpid() == 1 ? LOG_EMERG : LOG_ERR, error, __VA_ARGS__)
+#define log_emergency_errno(error, ...) log_full_errno(log_emergency_level(), error, __VA_ARGS__)
#ifdef LOG_TRACE
# define log_trace(...) log_debug(__VA_ARGS__)
@@ -265,7 +238,7 @@ void log_assert_failed_return_realm(
# define log_trace(...) do {} while (0)
#endif
-#ifdef ENABLE_DEBUG_ELOGIND
+#if ENABLE_DEBUG_ELOGIND
# define log_debug_elogind(...) log_debug(__VA_ARGS__);usleep(25*USEC_PER_MSEC)
#else
# define log_debug_elogind(...) do {} while (0)
@@ -273,9 +246,14 @@ void log_assert_failed_return_realm(
/* Structured logging */
#define log_struct_errno(level, error, ...) \
log_struct_internal(LOG_REALM_PLUS_LEVEL(LOG_REALM, level), \
- error, __FILE__, __LINE__, __func__, __VA_ARGS__)
+ error, __FILE__, __LINE__, __func__, __VA_ARGS__, NULL)
#define log_struct(level, ...) log_struct_errno(level, 0, __VA_ARGS__)
+#define log_struct_iovec_errno(level, error, iovec, n_iovec) \
+ log_struct_iovec_internal(LOG_REALM_PLUS_LEVEL(LOG_REALM, level), \
+ error, __FILE__, __LINE__, __func__, iovec, n_iovec)
+#define log_struct_iovec(level, iovec, n_iovec) log_struct_iovec_errno(level, 0, iovec, n_iovec)
+
/* This modifies the buffer passed! */
#define log_dump(level, buffer) \
log_dump_internal(LOG_REALM_PLUS_LEVEL(LOG_REALM, level), \
@@ -294,10 +272,23 @@ LogTarget log_target_from_string(const char *s) _pure_;
#if 0 /// UNNEEDED by elogind
void log_received_signal(int level, const struct signalfd_siginfo *si);
+/* If turned on, any requests for a log target involving "syslog" will be implicitly upgraded to the equivalent journal target */
void log_set_upgrade_syslog_to_journal(bool b);
+
+/* If turned on, and log_open() is called, we'll not use STDERR_FILENO for logging ever, but rather open /dev/console */
void log_set_always_reopen_console(bool b);
#endif // 0
+/* If turned on, we'll open the log stream implicitly if needed on each individual log call. This is normally not
+ * desired as we want to reuse our logging streams. It is useful however */
+void log_set_open_when_needed(bool b);
+
+/* If turned on, then we'll never use IPC-based logging, i.e. never log to syslog or the journal. We'll only log to
+ * stderr, the console or kmsg */
+void log_set_prohibit_ipc(bool b);
+
+int log_dup_console(void);
+
int log_syntax_internal(
const char *unit,
int level,
@@ -309,6 +300,16 @@ int log_syntax_internal(
const char *func,
const char *format, ...) _printf_(9, 10);
+int log_syntax_invalid_utf8_internal(
+ const char *unit,
+ int level,
+ const char *config_file,
+ unsigned config_line,
+ const char *file,
+ int line,
+ const char *func,
+ const char *rvalue);
+
#define log_syntax(unit, level, config_file, config_line, error, ...) \
({ \
int _level = (level), _e = (error); \
@@ -320,10 +321,9 @@ int log_syntax_internal(
#define log_syntax_invalid_utf8(unit, level, config_file, config_line, rvalue) \
({ \
int _level = (level); \
- if (log_get_max_level() >= LOG_PRI(_level)) { \
- _cleanup_free_ char *_p = NULL; \
- _p = utf8_escape_invalid(rvalue); \
- log_syntax_internal(unit, _level, config_file, config_line, 0, __FILE__, __LINE__, __func__, \
- "String is not UTF-8 clean, ignoring assignment: %s", strna(_p)); \
- } \
+ (log_get_max_level() >= LOG_PRI(_level)) \
+ ? log_syntax_invalid_utf8_internal(unit, _level, config_file, config_line, __FILE__, __LINE__, __func__, rvalue) \
+ : -EINVAL; \
})
+
+#define DEBUG_LOGGING _unlikely_(log_get_max_level() >= LOG_DEBUG)
diff --git a/src/basic/login-util.c b/src/basic/login-util.c
index 339e94f12..085ccd091 100644
--- a/src/basic/login-util.c
+++ b/src/basic/login-util.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <string.h>
diff --git a/src/basic/login-util.h b/src/basic/login-util.h
index a71ebd4ef..f8ff779c9 100644
--- a/src/basic/login-util.h
+++ b/src/basic/login-util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <unistd.h>
diff --git a/src/basic/macro.h b/src/basic/macro.h
index a51562db3..d1365f705 100644
--- a/src/basic/macro.h
+++ b/src/basic/macro.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 <stdbool.h>
#include <sys/param.h>
@@ -47,6 +29,31 @@
#define _weakref_(x) __attribute__((weakref(#x)))
#define _alignas_(x) __attribute__((aligned(__alignof(x))))
#define _cleanup_(x) __attribute__((cleanup(x)))
+#if __GNUC__ >= 7
+#define _fallthrough_ __attribute__((fallthrough))
+#else
+#define _fallthrough_
+#endif
+/* Define C11 noreturn without <stdnoreturn.h> and even on older gcc
+ * compiler versions */
+#ifndef _noreturn_
+#if __STDC_VERSION__ >= 201112L
+#define _noreturn_ _Noreturn
+#else
+#define _noreturn_ __attribute__((noreturn))
+#endif
+#endif
+
+#if !defined(HAS_FEATURE_MEMORY_SANITIZER)
+# if defined(__has_feature)
+# if __has_feature(memory_sanitizer)
+# define HAS_FEATURE_MEMORY_SANITIZER 1
+# endif
+# endif
+# if !defined(HAS_FEATURE_MEMORY_SANITIZER)
+# define HAS_FEATURE_MEMORY_SANITIZER 0
+# endif
+#endif
/* Temporarily disable some warnings */
#define DISABLE_WARNING_DECLARATION_AFTER_STATEMENT \
@@ -133,11 +140,25 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
return 1UL << (sizeof(u) * 8 - __builtin_clzl(u - 1UL));
}
+#ifndef __COVERITY__
+# define VOID_0 ((void)0)
+#else
+# define VOID_0 ((void*)0)
+#endif
+
#define ELEMENTSOF(x) \
__extension__ (__builtin_choose_expr( \
!__builtin_types_compatible_p(typeof(x), typeof(&*(x))), \
sizeof(x)/sizeof((x)[0]), \
- (void)0))
+ VOID_0))
+
+/*
+ * STRLEN - return the length of a string literal, minus the trailing NUL byte.
+ * Contrary to strlen(), this is a constant expression.
+ * @x: a string literal.
+ */
+#define STRLEN(x) (sizeof(""x"") - 1)
+
/*
* container_of - cast a member of a structure out to the containing structure
* @ptr: the pointer to the member.
@@ -167,7 +188,7 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
__builtin_constant_p(_B) && \
__builtin_types_compatible_p(typeof(_A), typeof(_B)), \
((_A) > (_B)) ? (_A) : (_B), \
- (void)0))
+ VOID_0))
/* takes two types and returns the size of the larger one */
#define MAXSIZE(A, B) (sizeof(union _packed_ { typeof(A) a; typeof(B) b; }))
@@ -323,13 +344,15 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
({ \
typeof(x) _x_ = (x); \
unsigned ans = 1; \
- while (_x_ /= 10) \
+ while ((_x_ /= 10) != 0) \
ans++; \
ans; \
})
#define SET_FLAG(v, flag, b) \
(v) = (b) ? ((v) | (flag)) : ((v) & ~(flag))
+#define FLAGS_SET(v, flags) \
+ (((v) & (flags)) == (flags))
#define CASE_F(X) case X:
#define CASE_F_1(CASE, X) CASE_F(X)
@@ -394,21 +417,10 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
#endif
#endif
-/* Define C11 noreturn without <stdnoreturn.h> and even on older gcc
- * compiler versions */
-#ifndef noreturn
-#if __STDC_VERSION__ >= 201112L
-#define noreturn _Noreturn
-#else
-#define noreturn __attribute__((noreturn))
-#endif
-#endif
-
#define DEFINE_TRIVIAL_CLEANUP_FUNC(type, func) \
static inline void func##p(type *p) { \
if (*p) \
func(*p); \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
+ }
#include "log.h"
diff --git a/src/basic/memfd-util.c b/src/basic/memfd-util.c
index 2ecec8c90..49481e6a5 100644
--- a/src/basic/memfd-util.c
+++ b/src/basic/memfd-util.c
@@ -1,27 +1,10 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
-#ifdef HAVE_LINUX_MEMFD_H
+#if HAVE_LINUX_MEMFD_H
#include <linux/memfd.h>
#endif
#include <stdio.h>
@@ -172,9 +155,6 @@ int memfd_new_and_map(const char *name, size_t sz, void **p) {
if (r < 0)
return r;
- r = fd;
- fd = -1;
-
- return r;
+ return TAKE_FD(fd);
}
#endif // 0
diff --git a/src/basic/memfd-util.h b/src/basic/memfd-util.h
index 781d1a431..7482dfcc0 100644
--- a/src/basic/memfd-util.h
+++ b/src/basic/memfd-util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 <stddef.h>
#include <stdint.h>
diff --git a/src/basic/mempool.c b/src/basic/mempool.c
index f95e2beb0..a5ec8a102 100644
--- a/src/basic/mempool.c
+++ b/src/basic/mempool.c
@@ -1,22 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2010-2014 Lennart Poettering
- Copyright 2014 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <stdint.h>
#include <stdlib.h>
@@ -27,12 +9,12 @@
struct pool {
struct pool *next;
- unsigned n_tiles;
- unsigned n_used;
+ size_t n_tiles;
+ size_t n_used;
};
void* mempool_alloc_tile(struct mempool *mp) {
- unsigned i;
+ size_t i;
/* When a tile is released we add it to the list and simply
* place the next pointer at its offset 0. */
@@ -50,8 +32,7 @@ void* mempool_alloc_tile(struct mempool *mp) {
if (_unlikely_(!mp->first_pool) ||
_unlikely_(mp->first_pool->n_used >= mp->first_pool->n_tiles)) {
- unsigned n;
- size_t size;
+ size_t size, n;
struct pool *p;
n = mp->first_pool ? mp->first_pool->n_tiles : 0;
@@ -89,7 +70,7 @@ void mempool_free_tile(struct mempool *mp, void *p) {
mp->freelist = p;
}
-#ifdef VALGRIND
+#if VALGRIND
void mempool_drop(struct mempool *mp) {
struct pool *p = mp->first_pool;
diff --git a/src/basic/mempool.h b/src/basic/mempool.h
index 0618b8dd2..2a41cb358 100644
--- a/src/basic/mempool.h
+++ b/src/basic/mempool.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2011-2014 Lennart Poettering
- Copyright 2014 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 <stddef.h>
@@ -41,7 +23,6 @@ static struct mempool pool_name = { \
.at_least = alloc_at_least, \
}
-
-#ifdef VALGRIND
+#if VALGRIND
void mempool_drop(struct mempool *mp);
#endif
diff --git a/src/basic/meson.build b/src/basic/meson.build
new file mode 100644
index 000000000..c199e78c8
--- /dev/null
+++ b/src/basic/meson.build
@@ -0,0 +1,494 @@
+# SPDX-License-Identifier: LGPL-2.1+
+
+#if 0 /// elogind has a shorter list
+# basic_sources = files('''
+# MurmurHash2.c
+# MurmurHash2.h
+# af-list.c
+# af-list.h
+# alloc-util.c
+# alloc-util.h
+# architecture.c
+# architecture.h
+# arphrd-list.c
+# arphrd-list.h
+# async.c
+# async.h
+# audit-util.c
+# audit-util.h
+# barrier.c
+# barrier.h
+# bitmap.c
+# bitmap.h
+# blkid-util.h
+# blockdev-util.c
+# blockdev-util.h
+# bpf-program.c
+# bpf-program.h
+# btrfs-ctree.h
+# btrfs-util.c
+# btrfs-util.h
+# build.h
+# bus-label.c
+# bus-label.h
+# calendarspec.c
+# calendarspec.h
+# cap-list.c
+# cap-list.h
+# capability-util.c
+# capability-util.h
+# cgroup-util.c
+# cgroup-util.h
+# chattr-util.c
+# chattr-util.h
+# clock-util.c
+# clock-util.h
+# conf-files.c
+# conf-files.h
+# copy.c
+# copy.h
+# cpu-set-util.c
+# cpu-set-util.h
+# crypt-util.c
+# crypt-util.h
+# def.h
+# device-nodes.c
+# device-nodes.h
+# dirent-util.c
+# dirent-util.h
+# env-util.c
+# env-util.h
+# errno-list.c
+# errno-list.h
+# escape.c
+# escape.h
+# ether-addr-util.c
+# ether-addr-util.h
+# exec-util.c
+# exec-util.h
+# exit-status.c
+# exit-status.h
+# extract-word.c
+# extract-word.h
+# fd-util.c
+# fd-util.h
+# fileio-label.c
+# fileio-label.h
+# fileio.c
+# fileio.h
+# format-table.c
+# format-table.h
+# format-util.h
+# fs-util.c
+# fs-util.h
+# glob-util.c
+# glob-util.h
+# gunicode.c
+# gunicode.h
+# hash-funcs.c
+# hash-funcs.h
+# hashmap.c
+# hashmap.h
+# hexdecoct.c
+# hexdecoct.h
+# hostname-util.c
+# hostname-util.h
+# in-addr-util.c
+# in-addr-util.h
+# io-util.c
+# io-util.h
+# ioprio.h
+# journal-importer.c
+# journal-importer.h
+# khash.c
+# khash.h
+# label.c
+# label.h
+# list.h
+# locale-util.c
+# locale-util.h
+# lockfile-util.c
+# lockfile-util.h
+# log.c
+# log.h
+# login-util.c
+# login-util.h
+# macro.h
+# memfd-util.c
+# memfd-util.h
+# mempool.c
+# mempool.h
+# missing_syscall.h
+# mkdir-label.c
+# mkdir.c
+# mkdir.h
+# module-util.h
+# mount-util.c
+# mount-util.h
+# nss-util.h
+# ordered-set.c
+# ordered-set.h
+# pager.c
+# pager.h
+# os-util.c
+# os-util.h
+# parse-util.c
+# parse-util.h
+# path-util.c
+# path-util.h
+# prioq.c
+# prioq.h
+# proc-cmdline.c
+# proc-cmdline.h
+# process-util.c
+# process-util.h
+# procfs-util.c
+# procfs-util.h
+# random-util.c
+# random-util.h
+# ratelimit.c
+# ratelimit.h
+# raw-clone.h
+# raw-reboot.h
+# reboot-util.c
+# reboot-util.h
+# refcnt.h
+# replace-var.c
+# replace-var.h
+# rlimit-util.c
+# rlimit-util.h
+# rm-rf.c
+# rm-rf.h
+# securebits-util.c
+# securebits-util.h
+# securebits.h
+# selinux-util.c
+# selinux-util.h
+# set.h
+# sigbus.c
+# sigbus.h
+# signal-util.c
+# signal-util.h
+# siphash24.c
+# siphash24.h
+# smack-util.c
+# smack-util.h
+# socket-label.c
+# socket-protocol-list.c
+# socket-protocol-list.h
+# socket-util.c
+# socket-util.h
+# sparse-endian.h
+# special.h
+# stat-util.c
+# stat-util.h
+# stdio-util.h
+# strbuf.c
+# strbuf.h
+# string-table.c
+# string-table.h
+# string-util.c
+# string-util.h
+# strv.c
+# strv.h
+# strxcpyx.c
+# strxcpyx.h
+# syslog-util.c
+# syslog-util.h
+# terminal-util.c
+# terminal-util.h
+# time-util.c
+# time-util.h
+# umask-util.h
+# unaligned.h
+# unit-def.c
+# unit-def.h
+# unit-name.c
+# unit-name.h
+# user-util.c
+# user-util.h
+# utf8.c
+# utf8.h
+# util.c
+# util.h
+# verbs.c
+# verbs.h
+# virt.c
+# virt.h
+# web-util.c
+# web-util.h
+# xattr-util.c
+# xattr-util.h
+# xml.c
+# xml.h
+# '''.split())
+#else
+basic_sources = files('''
+ alloc-util.c
+ alloc-util.h
+ audit-util.c
+ audit-util.h
+ build.h
+ bus-label.c
+ bus-label.h
+ capability-util.c
+ capability-util.h
+ cgroup-util.c
+ cap-list.c
+ cap-list.h
+ cgroup-util.h
+ conf-files.c
+ conf-files.h
+ copy.c
+ copy.h
+ def.h
+ dirent-util.c
+ dirent-util.h
+ env-util.c
+ env-util.h
+ errno-list.c
+ errno-list.h
+ escape.c
+ escape.h
+ exec-util.c
+ exec-util.h
+ extract-word.c
+ extract-word.h
+ fd-util.c
+ fd-util.h
+ fileio.c
+ fileio.h
+ fileio-label.c
+ fileio-label.h
+ format-table.c
+ format-table.h
+ format-util.h
+ fs-util.c
+ fs-util.h
+ gunicode.c
+ gunicode.h
+ hash-funcs.c
+ hash-funcs.h
+ hashmap.c
+ hashmap.h
+ hexdecoct.c
+ hexdecoct.h
+ hostname-util.c
+ hostname-util.h
+ io-util.c
+ io-util.h
+ khash.c
+ khash.h
+ label.c
+ label.h
+ list.h
+ locale-util.c
+ locale-util.h
+ log.c
+ log.h
+ login-util.c
+ login-util.h
+ macro.h
+ memfd-util.c
+ memfd-util.h
+ mempool.c
+ mempool.h
+ missing_syscall.h
+ mkdir.c
+ mkdir.h
+ mkdir-label.c
+ mount-util.c
+ mount-util.h
+ pager.c
+ pager.h
+ parse-printf-format.c
+ parse-printf-format.h
+ parse-util.c
+ parse-util.h
+ path-util.c
+ path-util.h
+ prioq.c
+ prioq.h
+ proc-cmdline.c
+ proc-cmdline.h
+ procfs-util.c
+ procfs-util.h
+ process-util.c
+ process-util.h
+ random-util.c
+ random-util.h
+ refcnt.h
+ rm-rf.c
+ rm-rf.h
+ selinux-util.c
+ selinux-util.h
+ set.h
+ sigbus.c
+ sigbus.h
+ signal-util.c
+ signal-util.h
+ siphash24.c
+ siphash24.h
+ smack-util.c
+ smack-util.h
+ socket-util.c
+ socket-util.h
+ sparse-endian.h
+ special.h
+ stat-util.c
+ stat-util.h
+ stdio-util.h
+ string-table.c
+ string-table.h
+ string-util.c
+ string-util.h
+ strv.c
+ strv.h
+ syslog-util.c
+ syslog-util.h
+ terminal-util.c
+ terminal-util.h
+ time-util.c
+ time-util.h
+ umask-util.h
+ unaligned.h
+ unit-def.c
+ unit-def.h
+ unit-name.c
+ unit-name.h
+ user-util.c
+ user-util.h
+ utf8.c
+ utf8.h
+ util.c
+ util.h
+ verbs.c
+ verbs.h
+ virt.c
+ virt.h
+ xattr-util.c
+ xattr-util.h
+'''.split())
+#endif // 0
+
+missing_h = files('missing.h')
+
+generate_gperfs = find_program('generate-gperfs.py')
+
+#if 0 /// elogind has only the cap and errno list.
+# generate_af_list = find_program('generate-af-list.sh')
+# af_list_txt = custom_target(
+# 'af-list.txt',
+# output : 'af-list.txt',
+# command : [generate_af_list, cpp],
+# capture : true)
+#
+# generate_arphrd_list = find_program('generate-arphrd-list.sh')
+# arphrd_list_txt = custom_target(
+# 'arphrd-list.txt',
+# output : 'arphrd-list.txt',
+# command : [generate_arphrd_list, cpp],
+# capture : true)
+#endif // 0
+
+generate_cap_list = find_program('generate-cap-list.sh')
+cap_list_txt = custom_target(
+ 'cap-list.txt',
+ output : 'cap-list.txt',
+#if 0 /// elogind needs musl_missing.h, so generate_cap_list must know the source root
+# command : [generate_cap_list, cpp, config_h, missing_h],
+#else
+ command : [generate_cap_list, cpp, meson.source_root(), config_h, missing_h],
+#endif // 0
+ capture : true)
+
+generate_errno_list = find_program('generate-errno-list.sh')
+errno_list_txt = custom_target(
+ 'errno-list.txt',
+ output : 'errno-list.txt',
+ command : [generate_errno_list, cpp],
+ capture : true)
+
+generate_socket_protocol_list = find_program('generate-socket-protocol-list.sh')
+socket_protocol_list_txt = custom_target(
+ 'socket-protocol-list.txt',
+ output : 'socket-protocol-list.txt',
+ command : [generate_socket_protocol_list, cpp],
+ capture : true)
+
+generated_gperf_headers = []
+#if 0 /// elogind has only the cap and errno list.
+# foreach item : [['af', af_list_txt, 'af', ''],
+# ['arphrd', arphrd_list_txt, 'arphrd', 'ARPHRD_'],
+# ['cap', cap_list_txt, 'capability', ''],
+# ['errno', errno_list_txt, 'errno', ''],
+# ['socket-protocol', socket_protocol_list_txt, 'socket_protocol', 'IPPROTO_']]
+#else
+foreach item : [['cap', cap_list_txt, 'capability', ''],
+ ['errno', errno_list_txt, 'errno', '']]
+#endif // 0
+
+ fname = '@0@-from-name.gperf'.format(item[0])
+ gperf_file = custom_target(
+ fname,
+ input : item[1],
+ output : fname,
+ command : [generate_gperfs, item[2], item[3], '@INPUT@'],
+ capture : true)
+
+ fname = '@0@-from-name.h'.format(item[0])
+ target1 = custom_target(
+ fname,
+ input : gperf_file,
+ output : fname,
+ command : [gperf,
+ '-L', 'ANSI-C', '-t', '--ignore-case',
+ '-N', 'lookup_@0@'.format(item[2]),
+ '-H', 'hash_@0@_name'.format(item[2]),
+ '-p', '-C',
+ '@INPUT@'],
+ capture : true)
+
+ fname = '@0@-to-name.h'.format(item[0])
+ awkscript = '@0@-to-name.awk'.format(item[0])
+ target2 = custom_target(
+ fname,
+ input : [awkscript, item[1]],
+ output : fname,
+ command : [awk, '-f', '@INPUT0@', '@INPUT1@'],
+ capture : true)
+
+ generated_gperf_headers += [target1, target2]
+endforeach
+
+basic_sources += [missing_h] + generated_gperf_headers
+#if 0 /// elogind does not need gcrypt
+# basic_gcrypt_sources = files(
+# 'gcrypt-util.c',
+# 'gcrypt-util.h')
+#endif // 0
+
+libbasic = static_library(
+ 'basic',
+ basic_sources,
+ include_directories : includes,
+ dependencies : [threads,
+ libcap,
+#if 0 /// Neither blkid nor libmount in elogind
+# libblkid,
+# libmount,
+#endif // 0
+ libselinux],
+ c_args : ['-fvisibility=default'],
+ install : false)
+
+#if 0 /// elogind does not need gcrypt
+# # A convenience library that is separate from libbasic to avoid
+# # unnecessary linking to libgcrypt.
+# libbasic_gcrypt = static_library(
+# 'basic-gcrypt',
+# basic_gcrypt_sources,
+# include_directories : includes,
+# dependencies : [libgcrypt],
+# c_args : ['-fvisibility=default'])
+#endif // 0
diff --git a/src/basic/missing.h b/src/basic/missing.h
index c62c2db1c..fb1478548 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 <errno.h>
@@ -26,16 +8,19 @@
#include <inttypes.h>
#include <linux/audit.h>
#include <linux/capability.h>
+//#include <linux/falloc.h>
#include <linux/if_link.h>
#include <linux/input.h>
#include <linux/loop.h>
#include <linux/neighbour.h>
#include <linux/oom.h>
#include <linux/rtnetlink.h>
+//#include <linux/stat.h>
#include <net/ethernet.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <sys/socket.h>
+//#include <sys/stat.h>
#include <sys/syscall.h>
#include <uchar.h>
#include <unistd.h>
@@ -43,7 +28,7 @@
/// Additional includes needed by elogind
#include "musl_missing.h"
-#ifdef HAVE_AUDIT
+#if HAVE_AUDIT
#include <libaudit.h>
#endif
@@ -51,11 +36,11 @@
#include <asm/sgidefs.h>
#endif
-#ifdef HAVE_LINUX_BTRFS_H
+#if HAVE_LINUX_BTRFS_H
#include <linux/btrfs.h>
#endif
-#ifdef HAVE_LINUX_VM_SOCKETS_H
+#if HAVE_LINUX_VM_SOCKETS_H
#include <linux/vm_sockets.h>
#else
#define VMADDR_CID_ANY -1U
@@ -208,7 +193,33 @@ struct sockaddr_vm {
#endif
#if 0 /// UNNEEDED by elogind (It can not support BTRFS at all)
-#ifndef HAVE_LINUX_BTRFS_H
+#if ! HAVE_LINUX_BTRFS_H
+#define BTRFS_IOC_QGROUP_ASSIGN _IOW(BTRFS_IOCTL_MAGIC, 41, \
+ struct btrfs_ioctl_qgroup_assign_args)
+#define BTRFS_IOC_QGROUP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 42, \
+ struct btrfs_ioctl_qgroup_create_args)
+#define BTRFS_IOC_QUOTA_RESCAN _IOW(BTRFS_IOCTL_MAGIC, 44, \
+ struct btrfs_ioctl_quota_rescan_args)
+#define BTRFS_IOC_QUOTA_RESCAN_STATUS _IOR(BTRFS_IOCTL_MAGIC, 45, \
+ struct btrfs_ioctl_quota_rescan_args)
+
+struct btrfs_ioctl_quota_rescan_args {
+ __u64 flags;
+ __u64 progress;
+ __u64 reserved[6];
+};
+
+struct btrfs_ioctl_qgroup_assign_args {
+ __u64 assign;
+ __u64 src;
+ __u64 dst;
+};
+
+struct btrfs_ioctl_qgroup_create_args {
+ __u64 create;
+ __u64 qgroupid;
+};
+
struct btrfs_ioctl_vol_args {
int64_t fd;
char name[BTRFS_PATH_NAME_MAX + 1];
@@ -316,7 +327,6 @@ struct btrfs_ioctl_search_header {
__u32 len;
};
-
struct btrfs_ioctl_search_args {
struct btrfs_ioctl_search_key key;
char buf[BTRFS_SEARCH_ARGS_BUFSIZE];
@@ -495,6 +505,10 @@ struct btrfs_ioctl_quota_ctl_args {
#define BPF_FS_MAGIC 0xcafe4a11
#endif
+#ifndef OCFS2_SUPER_MAGIC
+#define OCFS2_SUPER_MAGIC 0x7461636f
+#endif
+
#ifndef MS_MOVE
#define MS_MOVE 8192
#endif
@@ -547,12 +561,40 @@ struct btrfs_ioctl_quota_ctl_args {
#define PR_SET_CHILD_SUBREAPER 36
#endif
+#ifndef PR_SET_MM_ARG_START
+#define PR_SET_MM_ARG_START 8
+#endif
+
+#ifndef PR_SET_MM_ARG_END
+#define PR_SET_MM_ARG_END 9
+#endif
+
+#ifndef PR_SET_MM_ENV_START
+#define PR_SET_MM_ENV_START 10
+#endif
+
+#ifndef PR_SET_MM_ENV_END
+#define PR_SET_MM_ENV_END 11
+#endif
+
+#ifndef EFIVARFS_MAGIC
+#define EFIVARFS_MAGIC 0xde5e81e4
+#endif
+
+#ifndef SMACK_MAGIC
+#define SMACK_MAGIC 0x43415d53
+#endif
+
+#ifndef DM_DEFERRED_REMOVE
+#define DM_DEFERRED_REMOVE (1 << 17)
+#endif
+
#ifndef MAX_HANDLE_SZ
#define MAX_HANDLE_SZ 128
#endif
-#ifndef HAVE_SECURE_GETENV
-# ifdef HAVE___SECURE_GETENV
+#if ! HAVE_SECURE_GETENV
+# if HAVE___SECURE_GETENV
# define secure_getenv __secure_getenv
# else
# error "neither secure_getenv nor __secure_getenv are available"
@@ -571,6 +613,10 @@ struct btrfs_ioctl_quota_ctl_args {
# define SO_REUSEPORT 15
#endif
+#ifndef SO_PEERGROUPS
+# define SO_PEERGROUPS 59
+#endif
+
#ifndef EVIOCREVOKE
# define EVIOCREVOKE _IOW('E', 0x91, int)
#endif
@@ -611,15 +657,14 @@ struct input_mask {
#else
#define __O_TMPFILE 020000000
#endif
+#endif
/* a horrid kludge trying to make sure that this will fail on old kernels */
#ifndef O_TMPFILE
#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
#endif
-#endif
-
-#if !HAVE_DECL_LO_FLAGS_PARTSCAN
+#if !HAVE_LO_FLAGS_PARTSCAN
#define LO_FLAGS_PARTSCAN 8
#endif
@@ -631,7 +676,7 @@ struct input_mask {
#define LOOP_CTL_GET_FREE 0x4C82
#endif
-#if !HAVE_DECL_IFLA_INET6_ADDR_GEN_MODE
+#if !HAVE_IFLA_INET6_ADDR_GEN_MODE
#define IFLA_INET6_UNSPEC 0
#define IFLA_INET6_FLAGS 1
#define IFLA_INET6_CONF 2
@@ -649,11 +694,11 @@ struct input_mask {
#define IN6_ADDR_GEN_MODE_NONE 1
#endif
-#if !HAVE_DECL_IN6_ADDR_GEN_MODE_STABLE_PRIVACY
+#if !HAVE_IN6_ADDR_GEN_MODE_STABLE_PRIVACY
#define IN6_ADDR_GEN_MODE_STABLE_PRIVACY 2
#endif
-#if !HAVE_DECL_IFLA_MACVLAN_FLAGS
+#if !HAVE_IFLA_MACVLAN_FLAGS
#define IFLA_MACVLAN_UNSPEC 0
#define IFLA_MACVLAN_MODE 1
#define IFLA_MACVLAN_FLAGS 2
@@ -662,19 +707,29 @@ struct input_mask {
#define IFLA_MACVLAN_MAX (__IFLA_MACVLAN_MAX - 1)
#endif
-#if !HAVE_DECL_IFLA_IPVLAN_MODE
+#if !HAVE_IFLA_IPVLAN_FLAGS
#define IFLA_IPVLAN_UNSPEC 0
#define IFLA_IPVLAN_MODE 1
-#define __IFLA_IPVLAN_MAX 2
+#define IFLA_IPVLAN_FLAGS 2
+#define __IFLA_IPVLAN_MAX 3
#define IFLA_IPVLAN_MAX (__IFLA_IPVLAN_MAX - 1)
#define IPVLAN_MODE_L2 0
#define IPVLAN_MODE_L3 1
+#define IPVLAN_MODE_L3S 2
#define IPVLAN_MAX 2
#endif
-#if !HAVE_DECL_IFLA_VTI_REMOTE
+#if !HAVE_IPVLAN_F_PRIVATE
+#define IPVLAN_F_PRIVATE 0x01
+#define IPVLAN_F_VEPA 0x02
+#define __IPVLAN_F_PRIVATE_MAX 3
+
+#define HAVE_IPVLAN_F_PRIVATE_MAX (__HAVE_IPVLAN_F_PRIVATE_MAX - 1)
+#endif
+
+#if !HAVE_IFLA_VTI_REMOTE
#define IFLA_VTI_UNSPEC 0
#define IFLA_VTI_LINK 1
#define IFLA_VTI_IKEY 2
@@ -686,7 +741,7 @@ struct input_mask {
#define IFLA_VTI_MAX (__IFLA_VTI_MAX - 1)
#endif
-#if !HAVE_DECL_IFLA_PHYS_PORT_ID
+#if !HAVE_IFLA_PHYS_PORT_ID
#define IFLA_EXT_MASK 29
#undef IFLA_PROMISCUITY
#define IFLA_PROMISCUITY 30
@@ -699,7 +754,7 @@ struct input_mask {
#define IFLA_MAX (__IFLA_MAX - 1)
#endif
-#if !HAVE_DECL_IFLA_BOND_AD_INFO
+#if !HAVE_IFLA_BOND_AD_INFO
#define IFLA_BOND_UNSPEC 0
#define IFLA_BOND_MODE 1
#define IFLA_BOND_ACTIVE_SLAVE 2
@@ -729,7 +784,7 @@ struct input_mask {
#define IFLA_BOND_MAX (__IFLA_BOND_MAX - 1)
#endif
-#if !HAVE_DECL_IFLA_VLAN_PROTOCOL
+#if !HAVE_IFLA_VLAN_PROTOCOL
#define IFLA_VLAN_UNSPEC 0
#define IFLA_VLAN_ID 1
#define IFLA_VLAN_FLAGS 2
@@ -741,7 +796,7 @@ struct input_mask {
#define IFLA_VLAN_MAX (__IFLA_VLAN_MAX - 1)
#endif
-#if !HAVE_DECL_IFLA_VXLAN_GPE
+#if !HAVE_IFLA_VXLAN_GPE
#define IFLA_VXLAN_UNSPEC 0
#define IFLA_VXLAN_ID 1
#define IFLA_VXLAN_GROUP 2
@@ -776,7 +831,7 @@ struct input_mask {
#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
#endif
-#if !HAVE_DECL_IFLA_GENEVE_LABEL
+#if !HAVE_IFLA_GENEVE_LABEL
#define IFLA_GENEVE_UNSPEC 0
#define IFLA_GENEVE_ID 1
#define IFLA_GENEVE_REMOTE 2
@@ -795,7 +850,7 @@ struct input_mask {
#define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1)
#endif
-#if !HAVE_DECL_IFLA_IPTUN_ENCAP_DPORT
+#if !HAVE_IFLA_IPTUN_ENCAP_DPORT
#define IFLA_IPTUN_UNSPEC 0
#define IFLA_IPTUN_LINK 1
#define IFLA_IPTUN_LOCAL 2
@@ -821,7 +876,7 @@ struct input_mask {
#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1)
#endif
-#if !HAVE_DECL_IFLA_GRE_ENCAP_DPORT
+#if !HAVE_IFLA_GRE_ENCAP_DPORT
#define IFLA_GRE_UNSPEC 0
#define IFLA_GRE_LINK 1
#define IFLA_GRE_IFLAGS 2
@@ -846,7 +901,7 @@ struct input_mask {
#define IFLA_GRE_MAX (__IFLA_GRE_MAX - 1)
#endif
-#if !HAVE_DECL_IFLA_BRIDGE_VLAN_INFO
+#if !HAVE_IFLA_BRIDGE_VLAN_INFO
#define IFLA_BRIDGE_FLAGS 0
#define IFLA_BRIDGE_MODE 1
#define IFLA_BRIDGE_VLAN_INFO 2
@@ -863,7 +918,7 @@ struct input_mask {
#define BRIDGE_VLAN_INFO_RANGE_END (1<<4) /* VLAN is end of vlan range */
#endif
-#if !HAVE_DECL_IFLA_BR_VLAN_DEFAULT_PVID
+#if !HAVE_IFLA_BR_VLAN_DEFAULT_PVID
#define IFLA_BR_UNSPEC 0
#define IFLA_BR_FORWARD_DELAY 1
#define IFLA_BR_HELLO_TIME 2
@@ -909,7 +964,7 @@ struct input_mask {
#define IFLA_BR_MAX (__IFLA_BR_MAX - 1)
#endif
-#if !HAVE_DECL_IFLA_BRPORT_LEARNING_SYNC
+#if !HAVE_IFLA_BRPORT_LEARNING_SYNC
#define IFLA_BRPORT_UNSPEC 0
#define IFLA_BRPORT_STATE 1
#define IFLA_BRPORT_PRIORITY 2
@@ -926,15 +981,46 @@ struct input_mask {
#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
#endif
-#if !HAVE_DECL_IFLA_BRPORT_PROXYARP
+#if !HAVE_FRA_UID_RANGE
+#define FRA_UNSPEC 0
+#define FRA_DST 1
+#define FRA_SRC 2
+#define FRA_IIFNAME 3
+#define FRA_GOTO 4
+#define FRA_UNUSED2 5
+#define FRA_PRIORITY 6
+#define FRA_UNUSED3 7
+#define FRA_UNUSED4 8
+#define FRA_UNUSED5 9
+#define FRA_FWMARK 10
+#define FRA_FLOW 11
+#define FRA_TUN_ID 12
+#define FRA_SUPPRESS_IFGROUP 13
+#define FRA_SUPPRESS_PREFIXLEN 14
+#define FRA_TABLE 15
+#define FRA_FWMASK 16
+#define FRA_OIFNAME 17
+#define FRA_PAD 18
+#define FRA_L3MDEV 19
+#define FRA_UID_RANGE 20
+#define __FRA_MAX 12
+
+#define FRA_MAX (__FRA_MAX - 1)
+#endif
+
+#if !HAVE_IFLA_BRPORT_PROXYARP
#define IFLA_BRPORT_PROXYARP 10
#endif
-#if !HAVE_DECL_IFLA_VRF_TABLE
+#if !HAVE_IFLA_VRF_TABLE
#define IFLA_VRF_TABLE 1
#endif
-#if !HAVE_DECL_NDA_IFINDEX
+#if !HAVE_VXCAN_INFO_PEER
+#define VXCAN_INFO_PEER 1
+#endif
+
+#if !HAVE_NDA_IFINDEX
#define NDA_UNSPEC 0
#define NDA_DST 1
#define NDA_LLADDR 2
@@ -953,6 +1039,14 @@ struct input_mask {
#define RTA_PREF 20
#endif
+#ifndef RTAX_QUICKACK
+#define RTAX_QUICKACK 15
+#endif
+
+#ifndef RTA_EXPIRES
+#define RTA_EXPIRES 23
+#endif
+
#ifndef IPV6_UNICAST_IF
#define IPV6_UNICAST_IF 76
#endif
@@ -961,6 +1055,10 @@ struct input_mask {
#define IPV6_MIN_MTU 1280
#endif
+#ifndef IPV4_MIN_MTU
+#define IPV4_MIN_MTU 68
+#endif
+
#ifndef IFF_MULTI_QUEUE
#define IFF_MULTI_QUEUE 0x100
#endif
@@ -1018,7 +1116,7 @@ struct input_mask {
#define LOOPBACK_IFINDEX 1
#endif
-#if !HAVE_DECL_IFA_FLAGS
+#if !HAVE_IFA_FLAGS
#define IFA_FLAGS 8
#endif
@@ -1089,7 +1187,7 @@ struct input_mask {
#endif
#endif // 0
-#ifndef HAVE_KEY_SERIAL_T
+#if ! HAVE_KEY_SERIAL_T
typedef int32_t key_serial_t;
#endif
@@ -1109,6 +1207,10 @@ typedef int32_t key_serial_t;
#define KEYCTL_DESCRIBE 6
#endif
+#ifndef KEYCTL_LINK
+#define KEYCTL_LINK 8
+#endif
+
#ifndef KEYCTL_READ
#define KEYCTL_READ 11
#endif
@@ -1181,11 +1283,11 @@ typedef int32_t key_serial_t;
#ifndef IF_OPER_UP
#define IF_OPER_UP 6
-#ifndef HAVE_CHAR32_T
+#if ! HAVE_CHAR32_T
#define char32_t uint32_t
#endif
-#ifndef HAVE_CHAR16_T
+#if ! HAVE_CHAR16_T
#define char16_t uint16_t
#endif
@@ -1198,7 +1300,7 @@ typedef int32_t key_serial_t;
#endif
#if 0 /// UNNEEDED by elogind
-#ifndef HAVE_STRUCT_ETHTOOL_LINK_SETTINGS
+#if ! HAVE_STRUCT_ETHTOOL_LINK_SETTINGS
#define ETHTOOL_GLINKSETTINGS 0x0000004c /* Get ethtool_link_settings */
#define ETHTOOL_SLINKSETTINGS 0x0000004d /* Set ethtool_link_settings */
@@ -1226,6 +1328,15 @@ struct ethtool_link_settings {
#endif
#endif // 0
+#if ! HAVE_STRUCT_FIB_RULE_UID_RANGE
+
+struct fib_rule_uid_range {
+ __u32 start;
+ __u32 end;
+};
+
+#endif
+
#endif
#ifndef SOL_ALG
@@ -1236,4 +1347,74 @@ struct ethtool_link_settings {
#define AF_VSOCK 40
#endif
+#ifndef EXT4_IOC_RESIZE_FS
+# define EXT4_IOC_RESIZE_FS _IOW('f', 16, __u64)
+#endif
+
+#ifndef NSFS_MAGIC
+#define NSFS_MAGIC 0x6e736673
+#endif
+
+#ifndef NS_GET_NSTYPE
+#define NS_GET_NSTYPE _IO(0xb7, 0x3)
+#endif
+
+#ifndef FALLOC_FL_KEEP_SIZE
+#define FALLOC_FL_KEEP_SIZE 0x01
+#endif
+
+#ifndef FALLOC_FL_PUNCH_HOLE
+#define FALLOC_FL_PUNCH_HOLE 0x02
+#endif
+
+#ifndef PF_KTHREAD
+#define PF_KTHREAD 0x00200000
+#endif
+
+#if ! HAVE_STRUCT_STATX
+struct statx_timestamp {
+ int64_t tv_sec;
+ uint32_t tv_nsec;
+ uint32_t __reserved;
+};
+struct statx {
+ uint32_t stx_mask;
+ uint32_t stx_blksize;
+ uint64_t stx_attributes;
+ uint32_t stx_nlink;
+ uint32_t stx_uid;
+ uint32_t stx_gid;
+ uint16_t stx_mode;
+ uint16_t __spare0[1];
+ uint64_t stx_ino;
+ uint64_t stx_size;
+ uint64_t stx_blocks;
+ uint64_t stx_attributes_mask;
+ struct statx_timestamp stx_atime;
+ struct statx_timestamp stx_btime;
+ struct statx_timestamp stx_ctime;
+ struct statx_timestamp stx_mtime;
+ uint32_t stx_rdev_major;
+ uint32_t stx_rdev_minor;
+ uint32_t stx_dev_major;
+ uint32_t stx_dev_minor;
+ uint64_t __spare2[14];
+};
+#endif
+
+#ifndef STATX_BTIME
+#define STATX_BTIME 0x00000800U
+#endif
+
+#ifndef AT_STATX_DONT_SYNC
+#define AT_STATX_DONT_SYNC 0x4000
+#endif
+
+/* The maximum thread/process name length including trailing NUL byte. This mimics the kernel definition of the same
+ * name, which we need in userspace at various places but is not defined in userspace currently, neither under this
+ * name nor any other. */
+#ifndef TASK_COMM_LEN
+#define TASK_COMM_LEN 16
+#endif
+
#include "missing_syscall.h"
diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h
index beadf369a..3232a89a0 100644
--- a/src/basic/missing_syscall.h
+++ b/src/basic/missing_syscall.h
@@ -1,38 +1,23 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2016 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/>.
-***/
-
/* Missing glibc definitions to access certain kernel APIs */
#if 0 /// UNNEEDED by elogind
-#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);
+#include <sys/types.h>
+
+#if !HAVE_PIVOT_ROOT
+static inline int missing_pivot_root(const char *new_root, const char *put_old) {
+ return syscall(__NR_pivot_root, new_root, put_old);
}
+
+# define pivot_root missing_pivot_root
#endif
#endif // 0
/* ======================================================================= */
-#if !HAVE_DECL_MEMFD_CREATE
+#if !HAVE_MEMFD_CREATE
# ifndef __NR_memfd_create
# if defined __x86_64__
# define __NR_memfd_create 319
@@ -61,7 +46,7 @@ static inline int pivot_root(const char *new_root, const char *put_old) {
# endif
# endif
-static inline int memfd_create(const char *name, unsigned int flags) {
+static inline int missing_memfd_create(const char *name, unsigned int flags) {
# ifdef __NR_memfd_create
return syscall(__NR_memfd_create, name, flags);
# else
@@ -69,11 +54,13 @@ static inline int memfd_create(const char *name, unsigned int flags) {
return -1;
# endif
}
+
+# define memfd_create missing_memfd_create
#endif
/* ======================================================================= */
-#if !HAVE_DECL_GETRANDOM
+#if !HAVE_GETRANDOM
# ifndef __NR_getrandom
# if defined __x86_64__
# define __NR_getrandom 318
@@ -108,7 +95,7 @@ static inline int memfd_create(const char *name, unsigned int flags) {
# endif
# endif
-static inline int getrandom(void *buffer, size_t count, unsigned flags) {
+static inline int missing_getrandom(void *buffer, size_t count, unsigned flags) {
# ifdef __NR_getrandom
return syscall(__NR_getrandom, buffer, count, flags);
# else
@@ -116,19 +103,23 @@ static inline int getrandom(void *buffer, size_t count, unsigned flags) {
return -1;
# endif
}
+
+# define getrandom missing_getrandom
#endif
/* ======================================================================= */
-#if !HAVE_DECL_GETTID
-static inline pid_t gettid(void) {
- return (pid_t) syscall(SYS_gettid);
+#if !HAVE_GETTID
+static inline pid_t missing_gettid(void) {
+ return (pid_t) syscall(__NR_gettid);
}
+
+# define gettid missing_gettid
#endif
/* ======================================================================= */
-#if !HAVE_DECL_NAME_TO_HANDLE_AT
+#if !HAVE_NAME_TO_HANDLE_AT
# ifndef __NR_name_to_handle_at
# if defined(__x86_64__)
# define __NR_name_to_handle_at 303
@@ -151,7 +142,7 @@ struct file_handle {
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) {
+static inline int missing_name_to_handle_at(int fd, const char *name, struct file_handle *handle, int *mnt_id, int flags) {
# ifdef __NR_name_to_handle_at
return syscall(__NR_name_to_handle_at, fd, name, handle, mnt_id, flags);
# else
@@ -159,11 +150,13 @@ static inline int name_to_handle_at(int fd, const char *name, struct file_handle
return -1;
# endif
}
+
+# define name_to_handle_at missing_name_to_handle_at
#endif
/* ======================================================================= */
-#if !HAVE_DECL_SETNS
+#if !HAVE_SETNS
# ifndef __NR_setns
# if defined(__x86_64__)
# define __NR_setns 308
@@ -176,7 +169,7 @@ static inline int name_to_handle_at(int fd, const char *name, struct file_handle
# endif
# endif
-static inline int setns(int fd, int nstype) {
+static inline int missing_setns(int fd, int nstype) {
# ifdef __NR_setns
return syscall(__NR_setns, fd, nstype);
# else
@@ -184,11 +177,12 @@ static inline int setns(int fd, int nstype) {
return -1;
# endif
}
+
+# define setns missing_setns
#endif
/* ======================================================================= */
-#if 0 /// UNNEEDED by elogind
static inline pid_t raw_getpid(void) {
#if defined(__alpha__)
return (pid_t) syscall(__NR_getxpid);
@@ -196,11 +190,10 @@ static inline pid_t raw_getpid(void) {
return (pid_t) syscall(__NR_getpid);
#endif
}
-#endif // 0
/* ======================================================================= */
-#if !HAVE_DECL_RENAMEAT2
+#if !HAVE_RENAMEAT2
# ifndef __NR_renameat2
# if defined __x86_64__
# define __NR_renameat2 316
@@ -231,7 +224,7 @@ static inline pid_t raw_getpid(void) {
# endif
# endif
-static inline int renameat2(int oldfd, const char *oldname, int newfd, const char *newname, unsigned flags) {
+static inline int missing_renameat2(int oldfd, const char *oldname, int newfd, const char *newname, unsigned flags) {
# ifdef __NR_renameat2
return syscall(__NR_renameat2, oldfd, oldname, newfd, newname, flags);
# else
@@ -239,12 +232,14 @@ static inline int renameat2(int oldfd, const char *oldname, int newfd, const cha
return -1;
# endif
}
+
+# define renameat2 missing_renameat2
#endif
/* ======================================================================= */
-#if !HAVE_DECL_KCMP
-static inline int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) {
+#if !HAVE_KCMP
+static inline int missing_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) {
# ifdef __NR_kcmp
return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2);
# else
@@ -252,42 +247,50 @@ static inline int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, uns
return -1;
# endif
}
+
+# define kcmp missing_kcmp
#endif
/* ======================================================================= */
-#if !HAVE_DECL_KEYCTL
-static inline long keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4,unsigned long arg5) {
+#if !HAVE_KEYCTL
+static inline long missing_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4,unsigned long arg5) {
# ifdef __NR_keyctl
return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5);
# else
errno = ENOSYS;
return -1;
# endif
+
+# define keyctl missing_keyctl
}
-static inline key_serial_t add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid) {
+static inline key_serial_t missing_add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid) {
# ifdef __NR_add_key
return syscall(__NR_add_key, type, description, payload, plen, ringid);
# else
errno = ENOSYS;
return -1;
# endif
+
+# define add_key missing_add_key
}
-static inline key_serial_t request_key(const char *type, const char *description, const char * callout_info, key_serial_t destringid) {
+static inline key_serial_t missing_request_key(const char *type, const char *description, const char * callout_info, key_serial_t destringid) {
# ifdef __NR_request_key
return syscall(__NR_request_key, type, description, callout_info, destringid);
# else
errno = ENOSYS;
return -1;
# endif
+
+# define request_key missing_request_key
}
#endif
/* ======================================================================= */
-#if !HAVE_DECL_COPY_FILE_RANGE
+#if !HAVE_COPY_FILE_RANGE
# ifndef __NR_copy_file_range
# if defined(__x86_64__)
# define __NR_copy_file_range 326
@@ -308,10 +311,10 @@ static inline key_serial_t request_key(const char *type, const char *description
# endif
# endif
-static inline ssize_t copy_file_range(int fd_in, loff_t *off_in,
- int fd_out, loff_t *off_out,
- size_t len,
- unsigned int flags) {
+static inline ssize_t missing_copy_file_range(int fd_in, loff_t *off_in,
+ int fd_out, loff_t *off_out,
+ size_t len,
+ unsigned int flags) {
# ifdef __NR_copy_file_range
return syscall(__NR_copy_file_range, fd_in, off_in, fd_out, off_out, len, flags);
# else
@@ -319,4 +322,111 @@ static inline ssize_t copy_file_range(int fd_in, loff_t *off_in,
return -1;
# endif
}
+
+# define copy_file_range missing_copy_file_range
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_BPF
+# ifndef __NR_bpf
+# if defined __i386__
+# define __NR_bpf 357
+# elif defined __x86_64__
+# define __NR_bpf 321
+# elif defined __aarch64__
+# define __NR_bpf 280
+# elif defined __arm__
+# define __NR_bpf 386
+# elif defined __sparc__
+# define __NR_bpf 349
+# elif defined __s390__
+# define __NR_bpf 351
+# elif defined __tilegx__
+# define __NR_bpf 280
+# else
+# warning "__NR_bpf not defined for your architecture"
+# endif
+# endif
+
+union bpf_attr;
+
+static inline int missing_bpf(int cmd, union bpf_attr *attr, size_t size) {
+#ifdef __NR_bpf
+ return (int) syscall(__NR_bpf, cmd, attr, size);
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+# define bpf missing_bpf
+#endif
+
+/* ======================================================================= */
+
+#ifndef __IGNORE_pkey_mprotect
+# ifndef __NR_pkey_mprotect
+# if defined __i386__
+# define __NR_pkey_mprotect 380
+# elif defined __x86_64__
+# define __NR_pkey_mprotect 329
+# elif defined __arm__
+# define __NR_pkey_mprotect 394
+# elif defined __aarch64__
+# define __NR_pkey_mprotect 394
+# elif defined __powerpc__
+# define __NR_pkey_mprotect 386
+# elif defined _MIPS_SIM
+# if _MIPS_SIM == _MIPS_SIM_ABI32
+# define __NR_pkey_mprotect 4363
+# endif
+# if _MIPS_SIM == _MIPS_SIM_NABI32
+# define __NR_pkey_mprotect 6327
+# endif
+# if _MIPS_SIM == _MIPS_SIM_ABI64
+# define __NR_pkey_mprotect 5323
+# endif
+# else
+# warning "__NR_pkey_mprotect not defined for your architecture"
+# endif
+# endif
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_STATX
+# ifndef __NR_statx
+# if defined __aarch64__ || defined __arm__
+# define __NR_statx 397
+# elif defined __alpha__
+# define __NR_statx 522
+# elif defined __i386__ || defined __powerpc64__
+# define __NR_statx 383
+# elif defined __sparc__
+# define __NR_statx 360
+# elif defined __x86_64__
+# define __NR_statx 332
+# else
+# warning "__NR_statx not defined for your architecture"
+# endif
+# endif
+
+struct statx;
+#endif
+
+/* This typedef is supposed to be always defined. */
+typedef struct statx struct_statx;
+
+#if !HAVE_STATX
+static inline ssize_t missing_statx(int dfd, const char *filename, unsigned flags, unsigned int mask, struct statx *buffer) {
+# ifdef __NR_statx
+ return syscall(__NR_statx, dfd, filename, flags, mask, buffer);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+
+# define statx missing_statx
#endif
diff --git a/src/basic/mkdir-label.c b/src/basic/mkdir-label.c
index a3bced293..07799ab01 100644
--- a/src/basic/mkdir-label.c
+++ b/src/basic/mkdir-label.c
@@ -1,32 +1,35 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <stdio.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "label.h"
+#include "macro.h"
#include "mkdir.h"
+#include "selinux-util.h"
+#include "smack-util.h"
+
+int mkdir_label(const char *path, mode_t mode) {
+ int r;
+
+ assert(path);
+
+ r = mac_selinux_create_file_prepare(path, S_IFDIR);
+ if (r < 0)
+ return r;
+
+ r = mkdir_errno_wrapper(path, mode);
+ mac_selinux_create_file_clear();
+ if (r < 0)
+ return r;
+
+ return mac_smack_fix(path, 0);
+}
-int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid) {
- return mkdir_safe_internal(path, mode, uid, gid, mkdir_label);
+int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) {
+ return mkdir_safe_internal(path, mode, uid, gid, flags, mkdir_label);
}
#if 0 /// UNNEEDED by elogind
diff --git a/src/basic/mkdir.c b/src/basic/mkdir.c
index db1e83291..9e9c172f9 100644
--- a/src/basic/mkdir.c
+++ b/src/basic/mkdir.c
@@ -1,60 +1,90 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <stdbool.h>
#include <string.h>
#include <sys/stat.h>
+#include "alloc-util.h"
#include "fs-util.h"
#include "macro.h"
#include "mkdir.h"
#include "path-util.h"
#include "stat-util.h"
+#include "stdio-util.h"
#include "user-util.h"
/// Additional includes needed by elogind
#include "missing.h"
-int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, mkdir_func_t _mkdir) {
+int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdir_func_t _mkdir) {
struct stat st;
+ int r;
- if (_mkdir(path, mode) >= 0)
- if (chmod_and_chown(path, mode, uid, gid) < 0)
- return -errno;
+ assert(_mkdir != mkdir);
+
+ if (_mkdir(path, mode) >= 0) {
+ r = chmod_and_chown(path, mode, uid, gid);
+ if (r < 0)
+ return r;
+ }
if (lstat(path, &st) < 0)
return -errno;
+ if ((flags & MKDIR_FOLLOW_SYMLINK) && S_ISLNK(st.st_mode)) {
+ _cleanup_free_ char *p = NULL;
+
+ r = chase_symlinks(path, NULL, CHASE_NONEXISTENT, &p);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return mkdir_safe_internal(p, mode, uid, gid,
+ flags & ~MKDIR_FOLLOW_SYMLINK,
+ _mkdir);
+
+ if (lstat(p, &st) < 0)
+ return -errno;
+ }
+
+ if (!S_ISDIR(st.st_mode)) {
+ log_full(flags & MKDIR_WARN_MODE ? LOG_WARNING : LOG_DEBUG,
+ "Path \"%s\" already exists and is not a directory, refusing.", path);
+ return -ENOTDIR;
+ }
if ((st.st_mode & 0007) > (mode & 0007) ||
(st.st_mode & 0070) > (mode & 0070) ||
- (st.st_mode & 0700) > (mode & 0700) ||
- (uid != UID_INVALID && st.st_uid != uid) ||
- (gid != GID_INVALID && st.st_gid != gid) ||
- !S_ISDIR(st.st_mode))
+ (st.st_mode & 0700) > (mode & 0700)) {
+ log_full(flags & MKDIR_WARN_MODE ? LOG_WARNING : LOG_DEBUG,
+ "Directory \"%s\" already exists, but has mode %04o that is too permissive (%04o was requested), refusing.",
+ path, st.st_mode & 0777, mode);
+ return -EEXIST;
+ }
+ if ((uid != UID_INVALID && st.st_uid != uid) ||
+ (gid != GID_INVALID && st.st_gid != gid)) {
+ char u[DECIMAL_STR_MAX(uid_t)] = "-", g[DECIMAL_STR_MAX(gid_t)] = "-";
+
+ if (uid != UID_INVALID)
+ xsprintf(u, UID_FMT, uid);
+ if (gid != UID_INVALID)
+ xsprintf(g, GID_FMT, gid);
+ log_full(flags & MKDIR_WARN_MODE ? LOG_WARNING : LOG_DEBUG,
+ "Directory \"%s\" already exists, but is owned by "UID_FMT":"GID_FMT" (%s:%s was requested), refusing.",
+ path, st.st_uid, st.st_gid, u, g);
return -EEXIST;
+ }
return 0;
}
-int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid) {
- return mkdir_safe_internal(path, mode, uid, gid, mkdir);
+int mkdir_errno_wrapper(const char *pathname, mode_t mode) {
+ if (mkdir(pathname, mode) < 0)
+ return -errno;
+ return 0;
+}
+
+int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) {
+ return mkdir_safe_internal(path, mode, uid, gid, flags, mkdir_errno_wrapper);
}
int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir) {
@@ -62,6 +92,7 @@ int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mk
int r;
assert(path);
+ assert(_mkdir != mkdir);
if (prefix && !path_startswith(path, prefix))
return -ENOTDIR;
@@ -89,8 +120,7 @@ int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mk
e = p + strcspn(p, "/");
p = e + strspn(e, "/");
- /* Is this the last component? If so, then we're
- * done */
+ /* Is this the last component? If so, then we're done */
if (*p == 0)
return 0;
@@ -101,13 +131,13 @@ int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mk
continue;
r = _mkdir(t, mode);
- if (r < 0 && errno != EEXIST)
- return -errno;
+ if (r < 0 && r != -EEXIST)
+ return r;
}
}
int mkdir_parents(const char *path, mode_t mode) {
- return mkdir_parents_internal(NULL, path, mode, mkdir);
+ return mkdir_parents_internal(NULL, path, mode, mkdir_errno_wrapper);
}
int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir) {
@@ -115,17 +145,19 @@ int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, mkdir_fu
/* Like mkdir -p */
+ assert(_mkdir != mkdir);
+
r = mkdir_parents_internal(prefix, path, mode, _mkdir);
if (r < 0)
return r;
r = _mkdir(path, mode);
- if (r < 0 && (errno != EEXIST || is_dir(path, true) <= 0))
- return -errno;
+ if (r < 0 && (r != -EEXIST || is_dir(path, true) <= 0))
+ return r;
return 0;
}
int mkdir_p(const char *path, mode_t mode) {
- return mkdir_p_internal(NULL, path, mode, mkdir);
+ return mkdir_p_internal(NULL, path, mode, mkdir_errno_wrapper);
}
diff --git a/src/basic/mkdir.h b/src/basic/mkdir.h
index 07ee10616..8016c38e9 100644
--- a/src/basic/mkdir.h
+++ b/src/basic/mkdir.h
@@ -1,33 +1,21 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 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 <sys/types.h>
-int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid);
+typedef enum MkdirFlags {
+ MKDIR_FOLLOW_SYMLINK = 1 << 0,
+ MKDIR_WARN_MODE = 1 << 1,
+} MkdirFlags;
+
+int mkdir_errno_wrapper(const char *pathname, mode_t mode);
+int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags);
int mkdir_parents(const char *path, mode_t mode);
int mkdir_p(const char *path, mode_t mode);
/* mandatory access control(MAC) versions */
-int mkdir_safe_label(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, MkdirFlags flags);
#if 0 /// UNNEEDED by elogind
int mkdir_parents_label(const char *path, mode_t mode);
#endif // 0
@@ -35,6 +23,6 @@ int mkdir_p_label(const char *path, mode_t mode);
/* internally used */
typedef int (*mkdir_func_t)(const char *pathname, mode_t mode);
-int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, mkdir_func_t _mkdir);
+int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdir_func_t _mkdir);
int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir);
int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir);
diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c
index aee878e88..f0dea723e 100644
--- a/src/basic/mount-util.c
+++ b/src/basic/mount-util.c
@@ -1,23 +1,7 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
+//#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>
@@ -25,8 +9,12 @@
#include <sys/statvfs.h>
#include <unistd.h>
+/* Include later */
+//#include <libmount.h>
+
#include "alloc-util.h"
#include "escape.h"
+//#include "extract-word.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
@@ -37,9 +25,82 @@
#include "set.h"
#include "stdio-util.h"
#include "string-util.h"
+#include "strv.h"
+
+/* This is the original MAX_HANDLE_SZ definition from the kernel, when the API was introduced. We use that in place of
+ * any more currently defined value to future-proof things: if the size is increased in the API headers, and our code
+ * is recompiled then it would cease working on old kernels, as those refuse any sizes larger than this value with
+ * EINVAL right-away. Hence, let's disconnect ourselves from any such API changes, and stick to the original definition
+ * from when it was introduced. We use it as a start value only anyway (see below), and hence should be able to deal
+ * with large file handles anyway. */
+#define ORIGINAL_MAX_HANDLE_SZ 128
+
+int name_to_handle_at_loop(
+ int fd,
+ const char *path,
+ struct file_handle **ret_handle,
+ int *ret_mnt_id,
+ int flags) {
+
+ _cleanup_free_ struct file_handle *h = NULL;
+ size_t n = ORIGINAL_MAX_HANDLE_SZ;
+
+ /* We need to invoke name_to_handle_at() in a loop, given that it might return EOVERFLOW when the specified
+ * buffer is too small. Note that in contrast to what the docs might suggest, MAX_HANDLE_SZ is only good as a
+ * start value, it is not an upper bound on the buffer size required.
+ *
+ * This improves on raw name_to_handle_at() also in one other regard: ret_handle and ret_mnt_id can be passed
+ * as NULL if there's no interest in either. */
+
+ for (;;) {
+ int mnt_id = -1;
+
+ h = malloc0(offsetof(struct file_handle, f_handle) + n);
+ if (!h)
+ return -ENOMEM;
+
+ h->handle_bytes = n;
+
+ if (name_to_handle_at(fd, path, h, &mnt_id, flags) >= 0) {
+
+ if (ret_handle)
+ *ret_handle = TAKE_PTR(h);
+
+ if (ret_mnt_id)
+ *ret_mnt_id = mnt_id;
+
+ return 0;
+ }
+ if (errno != EOVERFLOW)
+ return -errno;
+
+ if (!ret_handle && ret_mnt_id && mnt_id >= 0) {
+
+ /* As it appears, name_to_handle_at() fills in mnt_id even when it returns EOVERFLOW when the
+ * buffer is too small, but that's undocumented. Hence, let's make use of this if it appears to
+ * be filled in, and the caller was interested in only the mount ID an nothing else. */
+
+ *ret_mnt_id = mnt_id;
+ return 0;
+ }
+
+ /* If name_to_handle_at() didn't increase the byte size, then this EOVERFLOW is caused by something
+ * else (apparently EOVERFLOW is returned for untriggered nfs4 mounts sometimes), not by the too small
+ * buffer. In that case propagate EOVERFLOW */
+ if (h->handle_bytes <= n)
+ return -EOVERFLOW;
+
+ /* The buffer was too small. Size the new buffer by what name_to_handle_at() returned. */
+ n = h->handle_bytes;
+ if (offsetof(struct file_handle, f_handle) + n < n) /* check for addition overflow */
+ return -EOVERFLOW;
+
+ h = mfree(h);
+ }
+}
static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id) {
- char path[strlen("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)];
+ char path[STRLEN("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)];
_cleanup_free_ char *fdinfo = NULL;
_cleanup_close_ int subfd = -1;
char *p;
@@ -59,7 +120,7 @@ static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id
if (r == -ENOENT) /* The fdinfo directory is a relatively new addition */
return -EOPNOTSUPP;
if (r < 0)
- return -errno;
+ return r;
p = startswith(fdinfo, "mnt_id:");
if (!p) {
@@ -77,7 +138,7 @@ static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id
}
int fd_is_mount_point(int fd, const char *filename, int flags) {
- union file_handle_union h = FILE_HANDLE_INIT, h_parent = FILE_HANDLE_INIT;
+ _cleanup_free_ struct file_handle *h = NULL, *h_parent = NULL;
int mount_id = -1, mount_id_parent = -1;
bool nosupp = false, check_st_dev = true;
struct stat a, b;
@@ -109,39 +170,32 @@ int fd_is_mount_point(int fd, const char *filename, int flags) {
* subvolumes have different st_dev, even though they aren't
* real mounts of their own. */
- r = name_to_handle_at(fd, filename, &h.handle, &mount_id, flags);
- if (r < 0) {
- if (IN_SET(errno, ENOSYS, EACCES, EPERM))
- /* This kernel does not support name_to_handle_at() at all, or the syscall was blocked (maybe
- * through seccomp, because we are running inside of a container?): fall back to simpler
- * logic. */
+ r = name_to_handle_at_loop(fd, filename, &h, &mount_id, flags);
+ if (IN_SET(r, -ENOSYS, -EACCES, -EPERM, -EOVERFLOW, -EINVAL))
+ /* This kernel does not support name_to_handle_at() at all (ENOSYS), or the syscall was blocked
+ * (EACCES/EPERM; maybe through seccomp, because we are running inside of a container?), or the mount
+ * point is not triggered yet (EOVERFLOW, think nfs4), or some general name_to_handle_at() flakiness
+ * (EINVAL): fall back to simpler logic. */
+ goto fallback_fdinfo;
+ else if (r == -EOPNOTSUPP)
+ /* This kernel or file system does not support name_to_handle_at(), hence let's see if the upper fs
+ * supports it (in which case it is a mount point), otherwise fallback to the traditional stat()
+ * logic */
+ nosupp = true;
+ else if (r < 0)
+ return r;
+
+ r = name_to_handle_at_loop(fd, "", &h_parent, &mount_id_parent, AT_EMPTY_PATH);
+ if (r == -EOPNOTSUPP) {
+ if (nosupp)
+ /* Neither parent nor child do name_to_handle_at()? We have no choice but to fall back. */
goto fallback_fdinfo;
- else if (errno == EOPNOTSUPP)
- /* This kernel or file system does not support
- * name_to_handle_at(), hence let's see if the
- * upper fs supports it (in which case it is a
- * mount point), otherwise fallback to the
- * traditional stat() logic */
- nosupp = true;
else
- return -errno;
- }
-
- r = name_to_handle_at(fd, "", &h_parent.handle, &mount_id_parent, AT_EMPTY_PATH);
- if (r < 0) {
- if (errno == EOPNOTSUPP) {
- if (nosupp)
- /* Neither parent nor child do name_to_handle_at()?
- We have no choice but to fall back. */
- goto fallback_fdinfo;
- else
- /* The parent can't do name_to_handle_at() but the
- * directory we are interested in can?
- * If so, it must be a mount point. */
- return 1;
- } else
- return -errno;
- }
+ /* The parent can't do name_to_handle_at() but the directory we are interested in can? If so,
+ * it must be a mount point. */
+ return 1;
+ } else if (r < 0)
+ return r;
/* The parent can do name_to_handle_at() but the
* directory we are interested in can't? If so, it
@@ -154,9 +208,9 @@ int fd_is_mount_point(int fd, const char *filename, int flags) {
* assume this is the root directory, which is a mount
* point. */
- if (h.handle.handle_bytes == h_parent.handle.handle_bytes &&
- h.handle.handle_type == h_parent.handle.handle_type &&
- memcmp(h.handle.f_handle, h_parent.handle.f_handle, h.handle.handle_bytes) == 0)
+ if (h->handle_bytes == h_parent->handle_bytes &&
+ h->handle_type == h_parent->handle_type &&
+ memcmp(h->f_handle, h_parent->f_handle, h->handle_bytes) == 0)
return 1;
return mount_id != mount_id_parent;
@@ -212,6 +266,7 @@ int path_is_mount_point(const char *t, const char *root, int flags) {
int r;
assert(t);
+ assert((flags & ~AT_SYMLINK_FOLLOW) == 0);
if (path_equal(t, "/"))
return 1;
@@ -221,7 +276,7 @@ int path_is_mount_point(const char *t, const char *root, int flags) {
* /bin -> /usr/bin/ and /usr is a mount point, then the parent that we
* look at needs to be /usr, not /. */
if (flags & AT_SYMLINK_FOLLOW) {
- r = chase_symlinks(t, root, 0, &canonical);
+ r = chase_symlinks(t, root, CHASE_TRAIL_SLASH, &canonical);
if (r < 0)
return r;
@@ -236,7 +291,17 @@ int path_is_mount_point(const char *t, const char *root, int flags) {
if (fd < 0)
return -errno;
- return fd_is_mount_point(fd, basename(t), flags);
+ return fd_is_mount_point(fd, last_path_component(t), flags);
+}
+
+int path_get_mnt_id(const char *path, int *ret) {
+ int r;
+
+ r = name_to_handle_at_loop(AT_FDCWD, path, NULL, ret, 0);
+ if (IN_SET(r, -EOPNOTSUPP, -ENOSYS, -EACCES, -EPERM, -EOVERFLOW, -EINVAL)) /* kernel/fs don't support this, or seccomp blocks access, or untriggered mount, or name_to_handle_at() is flaky */
+ return fd_fdinfo_mnt_id(AT_FDCWD, path, 0, ret);
+
+ return r;
}
#if 0 /// UNNEEDED by elogind
@@ -258,6 +323,8 @@ int umount_recursive(const char *prefix, int flags) {
if (!proc_self_mountinfo)
return -errno;
+ (void) __fsetlocking(proc_self_mountinfo, FSETLOCKING_BYCALLER);
+
for (;;) {
_cleanup_free_ char *path = NULL, *p = NULL;
int k;
@@ -342,9 +409,9 @@ int bind_remount_recursive_with_mountinfo(const char *prefix, bool ro, char **bl
if (!cleaned)
return -ENOMEM;
- path_kill_slashes(cleaned);
+ path_simplify(cleaned, false);
- done = set_new(&string_hash_ops);
+ done = set_new(&path_hash_ops);
if (!done)
return -ENOMEM;
@@ -354,7 +421,7 @@ int bind_remount_recursive_with_mountinfo(const char *prefix, bool ro, char **bl
char *x;
unsigned long orig_flags;
- todo = set_new(&string_hash_ops);
+ todo = set_new(&path_hash_ops);
if (!todo)
return -ENOMEM;
@@ -472,14 +539,14 @@ int bind_remount_recursive_with_mountinfo(const char *prefix, bool ro, char **bl
while ((x = set_steal_first(todo))) {
r = set_consume(done, x);
- if (r == -EEXIST || r == 0)
+ if (IN_SET(r, 0, -EEXIST))
continue;
if (r < 0)
return r;
/* Deal with mount points that are obstructed by a later mount */
r = path_is_mount_point(x, NULL, 0);
- if (r == -ENOENT || r == 0)
+ if (IN_SET(r, 0, -ENOENT))
continue;
if (r < 0)
return r;
@@ -504,6 +571,8 @@ int bind_remount_recursive(const char *prefix, bool ro, char **blacklist) {
if (!proc_self_mountinfo)
return -errno;
+ (void) __fsetlocking(proc_self_mountinfo, FSETLOCKING_BYCALLER);
+
return bind_remount_recursive_with_mountinfo(prefix, ro, blacklist, proc_self_mountinfo);
}
@@ -526,30 +595,83 @@ int mount_move_root(const char *path) {
}
bool fstype_is_network(const char *fstype) {
- static const char table[] =
- "afs\0"
- "cifs\0"
- "smbfs\0"
- "sshfs\0"
- "ncpfs\0"
- "ncp\0"
- "nfs\0"
- "nfs4\0"
- "gfs\0"
- "gfs2\0"
- "glusterfs\0"
- "pvfs2\0" /* OrangeFS */
- "ocfs2\0"
- "lustre\0"
- ;
-
const char *x;
x = startswith(fstype, "fuse.");
if (x)
fstype = x;
- return nulstr_contains(table, fstype);
+ return STR_IN_SET(fstype,
+ "afs",
+ "cifs",
+ "smbfs",
+ "sshfs",
+ "ncpfs",
+ "ncp",
+ "nfs",
+ "nfs4",
+ "gfs",
+ "gfs2",
+ "glusterfs",
+ "pvfs2", /* OrangeFS */
+ "ocfs2",
+ "lustre");
+}
+
+bool fstype_is_api_vfs(const char *fstype) {
+ return STR_IN_SET(fstype,
+ "autofs",
+ "bpf",
+ "cgroup",
+ "cgroup2",
+ "configfs",
+ "cpuset",
+ "debugfs",
+ "devpts",
+ "devtmpfs",
+ "efivarfs",
+ "fusectl",
+ "hugetlbfs",
+ "mqueue",
+ "proc",
+ "pstore",
+ "ramfs",
+ "securityfs",
+ "sysfs",
+ "tmpfs",
+ "tracefs");
+}
+
+bool fstype_is_ro(const char *fstype) {
+ /* All Linux file systems that are necessarily read-only */
+ return STR_IN_SET(fstype,
+ "DM_verity_hash",
+ "iso9660",
+ "squashfs");
+}
+
+bool fstype_can_discard(const char *fstype) {
+ return STR_IN_SET(fstype,
+ "btrfs",
+ "ext4",
+ "vfat",
+ "xfs");
+}
+
+bool fstype_can_uid_gid(const char *fstype) {
+
+ /* All file systems that have a uid=/gid= mount option that fixates the owners of all files and directories,
+ * current and future. */
+
+ return STR_IN_SET(fstype,
+ "adfs",
+ "fat",
+ "hfs",
+ "hpfs",
+ "iso9660",
+ "msdos",
+ "ntfs",
+ "vfat");
}
int repeat_unmount(const char *path, int flags) {
@@ -575,24 +697,33 @@ int repeat_unmount(const char *path, int flags) {
#endif // 0
const char* mode_to_inaccessible_node(mode_t mode) {
- /* This function maps a node type to the correspondent inaccessible node type.
- * Character and block inaccessible devices may not be created (because major=0 and minor=0),
- * in such case we map character and block devices to the inaccessible node type socket. */
+ /* This function maps a node type to a corresponding inaccessible file node. These nodes are created during
+ * early boot by PID 1. In some cases we lacked the privs to create the character and block devices (maybe
+ * because we run in an userns environment, or miss CAP_SYS_MKNOD, or run with a devices policy that excludes
+ * device nodes with major and minor of 0), but that's fine, in that case we use an AF_UNIX file node instead,
+ * which is not the same, but close enough for most uses. And most importantly, the kernel allows bind mounts
+ * from socket nodes to any non-directory file nodes, and that's the most important thing that matters. */
+
switch(mode & S_IFMT) {
case S_IFREG:
return "/run/systemd/inaccessible/reg";
+
case S_IFDIR:
return "/run/systemd/inaccessible/dir";
+
case S_IFCHR:
if (access("/run/systemd/inaccessible/chr", F_OK) == 0)
return "/run/systemd/inaccessible/chr";
return "/run/systemd/inaccessible/sock";
+
case S_IFBLK:
if (access("/run/systemd/inaccessible/blk", F_OK) == 0)
return "/run/systemd/inaccessible/blk";
return "/run/systemd/inaccessible/sock";
+
case S_IFIFO:
return "/run/systemd/inaccessible/fifo";
+
case S_IFSOCK:
return "/run/systemd/inaccessible/sock";
}
@@ -675,29 +806,37 @@ int mount_verbose(
unsigned long flags,
const char *options) {
- _cleanup_free_ char *fl = NULL;
+ _cleanup_free_ char *fl = NULL, *o = NULL;
+ unsigned long f;
+ int r;
- fl = mount_flags_to_string(flags);
+ r = mount_option_mangle(options, flags, &f, &o);
+ if (r < 0)
+ return log_full_errno(error_log_level, r,
+ "Failed to mangle mount options %s: %m",
+ strempty(options));
- if ((flags & MS_REMOUNT) && !what && !type)
+ fl = mount_flags_to_string(f);
+
+ if ((f & MS_REMOUNT) && !what && !type)
log_debug("Remounting %s (%s \"%s\")...",
- where, strnull(fl), strempty(options));
+ where, strnull(fl), strempty(o));
else if (!what && !type)
log_debug("Mounting %s (%s \"%s\")...",
- where, strnull(fl), strempty(options));
- else if ((flags & MS_BIND) && !type)
+ where, strnull(fl), strempty(o));
+ else if ((f & MS_BIND) && !type)
log_debug("Bind-mounting %s on %s (%s \"%s\")...",
- what, where, strnull(fl), strempty(options));
- else if (flags & MS_MOVE)
+ what, where, strnull(fl), strempty(o));
+ else if (f & MS_MOVE)
log_debug("Moving mount %s → %s (%s \"%s\")...",
- what, where, strnull(fl), strempty(options));
+ what, where, strnull(fl), strempty(o));
else
log_debug("Mounting %s on %s (%s \"%s\")...",
- strna(type), where, strnull(fl), strempty(options));
- if (mount(what, where, type, flags, options) < 0)
+ strna(type), where, strnull(fl), strempty(o));
+ if (mount(what, where, type, f, o) < 0)
return log_full_errno(error_log_level, errno,
"Failed to mount %s on %s (%s \"%s\"): %m",
- strna(type), where, strnull(fl), strempty(options));
+ strna(type), where, strnull(fl), strempty(o));
return 0;
}
@@ -707,6 +846,7 @@ int umount_verbose(const char *what) {
return log_error_errno(errno, "Failed to unmount %s: %m", what);
return 0;
}
+#endif // 0
const char *mount_propagation_flags_to_string(unsigned long flags) {
@@ -724,7 +864,6 @@ const char *mount_propagation_flags_to_string(unsigned long flags) {
return NULL;
}
-
int mount_propagation_flags_from_string(const char *name, unsigned long *ret) {
if (isempty(name))
@@ -739,4 +878,74 @@ int mount_propagation_flags_from_string(const char *name, unsigned long *ret) {
return -EINVAL;
return 0;
}
+
+#if 0 /// UNNEEDED by elogind
+int mount_option_mangle(
+ const char *options,
+ unsigned long mount_flags,
+ unsigned long *ret_mount_flags,
+ char **ret_remaining_options) {
+
+ const struct libmnt_optmap *map;
+ _cleanup_free_ char *ret = NULL;
+ const char *p;
+ int r;
+
+ /* This extracts mount flags from the mount options, and store
+ * non-mount-flag options to '*ret_remaining_options'.
+ * E.g.,
+ * "rw,nosuid,nodev,relatime,size=1630748k,mode=700,uid=1000,gid=1000"
+ * is split to MS_NOSUID|MS_NODEV|MS_RELATIME and
+ * "size=1630748k,mode=700,uid=1000,gid=1000".
+ * See more examples in test-mount-utils.c.
+ *
+ * Note that if 'options' does not contain any non-mount-flag options,
+ * then '*ret_remaining_options' is set to NULL instread of empty string.
+ * Note that this does not check validity of options stored in
+ * '*ret_remaining_options'.
+ * Note that if 'options' is NULL, then this just copies 'mount_flags'
+ * to '*ret_mount_flags'. */
+
+ assert(ret_mount_flags);
+ assert(ret_remaining_options);
+
+ map = mnt_get_builtin_optmap(MNT_LINUX_MAP);
+ if (!map)
+ return -EINVAL;
+
+ p = options;
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
+ const struct libmnt_optmap *ent;
+
+ r = extract_first_word(&p, &word, ",", EXTRACT_QUOTES);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
+ for (ent = map; ent->name; ent++) {
+ /* All entries in MNT_LINUX_MAP do not take any argument.
+ * Thus, ent->name does not contain "=" or "[=]". */
+ if (!streq(word, ent->name))
+ continue;
+
+ if (!(ent->mask & MNT_INVERT))
+ mount_flags |= ent->id;
+ else if (mount_flags & ent->id)
+ mount_flags ^= ent->id;
+
+ break;
+ }
+
+ /* If 'word' is not a mount flag, then store it in '*ret_remaining_options'. */
+ if (!ent->name && !strextend_with_separator(&ret, ",", word, NULL))
+ return -ENOMEM;
+ }
+
+ *ret_mount_flags = mount_flags;
+ *ret_remaining_options = TAKE_PTR(ret);
+
+ return 0;
+}
#endif // 0
diff --git a/src/basic/mount-util.h b/src/basic/mount-util.h
index 56a1f8487..0326f0a2e 100644
--- a/src/basic/mount-util.h
+++ b/src/basic/mount-util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <fcntl.h>
#include <mntent.h>
#include <stdbool.h>
@@ -29,6 +11,10 @@
#include "macro.h"
#include "missing.h"
+int name_to_handle_at_loop(int fd, const char *path, struct file_handle **ret_handle, int *ret_mnt_id, int flags);
+
+int path_get_mnt_id(const char *path, int *ret);
+
int fd_is_mount_point(int fd, const char *filename, int flags);
int path_is_mount_point(const char *path, const char *root, int flags);
@@ -48,16 +34,13 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, endmntent);
#if 0 /// UNNEEDED by elogind
bool fstype_is_network(const char *fstype);
#endif // 0
-
-union file_handle_union {
- struct file_handle handle;
- char padding[sizeof(struct file_handle) + MAX_HANDLE_SZ];
-};
+bool fstype_is_api_vfs(const char *fstype);
+bool fstype_is_ro(const char *fsype);
+bool fstype_can_discard(const char *fstype);
+bool fstype_can_uid_gid(const char *fstype);
const char* mode_to_inaccessible_node(mode_t mode);
-#define FILE_HANDLE_INIT { .handle.handle_bytes = MAX_HANDLE_SZ }
-
#if 0 /// UNNEEDED by elogind
int mount_verbose(
int error_log_level,
@@ -67,7 +50,15 @@ int mount_verbose(
unsigned long flags,
const char *options);
int umount_verbose(const char *where);
+#endif // 0
const char *mount_propagation_flags_to_string(unsigned long flags);
int mount_propagation_flags_from_string(const char *name, unsigned long *ret);
+
+#if 0 /// UNNEEDED by elogind
+int mount_option_mangle(
+ const char *options,
+ unsigned long mount_flags,
+ unsigned long *ret_mount_flags,
+ char **ret_remaining_options);
#endif // 0
diff --git a/src/shared/pager.c b/src/basic/pager.c
index 8f3fc133b..c0ad0bb3b 100644
--- a/src/shared/pager.c
+++ b/src/basic/pager.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <signal.h>
@@ -41,7 +24,12 @@
static pid_t pager_pid = 0;
-noreturn static void pager_fallback(void) {
+static int stored_stdout = -1;
+static int stored_stderr = -1;
+static bool stdout_redirected = false;
+static bool stderr_redirected = false;
+
+_noreturn_ static void pager_fallback(void) {
int r;
r = copy_bytes(STDIN_FILENO, STDOUT_FILENO, (uint64_t) -1, 0);
@@ -53,15 +41,10 @@ noreturn static void pager_fallback(void) {
_exit(EXIT_SUCCESS);
}
-static int stored_stdout = -1;
-static int stored_stderr = -1;
-static bool stdout_redirected = false;
-static bool stderr_redirected = false;
-
int pager_open(bool no_pager, bool jump_to_end) {
_cleanup_close_pair_ int fd[2] = { -1, -1 };
const char *pager;
- pid_t parent_pid;
+ int r;
if (no_pager)
return 0;
@@ -72,6 +55,9 @@ int pager_open(bool no_pager, bool jump_to_end) {
if (terminal_is_dumb())
return 0;
+ if (!is_main_thread())
+ return -EPERM;
+
pager = getenv("SYSTEMD_PAGER");
if (!pager)
pager = getenv("PAGER");
@@ -80,25 +66,21 @@ int pager_open(bool no_pager, bool jump_to_end) {
if (pager && STR_IN_SET(pager, "", "cat"))
return 0;
- /* Determine and cache number of columns before we spawn the
- * pager so that we get the value from the actual tty */
+ /* Determine and cache number of columns/lines before we spawn the pager so that we get the value from the
+ * actual tty */
(void) columns();
+ (void) lines();
- if (pipe(fd) < 0)
+ if (pipe2(fd, O_CLOEXEC) < 0)
return log_error_errno(errno, "Failed to create pager pipe: %m");
- parent_pid = getpid();
-
- pager_pid = fork();
- if (pager_pid < 0)
- return log_error_errno(errno, "Failed to fork pager: %m");
-
- /* In the child start the pager */
- if (pager_pid == 0) {
+ r = safe_fork("(pager)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pager_pid);
+ if (r < 0)
+ return r;
+ if (r == 0) {
const char* less_opts, *less_charset;
- (void) reset_all_signal_handlers();
- (void) reset_signal_mask();
+ /* In the child start the pager */
(void) dup2(fd[0], STDIN_FILENO);
safe_close_pair(fd);
@@ -122,15 +104,6 @@ int pager_open(bool no_pager, bool jump_to_end) {
setenv("LESSCHARSET", less_charset, 1) < 0)
_exit(EXIT_FAILURE);
- /* 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);
@@ -203,7 +176,6 @@ int show_man_page(const char *desc, bool null_stdio) {
pid_t pid;
size_t k;
int r;
- siginfo_t status;
k = strlen(desc);
@@ -221,34 +193,16 @@ int show_man_page(const char *desc, bool null_stdio) {
} else
args[1] = desc;
- pid = fork();
- if (pid < 0)
- return log_error_errno(errno, "Failed to fork: %m");
-
- if (pid == 0) {
+ r = safe_fork("(man)", FORK_RESET_SIGNALS|FORK_DEATHSIG|(null_stdio ? FORK_NULL_STDIO : 0)|FORK_LOG, &pid);
+ if (r < 0)
+ return r;
+ if (r == 0) {
/* Child */
-
- (void) reset_all_signal_handlers();
- (void) reset_signal_mask();
-
- if (null_stdio) {
- r = make_null_stdio();
- if (r < 0) {
- log_error_errno(r, "Failed to kill stdio: %m");
- _exit(EXIT_FAILURE);
- }
- }
-
execvp(args[0], (char**) args);
log_error_errno(errno, "Failed to execute man: %m");
_exit(EXIT_FAILURE);
}
- r = wait_for_terminate(pid, &status);
- if (r < 0)
- return r;
-
- log_debug("Exit code %i status %i", status.si_code, status.si_status);
- return status.si_status;
+ return wait_for_terminate_and_check(NULL, pid, 0);
}
#endif // 0
diff --git a/src/basic/pager.h b/src/basic/pager.h
new file mode 100644
index 000000000..edeae3a11
--- /dev/null
+++ b/src/basic/pager.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <stdbool.h>
+
+#include "macro.h"
+
+int pager_open(bool no_pager, bool jump_to_end);
+void pager_close(void);
+bool pager_have(void) _pure_;
+
+#if 0 /// UNNEEDED by elogind
+int show_man_page(const char *page, bool null_stdio);
+#endif // 0
diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c
index 011355962..3935d8a3e 100644
--- a/src/basic/parse-util.c
+++ b/src/basic/parse-util.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <inttypes.h>
@@ -23,11 +6,16 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/socket.h>
#include "alloc-util.h"
+#include "errno-list.h"
//#include "extract-word.h"
+#include "locale-util.h"
#include "macro.h"
+#include "missing.h"
#include "parse-util.h"
+#include "process-util.h"
#include "string-util.h"
/// Additional includes needed by elogind
@@ -61,7 +49,7 @@ int parse_pid(const char *s, pid_t* ret_pid) {
if ((unsigned long) pid != ul)
return -ERANGE;
- if (pid <= 0)
+ if (!pid_is_valid(pid))
return -ERANGE;
*ret_pid = pid;
@@ -83,7 +71,7 @@ int parse_mode(const char *s, mode_t *ret) {
l = strtol(s, &x, 8);
if (errno > 0)
return -errno;
- if (!x || x == s || *x)
+ if (!x || x == s || *x != 0)
return -EINVAL;
if (l < 0 || l > 07777)
return -ERANGE;
@@ -105,6 +93,30 @@ int parse_ifindex(const char *s, int *ret) {
return 0;
}
+int parse_mtu(int family, const char *s, uint32_t *ret) {
+ uint64_t u;
+ size_t m;
+ int r;
+
+ r = parse_size(s, 1024, &u);
+ if (r < 0)
+ return r;
+
+ if (u > UINT32_MAX)
+ return -ERANGE;
+
+ if (family == AF_INET6)
+ m = IPV6_MIN_MTU; /* This is 1280 */
+ else
+ m = IPV4_MIN_MTU; /* For all other protocols, including 'unspecified' we assume the IPv4 minimal MTU */
+
+ if (u < m)
+ return -ERANGE;
+
+ *ret = (uint32_t) u;
+ return 0;
+}
+
int parse_size(const char *t, uint64_t base, uint64_t *size) {
/* Soo, sometimes we want to parse IEC binary suffixes, and
@@ -154,7 +166,7 @@ int parse_size(const char *t, uint64_t base, uint64_t *size) {
unsigned n_entries, start_pos = 0;
assert(t);
- assert(base == 1000 || base == 1024);
+ assert(IN_SET(base, 1000, 1024));
assert(size);
if (base == 1000) {
@@ -272,6 +284,64 @@ int parse_range(const char *t, unsigned *lower, unsigned *upper) {
}
#endif // 0
+int parse_errno(const char *t) {
+ int r, e;
+
+ assert(t);
+
+ r = errno_from_name(t);
+ if (r > 0)
+ return r;
+
+ r = safe_atoi(t, &e);
+ if (r < 0)
+ return r;
+
+ /* 0 is also allowed here */
+ if (!errno_is_valid(e) && e != 0)
+ return -ERANGE;
+
+ return e;
+}
+
+int parse_syscall_and_errno(const char *in, char **name, int *error) {
+ _cleanup_free_ char *n = NULL;
+ char *p;
+ int e = -1;
+
+ assert(in);
+ assert(name);
+ assert(error);
+
+ /*
+ * This parse "syscall:errno" like "uname:EILSEQ", "@sync:255".
+ * If errno is omitted, then error is set to -1.
+ * Empty syscall name is not allowed.
+ * Here, we do not check that the syscall name is valid or not.
+ */
+
+ p = strchr(in, ':');
+ if (p) {
+ e = parse_errno(p + 1);
+ if (e < 0)
+ return e;
+
+ n = strndup(in, p - in);
+ } else
+ n = strdup(in);
+
+ if (!n)
+ return -ENOMEM;
+
+ if (isempty(n))
+ return -EINVAL;
+
+ *error = e;
+ *name = TAKE_PTR(n);
+
+ return 0;
+}
+
char *format_bytes(char *buf, size_t l, uint64_t t) {
unsigned i;
@@ -313,12 +383,13 @@ finish:
}
-int safe_atou(const char *s, unsigned *ret_u) {
+int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) {
char *x = NULL;
unsigned long l;
assert(s);
assert(ret_u);
+ assert(base <= 16);
/* strtoul() is happy to parse negative values, and silently
* converts them to unsigned values without generating an
@@ -331,10 +402,10 @@ int safe_atou(const char *s, unsigned *ret_u) {
s += strspn(s, WHITESPACE);
errno = 0;
- l = strtoul(s, &x, 0);
+ l = strtoul(s, &x, base);
if (errno > 0)
return -errno;
- if (!x || x == s || *x)
+ if (!x || x == s || *x != 0)
return -EINVAL;
if (s[0] == '-')
return -ERANGE;
@@ -356,7 +427,7 @@ int safe_atoi(const char *s, int *ret_i) {
l = strtol(s, &x, 0);
if (errno > 0)
return -errno;
- if (!x || x == s || *x)
+ if (!x || x == s || *x != 0)
return -EINVAL;
if ((long) (int) l != l)
return -ERANGE;
@@ -378,7 +449,7 @@ int safe_atollu(const char *s, long long unsigned *ret_llu) {
l = strtoull(s, &x, 0);
if (errno > 0)
return -errno;
- if (!x || x == s || *x)
+ if (!x || x == s || *x != 0)
return -EINVAL;
if (*s == '-')
return -ERANGE;
@@ -398,7 +469,7 @@ int safe_atolli(const char *s, long long int *ret_lli) {
l = strtoll(s, &x, 0);
if (errno > 0)
return -errno;
- if (!x || x == s || *x)
+ if (!x || x == s || *x != 0)
return -EINVAL;
*ret_lli = l;
@@ -418,7 +489,7 @@ int safe_atou8(const char *s, uint8_t *ret) {
l = strtoul(s, &x, 0);
if (errno > 0)
return -errno;
- if (!x || x == s || *x)
+ if (!x || x == s || *x != 0)
return -EINVAL;
if (s[0] == '-')
return -ERANGE;
@@ -429,20 +500,21 @@ int safe_atou8(const char *s, uint8_t *ret) {
return 0;
}
-int safe_atou16(const char *s, uint16_t *ret) {
+int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) {
char *x = NULL;
unsigned long l;
assert(s);
assert(ret);
+ assert(base <= 16);
s += strspn(s, WHITESPACE);
errno = 0;
- l = strtoul(s, &x, 0);
+ l = strtoul(s, &x, base);
if (errno > 0)
return -errno;
- if (!x || x == s || *x)
+ if (!x || x == s || *x != 0)
return -EINVAL;
if (s[0] == '-')
return -ERANGE;
@@ -464,7 +536,7 @@ int safe_atoi16(const char *s, int16_t *ret) {
l = strtol(s, &x, 0);
if (errno > 0)
return -errno;
- if (!x || x == s || *x)
+ if (!x || x == s || *x != 0)
return -EINVAL;
if ((long) (int16_t) l != l)
return -ERANGE;
@@ -474,9 +546,9 @@ int safe_atoi16(const char *s, int16_t *ret) {
}
int safe_atod(const char *s, double *ret_d) {
+ _cleanup_(freelocalep) locale_t loc = (locale_t) 0;
char *x = NULL;
double d = 0;
- locale_t loc;
assert(s);
assert(ret_d);
@@ -487,16 +559,11 @@ int safe_atod(const char *s, double *ret_d) {
errno = 0;
d = strtod_l(s, &x, loc);
- if (errno > 0) {
- freelocale(loc);
+ if (errno > 0)
return -errno;
- }
- if (!x || x == s || *x) {
- freelocale(loc);
+ if (!x || x == s || *x != 0)
return -EINVAL;
- }
- freelocale(loc);
*ret_d = (double) d;
return 0;
}
@@ -539,19 +606,20 @@ int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
int parse_percent_unbounded(const char *p) {
const char *pc, *n;
- unsigned v;
- int r;
+ int r, v;
pc = endswith(p, "%");
if (!pc)
return -EINVAL;
n = strndupa(p, pc - p);
- r = safe_atou(n, &v);
+ r = safe_atoi(n, &v);
if (r < 0)
return r;
+ if (v < 0)
+ return -ERANGE;
- return (int) v;
+ return v;
}
int parse_percent(const char *p) {
@@ -564,6 +632,58 @@ int parse_percent(const char *p) {
return v;
}
+int parse_permille_unbounded(const char *p) {
+ const char *pc, *pm, *dot, *n;
+ int r, q, v;
+
+ pm = endswith(p, "‰");
+ if (pm) {
+ n = strndupa(p, pm - p);
+ r = safe_atoi(n, &v);
+ if (r < 0)
+ return r;
+ } else {
+ pc = endswith(p, "%");
+ if (!pc)
+ return -EINVAL;
+
+ dot = memchr(p, '.', pc - p);
+ if (dot) {
+ if (dot + 2 != pc)
+ return -EINVAL;
+ if (dot[1] < '0' || dot[1] > '9')
+ return -EINVAL;
+ q = dot[1] - '0';
+ n = strndupa(p, dot - p);
+ } else {
+ q = 0;
+ n = strndupa(p, pc - p);
+ }
+ r = safe_atoi(n, &v);
+ if (r < 0)
+ return r;
+ if (v > (INT_MAX - q) / 10)
+ return -ERANGE;
+
+ v = v * 10 + q;
+ }
+
+ if (v < 0)
+ return -ERANGE;
+
+ return v;
+}
+
+int parse_permille(const char *p) {
+ int v;
+
+ v = parse_permille_unbounded(p);
+ if (v > 1000)
+ return -ERANGE;
+
+ return v;
+}
+
#if 0 /// UNNEEDED by elogind
int parse_nice(const char *p, int *ret) {
int n, r;
@@ -610,3 +730,20 @@ int parse_dev(const char *s, dev_t *ret) {
*ret = d;
return 0;
}
+
+int parse_oom_score_adjust(const char *s, int *ret) {
+ int r, v;
+
+ assert(s);
+ assert(ret);
+
+ r = safe_atoi(s, &v);
+ if (r < 0)
+ return r;
+
+ if (v < OOM_SCORE_ADJ_MIN || v > OOM_SCORE_ADJ_MAX)
+ return -ERANGE;
+
+ *ret = v;
+ return 0;
+}
diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h
index ecbf4bdad..b9c718c27 100644
--- a/src/basic/parse-util.h
+++ b/src/basic/parse-util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 <limits.h>
#include <stddef.h>
@@ -34,23 +16,40 @@ int parse_dev(const char *s, dev_t *ret);
int parse_pid(const char *s, pid_t* ret_pid);
int parse_mode(const char *s, mode_t *ret);
int parse_ifindex(const char *s, int *ret);
+int parse_mtu(int family, const char *s, uint32_t *ret);
int parse_size(const char *t, uint64_t base, uint64_t *size);
#if 0 /// UNNEEDED by elogind
int parse_range(const char *t, unsigned *lower, unsigned *upper);
#endif // 0
+int parse_errno(const char *t);
+int parse_syscall_and_errno(const char *in, char **name, int *error);
#define FORMAT_BYTES_MAX 8
char *format_bytes(char *buf, size_t l, uint64_t t);
-int safe_atou(const char *s, unsigned *ret_u);
+int safe_atou_full(const char *s, unsigned base, unsigned *ret_u);
+
+static inline int safe_atou(const char *s, unsigned *ret_u) {
+ return safe_atou_full(s, 0, ret_u);
+}
+
int safe_atoi(const char *s, int *ret_i);
int safe_atollu(const char *s, unsigned long long *ret_u);
int safe_atolli(const char *s, long long int *ret_i);
int safe_atou8(const char *s, uint8_t *ret);
-int safe_atou16(const char *s, uint16_t *ret);
+int safe_atou16_full(const char *s, unsigned base, uint16_t *ret);
+
+static inline int safe_atou16(const char *s, uint16_t *ret) {
+ return safe_atou16_full(s, 0, ret);
+}
+
+static inline int safe_atoux16(const char *s, uint16_t *ret) {
+ return safe_atou16_full(s, 16, ret);
+}
+
int safe_atoi16(const char *s, int16_t *ret);
static inline int safe_atou32(const char *s, uint32_t *ret_u) {
@@ -112,8 +111,13 @@ int parse_fractional_part_u(const char **s, size_t digits, unsigned *res);
int parse_percent_unbounded(const char *p);
int parse_percent(const char *p);
+int parse_permille_unbounded(const char *p);
+int parse_permille(const char *p);
+
#if 0 /// UNNEEDED by elogind
int parse_nice(const char *p, int *ret);
int parse_ip_port(const char *s, uint16_t *ret);
#endif // 0
+
+int parse_oom_score_adjust(const char *s, int *ret);
diff --git a/src/basic/path-util.c b/src/basic/path-util.c
index acd1007e3..12e91c40a 100644
--- a/src/basic/path-util.c
+++ b/src/basic/path-util.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <limits.h>
@@ -34,14 +17,17 @@
#include "alloc-util.h"
#include "extract-word.h"
#include "fs-util.h"
+//#include "glob-util.h"
#include "log.h"
#include "macro.h"
#include "missing.h"
+#include "parse-util.h"
#include "path-util.h"
#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
+//#include "utf8.h"
bool path_is_absolute(const char *p) {
return p[0] == '/';
@@ -79,15 +65,37 @@ char *path_make_absolute(const char *p, const char *prefix) {
/* Makes every item in the list an absolute path by prepending
* the prefix, if specified and necessary */
- if (path_is_absolute(p) || !prefix)
+ if (path_is_absolute(p) || isempty(prefix))
return strdup(p);
- return strjoin(prefix, "/", p);
+ if (endswith(prefix, "/"))
+ return strjoin(prefix, p);
+ else
+ return strjoin(prefix, "/", p);
}
#endif // 0
+int safe_getcwd(char **ret) {
+ char *cwd;
+
+ cwd = get_current_dir_name();
+ if (!cwd)
+ return negative_errno();
+
+ /* Let's make sure the directory is really absolute, to protect us from the logic behind
+ * CVE-2018-1000001 */
+ if (cwd[0] != '/') {
+ free(cwd);
+ return -ENOMEDIUM;
+ }
+
+ *ret = cwd;
+ return 0;
+}
+
int path_make_absolute_cwd(const char *p, char **ret) {
char *c;
+ int r;
assert(p);
assert(ret);
@@ -100,11 +108,14 @@ int path_make_absolute_cwd(const char *p, char **ret) {
else {
_cleanup_free_ char *cwd = NULL;
- cwd = get_current_dir_name();
- if (!cwd)
- return negative_errno();
+ r = safe_getcwd(&cwd);
+ if (r < 0)
+ return r;
- c = strjoin(cwd, "/", p);
+ if (endswith(cwd, "/"))
+ c = strjoin(cwd, p);
+ else
+ c = strjoin(cwd, "/", p);
}
if (!c)
return -ENOMEM;
@@ -115,8 +126,8 @@ int path_make_absolute_cwd(const char *p, char **ret) {
#if 0 /// UNNEEDED by elogind
int path_make_relative(const char *from_dir, const char *to_path, char **_r) {
- char *r, *p;
- unsigned n_parents;
+ char *f, *t, *r, *p;
+ unsigned n_parents = 0;
assert(from_dir);
assert(to_path);
@@ -124,76 +135,81 @@ int path_make_relative(const char *from_dir, const char *to_path, char **_r) {
/* Strips the common part, and adds ".." elements as necessary. */
- if (!path_is_absolute(from_dir))
+ if (!path_is_absolute(from_dir) || !path_is_absolute(to_path))
return -EINVAL;
- if (!path_is_absolute(to_path))
- return -EINVAL;
+ f = strdupa(from_dir);
+ t = strdupa(to_path);
+
+ path_simplify(f, true);
+ path_simplify(t, true);
/* Skip the common part. */
for (;;) {
- size_t a;
- size_t b;
+ size_t a, b;
- from_dir += strspn(from_dir, "/");
- to_path += strspn(to_path, "/");
+ f += *f == '/';
+ t += *t == '/';
- if (!*from_dir) {
- if (!*to_path)
+ if (!*f) {
+ if (!*t)
/* from_dir equals to_path. */
r = strdup(".");
else
/* from_dir is a parent directory of to_path. */
- r = strdup(to_path);
-
+ r = strdup(t);
if (!r)
return -ENOMEM;
- path_kill_slashes(r);
-
*_r = r;
return 0;
}
- if (!*to_path)
+ if (!*t)
break;
- a = strcspn(from_dir, "/");
- b = strcspn(to_path, "/");
-
- if (a != b)
- break;
+ a = strcspn(f, "/");
+ b = strcspn(t, "/");
- if (memcmp(from_dir, to_path, a) != 0)
+ if (a != b || memcmp(f, t, a) != 0)
break;
- from_dir += a;
- to_path += b;
+ f += a;
+ t += b;
}
/* If we're here, then "from_dir" has one or more elements that need to
* be replaced with "..". */
/* Count the number of necessary ".." elements. */
- for (n_parents = 0;;) {
- from_dir += strspn(from_dir, "/");
+ for (; *f;) {
+ size_t w;
- if (!*from_dir)
- break;
+ w = strcspn(f, "/");
+
+ /* If this includes ".." we can't do a simple series of "..", refuse */
+ if (w == 2 && f[0] == '.' && f[1] == '.')
+ return -EINVAL;
- from_dir += strcspn(from_dir, "/");
+ /* Count number of elements */
n_parents++;
+
+ f += w;
+ f += *f == '/';
}
- r = malloc(n_parents * 3 + strlen(to_path) + 1);
+ r = new(char, n_parents * 3 + strlen(t) + 1);
if (!r)
return -ENOMEM;
- for (p = r; n_parents > 0; n_parents--, p += 3)
- memcpy(p, "../", 3);
+ for (p = r; n_parents > 0; n_parents--)
+ p = mempcpy(p, "../", 3);
- strcpy(p, to_path);
- path_kill_slashes(r);
+ if (*t)
+ strcpy(p, t);
+ else
+ /* Remove trailing slash */
+ *(--p) = 0;
*_r = r;
return 0;
@@ -214,8 +230,8 @@ int path_strv_make_absolute_cwd(char **l) {
if (r < 0)
return r;
- free(*s);
- *s = t;
+ path_simplify(t, false);
+ free_and_replace(*s, t);
}
return 0;
@@ -257,8 +273,7 @@ char **path_strv_resolve(char **l, const char *root) {
r = chase_symlinks(t, root, 0, &u);
if (r == -ENOENT) {
if (root) {
- u = orig;
- orig = NULL;
+ u = TAKE_PTR(orig);
free(t);
} else
u = t;
@@ -316,17 +331,30 @@ char **path_strv_resolve_uniq(char **l, const char *root) {
return strv_uniq(l);
}
-char *path_kill_slashes(char *path) {
+char *path_simplify(char *path, bool kill_dots) {
char *f, *t;
- bool slash = false;
+ bool slash = false, ignore_slash = false, absolute;
+
+ assert(path);
- /* Removes redundant inner and trailing slashes. Modifies the
- * passed string in-place.
+ /* Removes redundant inner and trailing slashes. Also removes unnecessary dots
+ * if kill_dots is true. Modifies the passed string in-place.
*
- * ///foo///bar/ becomes /foo/bar
+ * ///foo//./bar/. becomes /foo/./bar/. (if kill_dots is false)
+ * ///foo//./bar/. becomes /foo/bar (if kill_dots is true)
+ * .//./foo//./bar/. becomes ./foo/bar (if kill_dots is false)
+ * .//./foo//./bar/. becomes foo/bar (if kill_dots is true)
*/
- for (f = path, t = path; *f; f++) {
+ absolute = path_is_absolute(path);
+
+ f = path;
+ if (kill_dots && *f == '.' && IN_SET(f[1], 0, '/')) {
+ ignore_slash = true;
+ f++;
+ }
+
+ for (t = path; *f; f++) {
if (*f == '/') {
slash = true;
@@ -334,17 +362,21 @@ char *path_kill_slashes(char *path) {
}
if (slash) {
+ if (kill_dots && *f == '.' && IN_SET(f[1], 0, '/'))
+ continue;
+
slash = false;
- *(t++) = '/';
+ if (ignore_slash)
+ ignore_slash = false;
+ else
+ *(t++) = '/';
}
*(t++) = *f;
}
- /* Special rule, if we are talking of the root directory, a
- trailing slash is good */
-
- if (t == path && slash)
+ /* Special rule, if we are talking of the root directory, a trailing slash is good */
+ if (absolute && t == path)
*(t++) = '/';
*t = 0;
@@ -511,7 +543,7 @@ int find_binary(const char *name, char **ret) {
/* Found it! */
if (ret) {
- *ret = path_kill_slashes(j);
+ *ret = path_simplify(j, false);
j = NULL;
}
@@ -531,7 +563,7 @@ bool paths_check_timestamp(const char* const* paths, usec_t *timestamp, bool upd
assert(timestamp);
- if (paths == NULL)
+ if (!paths)
return false;
STRV_FOREACH(i, paths) {
@@ -623,7 +655,7 @@ char *prefix_root(const char *root, const char *path) {
while (path[0] == '/' && path[1] == '/')
path++;
- if (isempty(root) || path_equal(root, "/"))
+ if (empty_or_root(root))
return strdup(path);
l = strlen(root) + 1 + strlen(path) + 1;
@@ -668,12 +700,12 @@ int parse_path_argument_and_warn(const char *path, bool suppress_root, char **ar
if (r < 0)
return log_error_errno(r, "Failed to parse path \"%s\" and make it absolute: %m", path);
- path_kill_slashes(p);
- if (suppress_root && path_equal(p, "/"))
+ path_simplify(p, false);
+ if (suppress_root && empty_or_root(p))
p = mfree(p);
- free(*arg);
- *arg = p;
+ free_and_replace(*arg, p);
+
return 0;
}
#endif // 0
@@ -699,6 +731,44 @@ char* dirname_malloc(const char *path) {
return dir2;
}
+const char *last_path_component(const char *path) {
+
+ /* Finds the last component of the path, preserving the optional trailing slash that signifies a directory.
+ *
+ * a/b/c → c
+ * a/b/c/ → c/
+ * x → x
+ * x/ → x/
+ * /y → y
+ * /y/ → y/
+ * / → /
+ * // → /
+ * /foo/a → a
+ * /foo/a/ → a/
+ *
+ * Also, the empty string is mapped to itself.
+ *
+ * This is different than basename(), which returns "" when a trailing slash is present.
+ */
+
+ unsigned l, k;
+
+ l = k = strlen(path);
+ if (l == 0) /* special case — an empty string */
+ return path;
+
+ while (k > 0 && path[k-1] == '/')
+ k--;
+
+ if (k == 0) /* the root directory */
+ return path + l - 1;
+
+ while (k > 0 && path[k-1] != '/')
+ k--;
+
+ return path + k;
+}
+
bool filename_is_valid(const char *p) {
const char *e;
@@ -718,7 +788,7 @@ bool filename_is_valid(const char *p) {
return true;
}
-bool path_is_safe(const char *p) {
+bool path_is_normalized(const char *p) {
if (isempty(p))
return false;
@@ -732,7 +802,6 @@ bool path_is_safe(const char *p) {
if (strlen(p)+1 > PATH_MAX)
return false;
- /* The following two checks are not really dangerous, but hey, they still are confusing */
if (startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
return false;
@@ -821,17 +890,36 @@ bool hidden_or_backup_file(const char *filename) {
#if 0 /// UNNEEDED by elogind
bool is_device_path(const char *path) {
- /* Returns true on paths that refer to a device, either in
- * sysfs or in /dev */
+ /* Returns true on paths that likely refer to a device, either by path in sysfs or to something in /dev */
- return path_startswith(path, "/dev/") ||
- path_startswith(path, "/sys/");
+ return PATH_STARTSWITH_SET(path, "/dev/", "/sys/");
}
-bool is_deviceallow_pattern(const char *path) {
- return path_startswith(path, "/dev/") ||
- startswith(path, "block-") ||
- startswith(path, "char-");
+bool valid_device_node_path(const char *path) {
+
+ /* Some superficial checks whether the specified path is a valid device node path, all without looking at the
+ * actual device node. */
+
+ if (!PATH_STARTSWITH_SET(path, "/dev/", "/run/systemd/inaccessible/"))
+ return false;
+
+ if (endswith(path, "/")) /* can't be a device node if it ends in a slash */
+ return false;
+
+ return path_is_normalized(path);
+}
+
+bool valid_device_allow_pattern(const char *path) {
+ assert(path);
+
+ /* Like valid_device_node_path(), but also allows full-subsystem expressions, like DeviceAllow= and DeviceDeny=
+ * accept it */
+
+ if (startswith(path, "block-") ||
+ startswith(path, "char-"))
+ return true;
+
+ return valid_device_node_path(path);
}
int systemd_installation_has_version(const char *root, unsigned minimal_version) {
@@ -849,7 +937,9 @@ int systemd_installation_has_version(const char *root, unsigned minimal_version)
* for Gentoo which does a merge without making /lib a symlink.
*/
"lib/systemd/libsystemd-shared-*.so\0"
- "usr/lib/systemd/libsystemd-shared-*.so\0") {
+ "lib64/systemd/libsystemd-shared-*.so\0"
+ "usr/lib/systemd/libsystemd-shared-*.so\0"
+ "usr/lib64/systemd/libsystemd-shared-*.so\0") {
_cleanup_strv_free_ char **names = NULL;
_cleanup_free_ char *path = NULL;
@@ -865,7 +955,7 @@ int systemd_installation_has_version(const char *root, unsigned minimal_version)
if (r < 0)
return r;
- assert_se((c = endswith(path, "*.so")));
+ assert_se(c = endswith(path, "*.so"));
*c = '\0'; /* truncate the glob part */
STRV_FOREACH(name, names) {
@@ -913,3 +1003,63 @@ bool dot_or_dot_dot(const char *path) {
return path[2] == 0;
}
+
+bool empty_or_root(const char *root) {
+
+ /* For operations relative to some root directory, returns true if the specified root directory is redundant,
+ * i.e. either / or NULL or the empty string or any equivalent. */
+
+ if (!root)
+ return true;
+
+ return root[strspn(root, "/")] == 0;
+}
+
+#if 0 /// UNNEEDED by elogind
+int path_simplify_and_warn(
+ char *path,
+ unsigned flag,
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *lvalue) {
+
+ bool absolute, fatal = flag & PATH_CHECK_FATAL;
+
+ assert(!FLAGS_SET(flag, PATH_CHECK_ABSOLUTE | PATH_CHECK_RELATIVE));
+
+ if (!utf8_is_valid(path)) {
+ log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, path);
+ return -EINVAL;
+ }
+
+ if (flag & (PATH_CHECK_ABSOLUTE | PATH_CHECK_RELATIVE)) {
+ absolute = path_is_absolute(path);
+
+ if (!absolute && (flag & PATH_CHECK_ABSOLUTE)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "%s= path is not absolute%s: %s",
+ lvalue, fatal ? "" : ", ignoring", path);
+ return -EINVAL;
+ }
+
+ if (absolute && (flag & PATH_CHECK_RELATIVE)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "%s= path is absolute%s: %s",
+ lvalue, fatal ? "" : ", ignoring", path);
+ return -EINVAL;
+ }
+ }
+
+ path_simplify(path, true);
+
+ if (!path_is_normalized(path)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "%s= path is not normalized%s: %s",
+ lvalue, fatal ? "" : ", ignoring", path);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+#endif // 0
diff --git a/src/basic/path-util.h b/src/basic/path-util.h
index 3c0dbb321..fd571e9ca 100644
--- a/src/basic/path-util.h
+++ b/src/basic/path-util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010-2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <alloca.h>
#include <stdbool.h>
#include <stddef.h>
@@ -27,13 +9,32 @@
#include "string-util.h"
#include "time-util.h"
-#define DEFAULT_PATH_NORMAL "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin"
-#define DEFAULT_PATH_SPLIT_USR DEFAULT_PATH_NORMAL ":/sbin:/bin"
+#define PATH_SPLIT_SBIN_BIN(x) x "sbin:" x "bin"
+#define PATH_SPLIT_SBIN_BIN_NULSTR(x) x "sbin\0" x "bin\0"
+
+#define PATH_NORMAL_SBIN_BIN(x) x "bin"
+#define PATH_NORMAL_SBIN_BIN_NULSTR(x) x "bin\0"
-#ifdef HAVE_SPLIT_USR
+#if HAVE_SPLIT_BIN
+# define PATH_SBIN_BIN(x) PATH_SPLIT_SBIN_BIN(x)
+# define PATH_SBIN_BIN_NULSTR(x) PATH_SPLIT_SBIN_BIN_NULSTR(x)
+#else
+# define PATH_SBIN_BIN(x) PATH_NORMAL_SBIN_BIN(x)
+# define PATH_SBIN_BIN_NULSTR(x) PATH_NORMAL_SBIN_BIN_NULSTR(x)
+#endif
+
+#define DEFAULT_PATH_NORMAL PATH_SBIN_BIN("/usr/local/") ":" PATH_SBIN_BIN("/usr/")
+#define DEFAULT_PATH_NORMAL_NULSTR PATH_SBIN_BIN_NULSTR("/usr/local/") PATH_SBIN_BIN_NULSTR("/usr/")
+#define DEFAULT_PATH_SPLIT_USR DEFAULT_PATH_NORMAL ":" PATH_SBIN_BIN("/")
+#define DEFAULT_PATH_SPLIT_USR_NULSTR DEFAULT_PATH_NORMAL_NULSTR PATH_SBIN_BIN_NULSTR("/")
+#define DEFAULT_PATH_COMPAT PATH_SPLIT_SBIN_BIN("/usr/local/") ":" PATH_SPLIT_SBIN_BIN("/usr/") ":" PATH_SPLIT_SBIN_BIN("/")
+
+#if HAVE_SPLIT_USR
# define DEFAULT_PATH DEFAULT_PATH_SPLIT_USR
+# define DEFAULT_PATH_NULSTR DEFAULT_PATH_SPLIT_USR_NULSTR
#else
# define DEFAULT_PATH DEFAULT_PATH_NORMAL
+# define DEFAULT_PATH_NULSTR DEFAULT_PATH_NORMAL_NULSTR
#endif
bool is_path(const char *p) _pure_;
@@ -44,16 +45,17 @@ bool path_is_absolute(const char *p) _pure_;
#if 0 /// UNNEEDED by elogind
char* path_make_absolute(const char *p, const char *prefix);
#endif // 0
+int safe_getcwd(char **ret);
int path_make_absolute_cwd(const char *p, char **ret);
#if 0 /// UNNEEDED by elogind
int path_make_relative(const char *from_dir, const char *to_path, char **_r);
#endif // 0
-char* path_kill_slashes(char *path);
char* path_startswith(const char *path, const char *prefix) _pure_;
int path_compare(const char *a, const char *b) _pure_;
bool path_equal(const char *a, const char *b) _pure_;
bool path_equal_or_files_same(const char *a, const char *b, int flags);
char* path_join(const char *root, const char *path, const char *rest);
+char* path_simplify(char *path, bool kill_dots);
static inline bool path_equal_ptr(const char *a, const char *b) {
return !!a == !!b && (!a || path_equal(a, b));
@@ -103,11 +105,11 @@ int mkfs_exists(const char *fstype);
* the tree, to root. Also returns "" (and not "/"!) for the root
* directory. Excludes the specified directory itself */
#define PATH_FOREACH_PREFIX(prefix, path) \
- for (char *_slash = ({ path_kill_slashes(strcpy(prefix, path)); streq(prefix, "/") ? NULL : strrchr(prefix, '/'); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/'))
+ for (char *_slash = ({ path_simplify(strcpy(prefix, path), false); streq(prefix, "/") ? NULL : strrchr(prefix, '/'); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/'))
/* Same as PATH_FOREACH_PREFIX but also includes the specified path itself */
#define PATH_FOREACH_PREFIX_MORE(prefix, path) \
- for (char *_slash = ({ path_kill_slashes(strcpy(prefix, path)); if (streq(prefix, "/")) prefix[0] = 0; strrchr(prefix, 0); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/'))
+ for (char *_slash = ({ path_simplify(strcpy(prefix, path), false); if (streq(prefix, "/")) prefix[0] = 0; strrchr(prefix, 0); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/'))
char *prefix_root(const char *root, const char *path);
@@ -120,7 +122,7 @@ char *prefix_root(const char *root, const char *path);
size_t _l; \
while (_path[0] == '/' && _path[1] == '/') \
_path ++; \
- if (isempty(_root) || path_equal(_root, "/")) \
+ if (empty_or_root(_root)) \
_ret = _path; \
else { \
_l = strlen(_root) + 1 + strlen(_path) + 1; \
@@ -141,9 +143,10 @@ int parse_path_argument_and_warn(const char *path, bool suppress_root, char **ar
#endif // 0
char* dirname_malloc(const char *path);
+const char *last_path_component(const char *path);
bool filename_is_valid(const char *p) _pure_;
-bool path_is_safe(const char *p) _pure_;
+bool path_is_normalized(const char *p) _pure_;
char *file_in_same_dir(const char *path, const char *filename);
@@ -151,9 +154,36 @@ bool hidden_or_backup_file(const char *filename) _pure_;
#if 0 /// UNNEEDED by elogind
bool is_device_path(const char *path);
-bool is_deviceallow_pattern(const char *path);
+
+bool valid_device_node_path(const char *path);
+bool valid_device_allow_pattern(const char *path);
int systemd_installation_has_version(const char *root, unsigned minimal_version);
#endif // 0
bool dot_or_dot_dot(const char *path);
+
+static inline const char *skip_dev_prefix(const char *p) {
+ const char *e;
+
+ /* Drop any /dev prefix if there is any */
+
+ e = path_startswith(p, "/dev/");
+
+ return e ?: p;
+}
+
+bool empty_or_root(const char *root);
+static inline const char *empty_to_root(const char *path) {
+ return isempty(path) ? "/" : path;
+}
+
+#if 0 /// UNNEEDED by elogind
+enum {
+ PATH_CHECK_FATAL = 1 << 0, /* If not set, then error message is appended with 'ignoring'. */
+ PATH_CHECK_ABSOLUTE = 1 << 1,
+ PATH_CHECK_RELATIVE = 1 << 2,
+};
+
+int path_simplify_and_warn(char *path, unsigned flag, const char *unit, const char *filename, unsigned line, const char *lvalue);
+#endif // 0
diff --git a/src/basic/prioq.c b/src/basic/prioq.c
index 4570b8e4b..ef28a086d 100644
--- a/src/basic/prioq.c
+++ b/src/basic/prioq.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
/*
* Priority Queue
@@ -172,7 +155,7 @@ int prioq_put(Prioq *q, void *data, unsigned *idx) {
struct prioq_item *j;
n = MAX((q->n_items+1) * 2, 16u);
- j = realloc(q->items, sizeof(struct prioq_item) * n);
+ j = reallocarray(q->items, n, sizeof(struct prioq_item));
if (!j)
return -ENOMEM;
diff --git a/src/basic/prioq.h b/src/basic/prioq.h
index 113c73d04..e03617526 100644
--- a/src/basic/prioq.h
+++ b/src/basic/prioq.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 "hashmap.h"
diff --git a/src/basic/proc-cmdline.c b/src/basic/proc-cmdline.c
index e2eba45a3..ae3323379 100644
--- a/src/basic/proc-cmdline.c
+++ b/src/basic/proc-cmdline.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <stdbool.h>
#include <stddef.h>
@@ -206,10 +189,8 @@ int proc_cmdline_get_key(const char *key, unsigned flags, char **value) {
}
}
- if (value) {
- *value = ret;
- ret = NULL;
- }
+ if (value)
+ *value = TAKE_PTR(ret);
return found;
}
@@ -273,17 +254,21 @@ static const char * const rlmap_initrd[] = {
};
const char* runlevel_to_target(const char *word) {
+ const char * const *rlmap_ptr;
size_t i;
- const char * const *rlmap_ptr = in_initrd() ? rlmap_initrd
- : rlmap;
if (!word)
return NULL;
- if (in_initrd() && (word = startswith(word, "rd.")) == NULL)
- return NULL;
+ if (in_initrd()) {
+ word = startswith(word, "rd.");
+ if (!word)
+ return NULL;
+ }
+
+ rlmap_ptr = in_initrd() ? rlmap_initrd : rlmap;
- for (i = 0; rlmap_ptr[i] != NULL; i += 2)
+ for (i = 0; rlmap_ptr[i]; i += 2)
if (streq(word, rlmap_ptr[i]))
return rlmap_ptr[i+1];
diff --git a/src/basic/proc-cmdline.h b/src/basic/proc-cmdline.h
index 46d0d76ff..5cb323f79 100644
--- a/src/basic/proc-cmdline.h
+++ b/src/basic/proc-cmdline.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 "log.h"
diff --git a/src/basic/process-util.c b/src/basic/process-util.c
index da825a7c3..77d76958c 100644
--- a/src/basic/process-util.c
+++ b/src/basic/process-util.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <ctype.h>
#include <errno.h>
@@ -25,15 +8,18 @@
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
+#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/mman.h>
+#include <sys/mount.h>
#include <sys/personality.h>
#include <sys/prctl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <syslog.h>
#include <unistd.h>
-#ifdef HAVE_VALGRIND_VALGRIND_H
+#if HAVE_VALGRIND_VALGRIND_H
#include <valgrind/valgrind.h>
#endif
@@ -48,10 +34,12 @@
#include "macro.h"
#include "missing.h"
#include "process-util.h"
+#include "raw-clone.h"
#include "signal-util.h"
//#include "stat-util.h"
#include "string-table.h"
#include "string-util.h"
+//#include "terminal-util.h"
#include "user-util.h"
#include "util.h"
@@ -83,20 +71,31 @@ int get_process_state(pid_t pid) {
return (unsigned char) state;
}
-int get_process_comm(pid_t pid, char **name) {
+int get_process_comm(pid_t pid, char **ret) {
+ _cleanup_free_ char *escaped = NULL, *comm = NULL;
const char *p;
int r;
- assert(name);
+ assert(ret);
assert(pid >= 0);
+ escaped = new(char, TASK_COMM_LEN);
+ if (!escaped)
+ return -ENOMEM;
+
p = procfs_file_alloca(pid, "comm");
- r = read_one_line_file(p, name);
+ r = read_one_line_file(p, &comm);
if (r == -ENOENT)
return -ESRCH;
+ if (r < 0)
+ return r;
- return r;
+ /* Escape unprintable characters, just in case, but don't grow the string beyond the underlying size */
+ cellescape(escaped, TASK_COMM_LEN, comm);
+
+ *ret = TAKE_PTR(escaped);
+ return 0;
}
int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
@@ -127,6 +126,8 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
return -errno;
}
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
if (max_length == 1) {
/* If there's only room for one byte, return the empty string */
@@ -252,15 +253,10 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
memcpy(ans, "[...]", max_length-1);
ans[max_length-1] = 0;
} else {
- char *e;
-
t[max_length - 6] = 0;
/* Chop off final spaces */
- e = strchr(t, 0);
- while (e > t && isspace(e[-1]))
- e--;
- *e = 0;
+ delete_trailing_chars(t, WHITESPACE);
ans = strjoin("[", t, "...]");
}
@@ -273,7 +269,6 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
return 0;
}
-#if 0 /// UNNEEDED by elogind
int rename_process(const char name[]) {
static size_t mm_size = 0;
static char *mm = NULL;
@@ -291,11 +286,18 @@ int rename_process(const char name[]) {
if (isempty(name))
return -EINVAL; /* let's not confuse users unnecessarily with an empty name */
+ if (!is_main_thread())
+ return -EPERM; /* Let's not allow setting the process name from other threads than the main one, as we
+ * cache things without locking, and we make assumptions that PR_SET_NAME sets the
+ * process name that isn't correct on any other threads */
+
l = strlen(name);
- /* First step, change the comm field. */
- (void) prctl(PR_SET_NAME, name);
- if (l > 15) /* Linux process names can be 15 chars at max */
+ /* First step, change the comm field. The main thread's comm is identical to the process comm. This means we
+ * can use PR_SET_NAME, which sets the thread name for the calling thread. */
+ if (prctl(PR_SET_NAME, name) < 0)
+ log_debug_errno(errno, "PR_SET_NAME failed: %m");
+ if (l >= TASK_COMM_LEN) /* Linux process names can be 15 chars at max */
truncated = true;
/* Second step, change glibc's ID of the process name. */
@@ -311,19 +313,18 @@ int rename_process(const char name[]) {
/* Third step, completely replace the argv[] array the kernel maintains for us. This requires privileges, but
* has the advantage that the argv[] array is exactly what we want it to be, and not filled up with zeros at
* the end. This is the best option for changing /proc/self/cmdline. */
- if (mm_size < l+1) {
+
+ /* Let's not bother with this if we don't have euid == 0. Strictly speaking we should check for the
+ * CAP_SYS_RESOURCE capability which is independent of the euid. In our own code the capability generally is
+ * present only for euid == 0, hence let's use this as quick bypass check, to avoid calling mmap() if
+ * PR_SET_MM_ARG_{START,END} fails with EPERM later on anyway. After all geteuid() is dead cheap to call, but
+ * mmap() is not. */
+ if (geteuid() != 0)
+ log_debug("Skipping PR_SET_MM, as we don't have privileges.");
+ else if (mm_size < l+1) {
size_t nn_size;
char *nn;
- /* Let's not bother with this if we don't have euid == 0. Strictly speaking if people do weird stuff
- * with capabilities this could work even for euid != 0, but our own code generally doesn't do that,
- * hence let's use this as quick bypass check, to avoid calling mmap() if PR_SET_MM_ARG_START fails
- * with EPERM later on anyway. After all geteuid() is dead cheap to call, but mmap() is not. */
- if (geteuid() != 0) {
- log_debug("Skipping PR_SET_MM_ARG_START, as we don't have privileges.");
- goto use_saved_argv;
- }
-
nn_size = PAGE_ALIGN(l+1);
nn = mmap(NULL, nn_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (nn == MAP_FAILED) {
@@ -350,9 +351,14 @@ int rename_process(const char name[]) {
mm = nn;
mm_size = nn_size;
- } else
+ } else {
strncpy(mm, name, mm_size);
+ /* Update the end pointer, continuing regardless of any failure. */
+ if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) mm + l + 1, 0, 0) < 0)
+ log_debug_errno(errno, "PR_SET_MM_ARG_END failed, proceeding without: %m");
+ }
+
use_saved_argv:
/* Fourth step: in all cases we'll also update the original argv[], so that our own code gets it right too if
* it still looks here */
@@ -379,38 +385,63 @@ use_saved_argv:
return !truncated;
}
-#endif // 0
int is_kernel_thread(pid_t pid) {
+ _cleanup_free_ char *line = NULL;
+ unsigned long long flags;
+ size_t l, i;
const char *p;
- size_t count;
- char c;
- bool eof;
- FILE *f;
+ char *q;
+ int r;
- if (pid == 0 || pid == 1) /* pid 1, and we ourselves certainly aren't a kernel thread */
+ if (IN_SET(pid, 0, 1) || pid == getpid_cached()) /* pid 1, and we ourselves certainly aren't a kernel thread */
return 0;
+ if (!pid_is_valid(pid))
+ return -EINVAL;
- assert(pid > 1);
+ p = procfs_file_alloca(pid, "stat");
+ r = read_one_line_file(p, &line);
+ if (r == -ENOENT)
+ return -ESRCH;
+ if (r < 0)
+ return r;
- p = procfs_file_alloca(pid, "cmdline");
- f = fopen(p, "re");
- if (!f) {
- if (errno == ENOENT)
- return -ESRCH;
- return -errno;
+ /* Skip past the comm field */
+ q = strrchr(line, ')');
+ if (!q)
+ return -EINVAL;
+ q++;
+
+ /* Skip 6 fields to reach the flags field */
+ for (i = 0; i < 6; i++) {
+ l = strspn(q, WHITESPACE);
+ if (l < 1)
+ return -EINVAL;
+ q += l;
+
+ l = strcspn(q, WHITESPACE);
+ if (l < 1)
+ return -EINVAL;
+ q += l;
}
- count = fread(&c, 1, 1, f);
- eof = feof(f);
- fclose(f);
+ /* Skip preceeding whitespace */
+ l = strspn(q, WHITESPACE);
+ if (l < 1)
+ return -EINVAL;
+ q += l;
- /* Kernel threads have an empty cmdline */
+ /* Truncate the rest */
+ l = strcspn(q, WHITESPACE);
+ if (l < 1)
+ return -EINVAL;
+ q[l] = 0;
- if (count <= 0)
- return eof ? 1 : -errno;
+ r = safe_atollu(q, &flags);
+ if (r < 0)
+ return r;
- return 0;
+ return !!(flags & PF_KTHREAD);
}
#if 0 /// UNNEEDED by elogind
@@ -474,6 +505,9 @@ static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
assert(field);
assert(uid);
+ if (pid < 0)
+ return -EINVAL;
+
p = procfs_file_alloca(pid, "status");
f = fopen(p, "re");
if (!f) {
@@ -482,6 +516,8 @@ static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
return -errno;
}
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
FOREACH_LINE(line, f, return -errno) {
char *l;
@@ -501,10 +537,22 @@ static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
}
int get_process_uid(pid_t pid, uid_t *uid) {
+
+ if (pid == 0 || pid == getpid_cached()) {
+ *uid = getuid();
+ return 0;
+ }
+
return get_process_id(pid, "Uid:", uid);
}
int get_process_gid(pid_t pid, gid_t *gid) {
+
+ if (pid == 0 || pid == getpid_cached()) {
+ *gid = getgid();
+ return 0;
+ }
+
assert_cc(sizeof(uid_t) == sizeof(gid_t));
return get_process_id(pid, "Gid:", gid);
}
@@ -548,6 +596,8 @@ int get_process_environ(pid_t pid, char **env) {
return -errno;
}
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
while ((c = fgetc(f)) != EOF) {
if (!GREEDY_REALLOC(outcome, allocated, sz + 5))
return -ENOMEM;
@@ -565,8 +615,7 @@ int get_process_environ(pid_t pid, char **env) {
} else
outcome[sz] = '\0';
- *env = outcome;
- outcome = NULL;
+ *env = TAKE_PTR(outcome);
return 0;
}
@@ -580,7 +629,7 @@ int get_process_ppid(pid_t pid, pid_t *_ppid) {
assert(pid >= 0);
assert(_ppid);
- if (pid == 0) {
+ if (pid == 0 || pid == getpid_cached()) {
*_ppid = getppid();
return 0;
}
@@ -654,33 +703,107 @@ int wait_for_terminate(pid_t pid, siginfo_t *status) {
* A warning is emitted if the process terminates abnormally,
* and also if it returns non-zero unless check_exit_code is true.
*/
-int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code) {
- int r;
+int wait_for_terminate_and_check(const char *name, pid_t pid, WaitFlags flags) {
+ _cleanup_free_ char *buffer = NULL;
siginfo_t status;
+ int r, prio;
- assert(name);
assert(pid > 1);
+ if (!name) {
+ r = get_process_comm(pid, &buffer);
+ if (r < 0)
+ log_debug_errno(r, "Failed to acquire process name of " PID_FMT ", ignoring: %m", pid);
+ else
+ name = buffer;
+ }
+
+ prio = flags & WAIT_LOG_ABNORMAL ? LOG_ERR : LOG_DEBUG;
+
r = wait_for_terminate(pid, &status);
if (r < 0)
- return log_warning_errno(r, "Failed to wait for %s: %m", name);
+ return log_full_errno(prio, r, "Failed to wait for %s: %m", strna(name));
if (status.si_code == CLD_EXITED) {
- if (status.si_status != 0)
- log_full(check_exit_code ? LOG_WARNING : LOG_DEBUG,
- "%s failed with error code %i.", name, status.si_status);
+ if (status.si_status != EXIT_SUCCESS)
+ log_full(flags & WAIT_LOG_NON_ZERO_EXIT_STATUS ? LOG_ERR : LOG_DEBUG,
+ "%s failed with exit status %i.", strna(name), status.si_status);
else
log_debug("%s succeeded.", name);
return status.si_status;
- } 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));
+ } else if (IN_SET(status.si_code, CLD_KILLED, CLD_DUMPED)) {
+
+ log_full(prio, "%s terminated by signal %s.", strna(name), signal_to_string(status.si_status));
return -EPROTO;
}
- log_warning("%s failed due to unknown reason.", name);
+ log_full(prio, "%s failed due to unknown reason.", strna(name));
+ return -EPROTO;
+}
+
+/*
+ * Return values:
+ *
+ * < 0 : wait_for_terminate_with_timeout() failed to get the state of the process, the process timed out, the process
+ * was terminated by a signal, or failed for an unknown reason.
+ *
+ * >=0 : The process terminated normally with no failures.
+ *
+ * Success is indicated by a return value of zero, a timeout is indicated by ETIMEDOUT, and all other child failure
+ * states are indicated by error is indicated by a non-zero value.
+ *
+ * This call assumes SIGCHLD has been blocked already, in particular before the child to wait for has been forked off
+ * to remain entirely race-free.
+ */
+int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout) {
+ sigset_t mask;
+ int r;
+ usec_t until;
+
+ assert_se(sigemptyset(&mask) == 0);
+ assert_se(sigaddset(&mask, SIGCHLD) == 0);
+
+ /* Drop into a sigtimewait-based timeout. Waiting for the
+ * pid to exit. */
+ until = now(CLOCK_MONOTONIC) + timeout;
+ for (;;) {
+ usec_t n;
+ siginfo_t status = {};
+ struct timespec ts;
+
+ n = now(CLOCK_MONOTONIC);
+ if (n >= until)
+ break;
+
+ r = sigtimedwait(&mask, NULL, timespec_store(&ts, until - n)) < 0 ? -errno : 0;
+ /* Assuming we woke due to the child exiting. */
+ if (waitid(P_PID, pid, &status, WEXITED|WNOHANG) == 0) {
+ if (status.si_pid == pid) {
+ /* This is the correct child.*/
+ if (status.si_code == CLD_EXITED)
+ return (status.si_status == 0) ? 0 : -EPROTO;
+ else
+ return -EPROTO;
+ }
+ }
+ /* Not the child, check for errors and proceed appropriately */
+ if (r < 0) {
+ switch (r) {
+ case -EAGAIN:
+ /* Timed out, child is likely hung. */
+ return -ETIMEDOUT;
+ case -EINTR:
+ /* Received a different signal and should retry */
+ continue;
+ default:
+ /* Return any unexpected errors */
+ return r;
+ }
+ }
+ }
+
return -EPROTO;
}
@@ -693,6 +816,8 @@ void sigkill_wait(pid_t pid) {
}
void sigkill_waitp(pid_t *pid) {
+ PROTECT_ERRNO;
+
if (!pid)
return;
if (*pid <= 1)
@@ -700,6 +825,14 @@ void sigkill_waitp(pid_t *pid) {
sigkill_wait(*pid);
}
+#endif // 0
+
+void sigterm_wait(pid_t pid) {
+ assert(pid > 1);
+
+ if (kill_and_sigcont(pid, SIGTERM) > 0)
+ (void) wait_for_terminate(pid, NULL);
+}
int kill_and_sigcont(pid_t pid, int sig) {
int r;
@@ -713,19 +846,34 @@ int kill_and_sigcont(pid_t pid, int sig) {
return r;
}
-#endif // 0
-int getenv_for_pid(pid_t pid, const char *field, char **_value) {
+int getenv_for_pid(pid_t pid, const char *field, char **ret) {
_cleanup_fclose_ FILE *f = NULL;
char *value = NULL;
- int r;
bool done = false;
- size_t l;
const char *path;
+ size_t l;
assert(pid >= 0);
assert(field);
- assert(_value);
+ assert(ret);
+
+ if (pid == 0 || pid == getpid_cached()) {
+ const char *e;
+
+ e = getenv(field);
+ if (!e) {
+ *ret = NULL;
+ return 0;
+ }
+
+ value = strdup(e);
+ if (!value)
+ return -ENOMEM;
+
+ *ret = value;
+ return 1;
+ }
path = procfs_file_alloca(pid, "environ");
@@ -733,15 +881,17 @@ int getenv_for_pid(pid_t pid, const char *field, char **_value) {
if (!f) {
if (errno == ENOENT)
return -ESRCH;
+
return -errno;
}
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
l = strlen(field);
- r = 0;
do {
char line[LINE_MAX];
- unsigned i;
+ size_t i;
for (i = 0; i < sizeof(line)-1; i++) {
int c;
@@ -762,14 +912,14 @@ int getenv_for_pid(pid_t pid, const char *field, char **_value) {
if (!value)
return -ENOMEM;
- r = 1;
- break;
+ *ret = value;
+ return 1;
}
} while (!done);
- *_value = value;
- return r;
+ *ret = NULL;
+ return 0;
}
bool pid_is_unwaited(pid_t pid) {
@@ -781,6 +931,9 @@ bool pid_is_unwaited(pid_t pid) {
if (pid <= 1) /* If we or PID 1 would be dead and have been waited for, this code would not be running */
return true;
+ if (pid == getpid_cached())
+ return true;
+
if (kill(pid, 0) >= 0)
return true;
@@ -798,8 +951,11 @@ bool pid_is_alive(pid_t pid) {
if (pid <= 1) /* If we or PID 1 would be a zombie, this code would not be running */
return true;
+ if (pid == getpid_cached())
+ return true;
+
r = get_process_state(pid);
- if (r == -ESRCH || r == 'Z')
+ if (IN_SET(r, -ESRCH, 'Z'))
return false;
return true;
@@ -810,7 +966,10 @@ int pid_from_same_root_fs(pid_t pid) {
const char *root;
if (pid < 0)
- return 0;
+ return false;
+
+ if (pid == 0 || pid == getpid_cached())
+ return true;
root = procfs_file_alloca(pid, "root");
@@ -822,13 +981,13 @@ bool is_main_thread(void) {
static thread_local int cached = 0;
if (_unlikely_(cached == 0))
- cached = getpid() == gettid() ? 1 : -1;
+ cached = getpid_cached() == gettid() ? 1 : -1;
return cached > 0;
}
#if 0 /// UNNEEDED by elogind
-noreturn void freeze(void) {
+_noreturn_ void freeze(void) {
log_close();
@@ -837,6 +996,17 @@ noreturn void freeze(void) {
sync();
+ /* Let's not freeze right away, but keep reaping zombies. */
+ for (;;) {
+ int r;
+ siginfo_t si = {};
+
+ r = waitid(P_ALL, 0, &si, WEXITED);
+ if (r < 0 && errno != EINTR)
+ break;
+ }
+
+ /* waitid() failed with an unexpected error, things are really borked. Freeze now! */
for (;;)
pause();
}
@@ -885,9 +1055,50 @@ const char* personality_to_string(unsigned long p) {
return architecture_to_string(architecture);
}
+int safe_personality(unsigned long p) {
+ int ret;
+
+ /* So here's the deal, personality() is weirdly defined by glibc. In some cases it returns a failure via errno,
+ * and in others as negative return value containing an errno-like value. Let's work around this: this is a
+ * wrapper that uses errno if it is set, and uses the return value otherwise. And then it sets both errno and
+ * the return value indicating the same issue, so that we are definitely on the safe side.
+ *
+ * See https://github.com/systemd/systemd/issues/6737 */
+
+ errno = 0;
+ ret = personality(p);
+ if (ret < 0) {
+ if (errno != 0)
+ return -errno;
+
+ errno = -ret;
+ }
+
+ return ret;
+}
+
+int opinionated_personality(unsigned long *ret) {
+ int current;
+
+ /* Returns the current personality, or PERSONALITY_INVALID if we can't determine it. This function is a bit
+ * opinionated though, and ignores all the finer-grained bits and exotic personalities, only distinguishing the
+ * two most relevant personalities: PER_LINUX and PER_LINUX32. */
+
+ current = safe_personality(PERSONALITY_INVALID);
+ if (current < 0)
+ return current;
+
+ if (((unsigned long) current & 0xffff) == PER_LINUX32)
+ *ret = PER_LINUX32;
+ else
+ *ret = PER_LINUX;
+
+ return 0;
+}
+
void valgrind_summary_hack(void) {
-#ifdef HAVE_VALGRIND_VALGRIND_H
- if (getpid() == 1 && RUNNING_ON_VALGRIND) {
+#if HAVE_VALGRIND_VALGRIND_H
+ if (getpid_cached() == 1 && RUNNING_ON_VALGRIND) {
pid_t pid;
pid = raw_clone(SIGCHLD);
if (pid < 0)
@@ -930,7 +1141,347 @@ int ioprio_parse_priority(const char *s, int *ret) {
*ret = i;
return 0;
}
+#endif // 0
+
+/* The cached PID, possible values:
+ *
+ * == UNSET [0] → cache not initialized yet
+ * == BUSY [-1] → some thread is initializing it at the moment
+ * any other → the cached PID
+ */
+
+#define CACHED_PID_UNSET ((pid_t) 0)
+#define CACHED_PID_BUSY ((pid_t) -1)
+
+static pid_t cached_pid = CACHED_PID_UNSET;
+
+void reset_cached_pid(void) {
+ /* Invoked in the child after a fork(), i.e. at the first moment the PID changed */
+ cached_pid = CACHED_PID_UNSET;
+}
+
+/* We use glibc __register_atfork() + __dso_handle directly here, as they are not included in the glibc
+ * headers. __register_atfork() is mostly equivalent to pthread_atfork(), but doesn't require us to link against
+ * libpthread, as it is part of glibc anyway. */
+#ifdef __GLIBC__
+extern int __register_atfork(void (*prepare) (void), void (*parent) (void), void (*child) (void), void * __dso_handle);
+extern void* __dso_handle __attribute__ ((__weak__));
+#endif // ifdef __GLIBC__
+
+pid_t getpid_cached(void) {
+ static bool installed = false;
+ pid_t current_value;
+
+ /* getpid_cached() is much like getpid(), but caches the value in local memory, to avoid having to invoke a
+ * system call each time. This restores glibc behaviour from before 2.24, when getpid() was unconditionally
+ * cached. Starting with 2.24 getpid() started to become prohibitively expensive when used for detecting when
+ * objects were used across fork()s. With this caching the old behaviour is somewhat restored.
+ *
+ * https://bugzilla.redhat.com/show_bug.cgi?id=1443976
+ * https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=c579f48edba88380635ab98cb612030e3ed8691e
+ */
+
+ current_value = __sync_val_compare_and_swap(&cached_pid, CACHED_PID_UNSET, CACHED_PID_BUSY);
+
+ switch (current_value) {
+
+ case CACHED_PID_UNSET: { /* Not initialized yet, then do so now */
+ pid_t new_pid;
+
+ new_pid = raw_getpid();
+
+ if (!installed) {
+ /* __register_atfork() either returns 0 or -ENOMEM, in its glibc implementation. Since it's
+ * only half-documented (glibc doesn't document it but LSB does — though only superficially)
+ * we'll check for errors only in the most generic fashion possible. */
+
+ if (__register_atfork(NULL, NULL, reset_cached_pid, __dso_handle) != 0) {
+ /* OOM? Let's try again later */
+ cached_pid = CACHED_PID_UNSET;
+ return new_pid;
+ }
+
+ installed = true;
+ }
+
+ cached_pid = new_pid;
+ return new_pid;
+ }
+
+ case CACHED_PID_BUSY: /* Somebody else is currently initializing */
+ return raw_getpid();
+
+ default: /* Properly initialized */
+ return current_value;
+ }
+}
+
+int must_be_root(void) {
+
+ if (geteuid() == 0)
+ return 0;
+
+ log_error("Need to be root.");
+ return -EPERM;
+}
+
+int safe_fork_full(
+ const char *name,
+ const int except_fds[],
+ size_t n_except_fds,
+ ForkFlags flags,
+ pid_t *ret_pid) {
+
+ pid_t original_pid, pid;
+ sigset_t saved_ss, ss;
+ bool block_signals = false;
+ int prio, r;
+
+ /* A wrapper around fork(), that does a couple of important initializations in addition to mere forking. Always
+ * returns the child's PID in *ret_pid. Returns == 0 in the child, and > 0 in the parent. */
+
+ prio = flags & FORK_LOG ? LOG_ERR : LOG_DEBUG;
+
+ original_pid = getpid_cached();
+
+ if (flags & (FORK_RESET_SIGNALS|FORK_DEATHSIG)) {
+
+ /* We temporarily block all signals, so that the new child has them blocked initially. This way, we can
+ * be sure that SIGTERMs are not lost we might send to the child. */
+
+ if (sigfillset(&ss) < 0)
+ return log_full_errno(prio, errno, "Failed to reset signal set: %m");
+
+ block_signals = true;
+
+ } else if (flags & FORK_WAIT) {
+
+ /* Let's block SIGCHLD at least, so that we can safely watch for the child process */
+
+ if (sigemptyset(&ss) < 0)
+ return log_full_errno(prio, errno, "Failed to clear signal set: %m");
+
+ if (sigaddset(&ss, SIGCHLD) < 0)
+ return log_full_errno(prio, errno, "Failed to add SIGCHLD to signal set: %m");
+
+ block_signals = true;
+ }
+
+ if (block_signals)
+ if (sigprocmask(SIG_SETMASK, &ss, &saved_ss) < 0)
+ return log_full_errno(prio, errno, "Failed to set signal mask: %m");
+
+ if (flags & FORK_NEW_MOUNTNS)
+ pid = raw_clone(SIGCHLD|CLONE_NEWNS);
+ else
+ pid = fork();
+ if (pid < 0) {
+ r = -errno;
+
+ if (block_signals) /* undo what we did above */
+ (void) sigprocmask(SIG_SETMASK, &saved_ss, NULL);
+
+ return log_full_errno(prio, r, "Failed to fork: %m");
+ }
+ if (pid > 0) {
+ /* We are in the parent process */
+
+ log_debug("Successfully forked off '%s' as PID " PID_FMT ".", strna(name), pid);
+
+ if (flags & FORK_WAIT) {
+ r = wait_for_terminate_and_check(name, pid, (flags & FORK_LOG ? WAIT_LOG : 0));
+ if (r < 0)
+ return r;
+ if (r != EXIT_SUCCESS) /* exit status > 0 should be treated as failure, too */
+ return -EPROTO;
+ }
+ if (block_signals) /* undo what we did above */
+ (void) sigprocmask(SIG_SETMASK, &saved_ss, NULL);
+
+ if (ret_pid)
+ *ret_pid = pid;
+
+ return 1;
+ }
+
+ /* We are in the child process */
+
+ if (flags & FORK_REOPEN_LOG) {
+ /* Close the logs if requested, before we log anything. And make sure we reopen it if needed. */
+ log_close();
+ log_set_open_when_needed(true);
+ }
+
+ if (name) {
+ r = rename_process(name);
+ if (r < 0)
+ log_full_errno(flags & FORK_LOG ? LOG_WARNING : LOG_DEBUG,
+ r, "Failed to rename process, ignoring: %m");
+ }
+
+ if (flags & FORK_DEATHSIG)
+ if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0) {
+ log_full_errno(prio, errno, "Failed to set death signal: %m");
+ _exit(EXIT_FAILURE);
+ }
+
+ if (flags & FORK_RESET_SIGNALS) {
+ r = reset_all_signal_handlers();
+ if (r < 0) {
+ log_full_errno(prio, r, "Failed to reset signal handlers: %m");
+ _exit(EXIT_FAILURE);
+ }
+
+ /* This implicitly undoes the signal mask stuff we did before the fork()ing above */
+ r = reset_signal_mask();
+ if (r < 0) {
+ log_full_errno(prio, r, "Failed to reset signal mask: %m");
+ _exit(EXIT_FAILURE);
+ }
+ } else if (block_signals) { /* undo what we did above */
+ if (sigprocmask(SIG_SETMASK, &saved_ss, NULL) < 0) {
+ log_full_errno(prio, errno, "Failed to restore signal mask: %m");
+ _exit(EXIT_FAILURE);
+ }
+ }
+
+ if (flags & FORK_DEATHSIG) {
+ pid_t ppid;
+ /* Let's see if the parent PID is still the one we started from? If not, then the parent
+ * already died by the time we set PR_SET_PDEATHSIG, hence let's emulate the effect */
+
+ ppid = getppid();
+ if (ppid == 0)
+ /* Parent is in a differn't PID namespace. */;
+ else if (ppid != original_pid) {
+ log_debug("Parent died early, raising SIGTERM.");
+ (void) raise(SIGTERM);
+ _exit(EXIT_FAILURE);
+ }
+ }
+
+ if (FLAGS_SET(flags, FORK_NEW_MOUNTNS | FORK_MOUNTNS_SLAVE)) {
+
+ /* Optionally, make sure we never propagate mounts to the host. */
+
+ if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) {
+ log_full_errno(prio, errno, "Failed to remount root directory as MS_SLAVE: %m");
+ _exit(EXIT_FAILURE);
+ }
+ }
+
+ if (flags & FORK_CLOSE_ALL_FDS) {
+ /* Close the logs here in case it got reopened above, as close_all_fds() would close them for us */
+ log_close();
+
+ r = close_all_fds(except_fds, n_except_fds);
+ if (r < 0) {
+ log_full_errno(prio, r, "Failed to close all file descriptors: %m");
+ _exit(EXIT_FAILURE);
+ }
+ }
+
+ /* When we were asked to reopen the logs, do so again now */
+ if (flags & FORK_REOPEN_LOG) {
+ log_open();
+ log_set_open_when_needed(false);
+ }
+
+ if (flags & FORK_NULL_STDIO) {
+ r = make_null_stdio();
+ if (r < 0) {
+ log_full_errno(prio, r, "Failed to connect stdin/stdout to /dev/null: %m");
+ _exit(EXIT_FAILURE);
+ }
+ }
+
+ if (ret_pid)
+ *ret_pid = getpid_cached();
+
+ return 0;
+}
+
+int fork_agent(const char *name, const int except[], size_t n_except, pid_t *ret_pid, const char *path, ...) {
+ bool stdout_is_tty, stderr_is_tty;
+ size_t n, i;
+ va_list ap;
+ char **l;
+ int r;
+
+ assert(path);
+
+ /* Spawns a temporary TTY agent, making sure it goes away when we go away */
+
+ r = safe_fork_full(name, except, n_except, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS, ret_pid);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ return 0;
+
+ /* In the child: */
+
+ stdout_is_tty = isatty(STDOUT_FILENO);
+ stderr_is_tty = isatty(STDERR_FILENO);
+
+ if (!stdout_is_tty || !stderr_is_tty) {
+ int fd;
+
+ /* 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_errno(errno, "Failed to open /dev/tty: %m");
+ _exit(EXIT_FAILURE);
+ }
+
+ if (!stdout_is_tty && dup2(fd, STDOUT_FILENO) < 0) {
+ log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
+ _exit(EXIT_FAILURE);
+ }
+
+ if (!stderr_is_tty && dup2(fd, STDERR_FILENO) < 0) {
+ log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
+ _exit(EXIT_FAILURE);
+ }
+
+ safe_close_above_stdio(fd);
+ }
+
+ /* Count arguments */
+ va_start(ap, path);
+ for (n = 0; va_arg(ap, char*); n++)
+ ;
+ va_end(ap);
+
+ /* Allocate strv */
+ l = newa(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 set_oom_score_adjust(int value) {
+ char t[DECIMAL_STR_MAX(int)];
+
+ sprintf(t, "%i", value);
+
+ return write_string_file("/proc/self/oom_score_adj", t,
+ WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_DISABLE_BUFFER);
+}
+
+#if 0 /// UNNEEDED by elogind
static const char *const ioprio_class_table[] = {
[IOPRIO_CLASS_NONE] = "none",
[IOPRIO_CLASS_RT] = "realtime",
@@ -938,7 +1489,7 @@ static const char *const ioprio_class_table[] = {
[IOPRIO_CLASS_IDLE] = "idle"
};
-DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
+DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, IOPRIO_N_CLASSES);
static const char *const sigchld_code_table[] = {
[CLD_EXITED] = "exited",
diff --git a/src/basic/process-util.h b/src/basic/process-util.h
index 171e87189..f73055218 100644
--- a/src/basic/process-util.h
+++ b/src/basic/process-util.h
@@ -1,25 +1,9 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <alloca.h>
+#include <errno.h>
+#include <sched.h>
#include <signal.h>
#include <stdbool.h>
#include <stddef.h>
@@ -31,6 +15,7 @@
#include "format-util.h"
//#include "ioprio.h"
#include "macro.h"
+#include "time-util.h"
#define procfs_file_alloca(pid, field) \
({ \
@@ -39,7 +24,7 @@
if (_pid_ == 0) { \
_r_ = ("/proc/self/" field); \
} else { \
- _r_ = alloca(strlen("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \
+ _r_ = alloca(STRLEN("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \
sprintf((char*) _r_, "/proc/"PID_FMT"/" field, _pid_); \
} \
_r_; \
@@ -60,16 +45,27 @@ int get_process_ppid(pid_t pid, pid_t *ppid);
#endif // 0
int wait_for_terminate(pid_t pid, siginfo_t *status);
-int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code);
+typedef enum WaitFlags {
+ WAIT_LOG_ABNORMAL = 1 << 0,
+ WAIT_LOG_NON_ZERO_EXIT_STATUS = 1 << 1,
+
+ /* A shortcut for requesting the most complete logging */
+ WAIT_LOG = WAIT_LOG_ABNORMAL|WAIT_LOG_NON_ZERO_EXIT_STATUS,
+} WaitFlags;
+
+int wait_for_terminate_and_check(const char *name, pid_t pid, WaitFlags flags);
+int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout);
#if 0 /// UNNEEDED by elogind
+
void sigkill_wait(pid_t pid);
void sigkill_waitp(pid_t *pid);
+#endif // 0
+void sigterm_wait(pid_t pid);
int kill_and_sigcont(pid_t pid, int sig);
int rename_process(const char name[]);
-#endif // 0
int is_kernel_thread(pid_t pid);
int getenv_for_pid(pid_t pid, const char *field, char **_value);
@@ -83,7 +79,7 @@ int pid_from_same_root_fs(pid_t pid);
bool is_main_thread(void);
#if 0 /// UNNEEDED by elogind
-noreturn void freeze(void);
+_noreturn_ void freeze(void);
bool oom_score_adjust_is_valid(int oa);
#endif // 0
@@ -99,18 +95,28 @@ bool oom_score_adjust_is_valid(int oa);
unsigned long personality_from_string(const char *p);
const char *personality_to_string(unsigned long);
+int safe_personality(unsigned long p);
+int opinionated_personality(unsigned long *ret);
+
int ioprio_class_to_string_alloc(int i, char **s);
int ioprio_class_from_string(const char *s);
const char *sigchld_code_to_string(int i) _const_;
int sigchld_code_from_string(const char *s) _pure_;
+#endif // 0
int sched_policy_to_string_alloc(int i, char **s);
+#if 0 /// UNNEEDED by elogind
int sched_policy_from_string(const char *s);
#endif // 0
-#define PTR_TO_PID(p) ((pid_t) ((uintptr_t) p))
-#define PID_TO_PTR(p) ((void*) ((uintptr_t) p))
+static inline pid_t PTR_TO_PID(const void *p) {
+ return (pid_t) ((uintptr_t) p);
+}
+
+static inline void* PID_TO_PTR(pid_t pid) {
+ return (void*) ((uintptr_t) pid);
+}
void valgrind_summary_hack(void);
@@ -120,6 +126,16 @@ int pid_compare_func(const void *a, const void *b);
static inline bool nice_is_valid(int n) {
return n >= PRIO_MIN && n < PRIO_MAX;
}
+#endif // 0
+
+static inline bool sched_policy_is_valid(int i) {
+ return IN_SET(i, SCHED_OTHER, SCHED_BATCH, SCHED_IDLE, SCHED_FIFO, SCHED_RR);
+}
+
+#if 0 /// UNNEEDED by elogind
+static inline bool sched_priority_is_valid(int i) {
+ return i >= 0 && i <= sched_get_priority_max(SCHED_RR);
+}
static inline bool ioprio_class_is_valid(int i) {
return IN_SET(i, IOPRIO_CLASS_NONE, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE);
@@ -128,6 +144,73 @@ static inline bool ioprio_class_is_valid(int i) {
static inline bool ioprio_priority_is_valid(int i) {
return i >= 0 && i < IOPRIO_BE_NR;
}
+#endif // 0
+
+static inline bool pid_is_valid(pid_t p) {
+ return p > 0;
+}
+static inline int sched_policy_to_string_alloc_with_check(int n, char **s) {
+ if (!sched_policy_is_valid(n))
+ return -EINVAL;
+
+ return sched_policy_to_string_alloc(n, s);
+}
+
+#if 0 /// UNNEEDED by elogind
int ioprio_parse_priority(const char *s, int *ret);
#endif // 0
+
+pid_t getpid_cached(void);
+void reset_cached_pid(void);
+
+int must_be_root(void);
+
+typedef enum ForkFlags {
+ FORK_RESET_SIGNALS = 1 << 0,
+ FORK_CLOSE_ALL_FDS = 1 << 1,
+ FORK_DEATHSIG = 1 << 2,
+ FORK_NULL_STDIO = 1 << 3,
+ FORK_REOPEN_LOG = 1 << 4,
+ FORK_LOG = 1 << 5,
+ FORK_WAIT = 1 << 6,
+ FORK_NEW_MOUNTNS = 1 << 7,
+ FORK_MOUNTNS_SLAVE = 1 << 8,
+} ForkFlags;
+
+int safe_fork_full(const char *name, const int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid);
+
+static inline int safe_fork(const char *name, ForkFlags flags, pid_t *ret_pid) {
+ return safe_fork_full(name, NULL, 0, flags, ret_pid);
+}
+
+int fork_agent(const char *name, const int except[], size_t n_except, pid_t *pid, const char *path, ...);
+
+int set_oom_score_adjust(int value);
+
+#if SIZEOF_PID_T == 4
+/* The highest possibly (theoretic) pid_t value on this architecture. */
+#define PID_T_MAX ((pid_t) INT32_MAX)
+/* The maximum number of concurrent processes Linux allows on this architecture, as well as the highest valid PID value
+ * the kernel will potentially assign. This reflects a value compiled into the kernel (PID_MAX_LIMIT), and sets the
+ * upper boundary on what may be written to the /proc/sys/kernel/pid_max sysctl (but do note that the sysctl is off by
+ * 1, since PID 0 can never exist and there can hence only be one process less than the limit would suggest). Since
+ * these values are documented in proc(5) we feel quite confident that they are stable enough for the near future at
+ * least to define them here too. */
+#define TASKS_MAX 4194303U
+#elif SIZEOF_PID_T == 2
+#define PID_T_MAX ((pid_t) INT16_MAX)
+#define TASKS_MAX 32767U
+#else
+#error "Unknown pid_t size"
+#endif
+
+assert_cc(TASKS_MAX <= (unsigned long) PID_T_MAX)
+
+/* Like TAKE_PTR() but for child PIDs, resetting them to 0 */
+#define TAKE_PID(pid) \
+ ({ \
+ pid_t _pid_ = (pid); \
+ (pid) = 0; \
+ _pid_; \
+ })
diff --git a/src/basic/procfs-util.c b/src/basic/procfs-util.c
new file mode 100644
index 000000000..f821d64d5
--- /dev/null
+++ b/src/basic/procfs-util.c
@@ -0,0 +1,269 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <errno.h>
+
+#include "alloc-util.h"
+#include "def.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "parse-util.h"
+#include "process-util.h"
+#include "procfs-util.h"
+#include "stdio-util.h"
+#include "string-util.h"
+
+int procfs_tasks_get_limit(uint64_t *ret) {
+ _cleanup_free_ char *value = NULL;
+ uint64_t pid_max, threads_max;
+ int r;
+
+ assert(ret);
+
+ /* So there are two sysctl files that control the system limit of processes:
+ *
+ * 1. kernel.threads-max: this is probably the sysctl that makes more sense, as it directly puts a limit on
+ * concurrent tasks.
+ *
+ * 2. kernel.pid_max: this limits the numeric range PIDs can take, and thus indirectly also limits the number
+ * of concurrent threads. AFAICS it's primarily a compatibility concept: some crappy old code used a signed
+ * 16bit type for PIDs, hence the kernel provides a way to ensure the PIDs never go beyond INT16_MAX by
+ * default.
+ *
+ * By default #2 is set to much lower values than #1, hence the limit people come into contact with first, as
+ * it's the lowest boundary they need to bump when they want higher number of processes.
+ *
+ * Also note the weird definition of #2: PIDs assigned will be kept below this value, which means the number of
+ * tasks that can be created is one lower, as PID 0 is not a valid process ID. */
+
+ r = read_one_line_file("/proc/sys/kernel/pid_max", &value);
+ if (r < 0)
+ return r;
+
+ r = safe_atou64(value, &pid_max);
+ if (r < 0)
+ return r;
+
+ value = mfree(value);
+ r = read_one_line_file("/proc/sys/kernel/threads-max", &value);
+ if (r < 0)
+ return r;
+
+ r = safe_atou64(value, &threads_max);
+ if (r < 0)
+ return r;
+
+ /* Subtract one from pid_max, since PID 0 is not a valid PID */
+ *ret = MIN(pid_max-1, threads_max);
+ return 0;
+}
+
+#if 0 /// UNNEEDED by elogind
+int procfs_tasks_set_limit(uint64_t limit) {
+ char buffer[DECIMAL_STR_MAX(uint64_t)+1];
+ _cleanup_free_ char *value = NULL;
+ uint64_t pid_max;
+ int r;
+
+ if (limit == 0) /* This makes no sense, we are userspace and hence count as tasks too, and we want to live,
+ * hence the limit conceptually has to be above 0. Also, most likely if anyone asks for a zero
+ * limit he/she probably means "no limit", hence let's better refuse this to avoid
+ * confusion. */
+ return -EINVAL;
+
+ /* The Linux kernel doesn't allow this value to go below 20, hence don't allow this either, higher values than
+ * TASKS_MAX are not accepted by the pid_max sysctl. We'll treat anything this high as "unbounded" and hence
+ * set it to the maximum. */
+ limit = CLAMP(limit, 20U, TASKS_MAX);
+
+ r = read_one_line_file("/proc/sys/kernel/pid_max", &value);
+ if (r < 0)
+ return r;
+ r = safe_atou64(value, &pid_max);
+ if (r < 0)
+ return r;
+
+ /* As pid_max is about the numeric pid_t range we'll bump it if necessary, but only ever increase it, never
+ * decrease it, as threads-max is the much more relevant sysctl. */
+ if (limit > pid_max-1) {
+ sprintf(buffer, "%" PRIu64, limit+1); /* Add one, since PID 0 is not a valid PID */
+ r = write_string_file("/proc/sys/kernel/pid_max", buffer, WRITE_STRING_FILE_DISABLE_BUFFER);
+ if (r < 0)
+ return r;
+ }
+
+ sprintf(buffer, "%" PRIu64, limit);
+ r = write_string_file("/proc/sys/kernel/threads-max", buffer, WRITE_STRING_FILE_DISABLE_BUFFER);
+ if (r < 0) {
+ uint64_t threads_max;
+
+ /* Hmm, we couldn't write this? If so, maybe it was already set properly? In that case let's not
+ * generate an error */
+
+ value = mfree(value);
+ if (read_one_line_file("/proc/sys/kernel/threads-max", &value) < 0)
+ return r; /* return original error */
+
+ if (safe_atou64(value, &threads_max) < 0)
+ return r; /* return original error */
+
+ if (MIN(pid_max-1, threads_max) != limit)
+ return r; /* return original error */
+
+ /* Yay! Value set already matches what we were trying to set, hence consider this a success. */
+ }
+
+ return 0;
+}
+
+int procfs_tasks_get_current(uint64_t *ret) {
+ _cleanup_free_ char *value = NULL;
+ const char *p, *nr;
+ size_t n;
+ int r;
+
+ assert(ret);
+
+ r = read_one_line_file("/proc/loadavg", &value);
+ if (r < 0)
+ return r;
+
+ /* Look for the second part of the fourth field, which is separated by a slash from the first part. None of the
+ * earlier fields use a slash, hence let's use this to find the right spot. */
+ p = strchr(value, '/');
+ if (!p)
+ return -EINVAL;
+
+ p++;
+ n = strspn(p, DIGITS);
+ nr = strndupa(p, n);
+
+ return safe_atou64(nr, ret);
+}
+
+static uint64_t calc_gcd64(uint64_t a, uint64_t b) {
+
+ while (b > 0) {
+ uint64_t t;
+
+ t = a % b;
+
+ a = b;
+ b = t;
+ }
+
+ return a;
+}
+
+int procfs_cpu_get_usage(nsec_t *ret) {
+ _cleanup_free_ char *first_line = NULL;
+ unsigned long user_ticks, nice_ticks, system_ticks, irq_ticks, softirq_ticks,
+ guest_ticks = 0, guest_nice_ticks = 0;
+ long ticks_per_second;
+ uint64_t sum, gcd, a, b;
+ const char *p;
+ int r;
+
+ assert(ret);
+
+ r = read_one_line_file("/proc/stat", &first_line);
+ if (r < 0)
+ return r;
+
+ p = first_word(first_line, "cpu");
+ if (!p)
+ return -EINVAL;
+
+ if (sscanf(p, "%lu %lu %lu %*u %*u %lu %lu %*u %lu %lu",
+ &user_ticks,
+ &nice_ticks,
+ &system_ticks,
+ &irq_ticks,
+ &softirq_ticks,
+ &guest_ticks,
+ &guest_nice_ticks) < 5) /* we only insist on the first five fields */
+ return -EINVAL;
+
+ ticks_per_second = sysconf(_SC_CLK_TCK);
+ if (ticks_per_second < 0)
+ return -errno;
+ assert(ticks_per_second > 0);
+
+ sum = (uint64_t) user_ticks + (uint64_t) nice_ticks + (uint64_t) system_ticks +
+ (uint64_t) irq_ticks + (uint64_t) softirq_ticks +
+ (uint64_t) guest_ticks + (uint64_t) guest_nice_ticks;
+
+ /* Let's reduce this fraction before we apply it to avoid overflows when converting this to µsec */
+ gcd = calc_gcd64(NSEC_PER_SEC, ticks_per_second);
+
+ a = (uint64_t) NSEC_PER_SEC / gcd;
+ b = (uint64_t) ticks_per_second / gcd;
+
+ *ret = DIV_ROUND_UP((nsec_t) sum * (nsec_t) a, (nsec_t) b);
+ return 0;
+}
+
+int procfs_memory_get_current(uint64_t *ret) {
+ uint64_t mem_total = UINT64_MAX, mem_free = UINT64_MAX;
+ _cleanup_fclose_ FILE *f = NULL;
+ int r;
+
+ assert(ret);
+
+ f = fopen("/proc/meminfo", "re");
+ if (!f)
+ return -errno;
+
+ for (;;) {
+ _cleanup_free_ char *line = NULL;
+ uint64_t *v;
+ char *p, *e;
+ size_t n;
+
+ r = read_line(f, LONG_LINE_MAX, &line);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -EINVAL; /* EOF: Couldn't find one or both fields? */
+
+ p = first_word(line, "MemTotal:");
+ if (p)
+ v = &mem_total;
+ else {
+ p = first_word(line, "MemFree:");
+ if (p)
+ v = &mem_free;
+ else
+ continue;
+ }
+
+ /* Determine length of numeric value */
+ n = strspn(p, DIGITS);
+ if (n == 0)
+ return -EINVAL;
+ e = p + n;
+
+ /* Ensure the line ends in " kB" */
+ n = strspn(e, WHITESPACE);
+ if (n == 0)
+ return -EINVAL;
+ if (!streq(e + n, "kB"))
+ return -EINVAL;
+
+ *e = 0;
+ r = safe_atou64(p, v);
+ if (r < 0)
+ return r;
+ if (*v == UINT64_MAX)
+ return -EINVAL;
+
+ if (mem_total != UINT64_MAX && mem_free != UINT64_MAX)
+ break;
+ }
+
+ if (mem_free > mem_total)
+ return -EINVAL;
+
+ *ret = (mem_total - mem_free) * 1024U;
+ return 0;
+}
+#endif // 0
diff --git a/src/basic/procfs-util.h b/src/basic/procfs-util.h
new file mode 100644
index 000000000..0d1c7d231
--- /dev/null
+++ b/src/basic/procfs-util.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <inttypes.h>
+
+#include "time-util.h"
+
+int procfs_tasks_get_limit(uint64_t *ret);
+#if 0 /// UNNEEDED by elogind
+int procfs_tasks_set_limit(uint64_t limit);
+int procfs_tasks_get_current(uint64_t *ret);
+
+int procfs_cpu_get_usage(nsec_t *ret);
+
+int procfs_memory_get_current(uint64_t *ret);
+#endif // 0
diff --git a/src/basic/random-util.c b/src/basic/random-util.c
index 810eeab4d..eed9d59ce 100644
--- a/src/basic/random-util.c
+++ b/src/basic/random-util.c
@@ -1,36 +1,20 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <elf.h>
#include <errno.h>
#include <fcntl.h>
+//#include <linux/random.h>
#include <stdbool.h>
+//#include <stdint.h>
#include <stdlib.h>
+#include <string.h>
#include <sys/time.h>
-#include <linux/random.h>
-#include <stdint.h>
-#ifdef HAVE_SYS_AUXV_H
+#if HAVE_SYS_AUXV_H
# include <sys/auxv.h>
#endif
-#ifdef USE_SYS_RANDOM_H
+#if USE_SYS_RANDOM_H
# include <sys/random.h>
#else
# include <linux/random.h>
@@ -46,7 +30,7 @@ int acquire_random_bytes(void *p, size_t n, bool high_quality_required) {
static int have_syscall = -1;
_cleanup_close_ int fd = -1;
- unsigned already_done = 0;
+ size_t already_done = 0;
int r;
/* Gathers some randomness from the kernel. This call will never block. If
@@ -57,14 +41,14 @@ int acquire_random_bytes(void *p, size_t n, bool high_quality_required) {
* for us. */
/* Use the getrandom() syscall unless we know we don't have it. */
- if (have_syscall != 0) {
+ if (have_syscall != 0 && !HAS_FEATURE_MEMORY_SANITIZER) {
r = getrandom(p, n, GRND_NONBLOCK);
if (r > 0) {
have_syscall = true;
if ((size_t) r == n)
return 0;
if (!high_quality_required) {
- /* Fill in the remaing bytes using pseudorandom values */
+ /* Fill in the remaining bytes using pseudorandom values */
pseudorandom_bytes((uint8_t*) p + r, n - r);
return 0;
}
@@ -100,14 +84,14 @@ int acquire_random_bytes(void *p, size_t n, bool high_quality_required) {
void initialize_srand(void) {
static bool srand_called = false;
unsigned x;
-#ifdef HAVE_SYS_AUXV_H
+#if HAVE_SYS_AUXV_H
void *auxv;
#endif
if (srand_called)
return;
-#ifdef HAVE_SYS_AUXV_H
+#if HAVE_SYS_AUXV_H
/* The kernel provides us with 16 bytes of entropy in auxv, so let's
* try to make use of that to seed the pseudo-random generator. It's
* better than nothing... */
@@ -120,7 +104,6 @@ void initialize_srand(void) {
#endif
x = 0;
-
x ^= (unsigned) now(CLOCK_REALTIME);
x ^= (unsigned) gettid();
diff --git a/src/basic/random-util.h b/src/basic/random-util.h
index 804e225fc..9a103f0e9 100644
--- a/src/basic/random-util.h
+++ b/src/basic/random-util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 <stddef.h>
#include <stdint.h>
diff --git a/src/basic/raw-clone.h b/src/basic/raw-clone.h
new file mode 100644
index 000000000..fbd2d8c51
--- /dev/null
+++ b/src/basic/raw-clone.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+/***
+ Copyright © 2016 Michael Karcher
+***/
+
+//#include <errno.h>
+#include <sched.h>
+#include <sys/syscall.h>
+
+#include "log.h"
+#include "macro.h"
+
+/**
+ * raw_clone() - uses clone to create a new process with clone flags
+ * @flags: Flags to pass to the clone system call
+ *
+ * Uses the clone system call to create a new process with the cloning flags and termination signal passed in the flags
+ * parameter. Opposed to glibc's clone funtion, using this function does not set up a separate stack for the child, but
+ * relies on copy-on-write semantics on the one stack at a common virtual address, just as fork does.
+ *
+ * To obtain copy-on-write semantics, flags must not contain CLONE_VM, and thus CLONE_THREAD and CLONE_SIGHAND (which
+ * require CLONE_VM) are not usable.
+ *
+ * Additionally, as this function does not pass the ptid, newtls and ctid parameters to the kernel, flags must not
+ * contain CLONE_PARENT_SETTID, CLONE_CHILD_SETTID, CLONE_CHILD_CLEARTID or CLONE_SETTLS.
+ *
+ * Returns: 0 in the child process and the child process id in the parent.
+ */
+static inline pid_t raw_clone(unsigned long flags) {
+ pid_t ret;
+
+ assert((flags & (CLONE_VM|CLONE_PARENT_SETTID|CLONE_CHILD_SETTID|
+ CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0);
+#if defined(__s390x__) || defined(__s390__) || defined(__CRIS__)
+ /* On s390/s390x and cris the order of the first and second arguments
+ * of the raw clone() system call is reversed. */
+ ret = (pid_t) syscall(__NR_clone, NULL, flags);
+#elif defined(__sparc__)
+ {
+ /**
+ * sparc always returns the other process id in %o0, and
+ * a boolean flag whether this is the child or the parent in
+ * %o1. Inline assembly is needed to get the flag returned
+ * in %o1.
+ */
+ int in_child, child_pid, error;
+
+ asm volatile("mov %3, %%g1\n\t"
+ "mov %4, %%o0\n\t"
+ "mov 0 , %%o1\n\t"
+#if defined(__arch64__)
+ "t 0x6d\n\t"
+#else
+ "t 0x10\n\t"
+#endif
+ "addx %%g0, 0, %2\n\t"
+ "mov %%o1, %0\n\t"
+ "mov %%o0, %1" :
+ "=r"(in_child), "=r"(child_pid), "=r"(error) :
+ "i"(__NR_clone), "r"(flags) :
+ "%o1", "%o0", "%g1" "cc" );
+
+ if (error) {
+ errno = child_pid;
+ ret = -1;
+ } else
+ ret = in_child ? 0 : child_pid;
+ }
+#else
+ ret = (pid_t) syscall(__NR_clone, flags, NULL);
+#endif
+
+ if (ret == 0)
+ reset_cached_pid();
+
+ return ret;
+}
diff --git a/src/basic/refcnt.h b/src/basic/refcnt.h
index 1d77a6445..d2be6086d 100644
--- a/src/basic/refcnt.h
+++ b/src/basic/refcnt.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
/* A type-safe atomic refcounter.
*
* DO NOT USE THIS UNLESS YOU ACTUALLY CARE ABOUT THREAD SAFETY! */
diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c
index 156366c7d..1b0de8bd0 100644
--- a/src/basic/rm-rf.c
+++ b/src/basic/rm-rf.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <fcntl.h>
@@ -25,6 +8,7 @@
#include <sys/statfs.h>
#include <unistd.h>
+#include "alloc-util.h"
//#include "btrfs-util.h"
#include "cgroup-util.h"
#include "dirent-util.h"
@@ -61,13 +45,15 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
}
if (is_physical_fs(&sfs)) {
- /* We refuse to clean physical file systems
- * with this call, unless explicitly
- * requested. This is extra paranoia just to
- * be sure we never ever remove non-state
- * data */
+ /* We refuse to clean physical file systems with this call,
+ * unless explicitly requested. This is extra paranoia just
+ * to be sure we never ever remove non-state data. */
+ _cleanup_free_ char *path = NULL;
+
+ (void) fd_get_path(fd, &path);
+ log_error("Attempted to remove disk file system under \"%s\", and we can't allow that.",
+ strna(path));
- log_error("Attempted to remove disk file system, and we can't allow that.");
safe_close(fd);
return -EPERM;
}
@@ -133,7 +119,7 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
r = btrfs_subvol_remove_fd(fd, de->d_name, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA);
if (r < 0) {
- if (r != -ENOTTY && r != -EINVAL) {
+ if (!IN_SET(r, -ENOTTY, -EINVAL)) {
if (ret == 0)
ret = r;
@@ -185,18 +171,18 @@ int rm_rf(const char *path, RemoveFlags flags) {
* call. This is extra paranoia to never cause a really
* seriously broken system. */
if (path_equal_or_files_same(path, "/", AT_SYMLINK_NOFOLLOW)) {
- log_error("Attempted to remove entire root file system, and we can't allow that.");
+ log_error("Attempted to remove entire root file system (\"%s\"), and we can't allow that.", path);
return -EPERM;
}
#if 0 /// elogind does not support BTRFS this directly
- if ((flags & (REMOVE_SUBVOLUME|REMOVE_ROOT|REMOVE_PHYSICAL)) == (REMOVE_SUBVOLUME|REMOVE_ROOT|REMOVE_PHYSICAL)) {
+ if (FLAGS_SET(flags, REMOVE_SUBVOLUME | REMOVE_ROOT | REMOVE_PHYSICAL)) {
/* Try to remove as subvolume first */
r = btrfs_subvol_remove(path, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA);
if (r >= 0)
return r;
- if (r != -ENOTTY && r != -EINVAL && r != -ENOTDIR)
+ if (!IN_SET(r, -ENOTTY, -EINVAL, -ENOTDIR))
return r;
/* Not btrfs or not a subvolume */
@@ -205,8 +191,7 @@ int rm_rf(const char *path, RemoveFlags flags) {
fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
if (fd < 0) {
-
- if (errno != ENOTDIR && errno != ELOOP)
+ if (!IN_SET(errno, ENOTDIR, ELOOP))
return -errno;
if (!(flags & REMOVE_PHYSICAL)) {
@@ -214,7 +199,7 @@ int rm_rf(const char *path, RemoveFlags flags) {
return -errno;
if (is_physical_fs(&s)) {
- log_error("Attempted to remove disk file system, and we can't allow that.");
+ log_error("Attempted to remove files from a disk file system under \"%s\", refusing.", path);
return -EPERM;
}
}
diff --git a/src/basic/rm-rf.h b/src/basic/rm-rf.h
index e13f7003e..0a2d7f035 100644
--- a/src/basic/rm-rf.h
+++ b/src/basic/rm-rf.h
@@ -1,31 +1,15 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 "util.h"
+
typedef enum RemoveFlags {
- REMOVE_ONLY_DIRECTORIES = 1,
- REMOVE_ROOT = 2,
- REMOVE_PHYSICAL = 4, /* if not set, only removes files on tmpfs, never physical file systems */
- REMOVE_SUBVOLUME = 8,
+ REMOVE_ONLY_DIRECTORIES = 1 << 0,
+ REMOVE_ROOT = 1 << 1,
+ REMOVE_PHYSICAL = 1 << 2, /* if not set, only removes files on tmpfs, never physical file systems */
+ REMOVE_SUBVOLUME = 1 << 3,
} RemoveFlags;
int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev);
@@ -33,6 +17,7 @@ int rm_rf(const char *path, RemoveFlags flags);
/* Useful for usage with _cleanup_(), destroys a directory and frees the pointer */
static inline void rm_rf_physical_and_free(char *p) {
+ PROTECT_ERRNO;
(void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
free(p);
}
diff --git a/src/basic/selinux-util.c b/src/basic/selinux-util.c
index c7a04ad76..15e62c491 100644
--- a/src/basic/selinux-util.c
+++ b/src/basic/selinux-util.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <malloc.h>
@@ -26,21 +9,23 @@
#include <sys/un.h>
#include <syslog.h>
-#ifdef HAVE_SELINUX
+#if HAVE_SELINUX
#include <selinux/context.h>
#include <selinux/label.h>
#include <selinux/selinux.h>
#endif
#include "alloc-util.h"
+//#include "fd-util.h"
#include "log.h"
#include "macro.h"
#include "path-util.h"
#include "selinux-util.h"
+//#include "stdio-util.h"
#include "time-util.h"
#include "util.h"
-#ifdef HAVE_SELINUX
+#if HAVE_SELINUX
DEFINE_TRIVIAL_CLEANUP_FUNC(char*, freecon);
DEFINE_TRIVIAL_CLEANUP_FUNC(context_t, context_free);
@@ -50,11 +35,12 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(context_t, context_free);
static int cached_use = -1;
static struct selabel_handle *label_hnd = NULL;
-#define log_enforcing(...) log_full_errno(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, errno, __VA_ARGS__)
+#define log_enforcing(...) log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, __VA_ARGS__)
+#define log_enforcing_errno(r, ...) log_full_errno(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, r, __VA_ARGS__)
#endif
bool mac_selinux_use(void) {
-#ifdef HAVE_SELINUX
+#if HAVE_SELINUX
if (cached_use < 0)
cached_use = is_selinux_enabled() > 0;
@@ -65,7 +51,7 @@ bool mac_selinux_use(void) {
}
void mac_selinux_retest(void) {
-#ifdef HAVE_SELINUX
+#if HAVE_SELINUX
cached_use = -1;
#endif
}
@@ -73,7 +59,7 @@ void mac_selinux_retest(void) {
int mac_selinux_init(void) {
int r = 0;
-#ifdef HAVE_SELINUX
+#if HAVE_SELINUX
usec_t before_timestamp, after_timestamp;
struct mallinfo before_mallinfo, after_mallinfo;
@@ -88,7 +74,7 @@ int mac_selinux_init(void) {
label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
if (!label_hnd) {
- log_enforcing("Failed to initialize SELinux context: %m");
+ log_enforcing_errno(errno, "Failed to initialize SELinux context: %m");
r = security_getenforce() == 1 ? -errno : 0;
} else {
char timespan[FORMAT_TIMESPAN_MAX];
@@ -110,7 +96,7 @@ int mac_selinux_init(void) {
void mac_selinux_finish(void) {
-#ifdef HAVE_SELINUX
+#if HAVE_SELINUX
if (!label_hnd)
return;
@@ -119,9 +105,12 @@ void mac_selinux_finish(void) {
#endif
}
-int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
+int mac_selinux_fix(const char *path, LabelFixFlags flags) {
-#ifdef HAVE_SELINUX
+#if HAVE_SELINUX
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+ _cleanup_freecon_ char* fcon = NULL;
+ _cleanup_close_ int fd = -1;
struct stat st;
int r;
@@ -131,37 +120,55 @@ int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
if (!label_hnd)
return 0;
- r = lstat(path, &st);
- if (r >= 0) {
- _cleanup_freecon_ char* fcon = NULL;
+ /* Open the file as O_PATH, to pin it while we determine and adjust the label */
+ fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
+ if (fd < 0) {
+ if ((flags & LABEL_IGNORE_ENOENT) && errno == ENOENT)
+ return 0;
- r = selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode);
+ return -errno;
+ }
+
+ if (fstat(fd, &st) < 0)
+ return -errno;
+
+ if (selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode) < 0) {
+ r = -errno;
/* If there's no label to set, then exit without warning */
- if (r < 0 && errno == ENOENT)
+ if (r == -ENOENT)
return 0;
- if (r >= 0) {
- r = lsetfilecon_raw(path, fcon);
-
- /* If the FS doesn't support labels, then exit without warning */
- if (r < 0 && errno == EOPNOTSUPP)
- return 0;
- }
+ goto fail;
}
- if (r < 0) {
- /* Ignore ENOENT in some cases */
- if (ignore_enoent && errno == ENOENT)
+ xsprintf(procfs_path, "/proc/self/fd/%i", fd);
+ if (setfilecon_raw(procfs_path, fcon) < 0) {
+ _cleanup_freecon_ char *oldcon = NULL;
+
+ r = -errno;
+
+ /* If the FS doesn't support labels, then exit without warning */
+ if (r == -EOPNOTSUPP)
return 0;
- if (ignore_erofs && errno == EROFS)
+ /* It the FS is read-only and we were told to ignore failures caused by that, suppress error */
+ if (r == -EROFS && (flags & LABEL_IGNORE_EROFS))
return 0;
- log_enforcing("Unable to fix SELinux security context of %s: %m", path);
- if (security_getenforce() == 1)
- return -errno;
+ /* If the old label is identical to the new one, suppress any kind of error */
+ if (getfilecon_raw(procfs_path, &oldcon) >= 0 && streq(fcon, oldcon))
+ return 0;
+
+ goto fail;
}
+
+ return 0;
+
+fail:
+ log_enforcing_errno(r, "Unable to fix SELinux security context of %s: %m", path);
+ if (security_getenforce() == 1)
+ return r;
#endif
return 0;
@@ -170,7 +177,7 @@ int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
#if 0 /// UNNEDED by elogind
int mac_selinux_apply(const char *path, const char *label) {
-#ifdef HAVE_SELINUX
+#if HAVE_SELINUX
if (!mac_selinux_use())
return 0;
@@ -178,7 +185,7 @@ int mac_selinux_apply(const char *path, const char *label) {
assert(label);
if (setfilecon(path, label) < 0) {
- log_enforcing("Failed to set SELinux security context %s on path %s: %m", label, path);
+ log_enforcing_errno(errno, "Failed to set SELinux security context %s on path %s: %m", label, path);
if (security_getenforce() > 0)
return -errno;
}
@@ -189,7 +196,7 @@ int mac_selinux_apply(const char *path, const char *label) {
int mac_selinux_get_create_label_from_exe(const char *exe, char **label) {
int r = -EOPNOTSUPP;
-#ifdef HAVE_SELINUX
+#if HAVE_SELINUX
_cleanup_freecon_ char *mycon = NULL, *fcon = NULL;
security_class_t sclass;
@@ -221,7 +228,7 @@ int mac_selinux_get_our_label(char **label) {
assert(label);
-#ifdef HAVE_SELINUX
+#if HAVE_SELINUX
if (!mac_selinux_use())
return -EOPNOTSUPP;
@@ -236,7 +243,7 @@ int mac_selinux_get_our_label(char **label) {
int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *exec_label, char **label) {
int r = -EOPNOTSUPP;
-#ifdef HAVE_SELINUX
+#if HAVE_SELINUX
_cleanup_freecon_ char *mycon = NULL, *peercon = NULL, *fcon = NULL;
_cleanup_context_free_ context_t pcon = NULL, bcon = NULL;
security_class_t sclass;
@@ -297,14 +304,13 @@ int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *
char* mac_selinux_free(char *label) {
-#ifdef HAVE_SELINUX
+#if HAVE_SELINUX
if (!label)
return NULL;
if (!mac_selinux_use())
return NULL;
-
freecon(label);
#endif
@@ -314,7 +320,7 @@ char* mac_selinux_free(char *label) {
int mac_selinux_create_file_prepare(const char *path, mode_t mode) {
-#ifdef HAVE_SELINUX
+#if HAVE_SELINUX
_cleanup_freecon_ char *filecon = NULL;
int r;
@@ -340,12 +346,12 @@ int mac_selinux_create_file_prepare(const char *path, mode_t mode) {
if (errno == ENOENT)
return 0;
- log_enforcing("Failed to determine SELinux security context for %s: %m", path);
+ log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", path);
} else {
if (setfscreatecon_raw(filecon) >= 0)
return 0; /* Success! */
- log_enforcing("Failed to set SELinux security context %s for %s: %m", filecon, path);
+ log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", filecon, path);
}
if (security_getenforce() > 0)
@@ -357,7 +363,7 @@ int mac_selinux_create_file_prepare(const char *path, mode_t mode) {
void mac_selinux_create_file_clear(void) {
-#ifdef HAVE_SELINUX
+#if HAVE_SELINUX
PROTECT_ERRNO;
if (!mac_selinux_use())
@@ -370,14 +376,14 @@ void mac_selinux_create_file_clear(void) {
#if 0 /// UNNEEDED by elogind
int mac_selinux_create_socket_prepare(const char *label) {
-#ifdef HAVE_SELINUX
+#if HAVE_SELINUX
if (!mac_selinux_use())
return 0;
assert(label);
if (setsockcreatecon(label) < 0) {
- log_enforcing("Failed to set SELinux security context %s for sockets: %m", label);
+ log_enforcing_errno(errno, "Failed to set SELinux security context %s for sockets: %m", label);
if (security_getenforce() == 1)
return -errno;
@@ -389,7 +395,7 @@ int mac_selinux_create_socket_prepare(const char *label) {
void mac_selinux_create_socket_clear(void) {
-#ifdef HAVE_SELINUX
+#if HAVE_SELINUX
PROTECT_ERRNO;
if (!mac_selinux_use())
@@ -403,7 +409,7 @@ int mac_selinux_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
+#if HAVE_SELINUX
_cleanup_freecon_ char *fcon = NULL;
const struct sockaddr_un *un;
bool context_changed = false;
@@ -449,13 +455,13 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
if (errno == ENOENT)
goto skipped;
- log_enforcing("Failed to determine SELinux security context for %s: %m", path);
+ log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", path);
if (security_getenforce() > 0)
return -errno;
} else {
if (setfscreatecon_raw(fcon) < 0) {
- log_enforcing("Failed to set SELinux security context %s for %s: %m", fcon, path);
+ log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", fcon, path);
if (security_getenforce() > 0)
return -errno;
} else
diff --git a/src/basic/selinux-util.h b/src/basic/selinux-util.h
index 2a71afefa..b2a0d6dd4 100644
--- a/src/basic/selinux-util.h
+++ b/src/basic/selinux-util.h
@@ -1,29 +1,12 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "macro.h"
+#include "label.h"
bool mac_selinux_use(void);
void mac_selinux_retest(void);
@@ -31,7 +14,7 @@ void mac_selinux_retest(void);
int mac_selinux_init(void);
void mac_selinux_finish(void);
-int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs);
+int mac_selinux_fix(const char *path, LabelFixFlags flags);
#if 0 /// UNNEEDED by elogind
int mac_selinux_apply(const char *path, const char *label);
diff --git a/src/basic/set.h b/src/basic/set.h
index 70c462a1a..4307c3c3b 100644
--- a/src/basic/set.h
+++ b/src/basic/set.h
@@ -1,24 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 "extract-word.h"
#include "hashmap.h"
#include "macro.h"
@@ -108,6 +91,18 @@ static inline void *set_steal_first(Set *s) {
return internal_hashmap_steal_first(HASHMAP_BASE(s));
}
+#define set_clear_with_destructor(_s, _f) \
+ ({ \
+ void *_item; \
+ while ((_item = set_steal_first(_s))) \
+ _f(_item); \
+ })
+#define set_free_with_destructor(_s, _f) \
+ ({ \
+ set_clear_with_destructor(_s, _f); \
+ set_free(_s); \
+ })
+
/* no set_steal_first_key */
/* no set_first_key */
diff --git a/src/basic/sigbus.c b/src/basic/sigbus.c
new file mode 100644
index 000000000..70afba6bc
--- /dev/null
+++ b/src/basic/sigbus.c
@@ -0,0 +1,135 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <errno.h>
+#include <signal.h>
+#include <stddef.h>
+#include <sys/mman.h>
+
+#include "macro.h"
+#include "sigbus.h"
+#include "util.h"
+
+#define SIGBUS_QUEUE_MAX 64
+
+static struct sigaction old_sigaction;
+static unsigned n_installed = 0;
+
+/* We maintain a fixed size list of page addresses that triggered a
+ SIGBUS. We access with list with atomic operations, so that we
+ don't have to deal with locks between signal handler and main
+ programs in possibly multiple threads. */
+
+static void* volatile sigbus_queue[SIGBUS_QUEUE_MAX];
+static volatile sig_atomic_t n_sigbus_queue = 0;
+
+static void sigbus_push(void *addr) {
+ unsigned u;
+
+ assert(addr);
+
+ /* Find a free place, increase the number of entries and leave, if we can */
+ for (u = 0; u < SIGBUS_QUEUE_MAX; u++)
+ if (__sync_bool_compare_and_swap(&sigbus_queue[u], NULL, addr)) {
+ __sync_fetch_and_add(&n_sigbus_queue, 1);
+ return;
+ }
+
+ /* If we can't, make sure the queue size is out of bounds, to
+ * mark it as overflow */
+ for (;;) {
+ unsigned c;
+
+ __sync_synchronize();
+ c = n_sigbus_queue;
+
+ if (c > SIGBUS_QUEUE_MAX) /* already overflow */
+ return;
+
+ if (__sync_bool_compare_and_swap(&n_sigbus_queue, c, c + SIGBUS_QUEUE_MAX))
+ return;
+ }
+}
+
+int sigbus_pop(void **ret) {
+ assert(ret);
+
+ for (;;) {
+ unsigned u, c;
+
+ __sync_synchronize();
+ c = n_sigbus_queue;
+
+ if (_likely_(c == 0))
+ return 0;
+
+ if (_unlikely_(c >= SIGBUS_QUEUE_MAX))
+ return -EOVERFLOW;
+
+ for (u = 0; u < SIGBUS_QUEUE_MAX; u++) {
+ void *addr;
+
+ addr = sigbus_queue[u];
+ if (!addr)
+ continue;
+
+ if (__sync_bool_compare_and_swap(&sigbus_queue[u], addr, NULL)) {
+ __sync_fetch_and_sub(&n_sigbus_queue, 1);
+ *ret = addr;
+ return 1;
+ }
+ }
+ }
+}
+
+static void sigbus_handler(int sn, siginfo_t *si, void *data) {
+ unsigned long ul;
+ void *aligned;
+
+ assert(sn == SIGBUS);
+ assert(si);
+
+ if (si->si_code != BUS_ADRERR || !si->si_addr) {
+ assert_se(sigaction(SIGBUS, &old_sigaction, NULL) == 0);
+ raise(SIGBUS);
+ return;
+ }
+
+ ul = (unsigned long) si->si_addr;
+ ul = ul / page_size();
+ ul = ul * page_size();
+ aligned = (void*) ul;
+
+ /* Let's remember which address failed */
+ sigbus_push(aligned);
+
+ /* Replace mapping with an anonymous page, so that the
+ * execution can continue, however with a zeroed out page */
+ assert_se(mmap(aligned, page_size(), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0) == aligned);
+}
+
+void sigbus_install(void) {
+ struct sigaction sa = {
+ .sa_sigaction = sigbus_handler,
+ .sa_flags = SA_SIGINFO,
+ };
+
+ n_installed++;
+
+ if (n_installed == 1)
+ assert_se(sigaction(SIGBUS, &sa, &old_sigaction) == 0);
+
+ return;
+}
+
+void sigbus_reset(void) {
+
+ if (n_installed <= 0)
+ return;
+
+ n_installed--;
+
+ if (n_installed == 0)
+ assert_se(sigaction(SIGBUS, &old_sigaction, NULL) == 0);
+
+ return;
+}
diff --git a/src/basic/sigbus.h b/src/basic/sigbus.h
new file mode 100644
index 000000000..459e19fca
--- /dev/null
+++ b/src/basic/sigbus.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+void sigbus_install(void);
+void sigbus_reset(void);
+
+int sigbus_pop(void **ret);
diff --git a/src/basic/signal-util.c b/src/basic/signal-util.c
index 8e83bfcf0..038b191b4 100644
--- a/src/basic/signal-util.c
+++ b/src/basic/signal-util.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <stdarg.h>
@@ -38,7 +21,7 @@ int reset_all_signal_handlers(void) {
for (sig = 1; sig < _NSIG; sig++) {
/* These two cannot be caught... */
- if (sig == SIGKILL || sig == SIGSTOP)
+ if (IN_SET(sig, SIGKILL, SIGSTOP))
continue;
/* On Linux the first two RT signals are reserved by
@@ -227,7 +210,7 @@ static const char *const __signal_table[] = {
DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
const char *signal_to_string(int signo) {
- static thread_local char buf[sizeof("RTMIN+")-1 + DECIMAL_STR_MAX(int) + 1];
+ static thread_local char buf[STRLEN("RTMIN+") + DECIMAL_STR_MAX(int) + 1];
const char *name;
name = __signal_to_string(signo);
@@ -243,38 +226,68 @@ const char *signal_to_string(int signo) {
}
int signal_from_string(const char *s) {
- int signo;
- int offset = 0;
- unsigned u;
+ const char *p;
+ int signo, r;
+ /* Check that the input is a signal number. */
+ if (safe_atoi(s, &signo) >= 0) {
+ if (SIGNAL_VALID(signo))
+ return signo;
+ else
+ return -ERANGE;
+ }
+
+ /* Drop "SIG" prefix. */
+ if (startswith(s, "SIG"))
+ s += 3;
+
+ /* Check that the input is a signal name. */
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 (SIGNAL_VALID(signo))
- return signo;
+ /* Check that the input is RTMIN or
+ * RTMIN+n (0 <= n <= SIGRTMAX-SIGRTMIN). */
+ p = startswith(s, "RTMIN");
+ if (p) {
+ if (*p == '\0')
+ return SIGRTMIN;
+ if (*p != '+')
+ return -EINVAL;
+
+ r = safe_atoi(p, &signo);
+ if (r < 0)
+ return r;
+
+ if (signo < 0 || signo > SIGRTMAX - SIGRTMIN)
+ return -ERANGE;
+
+ return signo + SIGRTMIN;
}
- return -EINVAL;
-}
-int signal_from_string_try_harder(const char *s) {
- int signo;
- assert(s);
+ /* Check that the input is RTMAX or
+ * RTMAX-n (0 <= n <= SIGRTMAX-SIGRTMIN). */
+ p = startswith(s, "RTMAX");
+ if (p) {
+ if (*p == '\0')
+ return SIGRTMAX;
+ if (*p != '-')
+ return -EINVAL;
- signo = signal_from_string(s);
- if (signo <= 0)
- if (startswith(s, "SIG"))
- return signal_from_string(s+3);
+ r = safe_atoi(p, &signo);
+ if (r < 0)
+ return r;
- return signo;
+ if (signo > 0 || signo < SIGRTMIN - SIGRTMAX)
+ return -ERANGE;
+
+ return signo + SIGRTMAX;
+ }
+
+ return -EINVAL;
}
+
#if 0 /// UNNEEDED by elogind
void nop_signal_handler(int sig) {
/* nothing here */
diff --git a/src/basic/signal-util.h b/src/basic/signal-util.h
index 8dc9e3aea..dfa4a75e8 100644
--- a/src/basic/signal-util.h
+++ b/src/basic/signal-util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010-2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 "macro.h"
@@ -38,9 +20,7 @@ int sigprocmask_many(int how, sigset_t *old, ...);
const char *signal_to_string(int i) _const_;
int signal_from_string(const char *s) _pure_;
-int signal_from_string_try_harder(const char *s);
#if 0 /// UNNEEDED by elogind
-
void nop_signal_handler(int sig);
#endif // 0
@@ -48,13 +28,20 @@ static inline void block_signals_reset(sigset_t *ss) {
assert_se(sigprocmask(SIG_SETMASK, ss, NULL) >= 0);
}
-#define BLOCK_SIGNALS(...) \
- _cleanup_(block_signals_reset) _unused_ sigset_t _saved_sigset = ({ \
- sigset_t t; \
- assert_se(sigprocmask_many(SIG_BLOCK, &t, __VA_ARGS__, -1) >= 0); \
- t; \
+#define BLOCK_SIGNALS(...) \
+ _cleanup_(block_signals_reset) _unused_ sigset_t _saved_sigset = ({ \
+ sigset_t _t; \
+ assert_se(sigprocmask_many(SIG_BLOCK, &_t, __VA_ARGS__, -1) >= 0); \
+ _t; \
})
static inline bool SIGNAL_VALID(int signo) {
return signo > 0 && signo < _NSIG;
}
+
+static inline const char* signal_to_string_with_check(int n) {
+ if (!SIGNAL_VALID(n))
+ return NULL;
+
+ return signal_to_string(n);
+}
diff --git a/src/basic/siphash24.c b/src/basic/siphash24.c
index e8b18dd16..fe1413469 100644
--- a/src/basic/siphash24.c
+++ b/src/basic/siphash24.c
@@ -69,7 +69,7 @@ void siphash24_init(struct siphash *state, const uint8_t k[16]) {
}
#if 1 /// let's add a diagnostic push to silence -Wimplicit-fallthrough to elogind
-# ifdef __GNUC__
+# if defined(__GNUC__) && (__GNUC__ > 6)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
# endif // __GNUC__
@@ -133,25 +133,25 @@ void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
switch (left) {
case 7:
state->padding |= ((uint64_t) in[6]) << 48;
- /* fall through */
+ _fallthrough_;
case 6:
state->padding |= ((uint64_t) in[5]) << 40;
- /* fall through */
+ _fallthrough_;
case 5:
state->padding |= ((uint64_t) in[4]) << 32;
- /* fall through */
+ _fallthrough_;
case 4:
state->padding |= ((uint64_t) in[3]) << 24;
- /* fall through */
+ _fallthrough_;
case 3:
state->padding |= ((uint64_t) in[2]) << 16;
- /* fall through */
+ _fallthrough_;
case 2:
state->padding |= ((uint64_t) in[1]) << 8;
- /* fall through */
+ _fallthrough_;
case 1:
state->padding |= ((uint64_t) in[0]);
- /* fall through */
+ _fallthrough_;
case 0:
break;
}
diff --git a/src/basic/smack-util.c b/src/basic/smack-util.c
index 9bcc4a3a2..8c82d008c 100644
--- a/src/basic/smack-util.c
+++ b/src/basic/smack-util.c
@@ -1,41 +1,30 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Intel Corporation
+ Copyright © 2013 Intel Corporation
Author: 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 <errno.h>
+#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/xattr.h>
#include <unistd.h>
#include "alloc-util.h"
+#include "fd-util.h"
#include "fileio.h"
#include "log.h"
#include "macro.h"
#include "path-util.h"
#include "process-util.h"
#include "smack-util.h"
+#include "stdio-util.h"
#include "string-table.h"
#include "xattr-util.h"
-#ifdef HAVE_SMACK
+#if ENABLE_SMACK
bool mac_smack_use(void) {
static int cached_use = -1;
@@ -135,59 +124,84 @@ int mac_smack_apply_pid(pid_t pid, const char *label) {
}
#endif // 0
-int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
+int mac_smack_fix(const char *path, LabelFixFlags flags) {
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+ _cleanup_close_ int fd = -1;
+ const char *label;
struct stat st;
- int r = 0;
+ int r;
assert(path);
if (!mac_smack_use())
return 0;
+ /* Path must be in /dev. Note that this check is pretty sloppy, as we might be called with non-normalized paths
+ * and hence not detect all cases of /dev. */
+
+ if (path_is_absolute(path)) {
+ if (!path_startswith(path, "/dev"))
+ return 0;
+ } else {
+ _cleanup_free_ char *cwd = NULL;
+
+ r = safe_getcwd(&cwd);
+ if (r < 0)
+ return r;
+
+ if (!path_startswith(cwd, "/dev"))
+ return 0;
+ }
+
+ fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
+ if (fd < 0) {
+ if ((flags & LABEL_IGNORE_ENOENT) && errno == ENOENT)
+ return 0;
+
+ return -errno;
+ }
+
+ if (fstat(fd, &st) < 0)
+ return -errno;
+
/*
- * Path must be in /dev and must exist
+ * Label directories and character devices "*".
+ * Label symlinks "_".
+ * Don't change anything else.
*/
- if (!path_startswith(path, "/dev"))
+
+ if (S_ISDIR(st.st_mode))
+ label = SMACK_STAR_LABEL;
+ else if (S_ISLNK(st.st_mode))
+ label = SMACK_FLOOR_LABEL;
+ else if (S_ISCHR(st.st_mode))
+ label = SMACK_STAR_LABEL;
+ else
return 0;
- r = lstat(path, &st);
- if (r >= 0) {
- const char *label;
-
- /*
- * Label directories and character devices "*".
- * Label symlinks "_".
- * Don't change anything else.
- */
-
- if (S_ISDIR(st.st_mode))
- label = SMACK_STAR_LABEL;
- else if (S_ISLNK(st.st_mode))
- label = SMACK_FLOOR_LABEL;
- else if (S_ISCHR(st.st_mode))
- label = SMACK_STAR_LABEL;
- else
- return 0;
+ xsprintf(procfs_path, "/proc/self/fd/%i", fd);
+ if (setxattr(procfs_path, "security.SMACK64", label, strlen(label), 0) < 0) {
+ _cleanup_free_ char *old_label = NULL;
- r = lsetxattr(path, "security.SMACK64", label, strlen(label), 0);
+ r = -errno;
/* If the FS doesn't support labels, then exit without warning */
- if (r < 0 && errno == EOPNOTSUPP)
+ if (r == -EOPNOTSUPP)
return 0;
- }
- if (r < 0) {
- /* Ignore ENOENT in some cases */
- if (ignore_enoent && errno == ENOENT)
+ /* It the FS is read-only and we were told to ignore failures caused by that, suppress error */
+ if (r == -EROFS && (flags & LABEL_IGNORE_EROFS))
return 0;
- if (ignore_erofs && errno == EROFS)
+ /* If the old label is identical to the new one, suppress any kind of error */
+ if (getxattr_malloc(procfs_path, "security.SMACK64", &old_label, false) >= 0 &&
+ streq(old_label, label))
return 0;
- r = log_debug_errno(errno, "Unable to fix SMACK label of %s: %m", path);
+ return log_debug_errno(r, "Unable to fix SMACK label of %s: %m", path);
}
- return r;
+ return 0;
}
#if 0 /// UNNEEDED by elogind
@@ -237,7 +251,7 @@ int mac_smack_apply_pid(pid_t pid, const char *label) {
}
#endif // 0
-int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
+int mac_smack_fix(const char *path, LabelFixFlags flags) {
return 0;
}
diff --git a/src/basic/smack-util.h b/src/basic/smack-util.h
index 797c7f0de..2424d479e 100644
--- a/src/basic/smack-util.h
+++ b/src/basic/smack-util.h
@@ -1,29 +1,16 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Intel Corporation
+ Copyright © 2013 Intel Corporation
Author: 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 <stdbool.h>
#include <sys/types.h>
+#include "label.h"
#include "macro.h"
#define SMACK_FLOOR_LABEL "_"
@@ -31,12 +18,12 @@
#if 0 /// UNNEEDED by elogind
typedef enum SmackAttr {
- SMACK_ATTR_ACCESS = 0,
- SMACK_ATTR_EXEC = 1,
- SMACK_ATTR_MMAP = 2,
- SMACK_ATTR_TRANSMUTE = 3,
- SMACK_ATTR_IPIN = 4,
- SMACK_ATTR_IPOUT = 5,
+ SMACK_ATTR_ACCESS,
+ SMACK_ATTR_EXEC,
+ SMACK_ATTR_MMAP,
+ SMACK_ATTR_TRANSMUTE,
+ SMACK_ATTR_IPIN,
+ SMACK_ATTR_IPOUT,
_SMACK_ATTR_MAX,
_SMACK_ATTR_INVALID = -1,
} SmackAttr;
@@ -44,7 +31,7 @@ typedef enum SmackAttr {
bool mac_smack_use(void);
-int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs);
+int mac_smack_fix(const char *path, LabelFixFlags flags);
#if 0 /// UNNEEDED by elogind
const char* smack_attr_to_string(SmackAttr i) _const_;
diff --git a/src/basic/socket-protocol-to-name.awk b/src/basic/socket-protocol-to-name.awk
new file mode 100644
index 000000000..4848a7631
--- /dev/null
+++ b/src/basic/socket-protocol-to-name.awk
@@ -0,0 +1,9 @@
+BEGIN{
+ print "static const char* const socket_protocol_names[] = { "
+}
+!/HOPOPTS/ {
+ printf " [IPPROTO_%s] = \"%s\",\n", $1, tolower($1)
+}
+END{
+ print "};"
+}
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c
index c1312c1d2..7958e815b 100644
--- a/src/basic/socket-util.c
+++ b/src/basic/socket-util.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <arpa/inet.h>
#include <errno.h>
@@ -23,6 +6,7 @@
#include <net/if.h>
#include <netdb.h>
#include <netinet/ip.h>
+#include <poll.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
@@ -39,6 +23,7 @@
#include "missing.h"
#include "parse-util.h"
#include "path-util.h"
+#include "process-util.h"
#include "socket-util.h"
#include "string-table.h"
#include "string-util.h"
@@ -48,12 +33,23 @@
#include "util.h"
#if 0 /// UNNEEDED by elogind
-#ifdef ENABLE_IDN
-# define IDN_FLAGS (NI_IDN|NI_IDN_USE_STD3_ASCII_RULES)
+#if ENABLE_IDN
+# define IDN_FLAGS NI_IDN
#else
# define IDN_FLAGS 0
#endif
+static const char* const socket_address_type_table[] = {
+ [SOCK_STREAM] = "Stream",
+ [SOCK_DGRAM] = "Datagram",
+ [SOCK_RAW] = "Raw",
+ [SOCK_RDM] = "ReliableDatagram",
+ [SOCK_SEQPACKET] = "SequentialPacket",
+ [SOCK_DCCP] = "DatagramCongestionControl",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(socket_address_type, int);
+
int socket_address_parse(SocketAddress *a, const char *s) {
char *e, *n;
unsigned u;
@@ -66,6 +62,8 @@ int socket_address_parse(SocketAddress *a, const char *s) {
a->type = SOCK_STREAM;
if (*s == '[') {
+ uint16_t port;
+
/* IPv6 in [x:.....:z]:p notation */
e = strchr(s+1, ']');
@@ -84,6 +82,7 @@ int socket_address_parse(SocketAddress *a, const char *s) {
e++;
r = safe_atou(e, &u);
+ r = parse_ip_port(e, &port);
if (r < 0)
return r;
@@ -92,6 +91,7 @@ int socket_address_parse(SocketAddress *a, const char *s) {
a->sockaddr.in6.sin6_family = AF_INET6;
a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
+ a->sockaddr.in6.sin6_port = htobe16(port);
a->size = sizeof(struct sockaddr_in6);
} else if (*s == '/') {
@@ -121,13 +121,15 @@ int socket_address_parse(SocketAddress *a, const char *s) {
} else if (startswith(s, "vsock:")) {
/* AF_VSOCK socket in vsock:cid:port notation */
- const char *cid_start = s + strlen("vsock:");
+ const char *cid_start = s + STRLEN("vsock:");
+ unsigned port;
e = strchr(cid_start, ':');
if (!e)
return -EINVAL;
r = safe_atou(e+1, &u);
+ r = safe_atou(e+1, &port);
if (r < 0)
return r;
@@ -141,12 +143,16 @@ int socket_address_parse(SocketAddress *a, const char *s) {
a->sockaddr.vm.svm_family = AF_VSOCK;
a->sockaddr.vm.svm_port = u;
+ a->sockaddr.vm.svm_port = port;
a->size = sizeof(struct sockaddr_vm);
} else {
+ uint16_t port;
+
e = strchr(s, ':');
if (e) {
r = safe_atou(e+1, &u);
+ r = parse_ip_port(e + 1, &port);
if (r < 0)
return r;
@@ -164,6 +170,7 @@ int socket_address_parse(SocketAddress *a, const char *s) {
/* Gotcha, it's a traditional IPv4 address */
a->sockaddr.in.sin_family = AF_INET;
a->sockaddr.in.sin_port = htobe16((uint16_t)u);
+ a->sockaddr.in.sin_port = htobe16(port);
a->size = sizeof(struct sockaddr_in);
} else {
unsigned idx;
@@ -178,6 +185,7 @@ int socket_address_parse(SocketAddress *a, const char *s) {
a->sockaddr.in6.sin6_family = AF_INET6;
a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
+ a->sockaddr.in6.sin6_port = htobe16(port);
a->sockaddr.in6.sin6_scope_id = idx;
a->sockaddr.in6.sin6_addr = in6addr_any;
a->size = sizeof(struct sockaddr_in6);
@@ -186,6 +194,7 @@ int socket_address_parse(SocketAddress *a, const char *s) {
/* Just a port */
r = safe_atou(s, &u);
+ r = parse_ip_port(s, &port);
if (r < 0)
return r;
@@ -195,11 +204,13 @@ int socket_address_parse(SocketAddress *a, const char *s) {
if (socket_ipv6_is_supported()) {
a->sockaddr.in6.sin6_family = AF_INET6;
a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
+ a->sockaddr.in6.sin6_port = htobe16(port);
a->sockaddr.in6.sin6_addr = in6addr_any;
a->size = sizeof(struct sockaddr_in6);
} else {
a->sockaddr.in.sin_family = AF_INET;
a->sockaddr.in.sin_port = htobe16((uint16_t)u);
+ a->sockaddr.in.sin_port = htobe16(port);
a->sockaddr.in.sin_addr.s_addr = INADDR_ANY;
a->size = sizeof(struct sockaddr_in);
}
@@ -268,7 +279,7 @@ int socket_address_verify(const SocketAddress *a) {
if (a->sockaddr.in.sin_port == 0)
return -EINVAL;
- if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM)
+ if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM))
return -EINVAL;
return 0;
@@ -280,7 +291,7 @@ int socket_address_verify(const SocketAddress *a) {
if (a->sockaddr.in6.sin6_port == 0)
return -EINVAL;
- if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM)
+ if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM))
return -EINVAL;
return 0;
@@ -304,7 +315,7 @@ int socket_address_verify(const SocketAddress *a) {
}
}
- if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM && a->type != SOCK_SEQPACKET)
+ if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET))
return -EINVAL;
return 0;
@@ -314,7 +325,7 @@ int socket_address_verify(const SocketAddress *a) {
if (a->size != sizeof(struct sockaddr_nl))
return -EINVAL;
- if (a->type != SOCK_RAW && a->type != SOCK_DGRAM)
+ if (!IN_SET(a->type, SOCK_RAW, SOCK_DGRAM))
return -EINVAL;
return 0;
@@ -323,7 +334,7 @@ int socket_address_verify(const SocketAddress *a) {
if (a->size != sizeof(struct sockaddr_vm))
return -EINVAL;
- if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM)
+ if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM))
return -EINVAL;
return 0;
@@ -364,8 +375,7 @@ bool socket_address_can_accept(const SocketAddress *a) {
assert(a);
return
- a->type == SOCK_STREAM ||
- a->type == SOCK_SEQPACKET;
+ IN_SET(a->type, SOCK_STREAM, SOCK_SEQPACKET);
}
bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) {
@@ -527,23 +537,27 @@ bool socket_address_matches_fd(const SocketAddress *a, int fd) {
return socket_address_equal(a, &b);
}
+#endif // 0
-int sockaddr_port(const struct sockaddr *_sa, unsigned *port) {
+int sockaddr_port(const struct sockaddr *_sa, unsigned *ret_port) {
union sockaddr_union *sa = (union sockaddr_union*) _sa;
+ /* Note, this returns the port as 'unsigned' rather than 'uint16_t', as AF_VSOCK knows larger ports */
+
assert(sa);
switch (sa->sa.sa_family) {
+
case AF_INET:
- *port = be16toh(sa->in.sin_port);
+ *ret_port = be16toh(sa->in.sin_port);
return 0;
case AF_INET6:
- *port = be16toh(sa->in6.sin6_port);
+ *ret_port = be16toh(sa->in6.sin6_port);
return 0;
case AF_VSOCK:
- *port = sa->vm.svm_port;
+ *ret_port = sa->vm.svm_port;
return 0;
default:
@@ -551,6 +565,7 @@ int sockaddr_port(const struct sockaddr *_sa, unsigned *port) {
}
}
+#if 0 /// UNNEEDED by elogind
int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret) {
union sockaddr_union *sa = (union sockaddr_union*) _sa;
char *p;
@@ -667,7 +682,6 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
return -EOPNOTSUPP;
}
-
*ret = p;
return 0;
}
@@ -748,19 +762,6 @@ int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret)
return 0;
}
-int getnameinfo_pretty(int fd, char **ret) {
- union sockaddr_union sa;
- socklen_t salen = sizeof(sa);
-
- assert(fd >= 0);
- assert(ret);
-
- if (getsockname(fd, &sa.sa, &salen) < 0)
- return -errno;
-
- return socknameinfo_pretty(&sa, salen, ret);
-}
-
int socket_address_unlink(SocketAddress *a) {
assert(a);
@@ -793,7 +794,8 @@ static const char* const netlink_family_table[] = {
[NETLINK_KOBJECT_UEVENT] = "kobject-uevent",
[NETLINK_GENERIC] = "generic",
[NETLINK_SCSITRANSPORT] = "scsitransport",
- [NETLINK_ECRYPTFS] = "ecryptfs"
+ [NETLINK_ECRYPTFS] = "ecryptfs",
+ [NETLINK_RDMA] = "rdma",
};
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family, int, INT_MAX);
@@ -806,6 +808,18 @@ static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIN
DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
+SocketAddressBindIPv6Only socket_address_bind_ipv6_only_or_bool_from_string(const char *n) {
+ int r;
+
+ r = parse_boolean(n);
+ if (r > 0)
+ return SOCKET_ADDRESS_IPV6_ONLY;
+ if (r == 0)
+ return SOCKET_ADDRESS_BOTH;
+
+ return socket_address_bind_ipv6_only_from_string(n);
+}
+
bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b) {
assert(a);
assert(b);
@@ -894,7 +908,7 @@ bool ifname_valid(const char *p) {
if ((unsigned char) *p <= 32U)
return false;
- if (*p == ':' || *p == '/')
+ if (IN_SET(*p, ':', '/'))
return false;
numeric = numeric && (*p >= '0' && *p <= '9');
@@ -943,56 +957,76 @@ int getpeercred(int fd, struct ucred *ucred) {
if (n != sizeof(struct ucred))
return -EIO;
- /* Check if the data is actually useful and not suppressed due
- * to namespacing issues */
- if (u.pid <= 0)
- return -ENODATA;
- if (u.uid == UID_INVALID)
- return -ENODATA;
- if (u.gid == GID_INVALID)
+ /* Check if the data is actually useful and not suppressed due to namespacing issues */
+ if (!pid_is_valid(u.pid))
return -ENODATA;
+ /* Note that we don't check UID/GID here, as namespace translation works differently there: instead of
+ * receiving in "invalid" user/group we get the overflow UID/GID. */
+
*ucred = u;
return 0;
}
int getpeersec(int fd, char **ret) {
+ _cleanup_free_ char *s = NULL;
socklen_t n = 64;
- char *s;
- int r;
assert(fd >= 0);
assert(ret);
- s = new0(char, n);
- if (!s)
- return -ENOMEM;
+ for (;;) {
+ s = new0(char, n+1);
+ if (!s)
+ return -ENOMEM;
- r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
- if (r < 0) {
- free(s);
+ if (getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n) >= 0)
+ break;
if (errno != ERANGE)
return -errno;
- s = new0(char, n);
- if (!s)
+ s = mfree(s);
+ }
+
+ if (isempty(s))
+ return -EOPNOTSUPP;
+
+ *ret = TAKE_PTR(s);
+
+ return 0;
+}
+
+int getpeergroups(int fd, gid_t **ret) {
+ socklen_t n = sizeof(gid_t) * 64;
+ _cleanup_free_ gid_t *d = NULL;
+
+ assert(fd >= 0);
+ assert(ret);
+
+ for (;;) {
+ d = malloc(n);
+ if (!d)
return -ENOMEM;
- r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
- if (r < 0) {
- free(s);
+ if (getsockopt(fd, SOL_SOCKET, SO_PEERGROUPS, d, &n) >= 0)
+ break;
+
+ if (errno != ERANGE)
return -errno;
- }
- }
- if (isempty(s)) {
- free(s);
- return -EOPNOTSUPP;
+ d = mfree(d);
}
- *ret = s;
- return 0;
+ assert_se(n % sizeof(gid_t) == 0);
+ n /= sizeof(gid_t);
+
+ if ((socklen_t) (int) n != n)
+ return -E2BIG;
+
+ *ret = TAKE_PTR(d);
+
+ return (int) n;
}
int send_one_fd_sa(
@@ -1051,7 +1085,7 @@ int receive_one_fd(int transport_fd, int flags) {
* combination with send_one_fd().
*/
- if (recvmsg(transport_fd, &mh, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC | flags) < 0)
+ if (recvmsg(transport_fd, &mh, MSG_CMSG_CLOEXEC | flags) < 0)
return -errno;
CMSG_FOREACH(cmsg, &mh) {
@@ -1084,7 +1118,7 @@ ssize_t next_datagram_size_fd(int fd) {
l = recv(fd, NULL, 0, MSG_PEEK|MSG_TRUNC);
if (l < 0) {
- if (errno == EOPNOTSUPP || errno == EFAULT)
+ if (IN_SET(errno, EOPNOTSUPP, EFAULT))
goto fallback;
return -errno;
@@ -1114,7 +1148,6 @@ int flush_accept(int fd) {
};
int r;
-
/* Similar to flush_fd() but flushes all incoming connection by accepting them and immediately closing them. */
for (;;) {
diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h
index ad1924474..35191616f 100644
--- a/src/basic/socket-util.h
+++ b/src/basic/socket-util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 <netinet/ether.h>
#include <netinet/in.h>
#include <stdbool.h>
@@ -27,22 +9,36 @@
#include <sys/types.h>
#include <sys/un.h>
#include <linux/netlink.h>
+#include <linux/if_infiniband.h>
#include <linux/if_packet.h>
#include "macro.h"
+#include "missing.h"
#include "util.h"
union sockaddr_union {
+ /* The minimal, abstract version */
struct sockaddr sa;
+
+ /* The libc provided version that allocates "enough room" for every protocol */
+ struct sockaddr_storage storage;
+
+ /* Protoctol-specific implementations */
struct sockaddr_in in;
struct sockaddr_in6 in6;
struct sockaddr_un un;
-#if 0 /// UNNEEDED by elogind, only 'sa', 'in', 'in6' and 'un' are used in all of elogind.
+#if 0 /// UNNEEDED by elogind.
struct sockaddr_nl nl;
- struct sockaddr_storage storage;
struct sockaddr_ll ll;
- struct sockaddr_vm vm;
#endif // 0
+ struct sockaddr_vm vm;
+
+ /* Ensure there is enough space to store Infiniband addresses */
+ uint8_t ll_buffer[offsetof(struct sockaddr_ll, sll_addr) + CONST_MAX(ETH_ALEN, INFINIBAND_ALEN)];
+
+ /* Ensure there is enough space after the AF_UNIX sun_path for one more NUL byte, just to be sure that the path
+ * component is always followed by at least one NUL byte. */
+ uint8_t un_buffer[sizeof(struct sockaddr_un) + 1];
};
#if 0 /// UNNEEDED by elogind
@@ -70,6 +66,9 @@ typedef enum SocketAddressBindIPv6Only {
#define socket_address_family(a) ((a)->sockaddr.sa.sa_family)
+const char* socket_address_type_to_string(int t) _const_;
+int socket_address_type_from_string(const char *s) _pure_;
+
int socket_address_parse(SocketAddress *a, const char *s);
int socket_address_parse_and_warn(SocketAddress *a, const char *s);
int socket_address_parse_netlink(SocketAddress *a, const char *s);
@@ -103,18 +102,20 @@ bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) _pure_
const char* socket_address_get_path(const SocketAddress *a);
bool socket_ipv6_is_supported(void);
+#endif // 0
int sockaddr_port(const struct sockaddr *_sa, unsigned *port);
+#if 0 /// UNNEEDED by elogind
int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret);
int getpeername_pretty(int fd, bool include_port, char **ret);
int getsockname_pretty(int fd, char **ret);
int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret);
-int getnameinfo_pretty(int fd, char **ret);
const char* socket_address_bind_ipv6_only_to_string(SocketAddressBindIPv6Only b) _const_;
SocketAddressBindIPv6Only socket_address_bind_ipv6_only_from_string(const char *s) _pure_;
+SocketAddressBindIPv6Only socket_address_bind_ipv6_only_or_bool_from_string(const char *s);
int netlink_family_to_string_alloc(int b, char **s);
int netlink_family_from_string(const char *s) _pure_;
@@ -135,6 +136,7 @@ bool address_label_valid(const char *p);
int getpeercred(int fd, struct ucred *ucred);
int getpeersec(int fd, char **ret);
+int getpeergroups(int fd, gid_t **ret);
int send_one_fd_sa(int transport_fd,
int fd,
@@ -156,6 +158,23 @@ int flush_accept(int fd);
struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length);
#endif // 0
+/*
+ * Certain hardware address types (e.g Infiniband) do not fit into sll_addr
+ * (8 bytes) and run over the structure. This macro returns the correct size that
+ * must be passed to kernel.
+ */
+#define SOCKADDR_LL_LEN(sa) \
+ ({ \
+ const struct sockaddr_ll *_sa = &(sa); \
+ size_t _mac_len = sizeof(_sa->sll_addr); \
+ assert(_sa->sll_family == AF_PACKET); \
+ if (be16toh(_sa->sll_hatype) == ARPHRD_ETHER) \
+ _mac_len = MAX(_mac_len, (size_t) ETH_ALEN); \
+ if (be16toh(_sa->sll_hatype) == ARPHRD_INFINIBAND) \
+ _mac_len = MAX(_mac_len, (size_t) INFINIBAND_ALEN); \
+ offsetof(struct sockaddr_ll, sll_addr) + _mac_len; \
+ })
+
/* Covers only file system and abstract AF_UNIX socket addresses, but not unnamed socket addresses. */
#define SOCKADDR_UN_LEN(sa) \
({ \
diff --git a/src/basic/sparse-endian.h b/src/basic/sparse-endian.h
index a3573b84a..5e59de543 100644
--- a/src/basic/sparse-endian.h
+++ b/src/basic/sparse-endian.h
@@ -1,4 +1,6 @@
-/* Copyright (c) 2012 Josh Triplett <josh@joshtriplett.org>
+/* SPDX-License-Identifier: MIT
+ *
+ * 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
diff --git a/src/basic/special.h b/src/basic/special.h
new file mode 100644
index 000000000..379a3d797
--- /dev/null
+++ b/src/basic/special.h
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#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"
+#define SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET "suspend-then-hibernate.target"
+
+/* Special boot targets */
+#define SPECIAL_RESCUE_TARGET "rescue.target"
+#define SPECIAL_EMERGENCY_TARGET "emergency.target"
+#define SPECIAL_MULTI_USER_TARGET "multi-user.target"
+#define SPECIAL_GRAPHICAL_TARGET "graphical.target"
+
+/* Early boot targets */
+#define SPECIAL_SYSINIT_TARGET "sysinit.target"
+#define SPECIAL_SOCKETS_TARGET "sockets.target"
+#define SPECIAL_TIMERS_TARGET "timers.target"
+#define SPECIAL_PATHS_TARGET "paths.target"
+#define SPECIAL_LOCAL_FS_TARGET "local-fs.target"
+#define SPECIAL_LOCAL_FS_PRE_TARGET "local-fs-pre.target"
+#define SPECIAL_INITRD_FS_TARGET "initrd-fs.target"
+#define SPECIAL_INITRD_ROOT_DEVICE_TARGET "initrd-root-device.target"
+#define SPECIAL_INITRD_ROOT_FS_TARGET "initrd-root-fs.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_NETWORK_ONLINE_TARGET "network-online.target"
+#define SPECIAL_TIME_SYNC_TARGET "time-sync.target" /* LSB's $time */
+#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 */
+
+/*
+ * 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"
+#define SPECIAL_TMPFILES_SETUP_SERVICE "systemd-tmpfiles-setup.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"
+
+/* Where we add all our system units, users and machines by default */
+#define SPECIAL_SYSTEM_SLICE "system.slice"
+#define SPECIAL_USER_SLICE "user.slice"
+#define SPECIAL_MACHINE_SLICE "machine.slice"
+#define SPECIAL_ROOT_SLICE "-.slice"
+
+/* The scope unit systemd itself lives in. */
+#define SPECIAL_INIT_SCOPE "init.scope"
+
+/* The root directory. */
+#define SPECIAL_ROOT_MOUNT "-.mount"
diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c
index 0280afeec..ee064d2ae 100644
--- a/src/basic/stat-util.c
+++ b/src/basic/stat-util.c
@@ -1,33 +1,18 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
#include <linux/magic.h>
+//#include <sched.h>
+//#include <sys/stat.h>
#include <sys/statvfs.h>
+//#include <sys/types.h>
#include <unistd.h>
#include "dirent-util.h"
#include "fd-util.h"
+#include "fs-util.h"
#include "macro.h"
#include "missing.h"
#include "stat-util.h"
@@ -149,33 +134,7 @@ int path_is_read_only_fs(const char *path) {
}
#if 0 /// UNNEEDED by elogind
-int path_is_os_tree(const char *path) {
- int r;
-
- assert(path);
-
- /* Does the path exist at all? If not, generate an error immediately. This is useful so that a missing root dir
- * always results in -ENOENT, and we can properly distuingish the case where the whole root doesn't exist from
- * the case where just the os-release file is missing. */
- if (laccess(path, F_OK) < 0)
- return -errno;
-
- /* We use /usr/lib/os-release as flag file if something is an OS */
- r = chase_symlinks("/usr/lib/os-release", path, CHASE_PREFIX_ROOT, NULL);
- if (r == -ENOENT) {
-
- /* Also check for the old location in /etc, just in case. */
- r = chase_symlinks("/etc/os-release", path, CHASE_PREFIX_ROOT, NULL);
- if (r == -ENOENT)
- return 0; /* We got nothing */
- }
- if (r < 0)
- return r;
-
- return 1;
-}
#endif // 0
-
int files_same(const char *filea, const char *fileb, int flags) {
struct stat a, b;
@@ -199,8 +158,7 @@ bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) {
return F_TYPE_EQUAL(s->f_type, magic_value);
}
-#if 0 /// UNNEEDED by elogind
-int fd_check_fstype(int fd, statfs_f_type_t magic_value) {
+int fd_is_fs_type(int fd, statfs_f_type_t magic_value) {
struct statfs s;
if (fstatfs(fd, &s) < 0)
@@ -209,20 +167,32 @@ int fd_check_fstype(int fd, statfs_f_type_t magic_value) {
return is_fs_type(&s, magic_value);
}
-int path_check_fstype(const char *path, statfs_f_type_t magic_value) {
+#if 0 /// UNNEEDED by elogind
+int path_is_fs_type(const char *path, statfs_f_type_t magic_value) {
_cleanup_close_ int fd = -1;
fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH);
if (fd < 0)
return -errno;
- return fd_check_fstype(fd, magic_value);
+ return fd_is_fs_type(fd, magic_value);
}
#endif // 0
bool is_temporary_fs(const struct statfs *s) {
- return is_fs_type(s, TMPFS_MAGIC) ||
- is_fs_type(s, RAMFS_MAGIC);
+ return is_fs_type(s, TMPFS_MAGIC) ||
+ is_fs_type(s, RAMFS_MAGIC);
+}
+
+bool is_network_fs(const struct statfs *s) {
+ return is_fs_type(s, CIFS_MAGIC_NUMBER) ||
+ is_fs_type(s, CODA_SUPER_MAGIC) ||
+ is_fs_type(s, NCP_SUPER_MAGIC) ||
+ is_fs_type(s, NFS_SUPER_MAGIC) ||
+ is_fs_type(s, SMB_SUPER_MAGIC) ||
+ is_fs_type(s, V9FS_MAGIC) ||
+ is_fs_type(s, AFS_SUPER_MAGIC) ||
+ is_fs_type(s, OCFS2_SUPER_MAGIC);
}
#if 0 /// UNNEEDED by elogind
@@ -235,6 +205,29 @@ int fd_is_temporary_fs(int fd) {
return is_temporary_fs(&s);
}
+int fd_is_network_fs(int fd) {
+ struct statfs s;
+
+ if (fstatfs(fd, &s) < 0)
+ return -errno;
+
+ return is_network_fs(&s);
+}
+
+int fd_is_network_ns(int fd) {
+ int r;
+
+ r = fd_is_fs_type(fd, NSFS_MAGIC);
+ if (r <= 0)
+ return r;
+
+ r = ioctl(fd, NS_GET_NSTYPE);
+ if (r < 0)
+ return -errno;
+
+ return r == CLONE_NEWNET;
+}
+
int path_is_temporary_fs(const char *path) {
_cleanup_close_ int fd = -1;
@@ -245,3 +238,32 @@ int path_is_temporary_fs(const char *path) {
return fd_is_temporary_fs(fd);
}
#endif // 0
+
+int stat_verify_regular(const struct stat *st) {
+ assert(st);
+
+ /* Checks whether the specified stat() structure refers to a regular file. If not returns an appropriate error
+ * code. */
+
+ if (S_ISDIR(st->st_mode))
+ return -EISDIR;
+
+ if (S_ISLNK(st->st_mode))
+ return -ELOOP;
+
+ if (!S_ISREG(st->st_mode))
+ return -EBADFD;
+
+ return 0;
+}
+
+int fd_verify_regular(int fd) {
+ struct stat st;
+
+ assert(fd >= 0);
+
+ if (fstat(fd, &st) < 0)
+ return -errno;
+
+ return stat_verify_regular(&st);
+}
diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h
index c74d1d58e..7b9d14bea 100644
--- a/src/basic/stat-util.h
+++ b/src/basic/stat-util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010-2012 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <stddef.h>
#include <sys/stat.h>
@@ -54,7 +36,6 @@ int null_or_empty_fd(int fd);
int path_is_read_only_fs(const char *path);
#if 0 /// UNNEEDED by elogind
-int path_is_os_tree(const char *path);
#endif // 0
int files_same(const char *filea, const char *fileb, int flags);
@@ -65,13 +46,19 @@ typedef typeof(((struct statfs*)NULL)->f_type) statfs_f_type_t;
bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) _pure_;
#if 0 /// UNNEEDED by elogind
-int fd_check_fstype(int fd, statfs_f_type_t magic_value);
-int path_check_fstype(const char *path, statfs_f_type_t magic_value);
#endif // 0
+int fd_is_fs_type(int fd, statfs_f_type_t magic_value);
+int path_is_fs_type(const char *path, statfs_f_type_t magic_value);
bool is_temporary_fs(const struct statfs *s) _pure_;
+bool is_network_fs(const struct statfs *s) _pure_;
+
#if 0 /// UNNEEDED by elogind
int fd_is_temporary_fs(int fd);
+int fd_is_network_fs(int fd);
+
+int fd_is_network_ns(int fd);
+
int path_is_temporary_fs(const char *path);
#endif // 0
@@ -80,3 +67,6 @@ int path_is_temporary_fs(const char *path);
* signed/unsigned comparison, because the magic can be 32 bit unsigned.
*/
#define F_TYPE_EQUAL(a, b) (a == (typeof(a)) b)
+
+int stat_verify_regular(const struct stat *st);
+int fd_verify_regular(int fd);
diff --git a/src/basic/stdio-util.h b/src/basic/stdio-util.h
index 3e0ea04f6..7bf10ab22 100644
--- a/src/basic/stdio-util.h
+++ b/src/basic/stdio-util.h
@@ -1,23 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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/>.
-***/
#if 0 /// elogind is musl-libc compatible and does not directly include printf.h
#include <printf.h>
@@ -30,9 +13,11 @@
#include "macro.h"
-#define xsprintf(buf, fmt, ...) \
- assert_message_se((size_t) snprintf(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__) < ELEMENTSOF(buf), "xsprintf: " #buf "[] must be big enough")
+#define snprintf_ok(buf, len, fmt, ...) \
+ ((size_t) snprintf(buf, len, fmt, __VA_ARGS__) < (len))
+#define xsprintf(buf, fmt, ...) \
+ assert_message_se(snprintf_ok(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__), "xsprintf: " #buf "[] must be big enough")
#define VA_FORMAT_ADVANCE(format, ap) \
do { \
diff --git a/src/basic/string-table.c b/src/basic/string-table.c
index a1499ab12..34931b03d 100644
--- a/src/basic/string-table.c
+++ b/src/basic/string-table.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include "string-table.h"
#include "string-util.h"
diff --git a/src/basic/string-table.h b/src/basic/string-table.h
index 369610efc..9bd787935 100644
--- a/src/basic/string-table.h
+++ b/src/basic/string-table.h
@@ -1,25 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 <errno.h>
#include <stddef.h>
#include <stdio.h>
@@ -89,16 +71,13 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
return (type) -1; \
} \
-
#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
- _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \
- struct __useless_struct_to_allow_trailing_semicolon__
+ _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope)
#define _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,scope) \
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
- _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \
- struct __useless_struct_to_allow_trailing_semicolon__
+ _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope)
#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)
@@ -110,10 +89,24 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
/* For string conversions where numbers are also acceptable */
#define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max) \
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,) \
- _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,) \
- struct __useless_struct_to_allow_trailing_semicolon__
+ _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,)
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max) \
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,static)
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max) \
_DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,static)
+
+#define DUMP_STRING_TABLE(name,type,max) \
+ do { \
+ type _k; \
+ flockfile(stdout); \
+ for (_k = 0; _k < (max); _k++) { \
+ const char *_t; \
+ _t = name##_to_string(_k); \
+ if (!_t) \
+ continue; \
+ fputs_unlocked(_t, stdout); \
+ fputc_unlocked('\n', stdout); \
+ } \
+ funlockfile(stdout); \
+ } while(false)
diff --git a/src/basic/string-util.c b/src/basic/string-util.c
index 9b060a9a2..d7ba43541 100644
--- a/src/basic/string-util.c
+++ b/src/basic/string-util.c
@@ -1,35 +1,23 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
+#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
#include "alloc-util.h"
+#include "escape.h"
#include "gunicode.h"
+#include "locale-util.h"
#include "macro.h"
#include "string-util.h"
+//#include "terminal-util.h"
#include "utf8.h"
#include "util.h"
+#include "fileio.h"
int strcmp_ptr(const char *a, const char *b) {
@@ -215,7 +203,7 @@ char *strnappend(const char *s, const char *suffix, size_t b) {
}
char *strappend(const char *s, const char *suffix) {
- return strnappend(s, suffix, suffix ? strlen(suffix) : 0);
+ return strnappend(s, suffix, strlen_ptr(suffix));
}
char *strjoin_real(const char *x, ...) {
@@ -276,27 +264,24 @@ char *strjoin_real(const char *x, ...) {
}
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;
+ if (!s)
+ return NULL;
- *e = 0;
+ /* Drops trailing whitespace. Modifies the string in place. Returns pointer to first non-space character */
- return s;
+ return delete_trailing_chars(skip_leading_chars(s, WHITESPACE), WHITESPACE);
}
-#if 0 /// UNNEEDED by elogind
char *delete_chars(char *s, const char *bad) {
char *f, *t;
- /* Drops all whitespace, regardless where in the string */
+ /* Drops all specified bad characters, regardless where in the string */
+
+ if (!s)
+ return NULL;
+
+ if (!bad)
+ bad = WHITESPACE;
for (f = s, t = s; *f; f++) {
if (strchr(bad, *f))
@@ -309,7 +294,26 @@ char *delete_chars(char *s, const char *bad) {
return s;
}
-#endif // 0
+
+char *delete_trailing_chars(char *s, const char *bad) {
+ char *p, *c = s;
+
+ /* Drops all specified bad characters, at the end of the string */
+
+ if (!s)
+ return NULL;
+
+ if (!bad)
+ bad = WHITESPACE;
+
+ for (p = s; *p; p++)
+ if (!strchr(bad, *p))
+ c = p + 1;
+
+ *c = 0;
+
+ return s;
+}
char *truncate_nl(char *s) {
assert(s);
@@ -436,90 +440,154 @@ bool string_has_cc(const char *p, const char *ok) {
return false;
}
+static int write_ellipsis(char *buf, bool unicode) {
+ if (unicode || is_locale_utf8()) {
+ buf[0] = 0xe2; /* tri-dot ellipsis: … */
+ buf[1] = 0x80;
+ buf[2] = 0xa6;
+ } else {
+ buf[0] = '.';
+ buf[1] = '.';
+ buf[2] = '.';
+ }
+
+ return 3;
+}
+
static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
- size_t x;
- char *r;
+ size_t x, need_space, suffix_len;
+ char *t;
assert(s);
assert(percent <= 100);
- assert(new_length >= 3);
+ assert(new_length != (size_t) -1);
- if (old_length <= 3 || old_length <= new_length)
+ if (old_length <= new_length)
return strndup(s, old_length);
- r = new0(char, new_length+3);
- if (!r)
+ /* Special case short ellipsations */
+ switch (new_length) {
+
+ case 0:
+ return strdup("");
+
+ case 1:
+ if (is_locale_utf8())
+ return strdup("…");
+ else
+ return strdup(".");
+
+ case 2:
+ if (!is_locale_utf8())
+ return strdup("..");
+
+ break;
+
+ default:
+ break;
+ }
+
+ /* Calculate how much space the ellipsis will take up. If we are in UTF-8 mode we only need space for one
+ * character ("…"), otherwise for three characters ("..."). Note that in both cases we need 3 bytes of storage,
+ * either for the UTF-8 encoded character or for three ASCII characters. */
+ need_space = is_locale_utf8() ? 1 : 3;
+
+ t = new(char, new_length+3);
+ if (!t)
return NULL;
- x = (new_length * percent) / 100;
+ assert(new_length >= need_space);
- if (x > new_length - 3)
- x = new_length - 3;
+ x = ((new_length - need_space) * percent + 50) / 100;
+ assert(x <= new_length - need_space);
- memcpy(r, s, x);
- r[x] = 0xe2; /* tri-dot ellipsis: … */
- r[x+1] = 0x80;
- r[x+2] = 0xa6;
- memcpy(r + x + 3,
- s + old_length - (new_length - x - 1),
- new_length - x - 1);
+ memcpy(t, s, x);
+ write_ellipsis(t + x, false);
+ suffix_len = new_length - x - need_space;
+ memcpy(t + x + 3, s + old_length - suffix_len, suffix_len);
+ *(t + x + 3 + suffix_len) = '\0';
- return r;
+ return t;
}
char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
- size_t x;
- char *e;
+ size_t x, k, len, len2;
const char *i, *j;
- unsigned k, len, len2;
+ char *e;
int r;
+ /* Note that 'old_length' refers to bytes in the string, while 'new_length' refers to character cells taken up
+ * on screen. This distinction doesn't matter for ASCII strings, but it does matter for non-ASCII UTF-8
+ * strings.
+ *
+ * Ellipsation is done in a locale-dependent way:
+ * 1. If the string passed in is fully ASCII and the current locale is not UTF-8, three dots are used ("...")
+ * 2. Otherwise, a unicode ellipsis is used ("…")
+ *
+ * In other words: you'll get a unicode ellipsis as soon as either the string contains non-ASCII characters or
+ * the current locale is UTF-8.
+ */
+
assert(s);
assert(percent <= 100);
- assert(new_length >= 3);
- /* if no multibyte characters use ascii_ellipsize_mem for speed */
- if (ascii_is_valid(s))
- return ascii_ellipsize_mem(s, old_length, new_length, percent);
-
- if (old_length <= 3 || old_length <= new_length)
+ if (new_length == (size_t) -1)
return strndup(s, old_length);
- x = (new_length * percent) / 100;
+ if (new_length == 0)
+ return strdup("");
+
+ /* If no multibyte characters use ascii_ellipsize_mem for speed */
+ if (ascii_is_valid_n(s, old_length))
+ return ascii_ellipsize_mem(s, old_length, new_length, percent);
- if (x > new_length - 3)
- x = new_length - 3;
+ x = ((new_length - 1) * percent) / 100;
+ assert(x <= new_length - 1);
k = 0;
- for (i = s; k < x && i < s + old_length; i = utf8_next_char(i)) {
+ for (i = s; i < s + old_length; i = utf8_next_char(i)) {
char32_t c;
+ int w;
r = utf8_encoded_to_unichar(i, &c);
if (r < 0)
return NULL;
- k += unichar_iswide(c) ? 2 : 1;
- }
- if (k > x) /* last character was wide and went over quota */
- x++;
+ w = unichar_iswide(c) ? 2 : 1;
+ if (k + w <= x)
+ k += w;
+ else
+ break;
+ }
- for (j = s + old_length; k < new_length && j > i; ) {
+ for (j = s + old_length; j > i; ) {
char32_t c;
+ int w;
+ const char *jj;
- j = utf8_prev_char(j);
- r = utf8_encoded_to_unichar(j, &c);
+ jj = utf8_prev_char(j);
+ r = utf8_encoded_to_unichar(jj, &c);
if (r < 0)
return NULL;
- k += unichar_iswide(c) ? 2 : 1;
+
+ w = unichar_iswide(c) ? 2 : 1;
+ if (k + w <= new_length) {
+ k += w;
+ j = jj;
+ } else
+ break;
}
assert(i <= j);
/* we don't actually need to ellipsize */
if (i == j)
- return memdup(s, old_length + 1);
+ return memdup_suffix0(s, old_length);
- /* make space for ellipsis */
- j = utf8_next_char(j);
+ /* make space for ellipsis, if possible */
+ if (j < s + old_length)
+ j = utf8_next_char(j);
+ else if (i > s)
+ i = utf8_prev_char(i);
len = i - s;
len2 = s + old_length - j;
@@ -533,20 +601,84 @@ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne
*/
memcpy(e, s, len);
- e[len] = 0xe2; /* tri-dot ellipsis: … */
- e[len + 1] = 0x80;
- e[len + 2] = 0xa6;
-
- memcpy(e + len + 3, j, len2 + 1);
+ write_ellipsis(e + len, true);
+ memcpy(e + len + 3, j, len2);
+ *(e + len + 3 + len2) = '\0';
return e;
}
-char *ellipsize(const char *s, size_t length, unsigned percent) {
- return ellipsize_mem(s, strlen(s), length, percent);
+char *cellescape(char *buf, size_t len, const char *s) {
+ /* Escape and ellipsize s into buffer buf of size len. Only non-control ASCII
+ * characters are copied as they are, everything else is escaped. The result
+ * is different then if escaping and ellipsization was performed in two
+ * separate steps, because each sequence is either stored in full or skipped.
+ *
+ * This function should be used for logging about strings which expected to
+ * be plain ASCII in a safe way.
+ *
+ * An ellipsis will be used if s is too long. It was always placed at the
+ * very end.
+ */
+
+ size_t i = 0, last_char_width[4] = {}, k = 0, j;
+
+ assert(len > 0); /* at least a terminating NUL */
+
+ for (;;) {
+ char four[4];
+ int w;
+
+ if (*s == 0) /* terminating NUL detected? then we are done! */
+ goto done;
+
+ w = cescape_char(*s, four);
+ if (i + w + 1 > len) /* This character doesn't fit into the buffer anymore? In that case let's
+ * ellipsize at the previous location */
+ break;
+
+ /* OK, there was space, let's add this escaped character to the buffer */
+ memcpy(buf + i, four, w);
+ i += w;
+
+ /* And remember its width in the ring buffer */
+ last_char_width[k] = w;
+ k = (k + 1) % 4;
+
+ s++;
+ }
+
+ /* Ellipsation is necessary. This means we might need to truncate the string again to make space for 4
+ * characters ideally, but the buffer is shorter than that in the first place take what we can get */
+ for (j = 0; j < ELEMENTSOF(last_char_width); j++) {
+
+ if (i + 4 <= len) /* nice, we reached our space goal */
+ break;
+
+ k = k == 0 ? 3 : k - 1;
+ if (last_char_width[k] == 0) /* bummer, we reached the beginning of the strings */
+ break;
+
+ assert(i >= last_char_width[k]);
+ i -= last_char_width[k];
+ }
+
+ if (i + 4 <= len) /* yay, enough space */
+ i += write_ellipsis(buf + i, false);
+ else if (i + 3 <= len) { /* only space for ".." */
+ buf[i++] = '.';
+ buf[i++] = '.';
+ } else if (i + 2 <= len) /* only space for a single "." */
+ buf[i++] = '.';
+ else
+ assert(i + 1 <= len);
+
+ done:
+ buf[i] = '\0';
+ return buf;
}
-bool nulstr_contains(const char*nulstr, const char *needle) {
+bool nulstr_contains(const char *nulstr, const char *needle) {
const char *i;
if (!nulstr)
@@ -562,33 +694,33 @@ bool nulstr_contains(const char*nulstr, const char *needle) {
char* strshorten(char *s, size_t l) {
assert(s);
- if (l < strlen(s))
+ if (strnlen(s, l+1) > l)
s[l] = 0;
return s;
}
char *strreplace(const char *text, const char *old_string, const char *new_string) {
+ size_t l, old_len, new_len, allocated = 0;
+ char *t, *ret = NULL;
const char *f;
- char *t, *r;
- size_t l, old_len, new_len;
- assert(text);
assert(old_string);
assert(new_string);
+ if (!text)
+ return NULL;
+
old_len = strlen(old_string);
new_len = strlen(new_string);
l = strlen(text);
- r = new(char, l+1);
- if (!r)
+ if (!GREEDY_REALLOC(ret, allocated, l+1))
return NULL;
f = text;
- t = r;
+ t = ret;
while (*f) {
- char *a;
size_t d, nl;
if (!startswith(f, old_string)) {
@@ -596,42 +728,59 @@ char *strreplace(const char *text, const char *old_string, const char *new_strin
continue;
}
- d = t - r;
+ d = t - ret;
nl = l - old_len + new_len;
- a = realloc(r, nl + 1);
- if (!a)
- goto oom;
+
+ if (!GREEDY_REALLOC(ret, allocated, nl + 1))
+ return mfree(ret);
l = nl;
- r = a;
- t = r + d;
+ t = ret + d;
t = stpcpy(t, new_string);
f += old_len;
}
*t = 0;
- return r;
+ return ret;
+}
-oom:
- return mfree(r);
+static void advance_offsets(ssize_t diff, size_t offsets[2], size_t shift[2], size_t size) {
+ if (!offsets)
+ return;
+
+ if ((size_t) diff < offsets[0])
+ shift[0] += size;
+ if ((size_t) diff < offsets[1])
+ shift[1] += size;
}
-char *strip_tab_ansi(char **ibuf, size_t *_isz) {
+char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
const char *i, *begin = NULL;
enum {
STATE_OTHER,
STATE_ESCAPE,
- STATE_BRACKET
+ STATE_CSI,
+ STATE_CSO,
} state = STATE_OTHER;
char *obuf = NULL;
- size_t osz = 0, isz;
+ size_t osz = 0, isz, shift[2] = {};
FILE *f;
assert(ibuf);
assert(*ibuf);
- /* Strips ANSI color and replaces TABs by 8 spaces */
+ /* This does three things:
+ *
+ * 1. Replaces TABs by 8 spaces
+ * 2. Strips ANSI color sequences (a subset of CSI), i.e. ESC '[' … 'm' sequences
+ * 3. Strips ANSI operating system sequences (CSO), i.e. ESC ']' … BEL sequences
+ *
+ * Everything else will be left as it is. In particular other ANSI sequences are left as they are, as are any
+ * other special characters. Truncated ANSI sequences are left-as is too. This call is supposed to suppress the
+ * most basic formatting noise, but nothing else.
+ *
+ * Why care for CSO sequences? Well, to undo what terminal_urlify() and friends generate. */
isz = _isz ? *_isz : strlen(*ibuf);
@@ -639,6 +788,11 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz) {
if (!f)
return NULL;
+ /* Note we turn off internal locking on f for performance reasons. It's safe to do so since we created f here
+ * and it doesn't leave our scope. */
+
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
for (i = *ibuf; i < *ibuf + isz + 1; i++) {
switch (state) {
@@ -648,42 +802,65 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz) {
break;
else if (*i == '\x1B')
state = STATE_ESCAPE;
- else if (*i == '\t')
+ else if (*i == '\t') {
fputs(" ", f);
- else
+ advance_offsets(i - *ibuf, highlight, shift, 7);
+ } else
fputc(*i, f);
+
break;
case STATE_ESCAPE:
if (i >= *ibuf + isz) { /* EOT */
fputc('\x1B', f);
+ advance_offsets(i - *ibuf, highlight, shift, 1);
break;
- } else if (*i == '[') {
- state = STATE_BRACKET;
+ } else if (*i == '[') { /* ANSI CSI */
+ state = STATE_CSI;
+ begin = i + 1;
+ } else if (*i == ']') { /* ANSI CSO */
+ state = STATE_CSO;
begin = i + 1;
} else {
fputc('\x1B', f);
fputc(*i, f);
+ advance_offsets(i - *ibuf, highlight, shift, 1);
state = STATE_OTHER;
}
break;
- case STATE_BRACKET:
+ case STATE_CSI:
- if (i >= *ibuf + isz || /* EOT */
- (!(*i >= '0' && *i <= '9') && *i != ';' && *i != 'm')) {
+ if (i >= *ibuf + isz || /* EOT … */
+ !strchr("01234567890;m", *i)) { /* … or invalid chars in sequence */
fputc('\x1B', f);
fputc('[', f);
+ advance_offsets(i - *ibuf, highlight, shift, 2);
state = STATE_OTHER;
i = begin-1;
} else if (*i == 'm')
state = STATE_OTHER;
+
+ break;
+
+ case STATE_CSO:
+
+ if (i >= *ibuf + isz || /* EOT … */
+ (*i != '\a' && (uint8_t) *i < 32U) || (uint8_t) *i > 126U) { /* … or invalid chars in sequence */
+ fputc('\x1B', f);
+ fputc(']', f);
+ advance_offsets(i - *ibuf, highlight, shift, 2);
+ state = STATE_OTHER;
+ i = begin-1;
+ } else if (*i == '\a')
+ state = STATE_OTHER;
+
break;
}
}
- if (ferror(f)) {
+ if (fflush_and_check(f) < 0) {
fclose(f);
return mfree(obuf);
}
@@ -696,19 +873,28 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz) {
if (_isz)
*_isz = osz;
+ if (highlight) {
+ highlight[0] += shift[0];
+ highlight[1] += shift[1];
+ }
+
return obuf;
}
-char *strextend(char **x, ...) {
- va_list ap;
- size_t f, l;
+char *strextend_with_separator(char **x, const char *separator, ...) {
+ bool need_separator;
+ size_t f, l, l_separator;
char *r, *p;
+ va_list ap;
assert(x);
- l = f = *x ? strlen(*x) : 0;
+ l = f = strlen_ptr(*x);
- va_start(ap, x);
+ need_separator = !isempty(*x);
+ l_separator = strlen_ptr(separator);
+
+ va_start(ap, separator);
for (;;) {
const char *t;
size_t n;
@@ -718,22 +904,29 @@ char *strextend(char **x, ...) {
break;
n = strlen(t);
+
+ if (need_separator)
+ n += l_separator;
+
if (n > ((size_t) -1) - l) {
va_end(ap);
return NULL;
}
l += n;
+ need_separator = true;
}
va_end(ap);
+ need_separator = !isempty(*x);
+
r = realloc(*x, l+1);
if (!r)
return NULL;
p = r + f;
- va_start(ap, x);
+ va_start(ap, separator);
for (;;) {
const char *t;
@@ -741,10 +934,17 @@ char *strextend(char **x, ...) {
if (!t)
break;
+ if (need_separator && separator)
+ p = stpcpy(p, separator);
+
p = stpcpy(p, t);
+
+ need_separator = true;
}
va_end(ap);
+ assert(p == r + l);
+
*p = 0;
*x = r;
@@ -825,7 +1025,7 @@ int free_and_strdup(char **p, const char *s) {
return 1;
}
-#if !HAVE_DECL_EXPLICIT_BZERO
+#if !HAVE_EXPLICIT_BZERO
/*
* Pointer to memset is volatile so that compiler must de-reference
* the pointer and can't assume that it points to any function in
diff --git a/src/basic/string-util.h b/src/basic/string-util.h
index e8c2fc6dd..d3a01a65e 100644
--- a/src/basic/string-util.h
+++ b/src/basic/string-util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <alloca.h>
#include <stdbool.h>
#include <stddef.h>
@@ -51,15 +33,15 @@ static inline bool streq_ptr(const char *a, const char *b) {
}
static inline const char* strempty(const char *s) {
- return s ? s : "";
+ return s ?: "";
}
static inline const char* strnull(const char *s) {
- return s ? s : "(null)";
+ return s ?: "(null)";
}
static inline const char *strna(const char *s) {
- return s ? s : "n/a";
+ return s ?: "n/a";
}
static inline bool isempty(const char *p) {
@@ -71,7 +53,7 @@ static inline const char *empty_to_null(const char *p) {
}
#if 0 /// UNNEEDED by elogind
-static inline const char *strdash_if_empty(const char *str) {
+static inline const char *empty_to_dash(const char *str) {
return isempty(str) ? "-" : str;
}
#endif // 0
@@ -124,8 +106,8 @@ char *strjoin_real(const char *x, ...) _sentinel_;
({ \
const char *_appendees_[] = { a, __VA_ARGS__ }; \
char *_d_, *_p_; \
- int _len_ = 0; \
- unsigned _i_; \
+ size_t _len_ = 0; \
+ size_t _i_; \
for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \
_len_ += strlen(_appendees_[_i_]); \
_p_ = _d_ = alloca(_len_ + 1); \
@@ -136,11 +118,21 @@ char *strjoin_real(const char *x, ...) _sentinel_;
})
char *strstrip(char *s);
-#if 0 /// UNNEEDED by elogind
char *delete_chars(char *s, const char *bad);
-#endif // 0
+char *delete_trailing_chars(char *s, const char *bad);
char *truncate_nl(char *s);
+static inline char *skip_leading_chars(const char *s, const char *bad) {
+
+ if (!s)
+ return NULL;
+
+ if (!bad)
+ bad = WHITESPACE;
+
+ return (char*) s + strspn(s, bad);
+}
+
#if 0 /// UNNEEDED by elogind
char ascii_tolower(char x);
char *ascii_strlower(char *s);
@@ -164,17 +156,26 @@ static inline bool _pure_ in_charset(const char *s, const char* charset) {
bool string_has_cc(const char *p, const char *ok) _pure_;
char *ellipsize_mem(const char *s, size_t old_length_bytes, size_t new_length_columns, unsigned percent);
-char *ellipsize(const char *s, size_t length, unsigned percent);
+static inline char *ellipsize(const char *s, size_t length, unsigned percent) {
+ return ellipsize_mem(s, strlen(s), length, percent);
+}
+
+char *cellescape(char *buf, size_t len, const char *s);
-bool nulstr_contains(const char*nulstr, const char *needle);
+/* This limit is arbitrary, enough to give some idea what the string contains */
+#define CELLESCAPE_DEFAULT_LENGTH 64
+
+bool nulstr_contains(const char *nulstr, const char *needle);
char* strshorten(char *s, size_t l);
char *strreplace(const char *text, const char *old_string, const char *new_string);
-char *strip_tab_ansi(char **p, size_t *l);
+char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]);
+
+char *strextend_with_separator(char **x, const char *separator, ...) _sentinel_;
-char *strextend(char **x, ...) _sentinel_;
+#define strextend(x, ...) strextend_with_separator(x, NULL, __VA_ARGS__)
char *strrep(const char *s, unsigned n);
@@ -197,7 +198,7 @@ static inline void *memmem_safe(const void *haystack, size_t haystacklen, const
return memmem(haystack, haystacklen, needle, needlelen);
}
-#if !HAVE_DECL_EXPLICIT_BZERO
+#if !HAVE_EXPLICIT_BZERO
void explicit_bzero(void *p, size_t l);
#endif
@@ -208,3 +209,28 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(char *, string_free_erase);
#define _cleanup_string_free_erase_ _cleanup_(string_free_erasep)
bool string_is_safe(const char *p) _pure_;
+
+static inline size_t strlen_ptr(const char *s) {
+ if (!s)
+ return 0;
+
+ return strlen(s);
+}
+
+/* Like startswith(), but operates on arbitrary memory blocks */
+static inline void *memory_startswith(const void *p, size_t sz, const char *token) {
+ size_t n;
+
+ assert(token);
+
+ n = strlen(token);
+ if (sz < n)
+ return NULL;
+
+ assert(p);
+
+ if (memcmp(p, token, n) != 0)
+ return NULL;
+
+ return (uint8_t*) p + n;
+}
diff --git a/src/basic/strv.c b/src/basic/strv.c
index 1f42046c6..be406fd9b 100644
--- a/src/basic/strv.c
+++ b/src/basic/strv.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <fnmatch.h>
@@ -119,8 +102,8 @@ char **strv_copy(char * const *l) {
return r;
}
-unsigned strv_length(char * const *l) {
- unsigned n = 0;
+size_t strv_length(char * const *l) {
+ size_t n = 0;
if (!l)
return 0;
@@ -133,8 +116,8 @@ unsigned strv_length(char * const *l) {
char **strv_new_ap(const char *x, va_list ap) {
const char *s;
- char **a;
- unsigned n = 0, i = 0;
+ _cleanup_strv_free_ char **a = NULL;
+ size_t n = 0, i = 0;
va_list aq;
/* As a special trick we ignore all listed strings that equal
@@ -164,7 +147,7 @@ char **strv_new_ap(const char *x, va_list ap) {
if (x != STRV_IGNORE) {
a[i] = strdup(x);
if (!a[i])
- goto fail;
+ return NULL;
i++;
}
@@ -175,7 +158,7 @@ char **strv_new_ap(const char *x, va_list ap) {
a[i] = strdup(s);
if (!a[i])
- goto fail;
+ return NULL;
i++;
}
@@ -183,11 +166,7 @@ char **strv_new_ap(const char *x, va_list ap) {
a[i] = NULL;
- return a;
-
-fail:
- strv_free(a);
- return NULL;
+ return TAKE_PTR(a);
}
char **strv_new(const char *x, ...) {
@@ -214,7 +193,7 @@ int strv_extend_strv(char ***a, char **b, bool filter_duplicates) {
p = strv_length(*a);
q = strv_length(b);
- t = realloc(*a, sizeof(char*) * (p + q + 1));
+ t = reallocarray(*a, p + q + 1, sizeof(char *));
if (!t)
return -ENOMEM;
@@ -271,7 +250,7 @@ int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
char **strv_split(const char *s, const char *separator) {
const char *word, *state;
size_t l;
- unsigned n, i;
+ size_t n, i;
char **r;
assert(s);
@@ -302,7 +281,7 @@ char **strv_split(const char *s, const char *separator) {
#if 0 /// UNNEEDED by elogind
char **strv_split_newlines(const char *s) {
char **l;
- unsigned n;
+ size_t n;
assert(s);
@@ -344,8 +323,7 @@ int strv_split_extract(char ***t, const char *s, const char *separators, Extract
if (!GREEDY_REALLOC(l, allocated, n + 2))
return -ENOMEM;
- l[n++] = word;
- word = NULL;
+ l[n++] = TAKE_PTR(word);
l[n] = NULL;
}
@@ -356,8 +334,7 @@ int strv_split_extract(char ***t, const char *s, const char *separators, Extract
return -ENOMEM;
}
- *t = l;
- l = NULL;
+ *t = TAKE_PTR(l);
return (int) n;
}
@@ -397,46 +374,10 @@ char *strv_join(char **l, const char *separator) {
}
#if 0 /// UNNEEDED by elogind
-char *strv_join_quoted(char **l) {
- char *buf = NULL;
- char **s;
- size_t allocated = 0, len = 0;
-
- STRV_FOREACH(s, l) {
- /* assuming here that escaped string cannot be more
- * than twice as long, and reserving space for the
- * separator and quotes.
- */
- _cleanup_free_ char *esc = NULL;
- size_t needed;
-
- if (!GREEDY_REALLOC(buf, allocated,
- len + strlen(*s) * 2 + 3))
- goto oom;
-
- esc = cescape(*s);
- if (!esc)
- goto oom;
-
- needed = snprintf(buf + len, allocated - len, "%s\"%s\"",
- len > 0 ? " " : "", esc);
- assert(needed < allocated - len);
- len += needed;
- }
-
- if (!buf)
- buf = malloc0(1);
-
- return buf;
-
- oom:
- return mfree(buf);
-}
#endif // 0
-
int strv_push(char ***l, char *value) {
char **c;
- unsigned n, m;
+ size_t n, m;
if (!value)
return 0;
@@ -448,7 +389,7 @@ int strv_push(char ***l, char *value) {
if (m < n)
return -ENOMEM;
- c = realloc_multiply(*l, sizeof(char*), m);
+ c = reallocarray(*l, m, sizeof(char*));
if (!c)
return -ENOMEM;
@@ -461,7 +402,7 @@ int strv_push(char ***l, char *value) {
int strv_push_pair(char ***l, char *a, char *b) {
char **c;
- unsigned n, m;
+ size_t n, m;
if (!a && !b)
return 0;
@@ -473,7 +414,7 @@ int strv_push_pair(char ***l, char *a, char *b) {
if (m < n)
return -ENOMEM;
- c = realloc_multiply(*l, sizeof(char*), m);
+ c = reallocarray(*l, m, sizeof(char*));
if (!c)
return -ENOMEM;
@@ -487,14 +428,15 @@ int strv_push_pair(char ***l, char *a, char *b) {
return 0;
}
-int strv_push_prepend(char ***l, char *value) {
+int strv_insert(char ***l, size_t position, char *value) {
char **c;
- unsigned n, m, i;
+ size_t n, m, i;
if (!value)
return 0;
n = strv_length(*l);
+ position = MIN(position, n);
/* increase and check for overflow */
m = n + 2;
@@ -505,10 +447,12 @@ int strv_push_prepend(char ***l, char *value) {
if (!c)
return -ENOMEM;
- for (i = 0; i < n; i++)
+ for (i = 0; i < position; i++)
+ c[i] = (*l)[i];
+ c[position] = value;
+ for (i = position; i < n; i++)
c[i+1] = (*l)[i];
- c[0] = value;
c[n+1] = NULL;
free(*l);
@@ -586,7 +530,7 @@ int strv_extend_front(char ***l, const char *value) {
if (!v)
return -ENOMEM;
- c = realloc_multiply(*l, sizeof(char*), m);
+ c = reallocarray(*l, m, sizeof(char*));
if (!c) {
free(v);
return -ENOMEM;
@@ -658,7 +602,7 @@ char **strv_parse_nulstr(const char *s, size_t l) {
*/
const char *p;
- unsigned c = 0, i = 0;
+ size_t c = 0, i = 0;
char **v;
assert(s || l <= 0);
@@ -825,7 +769,7 @@ int strv_extendf(char ***l, const char *format, ...) {
}
char **strv_reverse(char **l) {
- unsigned n, i;
+ size_t n, i;
n = strv_length(l);
if (n <= 1)
@@ -907,7 +851,7 @@ int strv_extend_n(char ***l, const char *value, size_t n) {
k = strv_length(*l);
- nl = realloc(*l, sizeof(char*) * (k + n + 1));
+ nl = reallocarray(*l, k + n + 1, sizeof(char *));
if (!nl)
return -ENOMEM;
diff --git a/src/basic/strv.h b/src/basic/strv.h
index a01f685f9..ae75d40a9 100644
--- a/src/basic/strv.h
+++ b/src/basic/strv.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 <fnmatch.h>
#include <stdarg.h>
#include <stdbool.h>
@@ -44,7 +26,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(char**, strv_free_erase);
void strv_clear(char **l);
char **strv_copy(char * const *l);
-unsigned strv_length(char * const *l) _pure_;
+size_t strv_length(char * const *l) _pure_;
#if 0 /// UNNEEDED by elogind
int strv_extend_strv(char ***a, char **b, bool filter_duplicates);
@@ -57,7 +39,12 @@ int strv_extendf(char ***l, const char *format, ...) _printf_(2,0);
int strv_extend_front(char ***l, const char *value);
int strv_push(char ***l, char *value);
int strv_push_pair(char ***l, char *a, char *b);
-int strv_push_prepend(char ***l, char *value);
+int strv_insert(char ***l, size_t position, char *value);
+
+static inline int strv_push_prepend(char ***l, char *value) {
+ return strv_insert(l, 0, value);
+}
+
int strv_consume(char ***l, char *value);
#if 0 /// UNNEEDED by elogind
int strv_consume_pair(char ***l, char *a, char *b);
@@ -96,7 +83,6 @@ int strv_split_extract(char ***t, const char *s, const char *separators, Extract
char *strv_join(char **l, const char *separator);
#if 0 /// UNNEEDED by elogind
-char *strv_join_quoted(char **l);
#endif // 0
char **strv_parse_nulstr(const char *s, size_t l);
@@ -135,7 +121,7 @@ void strv_print(char **l);
if (!first) \
_l = (char**) &first; \
else { \
- unsigned _n; \
+ size_t _n; \
va_list _ap; \
\
_n = 1; \
@@ -189,6 +175,7 @@ static inline bool strv_fnmatch_or_empty(char* const* patterns, const char *s, i
}
char ***strv_free_free(char ***l);
+DEFINE_TRIVIAL_CLEANUP_FUNC(char***, strv_free_free);
char **strv_skip(char **l, size_t n);
#endif // 0
@@ -198,3 +185,11 @@ int strv_extend_n(char ***l, const char *value, size_t n);
#if 0 /// UNNEEDED by elogind
int fputstrv(FILE *f, char **l, const char *separator, bool *space);
#endif // 0
+
+#define strv_free_and_replace(a, b) \
+ ({ \
+ strv_free(a); \
+ (a) = (b); \
+ (b) = NULL; \
+ 0; \
+ })
diff --git a/src/basic/syslog-util.c b/src/basic/syslog-util.c
index 05d51b4be..edabe3c3a 100644
--- a/src/basic/syslog-util.c
+++ b/src/basic/syslog-util.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <string.h>
#include <syslog.h>
diff --git a/src/basic/syslog-util.h b/src/basic/syslog-util.h
index 86b321c8d..6c6cc7f2b 100644
--- a/src/basic/syslog-util.h
+++ b/src/basic/syslog-util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
int log_facility_unshifted_to_string_alloc(int i, char **s);
diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c
index 6cf623d51..f8623f9fd 100644
--- a/src/basic/terminal-util.c
+++ b/src/basic/terminal-util.c
@@ -1,51 +1,41 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
+#include <linux/kd.h>
+#include <linux/tiocl.h>
+#include <linux/vt.h>
+//#include <poll.h>
+//#include <signal.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <sys/inotify.h>
+//#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/sysmacros.h>
#include <sys/time.h>
-#include <linux/kd.h>
-#include <linux/tiocl.h>
-#include <linux/vt.h>
-#include <poll.h>
-#include <signal.h>
-#include <sys/ioctl.h>
#include <sys/types.h>
+//#include <sys/utsname.h>
#include <termios.h>
#include <unistd.h>
#include "alloc-util.h"
+//#include "copy.h"
+//#include "def.h"
+#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "io-util.h"
#include "log.h"
#include "macro.h"
+//#include "pager.h"
#include "parse-util.h"
+//#include "path-util.h"
+//#include "proc-cmdline.h"
#include "process-util.h"
#include "socket-util.h"
#include "stat-util.h"
@@ -55,12 +45,22 @@
#include "time-util.h"
#include "util.h"
+/// Additional includes needed by elogind
+#include "path-util.h"
+
static volatile unsigned cached_columns = 0;
static volatile unsigned cached_lines = 0;
+static volatile int cached_on_tty = -1;
+static volatile int cached_colors_enabled = -1;
+static volatile int cached_underline_enabled = -1;
+
int chvt(int vt) {
_cleanup_close_ int fd;
+ /* Switch to the specified vt number. If the VT is specified <= 0 switch to the VT the kernel log messages go,
+ * if that's configured. */
+
fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
if (fd < 0)
return -errno;
@@ -261,8 +261,8 @@ int reset_terminal_fd(int fd, bool switch_to_text) {
if (switch_to_text)
(void) ioctl(fd, KDSETMODE, KD_TEXT);
- /* Enable console unicode mode */
- (void) ioctl(fd, KDSKBMODE, K_UNICODE);
+ /* Set default keyboard mode */
+ (void) vt_reset_keyboard(fd);
if (tcgetattr(fd, &termios) < 0) {
r = -errno;
@@ -322,8 +322,8 @@ int reset_terminal(const char *name) {
#endif // 0
int open_terminal(const char *name, int mode) {
- int fd, r;
unsigned c = 0;
+ int fd;
/*
* If a TTY is in the process of being closed opening it might
@@ -353,8 +353,7 @@ int open_terminal(const char *name, int mode) {
c++;
}
- r = isatty(fd);
- if (r == 0) {
+ if (isatty(fd) <= 0) {
safe_close(fd);
return -ENOTTY;
}
@@ -365,44 +364,36 @@ int open_terminal(const char *name, int mode) {
#if 0 /// UNNEEDED by elogind
int acquire_terminal(
const char *name,
- bool fail,
- bool force,
- bool ignore_tiocstty_eperm,
+ AcquireTerminalFlags flags,
usec_t timeout) {
- int fd = -1, notify = -1, r = 0, wd = -1;
- usec_t ts = 0;
+ _cleanup_close_ int notify = -1, fd = -1;
+ usec_t ts = USEC_INFINITY;
+ int r, wd = -1;
assert(name);
+ assert(IN_SET(flags & ~ACQUIRE_TERMINAL_PERMISSIVE, ACQUIRE_TERMINAL_TRY, ACQUIRE_TERMINAL_FORCE, ACQUIRE_TERMINAL_WAIT));
- /* 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.
+ /* 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_INFINITY)
- ts = now(CLOCK_MONOTONIC);
-
- if (!fail && !force) {
+ * 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 to
+ * not configure any service on the same tty as an untrusted user this should not be a problem. (Which they
+ * probably should not do anyway.) */
+
+ if ((flags & ~ACQUIRE_TERMINAL_PERMISSIVE) == ACQUIRE_TERMINAL_WAIT) {
notify = inotify_init1(IN_CLOEXEC | (timeout != USEC_INFINITY ? IN_NONBLOCK : 0));
- if (notify < 0) {
- r = -errno;
- goto fail;
- }
+ if (notify < 0)
+ return -errno;
wd = inotify_add_watch(notify, name, IN_CLOSE);
- if (wd < 0) {
- r = -errno;
- goto fail;
- }
+ if (wd < 0)
+ return -errno;
+
+ if (timeout != USEC_INFINITY)
+ ts = now(CLOCK_MONOTONIC);
}
for (;;) {
@@ -414,41 +405,43 @@ int acquire_terminal(
if (notify >= 0) {
r = flush_fd(notify);
if (r < 0)
- goto fail;
+ return r;
}
- /* 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 */
+ /* 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. */
+ /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed if we already own the tty. */
assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
/* First, try to get the tty */
- if (ioctl(fd, TIOCSCTTY, force) < 0)
- r = -errno;
+ r = ioctl(fd, TIOCSCTTY,
+ (flags & ~ACQUIRE_TERMINAL_PERMISSIVE) == ACQUIRE_TERMINAL_FORCE) < 0 ? -errno : 0;
+ /* Reset signal handler to old value */
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;
+ /* Success? Exit the loop now! */
+ if (r >= 0)
+ break;
- if (r < 0 && (force || fail || r != -EPERM))
- goto fail;
+ /* Any failure besides -EPERM? Fail, regardless of the mode. */
+ if (r != -EPERM)
+ return r;
- if (r >= 0)
+ if (flags & ACQUIRE_TERMINAL_PERMISSIVE) /* If we are in permissive mode, then EPERM is fine, turn this
+ * into a success. Note that EPERM is also returned if we
+ * already are the owner of the TTY. */
break;
- assert(!fail);
- assert(!force);
+ if (flags != ACQUIRE_TERMINAL_WAIT) /* If we are in TRY or FORCE mode, then propagate EPERM as EPERM */
+ return r;
+
assert(notify >= 0);
+ assert(wd >= 0);
for (;;) {
union inotify_event_buffer buffer;
@@ -458,57 +451,44 @@ int acquire_terminal(
if (timeout != USEC_INFINITY) {
usec_t n;
+ assert(ts != USEC_INFINITY);
+
n = now(CLOCK_MONOTONIC);
- if (ts + timeout < n) {
- r = -ETIMEDOUT;
- goto fail;
- }
+ if (ts + timeout < n)
+ return -ETIMEDOUT;
r = fd_wait_for_event(notify, POLLIN, ts + timeout - n);
if (r < 0)
- goto fail;
-
- if (r == 0) {
- r = -ETIMEDOUT;
- goto fail;
- }
+ return r;
+ if (r == 0)
+ return -ETIMEDOUT;
}
l = read(notify, &buffer, sizeof(buffer));
if (l < 0) {
- if (errno == EINTR || errno == EAGAIN)
+ if (IN_SET(errno, EINTR, EAGAIN))
continue;
- r = -errno;
- goto fail;
+ return -errno;
}
FOREACH_INOTIFY_EVENT(e, buffer, l) {
- if (e->wd != wd || !(e->mask & IN_CLOSE)) {
- r = -EIO;
- goto fail;
- }
+ if (e->mask & IN_Q_OVERFLOW) /* If we hit an inotify queue overflow, simply check if the terminal is up for grabs now. */
+ break;
+
+ if (e->wd != wd || !(e->mask & IN_CLOSE)) /* Safety checks */
+ return -EIO;
}
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. */
+ /* 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. */
fd = safe_close(fd);
}
- safe_close(notify);
-
- return fd;
-
-fail:
- safe_close(fd);
- safe_close(notify);
-
- return r;
+ return TAKE_FD(fd);
}
#endif // 0
@@ -521,7 +501,7 @@ int release_terminal(void) {
_cleanup_close_ int fd = -1;
struct sigaction sa_old;
- int r = 0;
+ int r;
fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
if (fd < 0)
@@ -531,8 +511,7 @@ int release_terminal(void) {
* by our own TIOCNOTTY */
assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
- if (ioctl(fd, TIOCNOTTY) < 0)
- r = -errno;
+ r = ioctl(fd, TIOCNOTTY) < 0 ? -errno : 0;
assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
@@ -560,6 +539,7 @@ int terminal_vhangup(const char *name) {
int vt_disallocate(const char *name) {
_cleanup_close_ int fd = -1;
+ const char *e, *n;
unsigned u;
int r;
@@ -567,7 +547,8 @@ int vt_disallocate(const char *name) {
* (i.e. because it is the active one), at least clear it
* entirely (including the scrollback buffer) */
- if (!startswith(name, "/dev/"))
+ e = path_startswith(name, "/dev/");
+ if (!e)
return -EINVAL;
if (!tty_is_vc(name)) {
@@ -586,10 +567,11 @@ int vt_disallocate(const char *name) {
return 0;
}
- if (!startswith(name, "/dev/tty"))
+ n = startswith(e, "tty");
+ if (!n)
return -EINVAL;
- r = safe_atou(name+8, &u);
+ r = safe_atou(n, &u);
if (r < 0)
return r;
@@ -629,7 +611,7 @@ int make_console_stdio(void) {
/* Make /dev/console the controlling terminal and stdin/stdout/stderr */
- fd = acquire_terminal("/dev/console", false, true, true, USEC_INFINITY);
+ fd = acquire_terminal("/dev/console", ACQUIRE_TERMINAL_FORCE|ACQUIRE_TERMINAL_PERMISSIVE, USEC_INFINITY);
if (fd < 0)
return log_error_errno(fd, "Failed to acquire terminal: %m");
@@ -637,9 +619,11 @@ int make_console_stdio(void) {
if (r < 0)
log_warning_errno(r, "Failed to reset terminal, ignoring: %m");
- r = make_stdio(fd);
+ r = rearrange_stdio(fd, fd, fd); /* This invalidates 'fd' both on success and on failure. */
if (r < 0)
- return log_error_errno(r, "Failed to duplicate terminal fd: %m");
+ return log_error_errno(r, "Failed to make terminal stdin/stdout/stderr: %m");
+
+ reset_terminal_feature_caches();
return 0;
}
@@ -654,10 +638,7 @@ bool tty_is_vc(const char *tty) {
bool tty_is_console(const char *tty) {
assert(tty);
- if (startswith(tty, "/dev/"))
- tty += 5;
-
- return streq(tty, "console");
+ return streq(skip_dev_prefix(tty), "console");
}
int vtnr_from_tty(const char *tty) {
@@ -665,8 +646,7 @@ int vtnr_from_tty(const char *tty) {
assert(tty);
- if (startswith(tty, "/dev/"))
- tty += 5;
+ tty = skip_dev_prefix(tty);
if (!startswith(tty, "tty") )
return -EINVAL;
@@ -685,57 +665,79 @@ int vtnr_from_tty(const char *tty) {
}
#if 0 /// UNNEEDED by elogind
-char *resolve_dev_console(char **active) {
+ int resolve_dev_console(char **ret) {
+ _cleanup_free_ char *active = NULL;
char *tty;
+ int r;
+
+ assert(ret);
- /* 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) */
+ /* 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 (path_is_read_only_fs("/sys") > 0)
- return NULL;
+ return -ENOMEDIUM;
- if (read_one_line_file("/sys/class/tty/console/active", active) < 0)
- return NULL;
+ r = read_one_line_file("/sys/class/tty/console/active", &active);
+ if (r < 0)
+ return r;
- /* If multiple log outputs are configured the last one is what
- * /dev/console points to */
- tty = strrchr(*active, ' ');
+ /* If multiple log outputs are configured the last one is what /dev/console points to */
+ tty = strrchr(active, ' ');
if (tty)
tty++;
else
- tty = *active;
+ tty = active;
if (streq(tty, "tty0")) {
- char *tmp;
+ active = mfree(active);
/* Get the active VC (e.g. tty1) */
- if (read_one_line_file("/sys/class/tty/tty0/active", &tmp) >= 0) {
- free(*active);
- tty = *active = tmp;
- }
+ r = read_one_line_file("/sys/class/tty/tty0/active", &active);
+ if (r < 0)
+ return r;
+
+ tty = active;
+ }
+
+ if (tty == active)
+ *ret = TAKE_PTR(active);
+ else {
+ char *tmp;
+
+ tmp = strdup(tty);
+ if (!tmp)
+ return -ENOMEM;
+
+ *ret = tmp;
}
- return tty;
+ return 0;
}
-int get_kernel_consoles(char ***consoles) {
- _cleanup_strv_free_ char **con = NULL;
+int get_kernel_consoles(char ***ret) {
+ _cleanup_strv_free_ char **l = NULL;
_cleanup_free_ char *line = NULL;
- const char *active;
+ const char *p;
int r;
- assert(consoles);
+ assert(ret);
+
+ /* If /sys is mounted read-only this means we are running in some kind of container environment. In that
+ * case /sys would reflect the host system, not us, hence ignore the data we can read from it. */
+ if (path_is_read_only_fs("/sys") > 0)
+ goto fallback;
r = read_one_line_file("/sys/class/tty/console/active", &line);
if (r < 0)
return r;
- active = line;
+ p = line;
for (;;) {
_cleanup_free_ char *tty = NULL;
char *path;
- r = extract_first_word(&active, &tty, NULL, 0);
+ r = extract_first_word(&p, &tty, NULL, 0);
if (r < 0)
return r;
if (r == 0)
@@ -758,36 +760,42 @@ int get_kernel_consoles(char ***consoles) {
continue;
}
- r = strv_consume(&con, path);
+ r = strv_consume(&l, path);
if (r < 0)
return r;
}
- if (strv_isempty(con)) {
+ if (strv_isempty(l)) {
log_debug("No devices found for system console");
-
- r = strv_extend(&con, "/dev/console");
- if (r < 0)
- return r;
+ goto fallback;
}
- *consoles = con;
- con = NULL;
+ *ret = TAKE_PTR(l);
+
+ return 0;
+
+fallback:
+ r = strv_extend(&l, "/dev/console");
+ if (r < 0)
+ return r;
+
+ *ret = TAKE_PTR(l);
+
return 0;
}
bool tty_is_vc_resolve(const char *tty) {
- _cleanup_free_ char *active = NULL;
+ _cleanup_free_ char *resolved = NULL;
assert(tty);
- if (startswith(tty, "/dev/"))
- tty += 5;
+ tty = skip_dev_prefix(tty);
if (streq(tty, "console")) {
- tty = resolve_dev_console(&active);
- if (!tty)
+ if (resolve_dev_console(&resolved) < 0)
return false;
+
+ tty = resolved;
}
return tty_is_vc(tty);
@@ -814,7 +822,7 @@ unsigned columns(void) {
const char *e;
int c;
- if (_likely_(cached_columns > 0))
+ if (cached_columns > 0)
return cached_columns;
c = 0;
@@ -848,7 +856,7 @@ unsigned lines(void) {
const char *e;
int l;
- if (_likely_(cached_lines > 0))
+ if (cached_lines > 0)
return cached_lines;
l = 0;
@@ -874,45 +882,29 @@ void columns_lines_cache_reset(int signum) {
}
#endif // 0
-bool on_tty(void) {
- static int cached_on_tty = -1;
-
- if (_unlikely_(cached_on_tty < 0))
- cached_on_tty = isatty(STDOUT_FILENO) > 0;
+void reset_terminal_feature_caches(void) {
+ cached_columns = 0;
+ cached_lines = 0;
- return cached_on_tty;
+ cached_colors_enabled = -1;
+ cached_underline_enabled = -1;
+ cached_on_tty = -1;
}
-int make_stdio(int fd) {
- int r, s, t;
-
- assert(fd >= 0);
-
- r = dup2(fd, STDIN_FILENO);
- s = dup2(fd, STDOUT_FILENO);
- t = dup2(fd, STDERR_FILENO);
-
- if (fd >= 3)
- safe_close(fd);
-
- if (r < 0 || s < 0 || t < 0)
- return -errno;
-
- /* Explicitly unset O_CLOEXEC, since if fd was < 3, then
- * dup2() was a NOP and the bit hence possibly set. */
- stdio_unset_cloexec();
-
- return 0;
-}
+bool on_tty(void) {
-int make_null_stdio(void) {
- int null_fd;
+ /* We check both stdout and stderr, so that situations where pipes on the shell are used are reliably
+ * recognized, regardless if only the output or the errors are piped to some place. Since on_tty() is generally
+ * used to default to a safer, non-interactive, non-color mode of operation it's probably good to be defensive
+ * here, and check for both. Note that we don't check for STDIN_FILENO, because it should fine to use fancy
+ * terminal functionality when outputting stuff, even if the input is piped to us. */
- null_fd = open("/dev/null", O_RDWR|O_NOCTTY);
- if (null_fd < 0)
- return -errno;
+ if (cached_on_tty < 0)
+ cached_on_tty =
+ isatty(STDOUT_FILENO) > 0 &&
+ isatty(STDERR_FILENO) > 0;
- return make_stdio(null_fd);
+ return cached_on_tty;
}
int getttyname_malloc(int fd, char **ret) {
@@ -927,11 +919,9 @@ int getttyname_malloc(int fd, char **ret) {
r = ttyname_r(fd, path, sizeof(path));
if (r == 0) {
- const char *p;
char *c;
- p = startswith(path, "/dev/");
- c = strdup(p ?: path);
+ c = strdup(skip_dev_prefix(path));
if (!c)
return -ENOMEM;
@@ -1003,7 +993,7 @@ int get_ctty_devnr(pid_t pid, dev_t *d) {
}
int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
- char fn[sizeof("/dev/char/")-1 + 2*DECIMAL_STR_MAX(unsigned) + 1 + 1], *b = NULL;
+ char fn[STRLEN("/dev/char/") + 2*DECIMAL_STR_MAX(unsigned) + 1 + 1], *b = NULL;
_cleanup_free_ char *s = NULL;
const char *p;
dev_t devnr;
@@ -1106,7 +1096,6 @@ int ptsname_namespace(int pty, char **ret) {
int openpt_in_namespace(pid_t pid, int flags) {
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
_cleanup_close_pair_ int pair[2] = { -1, -1 };
- siginfo_t si;
pid_t child;
int r;
@@ -1119,11 +1108,10 @@ int openpt_in_namespace(pid_t pid, int flags) {
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
return -errno;
- child = fork();
- if (child < 0)
- return -errno;
-
- if (child == 0) {
+ r = safe_fork("(sd-openpt)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &child);
+ if (r < 0)
+ return r;
+ if (r == 0) {
int master;
pair[0] = safe_close(pair[0]);
@@ -1147,10 +1135,10 @@ int openpt_in_namespace(pid_t pid, int flags) {
pair[1] = safe_close(pair[1]);
- r = wait_for_terminate(child, &si);
+ r = wait_for_terminate_and_check("(sd-openpt)", child, 0);
if (r < 0)
return r;
- if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
+ if (r != EXIT_SUCCESS)
return -EIO;
return receive_one_fd(pair[0], 0);
@@ -1159,7 +1147,6 @@ int openpt_in_namespace(pid_t pid, int flags) {
int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
_cleanup_close_pair_ int pair[2] = { -1, -1 };
- siginfo_t si;
pid_t child;
int r;
@@ -1170,11 +1157,10 @@ int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
return -errno;
- child = fork();
- if (child < 0)
- return -errno;
-
- if (child == 0) {
+ r = safe_fork("(sd-terminal)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &child);
+ if (r < 0)
+ return r;
+ if (r == 0) {
int master;
pair[0] = safe_close(pair[0]);
@@ -1195,10 +1181,10 @@ int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
pair[1] = safe_close(pair[1]);
- r = wait_for_terminate(child, &si);
+ r = wait_for_terminate_and_check("(sd-terminal)", child, 0);
if (r < 0)
return r;
- if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
+ if (r != EXIT_SUCCESS)
return -EIO;
return receive_one_fd(pair[0], 0);
@@ -1223,22 +1209,264 @@ bool terminal_is_dumb(void) {
}
bool colors_enabled(void) {
- static int enabled = -1;
- if (_unlikely_(enabled < 0)) {
+ /* Returns true if colors are considered supported on our stdout. For that we check $SYSTEMD_COLORS first
+ * (which is the explicit way to turn colors on/off). If that didn't work we turn colors off unless we are on a
+ * TTY. And if we are on a TTY we turn it off if $TERM is set to "dumb". There's one special tweak though: if
+ * we are PID 1 then we do not check whether we are connected to a TTY, because we don't keep /dev/console open
+ * continously due to fear of SAK, and hence things are a bit weird. */
+
+ if (cached_colors_enabled < 0) {
#if 0 /// elogind does not allow such forcing, and we are never init!
int val;
val = getenv_bool("SYSTEMD_COLORS");
if (val >= 0)
- enabled = val;
- else if (getpid() == 1)
+ cached_colors_enabled = val;
+ else if (getpid_cached() == 1)
/* PID1 outputs to the console without holding it open all the time */
- enabled = !getenv_terminal_is_dumb();
+ cached_colors_enabled = !getenv_terminal_is_dumb();
else
#endif // 0
- enabled = !terminal_is_dumb();
+ cached_colors_enabled = !terminal_is_dumb();
+ }
+
+ return cached_colors_enabled;
+}
+
+#if 0 /// UNNEEDED by elogind
+bool dev_console_colors_enabled(void) {
+ _cleanup_free_ char *s = NULL;
+ int b;
+
+ /* Returns true if we assume that color is supported on /dev/console.
+ *
+ * For that we first check if we explicitly got told to use colors or not, by checking $SYSTEMD_COLORS. If that
+ * isn't set we check whether PID 1 has $TERM set, and if not, whether TERM is set on the kernel command
+ * line. If we find $TERM set we assume color if it's not set to "dumb", similarly to how regular
+ * colors_enabled() operates. */
+
+ b = getenv_bool("SYSTEMD_COLORS");
+ if (b >= 0)
+ return b;
+
+ if (getenv_for_pid(1, "TERM", &s) <= 0)
+ (void) proc_cmdline_get_key("TERM", 0, &s);
+
+ return !streq_ptr(s, "dumb");
+}
+#endif // 0
+
+bool underline_enabled(void) {
+
+ if (cached_underline_enabled < 0) {
+
+ /* The Linux console doesn't support underlining, turn it off, but only there. */
+
+ if (colors_enabled())
+ cached_underline_enabled = !streq_ptr(getenv("TERM"), "linux");
+ else
+ cached_underline_enabled = false;
+ }
+
+ return cached_underline_enabled;
+}
+
+int vt_default_utf8(void) {
+ _cleanup_free_ char *b = NULL;
+ int r;
+
+ /* Read the default VT UTF8 setting from the kernel */
+
+ r = read_one_line_file("/sys/module/vt/parameters/default_utf8", &b);
+ if (r < 0)
+ return r;
+
+ return parse_boolean(b);
+}
+
+int vt_reset_keyboard(int fd) {
+ int kb;
+
+ /* If we can't read the default, then default to unicode. It's 2017 after all. */
+ kb = vt_default_utf8() != 0 ? K_UNICODE : K_XLATE;
+
+ if (ioctl(fd, KDSKBMODE, kb) < 0)
+ return -errno;
+
+ return 0;
+}
+
+#if 0 /// UNNEEDED by elogind
+static bool urlify_enabled(void) {
+ static int cached_urlify_enabled = -1;
+
+ /* Unfortunately 'less' doesn't support links like this yet 😭, hence let's disable this as long as there's a
+ * pager in effect. Let's drop this check as soon as less got fixed a and enough time passed so that it's safe
+ * to assume that a link-enabled 'less' version has hit most installations. */
+
+ if (cached_urlify_enabled < 0) {
+ int val;
+
+ val = getenv_bool("SYSTEMD_URLIFY");
+ if (val >= 0)
+ cached_urlify_enabled = val;
+ else
+ cached_urlify_enabled = colors_enabled() && !pager_have();
+ }
+
+ return cached_urlify_enabled;
+}
+
+int terminal_urlify(const char *url, const char *text, char **ret) {
+ char *n;
+
+ assert(url);
+
+ /* Takes an URL and a pretty string and formats it as clickable link for the terminal. See
+ * https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda for details. */
+
+ if (isempty(text))
+ text = url;
+
+ if (urlify_enabled())
+ n = strjoin("\x1B]8;;", url, "\a", text, "\x1B]8;;\a");
+ else
+ n = strdup(text);
+ if (!n)
+ return -ENOMEM;
+
+ *ret = n;
+ return 0;
+}
+
+int terminal_urlify_path(const char *path, const char *text, char **ret) {
+ _cleanup_free_ char *absolute = NULL;
+ struct utsname u;
+ const char *url;
+ int r;
+
+ assert(path);
+
+ /* Much like terminal_urlify() above, but takes a file system path as input
+ * and turns it into a proper file:// URL first. */
+
+ if (isempty(path))
+ return -EINVAL;
+
+ if (isempty(text))
+ text = path;
+
+ if (!urlify_enabled()) {
+ char *n;
+
+ n = strdup(text);
+ if (!n)
+ return -ENOMEM;
+
+ *ret = n;
+ return 0;
}
- return enabled;
+ if (uname(&u) < 0)
+ return -errno;
+
+ if (!path_is_absolute(path)) {
+ r = path_make_absolute_cwd(path, &absolute);
+ if (r < 0)
+ return r;
+
+ path = absolute;
+ }
+
+ /* As suggested by https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda, let's include the local
+ * hostname here. Note that we don't use gethostname_malloc() or gethostname_strict() since we are interested
+ * in the raw string the kernel has set, whatever it may be, under the assumption that terminals are not overly
+ * careful with validating the strings either. */
+
+ url = strjoina("file://", u.nodename, path);
+
+ return terminal_urlify(url, text, ret);
}
+
+static int cat_file(const char *filename, bool newline) {
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *urlified = NULL;
+ int r;
+
+ f = fopen(filename, "re");
+ if (!f)
+ return -errno;
+
+ r = terminal_urlify_path(filename, NULL, &urlified);
+ if (r < 0)
+ return r;
+
+ printf("%s%s# %s%s\n",
+ newline ? "\n" : "",
+ ansi_highlight_blue(),
+ urlified,
+ ansi_normal());
+ fflush(stdout);
+
+ for (;;) {
+ _cleanup_free_ char *line = NULL;
+
+ r = read_line(f, LONG_LINE_MAX, &line);
+ if (r < 0)
+ return log_error_errno(r, "Failed to read \"%s\": %m", filename);
+ if (r == 0)
+ break;
+
+ puts(line);
+ }
+
+ return 0;
+}
+
+int cat_files(const char *file, char **dropins, CatFlags flags) {
+ char **path;
+ int r;
+
+ if (file) {
+ r = cat_file(file, false);
+ if (r == -ENOENT && (flags & CAT_FLAGS_MAIN_FILE_OPTIONAL))
+ printf("%s# config file %s not found%s\n",
+ ansi_highlight_magenta(),
+ file,
+ ansi_normal());
+ else if (r < 0)
+ return log_warning_errno(r, "Failed to cat %s: %m", file);
+ }
+
+ STRV_FOREACH(path, dropins) {
+ r = cat_file(*path, file || path != dropins);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to cat %s: %m", *path);
+ }
+
+ return 0;
+}
+
+void print_separator(void) {
+
+ /* Outputs a separator line that resolves to whitespace when copied from the terminal. We do that by outputting
+ * one line filled with spaces with ANSI underline set, followed by a second (empty) line. */
+
+ if (underline_enabled()) {
+ size_t i, c;
+
+ c = columns();
+
+ flockfile(stdout);
+ fputs_unlocked(ANSI_UNDERLINE, stdout);
+
+ for (i = 0; i < c; i++)
+ fputc_unlocked(' ', stdout);
+
+ fputs_unlocked(ANSI_NORMAL "\n\n", stdout);
+ funlockfile(stdout);
+ } else
+ fputs("\n\n", stdout);
+}
+#endif // 0
diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h
index 84ba3a7f7..05b65972b 100644
--- a/src/basic/terminal-util.h
+++ b/src/basic/terminal-util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 <stdio.h>
@@ -27,21 +9,45 @@
#include "macro.h"
#include "time-util.h"
-#define ANSI_RED "\x1B[0;31m"
-#define ANSI_GREEN "\x1B[0;32m"
+/* Regular colors */
+#define ANSI_BLACK "\x1B[0;30m"
+#define ANSI_RED "\x1B[0;31m"
+#define ANSI_GREEN "\x1B[0;32m"
+#define ANSI_YELLOW "\x1B[0;33m"
+#define ANSI_BLUE "\x1B[0;34m"
+#define ANSI_MAGENTA "\x1B[0;35m"
+#define ANSI_CYAN "\x1B[0;36m"
+#define ANSI_WHITE "\x1B[0;37m"
+
+/* Bold/highlighted */
+#define ANSI_HIGHLIGHT_BLACK "\x1B[0;1;30m"
+#define ANSI_HIGHLIGHT_RED "\x1B[0;1;31m"
+#define ANSI_HIGHLIGHT_GREEN "\x1B[0;1;32m"
+#define ANSI_HIGHLIGHT_YELLOW "\x1B[0;1;33m"
+#define ANSI_HIGHLIGHT_BLUE "\x1B[0;1;34m"
+#define ANSI_HIGHLIGHT_MAGENTA "\x1B[0;1;35m"
+#define ANSI_HIGHLIGHT_CYAN "\x1B[0;1;36m"
+#define ANSI_HIGHLIGHT_WHITE "\x1B[0;1;37m"
+
+/* Underlined */
+#define ANSI_HIGHLIGHT_BLACK_UNDERLINE "\x1B[0;1;4;30m"
+#define ANSI_HIGHLIGHT_RED_UNDERLINE "\x1B[0;1;4;31m"
+#define ANSI_HIGHLIGHT_GREEN_UNDERLINE "\x1B[0;1;4;32m"
+#define ANSI_HIGHLIGHT_YELLOW_UNDERLINE "\x1B[0;1;4;33m"
+#define ANSI_HIGHLIGHT_BLUE_UNDERLINE "\x1B[0;1;4;34m"
+#define ANSI_HIGHLIGHT_MAGENTA_UNDERLINE "\x1B[0;1;4;35m"
+#define ANSI_HIGHLIGHT_CYAN_UNDERLINE "\x1B[0;1;4;36m"
+#define ANSI_HIGHLIGHT_WHITE_UNDERLINE "\x1B[0;1;4;37m"
+
+/* Other ANSI codes */
#define ANSI_UNDERLINE "\x1B[0;4m"
#define ANSI_HIGHLIGHT "\x1B[0;1;39m"
-#define ANSI_HIGHLIGHT_RED "\x1B[0;1;31m"
-#define ANSI_HIGHLIGHT_GREEN "\x1B[0;1;32m"
-#define ANSI_HIGHLIGHT_YELLOW "\x1B[0;1;33m"
-#define ANSI_HIGHLIGHT_BLUE "\x1B[0;1;34m"
#define ANSI_HIGHLIGHT_UNDERLINE "\x1B[0;1;4m"
-#define ANSI_HIGHLIGHT_RED_UNDERLINE "\x1B[0;1;4;31m"
-#define ANSI_HIGHLIGHT_GREEN_UNDERLINE "\x1B[0;1;4;32m"
-#define ANSI_HIGHLIGHT_YELLOW_UNDERLINE "\x1B[0;1;4;33m"
-#define ANSI_HIGHLIGHT_BLUE_UNDERLINE "\x1B[0;1;4;34m"
+
+/* Reset/clear ANSI styles */
#define ANSI_NORMAL "\x1B[0m"
+/* Erase characters until the end of the line */
#define ANSI_ERASE_TO_END_OF_LINE "\x1B[K"
/* Set cursor to top left corner and clear screen */
@@ -54,7 +60,23 @@ int reset_terminal(const char *name);
int open_terminal(const char *name, int mode);
#if 0 /// UNNEEDED by elogind
-int acquire_terminal(const char *name, bool fail, bool force, bool ignore_tiocstty_eperm, usec_t timeout);
+
+/* Flags for tweaking the way we become the controlling process of a terminal. */
+typedef enum AcquireTerminalFlags {
+ /* Try to become the controlling process of the TTY. If we can't return -EPERM. */
+ ACQUIRE_TERMINAL_TRY = 0,
+
+ /* Tell the kernel to forcibly make us the controlling process of the TTY. Returns -EPERM if the kernel doesn't allow that. */
+ ACQUIRE_TERMINAL_FORCE = 1,
+
+ /* If we can't become the controlling process of the TTY right-away, then wait until we can. */
+ ACQUIRE_TERMINAL_WAIT = 2,
+
+ /* Pick one of the above, and then OR this flag in, in order to request permissive behaviour, if we can't become controlling process then don't mind */
+ ACQUIRE_TERMINAL_PERMISSIVE = 1 << 2,
+} AcquireTerminalFlags;
+
+int acquire_terminal(const char *name, AcquireTerminalFlags flags, usec_t timeout);
int release_terminal(void);
int terminal_vhangup_fd(int fd);
@@ -70,9 +92,9 @@ int ask_string(char **ret, const char *text, ...) _printf_(2, 3);
int vt_disallocate(const char *name);
-char *resolve_dev_console(char **active);
#endif // 0
-int get_kernel_consoles(char ***consoles);
+int resolve_dev_console(char **ret);
+int get_kernel_consoles(char ***ret);
bool tty_is_vc(const char *tty);
#if 0 /// UNNEEDED by elogind
bool tty_is_vc_resolve(const char *tty);
@@ -83,8 +105,6 @@ int vtnr_from_tty(const char *tty);
const char *default_term_for_tty(const char *tty);
#endif // 0
-int make_stdio(int fd);
-int make_null_stdio(void);
#if 0 /// UNNEEDED by elogind
int make_console_stdio(void);
#endif // 0
@@ -93,33 +113,46 @@ int fd_columns(int fd);
unsigned columns(void);
int fd_lines(int fd);
unsigned lines(void);
+
#if 0 /// UNNEEDED by elogind
void columns_lines_cache_reset(int _unused_ signum);
#endif // 0
+void reset_terminal_feature_caches(void);
bool on_tty(void);
bool terminal_is_dumb(void);
bool colors_enabled(void);
+bool underline_enabled(void);
+#if 0 /// UNNEEDED by elogind
+bool dev_console_colors_enabled(void);
+#endif // 0
#define DEFINE_ANSI_FUNC(name, NAME) \
static inline const char *ansi_##name(void) { \
return colors_enabled() ? ANSI_##NAME : ""; \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
+ }
+
+#define DEFINE_ANSI_FUNC_UNDERLINE(name, NAME, REPLACEMENT) \
+ static inline const char *ansi_##name(void) { \
+ return underline_enabled() ? ANSI_##NAME : \
+ colors_enabled() ? ANSI_##REPLACEMENT : ""; \
+ }
-DEFINE_ANSI_FUNC(underline, UNDERLINE);
DEFINE_ANSI_FUNC(highlight, HIGHLIGHT);
-DEFINE_ANSI_FUNC(highlight_underline, HIGHLIGHT_UNDERLINE);
DEFINE_ANSI_FUNC(highlight_red, HIGHLIGHT_RED);
DEFINE_ANSI_FUNC(highlight_green, HIGHLIGHT_GREEN);
DEFINE_ANSI_FUNC(highlight_yellow, HIGHLIGHT_YELLOW);
DEFINE_ANSI_FUNC(highlight_blue, HIGHLIGHT_BLUE);
-DEFINE_ANSI_FUNC(highlight_red_underline, HIGHLIGHT_RED_UNDERLINE);
-DEFINE_ANSI_FUNC(highlight_green_underline, HIGHLIGHT_GREEN_UNDERLINE);
-DEFINE_ANSI_FUNC(highlight_yellow_underline, HIGHLIGHT_YELLOW_UNDERLINE);
-DEFINE_ANSI_FUNC(highlight_blue_underline, HIGHLIGHT_BLUE_UNDERLINE);
+DEFINE_ANSI_FUNC(highlight_magenta, HIGHLIGHT_MAGENTA);
DEFINE_ANSI_FUNC(normal, NORMAL);
+DEFINE_ANSI_FUNC_UNDERLINE(underline, UNDERLINE, NORMAL);
+DEFINE_ANSI_FUNC_UNDERLINE(highlight_underline, HIGHLIGHT_UNDERLINE, HIGHLIGHT);
+DEFINE_ANSI_FUNC_UNDERLINE(highlight_red_underline, HIGHLIGHT_RED_UNDERLINE, HIGHLIGHT_RED);
+DEFINE_ANSI_FUNC_UNDERLINE(highlight_green_underline, HIGHLIGHT_GREEN_UNDERLINE, HIGHLIGHT_GREEN);
+DEFINE_ANSI_FUNC_UNDERLINE(highlight_yellow_underline, HIGHLIGHT_YELLOW_UNDERLINE, HIGHLIGHT_YELLOW);
+DEFINE_ANSI_FUNC_UNDERLINE(highlight_blue_underline, HIGHLIGHT_BLUE_UNDERLINE, HIGHLIGHT_BLUE);
+
int get_ctty_devnr(pid_t pid, dev_t *d);
int get_ctty(pid_t, dev_t *_devnr, char **r);
@@ -133,3 +166,19 @@ int ptsname_namespace(int pty, char **ret);
int openpt_in_namespace(pid_t pid, int flags);
int open_terminal_in_namespace(pid_t pid, const char *name, int mode);
#endif // 0
+
+int vt_default_utf8(void);
+int vt_reset_keyboard(int fd);
+
+#if 0 /// UNNEEDED by elogind
+int terminal_urlify(const char *url, const char *text, char **ret);
+int terminal_urlify_path(const char *path, const char *text, char **ret);
+
+typedef enum CatFlags {
+ CAT_FLAGS_MAIN_FILE_OPTIONAL = 1 << 0,
+} CatFlags;
+
+int cat_files(const char *file, char **dropins, CatFlags flags);
+
+void print_separator(void);
+#endif // 0
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
index aadd3b715..6bd86bf4d 100644
--- a/src/basic/time-util.c
+++ b/src/basic/time-util.c
@@ -1,26 +1,10 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/timerfd.h>
@@ -32,10 +16,13 @@
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
+//#include "io-util.h"
#include "log.h"
#include "macro.h"
#include "parse-util.h"
#include "path-util.h"
+//#include "process-util.h"
+//#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
@@ -296,8 +283,11 @@ static char *format_timestamp_internal(
return NULL; /* Timestamp is unset */
/* Let's not format times with years > 9999 */
- if (t > USEC_TIMESTAMP_FORMATTABLE_MAX)
- return NULL;
+ if (t > USEC_TIMESTAMP_FORMATTABLE_MAX) {
+ assert(l >= strlen("--- XXXX-XX-XX XX:XX:XX") + 1);
+ strcpy(buf, "--- XXXX-XX-XX XX:XX:XX");
+ return buf;
+ }
sec = (time_t) (t / USEC_PER_SEC); /* Round down */
@@ -454,7 +444,7 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
{ "us", 1 },
};
- unsigned i;
+ size_t i;
char *p = buf;
bool something = false;
@@ -499,7 +489,7 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
/* Let's see if we should shows this in dot notation */
if (t < USEC_PER_MINUTE && b > 0) {
usec_t cc;
- int j;
+ signed char j;
j = 0;
for (cc = table[i].usec; cc > 1; cc /= 10)
@@ -609,7 +599,7 @@ int timestamp_deserialize(const char *value, usec_t *timestamp) {
}
#if 0 /// UNNEEDED by elogind
-int parse_timestamp(const char *t, usec_t *usec) {
+static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
static const struct {
const char *name;
const int nr;
@@ -630,15 +620,14 @@ int parse_timestamp(const char *t, usec_t *usec) {
{ "Sat", 6 },
};
- const char *k, *utc, *tzn = NULL;
+ const char *k, *utc = NULL, *tzn = NULL;
struct tm tm, copy;
time_t x;
usec_t x_usec, plus = 0, minus = 0, ret;
int r, weekday = -1, dst = -1;
- unsigned i;
+ size_t i;
- /*
- * Allowed syntaxes:
+ /* Allowed syntaxes:
*
* 2012-09-22 16:34:22
* 2012-09-22 16:34 (seconds will be set to 0)
@@ -652,90 +641,91 @@ int parse_timestamp(const char *t, usec_t *usec) {
* +5min
* -5days
* @2147483647 (seconds since epoch)
- *
*/
assert(t);
assert(usec);
- if (t[0] == '@')
+ if (t[0] == '@' && !with_tz)
return parse_sec(t + 1, usec);
ret = now(CLOCK_REALTIME);
- if (streq(t, "now"))
- goto finish;
+ if (!with_tz) {
+ if (streq(t, "now"))
+ goto finish;
- else if (t[0] == '+') {
- r = parse_sec(t+1, &plus);
- if (r < 0)
- return r;
+ else if (t[0] == '+') {
+ r = parse_sec(t+1, &plus);
+ if (r < 0)
+ return r;
- goto finish;
+ goto finish;
- } else if (t[0] == '-') {
- r = parse_sec(t+1, &minus);
- if (r < 0)
- return r;
+ } else if (t[0] == '-') {
+ r = parse_sec(t+1, &minus);
+ if (r < 0)
+ return r;
- goto finish;
+ goto finish;
- } else if ((k = endswith(t, " ago"))) {
- t = strndupa(t, k - t);
+ } else if ((k = endswith(t, " ago"))) {
+ t = strndupa(t, k - t);
- r = parse_sec(t, &minus);
- if (r < 0)
- return r;
+ r = parse_sec(t, &minus);
+ if (r < 0)
+ return r;
- goto finish;
+ goto finish;
- } else if ((k = endswith(t, " left"))) {
- t = strndupa(t, k - t);
+ } else if ((k = endswith(t, " left"))) {
+ t = strndupa(t, k - t);
- r = parse_sec(t, &plus);
- if (r < 0)
- return r;
+ r = parse_sec(t, &plus);
+ if (r < 0)
+ return r;
- goto finish;
- }
+ goto finish;
+ }
- /* See if the timestamp is suffixed with UTC */
- utc = endswith_no_case(t, " UTC");
- if (utc)
- t = strndupa(t, utc - t);
- else {
- const char *e = NULL;
- int j;
+ /* See if the timestamp is suffixed with UTC */
+ utc = endswith_no_case(t, " UTC");
+ if (utc)
+ t = strndupa(t, utc - t);
+ else {
+ const char *e = NULL;
+ int j;
- tzset();
+ tzset();
- /* See if the timestamp is suffixed by either the DST or non-DST local timezone. Note that we only
- * support the local timezones here, nothing else. Not because we wouldn't want to, but simply because
- * there are no nice APIs available to cover this. By accepting the local time zone strings, we make
- * sure that all timestamps written by format_timestamp() can be parsed correctly, even though we don't
- * support arbitrary timezone specifications. */
+ /* See if the timestamp is suffixed by either the DST or non-DST local timezone. Note that we only
+ * support the local timezones here, nothing else. Not because we wouldn't want to, but simply because
+ * there are no nice APIs available to cover this. By accepting the local time zone strings, we make
+ * sure that all timestamps written by format_timestamp() can be parsed correctly, even though we don't
+ * support arbitrary timezone specifications. */
- for (j = 0; j <= 1; j++) {
+ for (j = 0; j <= 1; j++) {
- if (isempty(tzname[j]))
- continue;
+ if (isempty(tzname[j]))
+ continue;
- e = endswith_no_case(t, tzname[j]);
- if (!e)
- continue;
- if (e == t)
- continue;
- if (e[-1] != ' ')
- continue;
+ e = endswith_no_case(t, tzname[j]);
+ if (!e)
+ continue;
+ if (e == t)
+ continue;
+ if (e[-1] != ' ')
+ continue;
- break;
- }
+ break;
+ }
- if (IN_SET(j, 0, 1)) {
- /* Found one of the two timezones specified. */
- t = strndupa(t, e - t - 1);
- dst = j;
- tzn = tzname[j];
+ if (IN_SET(j, 0, 1)) {
+ /* Found one of the two timezones specified. */
+ t = strndupa(t, e - t - 1);
+ dst = j;
+ tzn = tzname[j];
+ }
}
}
@@ -746,7 +736,7 @@ int parse_timestamp(const char *t, usec_t *usec) {
return -EINVAL;
tm.tm_isdst = dst;
- if (tzn)
+ if (!with_tz && tzn)
tm.tm_zone = tzn;
if (streq(t, "today")) {
@@ -859,11 +849,11 @@ parse_usec:
}
from_tm:
- x = mktime_or_timegm(&tm, utc);
- if (x < 0)
+ if (weekday >= 0 && tm.tm_wday != weekday)
return -EINVAL;
- if (weekday >= 0 && tm.tm_wday != weekday)
+ x = mktime_or_timegm(&tm, utc);
+ if (x < 0)
return -EINVAL;
ret = (usec_t) x * USEC_PER_SEC + x_usec;
@@ -886,6 +876,65 @@ finish:
return 0;
}
+
+typedef struct ParseTimestampResult {
+ usec_t usec;
+ int return_value;
+} ParseTimestampResult;
+
+int parse_timestamp(const char *t, usec_t *usec) {
+ char *last_space, *tz = NULL;
+ ParseTimestampResult *shared, tmp;
+ int r;
+
+ last_space = strrchr(t, ' ');
+ if (last_space != NULL && timezone_is_valid(last_space + 1, LOG_DEBUG))
+ tz = last_space + 1;
+
+ if (!tz || endswith_no_case(t, " UTC"))
+ return parse_timestamp_impl(t, usec, false);
+
+ shared = mmap(NULL, sizeof *shared, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
+ if (shared == MAP_FAILED)
+ return negative_errno();
+
+ r = safe_fork("(sd-timestamp)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_WAIT, NULL);
+ if (r < 0) {
+ (void) munmap(shared, sizeof *shared);
+ return r;
+ }
+ if (r == 0) {
+ bool with_tz = true;
+
+ if (setenv("TZ", tz, 1) != 0) {
+ shared->return_value = negative_errno();
+ _exit(EXIT_FAILURE);
+ }
+
+ tzset();
+
+ /* If there is a timezone that matches the tzname fields, leave the parsing to the implementation.
+ * Otherwise just cut it off. */
+ with_tz = !STR_IN_SET(tz, tzname[0], tzname[1]);
+
+ /* Cut off the timezone if we dont need it. */
+ if (with_tz)
+ t = strndupa(t, last_space - t);
+
+ shared->return_value = parse_timestamp_impl(t, &shared->usec, with_tz);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ tmp = *shared;
+ if (munmap(shared, sizeof *shared) != 0)
+ return negative_errno();
+
+ if (tmp.return_value == 0)
+ *usec = tmp.usec;
+
+ return tmp.return_value;
+}
#endif // 0
static char* extract_multiplier(char *p, usec_t *multiplier) {
@@ -923,7 +972,7 @@ static char* extract_multiplier(char *p, usec_t *multiplier) {
{ "us", 1ULL },
{ "µs", 1ULL },
};
- unsigned i;
+ size_t i;
for (i = 0; i < ELEMENTSOF(table); i++) {
char *e;
@@ -1025,7 +1074,11 @@ int parse_sec(const char *t, usec_t *usec) {
#if 0 /// UNNEEDED by elogind
int parse_sec_fix_0(const char *t, usec_t *usec) {
+ assert(t);
+ assert(usec);
+
t += strspn(t, WHITESPACE);
+
if (streq(t, "0")) {
*usec = USEC_INFINITY;
return 0;
@@ -1094,8 +1147,8 @@ int parse_nsec(const char *t, nsec_t *nsec) {
for (;;) {
long long l, z = 0;
+ size_t n = 0, i;
char *e;
- unsigned i, n = 0;
p += strspn(p, WHITESPACE);
@@ -1230,16 +1283,17 @@ int get_timezones(char ***ret) {
} else if (errno != ENOENT)
return -errno;
- *ret = zones;
- zones = NULL;
+ *ret = TAKE_PTR(zones);
return 0;
}
-bool timezone_is_valid(const char *name) {
+bool timezone_is_valid(const char *name, int log_level) {
bool slash = false;
const char *p, *t;
- struct stat st;
+ _cleanup_close_ int fd = -1;
+ char buf[4];
+ int r;
if (isempty(name))
return false;
@@ -1251,7 +1305,7 @@ bool timezone_is_valid(const char *name) {
if (!(*p >= '0' && *p <= '9') &&
!(*p >= 'a' && *p <= 'z') &&
!(*p >= 'A' && *p <= 'Z') &&
- !(*p == '-' || *p == '_' || *p == '+' || *p == '/'))
+ !IN_SET(*p, '-', '_', '+', '/'))
return false;
if (*p == '/') {
@@ -1267,12 +1321,34 @@ bool timezone_is_valid(const char *name) {
if (slash)
return false;
+ if (p - name >= PATH_MAX)
+ return false;
+
t = strjoina("/usr/share/zoneinfo/", name);
- if (stat(t, &st) < 0)
+
+ fd = open(t, O_RDONLY|O_CLOEXEC);
+ if (fd < 0) {
+ log_full_errno(log_level, errno, "Failed to open timezone file '%s': %m", t);
+ return false;
+ }
+
+ r = fd_verify_regular(fd);
+ if (r < 0) {
+ log_full_errno(log_level, r, "Timezone file '%s' is not a regular file: %m", t);
return false;
+ }
+
+ r = loop_read_exact(fd, buf, 4, false);
+ if (r < 0) {
+ log_full_errno(log_level, r, "Failed to read from timezone file '%s': %m", t);
+ return false;
+ }
- if (!S_ISREG(st.st_mode))
+ /* Magic from tzfile(5) */
+ if (memcmp(buf, "TZif", 4) != 0) {
+ log_full(log_level, "Timezone file '%s' has wrong magic bytes", t);
return false;
+ }
return true;
}
@@ -1308,7 +1384,7 @@ clockid_t clock_boottime_or_monotonic(void) {
#endif // 0
#if 1 /// let's add a diagnostic push to silence -Wimplicit-fallthrough to elogind
-# ifdef __GNUC__
+# if defined(__GNUC__) && (__GNUC__ > 6)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
# endif // __GNUC__
@@ -1329,8 +1405,7 @@ bool clock_supported(clockid_t clock) {
if (!clock_boottime_supported())
return false;
- /* fall through */
-
+ _fallthrough_;
default:
/* For everything else, check properly */
return clock_gettime(clock, &ts) >= 0;
@@ -1359,7 +1434,7 @@ int get_timezone(char **tz) {
if (!e)
return -EINVAL;
- if (!timezone_is_valid(e))
+ if (!timezone_is_valid(e, LOG_DEBUG))
return -EINVAL;
z = strdup(e);
@@ -1413,3 +1488,33 @@ usec_t usec_shift_clock(usec_t x, clockid_t from, clockid_t to) {
return usec_sub_unsigned(b, usec_sub_unsigned(a, x));
}
#endif // 0
+
+bool in_utc_timezone(void) {
+ tzset();
+
+ return timezone == 0 && daylight == 0;
+}
+
+int time_change_fd(void) {
+
+ /* We only care for the cancellation event, hence we set the timeout to the latest possible value. */
+ static const struct itimerspec its = {
+ .it_value.tv_sec = TIME_T_MAX,
+ };
+
+ _cleanup_close_ int fd;
+
+ assert_cc(sizeof(time_t) == sizeof(TIME_T_MAX));
+
+ /* Uses TFD_TIMER_CANCEL_ON_SET to get notifications whenever CLOCK_REALTIME makes a jump relative to
+ * CLOCK_MONOTONIC. */
+
+ fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC);
+ if (fd < 0)
+ return -errno;
+
+ if (timerfd_settime(fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0)
+ return -errno;
+
+ return TAKE_FD(fd);
+}
diff --git a/src/basic/time-util.h b/src/basic/time-util.h
index 6bf0f72ef..6a7d90d51 100644
--- a/src/basic/time-util.h
+++ b/src/basic/time-util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 <stdbool.h>
#include <stddef.h>
@@ -103,12 +85,12 @@ triple_timestamp* triple_timestamp_from_realtime(triple_timestamp *ts, usec_t u)
#define TRIPLE_TIMESTAMP_HAS_CLOCK(clock) \
IN_SET(clock, CLOCK_REALTIME, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM)
-static inline bool dual_timestamp_is_set(dual_timestamp *ts) {
+static inline bool dual_timestamp_is_set(const dual_timestamp *ts) {
return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) ||
(ts->monotonic > 0 && ts->monotonic != USEC_INFINITY));
}
-static inline bool triple_timestamp_is_set(triple_timestamp *ts) {
+static inline bool triple_timestamp_is_set(const triple_timestamp *ts) {
return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) ||
(ts->monotonic > 0 && ts->monotonic != USEC_INFINITY) ||
(ts->boottime > 0 && ts->boottime != USEC_INFINITY));
@@ -157,7 +139,7 @@ int parse_nsec(const char *t, nsec_t *nsec);
bool ntp_synced(void);
int get_timezones(char ***l);
-bool timezone_is_valid(const char *name);
+bool timezone_is_valid(const char *name, int log_level);
#endif // 0
bool clock_boottime_supported(void);
@@ -168,10 +150,6 @@ clockid_t clock_boottime_or_monotonic(void);
usec_t usec_shift_clock(usec_t, clockid_t from, clockid_t to);
#endif // 0
-#define xstrftime(buf, fmt, tm) \
- assert_message_se(strftime(buf, ELEMENTSOF(buf), fmt, tm) > 0, \
- "xstrftime: " #buf "[] must be big enough")
-
#if 0 /// UNNEEDED by elogind
int get_timezone(char **timezone);
@@ -183,6 +161,8 @@ struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc);
unsigned long usec_to_jiffies(usec_t usec);
#endif // 0
+bool in_utc_timezone(void);
+
static inline usec_t usec_add(usec_t a, usec_t b) {
usec_t c;
@@ -221,5 +201,7 @@ static inline usec_t usec_sub_signed(usec_t timestamp, int64_t delta) {
/* With a 32bit time_t we can't go beyond 2038... */
#define USEC_TIMESTAMP_FORMATTABLE_MAX ((usec_t) 2147483647000000)
#else
-#error "Yuck, time_t is neither 4 not 8 bytes wide?"
+#error "Yuck, time_t is neither 4 nor 8 bytes wide?"
#endif
+
+int time_change_fd(void);
diff --git a/src/basic/umask-util.h b/src/basic/umask-util.h
index 359d87d27..e964292ea 100644
--- a/src/basic/umask-util.h
+++ b/src/basic/umask-util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <sys/stat.h>
#include <sys/types.h>
diff --git a/src/basic/unaligned.h b/src/basic/unaligned.h
index 7c847a3cc..8a1d06445 100644
--- a/src/basic/unaligned.h
+++ b/src/basic/unaligned.h
@@ -1,23 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <endian.h>
#include <stdint.h>
@@ -25,89 +8,77 @@
/* BE */
static inline uint16_t unaligned_read_be16(const void *_u) {
- const uint8_t *u = _u;
+ const struct __attribute__((packed, may_alias)) { uint16_t x; } *u = _u;
- return (((uint16_t) u[0]) << 8) |
- ((uint16_t) u[1]);
+ return be16toh(u->x);
}
static inline uint32_t unaligned_read_be32(const void *_u) {
- const uint8_t *u = _u;
+ const struct __attribute__((packed, may_alias)) { uint32_t x; } *u = _u;
- return (((uint32_t) unaligned_read_be16(u)) << 16) |
- ((uint32_t) unaligned_read_be16(u + 2));
+ return be32toh(u->x);
}
static inline uint64_t unaligned_read_be64(const void *_u) {
- const uint8_t *u = _u;
+ const struct __attribute__((packed, may_alias)) { uint64_t x; } *u = _u;
- return (((uint64_t) unaligned_read_be32(u)) << 32) |
- ((uint64_t) unaligned_read_be32(u + 4));
+ return be64toh(u->x);
}
static inline void unaligned_write_be16(void *_u, uint16_t a) {
- uint8_t *u = _u;
+ struct __attribute__((packed, may_alias)) { uint16_t x; } *u = _u;
- u[0] = (uint8_t) (a >> 8);
- u[1] = (uint8_t) a;
+ u->x = be16toh(a);
}
static inline void unaligned_write_be32(void *_u, uint32_t a) {
- uint8_t *u = _u;
+ struct __attribute__((packed, may_alias)) { uint32_t x; } *u = _u;
- unaligned_write_be16(u, (uint16_t) (a >> 16));
- unaligned_write_be16(u + 2, (uint16_t) a);
+ u->x = be32toh(a);
}
static inline void unaligned_write_be64(void *_u, uint64_t a) {
- uint8_t *u = _u;
+ struct __attribute__((packed, may_alias)) { uint64_t x; } *u = _u;
- unaligned_write_be32(u, (uint32_t) (a >> 32));
- unaligned_write_be32(u + 4, (uint32_t) a);
+ u->x = be64toh(a);
}
/* LE */
static inline uint16_t unaligned_read_le16(const void *_u) {
- const uint8_t *u = _u;
+ const struct __attribute__((packed, may_alias)) { uint16_t x; } *u = _u;
- return (((uint16_t) u[1]) << 8) |
- ((uint16_t) u[0]);
+ return le16toh(u->x);
}
static inline uint32_t unaligned_read_le32(const void *_u) {
- const uint8_t *u = _u;
+ const struct __attribute__((packed, may_alias)) { uint32_t x; } *u = _u;
- return (((uint32_t) unaligned_read_le16(u + 2)) << 16) |
- ((uint32_t) unaligned_read_le16(u));
+ return le32toh(u->x);
}
static inline uint64_t unaligned_read_le64(const void *_u) {
- const uint8_t *u = _u;
+ const struct __attribute__((packed, may_alias)) { uint64_t x; } *u = _u;
- return (((uint64_t) unaligned_read_le32(u + 4)) << 32) |
- ((uint64_t) unaligned_read_le32(u));
+ return le64toh(u->x);
}
static inline void unaligned_write_le16(void *_u, uint16_t a) {
- uint8_t *u = _u;
+ struct __attribute__((packed, may_alias)) { uint16_t x; } *u = _u;
- u[0] = (uint8_t) a;
- u[1] = (uint8_t) (a >> 8);
+ u->x = le16toh(a);
}
static inline void unaligned_write_le32(void *_u, uint32_t a) {
- uint8_t *u = _u;
+ struct __attribute__((packed, may_alias)) { uint32_t x; } *u = _u;
- unaligned_write_le16(u, (uint16_t) a);
- unaligned_write_le16(u + 2, (uint16_t) (a >> 16));
+ u->x = le32toh(a);
}
static inline void unaligned_write_le64(void *_u, uint64_t a) {
- uint8_t *u = _u;
+ struct __attribute__((packed, may_alias)) { uint64_t x; } *u = _u;
- unaligned_write_le32(u, (uint32_t) a);
- unaligned_write_le32(u + 4, (uint32_t) (a >> 32));
+ u->x = le64toh(a);
}
#if __BYTE_ORDER == __BIG_ENDIAN
diff --git a/src/basic/unit-def.c b/src/basic/unit-def.c
new file mode 100644
index 000000000..ac6a9b37e
--- /dev/null
+++ b/src/basic/unit-def.c
@@ -0,0 +1,273 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "alloc-util.h"
+#include "bus-label.h"
+#include "string-table.h"
+#include "unit-def.h"
+#include "unit-name.h"
+
+char *unit_dbus_path_from_name(const char *name) {
+ _cleanup_free_ char *e = NULL;
+
+ assert(name);
+
+ e = bus_label_escape(name);
+ if (!e)
+ return NULL;
+
+ return strappend("/org/freedesktop/systemd1/unit/", e);
+}
+
+int unit_name_from_dbus_path(const char *path, char **name) {
+ const char *e;
+ char *n;
+
+ e = startswith(path, "/org/freedesktop/systemd1/unit/");
+ if (!e)
+ return -EINVAL;
+
+ n = bus_label_unescape(e);
+ if (!n)
+ return -ENOMEM;
+
+ *name = n;
+ return 0;
+}
+
+const char* unit_dbus_interface_from_type(UnitType t) {
+
+ static const char *const table[_UNIT_TYPE_MAX] = {
+ [UNIT_SERVICE] = "org.freedesktop.systemd1.Service",
+ [UNIT_SOCKET] = "org.freedesktop.systemd1.Socket",
+ [UNIT_TARGET] = "org.freedesktop.systemd1.Target",
+ [UNIT_DEVICE] = "org.freedesktop.systemd1.Device",
+ [UNIT_MOUNT] = "org.freedesktop.systemd1.Mount",
+ [UNIT_AUTOMOUNT] = "org.freedesktop.systemd1.Automount",
+ [UNIT_SWAP] = "org.freedesktop.systemd1.Swap",
+ [UNIT_TIMER] = "org.freedesktop.systemd1.Timer",
+ [UNIT_PATH] = "org.freedesktop.systemd1.Path",
+ [UNIT_SLICE] = "org.freedesktop.systemd1.Slice",
+ [UNIT_SCOPE] = "org.freedesktop.systemd1.Scope",
+ };
+
+ if (t < 0)
+ return NULL;
+ if (t >= _UNIT_TYPE_MAX)
+ return NULL;
+
+ return table[t];
+}
+
+const char *unit_dbus_interface_from_name(const char *name) {
+ UnitType t;
+
+ t = unit_name_to_type(name);
+ if (t < 0)
+ return NULL;
+
+ return unit_dbus_interface_from_type(t);
+}
+
+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_SWAP] = "swap",
+ [UNIT_TIMER] = "timer",
+ [UNIT_PATH] = "path",
+ [UNIT_SLICE] = "slice",
+ [UNIT_SCOPE] = "scope",
+};
+
+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_NOT_FOUND] = "not-found",
+ [UNIT_BAD_SETTING] = "bad-setting",
+ [UNIT_ERROR] = "error",
+ [UNIT_MERGED] = "merged",
+ [UNIT_MASKED] = "masked"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState);
+
+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 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 device_state_table[_DEVICE_STATE_MAX] = {
+ [DEVICE_DEAD] = "dead",
+ [DEVICE_TENTATIVE] = "tentative",
+ [DEVICE_PLUGGED] = "plugged",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState);
+
+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_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 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 scope_state_table[_SCOPE_STATE_MAX] = {
+ [SCOPE_DEAD] = "dead",
+ [SCOPE_RUNNING] = "running",
+ [SCOPE_ABANDONED] = "abandoned",
+ [SCOPE_STOP_SIGTERM] = "stop-sigterm",
+ [SCOPE_STOP_SIGKILL] = "stop-sigkill",
+ [SCOPE_FAILED] = "failed",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(scope_state, ScopeState);
+
+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_SIGABRT] = "stop-sigabrt",
+ [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 slice_state_table[_SLICE_STATE_MAX] = {
+ [SLICE_DEAD] = "dead",
+ [SLICE_ACTIVE] = "active"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(slice_state, SliceState);
+
+static const char* const socket_state_table[_SOCKET_STATE_MAX] = {
+ [SOCKET_DEAD] = "dead",
+ [SOCKET_START_PRE] = "start-pre",
+ [SOCKET_START_CHOWN] = "start-chown",
+ [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 swap_state_table[_SWAP_STATE_MAX] = {
+ [SWAP_DEAD] = "dead",
+ [SWAP_ACTIVATING] = "activating",
+ [SWAP_ACTIVATING_DONE] = "activating-done",
+ [SWAP_ACTIVE] = "active",
+ [SWAP_DEACTIVATING] = "deactivating",
+ [SWAP_DEACTIVATING_SIGTERM] = "deactivating-sigterm",
+ [SWAP_DEACTIVATING_SIGKILL] = "deactivating-sigkill",
+ [SWAP_FAILED] = "failed"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
+
+static const char* const target_state_table[_TARGET_STATE_MAX] = {
+ [TARGET_DEAD] = "dead",
+ [TARGET_ACTIVE] = "active"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(target_state, TargetState);
+
+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 unit_dependency_table[_UNIT_DEPENDENCY_MAX] = {
+ [UNIT_REQUIRES] = "Requires",
+ [UNIT_REQUISITE] = "Requisite",
+ [UNIT_WANTS] = "Wants",
+ [UNIT_BINDS_TO] = "BindsTo",
+ [UNIT_PART_OF] = "PartOf",
+ [UNIT_REQUIRED_BY] = "RequiredBy",
+ [UNIT_REQUISITE_OF] = "RequisiteOf",
+ [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_JOINS_NAMESPACE_OF] = "JoinsNamespaceOf",
+ [UNIT_REFERENCES] = "References",
+ [UNIT_REFERENCED_BY] = "ReferencedBy",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency);
+
+static const char* const notify_access_table[_NOTIFY_ACCESS_MAX] = {
+ [NOTIFY_NONE] = "none",
+ [NOTIFY_MAIN] = "main",
+ [NOTIFY_EXEC] = "exec",
+ [NOTIFY_ALL] = "all"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(notify_access, NotifyAccess);
diff --git a/src/basic/unit-def.h b/src/basic/unit-def.h
new file mode 100644
index 000000000..d7e2d7466
--- /dev/null
+++ b/src/basic/unit-def.h
@@ -0,0 +1,284 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <stdbool.h>
+
+#include "macro.h"
+
+typedef enum UnitType {
+ UNIT_SERVICE = 0,
+ UNIT_SOCKET,
+ UNIT_TARGET,
+ UNIT_DEVICE,
+ UNIT_MOUNT,
+ UNIT_AUTOMOUNT,
+ UNIT_SWAP,
+ UNIT_TIMER,
+ UNIT_PATH,
+ UNIT_SLICE,
+ UNIT_SCOPE,
+ _UNIT_TYPE_MAX,
+ _UNIT_TYPE_INVALID = -1
+} UnitType;
+
+typedef enum UnitLoadState {
+ UNIT_STUB = 0,
+ UNIT_LOADED,
+ UNIT_NOT_FOUND, /* error condition #1: unit file not found */
+ UNIT_BAD_SETTING, /* error condition #2: we couldn't parse some essential unit file setting */
+ UNIT_ERROR, /* error condition #3: other "system" error, catchall for the rest */
+ UNIT_MERGED,
+ UNIT_MASKED,
+ _UNIT_LOAD_STATE_MAX,
+ _UNIT_LOAD_STATE_INVALID = -1
+} UnitLoadState;
+
+typedef enum UnitActiveState {
+ UNIT_ACTIVE,
+ UNIT_RELOADING,
+ UNIT_INACTIVE,
+ UNIT_FAILED,
+ UNIT_ACTIVATING,
+ UNIT_DEACTIVATING,
+ _UNIT_ACTIVE_STATE_MAX,
+ _UNIT_ACTIVE_STATE_INVALID = -1
+} UnitActiveState;
+
+typedef enum AutomountState {
+ AUTOMOUNT_DEAD,
+ AUTOMOUNT_WAITING,
+ AUTOMOUNT_RUNNING,
+ AUTOMOUNT_FAILED,
+ _AUTOMOUNT_STATE_MAX,
+ _AUTOMOUNT_STATE_INVALID = -1
+} AutomountState;
+
+/* We simply watch devices, we cannot plug/unplug them. That
+ * simplifies the state engine greatly */
+typedef enum DeviceState {
+ DEVICE_DEAD,
+ DEVICE_TENTATIVE, /* mounted or swapped, but not (yet) announced by udev */
+ DEVICE_PLUGGED, /* announced by udev */
+ _DEVICE_STATE_MAX,
+ _DEVICE_STATE_INVALID = -1
+} DeviceState;
+
+typedef enum MountState {
+ MOUNT_DEAD,
+ MOUNT_MOUNTING, /* /usr/bin/mount is running, but the mount is not done yet. */
+ MOUNT_MOUNTING_DONE, /* /usr/bin/mount is running, and the mount is done. */
+ MOUNT_MOUNTED,
+ MOUNT_REMOUNTING,
+ MOUNT_UNMOUNTING,
+ MOUNT_REMOUNTING_SIGTERM,
+ MOUNT_REMOUNTING_SIGKILL,
+ MOUNT_UNMOUNTING_SIGTERM,
+ MOUNT_UNMOUNTING_SIGKILL,
+ MOUNT_FAILED,
+ _MOUNT_STATE_MAX,
+ _MOUNT_STATE_INVALID = -1
+} MountState;
+
+typedef enum PathState {
+ PATH_DEAD,
+ PATH_WAITING,
+ PATH_RUNNING,
+ PATH_FAILED,
+ _PATH_STATE_MAX,
+ _PATH_STATE_INVALID = -1
+} PathState;
+
+typedef enum ScopeState {
+ SCOPE_DEAD,
+ SCOPE_RUNNING,
+ SCOPE_ABANDONED,
+ SCOPE_STOP_SIGTERM,
+ SCOPE_STOP_SIGKILL,
+ SCOPE_FAILED,
+ _SCOPE_STATE_MAX,
+ _SCOPE_STATE_INVALID = -1
+} ScopeState;
+
+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_SIGABRT, /* Watchdog timeout */
+ 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 SliceState {
+ SLICE_DEAD,
+ SLICE_ACTIVE,
+ _SLICE_STATE_MAX,
+ _SLICE_STATE_INVALID = -1
+} SliceState;
+
+typedef enum SocketState {
+ SOCKET_DEAD,
+ SOCKET_START_PRE,
+ SOCKET_START_CHOWN,
+ 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 SwapState {
+ SWAP_DEAD,
+ SWAP_ACTIVATING, /* /sbin/swapon is running, but the swap not yet enabled. */
+ SWAP_ACTIVATING_DONE, /* /sbin/swapon is running, and the swap is done. */
+ SWAP_ACTIVE,
+ SWAP_DEACTIVATING,
+ SWAP_DEACTIVATING_SIGTERM,
+ SWAP_DEACTIVATING_SIGKILL,
+ SWAP_FAILED,
+ _SWAP_STATE_MAX,
+ _SWAP_STATE_INVALID = -1
+} SwapState;
+
+typedef enum TargetState {
+ TARGET_DEAD,
+ TARGET_ACTIVE,
+ _TARGET_STATE_MAX,
+ _TARGET_STATE_INVALID = -1
+} TargetState;
+
+typedef enum TimerState {
+ TIMER_DEAD,
+ TIMER_WAITING,
+ TIMER_RUNNING,
+ TIMER_ELAPSED,
+ TIMER_FAILED,
+ _TIMER_STATE_MAX,
+ _TIMER_STATE_INVALID = -1
+} TimerState;
+
+typedef enum UnitDependency {
+ /* Positive dependencies */
+ UNIT_REQUIRES,
+ UNIT_REQUISITE,
+ UNIT_WANTS,
+ UNIT_BINDS_TO,
+ UNIT_PART_OF,
+
+ /* Inverse of the above */
+ UNIT_REQUIRED_BY, /* inverse of 'requires' is 'required_by' */
+ UNIT_REQUISITE_OF, /* inverse of 'requisite' is 'requisite_of' */
+ 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,
+
+ /* Joins namespace of */
+ UNIT_JOINS_NAMESPACE_OF,
+
+ /* Reference information for GC logic */
+ UNIT_REFERENCES, /* Inverse of 'references' is 'referenced_by' */
+ UNIT_REFERENCED_BY,
+
+ _UNIT_DEPENDENCY_MAX,
+ _UNIT_DEPENDENCY_INVALID = -1
+} UnitDependency;
+
+typedef enum NotifyAccess {
+ NOTIFY_NONE,
+ NOTIFY_ALL,
+ NOTIFY_MAIN,
+ NOTIFY_EXEC,
+ _NOTIFY_ACCESS_MAX,
+ _NOTIFY_ACCESS_INVALID = -1
+} NotifyAccess;
+
+char *unit_dbus_path_from_name(const char *name);
+int unit_name_from_dbus_path(const char *path, char **name);
+
+const char* unit_dbus_interface_from_type(UnitType t);
+const char *unit_dbus_interface_from_name(const char *name);
+
+const char *unit_type_to_string(UnitType i) _const_;
+UnitType unit_type_from_string(const char *s) _pure_;
+
+const char *unit_load_state_to_string(UnitLoadState i) _const_;
+UnitLoadState unit_load_state_from_string(const char *s) _pure_;
+
+const char *unit_active_state_to_string(UnitActiveState i) _const_;
+UnitActiveState unit_active_state_from_string(const char *s) _pure_;
+
+const char* automount_state_to_string(AutomountState i) _const_;
+AutomountState automount_state_from_string(const char *s) _pure_;
+
+const char* device_state_to_string(DeviceState i) _const_;
+DeviceState device_state_from_string(const char *s) _pure_;
+
+const char* mount_state_to_string(MountState i) _const_;
+MountState mount_state_from_string(const char *s) _pure_;
+
+const char* path_state_to_string(PathState i) _const_;
+PathState path_state_from_string(const char *s) _pure_;
+
+const char* scope_state_to_string(ScopeState i) _const_;
+ScopeState scope_state_from_string(const char *s) _pure_;
+
+const char* service_state_to_string(ServiceState i) _const_;
+ServiceState service_state_from_string(const char *s) _pure_;
+
+const char* slice_state_to_string(SliceState i) _const_;
+SliceState slice_state_from_string(const char *s) _pure_;
+
+const char* socket_state_to_string(SocketState i) _const_;
+SocketState socket_state_from_string(const char *s) _pure_;
+
+const char* swap_state_to_string(SwapState i) _const_;
+SwapState swap_state_from_string(const char *s) _pure_;
+
+const char* target_state_to_string(TargetState i) _const_;
+TargetState target_state_from_string(const char *s) _pure_;
+
+const char *timer_state_to_string(TimerState i) _const_;
+TimerState timer_state_from_string(const char *s) _pure_;
+
+const char *unit_dependency_to_string(UnitDependency i) _const_;
+UnitDependency unit_dependency_from_string(const char *s) _pure_;
+
+const char* notify_access_to_string(NotifyAccess i) _const_;
+NotifyAccess notify_access_from_string(const char *s) _pure_;
diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c
index fb30c2527..bd0e3f428 100644
--- a/src/basic/unit-name.c
+++ b/src/basic/unit-name.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <stddef.h>
@@ -24,12 +7,10 @@
#include <string.h>
#include "alloc-util.h"
-#include "bus-label.h"
//#include "glob-util.h"
#include "hexdecoct.h"
-#include "macro.h"
#include "path-util.h"
-#include "string-table.h"
+#include "special.h"
#include "string-util.h"
#include "strv.h"
#include "unit-name.h"
@@ -212,6 +193,7 @@ int unit_name_to_prefix_and_instance(const char *n, char **ret) {
*ret = s;
return 0;
}
+#endif // 0
UnitType unit_name_to_type(const char *n) {
const char *e;
@@ -226,6 +208,7 @@ UnitType unit_name_to_type(const char *n) {
return unit_type_from_string(e + 1);
}
+#if 0 /// UNNEEDED by elogind
int unit_name_change_suffix(const char *n, const char *suffix, char **ret) {
char *e, *s;
size_t a, b;
@@ -257,25 +240,43 @@ int unit_name_change_suffix(const char *n, const char *suffix, char **ret) {
#endif // 0
int unit_name_build(const char *prefix, const char *instance, const char *suffix, char **ret) {
- char *s;
+ UnitType type;
assert(prefix);
assert(suffix);
assert(ret);
+ if (suffix[0] != '.')
+ return -EINVAL;
+
+ type = unit_type_from_string(suffix + 1);
+ if (type < 0)
+ return -EINVAL;
+
+ return unit_name_build_from_type(prefix, instance, type, ret);
+}
+
+int unit_name_build_from_type(const char *prefix, const char *instance, UnitType type, char **ret) {
+ const char *ut;
+ char *s;
+
+ assert(prefix);
+ assert(type >= 0);
+ assert(type < _UNIT_TYPE_MAX);
+ assert(ret);
+
if (!unit_prefix_is_valid(prefix))
return -EINVAL;
if (instance && !unit_instance_is_valid(instance))
return -EINVAL;
- if (!unit_suffix_is_valid(suffix))
- return -EINVAL;
+ ut = unit_type_to_string(type);
if (!instance)
- s = strappend(prefix, suffix);
+ s = strjoin(prefix, ".", ut);
else
- s = strjoin(prefix, "@", instance, suffix);
+ s = strjoin(prefix, "@", instance, ".", ut);
if (!s)
return -ENOMEM;
@@ -308,7 +309,7 @@ static char *do_escape(const char *f, char *t) {
for (; *f; f++) {
if (*f == '/')
*(t++) = '-';
- else if (*f == '-' || *f == '\\' || !strchr(VALID_CHARS, *f))
+ else if (IN_SET(*f, '-', '\\') || !strchr(VALID_CHARS, *f))
t = do_escape_char(*f, t);
else
*(t++) = *f;
@@ -367,8 +368,7 @@ int unit_name_unescape(const char *f, char **ret) {
*t = 0;
- *ret = r;
- r = NULL;
+ *ret = TAKE_PTR(r);
return 0;
}
@@ -383,24 +383,19 @@ int unit_name_path_escape(const char *f, char **ret) {
if (!p)
return -ENOMEM;
- path_kill_slashes(p);
+ path_simplify(p, false);
- if (STR_IN_SET(p, "/", ""))
+ if (empty_or_root(p))
s = strdup("-");
else {
- char *e;
-
- if (!path_is_safe(p))
+ if (!path_is_normalized(p))
return -EINVAL;
/* Truncate trailing slashes */
- e = endswith(p, "/");
- if (e)
- *e = 0;
+ delete_trailing_chars(p, "/");
/* Truncate leading slashes */
- if (p[0] == '/')
- p++;
+ p = skip_leading_chars(p, "/");
s = unit_name_escape(p);
}
@@ -443,7 +438,7 @@ int unit_name_path_unescape(const char *f, char **ret) {
if (!s)
return -ENOMEM;
- if (!path_is_safe(s)) {
+ if (!path_is_normalized(s)) {
free(s);
return -EINVAL;
}
@@ -578,91 +573,32 @@ int unit_name_to_path(const char *name, char **ret) {
return unit_name_path_unescape(prefix, ret);
}
-char *unit_dbus_path_from_name(const char *name) {
- _cleanup_free_ char *e = NULL;
-
- assert(name);
-
- e = bus_label_escape(name);
- if (!e)
- return NULL;
-
- return strappend("/org/freedesktop/systemd1/unit/", e);
-}
-
-int unit_name_from_dbus_path(const char *path, char **name) {
- const char *e;
- char *n;
-
- e = startswith(path, "/org/freedesktop/systemd1/unit/");
- if (!e)
- return -EINVAL;
-
- n = bus_label_unescape(e);
- if (!n)
- return -ENOMEM;
-
- *name = n;
- return 0;
-}
-
-const char* unit_dbus_interface_from_type(UnitType t) {
-
- static const char *const table[_UNIT_TYPE_MAX] = {
- [UNIT_SERVICE] = "org.freedesktop.systemd1.Service",
- [UNIT_SOCKET] = "org.freedesktop.systemd1.Socket",
- [UNIT_BUSNAME] = "org.freedesktop.systemd1.BusName",
- [UNIT_TARGET] = "org.freedesktop.systemd1.Target",
- [UNIT_DEVICE] = "org.freedesktop.systemd1.Device",
- [UNIT_MOUNT] = "org.freedesktop.systemd1.Mount",
- [UNIT_AUTOMOUNT] = "org.freedesktop.systemd1.Automount",
- [UNIT_SWAP] = "org.freedesktop.systemd1.Swap",
- [UNIT_TIMER] = "org.freedesktop.systemd1.Timer",
- [UNIT_PATH] = "org.freedesktop.systemd1.Path",
- [UNIT_SLICE] = "org.freedesktop.systemd1.Slice",
- [UNIT_SCOPE] = "org.freedesktop.systemd1.Scope",
- };
-
- if (t < 0)
- return NULL;
- if (t >= _UNIT_TYPE_MAX)
- return NULL;
-
- return table[t];
-}
-
-const char *unit_dbus_interface_from_name(const char *name) {
- UnitType t;
-
- t = unit_name_to_type(name);
- if (t < 0)
- return NULL;
-
- return unit_dbus_interface_from_type(t);
-}
-
-static char *do_escape_mangle(const char *f, UnitNameMangle allow_globs, char *t) {
+static bool do_escape_mangle(const char *f, bool allow_globs, char *t) {
const char *valid_chars;
+ bool mangled = false;
assert(f);
- assert(IN_SET(allow_globs, UNIT_NAME_GLOB, UNIT_NAME_NOGLOB));
assert(t);
- /* We'll only escape the obvious characters here, to play
- * safe. */
+ /* We'll only escape the obvious characters here, to play safe.
+ *
+ * Returns true if any characters were mangled, false otherwise.
+ */
- valid_chars = allow_globs == UNIT_NAME_GLOB ? VALID_CHARS_GLOB : VALID_CHARS_WITH_AT;
+ valid_chars = allow_globs ? VALID_CHARS_GLOB : VALID_CHARS_WITH_AT;
- for (; *f; f++) {
- if (*f == '/')
+ for (; *f; f++)
+ if (*f == '/') {
*(t++) = '-';
- else if (!strchr(valid_chars, *f))
+ mangled = true;
+ } else if (!strchr(valid_chars, *f)) {
t = do_escape_char(*f, t);
- else
+ mangled = true;
+ } else
*(t++) = *f;
- }
+ *t = 0;
- return t;
+ return mangled;
}
/**
@@ -672,9 +608,10 @@ static char *do_escape_mangle(const char *f, UnitNameMangle allow_globs, char *t
*
* If @allow_globs, globs characters are preserved. Otherwise, they are escaped.
*/
-int unit_name_mangle_with_suffix(const char *name, UnitNameMangle allow_globs, const char *suffix, char **ret) {
- char *s, *t;
+int unit_name_mangle_with_suffix(const char *name, UnitNameMangle flags, const char *suffix, char **ret) {
+ char *s;
int r;
+ bool mangled;
assert(name);
assert(suffix);
@@ -691,7 +628,7 @@ int unit_name_mangle_with_suffix(const char *name, UnitNameMangle allow_globs, c
goto good;
/* Already a fully valid globbing expression? If so, no mangling is necessary either... */
- if (allow_globs == UNIT_NAME_GLOB &&
+ if ((flags & UNIT_NAME_MANGLE_GLOB) &&
string_is_glob(name) &&
in_charset(name, VALID_CHARS_GLOB))
goto good;
@@ -716,13 +653,16 @@ int unit_name_mangle_with_suffix(const char *name, UnitNameMangle allow_globs, c
if (!s)
return -ENOMEM;
- t = do_escape_mangle(name, allow_globs, s);
- *t = 0;
+ mangled = do_escape_mangle(name, flags & UNIT_NAME_MANGLE_GLOB, s);
+ if (mangled)
+ log_full(flags & UNIT_NAME_MANGLE_WARN ? LOG_NOTICE : LOG_DEBUG,
+ "Invalid unit name \"%s\" was escaped as \"%s\" (maybe you should use systemd-escape?)",
+ name, s);
/* Append a suffix if it doesn't have any, but only if this is not a glob, so that we can allow "foo.*" as a
* valid glob. */
- if ((allow_globs != UNIT_NAME_GLOB || !string_is_glob(s)) && unit_name_to_type(s) < 0)
- strcpy(t, suffix);
+ if ((!(flags & UNIT_NAME_MANGLE_GLOB) || !string_is_glob(s)) && unit_name_to_type(s) < 0)
+ strcat(s, suffix);
*ret = s;
return 1;
@@ -746,7 +686,7 @@ int slice_build_parent_slice(const char *slice, char **ret) {
if (!slice_name_is_valid(slice))
return -EINVAL;
- if (streq(slice, "-.slice")) {
+ if (streq(slice, SPECIAL_ROOT_SLICE)) {
*ret = NULL;
return 0;
}
@@ -759,7 +699,7 @@ int slice_build_parent_slice(const char *slice, char **ret) {
if (dash)
strcpy(dash, ".slice");
else {
- r = free_and_strdup(&s, "-.slice");
+ r = free_and_strdup(&s, SPECIAL_ROOT_SLICE);
if (r < 0) {
free(s);
return r;
@@ -771,7 +711,7 @@ int slice_build_parent_slice(const char *slice, char **ret) {
}
#endif // 0
-int slice_build_subslice(const char *slice, const char*name, char **ret) {
+int slice_build_subslice(const char *slice, const char *name, char **ret) {
char *subslice;
assert(slice);
@@ -784,7 +724,7 @@ int slice_build_subslice(const char *slice, const char*name, char **ret) {
if (!unit_prefix_is_valid(name))
return -EINVAL;
- if (streq(slice, "-.slice"))
+ if (streq(slice, SPECIAL_ROOT_SLICE))
subslice = strappend(name, ".slice");
else {
char *e;
@@ -809,7 +749,7 @@ bool slice_name_is_valid(const char *name) {
if (!unit_name_is_valid(name, UNIT_NAME_PLAIN))
return false;
- if (streq(name, "-.slice"))
+ if (streq(name, SPECIAL_ROOT_SLICE))
return true;
e = endswith(name, ".slice");
@@ -839,226 +779,5 @@ bool slice_name_is_valid(const char *name) {
return true;
}
-
-static const char* const unit_type_table[_UNIT_TYPE_MAX] = {
- [UNIT_SERVICE] = "service",
- [UNIT_SOCKET] = "socket",
- [UNIT_BUSNAME] = "busname",
- [UNIT_TARGET] = "target",
- [UNIT_DEVICE] = "device",
- [UNIT_MOUNT] = "mount",
- [UNIT_AUTOMOUNT] = "automount",
- [UNIT_SWAP] = "swap",
- [UNIT_TIMER] = "timer",
- [UNIT_PATH] = "path",
- [UNIT_SLICE] = "slice",
- [UNIT_SCOPE] = "scope",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(unit_type, UnitType);
-
#if 0 /// UNNEEDED by elogind
-static const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = {
- [UNIT_STUB] = "stub",
- [UNIT_LOADED] = "loaded",
- [UNIT_NOT_FOUND] = "not-found",
- [UNIT_ERROR] = "error",
- [UNIT_MERGED] = "merged",
- [UNIT_MASKED] = "masked"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState);
-
-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 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 busname_state_table[_BUSNAME_STATE_MAX] = {
- [BUSNAME_DEAD] = "dead",
- [BUSNAME_MAKING] = "making",
- [BUSNAME_REGISTERED] = "registered",
- [BUSNAME_LISTENING] = "listening",
- [BUSNAME_RUNNING] = "running",
- [BUSNAME_SIGTERM] = "sigterm",
- [BUSNAME_SIGKILL] = "sigkill",
- [BUSNAME_FAILED] = "failed",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState);
-
-static const char* const device_state_table[_DEVICE_STATE_MAX] = {
- [DEVICE_DEAD] = "dead",
- [DEVICE_TENTATIVE] = "tentative",
- [DEVICE_PLUGGED] = "plugged",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState);
-
-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 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 scope_state_table[_SCOPE_STATE_MAX] = {
- [SCOPE_DEAD] = "dead",
- [SCOPE_RUNNING] = "running",
- [SCOPE_ABANDONED] = "abandoned",
- [SCOPE_STOP_SIGTERM] = "stop-sigterm",
- [SCOPE_STOP_SIGKILL] = "stop-sigkill",
- [SCOPE_FAILED] = "failed",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(scope_state, ScopeState);
-
-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_SIGABRT] = "stop-sigabrt",
- [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 slice_state_table[_SLICE_STATE_MAX] = {
- [SLICE_DEAD] = "dead",
- [SLICE_ACTIVE] = "active"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(slice_state, SliceState);
-
-static const char* const socket_state_table[_SOCKET_STATE_MAX] = {
- [SOCKET_DEAD] = "dead",
- [SOCKET_START_PRE] = "start-pre",
- [SOCKET_START_CHOWN] = "start-chown",
- [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 swap_state_table[_SWAP_STATE_MAX] = {
- [SWAP_DEAD] = "dead",
- [SWAP_ACTIVATING] = "activating",
- [SWAP_ACTIVATING_DONE] = "activating-done",
- [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 target_state_table[_TARGET_STATE_MAX] = {
- [TARGET_DEAD] = "dead",
- [TARGET_ACTIVE] = "active"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(target_state, TargetState);
-
-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 unit_dependency_table[_UNIT_DEPENDENCY_MAX] = {
- [UNIT_REQUIRES] = "Requires",
- [UNIT_REQUISITE] = "Requisite",
- [UNIT_WANTS] = "Wants",
- [UNIT_BINDS_TO] = "BindsTo",
- [UNIT_PART_OF] = "PartOf",
- [UNIT_REQUIRED_BY] = "RequiredBy",
- [UNIT_REQUISITE_OF] = "RequisiteOf",
- [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_JOINS_NAMESPACE_OF] = "JoinsNamespaceOf",
- [UNIT_REFERENCES] = "References",
- [UNIT_REFERENCED_BY] = "ReferencedBy",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency);
#endif // 0
-
-static const char* const notify_access_table[_NOTIFY_ACCESS_MAX] = {
- [NOTIFY_NONE] = "none",
- [NOTIFY_MAIN] = "main",
- [NOTIFY_EXEC] = "exec",
- [NOTIFY_ALL] = "all"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(notify_access, NotifyAccess);
diff --git a/src/basic/unit-name.h b/src/basic/unit-name.h
index bba9a4e80..a9a2923fd 100644
--- a/src/basic/unit-name.h
+++ b/src/basic/unit-name.h
@@ -1,273 +1,15 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include "macro.h"
+#include "unit-def.h"
#define UNIT_NAME_MAX 256
-typedef enum UnitType {
- UNIT_SERVICE = 0,
- UNIT_SOCKET,
- UNIT_BUSNAME,
- UNIT_TARGET,
- UNIT_DEVICE,
- UNIT_MOUNT,
- UNIT_AUTOMOUNT,
- UNIT_SWAP,
- UNIT_TIMER,
- UNIT_PATH,
- UNIT_SLICE,
- UNIT_SCOPE,
- _UNIT_TYPE_MAX,
- _UNIT_TYPE_INVALID = -1
-} UnitType;
-
#if 0 /// UNNEEDED by elogind
-typedef enum UnitLoadState {
- UNIT_STUB = 0,
- UNIT_LOADED,
- UNIT_NOT_FOUND,
- UNIT_ERROR,
- UNIT_MERGED,
- UNIT_MASKED,
- _UNIT_LOAD_STATE_MAX,
- _UNIT_LOAD_STATE_INVALID = -1
-} UnitLoadState;
-
-typedef enum UnitActiveState {
- UNIT_ACTIVE,
- UNIT_RELOADING,
- UNIT_INACTIVE,
- UNIT_FAILED,
- UNIT_ACTIVATING,
- UNIT_DEACTIVATING,
- _UNIT_ACTIVE_STATE_MAX,
- _UNIT_ACTIVE_STATE_INVALID = -1
-} UnitActiveState;
-
-typedef enum AutomountState {
- AUTOMOUNT_DEAD,
- AUTOMOUNT_WAITING,
- AUTOMOUNT_RUNNING,
- AUTOMOUNT_FAILED,
- _AUTOMOUNT_STATE_MAX,
- _AUTOMOUNT_STATE_INVALID = -1
-} AutomountState;
-
-typedef enum BusNameState {
- BUSNAME_DEAD,
- BUSNAME_MAKING,
- BUSNAME_REGISTERED,
- BUSNAME_LISTENING,
- BUSNAME_RUNNING,
- BUSNAME_SIGTERM,
- BUSNAME_SIGKILL,
- BUSNAME_FAILED,
- _BUSNAME_STATE_MAX,
- _BUSNAME_STATE_INVALID = -1
-} BusNameState;
-
-/* We simply watch devices, we cannot plug/unplug them. That
- * simplifies the state engine greatly */
-typedef enum DeviceState {
- DEVICE_DEAD,
- DEVICE_TENTATIVE, /* mounted or swapped, but not (yet) announced by udev */
- DEVICE_PLUGGED, /* announced by udev */
- _DEVICE_STATE_MAX,
- _DEVICE_STATE_INVALID = -1
-} DeviceState;
-
-typedef enum MountState {
- MOUNT_DEAD,
- MOUNT_MOUNTING, /* /usr/bin/mount is running, but the mount is not done yet. */
- MOUNT_MOUNTING_DONE, /* /usr/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 PathState {
- PATH_DEAD,
- PATH_WAITING,
- PATH_RUNNING,
- PATH_FAILED,
- _PATH_STATE_MAX,
- _PATH_STATE_INVALID = -1
-} PathState;
-
-typedef enum ScopeState {
- SCOPE_DEAD,
- SCOPE_RUNNING,
- SCOPE_ABANDONED,
- SCOPE_STOP_SIGTERM,
- SCOPE_STOP_SIGKILL,
- SCOPE_FAILED,
- _SCOPE_STATE_MAX,
- _SCOPE_STATE_INVALID = -1
-} ScopeState;
-
-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_SIGABRT, /* Watchdog timeout */
- 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 SliceState {
- SLICE_DEAD,
- SLICE_ACTIVE,
- _SLICE_STATE_MAX,
- _SLICE_STATE_INVALID = -1
-} SliceState;
-
-typedef enum SocketState {
- SOCKET_DEAD,
- SOCKET_START_PRE,
- SOCKET_START_CHOWN,
- 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 SwapState {
- SWAP_DEAD,
- SWAP_ACTIVATING, /* /sbin/swapon is running, but the swap not yet enabled. */
- SWAP_ACTIVATING_DONE, /* /sbin/swapon is running, and the swap is done. */
- 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 TargetState {
- TARGET_DEAD,
- TARGET_ACTIVE,
- _TARGET_STATE_MAX,
- _TARGET_STATE_INVALID = -1
-} TargetState;
-
-typedef enum TimerState {
- TIMER_DEAD,
- TIMER_WAITING,
- TIMER_RUNNING,
- TIMER_ELAPSED,
- TIMER_FAILED,
- _TIMER_STATE_MAX,
- _TIMER_STATE_INVALID = -1
-} TimerState;
-
-typedef enum UnitDependency {
- /* Positive dependencies */
- UNIT_REQUIRES,
- UNIT_REQUISITE,
- UNIT_WANTS,
- UNIT_BINDS_TO,
- UNIT_PART_OF,
-
- /* Inverse of the above */
- UNIT_REQUIRED_BY, /* inverse of 'requires' is 'required_by' */
- UNIT_REQUISITE_OF, /* inverse of 'requisite' is 'requisite_of' */
- 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,
-
- /* Joins namespace of */
- UNIT_JOINS_NAMESPACE_OF,
-
- /* Reference information for GC logic */
- UNIT_REFERENCES, /* Inverse of 'references' is 'referenced_by' */
- UNIT_REFERENCED_BY,
-
- _UNIT_DEPENDENCY_MAX,
- _UNIT_DEPENDENCY_INVALID = -1
-} UnitDependency;
#endif // 0
-
-typedef enum NotifyAccess {
- NOTIFY_NONE,
- NOTIFY_ALL,
- NOTIFY_MAIN,
- NOTIFY_EXEC,
- _NOTIFY_ACCESS_MAX,
- _NOTIFY_ACCESS_INVALID = -1
-} NotifyAccess;
-
typedef enum UnitNameFlags {
UNIT_NAME_PLAIN = 1, /* Allow foo.service */
UNIT_NAME_INSTANCE = 2, /* Allow foo@bar.service */
@@ -289,13 +31,16 @@ static inline int unit_prefix_and_instance_is_valid(const char *p) {
int unit_name_to_prefix(const char *n, char **prefix);
int unit_name_to_instance(const char *n, char **instance);
int unit_name_to_prefix_and_instance(const char *n, char **ret);
+#endif // 0
UnitType unit_name_to_type(const char *n) _pure_;
+#if 0 /// UNNEEDED by elogind
int unit_name_change_suffix(const char *n, const char *suffix, char **ret);
#endif // 0
int unit_name_build(const char *prefix, const char *instance, const char *suffix, char **ret);
+int unit_name_build_from_type(const char *prefix, const char *instance, UnitType, char **ret);
#if 0 /// UNNEEDED by elogind
char *unit_name_escape(const char *f);
@@ -311,77 +56,20 @@ int unit_name_from_path(const char *path, const char *suffix, char **ret);
int unit_name_from_path_instance(const char *prefix, const char *path, const char *suffix, char **ret);
int unit_name_to_path(const char *name, char **ret);
-char *unit_dbus_path_from_name(const char *name);
-int unit_name_from_dbus_path(const char *path, char **name);
-
-const char* unit_dbus_interface_from_type(UnitType t);
-const char *unit_dbus_interface_from_name(const char *name);
-
typedef enum UnitNameMangle {
- UNIT_NAME_NOGLOB,
- UNIT_NAME_GLOB,
+ UNIT_NAME_MANGLE_GLOB = 1,
+ UNIT_NAME_MANGLE_WARN = 2,
} UnitNameMangle;
-int unit_name_mangle_with_suffix(const char *name, UnitNameMangle allow_globs, const char *suffix, char **ret);
+int unit_name_mangle_with_suffix(const char *name, UnitNameMangle flags, const char *suffix, char **ret);
-static inline int unit_name_mangle(const char *name, UnitNameMangle allow_globs, char **ret) {
- return unit_name_mangle_with_suffix(name, allow_globs, ".service", ret);
+static inline int unit_name_mangle(const char *name, UnitNameMangle flags, char **ret) {
+ return unit_name_mangle_with_suffix(name, flags, ".service", ret);
}
int slice_build_parent_slice(const char *slice, char **ret);
#endif // 0
int slice_build_subslice(const char *slice, const char*name, char **subslice);
bool slice_name_is_valid(const char *name);
-
-const char *unit_type_to_string(UnitType i) _const_;
-UnitType unit_type_from_string(const char *s) _pure_;
-
#if 0 /// UNNEEDED by elogind
-const char *unit_load_state_to_string(UnitLoadState i) _const_;
-UnitLoadState unit_load_state_from_string(const char *s) _pure_;
-
-const char *unit_active_state_to_string(UnitActiveState i) _const_;
-UnitActiveState unit_active_state_from_string(const char *s) _pure_;
-
-const char* automount_state_to_string(AutomountState i) _const_;
-AutomountState automount_state_from_string(const char *s) _pure_;
-
-const char* busname_state_to_string(BusNameState i) _const_;
-BusNameState busname_state_from_string(const char *s) _pure_;
-
-const char* device_state_to_string(DeviceState i) _const_;
-DeviceState device_state_from_string(const char *s) _pure_;
-
-const char* mount_state_to_string(MountState i) _const_;
-MountState mount_state_from_string(const char *s) _pure_;
-
-const char* path_state_to_string(PathState i) _const_;
-PathState path_state_from_string(const char *s) _pure_;
-
-const char* scope_state_to_string(ScopeState i) _const_;
-ScopeState scope_state_from_string(const char *s) _pure_;
-
-const char* service_state_to_string(ServiceState i) _const_;
-ServiceState service_state_from_string(const char *s) _pure_;
-
-const char* slice_state_to_string(SliceState i) _const_;
-SliceState slice_state_from_string(const char *s) _pure_;
-
-const char* socket_state_to_string(SocketState i) _const_;
-SocketState socket_state_from_string(const char *s) _pure_;
-
-const char* swap_state_to_string(SwapState i) _const_;
-SwapState swap_state_from_string(const char *s) _pure_;
-
-const char* target_state_to_string(TargetState i) _const_;
-TargetState target_state_from_string(const char *s) _pure_;
-
-const char *timer_state_to_string(TimerState i) _const_;
-TimerState timer_state_from_string(const char *s) _pure_;
-
-const char *unit_dependency_to_string(UnitDependency i) _const_;
-UnitDependency unit_dependency_from_string(const char *s) _pure_;
#endif // 0
-
-const char* notify_access_to_string(NotifyAccess i) _const_;
-NotifyAccess notify_access_from_string(const char *s) _pure_;
diff --git a/src/basic/user-util.c b/src/basic/user-util.c
index 332e1c6a9..7bc5ba7e0 100644
--- a/src/basic/user-util.c
+++ b/src/basic/user-util.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <alloca.h>
#include <errno.h>
@@ -118,15 +101,14 @@ int get_user_creds(
assert(username);
assert(*username);
- /* We enforce some special rules for uid=0: in order to avoid
- * NSS lookups for root we hardcode its data. */
+ /* We enforce some special rules for uid=0 and uid=65534: in order to avoid NSS lookups for root we hardcode
+ * their user record data. */
- if (streq(*username, "root") || streq(*username, "0")) {
+ if (STR_IN_SET(*username, "root", "0")) {
*username = "root";
if (uid)
*uid = 0;
-
if (gid)
*gid = 0;
@@ -139,6 +121,24 @@ int get_user_creds(
return 0;
}
+ if (synthesize_nobody() &&
+ STR_IN_SET(*username, NOBODY_USER_NAME, "65534")) {
+ *username = NOBODY_USER_NAME;
+
+ if (uid)
+ *uid = UID_NOBODY;
+ if (gid)
+ *gid = GID_NOBODY;
+
+ if (home)
+ *home = "/";
+
+ if (shell)
+ *shell = "/sbin/nologin";
+
+ return 0;
+ }
+
if (parse_uid(*username, &u) >= 0) {
errno = 0;
p = getpwuid(u);
@@ -181,6 +181,25 @@ int get_user_creds(
return 0;
}
+static inline bool is_nologin_shell(const char *shell) {
+
+ return PATH_IN_SET(shell,
+ /* 'nologin' is the friendliest way to disable logins for a user account. It prints a nice
+ * message and exits. Different distributions place the binary at different places though,
+ * hence let's list them all. */
+ "/bin/nologin",
+ "/sbin/nologin",
+ "/usr/bin/nologin",
+ "/usr/sbin/nologin",
+ /* 'true' and 'false' work too for the same purpose, but are less friendly as they don't do
+ * any message printing. Different distributions place the binary at various places but at
+ * least not in the 'sbin' directory. */
+ "/bin/false",
+ "/usr/bin/false",
+ "/bin/true",
+ "/usr/bin/true");
+}
+
#if 0 /// UNNEEDED by elogind
int get_user_creds_clean(
const char **username,
@@ -197,15 +216,10 @@ int get_user_creds_clean(
return r;
if (shell &&
- (isempty(*shell) || PATH_IN_SET(*shell,
- "/bin/nologin",
- "/sbin/nologin",
- "/usr/bin/nologin",
- "/usr/sbin/nologin")))
+ (isempty(*shell) || is_nologin_shell(*shell)))
*shell = NULL;
- if (home &&
- (isempty(*home) || path_equal(*home, "/")))
+ if (home && empty_or_root(*home))
*home = NULL;
return 0;
@@ -220,7 +234,7 @@ int get_group_creds(const char **groupname, gid_t *gid) {
/* 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")) {
+ if (STR_IN_SET(*groupname, "root", "0")) {
*groupname = "root";
if (gid)
@@ -229,6 +243,16 @@ int get_group_creds(const char **groupname, gid_t *gid) {
return 0;
}
+ if (synthesize_nobody() &&
+ STR_IN_SET(*groupname, NOBODY_GROUP_NAME, "65534")) {
+ *groupname = NOBODY_GROUP_NAME;
+
+ if (gid)
+ *gid = GID_NOBODY;
+
+ return 0;
+ }
+
if (parse_gid(*groupname, &id) >= 0) {
errno = 0;
g = getgrgid(id);
@@ -261,6 +285,9 @@ char* uid_to_name(uid_t uid) {
/* Shortcut things to avoid NSS lookups */
if (uid == 0)
return strdup("root");
+ if (synthesize_nobody() &&
+ uid == UID_NOBODY)
+ return strdup(NOBODY_USER_NAME);
if (uid_is_valid(uid)) {
long bufsize;
@@ -299,6 +326,9 @@ char* gid_to_name(gid_t gid) {
if (gid == 0)
return strdup("root");
+ if (synthesize_nobody() &&
+ gid == GID_NOBODY)
+ return strdup(NOBODY_GROUP_NAME);
if (gid_is_valid(gid)) {
long bufsize;
@@ -333,8 +363,9 @@ char* gid_to_name(gid_t gid) {
#if 0 /// UNNEEDED by elogind
int in_gid(gid_t gid) {
+ long ngroups_max;
gid_t *gids;
- int ngroups_max, r, i;
+ int r, i;
if (getgid() == gid)
return 1;
@@ -348,7 +379,7 @@ int in_gid(gid_t gid) {
ngroups_max = sysconf(_SC_NGROUPS_MAX);
assert(ngroups_max > 0);
- gids = alloca(sizeof(gid_t) * ngroups_max);
+ gids = newa(gid_t, ngroups_max);
r = getgroups(ngroups_max, gids);
if (r < 0)
@@ -391,7 +422,7 @@ int get_home_dir(char **_h) {
return 0;
}
- /* Hardcode home directory for root to avoid NSS */
+ /* Hardcode home directory for root and nobody to avoid NSS */
u = getuid();
if (u == 0) {
h = strdup("/root");
@@ -401,6 +432,15 @@ int get_home_dir(char **_h) {
*_h = h;
return 0;
}
+ if (synthesize_nobody() &&
+ u == UID_NOBODY) {
+ h = strdup("/");
+ if (!h)
+ return -ENOMEM;
+
+ *_h = h;
+ return 0;
+ }
/* Check the database... */
errno = 0;
@@ -438,7 +478,7 @@ int get_shell(char **_s) {
return 0;
}
- /* Hardcode home directory for root to avoid NSS */
+ /* Hardcode shell for root and nobody to avoid NSS */
u = getuid();
if (u == 0) {
s = strdup("/bin/sh");
@@ -448,6 +488,15 @@ int get_shell(char **_s) {
*_s = s;
return 0;
}
+ if (synthesize_nobody() &&
+ u == UID_NOBODY) {
+ s = strdup("/sbin/nologin");
+ if (!s)
+ return -ENOMEM;
+
+ *_s = s;
+ return 0;
+ }
/* Check the database... */
errno = 0;
@@ -507,18 +556,18 @@ int take_etc_passwd_lock(const char *root) {
* awfully racy, and thus we just won't do them. */
if (root)
- path = prefix_roota(root, "/etc/.pwd.lock");
+ path = prefix_roota(root, ETC_PASSWD_LOCK_PATH);
else
- path = "/etc/.pwd.lock";
+ path = ETC_PASSWD_LOCK_PATH;
fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600);
if (fd < 0)
- return -errno;
+ return log_debug_errno(errno, "Cannot open %s: %m", path);
r = fcntl(fd, F_SETLKW, &flock);
if (r < 0) {
safe_close(fd);
- return -errno;
+ return log_debug_errno(errno, "Locking %s failed: %m", path);
}
return fd;
@@ -551,8 +600,7 @@ bool valid_user_group_name(const char *u) {
if (!(*i >= 'a' && *i <= 'z') &&
!(*i >= 'A' && *i <= 'Z') &&
!(*i >= '0' && *i <= '9') &&
- *i != '_' &&
- *i != '-')
+ !IN_SET(*i, '_', '-'))
return false;
}
@@ -601,6 +649,8 @@ bool valid_gecos(const char *d) {
}
bool valid_home(const char *p) {
+ /* Note that this function is also called by valid_shell(), any
+ * changes must account for that. */
if (isempty(p))
return false;
@@ -614,7 +664,7 @@ bool valid_home(const char *p) {
if (!path_is_absolute(p))
return false;
- if (!path_is_safe(p))
+ if (!path_is_normalized(p))
return false;
/* Colons are used as field separators, and hence not OK */
@@ -652,3 +702,134 @@ int maybe_setgroups(size_t size, const gid_t *list) {
return 0;
}
+
+bool synthesize_nobody(void) {
+
+#ifdef NOLEGACY
+ return true;
+#else
+ /* Returns true when we shall synthesize the "nobody" user (which we do by default). This can be turned off by
+ * touching /etc/systemd/dont-synthesize-nobody in order to provide upgrade compatibility with legacy systems
+ * that used the "nobody" user name and group name for other UIDs/GIDs than 65534.
+ *
+ * Note that we do not employ any kind of synchronization on the following caching variable. If the variable is
+ * accessed in multi-threaded programs in the worst case it might happen that we initialize twice, but that
+ * shouldn't matter as each initialization should come to the same result. */
+ static int cache = -1;
+
+ if (cache < 0)
+ cache = access("/etc/elogind/dont-synthesize-nobody", F_OK) < 0;
+
+ return cache;
+#endif
+}
+
+#if 0 /// UNNEEDED by elogind
+int putpwent_sane(const struct passwd *pw, FILE *stream) {
+ assert(pw);
+ assert(stream);
+
+ errno = 0;
+ if (putpwent(pw, stream) != 0)
+ return errno > 0 ? -errno : -EIO;
+
+ return 0;
+}
+
+int putspent_sane(const struct spwd *sp, FILE *stream) {
+ assert(sp);
+ assert(stream);
+
+ errno = 0;
+ if (putspent(sp, stream) != 0)
+ return errno > 0 ? -errno : -EIO;
+
+ return 0;
+}
+
+int putgrent_sane(const struct group *gr, FILE *stream) {
+ assert(gr);
+ assert(stream);
+
+ errno = 0;
+ if (putgrent(gr, stream) != 0)
+ return errno > 0 ? -errno : -EIO;
+
+ return 0;
+}
+
+#if ENABLE_GSHADOW
+int putsgent_sane(const struct sgrp *sg, FILE *stream) {
+ assert(sg);
+ assert(stream);
+
+ errno = 0;
+ if (putsgent(sg, stream) != 0)
+ return errno > 0 ? -errno : -EIO;
+
+ return 0;
+}
+#endif
+
+int fgetpwent_sane(FILE *stream, struct passwd **pw) {
+ struct passwd *p;
+
+ assert(pw);
+ assert(stream);
+
+ errno = 0;
+ p = fgetpwent(stream);
+ if (!p && errno != ENOENT)
+ return errno > 0 ? -errno : -EIO;
+
+ *pw = p;
+ return !!p;
+}
+
+int fgetspent_sane(FILE *stream, struct spwd **sp) {
+ struct spwd *s;
+
+ assert(sp);
+ assert(stream);
+
+ errno = 0;
+ s = fgetspent(stream);
+ if (!s && errno != ENOENT)
+ return errno > 0 ? -errno : -EIO;
+
+ *sp = s;
+ return !!s;
+}
+
+int fgetgrent_sane(FILE *stream, struct group **gr) {
+ struct group *g;
+
+ assert(gr);
+ assert(stream);
+
+ errno = 0;
+ g = fgetgrent(stream);
+ if (!g && errno != ENOENT)
+ return errno > 0 ? -errno : -EIO;
+
+ *gr = g;
+ return !!g;
+}
+
+#if ENABLE_GSHADOW
+int fgetsgent_sane(FILE *stream, struct sgrp **sg) {
+ struct sgrp *s;
+
+ assert(sg);
+ assert(stream);
+
+ errno = 0;
+ s = fgetsgent(stream);
+ if (!s && errno != ENOENT)
+ return errno > 0 ? -errno : -EIO;
+
+ *sg = s;
+ return !!s;
+}
+#endif
+#endif // 0
diff --git a/src/basic/user-util.h b/src/basic/user-util.h
index 4a1bc764a..14a4d180c 100644
--- a/src/basic/user-util.h
+++ b/src/basic/user-util.h
@@ -1,24 +1,10 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 <grp.h>
+//#include <gshadow.h>
+//#include <pwd.h>
+//#include <shadow.h>
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
@@ -67,17 +53,29 @@ int take_etc_passwd_lock(const char *root);
#define UID_INVALID ((uid_t) -1)
#define GID_INVALID ((gid_t) -1)
-/* Let's pick a UIDs within the 16bit range, so that we are compatible with containers using 16bit
- * user namespacing. At least on Fedora normal users are allocated until UID 60000, hence do not
- * allocate from below this. Also stay away from the upper end of the range as that is often used
- * for overflow/nobody users. */
-#define DYNAMIC_UID_MIN ((uid_t) UINT32_C(0x0000EF00))
-#define DYNAMIC_UID_MAX ((uid_t) UINT32_C(0x0000FFEF))
+#define UID_NOBODY ((uid_t) 65534U)
+#define GID_NOBODY ((gid_t) 65534U)
+#define ETC_PASSWD_LOCK_PATH "/etc/.pwd.lock"
+
+#if 0 /// UNNEEDED by elogind
static inline bool uid_is_dynamic(uid_t uid) {
return DYNAMIC_UID_MIN <= uid && uid <= DYNAMIC_UID_MAX;
}
+static inline bool gid_is_dynamic(gid_t gid) {
+ return uid_is_dynamic((uid_t) gid);
+}
+#endif // 0
+
+static inline bool uid_is_system(uid_t uid) {
+ return uid <= SYSTEM_UID_MAX;
+}
+
+static inline bool gid_is_system(gid_t gid) {
+ return gid <= SYSTEM_GID_MAX;
+}
+
/* The following macros add 1 when converting things, since UID 0 is a valid UID, while the pointer
* NULL is special */
#define PTR_TO_UID(p) ((uid_t) (((uintptr_t) (p))-1))
@@ -95,4 +93,28 @@ bool valid_user_group_name_or_id(const char *u);
bool valid_gecos(const char *d);
bool valid_home(const char *p);
+static inline bool valid_shell(const char *p) {
+ /* We have the same requirements, so just piggy-back on the home check.
+ *
+ * Let's ignore /etc/shells because this is only applicable to real and
+ * not system users. It is also incompatible with the idea of empty /etc.
+ */
+ return valid_home(p);
+}
+
int maybe_setgroups(size_t size, const gid_t *list);
+
+bool synthesize_nobody(void);
+
+#if 0 /// UNNEEDED by elogind
+int fgetpwent_sane(FILE *stream, struct passwd **pw);
+int fgetspent_sane(FILE *stream, struct spwd **sp);
+int fgetgrent_sane(FILE *stream, struct group **gr);
+int putpwent_sane(const struct passwd *pw, FILE *stream);
+int putspent_sane(const struct spwd *sp, FILE *stream);
+int putgrent_sane(const struct group *gr, FILE *stream);
+#ifdef ENABLE_GSHADOW
+int fgetsgent_sane(FILE *stream, struct sgrp **sg);
+int putsgent_sane(const struct sgrp *sg, FILE *stream);
+#endif
+#endif // 0
diff --git a/src/basic/utf8.c b/src/basic/utf8.c
index 6eae2b983..a5ce1a294 100644
--- a/src/basic/utf8.c
+++ b/src/basic/utf8.c
@@ -1,22 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2008-2011 Kay Sievers
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
/* Parts of this file are based on the GLIB utf8 validation functions. The
* original license text follows. */
@@ -47,6 +29,7 @@
#include <string.h>
#include "alloc-util.h"
+#include "gunicode.h"
#include "hexdecoct.h"
#include "macro.h"
#include "utf8.h"
@@ -73,7 +56,7 @@ static bool unichar_is_control(char32_t ch) {
'\t' is in C0 range, but more or less harmless and commonly used.
*/
- return (ch < ' ' && ch != '\t' && ch != '\n') ||
+ return (ch < ' ' && !IN_SET(ch, '\t', '\n')) ||
(0x7F <= ch && ch <= 0x9F);
}
@@ -258,6 +241,9 @@ char *utf8_escape_non_printable(const char *str) {
char *ascii_is_valid(const char *str) {
const char *p;
+ /* Check whether the string consists of valid ASCII bytes,
+ * i.e values between 0 and 127, inclusive. */
+
assert(str);
for (p = str; *p; p++)
@@ -267,6 +253,21 @@ char *ascii_is_valid(const char *str) {
return (char*) str;
}
+char *ascii_is_valid_n(const char *str, size_t len) {
+ size_t i;
+
+ /* Very similar to ascii_is_valid(), but checks exactly len
+ * bytes and rejects any NULs in that range. */
+
+ assert(str);
+
+ for (i = 0; i < len; i++)
+ if ((unsigned char) str[i] >= 128 || str[i] == 0)
+ return NULL;
+
+ return (char*) str;
+}
+
/**
* utf8_encode_unichar() - Encode single UCS-4 character as UTF-8
* @out_utf8: output buffer of at least 4 bytes or NULL
@@ -407,3 +408,42 @@ int utf8_encoded_valid_unichar(const char *str) {
return len;
}
+
+size_t utf8_n_codepoints(const char *str) {
+ size_t n = 0;
+
+ /* Returns the number of UTF-8 codepoints in this string, or (size_t) -1 if the string is not valid UTF-8. */
+
+ while (*str != 0) {
+ int k;
+
+ k = utf8_encoded_valid_unichar(str);
+ if (k < 0)
+ return (size_t) -1;
+
+ str += k;
+ n++;
+ }
+
+ return n;
+}
+
+size_t utf8_console_width(const char *str) {
+ size_t n = 0;
+
+ /* Returns the approximate width a string will take on screen when printed on a character cell
+ * terminal/console. */
+
+ while (*str != 0) {
+ char32_t c;
+
+ if (utf8_encoded_to_unichar(str, &c) < 0)
+ return (size_t) -1;
+
+ str = utf8_next_char(str);
+
+ n += unichar_iswide(c) ? 2 : 1;
+ }
+
+ return n;
+}
diff --git a/src/basic/utf8.h b/src/basic/utf8.h
index f9b9c9468..e8af7a576 100644
--- a/src/basic/utf8.h
+++ b/src/basic/utf8.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 <stddef.h>
#include <stdint.h>
@@ -34,6 +16,7 @@ bool unichar_is_valid(char32_t c);
const char *utf8_is_valid(const char *s) _pure_;
char *ascii_is_valid(const char *s) _pure_;
+char *ascii_is_valid_n(const char *str, size_t len);
bool utf8_is_printable_newline(const char* str, size_t length, bool newline) _pure_;
#define utf8_is_printable(str, length) utf8_is_printable_newline(str, length, true)
@@ -58,3 +41,6 @@ static inline bool utf16_is_trailing_surrogate(char16_t c) {
static inline char32_t utf16_surrogate_pair_to_unichar(char16_t lead, char16_t trail) {
return ((lead - 0xd800) << 10) + (trail - 0xdc00) + 0x10000;
}
+
+size_t utf8_n_codepoints(const char *str);
+size_t utf8_console_width(const char *str);
diff --git a/src/basic/util.c b/src/basic/util.c
index cd7f0e42d..d2ebb4516 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -1,24 +1,6 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <alloca.h>
-//#include <dirent.h>
//#include <errno.h>
//#include <fcntl.h>
#include <sched.h>
@@ -35,13 +17,15 @@
//#include <unistd.h>
#include "alloc-util.h"
+//#include "btrfs-util.h"
#include "build.h"
#include "cgroup-util.h"
//#include "def.h"
+//#include "device-nodes.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "fileio.h"
-//#include "formats-util.h"
+//#include "format-util.h"
#include "hashmap.h"
#include "hostname-util.h"
//#include "log.h"
@@ -50,6 +34,7 @@
#include "parse-util.h"
//#include "path-util.h"
#include "process-util.h"
+#include "procfs-util.h"
#include "set.h"
#include "signal-util.h"
#include "stat-util.h"
@@ -59,6 +44,7 @@
#include "umask-util.h"
#include "user-util.h"
#include "util.h"
+//#include "virt.h"
int saved_argc = 0;
char **saved_argv = NULL;
@@ -105,7 +91,7 @@ int socket_from_display(const char *display, char **path) {
k = strspn(display+1, "0123456789");
- f = new(char, strlen("/tmp/.X11-unix/X") + k + 1);
+ f = new(char, STRLEN("/tmp/.X11-unix/X") + k + 1);
if (!f)
return -ENOMEM;
@@ -119,76 +105,13 @@ int socket_from_display(const char *display, char **path) {
}
#if 0 /// UNNEEDED by elogind
-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;
- }
+bool kexec_loaded(void) {
+ _cleanup_free_ char *s = NULL;
- return -ENOENT;
-}
+ if (read_one_line_file("/sys/kernel/kexec_loaded", &s) < 0)
+ return false;
-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;
+ return s[0] == '1';
}
int prot_from_flags(int flags) {
@@ -210,112 +133,6 @@ int prot_from_flags(int flags) {
}
#endif // 0
-int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
- bool stdout_is_tty, stderr_is_tty;
- pid_t parent_pid, agent_pid;
- sigset_t ss, saved_ss;
- unsigned n, i;
- va_list ap;
- char **l;
-
- assert(pid);
- assert(path);
-
- /* Spawns a temporary TTY agent, making sure it goes away when
- * we go away */
-
- parent_pid = getpid();
-
- /* First we temporarily block all signals, so that the new
- * child has them blocked initially. This way, we can be sure
- * that SIGTERMs are not lost we might send to the agent. */
- assert_se(sigfillset(&ss) >= 0);
- assert_se(sigprocmask(SIG_SETMASK, &ss, &saved_ss) >= 0);
-
- agent_pid = fork();
- if (agent_pid < 0) {
- assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
- return -errno;
- }
-
- if (agent_pid != 0) {
- assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 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);
-
- /* Make sure we actually can kill the agent, if we need to, in
- * case somebody invoked us from a shell script that trapped
- * SIGTERM or so... */
- (void) reset_all_signal_handlers();
- (void) reset_signal_mask();
-
- /* Check whether our parent died before we were able
- * to set the death signal and unblock the signals */
- 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) {
- int fd;
-
- /* 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_errno(errno, "Failed to open /dev/tty: %m");
- _exit(EXIT_FAILURE);
- }
-
- if (!stdout_is_tty && dup2(fd, STDOUT_FILENO) < 0) {
- log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
- _exit(EXIT_FAILURE);
- }
-
- if (!stderr_is_tty && dup2(fd, STDERR_FILENO) < 0) {
- log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
- _exit(EXIT_FAILURE);
- }
-
- if (fd > STDERR_FILENO)
- 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);
-}
-
bool in_initrd(void) {
struct statfs s;
@@ -339,11 +156,11 @@ bool in_initrd(void) {
return saved_in_initrd;
}
+#if 0 /// UNNEEDED by elogind
void in_initrd_force(bool value) {
saved_in_initrd = value;
}
-#if 0 /// UNNEEDED by elogind
/* 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) {
@@ -351,11 +168,13 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
const void *p;
int comparison;
+ assert(!size_multiply_overflow(nmemb, size));
+
l = 0;
u = nmemb;
while (l < u) {
idx = (l + u) / 2;
- p = (const char *) base + idx * size;
+ p = (const uint8_t*) base + idx * size;
comparison = compar(key, p, arg);
if (comparison < 0)
u = idx;
@@ -366,6 +185,7 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
}
return NULL;
}
+#endif // 0
int on_ac_power(void) {
bool found_offline = false, found_online = false;
@@ -383,7 +203,7 @@ int on_ac_power(void) {
device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (device < 0) {
- if (errno == ENOENT || errno == ENOTDIR)
+ if (IN_SET(errno, ENOENT, ENOTDIR))
continue;
return -errno;
@@ -432,7 +252,6 @@ int on_ac_power(void) {
return found_online || !found_offline;
}
-#endif // 0
int container_get_leader(const char *machine, pid_t *pid) {
_cleanup_free_ char *s = NULL, *class = NULL;
const char *p;
@@ -446,7 +265,7 @@ int container_get_leader(const char *machine, pid_t *pid) {
return -EINVAL;
p = strjoina("/run/systemd/machines/", machine);
- r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
if (r == -ENOENT)
return -EHOSTDOWN;
if (r < 0)
@@ -587,6 +406,7 @@ uint64_t physical_memory(void) {
uint64_t mem, lim;
size_t ps;
long sc;
+ int r;
/* We return this as uint64_t in case we are running as 32bit process on a 64bit kernel with huge amounts of
* memory.
@@ -600,13 +420,40 @@ uint64_t physical_memory(void) {
ps = page_size();
mem = (uint64_t) sc * (uint64_t) ps;
- if (cg_get_root_path(&root) < 0)
+ r = cg_get_root_path(&root);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to determine root cgroup, ignoring cgroup memory limit: %m");
return mem;
+ }
- if (cg_get_attribute("memory", root, "memory.limit_in_bytes", &value))
+ r = cg_all_unified();
+ if (r < 0) {
+ log_debug_errno(r, "Failed to determine root unified mode, ignoring cgroup memory limit: %m");
return mem;
+ }
+ if (r > 0) {
+ r = cg_get_attribute("memory", root, "memory.max", &value);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to read memory.max cgroup attribute, ignoring cgroup memory limit: %m");
+ return mem;
+ }
- if (safe_atou64(value, &lim) < 0)
+ if (streq(value, "max"))
+ return mem;
+ } else {
+ r = cg_get_attribute("memory", root, "memory.limit_in_bytes", &value);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to read memory.limit_in_bytes cgroup attribute, ignoring cgroup memory limit: %m");
+ return mem;
+ }
+ }
+
+ r = safe_atou64(value, &lim);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to parse cgroup memory limit '%s', ignoring: %m", value);
+ return mem;
+ }
+ if (lim == UINT64_MAX)
return mem;
/* Make sure the limit is a multiple of our own page size */
@@ -645,34 +492,37 @@ uint64_t physical_memory_scale(uint64_t v, uint64_t max) {
uint64_t system_tasks_max(void) {
-#if SIZEOF_PID_T == 4
-#define TASKS_MAX ((uint64_t) (INT32_MAX-1))
-#elif SIZEOF_PID_T == 2
-#define TASKS_MAX ((uint64_t) (INT16_MAX-1))
-#else
-#error "Unknown pid_t size"
-#endif
-
- _cleanup_free_ char *value = NULL, *root = NULL;
uint64_t a = TASKS_MAX, b = TASKS_MAX;
+ _cleanup_free_ char *root = NULL;
+ int r;
/* Determine the maximum number of tasks that may run on this system. We check three sources to determine this
* limit:
*
- * a) the maximum value for the pid_t type
+ * a) the maximum tasks value the kernel allows on this architecture
* b) the cgroups pids_max attribute for the system
- * c) the kernel's configure maximum PID value
+ * c) the kernel's configured maximum PID value
*
* And then pick the smallest of the three */
- if (read_one_line_file("/proc/sys/kernel/pid_max", &value) >= 0)
- (void) safe_atou64(value, &a);
+ r = procfs_tasks_get_limit(&a);
+ if (r < 0)
+ log_debug_errno(r, "Failed to read maximum number of tasks from /proc, ignoring: %m");
- if (cg_get_root_path(&root) >= 0) {
- value = mfree(value);
+ r = cg_get_root_path(&root);
+ if (r < 0)
+ log_debug_errno(r, "Failed to determine cgroup root path, ignoring: %m");
+ else {
+ _cleanup_free_ char *value = NULL;
- if (cg_get_attribute("pids", root, "pids.max", &value) >= 0)
- (void) safe_atou64(value, &b);
+ r = cg_get_attribute("pids", root, "pids.max", &value);
+ if (r < 0)
+ log_debug_errno(r, "Failed to read pids.max attribute of cgroup root, ignoring: %m");
+ else if (!streq(value, "max")) {
+ r = safe_atou64(value, &b);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse pids.max attribute of cgroup root, ignoring: %m");
+ }
}
return MIN3(TASKS_MAX,
@@ -698,33 +548,84 @@ uint64_t system_tasks_max_scale(uint64_t v, uint64_t max) {
return m / max;
}
+int version(void) {
+ puts(PACKAGE_STRING "\n"
+ SYSTEMD_FEATURES);
+ return 0;
+}
+
#if 0 /// UNNEEDED by elogind
-int update_reboot_parameter_and_warn(const char *param) {
- int r;
+/* This is a direct translation of str_verscmp from boot.c */
+static bool is_digit(int c) {
+ return c >= '0' && c <= '9';
+}
- if (isempty(param)) {
- if (unlink("/run/systemd/reboot-param") < 0) {
- if (errno == ENOENT)
- return 0;
+static int c_order(int c) {
+ if (c == 0 || is_digit(c))
+ return 0;
+
+ if ((c >= 'a') && (c <= 'z'))
+ return c;
+
+ return c + 0x10000;
+}
- return log_warning_errno(errno, "Failed to unlink reboot parameter file: %m");
+int str_verscmp(const char *s1, const char *s2) {
+ const char *os1, *os2;
+
+ assert(s1);
+ assert(s2);
+
+ os1 = s1;
+ os2 = s2;
+
+ while (*s1 || *s2) {
+ int first;
+
+ while ((*s1 && !is_digit(*s1)) || (*s2 && !is_digit(*s2))) {
+ int order;
+
+ order = c_order(*s1) - c_order(*s2);
+ if (order != 0)
+ return order;
+ s1++;
+ s2++;
}
- return 0;
- }
+ while (*s1 == '0')
+ s1++;
+ while (*s2 == '0')
+ s2++;
+
+ first = 0;
+ while (is_digit(*s1) && is_digit(*s2)) {
+ if (first == 0)
+ first = *s1 - *s2;
+ s1++;
+ s2++;
+ }
- RUN_WITH_UMASK(0022) {
- r = write_string_file("/run/systemd/reboot-param", param, WRITE_STRING_FILE_CREATE);
- if (r < 0)
- return log_warning_errno(r, "Failed to write reboot parameter file: %m");
+ if (is_digit(*s1))
+ return 1;
+ if (is_digit(*s2))
+ return -1;
+
+ if (first != 0)
+ return first;
}
- return 0;
+ return strcmp(os1, os2);
}
-#endif // 0
-int version(void) {
- puts(PACKAGE_STRING "\n"
- SYSTEMD_FEATURES);
- return 0;
+/* Turn off core dumps but only if we're running outside of a container. */
+void disable_coredumps(void) {
+ int r;
+
+ if (detect_container() > 0)
+ return;
+
+ r = write_string_file("/proc/sys/kernel/core_pattern", "|/bin/false", 0);
+ if (r < 0)
+ log_debug_errno(r, "Failed to turn off coredumps, ignoring: %m");
}
+#endif // 0
diff --git a/src/basic/util.h b/src/basic/util.h
index a2a01f886..ff21a99b9 100644
--- a/src/basic/util.h
+++ b/src/basic/util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <alloca.h>
#include <errno.h>
#include <fcntl.h>
@@ -73,9 +55,7 @@ bool display_is_local(const char *display) _pure_;
int socket_from_display(const char *display, char **path);
#if 0 /// UNNEEDED by elogind
-int block_get_whole_disk(dev_t d, dev_t *ret);
#endif // 0
-
#define NULSTR_FOREACH(i, l) \
for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
@@ -91,18 +71,29 @@ bool kexec_loaded(void);
int prot_from_flags(int flags) _const_;
#endif // 0
-int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...);
-
bool in_initrd(void);
+#if 0 /// UNNEEDED by elogind
void in_initrd_force(bool value);
-#if 0 /// UNNEEDED by elogind
void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
int (*compar) (const void *, const void *, void *),
void *arg);
#endif // 0
/**
+ * Normal bsearch requires base to be nonnull. Here were require
+ * that only if nmemb > 0.
+ */
+static inline void* bsearch_safe(const void *key, const void *base,
+ size_t nmemb, size_t size, comparison_fn_t compar) {
+ if (nmemb <= 0)
+ return NULL;
+
+ assert(base);
+ return bsearch(key, base, nmemb, size, compar);
+}
+
+/**
* Normal qsort requires base to be nonnull. Here were require
* that only if nmemb > 0.
*/
@@ -114,6 +105,22 @@ static inline void qsort_safe(void *base, size_t nmemb, size_t size, comparison_
qsort(base, nmemb, size, compar);
}
+/* A wrapper around the above, but that adds typesafety: the element size is automatically derived from the type and so
+ * is the prototype for the comparison function */
+#define typesafe_qsort(p, n, func) \
+ ({ \
+ int (*_func_)(const typeof(p[0])*, const typeof(p[0])*) = func; \
+ qsort_safe((p), (n), sizeof((p)[0]), (__compar_fn_t) _func_); \
+ })
+
+static inline void qsort_r_safe(void *base, size_t nmemb, size_t size, int (*compar)(const void*, const void*, void*), void *userdata) {
+ if (nmemb <= 1)
+ return;
+
+ assert(base);
+ qsort_r(base, nmemb, size, compar, userdata);
+}
+
/**
* Normal memcpy requires src to be nonnull. We do nothing if n is 0.
*/
@@ -124,9 +131,7 @@ static inline void memcpy_safe(void *dst, const void *src, size_t n) {
memcpy(dst, src, n);
}
-#if 0 /// UNNEEDED by elogind
int on_ac_power(void);
-#endif // 0
#define memzero(x,l) (memset((x), 0, (l)))
#define zero(x) (memzero(&(x), sizeof(x)))
@@ -188,8 +193,6 @@ static inline unsigned log2u_round_up(unsigned x) {
return log2u(x - 1) + 1;
}
-#if 0 /// UNNEEDED by elogind
-#endif // 0
int container_get_leader(const char *machine, pid_t *pid);
int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd);
@@ -201,8 +204,10 @@ uint64_t physical_memory_scale(uint64_t v, uint64_t max);
uint64_t system_tasks_max(void);
uint64_t system_tasks_max_scale(uint64_t v, uint64_t max);
+int version(void);
+
#if 0 /// UNNEEDED by elogind
-#endif // 0
-int update_reboot_parameter_and_warn(const char *param);
+int str_verscmp(const char *s1, const char *s2);
-int version(void);
+void disable_coredumps(void);
+#endif // 0
diff --git a/src/basic/verbs.c b/src/basic/verbs.c
index d9cdb38d6..d9e9ec26a 100644
--- a/src/basic/verbs.c
+++ b/src/basic/verbs.c
@@ -1,38 +1,56 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <getopt.h>
#include <stdbool.h>
#include <stddef.h>
+//#include <string.h>
+#include "env-util.h"
#include "log.h"
#include "macro.h"
+#include "process-util.h"
#include "string-util.h"
#include "verbs.h"
#include "virt.h"
+/* Wraps running_in_chroot() which is used in various places, but also adds an environment variable check so external
+ * processes can reliably force this on.
+ */
+bool running_in_chroot_or_offline(void) {
+ int r;
+
+ /* Added to support use cases like rpm-ostree, where from %post scripts we only want to execute "preset", but
+ * not "start"/"restart" for example.
+ *
+ * See doc/ENVIRONMENT.md for docs.
+ */
+ r = getenv_bool("SYSTEMD_OFFLINE");
+ if (r < 0 && r != -ENXIO)
+ log_debug_errno(r, "Failed to parse $SYSTEMD_OFFLINE: %m");
+ else if (r >= 0)
+ return r > 0;
+
+ /* We've had this condition check for a long time which basically checks for legacy chroot case like Fedora's
+ * "mock", which is used for package builds. We don't want to try to start systemd services there, since
+ * without --new-chroot we don't even have systemd running, and even if we did, adding a concept of background
+ * daemons to builds would be an enormous change, requiring considering things like how the journal output is
+ * handled, etc. And there's really not a use case today for a build talking to a service.
+ *
+ * Note this call itself also looks for a different variable SYSTEMD_IGNORE_CHROOT=1.
+ */
+ r = running_in_chroot();
+ if (r < 0)
+ log_debug_errno(r, "running_in_chroot(): %m");
+
+ return r > 0;
+}
+
int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata) {
const Verb *verb;
const char *name;
unsigned i;
- int left;
+ int left, r;
assert(verbs);
assert(verbs[0].dispatch);
@@ -58,7 +76,7 @@ int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata) {
if (name)
found = streq(name, verbs[i].verb);
else
- found = !!(verbs[i].flags & VERB_DEFAULT);
+ found = verbs[i].flags & VERB_DEFAULT;
if (found) {
verb = &verbs[i];
@@ -83,11 +101,20 @@ int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata) {
return -EINVAL;
}
- if ((verb->flags & VERB_NOCHROOT) && running_in_chroot() > 0) {
- log_info("Running in chroot, ignoring request.");
+ if ((verb->flags & VERB_ONLINE_ONLY) && running_in_chroot_or_offline()) {
+ if (name)
+ log_info("Running in chroot, ignoring request: %s", name);
+ else
+ log_info("Running in chroot, ignoring request.");
return 0;
}
+ if (verb->flags & VERB_MUST_BE_ROOT) {
+ r = must_be_root();
+ if (r < 0)
+ return r;
+ }
+
if (name)
return verb->dispatch(left, argv + optind, userdata);
else {
diff --git a/src/basic/verbs.h b/src/basic/verbs.h
index 7b5e18510..e174255a7 100644
--- a/src/basic/verbs.h
+++ b/src/basic/verbs.h
@@ -1,33 +1,21 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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 VERB_ANY ((unsigned) -1)
-#define VERB_DEFAULT 1U
-#define VERB_NOCHROOT 2U
+
+typedef enum VerbFlags {
+ VERB_DEFAULT = 1 << 0,
+ VERB_ONLINE_ONLY = 1 << 1,
+ VERB_MUST_BE_ROOT = 1 << 2,
+} VerbFlags;
typedef struct {
const char *verb;
unsigned min_args, max_args;
- unsigned flags;
+ VerbFlags flags;
int (* const dispatch)(int argc, char *argv[], void *userdata);
} Verb;
+bool running_in_chroot_or_offline(void);
+
int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata);
diff --git a/src/basic/virt.c b/src/basic/virt.c
index 0060bb846..ac42947a4 100644
--- a/src/basic/virt.c
+++ b/src/basic/virt.c
@@ -1,22 +1,8 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#if defined(__i386__) || defined(__x86_64__)
+//#include <cpuid.h>
+#endif
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
@@ -25,6 +11,7 @@
#include "alloc-util.h"
#include "dirent-util.h"
+#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "macro.h"
@@ -46,40 +33,26 @@ static int detect_vm_cpuid(void) {
} cpuid_vendor_table[] = {
{ "XenVMMXenVMM", VIRTUALIZATION_XEN },
{ "KVMKVMKVM", VIRTUALIZATION_KVM },
+ { "TCGTCGTCGTCG", VIRTUALIZATION_QEMU },
/* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
{ "VMwareVMware", VIRTUALIZATION_VMWARE },
/* https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs */
{ "Microsoft Hv", VIRTUALIZATION_MICROSOFT },
/* https://wiki.freebsd.org/bhyve */
{ "bhyve bhyve ", VIRTUALIZATION_BHYVE },
+ { "QNXQVMBSQG", VIRTUALIZATION_QNX },
};
- uint32_t eax, ecx;
+ uint32_t eax, ebx, ecx, edx;
bool hypervisor;
/* http://lwn.net/Articles/301888/ */
-#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)
- );
+ if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) == 0)
+ return VIRTUALIZATION_NONE;
- hypervisor = !!(ecx & 0x80000000U);
+ hypervisor = ecx & 0x80000000U;
if (hypervisor) {
union {
@@ -89,17 +62,11 @@ static int detect_vm_cpuid(void) {
unsigned j;
/* 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)
- );
+ __cpuid(0x40000000U, eax, ebx, ecx, edx);
+
+ sig.sig32[0] = ebx;
+ sig.sig32[1] = ecx;
+ sig.sig32[2] = edx;
log_debug("Virtualization found, CPUID=%s", sig.text);
@@ -199,8 +166,6 @@ static int detect_vm_dmi(void) {
return r;
}
-
-
for (j = 0; j < ELEMENTSOF(dmi_vendor_table); j++)
if (startswith(s, dmi_vendor_table[j].vendor)) {
log_debug("Virtualization %s found in DMI (%s)", s, dmi_vendors[i]);
@@ -215,27 +180,50 @@ static int detect_vm_dmi(void) {
}
static int detect_vm_xen(void) {
+
/* Check for Dom0 will be executed later in detect_vm_xen_dom0
- Thats why we dont check the content of /proc/xen/capabilities here. */
- if (access("/proc/xen/capabilities", F_OK) < 0) {
- log_debug("Virtualization XEN not found, /proc/xen/capabilities does not exist");
+ The presence of /proc/xen indicates some form of a Xen domain */
+ if (access("/proc/xen", F_OK) < 0) {
+ log_debug("Virtualization XEN not found, /proc/xen does not exist");
return VIRTUALIZATION_NONE;
}
- log_debug("Virtualization XEN found (/proc/xen/capabilities exists)");
- return VIRTUALIZATION_XEN;
-
+ log_debug("Virtualization XEN found (/proc/xen exists)");
+ return VIRTUALIZATION_XEN;
}
-static bool detect_vm_xen_dom0(void) {
+#define XENFEAT_dom0 11 /* xen/include/public/features.h */
+#define PATH_FEATURES "/sys/hypervisor/properties/features"
+/* Returns -errno, or 0 for domU, or 1 for dom0 */
+static int detect_vm_xen_dom0(void) {
_cleanup_free_ char *domcap = NULL;
char *cap, *i;
int r;
+ r = read_one_line_file(PATH_FEATURES, &domcap);
+ if (r < 0 && r != -ENOENT)
+ return r;
+ if (r == 0) {
+ unsigned long features;
+
+ /* Here, we need to use sscanf() instead of safe_atoul()
+ * as the string lacks the leading "0x". */
+ r = sscanf(domcap, "%lx", &features);
+ if (r == 1) {
+ r = !!(features & (1U << XENFEAT_dom0));
+ log_debug("Virtualization XEN, found %s with value %08lx, "
+ "XENFEAT_dom0 (indicating the 'hardware domain') is%s set.",
+ PATH_FEATURES, features, r ? "" : " not");
+ return r;
+ }
+ log_debug("Virtualization XEN, found %s, unhandled content '%s'",
+ PATH_FEATURES, domcap);
+ }
+
r = read_one_line_file("/proc/xen/capabilities", &domcap);
if (r == -ENOENT) {
- log_debug("Virtualization XEN not found, /proc/xen/capabilities does not exist");
- return false;
+ log_debug("Virtualization XEN because /proc/xen/capabilities does not exist");
+ return 0;
}
if (r < 0)
return r;
@@ -246,11 +234,11 @@ static bool detect_vm_xen_dom0(void) {
break;
if (!cap) {
log_debug("Virtualization XEN DomU found (/proc/xen/capabilites)");
- return false;
+ return 0;
}
log_debug("Virtualization XEN Dom0 ignored (/proc/xen/capabilities)");
- return true;
+ return 1;
}
static int detect_vm_hypervisor(void) {
@@ -277,6 +265,10 @@ static int detect_vm_uml(void) {
/* Detect User-Mode Linux by reading /proc/cpuinfo */
r = read_full_file("/proc/cpuinfo", &cpuinfo_contents, NULL);
+ if (r == -ENOENT) {
+ log_debug("/proc/cpuinfo not found, assuming no UML virtualization.");
+ return VIRTUALIZATION_NONE;
+ }
if (r < 0)
return r;
@@ -285,7 +277,7 @@ static int detect_vm_uml(void) {
return VIRTUALIZATION_UML;
}
- log_debug("No virtualization found in /proc/cpuinfo.");
+ log_debug("UML virtualization not found in /proc/cpuinfo.");
return VIRTUALIZATION_NONE;
}
@@ -315,6 +307,7 @@ static int detect_vm_zvm(void) {
/* Returns a short identifier for the various VM implementations */
int detect_vm(void) {
static thread_local int cached_found = _VIRTUALIZATION_INVALID;
+ bool other = false;
int r, dmi;
if (cached_found >= 0)
@@ -322,13 +315,16 @@ int detect_vm(void) {
/* We have to use the correct order here:
*
- * -> First try to detect Oracle Virtualbox, even if it uses KVM.
- * -> Second try to detect from cpuid, this will report KVM for
- * whatever software is used even if info in dmi is overwritten.
- * -> Third try to detect from dmi. */
+ * → First, try to detect Oracle Virtualbox, even if it uses KVM, as well as Xen even if it cloaks as Microsoft
+ * Hyper-V.
+ *
+ * → Second, try to detect from CPUID, this will report KVM for whatever software is used even if info in DMI is
+ * overwritten.
+ *
+ * → Third, try to detect from DMI. */
dmi = detect_vm_dmi();
- if (dmi == VIRTUALIZATION_ORACLE) {
+ if (IN_SET(dmi, VIRTUALIZATION_ORACLE, VIRTUALIZATION_XEN)) {
r = dmi;
goto finish;
}
@@ -336,44 +332,57 @@ int detect_vm(void) {
r = detect_vm_cpuid();
if (r < 0)
return r;
- if (r != VIRTUALIZATION_NONE)
+ if (r == VIRTUALIZATION_VM_OTHER)
+ other = true;
+ else if (r != VIRTUALIZATION_NONE)
goto finish;
- r = dmi;
- if (r < 0)
- return r;
- if (r != VIRTUALIZATION_NONE)
+ /* Now, let's get back to DMI */
+ if (dmi < 0)
+ return dmi;
+ if (dmi == VIRTUALIZATION_VM_OTHER)
+ other = true;
+ else if (dmi != VIRTUALIZATION_NONE) {
+ r = dmi;
goto finish;
+ }
/* x86 xen will most likely be detected by cpuid. If not (most likely
- * because we're not an x86 guest), then we should try the xen capabilities
- * file next. If that's not found, then we check for the high-level
- * hypervisor sysfs file:
- *
- * https://bugs.freedesktop.org/show_bug.cgi?id=77271 */
+ * because we're not an x86 guest), then we should try the /proc/xen
+ * directory next. If that's not found, then we check for the high-level
+ * hypervisor sysfs file.
+ */
r = detect_vm_xen();
if (r < 0)
return r;
- if (r != VIRTUALIZATION_NONE)
+ if (r == VIRTUALIZATION_VM_OTHER)
+ other = true;
+ else if (r != VIRTUALIZATION_NONE)
goto finish;
r = detect_vm_hypervisor();
if (r < 0)
return r;
- if (r != VIRTUALIZATION_NONE)
+ if (r == VIRTUALIZATION_VM_OTHER)
+ other = true;
+ else if (r != VIRTUALIZATION_NONE)
goto finish;
r = detect_vm_device_tree();
if (r < 0)
return r;
- if (r != VIRTUALIZATION_NONE)
+ if (r == VIRTUALIZATION_VM_OTHER)
+ other = true;
+ else if (r != VIRTUALIZATION_NONE)
goto finish;
r = detect_vm_uml();
if (r < 0)
return r;
- if (r != VIRTUALIZATION_NONE)
+ if (r == VIRTUALIZATION_VM_OTHER)
+ other = true;
+ else if (r != VIRTUALIZATION_NONE)
goto finish;
r = detect_vm_zvm();
@@ -384,8 +393,16 @@ finish:
/* x86 xen Dom0 is detected as XEN in hypervisor and maybe others.
* In order to detect the Dom0 as not virtualization we need to
* double-check it */
- if (r == VIRTUALIZATION_XEN && detect_vm_xen_dom0())
- r = VIRTUALIZATION_NONE;
+ if (r == VIRTUALIZATION_XEN) {
+ int dom0;
+
+ dom0 = detect_vm_xen_dom0();
+ if (dom0 < 0)
+ return dom0;
+ if (dom0 > 0)
+ r = VIRTUALIZATION_NONE;
+ } else if (r == VIRTUALIZATION_NONE && other)
+ r = VIRTUALIZATION_VM_OTHER;
cached_found = r;
log_debug("Found VM virtualization %s", virtualization_to_string(r));
@@ -422,7 +439,7 @@ int detect_container(void) {
goto finish;
}
- if (getpid() == 1) {
+ if (getpid_cached() == 1) {
/* If we are PID 1 we can just check our own environment variable, and that's authoritative. */
e = getenv("container");
@@ -572,18 +589,18 @@ int running_in_userns(void) {
#endif // 0
int running_in_chroot(void) {
- int ret;
+ int r;
#if 0 /// elogind does not allow to ignore chroots, we are never init!
if (getenv_bool("SYSTEMD_IGNORE_CHROOT") > 0)
return 0;
#endif // 0
- ret = files_same("/proc/1/root", "/", 0);
- if (ret < 0)
- return ret;
+ r = files_same("/proc/1/root", "/", 0);
+ if (r < 0)
+ return r;
- return ret == 0;
+ return r == 0;
}
static const char *const virtualization_table[_VIRTUALIZATION_MAX] = {
@@ -599,6 +616,7 @@ static const char *const virtualization_table[_VIRTUALIZATION_MAX] = {
[VIRTUALIZATION_ZVM] = "zvm",
[VIRTUALIZATION_PARALLELS] = "parallels",
[VIRTUALIZATION_BHYVE] = "bhyve",
+ [VIRTUALIZATION_QNX] = "qnx",
[VIRTUALIZATION_VM_OTHER] = "vm-other",
[VIRTUALIZATION_SYSTEMD_NSPAWN] = "systemd-nspawn",
diff --git a/src/basic/virt.h b/src/basic/virt.h
index f448f4e8f..b56bc5c7f 100644
--- a/src/basic/virt.h
+++ b/src/basic/virt.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 "macro.h"
@@ -38,6 +20,7 @@ enum {
VIRTUALIZATION_ZVM,
VIRTUALIZATION_PARALLELS,
VIRTUALIZATION_BHYVE,
+ VIRTUALIZATION_QNX,
VIRTUALIZATION_VM_OTHER,
VIRTUALIZATION_VM_LAST = VIRTUALIZATION_VM_OTHER,
diff --git a/src/basic/xattr-util.c b/src/basic/xattr-util.c
index 6b5c54653..a9ec8e106 100644
--- a/src/basic/xattr-util.c
+++ b/src/basic/xattr-util.c
@@ -1,24 +1,8 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <fcntl.h>
+//#include <linux/stat.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -28,8 +12,10 @@
#include "alloc-util.h"
#include "fd-util.h"
#include "macro.h"
+//#include "missing.h"
#include "sparse-endian.h"
#include "stdio-util.h"
+//#include "string-util.h"
#include "time-util.h"
#include "xattr-util.h"
@@ -104,24 +90,42 @@ int fgetxattr_malloc(int fd, const char *name, char **value) {
}
#if 0 /// UNNEEDED by elogind
-ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags) {
- char fn[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
+int fgetxattrat_fake(
+ int dirfd,
+ const char *filename,
+ const char *attribute,
+ void *value, size_t size,
+ int flags,
+ size_t *ret_size) {
+
+ char fn[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
_cleanup_close_ int fd = -1;
ssize_t l;
/* The kernel doesn't have a fgetxattrat() command, hence let's emulate one */
- fd = openat(dirfd, filename, O_CLOEXEC|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0));
- if (fd < 0)
- return -errno;
+ if (flags & ~(AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH))
+ return -EINVAL;
- xsprintf(fn, "/proc/self/fd/%i", fd);
+ if (isempty(filename)) {
+ if (!(flags & AT_EMPTY_PATH))
+ return -EINVAL;
+
+ xsprintf(fn, "/proc/self/fd/%i", dirfd);
+ } else {
+ fd = openat(dirfd, filename, O_CLOEXEC|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0));
+ if (fd < 0)
+ return -errno;
+
+ xsprintf(fn, "/proc/self/fd/%i", fd);
+ }
l = getxattr(fn, attribute, value, size);
if (l < 0)
return -errno;
- return l;
+ *ret_size = l;
+ return 0;
}
static int parse_crtime(le64_t le, usec_t *usec) {
@@ -130,59 +134,73 @@ static int parse_crtime(le64_t le, usec_t *usec) {
assert(usec);
u = le64toh(le);
- if (u == 0 || u == (uint64_t) -1)
+ if (IN_SET(u, 0, (uint64_t) -1))
return -EIO;
*usec = (usec_t) u;
return 0;
}
-int fd_getcrtime(int fd, usec_t *usec) {
+int fd_getcrtime_at(int dirfd, const char *name, usec_t *ret, int flags) {
+ struct_statx sx;
+ usec_t a, b;
le64_t le;
- ssize_t n;
+ size_t n;
+ int r;
+
+ assert(ret);
+
+ if (flags & ~(AT_EMPTY_PATH|AT_SYMLINK_NOFOLLOW))
+ return -EINVAL;
+
+ /* So here's the deal: the creation/birth time (crtime/btime) of a file is a relatively newly supported concept
+ * on Linux (or more strictly speaking: a concept that only recently got supported in the API, it was
+ * implemented on various file systems on the lower level since a while, but never was accessible). However, we
+ * needed a concept like that for vaccuuming algorithms and such, hence we emulated it via a user xattr for a
+ * long time. Starting with Linux 4.11 there's statx() which exposes the timestamp to userspace for the first
+ * time, where it is available. Thius function will read it, but it tries to keep some compatibility with older
+ * systems: we try to read both the crtime/btime and the xattr, and then use whatever is older. After all the
+ * concept is useful for determining how "old" a file really is, and hence using the older of the two makes
+ * most sense. */
+
+ if (statx(dirfd, strempty(name), flags|AT_STATX_DONT_SYNC, STATX_BTIME, &sx) >= 0 &&
+ (sx.stx_mask & STATX_BTIME) &&
+ sx.stx_btime.tv_sec != 0)
+ a = (usec_t) sx.stx_btime.tv_sec * USEC_PER_SEC +
+ (usec_t) sx.stx_btime.tv_nsec / NSEC_PER_USEC;
+ else
+ a = USEC_INFINITY;
+
+ r = fgetxattrat_fake(dirfd, name, "user.crtime_usec", &le, sizeof(le), flags, &n);
+ if (r >= 0) {
+ if (n != sizeof(le))
+ r = -EIO;
+ else
+ r = parse_crtime(le, &b);
+ }
+ if (r < 0) {
+ if (a != USEC_INFINITY) {
+ *ret = a;
+ return 0;
+ }
- assert(fd >= 0);
- assert(usec);
+ return r;
+ }
- /* Until Linux gets a real concept of birthtime/creation time,
- * let's fake one with xattrs */
+ if (a != USEC_INFINITY)
+ *ret = MIN(a, b);
+ else
+ *ret = b;
- n = fgetxattr(fd, "user.crtime_usec", &le, sizeof(le));
- if (n < 0)
- return -errno;
- if (n != sizeof(le))
- return -EIO;
-
- return parse_crtime(le, usec);
+ return 0;
}
-int fd_getcrtime_at(int dirfd, const char *name, usec_t *usec, int flags) {
- le64_t le;
- ssize_t n;
-
- n = fgetxattrat_fake(dirfd, name, "user.crtime_usec", &le, sizeof(le), flags);
- if (n < 0)
- return -errno;
- if (n != sizeof(le))
- return -EIO;
-
- return parse_crtime(le, usec);
+int fd_getcrtime(int fd, usec_t *ret) {
+ return fd_getcrtime_at(fd, NULL, ret, AT_EMPTY_PATH);
}
-int path_getcrtime(const char *p, usec_t *usec) {
- le64_t le;
- ssize_t n;
-
- assert(p);
- assert(usec);
-
- n = getxattr(p, "user.crtime_usec", &le, sizeof(le));
- if (n < 0)
- return -errno;
- if (n != sizeof(le))
- return -EIO;
-
- return parse_crtime(le, usec);
+int path_getcrtime(const char *p, usec_t *ret) {
+ return fd_getcrtime_at(AT_FDCWD, p, ret, 0);
}
int fd_setcrtime(int fd, usec_t usec) {
@@ -190,7 +208,7 @@ int fd_setcrtime(int fd, usec_t usec) {
assert(fd >= 0);
- if (usec <= 0)
+ if (IN_SET(usec, 0, USEC_INFINITY))
usec = now(CLOCK_REALTIME);
le = htole64((uint64_t) usec);
diff --git a/src/basic/xattr-util.h b/src/basic/xattr-util.h
index 254f5a038..99dcc6f13 100644
--- a/src/basic/xattr-util.h
+++ b/src/basic/xattr-util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 <stddef.h>
#include <sys/types.h>
@@ -29,7 +11,13 @@ int getxattr_malloc(const char *path, const char *name, char **value, bool allow
int fgetxattr_malloc(int fd, const char *name, char **value);
#if 0 /// UNNEEDED by elogind
-ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags);
+int fgetxattrat_fake(
+ int dirfd,
+ const char *filename,
+ const char *attribute,
+ void *value, size_t size,
+ int flags,
+ size_t *ret_size);
int fd_setcrtime(int fd, usec_t usec);
diff --git a/src/cgroups-agent/Makefile b/src/cgroups-agent/Makefile
deleted file mode 120000
index d0b0e8e00..000000000
--- 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
index 9fb7e34dd..3cdd1b4c8 100644
--- a/src/cgroups-agent/cgroups-agent.c
+++ b/src/cgroups-agent/cgroups-agent.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <stdlib.h>
#include <sys/socket.h>
diff --git a/src/core/Makefile b/src/core/Makefile
deleted file mode 120000
index d0b0e8e00..000000000
--- a/src/core/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 04816239c..a08fd8009 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -1,26 +1,13 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <fcntl.h>
#include <fnmatch.h>
#include "alloc-util.h"
+//#include "blockdev-util.h"
+//#include "bpf-firewall.h"
+//#include "btrfs-util.h"
+//#include "bus-error.h"
#include "cgroup-util.h"
#include "cgroup.h"
#include "fd-util.h"
@@ -29,21 +16,51 @@
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
+//#include "procfs-util.h"
//#include "special.h"
+#include "stdio-util.h"
#include "string-table.h"
#include "string-util.h"
-#include "stdio-util.h"
+#include "virt.h"
#define CGROUP_CPU_QUOTA_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC)
+bool manager_owns_root_cgroup(Manager *m) {
+ assert(m);
+
+ /* Returns true if we are managing the root cgroup. Note that it isn't sufficient to just check whether the
+ * group root path equals "/" since that will also be the case if CLONE_NEWCGROUP is in the mix. Since there's
+ * appears to be no nice way to detect whether we are in a CLONE_NEWCGROUP namespace we instead just check if
+ * we run in any kind of container virtualization. */
+
+ if (detect_container() > 0)
+ return false;
+
+ return empty_or_root(m->cgroup_root);
+}
+
#if 0 /// UNNEEDED by elogind
+bool unit_has_root_cgroup(Unit *u) {
+ assert(u);
+
+ /* Returns whether this unit manages the root cgroup. This will return true if this unit is the root slice and
+ * the manager manages the root cgroup. */
+
+ if (!manager_owns_root_cgroup(u->manager))
+ return false;
+
+ return unit_has_name(u, SPECIAL_ROOT_SLICE);
+}
+
static void cgroup_compat_warn(void) {
static bool cgroup_compat_warned = false;
if (cgroup_compat_warned)
return;
- log_warning("cgroup compatibility translation between legacy and unified hierarchy settings activated. See cgroup-compat debug messages for details.");
+ log_warning("cgroup compatibility translation between legacy and unified hierarchy settings activated. "
+ "See cgroup-compat debug messages for details.");
+
cgroup_compat_warned = true;
}
@@ -142,6 +159,9 @@ void cgroup_context_done(CGroupContext *c) {
while (c->device_allow)
cgroup_context_free_device_allow(c, c->device_allow);
+
+ c->ip_address_allow = ip_address_access_free_all(c->ip_address_allow);
+ c->ip_address_deny = ip_address_access_free_all(c->ip_address_deny);
}
void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
@@ -150,6 +170,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
CGroupBlockIODeviceBandwidth *b;
CGroupBlockIODeviceWeight *w;
CGroupDeviceAllow *a;
+ IPAddressAccessItem *iaai;
char u[FORMAT_TIMESPAN_MAX];
assert(c);
@@ -163,6 +184,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
"%sBlockIOAccounting=%s\n"
"%sMemoryAccounting=%s\n"
"%sTasksAccounting=%s\n"
+ "%sIPAccounting=%s\n"
"%sCPUWeight=%" PRIu64 "\n"
"%sStartupCPUWeight=%" PRIu64 "\n"
"%sCPUShares=%" PRIu64 "\n"
@@ -185,6 +207,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
prefix, yes_no(c->blockio_accounting),
prefix, yes_no(c->memory_accounting),
prefix, yes_no(c->tasks_accounting),
+ prefix, yes_no(c->ip_accounting),
prefix, c->cpu_weight,
prefix, c->startup_cpu_weight,
prefix, c->cpu_shares,
@@ -203,6 +226,16 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
prefix, cgroup_device_policy_to_string(c->device_policy),
prefix, yes_no(c->delegate));
+ if (c->delegate) {
+ _cleanup_free_ char *t = NULL;
+
+ (void) cg_mask_to_string(c->delegate_controllers, &t);
+
+ fprintf(f, "%sDelegateControllers=%s\n",
+ prefix,
+ strempty(t));
+ }
+
LIST_FOREACH(device_allow, a, c->device_allow)
fprintf(f,
"%sDeviceAllow=%s %s%s%s\n",
@@ -254,34 +287,52 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
b->path,
format_bytes(buf, sizeof(buf), b->wbps));
}
+
+ LIST_FOREACH(items, iaai, c->ip_address_allow) {
+ _cleanup_free_ char *k = NULL;
+
+ (void) in_addr_to_string(iaai->family, &iaai->address, &k);
+ fprintf(f, "%sIPAddressAllow=%s/%u\n", prefix, strnull(k), iaai->prefixlen);
+ }
+
+ LIST_FOREACH(items, iaai, c->ip_address_deny) {
+ _cleanup_free_ char *k = NULL;
+
+ (void) in_addr_to_string(iaai->family, &iaai->address, &k);
+ fprintf(f, "%sIPAddressDeny=%s/%u\n", prefix, strnull(k), iaai->prefixlen);
+ }
}
-static int lookup_block_device(const char *p, dev_t *dev) {
+static int lookup_block_device(const char *p, dev_t *ret) {
struct stat st;
int r;
assert(p);
- assert(dev);
+ assert(ret);
- r = stat(p, &st);
- if (r < 0)
- return log_warning_errno(errno, "Couldn't stat device %s: %m", p);
+ if (stat(p, &st) < 0)
+ return log_warning_errno(errno, "Couldn't stat device '%s': %m", p);
if (S_ISBLK(st.st_mode))
- *dev = 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 */
- *dev = st.st_dev;
-
- /* If this is a partition, try to get the originating
- * block device */
- block_get_whole_disk(*dev, dev);
- } else {
- log_warning("%s is not a block device and file system block device cannot be determined or is not local.", p);
- return -ENODEV;
+ *ret = st.st_rdev;
+ else if (major(st.st_dev) != 0)
+ *ret = st.st_dev; /* If this is not a device node then use the block device this file is stored on */
+ else {
+ /* If this is btrfs, getting the backing block device is a bit harder */
+ r = btrfs_get_block_device(p, ret);
+ if (r < 0 && r != -ENOTTY)
+ return log_warning_errno(r, "Failed to determine block device backing btrfs file system '%s': %m", p);
+ if (r == -ENOTTY) {
+ log_warning("'%s' is not a block device node, and file system block device cannot be determined or is not local.", p);
+ return -ENODEV;
+ }
}
+ /* If this is a LUKS device, try to get the originating block device */
+ (void) block_get_originating(*ret, ret);
+
+ /* If this is a partition, try to get the originating block device */
+ (void) block_get_whole_disk(*ret, ret);
return 0;
}
@@ -335,7 +386,7 @@ static int whitelist_major(const char *path, const char *name, char type, const
assert(path);
assert(acc);
- assert(type == 'b' || type == 'c');
+ assert(IN_SET(type, 'b', 'c'));
f = fopen("/proc/devices", "re");
if (!f)
@@ -569,26 +620,22 @@ static void cgroup_apply_blkio_device_weight(Unit *u, const char *dev_path, uint
"Failed to set blkio.weight_device: %m");
}
-static unsigned cgroup_apply_io_device_limit(Unit *u, const char *dev_path, uint64_t *limits) {
+static void cgroup_apply_io_device_limit(Unit *u, const char *dev_path, uint64_t *limits) {
char limit_bufs[_CGROUP_IO_LIMIT_TYPE_MAX][DECIMAL_STR_MAX(uint64_t)];
char buf[DECIMAL_STR_MAX(dev_t)*2+2+(6+DECIMAL_STR_MAX(uint64_t)+1)*4];
CGroupIOLimitType type;
dev_t dev;
- unsigned n = 0;
int r;
r = lookup_block_device(dev_path, &dev);
if (r < 0)
- return 0;
+ return;
- for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++) {
- if (limits[type] != cgroup_io_limit_defaults[type]) {
+ for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++)
+ if (limits[type] != cgroup_io_limit_defaults[type])
xsprintf(limit_bufs[type], "%" PRIu64, limits[type]);
- n++;
- } else {
+ else
xsprintf(limit_bufs[type], "%s", limits[type] == CGROUP_LIMIT_MAX ? "max" : "0");
- }
- }
xsprintf(buf, "%u:%u rbps=%s wbps=%s riops=%s wiops=%s\n", major(dev), minor(dev),
limit_bufs[CGROUP_IO_RBPS_MAX], limit_bufs[CGROUP_IO_WBPS_MAX],
@@ -597,36 +644,28 @@ static unsigned cgroup_apply_io_device_limit(Unit *u, const char *dev_path, uint
if (r < 0)
log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set io.max: %m");
- return n;
}
-static unsigned cgroup_apply_blkio_device_limit(Unit *u, const char *dev_path, uint64_t rbps, uint64_t wbps) {
+static void cgroup_apply_blkio_device_limit(Unit *u, const char *dev_path, uint64_t rbps, uint64_t wbps) {
char buf[DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1];
dev_t dev;
- unsigned n = 0;
int r;
r = lookup_block_device(dev_path, &dev);
if (r < 0)
- return 0;
+ return;
- if (rbps != CGROUP_LIMIT_MAX)
- n++;
sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), rbps);
r = cg_set_attribute("blkio", u->cgroup_path, "blkio.throttle.read_bps_device", buf);
if (r < 0)
log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set blkio.throttle.read_bps_device: %m");
- if (wbps != CGROUP_LIMIT_MAX)
- n++;
sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), wbps);
r = cg_set_attribute("blkio", u->cgroup_path, "blkio.throttle.write_bps_device", buf);
if (r < 0)
log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set blkio.throttle.write_bps_device: %m");
-
- return n;
}
static bool cgroup_context_has_unified_memory_config(CGroupContext *c) {
@@ -646,7 +685,23 @@ static void cgroup_apply_unified_memory_limit(Unit *u, const char *file, uint64_
"Failed to set %s: %m", file);
}
-static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) {
+static void cgroup_apply_firewall(Unit *u) {
+ assert(u);
+
+ /* Best-effort: let's apply IP firewalling and/or accounting if that's enabled */
+
+ if (bpf_firewall_compile(u) < 0)
+ return;
+
+ (void) bpf_firewall_install(u);
+}
+
+static void cgroup_context_apply(
+ Unit *u,
+ CGroupMask apply_mask,
+ bool apply_bpf,
+ ManagerState state) {
+
const char *path;
CGroupContext *c;
bool is_root;
@@ -654,29 +709,28 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) {
assert(u);
- c = unit_get_cgroup_context(u);
- path = u->cgroup_path;
+ /* Nothing to do? Exit early! */
+ if (apply_mask == 0 && !apply_bpf)
+ return;
- assert(c);
- assert(path);
+ /* Some cgroup attributes are not supported on the root cgroup, hence silently ignore */
+ is_root = unit_has_root_cgroup(u);
- if (mask == 0)
- return;
+ assert_se(c = unit_get_cgroup_context(u));
+ assert_se(path = u->cgroup_path);
- /* Some cgroup attributes are not supported on the root cgroup,
- * hence silently ignore */
- is_root = isempty(path) || path_equal(path, "/");
- if (is_root)
- /* Make sure we don't try to display messages with an empty path. */
+ if (is_root) /* Make sure we don't try to display messages with an empty path. */
path = "/";
/* We generally ignore errors caused by read-only mounted
* cgroup trees (assuming we are running in a container then),
* and missing cgroups, i.e. EROFS and ENOENT. */
- if ((mask & CGROUP_MASK_CPU) && !is_root) {
- bool has_weight = cgroup_context_has_cpu_weight(c);
- bool has_shares = cgroup_context_has_cpu_shares(c);
+ if ((apply_mask & CGROUP_MASK_CPU) && !is_root) {
+ bool has_weight, has_shares;
+
+ has_weight = cgroup_context_has_cpu_weight(c);
+ has_shares = cgroup_context_has_cpu_shares(c);
if (cg_all_unified() > 0) {
uint64_t weight;
@@ -713,7 +767,7 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) {
}
}
- if (mask & CGROUP_MASK_IO) {
+ if (apply_mask & CGROUP_MASK_IO) {
bool has_io = cgroup_context_has_io_config(c);
bool has_blockio = cgroup_context_has_blockio_config(c);
@@ -762,16 +816,15 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) {
/* Apply limits and free ones without config. */
if (has_io) {
- CGroupIODeviceLimit *l, *next;
+ CGroupIODeviceLimit *l;
+
+ LIST_FOREACH(device_limits, l, c->io_device_limits)
+ cgroup_apply_io_device_limit(u, l->path, l->limits);
- LIST_FOREACH_SAFE(device_limits, l, next, c->io_device_limits) {
- if (!cgroup_apply_io_device_limit(u, l->path, l->limits))
- cgroup_context_free_io_device_limit(c, l);
- }
} else if (has_blockio) {
- CGroupBlockIODeviceBandwidth *b, *next;
+ CGroupBlockIODeviceBandwidth *b;
- LIST_FOREACH_SAFE(device_bandwidths, b, next, c->blockio_device_bandwidths) {
+ LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
uint64_t limits[_CGROUP_IO_LIMIT_TYPE_MAX];
CGroupIOLimitType type;
@@ -784,13 +837,12 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) {
log_cgroup_compat(u, "Applying BlockIO{Read|Write}Bandwidth %" PRIu64 " %" PRIu64 " as IO{Read|Write}BandwidthMax for %s",
b->rbps, b->wbps, b->path);
- if (!cgroup_apply_io_device_limit(u, b->path, limits))
- cgroup_context_free_blockio_device_bandwidth(c, b);
+ cgroup_apply_io_device_limit(u, b->path, limits);
}
}
}
- if (mask & CGROUP_MASK_BLKIO) {
+ if (apply_mask & CGROUP_MASK_BLKIO) {
bool has_io = cgroup_context_has_io_config(c);
bool has_blockio = cgroup_context_has_blockio_config(c);
@@ -839,25 +891,23 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) {
/* Apply limits and free ones without config. */
if (has_io) {
- CGroupIODeviceLimit *l, *next;
+ CGroupIODeviceLimit *l;
- LIST_FOREACH_SAFE(device_limits, l, next, c->io_device_limits) {
+ LIST_FOREACH(device_limits, l, c->io_device_limits) {
log_cgroup_compat(u, "Applying IO{Read|Write}Bandwidth %" PRIu64 " %" PRIu64 " as BlockIO{Read|Write}BandwidthMax for %s",
l->limits[CGROUP_IO_RBPS_MAX], l->limits[CGROUP_IO_WBPS_MAX], l->path);
- if (!cgroup_apply_blkio_device_limit(u, l->path, l->limits[CGROUP_IO_RBPS_MAX], l->limits[CGROUP_IO_WBPS_MAX]))
- cgroup_context_free_io_device_limit(c, l);
+ cgroup_apply_blkio_device_limit(u, l->path, l->limits[CGROUP_IO_RBPS_MAX], l->limits[CGROUP_IO_WBPS_MAX]);
}
} else if (has_blockio) {
- CGroupBlockIODeviceBandwidth *b, *next;
+ CGroupBlockIODeviceBandwidth *b;
- LIST_FOREACH_SAFE(device_bandwidths, b, next, c->blockio_device_bandwidths)
- if (!cgroup_apply_blkio_device_limit(u, b->path, b->rbps, b->wbps))
- cgroup_context_free_blockio_device_bandwidth(c, b);
+ LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths)
+ cgroup_apply_blkio_device_limit(u, b->path, b->rbps, b->wbps);
}
}
- if ((mask & CGROUP_MASK_MEMORY) && !is_root) {
+ if ((apply_mask & CGROUP_MASK_MEMORY) && !is_root) {
if (cg_all_unified() > 0) {
uint64_t max, swap_max = CGROUP_LIMIT_MAX;
@@ -897,7 +947,7 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) {
}
}
- if ((mask & CGROUP_MASK_DEVICES) && !is_root) {
+ if ((apply_mask & CGROUP_MASK_DEVICES) && !is_root) {
CGroupDeviceAllow *a;
/* Changing the devices list of a populated cgroup
@@ -921,8 +971,7 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) {
"/dev/random\0" "rwm\0"
"/dev/urandom\0" "rwm\0"
"/dev/tty\0" "rwm\0"
- "/dev/pts/ptmx\0" "rw\0" /* /dev/pts/ptmx may not be duplicated, but accessed */
- /* Allow /run/elogind/inaccessible/{chr,blk} devices for mapping InaccessiblePaths */
+ "/dev/ptmx\0" "rwm\0"
/* Allow /run/systemd/inaccessible/{chr,blk} devices for mapping InaccessiblePaths */
"-/run/systemd/inaccessible/chr\0" "rwm\0"
"-/run/systemd/inaccessible/blk\0" "rwm\0";
@@ -932,9 +981,8 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) {
NULSTR_FOREACH_PAIR(x, y, auto_devices)
whitelist_device(path, x, y);
+ /* PTS (/dev/pts) devices may not be duplicated, but accessed */
whitelist_major(path, "pts", 'c', "rw");
- whitelist_major(path, "kdbus", 'c', "rw");
- whitelist_major(path, "kdbus/*", 'c', "rw");
}
LIST_FOREACH(device_allow, a, c->device_allow) {
@@ -953,7 +1001,7 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) {
acc[k++] = 0;
- if (startswith(a->path, "/dev/"))
+ if (path_startswith(a->path, "/dev/"))
whitelist_device(path, a->path, acc);
else if ((val = startswith(a->path, "block-")))
whitelist_major(path, val, 'b', acc);
@@ -964,20 +1012,50 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) {
}
}
- if ((mask & CGROUP_MASK_PIDS) && !is_root) {
+ if (apply_mask & CGROUP_MASK_PIDS) {
+
+ if (is_root) {
+ /* So, the "pids" controller does not expose anything on the root cgroup, in order not to
+ * replicate knobs exposed elsewhere needlessly. We abstract this away here however, and when
+ * the knobs of the root cgroup are modified propagate this to the relevant sysctls. There's a
+ * non-obvious asymmetry however: unlike the cgroup properties we don't really want to take
+ * exclusive ownership of the sysctls, but we still want to honour things if the user sets
+ * limits. Hence we employ sort of a one-way strategy: when the user sets a bounded limit
+ * through us it counts. When the user afterwards unsets it again (i.e. sets it to unbounded)
+ * it also counts. But if the user never set a limit through us (i.e. we are the default of
+ * "unbounded") we leave things unmodified. For this we manage a global boolean that we turn on
+ * the first time we set a limit. Note that this boolean is flushed out on manager reload,
+ * which is desirable so that there's an offical way to release control of the sysctl from
+ * systemd: set the limit to unbounded and reload. */
+
+ if (c->tasks_max != CGROUP_LIMIT_MAX) {
+ u->manager->sysctl_pid_max_changed = true;
+ r = procfs_tasks_set_limit(c->tasks_max);
+ } else if (u->manager->sysctl_pid_max_changed)
+ r = procfs_tasks_set_limit(TASKS_MAX);
+ else
+ r = 0;
- if (c->tasks_max != CGROUP_LIMIT_MAX) {
- char buf[DECIMAL_STR_MAX(uint64_t) + 2];
+ if (r < 0)
+ log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
+ "Failed to write to tasks limit sysctls: %m");
- sprintf(buf, "%" PRIu64 "\n", c->tasks_max);
- r = cg_set_attribute("pids", path, "pids.max", buf);
- } else
- r = cg_set_attribute("pids", path, "pids.max", "max");
+ } else {
+ if (c->tasks_max != CGROUP_LIMIT_MAX) {
+ char buf[DECIMAL_STR_MAX(uint64_t) + 2];
- if (r < 0)
- log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
- "Failed to set pids.max: %m");
+ sprintf(buf, "%" PRIu64 "\n", c->tasks_max);
+ r = cg_set_attribute("pids", path, "pids.max", buf);
+ } else
+ r = cg_set_attribute("pids", path, "pids.max", "max");
+ if (r < 0)
+ log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
+ "Failed to set pids.max: %m");
+ }
}
+
+ if (apply_bpf)
+ cgroup_apply_firewall(u);
}
CGroupMask cgroup_context_get_mask(CGroupContext *c) {
@@ -1004,7 +1082,7 @@ CGroupMask cgroup_context_get_mask(CGroupContext *c) {
mask |= CGROUP_MASK_DEVICES;
if (c->tasks_accounting ||
- c->tasks_max != (uint64_t) -1)
+ c->tasks_max != CGROUP_LIMIT_MAX)
mask |= CGROUP_MASK_PIDS;
return mask;
@@ -1019,32 +1097,36 @@ CGroupMask unit_get_own_mask(Unit *u) {
if (!c)
return 0;
- /* If delegation is turned on, then turn on all cgroups,
- * unless we are on the legacy hierarchy and the process we
- * fork into it is known to drop privileges, and hence
- * shouldn't get access to the controllers.
+ return cgroup_context_get_mask(c) | unit_get_delegate_mask(u);
+}
+
+CGroupMask unit_get_delegate_mask(Unit *u) {
+ CGroupContext *c;
+
+ /* If delegation is turned on, then turn on selected controllers, unless we are on the legacy hierarchy and the
+ * process we fork into is known to drop privileges, and hence shouldn't get access to the controllers.
*
- * Note that on the unified hierarchy it is safe to delegate
- * controllers to unprivileged services. */
+ * Note that on the unified hierarchy it is safe to delegate controllers to unprivileged services. */
- if (c->delegate) {
+ if (!unit_cgroup_delegate(u))
+ return 0;
+
+ if (cg_all_unified() <= 0) {
ExecContext *e;
e = unit_get_exec_context(u);
- if (!e ||
- exec_context_maintains_privileges(e) ||
- cg_all_unified() > 0)
- return _CGROUP_MASK_ALL;
+ if (e && !exec_context_maintains_privileges(e))
+ return 0;
}
- return cgroup_context_get_mask(c);
+ assert_se(c = unit_get_cgroup_context(u));
+ return c->delegate_controllers;
}
CGroupMask unit_get_members_mask(Unit *u) {
assert(u);
- /* Returns the mask of controllers all of the unit's children
- * require, merged */
+ /* Returns the mask of controllers all of the unit's children require, merged */
if (u->cgroup_members_mask_valid)
return u->cgroup_members_mask;
@@ -1052,10 +1134,11 @@ CGroupMask unit_get_members_mask(Unit *u) {
u->cgroup_members_mask = 0;
if (u->type == UNIT_SLICE) {
+ void *v;
Unit *member;
Iterator i;
- SET_FOREACH(member, u->dependencies[UNIT_BEFORE], i) {
+ HASHMAP_FOREACH_KEY(v, member, u->dependencies[UNIT_BEFORE], i) {
if (member == u)
continue;
@@ -1063,9 +1146,7 @@ CGroupMask unit_get_members_mask(Unit *u) {
if (UNIT_DEREF(member->slice) != u)
continue;
- u->cgroup_members_mask |=
- unit_get_own_mask(member) |
- unit_get_members_mask(member);
+ u->cgroup_members_mask |= unit_get_subtree_mask(member); /* note that this calls ourselves again, for the children */
}
}
@@ -1083,7 +1164,7 @@ CGroupMask unit_get_siblings_mask(Unit *u) {
if (UNIT_ISSET(u->slice))
return unit_get_members_mask(UNIT_DEREF(u->slice));
- return unit_get_own_mask(u) | unit_get_members_mask(u);
+ return unit_get_subtree_mask(u); /* we are the top-level slice */
}
CGroupMask unit_get_subtree_mask(Unit *u) {
@@ -1124,6 +1205,34 @@ CGroupMask unit_get_enable_mask(Unit *u) {
return mask;
}
+bool unit_get_needs_bpf(Unit *u) {
+ CGroupContext *c;
+ Unit *p;
+ assert(u);
+
+ c = unit_get_cgroup_context(u);
+ if (!c)
+ return false;
+
+ if (c->ip_accounting ||
+ c->ip_address_allow ||
+ c->ip_address_deny)
+ return true;
+
+ /* If any parent slice has an IP access list defined, it applies too */
+ for (p = UNIT_DEREF(u->slice); p; p = UNIT_DEREF(p->slice)) {
+ c = unit_get_cgroup_context(p);
+ if (!c)
+ return false;
+
+ if (c->ip_address_allow ||
+ c->ip_address_deny)
+ return true;
+ }
+
+ return false;
+}
+
/* Recurse from a unit up through its containing slices, propagating
* mask bits upward. A unit is also member of itself. */
void unit_update_cgroup_members_masks(Unit *u) {
@@ -1173,16 +1282,15 @@ void unit_update_cgroup_members_masks(Unit *u) {
}
}
-static const char *migrate_callback(CGroupMask mask, void *userdata) {
- Unit *u = userdata;
+const char *unit_get_realized_cgroup_path(Unit *u, CGroupMask mask) {
- assert(mask != 0);
- assert(u);
+ /* Returns the realized cgroup path of the specified unit where all specified controllers are available. */
while (u) {
+
if (u->cgroup_path &&
u->cgroup_realized &&
- (u->cgroup_realized_mask & mask) == mask)
+ FLAGS_SET(u->cgroup_realized_mask, mask))
return u->cgroup_path;
u = UNIT_DEREF(u->slice);
@@ -1191,6 +1299,10 @@ static const char *migrate_callback(CGroupMask mask, void *userdata) {
return NULL;
}
+static const char *migrate_callback(CGroupMask mask, void *userdata) {
+ return unit_get_realized_cgroup_path(userdata, mask);
+}
+
char *unit_default_cgroup_path(Unit *u) {
_cleanup_free_ char *escaped = NULL, *slice = NULL;
int r;
@@ -1241,8 +1353,7 @@ int unit_set_cgroup_path(Unit *u, const char *path) {
unit_release_cgroup(u);
- u->cgroup_path = p;
- p = NULL;
+ u->cgroup_path = TAKE_PTR(p);
return 1;
}
@@ -1296,13 +1407,40 @@ int unit_watch_cgroup(Unit *u) {
return 0;
}
+int unit_pick_cgroup_path(Unit *u) {
+ _cleanup_free_ char *path = NULL;
+ int r;
+
+ assert(u);
+
+ if (u->cgroup_path)
+ return 0;
+
+ if (!UNIT_HAS_CGROUP_CONTEXT(u))
+ return -EINVAL;
+
+ path = unit_default_cgroup_path(u);
+ if (!path)
+ return log_oom();
+
+ r = unit_set_cgroup_path(u, path);
+ if (r == -EEXIST)
+ return log_unit_error_errno(u, r, "Control group %s exists already.", path);
+ if (r < 0)
+ return log_unit_error_errno(u, r, "Failed to set unit's control group path to %s: %m", path);
+
+ return 0;
+}
+
static int unit_create_cgroup(
Unit *u,
CGroupMask target_mask,
- CGroupMask enable_mask) {
+ CGroupMask enable_mask,
+ bool needs_bpf) {
CGroupContext *c;
int r;
+ bool created;
assert(u);
@@ -1310,39 +1448,37 @@ static int unit_create_cgroup(
if (!c)
return 0;
- if (!u->cgroup_path) {
- _cleanup_free_ char *path = NULL;
-
- path = unit_default_cgroup_path(u);
- if (!path)
- return log_oom();
-
- r = unit_set_cgroup_path(u, path);
- if (r == -EEXIST)
- return log_unit_error_errno(u, r, "Control group %s exists already.", path);
- if (r < 0)
- return log_unit_error_errno(u, r, "Failed to set unit's control group path to %s: %m", path);
- }
+ /* Figure out our cgroup path */
+ r = unit_pick_cgroup_path(u);
+ if (r < 0)
+ return r;
/* First, create our own group */
r = cg_create_everywhere(u->manager->cgroup_supported, target_mask, u->cgroup_path);
if (r < 0)
return log_unit_error_errno(u, r, "Failed to create cgroup %s: %m", u->cgroup_path);
+ created = !!r;
/* Start watching it */
(void) unit_watch_cgroup(u);
- /* Enable all controllers we need */
- r = cg_enable_everywhere(u->manager->cgroup_supported, enable_mask, u->cgroup_path);
- if (r < 0)
- log_unit_warning_errno(u, r, "Failed to enable controllers on cgroup %s, ignoring: %m", u->cgroup_path);
+ /* Preserve enabled controllers in delegated units, adjust others. */
+ if (created || !unit_cgroup_delegate(u)) {
+
+ /* Enable all controllers we need */
+ r = cg_enable_everywhere(u->manager->cgroup_supported, enable_mask, u->cgroup_path);
+ if (r < 0)
+ log_unit_warning_errno(u, r, "Failed to enable controllers on cgroup %s, ignoring: %m",
+ u->cgroup_path);
+ }
/* Keep track that this is now realized */
u->cgroup_realized = true;
u->cgroup_realized_mask = target_mask;
u->cgroup_enabled_mask = enable_mask;
+ u->cgroup_bpf_state = needs_bpf ? UNIT_CGROUP_BPF_ON : UNIT_CGROUP_BPF_OFF;
- if (u->type != UNIT_SLICE && !c->delegate) {
+ if (u->type != UNIT_SLICE && !unit_cgroup_delegate(u)) {
/* Then, possibly move things over, but not if
* subgroups may contain processes, which is the case
@@ -1355,19 +1491,142 @@ static int unit_create_cgroup(
return 0;
}
-int unit_attach_pids_to_cgroup(Unit *u) {
+static int unit_attach_pid_to_cgroup_via_bus(Unit *u, pid_t pid, const char *suffix_path) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ char *pp;
int r;
+
assert(u);
- r = unit_realize_cgroup(u);
+ if (MANAGER_IS_SYSTEM(u->manager))
+ return -EINVAL;
+
+ if (!u->manager->system_bus)
+ return -EIO;
+
+ if (!u->cgroup_path)
+ return -EINVAL;
+
+ /* Determine this unit's cgroup path relative to our cgroup root */
+ pp = path_startswith(u->cgroup_path, u->manager->cgroup_root);
+ if (!pp)
+ return -EINVAL;
+
+ pp = strjoina("/", pp, suffix_path);
+ path_simplify(pp, false);
+
+ r = sd_bus_call_method(u->manager->system_bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "AttachProcessesToUnit",
+ &error, NULL,
+ "ssau",
+ NULL /* empty unit name means client's unit, i.e. us */, pp, 1, (uint32_t) pid);
if (r < 0)
- return r;
+ return log_unit_debug_errno(u, r, "Failed to attach unit process " PID_FMT " via the bus: %s", pid, bus_error_message(&error, r));
+
+ return 0;
+}
+
+int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const char *suffix_path) {
+ CGroupMask delegated_mask;
+ const char *p;
+ Iterator i;
+ void *pidp;
+ int r, q;
+
+ assert(u);
+
+ if (!UNIT_HAS_CGROUP_CONTEXT(u))
+ return -EINVAL;
+
+ if (set_isempty(pids))
+ return 0;
- r = cg_attach_many_everywhere(u->manager->cgroup_supported, u->cgroup_path, u->pids, migrate_callback, u);
+ r = unit_realize_cgroup(u);
if (r < 0)
return r;
- return 0;
+ if (isempty(suffix_path))
+ p = u->cgroup_path;
+ else
+ p = strjoina(u->cgroup_path, "/", suffix_path);
+
+ delegated_mask = unit_get_delegate_mask(u);
+
+ r = 0;
+ SET_FOREACH(pidp, pids, i) {
+ pid_t pid = PTR_TO_PID(pidp);
+ CGroupController c;
+
+ /* First, attach the PID to the main cgroup hierarchy */
+ q = cg_attach(SYSTEMD_CGROUP_CONTROLLER, p, pid);
+ if (q < 0) {
+ log_unit_debug_errno(u, q, "Couldn't move process " PID_FMT " to requested cgroup '%s': %m", pid, p);
+
+ if (MANAGER_IS_USER(u->manager) && IN_SET(q, -EPERM, -EACCES)) {
+ int z;
+
+ /* If we are in a user instance, and we can't move the process ourselves due to
+ * permission problems, let's ask the system instance about it instead. Since it's more
+ * privileged it might be able to move the process across the leaves of a subtree who's
+ * top node is not owned by us. */
+
+ z = unit_attach_pid_to_cgroup_via_bus(u, pid, suffix_path);
+ if (z < 0)
+ log_unit_debug_errno(u, z, "Couldn't move process " PID_FMT " to requested cgroup '%s' via the system bus either: %m", pid, p);
+ else
+ continue; /* When the bus thing worked via the bus we are fully done for this PID. */
+ }
+
+ if (r >= 0)
+ r = q; /* Remember first error */
+
+ continue;
+ }
+
+ q = cg_all_unified();
+ if (q < 0)
+ return q;
+ if (q > 0)
+ continue;
+
+ /* In the legacy hierarchy, attach the process to the request cgroup if possible, and if not to the
+ * innermost realized one */
+
+ for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
+ CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c);
+ const char *realized;
+
+ if (!(u->manager->cgroup_supported & bit))
+ continue;
+
+ /* If this controller is delegated and realized, honour the caller's request for the cgroup suffix. */
+ if (delegated_mask & u->cgroup_realized_mask & bit) {
+ q = cg_attach(cgroup_controller_to_string(c), p, pid);
+ if (q >= 0)
+ continue; /* Success! */
+
+ log_unit_debug_errno(u, q, "Failed to attach PID " PID_FMT " to requested cgroup %s in controller %s, falling back to unit's cgroup: %m",
+ pid, p, cgroup_controller_to_string(c));
+ }
+
+ /* So this controller is either not delegate or realized, or something else weird happened. In
+ * that case let's attach the PID at least to the closest cgroup up the tree that is
+ * realized. */
+ realized = unit_get_realized_cgroup_path(u, bit);
+ if (!realized)
+ continue; /* Not even realized in the root slice? Then let's not bother */
+
+ q = cg_attach(cgroup_controller_to_string(c), realized, pid);
+ if (q < 0)
+ log_unit_debug_errno(u, q, "Failed to attach PID " PID_FMT " to realized cgroup %s in controller %s, ignoring: %m",
+ pid, realized, cgroup_controller_to_string(c));
+ }
+ }
+
+ return r;
}
static void cgroup_xattr_apply(Unit *u) {
@@ -1387,13 +1646,42 @@ static void cgroup_xattr_apply(Unit *u) {
sd_id128_to_string(u->invocation_id, ids), 32,
0);
if (r < 0)
- log_unit_warning_errno(u, r, "Failed to set invocation ID on control group %s, ignoring: %m", u->cgroup_path);
+ log_unit_debug_errno(u, r, "Failed to set invocation ID on control group %s, ignoring: %m", u->cgroup_path);
}
-static bool unit_has_mask_realized(Unit *u, CGroupMask target_mask, CGroupMask enable_mask) {
+static bool unit_has_mask_realized(
+ Unit *u,
+ CGroupMask target_mask,
+ CGroupMask enable_mask,
+ bool needs_bpf) {
+
assert(u);
- return u->cgroup_realized && u->cgroup_realized_mask == target_mask && u->cgroup_enabled_mask == enable_mask;
+ return u->cgroup_realized &&
+ u->cgroup_realized_mask == target_mask &&
+ u->cgroup_enabled_mask == enable_mask &&
+ ((needs_bpf && u->cgroup_bpf_state == UNIT_CGROUP_BPF_ON) ||
+ (!needs_bpf && u->cgroup_bpf_state == UNIT_CGROUP_BPF_OFF));
+}
+
+static void unit_add_to_cgroup_realize_queue(Unit *u) {
+ assert(u);
+
+ if (u->in_cgroup_realize_queue)
+ return;
+
+ LIST_PREPEND(cgroup_realize_queue, u->manager->cgroup_realize_queue, u);
+ u->in_cgroup_realize_queue = true;
+}
+
+static void unit_remove_from_cgroup_realize_queue(Unit *u) {
+ assert(u);
+
+ if (!u->in_cgroup_realize_queue)
+ return;
+
+ LIST_REMOVE(cgroup_realize_queue, u->manager->cgroup_realize_queue, u);
+ u->in_cgroup_realize_queue = false;
}
/* Check if necessary controllers and attributes for a unit are in place.
@@ -1404,21 +1692,25 @@ static bool unit_has_mask_realized(Unit *u, CGroupMask target_mask, CGroupMask e
* Returns 0 on success and < 0 on failure. */
static int unit_realize_cgroup_now(Unit *u, ManagerState state) {
CGroupMask target_mask, enable_mask;
+ bool needs_bpf, apply_bpf;
int r;
assert(u);
- if (u->in_cgroup_queue) {
- LIST_REMOVE(cgroup_queue, u->manager->cgroup_queue, u);
- u->in_cgroup_queue = false;
- }
+ unit_remove_from_cgroup_realize_queue(u);
target_mask = unit_get_target_mask(u);
enable_mask = unit_get_enable_mask(u);
+ needs_bpf = unit_get_needs_bpf(u);
- if (unit_has_mask_realized(u, target_mask, enable_mask))
+ if (unit_has_mask_realized(u, target_mask, enable_mask, needs_bpf))
return 0;
+ /* Make sure we apply the BPF filters either when one is configured, or if none is configured but previously
+ * the state was anything but off. This way, if a unit with a BPF filter applied is reconfigured to lose it
+ * this will trickle down properly to cgroupfs. */
+ apply_bpf = needs_bpf || u->cgroup_bpf_state != UNIT_CGROUP_BPF_OFF;
+
/* First, realize parents */
if (UNIT_ISSET(u->slice)) {
r = unit_realize_cgroup_now(UNIT_DEREF(u->slice), state);
@@ -1427,36 +1719,35 @@ static int unit_realize_cgroup_now(Unit *u, ManagerState state) {
}
/* And then do the real work */
- r = unit_create_cgroup(u, target_mask, enable_mask);
+ r = unit_create_cgroup(u, target_mask, enable_mask, needs_bpf);
if (r < 0)
return r;
/* Finally, apply the necessary attributes. */
- cgroup_context_apply(u, target_mask, state);
+ cgroup_context_apply(u, target_mask, apply_bpf, state);
cgroup_xattr_apply(u);
return 0;
}
-static void unit_add_to_cgroup_queue(Unit *u) {
-
- if (u->in_cgroup_queue)
- return;
-
- LIST_PREPEND(cgroup_queue, u->manager->cgroup_queue, u);
- u->in_cgroup_queue = true;
-}
-
-unsigned manager_dispatch_cgroup_queue(Manager *m) {
+unsigned manager_dispatch_cgroup_realize_queue(Manager *m) {
ManagerState state;
unsigned n = 0;
Unit *i;
int r;
+ assert(m);
+
state = manager_state(m);
- while ((i = m->cgroup_queue)) {
- assert(i->in_cgroup_queue);
+ while ((i = m->cgroup_realize_queue)) {
+ assert(i->in_cgroup_realize_queue);
+
+ if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(i))) {
+ /* Maybe things changed, and the unit is not actually active anymore? */
+ unit_remove_from_cgroup_realize_queue(i);
+ continue;
+ }
r = unit_realize_cgroup_now(i, state);
if (r < 0)
@@ -1468,7 +1759,7 @@ unsigned manager_dispatch_cgroup_queue(Manager *m) {
return n;
}
-static void unit_queue_siblings(Unit *u) {
+static void unit_add_siblings_to_cgroup_realize_queue(Unit *u) {
Unit *slice;
/* This adds the siblings of the specified unit and the
@@ -1478,8 +1769,9 @@ static void unit_queue_siblings(Unit *u) {
while ((slice = UNIT_DEREF(u->slice))) {
Iterator i;
Unit *m;
+ void *v;
- SET_FOREACH(m, slice->dependencies[UNIT_BEFORE], i) {
+ HASHMAP_FOREACH_KEY(v, m, u->dependencies[UNIT_BEFORE], i) {
if (m == u)
continue;
@@ -1496,10 +1788,13 @@ static void unit_queue_siblings(Unit *u) {
/* If the unit doesn't need any new controllers
* and has current ones realized, it doesn't need
* any changes. */
- if (unit_has_mask_realized(m, unit_get_target_mask(m), unit_get_enable_mask(m)))
+ if (unit_has_mask_realized(m,
+ unit_get_target_mask(m),
+ unit_get_enable_mask(m),
+ unit_get_needs_bpf(m)))
continue;
- unit_add_to_cgroup_queue(m);
+ unit_add_to_cgroup_realize_queue(m);
}
u = slice;
@@ -1524,7 +1819,7 @@ int unit_realize_cgroup(Unit *u) {
* iteration. */
/* Add all sibling slices to the cgroup queue. */
- unit_queue_siblings(u);
+ unit_add_siblings_to_cgroup_realize_queue(u);
/* And realize this one now (and apply the values) */
return unit_realize_cgroup_now(u, manager_state(u->manager));
@@ -1595,7 +1890,7 @@ int unit_search_main_pid(Unit *u, pid_t *ret) {
if (r < 0)
return r;
- mypid = getpid();
+ mypid = getpid_cached();
while (cg_read_pid(f, &npid) > 0) {
pid_t ppid;
@@ -1672,6 +1967,31 @@ static int unit_watch_pids_in_path(Unit *u, const char *path) {
return ret;
}
+int unit_synthesize_cgroup_empty_event(Unit *u) {
+ int r;
+
+ assert(u);
+
+ /* Enqueue a synthetic cgroup empty event if this unit doesn't watch any PIDs anymore. This is compatibility
+ * support for non-unified systems where notifications aren't reliable, and hence need to take whatever we can
+ * get as notification source as soon as we stopped having any useful PIDs to watch for. */
+
+ if (!u->cgroup_path)
+ return -ENOENT;
+
+ r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
+ if (r < 0)
+ return r;
+ if (r > 0) /* On unified we have reliable notifications, and don't need this */
+ return 0;
+
+ if (!set_isempty(u->pids))
+ return 0;
+
+ unit_add_to_cgroup_empty_queue(u);
+ return 0;
+}
+
int unit_watch_all_pids(Unit *u) {
int r;
@@ -1694,17 +2014,28 @@ int unit_watch_all_pids(Unit *u) {
return unit_watch_pids_in_path(u, u->cgroup_path);
}
-int unit_notify_cgroup_empty(Unit *u) {
+static int on_cgroup_empty_event(sd_event_source *s, void *userdata) {
+ Manager *m = userdata;
+ Unit *u;
int r;
- assert(u);
+ assert(s);
+ assert(m);
- if (!u->cgroup_path)
+ u = m->cgroup_empty_queue;
+ if (!u)
return 0;
- r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path);
- if (r <= 0)
- return r;
+ assert(u->in_cgroup_empty_queue);
+ u->in_cgroup_empty_queue = false;
+ LIST_REMOVE(cgroup_empty_queue, m->cgroup_empty_queue, u);
+
+ if (m->cgroup_empty_queue) {
+ /* More stuff queued, let's make sure we remain enabled */
+ r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT);
+ if (r < 0)
+ log_debug_errno(r, "Failed to reenable cgroup empty event source, ignoring: %m");
+ }
unit_add_to_gc_queue(u);
@@ -1714,6 +2045,51 @@ int unit_notify_cgroup_empty(Unit *u) {
return 0;
}
+void unit_add_to_cgroup_empty_queue(Unit *u) {
+ int r;
+
+ assert(u);
+
+ /* Note that there are four different ways how cgroup empty events reach us:
+ *
+ * 1. On the unified hierarchy we get an inotify event on the cgroup
+ *
+ * 2. On the legacy hierarchy, when running in system mode, we get a datagram on the cgroup agent socket
+ *
+ * 3. On the legacy hierarchy, when running in user mode, we get a D-Bus signal on the system bus
+ *
+ * 4. On the legacy hierarchy, in service units we start watching all processes of the cgroup for SIGCHLD as
+ * soon as we get one SIGCHLD, to deal with unreliable cgroup notifications.
+ *
+ * Regardless which way we got the notification, we'll verify it here, and then add it to a separate
+ * queue. This queue will be dispatched at a lower priority than the SIGCHLD handler, so that we always use
+ * SIGCHLD if we can get it first, and only use the cgroup empty notifications if there's no SIGCHLD pending
+ * (which might happen if the cgroup doesn't contain processes that are our own child, which is typically the
+ * case for scope units). */
+
+ if (u->in_cgroup_empty_queue)
+ return;
+
+ /* Let's verify that the cgroup is really empty */
+ if (!u->cgroup_path)
+ return;
+ r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path);
+ if (r < 0) {
+ log_unit_debug_errno(u, r, "Failed to determine whether cgroup %s is empty: %m", u->cgroup_path);
+ return;
+ }
+ if (r == 0)
+ return;
+
+ LIST_PREPEND(cgroup_empty_queue, u->manager->cgroup_empty_queue, u);
+ u->in_cgroup_empty_queue = true;
+
+ /* Trigger the defer event */
+ r = sd_event_source_set_enabled(u->manager->cgroup_empty_event_source, SD_EVENT_ONESHOT);
+ if (r < 0)
+ log_debug_errno(r, "Failed to enable cgroup empty event source: %m");
+}
+
static int on_cgroup_inotify_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
Manager *m = userdata;
@@ -1728,7 +2104,7 @@ static int on_cgroup_inotify_event(sd_event_source *s, int fd, uint32_t revents,
l = read(fd, &buffer, sizeof(buffer));
if (l < 0) {
- if (errno == EINTR || errno == EAGAIN)
+ if (IN_SET(errno, EINTR, EAGAIN))
return 0;
return log_error_errno(errno, "Failed to read control group inotify events: %m");
@@ -1753,7 +2129,7 @@ static int on_cgroup_inotify_event(sd_event_source *s, int fd, uint32_t revents,
* this here safely. */
continue;
- (void) unit_notify_cgroup_empty(u);
+ unit_add_to_cgroup_empty_queue(u);
}
}
}
@@ -1761,9 +2137,12 @@ static int on_cgroup_inotify_event(sd_event_source *s, int fd, uint32_t revents,
int manager_setup_cgroup(Manager *m) {
_cleanup_free_ char *path = NULL;
+ const char *scope_path;
CGroupController c;
int r, all_unified;
+#if 0 /// UNNEEDED by elogind
char *e;
+#endif // 0
assert(m);
@@ -1794,13 +2173,11 @@ int manager_setup_cgroup(Manager *m) {
*e = 0;
#endif // 0
- /* And make sure to store away the root value without trailing
- * slash, even for the root dir, so that we can easily prepend
- * it everywhere. */
- while ((e = endswith(m->cgroup_root, "/")))
- *e = 0;
log_debug_elogind("Cgroup Controller \"%s\" -> root \"%s\"",
SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root);
+ /* And make sure to store away the root value without trailing slash, even for the root dir, so that we can
+ * easily prepend it everywhere. */
+ delete_trailing_chars(m->cgroup_root, "/");
/* 2. Show data */
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, NULL, &path);
@@ -1812,9 +2189,9 @@ int manager_setup_cgroup(Manager *m) {
return log_error_errno(r, "Couldn't determine if we are running in the unified hierarchy: %m");
all_unified = cg_all_unified();
- if (r < 0)
- return log_error_errno(r, "Couldn't determine whether we are in all unified mode: %m");
- if (r > 0)
+ if (all_unified < 0)
+ return log_error_errno(all_unified, "Couldn't determine whether we are in all unified mode: %m");
+ if (all_unified > 0)
log_debug("Unified cgroup hierarchy is located at %s.", path);
else {
r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
@@ -1826,101 +2203,108 @@ int manager_setup_cgroup(Manager *m) {
log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER_LEGACY ". File system hierarchy is at %s.", path);
}
- if (!m->test_run) {
- const char *scope_path;
-
#if 0 /// elogind is not init, and does not install the agent here.
- /* 3. Install agent */
- if (cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) > 0) {
+ /* 3. Allocate cgroup empty defer event source */
+ m->cgroup_empty_event_source = sd_event_source_unref(m->cgroup_empty_event_source);
+ r = sd_event_add_defer(m->event, &m->cgroup_empty_event_source, on_cgroup_empty_event, m);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create cgroup empty event source: %m");
- /* In the unified hierarchy we can get
- * cgroup empty notifications via inotify. */
+ r = sd_event_source_set_priority(m->cgroup_empty_event_source, SD_EVENT_PRIORITY_NORMAL-5);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set priority of cgroup empty event source: %m");
- m->cgroup_inotify_event_source = sd_event_source_unref(m->cgroup_inotify_event_source);
- safe_close(m->cgroup_inotify_fd);
+ r = sd_event_source_set_enabled(m->cgroup_empty_event_source, SD_EVENT_OFF);
+ if (r < 0)
+ return log_error_errno(r, "Failed to disable cgroup empty event source: %m");
- m->cgroup_inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
- if (m->cgroup_inotify_fd < 0)
- return log_error_errno(errno, "Failed to create control group inotify object: %m");
+ (void) sd_event_source_set_description(m->cgroup_empty_event_source, "cgroup-empty");
- r = sd_event_add_io(m->event, &m->cgroup_inotify_event_source, m->cgroup_inotify_fd, EPOLLIN, on_cgroup_inotify_event, m);
- if (r < 0)
- return log_error_errno(r, "Failed to watch control group inotify object: %m");
+ /* 4. Install notifier inotify object, or agent */
+ if (cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) > 0) {
- /* Process cgroup empty notifications early, but after service notifications and SIGCHLD. Also
- * see handling of cgroup agent notifications, for the classic cgroup hierarchy support. */
- r = sd_event_source_set_priority(m->cgroup_inotify_event_source, SD_EVENT_PRIORITY_NORMAL-5);
- if (r < 0)
- return log_error_errno(r, "Failed to set priority of inotify event source: %m");
+ /* In the unified hierarchy we can get cgroup empty notifications via inotify. */
- (void) sd_event_source_set_description(m->cgroup_inotify_event_source, "cgroup-inotify");
+ m->cgroup_inotify_event_source = sd_event_source_unref(m->cgroup_inotify_event_source);
+ safe_close(m->cgroup_inotify_fd);
- } else if (MANAGER_IS_SYSTEM(m)) {
+ m->cgroup_inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
+ if (m->cgroup_inotify_fd < 0)
+ return log_error_errno(errno, "Failed to create control group inotify object: %m");
- /* On the legacy hierarchy we only get
- * notifications via cgroup agents. (Which
- * isn't really reliable, since it does not
- * generate events when control groups with
- * children run empty. */
+ r = sd_event_add_io(m->event, &m->cgroup_inotify_event_source, m->cgroup_inotify_fd, EPOLLIN, on_cgroup_inotify_event, m);
+ if (r < 0)
+ return log_error_errno(r, "Failed to watch control group inotify object: %m");
- r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, SYSTEMD_CGROUP_AGENT_PATH);
- if (r < 0)
- log_warning_errno(r, "Failed to install release agent, ignoring: %m");
- else if (r > 0)
- log_debug("Installed release agent.");
- else if (r == 0)
- log_debug("Release agent already installed.");
- }
+ /* Process cgroup empty notifications early, but after service notifications and SIGCHLD. Also
+ * see handling of cgroup agent notifications, for the classic cgroup hierarchy support. */
+ r = sd_event_source_set_priority(m->cgroup_inotify_event_source, SD_EVENT_PRIORITY_NORMAL-4);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set priority of inotify event source: %m");
- /* 4. Make sure we are in the special "init.scope" unit in the root slice. */
- scope_path = strjoina(m->cgroup_root, "/" SPECIAL_INIT_SCOPE);
- r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, scope_path, 0);
-#else
- /* Note:
- * This method is in core, and normally called by systemd
- * being init. As elogind is never init, we can not install
- * our agent here. We do so when mounting our cgroup file
- * system, so only if elogind is its own tiny controller.
- * Further, elogind is not meant to run in systemd init scope. */
- if (MANAGER_IS_SYSTEM(m))
- // we are our own cgroup controller
- scope_path = strjoina("");
- else if (streq(m->cgroup_root, "/elogind"))
- // root already is our cgroup
- scope_path = strjoina(m->cgroup_root);
- else
- // we have to create our own group
- scope_path = strjoina(m->cgroup_root, "/elogind");
- r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, scope_path, 0);
-#endif // 0
+ (void) sd_event_source_set_description(m->cgroup_inotify_event_source, "cgroup-inotify");
+
+ } else if (MANAGER_IS_SYSTEM(m) && m->test_run_flags == 0) {
+
+ /* On the legacy hierarchy we only get notifications via cgroup agents. (Which isn't really reliable,
+ * since it does not generate events when control groups with children run empty. */
+
+ r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, SYSTEMD_CGROUP_AGENT_PATH);
if (r < 0)
- return log_error_errno(r, "Failed to create %s control group: %m", scope_path);
- log_debug_elogind("Created control group \"%s\"", scope_path);
+ log_warning_errno(r, "Failed to install release agent, ignoring: %m");
+ else if (r > 0)
+ log_debug("Installed release agent.");
+ else if (r == 0)
+ log_debug("Release agent already installed.");
+ }
-#if 0 /// elogind is not a "sub-controller" like systemd, so migration is not needed.
- /* also, move all other userspace processes remaining
- * in the root cgroup into that scope. */
+ /* 5. Make sure we are in the special "init.scope" unit in the root slice. */
+ scope_path = strjoina(m->cgroup_root, "/" SPECIAL_INIT_SCOPE);
+ r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, scope_path, 0);
+ if (r >= 0) {
+ /* Also, move all other userspace processes remaining in the root cgroup into that scope. */
r = cg_migrate(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, SYSTEMD_CGROUP_CONTROLLER, scope_path, 0);
if (r < 0)
log_warning_errno(r, "Couldn't move remaining userspace processes, ignoring: %m");
+#else
+ /* Note:
+ * This method is in core, and normally called by systemd
+ * being init. As elogind is never init, we can not install
+ * our agent here. We do so when mounting our cgroup file
+ * system, so only if elogind is its own tiny controller.
+ * Further, elogind is not meant to run in systemd init scope. */
+ if (MANAGER_IS_SYSTEM(m))
+ // we are our own cgroup controller
+ scope_path = strjoina("");
+ else if (streq(m->cgroup_root, "/elogind"))
+ // root already is our cgroup
+ scope_path = strjoina(m->cgroup_root);
+ else
+ // we have to create our own group
+ scope_path = strjoina(m->cgroup_root, "/elogind");
+ r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, scope_path, 0);
#endif // 0
+ log_debug_elogind("Created control group \"%s\"", scope_path);
- /* 5. And pin it, so that it cannot be unmounted */
+ /* 6. And pin it, so that it cannot be unmounted */
safe_close(m->pin_cgroupfs_fd);
m->pin_cgroupfs_fd = open(path, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY|O_NONBLOCK);
if (m->pin_cgroupfs_fd < 0)
return log_error_errno(errno, "Failed to open pin file: %m");
- /* 6. Always enable hierarchical support if it exists... */
- if (!all_unified)
- (void) cg_set_attribute("memory", "/", "memory.use_hierarchy", "1");
- }
+#if 0 /// this is from the cgroup migration above that elogind does not need.
+ } else if (r < 0 && !m->test_run_flags)
+ return log_error_errno(r, "Failed to create %s control group: %m", scope_path);
+#endif // 0
+
+ /* 7. Always enable hierarchical support if it exists... */
+ if (!all_unified && m->test_run_flags == 0)
+ (void) cg_set_attribute("memory", "/", "memory.use_hierarchy", "1");
- /* 7. Figure out which controllers are supported */
+ /* 8. Figure out which controllers are supported, and log about it */
r = cg_mask_supported(&m->cgroup_supported);
if (r < 0)
return log_error_errno(r, "Failed to determine supported controllers: %m");
-
for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++)
log_debug("Controller '%s' supported: %s", cgroup_controller_to_string(c), yes_no(m->cgroup_supported & CGROUP_CONTROLLER_TO_MASK(c)));
@@ -1930,12 +2314,14 @@ int manager_setup_cgroup(Manager *m) {
void manager_shutdown_cgroup(Manager *m, bool delete) {
assert(m);
+#if 0 /// elogind is not init
/* We can't really delete the group, since we are in it. But
* let's trim it. */
- if (delete && m->cgroup_root)
+ if (delete && m->cgroup_root && m->test_run_flags != MANAGER_TEST_RUN_MINIMAL)
(void) cg_trim(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, false);
-#if 0 /// elogind does not support the unified hierarchy, yet.
+ m->cgroup_empty_event_source = sd_event_source_unref(m->cgroup_empty_event_source);
+
m->cgroup_inotify_wd_unit = hashmap_free(m->cgroup_inotify_wd_unit);
m->cgroup_inotify_event_source = sd_event_source_unref(m->cgroup_inotify_event_source);
@@ -1977,40 +2363,46 @@ Unit* manager_get_unit_by_cgroup(Manager *m, const char *cgroup) {
Unit *manager_get_unit_by_pid_cgroup(Manager *m, pid_t pid) {
_cleanup_free_ char *cgroup = NULL;
- int r;
assert(m);
- if (pid <= 0)
+ if (!pid_is_valid(pid))
return NULL;
- r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup);
- if (r < 0)
+ if (cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup) < 0)
return NULL;
return manager_get_unit_by_cgroup(m, cgroup);
}
Unit *manager_get_unit_by_pid(Manager *m, pid_t pid) {
- Unit *u;
+ Unit *u, **array;
assert(m);
- if (pid <= 0)
+ /* Note that a process might be owned by multiple units, we return only one here, which is good enough for most
+ * cases, though not strictly correct. We prefer the one reported by cgroup membership, as that's the most
+ * relevant one as children of the process will be assigned to that one, too, before all else. */
+
+ if (!pid_is_valid(pid))
return NULL;
- if (pid == 1)
+ if (pid == getpid_cached())
return hashmap_get(m->units, SPECIAL_INIT_SCOPE);
- u = hashmap_get(m->watch_pids1, PID_TO_PTR(pid));
+ u = manager_get_unit_by_pid_cgroup(m, pid);
if (u)
return u;
- u = hashmap_get(m->watch_pids2, PID_TO_PTR(pid));
+ u = hashmap_get(m->watch_pids, PID_TO_PTR(pid));
if (u)
return u;
- return manager_get_unit_by_pid_cgroup(m, pid);
+ array = hashmap_get(m->watch_pids, PID_TO_PTR(-pid));
+ if (array)
+ return array[0];
+
+ return NULL;
}
#endif // 0
@@ -2021,13 +2413,17 @@ int manager_notify_cgroup_empty(Manager *m, const char *cgroup) {
assert(m);
assert(cgroup);
+ /* Called on the legacy hierarchy whenever we get an explicit cgroup notification from the cgroup agent process
+ * or from the --system instance */
+
log_debug("Got cgroup empty notification for: %s", cgroup);
u = manager_get_unit_by_cgroup(m, cgroup);
if (!u)
return 0;
- return unit_notify_cgroup_empty(u);
+ unit_add_to_cgroup_empty_queue(u);
+ return 1;
}
#else
int manager_notify_cgroup_empty(Manager *m, const char *cgroup) {
@@ -2057,9 +2453,16 @@ int unit_get_memory_current(Unit *u, uint64_t *ret) {
assert(u);
assert(ret);
+ if (!UNIT_CGROUP_BOOL(u, memory_accounting))
+ return -ENODATA;
+
if (!u->cgroup_path)
return -ENODATA;
+ /* The root cgroup doesn't expose this information, let's get it from /proc instead */
+ if (unit_has_root_cgroup(u))
+ return procfs_memory_get_current(ret);
+
if ((u->cgroup_realized_mask & CGROUP_MASK_MEMORY) == 0)
return -ENODATA;
@@ -2085,9 +2488,16 @@ int unit_get_tasks_current(Unit *u, uint64_t *ret) {
assert(u);
assert(ret);
+ if (!UNIT_CGROUP_BOOL(u, tasks_accounting))
+ return -ENODATA;
+
if (!u->cgroup_path)
return -ENODATA;
+ /* The root cgroup doesn't expose this information, let's get it from /proc instead */
+ if (unit_has_root_cgroup(u))
+ return procfs_tasks_get_current(ret);
+
if ((u->cgroup_realized_mask & CGROUP_MASK_PIDS) == 0)
return -ENODATA;
@@ -2111,20 +2521,25 @@ static int unit_get_cpu_usage_raw(Unit *u, nsec_t *ret) {
if (!u->cgroup_path)
return -ENODATA;
+ /* The root cgroup doesn't expose this information, let's get it from /proc instead */
+ if (unit_has_root_cgroup(u))
+ return procfs_cpu_get_usage(ret);
+
r = cg_all_unified();
if (r < 0)
return r;
if (r > 0) {
- const char *keys[] = { "usage_usec", NULL };
_cleanup_free_ char *val = NULL;
uint64_t us;
if ((u->cgroup_realized_mask & CGROUP_MASK_CPU) == 0)
return -ENODATA;
- r = cg_get_keyed_attribute("cpu", u->cgroup_path, "cpu.stat", keys, &val);
+ r = cg_get_keyed_attribute("cpu", u->cgroup_path, "cpu.stat", STRV_MAKE("usage_usec"), &val);
if (r < 0)
return r;
+ if (IN_SET(r, -ENOENT, -ENXIO))
+ return -ENODATA;
r = safe_atou64(val, &us);
if (r < 0)
@@ -2160,6 +2575,9 @@ int unit_get_cpu_usage(Unit *u, nsec_t *ret) {
* started. If the cgroup has been removed already, returns the last cached value. To cache the value, simply
* call this function with a NULL return value. */
+ if (!UNIT_CGROUP_BOOL(u, cpu_accounting))
+ return -ENODATA;
+
r = unit_get_cpu_usage_raw(u, &ns);
if (r == -ENODATA && u->cpu_usage_last != NSEC_INFINITY) {
/* If we can't get the CPU usage anymore (because the cgroup was already removed, for example), use our
@@ -2184,7 +2602,45 @@ int unit_get_cpu_usage(Unit *u, nsec_t *ret) {
return 0;
}
-int unit_reset_cpu_usage(Unit *u) {
+int unit_get_ip_accounting(
+ Unit *u,
+ CGroupIPAccountingMetric metric,
+ uint64_t *ret) {
+
+ uint64_t value;
+ int fd, r;
+
+ assert(u);
+ assert(metric >= 0);
+ assert(metric < _CGROUP_IP_ACCOUNTING_METRIC_MAX);
+ assert(ret);
+
+ if (!UNIT_CGROUP_BOOL(u, ip_accounting))
+ return -ENODATA;
+
+ fd = IN_SET(metric, CGROUP_IP_INGRESS_BYTES, CGROUP_IP_INGRESS_PACKETS) ?
+ u->ip_accounting_ingress_map_fd :
+ u->ip_accounting_egress_map_fd;
+ if (fd < 0)
+ return -ENODATA;
+
+ if (IN_SET(metric, CGROUP_IP_INGRESS_BYTES, CGROUP_IP_EGRESS_BYTES))
+ r = bpf_firewall_read_accounting(fd, &value, NULL);
+ else
+ r = bpf_firewall_read_accounting(fd, NULL, &value);
+ if (r < 0)
+ return r;
+
+ /* Add in additional metrics from a previous runtime. Note that when reexecing/reloading the daemon we compile
+ * all BPF programs and maps anew, but serialize the old counters. When deserializing we store them in the
+ * ip_accounting_extra[] field, and add them in here transparently. */
+
+ *ret = value + u->ip_accounting_extra[metric];
+
+ return r;
+}
+
+int unit_reset_cpu_accounting(Unit *u) {
nsec_t ns;
int r;
@@ -2202,16 +2658,20 @@ int unit_reset_cpu_usage(Unit *u) {
return 0;
}
-bool unit_cgroup_delegate(Unit *u) {
- CGroupContext *c;
+int unit_reset_ip_accounting(Unit *u) {
+ int r = 0, q = 0;
assert(u);
- c = unit_get_cgroup_context(u);
- if (!c)
- return false;
+ if (u->ip_accounting_ingress_map_fd >= 0)
+ r = bpf_firewall_reset_accounting(u->ip_accounting_ingress_map_fd);
- return c->delegate;
+ if (u->ip_accounting_egress_map_fd >= 0)
+ q = bpf_firewall_reset_accounting(u->ip_accounting_egress_map_fd);
+
+ zero(u->ip_accounting_extra);
+
+ return r < 0 ? r : q;
}
void unit_invalidate_cgroup(Unit *u, CGroupMask m) {
@@ -2227,11 +2687,60 @@ void unit_invalidate_cgroup(Unit *u, CGroupMask m) {
if (m & (CGROUP_MASK_IO | CGROUP_MASK_BLKIO))
m |= CGROUP_MASK_IO | CGROUP_MASK_BLKIO;
- if ((u->cgroup_realized_mask & m) == 0)
+ if (m & (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT))
+ m |= CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT;
+
+ if ((u->cgroup_realized_mask & m) == 0) /* NOP? */
return;
u->cgroup_realized_mask &= ~m;
- unit_add_to_cgroup_queue(u);
+ unit_add_to_cgroup_realize_queue(u);
+}
+
+void unit_invalidate_cgroup_bpf(Unit *u) {
+ assert(u);
+
+ if (!UNIT_HAS_CGROUP_CONTEXT(u))
+ return;
+
+ if (u->cgroup_bpf_state == UNIT_CGROUP_BPF_INVALIDATED) /* NOP? */
+ return;
+
+ u->cgroup_bpf_state = UNIT_CGROUP_BPF_INVALIDATED;
+ unit_add_to_cgroup_realize_queue(u);
+
+ /* If we are a slice unit, we also need to put compile a new BPF program for all our children, as the IP access
+ * list of our children includes our own. */
+ if (u->type == UNIT_SLICE) {
+ Unit *member;
+ Iterator i;
+ void *v;
+
+ HASHMAP_FOREACH_KEY(v, member, u->dependencies[UNIT_BEFORE], i) {
+ if (member == u)
+ continue;
+
+ if (UNIT_DEREF(member->slice) != u)
+ continue;
+
+ unit_invalidate_cgroup_bpf(member);
+ }
+ }
+}
+
+bool unit_cgroup_delegate(Unit *u) {
+ CGroupContext *c;
+
+ assert(u);
+
+ if (!UNIT_VTABLE(u)->can_delegate)
+ return false;
+
+ c = unit_get_cgroup_context(u);
+ if (!c)
+ return false;
+
+ return c->delegate;
}
void manager_invalidate_startup_units(Manager *m) {
diff --git a/src/core/cgroup.h b/src/core/cgroup.h
index dd8e436b9..915428e2e 100644
--- a/src/core/cgroup.h
+++ b/src/core/cgroup.h
@@ -1,29 +1,12 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 "cgroup-util.h"
+//#include "ip-address-access.h"
//#include "list.h"
//#include "time-util.h"
-#include "cgroup-util.h"
#if 0 /// UNNEEDED by elogind
typedef struct CGroupContext CGroupContext;
@@ -88,6 +71,7 @@ struct CGroupContext {
bool blockio_accounting;
bool memory_accounting;
bool tasks_accounting;
+ bool ip_accounting;
/* For unified hierarchy */
uint64_t cpu_weight;
@@ -104,6 +88,9 @@ struct CGroupContext {
uint64_t memory_max;
uint64_t memory_swap_max;
+ LIST_HEAD(IPAddressAccessItem, ip_address_allow);
+ LIST_HEAD(IPAddressAccessItem, ip_address_deny);
+
/* For legacy hierarchies */
uint64_t cpu_shares;
uint64_t startup_cpu_shares;
@@ -122,9 +109,21 @@ struct CGroupContext {
uint64_t tasks_max;
bool delegate;
+ CGroupMask delegate_controllers;
};
-#include "unit.h"
+/* Used when querying IP accounting data */
+typedef enum CGroupIPAccountingMetric {
+ CGROUP_IP_INGRESS_BYTES,
+ CGROUP_IP_INGRESS_PACKETS,
+ CGROUP_IP_EGRESS_BYTES,
+ CGROUP_IP_EGRESS_PACKETS,
+ _CGROUP_IP_ACCOUNTING_METRIC_MAX,
+ _CGROUP_IP_ACCOUNTING_METRIC_INVALID = -1,
+} CGroupIPAccountingMetric;
+
+typedef struct Unit Unit;
+typedef struct Manager Manager;
void cgroup_context_init(CGroupContext *c);
void cgroup_context_done(CGroupContext *c);
@@ -139,24 +138,31 @@ void cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODe
void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockIODeviceBandwidth *b);
CGroupMask unit_get_own_mask(Unit *u);
-CGroupMask unit_get_siblings_mask(Unit *u);
+CGroupMask unit_get_delegate_mask(Unit *u);
CGroupMask unit_get_members_mask(Unit *u);
+CGroupMask unit_get_siblings_mask(Unit *u);
CGroupMask unit_get_subtree_mask(Unit *u);
CGroupMask unit_get_target_mask(Unit *u);
CGroupMask unit_get_enable_mask(Unit *u);
+bool unit_get_needs_bpf(Unit *u);
+
void unit_update_cgroup_members_masks(Unit *u);
+const char *unit_get_realized_cgroup_path(Unit *u, CGroupMask mask);
char *unit_default_cgroup_path(Unit *u);
int unit_set_cgroup_path(Unit *u, const char *path);
+int unit_pick_cgroup_path(Unit *u);
int unit_realize_cgroup(Unit *u);
void unit_release_cgroup(Unit *u);
void unit_prune_cgroup(Unit *u);
int unit_watch_cgroup(Unit *u);
-int unit_attach_pids_to_cgroup(Unit *u);
+void unit_add_to_cgroup_empty_queue(Unit *u);
+
+int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const char *suffix_path);
#else
# include "logind.h"
#endif // 0
@@ -165,7 +171,7 @@ int manager_setup_cgroup(Manager *m);
void manager_shutdown_cgroup(Manager *m, bool delete);
#if 0 /// UNNEEDED by elogind
-unsigned manager_dispatch_cgroup_queue(Manager *m);
+unsigned manager_dispatch_cgroup_realize_queue(Manager *m);
Unit *manager_get_unit_by_cgroup(Manager *m, const char *cgroup);
Unit *manager_get_unit_by_pid_cgroup(Manager *m, pid_t pid);
@@ -174,22 +180,39 @@ Unit* manager_get_unit_by_pid(Manager *m, pid_t pid);
int unit_search_main_pid(Unit *u, pid_t *ret);
int unit_watch_all_pids(Unit *u);
+int unit_synthesize_cgroup_empty_event(Unit *u);
+
int unit_get_memory_current(Unit *u, uint64_t *ret);
int unit_get_tasks_current(Unit *u, uint64_t *ret);
int unit_get_cpu_usage(Unit *u, nsec_t *ret);
-int unit_reset_cpu_usage(Unit *u);
+int unit_get_ip_accounting(Unit *u, CGroupIPAccountingMetric metric, uint64_t *ret);
-bool unit_cgroup_delegate(Unit *u);
+int unit_reset_cpu_accounting(Unit *u);
+int unit_reset_ip_accounting(Unit *u);
+
+#define UNIT_CGROUP_BOOL(u, name) \
+ ({ \
+ CGroupContext *cc = unit_get_cgroup_context(u); \
+ cc ? cc->name : false; \
+ })
-int unit_notify_cgroup_empty(Unit *u);
#endif // 0
+bool manager_owns_root_cgroup(Manager *m);
+
+#if 0 /// UNNEEDED by elogind
+bool unit_has_root_cgroup(Unit *u);
+#endif // 0
+
int manager_notify_cgroup_empty(Manager *m, const char *group);
#if 0 /// UNNEEDED by elogind
void unit_invalidate_cgroup(Unit *u, CGroupMask m);
+void unit_invalidate_cgroup_bpf(Unit *u);
void manager_invalidate_startup_units(Manager *m);
const char* cgroup_device_policy_to_string(CGroupDevicePolicy i) _const_;
CGroupDevicePolicy cgroup_device_policy_from_string(const char *s) _pure_;
+
+bool unit_cgroup_delegate(Unit *u);
#endif // 0
diff --git a/src/core/meson.build b/src/core/meson.build
new file mode 100644
index 000000000..22a3c6ba5
--- /dev/null
+++ b/src/core/meson.build
@@ -0,0 +1,234 @@
+# SPDX-License-Identifier: LGPL-2.1+
+
+#if 0 /// elogind has only two of the parts here in it...
+# libcore_la_sources = '''
+# audit-fd.c
+# audit-fd.h
+# automount.c
+# automount.h
+# bpf-firewall.c
+# bpf-firewall.h
+# cgroup.c
+# cgroup.h
+# chown-recursive.c
+# chown-recursive.h
+# dbus-automount.c
+# dbus-automount.h
+# dbus-cgroup.c
+# dbus-cgroup.h
+# dbus-device.c
+# dbus-device.h
+# dbus-execute.c
+# dbus-execute.h
+# dbus-job.c
+# dbus-job.h
+# dbus-kill.c
+# dbus-kill.h
+# dbus-manager.c
+# dbus-manager.h
+# dbus-mount.c
+# dbus-mount.h
+# dbus-path.c
+# dbus-path.h
+# dbus-scope.c
+# dbus-scope.h
+# dbus-service.c
+# dbus-service.h
+# dbus-slice.c
+# dbus-slice.h
+# dbus-socket.c
+# dbus-socket.h
+# dbus-swap.c
+# dbus-swap.h
+# dbus-target.c
+# dbus-target.h
+# dbus-timer.c
+# dbus-timer.h
+# dbus-unit.c
+# dbus-unit.h
+# dbus-util.c
+# dbus-util.h
+# dbus.c
+# dbus.h
+# device.c
+# device.h
+# dynamic-user.c
+# dynamic-user.h
+# emergency-action.c
+# emergency-action.h
+# execute.c
+# execute.h
+# hostname-setup.c
+# hostname-setup.h
+# ima-setup.c
+# ima-setup.h
+# ip-address-access.c
+# ip-address-access.h
+# job.c
+# job.h
+# kill.c
+# kill.h
+# killall.c
+# killall.h
+# kmod-setup.c
+# kmod-setup.h
+# load-dropin.c
+# load-dropin.h
+# load-fragment.c
+# load-fragment.h
+# locale-setup.c
+# locale-setup.h
+# loopback-setup.c
+# loopback-setup.h
+# machine-id-setup.c
+# machine-id-setup.h
+# manager.c
+# manager.h
+# mount-setup.c
+# mount-setup.h
+# mount.c
+# mount.h
+# namespace.c
+# namespace.h
+# path.c
+# path.h
+# scope.c
+# scope.h
+# selinux-access.c
+# selinux-access.h
+# selinux-setup.c
+# selinux-setup.h
+# service.c
+# service.h
+# show-status.c
+# show-status.h
+# slice.c
+# slice.h
+# smack-setup.c
+# smack-setup.h
+# socket.c
+# socket.h
+# swap.c
+# swap.h
+# target.c
+# target.h
+# timer.c
+# timer.h
+# transaction.c
+# transaction.h
+# unit-printf.c
+# unit-printf.h
+# unit.c
+# unit.h
+# '''.split()
+#else
+libcore_la_sources = files('''
+ cgroup.c
+ cgroup.h
+ mount-setup.c
+ mount-setup.h
+'''.split())
+#endif // 0
+
+#if 0 /// The rest is not needed by elogind, we use the sources directly in login
+# load_fragment_gperf_gperf = custom_target(
+# 'load-fragment-gperf.gperf',
+# input : 'load-fragment-gperf.gperf.m4',
+# output: 'load-fragment-gperf.gperf',
+# command : [meson_apply_m4, config_h, '@INPUT@'],
+# capture : true)
+#
+# load_fragment_gperf_c = custom_target(
+# 'load-fragment-gperf.c',
+# input : load_fragment_gperf_gperf,
+# output : 'load-fragment-gperf.c',
+# command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@'])
+#
+# awkscript = 'load-fragment-gperf-nulstr.awk'
+# load_fragment_gperf_nulstr_c = custom_target(
+# 'load-fragment-gperf-nulstr.c',
+# input : [awkscript, load_fragment_gperf_gperf],
+# output : 'load-fragment-gperf-nulstr.c',
+# command : [awk, '-f', '@INPUT0@', '@INPUT1@'],
+# capture : true)
+#
+# libcore = static_library(
+# 'core',
+# libcore_la_sources,
+# load_fragment_gperf_c,
+# load_fragment_gperf_nulstr_c,
+# include_directories : includes,
+# dependencies : [threads,
+# librt,
+# libseccomp,
+# libpam,
+# libaudit,
+# libkmod,
+# libapparmor,
+# libselinux,
+# libmount])
+#
+# systemd_sources = files('main.c')
+#
+# systemd_shutdown_sources = files('''
+# shutdown.c
+# umount.c
+# umount.h
+# mount-setup.c
+# mount-setup.h
+# killall.c
+# killall.h
+# '''.split())
+#
+# in_files = [['macros.systemd', rpmmacrosdir],
+# ['triggers.systemd', ''],
+# ['systemd.pc', pkgconfigdatadir],
+# ['system.conf', pkgsysconfdir]]
+#
+# foreach item : in_files
+# file = item[0]
+# dir = item[1]
+#
+# # If 'no', disable generation completely.
+# # If '', generate, but do not install.
+# if dir != 'no'
+# gen = configure_file(
+# input : file + '.in',
+# output : file,
+# configuration : substs)
+# if dir != ''
+# install_data(gen,
+# install_dir : dir)
+# endif
+# endif
+# endforeach
+#
+# install_data('org.freedesktop.systemd1.conf',
+# install_dir : dbuspolicydir)
+# install_data('org.freedesktop.systemd1.service',
+# install_dir : dbussystemservicedir)
+#
+# policy = configure_file(
+# input : 'org.freedesktop.systemd1.policy.in',
+# output : 'org.freedesktop.systemd1.policy',
+# configuration : substs)
+# install_data(policy,
+# install_dir : polkitpolicydir)
+#
+# install_data('user.conf',
+# install_dir : pkgsysconfdir)
+#
+# meson.add_install_script('sh', '-c', mkdir_p.format(systemshutdowndir))
+# meson.add_install_script('sh', '-c', mkdir_p.format(systemsleepdir))
+# meson.add_install_script('sh', '-c', mkdir_p.format(systemgeneratordir))
+# meson.add_install_script('sh', '-c', mkdir_p.format(usergeneratordir))
+#
+# meson.add_install_script('sh', '-c',
+# mkdir_p.format(join_paths(pkgsysconfdir, 'system/multi-user.target.wants')))
+# meson.add_install_script('sh', '-c',
+# mkdir_p.format(join_paths(pkgsysconfdir, 'system/getty.target.wants')))
+# meson.add_install_script('sh', '-c',
+# mkdir_p.format(join_paths(pkgsysconfdir, 'user')))
+# meson.add_install_script('sh', '-c',
+# mkdir_p.format(join_paths(sysconfdir, 'xdg/systemd')))
+#endif // 0
diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c
index 5a5bc7fda..dd089e679 100644
--- a/src/core/mount-setup.c
+++ b/src/core/mount-setup.c
@@ -1,26 +1,10 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <ftw.h>
#include <stdlib.h>
#include <sys/mount.h>
+//#include <sys/statvfs.h>
#include <unistd.h>
#include "alloc-util.h"
@@ -28,6 +12,7 @@
#include "cgroup-util.h"
//#include "dev-setup.h"
//#include "efivars.h"
+//#include "fileio.h"
#include "fs-util.h"
#include "label.h"
//#include "log.h"
@@ -48,9 +33,10 @@
#include "string-util.h"
typedef enum MountMode {
- MNT_NONE = 0,
- MNT_FATAL = 1 << 0,
- MNT_IN_CONTAINER = 1 << 1,
+ MNT_NONE = 0,
+ MNT_FATAL = 1 << 0,
+ MNT_IN_CONTAINER = 1 << 1,
+ MNT_CHECK_WRITABLE = 1 << 2,
} MountMode;
typedef struct MountPoint {
@@ -67,7 +53,7 @@ typedef struct MountPoint {
* fourth (securityfs) is needed by IMA to load a custom policy. The
* other ones we can delay until SELinux and IMA are loaded. When
* SMACK is enabled we need smackfs, too, so it's a fifth one. */
-#ifdef HAVE_SMACK
+#if ENABLE_SMACK
#define N_EARLY_MOUNT 5
#else
#define N_EARLY_MOUNT 4
@@ -83,7 +69,7 @@ static const MountPoint mount_table[] = {
NULL, MNT_FATAL|MNT_IN_CONTAINER },
{ "securityfs", "/sys/kernel/security", "securityfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
NULL, MNT_NONE },
-#ifdef HAVE_SMACK
+#if ENABLE_SMACK
{ "smackfs", "/sys/fs/smackfs", "smackfs", "smackfsdef=*", MS_NOSUID|MS_NOEXEC|MS_NODEV,
mac_smack_use, MNT_FATAL },
{ "tmpfs", "/dev/shm", "tmpfs", "mode=1777,smackfsroot=*", MS_NOSUID|MS_NODEV|MS_STRICTATIME,
@@ -93,34 +79,40 @@ static const MountPoint mount_table[] = {
NULL, MNT_FATAL|MNT_IN_CONTAINER },
{ "devpts", "/dev/pts", "devpts", "mode=620,gid=" STRINGIFY(TTY_GID), MS_NOSUID|MS_NOEXEC,
NULL, MNT_IN_CONTAINER },
-#ifdef HAVE_SMACK
+#if ENABLE_SMACK
{ "tmpfs", "/run", "tmpfs", "mode=755,smackfsroot=*", MS_NOSUID|MS_NODEV|MS_STRICTATIME,
mac_smack_use, MNT_FATAL },
#endif
{ "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME,
NULL, MNT_FATAL|MNT_IN_CONTAINER },
- { "cgroup", "/sys/fs/cgroup", "cgroup2", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
- cg_is_unified_wanted, MNT_IN_CONTAINER },
#endif // 0
+ { "cgroup2", "/sys/fs/cgroup", "cgroup2", "nsdelegate", MS_NOSUID|MS_NOEXEC|MS_NODEV,
+ cg_is_unified_wanted, MNT_IN_CONTAINER|MNT_CHECK_WRITABLE },
+ { "cgroup2", "/sys/fs/cgroup", "cgroup2", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
+ cg_is_unified_wanted, MNT_IN_CONTAINER|MNT_CHECK_WRITABLE },
{ "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME,
cg_is_legacy_wanted, MNT_FATAL|MNT_IN_CONTAINER },
+ { "cgroup2", "/sys/fs/cgroup/unified", "cgroup2", "nsdelegate", MS_NOSUID|MS_NOEXEC|MS_NODEV,
+ cg_is_hybrid_wanted, MNT_IN_CONTAINER|MNT_CHECK_WRITABLE },
+ { "cgroup2", "/sys/fs/cgroup/unified", "cgroup2", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
+ cg_is_hybrid_wanted, MNT_IN_CONTAINER|MNT_CHECK_WRITABLE },
#if 0 /// UNNEEDED by elogind
- { "cgroup", "/sys/fs/cgroup/unified", "cgroup2", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
- cg_is_hybrid_wanted, MNT_IN_CONTAINER },
{ "cgroup", "/sys/fs/cgroup/systemd", "cgroup", "none,name=systemd,xattr", MS_NOSUID|MS_NOEXEC|MS_NODEV,
cg_is_legacy_wanted, MNT_IN_CONTAINER },
{ "cgroup", "/sys/fs/cgroup/systemd", "cgroup", "none,name=systemd", MS_NOSUID|MS_NOEXEC|MS_NODEV,
cg_is_legacy_wanted, MNT_FATAL|MNT_IN_CONTAINER },
{ "pstore", "/sys/fs/pstore", "pstore", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
NULL, MNT_NONE },
-#ifdef ENABLE_EFI
+#if ENABLE_EFI
{ "efivarfs", "/sys/firmware/efi/efivars", "efivarfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
is_efi_boot, MNT_NONE },
#endif
+ { "bpf", "/sys/fs/bpf", "bpf", "mode=700", MS_NOSUID|MS_NOEXEC|MS_NODEV,
+ NULL, MNT_NONE, },
#else
{ "cgroup", "/sys/fs/cgroup/elogind", "cgroup", "none,name=elogind,release_agent="SYSTEMD_CGROUP_AGENT_PATH",xattr", MS_NOSUID|MS_NOEXEC|MS_NODEV,
cg_is_legacy_wanted, MNT_IN_CONTAINER },
- { "cgroup", "/sys/fs/cgroup/elogind", "cgroup", "none,name=elogind,release_agent="SYSTEMD_CGROUP_AGENT_PATH, MS_NOSUID|MS_NOEXEC|MS_NODEV,
+ { "cgroup", "/sys/fs/cgroup/elogind", "cgroup", "none,name=elogind,release_agent="SYSTEMD_CGROUP_AGENT_PATH, MS_NOSUID|MS_NOEXEC|MS_NODEV,
cg_is_legacy_wanted, MNT_FATAL|MNT_IN_CONTAINER },
#endif // 0
};
@@ -162,20 +154,22 @@ bool mount_point_ignore(const char *path) {
#endif // 0
static int mount_one(const MountPoint *p, bool relabel) {
- int r;
+ int r, priority;
assert(p);
+ priority = (p->mode & MNT_FATAL) ? LOG_ERR : LOG_DEBUG;
+
if (p->condition_fn && !p->condition_fn())
return 0;
/* Relabel first, just in case */
if (relabel)
- (void) label_fix(p->where, true, true);
+ (void) label_fix(p->where, LABEL_IGNORE_ENOENT|LABEL_IGNORE_EROFS);
r = path_is_mount_point(p->where, NULL, AT_SYMLINK_FOLLOW);
if (r < 0 && r != -ENOENT) {
- log_full_errno((p->mode & MNT_FATAL) ? LOG_ERR : LOG_DEBUG, r, "Failed to determine whether %s is a mount point: %m", p->where);
+ log_full_errno(priority, r, "Failed to determine whether %s is a mount point: %m", p->where);
return (p->mode & MNT_FATAL) ? r : 0;
}
if (r > 0)
@@ -203,13 +197,25 @@ static int mount_one(const MountPoint *p, bool relabel) {
p->type,
p->flags,
p->options) < 0) {
- log_full_errno((p->mode & MNT_FATAL) ? LOG_ERR : LOG_DEBUG, errno, "Failed to mount %s at %s: %m", p->type, p->where);
+ log_full_errno(priority, errno, "Failed to mount %s at %s: %m", p->type, p->where);
return (p->mode & MNT_FATAL) ? -errno : 0;
}
/* Relabel again, since we now mounted something fresh here */
if (relabel)
- (void) label_fix(p->where, false, false);
+ (void) label_fix(p->where, 0);
+
+ if (p->mode & MNT_CHECK_WRITABLE) {
+ if (access(p->where, W_OK) < 0) {
+ r = -errno;
+
+ (void) umount(p->where);
+ (void) rmdir(p->where);
+
+ log_full_errno(priority, r, "Mount point %s not writable after mounting: %m", p->where);
+ return (p->mode & MNT_FATAL) ? r : 0;
+ }
+ }
return 1;
}
@@ -240,6 +246,7 @@ int mount_setup_early(void) {
int mount_cgroup_controllers(char ***join_controllers) {
_cleanup_set_free_free_ Set *controllers = NULL;
+ bool has_argument = !!join_controllers;
int r;
if (!cg_is_legacy_wanted())
@@ -247,11 +254,20 @@ int mount_cgroup_controllers(char ***join_controllers) {
/* Mount all available cgroup controllers that are built into the kernel. */
- controllers = set_new(&string_hash_ops);
- if (!controllers)
- return log_oom();
+ if (!has_argument)
+ /* The defaults:
+ * mount "cpu" + "cpuacct" together, and "net_cls" + "net_prio".
+ *
+ * We'd like to add "cpuset" to the mix, but "cpuset" doesn't really
+ * work for groups with no initialized attributes.
+ */
+ join_controllers = (char**[]) {
+ STRV_MAKE("cpu", "cpuacct"),
+ STRV_MAKE("net_cls", "net_prio"),
+ NULL,
+ };
- r = cg_kernel_controllers(controllers);
+ r = cg_kernel_controllers(&controllers);
if (r < 0)
return log_error_errno(r, "Failed to enumerate cgroup controllers: %m");
@@ -269,12 +285,11 @@ int mount_cgroup_controllers(char ***join_controllers) {
if (!controller)
break;
- if (join_controllers)
- for (k = join_controllers; *k; k++)
- if (strv_find(*k, controller))
- break;
+ for (k = join_controllers; *k; k++)
+ if (strv_find(*k, controller))
+ break;
- if (k && *k) {
+ if (*k) {
char **i, **j;
for (i = *k, j = *k; *i; i++) {
@@ -284,7 +299,8 @@ int mount_cgroup_controllers(char ***join_controllers) {
t = set_remove(controllers, *i);
if (!t) {
- free(*i);
+ if (has_argument)
+ free(*i);
continue;
}
}
@@ -297,10 +313,8 @@ int mount_cgroup_controllers(char ***join_controllers) {
options = strv_join(*k, ",");
if (!options)
return log_oom();
- } else {
- options = controller;
- controller = NULL;
- }
+ } else
+ options = TAKE_PTR(controller);
where = strappend("/sys/fs/cgroup/", options);
if (!where)
@@ -313,7 +327,7 @@ int mount_cgroup_controllers(char ***join_controllers) {
if (r < 0)
return r;
- if (r > 0 && k && *k) {
+ if (r > 0 && *k) {
char **i;
for (i = *k; *i; i++) {
@@ -347,7 +361,7 @@ int mount_cgroup_controllers(char ***join_controllers) {
return 0;
}
-#if defined(HAVE_SELINUX) || defined(HAVE_SMACK)
+#if HAVE_SELINUX || ENABLE_SMACK
static int nftw_cb(
const char *fpath,
const struct stat *sb,
@@ -358,7 +372,7 @@ static int nftw_cb(
if (_unlikely_(ftwbuf->level == 0))
return FTW_CONTINUE;
- label_fix(fpath, false, false);
+ (void) label_fix(fpath, 0);
/* /run/initramfs is static data and big, no need to
* dynamically relabel its contents at boot... */
@@ -369,6 +383,34 @@ static int nftw_cb(
return FTW_CONTINUE;
};
+
+static int relabel_cgroup_filesystems(void) {
+ int r;
+ struct statfs st;
+
+ r = cg_all_unified();
+ if (r == 0) {
+ /* Temporarily remount the root cgroup filesystem to give it a proper label. Do this
+ only when the filesystem has been already populated by a previous instance of systemd
+ running from initrd. Otherwise don't remount anything and leave the filesystem read-write
+ for the cgroup filesystems to be mounted inside. */
+ if (statfs("/sys/fs/cgroup", &st) < 0)
+ return log_error_errno(errno, "Failed to determine mount flags for /sys/fs/cgroup: %m");
+
+ if (st.f_flags & ST_RDONLY)
+ (void) mount(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT, NULL);
+
+ (void) label_fix("/sys/fs/cgroup", 0);
+ (void) nftw("/sys/fs/cgroup", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
+
+ if (st.f_flags & ST_RDONLY)
+ (void) mount(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT|MS_RDONLY, NULL);
+
+ } else if (r < 0)
+ return log_error_errno(r, "Failed to determine whether we are in all unified mode: %m");
+
+ return 0;
+}
#endif
#endif // 0
@@ -380,7 +422,7 @@ int mount_setup(bool loaded_policy) {
return r;
#if 0 /// elogind does not control /, /dev, /run and /run/systemd/* are setup elsewhere.
-#if defined(HAVE_SELINUX) || defined(HAVE_SMACK)
+#if HAVE_SELINUX || ENABLE_SMACK
/* 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
@@ -391,13 +433,17 @@ int mount_setup(bool loaded_policy) {
before_relabel = now(CLOCK_MONOTONIC);
- nftw("/dev", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
- nftw("/dev/shm", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
- nftw("/run", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
+ (void) nftw("/dev", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
+ (void) nftw("/dev/shm", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
+ (void) nftw("/run", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
+
+ r = relabel_cgroup_filesystems();
+ if (r < 0)
+ return r;
after_relabel = now(CLOCK_MONOTONIC);
- log_info("Relabelled /dev and /run in %s.",
+ log_info("Relabelled /dev, /run and /sys/fs/cgroup in %s.",
format_timespan(timespan, sizeof(timespan), after_relabel - before_relabel, 0));
}
#endif
@@ -426,14 +472,20 @@ int mount_setup(bool loaded_policy) {
(void) mkdir_label("/run/systemd/system", 0755);
#endif // 0
- /* Set up inaccessible items */
+ /* Set up inaccessible (and empty) file nodes of all types */
(void) mkdir_label("/run/systemd/inaccessible", 0000);
(void) mknod("/run/systemd/inaccessible/reg", S_IFREG | 0000, 0);
(void) mkdir_label("/run/systemd/inaccessible/dir", 0000);
- (void) mknod("/run/systemd/inaccessible/chr", S_IFCHR | 0000, makedev(0, 0));
- (void) mknod("/run/systemd/inaccessible/blk", S_IFBLK | 0000, makedev(0, 0));
(void) mkfifo("/run/systemd/inaccessible/fifo", 0000);
(void) mknod("/run/systemd/inaccessible/sock", S_IFSOCK | 0000, 0);
+ /* The following two are likely to fail if we lack the privs for it (for example in an userns environment, if
+ * CAP_SYS_MKNOD is missing, or if a device node policy prohibit major/minor of 0 device nodes to be
+ * created). But that's entirely fine. Consumers of these files should carry fallback to use a different node
+ * then, for example /run/systemd/inaccessible/sock, which is close enough in behaviour and semantics for most
+ * uses. */
+ (void) mknod("/run/systemd/inaccessible/chr", S_IFCHR | 0000, makedev(0, 0));
+ (void) mknod("/run/systemd/inaccessible/blk", S_IFBLK | 0000, makedev(0, 0));
+
return 0;
}
diff --git a/src/core/mount-setup.h b/src/core/mount-setup.h
index b6c2d7cb8..5dc75e2ef 100644
--- a/src/core/mount-setup.h
+++ b/src/core/mount-setup.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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>
#if 0 /// UNNEEDED by elogind
diff --git a/src/libelogind/.gitignore b/src/libelogind/.gitignore
deleted file mode 100644
index 17111f7a3..000000000
--- a/src/libelogind/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/libelogind.pc
diff --git a/src/libelogind/Makefile b/src/libelogind/Makefile
deleted file mode 120000
index d0b0e8e00..000000000
--- a/src/libelogind/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/libelogind/libelogind.pc.in b/src/libelogind/libelogind.pc.in
index 015cb721f..2fd18b983 100644
--- a/src/libelogind/libelogind.pc.in
+++ b/src/libelogind/libelogind.pc.in
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# This file is part of elogind.
#
# elogind is free software; you can redistribute it and/or modify it
@@ -8,7 +10,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@rootlibdir@
+#if 0 /// To be able to act as a drop-in replacement, elogind has a systemd subdir
+# includedir=@includedir@
+#else
includedir=@includedir@/elogind
+#endif // 0
Name: elogind
Description: elogind Library
diff --git a/src/libelogind/libelogind.sym b/src/libelogind/libelogind.sym
index f7613e5e1..788e10034 100644
--- a/src/libelogind/libelogind.sym
+++ b/src/libelogind/libelogind.sym
@@ -1,5 +1,5 @@
/***
- This file is part of systemd.
+ SPDX-License-Identifier: LGPL-2.1+
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
@@ -363,9 +363,9 @@ global:
sd_bus_creds_get_cmdline;
sd_bus_creds_get_cgroup;
/* sd_bus_creds_get_unit; */
- /* sd_bus_creds_get_slice; */
+ sd_bus_creds_get_slice;
/* sd_bus_creds_get_user_unit; */
- /* sd_bus_creds_get_user_slice; */
+ sd_bus_creds_get_user_slice;
sd_bus_creds_get_session;
sd_bus_creds_get_owner_uid;
sd_bus_creds_has_effective_cap;
@@ -482,30 +482,30 @@ global:
sd_listen_fds_with_names;
} LIBSYSTEMD_226;
-/*
- * These methods are not needed by elogind.
- * LIBSYSTEMD_229 {
- * global:
- * sd_journal_has_runtime_files;
- * sd_journal_has_persistent_files;
- * sd_journal_enumerate_fields;
- * sd_journal_restart_fields;
- * } LIBSYSTEMD_227;
-*/
-
-/*
- * These methods are not needed by elogind.
- * LIBSYSTEMD_230 {
- * global:
- * sd_journal_open_directory_fd;
- * sd_journal_open_files_fd;
- * } LIBSYSTEMD_229;
-*/
+/** 0 /// UNNEEDED by elogind
+ * LIBSYSTEMD_229 {
+ * global:
+ * sd_journal_has_runtime_files;
+ * sd_journal_has_persistent_files;
+ * sd_journal_enumerate_fields;
+ * sd_journal_restart_fields;
+ * } LIBSYSTEMD_227;
+ *
+ * LIBSYSTEMD_230 {
+ * global:
+ * sd_journal_open_directory_fd;
+ * sd_journal_open_files_fd;
+ * } LIBSYSTEMD_229;
+ * // 0 **/
LIBSYSTEMD_231 {
global:
sd_event_get_iteration;
+/** 0 /// Previous blocks unused by elogind
+ * } LIBSYSTEMD_230;
+ * else **/
} LIBSYSTEMD_227;
+/** // 0 **/
LIBSYSTEMD_232 {
global:
@@ -521,10 +521,58 @@ global:
LIBSYSTEMD_233 {
global:
sd_id128_get_machine_app_specific;
- /* sd_is_socket_sockaddr; */
+ sd_is_socket_sockaddr;
} LIBSYSTEMD_232;
LIBSYSTEMD_234 {
global:
sd_bus_message_appendv;
} LIBSYSTEMD_233;
+
+LIBSYSTEMD_236 {
+global:
+ sd_bus_message_new;
+ sd_bus_message_seal;
+} LIBSYSTEMD_234;
+
+LIBSYSTEMD_237 {
+global:
+ sd_bus_set_watch_bind;
+ sd_bus_get_watch_bind;
+ sd_bus_request_name_async;
+ sd_bus_release_name_async;
+ sd_bus_add_match_async;
+ sd_bus_match_signal;
+ sd_bus_match_signal_async;
+ sd_bus_is_ready;
+ sd_bus_set_connected_signal;
+ sd_bus_get_connected_signal;
+ sd_bus_set_sender;
+ sd_bus_get_sender;
+ sd_bus_message_set_sender;
+ sd_event_source_get_io_fd_own;
+ sd_event_source_set_io_fd_own;
+} LIBSYSTEMD_236;
+
+LIBSYSTEMD_238 {
+global:
+ sd_bus_get_n_queued_read;
+ sd_bus_get_n_queued_write;
+} LIBSYSTEMD_237;
+
+LIBSYSTEMD_239 {
+global:
+ sd_bus_open_with_description;
+ sd_bus_open_user_with_description;
+ sd_bus_open_system_with_description;
+ sd_bus_slot_get_floating;
+ sd_bus_slot_set_floating;
+ sd_bus_slot_get_destroy_callback;
+ sd_bus_slot_set_destroy_callback;
+ sd_bus_track_get_destroy_callback;
+ sd_bus_track_set_destroy_callback;
+ sd_event_add_inotify;
+ sd_event_source_get_inotify_mask;
+ sd_event_source_set_destroy_callback;
+ sd_event_source_get_destroy_callback;
+} LIBSYSTEMD_238;
diff --git a/src/libelogind/meson.build b/src/libelogind/meson.build
new file mode 100644
index 000000000..dfecea3bc
--- /dev/null
+++ b/src/libelogind/meson.build
@@ -0,0 +1,153 @@
+# SPDX-License-Identifier: LGPL-2.1+
+
+id128_sources = files('''
+ sd-id128/id128-util.c
+ sd-id128/id128-util.h
+ sd-id128/sd-id128.c
+'''.split())
+
+sd_daemon_c = files('sd-daemon/sd-daemon.c')
+sd_event_c = files('sd-event/sd-event.c')
+sd_login_c = files('sd-login/sd-login.c')
+
+#if 0 /// elogind has a shorter list, of course...
+# libsystemd_sources = files('''
+# sd-bus/bus-common-errors.c
+# sd-bus/bus-common-errors.h
+# sd-bus/bus-container.c
+# sd-bus/bus-container.h
+# sd-bus/bus-control.c
+# sd-bus/bus-control.h
+# sd-bus/bus-convenience.c
+# sd-bus/bus-creds.c
+# sd-bus/bus-creds.h
+# sd-bus/bus-dump.c
+# sd-bus/bus-dump.h
+# sd-bus/bus-error.c
+# sd-bus/bus-error.h
+# sd-bus/bus-gvariant.c
+# sd-bus/bus-gvariant.h
+# sd-bus/bus-internal.c
+# sd-bus/bus-internal.h
+# sd-bus/bus-introspect.c
+# sd-bus/bus-introspect.h
+# sd-bus/bus-kernel.c
+# sd-bus/bus-kernel.h
+# sd-bus/bus-match.c
+# sd-bus/bus-match.h
+# sd-bus/bus-message.c
+# sd-bus/bus-message.h
+# sd-bus/bus-objects.c
+# sd-bus/bus-objects.h
+# sd-bus/bus-protocol.h
+# sd-bus/bus-signature.c
+# sd-bus/bus-signature.h
+# sd-bus/bus-slot.c
+# sd-bus/bus-slot.h
+# sd-bus/bus-socket.c
+# sd-bus/bus-socket.h
+# sd-bus/bus-track.c
+# sd-bus/bus-track.h
+# sd-bus/bus-type.c
+# sd-bus/bus-type.h
+# sd-bus/sd-bus.c
+# sd-device/device-enumerator-private.h
+# sd-device/device-enumerator.c
+# sd-device/device-internal.h
+# sd-device/device-private.c
+# sd-device/device-private.h
+# sd-device/device-util.h
+# sd-device/sd-device.c
+# sd-hwdb/hwdb-internal.h
+# sd-hwdb/hwdb-util.h
+# sd-hwdb/sd-hwdb.c
+# sd-netlink/generic-netlink.c
+# sd-netlink/local-addresses.c
+# sd-netlink/local-addresses.h
+# sd-netlink/netlink-internal.h
+# sd-netlink/netlink-message.c
+# sd-netlink/netlink-socket.c
+# sd-netlink/netlink-types.c
+# sd-netlink/netlink-types.h
+# sd-netlink/netlink-util.c
+# sd-netlink/netlink-util.h
+# sd-netlink/rtnl-message.c
+# sd-netlink/sd-netlink.c
+# sd-network/network-util.c
+# sd-network/network-util.h
+# sd-network/sd-network.c
+# sd-path/sd-path.c
+# sd-resolve/sd-resolve.c
+# sd-utf8/sd-utf8.c
+# '''.split()) + id128_sources + sd_daemon_c + sd_event_c + sd_login_c
+#else
+libelogind_sources = files('''
+ sd-bus/bus-common-errors.c
+ sd-bus/bus-common-errors.h
+ sd-bus/bus-container.c
+ sd-bus/bus-container.h
+ sd-bus/bus-control.c
+ sd-bus/bus-control.h
+ sd-bus/bus-convenience.c
+ sd-bus/bus-creds.c
+ sd-bus/bus-creds.h
+ sd-bus/bus-error.c
+ sd-bus/bus-error.h
+ sd-bus/bus-gvariant.c
+ sd-bus/bus-gvariant.h
+ sd-bus/bus-internal.c
+ sd-bus/bus-internal.h
+ sd-bus/bus-introspect.c
+ sd-bus/bus-introspect.h
+ sd-bus/bus-kernel.c
+ sd-bus/bus-kernel.h
+ sd-bus/bus-match.c
+ sd-bus/bus-match.h
+ sd-bus/bus-message.c
+ sd-bus/bus-message.h
+ sd-bus/bus-objects.c
+ sd-bus/bus-objects.h
+ sd-bus/bus-protocol.h
+ sd-bus/bus-signature.c
+ sd-bus/bus-signature.h
+ sd-bus/bus-slot.c
+ sd-bus/bus-slot.h
+ sd-bus/bus-socket.c
+ sd-bus/bus-socket.h
+ sd-bus/bus-track.c
+ sd-bus/bus-track.h
+ sd-bus/bus-type.c
+ sd-bus/bus-type.h
+ sd-bus/sd-bus.c
+ sd-daemon/sd-daemon.c
+ sd-event/sd-event.c
+ sd-id128/id128-util.c
+ sd-id128/id128-util.h
+ sd-id128/sd-id128.c
+'''.split()) + sd_login_c
+#endif // 0
+
+libelogind_c_args = ['-fvisibility=default']
+
+libelogind_static = static_library(
+ 'elogind_static',
+ libelogind_sources,
+ install : false,
+ include_directories : includes,
+ link_with : libbasic,
+#if 0 /// elogind does not need librt
+# dependencies : [threads,
+# librt],
+#else
+ dependencies : [threads],
+#endif // 0
+ c_args : libelogind_c_args)
+
+libelogind_sym = 'src/libelogind/libelogind.sym'
+
+libelogind_pc = configure_file(
+ input : 'libelogind.pc.in',
+ output : 'libelogind.pc',
+ configuration : substs)
+install_data(libelogind_pc,
+ install_dir : pkgconfiglibdir)
diff --git a/src/libelogind/sd-bus/Makefile b/src/libelogind/sd-bus/Makefile
deleted file mode 120000
index 94aaae2c4..000000000
--- a/src/libelogind/sd-bus/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../../Makefile \ No newline at end of file
diff --git a/src/libelogind/sd-bus/bus-bloom.c b/src/libelogind/sd-bus/bus-bloom.c
deleted file mode 100644
index 112769fcb..000000000
--- a/src/libelogind/sd-bus/bus-bloom.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "bus-bloom.h"
-#include "siphash24.h"
-#include "util.h"
-
-static inline void set_bit(uint64_t filter[], unsigned long b) {
- filter[b >> 6] |= 1ULL << (b & 63);
-}
-
-static const sd_id128_t hash_keys[] = {
- SD_ID128_ARRAY(b9,66,0b,f0,46,70,47,c1,88,75,c4,9c,54,b9,bd,15),
- SD_ID128_ARRAY(aa,a1,54,a2,e0,71,4b,39,bf,e1,dd,2e,9f,c5,4a,3b),
- SD_ID128_ARRAY(63,fd,ae,be,cd,82,48,12,a1,6e,41,26,cb,fa,a0,c8),
- SD_ID128_ARRAY(23,be,45,29,32,d2,46,2d,82,03,52,28,fe,37,17,f5),
- SD_ID128_ARRAY(56,3b,bf,ee,5a,4f,43,39,af,aa,94,08,df,f0,fc,10),
- SD_ID128_ARRAY(31,80,c8,73,c7,ea,46,d3,aa,25,75,0f,9e,4c,09,29),
- SD_ID128_ARRAY(7d,f7,18,4b,7b,a4,44,d5,85,3c,06,e0,65,53,96,6d),
- SD_ID128_ARRAY(f2,77,e9,6f,93,b5,4e,71,9a,0c,34,88,39,25,bf,35),
-};
-
-static void bloom_add_data(
- uint64_t filter[], /* The filter bits */
- size_t size, /* Size of the filter in bytes */
- unsigned k, /* Number of hash functions */
- const void *data, /* Data to hash */
- size_t n) { /* Size of data to hash in bytes */
-
- uint64_t h;
- uint64_t m;
- unsigned w, i, c = 0;
- unsigned hash_index;
-
- assert(size > 0);
- assert(k > 0);
-
- /* Determine bits in filter */
- m = size * 8;
-
- /* Determine how many bytes we need to generate a bit index 0..m for this filter */
- w = (u64log2(m) + 7) / 8;
-
- assert(w <= sizeof(uint64_t));
-
- /* Make sure we have enough hash keys to generate m * k bits
- * of hash value. Note that SipHash24 generates 64 bits of
- * hash value for each 128 bits of hash key. */
- assert(k * w <= ELEMENTSOF(hash_keys) * 8);
-
- for (i = 0, hash_index = 0; i < k; i++) {
- uint64_t p = 0;
- unsigned d;
-
- for (d = 0; d < w; d++) {
- if (c <= 0) {
- h = siphash24(data, n, hash_keys[hash_index++].bytes);
- c += 8;
- }
-
- p = (p << 8ULL) | (uint64_t) ((uint8_t *)&h)[8 - c];
- c--;
- }
-
- p &= m - 1;
- set_bit(filter, p);
- }
-
- /* log_debug("bloom: adding <%.*s>", (int) n, (char*) data); */
-}
-
-void bloom_add_pair(uint64_t filter[], size_t size, unsigned k, const char *a, const char *b) {
- size_t n;
- char *c;
-
- assert(filter);
- assert(a);
- assert(b);
-
- n = strlen(a) + 1 + strlen(b);
- c = alloca(n + 1);
- strcpy(stpcpy(stpcpy(c, a), ":"), b);
-
- bloom_add_data(filter, size, k, c, n);
-}
-
-void bloom_add_prefixes(uint64_t filter[], size_t size, unsigned k, const char *a, const char *b, char sep) {
- size_t n;
- char *c, *p;
-
- assert(filter);
- assert(a);
- assert(b);
-
- n = strlen(a) + 1 + strlen(b);
- c = alloca(n + 1);
-
- p = stpcpy(stpcpy(c, a), ":");
- strcpy(p, b);
-
- bloom_add_data(filter, size, k, c, n);
-
- for (;;) {
- char *e;
-
- e = strrchr(p, sep);
- if (!e)
- break;
-
- *(e + 1) = 0;
- bloom_add_data(filter, size, k, c, e - c + 1);
-
- if (e == p)
- break;
-
- *e = 0;
- bloom_add_data(filter, size, k, c, e - c);
- }
-}
-
-bool bloom_validate_parameters(size_t size, unsigned k) {
- uint64_t m;
- unsigned w;
-
- if (size <= 0)
- return false;
-
- if (k <= 0)
- return false;
-
- m = size * 8;
- w = (u64log2(m) + 7) / 8;
- if (w > sizeof(uint64_t))
- return false;
-
- if (k * w > ELEMENTSOF(hash_keys) * 8)
- return false;
-
- return true;
-}
diff --git a/src/libelogind/sd-bus/bus-bloom.h b/src/libelogind/sd-bus/bus-bloom.h
deleted file mode 100644
index c824622b9..000000000
--- a/src/libelogind/sd-bus/bus-bloom.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 <stddef.h>
-#include <stdint.h>
-
-/*
- * Our default bloom filter has the following parameters:
- *
- * m=512 (bits in the filter)
- * k=8 (hash functions)
- *
- * We use SipHash24 as hash function with a number of (originally
- * randomized) but fixed hash keys.
- *
- */
-
-#define DEFAULT_BLOOM_SIZE (512/8) /* m: filter size */
-#define DEFAULT_BLOOM_N_HASH 8 /* k: number of hash functions */
-
-void bloom_add_pair(uint64_t filter[], size_t size, unsigned n_hash, const char *a, const char *b);
-void bloom_add_prefixes(uint64_t filter[], size_t size, unsigned n_hash, const char *a, const char *b, char sep);
-
-bool bloom_validate_parameters(size_t size, unsigned n_hash);
diff --git a/src/libelogind/sd-bus/bus-common-errors.c b/src/libelogind/sd-bus/bus-common-errors.c
index a6d38b982..59974b254 100644
--- a/src/libelogind/sd-bus/bus-common-errors.c
+++ b/src/libelogind/sd-bus/bus-common-errors.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
@@ -31,6 +14,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
SD_BUS_ERROR_MAP(BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID, ENOENT),
SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_EXISTS, EEXIST),
SD_BUS_ERROR_MAP(BUS_ERROR_LOAD_FAILED, EIO),
+ SD_BUS_ERROR_MAP(BUS_ERROR_BAD_UNIT_SETTING, ENOEXEC),
SD_BUS_ERROR_MAP(BUS_ERROR_JOB_FAILED, EREMOTEIO),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_JOB, ENOENT),
SD_BUS_ERROR_MAP(BUS_ERROR_NOT_SUBSCRIBED, EINVAL),
@@ -74,6 +58,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
#if 0 /// UNNEEDED by elogind
SD_BUS_ERROR_MAP(BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, EALREADY),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NO_NTP_SUPPORT, EOPNOTSUPP),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_PROCESS, ESRCH),
diff --git a/src/libelogind/sd-bus/bus-common-errors.h b/src/libelogind/sd-bus/bus-common-errors.h
index aad97ff5c..fa44ca1f6 100644
--- a/src/libelogind/sd-bus/bus-common-errors.h
+++ b/src/libelogind/sd-bus/bus-common-errors.h
@@ -1,22 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "bus-error.h"
@@ -24,8 +9,10 @@
#if 0 /// only system command elogind knows are needed
#define BUS_ERROR_NO_SUCH_UNIT "org.freedesktop.systemd1.NoSuchUnit"
#define BUS_ERROR_NO_UNIT_FOR_PID "org.freedesktop.systemd1.NoUnitForPID"
+#define BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID "org.freedesktop.elogind1.NoUnitForInvocationID"
#define BUS_ERROR_UNIT_EXISTS "org.freedesktop.systemd1.UnitExists"
#define BUS_ERROR_LOAD_FAILED "org.freedesktop.systemd1.LoadFailed"
+#define BUS_ERROR_BAD_UNIT_SETTING "org.freedesktop.systemd1.BadUnitSetting"
#define BUS_ERROR_JOB_FAILED "org.freedesktop.systemd1.JobFailed"
#define BUS_ERROR_NO_SUCH_JOB "org.freedesktop.systemd1.NoSuchJob"
#define BUS_ERROR_NOT_SUBSCRIBED "org.freedesktop.systemd1.NotSubscribed"
@@ -42,6 +29,9 @@
#define BUS_ERROR_SHUTTING_DOWN "org.freedesktop.systemd1.ShuttingDown"
#define BUS_ERROR_SCOPE_NOT_RUNNING "org.freedesktop.systemd1.ScopeNotRunning"
#endif // 0
+#define BUS_ERROR_NO_SUCH_DYNAMIC_USER "org.freedesktop.elogind1.NoSuchDynamicUser"
+#define BUS_ERROR_NOT_REFERENCED "org.freedesktop.elogind1.NotReferenced"
+#define BUS_ERROR_DISK_FULL "org.freedesktop.elogind1.DiskFull"
#if 0 /// no machined in elogind
#define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine"
@@ -53,6 +43,8 @@
#define BUS_ERROR_NO_SUCH_GROUP_MAPPING "org.freedesktop.machine1.NoSuchGroupMapping"
#endif // 0
+#define BUS_ERROR_NO_SUCH_PORTABLE_IMAGE "org.freedesktop.portable1.NoSuchImage"
+
#define BUS_ERROR_NO_SUCH_SESSION "org.freedesktop.login1.NoSuchSession"
#define BUS_ERROR_NO_SESSION_FOR_PID "org.freedesktop.login1.NoSessionForPID"
#define BUS_ERROR_NO_SUCH_USER "org.freedesktop.login1.NoSuchUser"
@@ -68,6 +60,7 @@
#if 0 /// more services unsupported by elogind
#define BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED "org.freedesktop.timedate1.AutomaticTimeSyncEnabled"
+#define BUS_ERROR_NO_NTP_SUPPORT "org.freedesktop.timedate1.NoNTPSupport"
#define BUS_ERROR_NO_SUCH_PROCESS "org.freedesktop.systemd1.NoSuchProcess"
@@ -83,6 +76,8 @@
#define BUS_ERROR_NO_SUCH_LINK "org.freedesktop.resolve1.NoSuchLink"
#define BUS_ERROR_LINK_BUSY "org.freedesktop.resolve1.LinkBusy"
#define BUS_ERROR_NETWORK_DOWN "org.freedesktop.resolve1.NetworkDown"
+#define BUS_ERROR_NO_SUCH_DNSSD_SERVICE "org.freedesktop.resolve1.NoSuchDnssdService"
+#define BUS_ERROR_DNSSD_SERVICE_EXISTS "org.freedesktop.resolve1.DnssdServiceExists"
#define _BUS_ERROR_DNS "org.freedesktop.resolve1.DnsError."
#define BUS_ERROR_NO_SUCH_TRANSFER "org.freedesktop.import1.NoSuchTransfer"
diff --git a/src/libelogind/sd-bus/bus-container.c b/src/libelogind/sd-bus/bus-container.c
index 3191d27de..f50274a6a 100644
--- a/src/libelogind/sd-bus/bus-container.c
+++ b/src/libelogind/sd-bus/bus-container.c
@@ -1,20 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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>
@@ -30,9 +15,8 @@
int bus_container_connect_socket(sd_bus *b) {
_cleanup_close_pair_ int pair[2] = { -1, -1 };
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
- pid_t child;
- siginfo_t si;
int r, error_buf = 0;
+ pid_t child;
ssize_t n;
assert(b);
@@ -54,6 +38,8 @@ int bus_container_connect_socket(sd_bus *b) {
if (b->input_fd < 0)
return -errno;
+ b->input_fd = fd_move_above_stdio(b->input_fd);
+
b->output_fd = b->input_fd;
bus_socket_setup(b);
@@ -61,11 +47,10 @@ int bus_container_connect_socket(sd_bus *b) {
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
return -errno;
- child = fork();
- if (child < 0)
- return -errno;
-
- if (child == 0) {
+ r = safe_fork("(sd-buscntr)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &child);
+ if (r < 0)
+ return r;
+ if (r == 0) {
pid_t grandchild;
pair[0] = safe_close(pair[0]);
@@ -81,11 +66,10 @@ int bus_container_connect_socket(sd_bus *b) {
* comes from a process from within the container, and
* not outside of it */
- grandchild = fork();
- if (grandchild < 0)
+ r = safe_fork("(sd-buscntr2)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &grandchild);
+ if (r < 0)
_exit(EXIT_FAILURE);
-
- if (grandchild == 0) {
+ if (r == 0) {
r = connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size);
if (r < 0) {
@@ -98,21 +82,20 @@ int bus_container_connect_socket(sd_bus *b) {
_exit(EXIT_SUCCESS);
}
- r = wait_for_terminate(grandchild, &si);
+ r = wait_for_terminate_and_check("(sd-buscntr2)", grandchild, 0);
if (r < 0)
_exit(EXIT_FAILURE);
- if (si.si_code != CLD_EXITED)
- _exit(EXIT_FAILURE);
-
- _exit(si.si_status);
+ _exit(r);
}
pair[1] = safe_close(pair[1]);
- r = wait_for_terminate(child, &si);
+ r = wait_for_terminate_and_check("(sd-buscntr)", child, 0);
if (r < 0)
return r;
+ if (r != EXIT_SUCCESS)
+ return -EPROTO;
n = read(pair[0], &error_buf, sizeof(error_buf));
if (n < 0)
@@ -132,146 +115,5 @@ int bus_container_connect_socket(sd_bus *b) {
return -error_buf;
}
- if (si.si_code != CLD_EXITED)
- return -EIO;
-
- if (si.si_status != EXIT_SUCCESS)
- return -EIO;
-
return bus_socket_start_auth(b);
}
-
-int bus_container_connect_kernel(sd_bus *b) {
- _cleanup_close_pair_ int pair[2] = { -1, -1 };
- _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
- union {
- struct cmsghdr cmsghdr;
- uint8_t buf[CMSG_SPACE(sizeof(int))];
- } control = {};
- int error_buf = 0;
- struct iovec iov = {
- .iov_base = &error_buf,
- .iov_len = sizeof(error_buf),
- };
- struct msghdr mh = {
- .msg_control = &control,
- .msg_controllen = sizeof(control),
- .msg_iov = &iov,
- .msg_iovlen = 1,
- };
- struct cmsghdr *cmsg;
- pid_t child;
- siginfo_t si;
- int r, fd = -1;
- ssize_t n;
-
- assert(b);
- assert(b->input_fd < 0);
- assert(b->output_fd < 0);
- assert(b->nspid > 0 || b->machine);
-
- if (b->nspid <= 0) {
- r = container_get_leader(b->machine, &b->nspid);
- if (r < 0)
- return r;
- }
-
- r = namespace_open(b->nspid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
- if (r < 0)
- return r;
-
- if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
- return -errno;
-
- child = fork();
- if (child < 0)
- return -errno;
-
- if (child == 0) {
- pid_t grandchild;
-
- pair[0] = safe_close(pair[0]);
-
- r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
- if (r < 0)
- _exit(EXIT_FAILURE);
-
- /* We just changed PID namespace, however it will only
- * take effect on the children we now fork. Hence,
- * let's fork another time, and connect from this
- * grandchild, so that kdbus only sees the credentials
- * of this process which comes from within the
- * container, and not outside of it */
-
- grandchild = fork();
- if (grandchild < 0)
- _exit(EXIT_FAILURE);
-
- if (grandchild == 0) {
- fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0) {
- /* Try to send error up */
- error_buf = errno;
- (void) write(pair[1], &error_buf, sizeof(error_buf));
- _exit(EXIT_FAILURE);
- }
-
- r = send_one_fd(pair[1], fd, 0);
- if (r < 0)
- _exit(EXIT_FAILURE);
-
- _exit(EXIT_SUCCESS);
- }
-
- r = wait_for_terminate(grandchild, &si);
- if (r < 0)
- _exit(EXIT_FAILURE);
-
- if (si.si_code != CLD_EXITED)
- _exit(EXIT_FAILURE);
-
- _exit(si.si_status);
- }
-
- pair[1] = safe_close(pair[1]);
-
- r = wait_for_terminate(child, &si);
- if (r < 0)
- return r;
-
- n = recvmsg(pair[0], &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
- if (n < 0)
- return -errno;
-
- CMSG_FOREACH(cmsg, &mh) {
- if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
- int *fds;
- unsigned n_fds;
-
- assert(fd < 0);
-
- fds = (int*) CMSG_DATA(cmsg);
- n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
-
- if (n_fds != 1) {
- close_many(fds, n_fds);
- return -EIO;
- }
-
- fd = fds[0];
- }
- }
-
- /* If there's an fd passed, we are good. */
- if (fd >= 0) {
- b->input_fd = b->output_fd = fd;
- return bus_kernel_take_fd(b);
- }
-
- /* If there's an error passed, use it */
- if (n == sizeof(error_buf) && error_buf > 0)
- return -error_buf;
-
- /* Otherwise, we have no clue */
- return -EIO;
-}
diff --git a/src/libelogind/sd-bus/bus-container.h b/src/libelogind/sd-bus/bus-container.h
index 509ef4562..dd115b4e2 100644
--- a/src/libelogind/sd-bus/bus-container.h
+++ b/src/libelogind/sd-bus/bus-container.h
@@ -1,25 +1,9 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-bus.h"
int bus_container_connect_socket(sd_bus *b);
-int bus_container_connect_kernel(sd_bus *b);
diff --git a/src/libelogind/sd-bus/bus-control.c b/src/libelogind/sd-bus/bus-control.c
index b56bb0771..18a2cc2c9 100644
--- a/src/libelogind/sd-bus/bus-control.c
+++ b/src/libelogind/sd-bus/bus-control.c
@@ -1,23 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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_VALGRIND_MEMCHECK_H
+#if HAVE_VALGRIND_MEMCHECK_H
#include <valgrind/memcheck.h>
#endif
@@ -27,12 +12,12 @@
#include "sd-bus.h"
#include "alloc-util.h"
-#include "bus-bloom.h"
#include "bus-control.h"
#include "bus-internal.h"
#include "bus-message.h"
#include "bus-util.h"
#include "capability-util.h"
+#include "process-util.h"
#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
@@ -42,6 +27,7 @@ _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
int r;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(unique, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -56,52 +42,61 @@ _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
return 0;
}
-static int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags) {
- struct kdbus_cmd *n;
- size_t size, l;
- int r;
+static int validate_request_name_parameters(
+ sd_bus *bus,
+ const char *name,
+ uint64_t flags,
+ uint32_t *ret_param) {
+
+ uint32_t param = 0;
assert(bus);
assert(name);
+ assert(ret_param);
- l = strlen(name) + 1;
- size = offsetof(struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(l);
- n = alloca0_align(size, 8);
- n->size = size;
- n->flags = request_name_flags_to_kdbus(flags);
+ assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
+ assert_return(service_name_is_valid(name), -EINVAL);
+ assert_return(name[0] != ':', -EINVAL);
- n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
- n->items[0].type = KDBUS_ITEM_NAME;
- memcpy(n->items[0].str, name, l);
+ if (!bus->bus_client)
+ return -EINVAL;
-#ifdef HAVE_VALGRIND_MEMCHECK_H
- VALGRIND_MAKE_MEM_DEFINED(n, n->size);
-#endif
+ /* Don't allow requesting the special driver and local names */
+ if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
+ return -EINVAL;
- r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
- if (r < 0)
- return -errno;
+ if (!BUS_IS_OPEN(bus->state))
+ return -ENOTCONN;
- if (n->return_flags & KDBUS_NAME_IN_QUEUE)
- return 0;
+ if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
+ param |= BUS_NAME_ALLOW_REPLACEMENT;
+ if (flags & SD_BUS_NAME_REPLACE_EXISTING)
+ param |= BUS_NAME_REPLACE_EXISTING;
+ if (!(flags & SD_BUS_NAME_QUEUE))
+ param |= BUS_NAME_DO_NOT_QUEUE;
- return 1;
+ *ret_param = param;
+
+ return 0;
}
-static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) {
+_public_ int sd_bus_request_name(
+ sd_bus *bus,
+ const char *name,
+ uint64_t flags) {
+
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
uint32_t ret, param = 0;
int r;
- assert(bus);
- assert(name);
+ assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
+ assert_return(name, -EINVAL);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
- if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
- param |= BUS_NAME_ALLOW_REPLACEMENT;
- if (flags & SD_BUS_NAME_REPLACE_EXISTING)
- param |= BUS_NAME_REPLACE_EXISTING;
- if (!(flags & SD_BUS_NAME_QUEUE))
- param |= BUS_NAME_DO_NOT_QUEUE;
+ r = validate_request_name_parameters(bus, name, flags, &param);
+ if (r < 0)
+ return r;
r = sd_bus_call_method(
bus,
@@ -121,76 +116,145 @@ static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags)
if (r < 0)
return r;
- if (ret == BUS_NAME_ALREADY_OWNER)
+ switch (ret) {
+
+ case BUS_NAME_ALREADY_OWNER:
return -EALREADY;
- else if (ret == BUS_NAME_EXISTS)
+
+ case BUS_NAME_EXISTS:
return -EEXIST;
- else if (ret == BUS_NAME_IN_QUEUE)
+
+ case BUS_NAME_IN_QUEUE:
return 0;
- else if (ret == BUS_NAME_PRIMARY_OWNER)
+
+ case BUS_NAME_PRIMARY_OWNER:
return 1;
+ }
return -EIO;
}
-_public_ int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) {
+static int default_request_name_handler(
+ sd_bus_message *m,
+ void *userdata,
+ sd_bus_error *ret_error) {
+
+ uint32_t ret;
+ int r;
+
+ assert(m);
+
+ if (sd_bus_message_is_method_error(m, NULL)) {
+ log_debug_errno(sd_bus_message_get_errno(m),
+ "Unable to request name, failing connection: %s",
+ sd_bus_message_get_error(m)->message);
+
+ bus_enter_closing(sd_bus_message_get_bus(m));
+ return 1;
+ }
+
+ r = sd_bus_message_read(m, "u", &ret);
+ if (r < 0)
+ return r;
+
+ switch (ret) {
+
+ case BUS_NAME_ALREADY_OWNER:
+ log_debug("Already owner of requested service name, ignoring.");
+ return 1;
+
+ case BUS_NAME_IN_QUEUE:
+ log_debug("In queue for requested service name.");
+ return 1;
+
+ case BUS_NAME_PRIMARY_OWNER:
+ log_debug("Successfully acquired requested service name.");
+ return 1;
+
+ case BUS_NAME_EXISTS:
+ log_debug("Requested service name already owned, failing connection.");
+ bus_enter_closing(sd_bus_message_get_bus(m));
+ return 1;
+ }
+
+ log_debug("Unexpected response from RequestName(), failing connection.");
+ bus_enter_closing(sd_bus_message_get_bus(m));
+ return 1;
+}
+
+_public_ int sd_bus_request_name_async(
+ sd_bus *bus,
+ sd_bus_slot **ret_slot,
+ const char *name,
+ uint64_t flags,
+ sd_bus_message_handler_t callback,
+ void *userdata) {
+
+ uint32_t param = 0;
+ int r;
+
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(name, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
- assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
+
+ r = validate_request_name_parameters(bus, name, flags, &param);
+ if (r < 0)
+ return r;
+
+ return sd_bus_call_method_async(
+ bus,
+ ret_slot,
+ "org.freedesktop.DBus",
+ "/org/freedesktop/DBus",
+ "org.freedesktop.DBus",
+ "RequestName",
+ callback ?: default_request_name_handler,
+ userdata,
+ "su",
+ name,
+ param);
+}
+
+static int validate_release_name_parameters(
+ sd_bus *bus,
+ const char *name) {
+
+ assert(bus);
+ assert(name);
+
assert_return(service_name_is_valid(name), -EINVAL);
assert_return(name[0] != ':', -EINVAL);
if (!bus->bus_client)
return -EINVAL;
- /* Don't allow requesting the special driver and local names */
+ /* Don't allow releasing the special driver and local names */
if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
return -EINVAL;
if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
- if (bus->is_kernel)
- return bus_request_name_kernel(bus, name, flags);
- else
- return bus_request_name_dbus1(bus, name, flags);
-}
-
-static int bus_release_name_kernel(sd_bus *bus, const char *name) {
- struct kdbus_cmd *n;
- size_t size, l;
- int r;
-
- assert(bus);
- assert(name);
-
- l = strlen(name) + 1;
- size = offsetof(struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(l);
- n = alloca0_align(size, 8);
- n->size = size;
-
- n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
- n->items[0].type = KDBUS_ITEM_NAME;
- memcpy(n->items[0].str, name, l);
-
-#ifdef HAVE_VALGRIND_MEMCHECK_H
- VALGRIND_MAKE_MEM_DEFINED(n, n->size);
-#endif
- r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
- if (r < 0)
- return -errno;
-
return 0;
}
-static int bus_release_name_dbus1(sd_bus *bus, const char *name) {
+_public_ int sd_bus_release_name(
+ sd_bus *bus,
+ const char *name) {
+
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
uint32_t ret;
int r;
- assert(bus);
- assert(name);
+ assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
+ assert_return(name, -EINVAL);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
+
+ r = validate_release_name_parameters(bus, name);
+ if (r < 0)
+ return r;
r = sd_bus_call_method(
bus,
@@ -208,129 +272,112 @@ static int bus_release_name_dbus1(sd_bus *bus, const char *name) {
r = sd_bus_message_read(reply, "u", &ret);
if (r < 0)
return r;
- if (ret == BUS_NAME_NON_EXISTENT)
- return -ESRCH;
- if (ret == BUS_NAME_NOT_OWNER)
- return -EADDRINUSE;
- if (ret == BUS_NAME_RELEASED)
- return 0;
- return -EINVAL;
-}
+ switch (ret) {
-_public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
- assert_return(bus, -EINVAL);
- assert_return(name, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
- assert_return(service_name_is_valid(name), -EINVAL);
- assert_return(name[0] != ':', -EINVAL);
-
- if (!bus->bus_client)
- return -EINVAL;
+ case BUS_NAME_NON_EXISTENT:
+ return -ESRCH;
- /* Don't allow releasing the special driver and local names */
- if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
- return -EINVAL;
+ case BUS_NAME_NOT_OWNER:
+ return -EADDRINUSE;
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
+ case BUS_NAME_RELEASED:
+ return 0;
+ }
- if (bus->is_kernel)
- return bus_release_name_kernel(bus, name);
- else
- return bus_release_name_dbus1(bus, name);
+ return -EIO;
}
-static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) {
- struct kdbus_cmd_list cmd = {
- .size = sizeof(cmd),
- .flags = flags,
- };
- struct kdbus_info *name_list, *name;
- uint64_t previous_id = 0;
+static int default_release_name_handler(
+ sd_bus_message *m,
+ void *userdata,
+ sd_bus_error *ret_error) {
+
+ uint32_t ret;
int r;
- /* Caller will free half-constructed list on failure... */
+ assert(m);
- r = ioctl(bus->input_fd, KDBUS_CMD_LIST, &cmd);
- if (r < 0)
- return -errno;
+ if (sd_bus_message_is_method_error(m, NULL)) {
+ log_debug_errno(sd_bus_message_get_errno(m),
+ "Unable to release name, failing connection: %s",
+ sd_bus_message_get_error(m)->message);
- name_list = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
+ bus_enter_closing(sd_bus_message_get_bus(m));
+ return 1;
+ }
- KDBUS_FOREACH(name, name_list, cmd.list_size) {
- struct kdbus_item *item;
+ r = sd_bus_message_read(m, "u", &ret);
+ if (r < 0)
+ return r;
- if ((flags & KDBUS_LIST_UNIQUE) && name->id != previous_id && !(name->flags & KDBUS_HELLO_ACTIVATOR)) {
- char *n;
+ switch (ret) {
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wformat"
- if (asprintf(&n, ":1.%llu", name->id) < 0) {
- r = -ENOMEM;
- goto fail;
- }
-#pragma GCC diagnostic pop
-
- r = strv_consume(x, n);
- if (r < 0)
- goto fail;
+ case BUS_NAME_NON_EXISTENT:
+ log_debug("Name asked to release is not taken currently, ignoring.");
+ return 1;
- previous_id = name->id;
- }
+ case BUS_NAME_NOT_OWNER:
+ log_debug("Name asked to release is owned by somebody else, ignoring.");
+ return 1;
- KDBUS_ITEM_FOREACH(item, name, items) {
- if (item->type == KDBUS_ITEM_OWNED_NAME) {
- if (service_name_is_valid(item->name.name)) {
- r = strv_extend(x, item->name.name);
- if (r < 0) {
- r = -ENOMEM;
- goto fail;
- }
- }
- }
- }
+ case BUS_NAME_RELEASED:
+ log_debug("Name successfully released.");
+ return 1;
}
- r = 0;
-
-fail:
- bus_kernel_cmd_free(bus, cmd.offset);
- return r;
+ log_debug("Unexpected response from ReleaseName(), failing connection.");
+ bus_enter_closing(sd_bus_message_get_bus(m));
+ return 1;
}
-static int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) {
- _cleanup_strv_free_ char **x = NULL, **y = NULL;
- int r;
-
- if (acquired) {
- r = kernel_get_list(bus, KDBUS_LIST_UNIQUE | KDBUS_LIST_NAMES, &x);
- if (r < 0)
- return r;
- }
+_public_ int sd_bus_release_name_async(
+ sd_bus *bus,
+ sd_bus_slot **ret_slot,
+ const char *name,
+ sd_bus_message_handler_t callback,
+ void *userdata) {
- if (activatable) {
- r = kernel_get_list(bus, KDBUS_LIST_ACTIVATORS, &y);
- if (r < 0)
- return r;
+ int r;
- *activatable = y;
- y = NULL;
- }
+ assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
+ assert_return(name, -EINVAL);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
- if (acquired) {
- *acquired = x;
- x = NULL;
- }
+ r = validate_release_name_parameters(bus, name);
+ if (r < 0)
+ return r;
- return 0;
+ return sd_bus_call_method_async(
+ bus,
+ ret_slot,
+ "org.freedesktop.DBus",
+ "/org/freedesktop/DBus",
+ "org.freedesktop.DBus",
+ "ReleaseName",
+ callback ?: default_release_name_handler,
+ userdata,
+ "s",
+ name);
}
-static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
+_public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_strv_free_ char **x = NULL, **y = NULL;
int r;
+ assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
+ assert_return(acquired || activatable, -EINVAL);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
+
+ if (!bus->bus_client)
+ return -EINVAL;
+
+ if (!BUS_IS_OPEN(bus->state))
+ return -ENOTCONN;
+
if (acquired) {
r = sd_bus_call_method(
bus,
@@ -368,401 +415,51 @@ static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatab
if (r < 0)
return r;
- *activatable = y;
- y = NULL;
- }
-
- if (acquired) {
- *acquired = x;
- x = NULL;
+ *activatable = TAKE_PTR(y);
}
- return 0;
-}
-
-_public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
- assert_return(bus, -EINVAL);
- assert_return(acquired || activatable, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (!bus->bus_client)
- return -EINVAL;
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- if (bus->is_kernel)
- return bus_list_names_kernel(bus, acquired, activatable);
- else
- return bus_list_names_dbus1(bus, acquired, activatable);
-}
-
-static int bus_populate_creds_from_items(
- sd_bus *bus,
- struct kdbus_info *info,
- uint64_t mask,
- sd_bus_creds *c) {
-
- struct kdbus_item *item;
- uint64_t m;
- int r;
-
- assert(bus);
- assert(info);
- assert(c);
-
- KDBUS_ITEM_FOREACH(item, info, items) {
-
- switch (item->type) {
-
- case KDBUS_ITEM_PIDS:
-
- if (mask & SD_BUS_CREDS_PID && item->pids.pid > 0) {
- c->pid = (pid_t) item->pids.pid;
- c->mask |= SD_BUS_CREDS_PID;
- }
-
- if (mask & SD_BUS_CREDS_TID && item->pids.tid > 0) {
- c->tid = (pid_t) item->pids.tid;
- c->mask |= SD_BUS_CREDS_TID;
- }
-
- if (mask & SD_BUS_CREDS_PPID) {
- if (item->pids.ppid > 0) {
- c->ppid = (pid_t) item->pids.ppid;
- c->mask |= SD_BUS_CREDS_PPID;
- } else if (item->pids.pid == 1) {
- /* The structure doesn't
- * really distinguish the case
- * where a process has no
- * parent and where we don't
- * know it because it could
- * not be translated due to
- * namespaces. However, we
- * know that PID 1 has no
- * parent process, hence let's
- * patch that in, manually. */
- c->ppid = 0;
- c->mask |= SD_BUS_CREDS_PPID;
- }
- }
-
- break;
-
- case KDBUS_ITEM_CREDS:
-
- if (mask & SD_BUS_CREDS_UID && (uid_t) item->creds.uid != UID_INVALID) {
- c->uid = (uid_t) item->creds.uid;
- c->mask |= SD_BUS_CREDS_UID;
- }
-
- if (mask & SD_BUS_CREDS_EUID && (uid_t) item->creds.euid != UID_INVALID) {
- c->euid = (uid_t) item->creds.euid;
- c->mask |= SD_BUS_CREDS_EUID;
- }
-
- if (mask & SD_BUS_CREDS_SUID && (uid_t) item->creds.suid != UID_INVALID) {
- c->suid = (uid_t) item->creds.suid;
- c->mask |= SD_BUS_CREDS_SUID;
- }
-
- if (mask & SD_BUS_CREDS_FSUID && (uid_t) item->creds.fsuid != UID_INVALID) {
- c->fsuid = (uid_t) item->creds.fsuid;
- c->mask |= SD_BUS_CREDS_FSUID;
- }
-
- if (mask & SD_BUS_CREDS_GID && (gid_t) item->creds.gid != GID_INVALID) {
- c->gid = (gid_t) item->creds.gid;
- c->mask |= SD_BUS_CREDS_GID;
- }
-
- if (mask & SD_BUS_CREDS_EGID && (gid_t) item->creds.egid != GID_INVALID) {
- c->egid = (gid_t) item->creds.egid;
- c->mask |= SD_BUS_CREDS_EGID;
- }
-
- if (mask & SD_BUS_CREDS_SGID && (gid_t) item->creds.sgid != GID_INVALID) {
- c->sgid = (gid_t) item->creds.sgid;
- c->mask |= SD_BUS_CREDS_SGID;
- }
-
- if (mask & SD_BUS_CREDS_FSGID && (gid_t) item->creds.fsgid != GID_INVALID) {
- c->fsgid = (gid_t) item->creds.fsgid;
- c->mask |= SD_BUS_CREDS_FSGID;
- }
-
- break;
-
- case KDBUS_ITEM_PID_COMM:
- if (mask & SD_BUS_CREDS_COMM) {
- r = free_and_strdup(&c->comm, item->str);
- if (r < 0)
- return r;
-
- c->mask |= SD_BUS_CREDS_COMM;
- }
- break;
-
- case KDBUS_ITEM_TID_COMM:
- if (mask & SD_BUS_CREDS_TID_COMM) {
- r = free_and_strdup(&c->tid_comm, item->str);
- if (r < 0)
- return r;
-
- c->mask |= SD_BUS_CREDS_TID_COMM;
- }
- break;
-
- case KDBUS_ITEM_EXE:
- if (mask & SD_BUS_CREDS_EXE) {
- r = free_and_strdup(&c->exe, item->str);
- if (r < 0)
- return r;
-
- c->mask |= SD_BUS_CREDS_EXE;
- }
- break;
-
- case KDBUS_ITEM_CMDLINE:
- if (mask & SD_BUS_CREDS_CMDLINE) {
- c->cmdline_size = item->size - offsetof(struct kdbus_item, data);
- c->cmdline = memdup(item->data, c->cmdline_size);
- if (!c->cmdline)
- return -ENOMEM;
-
- c->mask |= SD_BUS_CREDS_CMDLINE;
- }
- break;
-
- case KDBUS_ITEM_CGROUP:
- m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
- SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
- SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
-
- if (m) {
- r = free_and_strdup(&c->cgroup, item->str);
- if (r < 0)
- return r;
-
- r = bus_get_root_path(bus);
- if (r < 0)
- return r;
-
- r = free_and_strdup(&c->cgroup_root, bus->cgroup_root);
- if (r < 0)
- return r;
-
- c->mask |= m;
- }
- break;
-
- case KDBUS_ITEM_CAPS:
- m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
- SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
-
- if (m) {
- if (item->caps.last_cap != cap_last_cap() ||
- item->size - offsetof(struct kdbus_item, caps.caps) < DIV_ROUND_UP(item->caps.last_cap, 32U) * 4 * 4)
- return -EBADMSG;
-
- c->capability = memdup(item->caps.caps, item->size - offsetof(struct kdbus_item, caps.caps));
- if (!c->capability)
- return -ENOMEM;
-
- c->mask |= m;
- }
- break;
-
- case KDBUS_ITEM_SECLABEL:
- if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
- r = free_and_strdup(&c->label, item->str);
- if (r < 0)
- return r;
-
- c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
- }
- break;
-
- case KDBUS_ITEM_AUDIT:
- if (mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
- c->audit_session_id = (uint32_t) item->audit.sessionid;
- c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
- }
-
- if (mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
- c->audit_login_uid = (uid_t) item->audit.loginuid;
- c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
- }
- break;
-
- case KDBUS_ITEM_OWNED_NAME:
- if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
- r = strv_extend(&c->well_known_names, item->name.name);
- if (r < 0)
- return r;
-
- c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
- }
- break;
-
- case KDBUS_ITEM_CONN_DESCRIPTION:
- if (mask & SD_BUS_CREDS_DESCRIPTION) {
- r = free_and_strdup(&c->description, item->str);
- if (r < 0)
- return r;
-
- c->mask |= SD_BUS_CREDS_DESCRIPTION;
- }
- break;
-
- case KDBUS_ITEM_AUXGROUPS:
- if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
- size_t i, n;
- uid_t *g;
-
- n = (item->size - offsetof(struct kdbus_item, data64)) / sizeof(uint64_t);
- g = new(gid_t, n);
- if (!g)
- return -ENOMEM;
-
- for (i = 0; i < n; i++)
- g[i] = item->data64[i];
-
- free(c->supplementary_gids);
- c->supplementary_gids = g;
- c->n_supplementary_gids = n;
-
- c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
- }
- break;
- }
- }
+ if (acquired)
+ *acquired = TAKE_PTR(x);
return 0;
}
-int bus_get_name_creds_kdbus(
+_public_ int sd_bus_get_name_creds(
sd_bus *bus,
const char *name,
uint64_t mask,
- bool allow_activator,
sd_bus_creds **creds) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_unique = NULL, *reply = NULL;
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
- struct kdbus_cmd_info *cmd;
- struct kdbus_info *conn_info;
- size_t size, l;
- uint64_t id;
+ const char *unique = NULL;
+ pid_t pid = 0;
int r;
- if (streq(name, "org.freedesktop.DBus"))
- return -EOPNOTSUPP;
-
- r = bus_kernel_parse_unique_name(name, &id);
- if (r < 0)
- return r;
- if (r > 0) {
- size = offsetof(struct kdbus_cmd_info, items);
- cmd = alloca0_align(size, 8);
- cmd->id = id;
- } else {
- l = strlen(name) + 1;
- size = offsetof(struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(l);
- cmd = alloca0_align(size, 8);
- cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
- cmd->items[0].type = KDBUS_ITEM_NAME;
- memcpy(cmd->items[0].str, name, l);
- }
-
- /* If augmentation is on, and the bus didn't provide us
- * the bits we want, then ask for the PID/TID so that we
- * can read the rest from /proc. */
- if ((mask & SD_BUS_CREDS_AUGMENT) &&
- (mask & (SD_BUS_CREDS_PPID|
- SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
- SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
- SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
- SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
- SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
- SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
- SD_BUS_CREDS_SELINUX_CONTEXT|
- SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
- mask |= SD_BUS_CREDS_PID;
-
- cmd->size = size;
- cmd->attach_flags = attach_flags_to_kdbus(mask);
-
- r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
- if (r < 0)
- return -errno;
-
- conn_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
-
- /* Non-activated names are considered not available */
- if (!allow_activator && (conn_info->flags & KDBUS_HELLO_ACTIVATOR)) {
- if (name[0] == ':')
- r = -ENXIO;
- else
- r = -ESRCH;
- goto fail;
- }
-
- c = bus_creds_new();
- if (!c) {
- r = -ENOMEM;
- goto fail;
- }
-
- if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wformat"
- if (asprintf(&c->unique_name, ":1.%llu", conn_info->id) < 0) {
- r = -ENOMEM;
- goto fail;
- }
-#pragma GCC diagnostic pop
-
- c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
- }
-
- /* If KDBUS_ITEM_OWNED_NAME is requested then we'll get 0 of
- them in case the service has no names. This does not mean
- however that the list of owned names could not be
- acquired. Hence, let's explicitly clarify that the data is
- complete. */
- c->mask |= mask & SD_BUS_CREDS_WELL_KNOWN_NAMES;
-
- r = bus_populate_creds_from_items(bus, conn_info, mask, c);
- if (r < 0)
- goto fail;
-
- r = bus_creds_add_more(c, mask, 0, 0);
- if (r < 0)
- goto fail;
+ assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
+ assert_return(name, -EINVAL);
+ assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
+ assert_return(mask == 0 || creds, -EINVAL);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
+ assert_return(service_name_is_valid(name), -EINVAL);
- if (creds) {
- *creds = c;
- c = NULL;
- }
+ if (!bus->bus_client)
+ return -EINVAL;
- r = 0;
+ /* Turn off augmenting if this isn't a local connection. If the connection is not local, then /proc is not
+ * going to match. */
+ if (!bus->is_local)
+ mask &= ~SD_BUS_CREDS_AUGMENT;
-fail:
- bus_kernel_cmd_free(bus, cmd->offset);
- return r;
-}
+ if (streq(name, "org.freedesktop.DBus.Local"))
+ return -EINVAL;
-static int bus_get_name_creds_dbus1(
- sd_bus *bus,
- const char *name,
- uint64_t mask,
- sd_bus_creds **creds) {
+ if (streq(name, "org.freedesktop.DBus"))
+ return sd_bus_get_owner_creds(bus, mask, creds);
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_unique = NULL, *reply = NULL;
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
- const char *unique = NULL;
- pid_t pid = 0;
- int r;
+ if (!BUS_IS_OPEN(bus->state))
+ return -ENOTCONN;
/* Only query the owner if the caller wants to know it or if
* the caller just wants to check whether a name exists */
@@ -1018,112 +715,35 @@ static int bus_get_name_creds_dbus1(
return r;
}
- if (creds) {
- *creds = c;
- c = NULL;
- }
+ if (creds)
+ *creds = TAKE_PTR(c);
return 0;
}
-_public_ int sd_bus_get_name_creds(
- sd_bus *bus,
- const char *name,
- uint64_t mask,
- sd_bus_creds **creds) {
+_public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
+ bool do_label, do_groups;
+ pid_t pid = 0;
+ int r;
assert_return(bus, -EINVAL);
- assert_return(name, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
- assert_return(mask == 0 || creds, -EINVAL);
+ assert_return(ret, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
- assert_return(service_name_is_valid(name), -EINVAL);
-
- if (!bus->bus_client)
- return -EINVAL;
-
- /* Turn off augmenting if this isn't a local connection. If the connection is not local, then /proc is not
- * going to match. */
- if (!bus->is_local)
- mask &= ~SD_BUS_CREDS_AUGMENT;
-
- if (streq(name, "org.freedesktop.DBus.Local"))
- return -EINVAL;
-
- if (streq(name, "org.freedesktop.DBus"))
- return sd_bus_get_owner_creds(bus, mask, creds);
if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
- if (bus->is_kernel)
- return bus_get_name_creds_kdbus(bus, name, mask, false, creds);
- else
- return bus_get_name_creds_dbus1(bus, name, mask, creds);
-}
-
-static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
- struct kdbus_cmd_info cmd = {
- .size = sizeof(struct kdbus_cmd_info),
- };
- struct kdbus_info *creator_info;
- pid_t pid = 0;
- int r;
-
- c = bus_creds_new();
- if (!c)
- return -ENOMEM;
-
- /* If augmentation is on, and the bus doesn't didn't allow us
- * to get the bits we want, then ask for the PID/TID so that we
- * can read the rest from /proc. */
- if ((mask & SD_BUS_CREDS_AUGMENT) &&
- (mask & (SD_BUS_CREDS_PPID|
- SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
- SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
- SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
- SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
- SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
- SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
- SD_BUS_CREDS_SELINUX_CONTEXT|
- SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
- mask |= SD_BUS_CREDS_PID;
-
- cmd.attach_flags = attach_flags_to_kdbus(mask);
-
- r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
- if (r < 0)
- return -errno;
-
- creator_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
-
- r = bus_populate_creds_from_items(bus, creator_info, mask, c);
- bus_kernel_cmd_free(bus, cmd.offset);
- if (r < 0)
- return r;
-
- r = bus_creds_add_more(c, mask, pid, 0);
- if (r < 0)
- return r;
-
- *ret = c;
- c = NULL;
- return 0;
-}
-
-static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
- pid_t pid = 0;
- bool do_label;
- int r;
-
- assert(bus);
+ if (!bus->is_local)
+ mask &= ~SD_BUS_CREDS_AUGMENT;
do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT);
+ do_groups = bus->n_groups != (size_t) -1 && (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS);
/* Avoid allocating anything if we have no chance of returning useful data */
- if (!bus->ucred_valid && !do_label)
+ if (!bus->ucred_valid && !do_label && !do_groups)
return -ENODATA;
c = bus_creds_new();
@@ -1131,17 +751,17 @@ static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **
return -ENOMEM;
if (bus->ucred_valid) {
- if (bus->ucred.pid > 0) {
+ if (pid_is_valid(bus->ucred.pid)) {
pid = c->pid = bus->ucred.pid;
c->mask |= SD_BUS_CREDS_PID & mask;
}
- if (bus->ucred.uid != UID_INVALID) {
+ if (uid_is_valid(bus->ucred.uid)) {
c->euid = bus->ucred.uid;
c->mask |= SD_BUS_CREDS_EUID & mask;
}
- if (bus->ucred.gid != GID_INVALID) {
+ if (gid_is_valid(bus->ucred.gid)) {
c->egid = bus->ucred.gid;
c->mask |= SD_BUS_CREDS_EGID & mask;
}
@@ -1155,436 +775,42 @@ static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **
c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
}
- r = bus_creds_add_more(c, mask, pid, 0);
- if (r < 0)
- return r;
-
- *ret = c;
- c = NULL;
- return 0;
-}
-
-_public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
- assert_return(bus, -EINVAL);
- assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
- assert_return(ret, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- if (!bus->is_local)
- mask &= ~SD_BUS_CREDS_AUGMENT;
-
- if (bus->is_kernel)
- return bus_get_owner_creds_kdbus(bus, mask, ret);
- else
- return bus_get_owner_creds_dbus1(bus, mask, ret);
-}
-
-static int add_name_change_match(sd_bus *bus,
- uint64_t cookie,
- const char *name,
- const char *old_owner,
- const char *new_owner) {
-
- uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
- int is_name_id = -1, r;
- struct kdbus_item *item;
-
- assert(bus);
-
- /* If we encounter a match that could match against
- * NameOwnerChanged messages, then we need to create
- * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
- * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
- * multiple if the match is underspecified.
- *
- * The NameOwnerChanged signals take three parameters with
- * unique or well-known names, but only some forms actually
- * exist:
- *
- * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
- * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
- * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
- * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
- * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
- *
- * For the latter two the two unique names must be identical.
- *
- * */
-
- if (name) {
- is_name_id = bus_kernel_parse_unique_name(name, &name_id);
- if (is_name_id < 0)
- return 0;
- }
-
- if (!isempty(old_owner)) {
- r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
- if (r < 0)
- return 0;
- if (r == 0)
- return 0;
- if (is_name_id > 0 && old_owner_id != name_id)
- return 0;
- } else
- old_owner_id = KDBUS_MATCH_ID_ANY;
-
- if (!isempty(new_owner)) {
- r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
- if (r < 0)
- return r;
- if (r == 0)
- return 0;
- if (is_name_id > 0 && new_owner_id != name_id)
- return 0;
- } else
- new_owner_id = KDBUS_MATCH_ID_ANY;
-
- if (is_name_id <= 0) {
- struct kdbus_cmd_match *m;
- size_t sz, l;
-
- /* If the name argument is missing or is a well-known
- * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
- * matches for it */
-
- l = name ? strlen(name) + 1 : 0;
-
- sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
- offsetof(struct kdbus_item, name_change) +
- offsetof(struct kdbus_notify_name_change, name) +
- l);
-
- m = alloca0_align(sz, 8);
- m->size = sz;
- m->cookie = cookie;
-
- item = m->items;
- item->size =
- offsetof(struct kdbus_item, name_change) +
- offsetof(struct kdbus_notify_name_change, name) +
- l;
-
- item->name_change.old_id.id = old_owner_id;
- item->name_change.new_id.id = new_owner_id;
-
- memcpy_safe(item->name_change.name, name, l);
-
- /* If the old name is unset or empty, then
- * this can match against added names */
- if (isempty(old_owner)) {
- item->type = KDBUS_ITEM_NAME_ADD;
-
- r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
- if (r < 0)
- return -errno;
- }
-
- /* If the new name is unset or empty, then
- * this can match against removed names */
- if (isempty(new_owner)) {
- item->type = KDBUS_ITEM_NAME_REMOVE;
-
- r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
- if (r < 0)
- return -errno;
- }
-
- /* The CHANGE match we need in either case, because
- * what is reported as a name change by the kernel
- * might just be an owner change between starter and
- * normal clients. For userspace such a change should
- * be considered a removal/addition, hence let's
- * subscribe to this unconditionally. */
- item->type = KDBUS_ITEM_NAME_CHANGE;
- r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
- if (r < 0)
- return -errno;
- }
-
- if (is_name_id != 0) {
- struct kdbus_cmd_match *m;
- uint64_t sz;
-
- /* If the name argument is missing or is a unique
- * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
- * for it */
-
- sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
- offsetof(struct kdbus_item, id_change) +
- sizeof(struct kdbus_notify_id_change));
-
- m = alloca0_align(sz, 8);
- m->size = sz;
- m->cookie = cookie;
-
- item = m->items;
- item->size =
- offsetof(struct kdbus_item, id_change) +
- sizeof(struct kdbus_notify_id_change);
- item->id_change.id = name_id;
-
- /* If the old name is unset or empty, then this can
- * match against added ids */
- if (isempty(old_owner)) {
- item->type = KDBUS_ITEM_ID_ADD;
- if (!isempty(new_owner))
- item->id_change.id = new_owner_id;
-
- r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
- if (r < 0)
- return -errno;
- }
-
- /* If thew new name is unset or empty, then this can
- * match against removed ids */
- if (isempty(new_owner)) {
- item->type = KDBUS_ITEM_ID_REMOVE;
- if (!isempty(old_owner))
- item->id_change.id = old_owner_id;
-
- r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
- if (r < 0)
- return -errno;
- }
- }
-
- return 0;
-}
-
-int bus_add_match_internal_kernel(
- sd_bus *bus,
- struct bus_match_component *components,
- unsigned n_components,
- uint64_t cookie) {
-
- struct kdbus_cmd_match *m;
- struct kdbus_item *item;
- uint64_t *bloom;
- size_t sz;
- const char *sender = NULL;
- size_t sender_length = 0;
- uint64_t src_id = KDBUS_MATCH_ID_ANY, dst_id = KDBUS_MATCH_ID_ANY;
- bool using_bloom = false;
- unsigned i;
- bool matches_name_change = true;
- const char *name_change_arg[3] = {};
- int r;
-
- assert(bus);
-
- /* Monitor streams don't support matches, make this a NOP */
- if (bus->hello_flags & KDBUS_HELLO_MONITOR)
- return 0;
-
- bloom = alloca0(bus->bloom_size);
-
- sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
-
- for (i = 0; i < n_components; i++) {
- struct bus_match_component *c = &components[i];
-
- switch (c->type) {
-
- case BUS_MATCH_SENDER:
- if (!streq(c->value_str, "org.freedesktop.DBus"))
- matches_name_change = false;
-
- r = bus_kernel_parse_unique_name(c->value_str, &src_id);
- if (r < 0)
- return r;
- else if (r > 0)
- sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
- else {
- sender = c->value_str;
- sender_length = strlen(sender);
- sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
- }
-
- break;
-
- case BUS_MATCH_MESSAGE_TYPE:
- if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
- matches_name_change = false;
-
- bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
- using_bloom = true;
- break;
-
- case BUS_MATCH_INTERFACE:
- if (!streq(c->value_str, "org.freedesktop.DBus"))
- matches_name_change = false;
-
- bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
- using_bloom = true;
- break;
-
- case BUS_MATCH_MEMBER:
- if (!streq(c->value_str, "NameOwnerChanged"))
- matches_name_change = false;
-
- bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
- using_bloom = true;
- break;
-
- case BUS_MATCH_PATH:
- if (!streq(c->value_str, "/org/freedesktop/DBus"))
- matches_name_change = false;
-
- bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
- using_bloom = true;
- break;
-
- case BUS_MATCH_PATH_NAMESPACE:
- bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
- using_bloom = true;
- break;
-
- case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
- char buf[sizeof("arg")-1 + 2 + 1];
-
- if (c->type - BUS_MATCH_ARG < 3)
- name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
-
- xsprintf(buf, "arg%i", c->type - BUS_MATCH_ARG);
- bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
- using_bloom = true;
- break;
- }
-
- case BUS_MATCH_ARG_HAS...BUS_MATCH_ARG_HAS_LAST: {
- char buf[sizeof("arg")-1 + 2 + sizeof("-has")];
-
- xsprintf(buf, "arg%i-has", c->type - BUS_MATCH_ARG_HAS);
- bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
- using_bloom = true;
- break;
- }
-
- case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST:
- /*
- * XXX: DBus spec defines arg[0..63]path= matching to be
- * a two-way glob. That is, if either string is a prefix
- * of the other, it matches.
- * This is really hard to realize in bloom-filters, as
- * we would have to create a bloom-match for each prefix
- * of @c->value_str. This is excessive, hence we just
- * ignore all those matches and accept everything from
- * the kernel. People should really avoid those matches.
- * If they're used in real-life some day, we will have
- * to properly support multiple-matches here.
- */
- break;
-
- case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
- char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
-
- xsprintf(buf, "arg%i-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
- bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
- using_bloom = true;
- break;
- }
-
- case BUS_MATCH_DESTINATION:
- /*
- * Kernel only supports matching on destination IDs, but
- * not on destination names. So just skip the
- * destination name restriction and verify it in
- * user-space on retrieval.
- */
- r = bus_kernel_parse_unique_name(c->value_str, &dst_id);
- if (r < 0)
- return r;
- else if (r > 0)
- sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
-
- /* if not a broadcast, it cannot be a name-change */
- if (r <= 0 || dst_id != KDBUS_DST_ID_BROADCAST)
- matches_name_change = false;
-
- break;
-
- case BUS_MATCH_ROOT:
- case BUS_MATCH_VALUE:
- case BUS_MATCH_LEAF:
- case _BUS_MATCH_NODE_TYPE_MAX:
- case _BUS_MATCH_NODE_TYPE_INVALID:
- assert_not_reached("Invalid match type?");
- }
- }
-
- if (using_bloom)
- sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
-
- m = alloca0_align(sz, 8);
- m->size = sz;
- m->cookie = cookie;
-
- item = m->items;
-
- if (src_id != KDBUS_MATCH_ID_ANY) {
- item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
- item->type = KDBUS_ITEM_ID;
- item->id = src_id;
- item = KDBUS_ITEM_NEXT(item);
- }
-
- if (dst_id != KDBUS_MATCH_ID_ANY) {
- item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
- item->type = KDBUS_ITEM_DST_ID;
- item->id = dst_id;
- item = KDBUS_ITEM_NEXT(item);
- }
+ if (do_groups) {
+ c->supplementary_gids = newdup(gid_t, bus->groups, bus->n_groups);
+ if (!c->supplementary_gids)
+ return -ENOMEM;
- if (using_bloom) {
- item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
- item->type = KDBUS_ITEM_BLOOM_MASK;
- memcpy(item->data64, bloom, bus->bloom_size);
- item = KDBUS_ITEM_NEXT(item);
- }
+ c->n_supplementary_gids = bus->n_groups;
- if (sender) {
- item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
- item->type = KDBUS_ITEM_NAME;
- memcpy(item->str, sender, sender_length + 1);
+ c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
}
- r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
+ r = bus_creds_add_more(c, mask, pid, 0);
if (r < 0)
- return -errno;
-
- if (matches_name_change) {
+ return r;
- /* If this match could theoretically match
- * NameOwnerChanged messages, we need to
- * install a second non-bloom filter explitly
- * for it */
-
- r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
- if (r < 0)
- return r;
- }
+ *ret = TAKE_PTR(c);
return 0;
}
-#define internal_match(bus, m) \
- ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
+#define append_eavesdrop(bus, m) \
+ ((bus)->is_monitor \
? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
: (m))
-static int bus_add_match_internal_dbus1(
+int bus_add_match_internal(
sd_bus *bus,
const char *match) {
const char *e;
assert(bus);
- assert(match);
- e = internal_match(bus, match);
+ if (!bus->bus_client)
+ return -EINVAL;
+
+ e = append_eavesdrop(bus, match);
return sd_bus_call_method(
bus,
@@ -1597,49 +823,36 @@ static int bus_add_match_internal_dbus1(
"s",
e);
}
-
-int bus_add_match_internal(
+int bus_add_match_internal_async(
sd_bus *bus,
+ sd_bus_slot **ret_slot,
const char *match,
- struct bus_match_component *components,
- unsigned n_components,
- uint64_t cookie) {
+ sd_bus_message_handler_t callback,
+ void *userdata) {
+
+ const char *e;
assert(bus);
if (!bus->bus_client)
return -EINVAL;
- if (bus->is_kernel)
- return bus_add_match_internal_kernel(bus, components, n_components, cookie);
- else
- return bus_add_match_internal_dbus1(bus, match);
-}
-
-int bus_remove_match_internal_kernel(
- sd_bus *bus,
- uint64_t cookie) {
-
- struct kdbus_cmd_match m = {
- .size = offsetof(struct kdbus_cmd_match, items),
- .cookie = cookie,
- };
- int r;
-
- assert(bus);
-
- /* Monitor streams don't support matches, make this a NOP */
- if (bus->hello_flags & KDBUS_HELLO_MONITOR)
- return 0;
-
- r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
- if (r < 0)
- return -errno;
+ e = append_eavesdrop(bus, match);
- return 0;
+ return sd_bus_call_method_async(
+ bus,
+ ret_slot,
+ "org.freedesktop.DBus",
+ "/org/freedesktop/DBus",
+ "org.freedesktop.DBus",
+ "AddMatch",
+ callback,
+ userdata,
+ "s",
+ e);
}
-static int bus_remove_match_internal_dbus1(
+int bus_remove_match_internal(
sd_bus *bus,
const char *match) {
@@ -1648,10 +861,16 @@ static int bus_remove_match_internal_dbus1(
assert(bus);
assert(match);
- e = internal_match(bus, match);
+ if (!bus->bus_client)
+ return -EINVAL;
- return sd_bus_call_method(
+ e = append_eavesdrop(bus, match);
+
+ /* Fire and forget */
+
+ return sd_bus_call_method_async(
bus,
+ NULL,
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
"org.freedesktop.DBus",
@@ -1662,28 +881,13 @@ static int bus_remove_match_internal_dbus1(
e);
}
-int bus_remove_match_internal(
- sd_bus *bus,
- const char *match,
- uint64_t cookie) {
-
- assert(bus);
-
- if (!bus->bus_client)
- return -EINVAL;
-
- if (bus->is_kernel)
- return bus_remove_match_internal_kernel(bus, cookie);
- else
- return bus_remove_match_internal_dbus1(bus, match);
-}
-
_public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
const char *mid;
int r;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(name, -EINVAL);
assert_return(machine, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
diff --git a/src/libelogind/sd-bus/bus-control.h b/src/libelogind/sd-bus/bus-control.h
index c181aa795..901729749 100644
--- a/src/libelogind/sd-bus/bus-control.h
+++ b/src/libelogind/sd-bus/bus-control.h
@@ -1,32 +1,12 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-bus.h"
-#include "bus-match.h"
-
-int bus_add_match_internal(sd_bus *bus, const char *match, struct bus_match_component *components, unsigned n_components, uint64_t cookie);
-int bus_remove_match_internal(sd_bus *bus, const char *match, uint64_t cookie);
-
-int bus_add_match_internal_kernel(sd_bus *bus, struct bus_match_component *components, unsigned n_components, uint64_t cookie);
-int bus_remove_match_internal_kernel(sd_bus *bus, uint64_t cookie);
+int bus_add_match_internal(sd_bus *bus, const char *match);
+int bus_add_match_internal_async(sd_bus *bus, sd_bus_slot **ret, const char *match, sd_bus_message_handler_t callback, void *userdata);
-int bus_get_name_creds_kdbus(sd_bus *bus, const char *name, uint64_t mask, bool allow_activator, sd_bus_creds **creds);
+int bus_remove_match_internal(sd_bus *bus, const char *match);
diff --git a/src/libelogind/sd-bus/bus-convenience.c b/src/libelogind/sd-bus/bus-convenience.c
index 04158cae4..68a419c6d 100644
--- a/src/libelogind/sd-bus/bus-convenience.c
+++ b/src/libelogind/sd-bus/bus-convenience.c
@@ -1,20 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "bus-internal.h"
@@ -35,6 +20,7 @@ _public_ int sd_bus_emit_signal(
int r;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(!bus_pid_changed(bus), -ECHILD);
if (!BUS_IS_OPEN(bus->state))
@@ -72,6 +58,7 @@ _public_ int sd_bus_call_method_async(
int r;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(!bus_pid_changed(bus), -ECHILD);
if (!BUS_IS_OPEN(bus->state))
@@ -533,22 +520,20 @@ _public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_b
* to get it from the sender or peer. */
if (call->sender)
- /* There's a sender, but the creds are
- * missing. This means we are talking via
- * dbus1, or are getting a message that was
- * sent to us via kdbus, but was converted
- * from a dbus1 message by the bus-proxy and
- * thus also lacks the creds. */
+ /* There's a sender, but the creds are missing. */
return sd_bus_get_name_creds(call->bus, call->sender, mask, creds);
else
- /* There's no sender, hence we are on a dbus1
- * direct connection. For direct connections
+ /* There's no sender. For direct connections
* the credentials of the AF_UNIX peer matter,
- * which may be queried via
- * sd_bus_get_owner_creds(). */
+ * which may be queried via sd_bus_get_owner_creds(). */
return sd_bus_get_owner_creds(call->bus, mask, creds);
}
+ log_debug_elogind("Called by UID %u ; %s [%s] (%s)", c->uid,
+ c->unique_name ? c->unique_name : "no name",
+ c->label ? c->label : "no label",
+ c->description ? c->description : "no desc");
+
return bus_creds_extend_by_pid(c, mask, creds);
}
@@ -579,9 +564,6 @@ _public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability)
* here. */
assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EFFECTIVE_CAPS) == 0, -EPERM);
- /* Note that not even on kdbus we might have the caps
- * field, due to faked identities, or namespace
- * translation issues. */
r = sd_bus_creds_has_effective_cap(creds, capability);
if (r > 0)
return 1;
@@ -624,3 +606,71 @@ _public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability)
return 0;
}
+
+#define make_expression(sender, path, interface, member) \
+ strjoina( \
+ "type='signal'", \
+ sender ? ",sender='" : "", \
+ sender ?: "", \
+ sender ? "'" : "", \
+ path ? ",path='" : "", \
+ path ?: "", \
+ path ? "'" : "", \
+ interface ? ",interface='" : "", \
+ interface ?: "", \
+ interface ? "'" : "", \
+ member ? ",member='" : "", \
+ member ?: "", \
+ member ? "'" : "" \
+ )
+
+_public_ int sd_bus_match_signal(
+ sd_bus *bus,
+ sd_bus_slot **ret,
+ const char *sender,
+ const char *path,
+ const char *interface,
+ const char *member,
+ sd_bus_message_handler_t callback,
+ void *userdata) {
+
+ const char *expression;
+
+ assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
+ assert_return(!sender || service_name_is_valid(sender), -EINVAL);
+ assert_return(!path || object_path_is_valid(path), -EINVAL);
+ assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
+ assert_return(!member || member_name_is_valid(member), -EINVAL);
+
+ expression = make_expression(sender, path, interface, member);
+
+ return sd_bus_add_match(bus, ret, expression, callback, userdata);
+}
+
+_public_ int sd_bus_match_signal_async(
+ sd_bus *bus,
+ sd_bus_slot **ret,
+ const char *sender,
+ const char *path,
+ const char *interface,
+ const char *member,
+ sd_bus_message_handler_t callback,
+ sd_bus_message_handler_t install_callback,
+ void *userdata) {
+
+ const char *expression;
+
+ assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
+ assert_return(!sender || service_name_is_valid(sender), -EINVAL);
+ assert_return(!path || object_path_is_valid(path), -EINVAL);
+ assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
+ assert_return(!member || member_name_is_valid(member), -EINVAL);
+
+ expression = make_expression(sender, path, interface, member);
+
+ return sd_bus_add_match_async(bus, ret, expression, callback, install_callback, userdata);
+}
diff --git a/src/libelogind/sd-bus/bus-creds.c b/src/libelogind/sd-bus/bus-creds.c
index d52bbff84..7104a5371 100644
--- a/src/libelogind/sd-bus/bus-creds.c
+++ b/src/libelogind/sd-bus/bus-creds.c
@@ -1,20 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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/capability.h>
@@ -128,7 +113,6 @@ _public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) {
sd_bus_message_unref(m);
}
-
return NULL;
}
@@ -165,7 +149,7 @@ _public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t m
assert_return(ret, -EINVAL);
if (pid == 0)
- pid = getpid();
+ pid = getpid_cached();
c = bus_creds_new();
if (!c)
@@ -221,7 +205,6 @@ _public_ int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid) {
return 0;
}
-
_public_ int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid) {
assert_return(c, -EINVAL);
assert_return(fsuid, -EINVAL);
@@ -444,6 +427,7 @@ _public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) {
*ret = c->user_unit;
return 0;
}
+#endif // 0
_public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) {
int r;
@@ -498,7 +482,6 @@ _public_ int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **ret) {
*ret = c->user_slice;
return 0;
}
-#endif // 0
_public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) {
int r;
@@ -543,15 +526,12 @@ _public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) {
assert(c->cgroup);
r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
+ log_debug_elogind("Shifted to %s from %s/%s for c->uid %u (result %d)",
+ shifted, c->cgroup_root, c->cgroup, c->uid, r);
if (r < 0)
return r;
-#if 0 /// elogind does not support systemd slices
return cg_path_get_owner_uid(shifted, uid);
-#else
- *uid = c->uid;
- return 0;
-#endif // 0
}
_public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
@@ -580,7 +560,7 @@ _public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessio
if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID))
return -ENODATA;
- if (c->audit_session_id == AUDIT_SESSION_INVALID)
+ if (!audit_session_is_valid(c->audit_session_id))
return -ENXIO;
*sessionid = c->audit_session_id;
@@ -594,7 +574,7 @@ _public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) {
if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID))
return -ENODATA;
- if (c->audit_login_uid == UID_INVALID)
+ if (!uid_is_valid(c->audit_login_uid))
return -ENXIO;
*uid = c->audit_login_uid;
@@ -826,7 +806,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
if (!f) {
if (errno == ENOENT)
return -ESRCH;
- else if (errno != EPERM && errno != EACCES)
+ else if (!IN_SET(errno, EPERM, EACCES))
return -errno;
} else {
char line[LINE_MAX];
@@ -984,7 +964,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
p = procfs_file_alloca(pid, "attr/current");
r = read_one_line_file(p, &c->label);
if (r < 0) {
- if (r != -ENOENT && r != -EINVAL && r != -EPERM && r != -EACCES)
+ if (!IN_SET(r, -ENOENT, -EINVAL, -EPERM, -EACCES))
return r;
} else
c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
@@ -993,7 +973,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
if (missing & SD_BUS_CREDS_COMM) {
r = get_process_comm(pid, &c->comm);
if (r < 0) {
- if (r != -EPERM && r != -EACCES)
+ if (!IN_SET(r, -EPERM, -EACCES))
return r;
} else
c->mask |= SD_BUS_CREDS_COMM;
@@ -1012,7 +992,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
c->exe = NULL;
c->mask |= SD_BUS_CREDS_EXE;
} else if (r < 0) {
- if (r != -EPERM && r != -EACCES)
+ if (!IN_SET(r, -EPERM, -EACCES))
return r;
} else
c->mask |= SD_BUS_CREDS_EXE;
@@ -1026,7 +1006,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
if (r == -ENOENT)
return -ESRCH;
if (r < 0) {
- if (r != -EPERM && r != -EACCES)
+ if (!IN_SET(r, -EPERM, -EACCES))
return r;
} else {
if (c->cmdline_size == 0)
@@ -1046,7 +1026,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
if (r == -ENOENT)
return -ESRCH;
if (r < 0) {
- if (r != -EPERM && r != -EACCES)
+ if (!IN_SET(r, -EPERM, -EACCES))
return r;
} else
c->mask |= SD_BUS_CREDS_TID_COMM;
@@ -1057,7 +1037,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
if (!c->cgroup) {
r = cg_pid_get_path(NULL, pid, &c->cgroup);
if (r < 0) {
- if (r != -EPERM && r != -EACCES)
+ if (!IN_SET(r, -EPERM, -EACCES))
return r;
}
}
@@ -1079,7 +1059,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
c->audit_session_id = AUDIT_SESSION_INVALID;
c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
} else if (r < 0) {
- if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
+ if (!IN_SET(r, -EOPNOTSUPP, -ENOENT, -EPERM, -EACCES))
return r;
} else
c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
@@ -1092,7 +1072,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
c->audit_login_uid = UID_INVALID;
c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
} else if (r < 0) {
- if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
+ if (!IN_SET(r, -EOPNOTSUPP, -ENOENT, -EPERM, -EACCES))
return r;
} else
c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
@@ -1105,7 +1085,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
c->tty = NULL;
c->mask |= SD_BUS_CREDS_TTY;
} else if (r < 0) {
- if (r != -EPERM && r != -EACCES && r != -ENOENT)
+ if (!IN_SET(r, -EPERM, -EACCES, -ENOENT))
return r;
} else
c->mask |= SD_BUS_CREDS_TTY;
@@ -1353,7 +1333,7 @@ int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret)
if (r < 0)
return r;
- *ret = n;
- n = NULL;
+ *ret = TAKE_PTR(n);
+
return 0;
}
diff --git a/src/libelogind/sd-bus/bus-creds.h b/src/libelogind/sd-bus/bus-creds.h
index df8a1f100..7b77a1d73 100644
--- a/src/libelogind/sd-bus/bus-creds.h
+++ b/src/libelogind/sd-bus/bus-creds.h
@@ -1,22 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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>
diff --git a/src/libelogind/sd-bus/bus-error.c b/src/libelogind/sd-bus/bus-error.c
index 378f7a377..ec359ac13 100644
--- a/src/libelogind/sd-bus/bus-error.c
+++ b/src/libelogind/sd-bus/bus-error.c
@@ -1,20 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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>
@@ -107,6 +92,7 @@ static int bus_error_name_to_errno(const char *name) {
}
m = __start_BUS_ERROR_MAP;
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
while (m < __stop_BUS_ERROR_MAP) {
/* For magic ELF error maps, the end marker might
* appear in the middle of things, since multiple maps
@@ -124,6 +110,7 @@ static int bus_error_name_to_errno(const char *name) {
m++;
}
+#endif
return EIO;
}
@@ -594,7 +581,7 @@ _public_ int sd_bus_error_add_map(const sd_bus_error_map *map) {
if (additional_error_maps[n] == map)
return 0;
- maps = realloc_multiply(additional_error_maps, sizeof(struct sd_bus_error_map*), n + 2);
+ maps = reallocarray(additional_error_maps, n + 2, sizeof(struct sd_bus_error_map*));
if (!maps)
return -ENOMEM;
diff --git a/src/libelogind/sd-bus/bus-error.h b/src/libelogind/sd-bus/bus-error.h
index e2c4cf4b3..93cb9acd9 100644
--- a/src/libelogind/sd-bus/bus-error.h
+++ b/src/libelogind/sd-bus/bus-error.h
@@ -1,22 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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>
diff --git a/src/libelogind/sd-bus/bus-gvariant.c b/src/libelogind/sd-bus/bus-gvariant.c
index 58782767f..05b17589d 100644
--- a/src/libelogind/sd-bus/bus-gvariant.c
+++ b/src/libelogind/sd-bus/bus-gvariant.c
@@ -1,21 +1,11 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
+***/
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
+#include <errno.h>
+#include <string.h>
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+#include "sd-bus.h"
#include "bus-gvariant.h"
#include "bus-signature.h"
diff --git a/src/libelogind/sd-bus/bus-gvariant.h b/src/libelogind/sd-bus/bus-gvariant.h
index 6da637fb0..40e3053ec 100644
--- a/src/libelogind/sd-bus/bus-gvariant.h
+++ b/src/libelogind/sd-bus/bus-gvariant.h
@@ -1,22 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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"
diff --git a/src/libelogind/sd-bus/bus-internal.c b/src/libelogind/sd-bus/bus-internal.c
index 14d590a80..3e0f7d047 100644
--- a/src/libelogind/sd-bus/bus-internal.c
+++ b/src/libelogind/sd-bus/bus-internal.c
@@ -1,20 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "alloc-util.h"
@@ -148,7 +133,7 @@ bool service_name_is_valid(const char *p) {
(*q >= 'a' && *q <= 'z') ||
(*q >= 'A' && *q <= 'Z') ||
((!dot || unique) && *q >= '0' && *q <= '9') ||
- *q == '_' || *q == '-';
+ IN_SET(*q, '_', '-');
if (!good)
return false;
@@ -363,13 +348,18 @@ int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
} else
return r;
- log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
+ log_debug("Failed to process message type=%s sender=%s destination=%s path=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " signature=%s error-name=%s error-message=%s: %s",
bus_message_type_to_string(m->header->type),
- strna(m->sender),
- strna(m->path),
- strna(m->interface),
- strna(m->member),
+ strna(sd_bus_message_get_sender(m)),
+ strna(sd_bus_message_get_destination(m)),
+ strna(sd_bus_message_get_path(m)),
+ strna(sd_bus_message_get_interface(m)),
+ strna(sd_bus_message_get_member(m)),
+ BUS_MESSAGE_COOKIE(m),
+ m->reply_cookie,
strna(m->root_container.signature),
+ strna(m->error.name),
+ strna(m->error.message),
bus_error_message(error, r));
return 1;
diff --git a/src/libelogind/sd-bus/bus-internal.h b/src/libelogind/sd-bus/bus-internal.h
index 4818ae28b..904d61038 100644
--- a/src/libelogind/sd-bus/bus-internal.h
+++ b/src/libelogind/sd-bus/bus-internal.h
@@ -1,22 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <pthread.h>
@@ -27,8 +12,8 @@
#include "bus-error.h"
#include "bus-kernel.h"
#include "bus-match.h"
+#include "def.h"
#include "hashmap.h"
-#include "kdbus.h"
#include "list.h"
#include "prioq.h"
#include "refcnt.h"
@@ -37,7 +22,7 @@
struct reply_callback {
sd_bus_message_handler_t callback;
- usec_t timeout;
+ usec_t timeout_usec; /* this is a relative timeout until we reach the BUS_HELLO state, and an absolute one right after */
uint64_t cookie;
unsigned prioq_idx;
};
@@ -52,8 +37,10 @@ struct filter_callback {
struct match_callback {
sd_bus_message_handler_t callback;
+ sd_bus_message_handler_t install_callback;
+
+ sd_bus_slot *install_slot; /* The AddMatch() call */
- uint64_t cookie;
unsigned last_iteration;
char *match_string;
@@ -137,8 +124,17 @@ struct sd_bus_slot {
unsigned n_ref;
sd_bus *bus;
void *userdata;
+ sd_bus_destroy_t destroy_callback;
BusSlotType type:5;
+
+ /* Slots can be "floating" or not. If they are not floating (the usual case) then they reference the bus object
+ * they are associated with. This means the bus object stays allocated at least as long as there is a slot
+ * around associated with it. If it is floating, then the slot's lifecycle is bound to the lifecycle of the
+ * bus: it will be disconnected from the bus when the bus is destroyed, and it keeping the slot reffed hence
+ * won't mean the bus stays reffed too. Internally this means the reference direction is reversed: floating
+ * slots objects are referenced by the bus object, and not vice versa. */
bool floating:1;
+
bool match_added:1;
char *description;
@@ -157,12 +153,14 @@ struct sd_bus_slot {
enum bus_state {
BUS_UNSET,
- BUS_OPENING,
- BUS_AUTHENTICATING,
- BUS_HELLO,
+ BUS_WATCH_BIND, /* waiting for the socket to appear via inotify */
+ BUS_OPENING, /* the kernel's connect() is still not ready */
+ BUS_AUTHENTICATING, /* we are currently in the "SASL" authorization phase of dbus */
+ BUS_HELLO, /* we are waiting for the Hello() response */
BUS_RUNNING,
BUS_CLOSING,
- BUS_CLOSED
+ BUS_CLOSED,
+ _BUS_STATE_MAX,
};
static inline bool BUS_IS_OPEN(enum bus_state state) {
@@ -188,10 +186,10 @@ struct sd_bus {
enum bus_state state;
int input_fd, output_fd;
+ int inotify_fd;
int message_version;
int message_endian;
- bool is_kernel:1;
bool can_fds:1;
bool bus_client:1;
bool ucred_valid:1;
@@ -203,8 +201,6 @@ struct sd_bus {
bool filter_callbacks_modified:1;
bool nodes_modified:1;
bool trusted:1;
- bool fake_creds_valid:1;
- bool fake_pids_valid:1;
bool manual_peer_interface:1;
bool is_system:1;
bool is_user:1;
@@ -213,6 +209,11 @@ struct sd_bus {
bool exited:1;
bool exit_triggered:1;
bool is_local:1;
+ bool watch_bind:1;
+ bool is_monitor:1;
+ bool accept_fd:1;
+ bool attach_timestamp:1;
+ bool connected_signal:1;
int use_memfd;
@@ -245,7 +246,6 @@ struct sd_bus {
union sockaddr_union sockaddr;
socklen_t sockaddr_size;
- char *kernel;
char *machine;
pid_t nspid;
@@ -265,19 +265,19 @@ struct sd_bus {
struct ucred ucred;
char *label;
+ gid_t *groups;
+ size_t n_groups;
uint64_t creds_mask;
int *fds;
- unsigned n_fds;
+ size_t n_fds;
char *exec_path;
char **exec_argv;
unsigned iteration_counter;
- void *kdbus_buffer;
-
/* We do locking around the memfd cache, since we want to
* allow people to process a sd_bus_message in a different
* thread then it was generated on and free it there. Since
@@ -289,16 +289,13 @@ struct sd_bus {
unsigned n_memfd_cache;
pid_t original_pid;
-
- uint64_t hello_flags;
- uint64_t attach_flags;
-
- uint64_t match_cookie;
+ pid_t busexec_pid;
sd_event_source *input_io_event_source;
sd_event_source *output_io_event_source;
sd_event_source *time_event_source;
sd_event_source *quit_event_source;
+ sd_event_source *inotify_event_source;
sd_event *event;
int event_priority;
@@ -310,29 +307,31 @@ struct sd_bus {
sd_bus **default_bus_ptr;
pid_t tid;
- struct kdbus_creds fake_creds;
- struct kdbus_pids fake_pids;
- char *fake_label;
-
char *cgroup_root;
char *description;
-
- size_t bloom_size;
- unsigned bloom_n_hash;
+ char *patch_sender;
sd_bus_track *track_queue;
LIST_HEAD(sd_bus_slot, slots);
LIST_HEAD(sd_bus_track, tracks);
+
+ int *inotify_watches;
+ size_t n_inotify_watches;
};
+/* For method calls we time-out at 25s, like in the D-Bus reference implementation */
#define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC))
+/* For the authentication phase we grant 90s, to provide extra room during boot, when RNGs and such are not filled up
+ * with enough entropy yet and might delay the boot */
+#define BUS_AUTH_TIMEOUT ((usec_t) DEFAULT_TIMEOUT_USEC)
+
#define BUS_WQUEUE_MAX (192*1024)
#define BUS_RQUEUE_MAX (192*1024)
-#define BUS_MESSAGE_SIZE_MAX (64*1024*1024)
+#define BUS_MESSAGE_SIZE_MAX (128*1024*1024)
#define BUS_AUTH_SIZE_MAX (64*1024)
#define BUS_CONTAINER_DEPTH 128
@@ -365,6 +364,8 @@ const char *bus_message_type_to_string(uint8_t u) _pure_;
#define error_name_is_valid interface_name_is_valid
+sd_bus *bus_resolve(sd_bus *bus);
+
int bus_ensure_running(sd_bus *bus);
int bus_start_running(sd_bus *bus);
int bus_next_address(sd_bus *bus);
@@ -377,6 +378,12 @@ bool bus_pid_changed(sd_bus *bus);
char *bus_address_escape(const char *v);
+int bus_attach_io_events(sd_bus *b);
+int bus_attach_inotify_event(sd_bus *b);
+
+void bus_close_inotify_fd(sd_bus *b);
+void bus_close_io_fds(sd_bus *b);
+
#define OBJECT_PATH_FOREACH_PREFIX(prefix, path) \
for (char *_slash = ({ strcpy((prefix), (path)); streq((prefix), "/") ? NULL : strrchr((prefix), '/'); }) ; \
_slash && !(_slash[(_slash) == (prefix)] = 0); \
@@ -396,9 +403,7 @@ int bus_set_address_system_remote(sd_bus *b, const char *host);
int bus_set_address_system_machine(sd_bus *b, const char *machine);
#if 0 /// UNNEEDED by elogind
-int bus_remove_match_by_string(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata);
#endif // 0
-
int bus_get_root_path(sd_bus *bus);
int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error);
@@ -408,3 +413,7 @@ int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error);
if (!assert_log(expr, #expr)) \
return sd_bus_error_set_errno(error, r); \
} while (false)
+
+void bus_enter_closing(sd_bus *bus);
+
+void bus_set_state(sd_bus *bus, enum bus_state state);
diff --git a/src/libelogind/sd-bus/bus-introspect.c b/src/libelogind/sd-bus/bus-introspect.c
index d4b9878b1..483c29949 100644
--- a/src/libelogind/sd-bus/bus-introspect.c
+++ b/src/libelogind/sd-bus/bus-introspect.c
@@ -1,22 +1,9 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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_ext.h>
+
#include "bus-internal.h"
#include "bus-introspect.h"
#include "bus-protocol.h"
@@ -36,6 +23,8 @@ int introspect_begin(struct introspect *i, bool trusted) {
if (!i->f)
return -ENOMEM;
+ (void) __fsetlocking(i->f, FSETLOCKING_BYCALLER);
+
fputs(BUS_INTROSPECT_DOCTYPE
"<node>\n", i->f);
@@ -81,9 +70,9 @@ static void introspect_write_flags(struct introspect *i, int type, int flags) {
if (type == _SD_BUS_VTABLE_METHOD && (flags & SD_BUS_VTABLE_METHOD_NO_REPLY))
fputs(" <annotation name=\"org.freedesktop.DBus.Method.NoReply\" value=\"true\"/>\n", i->f);
- if (type == _SD_BUS_VTABLE_PROPERTY || type == _SD_BUS_VTABLE_WRITABLE_PROPERTY) {
+ if (IN_SET(type, _SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY)) {
if (flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT)
- fputs(" <annotation name=\"org.freedesktop.login1.Explicit\" value=\"true\"/>\n", i->f);
+ fputs(" <annotation name=\"org.freedesktop.elogind1.Explicit\" value=\"true\"/>\n", i->f);
if (flags & SD_BUS_VTABLE_PROPERTY_CONST)
fputs(" <annotation name=\"org.freedesktop.DBus.Property.EmitsChangedSignal\" value=\"const\"/>\n", i->f);
@@ -94,9 +83,9 @@ static void introspect_write_flags(struct introspect *i, int type, int flags) {
}
if (!i->trusted &&
- (type == _SD_BUS_VTABLE_METHOD || type == _SD_BUS_VTABLE_WRITABLE_PROPERTY) &&
+ IN_SET(type, _SD_BUS_VTABLE_METHOD, _SD_BUS_VTABLE_WRITABLE_PROPERTY) &&
!(flags & SD_BUS_VTABLE_UNPRIVILEGED))
- fputs(" <annotation name=\"org.freedesktop.login1.Privileged\" value=\"true\"/>\n", i->f);
+ fputs(" <annotation name=\"org.freedesktop.elogind1.Privileged\" value=\"true\"/>\n", i->f);
}
static int introspect_write_arguments(struct introspect *i, const char *signature, const char *direction) {
diff --git a/src/libelogind/sd-bus/bus-introspect.h b/src/libelogind/sd-bus/bus-introspect.h
index 8e2f3800c..5dcaeace9 100644
--- a/src/libelogind/sd-bus/bus-introspect.h
+++ b/src/libelogind/sd-bus/bus-introspect.h
@@ -1,22 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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>
diff --git a/src/libelogind/sd-bus/bus-kernel.c b/src/libelogind/sd-bus/bus-kernel.c
index 84a8b7766..e0f521b4f 100644
--- a/src/libelogind/sd-bus/bus-kernel.c
+++ b/src/libelogind/sd-bus/bus-kernel.c
@@ -1,23 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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_VALGRIND_MEMCHECK_H
+#if HAVE_VALGRIND_MEMCHECK_H
#include <valgrind/memcheck.h>
#endif
@@ -33,7 +18,6 @@
#undef basename
#include "alloc-util.h"
-#include "bus-bloom.h"
#include "bus-internal.h"
#include "bus-kernel.h"
#include "bus-label.h"
@@ -51,1471 +35,14 @@
#include "user-util.h"
#include "util.h"
-#pragma GCC diagnostic ignored "-Wformat"
-
-#define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t))
-
-int bus_kernel_parse_unique_name(const char *s, uint64_t *id) {
- int r;
-
- assert(s);
- assert(id);
-
- if (!startswith(s, ":1."))
- return 0;
-
- r = safe_atou64(s + 3, id);
- if (r < 0)
- return r;
-
- return 1;
-}
-
-static void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) {
- assert(d);
- assert(sz > 0);
-
- *d = ALIGN8_PTR(*d);
-
- /* Note that p can be NULL, which encodes a region full of
- * zeroes, which is useful to optimize certain padding
- * conditions */
-
- (*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec);
- (*d)->type = KDBUS_ITEM_PAYLOAD_VEC;
- (*d)->vec.address = PTR_TO_UINT64(p);
- (*d)->vec.size = sz;
-
- *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
-}
-
-static void append_payload_memfd(struct kdbus_item **d, int memfd, size_t start, size_t sz) {
- assert(d);
- assert(memfd >= 0);
- assert(sz > 0);
-
- *d = ALIGN8_PTR(*d);
- (*d)->size = offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd);
- (*d)->type = KDBUS_ITEM_PAYLOAD_MEMFD;
- (*d)->memfd.fd = memfd;
- (*d)->memfd.start = start;
- (*d)->memfd.size = sz;
-
- *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
-}
-
-static void append_destination(struct kdbus_item **d, const char *s, size_t length) {
- assert(d);
- assert(s);
-
- *d = ALIGN8_PTR(*d);
-
- (*d)->size = offsetof(struct kdbus_item, str) + length + 1;
- (*d)->type = KDBUS_ITEM_DST_NAME;
- memcpy((*d)->str, s, length + 1);
-
- *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
-}
-
-static struct kdbus_bloom_filter *append_bloom(struct kdbus_item **d, size_t length) {
- struct kdbus_item *i;
-
- assert(d);
-
- i = ALIGN8_PTR(*d);
-
- i->size = offsetof(struct kdbus_item, bloom_filter) +
- offsetof(struct kdbus_bloom_filter, data) +
- length;
- i->type = KDBUS_ITEM_BLOOM_FILTER;
-
- *d = (struct kdbus_item *) ((uint8_t*) i + i->size);
-
- return &i->bloom_filter;
-}
-
-static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) {
- assert(d);
- assert(fds);
- assert(n_fds > 0);
-
- *d = ALIGN8_PTR(*d);
- (*d)->size = offsetof(struct kdbus_item, fds) + sizeof(int) * n_fds;
- (*d)->type = KDBUS_ITEM_FDS;
- memcpy((*d)->fds, fds, sizeof(int) * n_fds);
-
- *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
-}
-
-static void add_bloom_arg(void *data, size_t size, unsigned n_hash, unsigned i, const char *t) {
- char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
- char *e;
-
- assert(data);
- assert(size > 0);
- assert(i < 64);
- assert(t);
-
- e = stpcpy(buf, "arg");
- if (i < 10)
- *(e++) = '0' + (char) i;
- else {
- *(e++) = '0' + (char) (i / 10);
- *(e++) = '0' + (char) (i % 10);
- }
-
- *e = 0;
- bloom_add_pair(data, size, n_hash, buf, t);
-
- strcpy(e, "-dot-prefix");
- bloom_add_prefixes(data, size, n_hash, buf, t, '.');
- strcpy(e, "-slash-prefix");
- bloom_add_prefixes(data, size, n_hash, buf, t, '/');
-}
-
-static void add_bloom_arg_has(void *data, size_t size, unsigned n_hash, unsigned i, const char *t) {
- char buf[sizeof("arg")-1 + 2 + sizeof("-has")];
- char *e;
-
- assert(data);
- assert(size > 0);
- assert(i < 64);
- assert(t);
-
- e = stpcpy(buf, "arg");
- if (i < 10)
- *(e++) = '0' + (char) i;
- else {
- *(e++) = '0' + (char) (i / 10);
- *(e++) = '0' + (char) (i % 10);
- }
-
- strcpy(e, "-has");
- bloom_add_pair(data, size, n_hash, buf, t);
-}
-
-static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter *bloom) {
- void *data;
- unsigned i;
- int r;
-
- assert(m);
- assert(bloom);
-
- data = bloom->data;
- memzero(data, m->bus->bloom_size);
- bloom->generation = 0;
-
- bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "message-type", bus_message_type_to_string(m->header->type));
-
- if (m->interface)
- bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "interface", m->interface);
- if (m->member)
- bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "member", m->member);
- if (m->path) {
- bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path", m->path);
- bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path-slash-prefix", m->path);
- bloom_add_prefixes(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path-slash-prefix", m->path, '/');
- }
-
- r = sd_bus_message_rewind(m, true);
- if (r < 0)
- return r;
-
- for (i = 0; i < 64; i++) {
- const char *t, *contents;
- char type;
-
- r = sd_bus_message_peek_type(m, &type, &contents);
- if (r < 0)
- return r;
-
- if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
-
- /* The bloom filter includes simple strings of any kind */
- r = sd_bus_message_read_basic(m, type, &t);
- if (r < 0)
- return r;
-
- add_bloom_arg(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t);
- }
-
- if (type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")) {
-
- /* As well as array of simple strings of any kinds */
- r = sd_bus_message_enter_container(m, type, contents);
- if (r < 0)
- return r;
-
- while ((r = sd_bus_message_read_basic(m, contents[0], &t)) > 0)
- add_bloom_arg_has(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t);
- if (r < 0)
- return r;
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return r;
-
- } else
- /* Stop adding to bloom filter as soon as we
- * run into the first argument we cannot add
- * to it. */
- break;
- }
-
- return 0;
-}
-
-static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
- struct bus_body_part *part;
- struct kdbus_item *d;
- const char *destination;
- bool well_known = false;
- uint64_t dst_id;
- size_t sz, dl;
- unsigned i;
- int r;
-
- assert(b);
- assert(m);
- assert(m->sealed);
-
- /* We put this together only once, if this message is reused
- * we reuse the earlier-built version */
- if (m->kdbus)
- return 0;
-
- destination = m->destination ?: m->destination_ptr;
-
- if (destination) {
- r = bus_kernel_parse_unique_name(destination, &dst_id);
- if (r < 0)
- return r;
- if (r == 0) {
- well_known = true;
-
- /* verify_destination_id will usually be 0, which makes the kernel
- * driver only look at the provided well-known name. Otherwise,
- * the kernel will make sure the provided destination id matches
- * the owner of the provided well-known-name, and fail if they
- * differ. Currently, this is only needed for bus-proxyd. */
- dst_id = m->verify_destination_id;
- }
- } else
- dst_id = KDBUS_DST_ID_BROADCAST;
-
- sz = offsetof(struct kdbus_msg, items);
-
- /* Add in fixed header, fields header and payload */
- sz += (1 + m->n_body_parts) * ALIGN8(offsetof(struct kdbus_item, vec) +
- MAX(sizeof(struct kdbus_vec),
- sizeof(struct kdbus_memfd)));
-
- /* Add space for bloom filter */
- sz += ALIGN8(offsetof(struct kdbus_item, bloom_filter) +
- offsetof(struct kdbus_bloom_filter, data) +
- m->bus->bloom_size);
-
- /* Add in well-known destination header */
- if (well_known) {
- dl = strlen(destination);
- sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1);
- }
-
- /* Add space for unix fds */
- if (m->n_fds > 0)
- sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
-
- m->kdbus = memalign(8, sz);
- if (!m->kdbus) {
- r = -ENOMEM;
- goto fail;
- }
-
- m->free_kdbus = true;
- memzero(m->kdbus, sz);
-
- m->kdbus->flags =
- ((m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_EXPECT_REPLY) |
- ((m->header->flags & BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_NO_AUTO_START : 0) |
- ((m->header->type == SD_BUS_MESSAGE_SIGNAL) ? KDBUS_MSG_SIGNAL : 0);
-
- m->kdbus->dst_id = dst_id;
- m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS;
- m->kdbus->cookie = m->header->dbus2.cookie;
- m->kdbus->priority = m->priority;
-
- if (m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
- m->kdbus->cookie_reply = m->reply_cookie;
- else {
- struct timespec now;
-
- assert_se(clock_gettime(CLOCK_MONOTONIC_COARSE, &now) == 0);
- m->kdbus->timeout_ns = now.tv_sec * NSEC_PER_SEC + now.tv_nsec +
- m->timeout * NSEC_PER_USEC;
- }
-
- d = m->kdbus->items;
-
- if (well_known)
- append_destination(&d, destination, dl);
-
- append_payload_vec(&d, m->header, BUS_MESSAGE_BODY_BEGIN(m));
-
- MESSAGE_FOREACH_PART(part, i, m) {
- if (part->is_zero) {
- /* If this is padding then simply send a
- * vector with a NULL data pointer which the
- * kernel will just pass through. This is the
- * most efficient way to encode zeroes */
-
- append_payload_vec(&d, NULL, part->size);
- continue;
- }
-
- if (part->memfd >= 0 && part->sealed && destination) {
- /* Try to send a memfd, if the part is
- * sealed and this is not a broadcast. Since we can only */
-
- append_payload_memfd(&d, part->memfd, part->memfd_offset, part->size);
- continue;
- }
-
- /* Otherwise, let's send a vector to the actual data.
- * For that, we need to map it first. */
- r = bus_body_part_map(part);
- if (r < 0)
- goto fail;
-
- append_payload_vec(&d, part->data, part->size);
- }
-
- if (m->header->type == SD_BUS_MESSAGE_SIGNAL) {
- struct kdbus_bloom_filter *bloom;
-
- bloom = append_bloom(&d, m->bus->bloom_size);
- r = bus_message_setup_bloom(m, bloom);
- if (r < 0)
- goto fail;
- }
-
- if (m->n_fds > 0)
- append_fds(&d, m->fds, m->n_fds);
-
- m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
- assert(m->kdbus->size <= sz);
-
- return 0;
-
-fail:
- m->poisoned = true;
- return r;
-}
-
-static void unset_memfds(struct sd_bus_message *m) {
- struct bus_body_part *part;
- unsigned i;
-
- assert(m);
-
- /* Make sure the memfds are not freed twice */
- MESSAGE_FOREACH_PART(part, i, m)
- if (part->memfd >= 0)
- part->memfd = -1;
-}
-
-static void message_set_timestamp(sd_bus *bus, sd_bus_message *m, const struct kdbus_timestamp *ts) {
- assert(bus);
- assert(m);
-
- if (!ts)
- return;
-
- if (!(bus->attach_flags & KDBUS_ATTACH_TIMESTAMP))
- return;
-
- m->realtime = ts->realtime_ns / NSEC_PER_USEC;
- m->monotonic = ts->monotonic_ns / NSEC_PER_USEC;
- m->seqnum = ts->seqnum;
-}
-
-static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
- sd_bus_message *m = NULL;
- struct kdbus_item *d;
- unsigned n_fds = 0;
- _cleanup_free_ int *fds = NULL;
- struct bus_header *header = NULL;
- void *footer = NULL;
- size_t header_size = 0, footer_size = 0;
- size_t n_bytes = 0, idx = 0;
- const char *destination = NULL, *seclabel = NULL;
- bool last_was_memfd = false;
- int r;
-
- assert(bus);
- assert(k);
- assert(k->payload_type == KDBUS_PAYLOAD_DBUS);
-
- KDBUS_ITEM_FOREACH(d, k, items) {
- size_t l;
-
- l = d->size - offsetof(struct kdbus_item, data);
-
- switch (d->type) {
-
- case KDBUS_ITEM_PAYLOAD_OFF:
- if (!header) {
- header = (struct bus_header*)((uint8_t*) k + d->vec.offset);
- header_size = d->vec.size;
- }
-
- footer = (uint8_t*) k + d->vec.offset;
- footer_size = d->vec.size;
-
- n_bytes += d->vec.size;
- last_was_memfd = false;
- break;
-
- case KDBUS_ITEM_PAYLOAD_MEMFD:
- if (!header) /* memfd cannot be first part */
- return -EBADMSG;
-
- n_bytes += d->memfd.size;
- last_was_memfd = true;
- break;
-
- case KDBUS_ITEM_FDS: {
- int *f;
- unsigned j;
-
- j = l / sizeof(int);
- f = realloc(fds, sizeof(int) * (n_fds + j));
- if (!f)
- return -ENOMEM;
-
- fds = f;
- memcpy(fds + n_fds, d->fds, sizeof(int) * j);
- n_fds += j;
- break;
- }
-
- case KDBUS_ITEM_SECLABEL:
- seclabel = d->str;
- break;
- }
- }
-
- if (last_was_memfd) /* memfd cannot be last part */
- return -EBADMSG;
-
- if (!header)
- return -EBADMSG;
-
- if (header_size < sizeof(struct bus_header))
- return -EBADMSG;
-
- /* on kdbus we only speak native endian gvariant, never dbus1
- * marshalling or reverse endian */
- if (header->version != 2 ||
- header->endian != BUS_NATIVE_ENDIAN)
- return -EPROTOTYPE;
-
- r = bus_message_from_header(
- bus,
- header, header_size,
- footer, footer_size,
- n_bytes,
- fds, n_fds,
- seclabel, 0, &m);
- if (r < 0)
- return r;
-
- /* The well-known names list is different from the other
- credentials. If we asked for it, but nothing is there, this
- means that the list of well-known names is simply empty, not
- that we lack any data */
-
- m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
-
- KDBUS_ITEM_FOREACH(d, k, items) {
- size_t l;
-
- l = d->size - offsetof(struct kdbus_item, data);
-
- switch (d->type) {
-
- case KDBUS_ITEM_PAYLOAD_OFF: {
- size_t begin_body;
-
- begin_body = BUS_MESSAGE_BODY_BEGIN(m);
-
- if (idx + d->vec.size > begin_body) {
- struct bus_body_part *part;
-
- /* Contains body material */
-
- part = message_append_part(m);
- if (!part) {
- r = -ENOMEM;
- goto fail;
- }
-
- /* A -1 offset is NUL padding. */
- part->is_zero = d->vec.offset == ~0ULL;
-
- if (idx >= begin_body) {
- if (!part->is_zero)
- part->data = (uint8_t* )k + d->vec.offset;
- part->size = d->vec.size;
- } else {
- if (!part->is_zero)
- part->data = (uint8_t*) k + d->vec.offset + (begin_body - idx);
- part->size = d->vec.size - (begin_body - idx);
- }
-
- part->sealed = true;
- }
-
- idx += d->vec.size;
- break;
- }
-
- case KDBUS_ITEM_PAYLOAD_MEMFD: {
- struct bus_body_part *part;
-
- if (idx < BUS_MESSAGE_BODY_BEGIN(m)) {
- r = -EBADMSG;
- goto fail;
- }
-
- part = message_append_part(m);
- if (!part) {
- r = -ENOMEM;
- goto fail;
- }
-
- part->memfd = d->memfd.fd;
- part->memfd_offset = d->memfd.start;
- part->size = d->memfd.size;
- part->sealed = true;
-
- idx += d->memfd.size;
- break;
- }
-
- case KDBUS_ITEM_PIDS:
-
- /* The PID/TID might be missing, when the data
- * is faked by a bus proxy and it lacks that
- * information about the real client (since
- * SO_PEERCRED is used for that). Also kernel
- * namespacing might make some of this data
- * unavailable when untranslatable. */
-
- if (d->pids.pid > 0) {
- m->creds.pid = (pid_t) d->pids.pid;
- m->creds.mask |= SD_BUS_CREDS_PID & bus->creds_mask;
- }
-
- if (d->pids.tid > 0) {
- m->creds.tid = (pid_t) d->pids.tid;
- m->creds.mask |= SD_BUS_CREDS_TID & bus->creds_mask;
- }
-
- if (d->pids.ppid > 0) {
- m->creds.ppid = (pid_t) d->pids.ppid;
- m->creds.mask |= SD_BUS_CREDS_PPID & bus->creds_mask;
- } else if (d->pids.pid == 1) {
- m->creds.ppid = 0;
- m->creds.mask |= SD_BUS_CREDS_PPID & bus->creds_mask;
- }
-
- break;
-
- case KDBUS_ITEM_CREDS:
-
- /* EUID/SUID/FSUID/EGID/SGID/FSGID might be
- * missing too (see above). */
-
- if ((uid_t) d->creds.uid != UID_INVALID) {
- m->creds.uid = (uid_t) d->creds.uid;
- m->creds.mask |= SD_BUS_CREDS_UID & bus->creds_mask;
- }
-
- if ((uid_t) d->creds.euid != UID_INVALID) {
- m->creds.euid = (uid_t) d->creds.euid;
- m->creds.mask |= SD_BUS_CREDS_EUID & bus->creds_mask;
- }
-
- if ((uid_t) d->creds.suid != UID_INVALID) {
- m->creds.suid = (uid_t) d->creds.suid;
- m->creds.mask |= SD_BUS_CREDS_SUID & bus->creds_mask;
- }
-
- if ((uid_t) d->creds.fsuid != UID_INVALID) {
- m->creds.fsuid = (uid_t) d->creds.fsuid;
- m->creds.mask |= SD_BUS_CREDS_FSUID & bus->creds_mask;
- }
-
- if ((gid_t) d->creds.gid != GID_INVALID) {
- m->creds.gid = (gid_t) d->creds.gid;
- m->creds.mask |= SD_BUS_CREDS_GID & bus->creds_mask;
- }
-
- if ((gid_t) d->creds.egid != GID_INVALID) {
- m->creds.egid = (gid_t) d->creds.egid;
- m->creds.mask |= SD_BUS_CREDS_EGID & bus->creds_mask;
- }
-
- if ((gid_t) d->creds.sgid != GID_INVALID) {
- m->creds.sgid = (gid_t) d->creds.sgid;
- m->creds.mask |= SD_BUS_CREDS_SGID & bus->creds_mask;
- }
-
- if ((gid_t) d->creds.fsgid != GID_INVALID) {
- m->creds.fsgid = (gid_t) d->creds.fsgid;
- m->creds.mask |= SD_BUS_CREDS_FSGID & bus->creds_mask;
- }
-
- break;
-
- case KDBUS_ITEM_TIMESTAMP:
- message_set_timestamp(bus, m, &d->timestamp);
- break;
-
- case KDBUS_ITEM_PID_COMM:
- m->creds.comm = d->str;
- m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask;
- break;
-
- case KDBUS_ITEM_TID_COMM:
- m->creds.tid_comm = d->str;
- m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask;
- break;
-
- case KDBUS_ITEM_EXE:
- m->creds.exe = d->str;
- m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask;
- break;
-
- case KDBUS_ITEM_CMDLINE:
- m->creds.cmdline = d->str;
- m->creds.cmdline_size = l;
- m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask;
- break;
-
- case KDBUS_ITEM_CGROUP:
- m->creds.cgroup = d->str;
- m->creds.mask |= (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID) & bus->creds_mask;
-
- r = bus_get_root_path(bus);
- if (r < 0)
- goto fail;
-
- m->creds.cgroup_root = bus->cgroup_root;
- break;
-
- case KDBUS_ITEM_AUDIT:
- m->creds.audit_session_id = (uint32_t) d->audit.sessionid;
- m->creds.mask |= SD_BUS_CREDS_AUDIT_SESSION_ID & bus->creds_mask;
-
- m->creds.audit_login_uid = (uid_t) d->audit.loginuid;
- m->creds.mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID & bus->creds_mask;
- break;
-
- case KDBUS_ITEM_CAPS:
- if (d->caps.last_cap != cap_last_cap() ||
- d->size - offsetof(struct kdbus_item, caps.caps) < DIV_ROUND_UP(d->caps.last_cap, 32U) * 4 * 4) {
- r = -EBADMSG;
- goto fail;
- }
-
- m->creds.capability = d->caps.caps;
- m->creds.mask |= (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS) & bus->creds_mask;
- break;
-
- case KDBUS_ITEM_DST_NAME:
- if (!service_name_is_valid(d->str)) {
- r = -EBADMSG;
- goto fail;
- }
-
- destination = d->str;
- break;
-
- case KDBUS_ITEM_OWNED_NAME:
- if (!service_name_is_valid(d->name.name)) {
- r = -EBADMSG;
- goto fail;
- }
-
- if (bus->creds_mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
- char **wkn;
- size_t n;
-
- /* We just extend the array here, but
- * do not allocate the strings inside
- * of it, instead we just point to our
- * buffer directly. */
- n = strv_length(m->creds.well_known_names);
- wkn = realloc(m->creds.well_known_names, (n + 2) * sizeof(char*));
- if (!wkn) {
- r = -ENOMEM;
- goto fail;
- }
-
- wkn[n] = d->name.name;
- wkn[n+1] = NULL;
- m->creds.well_known_names = wkn;
-
- m->creds.mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
- }
- break;
-
- case KDBUS_ITEM_CONN_DESCRIPTION:
- m->creds.description = d->str;
- m->creds.mask |= SD_BUS_CREDS_DESCRIPTION & bus->creds_mask;
- break;
-
- case KDBUS_ITEM_AUXGROUPS:
-
- if (bus->creds_mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
- size_t i, n;
- gid_t *g;
-
- n = (d->size - offsetof(struct kdbus_item, data64)) / sizeof(uint64_t);
- g = new(gid_t, n);
- if (!g) {
- r = -ENOMEM;
- goto fail;
- }
-
- for (i = 0; i < n; i++)
- g[i] = d->data64[i];
-
- m->creds.supplementary_gids = g;
- m->creds.n_supplementary_gids = n;
- m->creds.mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
- }
-
- break;
-
- case KDBUS_ITEM_FDS:
- case KDBUS_ITEM_SECLABEL:
- case KDBUS_ITEM_BLOOM_FILTER:
- break;
-
- default:
- log_debug("Got unknown field from kernel %llu", d->type);
- }
- }
-
- /* If we requested the list of well-known names to be appended
- * and the sender had none no item for it will be
- * attached. However, this does *not* mean that the kernel
- * didn't want to provide this information to us. Hence, let's
- * explicitly mark this information as available if it was
- * requested. */
- m->creds.mask |= bus->creds_mask & SD_BUS_CREDS_WELL_KNOWN_NAMES;
-
- r = bus_message_parse_fields(m);
- if (r < 0)
- goto fail;
-
- /* Refuse messages if kdbus and dbus1 cookie doesn't match up */
- if ((uint64_t) m->header->dbus2.cookie != k->cookie) {
- r = -EBADMSG;
- goto fail;
- }
-
- /* Refuse messages where the reply flag doesn't match up */
- if (!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) != !!(k->flags & KDBUS_MSG_EXPECT_REPLY)) {
- r = -EBADMSG;
- goto fail;
- }
-
- /* Refuse reply messages where the reply cookie doesn't match up */
- if ((m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) && m->reply_cookie != k->cookie_reply) {
- r = -EBADMSG;
- goto fail;
- }
-
- /* Refuse messages where the autostart flag doesn't match up */
- if (!(m->header->flags & BUS_MESSAGE_NO_AUTO_START) != !(k->flags & KDBUS_MSG_NO_AUTO_START)) {
- r = -EBADMSG;
- goto fail;
- }
-
- /* Override information from the user header with data from the kernel */
- if (k->src_id == KDBUS_SRC_ID_KERNEL)
- bus_message_set_sender_driver(bus, m);
- else {
- xsprintf(m->sender_buffer, ":1.%llu", k->src_id);
- m->sender = m->creds.unique_name = m->sender_buffer;
- }
-
- if (destination)
- m->destination = destination;
- else if (k->dst_id == KDBUS_DST_ID_BROADCAST)
- m->destination = NULL;
- else if (k->dst_id == KDBUS_DST_ID_NAME)
- m->destination = bus->unique_name; /* fill in unique name if the well-known name is missing */
- else {
- xsprintf(m->destination_buffer, ":1.%llu", k->dst_id);
- m->destination = m->destination_buffer;
- }
-
- /* We take possession of the kmsg struct now */
- m->kdbus = k;
- m->release_kdbus = true;
- m->free_fds = true;
- fds = NULL;
-
- bus->rqueue[bus->rqueue_size++] = m;
-
- return 1;
-
-fail:
- unset_memfds(m);
- sd_bus_message_unref(m);
-
- return r;
-}
-
-int bus_kernel_take_fd(sd_bus *b) {
- struct kdbus_bloom_parameter *bloom = NULL;
- struct kdbus_item *items, *item;
- struct kdbus_cmd_hello *hello;
- _cleanup_free_ char *g = NULL;
- const char *name;
- size_t l = 0, m = 0, sz;
- int r;
-
- assert(b);
-
- if (b->is_server)
- return -EINVAL;
-
- b->use_memfd = 1;
-
- if (b->description) {
- g = bus_label_escape(b->description);
- if (!g)
- return -ENOMEM;
-
- name = g;
- } else {
- char pr[17] = {};
-
- /* If no name is explicitly set, we'll include a hint
- * indicating the library implementation, a hint which
- * kind of bus this is and the thread name */
-
- assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
-
- if (isempty(pr)) {
- name = b->is_system ? "sd-system" :
- b->is_user ? "sd-user" : "sd";
- } else {
- _cleanup_free_ char *e = NULL;
-
- e = bus_label_escape(pr);
- if (!e)
- return -ENOMEM;
-
- g = strappend(b->is_system ? "sd-system-" :
- b->is_user ? "sd-user-" : "sd-",
- e);
- if (!g)
- return -ENOMEM;
-
- name = g;
- }
-
- b->description = bus_label_unescape(name);
- if (!b->description)
- return -ENOMEM;
- }
-
- m = strlen(name);
-
- sz = ALIGN8(offsetof(struct kdbus_cmd_hello, items)) +
- ALIGN8(offsetof(struct kdbus_item, str) + m + 1);
-
- if (b->fake_creds_valid)
- sz += ALIGN8(offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds));
-
- if (b->fake_pids_valid)
- sz += ALIGN8(offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids));
-
- if (b->fake_label) {
- l = strlen(b->fake_label);
- sz += ALIGN8(offsetof(struct kdbus_item, str) + l + 1);
- }
-
- hello = alloca0_align(sz, 8);
- hello->size = sz;
- hello->flags = b->hello_flags;
- hello->attach_flags_send = _KDBUS_ATTACH_ANY;
- hello->attach_flags_recv = b->attach_flags;
- hello->pool_size = KDBUS_POOL_SIZE;
-
- item = hello->items;
-
- item->size = offsetof(struct kdbus_item, str) + m + 1;
- item->type = KDBUS_ITEM_CONN_DESCRIPTION;
- memcpy(item->str, name, m + 1);
- item = KDBUS_ITEM_NEXT(item);
-
- if (b->fake_creds_valid) {
- item->size = offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds);
- item->type = KDBUS_ITEM_CREDS;
- item->creds = b->fake_creds;
-
- item = KDBUS_ITEM_NEXT(item);
- }
-
- if (b->fake_pids_valid) {
- item->size = offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids);
- item->type = KDBUS_ITEM_PIDS;
- item->pids = b->fake_pids;
-
- item = KDBUS_ITEM_NEXT(item);
- }
-
- if (b->fake_label) {
- item->size = offsetof(struct kdbus_item, str) + l + 1;
- item->type = KDBUS_ITEM_SECLABEL;
- memcpy(item->str, b->fake_label, l+1);
- }
-
- r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello);
- if (r < 0) {
- if (errno == ENOTTY)
- /* If the ioctl is not supported we assume that the
- * API version changed in a major incompatible way,
- * let's indicate an API incompatibility in this
- * case. */
- return -ESOCKTNOSUPPORT;
-
- return -errno;
- }
-
- if (!b->kdbus_buffer) {
- b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0);
- if (b->kdbus_buffer == MAP_FAILED) {
- b->kdbus_buffer = NULL;
- r = -errno;
- goto fail;
- }
- }
-
- /* The higher 32bit of the bus_flags fields are considered
- * 'incompatible flags'. Refuse them all for now. */
- if (hello->bus_flags > 0xFFFFFFFFULL) {
- r = -ESOCKTNOSUPPORT;
- goto fail;
- }
-
- /* extract bloom parameters from items */
- items = (void*)((uint8_t*)b->kdbus_buffer + hello->offset);
- KDBUS_FOREACH(item, items, hello->items_size) {
- switch (item->type) {
- case KDBUS_ITEM_BLOOM_PARAMETER:
- bloom = &item->bloom_parameter;
- break;
- }
- }
-
- if (!bloom || !bloom_validate_parameters((size_t) bloom->size, (unsigned) bloom->n_hash)) {
- r = -EOPNOTSUPP;
- goto fail;
- }
-
- b->bloom_size = (size_t) bloom->size;
- b->bloom_n_hash = (unsigned) bloom->n_hash;
-
- if (asprintf(&b->unique_name, ":1.%llu", hello->id) < 0) {
- r = -ENOMEM;
- goto fail;
- }
-
- b->unique_id = hello->id;
-
- b->is_kernel = true;
- b->bus_client = true;
- b->can_fds = !!(hello->flags & KDBUS_HELLO_ACCEPT_FD);
- b->message_version = 2;
- b->message_endian = BUS_NATIVE_ENDIAN;
-
- /* the kernel told us the UUID of the underlying bus */
- memcpy(b->server_id.bytes, hello->id128, sizeof(b->server_id.bytes));
-
- /* free returned items */
- (void) bus_kernel_cmd_free(b, hello->offset);
- return bus_start_running(b);
-
-fail:
- (void) bus_kernel_cmd_free(b, hello->offset);
- return r;
-}
-
-int bus_kernel_connect(sd_bus *b) {
- assert(b);
- assert(b->input_fd < 0);
- assert(b->output_fd < 0);
- assert(b->kernel);
-
- if (b->is_server)
- return -EINVAL;
-
- b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (b->input_fd < 0)
- return -errno;
-
- b->output_fd = b->input_fd;
-
- return bus_kernel_take_fd(b);
-}
-
-int bus_kernel_cmd_free(sd_bus *bus, uint64_t offset) {
- struct kdbus_cmd_free cmd = {
- .size = sizeof(cmd),
- .offset = offset,
- };
- int r;
-
- assert(bus);
- assert(bus->is_kernel);
-
- r = ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd);
- if (r < 0)
- return -errno;
-
- return 0;
-}
-
-static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
- struct kdbus_item *d;
-
- assert(bus);
- assert(k);
-
- KDBUS_ITEM_FOREACH(d, k, items) {
- if (d->type == KDBUS_ITEM_FDS)
- close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
- else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD)
- safe_close(d->memfd.fd);
- }
-
- bus_kernel_cmd_free(bus, (uint8_t*) k - (uint8_t*) bus->kdbus_buffer);
-}
-
-int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call) {
- struct kdbus_cmd_send cmd = { };
- int r;
-
- assert(bus);
- assert(m);
- assert(bus->state == BUS_RUNNING);
-
- /* If we can't deliver, we want room for the error message */
- r = bus_rqueue_make_room(bus);
- if (r < 0)
- return r;
-
- r = bus_message_setup_kmsg(bus, m);
- if (r < 0)
- return r;
-
- cmd.size = sizeof(cmd);
- cmd.msg_address = (uintptr_t)m->kdbus;
-
- /* If this is a synchronous method call, then let's tell the
- * kernel, so that it can pass CPU time/scheduling to the
- * destination for the time, if it wants to. If we
- * synchronously wait for the result anyway, we won't need CPU
- * anyway. */
- if (hint_sync_call) {
- m->kdbus->flags |= KDBUS_MSG_EXPECT_REPLY;
- cmd.flags |= KDBUS_SEND_SYNC_REPLY;
- }
-
- r = ioctl(bus->output_fd, KDBUS_CMD_SEND, &cmd);
- if (r < 0) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- sd_bus_message *reply;
-
- if (errno == EAGAIN || errno == EINTR)
- return 0;
- else if (errno == ENXIO || errno == ESRCH) {
-
- /* ENXIO: unique name not known
- * ESRCH: well-known name not known */
-
- if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
- sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Destination %s not known", m->destination);
- else {
- log_debug("Could not deliver message to %s as destination is not known. Ignoring.", m->destination);
- return 0;
- }
-
- } else if (errno == EADDRNOTAVAIL) {
-
- /* EADDRNOTAVAIL: activation is possible, but turned off in request flags */
-
- if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
- sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Activation of %s not requested", m->destination);
- else {
- log_debug("Could not deliver message to %s as destination is not activated. Ignoring.", m->destination);
- return 0;
- }
- } else
- return -errno;
-
- r = bus_message_new_synthetic_error(
- bus,
- BUS_MESSAGE_COOKIE(m),
- &error,
- &reply);
-
- if (r < 0)
- return r;
-
- r = bus_seal_synthetic_message(bus, reply);
- if (r < 0)
- return r;
-
- bus->rqueue[bus->rqueue_size++] = reply;
-
- } else if (hint_sync_call) {
- struct kdbus_msg *k;
-
- k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + cmd.reply.offset);
- assert(k);
-
- if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
-
- r = bus_kernel_make_message(bus, k);
- if (r < 0) {
- close_kdbus_msg(bus, k);
-
- /* Anybody can send us invalid messages, let's just drop them. */
- if (r == -EBADMSG || r == -EPROTOTYPE)
- log_debug_errno(r, "Ignoring invalid synchronous reply: %m");
- else
- return r;
- }
- } else {
- log_debug("Ignoring message with unknown payload type %llu.", k->payload_type);
- close_kdbus_msg(bus, k);
- }
- }
-
- return 1;
-}
-
-static int push_name_owner_changed(
- sd_bus *bus,
- const char *name,
- const char *old_owner,
- const char *new_owner,
- const struct kdbus_timestamp *ts) {
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- int r;
-
- assert(bus);
-
- r = sd_bus_message_new_signal(
- bus,
- &m,
- "/org/freedesktop/DBus",
- "org.freedesktop.DBus",
- "NameOwnerChanged");
- if (r < 0)
- return r;
-
- r = sd_bus_message_append(m, "sss", name, old_owner, new_owner);
- if (r < 0)
- return r;
-
- bus_message_set_sender_driver(bus, m);
- message_set_timestamp(bus, m, ts);
-
- r = bus_seal_synthetic_message(bus, m);
- if (r < 0)
- return r;
-
- bus->rqueue[bus->rqueue_size++] = m;
- m = NULL;
-
- return 1;
-}
-
-static int translate_name_change(
- sd_bus *bus,
- const struct kdbus_msg *k,
- const struct kdbus_item *d,
- const struct kdbus_timestamp *ts) {
-
- char new_owner[UNIQUE_NAME_MAX], old_owner[UNIQUE_NAME_MAX];
-
- assert(bus);
- assert(k);
- assert(d);
-
- if (d->type == KDBUS_ITEM_NAME_ADD || (d->name_change.old_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR)))
- old_owner[0] = 0;
- else
- sprintf(old_owner, ":1.%llu", d->name_change.old_id.id);
-
- if (d->type == KDBUS_ITEM_NAME_REMOVE || (d->name_change.new_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR))) {
-
- if (isempty(old_owner))
- return 0;
-
- new_owner[0] = 0;
- } else
- sprintf(new_owner, ":1.%llu", d->name_change.new_id.id);
-
- return push_name_owner_changed(bus, d->name_change.name, old_owner, new_owner, ts);
-}
-
-static int translate_id_change(
- sd_bus *bus,
- const struct kdbus_msg *k,
- const struct kdbus_item *d,
- const struct kdbus_timestamp *ts) {
-
- char owner[UNIQUE_NAME_MAX];
-
- assert(bus);
- assert(k);
- assert(d);
-
- sprintf(owner, ":1.%llu", d->id_change.id);
-
- return push_name_owner_changed(
- bus, owner,
- d->type == KDBUS_ITEM_ID_ADD ? NULL : owner,
- d->type == KDBUS_ITEM_ID_ADD ? owner : NULL,
- ts);
-}
-
-static int translate_reply(
- sd_bus *bus,
- const struct kdbus_msg *k,
- const struct kdbus_item *d,
- const struct kdbus_timestamp *ts) {
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- int r;
-
- assert(bus);
- assert(k);
- assert(d);
-
- r = bus_message_new_synthetic_error(
- bus,
- k->cookie_reply,
- d->type == KDBUS_ITEM_REPLY_TIMEOUT ?
- &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call timed out") :
- &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call peer died"),
- &m);
- if (r < 0)
- return r;
-
- message_set_timestamp(bus, m, ts);
-
- r = bus_seal_synthetic_message(bus, m);
- if (r < 0)
- return r;
-
- bus->rqueue[bus->rqueue_size++] = m;
- m = NULL;
-
- return 1;
-}
-
-static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) {
- static int (* const translate[])(sd_bus *bus, const struct kdbus_msg *k, const struct kdbus_item *d, const struct kdbus_timestamp *ts) = {
- [KDBUS_ITEM_NAME_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
- [KDBUS_ITEM_NAME_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
- [KDBUS_ITEM_NAME_CHANGE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
-
- [KDBUS_ITEM_ID_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
- [KDBUS_ITEM_ID_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
-
- [KDBUS_ITEM_REPLY_TIMEOUT - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
- [KDBUS_ITEM_REPLY_DEAD - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
- };
-
- struct kdbus_item *d, *found = NULL;
- struct kdbus_timestamp *ts = NULL;
-
- assert(bus);
- assert(k);
- assert(k->payload_type == KDBUS_PAYLOAD_KERNEL);
-
- KDBUS_ITEM_FOREACH(d, k, items) {
- if (d->type == KDBUS_ITEM_TIMESTAMP)
- ts = &d->timestamp;
- else if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) {
- if (found)
- return -EBADMSG;
- found = d;
- } else
- log_debug("Got unknown field from kernel %llu", d->type);
- }
-
- if (!found) {
- log_debug("Didn't find a kernel message to translate.");
- return 0;
- }
-
- return translate[found->type - _KDBUS_ITEM_KERNEL_BASE](bus, k, found, ts);
-}
-
-int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority) {
- struct kdbus_cmd_recv recv = { .size = sizeof(recv) };
- struct kdbus_msg *k;
- int r;
-
- assert(bus);
-
- r = bus_rqueue_make_room(bus);
- if (r < 0)
- return r;
-
- if (hint_priority) {
- recv.flags |= KDBUS_RECV_USE_PRIORITY;
- recv.priority = priority;
- }
-
- r = ioctl(bus->input_fd, KDBUS_CMD_RECV, &recv);
- if (recv.return_flags & KDBUS_RECV_RETURN_DROPPED_MSGS)
- log_debug("%s: kdbus reports %" PRIu64 " dropped broadcast messages, ignoring.", strna(bus->description), (uint64_t) recv.dropped_msgs);
- if (r < 0) {
- if (errno == EAGAIN)
- return 0;
-
- return -errno;
- }
-
- k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + recv.msg.offset);
- if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
- r = bus_kernel_make_message(bus, k);
-
- /* Anybody can send us invalid messages, let's just drop them. */
- if (r == -EBADMSG || r == -EPROTOTYPE) {
- log_debug_errno(r, "Ignoring invalid message: %m");
- r = 0;
- }
-
- if (r <= 0)
- close_kdbus_msg(bus, k);
- } else if (k->payload_type == KDBUS_PAYLOAD_KERNEL) {
- r = bus_kernel_translate_message(bus, k);
- close_kdbus_msg(bus, k);
- } else {
- log_debug("Ignoring message with unknown payload type %llu.", k->payload_type);
- r = 0;
- close_kdbus_msg(bus, k);
- }
-
- return r < 0 ? r : 1;
-}
-
-int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *allocated) {
- struct memfd_cache *c;
- int fd;
-
- assert(address);
- assert(mapped);
- assert(allocated);
-
- if (!bus || !bus->is_kernel)
- return -EOPNOTSUPP;
-
- assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) == 0);
-
- if (bus->n_memfd_cache <= 0) {
- int r;
-
- assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
-
- r = memfd_new(bus->description);
- if (r < 0)
- return r;
-
- *address = NULL;
- *mapped = 0;
- *allocated = 0;
- return r;
- }
-
- c = &bus->memfd_cache[--bus->n_memfd_cache];
-
- assert(c->fd >= 0);
- assert(c->mapped == 0 || c->address);
-
- *address = c->address;
- *mapped = c->mapped;
- *allocated = c->allocated;
- fd = c->fd;
-
- assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
-
- return fd;
-}
-
-static void close_and_munmap(int fd, void *address, size_t size) {
+void close_and_munmap(int fd, void *address, size_t size) {
if (size > 0)
assert_se(munmap(address, PAGE_ALIGN(size)) >= 0);
safe_close(fd);
}
-void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, size_t allocated) {
- struct memfd_cache *c;
- uint64_t max_mapped = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX);
-
- assert(fd >= 0);
- assert(mapped == 0 || address);
-
- if (!bus || !bus->is_kernel) {
- close_and_munmap(fd, address, mapped);
- return;
- }
-
- assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) == 0);
-
- if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
- assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
-
- close_and_munmap(fd, address, mapped);
- return;
- }
-
- c = &bus->memfd_cache[bus->n_memfd_cache++];
- c->fd = fd;
- c->address = address;
-
- /* If overly long, let's return a bit to the OS */
- if (mapped > max_mapped) {
- assert_se(memfd_set_size(fd, max_mapped) >= 0);
- assert_se(munmap((uint8_t*) address + max_mapped, PAGE_ALIGN(mapped - max_mapped)) >= 0);
- c->mapped = c->allocated = max_mapped;
- } else {
- c->mapped = mapped;
- c->allocated = allocated;
- }
-
- assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
-}
-
-void bus_kernel_flush_memfd(sd_bus *b) {
+void bus_flush_memfd(sd_bus *b) {
unsigned i;
assert(b);
@@ -1523,262 +50,5 @@ void bus_kernel_flush_memfd(sd_bus *b) {
for (i = 0; i < b->n_memfd_cache; i++)
close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].mapped);
}
-
-uint64_t request_name_flags_to_kdbus(uint64_t flags) {
- uint64_t f = 0;
-
- if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
- f |= KDBUS_NAME_ALLOW_REPLACEMENT;
-
- if (flags & SD_BUS_NAME_REPLACE_EXISTING)
- f |= KDBUS_NAME_REPLACE_EXISTING;
-
- if (flags & SD_BUS_NAME_QUEUE)
- f |= KDBUS_NAME_QUEUE;
-
- return f;
-}
-
-uint64_t attach_flags_to_kdbus(uint64_t mask) {
- uint64_t m = 0;
-
- if (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
- SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID))
- m |= KDBUS_ATTACH_CREDS;
-
- if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_TID|SD_BUS_CREDS_PPID))
- m |= KDBUS_ATTACH_PIDS;
-
- if (mask & SD_BUS_CREDS_COMM)
- m |= KDBUS_ATTACH_PID_COMM;
-
- if (mask & SD_BUS_CREDS_TID_COMM)
- m |= KDBUS_ATTACH_TID_COMM;
-
- if (mask & SD_BUS_CREDS_EXE)
- m |= KDBUS_ATTACH_EXE;
-
- if (mask & SD_BUS_CREDS_CMDLINE)
- m |= KDBUS_ATTACH_CMDLINE;
-
- if (mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID))
- m |= KDBUS_ATTACH_CGROUP;
-
- if (mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS))
- m |= KDBUS_ATTACH_CAPS;
-
- if (mask & SD_BUS_CREDS_SELINUX_CONTEXT)
- m |= KDBUS_ATTACH_SECLABEL;
-
- if (mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID))
- m |= KDBUS_ATTACH_AUDIT;
-
- if (mask & SD_BUS_CREDS_WELL_KNOWN_NAMES)
- m |= KDBUS_ATTACH_NAMES;
-
- if (mask & SD_BUS_CREDS_DESCRIPTION)
- m |= KDBUS_ATTACH_CONN_DESCRIPTION;
-
- if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS)
- m |= KDBUS_ATTACH_AUXGROUPS;
-
- return m;
-}
-
-int bus_kernel_create_bus(const char *name, bool world, char **s) {
- struct kdbus_cmd *make;
- struct kdbus_item *n;
- size_t l;
- int fd;
-
- assert(name);
- assert(s);
-
- fd = open("/sys/fs/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return -errno;
-
- l = strlen(name);
- make = alloca0_align(offsetof(struct kdbus_cmd, items) +
- ALIGN8(offsetof(struct kdbus_item, bloom_parameter) + sizeof(struct kdbus_bloom_parameter)) +
- ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)) +
- ALIGN8(offsetof(struct kdbus_item, str) + DECIMAL_STR_MAX(uid_t) + 1 + l + 1),
- 8);
-
- make->size = offsetof(struct kdbus_cmd, items);
-
- /* Set the bloom parameters */
- n = make->items;
- n->size = offsetof(struct kdbus_item, bloom_parameter) +
- sizeof(struct kdbus_bloom_parameter);
- n->type = KDBUS_ITEM_BLOOM_PARAMETER;
- n->bloom_parameter.size = DEFAULT_BLOOM_SIZE;
- n->bloom_parameter.n_hash = DEFAULT_BLOOM_N_HASH;
-
- assert_cc(DEFAULT_BLOOM_SIZE > 0);
- assert_cc(DEFAULT_BLOOM_N_HASH > 0);
-
- make->size += ALIGN8(n->size);
-
- /* Provide all metadata via bus-owner queries */
- n = KDBUS_ITEM_NEXT(n);
- n->type = KDBUS_ITEM_ATTACH_FLAGS_SEND;
- n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t);
- n->data64[0] = _KDBUS_ATTACH_ANY;
- make->size += ALIGN8(n->size);
-
- /* Set the a good name */
- n = KDBUS_ITEM_NEXT(n);
- sprintf(n->str, UID_FMT "-%s", getuid(), name);
- n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
- n->type = KDBUS_ITEM_MAKE_NAME;
- make->size += ALIGN8(n->size);
-
- make->flags = world ? KDBUS_MAKE_ACCESS_WORLD : 0;
-
- if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
- safe_close(fd);
-
- /* Major API change? then the ioctls got shuffled around. */
- if (errno == ENOTTY)
- return -ESOCKTNOSUPPORT;
-
- return -errno;
- }
-
- if (s) {
- char *p;
-
- p = strjoin("/sys/fs/kdbus/", n->str, "/bus");
- if (!p) {
- safe_close(fd);
- return -ENOMEM;
- }
-
- *s = p;
- }
-
- return fd;
-}
-
-int bus_kernel_open_bus_fd(const char *bus, char **path) {
- char *p;
- int fd;
- size_t len;
-
- assert(bus);
-
- len = strlen("/sys/fs/kdbus/") + DECIMAL_STR_MAX(uid_t) + 1 + strlen(bus) + strlen("/bus") + 1;
-
- if (path) {
- p = new(char, len);
- if (!p)
- return -ENOMEM;
- } else
- p = newa(char, len);
-
- sprintf(p, "/sys/fs/kdbus/" UID_FMT "-%s/bus", getuid(), bus);
-
- fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0) {
- if (path)
- free(p);
-
- return -errno;
- }
-
- if (path)
- *path = p;
-
- return fd;
-}
-
-int bus_kernel_try_close(sd_bus *bus) {
- struct kdbus_cmd byebye = { .size = sizeof(byebye) };
-
- assert(bus);
- assert(bus->is_kernel);
-
- if (ioctl(bus->input_fd, KDBUS_CMD_BYEBYE, &byebye) < 0)
- return -errno;
-
- return 0;
-}
-
#if 0 /// UNNEEDED by elogind
-int bus_kernel_drop_one(int fd) {
- struct kdbus_cmd_recv recv = {
- .size = sizeof(recv),
- .flags = KDBUS_RECV_DROP,
- };
-
- assert(fd >= 0);
-
- if (ioctl(fd, KDBUS_CMD_RECV, &recv) < 0)
- return -errno;
-
- return 0;
-}
#endif // 0
-
-int bus_kernel_realize_attach_flags(sd_bus *bus) {
- struct kdbus_cmd *update;
- struct kdbus_item *n;
-
- assert(bus);
- assert(bus->is_kernel);
-
- update = alloca0_align(offsetof(struct kdbus_cmd, items) +
- ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)),
- 8);
-
- n = update->items;
- n->type = KDBUS_ITEM_ATTACH_FLAGS_RECV;
- n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t);
- n->data64[0] = bus->attach_flags;
-
- update->size =
- offsetof(struct kdbus_cmd, items) +
- ALIGN8(n->size);
-
- if (ioctl(bus->input_fd, KDBUS_CMD_UPDATE, update) < 0)
- return -errno;
-
- return 0;
-}
-
-int bus_kernel_get_bus_name(sd_bus *bus, char **name) {
- struct kdbus_cmd_info cmd = {
- .size = sizeof(struct kdbus_cmd_info),
- };
- struct kdbus_info *info;
- struct kdbus_item *item;
- char *n = NULL;
- int r;
-
- assert(bus);
- assert(name);
- assert(bus->is_kernel);
-
- r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
- if (r < 0)
- return -errno;
-
- info = (struct kdbus_info*) ((uint8_t*) bus->kdbus_buffer + cmd.offset);
-
- KDBUS_ITEM_FOREACH(item, info, items)
- if (item->type == KDBUS_ITEM_MAKE_NAME) {
- r = free_and_strdup(&n, item->str);
- break;
- }
-
- bus_kernel_cmd_free(bus, cmd.offset);
-
- if (r < 0)
- return r;
- if (!n)
- return -EIO;
-
- *name = n;
- return 0;
-}
diff --git a/src/libelogind/sd-bus/bus-kernel.h b/src/libelogind/sd-bus/bus-kernel.h
index eac75253c..9fcbeb0e3 100644
--- a/src/libelogind/sd-bus/bus-kernel.h
+++ b/src/libelogind/sd-bus/bus-kernel.h
@@ -1,45 +1,11 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 "sd-bus.h"
-#define KDBUS_ITEM_NEXT(item) \
- (typeof(item))(((uint8_t *)item) + ALIGN8((item)->size))
-
-#define KDBUS_ITEM_FOREACH(part, head, first) \
- for (part = (head)->first; \
- ((uint8_t *)(part) < (uint8_t *)(head) + (head)->size) && \
- ((uint8_t *) part >= (uint8_t *) head); \
- part = KDBUS_ITEM_NEXT(part))
-#define KDBUS_FOREACH(iter, first, _size) \
- for (iter = (first); \
- ((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \
- ((uint8_t *)(iter) >= (uint8_t *)(first)); \
- iter = (void*)(((uint8_t *)iter) + ALIGN8((iter)->size)))
-
-#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data)
-#define KDBUS_ITEM_SIZE(s) ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE)
-
#define MEMFD_CACHE_MAX 32
/* When we cache a memfd block for reuse, we will truncate blocks
@@ -50,10 +16,6 @@
* sending vectors */
#define MEMFD_MIN_SIZE (512*1024)
-/* The size of the per-connection memory pool that we set up and where
- * the kernel places our incoming messages */
-#define KDBUS_POOL_SIZE (16*1024*1024)
-
struct memfd_cache {
int fd;
void *address;
@@ -61,37 +23,9 @@ struct memfd_cache {
size_t allocated;
};
-int bus_kernel_connect(sd_bus *b);
-int bus_kernel_take_fd(sd_bus *b);
-
-int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call);
-int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority);
-
-int bus_kernel_open_bus_fd(const char *bus, char **path);
-
-int bus_kernel_create_bus(const char *name, bool world, char **s);
#if 0 /// UNNEEDED by elogind
-int bus_kernel_create_endpoint(const char *bus_name, const char *ep_name, char **path);
#endif // 0
-
-int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *allocated);
-void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, size_t allocated);
-
-void bus_kernel_flush_memfd(sd_bus *bus);
-
-int bus_kernel_parse_unique_name(const char *s, uint64_t *id);
-
-uint64_t request_name_flags_to_kdbus(uint64_t sd_bus_flags);
-uint64_t attach_flags_to_kdbus(uint64_t sd_bus_flags);
-
-int bus_kernel_try_close(sd_bus *bus);
-
+void close_and_munmap(int fd, void *address, size_t size);
+void bus_flush_memfd(sd_bus *bus);
#if 0 /// UNNEEDED by elogind
-int bus_kernel_drop_one(int fd);
#endif // 0
-
-int bus_kernel_realize_attach_flags(sd_bus *bus);
-
-int bus_kernel_get_bus_name(sd_bus *bus, char **name);
-
-int bus_kernel_cmd_free(sd_bus *bus, uint64_t offset);
diff --git a/src/libelogind/sd-bus/bus-match.c b/src/libelogind/sd-bus/bus-match.c
index 3e6930a0d..2ef6e191c 100644
--- a/src/libelogind/sd-bus/bus-match.c
+++ b/src/libelogind/sd-bus/bus-match.c
@@ -1,22 +1,9 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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_ext.h>
+
#include "alloc-util.h"
#include "bus-internal.h"
#include "bus-match.h"
@@ -453,7 +440,7 @@ static int bus_match_add_compare_value(
int r;
assert(where);
- assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
+ assert(IN_SET(where->type, BUS_MATCH_ROOT, BUS_MATCH_VALUE));
assert(BUS_MATCH_IS_COMPARE(t));
assert(ret);
@@ -567,7 +554,7 @@ static int bus_match_find_compare_value(
struct bus_match_node *c, *n;
assert(where);
- assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
+ assert(IN_SET(where->type, BUS_MATCH_ROOT, BUS_MATCH_VALUE));
assert(BUS_MATCH_IS_COMPARE(t));
assert(ret);
@@ -601,7 +588,7 @@ static int bus_match_add_leaf(
struct bus_match_node *n;
assert(where);
- assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
+ assert(IN_SET(where->type, BUS_MATCH_ROOT, BUS_MATCH_VALUE));
assert(callback);
n = new0(struct bus_match_node, 1);
@@ -631,7 +618,7 @@ static int bus_match_find_leaf(
struct bus_match_node *c;
assert(where);
- assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
+ assert(IN_SET(where->type, BUS_MATCH_ROOT, BUS_MATCH_VALUE));
assert(ret);
for (c = where->child; c; c = c->next) {
@@ -900,12 +887,10 @@ int bus_match_parse(
}
components[n_components].type = t;
- components[n_components].value_str = value;
+ components[n_components].value_str = TAKE_PTR(value);
components[n_components].value_u8 = u;
n_components++;
- value = NULL;
-
if (q[quoted] == 0)
break;
@@ -954,6 +939,8 @@ char *bus_match_to_string(struct bus_match_component *components, unsigned n_com
if (!f)
return NULL;
+ __fsetlocking(f, FSETLOCKING_BYCALLER);
+
for (i = 0; i < n_components; i++) {
char buf[32];
diff --git a/src/libelogind/sd-bus/bus-match.h b/src/libelogind/sd-bus/bus-match.h
index 9985db133..0891d62e1 100644
--- a/src/libelogind/sd-bus/bus-match.h
+++ b/src/libelogind/sd-bus/bus-match.h
@@ -1,22 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-bus.h"
diff --git a/src/libelogind/sd-bus/bus-message.c b/src/libelogind/sd-bus/bus-message.c
index a9853e326..4fb06c2a1 100644
--- a/src/libelogind/sd-bus/bus-message.c
+++ b/src/libelogind/sd-bus/bus-message.c
@@ -1,20 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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>
@@ -62,22 +47,9 @@ static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
assert(m);
assert(part);
- if (part->memfd >= 0) {
- /* If we can reuse the memfd, try that. For that it
- * can't be sealed yet. */
-
- if (!part->sealed) {
- assert(part->memfd_offset == 0);
- assert(part->data == part->mmap_begin);
- bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated);
- } else {
- if (part->mapped > 0)
- assert_se(munmap(part->mmap_begin, part->mapped) == 0);
-
- safe_close(part->memfd);
- }
-
- } else if (part->munmap_this)
+ if (part->memfd >= 0)
+ close_and_munmap(part->memfd, part->mmap_begin, part->mapped);
+ else if (part->munmap_this)
munmap(part->mmap_begin, part->mapped);
else if (part->free_this)
free(part->data);
@@ -121,7 +93,7 @@ static void message_reset_containers(sd_bus_message *m) {
m->root_container.index = 0;
}
-static void message_free(sd_bus_message *m) {
+static sd_bus_message* message_free(sd_bus_message *m) {
assert(m);
if (m->free_header)
@@ -129,12 +101,6 @@ static void message_free(sd_bus_message *m) {
message_reset_parts(m);
- if (m->release_kdbus)
- bus_kernel_cmd_free(m->bus, (uint8_t *) m->kdbus - (uint8_t *) m->bus->kdbus_buffer);
-
- if (m->free_kdbus)
- free(m->kdbus);
-
sd_bus_unref(m->bus);
if (m->free_fds) {
@@ -145,7 +111,6 @@ static void message_free(sd_bus_message *m) {
if (m->iovec != m->iovec_fixed)
free(m->iovec);
- m->destination_ptr = mfree(m->destination_ptr);
message_reset_containers(m);
free(m->root_container.signature);
free(m->root_container.offsets);
@@ -153,9 +118,11 @@ static void message_free(sd_bus_message *m) {
free(m->root_container.peeked_signature);
bus_creds_done(&m->creds);
- free(m);
+ return mfree(m);
}
+DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, message_free);
+
static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
void *op, *np;
size_t old_size, new_size, start;
@@ -431,7 +398,7 @@ int bus_message_from_header(
size_t footer_accessible,
size_t message_size,
int *fds,
- unsigned n_fds,
+ size_t n_fds,
const char *label,
size_t extra,
sd_bus_message **ret) {
@@ -532,8 +499,7 @@ int bus_message_from_header(
}
m->bus = sd_bus_ref(bus);
- *ret = m;
- m = NULL;
+ *ret = TAKE_PTR(m);
return 0;
}
@@ -543,11 +509,11 @@ int bus_message_from_malloc(
void *buffer,
size_t length,
int *fds,
- unsigned n_fds,
+ size_t n_fds,
const char *label,
sd_bus_message **ret) {
- sd_bus_message *m;
+ _cleanup_(message_freep) sd_bus_message *m = NULL;
size_t sz;
int r;
@@ -578,42 +544,46 @@ int bus_message_from_malloc(
r = bus_message_parse_fields(m);
if (r < 0)
- goto fail;
+ return r;
/* We take possession of the memory and fds now */
m->free_header = true;
m->free_fds = true;
- *ret = m;
+ *ret = TAKE_PTR(m);
return 0;
-
-fail:
- message_free(m);
- return r;
}
-static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
- sd_bus_message *m;
+_public_ int sd_bus_message_new(
+ sd_bus *bus,
+ sd_bus_message **m,
+ uint8_t type) {
+
+ sd_bus_message *t;
- assert(bus);
+ assert_return(bus, -ENOTCONN);
+ assert_return(bus->state != BUS_UNSET, -ENOTCONN);
+ assert_return(m, -EINVAL);
+ assert_return(type < _SD_BUS_MESSAGE_TYPE_MAX, -EINVAL);
- m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
- if (!m)
- return NULL;
+ t = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
+ if (!t)
+ return -ENOMEM;
- m->n_ref = 1;
- m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
- m->header->endian = BUS_NATIVE_ENDIAN;
- m->header->type = type;
- m->header->version = bus->message_version;
- m->allow_fds = bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
- m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
- m->bus = sd_bus_ref(bus);
+ t->n_ref = 1;
+ t->header = (struct bus_header*) ((uint8_t*) t + ALIGN(sizeof(struct sd_bus_message)));
+ t->header->endian = BUS_NATIVE_ENDIAN;
+ t->header->type = type;
+ t->header->version = bus->message_version;
+ t->allow_fds = bus->can_fds || !IN_SET(bus->state, BUS_HELLO, BUS_RUNNING);
+ t->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(t);
+ t->bus = sd_bus_ref(bus);
if (bus->allow_interactive_authorization)
- m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
+ t->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
- return m;
+ *m = t;
+ return 0;
}
_public_ int sd_bus_message_new_signal(
@@ -623,7 +593,7 @@ _public_ int sd_bus_message_new_signal(
const char *interface,
const char *member) {
- sd_bus_message *t;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
int r;
assert_return(bus, -ENOTCONN);
@@ -633,28 +603,26 @@ _public_ int sd_bus_message_new_signal(
assert_return(member_name_is_valid(member), -EINVAL);
assert_return(m, -EINVAL);
- t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
- if (!t)
+ r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_SIGNAL);
+ if (r < 0)
return -ENOMEM;
+ assert(t);
+
t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
if (r < 0)
- goto fail;
+ return r;
r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
if (r < 0)
- goto fail;
+ return r;
r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
if (r < 0)
- goto fail;
+ return r;
- *m = t;
+ *m = TAKE_PTR(t);
return 0;
-
-fail:
- sd_bus_message_unref(t);
- return r;
}
_public_ int sd_bus_message_new_method_call(
@@ -665,7 +633,7 @@ _public_ int sd_bus_message_new_method_call(
const char *interface,
const char *member) {
- sd_bus_message *t;
+ _cleanup_(message_freep) sd_bus_message *t = NULL;
int r;
assert_return(bus, -ENOTCONN);
@@ -676,35 +644,33 @@ _public_ int sd_bus_message_new_method_call(
assert_return(member_name_is_valid(member), -EINVAL);
assert_return(m, -EINVAL);
- t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
- if (!t)
+ r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_CALL);
+ if (r < 0)
return -ENOMEM;
+ assert(t);
+
r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
if (r < 0)
- goto fail;
+ return r;
r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
if (r < 0)
- goto fail;
+ return r;
if (interface) {
r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
if (r < 0)
- goto fail;
+ return r;
}
if (destination) {
r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
if (r < 0)
- goto fail;
+ return r;
}
- *m = t;
+ *m = TAKE_PTR(t);
return 0;
-
-fail:
- message_free(t);
- return r;
}
static int message_new_reply(
@@ -712,7 +678,8 @@ static int message_new_reply(
uint8_t type,
sd_bus_message **m) {
- sd_bus_message *t;
+ _cleanup_(message_freep) sd_bus_message *t = NULL;
+ uint64_t cookie;
int r;
assert_return(call, -EINVAL);
@@ -721,34 +688,33 @@ static int message_new_reply(
assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
assert_return(m, -EINVAL);
- t = message_new(call->bus, type);
- if (!t)
+ cookie = BUS_MESSAGE_COOKIE(call);
+ if (cookie == 0)
+ return -EOPNOTSUPP;
+
+ r = sd_bus_message_new(call->bus, &t, type);
+ if (r < 0)
return -ENOMEM;
- t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
- t->reply_cookie = BUS_MESSAGE_COOKIE(call);
- if (t->reply_cookie == 0)
- return -EOPNOTSUPP;
+ assert(t);
+ t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
+ t->reply_cookie = cookie;
r = message_append_reply_cookie(t, t->reply_cookie);
if (r < 0)
- goto fail;
+ return r;
if (call->sender) {
r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
if (r < 0)
- goto fail;
+ return r;
}
t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
t->enforced_reply_signature = call->enforced_reply_signature;
- *m = t;
+ *m = TAKE_PTR(t);
return 0;
-
-fail:
- message_free(t);
- return r;
}
_public_ int sd_bus_message_new_method_return(
@@ -763,7 +729,7 @@ _public_ int sd_bus_message_new_method_error(
sd_bus_message **m,
const sd_bus_error *e) {
- sd_bus_message *t;
+ _cleanup_(message_freep) sd_bus_message *t = NULL;
int r;
assert_return(sd_bus_error_is_set(e), -EINVAL);
@@ -775,22 +741,18 @@ _public_ int sd_bus_message_new_method_error(
r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
if (r < 0)
- goto fail;
+ return r;
if (e->message) {
r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
if (r < 0)
- goto fail;
+ return r;
}
t->error._need_free = -1;
- *m = t;
+ *m = TAKE_PTR(t);
return 0;
-
-fail:
- message_free(t);
- return r;
}
_public_ int sd_bus_message_new_method_errorf(
@@ -870,50 +832,48 @@ int bus_message_new_synthetic_error(
const sd_bus_error *e,
sd_bus_message **m) {
- sd_bus_message *t;
+ _cleanup_(message_freep) sd_bus_message *t = NULL;
int r;
assert(bus);
assert(sd_bus_error_is_set(e));
assert(m);
- t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
- if (!t)
+ r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_ERROR);
+ if (r < 0)
return -ENOMEM;
+ assert(t);
+
t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
t->reply_cookie = cookie;
r = message_append_reply_cookie(t, t->reply_cookie);
if (r < 0)
- goto fail;
+ return r;
if (bus && bus->unique_name) {
r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
if (r < 0)
- goto fail;
+ return r;
}
r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
if (r < 0)
- goto fail;
+ return r;
if (e->message) {
r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
if (r < 0)
- goto fail;
+ return r;
}
t->error._need_free = -1;
bus_message_set_sender_driver(bus, t);
- *m = t;
+ *m = TAKE_PTR(t);
return 0;
-
-fail:
- message_free(t);
- return r;
}
_public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
@@ -938,8 +898,7 @@ _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
if (m->n_ref > 0)
return NULL;
- message_free(m);
- return NULL;
+ return message_free(m);
}
_public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
@@ -1086,10 +1045,10 @@ _public_ int sd_bus_message_is_signal(
if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
return 0;
- if (interface && (!m->interface || !streq(m->interface, interface)))
+ if (interface && !streq_ptr(m->interface, interface))
return 0;
- if (member && (!m->member || !streq(m->member, member)))
+ if (member && !streq_ptr(m->member, member))
return 0;
return 1;
@@ -1105,10 +1064,10 @@ _public_ int sd_bus_message_is_method_call(
if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
return 0;
- if (interface && (!m->interface || !streq(m->interface, interface)))
+ if (interface && !streq_ptr(m->interface, interface))
return 0;
- if (member && (!m->member || !streq(m->member, member)))
+ if (member && !streq_ptr(m->member, member))
return 0;
return 1;
@@ -1120,7 +1079,7 @@ _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name)
if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
return 0;
- if (name && (!m->error.name || !streq(m->error.name, name)))
+ if (name && !streq_ptr(m->error.name, name))
return 0;
return 1;
@@ -1215,7 +1174,6 @@ static int part_make_space(
void **q) {
void *n;
- int r;
assert(m);
assert(part);
@@ -1224,61 +1182,19 @@ static int part_make_space(
if (m->poisoned)
return -ENOMEM;
- if (!part->data && part->memfd < 0) {
- part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
- part->mmap_begin = part->data;
- }
-
- if (part->memfd >= 0) {
-
- if (part->allocated == 0 || sz > part->allocated) {
- uint64_t new_allocated;
-
- new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
- r = memfd_set_size(part->memfd, new_allocated);
- if (r < 0) {
- m->poisoned = true;
- return r;
- }
-
- part->allocated = new_allocated;
- }
-
- if (!part->data || sz > part->mapped) {
- size_t psz;
-
- psz = PAGE_ALIGN(sz > 0 ? sz : 1);
- if (part->mapped <= 0)
- n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
- else
- n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
-
- if (n == MAP_FAILED) {
- m->poisoned = true;
- return -errno;
- }
+ if (part->allocated == 0 || sz > part->allocated) {
+ size_t new_allocated;
- part->mmap_begin = part->data = n;
- part->mapped = psz;
- part->memfd_offset = 0;
+ new_allocated = sz > 0 ? 2 * sz : 64;
+ n = realloc(part->data, new_allocated);
+ if (!n) {
+ m->poisoned = true;
+ return -ENOMEM;
}
- part->munmap_this = true;
- } else {
- if (part->allocated == 0 || sz > part->allocated) {
- size_t new_allocated;
-
- new_allocated = sz > 0 ? 2 * sz : 64;
- n = realloc(part->data, new_allocated);
- if (!n) {
- m->poisoned = true;
- return -ENOMEM;
- }
-
- part->data = n;
- part->allocated = new_allocated;
- part->free_this = true;
- }
+ part->data = n;
+ part->allocated = new_allocated;
+ part->free_this = true;
}
if (q)
@@ -1364,7 +1280,9 @@ static void *message_extend_body(
m->n_body_parts <= 0 ||
m->body_end->sealed ||
(padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
- (force_inline && m->body_end->size > MEMFD_MIN_SIZE); /* if this must be an inlined extension, let's create a new part if the previous part is large enough to be inlined */
+ (force_inline && m->body_end->size > MEMFD_MIN_SIZE);
+ /* If this must be an inlined extension, let's create a new part if
+ * the previous part is large enough to be inlined. */
if (add_new_part) {
if (padding > 0) {
@@ -1411,7 +1329,7 @@ static void *message_extend_body(
}
} else
/* Return something that is not NULL and is aligned */
- p = (uint8_t *) NULL + align;
+ p = (uint8_t*) align;
m->body_size = end_body;
message_extend_containers(m, added);
@@ -1442,7 +1360,7 @@ static int message_push_fd(sd_bus_message *m, int fd) {
if (copy < 0)
return -errno;
- f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
+ f = reallocarray(m->fds, sizeof(int), m->n_fds + 1);
if (!f) {
m->poisoned = true;
safe_close(copy);
@@ -1498,7 +1416,7 @@ int message_append_basic(sd_bus_message *m, char type, const void *p, const void
case SD_BUS_TYPE_STRING:
p = strempty(p);
- /* Fall through... */
+ _fallthrough_;
case SD_BUS_TYPE_OBJECT_PATH:
if (!p)
return -EINVAL;
@@ -1558,7 +1476,7 @@ int message_append_basic(sd_bus_message *m, char type, const void *p, const void
* into the empty string */
p = strempty(p);
- /* Fall through... */
+ _fallthrough_;
case SD_BUS_TYPE_OBJECT_PATH:
if (!p)
@@ -1612,7 +1530,7 @@ int message_append_basic(sd_bus_message *m, char type, const void *p, const void
if (!a)
return -ENOMEM;
- if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
+ if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
*(uint32_t*) a = sz - 5;
memcpy((uint8_t*) a + 4, p, sz - 4);
@@ -1707,7 +1625,7 @@ _public_ int sd_bus_message_append_string_space(
_public_ int sd_bus_message_append_string_iovec(
sd_bus_message *m,
const struct iovec *iov,
- unsigned n) {
+ unsigned n /* should be size_t, but is API now… 😞 */) {
size_t size;
unsigned i;
@@ -2033,7 +1951,7 @@ _public_ int sd_bus_message_open_container(
struct bus_container *c, *w;
uint32_t *array_size = NULL;
- char *signature;
+ _cleanup_free_ char *signature = NULL;
size_t before, begin = 0;
bool need_offsets = false;
int r;
@@ -2072,16 +1990,13 @@ _public_ int sd_bus_message_open_container(
r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
else
r = -EINVAL;
-
- if (r < 0) {
- free(signature);
+ if (r < 0)
return r;
- }
/* OK, let's fill it in */
w = m->containers + m->n_containers++;
w->enclosing = type;
- w->signature = signature;
+ w->signature = TAKE_PTR(signature);
w->index = 0;
w->array_size = array_size;
w->before = before;
@@ -2291,7 +2206,7 @@ _public_ int sd_bus_message_close_container(sd_bus_message *m) {
r = bus_message_close_array(m, c);
else if (c->enclosing == SD_BUS_TYPE_VARIANT)
r = bus_message_close_variant(m, c);
- else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
+ else if (IN_SET(c->enclosing, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY))
r = bus_message_close_struct(m, c, true);
else
assert_not_reached("Unknown container type");
@@ -2631,7 +2546,7 @@ _public_ int sd_bus_message_append_array_iovec(
sd_bus_message *m,
char type,
const struct iovec *iov,
- unsigned n) {
+ unsigned n /* should be size_t, but is API now… 😞 */) {
size_t size;
unsigned i;
@@ -2688,7 +2603,7 @@ _public_ int sd_bus_message_append_array_memfd(
if (r < 0)
return r;
- copy_fd = dup(memfd);
+ copy_fd = fcntl(memfd, F_DUPFD_CLOEXEC, 3);
if (copy_fd < 0)
return copy_fd;
@@ -2763,7 +2678,7 @@ _public_ int sd_bus_message_append_string_memfd(
if (r < 0)
return r;
- copy_fd = dup(memfd);
+ copy_fd = fcntl(memfd, FD_CLOEXEC, 3);
if (copy_fd < 0)
return copy_fd;
@@ -2919,13 +2834,13 @@ static int bus_message_close_header(sd_bus_message *m) {
return 0;
}
-int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
+_public_ int sd_bus_message_seal(sd_bus_message *m, uint64_t cookie, uint64_t timeout_usec) {
struct bus_body_part *part;
size_t a;
unsigned i;
int r;
- assert(m);
+ assert_return(m, -EINVAL);
if (m->sealed)
return -EPERM;
@@ -2975,7 +2890,7 @@ int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
else
m->header->dbus1.serial = (uint32_t) cookie;
- m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
+ m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout_usec;
/* Add padding at the end of the fields part, since we know
* the body needs to start at an 8 byte alignment. We made
@@ -3233,9 +3148,7 @@ static int container_next_item(sd_bus_message *m, struct bus_container *c, size_
c->offset_index++;
- } else if (c->enclosing == 0 ||
- c->enclosing == SD_BUS_TYPE_STRUCT ||
- c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
+ } else if (IN_SET(c->enclosing, 0, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
int alignment;
size_t n, j;
@@ -3279,7 +3192,6 @@ end:
return 0;
}
-
static int message_peek_body(
sd_bus_message *m,
size_t *rindex,
@@ -4056,9 +3968,9 @@ _public_ int sd_bus_message_enter_container(sd_bus_message *m,
const char *contents) {
struct bus_container *c, *w;
uint32_t *array_size = NULL;
- char *signature;
+ _cleanup_free_ char *signature = NULL;
size_t before;
- size_t *offsets = NULL;
+ _cleanup_free_ size_t *offsets = NULL;
size_t n_offsets = 0, item_size = 0;
int r;
@@ -4132,17 +4044,13 @@ _public_ int sd_bus_message_enter_container(sd_bus_message *m,
r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
else
r = -EINVAL;
-
- if (r <= 0) {
- free(signature);
- free(offsets);
+ if (r <= 0)
return r;
- }
/* OK, let's fill it in */
w = m->containers + m->n_containers++;
w->enclosing = type;
- w->signature = signature;
+ w->signature = TAKE_PTR(signature);
w->peeked_signature = NULL;
w->index = 0;
@@ -4159,7 +4067,7 @@ _public_ int sd_bus_message_enter_container(sd_bus_message *m,
w->array_size = array_size;
w->item_size = item_size;
- w->offsets = offsets;
+ w->offsets = TAKE_PTR(offsets);
w->n_offsets = n_offsets;
w->offset_index = 0;
@@ -4283,8 +4191,7 @@ _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char
return 1;
}
- if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
- c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
+ if (IN_SET(c->signature[c->index], SD_BUS_TYPE_STRUCT_BEGIN, SD_BUS_TYPE_DICT_ENTRY_BEGIN)) {
if (contents) {
size_t l;
@@ -4429,7 +4336,7 @@ static int message_read_ap(
/* Ideally, we'd just call ourselves recursively on every
* complex type. However, the state of a va_list that is
* passed to a function is undefined after that function
- * returns. This means we need to docode the va_list linearly
+ * returns. This means we need to decode the va_list linearly
* in a single stackframe. We hence implement our own
* home-grown stack in an array. */
@@ -4825,7 +4732,7 @@ _public_ int sd_bus_message_read_array(
if (sz == 0)
/* Zero length array, let's return some aligned
* pointer that is not NULL */
- p = (uint8_t*) NULL + align;
+ p = (uint8_t*) align;
else {
r = message_peek_body(m, &m->rindex, align, sz, &p);
if (r < 0)
@@ -5122,8 +5029,7 @@ static int message_skip_fields(
(*signature)++;
- } else if (t == SD_BUS_TYPE_STRUCT ||
- t == SD_BUS_TYPE_DICT_ENTRY) {
+ } else if (IN_SET(t, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
r = signature_element_length(*signature, &l);
if (r < 0)
@@ -5368,14 +5274,13 @@ int bus_message_parse_fields(sd_bus_message *m) {
r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
- if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
+ if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client) {
m->creds.unique_name = (char*) m->sender;
m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
}
break;
-
case BUS_MESSAGE_HEADER_SIGNATURE: {
const char *s;
char *c;
@@ -5397,8 +5302,7 @@ int bus_message_parse_fields(sd_bus_message *m) {
if (!c)
return -ENOMEM;
- free(m->root_container.signature);
- m->root_container.signature = c;
+ free_and_replace(m->root_container.signature, c);
break;
}
@@ -5535,11 +5439,20 @@ _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *desti
return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
}
+_public_ int sd_bus_message_set_sender(sd_bus_message *m, const char *sender) {
+ assert_return(m, -EINVAL);
+ assert_return(sender, -EINVAL);
+ assert_return(!m->sealed, -EPERM);
+ assert_return(!m->sender, -EEXIST);
+
+ return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
+}
+
#if 0 /// UNNEEDED by elogind
int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
size_t total;
void *p, *e;
- unsigned i;
+ size_t i;
struct bus_body_part *part;
assert(m);
@@ -5592,7 +5505,7 @@ int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
}
_public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
- char **strv = NULL;
+ _cleanup_strv_free_ char **strv = NULL;
int r;
assert_return(m, -EINVAL);
@@ -5600,12 +5513,10 @@ _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
assert_return(l, -EINVAL);
r = bus_message_read_strv_extend(m, &strv);
- if (r <= 0) {
- strv_free(strv);
+ if (r <= 0)
return r;
- }
- *l = strv;
+ *l = TAKE_PTR(strv);
return 1;
}
@@ -5783,9 +5694,7 @@ _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int
assert(r > 0);
- if (type == SD_BUS_TYPE_OBJECT_PATH ||
- type == SD_BUS_TYPE_SIGNATURE ||
- type == SD_BUS_TYPE_STRING)
+ if (IN_SET(type, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE, SD_BUS_TYPE_STRING))
r = sd_bus_message_append_basic(m, type, basic.string);
else
r = sd_bus_message_append_basic(m, type, &basic);
@@ -5857,10 +5766,12 @@ int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
case SD_BUS_MESSAGE_METHOD_RETURN:
case SD_BUS_MESSAGE_METHOD_ERROR:
- n = message_new(bus, (*m)->header->type);
- if (!n)
+ r = sd_bus_message_new(bus, &n, (*m)->header->type);
+ if (r < 0)
return -ENOMEM;
+ assert(n);
+
n->reply_cookie = (*m)->reply_cookie;
r = message_append_reply_cookie(n, n->reply_cookie);
@@ -5903,13 +5814,12 @@ int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
timeout = BUS_DEFAULT_TIMEOUT;
- r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
+ r = sd_bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
if (r < 0)
return r;
sd_bus_message_unref(*m);
- *m = n;
- n = NULL;
+ *m = TAKE_PTR(n);
return 0;
}
diff --git a/src/libelogind/sd-bus/bus-message.h b/src/libelogind/sd-bus/bus-message.h
index df501d316..bb6eb786c 100644
--- a/src/libelogind/sd-bus/bus-message.h
+++ b/src/libelogind/sd-bus/bus-message.h
@@ -1,22 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <byteswap.h>
@@ -92,9 +77,7 @@ struct sd_bus_message {
bool dont_send:1;
bool allow_fds:1;
bool free_header:1;
- bool free_kdbus:1;
bool free_fds:1;
- bool release_kdbus:1;
bool poisoned:1;
/* The first and last bytes of the message */
@@ -128,8 +111,6 @@ struct sd_bus_message {
struct iovec iovec_fixed[2];
unsigned n_iovec;
- struct kdbus_msg *kdbus;
-
char *peeked_signature;
/* If set replies to this message must carry the signature
@@ -139,10 +120,6 @@ struct sd_bus_message {
usec_t timeout;
- char sender_buffer[3 + DECIMAL_STR_MAX(uint64_t) + 1];
- char destination_buffer[3 + DECIMAL_STR_MAX(uint64_t) + 1];
- char *destination_ptr;
-
size_t header_offsets[_BUS_MESSAGE_HEADER_MAX];
unsigned n_header_offsets;
};
@@ -191,7 +168,6 @@ static inline bool BUS_MESSAGE_IS_GVARIANT(sd_bus_message *m) {
return m->header->version == 2;
}
-int bus_message_seal(sd_bus_message *m, uint64_t serial, usec_t timeout);
#if 0 /// UNNEEDED by elogind
int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz);
#endif // 0
@@ -205,7 +181,7 @@ int bus_message_from_header(
size_t footer_accessible,
size_t message_size,
int *fds,
- unsigned n_fds,
+ size_t n_fds,
const char *label,
size_t extra,
sd_bus_message **ret);
@@ -215,7 +191,7 @@ int bus_message_from_malloc(
void *buffer,
size_t length,
int *fds,
- unsigned n_fds,
+ size_t n_fds,
const char *label,
sd_bus_message **ret);
diff --git a/src/libelogind/sd-bus/bus-objects.c b/src/libelogind/sd-bus/bus-objects.c
index 98911d520..9609834fa 100644
--- a/src/libelogind/sd-bus/bus-objects.c
+++ b/src/libelogind/sd-bus/bus-objects.c
@@ -1,20 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "alloc-util.h"
@@ -38,7 +23,7 @@ static int node_vtable_get_userdata(
sd_bus_error *error) {
sd_bus_slot *s;
- void *u;
+ void *u, *found_u;
int r;
assert(bus);
@@ -50,7 +35,7 @@ static int node_vtable_get_userdata(
if (c->find) {
bus->current_slot = sd_bus_slot_ref(s);
bus->current_userdata = u;
- r = c->find(bus, path, c->interface, u, &u, error);
+ r = c->find(bus, path, c->interface, u, &found_u, error);
bus->current_userdata = NULL;
bus->current_slot = sd_bus_slot_unref(s);
@@ -60,10 +45,11 @@ static int node_vtable_get_userdata(
return -sd_bus_error_get_errno(error);
if (r == 0)
return r;
- }
+ } else
+ found_u = u;
if (userdata)
- *userdata = u;
+ *userdata = found_u;
return 1;
}
@@ -171,9 +157,9 @@ static int add_enumerated_to_set(
enum {
/* if set, add_subtree() works recursively */
- CHILDREN_RECURSIVE = (1U << 1),
+ CHILDREN_RECURSIVE = 1 << 0,
/* if set, add_subtree() scans object-manager hierarchies recursively */
- CHILDREN_SUBHIERARCHIES = (1U << 0),
+ CHILDREN_SUBHIERARCHIES = 1 << 1,
};
static int add_subtree_to_set(
@@ -752,7 +738,7 @@ static int vtable_append_all_properties(
return 1;
for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
- if (v->type != _SD_BUS_VTABLE_PROPERTY && v->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
+ if (!IN_SET(v->type, _SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY))
continue;
if (v->flags & SD_BUS_VTABLE_HIDDEN)
@@ -829,6 +815,9 @@ static int property_get_all_callbacks_run(
return 0;
}
+ if (!*found_object)
+ return 0;
+
if (!found_interface) {
r = sd_bus_reply_method_errorf(
m,
@@ -1364,7 +1353,7 @@ int bus_process_object(sd_bus *bus, sd_bus_message *m) {
assert(bus);
assert(m);
- if (bus->hello_flags & KDBUS_HELLO_MONITOR)
+ if (bus->is_monitor)
return 0;
if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
@@ -1465,14 +1454,12 @@ static struct node *bus_node_allocate(sd_bus *bus, const char *path) {
return NULL;
n->parent = parent;
- n->path = s;
- s = NULL; /* do not free */
+ n->path = TAKE_PTR(s);
r = hashmap_put(bus->nodes, n->path, n);
if (r < 0) {
free(n->path);
- free(n);
- return NULL;
+ return mfree(n);
}
if (parent)
@@ -1494,7 +1481,7 @@ void bus_node_gc(sd_bus *b, struct node *n) {
n->object_managers)
return;
- assert(hashmap_remove(b->nodes, n->path) == n);
+ assert_se(hashmap_remove(b->nodes, n->path) == n);
if (n->parent)
LIST_REMOVE(siblings, n->parent->child, n);
@@ -1543,6 +1530,7 @@ static int bus_add_object(
int r;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(object_path_is_valid(path), -EINVAL);
assert_return(callback, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -1646,6 +1634,7 @@ static int add_object_vtable_internal(
int r;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(object_path_is_valid(path), -EINVAL);
assert_return(interface_name_is_valid(interface), -EINVAL);
assert_return(vtable, -EINVAL);
@@ -1751,8 +1740,7 @@ static int add_object_vtable_internal(
goto fail;
}
- /* Fall through */
-
+ _fallthrough_;
case _SD_BUS_VTABLE_PROPERTY: {
struct vtable_member *m;
@@ -1856,6 +1844,7 @@ _public_ int sd_bus_add_node_enumerator(
int r;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(object_path_is_valid(path), -EINVAL);
assert_return(callback, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -1996,7 +1985,7 @@ static int emit_properties_changed_on_interface(
* as changing in the message. */
for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
- if (v->type != _SD_BUS_VTABLE_PROPERTY && v->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
+ if (!IN_SET(v->type, _SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY))
continue;
if (v->flags & SD_BUS_VTABLE_HIDDEN)
@@ -2067,7 +2056,7 @@ static int emit_properties_changed_on_interface(
const sd_bus_vtable *v;
for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
- if (v->type != _SD_BUS_VTABLE_PROPERTY && v->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
+ if (!IN_SET(v->type, _SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY))
continue;
if (v->flags & SD_BUS_VTABLE_HIDDEN)
@@ -2107,6 +2096,7 @@ _public_ int sd_bus_emit_properties_changed_strv(
int r;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(object_path_is_valid(path), -EINVAL);
assert_return(interface_name_is_valid(interface), -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -2153,6 +2143,7 @@ _public_ int sd_bus_emit_properties_changed(
char **names;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(object_path_is_valid(path), -EINVAL);
assert_return(interface_name_is_valid(interface), -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -2337,6 +2328,7 @@ _public_ int sd_bus_emit_object_added(sd_bus *bus, const char *path) {
*/
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(object_path_is_valid(path), -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -2507,6 +2499,7 @@ _public_ int sd_bus_emit_object_removed(sd_bus *bus, const char *path) {
*/
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(object_path_is_valid(path), -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -2660,6 +2653,7 @@ _public_ int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, ch
int r;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(object_path_is_valid(path), -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -2726,6 +2720,7 @@ _public_ int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const c
char **interfaces;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(object_path_is_valid(path), -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -2743,6 +2738,7 @@ _public_ int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path,
int r;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(object_path_is_valid(path), -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -2777,6 +2773,7 @@ _public_ int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const
char **interfaces;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(object_path_is_valid(path), -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -2794,6 +2791,7 @@ _public_ int sd_bus_add_object_manager(sd_bus *bus, sd_bus_slot **slot, const ch
int r;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(object_path_is_valid(path), -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
diff --git a/src/libelogind/sd-bus/bus-objects.h b/src/libelogind/sd-bus/bus-objects.h
index e0b8c534e..e8e1a522c 100644
--- a/src/libelogind/sd-bus/bus-objects.h
+++ b/src/libelogind/sd-bus/bus-objects.h
@@ -1,22 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "bus-internal.h"
diff --git a/src/libelogind/sd-bus/bus-protocol.h b/src/libelogind/sd-bus/bus-protocol.h
index 9d180cb28..20d19d402 100644
--- a/src/libelogind/sd-bus/bus-protocol.h
+++ b/src/libelogind/sd-bus/bus-protocol.h
@@ -1,22 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <endian.h>
diff --git a/src/libelogind/sd-bus/bus-signature.c b/src/libelogind/sd-bus/bus-signature.c
index 7bc243494..18c91e870 100644
--- a/src/libelogind/sd-bus/bus-signature.c
+++ b/src/libelogind/sd-bus/bus-signature.c
@@ -1,24 +1,11 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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>
+#include "sd-bus.h"
+
#include "bus-signature.h"
#include "bus-type.h"
@@ -106,7 +93,6 @@ static int signature_element_length_internal(
return -EINVAL;
}
-
int signature_element_length(const char *s, size_t *l) {
return signature_element_length_internal(s, true, 0, 0, l);
}
diff --git a/src/libelogind/sd-bus/bus-signature.h b/src/libelogind/sd-bus/bus-signature.h
index 1e0cd7f58..d4b43bac0 100644
--- a/src/libelogind/sd-bus/bus-signature.h
+++ b/src/libelogind/sd-bus/bus-signature.h
@@ -1,22 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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>
diff --git a/src/libelogind/sd-bus/bus-slot.c b/src/libelogind/sd-bus/bus-slot.c
index 33590c31a..fbf37320d 100644
--- a/src/libelogind/sd-bus/bus-slot.c
+++ b/src/libelogind/sd-bus/bus-slot.c
@@ -1,20 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-bus.h"
@@ -80,7 +65,7 @@ void bus_slot_disconnect(sd_bus_slot *slot) {
if (slot->reply_callback.cookie != 0)
ordered_hashmap_remove(slot->bus->reply_callbacks, &slot->reply_callback.cookie);
- if (slot->reply_callback.timeout != 0)
+ if (slot->reply_callback.timeout_usec != 0)
prioq_remove(slot->bus->reply_callbacks_prioq, &slot->reply_callback, &slot->reply_callback.prioq_idx);
break;
@@ -93,12 +78,17 @@ void bus_slot_disconnect(sd_bus_slot *slot) {
case BUS_MATCH_CALLBACK:
if (slot->match_added)
- bus_remove_match_internal(slot->bus, slot->match_callback.match_string, slot->match_callback.cookie);
+ (void) bus_remove_match_internal(slot->bus, slot->match_callback.match_string);
+
+ if (slot->match_callback.install_slot) {
+ bus_slot_disconnect(slot->match_callback.install_slot);
+ slot->match_callback.install_slot = sd_bus_slot_unref(slot->match_callback.install_slot);
+ }
slot->bus->match_callbacks_modified = true;
bus_match_remove(&slot->bus->match_callbacks, &slot->match_callback);
- free(slot->match_callback.match_string);
+ slot->match_callback.match_string = mfree(slot->match_callback.match_string);
break;
@@ -164,7 +154,6 @@ void bus_slot_disconnect(sd_bus_slot *slot) {
key.interface = slot->node_vtable.interface;
key.member = v->x.method.member;
-
x = hashmap_remove(slot->bus->vtable_properties, &key);
break;
}}
@@ -173,7 +162,7 @@ void bus_slot_disconnect(sd_bus_slot *slot) {
}
}
- free(slot->node_vtable.interface);
+ slot->node_vtable.interface = mfree(slot->node_vtable.interface);
if (slot->node_vtable.node) {
LIST_REMOVE(vtables, slot->node_vtable.node->vtables, &slot->node_vtable);
@@ -211,6 +200,10 @@ _public_ sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) {
}
bus_slot_disconnect(slot);
+
+ if (slot->destroy_callback)
+ slot->destroy_callback(slot->userdata);
+
free(slot->description);
return mfree(slot);
}
@@ -238,6 +231,22 @@ _public_ void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata) {
return ret;
}
+_public_ int sd_bus_slot_set_destroy_callback(sd_bus_slot *slot, sd_bus_destroy_t callback) {
+ assert_return(slot, -EINVAL);
+
+ slot->destroy_callback = callback;
+ return 0;
+}
+
+_public_ int sd_bus_slot_get_destroy_callback(sd_bus_slot *slot, sd_bus_destroy_t *callback) {
+ assert_return(slot, -EINVAL);
+
+ if (callback)
+ *callback = slot->destroy_callback;
+
+ return !!slot->destroy_callback;
+}
+
_public_ sd_bus_message *sd_bus_slot_get_current_message(sd_bus_slot *slot) {
assert_return(slot, NULL);
assert_return(slot->type >= 0, NULL);
@@ -268,6 +277,37 @@ _public_ void* sd_bus_slot_get_current_userdata(sd_bus_slot *slot) {
return slot->bus->current_userdata;
}
+_public_ int sd_bus_slot_get_floating(sd_bus_slot *slot) {
+ assert_return(slot, -EINVAL);
+
+ return slot->floating;
+}
+
+_public_ int sd_bus_slot_set_floating(sd_bus_slot *slot, int b) {
+ assert_return(slot, -EINVAL);
+
+ if (slot->floating == !!b)
+ return 0;
+
+ if (!slot->bus) /* already disconnected slots can't be reconnected */
+ return -ESTALE;
+
+ slot->floating = b;
+
+ /* When a slot is "floating" then the bus references the slot. Otherwise the slot references the bus. Hence,
+ * when we move from one to the other, let's increase one reference and decrease the other. */
+
+ if (b) {
+ sd_bus_slot_ref(slot);
+ sd_bus_unref(slot->bus);
+ } else {
+ sd_bus_ref(slot->bus);
+ sd_bus_slot_unref(slot);
+ }
+
+ return 1;
+}
+
_public_ int sd_bus_slot_set_description(sd_bus_slot *slot, const char *description) {
assert_return(slot, -EINVAL);
@@ -277,8 +317,13 @@ _public_ int sd_bus_slot_set_description(sd_bus_slot *slot, const char *descript
_public_ int sd_bus_slot_get_description(sd_bus_slot *slot, const char **description) {
assert_return(slot, -EINVAL);
assert_return(description, -EINVAL);
- assert_return(slot->description, -ENXIO);
- *description = slot->description;
+ if (slot->description)
+ *description = slot->description;
+ else if (slot->type == BUS_MATCH_CALLBACK)
+ *description = slot->match_callback.match_string;
+ else
+ return -ENXIO;
+
return 0;
}
diff --git a/src/libelogind/sd-bus/bus-slot.h b/src/libelogind/sd-bus/bus-slot.h
index 3b8b94dc6..f1e1e23ac 100644
--- a/src/libelogind/sd-bus/bus-slot.h
+++ b/src/libelogind/sd-bus/bus-slot.h
@@ -1,22 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-bus.h"
diff --git a/src/libelogind/sd-bus/bus-socket.c b/src/libelogind/sd-bus/bus-socket.c
index 8b25002f0..b147a3843 100644
--- a/src/libelogind/sd-bus/bus-socket.c
+++ b/src/libelogind/sd-bus/bus-socket.c
@@ -1,20 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <endian.h>
@@ -31,9 +16,13 @@
#include "bus-socket.h"
#include "fd-util.h"
#include "format-util.h"
+#include "fs-util.h"
#include "hexdecoct.h"
+#include "io-util.h"
#include "macro.h"
#include "missing.h"
+#include "path-util.h"
+#include "process-util.h"
#include "selinux-util.h"
#include "signal-util.h"
#include "stdio-util.h"
@@ -187,7 +176,7 @@ static int bus_socket_auth_verify_client(sd_bus *b) {
if (!e)
return 0;
- if (b->hello_flags & KDBUS_HELLO_ACCEPT_FD) {
+ if (b->accept_fd) {
f = memmem(e + 2, b->rbuffer_size - (e - (char*) b->rbuffer) - 2, "\r\n", 2);
if (!f)
return 0;
@@ -231,8 +220,9 @@ static int bus_socket_auth_verify_client(sd_bus *b) {
if (f)
b->can_fds =
- (f - e == strlen("\r\nAGREE_UNIX_FD")) &&
- memcmp(e + 2, "AGREE_UNIX_FD", strlen("AGREE_UNIX_FD")) == 0;
+ (f - e == STRLEN("\r\nAGREE_UNIX_FD")) &&
+ memcmp(e + 2, "AGREE_UNIX_FD",
+ STRLEN("AGREE_UNIX_FD")) == 0;
b->rbuffer_size -= (start - (char*) b->rbuffer);
memmove(b->rbuffer, start, b->rbuffer_size);
@@ -255,16 +245,13 @@ static bool line_equals(const char *s, size_t m, const char *line) {
}
static bool line_begins(const char *s, size_t m, const char *word) {
- size_t l;
-
- l = strlen(word);
- if (m < l)
- return false;
+ const char *p;
- if (memcmp(s, word, l) != 0)
+ p = memory_startswith(s, m, word);
+ if (!p)
return false;
- return m == l || (m > l && s[l] == ' ');
+ return IN_SET(*p, 0, ' ');
}
static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) {
@@ -343,7 +330,7 @@ static int bus_socket_auth_write(sd_bus *b, const char *t) {
assert(t);
/* We only make use of the first iovec */
- assert(b->auth_index == 0 || b->auth_index == 1);
+ assert(IN_SET(b->auth_index, 0, 1));
l = strlen(t);
p = malloc(b->auth_iovec[0].iov_len + l);
@@ -473,7 +460,7 @@ static int bus_socket_auth_verify_server(sd_bus *b) {
r = bus_socket_auth_write_ok(b);
}
} else if (line_equals(line, l, "NEGOTIATE_UNIX_FD")) {
- if (b->auth == _BUS_AUTH_INVALID || !(b->hello_flags & KDBUS_HELLO_ACCEPT_FD))
+ if (b->auth == _BUS_AUTH_INVALID || !b->accept_fd)
r = bus_socket_auth_write(b, "ERROR\r\n");
else {
b->can_fds = true;
@@ -546,7 +533,7 @@ static int bus_socket_read_auth(sd_bus *b) {
mh.msg_control = &control;
mh.msg_controllen = sizeof(control);
- k = recvmsg(b->input_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
+ k = recvmsg(b->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
if (k < 0 && errno == ENOTSOCK) {
b->prefer_readv = true;
k = readv(b->input_fd, &iov, 1);
@@ -590,10 +577,9 @@ void bus_socket_setup(sd_bus *b) {
assert(b);
/* Increase the buffers to 8 MB */
- fd_inc_rcvbuf(b->input_fd, SNDBUF_SIZE);
- fd_inc_sndbuf(b->output_fd, SNDBUF_SIZE);
+ (void) fd_inc_rcvbuf(b->input_fd, SNDBUF_SIZE);
+ (void) fd_inc_sndbuf(b->output_fd, SNDBUF_SIZE);
- b->is_kernel = false;
b->message_version = 1;
b->message_endian = 0;
}
@@ -602,16 +588,24 @@ static void bus_get_peercred(sd_bus *b) {
int r;
assert(b);
+ assert(!b->ucred_valid);
+ assert(!b->label);
+ assert(b->n_groups == (size_t) -1);
/* Get the peer for socketpair() sockets */
b->ucred_valid = getpeercred(b->input_fd, &b->ucred) >= 0;
/* Get the SELinux context of the peer */
- if (mac_selinux_use()) {
- r = getpeersec(b->input_fd, &b->label);
- if (r < 0 && r != -EOPNOTSUPP)
- log_debug_errno(r, "Failed to determine peer security context: %m");
- }
+ r = getpeersec(b->input_fd, &b->label);
+ if (r < 0 && !IN_SET(r, -EOPNOTSUPP, -ENOPROTOOPT))
+ log_debug_errno(r, "Failed to determine peer security context: %m");
+
+ /* Get the list of auxiliary groups of the peer */
+ r = getpeergroups(b->input_fd, &b->groups);
+ if (r >= 0)
+ b->n_groups = (size_t) r;
+ else if (!IN_SET(r, -EOPNOTSUPP, -ENOPROTOOPT))
+ log_debug_errno(r, "Failed to determine peer's group list: %m");
}
static int bus_socket_start_auth_client(sd_bus *b) {
@@ -640,7 +634,7 @@ static int bus_socket_start_auth_client(sd_bus *b) {
if (!b->auth_buffer)
return -ENOMEM;
- if (b->hello_flags & KDBUS_HELLO_ACCEPT_FD)
+ if (b->accept_fd)
auth_suffix = "\r\nNEGOTIATE_UNIX_FD\r\nBEGIN\r\n";
else
auth_suffix = "\r\nBEGIN\r\n";
@@ -660,15 +654,15 @@ int bus_socket_start_auth(sd_bus *b) {
bus_get_peercred(b);
- b->state = BUS_AUTHENTICATING;
- b->auth_timeout = now(CLOCK_MONOTONIC) + BUS_DEFAULT_TIMEOUT;
+ bus_set_state(b, BUS_AUTHENTICATING);
+ b->auth_timeout = now(CLOCK_MONOTONIC) + BUS_AUTH_TIMEOUT;
if (sd_is_socket(b->input_fd, AF_UNIX, 0, 0) <= 0)
- b->hello_flags &= ~KDBUS_HELLO_ACCEPT_FD;
+ b->accept_fd = false;
if (b->output_fd != b->input_fd)
if (sd_is_socket(b->output_fd, AF_UNIX, 0, 0) <= 0)
- b->hello_flags &= ~KDBUS_HELLO_ACCEPT_FD;
+ b->accept_fd = false;
if (b->is_server)
return bus_socket_read_auth(b);
@@ -676,69 +670,279 @@ int bus_socket_start_auth(sd_bus *b) {
return bus_socket_start_auth_client(b);
}
+static int bus_socket_inotify_setup(sd_bus *b) {
+ _cleanup_free_ int *new_watches = NULL;
+ _cleanup_free_ char *absolute = NULL;
+ size_t n_allocated = 0, n = 0, done = 0, i;
+ unsigned max_follow = 32;
+ const char *p;
+ int wd, r;
+
+ assert(b);
+ assert(b->watch_bind);
+ assert(b->sockaddr.sa.sa_family == AF_UNIX);
+ assert(b->sockaddr.un.sun_path[0] != 0);
+
+ /* Sets up an inotify fd in case watch_bind is enabled: wait until the configured AF_UNIX file system socket
+ * appears before connecting to it. The implemented is pretty simplistic: we just subscribe to relevant changes
+ * to all prefix components of the path, and every time we get an event for that we try to reconnect again,
+ * without actually caring what precisely the event we got told us. If we still can't connect we re-subscribe
+ * to all relevant changes of anything in the path, so that our watches include any possibly newly created path
+ * components. */
+
+ if (b->inotify_fd < 0) {
+ b->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
+ if (b->inotify_fd < 0)
+ return -errno;
+
+ b->inotify_fd = fd_move_above_stdio(b->inotify_fd);
+ }
+
+ /* Make sure the path is NUL terminated */
+ p = strndupa(b->sockaddr.un.sun_path, sizeof(b->sockaddr.un.sun_path));
+
+ /* Make sure the path is absolute */
+ r = path_make_absolute_cwd(p, &absolute);
+ if (r < 0)
+ goto fail;
+
+ /* Watch all parent directories, and don't mind any prefix that doesn't exist yet. For the innermost directory
+ * that exists we want to know when files are created or moved into it. For all parents of it we just care if
+ * they are removed or renamed. */
+
+ if (!GREEDY_REALLOC(new_watches, n_allocated, n + 1)) {
+ r = -ENOMEM;
+ goto fail;
+ }
+
+ /* Start with the top-level directory, which is a bit simpler than the rest, since it can't be a symlink, and
+ * always exists */
+ wd = inotify_add_watch(b->inotify_fd, "/", IN_CREATE|IN_MOVED_TO);
+ if (wd < 0) {
+ r = log_debug_errno(errno, "Failed to add inotify watch on /: %m");
+ goto fail;
+ } else
+ new_watches[n++] = wd;
+
+ for (;;) {
+ _cleanup_free_ char *component = NULL, *prefix = NULL, *destination = NULL;
+ size_t n_slashes, n_component;
+ char *c = NULL;
+
+ n_slashes = strspn(absolute + done, "/");
+ n_component = n_slashes + strcspn(absolute + done + n_slashes, "/");
+
+ if (n_component == 0) /* The end */
+ break;
+
+ component = strndup(absolute + done, n_component);
+ if (!component) {
+ r = -ENOMEM;
+ goto fail;
+ }
+
+ /* A trailing slash? That's a directory, and not a socket then */
+ if (path_equal(component, "/")) {
+ r = -EISDIR;
+ goto fail;
+ }
+
+ /* A single dot? Let's eat this up */
+ if (path_equal(component, "/.")) {
+ done += n_component;
+ continue;
+ }
+
+ prefix = strndup(absolute, done + n_component);
+ if (!prefix) {
+ r = -ENOMEM;
+ goto fail;
+ }
+
+ if (!GREEDY_REALLOC(new_watches, n_allocated, n + 1)) {
+ r = -ENOMEM;
+ goto fail;
+ }
+
+ wd = inotify_add_watch(b->inotify_fd, prefix, IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CREATE|IN_MOVED_TO|IN_DONT_FOLLOW);
+ log_debug("Added inotify watch for %s on bus %s: %i", prefix, strna(b->description), wd);
+
+ if (wd < 0) {
+ if (IN_SET(errno, ENOENT, ELOOP))
+ break; /* This component doesn't exist yet, or the path contains a cyclic symlink right now */
+
+ r = log_debug_errno(errno, "Failed to add inotify watch on %s: %m", empty_to_root(prefix));
+ goto fail;
+ } else
+ new_watches[n++] = wd;
+
+ /* Check if this is possibly a symlink. If so, let's follow it and watch it too. */
+ r = readlink_malloc(prefix, &destination);
+ if (r == -EINVAL) { /* not a symlink */
+ done += n_component;
+ continue;
+ }
+ if (r < 0)
+ goto fail;
+
+ if (isempty(destination)) { /* Empty symlink target? Yuck! */
+ r = -EINVAL;
+ goto fail;
+ }
+
+ if (max_follow <= 0) { /* Let's make sure we don't follow symlinks forever */
+ r = -ELOOP;
+ goto fail;
+ }
+
+ if (path_is_absolute(destination)) {
+ /* For absolute symlinks we build the new path and start anew */
+ c = strjoin(destination, absolute + done + n_component);
+ done = 0;
+ } else {
+ _cleanup_free_ char *t = NULL;
+
+ /* For relative symlinks we replace the last component, and try again */
+ t = strndup(absolute, done);
+ if (!t)
+ return -ENOMEM;
+
+ c = strjoin(t, "/", destination, absolute + done + n_component);
+ }
+ if (!c) {
+ r = -ENOMEM;
+ goto fail;
+ }
+
+ free(absolute);
+ absolute = c;
+
+ max_follow--;
+ }
+
+ /* And now, let's remove all watches from the previous iteration we don't need anymore */
+ for (i = 0; i < b->n_inotify_watches; i++) {
+ bool found = false;
+ size_t j;
+
+ for (j = 0; j < n; j++)
+ if (new_watches[j] == b->inotify_watches[i]) {
+ found = true;
+ break;
+ }
+
+ if (found)
+ continue;
+
+ (void) inotify_rm_watch(b->inotify_fd, b->inotify_watches[i]);
+ }
+
+ free_and_replace(b->inotify_watches, new_watches);
+ b->n_inotify_watches = n;
+
+ return 0;
+
+fail:
+ bus_close_inotify_fd(b);
+ return r;
+}
+
int bus_socket_connect(sd_bus *b) {
+ bool inotify_done = false;
int r;
assert(b);
- assert(b->input_fd < 0);
- assert(b->output_fd < 0);
- assert(b->sockaddr.sa.sa_family != AF_UNSPEC);
- b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (b->input_fd < 0)
- return -errno;
+ for (;;) {
+ assert(b->input_fd < 0);
+ assert(b->output_fd < 0);
+ assert(b->sockaddr.sa.sa_family != AF_UNSPEC);
- b->output_fd = b->input_fd;
+ b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ if (b->input_fd < 0)
+ return -errno;
- bus_socket_setup(b);
+ b->input_fd = fd_move_above_stdio(b->input_fd);
- r = connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size);
- if (r < 0) {
- if (errno == EINPROGRESS)
- return 1;
+ b->output_fd = b->input_fd;
+ bus_socket_setup(b);
- return -errno;
+ if (connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size) < 0) {
+ if (errno == EINPROGRESS) {
+
+ /* If we have any inotify watches open, close them now, we don't need them anymore, as
+ * we have successfully initiated a connection */
+ bus_close_inotify_fd(b);
+
+ /* Note that very likely we are already in BUS_OPENING state here, as we enter it when
+ * we start parsing the address string. The only reason we set the state explicitly
+ * here, is to undo BUS_WATCH_BIND, in case we did the inotify magic. */
+ bus_set_state(b, BUS_OPENING);
+ return 1;
+ }
+
+ if (IN_SET(errno, ENOENT, ECONNREFUSED) && /* ENOENT → unix socket doesn't exist at all; ECONNREFUSED → unix socket stale */
+ b->watch_bind &&
+ b->sockaddr.sa.sa_family == AF_UNIX &&
+ b->sockaddr.un.sun_path[0] != 0) {
+
+ /* This connection attempt failed, let's release the socket for now, and start with a
+ * fresh one when reconnecting. */
+ bus_close_io_fds(b);
+
+ if (inotify_done) {
+ /* inotify set up already, don't do it again, just return now, and remember
+ * that we are waiting for inotify events now. */
+ bus_set_state(b, BUS_WATCH_BIND);
+ return 1;
+ }
+
+ /* This is a file system socket, and the inotify logic is enabled. Let's create the necessary inotify fd. */
+ r = bus_socket_inotify_setup(b);
+ if (r < 0)
+ return r;
+
+ /* Let's now try to connect a second time, because in theory there's otherwise a race
+ * here: the socket might have been created in the time between our first connect() and
+ * the time we set up the inotify logic. But let's remember that we set up inotify now,
+ * so that we don't do the connect() more than twice. */
+ inotify_done = true;
+
+ } else
+ return -errno;
+ } else
+ break;
}
+ /* Yay, established, we don't need no inotify anymore! */
+ bus_close_inotify_fd(b);
+
return bus_socket_start_auth(b);
}
int bus_socket_exec(sd_bus *b) {
int s[2], r;
- pid_t pid;
assert(b);
assert(b->input_fd < 0);
assert(b->output_fd < 0);
assert(b->exec_path);
+ assert(b->busexec_pid == 0);
r = socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, s);
if (r < 0)
return -errno;
- pid = fork();
- if (pid < 0) {
+ r = safe_fork_full("(sd-busexec)", s+1, 1, FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS, &b->busexec_pid);
+ if (r < 0) {
safe_close_pair(s);
- return -errno;
+ return r;
}
- if (pid == 0) {
+ if (r == 0) {
/* Child */
- (void) reset_all_signal_handlers();
- (void) reset_signal_mask();
-
- close_all_fds(s+1, 1);
-
- assert_se(dup3(s[1], STDIN_FILENO, 0) == STDIN_FILENO);
- assert_se(dup3(s[1], STDOUT_FILENO, 0) == STDOUT_FILENO);
-
- if (s[1] != STDIN_FILENO && s[1] != STDOUT_FILENO)
- safe_close(s[1]);
-
- fd_cloexec(STDIN_FILENO, false);
- fd_cloexec(STDOUT_FILENO, false);
- fd_nonblock(STDIN_FILENO, false);
- fd_nonblock(STDOUT_FILENO, false);
+ if (rearrange_stdio(s[1], s[1], STDERR_FILENO) < 0)
+ _exit(EXIT_FAILURE);
if (b->exec_argv)
execvp(b->exec_path, b->exec_argv);
@@ -751,7 +955,7 @@ int bus_socket_exec(sd_bus *b) {
}
safe_close(s[1]);
- b->output_fd = b->input_fd = s[0];
+ b->output_fd = b->input_fd = fd_move_above_stdio(s[0]);
bus_socket_setup(b);
@@ -776,7 +980,7 @@ int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
assert(bus);
assert(m);
assert(idx);
- assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
+ assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
if (*idx >= BUS_MESSAGE_SIZE(m))
return 0;
@@ -800,7 +1004,7 @@ int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
.msg_iovlen = m->n_iovec,
};
- if (m->n_fds > 0) {
+ if (m->n_fds > 0 && *idx == 0) {
struct cmsghdr *control;
mh.msg_control = control = alloca(CMSG_SPACE(sizeof(int) * m->n_fds));
@@ -831,7 +1035,7 @@ static int bus_socket_read_message_need(sd_bus *bus, size_t *need) {
assert(bus);
assert(need);
- assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
+ assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
if (bus->rbuffer_size < sizeof(struct bus_header)) {
*need = sizeof(struct bus_header) + 8;
@@ -883,7 +1087,7 @@ static int bus_socket_make_message(sd_bus *bus, size_t size) {
assert(bus);
assert(bus->rbuffer_size >= size);
- assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
+ assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
r = bus_rqueue_make_room(bus);
if (r < 0)
@@ -932,7 +1136,7 @@ int bus_socket_read_message(sd_bus *bus) {
bool handle_cmsg = false;
assert(bus);
- assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
+ assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
r = bus_socket_read_message_need(bus, &need);
if (r < 0)
@@ -959,7 +1163,7 @@ int bus_socket_read_message(sd_bus *bus) {
mh.msg_control = &control;
mh.msg_controllen = sizeof(control);
- k = recvmsg(bus->input_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
+ k = recvmsg(bus->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
if (k < 0 && errno == ENOTSOCK) {
bus->prefer_readv = true;
k = readv(bus->input_fd, &iov, 1);
@@ -979,7 +1183,7 @@ int bus_socket_read_message(sd_bus *bus) {
CMSG_FOREACH(cmsg, &mh)
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_RIGHTS) {
- int n, *f;
+ int n, *f, i;
n = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
@@ -992,15 +1196,15 @@ int bus_socket_read_message(sd_bus *bus) {
return -EIO;
}
- f = realloc(bus->fds, sizeof(int) * (bus->n_fds + n));
+ f = reallocarray(bus->fds, bus->n_fds + n, sizeof(int));
if (!f) {
close_many((int*) CMSG_DATA(cmsg), n);
return -ENOMEM;
}
- memcpy_safe(f + bus->n_fds, CMSG_DATA(cmsg), n * sizeof(int));
+ for (i = 0; i < n; i++)
+ f[bus->n_fds++] = fd_move_above_stdio(((int*) CMSG_DATA(cmsg))[i]);
bus->fds = f;
- bus->n_fds += n;
} else
log_debug("Got unexpected auxiliary data with level=%d and type=%d",
cmsg->cmsg_level, cmsg->cmsg_type);
@@ -1062,3 +1266,34 @@ int bus_socket_process_authenticating(sd_bus *b) {
return bus_socket_read_auth(b);
}
+
+int bus_socket_process_watch_bind(sd_bus *b) {
+ int r, q;
+
+ assert(b);
+ assert(b->state == BUS_WATCH_BIND);
+ assert(b->inotify_fd >= 0);
+
+ r = flush_fd(b->inotify_fd);
+ if (r <= 0)
+ return r;
+
+ log_debug("Got inotify event on bus %s.", strna(b->description));
+
+ /* We flushed events out of the inotify fd. In that case, maybe the socket is valid now? Let's try to connect
+ * to it again */
+
+ r = bus_socket_connect(b);
+ if (r < 0)
+ return r;
+
+ q = bus_attach_io_events(b);
+ if (q < 0)
+ return q;
+
+ q = bus_attach_inotify_event(b);
+ if (q < 0)
+ return q;
+
+ return r;
+}
diff --git a/src/libelogind/sd-bus/bus-socket.h b/src/libelogind/sd-bus/bus-socket.h
index 684feead7..d1118ca1d 100644
--- a/src/libelogind/sd-bus/bus-socket.h
+++ b/src/libelogind/sd-bus/bus-socket.h
@@ -1,22 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-bus.h"
@@ -33,5 +18,6 @@ int bus_socket_read_message(sd_bus *bus);
int bus_socket_process_opening(sd_bus *b);
int bus_socket_process_authenticating(sd_bus *b);
+int bus_socket_process_watch_bind(sd_bus *b);
bool bus_socket_auth_needs_write(sd_bus *b);
diff --git a/src/libelogind/sd-bus/bus-track.c b/src/libelogind/sd-bus/bus-track.c
index 4acaf2479..16bf615f5 100644
--- a/src/libelogind/sd-bus/bus-track.c
+++ b/src/libelogind/sd-bus/bus-track.c
@@ -1,20 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-bus.h"
@@ -43,29 +28,18 @@ struct sd_bus_track {
bool in_queue:1; /* In bus->track_queue? */
bool modified:1;
bool recursive:1;
+ sd_bus_destroy_t destroy_callback;
LIST_FIELDS(sd_bus_track, tracks);
};
-#define MATCH_PREFIX \
- "type='signal'," \
- "sender='org.freedesktop.DBus'," \
- "path='/org/freedesktop/DBus'," \
- "interface='org.freedesktop.DBus'," \
- "member='NameOwnerChanged'," \
- "arg0='"
-
-#define MATCH_SUFFIX \
- "'"
-
-#define MATCH_FOR_NAME(name) \
- ({ \
- char *_x; \
- size_t _l = strlen(name); \
- _x = alloca(strlen(MATCH_PREFIX)+_l+strlen(MATCH_SUFFIX)+1); \
- strcpy(stpcpy(stpcpy(_x, MATCH_PREFIX), name), MATCH_SUFFIX); \
- _x; \
- })
+#define MATCH_FOR_NAME(name) \
+ strjoina("type='signal'," \
+ "sender='org.freedesktop.DBus'," \
+ "path='/org/freedesktop/DBus'," \
+ "interface='org.freedesktop.DBus'," \
+ "member='NameOwnerChanged'," \
+ "arg0='", name, "'")
static struct track_item* track_item_free(struct track_item *i) {
@@ -147,6 +121,7 @@ _public_ int sd_bus_track_new(
sd_bus_track *t;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(track, -EINVAL);
if (!bus->bus_client)
@@ -183,27 +158,25 @@ _public_ sd_bus_track* sd_bus_track_ref(sd_bus_track *track) {
}
_public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) {
- struct track_item *i;
-
if (!track)
return NULL;
assert(track->n_ref > 0);
+ track->n_ref--;
- if (track->n_ref > 1) {
- track->n_ref--;
+ if (track->n_ref > 0)
return NULL;
- }
-
- while ((i = hashmap_steal_first(track->names)))
- track_item_free(i);
if (track->in_list)
LIST_REMOVE(tracks, track->bus->tracks, track);
bus_track_remove_from_queue(track);
- hashmap_free(track->names);
- sd_bus_unref(track->bus);
+ track->names = hashmap_free_with_destructor(track->names, track_item_free);
+ track->bus = sd_bus_unref(track->bus);
+
+ if (track->destroy_callback)
+ track->destroy_callback(track->userdata);
+
return mfree(track);
}
@@ -263,9 +236,7 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
bus_track_remove_from_queue(track); /* don't dispatch this while we work in it */
- track->n_adding++; /* make sure we aren't dispatched while we synchronously add this match */
- r = sd_bus_add_match(track->bus, &n->slot, match, on_name_owner_changed, track);
- track->n_adding--;
+ r = sd_bus_add_match_async(track->bus, &n->slot, match, on_name_owner_changed, NULL, track);
if (r < 0) {
bus_track_add_to_queue(track);
return r;
@@ -428,8 +399,6 @@ void bus_track_dispatch(sd_bus_track *track) {
}
void bus_track_close(sd_bus_track *track) {
- struct track_item *i;
-
assert(track);
/* Called whenever our bus connected is closed. If so, and our track object is non-empty, dispatch it
@@ -447,8 +416,7 @@ void bus_track_close(sd_bus_track *track) {
return;
/* Let's flush out all names */
- while ((i = hashmap_steal_first(track->names)))
- track_item_free(i);
+ hashmap_clear_with_destructor(track->names, track_item_free);
/* Invoke handler */
if (track->handler)
@@ -472,6 +440,22 @@ _public_ void *sd_bus_track_set_userdata(sd_bus_track *track, void *userdata) {
return ret;
}
+_public_ int sd_bus_track_set_destroy_callback(sd_bus_track *track, sd_bus_destroy_t callback) {
+ assert_return(track, -EINVAL);
+
+ track->destroy_callback = callback;
+ return 0;
+}
+
+_public_ int sd_bus_track_get_destroy_callback(sd_bus_track *track, sd_bus_destroy_t *ret) {
+ assert_return(track, -EINVAL);
+
+ if (ret)
+ *ret = track->destroy_callback;
+
+ return !!track->destroy_callback;
+}
+
_public_ int sd_bus_track_set_recursive(sd_bus_track *track, int b) {
assert_return(track, -EINVAL);
diff --git a/src/libelogind/sd-bus/bus-track.h b/src/libelogind/sd-bus/bus-track.h
index 26bd05f5c..f9590265d 100644
--- a/src/libelogind/sd-bus/bus-track.h
+++ b/src/libelogind/sd-bus/bus-track.h
@@ -1,22 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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 bus_track_dispatch(sd_bus_track *track);
diff --git a/src/libelogind/sd-bus/bus-type.c b/src/libelogind/sd-bus/bus-type.c
index 27014eed2..d4482e10c 100644
--- a/src/libelogind/sd-bus/bus-type.c
+++ b/src/libelogind/sd-bus/bus-type.c
@@ -1,21 +1,10 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
+***/
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
+#include <errno.h>
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+#include "sd-bus.h"
#include "bus-type.h"
diff --git a/src/libelogind/sd-bus/bus-type.h b/src/libelogind/sd-bus/bus-type.h
index 5c87eb5f0..cdac55c62 100644
--- a/src/libelogind/sd-bus/bus-type.h
+++ b/src/libelogind/sd-bus/bus-type.h
@@ -1,28 +1,11 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 "sd-bus.h"
-
#include "macro.h"
bool bus_type_is_valid(char c) _const_;
diff --git a/src/libelogind/sd-bus/kdbus.h b/src/libelogind/sd-bus/kdbus.h
deleted file mode 100644
index ecffc6b13..000000000
--- a/src/libelogind/sd-bus/kdbus.h
+++ /dev/null
@@ -1,980 +0,0 @@
-/*
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef _UAPI_KDBUS_H_
-#define _UAPI_KDBUS_H_
-
-#include <linux/ioctl.h>
-#include <linux/types.h>
-
-#define KDBUS_IOCTL_MAGIC 0x95
-#define KDBUS_SRC_ID_KERNEL (0)
-#define KDBUS_DST_ID_NAME (0)
-#define KDBUS_MATCH_ID_ANY (~0ULL)
-#define KDBUS_DST_ID_BROADCAST (~0ULL)
-#define KDBUS_FLAG_NEGOTIATE (1ULL << 63)
-
-/**
- * struct kdbus_notify_id_change - name registry change message
- * @id: New or former owner of the name
- * @flags: flags field from KDBUS_HELLO_*
- *
- * Sent from kernel to userspace when the owner or activator of
- * a well-known name changes.
- *
- * Attached to:
- * KDBUS_ITEM_ID_ADD
- * KDBUS_ITEM_ID_REMOVE
- */
-struct kdbus_notify_id_change {
- __u64 id;
- __u64 flags;
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_notify_name_change - name registry change message
- * @old_id: ID and flags of former owner of a name
- * @new_id: ID and flags of new owner of a name
- * @name: Well-known name
- *
- * Sent from kernel to userspace when the owner or activator of
- * a well-known name changes.
- *
- * Attached to:
- * KDBUS_ITEM_NAME_ADD
- * KDBUS_ITEM_NAME_REMOVE
- * KDBUS_ITEM_NAME_CHANGE
- */
-struct kdbus_notify_name_change {
- struct kdbus_notify_id_change old_id;
- struct kdbus_notify_id_change new_id;
- char name[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_creds - process credentials
- * @uid: User ID
- * @euid: Effective UID
- * @suid: Saved UID
- * @fsuid: Filesystem UID
- * @gid: Group ID
- * @egid: Effective GID
- * @sgid: Saved GID
- * @fsgid: Filesystem GID
- *
- * Attached to:
- * KDBUS_ITEM_CREDS
- */
-struct kdbus_creds {
- __u64 uid;
- __u64 euid;
- __u64 suid;
- __u64 fsuid;
- __u64 gid;
- __u64 egid;
- __u64 sgid;
- __u64 fsgid;
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_pids - process identifiers
- * @pid: Process ID
- * @tid: Thread ID
- * @ppid: Parent process ID
- *
- * The PID and TID of a process.
- *
- * Attached to:
- * KDBUS_ITEM_PIDS
- */
-struct kdbus_pids {
- __u64 pid;
- __u64 tid;
- __u64 ppid;
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_caps - process capabilities
- * @last_cap: Highest currently known capability bit
- * @caps: Variable number of 32-bit capabilities flags
- *
- * Contains a variable number of 32-bit capabilities flags.
- *
- * Attached to:
- * KDBUS_ITEM_CAPS
- */
-struct kdbus_caps {
- __u32 last_cap;
- __u32 caps[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_audit - audit information
- * @sessionid: The audit session ID
- * @loginuid: The audit login uid
- *
- * Attached to:
- * KDBUS_ITEM_AUDIT
- */
-struct kdbus_audit {
- __u32 sessionid;
- __u32 loginuid;
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_timestamp
- * @seqnum: Global per-domain message sequence number
- * @monotonic_ns: Monotonic timestamp, in nanoseconds
- * @realtime_ns: Realtime timestamp, in nanoseconds
- *
- * Attached to:
- * KDBUS_ITEM_TIMESTAMP
- */
-struct kdbus_timestamp {
- __u64 seqnum;
- __u64 monotonic_ns;
- __u64 realtime_ns;
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_vec - I/O vector for kdbus payload items
- * @size: The size of the vector
- * @address: Memory address of data buffer
- * @offset: Offset in the in-message payload memory,
- * relative to the message head
- *
- * Attached to:
- * KDBUS_ITEM_PAYLOAD_VEC, KDBUS_ITEM_PAYLOAD_OFF
- */
-struct kdbus_vec {
- __u64 size;
- union {
- __u64 address;
- __u64 offset;
- };
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_bloom_parameter - bus-wide bloom parameters
- * @size: Size of the bit field in bytes (m / 8)
- * @n_hash: Number of hash functions used (k)
- */
-struct kdbus_bloom_parameter {
- __u64 size;
- __u64 n_hash;
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_bloom_filter - bloom filter containing n elements
- * @generation: Generation of the element set in the filter
- * @data: Bit field, multiple of 8 bytes
- */
-struct kdbus_bloom_filter {
- __u64 generation;
- __u64 data[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_memfd - a kdbus memfd
- * @start: The offset into the memfd where the segment starts
- * @size: The size of the memfd segment
- * @fd: The file descriptor number
- * @__pad: Padding to ensure proper alignment and size
- *
- * Attached to:
- * KDBUS_ITEM_PAYLOAD_MEMFD
- */
-struct kdbus_memfd {
- __u64 start;
- __u64 size;
- int fd;
- __u32 __pad;
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_name - a registered well-known name with its flags
- * @flags: Flags from KDBUS_NAME_*
- * @name: Well-known name
- *
- * Attached to:
- * KDBUS_ITEM_OWNED_NAME
- */
-struct kdbus_name {
- __u64 flags;
- char name[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_policy_access_type - permissions of a policy record
- * @_KDBUS_POLICY_ACCESS_NULL: Uninitialized/invalid
- * @KDBUS_POLICY_ACCESS_USER: Grant access to a uid
- * @KDBUS_POLICY_ACCESS_GROUP: Grant access to gid
- * @KDBUS_POLICY_ACCESS_WORLD: World-accessible
- */
-enum kdbus_policy_access_type {
- _KDBUS_POLICY_ACCESS_NULL,
- KDBUS_POLICY_ACCESS_USER,
- KDBUS_POLICY_ACCESS_GROUP,
- KDBUS_POLICY_ACCESS_WORLD,
-};
-
-/**
- * enum kdbus_policy_access_flags - mode flags
- * @KDBUS_POLICY_OWN: Allow to own a well-known name
- * Implies KDBUS_POLICY_TALK and KDBUS_POLICY_SEE
- * @KDBUS_POLICY_TALK: Allow communication to a well-known name
- * Implies KDBUS_POLICY_SEE
- * @KDBUS_POLICY_SEE: Allow to see a well-known name
- */
-enum kdbus_policy_type {
- KDBUS_POLICY_SEE = 0,
- KDBUS_POLICY_TALK,
- KDBUS_POLICY_OWN,
-};
-
-/**
- * struct kdbus_policy_access - policy access item
- * @type: One of KDBUS_POLICY_ACCESS_* types
- * @access: Access to grant
- * @id: For KDBUS_POLICY_ACCESS_USER, the uid
- * For KDBUS_POLICY_ACCESS_GROUP, the gid
- */
-struct kdbus_policy_access {
- __u64 type; /* USER, GROUP, WORLD */
- __u64 access; /* OWN, TALK, SEE */
- __u64 id; /* uid, gid, 0 */
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_attach_flags - flags for metadata attachments
- * @KDBUS_ATTACH_TIMESTAMP: Timestamp
- * @KDBUS_ATTACH_CREDS: Credentials
- * @KDBUS_ATTACH_PIDS: PIDs
- * @KDBUS_ATTACH_AUXGROUPS: Auxiliary groups
- * @KDBUS_ATTACH_NAMES: Well-known names
- * @KDBUS_ATTACH_TID_COMM: The "comm" process identifier of the TID
- * @KDBUS_ATTACH_PID_COMM: The "comm" process identifier of the PID
- * @KDBUS_ATTACH_EXE: The path of the executable
- * @KDBUS_ATTACH_CMDLINE: The process command line
- * @KDBUS_ATTACH_CGROUP: The croup membership
- * @KDBUS_ATTACH_CAPS: The process capabilities
- * @KDBUS_ATTACH_SECLABEL: The security label
- * @KDBUS_ATTACH_AUDIT: The audit IDs
- * @KDBUS_ATTACH_CONN_DESCRIPTION: The human-readable connection name
- * @_KDBUS_ATTACH_ALL: All of the above
- * @_KDBUS_ATTACH_ANY: Wildcard match to enable any kind of
- * metatdata.
- */
-enum kdbus_attach_flags {
- KDBUS_ATTACH_TIMESTAMP = 1ULL << 0,
- KDBUS_ATTACH_CREDS = 1ULL << 1,
- KDBUS_ATTACH_PIDS = 1ULL << 2,
- KDBUS_ATTACH_AUXGROUPS = 1ULL << 3,
- KDBUS_ATTACH_NAMES = 1ULL << 4,
- KDBUS_ATTACH_TID_COMM = 1ULL << 5,
- KDBUS_ATTACH_PID_COMM = 1ULL << 6,
- KDBUS_ATTACH_EXE = 1ULL << 7,
- KDBUS_ATTACH_CMDLINE = 1ULL << 8,
- KDBUS_ATTACH_CGROUP = 1ULL << 9,
- KDBUS_ATTACH_CAPS = 1ULL << 10,
- KDBUS_ATTACH_SECLABEL = 1ULL << 11,
- KDBUS_ATTACH_AUDIT = 1ULL << 12,
- KDBUS_ATTACH_CONN_DESCRIPTION = 1ULL << 13,
- _KDBUS_ATTACH_ALL = (1ULL << 14) - 1,
- _KDBUS_ATTACH_ANY = ~0ULL
-};
-
-/**
- * enum kdbus_item_type - item types to chain data in a list
- * @_KDBUS_ITEM_NULL: Uninitialized/invalid
- * @_KDBUS_ITEM_USER_BASE: Start of user items
- * @KDBUS_ITEM_NEGOTIATE: Negotiate supported items
- * @KDBUS_ITEM_PAYLOAD_VEC: Vector to data
- * @KDBUS_ITEM_PAYLOAD_OFF: Data at returned offset to message head
- * @KDBUS_ITEM_PAYLOAD_MEMFD: Data as sealed memfd
- * @KDBUS_ITEM_FDS: Attached file descriptors
- * @KDBUS_ITEM_CANCEL_FD: FD used to cancel a synchronous
- * operation by writing to it from
- * userspace
- * @KDBUS_ITEM_BLOOM_PARAMETER: Bus-wide bloom parameters, used with
- * KDBUS_CMD_BUS_MAKE, carries a
- * struct kdbus_bloom_parameter
- * @KDBUS_ITEM_BLOOM_FILTER: Bloom filter carried with a message,
- * used to match against a bloom mask of a
- * connection, carries a struct
- * kdbus_bloom_filter
- * @KDBUS_ITEM_BLOOM_MASK: Bloom mask used to match against a
- * message'sbloom filter
- * @KDBUS_ITEM_DST_NAME: Destination's well-known name
- * @KDBUS_ITEM_MAKE_NAME: Name of domain, bus, endpoint
- * @KDBUS_ITEM_ATTACH_FLAGS_SEND: Attach-flags, used for updating which
- * metadata a connection opts in to send
- * @KDBUS_ITEM_ATTACH_FLAGS_RECV: Attach-flags, used for updating which
- * metadata a connection requests to
- * receive for each reeceived message
- * @KDBUS_ITEM_ID: Connection ID
- * @KDBUS_ITEM_NAME: Well-know name with flags
- * @_KDBUS_ITEM_ATTACH_BASE: Start of metadata attach items
- * @KDBUS_ITEM_TIMESTAMP: Timestamp
- * @KDBUS_ITEM_CREDS: Process credentials
- * @KDBUS_ITEM_PIDS: Process identifiers
- * @KDBUS_ITEM_AUXGROUPS: Auxiliary process groups
- * @KDBUS_ITEM_OWNED_NAME: A name owned by the associated
- * connection
- * @KDBUS_ITEM_TID_COMM: Thread ID "comm" identifier
- * (Don't trust this, see below.)
- * @KDBUS_ITEM_PID_COMM: Process ID "comm" identifier
- * (Don't trust this, see below.)
- * @KDBUS_ITEM_EXE: The path of the executable
- * (Don't trust this, see below.)
- * @KDBUS_ITEM_CMDLINE: The process command line
- * (Don't trust this, see below.)
- * @KDBUS_ITEM_CGROUP: The croup membership
- * @KDBUS_ITEM_CAPS: The process capabilities
- * @KDBUS_ITEM_SECLABEL: The security label
- * @KDBUS_ITEM_AUDIT: The audit IDs
- * @KDBUS_ITEM_CONN_DESCRIPTION: The connection's human-readable name
- * (debugging)
- * @_KDBUS_ITEM_POLICY_BASE: Start of policy items
- * @KDBUS_ITEM_POLICY_ACCESS: Policy access block
- * @_KDBUS_ITEM_KERNEL_BASE: Start of kernel-generated message items
- * @KDBUS_ITEM_NAME_ADD: Notification in kdbus_notify_name_change
- * @KDBUS_ITEM_NAME_REMOVE: Notification in kdbus_notify_name_change
- * @KDBUS_ITEM_NAME_CHANGE: Notification in kdbus_notify_name_change
- * @KDBUS_ITEM_ID_ADD: Notification in kdbus_notify_id_change
- * @KDBUS_ITEM_ID_REMOVE: Notification in kdbus_notify_id_change
- * @KDBUS_ITEM_REPLY_TIMEOUT: Timeout has been reached
- * @KDBUS_ITEM_REPLY_DEAD: Destination died
- *
- * N.B: The process and thread COMM fields, as well as the CMDLINE and
- * EXE fields may be altered by unprivileged processes und should
- * hence *not* used for security decisions. Peers should make use of
- * these items only for informational purposes, such as generating log
- * records.
- */
-enum kdbus_item_type {
- _KDBUS_ITEM_NULL,
- _KDBUS_ITEM_USER_BASE,
- KDBUS_ITEM_NEGOTIATE = _KDBUS_ITEM_USER_BASE,
- KDBUS_ITEM_PAYLOAD_VEC,
- KDBUS_ITEM_PAYLOAD_OFF,
- KDBUS_ITEM_PAYLOAD_MEMFD,
- KDBUS_ITEM_FDS,
- KDBUS_ITEM_CANCEL_FD,
- KDBUS_ITEM_BLOOM_PARAMETER,
- KDBUS_ITEM_BLOOM_FILTER,
- KDBUS_ITEM_BLOOM_MASK,
- KDBUS_ITEM_DST_NAME,
- KDBUS_ITEM_MAKE_NAME,
- KDBUS_ITEM_ATTACH_FLAGS_SEND,
- KDBUS_ITEM_ATTACH_FLAGS_RECV,
- KDBUS_ITEM_ID,
- KDBUS_ITEM_NAME,
- KDBUS_ITEM_DST_ID,
-
- /* keep these item types in sync with KDBUS_ATTACH_* flags */
- _KDBUS_ITEM_ATTACH_BASE = 0x1000,
- KDBUS_ITEM_TIMESTAMP = _KDBUS_ITEM_ATTACH_BASE,
- KDBUS_ITEM_CREDS,
- KDBUS_ITEM_PIDS,
- KDBUS_ITEM_AUXGROUPS,
- KDBUS_ITEM_OWNED_NAME,
- KDBUS_ITEM_TID_COMM,
- KDBUS_ITEM_PID_COMM,
- KDBUS_ITEM_EXE,
- KDBUS_ITEM_CMDLINE,
- KDBUS_ITEM_CGROUP,
- KDBUS_ITEM_CAPS,
- KDBUS_ITEM_SECLABEL,
- KDBUS_ITEM_AUDIT,
- KDBUS_ITEM_CONN_DESCRIPTION,
-
- _KDBUS_ITEM_POLICY_BASE = 0x2000,
- KDBUS_ITEM_POLICY_ACCESS = _KDBUS_ITEM_POLICY_BASE,
-
- _KDBUS_ITEM_KERNEL_BASE = 0x8000,
- KDBUS_ITEM_NAME_ADD = _KDBUS_ITEM_KERNEL_BASE,
- KDBUS_ITEM_NAME_REMOVE,
- KDBUS_ITEM_NAME_CHANGE,
- KDBUS_ITEM_ID_ADD,
- KDBUS_ITEM_ID_REMOVE,
- KDBUS_ITEM_REPLY_TIMEOUT,
- KDBUS_ITEM_REPLY_DEAD,
-};
-
-/**
- * struct kdbus_item - chain of data blocks
- * @size: Overall data record size
- * @type: Kdbus_item type of data
- * @data: Generic bytes
- * @data32: Generic 32 bit array
- * @data64: Generic 64 bit array
- * @str: Generic string
- * @id: Connection ID
- * @vec: KDBUS_ITEM_PAYLOAD_VEC
- * @creds: KDBUS_ITEM_CREDS
- * @audit: KDBUS_ITEM_AUDIT
- * @timestamp: KDBUS_ITEM_TIMESTAMP
- * @name: KDBUS_ITEM_NAME
- * @bloom_parameter: KDBUS_ITEM_BLOOM_PARAMETER
- * @bloom_filter: KDBUS_ITEM_BLOOM_FILTER
- * @memfd: KDBUS_ITEM_PAYLOAD_MEMFD
- * @name_change: KDBUS_ITEM_NAME_ADD
- * KDBUS_ITEM_NAME_REMOVE
- * KDBUS_ITEM_NAME_CHANGE
- * @id_change: KDBUS_ITEM_ID_ADD
- * KDBUS_ITEM_ID_REMOVE
- * @policy: KDBUS_ITEM_POLICY_ACCESS
- */
-struct kdbus_item {
- __u64 size;
- __u64 type;
- union {
- __u8 data[0];
- __u32 data32[0];
- __u64 data64[0];
- char str[0];
-
- __u64 id;
- struct kdbus_vec vec;
- struct kdbus_creds creds;
- struct kdbus_pids pids;
- struct kdbus_audit audit;
- struct kdbus_caps caps;
- struct kdbus_timestamp timestamp;
- struct kdbus_name name;
- struct kdbus_bloom_parameter bloom_parameter;
- struct kdbus_bloom_filter bloom_filter;
- struct kdbus_memfd memfd;
- int fds[0];
- struct kdbus_notify_name_change name_change;
- struct kdbus_notify_id_change id_change;
- struct kdbus_policy_access policy_access;
- };
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_msg_flags - type of message
- * @KDBUS_MSG_EXPECT_REPLY: Expect a reply message, used for
- * method calls. The userspace-supplied
- * cookie identifies the message and the
- * respective reply carries the cookie
- * in cookie_reply
- * @KDBUS_MSG_NO_AUTO_START: Do not start a service if the addressed
- * name is not currently active. This flag is
- * not looked at by the kernel but only
- * serves as hint for userspace implementations.
- * @KDBUS_MSG_SIGNAL: Treat this message as signal
- */
-enum kdbus_msg_flags {
- KDBUS_MSG_EXPECT_REPLY = 1ULL << 0,
- KDBUS_MSG_NO_AUTO_START = 1ULL << 1,
- KDBUS_MSG_SIGNAL = 1ULL << 2,
-};
-
-/**
- * enum kdbus_payload_type - type of payload carried by message
- * @KDBUS_PAYLOAD_KERNEL: Kernel-generated simple message
- * @KDBUS_PAYLOAD_DBUS: D-Bus marshalling "DBusDBus"
- *
- * Any payload-type is accepted. Common types will get added here once
- * established.
- */
-enum kdbus_payload_type {
- KDBUS_PAYLOAD_KERNEL,
- KDBUS_PAYLOAD_DBUS = 0x4442757344427573ULL,
-};
-
-/**
- * struct kdbus_msg - the representation of a kdbus message
- * @size: Total size of the message
- * @flags: Message flags (KDBUS_MSG_*), userspace → kernel
- * @priority: Message queue priority value
- * @dst_id: 64-bit ID of the destination connection
- * @src_id: 64-bit ID of the source connection
- * @payload_type: Payload type (KDBUS_PAYLOAD_*)
- * @cookie: Userspace-supplied cookie, for the connection
- * to identify its messages
- * @timeout_ns: The time to wait for a message reply from the peer.
- * If there is no reply, and the send command is
- * executed asynchronously, a kernel-generated message
- * with an attached KDBUS_ITEM_REPLY_TIMEOUT item
- * is sent to @src_id. For synchronously executed send
- * command, the value denotes the maximum time the call
- * blocks to wait for a reply. The timeout is expected in
- * nanoseconds and as absolute CLOCK_MONOTONIC value.
- * @cookie_reply: A reply to the requesting message with the same
- * cookie. The requesting connection can match its
- * request and the reply with this value
- * @items: A list of kdbus_items containing the message payload
- */
-struct kdbus_msg {
- __u64 size;
- __u64 flags;
- __s64 priority;
- __u64 dst_id;
- __u64 src_id;
- __u64 payload_type;
- __u64 cookie;
- union {
- __u64 timeout_ns;
- __u64 cookie_reply;
- };
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_msg_info - returned message container
- * @offset: Offset of kdbus_msg slice in pool
- * @msg_size: Copy of the kdbus_msg.size field
- * @return_flags: Command return flags, kernel → userspace
- */
-struct kdbus_msg_info {
- __u64 offset;
- __u64 msg_size;
- __u64 return_flags;
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_send_flags - flags for sending messages
- * @KDBUS_SEND_SYNC_REPLY: Wait for destination connection to
- * reply to this message. The
- * KDBUS_CMD_SEND ioctl() will block
- * until the reply is received, and
- * reply in struct kdbus_cmd_send will
- * yield the offset in the sender's pool
- * where the reply can be found.
- * This flag is only valid if
- * @KDBUS_MSG_EXPECT_REPLY is set as well.
- */
-enum kdbus_send_flags {
- KDBUS_SEND_SYNC_REPLY = 1ULL << 0,
-};
-
-/**
- * struct kdbus_cmd_send - send message
- * @size: Overall size of this structure
- * @flags: Flags to change send behavior (KDBUS_SEND_*)
- * @return_flags: Command return flags, kernel → userspace
- * @msg_address: Storage address of the kdbus_msg to send
- * @reply: Storage for message reply if KDBUS_SEND_SYNC_REPLY
- * was given
- * @items: Additional items for this command
- */
-struct kdbus_cmd_send {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __u64 msg_address;
- struct kdbus_msg_info reply;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_recv_flags - flags for de-queuing messages
- * @KDBUS_RECV_PEEK: Return the next queued message without
- * actually de-queuing it, and without installing
- * any file descriptors or other resources. It is
- * usually used to determine the activating
- * connection of a bus name.
- * @KDBUS_RECV_DROP: Drop and free the next queued message and all
- * its resources without actually receiving it.
- * @KDBUS_RECV_USE_PRIORITY: Only de-queue messages with the specified or
- * higher priority (lowest values); if not set,
- * the priority value is ignored.
- */
-enum kdbus_recv_flags {
- KDBUS_RECV_PEEK = 1ULL << 0,
- KDBUS_RECV_DROP = 1ULL << 1,
- KDBUS_RECV_USE_PRIORITY = 1ULL << 2,
-};
-
-/**
- * enum kdbus_recv_return_flags - return flags for message receive commands
- * @KDBUS_RECV_RETURN_INCOMPLETE_FDS: One or more file descriptors could not
- * be installed. These descriptors in
- * KDBUS_ITEM_FDS will carry the value -1.
- * @KDBUS_RECV_RETURN_DROPPED_MSGS: There have been dropped messages since
- * the last time a message was received.
- * The 'dropped_msgs' counter contains the
- * number of messages dropped pool
- * overflows or other missed broadcasts.
- */
-enum kdbus_recv_return_flags {
- KDBUS_RECV_RETURN_INCOMPLETE_FDS = 1ULL << 0,
- KDBUS_RECV_RETURN_DROPPED_MSGS = 1ULL << 1,
-};
-
-/**
- * struct kdbus_cmd_recv - struct to de-queue a buffered message
- * @size: Overall size of this object
- * @flags: KDBUS_RECV_* flags, userspace → kernel
- * @return_flags: Command return flags, kernel → userspace
- * @priority: Minimum priority of the messages to de-queue. Lowest
- * values have the highest priority.
- * @dropped_msgs: In case there were any dropped messages since the last
- * time a message was received, this will be set to the
- * number of lost messages and
- * KDBUS_RECV_RETURN_DROPPED_MSGS will be set in
- * 'return_flags'. This can only happen if the ioctl
- * returns 0 or EAGAIN.
- * @msg: Return storage for received message.
- * @items: Additional items for this command.
- *
- * This struct is used with the KDBUS_CMD_RECV ioctl.
- */
-struct kdbus_cmd_recv {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __s64 priority;
- __u64 dropped_msgs;
- struct kdbus_msg_info msg;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_cmd_free - struct to free a slice of memory in the pool
- * @size: Overall size of this structure
- * @flags: Flags for the free command, userspace → kernel
- * @return_flags: Command return flags, kernel → userspace
- * @offset: The offset of the memory slice, as returned by other
- * ioctls
- * @items: Additional items to modify the behavior
- *
- * This struct is used with the KDBUS_CMD_FREE ioctl.
- */
-struct kdbus_cmd_free {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __u64 offset;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_hello_flags - flags for struct kdbus_cmd_hello
- * @KDBUS_HELLO_ACCEPT_FD: The connection allows the reception of
- * any passed file descriptors
- * @KDBUS_HELLO_ACTIVATOR: Special-purpose connection which registers
- * a well-know name for a process to be started
- * when traffic arrives
- * @KDBUS_HELLO_POLICY_HOLDER: Special-purpose connection which registers
- * policy entries for a name. The provided name
- * is not activated and not registered with the
- * name database, it only allows unprivileged
- * connections to acquire a name, talk or discover
- * a service
- * @KDBUS_HELLO_MONITOR: Special-purpose connection to monitor
- * bus traffic
- */
-enum kdbus_hello_flags {
- KDBUS_HELLO_ACCEPT_FD = 1ULL << 0,
- KDBUS_HELLO_ACTIVATOR = 1ULL << 1,
- KDBUS_HELLO_POLICY_HOLDER = 1ULL << 2,
- KDBUS_HELLO_MONITOR = 1ULL << 3,
-};
-
-/**
- * struct kdbus_cmd_hello - struct to say hello to kdbus
- * @size: The total size of the structure
- * @flags: Connection flags (KDBUS_HELLO_*), userspace → kernel
- * @return_flags: Command return flags, kernel → userspace
- * @attach_flags_send: Mask of metadata to attach to each message sent
- * off by this connection (KDBUS_ATTACH_*)
- * @attach_flags_recv: Mask of metadata to attach to each message receieved
- * by the new connection (KDBUS_ATTACH_*)
- * @bus_flags: The flags field copied verbatim from the original
- * KDBUS_CMD_BUS_MAKE ioctl. It's intended to be useful
- * to do negotiation of features of the payload that is
- * transferred (kernel → userspace)
- * @id: The ID of this connection (kernel → userspace)
- * @pool_size: Size of the connection's buffer where the received
- * messages are placed
- * @offset: Pool offset where items are returned to report
- * additional information about the bus and the newly
- * created connection.
- * @items_size: Size of buffer returned in the pool slice at @offset.
- * @id128: Unique 128-bit ID of the bus (kernel → userspace)
- * @items: A list of items
- *
- * This struct is used with the KDBUS_CMD_HELLO ioctl.
- */
-struct kdbus_cmd_hello {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __u64 attach_flags_send;
- __u64 attach_flags_recv;
- __u64 bus_flags;
- __u64 id;
- __u64 pool_size;
- __u64 offset;
- __u64 items_size;
- __u8 id128[16];
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_info - connection information
- * @size: total size of the struct
- * @id: 64bit object ID
- * @flags: object creation flags
- * @items: list of items
- *
- * Note that the user is responsible for freeing the allocated memory with
- * the KDBUS_CMD_FREE ioctl.
- */
-struct kdbus_info {
- __u64 size;
- __u64 id;
- __u64 flags;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_list_flags - what to include into the returned list
- * @KDBUS_LIST_UNIQUE: active connections
- * @KDBUS_LIST_ACTIVATORS: activator connections
- * @KDBUS_LIST_NAMES: known well-known names
- * @KDBUS_LIST_QUEUED: queued-up names
- */
-enum kdbus_list_flags {
- KDBUS_LIST_UNIQUE = 1ULL << 0,
- KDBUS_LIST_NAMES = 1ULL << 1,
- KDBUS_LIST_ACTIVATORS = 1ULL << 2,
- KDBUS_LIST_QUEUED = 1ULL << 3,
-};
-
-/**
- * struct kdbus_cmd_list - list connections
- * @size: overall size of this object
- * @flags: flags for the query (KDBUS_LIST_*), userspace → kernel
- * @return_flags: command return flags, kernel → userspace
- * @offset: Offset in the caller's pool buffer where an array of
- * kdbus_info objects is stored.
- * The user must use KDBUS_CMD_FREE to free the
- * allocated memory.
- * @list_size: size of returned list in bytes
- * @items: Items for the command. Reserved for future use.
- *
- * This structure is used with the KDBUS_CMD_LIST ioctl.
- */
-struct kdbus_cmd_list {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __u64 offset;
- __u64 list_size;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_cmd_info - struct used for KDBUS_CMD_CONN_INFO ioctl
- * @size: The total size of the struct
- * @flags: Flags for this ioctl, userspace → kernel
- * @return_flags: Command return flags, kernel → userspace
- * @id: The 64-bit ID of the connection. If set to zero, passing
- * @name is required. kdbus will look up the name to
- * determine the ID in this case.
- * @attach_flags: Set of attach flags to specify the set of information
- * to receive, userspace → kernel
- * @offset: Returned offset in the caller's pool buffer where the
- * kdbus_info struct result is stored. The user must
- * use KDBUS_CMD_FREE to free the allocated memory.
- * @info_size: Output buffer to report size of data at @offset.
- * @items: The optional item list, containing the
- * well-known name to look up as a KDBUS_ITEM_NAME.
- * Only needed in case @id is zero.
- *
- * On success, the KDBUS_CMD_CONN_INFO ioctl will return 0 and @offset will
- * tell the user the offset in the connection pool buffer at which to find the
- * result in a struct kdbus_info.
- */
-struct kdbus_cmd_info {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __u64 id;
- __u64 attach_flags;
- __u64 offset;
- __u64 info_size;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_cmd_match_flags - flags to control the KDBUS_CMD_MATCH_ADD ioctl
- * @KDBUS_MATCH_REPLACE: If entries with the supplied cookie already
- * exists, remove them before installing the new
- * matches.
- */
-enum kdbus_cmd_match_flags {
- KDBUS_MATCH_REPLACE = 1ULL << 0,
-};
-
-/**
- * struct kdbus_cmd_match - struct to add or remove matches
- * @size: The total size of the struct
- * @flags: Flags for match command (KDBUS_MATCH_*),
- * userspace → kernel
- * @return_flags: Command return flags, kernel → userspace
- * @cookie: Userspace supplied cookie. When removing, the cookie
- * identifies the match to remove
- * @items: A list of items for additional information
- *
- * This structure is used with the KDBUS_CMD_MATCH_ADD and
- * KDBUS_CMD_MATCH_REMOVE ioctl.
- */
-struct kdbus_cmd_match {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __u64 cookie;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_make_flags - Flags for KDBUS_CMD_{BUS,ENDPOINT}_MAKE
- * @KDBUS_MAKE_ACCESS_GROUP: Make the bus or endpoint node group-accessible
- * @KDBUS_MAKE_ACCESS_WORLD: Make the bus or endpoint node world-accessible
- */
-enum kdbus_make_flags {
- KDBUS_MAKE_ACCESS_GROUP = 1ULL << 0,
- KDBUS_MAKE_ACCESS_WORLD = 1ULL << 1,
-};
-
-/**
- * enum kdbus_name_flags - flags for KDBUS_CMD_NAME_ACQUIRE
- * @KDBUS_NAME_REPLACE_EXISTING: Try to replace name of other connections
- * @KDBUS_NAME_ALLOW_REPLACEMENT: Allow the replacement of the name
- * @KDBUS_NAME_QUEUE: Name should be queued if busy
- * @KDBUS_NAME_IN_QUEUE: Name is queued
- * @KDBUS_NAME_ACTIVATOR: Name is owned by a activator connection
- */
-enum kdbus_name_flags {
- KDBUS_NAME_REPLACE_EXISTING = 1ULL << 0,
- KDBUS_NAME_ALLOW_REPLACEMENT = 1ULL << 1,
- KDBUS_NAME_QUEUE = 1ULL << 2,
- KDBUS_NAME_IN_QUEUE = 1ULL << 3,
- KDBUS_NAME_ACTIVATOR = 1ULL << 4,
-};
-
-/**
- * struct kdbus_cmd - generic ioctl payload
- * @size: Overall size of this structure
- * @flags: Flags for this ioctl, userspace → kernel
- * @return_flags: Ioctl return flags, kernel → userspace
- * @items: Additional items to modify the behavior
- *
- * This is a generic ioctl payload object. It's used by all ioctls that only
- * take flags and items as input.
- */
-struct kdbus_cmd {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * Ioctl API
- *
- * KDBUS_CMD_BUS_MAKE: After opening the "control" node, this command
- * creates a new bus with the specified
- * name. The bus is immediately shut down and
- * cleaned up when the opened file descriptor is
- * closed.
- *
- * KDBUS_CMD_ENDPOINT_MAKE: Creates a new named special endpoint to talk to
- * the bus. Such endpoints usually carry a more
- * restrictive policy and grant restricted access
- * to specific applications.
- * KDBUS_CMD_ENDPOINT_UPDATE: Update the properties of a custom enpoint. Used
- * to update the policy.
- *
- * KDBUS_CMD_HELLO: By opening the bus node, a connection is
- * created. After a HELLO the opened connection
- * becomes an active peer on the bus.
- * KDBUS_CMD_UPDATE: Update the properties of a connection. Used to
- * update the metadata subscription mask and
- * policy.
- * KDBUS_CMD_BYEBYE: Disconnect a connection. If there are no
- * messages queued up in the connection's pool,
- * the call succeeds, and the handle is rendered
- * unusable. Otherwise, -EBUSY is returned without
- * any further side-effects.
- * KDBUS_CMD_FREE: Release the allocated memory in the receiver's
- * pool.
- * KDBUS_CMD_CONN_INFO: Retrieve credentials and properties of the
- * initial creator of the connection. The data was
- * stored at registration time and does not
- * necessarily represent the connected process or
- * the actual state of the process.
- * KDBUS_CMD_BUS_CREATOR_INFO: Retrieve information of the creator of the bus
- * a connection is attached to.
- *
- * KDBUS_CMD_SEND: Send a message and pass data from userspace to
- * the kernel.
- * KDBUS_CMD_RECV: Receive a message from the kernel which is
- * placed in the receiver's pool.
- *
- * KDBUS_CMD_NAME_ACQUIRE: Request a well-known bus name to associate with
- * the connection. Well-known names are used to
- * address a peer on the bus.
- * KDBUS_CMD_NAME_RELEASE: Release a well-known name the connection
- * currently owns.
- * KDBUS_CMD_LIST: Retrieve the list of all currently registered
- * well-known and unique names.
- *
- * KDBUS_CMD_MATCH_ADD: Install a match which broadcast messages should
- * be delivered to the connection.
- * KDBUS_CMD_MATCH_REMOVE: Remove a current match for broadcast messages.
- */
-enum kdbus_ioctl_type {
- /* bus owner (00-0f) */
- KDBUS_CMD_BUS_MAKE = _IOW(KDBUS_IOCTL_MAGIC, 0x00,
- struct kdbus_cmd),
-
- /* endpoint owner (10-1f) */
- KDBUS_CMD_ENDPOINT_MAKE = _IOW(KDBUS_IOCTL_MAGIC, 0x10,
- struct kdbus_cmd),
- KDBUS_CMD_ENDPOINT_UPDATE = _IOW(KDBUS_IOCTL_MAGIC, 0x11,
- struct kdbus_cmd),
-
- /* connection owner (80-ff) */
- KDBUS_CMD_HELLO = _IOWR(KDBUS_IOCTL_MAGIC, 0x80,
- struct kdbus_cmd_hello),
- KDBUS_CMD_UPDATE = _IOW(KDBUS_IOCTL_MAGIC, 0x81,
- struct kdbus_cmd),
- KDBUS_CMD_BYEBYE = _IOW(KDBUS_IOCTL_MAGIC, 0x82,
- struct kdbus_cmd),
- KDBUS_CMD_FREE = _IOW(KDBUS_IOCTL_MAGIC, 0x83,
- struct kdbus_cmd_free),
- KDBUS_CMD_CONN_INFO = _IOR(KDBUS_IOCTL_MAGIC, 0x84,
- struct kdbus_cmd_info),
- KDBUS_CMD_BUS_CREATOR_INFO = _IOR(KDBUS_IOCTL_MAGIC, 0x85,
- struct kdbus_cmd_info),
- KDBUS_CMD_LIST = _IOR(KDBUS_IOCTL_MAGIC, 0x86,
- struct kdbus_cmd_list),
-
- KDBUS_CMD_SEND = _IOW(KDBUS_IOCTL_MAGIC, 0x90,
- struct kdbus_cmd_send),
- KDBUS_CMD_RECV = _IOR(KDBUS_IOCTL_MAGIC, 0x91,
- struct kdbus_cmd_recv),
-
- KDBUS_CMD_NAME_ACQUIRE = _IOW(KDBUS_IOCTL_MAGIC, 0xa0,
- struct kdbus_cmd),
- KDBUS_CMD_NAME_RELEASE = _IOW(KDBUS_IOCTL_MAGIC, 0xa1,
- struct kdbus_cmd),
-
- KDBUS_CMD_MATCH_ADD = _IOW(KDBUS_IOCTL_MAGIC, 0xb0,
- struct kdbus_cmd_match),
- KDBUS_CMD_MATCH_REMOVE = _IOW(KDBUS_IOCTL_MAGIC, 0xb1,
- struct kdbus_cmd_match),
-};
-
-#endif /* _UAPI_KDBUS_H_ */
diff --git a/src/libelogind/sd-bus/sd-bus.c b/src/libelogind/sd-bus/sd-bus.c
index fda12a384..2a490405e 100644
--- a/src/libelogind/sd-bus/sd-bus.c
+++ b/src/libelogind/sd-bus/sd-bus.c
@@ -1,28 +1,15 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <endian.h>
#include <netdb.h>
#include <poll.h>
#include <pthread.h>
+//#include <signal.h>
#include <stdlib.h>
#include <sys/mman.h>
+//#include <sys/wait.h>
#include <unistd.h>
#include "sd-bus.h"
@@ -49,14 +36,18 @@
#include "macro.h"
#include "missing.h"
#include "parse-util.h"
+//#include "process-util.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
+/// Additional includes needed by elogind
+#include "process-util.h"
+
#define log_debug_bus_message(m) \
do { \
sd_bus_message *_mm = (m); \
- log_debug("Got message type=%s sender=%s destination=%s object=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " error=%s", \
+ log_debug("Got message type=%s sender=%s destination=%s path=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " signature=%s error-name=%s error-message=%s", \
bus_message_type_to_string(_mm->header->type), \
strna(sd_bus_message_get_sender(_mm)), \
strna(sd_bus_message_get_destination(_mm)), \
@@ -65,29 +56,97 @@
strna(sd_bus_message_get_member(_mm)), \
BUS_MESSAGE_COOKIE(_mm), \
_mm->reply_cookie, \
+ strna(_mm->root_container.signature), \
+ strna(_mm->error.name), \
strna(_mm->error.message)); \
} while (false)
static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec);
-static int attach_io_events(sd_bus *b);
-static void detach_io_events(sd_bus *b);
+static void bus_detach_io_events(sd_bus *b);
+static void bus_detach_inotify_event(sd_bus *b);
static thread_local sd_bus *default_system_bus = NULL;
-#if 0 /// UNNEEDED by elogind
static thread_local sd_bus *default_user_bus = NULL;
-#endif // 0
static thread_local sd_bus *default_starter_bus = NULL;
-static void bus_close_fds(sd_bus *b) {
+static sd_bus **bus_choose_default(int (**bus_open)(sd_bus **)) {
+ const char *e;
+
+ /* Let's try our best to reuse another cached connection. If
+ * the starter bus type is set, connect via our normal
+ * connection logic, ignoring $DBUS_STARTER_ADDRESS, so that
+ * we can share the connection with the user/system default
+ * bus. */
+
+ e = secure_getenv("DBUS_STARTER_BUS_TYPE");
+ if (e) {
+ if (streq(e, "system")) {
+ if (bus_open)
+ *bus_open = sd_bus_open_system;
+ return &default_system_bus;
+ } else if (STR_IN_SET(e, "user", "session")) {
+ if (bus_open)
+ *bus_open = sd_bus_open_user;
+ return &default_user_bus;
+ }
+ }
+
+ /* No type is specified, so we have not other option than to
+ * use the starter address if it is set. */
+ e = secure_getenv("DBUS_STARTER_ADDRESS");
+ if (e) {
+ if (bus_open)
+ *bus_open = sd_bus_open;
+ return &default_starter_bus;
+ }
+
+ /* Finally, if nothing is set use the cached connection for
+ * the right scope */
+
+ if (cg_pid_get_owner_uid(0, NULL) >= 0) {
+ if (bus_open)
+ *bus_open = sd_bus_open_user;
+ return &default_user_bus;
+ } else {
+ if (bus_open)
+ *bus_open = sd_bus_open_system;
+ return &default_system_bus;
+ }
+}
+
+sd_bus *bus_resolve(sd_bus *bus) {
+ switch ((uintptr_t) bus) {
+ case (uintptr_t) SD_BUS_DEFAULT:
+ return *(bus_choose_default(NULL));
+ case (uintptr_t) SD_BUS_DEFAULT_USER:
+ return default_user_bus;
+ case (uintptr_t) SD_BUS_DEFAULT_SYSTEM:
+ return default_system_bus;
+ default:
+ return bus;
+ }
+}
+
+void bus_close_io_fds(sd_bus *b) {
assert(b);
- detach_io_events(b);
+ bus_detach_io_events(b);
if (b->input_fd != b->output_fd)
safe_close(b->output_fd);
b->output_fd = b->input_fd = safe_close(b->input_fd);
}
+void bus_close_inotify_fd(sd_bus *b) {
+ assert(b);
+
+ bus_detach_inotify_event(b);
+
+ b->inotify_fd = safe_close(b->inotify_fd);
+ b->inotify_watches = mfree(b->inotify_watches);
+ b->n_inotify_watches = 0;
+}
+
static void bus_reset_queues(sd_bus *b) {
assert(b);
@@ -104,7 +163,7 @@ static void bus_reset_queues(sd_bus *b) {
b->wqueue_allocated = 0;
}
-static void bus_free(sd_bus *b) {
+static sd_bus* bus_free(sd_bus *b) {
sd_bus_slot *s;
assert(b);
@@ -131,21 +190,19 @@ static void bus_free(sd_bus *b) {
if (b->default_bus_ptr)
*b->default_bus_ptr = NULL;
- bus_close_fds(b);
-
- if (b->kdbus_buffer)
- munmap(b->kdbus_buffer, KDBUS_POOL_SIZE);
+ bus_close_io_fds(b);
+ bus_close_inotify_fd(b);
free(b->label);
+ free(b->groups);
free(b->rbuffer);
free(b->unique_name);
free(b->auth_buffer);
free(b->address);
- free(b->kernel);
free(b->machine);
- free(b->fake_label);
free(b->cgroup_root);
free(b->description);
+ free(b->patch_sender);
free(b->exec_path);
strv_free(b->exec_argv);
@@ -167,63 +224,56 @@ static void bus_free(sd_bus *b) {
assert(hashmap_isempty(b->nodes));
hashmap_free(b->nodes);
- bus_kernel_flush_memfd(b);
+ bus_flush_memfd(b);
assert_se(pthread_mutex_destroy(&b->memfd_cache_mutex) == 0);
- free(b);
+ return mfree(b);
}
+DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus*, bus_free);
+
_public_ int sd_bus_new(sd_bus **ret) {
- sd_bus *r;
+ _cleanup_free_ sd_bus *b = NULL;
assert_return(ret, -EINVAL);
- r = new0(sd_bus, 1);
- if (!r)
+ b = new0(sd_bus, 1);
+ if (!b)
return -ENOMEM;
- r->n_ref = REFCNT_INIT;
- r->input_fd = r->output_fd = -1;
- r->message_version = 1;
- r->creds_mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME;
- r->hello_flags |= KDBUS_HELLO_ACCEPT_FD;
- r->attach_flags |= KDBUS_ATTACH_NAMES;
- r->original_pid = getpid();
+ b->n_ref = REFCNT_INIT;
+ b->input_fd = b->output_fd = -1;
+ b->inotify_fd = -1;
+ b->message_version = 1;
+ b->creds_mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME;
+ b->accept_fd = true;
+ b->original_pid = getpid_cached();
+ b->n_groups = (size_t) -1;
- assert_se(pthread_mutex_init(&r->memfd_cache_mutex, NULL) == 0);
+ assert_se(pthread_mutex_init(&b->memfd_cache_mutex, NULL) == 0);
- /* We guarantee that wqueue always has space for at least one
- * entry */
- if (!GREEDY_REALLOC(r->wqueue, r->wqueue_allocated, 1)) {
- free(r);
+ /* We guarantee that wqueue always has space for at least one entry */
+ if (!GREEDY_REALLOC(b->wqueue, b->wqueue_allocated, 1))
return -ENOMEM;
- }
- *ret = r;
+ *ret = TAKE_PTR(b);
return 0;
}
_public_ int sd_bus_set_address(sd_bus *bus, const char *address) {
- char *a;
-
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(bus->state == BUS_UNSET, -EPERM);
assert_return(address, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
- a = strdup(address);
- if (!a)
- return -ENOMEM;
-
- free(bus->address);
- bus->address = a;
-
- return 0;
+ return free_and_strdup(&bus->address, address);
}
_public_ int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd) {
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(bus->state == BUS_UNSET, -EPERM);
assert_return(input_fd >= 0, -EBADF);
assert_return(output_fd >= 0, -EBADF);
@@ -235,36 +285,32 @@ _public_ int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd) {
}
_public_ int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[]) {
- char *p, **a;
+ _cleanup_strv_free_ char **a = NULL;
+ int r;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(bus->state == BUS_UNSET, -EPERM);
assert_return(path, -EINVAL);
assert_return(!strv_isempty(argv), -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
- p = strdup(path);
- if (!p)
- return -ENOMEM;
-
a = strv_copy(argv);
- if (!a) {
- free(p);
+ if (!a)
return -ENOMEM;
- }
-
- free(bus->exec_path);
- strv_free(bus->exec_argv);
- bus->exec_path = p;
- bus->exec_argv = a;
+ r = free_and_strdup(&bus->exec_path, path);
+ if (r < 0)
+ return r;
- return 0;
+ return strv_free_and_replace(bus->exec_argv, a);
}
_public_ int sd_bus_set_bus_client(sd_bus *bus, int b) {
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(bus->state == BUS_UNSET, -EPERM);
+ assert_return(!bus->patch_sender, -EPERM);
assert_return(!bus_pid_changed(bus), -ECHILD);
bus->bus_client = !!b;
@@ -273,45 +319,40 @@ _public_ int sd_bus_set_bus_client(sd_bus *bus, int b) {
_public_ int sd_bus_set_monitor(sd_bus *bus, int b) {
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(bus->state == BUS_UNSET, -EPERM);
assert_return(!bus_pid_changed(bus), -ECHILD);
- SET_FLAG(bus->hello_flags, KDBUS_HELLO_MONITOR, b);
+ bus->is_monitor = !!b;
return 0;
}
_public_ int sd_bus_negotiate_fds(sd_bus *bus, int b) {
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(bus->state == BUS_UNSET, -EPERM);
assert_return(!bus_pid_changed(bus), -ECHILD);
- SET_FLAG(bus->hello_flags, KDBUS_HELLO_ACCEPT_FD, b);
+ bus->accept_fd = !!b;
return 0;
}
_public_ int sd_bus_negotiate_timestamp(sd_bus *bus, int b) {
- uint64_t new_flags;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(!IN_SET(bus->state, BUS_CLOSING, BUS_CLOSED), -EPERM);
assert_return(!bus_pid_changed(bus), -ECHILD);
- new_flags = bus->attach_flags;
- SET_FLAG(new_flags, KDBUS_ATTACH_TIMESTAMP, b);
-
- if (bus->attach_flags == new_flags)
- return 0;
-
- bus->attach_flags = new_flags;
- if (bus->state != BUS_UNSET && bus->is_kernel)
- bus_kernel_realize_attach_flags(bus);
+ /* This is not actually supported by any of our transports these days, but we do honour it for synthetic
+ * replies, and maybe one day classic D-Bus learns this too */
+ bus->attach_timestamp = !!b;
return 0;
}
_public_ int sd_bus_negotiate_creds(sd_bus *bus, int b, uint64_t mask) {
- uint64_t new_flags;
-
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(mask <= _SD_BUS_CREDS_ALL, -EINVAL);
assert_return(!IN_SET(bus->state, BUS_CLOSING, BUS_CLOSED), -EPERM);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -321,20 +362,12 @@ _public_ int sd_bus_negotiate_creds(sd_bus *bus, int b, uint64_t mask) {
/* The well knowns we need unconditionally, so that matches can work */
bus->creds_mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME;
- /* Make sure we don't lose the timestamp flag */
- new_flags = (bus->attach_flags & KDBUS_ATTACH_TIMESTAMP) | attach_flags_to_kdbus(bus->creds_mask);
- if (bus->attach_flags == new_flags)
- return 0;
-
- bus->attach_flags = new_flags;
- if (bus->state != BUS_UNSET && bus->is_kernel)
- bus_kernel_realize_attach_flags(bus);
-
return 0;
}
_public_ int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id) {
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(b || sd_id128_equal(server_id, SD_ID128_NULL), -EINVAL);
assert_return(bus->state == BUS_UNSET, -EPERM);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -346,6 +379,7 @@ _public_ int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id) {
_public_ int sd_bus_set_anonymous(sd_bus *bus, int b) {
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(bus->state == BUS_UNSET, -EPERM);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -355,6 +389,7 @@ _public_ int sd_bus_set_anonymous(sd_bus *bus, int b) {
_public_ int sd_bus_set_trusted(sd_bus *bus, int b) {
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(bus->state == BUS_UNSET, -EPERM);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -364,6 +399,7 @@ _public_ int sd_bus_set_trusted(sd_bus *bus, int b) {
_public_ int sd_bus_set_description(sd_bus *bus, const char *description) {
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(bus->state == BUS_UNSET, -EPERM);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -372,6 +408,7 @@ _public_ int sd_bus_set_description(sd_bus *bus, const char *description) {
_public_ int sd_bus_set_allow_interactive_authorization(sd_bus *bus, int b) {
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(!bus_pid_changed(bus), -ECHILD);
bus->allow_interactive_authorization = !!b;
@@ -380,11 +417,114 @@ _public_ int sd_bus_set_allow_interactive_authorization(sd_bus *bus, int b) {
_public_ int sd_bus_get_allow_interactive_authorization(sd_bus *bus) {
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(!bus_pid_changed(bus), -ECHILD);
return bus->allow_interactive_authorization;
}
+_public_ int sd_bus_set_watch_bind(sd_bus *bus, int b) {
+ assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
+ assert_return(bus->state == BUS_UNSET, -EPERM);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
+
+ bus->watch_bind = !!b;
+ return 0;
+}
+
+_public_ int sd_bus_get_watch_bind(sd_bus *bus) {
+ assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
+
+ return bus->watch_bind;
+}
+
+_public_ int sd_bus_set_connected_signal(sd_bus *bus, int b) {
+ assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
+ assert_return(bus->state == BUS_UNSET, -EPERM);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
+
+ bus->connected_signal = !!b;
+ return 0;
+}
+
+_public_ int sd_bus_get_connected_signal(sd_bus *bus) {
+ assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
+
+ return bus->connected_signal;
+}
+
+static int synthesize_connected_signal(sd_bus *bus) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ int r;
+
+ assert(bus);
+
+ /* If enabled, synthesizes a local "Connected" signal mirroring the local "Disconnected" signal. This is called
+ * whenever we fully established a connection, i.e. after the authorization phase, and after receiving the
+ * Hello() reply. Or in other words, whenver we enter BUS_RUNNING state.
+ *
+ * This is useful so that clients can start doing stuff whenver the connection is fully established in a way
+ * that works independently from whether we connected to a full bus or just a direct connection. */
+
+ if (!bus->connected_signal)
+ return 0;
+
+ r = sd_bus_message_new_signal(
+ bus,
+ &m,
+ "/org/freedesktop/DBus/Local",
+ "org.freedesktop.DBus.Local",
+ "Connected");
+ if (r < 0)
+ return r;
+
+ bus_message_set_sender_local(bus, m);
+
+ r = bus_seal_synthetic_message(bus, m);
+ if (r < 0)
+ return r;
+
+ r = bus_rqueue_make_room(bus);
+ if (r < 0)
+ return r;
+
+ /* Insert at the very front */
+ memmove(bus->rqueue + 1, bus->rqueue, sizeof(sd_bus_message*) * bus->rqueue_size);
+ bus->rqueue[0] = TAKE_PTR(m);
+ bus->rqueue_size++;
+
+ return 0;
+}
+
+void bus_set_state(sd_bus *bus, enum bus_state state) {
+
+ static const char * const table[_BUS_STATE_MAX] = {
+ [BUS_UNSET] = "UNSET",
+ [BUS_WATCH_BIND] = "WATCH_BIND",
+ [BUS_OPENING] = "OPENING",
+ [BUS_AUTHENTICATING] = "AUTHENTICATING",
+ [BUS_HELLO] = "HELLO",
+ [BUS_RUNNING] = "RUNNING",
+ [BUS_CLOSING] = "CLOSING",
+ [BUS_CLOSED] = "CLOSED",
+ };
+
+ assert(bus);
+ assert(state < _BUS_STATE_MAX);
+
+ if (state == bus->state)
+ return;
+
+ log_debug("Bus %s: changing state %s → %s", strna(bus->description), table[bus->state], table[state]);
+ bus->state = state;
+}
+
static int hello_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
const char *s;
sd_bus *bus;
@@ -393,7 +533,7 @@ static int hello_callback(sd_bus_message *reply, void *userdata, sd_bus_error *e
assert(reply);
bus = reply->bus;
assert(bus);
- assert(bus->state == BUS_HELLO || bus->state == BUS_CLOSING);
+ assert(IN_SET(bus->state, BUS_HELLO, BUS_CLOSING));
r = sd_bus_message_get_errno(reply);
if (r > 0)
@@ -406,12 +546,17 @@ static int hello_callback(sd_bus_message *reply, void *userdata, sd_bus_error *e
if (!service_name_is_valid(s) || s[0] != ':')
return -EBADMSG;
- bus->unique_name = strdup(s);
- if (!bus->unique_name)
- return -ENOMEM;
+ r = free_and_strdup(&bus->unique_name, s);
+ if (r < 0)
+ return r;
- if (bus->state == BUS_HELLO)
- bus->state = BUS_RUNNING;
+ if (bus->state == BUS_HELLO) {
+ bus_set_state(bus, BUS_RUNNING);
+
+ r = synthesize_connected_signal(bus);
+ if (r < 0)
+ return r;
+ }
return 1;
}
@@ -422,7 +567,7 @@ static int bus_send_hello(sd_bus *bus) {
assert(bus);
- if (!bus->bus_client || bus->is_kernel)
+ if (!bus->bus_client)
return 0;
r = sd_bus_message_new_method_call(
@@ -439,21 +584,44 @@ static int bus_send_hello(sd_bus *bus) {
}
int bus_start_running(sd_bus *bus) {
+ struct reply_callback *c;
+ Iterator i;
+ usec_t n;
+ int r;
+
assert(bus);
+ assert(bus->state < BUS_HELLO);
- if (bus->bus_client && !bus->is_kernel) {
- bus->state = BUS_HELLO;
+ /* We start all method call timeouts when we enter BUS_HELLO or BUS_RUNNING mode. At this point let's convert
+ * all relative to absolute timestamps. Note that we do not reshuffle the reply callback priority queue since
+ * adding a fixed value to all entries should not alter the internal order. */
+
+ n = now(CLOCK_MONOTONIC);
+ ORDERED_HASHMAP_FOREACH(c, bus->reply_callbacks, i) {
+ if (c->timeout_usec == 0)
+ continue;
+
+ c->timeout_usec = usec_add(n, c->timeout_usec);
+ }
+
+ if (bus->bus_client) {
+ bus_set_state(bus, BUS_HELLO);
return 1;
}
- bus->state = BUS_RUNNING;
+ bus_set_state(bus, BUS_RUNNING);
+
+ r = synthesize_connected_signal(bus);
+ if (r < 0)
+ return r;
+
return 1;
}
static int parse_address_key(const char **p, const char *key, char **value) {
size_t l, n = 0, allocated = 0;
+ _cleanup_free_ char *r = NULL;
const char *a;
- char *r = NULL;
assert(p);
assert(*p);
@@ -474,23 +642,19 @@ static int parse_address_key(const char **p, const char *key, char **value) {
} else
a = *p;
- while (*a != ';' && *a != ',' && *a != 0) {
+ while (!IN_SET(*a, ';', ',', 0)) {
char c;
if (*a == '%') {
int x, y;
x = unhexchar(a[1]);
- if (x < 0) {
- free(r);
+ if (x < 0)
return x;
- }
y = unhexchar(a[2]);
- if (y < 0) {
- free(r);
+ if (y < 0)
return y;
- }
c = (char) ((x << 4) | y);
a += 3;
@@ -517,8 +681,7 @@ static int parse_address_key(const char **p, const char *key, char **value) {
*p = a;
- free(*value);
- *value = r;
+ free_and_replace(*value, r);
return 1;
}
@@ -543,7 +706,7 @@ static int parse_unix_address(sd_bus *b, const char **p, char **guid) {
assert(*p);
assert(guid);
- while (**p != 0 && **p != ';') {
+ while (!IN_SET(**p, 0, ';')) {
r = parse_address_key(p, "guid", guid);
if (r < 0)
return r;
@@ -608,7 +771,7 @@ static int parse_tcp_address(sd_bus *b, const char **p, char **guid) {
assert(*p);
assert(guid);
- while (**p != 0 && **p != ';') {
+ while (!IN_SET(**p, 0, ';')) {
r = parse_address_key(p, "guid", guid);
if (r < 0)
return r;
@@ -676,7 +839,7 @@ static int parse_exec_address(sd_bus *b, const char **p, char **guid) {
assert(*p);
assert(guid);
- while (**p != 0 && **p != ';') {
+ while (!IN_SET(**p, 0, ';')) {
r = parse_address_key(p, "guid", guid);
if (r < 0)
goto fail;
@@ -757,43 +920,6 @@ fail:
return r;
}
-static int parse_kernel_address(sd_bus *b, const char **p, char **guid) {
- _cleanup_free_ char *path = NULL;
- int r;
-
- assert(b);
- assert(p);
- assert(*p);
- assert(guid);
-
- while (**p != 0 && **p != ';') {
- r = parse_address_key(p, "guid", guid);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- r = parse_address_key(p, "path", &path);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- skip_address_key(p);
- }
-
- if (!path)
- return -EINVAL;
-
- free(b->kernel);
- b->kernel = path;
- path = NULL;
-
- b->is_local = true;
-
- return 0;
-}
-
static int parse_container_unix_address(sd_bus *b, const char **p, char **guid) {
_cleanup_free_ char *machine = NULL, *pid = NULL;
int r;
@@ -803,7 +929,7 @@ static int parse_container_unix_address(sd_bus *b, const char **p, char **guid)
assert(*p);
assert(guid);
- while (**p != 0 && **p != ';') {
+ while (!IN_SET(**p, 0, ';')) {
r = parse_address_key(p, "guid", guid);
if (r < 0)
return r;
@@ -832,9 +958,7 @@ static int parse_container_unix_address(sd_bus *b, const char **p, char **guid)
if (!machine_name_is_valid(machine))
return -EINVAL;
- free(b->machine);
- b->machine = machine;
- machine = NULL;
+ free_and_replace(b->machine, machine);
} else {
b->machine = mfree(b->machine);
}
@@ -847,6 +971,7 @@ static int parse_container_unix_address(sd_bus *b, const char **p, char **guid)
b->nspid = 0;
b->sockaddr.un.sun_family = AF_UNIX;
+ /* Note that we use the old /var/run prefix here, to increase compatibility with really old containers */
strncpy(b->sockaddr.un.sun_path, "/var/run/dbus/system_bus_socket", sizeof(b->sockaddr.un.sun_path));
b->sockaddr_size = SOCKADDR_UN_LEN(b->sockaddr.un);
b->is_local = false;
@@ -854,67 +979,6 @@ static int parse_container_unix_address(sd_bus *b, const char **p, char **guid)
return 0;
}
-static int parse_container_kernel_address(sd_bus *b, const char **p, char **guid) {
- _cleanup_free_ char *machine = NULL, *pid = NULL;
- int r;
-
- assert(b);
- assert(p);
- assert(*p);
- assert(guid);
-
- while (**p != 0 && **p != ';') {
- r = parse_address_key(p, "guid", guid);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- r = parse_address_key(p, "machine", &machine);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- r = parse_address_key(p, "pid", &pid);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- skip_address_key(p);
- }
-
- if (!machine == !pid)
- return -EINVAL;
-
- if (machine) {
- if (!machine_name_is_valid(machine))
- return -EINVAL;
-
- free(b->machine);
- b->machine = machine;
- machine = NULL;
- } else {
- b->machine = mfree(b->machine);
- }
-
- if (pid) {
- r = parse_pid(pid, &b->nspid);
- if (r < 0)
- return r;
- } else
- b->nspid = 0;
-
- r = free_and_strdup(&b->kernel, "/sys/fs/kdbus/0-system/bus");
- if (r < 0)
- return r;
-
- b->is_local = false;
-
- return 0;
-}
-
static void bus_reset_parsed_address(sd_bus *b) {
assert(b);
@@ -923,7 +987,6 @@ static void bus_reset_parsed_address(sd_bus *b) {
b->exec_argv = strv_free(b->exec_argv);
b->exec_path = mfree(b->exec_path);
b->server_id = SD_ID128_NULL;
- b->kernel = mfree(b->kernel);
b->machine = mfree(b->machine);
b->nspid = 0;
}
@@ -977,14 +1040,6 @@ static int bus_parse_next_address(sd_bus *b) {
break;
- } else if (startswith(a, "kernel:")) {
-
- a += 7;
- r = parse_kernel_address(b, &a, &guid);
- if (r < 0)
- return r;
-
- break;
} else if (startswith(a, "x-machine-unix:")) {
a += 15;
@@ -993,14 +1048,6 @@ static int bus_parse_next_address(sd_bus *b) {
return r;
break;
- } else if (startswith(a, "x-machine-kernel:")) {
-
- a += 17;
- r = parse_container_kernel_address(b, &a, &guid);
- if (r < 0)
- return r;
-
- break;
}
a = strchr(a, ';');
@@ -1018,69 +1065,59 @@ static int bus_parse_next_address(sd_bus *b) {
return 1;
}
+static void bus_kill_exec(sd_bus *bus) {
+ if (pid_is_valid(bus->busexec_pid) > 0) {
+ sigterm_wait(bus->busexec_pid);
+ bus->busexec_pid = 0;
+ }
+}
+
static int bus_start_address(sd_bus *b) {
- bool container_kdbus_available = false;
- bool kdbus_available = false;
int r;
assert(b);
for (;;) {
- bool skipped = false;
+ bus_close_io_fds(b);
+ bus_close_inotify_fd(b);
- bus_close_fds(b);
+ bus_kill_exec(b);
- /*
- * Usually, if you provide multiple different bus-addresses, we
- * try all of them in order. We use the first one that
- * succeeds. However, if you mix kernel and unix addresses, we
- * never try unix-addresses if a previous kernel address was
- * tried and kdbus was available. This is required to prevent
- * clients to fallback to the bus-proxy if kdbus is available
- * but failed (eg., too many connections).
- */
+ /* If you provide multiple different bus-addresses, we
+ * try all of them in order and use the first one that
+ * succeeds. */
if (b->exec_path)
r = bus_socket_exec(b);
- else if ((b->nspid > 0 || b->machine) && b->kernel) {
- r = bus_container_connect_kernel(b);
- if (r < 0 && !IN_SET(r, -ENOENT, -ESOCKTNOSUPPORT))
- container_kdbus_available = true;
-
- } else if ((b->nspid > 0 || b->machine) && b->sockaddr.sa.sa_family != AF_UNSPEC) {
- if (!container_kdbus_available)
- r = bus_container_connect_socket(b);
- else
- skipped = true;
-
- } else if (b->kernel) {
- r = bus_kernel_connect(b);
- if (r < 0 && !IN_SET(r, -ENOENT, -ESOCKTNOSUPPORT))
- kdbus_available = true;
-
- } else if (b->sockaddr.sa.sa_family != AF_UNSPEC) {
- if (!kdbus_available)
- r = bus_socket_connect(b);
- else
- skipped = true;
- } else
- skipped = true;
+ else if ((b->nspid > 0 || b->machine) && b->sockaddr.sa.sa_family != AF_UNSPEC)
+ r = bus_container_connect_socket(b);
+ else if (b->sockaddr.sa.sa_family != AF_UNSPEC)
+ r = bus_socket_connect(b);
+ else
+ goto next;
- if (!skipped) {
- if (r >= 0) {
- r = attach_io_events(b);
- if (r >= 0)
- return r;
- }
+ if (r >= 0) {
+ int q;
+
+ q = bus_attach_io_events(b);
+ if (q < 0)
+ return q;
- b->last_connect_error = -r;
+ q = bus_attach_inotify_event(b);
+ if (q < 0)
+ return q;
+
+ return r;
}
+ b->last_connect_error = -r;
+
+ next:
r = bus_parse_next_address(b);
if (r < 0)
return r;
if (r == 0)
- return b->last_connect_error ? -b->last_connect_error : -ECONNREFUSED;
+ return b->last_connect_error > 0 ? -b->last_connect_error : -ECONNREFUSED;
}
}
@@ -1120,27 +1157,25 @@ static int bus_start_fd(sd_bus *b) {
if (fstat(b->input_fd, &st) < 0)
return -errno;
- if (S_ISCHR(b->input_fd))
- return bus_kernel_take_fd(b);
- else
- return bus_socket_take_fd(b);
+ return bus_socket_take_fd(b);
}
_public_ int sd_bus_start(sd_bus *bus) {
int r;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(bus->state == BUS_UNSET, -EPERM);
assert_return(!bus_pid_changed(bus), -ECHILD);
- bus->state = BUS_OPENING;
+ bus_set_state(bus, BUS_OPENING);
if (bus->is_server && bus->bus_client)
return -EINVAL;
if (bus->input_fd >= 0)
r = bus_start_fd(bus);
- else if (bus->address || bus->sockaddr.sa.sa_family != AF_UNSPEC || bus->exec_path || bus->kernel || bus->machine)
+ else if (bus->address || bus->sockaddr.sa.sa_family != AF_UNSPEC || bus->exec_path || bus->machine)
r = bus_start_address(bus);
else
return -EINVAL;
@@ -1153,9 +1188,9 @@ _public_ int sd_bus_start(sd_bus *bus) {
return bus_send_hello(bus);
}
-_public_ int sd_bus_open(sd_bus **ret) {
+_public_ int sd_bus_open_with_description(sd_bus **ret, const char *description) {
const char *e;
- sd_bus *b;
+ _cleanup_(bus_freep) sd_bus *b = NULL;
int r;
assert_return(ret, -EINVAL);
@@ -1167,21 +1202,21 @@ _public_ int sd_bus_open(sd_bus **ret) {
e = secure_getenv("DBUS_STARTER_BUS_TYPE");
if (e) {
if (streq(e, "system"))
- return sd_bus_open_system(ret);
-#if 0 /// elogind does not support systemd units
+ return sd_bus_open_system_with_description(ret, description);
+#if 0 /// elogind does not support systemd user instances
else if (STR_IN_SET(e, "session", "user"))
- return sd_bus_open_user(ret);
#endif // 0
+ return sd_bus_open_user_with_description(ret, description);
}
e = secure_getenv("DBUS_STARTER_ADDRESS");
if (!e) {
-#if 0 /// elogind does not support systemd units
+#if 0 /// elogind does not support systemd user instances
if (cg_pid_get_owner_uid(0, NULL) >= 0)
- return sd_bus_open_user(ret);
+ return sd_bus_open_user_with_description(ret, description);
else
#endif // 0
- return sd_bus_open_system(ret);
+ return sd_bus_open_system_with_description(ret, description);
}
r = sd_bus_new(&b);
@@ -1190,7 +1225,7 @@ _public_ int sd_bus_open(sd_bus **ret) {
r = sd_bus_set_address(b, e);
if (r < 0)
- goto fail;
+ return r;
b->bus_client = true;
@@ -1198,19 +1233,18 @@ _public_ int sd_bus_open(sd_bus **ret) {
* be safe, and authenticate everything */
b->trusted = false;
b->is_local = false;
- b->attach_flags |= KDBUS_ATTACH_CAPS | KDBUS_ATTACH_CREDS;
b->creds_mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_EFFECTIVE_CAPS;
r = sd_bus_start(b);
if (r < 0)
- goto fail;
+ return r;
- *ret = b;
+ *ret = TAKE_PTR(b);
return 0;
+}
-fail:
- bus_free(b);
- return r;
+_public_ int sd_bus_open(sd_bus **ret) {
+ return sd_bus_open_with_description(ret, NULL);
}
int bus_set_address_system(sd_bus *b) {
@@ -1224,8 +1258,8 @@ int bus_set_address_system(sd_bus *b) {
return sd_bus_set_address(b, DEFAULT_SYSTEM_BUS_ADDRESS);
}
-_public_ int sd_bus_open_system(sd_bus **ret) {
- sd_bus *b;
+_public_ int sd_bus_open_system_with_description(sd_bus **ret, const char *description) {
+ _cleanup_(bus_freep) sd_bus *b = NULL;
int r;
assert_return(ret, -EINVAL);
@@ -1234,9 +1268,15 @@ _public_ int sd_bus_open_system(sd_bus **ret) {
if (r < 0)
return r;
+ if (description) {
+ r = sd_bus_set_description(b, description);
+ if (r < 0)
+ return r;
+ }
+
r = bus_set_address_system(b);
if (r < 0)
- goto fail;
+ return r;
b->bus_client = true;
b->is_system = true;
@@ -1244,27 +1284,25 @@ _public_ int sd_bus_open_system(sd_bus **ret) {
/* Let's do per-method access control on the system bus. We
* need the caller's UID and capability set for that. */
b->trusted = false;
- b->attach_flags |= KDBUS_ATTACH_CAPS | KDBUS_ATTACH_CREDS;
b->creds_mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_EFFECTIVE_CAPS;
b->is_local = true;
r = sd_bus_start(b);
if (r < 0)
- goto fail;
+ return r;
- *ret = b;
+ *ret = TAKE_PTR(b);
return 0;
+}
-fail:
- bus_free(b);
- return r;
+_public_ int sd_bus_open_system(sd_bus **ret) {
+ return sd_bus_open_system_with_description(ret, NULL);
}
#if 0 /// elogind can not open/use a user bus
int bus_set_address_user(sd_bus *b) {
const char *e;
- uid_t uid;
- int r;
+ _cleanup_free_ char *ee = NULL, *s = NULL;
assert(b);
@@ -1272,32 +1310,26 @@ int bus_set_address_user(sd_bus *b) {
if (e)
return sd_bus_set_address(b, e);
- r = cg_pid_get_owner_uid(0, &uid);
- if (r < 0)
- uid = getuid();
-
e = secure_getenv("XDG_RUNTIME_DIR");
- if (e) {
- _cleanup_free_ char *ee = NULL;
-
- ee = bus_address_escape(e);
- if (!ee)
- return -ENOMEM;
+ if (!e)
+ return -ENOENT;
- (void) asprintf(&b->address, KERNEL_USER_BUS_ADDRESS_FMT ";" UNIX_USER_BUS_ADDRESS_FMT, uid, ee);
- } else
- (void) asprintf(&b->address, KERNEL_USER_BUS_ADDRESS_FMT, uid);
+ ee = bus_address_escape(e);
+ if (!ee)
+ return -ENOMEM;
- if (!b->address)
+ if (asprintf(&s, DEFAULT_USER_BUS_ADDRESS_FMT, ee) < 0)
return -ENOMEM;
+ b->address = TAKE_PTR(s);
+
return 0;
}
#endif // 0
-_public_ int sd_bus_open_user(sd_bus **ret) {
+_public_ int sd_bus_open_user_with_description(sd_bus **ret, const char *description) {
#if 0 /// elogind does not support user buses
- sd_bus *b;
+ _cleanup_(bus_freep) sd_bus *b = NULL;
int r;
assert_return(ret, -EINVAL);
@@ -1306,6 +1338,12 @@ _public_ int sd_bus_open_user(sd_bus **ret) {
if (r < 0)
return r;
+ if (description) {
+ r = sd_bus_set_description(b, description);
+ if (r < 0)
+ return r;
+ }
+
r = bus_set_address_user(b);
if (r < 0)
return r;
@@ -1320,22 +1358,22 @@ _public_ int sd_bus_open_user(sd_bus **ret) {
r = sd_bus_start(b);
if (r < 0)
- goto fail;
+ return r;
- *ret = b;
+ *ret = TAKE_PTR(b);
return 0;
-
-fail:
- bus_free(b);
- return r;
#else
- return sd_bus_open_system(ret);
+ return sd_bus_open_system_with_description(ret, description);
#endif // 0
}
+_public_ int sd_bus_open_user(sd_bus **ret) {
+ return sd_bus_open_user_with_description(ret, NULL);
+}
+
int bus_set_address_system_remote(sd_bus *b, const char *host) {
_cleanup_free_ char *e = NULL;
- char *m = NULL, *c = NULL;
+ char *m = NULL, *c = NULL, *a;
assert(b);
assert(host);
@@ -1347,7 +1385,7 @@ int bus_set_address_system_remote(sd_bus *b, const char *host) {
/* Let's make sure this is not a port of some kind,
* and is a valid machine name. */
- if (!in_charset(m, "0123456789") && machine_name_is_valid(m)) {
+ if (!in_charset(m, DIGITS) && machine_name_is_valid(m)) {
char *t;
/* Cut out the host part */
@@ -1356,7 +1394,7 @@ int bus_set_address_system_remote(sd_bus *b, const char *host) {
if (!e)
return -ENOMEM;
- c = strjoina(",argv4=--machine=", m);
+ c = strjoina(",argv5=--machine=", m);
}
}
@@ -1366,47 +1404,44 @@ int bus_set_address_system_remote(sd_bus *b, const char *host) {
return -ENOMEM;
}
- b->address = strjoin("unixexec:path=ssh,argv1=-xT,argv2=", e, ",argv3=systemd-stdio-bridge", c);
- if (!b->address)
+ a = strjoin("unixexec:path=ssh,argv1=-xT,argv2=--,argv3=", e, ",argv4=elogind-stdio-bridge", c);
+ if (!a)
return -ENOMEM;
- return 0;
- }
+ return free_and_replace(b->address, a);
+}
_public_ int sd_bus_open_system_remote(sd_bus **ret, const char *host) {
- sd_bus *bus;
+ _cleanup_(bus_freep) sd_bus *b = NULL;
int r;
assert_return(host, -EINVAL);
assert_return(ret, -EINVAL);
- r = sd_bus_new(&bus);
+ r = sd_bus_new(&b);
if (r < 0)
return r;
- r = bus_set_address_system_remote(bus, host);
+ r = bus_set_address_system_remote(b, host);
if (r < 0)
- goto fail;
+ return r;
- bus->bus_client = true;
- bus->trusted = false;
- bus->is_system = true;
- bus->is_local = false;
+ b->bus_client = true;
+ b->trusted = false;
+ b->is_system = true;
+ b->is_local = false;
- r = sd_bus_start(bus);
+ r = sd_bus_start(b);
if (r < 0)
- goto fail;
+ return r;
- *ret = bus;
+ *ret = TAKE_PTR(b);
return 0;
-
-fail:
- bus_free(bus);
- return r;
}
int bus_set_address_system_machine(sd_bus *b, const char *machine) {
_cleanup_free_ char *e = NULL;
+ char *a;
assert(b);
assert(machine);
@@ -1415,48 +1450,43 @@ int bus_set_address_system_machine(sd_bus *b, const char *machine) {
if (!e)
return -ENOMEM;
- b->address = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e);
- if (!b->address)
+ a = strjoin("x-machine-unix:machine=", e);
+ if (!a)
return -ENOMEM;
- return 0;
+ return free_and_replace(b->address, a);
}
_public_ int sd_bus_open_system_machine(sd_bus **ret, const char *machine) {
- sd_bus *bus;
+ _cleanup_(bus_freep) sd_bus *b = NULL;
int r;
assert_return(machine, -EINVAL);
assert_return(ret, -EINVAL);
assert_return(machine_name_is_valid(machine), -EINVAL);
- r = sd_bus_new(&bus);
+ r = sd_bus_new(&b);
if (r < 0)
return r;
- r = bus_set_address_system_machine(bus, machine);
+ r = bus_set_address_system_machine(b, machine);
if (r < 0)
- goto fail;
+ return r;
- bus->bus_client = true;
- bus->trusted = false;
- bus->is_system = true;
- bus->is_local = false;
+ b->bus_client = true;
+ b->trusted = false;
+ b->is_system = true;
+ b->is_local = false;
- r = sd_bus_start(bus);
+ r = sd_bus_start(b);
if (r < 0)
- goto fail;
+ return r;
- *ret = bus;
+ *ret = TAKE_PTR(b);
return 0;
-
-fail:
- bus_free(bus);
- return r;
}
_public_ void sd_bus_close(sd_bus *bus) {
-
if (!bus)
return;
if (bus->state == BUS_CLOSED)
@@ -1464,7 +1494,10 @@ _public_ void sd_bus_close(sd_bus *bus) {
if (bus_pid_changed(bus))
return;
- bus->state = BUS_CLOSED;
+ /* Don't leave ssh hanging around */
+ bus_kill_exec(bus);
+
+ bus_set_state(bus, BUS_CLOSED);
sd_bus_detach_event(bus);
@@ -1472,40 +1505,33 @@ _public_ void sd_bus_close(sd_bus *bus) {
* the bus object and the bus may be freed */
bus_reset_queues(bus);
- if (!bus->is_kernel)
- bus_close_fds(bus);
-
- /* We'll leave the fd open in case this is a kernel bus, since
- * there might still be memblocks around that reference this
- * bus, and they might need to invoke the KDBUS_CMD_FREE
- * ioctl on the fd when they are freed. */
+ bus_close_io_fds(bus);
+ bus_close_inotify_fd(bus);
}
_public_ sd_bus* sd_bus_flush_close_unref(sd_bus *bus) {
-
if (!bus)
return NULL;
+ /* Have to do this before flush() to prevent hang */
+ bus_kill_exec(bus);
+
sd_bus_flush(bus);
sd_bus_close(bus);
return sd_bus_unref(bus);
}
-static void bus_enter_closing(sd_bus *bus) {
+void bus_enter_closing(sd_bus *bus) {
assert(bus);
- if (bus->state != BUS_OPENING &&
- bus->state != BUS_AUTHENTICATING &&
- bus->state != BUS_HELLO &&
- bus->state != BUS_RUNNING)
+ if (!IN_SET(bus->state, BUS_WATCH_BIND, BUS_OPENING, BUS_AUTHENTICATING, BUS_HELLO, BUS_RUNNING))
return;
- bus->state = BUS_CLOSING;
+ bus_set_state(bus, BUS_CLOSING);
}
_public_ sd_bus *sd_bus_ref(sd_bus *bus) {
-
if (!bus)
return NULL;
@@ -1524,30 +1550,38 @@ _public_ sd_bus *sd_bus_unref(sd_bus *bus) {
if (i > 0)
return NULL;
- bus_free(bus);
- return NULL;
+ return bus_free(bus);
}
_public_ int sd_bus_is_open(sd_bus *bus) {
-
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(!bus_pid_changed(bus), -ECHILD);
return BUS_IS_OPEN(bus->state);
}
+_public_ int sd_bus_is_ready(sd_bus *bus) {
+ assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
+
+ return bus->state == BUS_RUNNING;
+}
+
_public_ int sd_bus_can_send(sd_bus *bus, char type) {
int r;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(bus->state != BUS_UNSET, -ENOTCONN);
assert_return(!bus_pid_changed(bus), -ECHILD);
- if (bus->hello_flags & KDBUS_HELLO_MONITOR)
+ if (bus->is_monitor)
return 0;
if (type == SD_BUS_TYPE_UNIX_FD) {
- if (!(bus->hello_flags & KDBUS_HELLO_ACCEPT_FD))
+ if (!bus->accept_fd)
return 0;
r = bus_ensure_running(bus);
@@ -1564,6 +1598,7 @@ _public_ int sd_bus_get_bus_id(sd_bus *bus, sd_id128_t *id) {
int r;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(id, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -1576,6 +1611,8 @@ _public_ int sd_bus_get_bus_id(sd_bus *bus, sd_id128_t *id) {
}
static int bus_seal_message(sd_bus *b, sd_bus_message *m, usec_t timeout) {
+ int r;
+
assert(b);
assert(m);
@@ -1590,7 +1627,13 @@ static int bus_seal_message(sd_bus *b, sd_bus_message *m, usec_t timeout) {
if (timeout == 0)
timeout = BUS_DEFAULT_TIMEOUT;
- return bus_message_seal(m, ++b->cookie, timeout);
+ if (!m->sender && b->patch_sender) {
+ r = sd_bus_message_set_sender(m, b->patch_sender);
+ if (r < 0)
+ return r;
+ }
+
+ return sd_bus_message_seal(m, ++b->cookie, timeout);
}
static int bus_remarshal_message(sd_bus *b, sd_bus_message **m) {
@@ -1606,14 +1649,6 @@ static int bus_remarshal_message(sd_bus *b, sd_bus_message **m) {
if (b->message_endian != 0 && b->message_endian != (*m)->header->endian)
remarshal = true;
- /* TODO: kdbus-messages received from the kernel contain data which is
- * not allowed to be passed to KDBUS_CMD_SEND. Therefore, we have to
- * force remarshaling of the message. Technically, we could just
- * recreate the kdbus message, but that is non-trivial as other parts of
- * the message refer to m->kdbus already. This should be fixed! */
- if ((*m)->kdbus && (*m)->release_kdbus)
- remarshal = true;
-
return remarshal ? bus_message_remarshal(b, m) : 0;
}
@@ -1623,7 +1658,7 @@ int bus_seal_synthetic_message(sd_bus *b, sd_bus_message *m) {
/* Fake some timestamps, if they were requested, and not
* already initialized */
- if (b->attach_flags & KDBUS_ATTACH_TIMESTAMP) {
+ if (b->attach_timestamp) {
if (m->realtime <= 0)
m->realtime = now(CLOCK_REALTIME);
@@ -1638,25 +1673,21 @@ int bus_seal_synthetic_message(sd_bus *b, sd_bus_message *m) {
* pick a fixed, artificial one. We use (uint32_t) -1 rather
* than (uint64_t) -1 since dbus1 only had 32bit identifiers,
* even though kdbus can do 64bit. */
- return bus_message_seal(m, 0xFFFFFFFFULL, 0);
+ return sd_bus_message_seal(m, 0xFFFFFFFFULL, 0);
}
-static int bus_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call, size_t *idx) {
+static int bus_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
int r;
assert(bus);
assert(m);
- if (bus->is_kernel)
- r = bus_kernel_write_message(bus, m, hint_sync_call);
- else
- r = bus_socket_write_message(bus, m, idx);
-
+ r = bus_socket_write_message(bus, m, idx);
if (r <= 0)
return r;
- if (bus->is_kernel || *idx >= BUS_MESSAGE_SIZE(m))
- log_debug("Sent message type=%s sender=%s destination=%s object=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " error=%s",
+ if (*idx >= BUS_MESSAGE_SIZE(m))
+ log_debug("Sent message type=%s sender=%s destination=%s path=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " signature=%s error-name=%s error-message=%s",
bus_message_type_to_string(m->header->type),
strna(sd_bus_message_get_sender(m)),
strna(sd_bus_message_get_destination(m)),
@@ -1665,6 +1696,8 @@ static int bus_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call
strna(sd_bus_message_get_member(m)),
BUS_MESSAGE_COOKIE(m),
m->reply_cookie,
+ strna(m->root_container.signature),
+ strna(m->error.name),
strna(m->error.message));
return r;
@@ -1674,17 +1707,17 @@ static int dispatch_wqueue(sd_bus *bus) {
int r, ret = 0;
assert(bus);
- assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
+ assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
while (bus->wqueue_size > 0) {
- r = bus_write_message(bus, bus->wqueue[0], false, &bus->windex);
+ r = bus_write_message(bus, bus->wqueue[0], &bus->windex);
if (r < 0)
return r;
else if (r == 0)
/* Didn't do anything this time */
return ret;
- else if (bus->is_kernel || bus->windex >= BUS_MESSAGE_SIZE(bus->wqueue[0])) {
+ else if (bus->windex >= BUS_MESSAGE_SIZE(bus->wqueue[0])) {
/* Fully written. Let's drop the entry from
* the queue.
*
@@ -1710,10 +1743,7 @@ static int dispatch_wqueue(sd_bus *bus) {
static int bus_read_message(sd_bus *bus, bool hint_priority, int64_t priority) {
assert(bus);
- if (bus->is_kernel)
- return bus_kernel_read_message(bus, hint_priority, priority);
- else
- return bus_socket_read_message(bus);
+ return bus_socket_read_message(bus);
}
int bus_rqueue_make_room(sd_bus *bus) {
@@ -1733,7 +1763,7 @@ static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd
assert(bus);
assert(m);
- assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
+ assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
/* Note that the priority logic is only available on kdbus,
* where the rqueue is unused. We check the rqueue here
@@ -1760,7 +1790,7 @@ static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd
}
}
-static int bus_send_internal(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie, bool hint_sync_call) {
+_public_ int sd_bus_send(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m);
int r;
@@ -1770,7 +1800,6 @@ static int bus_send_internal(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie,
bus = m->bus;
assert_return(!bus_pid_changed(bus), -ECHILD);
- assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS);
if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
@@ -1803,10 +1832,10 @@ static int bus_send_internal(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie,
if (m->dont_send)
goto finish;
- if ((bus->state == BUS_RUNNING || bus->state == BUS_HELLO) && bus->wqueue_size <= 0) {
+ if (IN_SET(bus->state, BUS_RUNNING, BUS_HELLO) && bus->wqueue_size <= 0) {
size_t idx = 0;
- r = bus_write_message(bus, m, hint_sync_call, &idx);
+ r = bus_write_message(bus, m, &idx);
if (r < 0) {
if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
bus_enter_closing(bus);
@@ -1816,7 +1845,7 @@ static int bus_send_internal(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie,
return r;
}
- if (!bus->is_kernel && idx < BUS_MESSAGE_SIZE(m)) {
+ if (idx < BUS_MESSAGE_SIZE(m)) {
/* Wasn't fully written. So let's remember how
* much was written. Note that the first entry
* of the wqueue array is always allocated so
@@ -1846,10 +1875,6 @@ finish:
return 1;
}
-_public_ int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *cookie) {
- return bus_send_internal(bus, m, cookie, false);
-}
-
_public_ int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *cookie) {
int r;
@@ -1876,26 +1901,35 @@ _public_ int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destinat
return sd_bus_send(bus, m, cookie);
}
-static usec_t calc_elapse(uint64_t usec) {
+static usec_t calc_elapse(sd_bus *bus, uint64_t usec) {
+ assert(bus);
+
if (usec == (uint64_t) -1)
return 0;
- return now(CLOCK_MONOTONIC) + usec;
+ /* We start all timeouts the instant we enter BUS_HELLO/BUS_RUNNING state, so that the don't run in parallel
+ * with any connection setup states. Hence, if a method callback is started earlier than that we just store the
+ * relative timestamp, and afterwards the absolute one. */
+
+ if (IN_SET(bus->state, BUS_WATCH_BIND, BUS_OPENING, BUS_AUTHENTICATING))
+ return usec;
+ else
+ return now(CLOCK_MONOTONIC) + usec;
}
static int timeout_compare(const void *a, const void *b) {
const struct reply_callback *x = a, *y = b;
- if (x->timeout != 0 && y->timeout == 0)
+ if (x->timeout_usec != 0 && y->timeout_usec == 0)
return -1;
- if (x->timeout == 0 && y->timeout != 0)
+ if (x->timeout_usec == 0 && y->timeout_usec != 0)
return 1;
- if (x->timeout < y->timeout)
+ if (x->timeout_usec < y->timeout_usec)
return -1;
- if (x->timeout > y->timeout)
+ if (x->timeout_usec > y->timeout_usec)
return 1;
return 0;
@@ -1915,18 +1949,20 @@ _public_ int sd_bus_call_async(
assert_return(m, -EINVAL);
assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
- assert_return(!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED), -EINVAL);
- assert_return(callback, -EINVAL);
+ assert_return(!m->sealed || (!!callback == !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)), -EINVAL);
if (!bus)
bus = m->bus;
assert_return(!bus_pid_changed(bus), -ECHILD);
- assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS);
if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
+ /* If no callback is specified and there's no interest in a slot, then there's no reason to ask for a reply */
+ if (!callback && !slot && !m->sealed)
+ m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
+
r = ordered_hashmap_ensure_allocated(&bus->reply_callbacks, &uint64_hash_ops);
if (r < 0)
return r;
@@ -1943,29 +1979,31 @@ _public_ int sd_bus_call_async(
if (r < 0)
return r;
- s = bus_slot_allocate(bus, !slot, BUS_REPLY_CALLBACK, sizeof(struct reply_callback), userdata);
- if (!s)
- return -ENOMEM;
+ if (slot || callback) {
+ s = bus_slot_allocate(bus, !slot, BUS_REPLY_CALLBACK, sizeof(struct reply_callback), userdata);
+ if (!s)
+ return -ENOMEM;
- s->reply_callback.callback = callback;
+ s->reply_callback.callback = callback;
- s->reply_callback.cookie = BUS_MESSAGE_COOKIE(m);
- r = ordered_hashmap_put(bus->reply_callbacks, &s->reply_callback.cookie, &s->reply_callback);
- if (r < 0) {
- s->reply_callback.cookie = 0;
- return r;
- }
-
- s->reply_callback.timeout = calc_elapse(m->timeout);
- if (s->reply_callback.timeout != 0) {
- r = prioq_put(bus->reply_callbacks_prioq, &s->reply_callback, &s->reply_callback.prioq_idx);
+ s->reply_callback.cookie = BUS_MESSAGE_COOKIE(m);
+ r = ordered_hashmap_put(bus->reply_callbacks, &s->reply_callback.cookie, &s->reply_callback);
if (r < 0) {
- s->reply_callback.timeout = 0;
+ s->reply_callback.cookie = 0;
return r;
}
+
+ s->reply_callback.timeout_usec = calc_elapse(bus, m->timeout);
+ if (s->reply_callback.timeout_usec != 0) {
+ r = prioq_put(bus->reply_callbacks_prioq, &s->reply_callback, &s->reply_callback.prioq_idx);
+ if (r < 0) {
+ s->reply_callback.timeout_usec = 0;
+ return r;
+ }
+ }
}
- r = sd_bus_send(bus, m, &s->reply_callback.cookie);
+ r = sd_bus_send(bus, m, s ? &s->reply_callback.cookie : NULL);
if (r < 0)
return r;
@@ -1981,7 +2019,7 @@ int bus_ensure_running(sd_bus *bus) {
assert(bus);
- if (bus->state == BUS_UNSET || bus->state == BUS_CLOSED || bus->state == BUS_CLOSING)
+ if (IN_SET(bus->state, BUS_UNSET, BUS_CLOSED, BUS_CLOSING))
return -ENOTCONN;
if (bus->state == BUS_RUNNING)
return 1;
@@ -2023,7 +2061,6 @@ _public_ int sd_bus_call(
bus = m->bus;
bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
- bus_assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS, error);
if (!BUS_IS_OPEN(bus->state)) {
r = -ENOTCONN;
@@ -2044,11 +2081,11 @@ _public_ int sd_bus_call(
if (r < 0)
goto fail;
- r = bus_send_internal(bus, m, &cookie, true);
+ r = sd_bus_send(bus, m, &cookie);
if (r < 0)
goto fail;
- timeout = calc_elapse(m->timeout);
+ timeout = calc_elapse(bus, m->timeout);
for (;;) {
usec_t left;
@@ -2067,7 +2104,7 @@ _public_ int sd_bus_call(
if (incoming->header->type == SD_BUS_MESSAGE_METHOD_RETURN) {
- if (incoming->n_fds <= 0 || (bus->hello_flags & KDBUS_HELLO_ACCEPT_FD)) {
+ if (incoming->n_fds <= 0 || bus->accept_fd) {
if (reply)
*reply = incoming;
else
@@ -2162,35 +2199,63 @@ fail:
_public_ int sd_bus_get_fd(sd_bus *bus) {
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(bus->input_fd == bus->output_fd, -EPERM);
assert_return(!bus_pid_changed(bus), -ECHILD);
- return bus->input_fd;
+ if (bus->state == BUS_CLOSED)
+ return -ENOTCONN;
+
+ if (bus->inotify_fd >= 0)
+ return bus->inotify_fd;
+
+ if (bus->input_fd >= 0)
+ return bus->input_fd;
+
+ return -ENOTCONN;
}
_public_ int sd_bus_get_events(sd_bus *bus) {
int flags = 0;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(!bus_pid_changed(bus), -ECHILD);
- if (!BUS_IS_OPEN(bus->state) && bus->state != BUS_CLOSING)
+ switch (bus->state) {
+
+ case BUS_UNSET:
+ case BUS_CLOSED:
return -ENOTCONN;
- if (bus->state == BUS_OPENING)
+ case BUS_WATCH_BIND:
+ flags |= POLLIN;
+ break;
+
+ case BUS_OPENING:
flags |= POLLOUT;
- else if (bus->state == BUS_AUTHENTICATING) {
+ break;
+ case BUS_AUTHENTICATING:
if (bus_socket_auth_needs_write(bus))
flags |= POLLOUT;
flags |= POLLIN;
+ break;
- } else if (bus->state == BUS_RUNNING || bus->state == BUS_HELLO) {
+ case BUS_RUNNING:
+ case BUS_HELLO:
if (bus->rqueue_size <= 0)
flags |= POLLIN;
if (bus->wqueue_size > 0)
flags |= POLLOUT;
+ break;
+
+ case BUS_CLOSING:
+ break;
+
+ default:
+ assert_not_reached("Unknown state");
}
return flags;
@@ -2200,6 +2265,7 @@ _public_ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
struct reply_callback *c;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(timeout_usec, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -2211,39 +2277,45 @@ _public_ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
return 1;
}
- if (bus->state == BUS_CLOSING) {
- *timeout_usec = 0;
- return 1;
- }
+ switch (bus->state) {
- if (bus->state == BUS_AUTHENTICATING) {
+ case BUS_AUTHENTICATING:
*timeout_usec = bus->auth_timeout;
return 1;
- }
- if (bus->state != BUS_RUNNING && bus->state != BUS_HELLO) {
- *timeout_usec = (uint64_t) -1;
- return 0;
- }
+ case BUS_RUNNING:
+ case BUS_HELLO:
+ if (bus->rqueue_size > 0) {
+ *timeout_usec = 0;
+ return 1;
+ }
+
+ c = prioq_peek(bus->reply_callbacks_prioq);
+ if (!c) {
+ *timeout_usec = (uint64_t) -1;
+ return 0;
+ }
+
+ if (c->timeout_usec == 0) {
+ *timeout_usec = (uint64_t) -1;
+ return 0;
+ }
- if (bus->rqueue_size > 0) {
+ *timeout_usec = c->timeout_usec;
+ return 1;
+
+ case BUS_CLOSING:
*timeout_usec = 0;
return 1;
- }
- c = prioq_peek(bus->reply_callbacks_prioq);
- if (!c) {
+ case BUS_WATCH_BIND:
+ case BUS_OPENING:
*timeout_usec = (uint64_t) -1;
return 0;
- }
- if (c->timeout == 0) {
- *timeout_usec = (uint64_t) -1;
- return 0;
+ default:
+ assert_not_reached("Unknown or unexpected stat");
}
-
- *timeout_usec = c->timeout;
- return 1;
}
static int process_timeout(sd_bus *bus) {
@@ -2251,17 +2323,19 @@ static int process_timeout(sd_bus *bus) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message* m = NULL;
struct reply_callback *c;
sd_bus_slot *slot;
+ bool is_hello;
usec_t n;
int r;
assert(bus);
+ assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
c = prioq_peek(bus->reply_callbacks_prioq);
if (!c)
return 0;
n = now(CLOCK_MONOTONIC);
- if (c->timeout > n)
+ if (c->timeout_usec > n)
return 0;
r = bus_message_new_synthetic_error(
@@ -2277,7 +2351,7 @@ static int process_timeout(sd_bus *bus) {
return r;
assert_se(prioq_pop(bus->reply_callbacks_prioq) == c);
- c->timeout = 0;
+ c->timeout_usec = 0;
ordered_hashmap_remove(bus->reply_callbacks, &c->cookie);
c->cookie = 0;
@@ -2286,6 +2360,8 @@ static int process_timeout(sd_bus *bus) {
bus->iteration_counter++;
+ is_hello = bus->state == BUS_HELLO && c->callback == hello_callback;
+
bus->current_message = m;
bus->current_slot = sd_bus_slot_ref(slot);
bus->current_handler = c->callback;
@@ -2303,6 +2379,11 @@ static int process_timeout(sd_bus *bus) {
sd_bus_slot_unref(slot);
+ /* When this is the hello message and it timed out, then make sure to propagate the error up, don't just log
+ * and ignore the callback handler's return value. */
+ if (is_hello)
+ return r;
+
return bus_maybe_reply_error(m, r, &error_buffer);
}
@@ -2318,8 +2399,7 @@ static int process_hello(sd_bus *bus, sd_bus_message *m) {
* here (we leave that to the usual handling), we just verify
* we don't let any earlier msg through. */
- if (m->header->type != SD_BUS_MESSAGE_METHOD_RETURN &&
- m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
+ if (!IN_SET(m->header->type, SD_BUS_MESSAGE_METHOD_RETURN, SD_BUS_MESSAGE_METHOD_ERROR))
return -EIO;
if (m->reply_cookie != 1)
@@ -2333,16 +2413,13 @@ static int process_reply(sd_bus *bus, sd_bus_message *m) {
_cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
struct reply_callback *c;
sd_bus_slot *slot;
+ bool is_hello;
int r;
assert(bus);
assert(m);
- if (m->header->type != SD_BUS_MESSAGE_METHOD_RETURN &&
- m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
- return 0;
-
- if (bus->is_kernel && (bus->hello_flags & KDBUS_HELLO_MONITOR))
+ if (!IN_SET(m->header->type, SD_BUS_MESSAGE_METHOD_RETURN, SD_BUS_MESSAGE_METHOD_ERROR))
return 0;
if (m->destination && bus->unique_name && !streq_ptr(m->destination, bus->unique_name))
@@ -2356,7 +2433,7 @@ static int process_reply(sd_bus *bus, sd_bus_message *m) {
slot = container_of(c, sd_bus_slot, reply_callback);
- if (m->n_fds > 0 && !(bus->hello_flags & KDBUS_HELLO_ACCEPT_FD)) {
+ if (m->n_fds > 0 && !bus->accept_fd) {
/* If the reply contained a file descriptor which we
* didn't want we pass an error instead. */
@@ -2385,11 +2462,13 @@ static int process_reply(sd_bus *bus, sd_bus_message *m) {
return r;
}
- if (c->timeout != 0) {
+ if (c->timeout_usec != 0) {
prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
- c->timeout = 0;
+ c->timeout_usec = 0;
}
+ is_hello = bus->state == BUS_HELLO && c->callback == hello_callback;
+
bus->current_slot = sd_bus_slot_ref(slot);
bus->current_handler = c->callback;
bus->current_userdata = slot->userdata;
@@ -2405,6 +2484,11 @@ static int process_reply(sd_bus *bus, sd_bus_message *m) {
sd_bus_slot_unref(slot);
+ /* When this is the hello message and it failed, then make sure to propagate the error up, don't just log and
+ * ignore the callback handler's return value. */
+ if (is_hello)
+ return r;
+
return bus_maybe_reply_error(m, r, &error_buffer);
}
@@ -2481,7 +2565,7 @@ static int process_builtin(sd_bus *bus, sd_bus_message *m) {
assert(bus);
assert(m);
- if (bus->hello_flags & KDBUS_HELLO_MONITOR)
+ if (bus->is_monitor)
return 0;
if (bus->manual_peer_interface)
@@ -2539,13 +2623,13 @@ static int process_fd_check(sd_bus *bus, sd_bus_message *m) {
* delivered to us later even though we ourselves did not
* negotiate it. */
- if (bus->hello_flags & KDBUS_HELLO_MONITOR)
+ if (bus->is_monitor)
return 0;
if (m->n_fds <= 0)
return 0;
- if (bus->hello_flags & KDBUS_HELLO_ACCEPT_FD)
+ if (bus->accept_fd)
return 0;
if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
@@ -2611,7 +2695,7 @@ static int process_running(sd_bus *bus, bool hint_priority, int64_t priority, sd
int r;
assert(bus);
- assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
+ assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
r = process_timeout(bus);
if (r != 0)
@@ -2640,8 +2724,8 @@ static int process_running(sd_bus *bus, bool hint_priority, int64_t priority, sd
if (r < 0)
return r;
- *ret = m;
- m = NULL;
+ *ret = TAKE_PTR(m);
+
return 1;
}
@@ -2716,9 +2800,9 @@ static int process_closing_reply_callback(sd_bus *bus, struct reply_callback *c)
if (r < 0)
return r;
- if (c->timeout != 0) {
+ if (c->timeout_usec != 0) {
prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
- c->timeout = 0;
+ c->timeout_usec = 0;
}
ordered_hashmap_remove(bus->reply_callbacks, &c->cookie);
@@ -2800,10 +2884,8 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) {
bus->exit_triggered = true;
(void) bus_exit_now(bus);
- if (ret) {
- *ret = m;
- m = NULL;
- }
+ if (ret)
+ *ret = TAKE_PTR(m);
r = 1;
@@ -2823,6 +2905,7 @@ static int bus_process_internal(sd_bus *bus, bool hint_priority, int64_t priorit
* means *ret is filled in with an unprocessed message. */
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(!bus_pid_changed(bus), -ECHILD);
/* We don't allow recursively invoking sd_bus_process(). */
@@ -2837,48 +2920,44 @@ static int bus_process_internal(sd_bus *bus, bool hint_priority, int64_t priorit
case BUS_CLOSED:
return -ECONNRESET;
+ case BUS_WATCH_BIND:
+ r = bus_socket_process_watch_bind(bus);
+ break;
+
case BUS_OPENING:
r = bus_socket_process_opening(bus);
- if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
- bus_enter_closing(bus);
- r = 1;
- } else if (r < 0)
- return r;
- if (ret)
- *ret = NULL;
- return r;
+ break;
case BUS_AUTHENTICATING:
r = bus_socket_process_authenticating(bus);
- if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
- bus_enter_closing(bus);
- r = 1;
- } else if (r < 0)
- return r;
-
- if (ret)
- *ret = NULL;
-
- return r;
+ break;
case BUS_RUNNING:
case BUS_HELLO:
r = process_running(bus, hint_priority, priority, ret);
- if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
- bus_enter_closing(bus);
- r = 1;
-
- if (ret)
- *ret = NULL;
- }
+ if (r >= 0)
+ return r;
- return r;
+ /* This branch initializes *ret, hence we don't use the generic error checking below */
+ break;
case BUS_CLOSING:
return process_closing(bus, ret);
+
+ default:
+ assert_not_reached("Unknown state");
}
- assert_not_reached("Unknown state");
+ if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
+ bus_enter_closing(bus);
+ r = 1;
+ } else if (r < 0)
+ return r;
+
+ if (ret)
+ *ret = NULL;
+
+ return r;
}
_public_ int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
@@ -2891,7 +2970,7 @@ _public_ int sd_bus_process_priority(sd_bus *bus, int64_t priority, sd_bus_messa
static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
struct pollfd p[2] = {};
- int r, e, n;
+ int r, n;
struct timespec ts;
usec_t m = USEC_INFINITY;
@@ -2903,45 +2982,52 @@ static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
- e = sd_bus_get_events(bus);
- if (e < 0)
- return e;
-
- if (need_more)
- /* The caller really needs some more data, he doesn't
- * care about what's already read, or any timeouts
- * except its own. */
- e |= POLLIN;
- else {
- usec_t until;
- /* The caller wants to process if there's something to
- * process, but doesn't care otherwise */
-
- r = sd_bus_get_timeout(bus, &until);
- if (r < 0)
- return r;
- if (r > 0) {
- usec_t nw;
- nw = now(CLOCK_MONOTONIC);
- m = until > nw ? until - nw : 0;
- }
- }
-
- if (timeout_usec != (uint64_t) -1 && (m == (uint64_t) -1 || timeout_usec < m))
- m = timeout_usec;
+ if (bus->state == BUS_WATCH_BIND) {
+ assert(bus->inotify_fd >= 0);
- p[0].fd = bus->input_fd;
- if (bus->output_fd == bus->input_fd) {
- p[0].events = e;
+ p[0].events = POLLIN;
+ p[0].fd = bus->inotify_fd;
n = 1;
} else {
- p[0].events = e & POLLIN;
- p[1].fd = bus->output_fd;
- p[1].events = e & POLLOUT;
- n = 2;
+ int e;
+
+ e = sd_bus_get_events(bus);
+ if (e < 0)
+ return e;
+
+ if (need_more)
+ /* The caller really needs some more data, he doesn't
+ * care about what's already read, or any timeouts
+ * except its own. */
+ e |= POLLIN;
+ else {
+ usec_t until;
+ /* The caller wants to process if there's something to
+ * process, but doesn't care otherwise */
+
+ r = sd_bus_get_timeout(bus, &until);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ m = usec_sub_unsigned(until, now(CLOCK_MONOTONIC));
+ }
+
+ p[0].fd = bus->input_fd;
+ if (bus->output_fd == bus->input_fd) {
+ p[0].events = e;
+ n = 1;
+ } else {
+ p[0].events = e & POLLIN;
+ p[1].fd = bus->output_fd;
+ p[1].events = e & POLLOUT;
+ n = 2;
+ }
}
- r = ppoll(p, n, m == (uint64_t) -1 ? NULL : timespec_store(&ts, m), NULL);
+ if (timeout_usec != (uint64_t) -1 && (m == USEC_INFINITY || timeout_usec < m))
+ m = timeout_usec;
+
+ r = ppoll(p, n, m == USEC_INFINITY ? NULL : timespec_store(&ts, m), NULL);
if (r < 0)
return -errno;
@@ -2951,6 +3037,7 @@ static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
_public_ int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec) {
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(!bus_pid_changed(bus), -ECHILD);
if (bus->state == BUS_CLOSING)
@@ -2969,6 +3056,7 @@ _public_ int sd_bus_flush(sd_bus *bus) {
int r;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(!bus_pid_changed(bus), -ECHILD);
if (bus->state == BUS_CLOSING)
@@ -2977,6 +3065,10 @@ _public_ int sd_bus_flush(sd_bus *bus) {
if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
+ /* We never were connected? Don't hang in inotify for good, as there's no timeout set for it */
+ if (bus->state == BUS_WATCH_BIND)
+ return -EUNATCH;
+
r = bus_ensure_running(bus);
if (r < 0)
return r;
@@ -3013,6 +3105,7 @@ _public_ int sd_bus_add_filter(
sd_bus_slot *s;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(callback, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -3031,11 +3124,78 @@ _public_ int sd_bus_add_filter(
return 0;
}
-_public_ int sd_bus_add_match(
+static int add_match_callback(
+ sd_bus_message *m,
+ void *userdata,
+ sd_bus_error *ret_error) {
+
+ sd_bus_slot *match_slot = userdata;
+ bool failed = false;
+ int r;
+
+ assert(m);
+ assert(match_slot);
+
+ sd_bus_slot_ref(match_slot);
+
+ if (sd_bus_message_is_method_error(m, NULL)) {
+ log_debug_errno(sd_bus_message_get_errno(m),
+ "Unable to add match %s, failing connection: %s",
+ match_slot->match_callback.match_string,
+ sd_bus_message_get_error(m)->message);
+
+ failed = true;
+ } else
+ log_debug("Match %s successfully installed.", match_slot->match_callback.match_string);
+
+ if (match_slot->match_callback.install_callback) {
+ sd_bus *bus;
+
+ bus = sd_bus_message_get_bus(m);
+
+ /* This function has been called as slot handler, and we want to call another slot handler. Let's
+ * update the slot callback metadata temporarily with our own data, and then revert back to the old
+ * values. */
+
+ assert(bus->current_slot == match_slot->match_callback.install_slot);
+ assert(bus->current_handler == add_match_callback);
+ assert(bus->current_userdata == userdata);
+
+ bus->current_slot = match_slot;
+ bus->current_handler = match_slot->match_callback.install_callback;
+ bus->current_userdata = match_slot->userdata;
+
+ r = match_slot->match_callback.install_callback(m, match_slot->userdata, ret_error);
+
+ bus->current_slot = match_slot->match_callback.install_slot;
+ bus->current_handler = add_match_callback;
+ bus->current_userdata = userdata;
+
+ match_slot->match_callback.install_slot = sd_bus_slot_unref(match_slot->match_callback.install_slot);
+ } else {
+ if (failed) /* Generic failure handling: destroy the connection */
+ bus_enter_closing(sd_bus_message_get_bus(m));
+
+ r = 1;
+ }
+
+ if (failed && match_slot->floating) {
+ bus_slot_disconnect(match_slot);
+ sd_bus_slot_unref(match_slot);
+ }
+
+ sd_bus_slot_unref(match_slot);
+
+ return r;
+}
+
+static int bus_add_match_full(
sd_bus *bus,
sd_bus_slot **slot,
+ bool asynchronous,
const char *match,
sd_bus_message_handler_t callback,
+ sd_bus_message_handler_t install_callback,
void *userdata) {
struct bus_match_component *components = NULL;
@@ -3044,6 +3204,7 @@ _public_ int sd_bus_add_match(
int r = 0;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(match, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -3058,31 +3219,40 @@ _public_ int sd_bus_add_match(
}
s->match_callback.callback = callback;
- s->match_callback.cookie = ++bus->match_cookie;
+ s->match_callback.install_callback = install_callback;
if (bus->bus_client) {
enum bus_match_scope scope;
scope = bus_match_get_scope(components, n_components);
- /* Do not install server-side matches for matches
- * against the local service, interface or bus
- * path. */
+ /* Do not install server-side matches for matches against the local service, interface or bus path. */
if (scope != BUS_MATCH_LOCAL) {
- if (!bus->is_kernel) {
- /* When this is not a kernel transport, we
- * store the original match string, so that we
- * can use it to remove the match again */
+ /* We store the original match string, so that we can use it to remove the match again. */
- s->match_callback.match_string = strdup(match);
- if (!s->match_callback.match_string) {
- r = -ENOMEM;
- goto finish;
- }
+ s->match_callback.match_string = strdup(match);
+ if (!s->match_callback.match_string) {
+ r = -ENOMEM;
+ goto finish;
}
- r = bus_add_match_internal(bus, s->match_callback.match_string, components, n_components, s->match_callback.cookie);
+ if (asynchronous) {
+ r = bus_add_match_internal_async(bus,
+ &s->match_callback.install_slot,
+ s->match_callback.match_string,
+ add_match_callback,
+ s);
+
+ if (r < 0)
+ return r;
+
+ /* Make the slot of the match call floating now. We need the reference, but we don't
+ * want that this match pins the bus object, hence we first create it non-floating, but
+ * then make it floating. */
+ r = sd_bus_slot_set_floating(s->match_callback.install_slot, true);
+ } else
+ r = bus_add_match_internal(bus, s->match_callback.match_string);
if (r < 0)
goto finish;
@@ -3107,37 +3277,27 @@ finish:
}
#if 0 /// UNNEEDED by elogind
-int bus_remove_match_by_string(
+#endif // 0
+_public_ int sd_bus_add_match(
sd_bus *bus,
+ sd_bus_slot **slot,
const char *match,
sd_bus_message_handler_t callback,
void *userdata) {
- struct bus_match_component *components = NULL;
- unsigned n_components = 0;
- struct match_callback *c;
- int r = 0;
-
- assert_return(bus, -EINVAL);
- assert_return(match, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- r = bus_match_parse(match, &components, &n_components);
- if (r < 0)
- goto finish;
-
- r = bus_match_find(&bus->match_callbacks, components, n_components, NULL, NULL, &c);
- if (r <= 0)
- goto finish;
-
- sd_bus_slot_unref(container_of(c, sd_bus_slot, match_callback));
+ return bus_add_match_full(bus, slot, false, match, callback, NULL, userdata);
+}
-finish:
- bus_match_parse_free(components, n_components);
+_public_ int sd_bus_add_match_async(
+ sd_bus *bus,
+ sd_bus_slot **slot,
+ const char *match,
+ sd_bus_message_handler_t callback,
+ sd_bus_message_handler_t install_callback,
+ void *userdata) {
- return r;
+ return bus_add_match_full(bus, slot, true, match, callback, install_callback, userdata);
}
-#endif // 0
bool bus_pid_changed(sd_bus *bus) {
assert(bus);
@@ -3145,7 +3305,7 @@ bool bus_pid_changed(sd_bus *bus) {
/* We don't support people creating a bus connection and
* keeping it around over a fork(). Let's complain. */
- return bus->original_pid != getpid();
+ return bus->original_pid != getpid_cached();
}
static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
@@ -3154,9 +3314,13 @@ static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userd
assert(bus);
+ /* Note that this is called both on input_fd, output_fd as well as inotify_fd events */
+
r = sd_bus_process(bus, NULL);
- if (r < 0)
- return r;
+ if (r < 0) {
+ log_debug_errno(r, "Processing of bus failed, closing down: %m");
+ bus_enter_closing(bus);
+ }
return 1;
}
@@ -3168,8 +3332,10 @@ static int time_callback(sd_event_source *s, uint64_t usec, void *userdata) {
assert(bus);
r = sd_bus_process(bus, NULL);
- if (r < 0)
- return r;
+ if (r < 0) {
+ log_debug_errno(r, "Processing of bus failed, closing down: %m");
+ bus_enter_closing(bus);
+ }
return 1;
}
@@ -3183,38 +3349,45 @@ static int prepare_callback(sd_event_source *s, void *userdata) {
assert(bus);
e = sd_bus_get_events(bus);
- if (e < 0)
- return e;
+ if (e < 0) {
+ r = e;
+ goto fail;
+ }
if (bus->output_fd != bus->input_fd) {
r = sd_event_source_set_io_events(bus->input_io_event_source, e & POLLIN);
if (r < 0)
- return r;
+ goto fail;
r = sd_event_source_set_io_events(bus->output_io_event_source, e & POLLOUT);
- if (r < 0)
- return r;
- } else {
+ } else
r = sd_event_source_set_io_events(bus->input_io_event_source, e);
- if (r < 0)
- return r;
- }
+ if (r < 0)
+ goto fail;
r = sd_bus_get_timeout(bus, &until);
if (r < 0)
- return r;
+ goto fail;
if (r > 0) {
int j;
j = sd_event_source_set_time(bus->time_event_source, until);
- if (j < 0)
- return j;
+ if (j < 0) {
+ r = j;
+ goto fail;
+ }
}
r = sd_event_source_set_enabled(bus->time_event_source, r > 0);
if (r < 0)
- return r;
+ goto fail;
+
+ return 1;
+
+fail:
+ log_debug_errno(r, "Preparing of bus events failed, closing down: %m");
+ bus_enter_closing(bus);
return 1;
}
@@ -3230,7 +3403,7 @@ static int quit_callback(sd_event_source *event, void *userdata) {
return 1;
}
-static int attach_io_events(sd_bus *bus) {
+int bus_attach_io_events(sd_bus *bus) {
int r;
assert(bus);
@@ -3284,7 +3457,7 @@ static int attach_io_events(sd_bus *bus) {
return 0;
}
-static void detach_io_events(sd_bus *bus) {
+static void bus_detach_io_events(sd_bus *bus) {
assert(bus);
if (bus->input_io_event_source) {
@@ -3298,10 +3471,49 @@ static void detach_io_events(sd_bus *bus) {
}
}
+int bus_attach_inotify_event(sd_bus *bus) {
+ int r;
+
+ assert(bus);
+
+ if (bus->inotify_fd < 0)
+ return 0;
+
+ if (!bus->event)
+ return 0;
+
+ if (!bus->inotify_event_source) {
+ r = sd_event_add_io(bus->event, &bus->inotify_event_source, bus->inotify_fd, EPOLLIN, io_callback, bus);
+ if (r < 0)
+ return r;
+
+ r = sd_event_source_set_priority(bus->inotify_event_source, bus->event_priority);
+ if (r < 0)
+ return r;
+
+ r = sd_event_source_set_description(bus->inotify_event_source, "bus-inotify");
+ } else
+ r = sd_event_source_set_io_fd(bus->inotify_event_source, bus->inotify_fd);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static void bus_detach_inotify_event(sd_bus *bus) {
+ assert(bus);
+
+ if (bus->inotify_event_source) {
+ sd_event_source_set_enabled(bus->inotify_event_source, SD_EVENT_OFF);
+ bus->inotify_event_source = sd_event_source_unref(bus->inotify_event_source);
+ }
+}
+
_public_ int sd_bus_attach_event(sd_bus *bus, sd_event *event, int priority) {
int r;
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(!bus->event, -EBUSY);
assert(!bus->input_io_event_source);
@@ -3338,7 +3550,11 @@ _public_ int sd_bus_attach_event(sd_bus *bus, sd_event *event, int priority) {
if (r < 0)
goto fail;
- r = attach_io_events(bus);
+ r = bus_attach_io_events(bus);
+ if (r < 0)
+ goto fail;
+
+ r = bus_attach_inotify_event(bus);
if (r < 0)
goto fail;
@@ -3351,11 +3567,13 @@ fail:
_public_ int sd_bus_detach_event(sd_bus *bus) {
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
if (!bus->event)
return 0;
- detach_io_events(bus);
+ bus_detach_io_events(bus);
+ bus_detach_inotify_event(bus);
if (bus->time_event_source) {
sd_event_source_set_enabled(bus->time_event_source, SD_EVENT_OFF);
@@ -3432,7 +3650,6 @@ _public_ int sd_bus_default_system(sd_bus **ret) {
return bus_default(sd_bus_open_system, &default_system_bus, ret);
}
-
_public_ int sd_bus_default_user(sd_bus **ret) {
#if 0 /// elogind does not support user buses
return bus_default(sd_bus_open_user, &default_user_bus, ret);
@@ -3442,43 +3659,11 @@ _public_ int sd_bus_default_user(sd_bus **ret) {
}
_public_ int sd_bus_default(sd_bus **ret) {
+ int (*bus_open)(sd_bus **) = NULL;
+ sd_bus **busp;
- const char *e;
-
- /* Let's try our best to reuse another cached connection. If
- * the starter bus type is set, connect via our normal
- * connection logic, ignoring $DBUS_STARTER_ADDRESS, so that
- * we can share the connection with the user/system default
- * bus. */
-
- e = secure_getenv("DBUS_STARTER_BUS_TYPE");
- if (e) {
- if (streq(e, "system"))
- return sd_bus_default_system(ret);
-#if 0 /// elogind does not support systemd units
- else if (STR_IN_SET(e, "user", "session"))
- return sd_bus_default_user(ret);
-#endif // 0
- }
-
- /* No type is specified, so we have not other option than to
- * use the starter address if it is set. */
-
- e = secure_getenv("DBUS_STARTER_ADDRESS");
- if (e) {
-
- return bus_default(sd_bus_open, &default_starter_bus, ret);
- }
-
- /* Finally, if nothing is set use the cached connection for
- * the right scope */
-
-#if 0 /// elogind does not support systemd units
- if (cg_pid_get_owner_uid(0, NULL) >= 0)
- return sd_bus_default_user(ret);
- else
-#endif // 0
- return sd_bus_default_system(ret);
+ busp = bus_choose_default(&bus_open);
+ return bus_default(bus_open, busp, ret);
}
_public_ int sd_bus_get_tid(sd_bus *b, pid_t *tid) {
@@ -3699,44 +3884,34 @@ _public_ int sd_bus_path_decode_many(const char *path, const char *path_template
}
va_end(list);
- free(labels);
- labels = NULL;
+ labels = mfree(labels);
return 1;
}
_public_ int sd_bus_try_close(sd_bus *bus) {
- int r;
-
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(!bus_pid_changed(bus), -ECHILD);
- if (!bus->is_kernel)
- return -EOPNOTSUPP;
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- if (bus->rqueue_size > 0)
- return -EBUSY;
-
- if (bus->wqueue_size > 0)
- return -EBUSY;
-
- r = bus_kernel_try_close(bus);
- if (r < 0)
- return r;
-
- sd_bus_close(bus);
- return 0;
+ return -EOPNOTSUPP;
}
_public_ int sd_bus_get_description(sd_bus *bus, const char **description) {
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(description, -EINVAL);
assert_return(bus->description, -ENXIO);
assert_return(!bus_pid_changed(bus), -ECHILD);
- *description = bus->description;
+ if (bus->description)
+ *description = bus->description;
+ else if (bus->is_system)
+ *description = "system";
+ else if (bus->is_user)
+ *description = "user";
+ else
+ *description = NULL;
+
return 0;
}
@@ -3759,32 +3934,11 @@ int bus_get_root_path(sd_bus *bus) {
}
_public_ int sd_bus_get_scope(sd_bus *bus, const char **scope) {
- int r;
-
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(scope, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
- if (bus->is_kernel) {
- _cleanup_free_ char *n = NULL;
- const char *dash;
-
- r = bus_kernel_get_bus_name(bus, &n);
- if (r < 0)
- return r;
-
- if (streq(n, "0-system")) {
- *scope = "system";
- return 0;
- }
-
- dash = strchr(n, '-');
- if (streq_ptr(dash, "-user")) {
- *scope = "user";
- return 0;
- }
- }
-
if (bus->is_user) {
*scope = "user";
return 0;
@@ -3801,6 +3955,7 @@ _public_ int sd_bus_get_scope(sd_bus *bus, const char **scope) {
_public_ int sd_bus_get_address(sd_bus *bus, const char **address) {
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(address, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -3814,6 +3969,7 @@ _public_ int sd_bus_get_address(sd_bus *bus, const char **address) {
_public_ int sd_bus_get_creds_mask(sd_bus *bus, uint64_t *mask) {
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(mask, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -3823,6 +3979,7 @@ _public_ int sd_bus_get_creds_mask(sd_bus *bus, uint64_t *mask) {
_public_ int sd_bus_is_bus_client(sd_bus *bus) {
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(!bus_pid_changed(bus), -ECHILD);
return bus->bus_client;
@@ -3830,6 +3987,7 @@ _public_ int sd_bus_is_bus_client(sd_bus *bus) {
_public_ int sd_bus_is_server(sd_bus *bus) {
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(!bus_pid_changed(bus), -ECHILD);
return bus->is_server;
@@ -3837,6 +3995,7 @@ _public_ int sd_bus_is_server(sd_bus *bus) {
_public_ int sd_bus_is_anonymous(sd_bus *bus) {
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(!bus_pid_changed(bus), -ECHILD);
return bus->anonymous_auth;
@@ -3844,6 +4003,7 @@ _public_ int sd_bus_is_anonymous(sd_bus *bus) {
_public_ int sd_bus_is_trusted(sd_bus *bus) {
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(!bus_pid_changed(bus), -ECHILD);
return bus->trusted;
@@ -3851,9 +4011,10 @@ _public_ int sd_bus_is_trusted(sd_bus *bus) {
_public_ int sd_bus_is_monitor(sd_bus *bus) {
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(!bus_pid_changed(bus), -ECHILD);
- return !!(bus->hello_flags & KDBUS_HELLO_MONITOR);
+ return bus->is_monitor;
}
static void flush_close(sd_bus *bus) {
@@ -3869,7 +4030,7 @@ static void flush_close(sd_bus *bus) {
_public_ void sd_bus_default_flush_close(void) {
flush_close(default_starter_bus);
-#if 0 /// There is no user bus with elogind
+#if 0 /// elogind does not support user buses
flush_close(default_user_bus);
#endif // 0
flush_close(default_system_bus);
@@ -3877,6 +4038,7 @@ _public_ void sd_bus_default_flush_close(void) {
_public_ int sd_bus_set_exit_on_disconnect(sd_bus *bus, int b) {
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
/* Turns on exit-on-disconnect, and triggers it immediately if the bus connection was already
* disconnected. Note that this is triggered exclusively on disconnections triggered by the server side, never
@@ -3889,6 +4051,48 @@ _public_ int sd_bus_set_exit_on_disconnect(sd_bus *bus, int b) {
_public_ int sd_bus_get_exit_on_disconnect(sd_bus *bus) {
assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
return bus->exit_on_disconnect;
}
+
+_public_ int sd_bus_set_sender(sd_bus *bus, const char *sender) {
+ assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
+ assert_return(!bus->bus_client, -EPERM);
+ assert_return(!sender || service_name_is_valid(sender), -EINVAL);
+
+ return free_and_strdup(&bus->patch_sender, sender);
+}
+
+_public_ int sd_bus_get_sender(sd_bus *bus, const char **ret) {
+ assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
+ assert_return(ret, -EINVAL);
+
+ if (!bus->patch_sender)
+ return -ENODATA;
+
+ *ret = bus->patch_sender;
+ return 0;
+}
+
+_public_ int sd_bus_get_n_queued_read(sd_bus *bus, uint64_t *ret) {
+ assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
+ assert_return(ret, -EINVAL);
+
+ *ret = bus->rqueue_size;
+ return 0;
+}
+
+_public_ int sd_bus_get_n_queued_write(sd_bus *bus, uint64_t *ret) {
+ assert_return(bus, -EINVAL);
+ assert_return(bus = bus_resolve(bus), -ENOPKG);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
+ assert_return(ret, -EINVAL);
+
+ *ret = bus->wqueue_size;
+ return 0;
+}
diff --git a/src/libelogind/sd-bus/test-bus-error.c b/src/libelogind/sd-bus/test-bus-error.c
index f7c889b7c..6d2f59688 100644
--- a/src/libelogind/sd-bus/test-bus-error.c
+++ b/src/libelogind/sd-bus/test-bus-error.c
@@ -1,20 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-bus.h"
diff --git a/src/libelogind/sd-bus/test-bus-introspect.c b/src/libelogind/sd-bus/test-bus-introspect.c
index 4425cfae2..00167cb64 100644
--- a/src/libelogind/sd-bus/test-bus-introspect.c
+++ b/src/libelogind/sd-bus/test-bus-introspect.c
@@ -1,20 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "bus-introspect.h"
diff --git a/src/libelogind/sd-bus/test-bus-match.c b/src/libelogind/sd-bus/test-bus-match.c
index 29c4529f9..2822a8f82 100644
--- a/src/libelogind/sd-bus/test-bus-match.c
+++ b/src/libelogind/sd-bus/test-bus-match.c
@@ -1,20 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "bus-match.h"
@@ -94,7 +79,7 @@ int main(int argc, char *argv[]) {
sd_bus_slot slots[19];
int r;
- r = sd_bus_open_system(&bus);
+ r = sd_bus_open_user(&bus);
if (r < 0)
return EXIT_TEST_SKIP;
@@ -121,7 +106,7 @@ int main(int argc, char *argv[]) {
assert_se(sd_bus_message_new_signal(bus, &m, "/foo/bar", "bar.x", "waldo") >= 0);
assert_se(sd_bus_message_append(m, "ssssas", "one", "two", "/prefix/three", "prefix.four", 3, "pi", "pa", "po") >= 0);
- assert_se(bus_message_seal(m, 1, 0) >= 0);
+ assert_se(sd_bus_message_seal(m, 1, 0) >= 0);
zero(mask);
assert_se(bus_match_run(NULL, &root, m) == 0);
diff --git a/src/libelogind/sd-bus/test-bus-server.c b/src/libelogind/sd-bus/test-bus-server.c
index b6272efc3..31b54e252 100644
--- a/src/libelogind/sd-bus/test-bus-server.c
+++ b/src/libelogind/sd-bus/test-bus-server.c
@@ -1,20 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <pthread.h>
@@ -80,7 +65,8 @@ static void *server(void *p) {
if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Exit")) {
- assert_se((sd_bus_can_send(bus, 'h') >= 1) == (c->server_negotiate_unix_fds && c->client_negotiate_unix_fds));
+ assert_se((sd_bus_can_send(bus, 'h') >= 1) ==
+ (c->server_negotiate_unix_fds && c->client_negotiate_unix_fds));
r = sd_bus_message_new_method_return(m, &reply);
if (r < 0) {
diff --git a/src/libelogind/sd-bus/test-bus-signature.c b/src/libelogind/sd-bus/test-bus-signature.c
index 4f4fd093b..1ba190919 100644
--- a/src/libelogind/sd-bus/test-bus-signature.c
+++ b/src/libelogind/sd-bus/test-bus-signature.c
@@ -1,20 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "bus-internal.h"
diff --git a/src/libelogind/sd-bus/test-bus-vtable.c b/src/libelogind/sd-bus/test-bus-vtable.c
index fd9ad8121..5604aa668 100644
--- a/src/libelogind/sd-bus/test-bus-vtable.c
+++ b/src/libelogind/sd-bus/test-bus-vtable.c
@@ -8,7 +8,15 @@
#include "sd-bus-vtable.h"
+#if 0 /// elogind should support both /run/dbus & /var/run/dbus (per Linux FHS)
#define DEFAULT_BUS_PATH "unix:path=/run/dbus/system_bus_socket"
+#else
+#if VARRUN_IS_SYMLINK
+ #define DEFAULT_BUS_PATH "unix:path=/run/dbus/system_bus_socket"
+#else
+ #define DEFAULT_BUS_PATH "unix:path=/var/run/dbus/system_bus_socket"
+#endif // VARRUN_IS_SYMLINK
+#endif // 0
struct context {
bool quit;
diff --git a/src/libelogind/sd-daemon/Makefile b/src/libelogind/sd-daemon/Makefile
deleted file mode 120000
index 94aaae2c4..000000000
--- a/src/libelogind/sd-daemon/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../../Makefile \ No newline at end of file
diff --git a/src/libelogind/sd-daemon/sd-daemon.c b/src/libelogind/sd-daemon/sd-daemon.c
index 47fc3a422..b9815ebaa 100644
--- a/src/libelogind/sd-daemon/sd-daemon.c
+++ b/src/libelogind/sd-daemon/sd-daemon.c
@@ -1,20 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- 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>
@@ -38,10 +23,14 @@
#include "fs-util.h"
#include "parse-util.h"
#include "path-util.h"
+//#include "process-util.h"
#include "socket-util.h"
#include "strv.h"
#include "util.h"
+/// Additional includes needed by elogind
+#include "process-util.h"
+
#define SNDBUF_SIZE (8*1024*1024)
static void unsetenv_all(bool unset_environment) {
@@ -70,7 +59,7 @@ _public_ int sd_listen_fds(int unset_environment) {
goto finish;
/* Is this for us? */
- if (getpid() != pid) {
+ if (getpid_cached() != pid) {
r = 0;
goto finish;
}
@@ -139,8 +128,7 @@ _public_ int sd_listen_fds_with_names(int unset_environment, char ***names) {
return r;
}
- *names = l;
- l = NULL;
+ *names = TAKE_PTR(l);
return n_fds;
}
@@ -161,7 +149,7 @@ _public_ int sd_is_fifo(int fd, const char *path) {
if (stat(path, &st_path) < 0) {
- if (errno == ENOENT || errno == ENOTDIR)
+ if (IN_SET(errno, ENOENT, ENOTDIR))
return 0;
return -errno;
@@ -191,7 +179,7 @@ _public_ int sd_is_special(int fd, const char *path) {
if (stat(path, &st_path) < 0) {
- if (errno == ENOENT || errno == ENOTDIR)
+ if (IN_SET(errno, ENOENT, ENOTDIR))
return 0;
return -errno;
@@ -297,8 +285,7 @@ _public_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint
if (l < sizeof(sa_family_t))
return -EINVAL;
- if (sockaddr.sa.sa_family != AF_INET &&
- sockaddr.sa.sa_family != AF_INET6)
+ if (!IN_SET(sockaddr.sa.sa_family, AF_INET, AF_INET6))
return 0;
if (family != 0)
@@ -306,17 +293,13 @@ _public_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint
return 0;
if (port > 0) {
- if (sockaddr.sa.sa_family == AF_INET) {
- if (l < sizeof(struct sockaddr_in))
- return -EINVAL;
+ unsigned sa_port;
- return htobe16(port) == sockaddr.in.sin_port;
- } else {
- if (l < sizeof(struct sockaddr_in6))
- return -EINVAL;
+ r = sockaddr_port(&sockaddr.sa, &sa_port);
+ if (r < 0)
+ return r;
- return htobe16(port) == sockaddr.in6.sin6_port;
- }
+ return port == sa_port;
}
return 1;
@@ -463,7 +446,13 @@ _public_ int sd_is_mq(int fd, const char *path) {
}
#endif // 0
-_public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char *state, const int *fds, unsigned n_fds) {
+_public_ int sd_pid_notify_with_fds(
+ pid_t pid,
+ int unset_environment,
+ const char *state,
+ const int *fds,
+ unsigned n_fds) {
+
union sockaddr_union sockaddr = {
.sa.sa_family = AF_UNIX,
};
@@ -478,7 +467,7 @@ _public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char
_cleanup_close_ int fd = -1;
struct cmsghdr *cmsg = NULL;
const char *e;
- bool have_pid;
+ bool send_ucred;
int r;
if (!state) {
@@ -496,7 +485,7 @@ _public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char
return 0;
/* Must be an abstract socket, or an absolute path */
- if ((e[0] != '@' && e[0] != '/') || e[1] == 0) {
+ if (!IN_SET(e[0], '@', '/') || e[1] == 0) {
r = -EINVAL;
goto finish;
}
@@ -512,7 +501,7 @@ _public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char
goto finish;
}
- fd_inc_sndbuf(fd, SNDBUF_SIZE);
+ (void) fd_inc_sndbuf(fd, SNDBUF_SIZE);
iovec.iov_len = strlen(state);
@@ -522,13 +511,16 @@ _public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char
msghdr.msg_namelen = SOCKADDR_UN_LEN(sockaddr.un);
- have_pid = pid != 0 && pid != getpid();
+ send_ucred =
+ (pid != 0 && pid != getpid_cached()) ||
+ getuid() != geteuid() ||
+ getgid() != getegid();
- if (n_fds > 0 || have_pid) {
+ if (n_fds > 0 || send_ucred) {
/* CMSG_SPACE(0) may return value different than zero, which results in miscalculated controllen. */
msghdr.msg_controllen =
(n_fds > 0 ? CMSG_SPACE(sizeof(int) * n_fds) : 0) +
- (have_pid ? CMSG_SPACE(sizeof(struct ucred)) : 0);
+ (send_ucred ? CMSG_SPACE(sizeof(struct ucred)) : 0);
msghdr.msg_control = alloca0(msghdr.msg_controllen);
@@ -540,11 +532,11 @@ _public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char
memcpy(CMSG_DATA(cmsg), fds, sizeof(int) * n_fds);
- if (have_pid)
+ if (send_ucred)
assert_se(cmsg = CMSG_NXTHDR(&msghdr, cmsg));
}
- if (have_pid) {
+ if (send_ucred) {
struct ucred *ucred;
cmsg->cmsg_level = SOL_SOCKET;
@@ -552,7 +544,7 @@ _public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char
cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
ucred = (struct ucred*) CMSG_DATA(cmsg);
- ucred->pid = pid;
+ ucred->pid = pid != 0 ? pid : getpid_cached();
ucred->uid = getuid();
ucred->gid = getgid();
}
@@ -565,7 +557,7 @@ _public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char
}
/* If that failed, try with our own ucred instead */
- if (have_pid) {
+ if (send_ucred) {
msghdr.msg_controllen -= CMSG_SPACE(sizeof(struct ucred));
if (msghdr.msg_controllen == 0)
msghdr.msg_control = NULL;
@@ -635,6 +627,7 @@ _public_ int sd_booted(void) {
* created. This takes place in mount-setup.c, so is
* guaranteed to happen very early during boot. */
+#if 0 /// elogind is always used without systemd running the show. (Well, it should...)
return laccess("/run/systemd/system/", F_OK) >= 0;
#else
return 0;
@@ -667,7 +660,7 @@ _public_ int sd_watchdog_enabled(int unset_environment, uint64_t *usec) {
goto finish;
/* Is this for us? */
- if (getpid() != pid) {
+ if (getpid_cached() != pid) {
r = 0;
goto finish;
}
diff --git a/src/libelogind/sd-event/Makefile b/src/libelogind/sd-event/Makefile
deleted file mode 120000
index 94aaae2c4..000000000
--- a/src/libelogind/sd-event/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../../Makefile \ No newline at end of file
diff --git a/src/libelogind/sd-event/sd-event.c b/src/libelogind/sd-event/sd-event.c
index b4686d006..d53b9a702 100644
--- a/src/libelogind/sd-event/sd-event.c
+++ b/src/libelogind/sd-event/sd-event.c
@@ -1,20 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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>
@@ -27,6 +12,7 @@
#include "alloc-util.h"
#include "fd-util.h"
+#include "fs-util.h"
#include "hashmap.h"
#include "list.h"
#include "macro.h"
@@ -55,6 +41,7 @@ typedef enum EventSourceType {
SOURCE_POST,
SOURCE_EXIT,
SOURCE_WATCHDOG,
+ SOURCE_INOTIFY,
_SOURCE_EVENT_SOURCE_TYPE_MAX,
_SOURCE_EVENT_SOURCE_TYPE_INVALID = -1
} EventSourceType;
@@ -72,6 +59,7 @@ static const char* const event_source_type_table[_SOURCE_EVENT_SOURCE_TYPE_MAX]
[SOURCE_POST] = "post",
[SOURCE_EXIT] = "exit",
[SOURCE_WATCHDOG] = "watchdog",
+ [SOURCE_INOTIFY] = "inotify",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(event_source_type, int);
@@ -83,12 +71,15 @@ typedef enum WakeupType {
WAKEUP_EVENT_SOURCE,
WAKEUP_CLOCK_DATA,
WAKEUP_SIGNAL_DATA,
+ WAKEUP_INOTIFY_DATA,
_WAKEUP_TYPE_MAX,
_WAKEUP_TYPE_INVALID = -1,
} WakeupType;
#define EVENT_SOURCE_IS_TIME(t) IN_SET((t), SOURCE_TIME_REALTIME, SOURCE_TIME_BOOTTIME, SOURCE_TIME_MONOTONIC, SOURCE_TIME_REALTIME_ALARM, SOURCE_TIME_BOOTTIME_ALARM)
+struct inode_data;
+
struct sd_event_source {
WakeupType wakeup;
@@ -112,6 +103,8 @@ struct sd_event_source {
uint64_t pending_iteration;
uint64_t prepare_iteration;
+ sd_event_destroy_t destroy_callback;
+
LIST_FIELDS(sd_event_source, sources);
union {
@@ -121,6 +114,7 @@ struct sd_event_source {
uint32_t events;
uint32_t revents;
bool registered:1;
+ bool owned:1;
} io;
struct {
sd_event_time_handler_t callback;
@@ -149,6 +143,12 @@ struct sd_event_source {
sd_event_handler_t callback;
unsigned prioq_index;
} exit;
+ struct {
+ sd_event_inotify_handler_t callback;
+ uint32_t mask;
+ struct inode_data *inode_data;
+ LIST_FIELDS(sd_event_source, by_inode_data);
+ } inotify;
};
};
@@ -183,6 +183,64 @@ struct signal_data {
sd_event_source *current;
};
+/* A structure listing all event sources currently watching a specific inode */
+struct inode_data {
+ /* The identifier for the inode, the combination of the .st_dev + .st_ino fields of the file */
+ ino_t ino;
+ dev_t dev;
+
+ /* An fd of the inode to watch. The fd is kept open until the next iteration of the loop, so that we can
+ * rearrange the priority still until then, as we need the original inode to change the priority as we need to
+ * add a watch descriptor to the right inotify for the priority which we can only do if we have a handle to the
+ * original inode. We keep a list of all inode_data objects with an open fd in the to_close list (see below) of
+ * the sd-event object, so that it is efficient to close everything, before entering the next event loop
+ * iteration. */
+ int fd;
+
+ /* The inotify "watch descriptor" */
+ int wd;
+
+ /* The combination of the mask of all inotify watches on this inode we manage. This is also the mask that has
+ * most recently been set on the watch descriptor. */
+ uint32_t combined_mask;
+
+ /* All event sources subscribed to this inode */
+ LIST_HEAD(sd_event_source, event_sources);
+
+ /* The inotify object we watch this inode with */
+ struct inotify_data *inotify_data;
+
+ /* A linked list of all inode data objects with fds to close (see above) */
+ LIST_FIELDS(struct inode_data, to_close);
+};
+
+/* A structure encapsulating an inotify fd */
+struct inotify_data {
+ WakeupType wakeup;
+
+ /* For each priority we maintain one inotify fd, so that we only have to dequeue a single event per priority at
+ * a time */
+
+ int fd;
+ int64_t priority;
+
+ Hashmap *inodes; /* The inode_data structures keyed by dev+ino */
+ Hashmap *wd; /* The inode_data structures keyed by the watch descriptor for each */
+
+ /* The buffer we read inotify events into */
+ union inotify_event_buffer buffer;
+ size_t buffer_filled; /* fill level of the buffer */
+
+ /* How many event sources are currently marked pending for this inotify. We won't read new events off the
+ * inotify fd as long as there are still pending events on the inotify (because we have no strategy of queuing
+ * the events locally if they can't be coalesced). */
+ unsigned n_pending;
+
+ /* A linked list of all inotify objects with data already read, that still need processing. We keep this list
+ * to make it efficient to figure out what inotify objects to process data on next. */
+ LIST_FIELDS(struct inotify_data, buffered);
+};
+
struct sd_event {
unsigned n_ref;
@@ -213,6 +271,14 @@ struct sd_event {
Prioq *exit;
+ Hashmap *inotify_data; /* indexed by priority */
+
+ /* A list of inode structures that still have an fd open, that we need to close before the next loop iteration */
+ LIST_HEAD(struct inode_data, inode_data_to_close);
+
+ /* A list of inotify objects that already have events buffered which aren't processed yet */
+ LIST_HEAD(struct inotify_data, inotify_data_buffered);
+
pid_t original_pid;
uint64_t iteration;
@@ -239,7 +305,14 @@ struct sd_event {
unsigned delays[sizeof(usec_t) * 8];
};
+static thread_local sd_event *default_event = NULL;
+
static void source_disconnect(sd_event_source *s);
+static void event_gc_inode_data(sd_event *e, struct inode_data *d);
+
+static sd_event *event_resolve(sd_event *e) {
+ return e == SD_EVENT_DEFAULT ? default_event : e;
+}
static int pending_prioq_compare(const void *a, const void *b) {
const sd_event_source *x = a, *y = b;
@@ -417,6 +490,8 @@ static void event_free(sd_event *e) {
free(e->signal_sources);
hashmap_free(e->signal_data);
+ hashmap_free(e->inotify_data);
+
hashmap_free(e->child_sources);
set_free(e->post_sources);
free(e);
@@ -428,16 +503,32 @@ _public_ int sd_event_new(sd_event** ret) {
assert_return(ret, -EINVAL);
- e = new0(sd_event, 1);
+ e = new(sd_event, 1);
if (!e)
return -ENOMEM;
- e->n_ref = 1;
- e->watchdog_fd = e->epoll_fd = e->realtime.fd = e->boottime.fd = e->monotonic.fd = e->realtime_alarm.fd = e->boottime_alarm.fd = -1;
- e->realtime.next = e->boottime.next = e->monotonic.next = e->realtime_alarm.next = e->boottime_alarm.next = USEC_INFINITY;
- e->realtime.wakeup = e->boottime.wakeup = e->monotonic.wakeup = e->realtime_alarm.wakeup = e->boottime_alarm.wakeup = WAKEUP_CLOCK_DATA;
- e->original_pid = getpid();
- e->perturb = USEC_INFINITY;
+ *e = (sd_event) {
+ .n_ref = 1,
+ .epoll_fd = -1,
+ .watchdog_fd = -1,
+ .realtime.wakeup = WAKEUP_CLOCK_DATA,
+ .realtime.fd = -1,
+ .realtime.next = USEC_INFINITY,
+ .boottime.wakeup = WAKEUP_CLOCK_DATA,
+ .boottime.fd = -1,
+ .boottime.next = USEC_INFINITY,
+ .monotonic.wakeup = WAKEUP_CLOCK_DATA,
+ .monotonic.fd = -1,
+ .monotonic.next = USEC_INFINITY,
+ .realtime_alarm.wakeup = WAKEUP_CLOCK_DATA,
+ .realtime_alarm.fd = -1,
+ .realtime_alarm.next = USEC_INFINITY,
+ .boottime_alarm.wakeup = WAKEUP_CLOCK_DATA,
+ .boottime_alarm.fd = -1,
+ .boottime_alarm.next = USEC_INFINITY,
+ .perturb = USEC_INFINITY,
+ .original_pid = getpid_cached(),
+ };
r = prioq_ensure_allocated(&e->pending, pending_prioq_compare);
if (r < 0)
@@ -449,6 +540,8 @@ _public_ int sd_event_new(sd_event** ret) {
goto fail;
}
+ e->epoll_fd = fd_move_above_stdio(e->epoll_fd);
+
if (secure_getenv("SD_EVENT_PROFILE_DELAYS")) {
log_debug("Event loop profiling enabled. Logarithmic histogram of event loop iterations in the range 2^0 ... 2^63 us will be logged every 5s.");
e->profile_delays = true;
@@ -493,7 +586,7 @@ static bool event_pid_changed(sd_event *e) {
/* We don't support people creating an event loop and keeping
* it around over a fork(). Let's complain. */
- return e->original_pid != getpid();
+ return e->original_pid != getpid_cached();
}
static void source_io_unregister(sd_event_source *s) {
@@ -521,18 +614,17 @@ static int source_io_register(
int enabled,
uint32_t events) {
- struct epoll_event ev = {};
+ struct epoll_event ev;
int r;
assert(s);
assert(s->type == SOURCE_IO);
assert(enabled != SD_EVENT_OFF);
- ev.events = events;
- ev.data.ptr = s;
-
- if (enabled == SD_EVENT_ONESHOT)
- ev.events |= EPOLLONESHOT;
+ ev = (struct epoll_event) {
+ .events = events | (enabled == SD_EVENT_ONESHOT ? EPOLLONESHOT : 0),
+ .data.ptr = s,
+ };
if (s->io.registered)
r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_MOD, s->io.fd, &ev);
@@ -624,7 +716,7 @@ static int event_make_signal_data(
int sig,
struct signal_data **ret) {
- struct epoll_event ev = {};
+ struct epoll_event ev;
struct signal_data *d;
bool added = false;
sigset_t ss_copy;
@@ -639,7 +731,7 @@ static int event_make_signal_data(
if (e->signal_sources && e->signal_sources[sig])
priority = e->signal_sources[sig]->priority;
else
- priority = 0;
+ priority = SD_EVENT_PRIORITY_NORMAL;
d = hashmap_get(e->signal_data, &priority);
if (d) {
@@ -653,13 +745,15 @@ static int event_make_signal_data(
if (r < 0)
return r;
- d = new0(struct signal_data, 1);
+ d = new(struct signal_data, 1);
if (!d)
return -ENOMEM;
- d->wakeup = WAKEUP_SIGNAL_DATA;
- d->fd = -1;
- d->priority = priority;
+ *d = (struct signal_data) {
+ .wakeup = WAKEUP_SIGNAL_DATA,
+ .fd = -1,
+ .priority = priority,
+ };
r = hashmap_put(e->signal_data, &d->priority, d);
if (r < 0) {
@@ -687,10 +781,12 @@ static int event_make_signal_data(
return 0;
}
- d->fd = r;
+ d->fd = fd_move_above_stdio(r);
- ev.events = EPOLLIN;
- ev.data.ptr = d;
+ ev = (struct epoll_event) {
+ .events = EPOLLIN,
+ .data.ptr = d,
+ };
r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, d->fd, &ev);
if (r < 0) {
@@ -857,6 +953,41 @@ static void source_disconnect(sd_event_source *s) {
prioq_remove(s->event->exit, s, &s->exit.prioq_index);
break;
+ case SOURCE_INOTIFY: {
+ struct inode_data *inode_data;
+
+ inode_data = s->inotify.inode_data;
+ if (inode_data) {
+ struct inotify_data *inotify_data;
+ assert_se(inotify_data = inode_data->inotify_data);
+
+ /* Detach this event source from the inode object */
+ LIST_REMOVE(inotify.by_inode_data, inode_data->event_sources, s);
+ s->inotify.inode_data = NULL;
+
+ if (s->pending) {
+ assert(inotify_data->n_pending > 0);
+ inotify_data->n_pending--;
+ }
+
+ /* Note that we don't reduce the inotify mask for the watch descriptor here if the inode is
+ * continued to being watched. That's because inotify doesn't really have an API for that: we
+ * can only change watch masks with access to the original inode either by fd or by path. But
+ * paths aren't stable, and keeping an O_PATH fd open all the time would mean wasting an fd
+ * continously and keeping the mount busy which we can't really do. We could reconstruct the
+ * original inode from /proc/self/fdinfo/$INOTIFY_FD (as all watch descriptors are listed
+ * there), but given the need for open_by_handle_at() which is privileged and not universally
+ * available this would be quite an incomplete solution. Hence we go the other way, leave the
+ * mask set, even if it is not minimized now, and ignore all events we aren't interested in
+ * anymore after reception. Yes, this sucks, but … Linux … */
+
+ /* Maybe release the inode data (and its inotify) */
+ event_gc_inode_data(s->event, inode_data);
+ }
+
+ break;
+ }
+
default:
assert_not_reached("Wut? I shouldn't exist.");
}
@@ -882,6 +1013,13 @@ static void source_free(sd_event_source *s) {
assert(s);
source_disconnect(s);
+
+ if (s->type == SOURCE_IO && s->io.owned)
+ s->io.fd = safe_close(s->io.fd);
+
+ if (s->destroy_callback)
+ s->destroy_callback(s->userdata);
+
free(s->description);
free(s);
}
@@ -927,6 +1065,19 @@ static int source_set_pending(sd_event_source *s, bool b) {
d->current = NULL;
}
+ if (s->type == SOURCE_INOTIFY) {
+
+ assert(s->inotify.inode_data);
+ assert(s->inotify.inode_data->inotify_data);
+
+ if (b)
+ s->inotify.inode_data->inotify_data->n_pending ++;
+ else {
+ assert(s->inotify.inode_data->inotify_data->n_pending > 0);
+ s->inotify.inode_data->inotify_data->n_pending --;
+ }
+ }
+
return 0;
}
@@ -935,15 +1086,18 @@ static sd_event_source *source_new(sd_event *e, bool floating, EventSourceType t
assert(e);
- s = new0(sd_event_source, 1);
+ s = new(sd_event_source, 1);
if (!s)
return NULL;
- s->n_ref = 1;
- s->event = e;
- s->floating = floating;
- s->type = type;
- s->pending_index = s->prepare_index = PRIOQ_IDX_NULL;
+ *s = (struct sd_event_source) {
+ .n_ref = 1,
+ .event = e,
+ .floating = floating,
+ .type = type,
+ .pending_index = PRIOQ_IDX_NULL,
+ .prepare_index = PRIOQ_IDX_NULL,
+ };
if (!floating)
sd_event_ref(e);
@@ -966,6 +1120,7 @@ _public_ int sd_event_add_io(
int r;
assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
assert_return(fd >= 0, -EBADF);
assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL);
assert_return(callback, -EINVAL);
@@ -1019,7 +1174,7 @@ static int event_setup_timer_fd(
struct clock_data *d,
clockid_t clock) {
- struct epoll_event ev = {};
+ struct epoll_event ev;
int r, fd;
assert(e);
@@ -1032,8 +1187,12 @@ static int event_setup_timer_fd(
if (fd < 0)
return -errno;
- ev.events = EPOLLIN;
- ev.data.ptr = d;
+ fd = fd_move_above_stdio(fd);
+
+ ev = (struct epoll_event) {
+ .events = EPOLLIN,
+ .data.ptr = d,
+ };
r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, fd, &ev);
if (r < 0) {
@@ -1066,6 +1225,7 @@ _public_ int sd_event_add_time(
int r;
assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
assert_return(accuracy != (uint64_t) -1, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
@@ -1147,6 +1307,7 @@ _public_ int sd_event_add_signal(
int r;
assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
assert_return(SIGNAL_VALID(sig), -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
@@ -1206,6 +1367,7 @@ _public_ int sd_event_add_child(
int r;
assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
assert_return(pid > 1, -EINVAL);
assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL);
assert_return(options != 0, -EINVAL);
@@ -1263,6 +1425,7 @@ _public_ int sd_event_add_defer(
int r;
assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
assert_return(callback, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
@@ -1297,6 +1460,7 @@ _public_ int sd_event_add_post(
int r;
assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
assert_return(callback, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
@@ -1335,6 +1499,7 @@ _public_ int sd_event_add_exit(
int r;
assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
assert_return(callback, -EINVAL);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
@@ -1364,6 +1529,405 @@ _public_ int sd_event_add_exit(
return 0;
}
+static void event_free_inotify_data(sd_event *e, struct inotify_data *d) {
+ assert(e);
+
+ if (!d)
+ return;
+
+ assert(hashmap_isempty(d->inodes));
+ assert(hashmap_isempty(d->wd));
+
+ if (d->buffer_filled > 0)
+ LIST_REMOVE(buffered, e->inotify_data_buffered, d);
+
+ hashmap_free(d->inodes);
+ hashmap_free(d->wd);
+
+ assert_se(hashmap_remove(e->inotify_data, &d->priority) == d);
+
+ if (d->fd >= 0) {
+ if (epoll_ctl(e->epoll_fd, EPOLL_CTL_DEL, d->fd, NULL) < 0)
+ log_debug_errno(errno, "Failed to remove inotify fd from epoll, ignoring: %m");
+
+ safe_close(d->fd);
+ }
+ free(d);
+}
+
+static int event_make_inotify_data(
+ sd_event *e,
+ int64_t priority,
+ struct inotify_data **ret) {
+
+ _cleanup_close_ int fd = -1;
+ struct inotify_data *d;
+ struct epoll_event ev;
+ int r;
+
+ assert(e);
+
+ d = hashmap_get(e->inotify_data, &priority);
+ if (d) {
+ if (ret)
+ *ret = d;
+ return 0;
+ }
+
+ fd = inotify_init1(IN_NONBLOCK|O_CLOEXEC);
+ if (fd < 0)
+ return -errno;
+
+ fd = fd_move_above_stdio(fd);
+
+ r = hashmap_ensure_allocated(&e->inotify_data, &uint64_hash_ops);
+ if (r < 0)
+ return r;
+
+ d = new(struct inotify_data, 1);
+ if (!d)
+ return -ENOMEM;
+
+ *d = (struct inotify_data) {
+ .wakeup = WAKEUP_INOTIFY_DATA,
+ .fd = TAKE_FD(fd),
+ .priority = priority,
+ };
+
+ r = hashmap_put(e->inotify_data, &d->priority, d);
+ if (r < 0) {
+ d->fd = safe_close(d->fd);
+ free(d);
+ return r;
+ }
+
+ ev = (struct epoll_event) {
+ .events = EPOLLIN,
+ .data.ptr = d,
+ };
+
+ if (epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, d->fd, &ev) < 0) {
+ r = -errno;
+ d->fd = safe_close(d->fd); /* let's close this ourselves, as event_free_inotify_data() would otherwise
+ * remove the fd from the epoll first, which we don't want as we couldn't
+ * add it in the first place. */
+ event_free_inotify_data(e, d);
+ return r;
+ }
+
+ if (ret)
+ *ret = d;
+
+ return 1;
+}
+
+static int inode_data_compare(const void *a, const void *b) {
+ const struct inode_data *x = a, *y = b;
+
+ assert(x);
+ assert(y);
+
+ if (x->dev < y->dev)
+ return -1;
+ if (x->dev > y->dev)
+ return 1;
+
+ if (x->ino < y->ino)
+ return -1;
+ if (x->ino > y->ino)
+ return 1;
+
+ return 0;
+}
+
+static void inode_data_hash_func(const void *p, struct siphash *state) {
+ const struct inode_data *d = p;
+
+ assert(p);
+
+ siphash24_compress(&d->dev, sizeof(d->dev), state);
+ siphash24_compress(&d->ino, sizeof(d->ino), state);
+}
+
+const struct hash_ops inode_data_hash_ops = {
+ .hash = inode_data_hash_func,
+ .compare = inode_data_compare
+};
+
+static void event_free_inode_data(
+ sd_event *e,
+ struct inode_data *d) {
+
+ assert(e);
+
+ if (!d)
+ return;
+
+ assert(!d->event_sources);
+
+ if (d->fd >= 0) {
+ LIST_REMOVE(to_close, e->inode_data_to_close, d);
+ safe_close(d->fd);
+ }
+
+ if (d->inotify_data) {
+
+ if (d->wd >= 0) {
+ if (d->inotify_data->fd >= 0) {
+ /* So here's a problem. At the time this runs the watch descriptor might already be
+ * invalidated, because an IN_IGNORED event might be queued right the moment we enter
+ * the syscall. Hence, whenever we get EINVAL, ignore it entirely, since it's a very
+ * likely case to happen. */
+
+ if (inotify_rm_watch(d->inotify_data->fd, d->wd) < 0 && errno != EINVAL)
+ log_debug_errno(errno, "Failed to remove watch descriptor %i from inotify, ignoring: %m", d->wd);
+ }
+
+ assert_se(hashmap_remove(d->inotify_data->wd, INT_TO_PTR(d->wd)) == d);
+ }
+
+ assert_se(hashmap_remove(d->inotify_data->inodes, d) == d);
+ }
+
+ free(d);
+}
+
+static void event_gc_inode_data(
+ sd_event *e,
+ struct inode_data *d) {
+
+ struct inotify_data *inotify_data;
+
+ assert(e);
+
+ if (!d)
+ return;
+
+ if (d->event_sources)
+ return;
+
+ inotify_data = d->inotify_data;
+ event_free_inode_data(e, d);
+
+ if (inotify_data && hashmap_isempty(inotify_data->inodes))
+ event_free_inotify_data(e, inotify_data);
+}
+
+static int event_make_inode_data(
+ sd_event *e,
+ struct inotify_data *inotify_data,
+ dev_t dev,
+ ino_t ino,
+ struct inode_data **ret) {
+
+ struct inode_data *d, key;
+ int r;
+
+ assert(e);
+ assert(inotify_data);
+
+ key = (struct inode_data) {
+ .ino = ino,
+ .dev = dev,
+ };
+
+ d = hashmap_get(inotify_data->inodes, &key);
+ if (d) {
+ if (ret)
+ *ret = d;
+
+ return 0;
+ }
+
+ r = hashmap_ensure_allocated(&inotify_data->inodes, &inode_data_hash_ops);
+ if (r < 0)
+ return r;
+
+ d = new(struct inode_data, 1);
+ if (!d)
+ return -ENOMEM;
+
+ *d = (struct inode_data) {
+ .dev = dev,
+ .ino = ino,
+ .wd = -1,
+ .fd = -1,
+ .inotify_data = inotify_data,
+ };
+
+ r = hashmap_put(inotify_data->inodes, d, d);
+ if (r < 0) {
+ free(d);
+ return r;
+ }
+
+ if (ret)
+ *ret = d;
+
+ return 1;
+}
+
+static uint32_t inode_data_determine_mask(struct inode_data *d) {
+ bool excl_unlink = true;
+ uint32_t combined = 0;
+ sd_event_source *s;
+
+ assert(d);
+
+ /* Combines the watch masks of all event sources watching this inode. We generally just OR them together, but
+ * the IN_EXCL_UNLINK flag is ANDed instead.
+ *
+ * Note that we add all sources to the mask here, regardless whether enabled, disabled or oneshot. That's
+ * because we cannot change the mask anymore after the event source was created once, since the kernel has no
+ * API for that. Hence we need to subscribe to the maximum mask we ever might be interested in, and supress
+ * events we don't care for client-side. */
+
+ LIST_FOREACH(inotify.by_inode_data, s, d->event_sources) {
+
+ if ((s->inotify.mask & IN_EXCL_UNLINK) == 0)
+ excl_unlink = false;
+
+ combined |= s->inotify.mask;
+ }
+
+ return (combined & ~(IN_ONESHOT|IN_DONT_FOLLOW|IN_ONLYDIR|IN_EXCL_UNLINK)) | (excl_unlink ? IN_EXCL_UNLINK : 0);
+}
+
+static int inode_data_realize_watch(sd_event *e, struct inode_data *d) {
+ uint32_t combined_mask;
+ int wd, r;
+
+ assert(d);
+ assert(d->fd >= 0);
+
+ combined_mask = inode_data_determine_mask(d);
+
+ if (d->wd >= 0 && combined_mask == d->combined_mask)
+ return 0;
+
+ r = hashmap_ensure_allocated(&d->inotify_data->wd, NULL);
+ if (r < 0)
+ return r;
+
+ wd = inotify_add_watch_fd(d->inotify_data->fd, d->fd, combined_mask);
+ if (wd < 0)
+ return -errno;
+
+ if (d->wd < 0) {
+ r = hashmap_put(d->inotify_data->wd, INT_TO_PTR(wd), d);
+ if (r < 0) {
+ (void) inotify_rm_watch(d->inotify_data->fd, wd);
+ return r;
+ }
+
+ d->wd = wd;
+
+ } else if (d->wd != wd) {
+
+ log_debug("Weird, the watch descriptor we already knew for this inode changed?");
+ (void) inotify_rm_watch(d->fd, wd);
+ return -EINVAL;
+ }
+
+ d->combined_mask = combined_mask;
+ return 1;
+}
+
+_public_ int sd_event_add_inotify(
+ sd_event *e,
+ sd_event_source **ret,
+ const char *path,
+ uint32_t mask,
+ sd_event_inotify_handler_t callback,
+ void *userdata) {
+
+ bool rm_inotify = false, rm_inode = false;
+ struct inotify_data *inotify_data = NULL;
+ struct inode_data *inode_data = NULL;
+ _cleanup_close_ int fd = -1;
+ sd_event_source *s;
+ struct stat st;
+ int r;
+
+ assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
+ assert_return(path, -EINVAL);
+ assert_return(callback, -EINVAL);
+ assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
+ assert_return(!event_pid_changed(e), -ECHILD);
+
+ /* Refuse IN_MASK_ADD since we coalesce watches on the same inode, and hence really don't want to merge
+ * masks. Or in other words, this whole code exists only to manage IN_MASK_ADD type operations for you, hence
+ * the user can't use them for us. */
+ if (mask & IN_MASK_ADD)
+ return -EINVAL;
+
+ fd = open(path, O_PATH|O_CLOEXEC|
+ (mask & IN_ONLYDIR ? O_DIRECTORY : 0)|
+ (mask & IN_DONT_FOLLOW ? O_NOFOLLOW : 0));
+ if (fd < 0)
+ return -errno;
+
+ if (fstat(fd, &st) < 0)
+ return -errno;
+
+ s = source_new(e, !ret, SOURCE_INOTIFY);
+ if (!s)
+ return -ENOMEM;
+
+ s->enabled = mask & IN_ONESHOT ? SD_EVENT_ONESHOT : SD_EVENT_ON;
+ s->inotify.mask = mask;
+ s->inotify.callback = callback;
+ s->userdata = userdata;
+
+ /* Allocate an inotify object for this priority, and an inode object within it */
+ r = event_make_inotify_data(e, SD_EVENT_PRIORITY_NORMAL, &inotify_data);
+ if (r < 0)
+ goto fail;
+ rm_inotify = r > 0;
+
+ r = event_make_inode_data(e, inotify_data, st.st_dev, st.st_ino, &inode_data);
+ if (r < 0)
+ goto fail;
+ rm_inode = r > 0;
+
+ /* Keep the O_PATH fd around until the first iteration of the loop, so that we can still change the priority of
+ * the event source, until then, for which we need the original inode. */
+ if (inode_data->fd < 0) {
+ inode_data->fd = TAKE_FD(fd);
+ LIST_PREPEND(to_close, e->inode_data_to_close, inode_data);
+ }
+
+ /* Link our event source to the inode data object */
+ LIST_PREPEND(inotify.by_inode_data, inode_data->event_sources, s);
+ s->inotify.inode_data = inode_data;
+
+ rm_inode = rm_inotify = false;
+
+ /* Actually realize the watch now */
+ r = inode_data_realize_watch(e, inode_data);
+ if (r < 0)
+ goto fail;
+
+ (void) sd_event_source_set_description(s, path);
+
+ if (ret)
+ *ret = s;
+
+ return 0;
+
+fail:
+ source_free(s);
+
+ if (rm_inode)
+ event_free_inode_data(e, inode_data);
+
+ if (rm_inotify)
+ event_free_inotify_data(e, inotify_data);
+
+ return r;
+}
+
_public_ sd_event_source* sd_event_source_ref(sd_event_source *s) {
if (!s)
@@ -1480,6 +2044,21 @@ _public_ int sd_event_source_set_io_fd(sd_event_source *s, int fd) {
return 0;
}
+_public_ int sd_event_source_get_io_fd_own(sd_event_source *s) {
+ assert_return(s, -EINVAL);
+ assert_return(s->type == SOURCE_IO, -EDOM);
+
+ return s->io.owned;
+}
+
+_public_ int sd_event_source_set_io_fd_own(sd_event_source *s, int own) {
+ assert_return(s, -EINVAL);
+ assert_return(s->type == SOURCE_IO, -EDOM);
+
+ s->io.owned = own;
+ return 0;
+}
+
_public_ int sd_event_source_get_io_events(sd_event_source *s, uint32_t* events) {
assert_return(s, -EINVAL);
assert_return(events, -EINVAL);
@@ -1503,6 +2082,10 @@ _public_ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events)
if (s->io.events == events && !(events & EPOLLET))
return 0;
+ r = source_set_pending(s, false);
+ if (r < 0)
+ return r;
+
if (s->enabled != SD_EVENT_OFF) {
r = source_io_register(s, s->enabled, events);
if (r < 0)
@@ -1510,7 +2093,6 @@ _public_ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events)
}
s->io.events = events;
- source_set_pending(s, false);
return 0;
}
@@ -1543,6 +2125,9 @@ _public_ int sd_event_source_get_priority(sd_event_source *s, int64_t *priority)
}
_public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority) {
+ bool rm_inotify = false, rm_inode = false;
+ struct inotify_data *new_inotify_data = NULL;
+ struct inode_data *new_inode_data = NULL;
int r;
assert_return(s, -EINVAL);
@@ -1552,7 +2137,59 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority)
if (s->priority == priority)
return 0;
- if (s->type == SOURCE_SIGNAL && s->enabled != SD_EVENT_OFF) {
+ if (s->type == SOURCE_INOTIFY) {
+ struct inode_data *old_inode_data;
+
+ assert(s->inotify.inode_data);
+ old_inode_data = s->inotify.inode_data;
+
+ /* We need the original fd to change the priority. If we don't have it we can't change the priority,
+ * anymore. Note that we close any fds when entering the next event loop iteration, i.e. for inotify
+ * events we allow priority changes only until the first following iteration. */
+ if (old_inode_data->fd < 0)
+ return -EOPNOTSUPP;
+
+ r = event_make_inotify_data(s->event, priority, &new_inotify_data);
+ if (r < 0)
+ return r;
+ rm_inotify = r > 0;
+
+ r = event_make_inode_data(s->event, new_inotify_data, old_inode_data->dev, old_inode_data->ino, &new_inode_data);
+ if (r < 0)
+ goto fail;
+ rm_inode = r > 0;
+
+ if (new_inode_data->fd < 0) {
+ /* Duplicate the fd for the new inode object if we don't have any yet */
+ new_inode_data->fd = fcntl(old_inode_data->fd, F_DUPFD_CLOEXEC, 3);
+ if (new_inode_data->fd < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ LIST_PREPEND(to_close, s->event->inode_data_to_close, new_inode_data);
+ }
+
+ /* Move the event source to the new inode data structure */
+ LIST_REMOVE(inotify.by_inode_data, old_inode_data->event_sources, s);
+ LIST_PREPEND(inotify.by_inode_data, new_inode_data->event_sources, s);
+ s->inotify.inode_data = new_inode_data;
+
+ /* Now create the new watch */
+ r = inode_data_realize_watch(s->event, new_inode_data);
+ if (r < 0) {
+ /* Move it back */
+ LIST_REMOVE(inotify.by_inode_data, new_inode_data->event_sources, s);
+ LIST_PREPEND(inotify.by_inode_data, old_inode_data->event_sources, s);
+ s->inotify.inode_data = old_inode_data;
+ goto fail;
+ }
+
+ s->priority = priority;
+
+ event_gc_inode_data(s->event, old_inode_data);
+
+ } else if (s->type == SOURCE_SIGNAL && s->enabled != SD_EVENT_OFF) {
struct signal_data *old, *d;
/* Move us from the signalfd belonging to the old
@@ -1582,6 +2219,15 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority)
prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
return 0;
+
+fail:
+ if (rm_inode)
+ event_free_inode_data(s->event, new_inode_data);
+
+ if (rm_inotify)
+ event_free_inotify_data(s->event, new_inotify_data);
+
+ return r;
}
_public_ int sd_event_source_get_enabled(sd_event_source *s, int *m) {
@@ -1597,7 +2243,7 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
int r;
assert_return(s, -EINVAL);
- assert_return(m == SD_EVENT_OFF || m == SD_EVENT_ON || m == SD_EVENT_ONESHOT, -EINVAL);
+ assert_return(IN_SET(m, SD_EVENT_OFF, SD_EVENT_ON, SD_EVENT_ONESHOT), -EINVAL);
assert_return(!event_pid_changed(s->event), -ECHILD);
/* If we are dead anyway, we are fine with turning off
@@ -1610,6 +2256,13 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
if (m == SD_EVENT_OFF) {
+ /* Unset the pending flag when this event source is disabled */
+ if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
+ r = source_set_pending(s, false);
+ if (r < 0)
+ return r;
+ }
+
switch (s->type) {
case SOURCE_IO:
@@ -1656,6 +2309,7 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
case SOURCE_DEFER:
case SOURCE_POST:
+ case SOURCE_INOTIFY:
s->enabled = m;
break;
@@ -1664,6 +2318,14 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
}
} else {
+
+ /* Unset the pending flag when this event source is enabled */
+ if (s->enabled == SD_EVENT_OFF && !IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
+ r = source_set_pending(s, false);
+ if (r < 0)
+ return r;
+ }
+
switch (s->type) {
case SOURCE_IO:
@@ -1728,6 +2390,7 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
case SOURCE_DEFER:
case SOURCE_POST:
+ case SOURCE_INOTIFY:
s->enabled = m;
break;
@@ -1757,15 +2420,18 @@ _public_ int sd_event_source_get_time(sd_event_source *s, uint64_t *usec) {
_public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
struct clock_data *d;
+ int r;
assert_return(s, -EINVAL);
assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM);
assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(s->event), -ECHILD);
- s->time.next = usec;
+ r = source_set_pending(s, false);
+ if (r < 0)
+ return r;
- source_set_pending(s, false);
+ s->time.next = usec;
d = event_get_clock_data(s->event, s->type);
assert(d);
@@ -1789,6 +2455,7 @@ _public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *use
_public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec) {
struct clock_data *d;
+ int r;
assert_return(s, -EINVAL);
assert_return(usec != (uint64_t) -1, -EINVAL);
@@ -1796,13 +2463,15 @@ _public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec
assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(s->event), -ECHILD);
+ r = source_set_pending(s, false);
+ if (r < 0)
+ return r;
+
if (usec == 0)
usec = DEFAULT_ACCURACY_USEC;
s->time.accuracy = usec;
- source_set_pending(s, false);
-
d = event_get_clock_data(s->event, s->type);
assert(d);
@@ -1832,6 +2501,16 @@ _public_ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid) {
return 0;
}
+_public_ int sd_event_source_get_inotify_mask(sd_event_source *s, uint32_t *mask) {
+ assert_return(s, -EINVAL);
+ assert_return(mask, -EINVAL);
+ assert_return(s->type == SOURCE_INOTIFY, -EDOM);
+ assert_return(!event_pid_changed(s->event), -ECHILD);
+
+ *mask = s->inotify.mask;
+ return 0;
+}
+
_public_ int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback) {
int r;
@@ -2050,7 +2729,7 @@ static int flush_timer(sd_event *e, int fd, uint32_t events, usec_t *next) {
ss = read(fd, &x, sizeof(x));
if (ss < 0) {
- if (errno == EAGAIN || errno == EINTR)
+ if (IN_SET(errno, EAGAIN, EINTR))
return 0;
return -errno;
@@ -2139,10 +2818,7 @@ static int process_child(sd_event *e) {
return -errno;
if (s->child.siginfo.si_pid != 0) {
- bool zombie =
- s->child.siginfo.si_code == CLD_EXITED ||
- s->child.siginfo.si_code == CLD_KILLED ||
- s->child.siginfo.si_code == CLD_DUMPED;
+ bool zombie = IN_SET(s->child.siginfo.si_code, CLD_EXITED, CLD_KILLED, CLD_DUMPED);
if (!zombie && (s->child.options & WEXITED)) {
/* If the child isn't dead then let's
@@ -2168,6 +2844,7 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) {
int r;
assert(e);
+ assert(d);
assert_return(events == EPOLLIN, -EIO);
/* If there's a signal queued on this priority and SIGCHLD is
@@ -2193,7 +2870,7 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) {
n = read(d->fd, &si, sizeof(si));
if (n < 0) {
- if (errno == EAGAIN || errno == EINTR)
+ if (IN_SET(errno, EAGAIN, EINTR))
return read_one;
return -errno;
@@ -2224,6 +2901,160 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) {
}
}
+static int event_inotify_data_read(sd_event *e, struct inotify_data *d, uint32_t revents) {
+ ssize_t n;
+
+ assert(e);
+ assert(d);
+
+ assert_return(revents == EPOLLIN, -EIO);
+
+ /* If there's already an event source pending for this priority, don't read another */
+ if (d->n_pending > 0)
+ return 0;
+
+ /* Is the read buffer non-empty? If so, let's not read more */
+ if (d->buffer_filled > 0)
+ return 0;
+
+ n = read(d->fd, &d->buffer, sizeof(d->buffer));
+ if (n < 0) {
+ if (IN_SET(errno, EAGAIN, EINTR))
+ return 0;
+
+ return -errno;
+ }
+
+ assert(n > 0);
+ d->buffer_filled = (size_t) n;
+ LIST_PREPEND(buffered, e->inotify_data_buffered, d);
+
+ return 1;
+}
+
+static void event_inotify_data_drop(sd_event *e, struct inotify_data *d, size_t sz) {
+ assert(e);
+ assert(d);
+ assert(sz <= d->buffer_filled);
+
+ if (sz == 0)
+ return;
+
+ /* Move the rest to the buffer to the front, in order to get things properly aligned again */
+ memmove(d->buffer.raw, d->buffer.raw + sz, d->buffer_filled - sz);
+ d->buffer_filled -= sz;
+
+ if (d->buffer_filled == 0)
+ LIST_REMOVE(buffered, e->inotify_data_buffered, d);
+}
+
+static int event_inotify_data_process(sd_event *e, struct inotify_data *d) {
+ int r;
+
+ assert(e);
+ assert(d);
+
+ /* If there's already an event source pending for this priority, don't read another */
+ if (d->n_pending > 0)
+ return 0;
+
+ while (d->buffer_filled > 0) {
+ size_t sz;
+
+ /* Let's validate that the event structures are complete */
+ if (d->buffer_filled < offsetof(struct inotify_event, name))
+ return -EIO;
+
+ sz = offsetof(struct inotify_event, name) + d->buffer.ev.len;
+ if (d->buffer_filled < sz)
+ return -EIO;
+
+ if (d->buffer.ev.mask & IN_Q_OVERFLOW) {
+ struct inode_data *inode_data;
+ Iterator i;
+
+ /* The queue overran, let's pass this event to all event sources connected to this inotify
+ * object */
+
+ HASHMAP_FOREACH(inode_data, d->inodes, i) {
+ sd_event_source *s;
+
+ LIST_FOREACH(inotify.by_inode_data, s, inode_data->event_sources) {
+
+ if (s->enabled == SD_EVENT_OFF)
+ continue;
+
+ r = source_set_pending(s, true);
+ if (r < 0)
+ return r;
+ }
+ }
+ } else {
+ struct inode_data *inode_data;
+ sd_event_source *s;
+
+ /* Find the inode object for this watch descriptor. If IN_IGNORED is set we also remove it from
+ * our watch descriptor table. */
+ if (d->buffer.ev.mask & IN_IGNORED) {
+
+ inode_data = hashmap_remove(d->wd, INT_TO_PTR(d->buffer.ev.wd));
+ if (!inode_data) {
+ event_inotify_data_drop(e, d, sz);
+ continue;
+ }
+
+ /* The watch descriptor was removed by the kernel, let's drop it here too */
+ inode_data->wd = -1;
+ } else {
+ inode_data = hashmap_get(d->wd, INT_TO_PTR(d->buffer.ev.wd));
+ if (!inode_data) {
+ event_inotify_data_drop(e, d, sz);
+ continue;
+ }
+ }
+
+ /* Trigger all event sources that are interested in these events. Also trigger all event
+ * sources if IN_IGNORED or IN_UNMOUNT is set. */
+ LIST_FOREACH(inotify.by_inode_data, s, inode_data->event_sources) {
+
+ if (s->enabled == SD_EVENT_OFF)
+ continue;
+
+ if ((d->buffer.ev.mask & (IN_IGNORED|IN_UNMOUNT)) == 0 &&
+ (s->inotify.mask & d->buffer.ev.mask & IN_ALL_EVENTS) == 0)
+ continue;
+
+ r = source_set_pending(s, true);
+ if (r < 0)
+ return r;
+ }
+ }
+
+ /* Something pending now? If so, let's finish, otherwise let's read more. */
+ if (d->n_pending > 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+static int process_inotify(sd_event *e) {
+ struct inotify_data *d;
+ int r, done = 0;
+
+ assert(e);
+
+ LIST_FOREACH(buffered, d, e->inotify_data_buffered) {
+ r = event_inotify_data_process(e, d);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ done ++;
+ }
+
+ return done;
+}
+
static int source_dispatch(sd_event_source *s) {
EventSourceType saved_type;
int r = 0;
@@ -2235,7 +3066,7 @@ static int source_dispatch(sd_event_source *s) {
* the event. */
saved_type = s->type;
- if (s->type != SOURCE_DEFER && s->type != SOURCE_EXIT) {
+ if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
r = source_set_pending(s, false);
if (r < 0)
return r;
@@ -2287,15 +3118,13 @@ static int source_dispatch(sd_event_source *s) {
case SOURCE_CHILD: {
bool zombie;
- zombie = s->child.siginfo.si_code == CLD_EXITED ||
- s->child.siginfo.si_code == CLD_KILLED ||
- s->child.siginfo.si_code == CLD_DUMPED;
+ zombie = IN_SET(s->child.siginfo.si_code, CLD_EXITED, CLD_KILLED, CLD_DUMPED);
r = s->child.callback(s, &s->child.siginfo, s->userdata);
/* Now, reap the PID for good. */
if (zombie)
- waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|WEXITED);
+ (void) waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|WEXITED);
break;
}
@@ -2312,6 +3141,28 @@ static int source_dispatch(sd_event_source *s) {
r = s->exit.callback(s, s->userdata);
break;
+ case SOURCE_INOTIFY: {
+ struct sd_event *e = s->event;
+ struct inotify_data *d;
+ size_t sz;
+
+ assert(s->inotify.inode_data);
+ assert_se(d = s->inotify.inode_data->inotify_data);
+
+ assert(d->buffer_filled >= offsetof(struct inotify_event, name));
+ sz = offsetof(struct inotify_event, name) + d->buffer.ev.len;
+ assert(d->buffer_filled >= sz);
+
+ r = s->inotify.callback(s, &d->buffer.ev, s->userdata);
+
+ /* When no event is pending anymore on this inotify object, then let's drop the event from the
+ * buffer. */
+ if (d->n_pending == 0)
+ event_inotify_data_drop(e, d, sz);
+
+ break;
+ }
+
case SOURCE_WATCHDOG:
case _SOURCE_EVENT_SOURCE_TYPE_MAX:
case _SOURCE_EVENT_SOURCE_TYPE_INVALID:
@@ -2370,6 +3221,7 @@ static int event_prepare(sd_event *e) {
static int dispatch_exit(sd_event *e) {
sd_event_source *p;
+ _cleanup_(sd_event_unrefp) sd_event *ref = NULL;
int r;
assert(e);
@@ -2380,15 +3232,11 @@ static int dispatch_exit(sd_event *e) {
return 0;
}
- sd_event_ref(e);
+ ref = sd_event_ref(e);
e->iteration++;
e->state = SD_EVENT_EXITING;
-
r = source_dispatch(p);
-
e->state = SD_EVENT_INITIAL;
- sd_event_unref(e);
-
return r;
}
@@ -2449,10 +3297,30 @@ static int process_watchdog(sd_event *e) {
return arm_watchdog(e);
}
+static void event_close_inode_data_fds(sd_event *e) {
+ struct inode_data *d;
+
+ assert(e);
+
+ /* Close the fds pointing to the inodes to watch now. We need to close them as they might otherwise pin
+ * filesystems. But we can't close them right-away as we need them as long as the user still wants to make
+ * adjustments to the even source, such as changing the priority (which requires us to remove and readd a watch
+ * for the inode). Hence, let's close them when entering the first iteration after they were added, as a
+ * compromise. */
+
+ while ((d = e->inode_data_to_close)) {
+ assert(d->fd >= 0);
+ d->fd = safe_close(d->fd);
+
+ LIST_REMOVE(to_close, e->inode_data_to_close, d);
+ }
+}
+
_public_ int sd_event_prepare(sd_event *e) {
int r;
assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
assert_return(!event_pid_changed(e), -ECHILD);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(e->state == SD_EVENT_INITIAL, -EBUSY);
@@ -2488,6 +3356,8 @@ _public_ int sd_event_prepare(sd_event *e) {
if (r < 0)
return r;
+ event_close_inode_data_fds(e);
+
if (event_next_pending(e) || e->need_process_child)
goto pending;
@@ -2510,6 +3380,7 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
int r, m, i;
assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
assert_return(!event_pid_changed(e), -ECHILD);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(e->state == SD_EVENT_ARMED, -EBUSY);
@@ -2522,6 +3393,10 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
ev_queue_max = MAX(e->n_sources, 1u);
ev_queue = newa(struct epoll_event, ev_queue_max);
+ /* If we still have inotify data buffered, then query the other fds, but don't wait on it */
+ if (e->inotify_data_buffered)
+ timeout = 0;
+
m = epoll_wait(e->epoll_fd, ev_queue, ev_queue_max,
timeout == (uint64_t) -1 ? -1 : (int) ((timeout + USEC_PER_MSEC - 1) / USEC_PER_MSEC));
if (m < 0) {
@@ -2559,6 +3434,10 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
r = process_signal(e, ev_queue[i].data.ptr, ev_queue[i].events);
break;
+ case WAKEUP_INOTIFY_DATA:
+ r = event_inotify_data_read(e, ev_queue[i].data.ptr, ev_queue[i].events);
+ break;
+
default:
assert_not_reached("Invalid wake-up pointer");
}
@@ -2597,6 +3476,10 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
goto finish;
}
+ r = process_inotify(e);
+ if (r < 0)
+ goto finish;
+
if (event_next_pending(e)) {
e->state = SD_EVENT_PENDING;
@@ -2616,6 +3499,7 @@ _public_ int sd_event_dispatch(sd_event *e) {
int r;
assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
assert_return(!event_pid_changed(e), -ECHILD);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(e->state == SD_EVENT_PENDING, -EBUSY);
@@ -2625,14 +3509,12 @@ _public_ int sd_event_dispatch(sd_event *e) {
p = event_next_pending(e);
if (p) {
- sd_event_ref(e);
+ _cleanup_(sd_event_unrefp) sd_event *ref = NULL;
+ ref = sd_event_ref(e);
e->state = SD_EVENT_RUNNING;
r = source_dispatch(p);
e->state = SD_EVENT_INITIAL;
-
- sd_event_unref(e);
-
return r;
}
@@ -2657,6 +3539,7 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) {
int r;
assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
assert_return(!event_pid_changed(e), -ECHILD);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(e->state == SD_EVENT_INITIAL, -EBUSY);
@@ -2698,30 +3581,29 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) {
}
_public_ int sd_event_loop(sd_event *e) {
+ _cleanup_(sd_event_unrefp) sd_event *ref = NULL;
int r;
assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
assert_return(!event_pid_changed(e), -ECHILD);
assert_return(e->state == SD_EVENT_INITIAL, -EBUSY);
- sd_event_ref(e);
+ ref = sd_event_ref(e);
while (e->state != SD_EVENT_FINISHED) {
r = sd_event_run(e, (uint64_t) -1);
if (r < 0)
- goto finish;
+ return r;
}
- r = e->exit_code;
-
-finish:
- sd_event_unref(e);
- return r;
+ return e->exit_code;
}
_public_ int sd_event_get_fd(sd_event *e) {
assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
assert_return(!event_pid_changed(e), -ECHILD);
return e->epoll_fd;
@@ -2729,6 +3611,7 @@ _public_ int sd_event_get_fd(sd_event *e) {
_public_ int sd_event_get_state(sd_event *e) {
assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
assert_return(!event_pid_changed(e), -ECHILD);
return e->state;
@@ -2736,6 +3619,7 @@ _public_ int sd_event_get_state(sd_event *e) {
_public_ int sd_event_get_exit_code(sd_event *e, int *code) {
assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
assert_return(code, -EINVAL);
assert_return(!event_pid_changed(e), -ECHILD);
@@ -2748,6 +3632,7 @@ _public_ int sd_event_get_exit_code(sd_event *e, int *code) {
_public_ int sd_event_exit(sd_event *e, int code) {
assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
@@ -2759,6 +3644,7 @@ _public_ int sd_event_exit(sd_event *e, int code) {
_public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) {
assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
assert_return(usec, -EINVAL);
assert_return(!event_pid_changed(e), -ECHILD);
@@ -2783,8 +3669,6 @@ _public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) {
}
_public_ int sd_event_default(sd_event **ret) {
-
- static thread_local sd_event *default_event = NULL;
sd_event *e = NULL;
int r;
@@ -2810,6 +3694,7 @@ _public_ int sd_event_default(sd_event **ret) {
_public_ int sd_event_get_tid(sd_event *e, pid_t *tid) {
assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
assert_return(tid, -EINVAL);
assert_return(!event_pid_changed(e), -ECHILD);
@@ -2825,13 +3710,14 @@ _public_ int sd_event_set_watchdog(sd_event *e, int b) {
int r;
assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
assert_return(!event_pid_changed(e), -ECHILD);
if (e->watchdog == !!b)
return e->watchdog;
if (b) {
- struct epoll_event ev = {};
+ struct epoll_event ev;
r = sd_watchdog_enabled(false, &e->watchdog_period);
if (r <= 0)
@@ -2849,8 +3735,10 @@ _public_ int sd_event_set_watchdog(sd_event *e, int b) {
if (r < 0)
goto fail;
- ev.events = EPOLLIN;
- ev.data.ptr = INT_TO_PTR(SOURCE_WATCHDOG);
+ ev = (struct epoll_event) {
+ .events = EPOLLIN,
+ .data.ptr = INT_TO_PTR(SOURCE_WATCHDOG),
+ };
r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, e->watchdog_fd, &ev);
if (r < 0) {
@@ -2875,6 +3763,7 @@ fail:
_public_ int sd_event_get_watchdog(sd_event *e) {
assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
assert_return(!event_pid_changed(e), -ECHILD);
return e->watchdog;
@@ -2882,8 +3771,25 @@ _public_ int sd_event_get_watchdog(sd_event *e) {
_public_ int sd_event_get_iteration(sd_event *e, uint64_t *ret) {
assert_return(e, -EINVAL);
+ assert_return(e = event_resolve(e), -ENOPKG);
assert_return(!event_pid_changed(e), -ECHILD);
*ret = e->iteration;
return 0;
}
+
+_public_ int sd_event_source_set_destroy_callback(sd_event_source *s, sd_event_destroy_t callback) {
+ assert_return(s, -EINVAL);
+
+ s->destroy_callback = callback;
+ return 0;
+}
+
+_public_ int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_destroy_t *ret) {
+ assert_return(s, -EINVAL);
+
+ if (ret)
+ *ret = s->destroy_callback;
+
+ return !!s->destroy_callback;
+}
diff --git a/src/libelogind/sd-event/test-event.c b/src/libelogind/sd-event/test-event.c
index 8425378f3..13dcf6ab9 100644
--- a/src/libelogind/sd-event/test-event.c
+++ b/src/libelogind/sd-event/test-event.c
@@ -1,31 +1,26 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 "sd-event.h"
+#include "alloc-util.h"
#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
#include "log.h"
#include "macro.h"
+#include "parse-util.h"
+//#include "process-util.h"
+#include "rm-rf.h"
#include "signal-util.h"
+#include "stdio-util.h"
+#include "string-util.h"
#include "util.h"
+/// Additional includes needed by elogind
+#include "process-util.h"
static int prepare_handler(sd_event_source *s, void *userdata) {
log_info("preparing %c", PTR_TO_INT(userdata));
@@ -96,7 +91,7 @@ static int signal_handler(sd_event_source *s, const struct signalfd_siginfo *si,
assert_se(pid >= 0);
if (pid == 0)
- _exit(0);
+ _exit(EXIT_SUCCESS);
assert_se(sd_event_add_child(sd_event_source_get_event(s), &p, pid, WEXITED, child_handler, INT_TO_PTR('f')) >= 0);
assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
@@ -195,7 +190,7 @@ static void test_basic(void) {
got_a = false, got_b = false, got_c = false, got_d = 0;
- /* Add a oneshot handler, trigger it, re-enable it, and trigger
+ /* Add a oneshot handler, trigger it, reenable it, and trigger
* it again. */
assert_se(sd_event_add_io(e, &w, d[0], EPOLLIN, io_handler, INT_TO_PTR('d')) >= 0);
assert_se(sd_event_source_set_enabled(w, SD_EVENT_ONESHOT) >= 0);
@@ -317,11 +312,11 @@ static void test_rtqueue(void) {
assert_se(sd_event_source_set_priority(v, -10) >= 0);
- assert(sigqueue(getpid(), SIGRTMIN+2, (union sigval) { .sival_int = 1 }) >= 0);
- assert(sigqueue(getpid(), SIGRTMIN+3, (union sigval) { .sival_int = 2 }) >= 0);
- assert(sigqueue(getpid(), SIGUSR2, (union sigval) { .sival_int = 3 }) >= 0);
- assert(sigqueue(getpid(), SIGRTMIN+3, (union sigval) { .sival_int = 4 }) >= 0);
- assert(sigqueue(getpid(), SIGUSR2, (union sigval) { .sival_int = 5 }) >= 0);
+ assert_se(sigqueue(getpid_cached(), SIGRTMIN+2, (union sigval) { .sival_int = 1 }) >= 0);
+ assert_se(sigqueue(getpid_cached(), SIGRTMIN+3, (union sigval) { .sival_int = 2 }) >= 0);
+ assert_se(sigqueue(getpid_cached(), SIGUSR2, (union sigval) { .sival_int = 3 }) >= 0);
+ assert_se(sigqueue(getpid_cached(), SIGRTMIN+3, (union sigval) { .sival_int = 4 }) >= 0);
+ assert_se(sigqueue(getpid_cached(), SIGUSR2, (union sigval) { .sival_int = 5 }) >= 0);
assert_se(n_rtqueue == 0);
assert_se(last_rtqueue_sigval == 0);
@@ -353,6 +348,142 @@ static void test_rtqueue(void) {
sd_event_unref(e);
}
+#define CREATE_EVENTS_MAX (70000U)
+
+struct inotify_context {
+ bool delete_self_handler_called;
+ unsigned create_called[CREATE_EVENTS_MAX];
+ unsigned create_overflow;
+ unsigned n_create_events;
+};
+
+static void maybe_exit(sd_event_source *s, struct inotify_context *c) {
+ unsigned n;
+
+ assert(s);
+ assert(c);
+
+ if (!c->delete_self_handler_called)
+ return;
+
+ for (n = 0; n < 3; n++) {
+ unsigned i;
+
+ if (c->create_overflow & (1U << n))
+ continue;
+
+ for (i = 0; i < c->n_create_events; i++)
+ if (!(c->create_called[i] & (1U << n)))
+ return;
+ }
+
+ sd_event_exit(sd_event_source_get_event(s), 0);
+}
+
+static int inotify_handler(sd_event_source *s, const struct inotify_event *ev, void *userdata) {
+ struct inotify_context *c = userdata;
+ const char *description;
+ unsigned bit, n;
+
+ assert_se(sd_event_source_get_description(s, &description) >= 0);
+ assert_se(safe_atou(description, &n) >= 0);
+
+ assert_se(n <= 3);
+ bit = 1U << n;
+
+ if (ev->mask & IN_Q_OVERFLOW) {
+ log_info("inotify-handler <%s>: overflow", description);
+ c->create_overflow |= bit;
+ } else if (ev->mask & IN_CREATE) {
+ unsigned i;
+
+ log_info("inotify-handler <%s>: create on %s", description, ev->name);
+
+ if (!streq(ev->name, "sub")) {
+ assert_se(safe_atou(ev->name, &i) >= 0);
+
+ assert_se(i < c->n_create_events);
+ c->create_called[i] |= bit;
+ }
+ } else if (ev->mask & IN_DELETE) {
+ log_info("inotify-handler <%s>: delete of %s", description, ev->name);
+ assert_se(streq(ev->name, "sub"));
+ } else
+ assert_not_reached("unexpected inotify event");
+
+ maybe_exit(s, c);
+ return 1;
+}
+
+static int delete_self_handler(sd_event_source *s, const struct inotify_event *ev, void *userdata) {
+ struct inotify_context *c = userdata;
+
+ if (ev->mask & IN_Q_OVERFLOW) {
+ log_info("delete-self-handler: overflow");
+ c->delete_self_handler_called = true;
+ } else if (ev->mask & IN_DELETE_SELF) {
+ log_info("delete-self-handler: delete-self");
+ c->delete_self_handler_called = true;
+ } else if (ev->mask & IN_IGNORED) {
+ log_info("delete-self-handler: ignore");
+ } else
+ assert_not_reached("unexpected inotify event (delete-self)");
+
+ maybe_exit(s, c);
+ return 1;
+}
+
+static void test_inotify(unsigned n_create_events) {
+ _cleanup_(rm_rf_physical_and_freep) char *p = NULL;
+ sd_event_source *a = NULL, *b = NULL, *c = NULL, *d = NULL;
+ struct inotify_context context = {
+ .n_create_events = n_create_events,
+ };
+ sd_event *e = NULL;
+ const char *q;
+ unsigned i;
+
+ assert_se(sd_event_default(&e) >= 0);
+
+ assert_se(mkdtemp_malloc("/tmp/test-inotify-XXXXXX", &p) >= 0);
+
+ assert_se(sd_event_add_inotify(e, &a, p, IN_CREATE|IN_ONLYDIR, inotify_handler, &context) >= 0);
+ assert_se(sd_event_add_inotify(e, &b, p, IN_CREATE|IN_DELETE|IN_DONT_FOLLOW, inotify_handler, &context) >= 0);
+ assert_se(sd_event_source_set_priority(b, SD_EVENT_PRIORITY_IDLE) >= 0);
+ assert_se(sd_event_source_set_priority(b, SD_EVENT_PRIORITY_NORMAL) >= 0);
+ assert_se(sd_event_add_inotify(e, &c, p, IN_CREATE|IN_DELETE|IN_EXCL_UNLINK, inotify_handler, &context) >= 0);
+ assert_se(sd_event_source_set_priority(c, SD_EVENT_PRIORITY_IDLE) >= 0);
+
+ assert_se(sd_event_source_set_description(a, "0") >= 0);
+ assert_se(sd_event_source_set_description(b, "1") >= 0);
+ assert_se(sd_event_source_set_description(c, "2") >= 0);
+
+ q = strjoina(p, "/sub");
+ assert_se(touch(q) >= 0);
+ assert_se(sd_event_add_inotify(e, &d, q, IN_DELETE_SELF, delete_self_handler, &context) >= 0);
+
+ for (i = 0; i < n_create_events; i++) {
+ char buf[DECIMAL_STR_MAX(unsigned)+1];
+ _cleanup_free_ char *z;
+
+ xsprintf(buf, "%u", i);
+ assert_se(z = strjoin(p, "/", buf));
+
+ assert_se(touch(z) >= 0);
+ }
+
+ assert_se(unlink(q) >= 0);
+
+ assert_se(sd_event_loop(e) >= 0);
+
+ sd_event_source_unref(a);
+ sd_event_source_unref(b);
+ sd_event_source_unref(c);
+ sd_event_source_unref(d);
+
+ sd_event_unref(e);
+}
+
int main(int argc, char *argv[]) {
log_set_max_level(LOG_DEBUG);
@@ -362,5 +493,8 @@ int main(int argc, char *argv[]) {
test_sd_event_now();
test_rtqueue();
+ test_inotify(100); /* should work without overflow */
+ test_inotify(33000); /* should trigger a q overflow */
+
return 0;
}
diff --git a/src/libelogind/sd-id128/Makefile b/src/libelogind/sd-id128/Makefile
deleted file mode 120000
index 94aaae2c4..000000000
--- a/src/libelogind/sd-id128/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../../Makefile \ No newline at end of file
diff --git a/src/libelogind/sd-id128/id128-util.c b/src/libelogind/sd-id128/id128-util.c
index ce8a6aad0..b72290936 100644
--- a/src/libelogind/sd-id128/id128-util.c
+++ b/src/libelogind/sd-id128/id128-util.c
@@ -1,26 +1,13 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 "fd-util.h"
+#include "fs-util.h"
#include "hexdecoct.h"
#include "id128-util.h"
#include "io-util.h"
@@ -75,7 +62,7 @@ bool id128_is_valid(const char *s) {
for (i = 0; i < l; i++) {
char c = s[i];
- if ((i == 8 || i == 13 || i == 18 || i == 23)) {
+ if (IN_SET(i, 8, 13, 18, 23)) {
if (c != '-')
return false;
} else {
@@ -116,7 +103,7 @@ int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) {
if (buffer[32] != '\n')
return -EINVAL;
- /* fall through */
+ _fallthrough_;
case 32: /* plain UUID without trailing newline */
if (f == ID128_UUID)
return -EINVAL;
@@ -128,7 +115,7 @@ int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) {
if (buffer[36] != '\n')
return -EINVAL;
- /* fall through */
+ _fallthrough_;
case 36: /* RFC UUID without trailing newline */
if (f == ID128_PLAIN)
return -EINVAL;
@@ -178,9 +165,13 @@ int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync) {
if (do_sync) {
if (fsync(fd) < 0)
return -errno;
+
+ r = fsync_directory_of_file(fd);
+ if (r < 0)
+ return r;
}
- return r;
+ return 0;
}
#if 0 /// UNNEEDED by elogind
diff --git a/src/libelogind/sd-id128/id128-util.h b/src/libelogind/sd-id128/id128-util.h
index d435b976d..3380286bc 100644
--- a/src/libelogind/sd-id128/id128-util.h
+++ b/src/libelogind/sd-id128/id128-util.h
@@ -1,22 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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>
diff --git a/src/libelogind/sd-id128/sd-id128.c b/src/libelogind/sd-id128/sd-id128.c
index d51abb205..b7123280f 100644
--- a/src/libelogind/sd-id128/sd-id128.c
+++ b/src/libelogind/sd-id128/sd-id128.c
@@ -1,20 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- 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>
@@ -30,6 +15,7 @@
#include "io-util.h"
#include "khash.h"
#include "macro.h"
+#include "missing.h"
#include "random-util.h"
#include "user-util.h"
#include "util.h"
@@ -65,7 +51,7 @@ _public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) {
if (i == 8)
is_guid = true;
- else if (i == 13 || i == 18 || i == 23) {
+ else if (IN_SET(i, 13, 18, 23)) {
if (!is_guid)
return -EINVAL;
} else
@@ -109,7 +95,7 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) {
return r;
if (sd_id128_is_null(saved_machine_id))
- return -EINVAL;
+ return -ENOMEDIUM;
}
*ret = saved_machine_id;
diff --git a/src/libelogind/sd-login/Makefile b/src/libelogind/sd-login/Makefile
deleted file mode 120000
index 94aaae2c4..000000000
--- a/src/libelogind/sd-login/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../../Makefile \ No newline at end of file
diff --git a/src/libelogind/sd-login/sd-login.c b/src/libelogind/sd-login/sd-login.c
index 7859f1c47..9b9ad7e42 100644
--- a/src/libelogind/sd-login/sd-login.c
+++ b/src/libelogind/sd-login/sd-login.c
@@ -1,20 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- 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>
@@ -114,51 +99,33 @@ _public_ int sd_pid_get_machine_name(pid_t pid, char **name) {
}
_public_ int sd_pid_get_slice(pid_t pid, char **slice) {
-#if 0 /// UNNEEDED by elogind
int r;
-#endif // 0
assert_return(pid >= 0, -EINVAL);
assert_return(slice, -EINVAL);
-#if 0 /// elogind does not support systemd slices
r = cg_pid_get_slice(pid, slice);
return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r;
-#else
- return -ESRCH;
-#endif // 0
}
_public_ int sd_pid_get_user_slice(pid_t pid, char **slice) {
-#if 0 /// UNNEEDED by elogind
int r;
-#endif // 0
assert_return(pid >= 0, -EINVAL);
assert_return(slice, -EINVAL);
-#if 0 /// elogind does not support systemd slices
r = cg_pid_get_user_slice(pid, slice);
return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r;
-#else
- return -ESRCH;
-#endif // 0
}
_public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) {
-#if 0 /// UNNEEDED by elogind
int r;
-#endif // 0
assert_return(pid >= 0, -EINVAL);
assert_return(uid, -EINVAL);
-#if 0 /// elogind does not support systemd slices
r = cg_pid_get_owner_uid(pid, uid);
return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r;
-#else
- return -ESRCH;
-#endif // 0
}
_public_ int sd_pid_get_cgroup(pid_t pid, char **cgroup) {
@@ -198,11 +165,7 @@ _public_ int sd_peer_get_session(int fd, char **session) {
if (r < 0)
return r;
-#if 0 /// elogind does not support systemd scopes
return cg_pid_get_session(ucred.pid, session);
-#else
- return -ESRCH;
-#endif // 0
}
_public_ int sd_peer_get_owner_uid(int fd, uid_t *uid) {
@@ -216,11 +179,7 @@ _public_ int sd_peer_get_owner_uid(int fd, uid_t *uid) {
if (r < 0)
return r;
-#if 0 /// elogind does not support systemd units
return cg_pid_get_owner_uid(ucred.pid, uid);
-#else
- return -ESRCH;
-#endif // 0
}
_public_ int sd_peer_get_unit(int fd, char **unit) {
@@ -288,11 +247,7 @@ _public_ int sd_peer_get_slice(int fd, char **slice) {
if (r < 0)
return r;
-#if 0 /// elogind does not support systemd slices
return cg_pid_get_slice(ucred.pid, slice);
-#else
- return -ESRCH;
-#endif // 0
}
_public_ int sd_peer_get_user_slice(int fd, char **slice) {
@@ -306,11 +261,7 @@ _public_ int sd_peer_get_user_slice(int fd, char **slice) {
if (r < 0)
return r;
-#if 0 /// elogind does not support systemd slices
return cg_pid_get_user_slice(ucred.pid, slice);
-#else
- return -ESRCH;
-#endif // 0
}
_public_ int sd_peer_get_cgroup(int fd, char **cgroup) {
@@ -349,7 +300,7 @@ _public_ int sd_uid_get_state(uid_t uid, char**state) {
if (r < 0)
return r;
- r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, "STATE", &s, NULL);
if (r == -ENOENT) {
free(s);
s = strdup("offline");
@@ -380,7 +331,7 @@ _public_ int sd_uid_get_display(uid_t uid, char **session) {
if (r < 0)
return r;
- r = parse_env_file(p, NEWLINE, "DISPLAY", &s, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, "DISPLAY", &s, NULL);
if (r == -ENOENT)
return -ENODATA;
if (r < 0)
@@ -388,8 +339,7 @@ _public_ int sd_uid_get_display(uid_t uid, char **session) {
if (isempty(s))
return -ENODATA;
- *session = s;
- s = NULL;
+ *session = TAKE_PTR(s);
return 0;
}
@@ -418,8 +368,7 @@ static int file_of_seat(const char *seat, char **_p) {
if (!p)
return -ENOMEM;
- *_p = p;
- p = NULL;
+ *_p = TAKE_PTR(p);
return 0;
}
@@ -437,7 +386,7 @@ _public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat)
variable = require_active ? "ACTIVE_UID" : "UIDS";
- r = parse_env_file(p, NEWLINE, variable, &s, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, variable, &s, NULL);
if (r == -ENOENT)
return 0;
if (r < 0)
@@ -466,7 +415,7 @@ static int uid_get_array(uid_t uid, const char *variable, char ***array) {
if (r < 0)
return r;
- r = parse_env_file(p, NEWLINE, variable, &s, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, variable, &s, NULL);
if (r == -ENOENT || (r >= 0 && isempty(s))) {
if (array)
*array = NULL;
@@ -480,7 +429,7 @@ static int uid_get_array(uid_t uid, const char *variable, char ***array) {
return -ENOMEM;
strv_uniq(a);
- r = strv_length(a);
+ r = (int) strv_length(a);
if (array)
*array = a;
@@ -544,7 +493,7 @@ _public_ int sd_session_is_active(const char *session) {
if (r < 0)
return r;
- r = parse_env_file(p, NEWLINE, "ACTIVE", &s, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, "ACTIVE", &s, NULL);
if (r == -ENOENT)
return -ENXIO;
if (r < 0)
@@ -563,7 +512,7 @@ _public_ int sd_session_is_remote(const char *session) {
if (r < 0)
return r;
- r = parse_env_file(p, NEWLINE, "REMOTE", &s, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, "REMOTE", &s, NULL);
if (r == -ENOENT)
return -ENXIO;
if (r < 0)
@@ -584,7 +533,7 @@ _public_ int sd_session_get_state(const char *session, char **state) {
if (r < 0)
return r;
- r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, "STATE", &s, NULL);
if (r == -ENOENT)
return -ENXIO;
if (r < 0)
@@ -592,8 +541,7 @@ _public_ int sd_session_get_state(const char *session, char **state) {
if (isempty(s))
return -EIO;
- *state = s;
- s = NULL;
+ *state = TAKE_PTR(s);
return 0;
}
@@ -608,7 +556,7 @@ _public_ int sd_session_get_uid(const char *session, uid_t *uid) {
if (r < 0)
return r;
- r = parse_env_file(p, NEWLINE, "UID", &s, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, "UID", &s, NULL);
if (r == -ENOENT)
return -ENXIO;
if (r < 0)
@@ -630,7 +578,7 @@ static int session_get_string(const char *session, const char *field, char **val
if (r < 0)
return r;
- r = parse_env_file(p, NEWLINE, field, &s, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, field, &s, NULL);
if (r == -ENOENT)
return -ENXIO;
if (r < 0)
@@ -638,8 +586,7 @@ static int session_get_string(const char *session, const char *field, char **val
if (isempty(s))
return -ENODATA;
- *value = s;
- s = NULL;
+ *value = TAKE_PTR(s);
return 0;
}
@@ -723,7 +670,7 @@ _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
if (r < 0)
return r;
- r = parse_env_file(p, NEWLINE,
+ r = parse_env_file(NULL, p, NEWLINE,
"ACTIVE", &s,
"ACTIVE_UID", &t,
NULL);
@@ -744,10 +691,8 @@ _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
return r;
}
- if (session && s) {
- *session = s;
- s = NULL;
- }
+ if (session && s)
+ *session = TAKE_PTR(s);
return 0;
}
@@ -763,7 +708,7 @@ _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **ui
if (r < 0)
return r;
- r = parse_env_file(p, NEWLINE,
+ r = parse_env_file(NULL, p, NEWLINE,
"SESSIONS", &s,
"UIDS", &t,
NULL);
@@ -808,17 +753,13 @@ _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **ui
}
}
- r = strv_length(a);
+ r = (int) strv_length(a);
- if (sessions) {
- *sessions = a;
- a = NULL;
- }
+ if (sessions)
+ *sessions = TAKE_PTR(a);
- if (uids) {
- *uids = b;
- b = NULL;
- }
+ if (uids)
+ *uids = TAKE_PTR(b);
if (n_uids)
*n_uids = n;
@@ -836,7 +777,7 @@ static int seat_get_can(const char *seat, const char *variable) {
if (r < 0)
return r;
- r = parse_env_file(p, NEWLINE,
+ r = parse_env_file(NULL, p, NEWLINE,
variable, &s,
NULL);
if (r == -ENOENT)
@@ -933,10 +874,8 @@ _public_ int sd_get_uids(uid_t **users) {
r++;
}
- if (users) {
- *users = l;
- l = NULL;
- }
+ if (users)
+ *users = TAKE_PTR(l);
return r;
}
@@ -972,10 +911,9 @@ _public_ int sd_get_machine_names(char ***machines) {
*b = NULL;
}
- if (machines) {
- *machines = l;
- l = NULL;
- }
+ if (machines)
+ *machines = TAKE_PTR(l);
+
return r;
}
@@ -988,7 +926,7 @@ _public_ int sd_machine_get_class(const char *machine, char **class) {
assert_return(class, -EINVAL);
p = strjoina("/run/systemd/machines/", machine);
- r = parse_env_file(p, NEWLINE, "CLASS", &c, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, "CLASS", &c, NULL);
if (r == -ENOENT)
return -ENXIO;
if (r < 0)
@@ -996,8 +934,7 @@ _public_ int sd_machine_get_class(const char *machine, char **class) {
if (!c)
return -EIO;
- *class = c;
- c = NULL;
+ *class = TAKE_PTR(c);
return 0;
}
@@ -1013,7 +950,7 @@ _public_ int sd_machine_get_ifindices(const char *machine, int **ifindices) {
assert_return(ifindices, -EINVAL);
p = strjoina("/run/systemd/machines/", machine);
- r = parse_env_file(p, NEWLINE, "NETIF", &netif, NULL);
+ r = parse_env_file(NULL, p, NEWLINE, "NETIF", &netif, NULL);
if (r == -ENOENT)
return -ENXIO;
if (r < 0)
@@ -1053,8 +990,9 @@ static inline sd_login_monitor* FD_TO_MONITOR(int fd) {
}
_public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) {
- int fd, k;
+ _cleanup_close_ int fd = -1;
bool good = false;
+ int k;
assert_return(m, -EINVAL);
@@ -1064,50 +1002,42 @@ _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) {
if (!category || streq(category, "seat")) {
k = inotify_add_watch(fd, "/run/systemd/seats/", IN_MOVED_TO|IN_DELETE);
- if (k < 0) {
- safe_close(fd);
+ if (k < 0)
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) {
- safe_close(fd);
+ if (k < 0)
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) {
- safe_close(fd);
+ if (k < 0)
return -errno;
- }
good = true;
}
if (!category || streq(category, "machine")) {
k = inotify_add_watch(fd, "/run/systemd/machines/", IN_MOVED_TO|IN_DELETE);
- if (k < 0) {
- safe_close(fd);
+ if (k < 0)
return -errno;
- }
good = true;
}
- if (!good) {
- close_nointr(fd);
+ if (!good)
return -EINVAL;
- }
*m = FD_TO_MONITOR(fd);
+ fd = -1;
+
return 0;
}
@@ -1124,10 +1054,15 @@ _public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) {
}
_public_ int sd_login_monitor_flush(sd_login_monitor *m) {
+ int r;
assert_return(m, -EINVAL);
- return flush_fd(MONITOR_TO_FD(m));
+ r = flush_fd(MONITOR_TO_FD(m));
+ if (r < 0)
+ return r;
+
+ return 0;
}
_public_ int sd_login_monitor_get_fd(sd_login_monitor *m) {
diff --git a/src/libelogind/sd-login/test-login.c b/src/libelogind/sd-login/test-login.c
index 3eb11cf4a..87ad0bd5d 100644
--- a/src/libelogind/sd-login/test-login.c
+++ b/src/libelogind/sd-login/test-login.c
@@ -1,20 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- 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 <poll.h>
@@ -57,10 +42,11 @@ static void test_login(void) {
*type = NULL, *class = NULL, *state = NULL, *state2 = NULL,
*seat = NULL, *session = NULL,
*unit = NULL, *user_unit = NULL, *slice = NULL;
- int r, k;
+ int r;
uid_t u, u2;
char *t, **seats, **sessions;
+#if 0 /// elogind does not support systemd units
r = sd_pid_get_unit(0, &unit);
assert_se(r >= 0 || r == -ENODATA);
log_info("sd_pid_get_unit(0, …) → \"%s\"", strna(unit));
@@ -68,6 +54,7 @@ static void test_login(void) {
r = sd_pid_get_user_unit(0, &user_unit);
assert_se(r >= 0 || r == -ENODATA);
log_info("sd_pid_get_user_unit(0, …) → \"%s\"", strna(user_unit));
+#endif // 0
r = sd_pid_get_slice(0, &slice);
assert_se(r >= 0 || r == -ENODATA);
@@ -159,7 +146,7 @@ static void test_login(void) {
if (r >= 0) {
assert_se(seat);
- log_info("sd_session_get_display(\"%s\") → \"%s\"", session, seat);
+ log_info("sd_session_get_seat(\"%s\") → \"%s\"", session, seat);
r = sd_seat_can_multi_session(seat);
assert_se(r >= 0);
@@ -173,7 +160,7 @@ static void test_login(void) {
assert_se(r >= 0);
log_info("sd_session_can_graphical(\"%s\") → %s", seat, yes_no(r));
} else {
- log_info_errno(r, "sd_session_get_display(\"%s\"): %m", session);
+ log_info_errno(r, "sd_session_get_seat(\"%s\"): %m", session);
assert_se(r == -ENODATA);
}
@@ -188,13 +175,14 @@ static void test_login(void) {
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(!!k == !!r);
-
- assert_se(sd_seat_get_active(seat, &session2, &u2) >= 0);
+ r = sd_seat_get_active(seat, &session2, &u2);
+ assert_se(r >= 0);
log_info("sd_seat_get_active(\"%s\", …) → \"%s\", "UID_FMT, seat, session2, u2);
+ r = sd_uid_is_on_seat(u, 1, seat);
+ assert_se(r >= 0);
+ assert_se(!!r == streq(session, session2));
+
r = sd_seat_get_sessions(seat, &sessions, &uids, &n);
assert_se(r >= 0);
assert_se(r == (int) strv_length(sessions));
diff --git a/src/login/70-power-switch.rules b/src/login/70-power-switch.rules
index 394a80f1f..f569ab50c 100644
--- a/src/login/70-power-switch.rules
+++ b/src/login/70-power-switch.rules
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
@@ -9,5 +11,10 @@ ACTION=="remove", GOTO="power_switch_end"
SUBSYSTEM=="input", KERNEL=="event*", ENV{ID_INPUT_SWITCH}=="1", TAG+="power-switch"
SUBSYSTEM=="input", KERNEL=="event*", ENV{ID_INPUT_KEY}=="1", TAG+="power-switch"
+SUBSYSTEM=="input", KERNEL=="event*", SUBSYSTEMS=="acpi", TAG+="power-switch"
+SUBSYSTEM=="input", KERNEL=="event*", KERNELS=="thinkpad_acpi", TAG+="power-switch"
+SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="twl4030_pwrbutton", TAG+="power-switch"
+SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="tps65217_pwr_but", TAG+="power-switch"
+SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="* WMI hotkeys", TAG+="power-switch"
LABEL="power_switch_end"
diff --git a/src/login/70-uaccess.rules b/src/login/70-uaccess.rules
index 50dcd2e27..3515d292a 100644
--- a/src/login/70-uaccess.rules
+++ b/src/login/70-uaccess.rules
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
@@ -25,7 +27,7 @@ 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" \
+SUBSYSTEM=="sound", TAG+="uaccess", \
OPTIONS+="static_node=snd/timer", OPTIONS+="static_node=snd/seq"
# ffado is an userspace driver for firewire sound cards
@@ -43,10 +45,7 @@ SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x010001*", TAG+="uaccess"
SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x014001*", TAG+="uaccess"
# DRI video devices
-SUBSYSTEM=="drm", KERNEL=="card*|renderD*", TAG+="uaccess"
-
-# KVM
-SUBSYSTEM=="misc", KERNEL=="kvm", TAG+="uaccess"
+SUBSYSTEM=="drm", KERNEL=="card*", TAG+="uaccess"
# smart-card readers
ENV{ID_SMARTCARD_READER}=="?*", TAG+="uaccess"
diff --git a/src/login/71-seat.rules.in b/src/login/71-seat.rules.in
index de55c9a4e..0db46adc8 100644
--- a/src/login/71-seat.rules.in
+++ b/src/login/71-seat.rules.in
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
diff --git a/src/login/73-seat-late.rules.in b/src/login/73-seat-late.rules.in
index 901df750f..ed53f324d 100644
--- a/src/login/73-seat-late.rules.in
+++ b/src/login/73-seat-late.rules.in
@@ -1,6 +1,8 @@
-# This file is part of systemd.
+# SPDX-License-Identifier: LGPL-2.1+
#
-# systemd is free software; you can redistribute it and/or modify it
+# This file is part of elogind.
+#
+# elogind is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
@@ -11,7 +13,8 @@ ENV{ID_SEAT}=="", ENV{ID_AUTOSEAT}=="1", ENV{ID_FOR_SEAT}!="", ENV{ID_SEAT}="sea
ENV{ID_SEAT}=="", IMPORT{parent}="ID_SEAT"
ENV{ID_SEAT}!="", TAG+="$env{ID_SEAT}"
-
-TAG=="uaccess", ENV{MAJOR}!="", RUN{builtin}+="uaccess"
+m4_ifdef(`HAVE_ACL',``
+TAG=="uaccess", ENV{MAJOR}!="", RUN{program}+="@rootlibexecdir@/elogind-uaccess-command %N $env{ID_SEAT}"''
+)m4_dnl
LABEL="seat_late_end"
diff --git a/src/login/Makefile b/src/login/Makefile
deleted file mode 120000
index d0b0e8e00..000000000
--- a/src/login/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/login/eloginctl.c b/src/login/eloginctl.c
index 8adfb62e9..644686ad2 100644
--- a/src/login/eloginctl.c
+++ b/src/login/eloginctl.c
@@ -36,6 +36,8 @@
elogind_action arg_action = _ACTION_INVALID;
bool arg_ask_password = true;
+bool arg_dry_run = false;
+bool arg_quiet = false;
bool arg_ignore_inhibitors = false;
bool arg_no_wall = false;
BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
@@ -46,11 +48,15 @@ static const struct {
HandleAction action;
const char* verb;
} action_table[_ACTION_MAX] = {
- [ACTION_POWEROFF] = { HANDLE_POWEROFF, "poweroff", },
- [ACTION_REBOOT] = { HANDLE_REBOOT, "reboot", },
- [ACTION_SUSPEND] = { HANDLE_SUSPEND, "suspend", },
- [ACTION_HIBERNATE] = { HANDLE_HIBERNATE, "hibernate", },
- [ACTION_HYBRID_SLEEP] = { HANDLE_HYBRID_SLEEP, "hybrid-sleep" },
+ [ACTION_HALT] = { HANDLE_HALT, "halt" },
+ [ACTION_POWEROFF] = { HANDLE_POWEROFF, "poweroff", },
+ [ACTION_REBOOT] = { HANDLE_REBOOT, "reboot", },
+ [ACTION_KEXEC] = { HANDLE_KEXEC, "kexec", },
+ [ACTION_SUSPEND] = { HANDLE_SUSPEND, "suspend", },
+ [ACTION_HIBERNATE] = { HANDLE_HIBERNATE, "hibernate", },
+ [ACTION_HYBRID_SLEEP] = { HANDLE_HYBRID_SLEEP, "hybrid-sleep" },
+ [ACTION_SUSPEND_THEN_HIBERNATE] = { HANDLE_SUSPEND_THEN_HIBERNATE, "suspend-then-hibernate" }
+ /* ACTION_CANCEL_SHUTDOWN is handled differently */
};
static int elogind_set_wall_message(sd_bus* bus, const char* msg);
@@ -66,7 +72,7 @@ static enum elogind_action verb_to_action(const char *verb) {
}
/* Original:
- * systemctl/systemctl.c:3292:logind_check_inhibitors()
+ * systemctl/systemctl.c:3314:logind_check_inhibitors()
*/
static int check_inhibitors(sd_bus* bus, enum elogind_action a) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
@@ -120,8 +126,10 @@ static int check_inhibitors(sd_bus* bus, enum elogind_action a) {
if (!sv)
return log_oom();
- if ((pid_t) pid < 0)
- return log_error_errno(ERANGE, "Bad PID %"PRIu32": %m", pid);
+ if (!pid_is_valid((pid_t) pid)) {
+ log_error("Invalid PID "PID_FMT".", (pid_t) pid);
+ return -ERANGE;
+ }
if (!strv_contains(sv,
IN_SET(a,
@@ -157,7 +165,7 @@ static int check_inhibitors(sd_bus* bus, enum elogind_action a) {
if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
continue;
- if (sd_session_get_type(*s, &type) < 0 || !STR_IN_SET(type, "x11", "tty"))
+ if (sd_session_get_type(*s, &type) < 0 || !STR_IN_SET(type, "x11", "wayland", "tty", "mir"))
continue;
sd_session_get_tty(*s, &tty);
@@ -179,7 +187,7 @@ static int check_inhibitors(sd_bus* bus, enum elogind_action a) {
}
/* Original:
- * systemctl/systemctl.c:8410:logind_cancel_shutdown()
+ * systemctl/systemctl.c:8683:logind_cancel_shutdown()
*/
int elogind_cancel_shutdown(sd_bus *bus) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
@@ -209,9 +217,9 @@ void elogind_cleanup(void) {
strv_free(arg_wall);
}
-/* Littel debug log helper, helps debugging systemctl comands we mimic. */
+/* Little debug log helper, helps debugging systemctl comands we mimic. */
static void elogind_log_special(enum elogind_action a) {
-#ifdef ENABLE_DEBUG_ELOGIND
+#if ENABLE_DEBUG_ELOGIND
switch (a) {
case ACTION_HALT:
log_struct(LOG_INFO,
@@ -255,6 +263,12 @@ static void elogind_log_special(enum elogind_action a) {
"MESSAGE_ID=" SD_MESSAGE_SLEEP_START_STR,
NULL);
break;
+ case ACTION_SUSPEND_THEN_HIBERNATE:
+ log_struct(LOG_INFO,
+ LOG_MESSAGE("Suspend-Then-Hibernate action called."),
+ "MESSAGE_ID=" SD_MESSAGE_SLEEP_START_STR,
+ NULL);
+ break;
case ACTION_CANCEL_SHUTDOWN:
log_struct(LOG_INFO,
LOG_MESSAGE("Cancel Shutdown called."),
@@ -268,15 +282,16 @@ static void elogind_log_special(enum elogind_action a) {
}
/* Original:
- * systemctl/systemctl.c:3229:logind_reboot()
+ * systemctl/systemctl.c:3242:logind_reboot()
*/
static int elogind_reboot(sd_bus *bus, enum elogind_action a) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *method = NULL, *description = NULL;
int r;
static const char *table[_ACTION_MAX] = {
- [ACTION_REBOOT] = "The system is going down for reboot NOW!",
- [ACTION_POWEROFF] = "The system is going down for power-off NOW!"
+ [ACTION_HALT] = "The system is going down for halt NOW!",
+ [ACTION_REBOOT] = "The system is going down for reboot NOW!",
+ [ACTION_POWEROFF] = "The system is going down for power-off NOW!"
};
if (!bus)
@@ -284,9 +299,9 @@ static int elogind_reboot(sd_bus *bus, enum elogind_action a) {
switch (a) {
- case ACTION_REBOOT:
- method = "Reboot";
- description = "reboot system";
+ case ACTION_HALT:
+ method = "Halt";
+ description = "halt system";
break;
case ACTION_POWEROFF:
@@ -294,6 +309,11 @@ static int elogind_reboot(sd_bus *bus, enum elogind_action a) {
description = "power off system";
break;
+ case ACTION_REBOOT:
+ method = "Reboot";
+ description = "reboot system";
+ break;
+
case ACTION_SUSPEND:
method = "Suspend";
description = "suspend system";
@@ -309,15 +329,26 @@ static int elogind_reboot(sd_bus *bus, enum elogind_action a) {
description = "put system into hybrid sleep";
break;
+ case ACTION_SUSPEND_THEN_HIBERNATE:
+ method = "SuspendThenHibernate";
+ description = "put system into suspend followed by hibernate";
+ break;
+
default:
return -EINVAL;
}
- polkit_agent_open_if_enabled();
+ /* No need for polkit_agent_open_maybe() in elogind. Do it directly. */
+ polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
- if ( IN_SET(a, ACTION_POWEROFF, ACTION_REBOOT) )
+ if ( IN_SET(a, ACTION_HALT, ACTION_POWEROFF, ACTION_REBOOT) )
(void) elogind_set_wall_message(bus, table[a]);
+ log_debug("%s org.freedesktop.login1.Manager %s dbus call.", arg_dry_run ? "Would execute" : "Executing", method);
+
+ if (arg_dry_run)
+ return 0;
+
/* Now call elogind itself to request the operation */
r = sd_bus_call_method(
bus,
@@ -338,7 +369,7 @@ static int elogind_reboot(sd_bus *bus, enum elogind_action a) {
}
/* Original:
- * systemctl/systemctl.c:8281:logind_schedule_shutdown()
+ * systemctl/systemctl.c:8553:logind_schedule_shutdown()
*/
static int elogind_schedule_shutdown(sd_bus *bus, enum elogind_action a) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
@@ -365,6 +396,9 @@ static int elogind_schedule_shutdown(sd_bus *bus, enum elogind_action a) {
break;
}
+ if (arg_dry_run)
+ action = strjoina("dry-", action);
+
(void) elogind_set_wall_message(bus, NULL);
r = sd_bus_call_method(
@@ -384,14 +418,14 @@ static int elogind_schedule_shutdown(sd_bus *bus, enum elogind_action a) {
"Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s",
bus_error_message(&error, r));
- log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
- format_timestamp(date, sizeof(date), arg_when));
+ if (!arg_quiet)
+ log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date, sizeof(date), arg_when));
return 0;
}
/* Original:
- * systemctl/systemctl.c:3193:logind_set_wall_message()
+ * systemctl/systemctl.c:3204:logind_set_wall_message()
* (Tweaked to allow an extra message to be appended.)
*/
static int elogind_set_wall_message(sd_bus* bus, const char* msg) {
@@ -406,6 +440,10 @@ static int elogind_set_wall_message(sd_bus* bus, const char* msg) {
if (!m)
return log_oom();
+ log_debug("%s wall message \"%s\".", arg_dry_run ? "Would set" : "Setting", m);
+ if (arg_dry_run)
+ return 0;
+
r = sd_bus_call_method(
bus,
"org.freedesktop.login1",
@@ -477,22 +515,6 @@ static int parse_shutdown_time_spec(const char *t, usec_t *_u) {
}
/* Original:
- * systemctl/systemctl.c:270:polkit_agent_open_if_enabled()
- */
-void polkit_agent_open_if_enabled(void) {
-
- /* Open the polkit agent as a child process if necessary */
-
- if (!arg_ask_password)
- return;
-
- if (arg_transport != BUS_TRANSPORT_LOCAL)
- return;
-
- polkit_agent_open();
-}
-
-/* Original:
* systemctl/systemctl.c:3482:start_special()
* However, this elogind variant is very different from the original.
*/
@@ -560,7 +582,8 @@ int start_special(int argc, char *argv[], void *userdata) {
ACTION_REBOOT,
ACTION_SUSPEND,
ACTION_HIBERNATE,
- ACTION_HYBRID_SLEEP)) {
+ ACTION_HYBRID_SLEEP,
+ ACTION_SUSPEND_THEN_HIBERNATE)) {
if (arg_when > 0)
return elogind_schedule_shutdown(bus, a);
else
diff --git a/src/login/eloginctl.h b/src/login/eloginctl.h
index b6e96930b..2c487a880 100644
--- a/src/login/eloginctl.h
+++ b/src/login/eloginctl.h
@@ -34,6 +34,7 @@ typedef enum elogind_action {
ACTION_SUSPEND,
ACTION_HIBERNATE,
ACTION_HYBRID_SLEEP,
+ ACTION_SUSPEND_THEN_HIBERNATE,
ACTION_CANCEL_SHUTDOWN,
_ACTION_MAX
} elogind_action;
@@ -41,7 +42,6 @@ typedef enum elogind_action {
int elogind_cancel_shutdown(sd_bus *bus);
void elogind_cleanup(void);
-void polkit_agent_open_if_enabled(void);
int start_special(int argc, char *argv[], void *userdata);
diff --git a/src/login/elogind-dbus.c b/src/login/elogind-dbus.c
index a9b39c238..bed528145 100644
--- a/src/login/elogind-dbus.c
+++ b/src/login/elogind-dbus.c
@@ -18,19 +18,13 @@
***/
-#include "bus-common-errors.h"
-#include "bus-error.h"
-#include "bus-util.h"
#include "elogind-dbus.h"
-#include "fd-util.h"
#include "process-util.h"
#include "sd-messages.h"
#include "sleep.h"
-#include "sleep-config.h"
#include "string-util.h"
#include "strv.h"
#include "update-utmp.h"
-#include "user-util.h"
static int bus_manager_log_shutdown(
@@ -81,22 +75,21 @@ static int bus_manager_log_shutdown(
/* elogind specific helper to make HALT and REBOOT possible. */
static int run_helper(const char *helper) {
- int pid = fork();
- if (pid < 0) {
- return log_error_errno(errno, "Failed to fork: %m");
- }
+ int r = 0;
- if (pid == 0) {
- /* Child */
+ r = safe_fork_full(helper, NULL, 0, FORK_RESET_SIGNALS|FORK_REOPEN_LOG, NULL);
- close_all_fds(NULL, 0);
+ if (r < 0)
+ return log_error_errno(errno, "Failed to fork run %s: %m", helper);
+ if (0 == r) {
+ /* Child */
execlp(helper, helper, NULL);
log_error_errno(errno, "Failed to execute %s: %m", helper);
_exit(EXIT_FAILURE);
}
- return wait_for_terminate_and_warn(helper, pid, true);
+ return 0;
}
/* elogind specific executor */
@@ -106,7 +99,7 @@ static int shutdown_or_sleep(Manager *m, HandleAction action) {
switch (action) {
case HANDLE_POWEROFF:
- return run_helper(HALT);
+ return run_helper(POWEROFF);
case HANDLE_REBOOT:
return run_helper(REBOOT);
case HANDLE_HALT:
@@ -114,17 +107,19 @@ static int shutdown_or_sleep(Manager *m, HandleAction action) {
case HANDLE_KEXEC:
return run_helper(KEXEC);
case HANDLE_SUSPEND:
- return do_sleep("suspend", m->suspend_mode, m->suspend_state);
+ return do_sleep(m, "suspend");
case HANDLE_HIBERNATE:
- return do_sleep("hibernate", m->hibernate_mode, m->hibernate_state);
+ return do_sleep(m, "hibernate");
case HANDLE_HYBRID_SLEEP:
- return do_sleep("hybrid-sleep", m->hybrid_sleep_mode, m->hybrid_sleep_state);
+ return do_sleep(m, "hybrid-sleep");
+ case HANDLE_SUSPEND_THEN_HIBERNATE:
+ return do_sleep(m, "suspend-then-hibernate");
default:
return -EINVAL;
}
}
-static int execute_shutdown_or_sleep(
+int execute_shutdown_or_sleep(
Manager *m,
InhibitWhat w,
HandleAction action,
@@ -157,7 +152,7 @@ static int execute_shutdown_or_sleep(
}
/* This comes from our patched update-utmp/update-utmp.c */
- update_utmp(2, argv_utmp, m->bus);
+ update_utmp(2, argv_utmp);
strv_free(argv_utmp);
}
@@ -171,7 +166,7 @@ static int execute_shutdown_or_sleep(
* sleeping processes to wake up, we have to tell them all
* by ourselves. */
if (w == INHIBIT_SLEEP) {
- send_prepare_for(m, w, false);
+ (void) send_prepare_for(m, w, false);
m->action_what = 0;
} else
m->action_what = w;
@@ -185,217 +180,6 @@ static int execute_shutdown_or_sleep(
return 0;
}
-int manager_dispatch_delayed(Manager *manager, bool timeout) {
-
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- Inhibitor *offending = NULL;
- int r;
-
- assert(manager);
-
- if ( (0 == manager->action_what) || (HANDLE_IGNORE == manager->pending_action) )
- return 0;
-
- if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
- _cleanup_free_ char *comm = NULL, *u = NULL;
-
- if (!timeout)
- return 0;
-
- (void) get_process_comm(offending->pid, &comm);
- u = uid_to_name(offending->uid);
-
- log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
- offending->uid, strna(u),
- offending->pid, strna(comm));
- }
-
- /* Actually do the operation */
- r = execute_shutdown_or_sleep(manager, manager->action_what, manager->pending_action, &error);
- if (r < 0) {
- log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
-
- manager->pending_action = HANDLE_IGNORE;
- manager->action_what = 0;
- /* It is not a critical error for elogind if suspending fails */
- }
-
- return 1;
-}
-
-static int delay_shutdown_or_sleep(
- Manager *m,
- InhibitWhat w,
- HandleAction action) {
-
- int r;
- usec_t timeout_val;
-
- assert(m);
- assert(w >= 0);
- assert(w < _INHIBIT_WHAT_MAX);
-
- timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
-
- if (m->inhibit_timeout_source) {
- r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
- if (r < 0)
- return log_error_errno(r, "sd_event_source_set_time() failed: %m");
-
- r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
- if (r < 0)
- return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
- } else {
- r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
- timeout_val, 0, manager_inhibit_timeout_handler, m);
- if (r < 0)
- return r;
- }
-
- m->pending_action = action;
- m->action_what = w;
-
- return 0;
-}
-
-int bus_manager_shutdown_or_sleep_now_or_later(
- Manager *m,
- HandleAction action,
- InhibitWhat w,
- sd_bus_error *error) {
-
- bool delayed;
- int r;
-
- assert(m);
- assert(w >= 0);
- assert(w <= _INHIBIT_WHAT_MAX);
-
- /* Tell everybody to prepare for shutdown/sleep */
- send_prepare_for(m, w, true);
-
- delayed =
- m->inhibit_delay_max > 0 &&
- manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
-
- log_debug_elogind("%s called for %s (%sdelayed)", __FUNCTION__,
- handle_action_to_string(action),
- delayed ? "" : "NOT ");
-
- if (delayed)
- /* Shutdown is delayed, keep in mind what we
- * want to do, and start a timeout */
- r = delay_shutdown_or_sleep(m, w, action);
- else
- /* Shutdown is not delayed, execute it
- * immediately */
- r = execute_shutdown_or_sleep(m, w, action, error);
-
- return r;
-}
-
-static int method_do_shutdown_or_sleep(
- Manager *m,
- sd_bus_message *message,
- HandleAction sleep_action,
- InhibitWhat w,
- const char *action,
- const char *action_multiple_sessions,
- const char *action_ignore_inhibit,
- const char *sleep_verb,
- sd_bus_error *error) {
-
- int interactive, r;
-
- assert(m);
- assert(message);
- assert(w >= 0);
- assert(w <= _INHIBIT_WHAT_MAX);
-
- r = sd_bus_message_read(message, "b", &interactive);
- if (r < 0)
- return r;
-
- log_debug_elogind("%s called with action '%s', sleep '%s' (%sinteractive)",
- __FUNCTION__, action, sleep_verb,
- interactive ? "" : "NOT ");
-
- /* Don't allow multiple jobs being executed at the same time */
- if (m->action_what)
- return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
-
- if (sleep_verb) {
- r = can_sleep(m, sleep_verb);
- if (r < 0)
- return r;
-
- if (r == 0)
- return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
- }
-
- if (IN_SET(sleep_action, HANDLE_HALT, HANDLE_POWEROFF, HANDLE_REBOOT)) {
- r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
- action_ignore_inhibit, error);
- log_debug_elogind("verify_shutdown_creds() returned %d", r);
- if (r != 0)
- return r;
- }
-
- r = bus_manager_shutdown_or_sleep_now_or_later(m, sleep_action, w, error);
- if (r < 0)
- return r;
-
- return sd_bus_reply_method_return(message, NULL);
-}
-
-int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- Manager *m = userdata;
-
- log_debug_elogind("%s called", __FUNCTION__);
-
- return method_do_shutdown_or_sleep(
- m, message,
- HANDLE_POWEROFF,
- INHIBIT_SHUTDOWN,
- "org.freedesktop.login1.power-off",
- "org.freedesktop.login1.power-off-multiple-sessions",
- "org.freedesktop.login1.power-off-ignore-inhibit",
- NULL,
- error);
-}
-
-int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- Manager *m = userdata;
-
- log_debug_elogind("%s called", __FUNCTION__);
-
- return method_do_shutdown_or_sleep(
- m, message,
- HANDLE_REBOOT,
- INHIBIT_SHUTDOWN,
- "org.freedesktop.login1.reboot",
- "org.freedesktop.login1.reboot-multiple-sessions",
- "org.freedesktop.login1.reboot-ignore-inhibit",
- NULL,
- error);
-}
-
-int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- Manager *m = userdata;
-
- log_debug_elogind("%s called", __FUNCTION__);
-
- return method_do_shutdown_or_sleep(
- m, message,
- HANDLE_SUSPEND,
- INHIBIT_SLEEP,
- "org.freedesktop.login1.suspend",
- "org.freedesktop.login1.suspend-multiple-sessions",
- "org.freedesktop.login1.suspend-ignore-inhibit",
- "suspend",
- error);
-}
-
int manager_scheduled_shutdown_handler(
sd_event_source *s,
uint64_t usec,
@@ -418,41 +202,37 @@ int manager_scheduled_shutdown_handler(
else
action = HANDLE_REBOOT;
- r = execute_shutdown_or_sleep(m, 0, action, &error);
- if (r < 0)
- return log_error_errno(r, "Unable to execute transition to %s: %m", m->scheduled_shutdown_type);
+ /* Don't allow multiple jobs being executed at the same time */
+ if (m->action_what) {
+ r = -EALREADY;
+ log_error("Scheduled shutdown to %s failed: shutdown or sleep operation already in progress",
+ m->scheduled_shutdown_type);
+ goto error;
+ }
- return 0;
-}
+ if (m->shutdown_dry_run) {
+ /* We do not process delay inhibitors here. Otherwise, we
+ * would have to be considered "in progress" (like the check
+ * above) for some seconds after our admin has seen the final
+ * wall message. */
-int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- Manager *m = userdata;
+ bus_manager_log_shutdown(m, INHIBIT_SHUTDOWN, action);
+ log_info("Running in dry run, suppressing action.");
+ reset_scheduled_shutdown(m);
- log_debug_elogind("%s called", __FUNCTION__);
-
- return method_do_shutdown_or_sleep(
- m, message,
- HANDLE_HIBERNATE,
- INHIBIT_SLEEP,
- "org.freedesktop.login1.hibernate",
- "org.freedesktop.login1.hibernate-multiple-sessions",
- "org.freedesktop.login1.hibernate-ignore-inhibit",
- "hibernate",
- error);
-}
+ return 0;
+ }
-int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- Manager *m = userdata;
+ r = execute_shutdown_or_sleep(m, 0, action, &error);
+ if (r < 0) {
+ log_error_errno(r, "Scheduled shutdown to %s failed: %m",
+ m->scheduled_shutdown_type);
+ goto error;
+ }
- log_debug_elogind("%s called", __FUNCTION__);
-
- return method_do_shutdown_or_sleep(
- m, message,
- HANDLE_HYBRID_SLEEP,
- INHIBIT_SLEEP,
- "org.freedesktop.login1.hibernate",
- "org.freedesktop.login1.hibernate-multiple-sessions",
- "org.freedesktop.login1.hibernate-ignore-inhibit",
- "hybrid-sleep",
- error);
+ return 0;
+
+error:
+ reset_scheduled_shutdown(m);
+ return r;
}
diff --git a/src/login/elogind-dbus.h b/src/login/elogind-dbus.h
index 87ab2b869..fbcff4fc2 100644
--- a/src/login/elogind-dbus.h
+++ b/src/login/elogind-dbus.h
@@ -23,23 +23,15 @@
#include "logind.h"
+int execute_shutdown_or_sleep(Manager *m, InhibitWhat w,
+ HandleAction action, sd_bus_error *error);
int manager_scheduled_shutdown_handler(sd_event_source *s, uint64_t usec,
void *userdata);
-int method_hibernate (sd_bus_message *message, void *userdata, sd_bus_error *error);
-int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error);
-int method_poweroff (sd_bus_message *message, void *userdata, sd_bus_error *error);
-int method_reboot (sd_bus_message *message, void *userdata, sd_bus_error *error);
-int method_suspend (sd_bus_message *message, void *userdata, sd_bus_error *error);
-
/* prototypes for former static functions in logind-dbus.c */
-int manager_inhibit_timeout_handler(sd_event_source *s, uint64_t usec, void *userdata);
-int send_prepare_for(Manager *m, InhibitWhat w, bool _active);
-int verify_shutdown_creds(Manager *m, sd_bus_message *message, InhibitWhat w,
- bool interactive, const char *action,
- const char *action_multiple_sessions,
- const char *action_ignore_inhibit,
- sd_bus_error *error);
+int delay_shutdown_or_sleep(Manager *m, InhibitWhat w, HandleAction action);
+void reset_scheduled_shutdown(Manager *m);
+int send_prepare_for(Manager *m, InhibitWhat w, bool _active);
#endif // ELOGIND_SRC_LOGIN_ELOGIND_DBUS_H_INCLUDED
diff --git a/src/login/elogind.c b/src/login/elogind.c
index 894827074..9fe52a94c 100644
--- a/src/login/elogind.c
+++ b/src/login/elogind.c
@@ -70,7 +70,7 @@ static void write_pid_file(void) {
pid_t pid;
int r;
- pid = getpid();
+ pid = getpid_cached();
xsprintf(c, PID_FMT "\n", pid);
@@ -97,60 +97,54 @@ static int elogind_daemonize(void) {
pid_t SID;
int r;
-#ifdef ENABLE_DEBUG_ELOGIND
+#if ENABLE_DEBUG_ELOGIND
log_notice("Double forking elogind");
- log_notice("Parent PID : %5d", getpid());
- log_notice("Parent SID : %5d", getsid(getpid()));
+ log_notice("Parent PID : %5d", getpid_cached());
+ log_notice("Parent SID : %5d", getsid(getpid_cached()));
#endif // ENABLE_DEBUG_ELOGIND
- child = fork();
+ r = safe_fork_full("elogind-forker", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_NULL_STDIO|FORK_WAIT, &child);
- if (child < 0)
- return log_error_errno(errno, "Failed to fork: %m");
+ if (r < 0)
+ return log_error_errno(errno, "Failed to fork daemon leader: %m");
- if (child) {
- /* Wait for the child to terminate, so the decoupling
- * is guaranteed to succeed.
- */
- r = wait_for_terminate_and_warn("elogind control child", child, true);
- if (r < 0)
- return r;
+ /* safe_fork_full() Has waited for the child to terminate, so we
+ * are safe to return here. The child already has forked off the
+ * daemon itself.
+ */
+ if (r)
return child;
- }
-#ifdef ENABLE_DEBUG_ELOGIND
- log_notice("Child PID : %5d", getpid());
- log_notice("Child SID : %5d", getsid(getpid()));
+#if ENABLE_DEBUG_ELOGIND
+ log_notice("Child PID : %5d", getpid_cached());
+ log_notice("Child SID : %5d", getsid(getpid_cached()));
#endif // ENABLE_DEBUG_ELOGIND
- /* The first child has to become a new session leader. */
- close_all_fds(NULL, 0);
SID = setsid();
if ((pid_t)-1 == SID)
return log_error_errno(errno, "Failed to create new SID: %m");
-#ifdef ENABLE_DEBUG_ELOGIND
- log_notice("Child new SID : %5d", getsid(getpid()));
+#if ENABLE_DEBUG_ELOGIND
+ log_notice("Child new SID : %5d", getsid(getpid_cached()));
#endif // ENABLE_DEBUG_ELOGIND
umask(0022);
/* Now the grandchild, the true daemon, can be created. */
- grandchild = fork();
+ r = safe_fork_full("elogind-daemon", NULL, 0, FORK_REOPEN_LOG, &grandchild);
- if (grandchild < 0)
- return log_error_errno(errno, "Failed to double fork: %m");
+ if (r < 0)
+ return log_error_errno(errno, "Failed to fork daemon: %m");
- if (grandchild)
+ if (r)
/* Exit immediately! */
return grandchild;
- close_all_fds(NULL, 0);
umask(0022);
-#ifdef ENABLE_DEBUG_ELOGIND
- log_notice("Grand child PID: %5d", getpid());
- log_notice("Grand child SID: %5d", getsid(getpid()));
+#if ENABLE_DEBUG_ELOGIND
+ log_notice("Grand child PID: %5d", getpid_cached());
+ log_notice("Grand child SID: %5d", getsid(getpid_cached()));
#endif // ENABLE_DEBUG_ELOGIND
/* Take care of our PID-file now */
@@ -176,7 +170,7 @@ static pid_t elogind_is_already_running(bool need_pid_file) {
if (r < 0)
goto we_are_alone;
- if ( (pid != getpid()) && pid_is_alive(pid))
+ if ( (pid != getpid_cached()) && pid_is_alive(pid))
return pid;
we_are_alone:
@@ -243,7 +237,7 @@ int elogind_setup_cgroups_agent(Manager *m) {
* to it. The system instance hence listens on this special socket, but the user instances listen on the system
* bus for these messages. */
- if (m->test_run)
+ if (m->test_run_flags)
return 0;
if (!MANAGER_IS_SYSTEM(m))
@@ -325,7 +319,7 @@ int elogind_startup(int argc, char *argv[]) {
/* Note: At this point, the logging is not initialized, so we can not
use log_debug_elogind(). */
-#ifdef ENABLE_DEBUG_ELOGIND
+#if ENABLE_DEBUG_ELOGIND
log_notice("elogind startup: Daemonize: %s, Show Help: %s, Wrong arg: %s",
daemonize ? "True" : "False",
show_help ? "True" : "False",
@@ -382,15 +376,16 @@ int elogind_manager_new(Manager* m) {
m->cgroups_agent_fd = -1;
m->pin_cgroupfs_fd = -1;
- m->test_run = false;
+ m->test_run_flags = 0;
/* Init sleep modes and states */
- m->suspend_mode = NULL;
- m->suspend_state = NULL;
- m->hibernate_mode = NULL;
- m->hibernate_state = NULL;
- m->hybrid_sleep_mode = NULL;
- m->hybrid_sleep_state = NULL;
+ m->suspend_mode = NULL;
+ m->suspend_state = NULL;
+ m->hibernate_mode = NULL;
+ m->hibernate_state = NULL;
+ m->hybrid_sleep_mode = NULL;
+ m->hybrid_sleep_state = NULL;
+ m->hibernate_delay_sec = 0;
/* If elogind should be its own controller, mount its cgroup */
if (streq(SYSTEMD_CGROUP_CONTROLLER, "_elogind")) {
@@ -410,7 +405,7 @@ int elogind_manager_new(Manager* m) {
/// Add-On for manager_reset_config()
void elogind_manager_reset_config(Manager* m) {
-#ifdef ENABLE_DEBUG_ELOGIND
+#if ENABLE_DEBUG_ELOGIND
int dbg_cnt;
#endif // ENABLE_DEBUG_ELOGIND
@@ -425,8 +420,10 @@ void elogind_manager_reset_config(Manager* m) {
m->hybrid_sleep_mode = strv_new("suspend", "platform", "shutdown", NULL);
if (!m->hybrid_sleep_state)
m->hybrid_sleep_state = strv_new("disk", NULL);
+ if (!m->hibernate_delay_sec)
+ m->hibernate_delay_sec = 180 * USEC_PER_MINUTE;
-#ifdef ENABLE_DEBUG_ELOGIND
+#if ENABLE_DEBUG_ELOGIND
dbg_cnt = -1;
while (m->suspend_mode && m->suspend_mode[++dbg_cnt])
log_debug_elogind("suspend_mode[%d] = %s",
@@ -451,6 +448,9 @@ void elogind_manager_reset_config(Manager* m) {
while (m->hybrid_sleep_state[++dbg_cnt])
log_debug_elogind("hybrid_sleep_state[%d] = %s",
dbg_cnt, m->hybrid_sleep_state[dbg_cnt]);
+ log_debug_elogind("hibernate_delay_sec: %lu seconds (%lu minutes)",
+ m->hibernate_delay_sec / USEC_PER_SEC,
+ m->hibernate_delay_sec / USEC_PER_MINUTE);
#endif // ENABLE_DEBUG_ELOGIND
}
diff --git a/src/login/inhibit.c b/src/login/inhibit.c
index 896fd570a..cc1ff2fe9 100644
--- a/src/login/inhibit.c
+++ b/src/login/inhibit.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <fcntl.h>
#include <getopt.h>
@@ -30,6 +13,7 @@
#include "bus-util.h"
#include "fd-util.h"
#include "format-util.h"
+#include "pager.h"
#include "process-util.h"
#include "signal-util.h"
#include "strv.h"
@@ -43,6 +27,7 @@ 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 = NULL;
+static bool arg_no_pager = false;
static enum {
ACTION_INHIBIT,
@@ -84,6 +69,8 @@ static int print_inhibitors(sd_bus *bus, sd_bus_error *error) {
unsigned n = 0;
int r;
+ (void) pager_open(arg_no_pager, false);
+
r = sd_bus_call_method(
bus,
"org.freedesktop.login1",
@@ -136,6 +123,7 @@ static void help(void) {
"Execute a process while inhibiting shutdown/sleep/idle.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
+ " --no-pager Do not pipe output into a pager\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"
@@ -156,6 +144,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_WHY,
ARG_MODE,
ARG_LIST,
+ ARG_NO_PAGER,
};
static const struct option options[] = {
@@ -166,6 +155,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "why", required_argument, NULL, ARG_WHY },
{ "mode", required_argument, NULL, ARG_MODE },
{ "list", no_argument, NULL, ARG_LIST },
+ { "no-pager", no_argument, NULL, ARG_NO_PAGER },
{}
};
@@ -205,6 +195,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_action = ACTION_LIST;
break;
+ case ARG_NO_PAGER:
+ arg_no_pager = true;
+ break;
+
case '?':
return -EINVAL;
@@ -247,6 +241,7 @@ int main(int argc, char *argv[]) {
if (arg_action == ACTION_LIST) {
r = print_inhibitors(bus, &error);
+ pager_close();
if (r < 0) {
log_error("Failed to list inhibitors: %s", bus_error_message(&error, -r));
return EXIT_FAILURE;
@@ -257,6 +252,9 @@ int main(int argc, char *argv[]) {
_cleanup_free_ char *w = NULL;
pid_t pid;
+ /* Ignore SIGINT and allow the forked process to receive it */
+ (void) ignore_signals(SIGINT, -1);
+
if (!arg_who)
arg_who = w = strv_join(argv + optind, " ");
@@ -269,28 +267,20 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE;
}
- pid = fork();
- if (pid < 0) {
- log_error_errno(errno, "Failed to fork: %m");
+ r = safe_fork("(inhibit)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
+ if (r < 0)
return EXIT_FAILURE;
- }
-
- if (pid == 0) {
+ if (r == 0) {
/* Child */
-
- (void) reset_all_signal_handlers();
- (void) reset_signal_mask();
-
- close_all_fds(NULL, 0);
-
execvp(argv[optind], argv + optind);
+ log_open();
log_error_errno(errno, "Failed to execute %s: %m", argv[optind]);
_exit(EXIT_FAILURE);
}
- r = wait_for_terminate_and_warn(argv[optind], pid, true);
+ r = wait_for_terminate_and_check(argv[optind], pid, WAIT_LOG);
return r < 0 ? EXIT_FAILURE : r;
}
- return 0;
+ return EXIT_SUCCESS;
}
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index eb23ec0ba..f74094396 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <getopt.h>
@@ -27,17 +10,21 @@
#include "alloc-util.h"
#include "bus-error.h"
+//#include "bus-unit-util.h"
#include "bus-util.h"
//#include "cgroup-show.h"
#include "cgroup-util.h"
+#include "format-table.h"
#include "log.h"
//#include "logs-show.h"
#include "macro.h"
#include "pager.h"
#include "parse-util.h"
#include "process-util.h"
+#include "sigbus.h"
#include "signal-util.h"
-//#include "spawn-polkit-agent.h"
+#include "spawn-polkit-agent.h"
+#include "string-table.h"
#include "strv.h"
#include "sysfs-show.h"
#include "terminal-util.h"
@@ -68,35 +55,21 @@ static OutputMode arg_output = OUTPUT_SHORT;
extern BusTransport arg_transport;
static char *arg_host = NULL;
extern bool arg_ask_password;
+extern bool arg_dry_run;
+extern bool arg_quiet;
extern bool arg_no_wall;
extern usec_t arg_when;
extern bool arg_ignore_inhibitors;
extern elogind_action arg_action;
#endif // 0
-#if 0 /// UNNEEDED by elogind
-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_transport != BUS_TRANSPORT_LOCAL)
- return;
-
- polkit_agent_open();
-}
-
static OutputFlags get_output_flags(void) {
return
arg_all * OUTPUT_SHOW_ALL |
- arg_full * OUTPUT_FULL_WIDTH |
- (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
+ (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
colors_enabled() * OUTPUT_COLOR;
}
-#endif // 0
static int get_session_path(sd_bus *bus, const char *session_id, sd_bus_error *error, char **path) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
@@ -126,19 +99,45 @@ static int get_session_path(sd_bus *bus, const char *session_id, sd_bus_error *e
return 0;
}
+static int show_table(Table *table, const char *word) {
+ int r;
+
+ assert(table);
+ assert(word);
+
+ if (table_get_rows(table) > 1) {
+ r = table_set_sort(table, (size_t) 0, (size_t) -1);
+ if (r < 0)
+ return log_error_errno(r, "Failed to sort table: %m");
+
+ table_set_header(table, arg_legend);
+
+ r = table_print(table, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to show table: %m");
+ }
+
+ if (arg_legend) {
+ if (table_get_rows(table) > 1)
+ printf("\n%zu %s listed.\n", table_get_rows(table) - 1, word);
+ else
+ printf("No %s.\n", word);
+ }
+
+ return 0;
+}
+
static int list_sessions(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- const char *id, *user, *seat, *object;
+ _cleanup_(table_unrefp) Table *table = NULL;
sd_bus *bus = userdata;
- unsigned k = 0;
- uint32_t uid;
int r;
assert(bus);
assert(argv);
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = sd_bus_call_method(
bus,
@@ -147,73 +146,79 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
"org.freedesktop.login1.Manager",
"ListSessions",
&error, &reply,
- "");
- if (r < 0) {
- log_error("Failed to list sessions: %s", bus_error_message(&error, r));
- return r;
- }
+ NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to list sessions: %s", bus_error_message(&error, r));
r = sd_bus_message_enter_container(reply, 'a', "(susso)");
if (r < 0)
return bus_log_parse_error(r);
- if (arg_legend)
- printf("%10s %10s %-16s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT", "TTY");
+ table = table_new("SESSION", "UID", "USER", "SEAT", "TTY");
+ if (!table)
+ return log_oom();
+
+ /* Right-align the first two fields (since they are numeric) */
+ (void) table_set_align_percent(table, TABLE_HEADER_CELL(0), 100);
+ (void) table_set_align_percent(table, TABLE_HEADER_CELL(1), 100);
+
+ for (;;) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error_tty = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_tty = NULL;
+ const char *id, *user, *seat, *object, *tty = NULL;
+ uint32_t uid;
- while ((r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object)) > 0) {
- _cleanup_(sd_bus_error_free) sd_bus_error error2 = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply2 = NULL;
- _cleanup_free_ char *path = NULL;
- const char *tty = NULL;
+ r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object);
+ if (r < 0)
+ return bus_log_parse_error(r);
+ if (r == 0)
+ break;
- r = get_session_path(bus, id, &error2, &path);
+ r = sd_bus_get_property(
+ bus,
+ "org.freedesktop.login1",
+ object,
+ "org.freedesktop.login1.Session",
+ "TTY",
+ &error_tty,
+ &reply_tty,
+ "s");
if (r < 0)
- log_warning("Failed to get session path: %s", bus_error_message(&error, r));
+ log_warning_errno(r, "Failed to get TTY for session %s: %s", id, bus_error_message(&error_tty, r));
else {
- r = sd_bus_get_property(
- bus,
- "org.freedesktop.login1",
- path,
- "org.freedesktop.login1.Session",
- "TTY",
- &error2,
- &reply2,
- "s");
+ r = sd_bus_message_read(reply_tty, "s", &tty);
if (r < 0)
- log_warning("Failed to get TTY for session %s: %s",
- id, bus_error_message(&error2, r));
- else {
- r = sd_bus_message_read(reply2, "s", &tty);
- if (r < 0)
- return bus_log_parse_error(r);
- }
+ return bus_log_parse_error(r);
}
- printf("%10s %10"PRIu32" %-16s %-16s %-16s\n", id, uid, user, seat, strna(tty));
- k++;
+ r = table_add_many(table,
+ TABLE_STRING, id,
+ TABLE_UINT32, uid,
+ TABLE_STRING, user,
+ TABLE_STRING, seat,
+ TABLE_STRING, strna(tty));
+ if (r < 0)
+ return log_error_errno(r, "Failed to add row to table: %m");
}
+
+ r = sd_bus_message_exit_container(reply);
if (r < 0)
return bus_log_parse_error(r);
- if (arg_legend)
- printf("\n%u sessions listed.\n", k);
-
- return 0;
+ return show_table(table, "sessions");
}
static int list_users(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- const char *user, *object;
+ _cleanup_(table_unrefp) Table *table = NULL;
sd_bus *bus = userdata;
- unsigned k = 0;
- uint32_t uid;
int r;
assert(bus);
assert(argv);
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = sd_bus_call_method(
bus,
@@ -222,43 +227,55 @@ static int list_users(int argc, char *argv[], void *userdata) {
"org.freedesktop.login1.Manager",
"ListUsers",
&error, &reply,
- "");
- if (r < 0) {
- log_error("Failed to list users: %s", bus_error_message(&error, r));
- return r;
- }
+ NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to list users: %s", bus_error_message(&error, r));
r = sd_bus_message_enter_container(reply, 'a', "(uso)");
if (r < 0)
return bus_log_parse_error(r);
- if (arg_legend)
- printf("%10s %-16s\n", "UID", "USER");
+ table = table_new("UID", "USER");
+ if (!table)
+ return log_oom();
+
+ (void) table_set_align_percent(table, TABLE_HEADER_CELL(0), 100);
- while ((r = sd_bus_message_read(reply, "(uso)", &uid, &user, &object)) > 0) {
- printf("%10"PRIu32" %-16s\n", uid, user);
- k++;
+ for (;;) {
+ const char *user;
+ uint32_t uid;
+
+ r = sd_bus_message_read(reply, "(uso)", &uid, &user, NULL);
+ if (r < 0)
+ return bus_log_parse_error(r);
+ if (r == 0)
+ break;
+
+ r = table_add_many(table,
+ TABLE_UINT32, uid,
+ TABLE_STRING, user);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add row to table: %m");
}
+
+ r = sd_bus_message_exit_container(reply);
if (r < 0)
return bus_log_parse_error(r);
- if (arg_legend)
- printf("\n%u users listed.\n", k);
-
- return 0;
+ return show_table(table, "users");
}
static int list_seats(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- const char *seat, *object;
+ _cleanup_(table_unrefp) Table *table = NULL;
sd_bus *bus = userdata;
- unsigned k = 0;
int r;
+
assert(bus);
assert(argv);
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
r = sd_bus_call_method(
bus,
@@ -267,30 +284,37 @@ static int list_seats(int argc, char *argv[], void *userdata) {
"org.freedesktop.login1.Manager",
"ListSeats",
&error, &reply,
- "");
- if (r < 0) {
- log_error("Failed to list seats: %s", bus_error_message(&error, r));
- return r;
- }
+ NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to list seats: %s", bus_error_message(&error, r));
r = sd_bus_message_enter_container(reply, 'a', "(so)");
if (r < 0)
return bus_log_parse_error(r);
- if (arg_legend)
- printf("%-16s\n", "SEAT");
+ table = table_new("SEAT");
+ if (!table)
+ return log_oom();
+
+ for (;;) {
+ const char *seat;
+
+ r = sd_bus_message_read(reply, "(so)", &seat, NULL);
+ if (r < 0)
+ return bus_log_parse_error(r);
+ if (r == 0)
+ break;
- while ((r = sd_bus_message_read(reply, "(so)", &seat, &object)) > 0) {
- printf("%-16s\n", seat);
- k++;
+ r = table_add_cell(table, NULL, TABLE_STRING, seat);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add row to table: %m");
}
+
+ r = sd_bus_message_exit_container(reply);
if (r < 0)
return bus_log_parse_error(r);
- if (arg_legend)
- printf("\n%u seats listed.\n", k);
-
- return 0;
+ return show_table(table, "seats");
}
#if 0 /// UNNEEDED by elogind
@@ -336,77 +360,52 @@ static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit
#endif // 0
typedef struct SessionStatusInfo {
- char *id;
+ const char *id;
uid_t uid;
- char *name;
+ const char *name;
struct dual_timestamp timestamp;
unsigned int vtnr;
- char *seat;
- char *tty;
- char *display;
- int remote;
- char *remote_host;
- char *remote_user;
- char *service;
+ 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;
- char *type;
- char *class;
- char *state;
- char *scope;
- char *desktop;
+ const char *type;
+ const char *class;
+ const char *state;
+ const char *scope;
+ const char *desktop;
} SessionStatusInfo;
typedef struct UserStatusInfo {
uid_t uid;
- int linger;
- char *name;
+ bool linger;
+ const char *name;
struct dual_timestamp timestamp;
- char *state;
+ const char *state;
char **sessions;
- char *display;
- char *slice;
+ const char *display;
+ const char *slice;
} UserStatusInfo;
typedef struct SeatStatusInfo {
- char *id;
- char *active_session;
+ const char *id;
+ const char *active_session;
char **sessions;
} SeatStatusInfo;
-static void session_status_info_clear(SessionStatusInfo *info) {
- if (info) {
- free(info->id);
- free(info->name);
- free(info->seat);
- free(info->tty);
- free(info->display);
- free(info->remote_host);
- free(info->remote_user);
- free(info->service);
- free(info->type);
- free(info->class);
- free(info->state);
- free(info->scope);
- free(info->desktop);
- zero(*info);
- }
-}
-
static void user_status_info_clear(UserStatusInfo *info) {
if (info) {
- free(info->name);
- free(info->state);
strv_free(info->sessions);
- free(info->display);
- free(info->slice);
zero(*info);
}
}
static void seat_status_info_clear(SeatStatusInfo *info) {
if (info) {
- free(info->id);
- free(info->active_session);
strv_free(info->sessions);
zero(*info);
}
@@ -424,22 +423,9 @@ static int prop_map_first_of_struct(sd_bus *bus, const char *member, sd_bus_mess
if (r < 0)
return r;
- if (contents[0] == 's' || contents[0] == 'o') {
- const char *s;
- char **p = (char **) userdata;
-
- r = sd_bus_message_read_basic(m, contents[0], &s);
- if (r < 0)
- return r;
-
- r = free_and_strdup(p, s);
- if (r < 0)
- return r;
- } else {
- r = sd_bus_message_read_basic(m, contents[0], userdata);
- if (r < 0)
- return r;
- }
+ r = sd_bus_message_read_basic(m, contents[0], userdata);
+ if (r < 0)
+ return r;
r = sd_bus_message_skip(m, contents+1);
if (r < 0)
@@ -500,12 +486,14 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
- char since2[FORMAT_TIMESTAMP_MAX], *s2;
- _cleanup_(session_status_info_clear) SessionStatusInfo i = {};
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ char since1[FORMAT_TIMESTAMP_RELATIVE_MAX];
+ char since2[FORMAT_TIMESTAMP_MAX];
+ const char *s1, *s2;
+ SessionStatusInfo i = {};
int r;
- r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &error, &i);
+ r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, BUS_MAP_BOOLEAN_AS_BOOL, &error, &m, &i);
if (r < 0)
return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
@@ -632,12 +620,14 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line)
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
- char since2[FORMAT_TIMESTAMP_MAX], *s2;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ char since1[FORMAT_TIMESTAMP_RELATIVE_MAX];
+ char since2[FORMAT_TIMESTAMP_MAX];
+ const char *s1, *s2;
_cleanup_(user_status_info_clear) UserStatusInfo i = {};
int r;
- r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &error, &i);
+ r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, BUS_MAP_BOOLEAN_AS_BOOL, &error, &m, &i);
if (r < 0)
return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
@@ -709,10 +699,11 @@ static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line)
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_(seat_status_info_clear) SeatStatusInfo i = {};
int r;
- r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &error, &i);
+ r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, 0, &error, &m, &i);
if (r < 0)
return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
@@ -748,7 +739,7 @@ static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line)
printf("\t Devices:\n");
- show_sysfs(i.id, "\t\t ", c);
+ show_sysfs(i.id, "\t\t ", c, get_output_flags());
}
return 0;
@@ -756,40 +747,41 @@ static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line)
#define property(name, fmt, ...) \
do { \
- if (arg_value) \
+ if (value) \
printf(fmt "\n", __VA_ARGS__); \
else \
printf("%s=" fmt "\n", name, __VA_ARGS__); \
- } while(0)
+ } while (0)
-static int print_property(const char *name, sd_bus_message *m, const char *contents) {
+static int print_property(const char *name, sd_bus_message *m, bool value, bool all) {
+ char type;
+ const char *contents;
int r;
assert(name);
assert(m);
- assert(contents);
- if (arg_property && !strv_find(arg_property, name))
- /* skip what we didn't read */
- return sd_bus_message_skip(m, contents);
+ r = sd_bus_message_peek_type(m, &type, &contents);
+ if (r < 0)
+ return r;
- switch (contents[0]) {
+ switch (type) {
- case SD_BUS_TYPE_STRUCT_BEGIN:
+ case SD_BUS_TYPE_STRUCT:
- if (contents[1] == SD_BUS_TYPE_STRING && STR_IN_SET(name, "Display", "Seat", "ActiveSession")) {
+ if (contents[0] == SD_BUS_TYPE_STRING && STR_IN_SET(name, "Display", "Seat", "ActiveSession")) {
const char *s;
r = sd_bus_message_read(m, "(so)", &s, NULL);
if (r < 0)
return bus_log_parse_error(r);
- if (arg_all || !isempty(s))
+ if (all || !isempty(s))
property(name, "%s", s);
- return 0;
+ return 1;
- } else if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "User")) {
+ } else if (contents[0] == SD_BUS_TYPE_UINT32 && streq(name, "User")) {
uint32_t uid;
r = sd_bus_message_read(m, "(uo)", &uid, NULL);
@@ -802,14 +794,13 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
}
property(name, UID_FMT, uid);
- return 0;
+ return 1;
}
-
break;
case SD_BUS_TYPE_ARRAY:
- if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Sessions")) {
+ if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Sessions")) {
const char *s;
bool space = false;
@@ -817,7 +808,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- if (!arg_value)
+ if (!value)
printf("%s=", name);
while ((r = sd_bus_message_read(m, "(so)", &s, NULL)) > 0) {
@@ -825,7 +816,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
space = true;
}
- if (space || !arg_value)
+ if (space || !value)
printf("\n");
if (r < 0)
@@ -835,89 +826,27 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
if (r < 0)
return bus_log_parse_error(r);
- return 0;
+ return 1;
}
-
break;
}
- r = bus_print_property(name, m, arg_value, arg_all);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (r == 0) {
- r = sd_bus_message_skip(m, contents);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (arg_all)
- printf("%s=[unprintable]\n", name);
- }
-
return 0;
}
static int show_properties(sd_bus *bus, const char *path, bool *new_line) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(bus);
assert(path);
assert(new_line);
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.login1",
- path,
- "org.freedesktop.DBus.Properties",
- "GetAll",
- &error,
- &reply,
- "s", "");
- if (r < 0)
- return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
-
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
- if (r < 0)
- return bus_log_parse_error(r);
-
if (*new_line)
printf("\n");
*new_line = true;
- while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
- const char *name, *contents;
-
- r = sd_bus_message_read(reply, "s", &name);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_peek_type(reply, NULL, &contents);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = print_property(name, reply, contents);
- if (r < 0)
- return r;
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
+ r = bus_print_all_properties(bus, "org.freedesktop.login1", path, print_property, arg_property, arg_value, arg_all, NULL);
if (r < 0)
return bus_log_parse_error(r);
@@ -936,7 +865,7 @@ static int show_session(int argc, char *argv[], void *userdata) {
properties = !strstr(argv[0], "status");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
if (argc <= 1) {
const char *session, *p = "/org/freedesktop/login1/session/self";
@@ -988,7 +917,7 @@ static int show_user(int argc, char *argv[], void *userdata) {
properties = !strstr(argv[0], "status");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
if (argc <= 1) {
/* If not argument is specified inspect the manager
@@ -1048,7 +977,7 @@ static int show_seat(int argc, char *argv[], void *userdata) {
properties = !strstr(argv[0], "status");
- pager_open(arg_no_pager, false);
+ (void) pager_open(arg_no_pager, false);
if (argc <= 1) {
/* If not argument is specified inspect the manager
@@ -1102,7 +1031,7 @@ static int activate(int argc, char *argv[], void *userdata) {
assert(bus);
assert(argv);
- polkit_agent_open_if_enabled();
+ polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
if (argc < 2) {
/* No argument? Let's either use $XDG_SESSION_ID (if specified), or an empty
@@ -1146,7 +1075,7 @@ static int kill_session(int argc, char *argv[], void *userdata) {
assert(bus);
assert(argv);
- polkit_agent_open_if_enabled();
+ polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
if (!arg_kill_who)
arg_kill_who = "all";
@@ -1180,16 +1109,16 @@ static int enable_linger(int argc, char *argv[], void *userdata) {
assert(bus);
assert(argv);
- polkit_agent_open_if_enabled();
+ polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
b = streq(argv[0], "enable-linger");
if (argc < 2) {
- /* No argument? Let's either use $XDG_SESSION_ID (if specified), or an empty
- * session name, in which case logind will try to guess our session. */
+ /* No argument? Let's use an empty user name,
+ * then logind will use our user. */
short_argv[0] = argv[0];
- short_argv[1] = getenv("XDG_SESSION_ID") ?: (char*) "";
+ short_argv[1] = (char*) "";
short_argv[2] = NULL;
argv = short_argv;
argc = 2;
@@ -1231,7 +1160,7 @@ static int terminate_user(int argc, char *argv[], void *userdata) {
assert(bus);
assert(argv);
- polkit_agent_open_if_enabled();
+ polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
for (i = 1; i < argc; i++) {
uid_t uid;
@@ -1265,7 +1194,7 @@ static int kill_user(int argc, char *argv[], void *userdata) {
assert(bus);
assert(argv);
- polkit_agent_open_if_enabled();
+ polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
if (!arg_kill_who)
arg_kill_who = "all";
@@ -1302,7 +1231,7 @@ static int attach(int argc, char *argv[], void *userdata) {
assert(bus);
assert(argv);
- polkit_agent_open_if_enabled();
+ polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
for (i = 2; i < argc; i++) {
@@ -1332,7 +1261,7 @@ static int flush_devices(int argc, char *argv[], void *userdata) {
assert(bus);
assert(argv);
- polkit_agent_open_if_enabled();
+ polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
r = sd_bus_call_method(
bus,
@@ -1356,7 +1285,7 @@ static int lock_sessions(int argc, char *argv[], void *userdata) {
assert(bus);
assert(argv);
- polkit_agent_open_if_enabled();
+ polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
r = sd_bus_call_method(
bus,
@@ -1380,7 +1309,7 @@ static int terminate_seat(int argc, char *argv[], void *userdata) {
assert(bus);
assert(argv);
- polkit_agent_open_if_enabled();
+ polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
for (i = 1; i < argc; i++) {
@@ -1408,8 +1337,10 @@ static int help(int argc, char *argv[], void *userdata) {
" -h --help Show this help\n"
" --version Show package version\n"
" --no-pager Do not pipe output into a pager\n"
-#if 1 /// elogind supports --no-wall
+#if 1 /// elogind supports --no-wall and --dry-run
" --no-wall Do not print any wall message\n"
+ " --dry-run Only print what would be done\n"
+ " -q --quiet Suppress output\n"
#endif // 1
" --no-legend Do not show the headers and footers\n"
" --no-ask-password Don't prompt for password\n"
@@ -1461,15 +1392,19 @@ static int help(int argc, char *argv[], void *userdata) {
" show-seat [NAME...] Show properties of seats or the manager\n"
" attach NAME DEVICE... Attach one or more devices to a seat\n"
" flush-devices Flush all device associations\n"
+#if 0 /// elogind adds some system commands to loginctl
+ " terminate-seat NAME... Terminate all sessions on one or more seats\n"
+#else
" terminate-seat NAME... Terminate all sessions on one or more seats\n\n"
-#if 1 /// elogind adds some system commands to loginctl
"System Commands:\n"
" poweroff [TIME] [WALL...] Turn off the machine\n"
" reboot [TIME] [WALL...] Reboot the machine\n"
" suspend Suspend the machine to memory\n"
" hibernate Suspend the machine to disk\n"
" hybrid-sleep Suspend the machine to memory and disk\n"
-#endif // 1
+ " suspend-then-hibernate Suspend the system, wake after a period of\n"
+ " time and put it into hibernate\n"
+#endif // 0
, program_invocation_short_name);
return 0;
@@ -1481,8 +1416,9 @@ static int parse_argv(int argc, char *argv[]) {
ARG_VERSION = 0x100,
ARG_VALUE,
ARG_NO_PAGER,
-#if 1 /// elogind supports --no-wall
+#if 1 /// elogind supports --no-wall and --dry-run
ARG_NO_WALL,
+ ARG_DRY_RUN,
#endif // 1
ARG_NO_LEGEND,
ARG_KILL_WHO,
@@ -1497,8 +1433,10 @@ static int parse_argv(int argc, char *argv[]) {
{ "value", no_argument, NULL, ARG_VALUE },
{ "full", no_argument, NULL, 'l' },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
-#if 1 /// elogind supports --no-wall
+#if 1 /// elogind supports --no-wall, --dry-run and --quiet
{ "no-wall", no_argument, NULL, ARG_NO_WALL },
+ { "dry-run", no_argument, NULL, ARG_DRY_RUN },
+ { "quiet", no_argument, NULL, 'q' },
#endif // 1
{ "no-legend", no_argument, NULL, ARG_NO_LEGEND },
{ "kill-who", required_argument, NULL, ARG_KILL_WHO },
@@ -1569,6 +1507,11 @@ static int parse_argv(int argc, char *argv[]) {
break;
case 'o':
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX);
+ return 0;
+ }
+
arg_output = output_mode_from_string(optarg);
if (arg_output < 0) {
log_error("Unknown output '%s'.", optarg);
@@ -1580,10 +1523,19 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_NO_PAGER:
arg_no_pager = true;
break;
-#if 1 /// elogind supports --no-wall
+#if 1 /// elogind supports --no-wall, -dry-run and --quiet
case ARG_NO_WALL:
arg_no_wall = true;
break;
+
+ case ARG_DRY_RUN:
+ arg_dry_run = true;
+ break;
+
+ case 'q':
+ arg_quiet = true;
+ break;
+
#endif // 1
case ARG_NO_LEGEND:
@@ -1599,7 +1551,12 @@ static int parse_argv(int argc, char *argv[]) {
break;
case 's':
- arg_signal = signal_from_string_try_harder(optarg);
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(signal, int, _NSIG);
+ return 0;
+ }
+
+ arg_signal = signal_from_string(optarg);
if (arg_signal < 0) {
log_error("Failed to parse signal string %s.", optarg);
return -EINVAL;
@@ -1672,6 +1629,7 @@ static int loginctl_main(int argc, char *argv[], sd_bus *bus) {
{ "suspend", VERB_ANY, 1, 0, start_special },
{ "hibernate", VERB_ANY, 1, 0, start_special },
{ "hybrid-sleep", VERB_ANY, 1, 0, start_special },
+ { "suspend-then-hibernate", VERB_ANY, 1, 0, start_special },
{ "cancel-shutdown", VERB_ANY, 1, 0, start_special },
#endif // 1
{}
@@ -1692,6 +1650,7 @@ int main(int argc, char *argv[]) {
elogind_set_program_name(argv[0]);
log_parse_environment();
log_open();
+ sigbus_install();
r = parse_argv(argc, argv);
if (r <= 0)
@@ -1708,8 +1667,9 @@ int main(int argc, char *argv[]) {
r = loginctl_main(argc, argv, bus);
finish:
+ /* make sure we terminate the bus connection first, and then close the
+ * pager, see issue #3543 for the details. */
sd_bus_flush_close_unref(bus);
-
pager_close();
#if 0 /// elogind does that in elogind_cleanup()
polkit_agent_close();
diff --git a/src/login/logind-acl.c b/src/login/logind-acl.c
index 1b69f4b9c..cafeb8822 100644
--- a/src/login/logind-acl.c
+++ b/src/login/logind-acl.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <string.h>
@@ -180,7 +163,7 @@ int devnode_acl_all(struct udev *udev,
bool del, uid_t old_uid,
bool add, uid_t new_uid) {
- _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
+ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
struct udev_list_entry *item = NULL, *first = NULL;
_cleanup_set_free_free_ Set *nodes = NULL;
_cleanup_closedir_ DIR *dir = NULL;
@@ -191,7 +174,7 @@ int devnode_acl_all(struct udev *udev,
assert(udev);
- nodes = set_new(&string_hash_ops);
+ nodes = set_new(&path_hash_ops);
if (!nodes)
return -ENOMEM;
@@ -221,7 +204,7 @@ int devnode_acl_all(struct udev *udev,
first = udev_enumerate_get_list_entry(e);
udev_list_entry_foreach(item, first) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
const char *node, *sn;
d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
diff --git a/src/login/logind-acl.h b/src/login/logind-acl.h
index 5587becca..56b4a5488 100644
--- a/src/login/logind-acl.h
+++ b/src/login/logind-acl.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 <sys/types.h>
@@ -28,7 +10,7 @@
#include <libudev.h>
#endif // 0
-#ifdef HAVE_ACL
+#if HAVE_ACL
int devnode_acl(const char *path,
bool flush,
diff --git a/src/login/logind-action.c b/src/login/logind-action.c
index 48d9fb856..a9f739129 100644
--- a/src/login/logind-action.c
+++ b/src/login/logind-action.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <unistd.h>
@@ -38,6 +21,26 @@
#include "sd-messages.h"
#include "strv.h"
+#if 0 /// elogind does this itself. No target table required
+const char* manager_target_for_action(HandleAction handle) {
+ static const char * const target_table[_HANDLE_ACTION_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,
+ [HANDLE_SUSPEND_THEN_HIBERNATE] = SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET,
+ };
+
+ assert(handle >= 0);
+ if (handle < (ssize_t) ELEMENTSOF(target_table))
+ return target_table[handle];
+ return NULL;
+}
+#endif // 0
+
int manager_handle_action(
Manager *m,
InhibitWhat inhibit_key,
@@ -52,25 +55,17 @@ int manager_handle_action(
[HANDLE_KEXEC] = "Rebooting via kexec...",
[HANDLE_SUSPEND] = "Suspending...",
[HANDLE_HIBERNATE] = "Hibernating...",
- [HANDLE_HYBRID_SLEEP] = "Hibernating and suspending..."
+ [HANDLE_HYBRID_SLEEP] = "Hibernating and suspending...",
+ [HANDLE_SUSPEND_THEN_HIBERNATE] = "Suspending, then hibernating...",
};
-#if 0 /// elogind does this itself. No target table required
- static const char * const target_table[_HANDLE_ACTION_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
- };
-#endif // 0
-
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
InhibitWhat inhibit_operation;
Inhibitor *offending = NULL;
bool supported;
+#if 0 /// elogind uses its own variant, which can use the handle directly.
+ const char *target;
+#endif // 0
int r;
assert(m);
@@ -102,7 +97,6 @@ int manager_handle_action(
/* Locking is handled differently from the rest. */
if (handle == HANDLE_LOCK) {
-
if (!is_edge)
return 0;
@@ -118,6 +112,8 @@ int manager_handle_action(
supported = can_sleep("hibernate") > 0;
else if (handle == HANDLE_HYBRID_SLEEP)
supported = can_sleep("hybrid-sleep") > 0;
+ else if (handle == HANDLE_SUSPEND_THEN_HIBERNATE)
+ supported = can_sleep("suspend-then-hibernate") > 0;
#else
if (handle == HANDLE_SUSPEND)
supported = can_sleep(m, "suspend") > 0;
@@ -125,6 +121,8 @@ int manager_handle_action(
supported = can_sleep(m, "hibernate") > 0;
else if (handle == HANDLE_HYBRID_SLEEP)
supported = can_sleep(m, "hybrid-sleep") > 0;
+ else if (handle == HANDLE_SUSPEND_THEN_HIBERNATE)
+ supported = can_sleep(m, "suspend-then-hibernate") > 0;
#endif // 0
else if (handle == HANDLE_KEXEC)
supported = access(KEXEC, X_OK) >= 0;
@@ -141,7 +139,13 @@ int manager_handle_action(
return -EALREADY;
}
- inhibit_operation = IN_SET(handle, HANDLE_SUSPEND, HANDLE_HIBERNATE, HANDLE_HYBRID_SLEEP) ? INHIBIT_SLEEP : INHIBIT_SHUTDOWN;
+#if 0 /// elogind uses its own variant, which can use the handle directly.
+ assert_se(target = manager_target_for_action(handle));
+#endif // 0
+
+ inhibit_operation = IN_SET(handle, HANDLE_SUSPEND, HANDLE_HIBERNATE,
+ HANDLE_HYBRID_SLEEP,
+ HANDLE_SUSPEND_THEN_HIBERNATE) ? INHIBIT_SLEEP : INHIBIT_SHUTDOWN;
/* If the actual operation is inhibited, warn and fail */
if (!ignore_inhibited &&
@@ -171,7 +175,7 @@ int manager_handle_action(
log_info("%s", message_table[handle]);
#if 0 /// elogind uses its own variant, which can use the handle directly.
- r = bus_manager_shutdown_or_sleep_now_or_later(m, target_table[handle], inhibit_operation, &error);
+ r = bus_manager_shutdown_or_sleep_now_or_later(m, target, inhibit_operation, &error);
#else
r = bus_manager_shutdown_or_sleep_now_or_later(m, handle, inhibit_operation, &error);
#endif // 0
@@ -192,7 +196,8 @@ static const char* const handle_action_table[_HANDLE_ACTION_MAX] = {
[HANDLE_SUSPEND] = "suspend",
[HANDLE_HIBERNATE] = "hibernate",
[HANDLE_HYBRID_SLEEP] = "hybrid-sleep",
- [HANDLE_LOCK] = "lock"
+ [HANDLE_SUSPEND_THEN_HIBERNATE] = "suspend-then-hibernate",
+ [HANDLE_LOCK] = "lock",
};
DEFINE_STRING_TABLE_LOOKUP(handle_action, HandleAction);
diff --git a/src/login/logind-action.h b/src/login/logind-action.h
index fb40ae48d..bc2d36050 100644
--- a/src/login/logind-action.h
+++ b/src/login/logind-action.h
@@ -1,23 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 "conf-parser.h"
typedef enum HandleAction {
HANDLE_IGNORE,
@@ -28,6 +12,7 @@ typedef enum HandleAction {
HANDLE_SUSPEND,
HANDLE_HIBERNATE,
HANDLE_HYBRID_SLEEP,
+ HANDLE_SUSPEND_THEN_HIBERNATE,
HANDLE_LOCK,
_HANDLE_ACTION_MAX,
_HANDLE_ACTION_INVALID = -1
@@ -46,4 +31,8 @@ int manager_handle_action(
const char* handle_action_to_string(HandleAction h) _const_;
HandleAction handle_action_from_string(const char *s) _pure_;
-int config_parse_handle_action(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+#if 0 /// elogind does this itself. No target table required
+const char* manager_target_for_action(HandleAction handle);
+#endif // 0
+
+CONFIG_PARSER_PROTOTYPE(config_parse_handle_action);
diff --git a/src/login/logind-button.c b/src/login/logind-button.c
index e53dd63c2..0defa6b9b 100644
--- a/src/login/logind-button.c
+++ b/src/login/logind-button.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <fcntl.h>
@@ -109,9 +92,13 @@ static void button_lid_switch_handle_action(Manager *manager, bool is_edge) {
assert(manager);
- /* If we are docked, handle the lid switch differently */
+ /* If we are docked or on external power, handle the lid switch
+ * differently */
if (manager_is_docked_or_external_displays(manager))
handle_action = manager->handle_lid_switch_docked;
+ else if (manager->handle_lid_switch_ep != _HANDLE_ACTION_INVALID &&
+ manager_is_on_external_power())
+ handle_action = manager->handle_lid_switch_ep;
else
handle_action = manager->handle_lid_switch;
@@ -167,8 +154,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
case KEY_POWER2:
log_struct(LOG_INFO,
LOG_MESSAGE("Power key pressed."),
- "MESSAGE_ID=" SD_MESSAGE_POWER_KEY_STR,
- NULL);
+ "MESSAGE_ID=" SD_MESSAGE_POWER_KEY_STR);
manager_handle_action(b->manager, INHIBIT_HANDLE_POWER_KEY, b->manager->handle_power_key, b->manager->power_key_ignore_inhibited, true);
break;
@@ -182,8 +168,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
case KEY_SLEEP:
log_struct(LOG_INFO,
LOG_MESSAGE("Suspend key pressed."),
- "MESSAGE_ID=" SD_MESSAGE_SUSPEND_KEY_STR,
- NULL);
+ "MESSAGE_ID=" SD_MESSAGE_SUSPEND_KEY_STR);
manager_handle_action(b->manager, INHIBIT_HANDLE_SUSPEND_KEY, b->manager->handle_suspend_key, b->manager->suspend_key_ignore_inhibited, true);
break;
@@ -191,8 +176,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
case KEY_SUSPEND:
log_struct(LOG_INFO,
LOG_MESSAGE("Hibernate key pressed."),
- "MESSAGE_ID=" SD_MESSAGE_HIBERNATE_KEY_STR,
- NULL);
+ "MESSAGE_ID=" SD_MESSAGE_HIBERNATE_KEY_STR);
manager_handle_action(b->manager, INHIBIT_HANDLE_HIBERNATE_KEY, b->manager->handle_hibernate_key, b->manager->hibernate_key_ignore_inhibited, true);
break;
@@ -203,8 +187,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
if (ev.code == SW_LID) {
log_struct(LOG_INFO,
LOG_MESSAGE("Lid closed."),
- "MESSAGE_ID=" SD_MESSAGE_LID_CLOSED_STR,
- NULL);
+ "MESSAGE_ID=" SD_MESSAGE_LID_CLOSED_STR);
b->lid_closed = true;
button_lid_switch_handle_action(b->manager, true);
@@ -213,8 +196,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
} else if (ev.code == SW_DOCK) {
log_struct(LOG_INFO,
LOG_MESSAGE("System docked."),
- "MESSAGE_ID=" SD_MESSAGE_SYSTEM_DOCKED_STR,
- NULL);
+ "MESSAGE_ID=" SD_MESSAGE_SYSTEM_DOCKED_STR);
b->docked = true;
}
@@ -224,8 +206,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
if (ev.code == SW_LID) {
log_struct(LOG_INFO,
LOG_MESSAGE("Lid opened."),
- "MESSAGE_ID=" SD_MESSAGE_LID_OPENED_STR,
- NULL);
+ "MESSAGE_ID=" SD_MESSAGE_LID_OPENED_STR);
b->lid_closed = false;
b->check_event_source = sd_event_source_unref(b->check_event_source);
@@ -233,8 +214,7 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
} else if (ev.code == SW_DOCK) {
log_struct(LOG_INFO,
LOG_MESSAGE("System undocked."),
- "MESSAGE_ID=" SD_MESSAGE_SYSTEM_UNDOCKED_STR,
- NULL);
+ "MESSAGE_ID=" SD_MESSAGE_SYSTEM_UNDOCKED_STR);
b->docked = false;
}
diff --git a/src/login/logind-button.h b/src/login/logind-button.h
index f30cba295..740cf0b78 100644
--- a/src/login/logind-button.h
+++ b/src/login/logind-button.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 Button Button;
#include "logind.h"
diff --git a/src/login/logind-core.c b/src/login/logind-core.c
index 7e6b63f12..db0df19e2 100644
--- a/src/login/logind-core.c
+++ b/src/login/logind-core.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <fcntl.h>
#include <pwd.h>
@@ -27,13 +10,74 @@
#include "bus-error.h"
#include "bus-util.h"
#include "cgroup-util.h"
+//#include "conf-parser.h"
#include "fd-util.h"
#include "logind.h"
+#include "parse-util.h"
+#include "process-util.h"
#include "strv.h"
#include "terminal-util.h"
#include "udev-util.h"
#include "user-util.h"
+void manager_reset_config(Manager *m) {
+ assert(m);
+
+#if 0 /// elogind does not support autospawning of vts
+ m->n_autovts = 6;
+ m->reserve_vt = 6;
+#endif // 0
+ m->remove_ipc = true;
+ 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->handle_lid_switch_ep = _HANDLE_ACTION_INVALID;
+ m->handle_lid_switch_docked = HANDLE_IGNORE;
+ m->power_key_ignore_inhibited = false;
+ m->suspend_key_ignore_inhibited = false;
+ m->hibernate_key_ignore_inhibited = false;
+ m->lid_switch_ignore_inhibited = true;
+
+ m->holdoff_timeout_usec = 30 * USEC_PER_SEC;
+
+ m->idle_action_usec = 30 * USEC_PER_MINUTE;
+ m->idle_action = HANDLE_IGNORE;
+
+ m->runtime_dir_size = physical_memory_scale(10U, 100U); /* 10% */
+ m->user_tasks_max = system_tasks_max_scale(DEFAULT_USER_TASKS_MAX_PERCENTAGE, 100U); /* 33% */
+ m->sessions_max = 8192;
+ m->inhibitors_max = 8192;
+
+ m->kill_user_processes = KILL_USER_PROCESSES;
+
+ m->kill_only_users = strv_free(m->kill_only_users);
+ m->kill_exclude_users = strv_free(m->kill_exclude_users);
+}
+
+int manager_parse_config_file(Manager *m) {
+ assert(m);
+
+#if 0 /// elogind parses its own config file
+ return config_parse_many_nulstr(PKGSYSCONFDIR "/logind.conf",
+ CONF_PATHS_NULSTR("systemd/logind.conf.d"),
+ "Login\0",
+ config_item_perf_lookup, logind_gperf_lookup,
+#else
+ const char* logind_conf = getenv("ELOGIND_CONF_FILE");
+
+ assert(m);
+
+ if (!logind_conf)
+ logind_conf = PKGSYSCONFDIR "/logind.conf";
+
+ return config_parse(NULL, logind_conf, NULL, "Login\0Sleep\0",
+ config_item_perf_lookup, logind_gperf_lookup,
+#endif // 0
+ CONFIG_PARSE_WARN, m);
+}
+
int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device) {
Device *d;
@@ -279,7 +323,7 @@ int manager_process_button_device(Manager *m, struct udev_device *d) {
return 0;
}
-int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
+int manager_get_session_by_pid(Manager *m, pid_t pid, Session **ret) {
#if 0 /// elogind does not support systemd units, but its own session system
_cleanup_free_ char *unit = NULL;
#else
@@ -290,34 +334,42 @@ int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
assert(m);
- if (pid < 1)
+ if (!pid_is_valid(pid))
return -EINVAL;
#if 0 /// elogind does not support systemd units, but its own session system
r = cg_pid_get_unit(pid, &unit);
if (r < 0)
- return 0;
+ goto not_found;
s = hashmap_get(m->session_units, unit);
+ if (!s)
+ goto not_found;
#else
log_debug_elogind("Searching session for PID %u", pid);
r = cg_pid_get_session(pid, &session_name);
if (r < 0)
- return 0;
+ goto not_found;
s = hashmap_get(m->sessions, session_name);
log_debug_elogind("Session Name \"%s\" -> Session \"%s\"",
session_name, s && s->id ? s->id : "NULL");
+ if (NULL == s)
+ goto not_found;
#endif // 0
- if (!s)
- return 0;
- if (session)
- *session = s;
+ if (ret)
+ *ret = s;
+
return 1;
+
+not_found:
+ if (ret)
+ *ret = NULL;
+ return 0;
}
-int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
+int manager_get_user_by_pid(Manager *m, pid_t pid, User **ret) {
#if 0 /// elogind does not support systemd units, but its own session system
_cleanup_free_ char *unit = NULL;
User *u;
@@ -327,29 +379,37 @@ int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
int r;
assert(m);
- assert(user);
- if (pid < 1)
+ if (!pid_is_valid(pid))
return -EINVAL;
#if 0 /// elogind does not support systemd units, but its own session system
r = cg_pid_get_slice(pid, &unit);
if (r < 0)
- return 0;
+ goto not_found;
u = hashmap_get(m->user_units, unit);
if (!u)
- return 0;
+ goto not_found;
+
+ if (ret)
+ *ret = u;
- *user = u;
#else
r = manager_get_session_by_pid (m, pid, &s);
if (r <= 0)
- return r;
+ goto not_found;
- *user = s->user;
+ if (ret)
+ *ret = s->user;
#endif // 0
return 1;
+
+not_found:
+ if (ret)
+ *ret = NULL;
+
+ return 0;
}
int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
@@ -408,6 +468,42 @@ bool manager_shall_kill(Manager *m, const char *user) {
}
#if 0 /// UNNEEDED by elogind
+int config_parse_n_autovts(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ unsigned *n = data;
+ unsigned o;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = safe_atou(rvalue, &o);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse number of autovts, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (o > 15) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "A maximum of 15 autovts are supported, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ *n = o;
+ return 0;
+}
+
static int vt_is_busy(unsigned int vtnr) {
struct vt_stat vt_stat;
int r = 0;
@@ -415,6 +511,9 @@ static int vt_is_busy(unsigned int vtnr) {
assert(vtnr >= 1);
+ /* VT_GETSTATE "cannot return state for more than 16 VTs, since v_state is short" */
+ assert(vtnr <= 15);
+
/* 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
@@ -486,7 +585,7 @@ static bool manager_is_docked(Manager *m) {
}
static int manager_count_external_displays(Manager *m) {
- _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
+ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
struct udev_list_entry *item = NULL, *first = NULL;
int r;
int n = 0;
@@ -505,7 +604,7 @@ static int manager_count_external_displays(Manager *m) {
first = udev_enumerate_get_list_entry(e);
udev_list_entry_foreach(item, first) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
struct udev_device *p;
const char *status, *enabled, *dash, *nn, *i;
bool external = false;
@@ -589,3 +688,37 @@ bool manager_is_docked_or_external_displays(Manager *m) {
return false;
}
+
+bool manager_is_on_external_power(void) {
+ int r;
+
+ /* For now we only check for AC power, but 'external power' can apply
+ * to anything that isn't an internal battery */
+ r = on_ac_power();
+ if (r < 0)
+ log_warning_errno(r, "Failed to read AC power status: %m");
+ else if (r > 0)
+ return true;
+
+ return false;
+}
+
+bool manager_all_buttons_ignored(Manager *m) {
+ assert(m);
+
+ if (m->handle_power_key != HANDLE_IGNORE)
+ return false;
+ if (m->handle_suspend_key != HANDLE_IGNORE)
+ return false;
+ if (m->handle_hibernate_key != HANDLE_IGNORE)
+ return false;
+ if (m->handle_lid_switch != HANDLE_IGNORE)
+ return false;
+ if (m->handle_lid_switch_ep != _HANDLE_ACTION_INVALID &&
+ m->handle_lid_switch_ep != HANDLE_IGNORE)
+ return false;
+ if (m->handle_lid_switch_docked != HANDLE_IGNORE)
+ return false;
+
+ return true;
+}
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 70d2b1ffc..9d7092869 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <pwd.h>
@@ -28,6 +11,7 @@
#include "audit-util.h"
#include "bus-common-errors.h"
#include "bus-error.h"
+//#include "bus-unit-util.h"
#include "bus-util.h"
#include "dirent-util.h"
//#include "efivars.h"
@@ -40,6 +24,7 @@
#include "mkdir.h"
#include "path-util.h"
#include "process-util.h"
+//#include "cgroup-util.h"
#include "selinux-util.h"
#include "sleep-config.h"
//#include "special.h"
@@ -52,29 +37,48 @@
/// Additional includes needed by elogind
#include "elogind-dbus.h"
-//#include "update-utmp.h"
-int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
+static int get_sender_session(Manager *m, sd_bus_message *message, sd_bus_error *error, Session **ret) {
+
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+ const char *name;
Session *session;
int r;
+ /* Get client login session. This is not what you are looking for these days,
+ * as apps may instead belong to a user service unit. This includes terminal
+ * emulators and hence command-line apps. */
+ r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_creds_get_session(creds, &name);
+ if (r == -ENXIO)
+ goto err_no_session;
+ if (r < 0)
+ return r;
+
+ session = hashmap_get(m->sessions, name);
+ if (!session)
+ goto err_no_session;
+
+ *ret = session;
+ return 0;
+
+err_no_session:
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID,
+ "Caller does not belong to any known session");
+}
+
+int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
+ Session *session;
+
assert(m);
assert(message);
assert(ret);
- if (isempty(name)) {
- r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
- if (r < 0)
- return r;
-
- r = sd_bus_creds_get_session(creds, &name);
- if (r == -ENXIO)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID,
- "Caller does not belong to any known session");
- if (r < 0)
- return r;
- }
+ if (isempty(name))
+ return get_sender_session(m, message, error, ret);
session = hashmap_get(m->sessions, name);
if (!session)
@@ -84,30 +88,48 @@ int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const ch
return 0;
}
-int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) {
+static int get_sender_user(Manager *m, sd_bus_message *message, sd_bus_error *error, User **ret) {
+
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+ uid_t uid;
User *user;
int r;
+ /* Note that we get the owner UID of the session, not the actual client UID here! */
+ r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_creds_get_owner_uid(creds, &uid);
+ if (r == -ENXIO)
+ goto err_no_user;
+ if (r < 0)
+ return r;
+
+ user = hashmap_get(m->users, UID_TO_PTR(uid));
+ if (!user)
+ goto err_no_user;
+
+ *ret = user;
+ return 0;
+
+err_no_user:
+ return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID, "Caller does not belong to any logged in user or lingering user");
+}
+
+int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) {
+ User *user;
+
assert(m);
assert(message);
assert(ret);
- if (uid == UID_INVALID) {
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
-
- /* Note that we get the owner UID of the session, not the actual client UID here! */
- r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
- if (r < 0)
- return r;
-
- r = sd_bus_creds_get_owner_uid(creds, &uid);
- if (r < 0)
- return r;
- }
+ if (!uid_is_valid(uid))
+ return get_sender_user(m, message, error, ret);
user = hashmap_get(m->users, UID_TO_PTR(uid));
if (!user)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "No user "UID_FMT" known or logged in", uid);
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "User ID "UID_FMT" is not logged in or lingering", uid);
*ret = user;
return 0;
@@ -218,9 +240,9 @@ static int property_get_preparing(
assert(m);
if (streq(property, "PreparingForShutdown"))
- b = !!(m->action_what & INHIBIT_SHUTDOWN);
+ b = m->action_what & INHIBIT_SHUTDOWN;
else
- b = !!(m->action_what & INHIBIT_SLEEP);
+ b = m->action_what & INHIBIT_SLEEP;
return sd_bus_message_append(reply, "b", b);
}
@@ -253,60 +275,9 @@ static int property_get_scheduled_shutdown(
}
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
-
-static int property_get_docked(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Manager *m = userdata;
-
- assert(bus);
- assert(reply);
- assert(m);
-
- return sd_bus_message_append(reply, "b", manager_is_docked_or_external_displays(m));
-}
-
-static int property_get_current_sessions(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Manager *m = userdata;
-
- assert(bus);
- assert(reply);
- assert(m);
-
- return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->sessions));
-}
-
-static int property_get_current_inhibitors(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Manager *m = userdata;
-
- assert(bus);
- assert(reply);
- assert(m);
-
- return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->inhibitors));
-}
+static BUS_DEFINE_PROPERTY_GET(property_get_docked, "b", Manager, manager_is_docked_or_external_displays);
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_compat_user_tasks_max, "t", CGROUP_LIMIT_MAX);
+static BUS_DEFINE_PROPERTY_GET_REF(property_get_hashmap_size, "t", Hashmap *, (uint64_t) hashmap_size);
static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *p = NULL;
@@ -333,6 +304,9 @@ static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_er
return sd_bus_reply_method_return(message, "o", p);
}
+/* Get login session of a process. This is not what you are looking for these days,
+ * as apps may instead belong to a user service unit. This includes terminal
+ * emulators and hence command-line apps. */
static int method_get_session_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *p = NULL;
Session *session = NULL;
@@ -423,7 +397,9 @@ static int method_get_user_by_pid(sd_bus_message *message, void *userdata, sd_bu
if (r < 0)
return r;
if (!user)
- return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID, "PID "PID_FMT" does not belong to any known or logged in user", pid);
+ return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID,
+ "PID "PID_FMT" does not belong to any logged in user or lingering user",
+ pid);
}
p = user_bus_path(user);
@@ -617,9 +593,9 @@ static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bu
static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
- uint32_t audit_id = 0;
_cleanup_free_ char *id = NULL;
Session *session = NULL;
+ uint32_t audit_id = 0;
Manager *m = userdata;
User *user = NULL;
Seat *seat = NULL;
@@ -643,7 +619,7 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
if (!uid_is_valid(uid))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UID");
- if (leader < 0 || leader == 1)
+ if (leader < 0 || leader == 1 || leader == getpid_cached())
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
if (isempty(type))
@@ -689,7 +665,7 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
if (v <= 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty);
- if (!vtnr)
+ if (vtnr == 0)
vtnr = (uint32_t) v;
else if (vtnr != (uint32_t) v)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match");
@@ -707,7 +683,7 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
if (seat) {
if (seat_has_vts(seat)) {
- if (!vtnr || vtnr > 63)
+ if (vtnr <= 0 || vtnr > 63)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "VT number out of range");
} else {
if (vtnr != 0)
@@ -715,10 +691,6 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
}
}
- r = sd_bus_message_enter_container(message, 'a', "(sv)");
- if (r < 0)
- return r;
-
if (t == _SESSION_TYPE_INVALID) {
if (!isempty(display))
t = SESSION_X11;
@@ -747,9 +719,13 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
return r;
}
- r = manager_get_session_by_pid(m, leader, NULL);
+ /* Check if we are already in a logind session. Or if we are in user@.service which is a special PAM session
+ * that avoids creating a logind session. */
+ r = manager_get_user_by_pid(m, leader, NULL);
+ if (r < 0)
+ return r;
if (r > 0)
- return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already running in a session");
+ return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already running in a session or user slice");
/*
* Old gdm and lightdm start the user-session on the same VT as
@@ -771,8 +747,8 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
if (hashmap_size(m->sessions) >= m->sessions_max)
return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Maximum number of sessions (%" PRIu64 ") reached, refusing further sessions.", m->sessions_max);
- audit_session_from_pid(leader, &audit_id);
- if (audit_id > 0) {
+ (void) audit_session_from_pid(leader, &audit_id);
+ if (audit_session_is_valid(audit_id)) {
/* Keep our session IDs and the audit session IDs in sync */
if (asprintf(&id, "%"PRIu32, audit_id) < 0)
@@ -783,9 +759,8 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
* the audit data and let's better register a new
* ID */
if (hashmap_get(m->sessions, id)) {
- log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
- audit_id = 0;
-
+ log_warning("Existing logind session ID %s used by new audit session, ignoring.", id);
+ audit_id = AUDIT_SESSION_INVALID;
id = mfree(id);
}
}
@@ -871,15 +846,22 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
goto fail;
}
- r = session_start(session);
+ r = sd_bus_message_enter_container(message, 'a', "(sv)");
+ if (r < 0)
+ return r;
+
+ r = session_start(session, message);
+ if (r < 0)
+ goto fail;
+
+ r = sd_bus_message_exit_container(message);
if (r < 0)
goto fail;
session->create_message = sd_bus_message_ref(message);
#if 0 /// UNNEEDED by elogind
- /* Now, let's wait until the slice unit and stuff got
- * created. We send the reply back from
+ /* Now, let's wait until the slice unit and stuff got created. We send the reply back from
* session_send_create_reply(). */
#else
/* We reply directly. */
@@ -1132,13 +1114,13 @@ static int method_terminate_seat(sd_bus_message *message, void *userdata, sd_bus
}
static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
_cleanup_free_ char *cc = NULL;
Manager *m = userdata;
int r, b, interactive;
struct passwd *pw;
const char *path;
- uint32_t uid;
- bool self = false;
+ uint32_t uid, auth_uid;
assert(message);
assert(m);
@@ -1147,22 +1129,23 @@ static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bu
if (r < 0)
return r;
- if (uid == UID_INVALID) {
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
-
- /* Note that we get the owner UID of the session, not the actual client UID here! */
- r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
- if (r < 0)
- return r;
+ r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID |
+ SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
+ if (r < 0)
+ return r;
+ if (!uid_is_valid(uid)) {
+ /* Note that we get the owner UID of the session or user unit,
+ * not the actual client UID here! */
r = sd_bus_creds_get_owner_uid(creds, &uid);
if (r < 0)
return r;
+ }
- self = true;
-
- } else if (!uid_is_valid(uid))
- return -EINVAL;
+ /* owner_uid is racy, so for authorization we must use euid */
+ r = sd_bus_creds_get_euid(creds, &auth_uid);
+ if (r < 0)
+ return r;
errno = 0;
pw = getpwuid(uid);
@@ -1172,7 +1155,8 @@ static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bu
r = bus_verify_polkit_async(
message,
CAP_SYS_ADMIN,
- self ? "org.freedesktop.login1.set-self-linger" : "org.freedesktop.login1.set-user-linger",
+ uid == auth_uid ? "org.freedesktop.login1.set-self-linger" :
+ "org.freedesktop.login1.set-user-linger",
NULL,
interactive,
UID_INVALID,
@@ -1183,9 +1167,9 @@ static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bu
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
- mkdir_p_label("/var/lib/systemd", 0755);
+ mkdir_p_label("/var/lib/elogind", 0755);
- r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
+ r = mkdir_safe_label("/var/lib/elogind/linger", 0755, 0, 0, MKDIR_WARN_MODE);
if (r < 0)
return r;
@@ -1193,7 +1177,7 @@ static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bu
if (!cc)
return -ENOMEM;
- path = strjoina("/var/lib/systemd/linger/", cc);
+ path = strjoina("/var/lib/elogind/linger/", cc);
if (b) {
User *u;
@@ -1220,7 +1204,7 @@ static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bu
}
static int trigger_device(Manager *m, struct udev_device *d) {
- _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
+ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
struct udev_list_entry *first, *item;
int r;
@@ -1251,14 +1235,14 @@ static int trigger_device(Manager *m, struct udev_device *d) {
if (!t)
return -ENOMEM;
- write_string_file(t, "change", WRITE_STRING_FILE_CREATE);
+ (void) write_string_file(t, "change", 0);
}
return 0;
}
static int attach_device(Manager *m, const char *seat, const char *sysfs) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
_cleanup_free_ char *rule = NULL, *file = NULL;
const char *id_for_seat;
int r;
@@ -1415,7 +1399,6 @@ static int have_multiple_sessions(
#if 0 /// elogind has its own variant in elogind-dbus.c
static int bus_manager_log_shutdown(
Manager *m,
- InhibitWhat w,
const char *unit_name) {
const char *p, *q;
@@ -1423,18 +1406,15 @@ static int bus_manager_log_shutdown(
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_HALT_TARGET)) {
+ p = "MESSAGE=System is halting";
+ q = "SHUTDOWN=halt";
} else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
p = "MESSAGE=System is rebooting with kexec";
q = "SHUTDOWN=kexec";
@@ -1451,8 +1431,7 @@ static int bus_manager_log_shutdown(
return log_struct(LOG_NOTICE,
"MESSAGE_ID=" SD_MESSAGE_SHUTDOWN_STR,
p,
- q,
- NULL);
+ q);
}
#endif // 0
@@ -1501,18 +1480,30 @@ int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
return r;
}
-static void reset_scheduled_shutdown(Manager *m) {
- m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
- m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
- m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
- m->scheduled_shutdown_type = mfree(m->scheduled_shutdown_type);
- m->scheduled_shutdown_timeout = 0;
- m->shutdown_dry_run = false;
+#if 0 /// elogind-dbus.c needs to access this
+static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
+#else
+int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
+#endif // 0
- if (m->unlink_nologin) {
- (void) unlink("/run/nologin");
- m->unlink_nologin = false;
- }
+ static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
+ [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
+ [INHIBIT_SLEEP] = "PrepareForSleep"
+ };
+
+ int active = _active;
+
+ assert(m);
+ assert(w >= 0);
+ assert(w < _INHIBIT_WHAT_MAX);
+ assert(signal_name[w]);
+
+ return sd_bus_emit_signal(m->bus,
+ "/org/freedesktop/login1",
+ "org.freedesktop.login1.Manager",
+ signal_name[w],
+ "b",
+ active);
}
#if 0 /// elogind has its own variant in elogind-dbus.c
@@ -1528,35 +1519,33 @@ static int execute_shutdown_or_sleep(
int r;
assert(m);
- assert(w >= 0);
+ assert(w > 0);
assert(w < _INHIBIT_WHAT_MAX);
assert(unit_name);
- bus_manager_log_shutdown(m, w, unit_name);
+ if (w == INHIBIT_SHUTDOWN)
+ bus_manager_log_shutdown(m, unit_name);
- if (m->shutdown_dry_run) {
- log_info("Running in dry run, suppressing action.");
- reset_scheduled_shutdown(m);
- } else {
- r = sd_bus_call_method(
- m->bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "StartUnit",
- error,
- &reply,
- "ss", unit_name, "replace-irreversibly");
- if (r < 0)
- return r;
+ r = sd_bus_call_method(
+ m->bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "StartUnit",
+ error,
+ &reply,
+ "ss", unit_name, "replace-irreversibly");
+ if (r < 0)
+ goto error;
- r = sd_bus_message_read(reply, "o", &p);
- if (r < 0)
- return r;
+ r = sd_bus_message_read(reply, "o", &p);
+ if (r < 0)
+ goto error;
- c = strdup(p);
- if (!c)
- return -ENOMEM;
+ c = strdup(p);
+ if (!c) {
+ r = -ENOMEM;
+ goto error;
}
m->action_unit = unit_name;
@@ -1568,7 +1557,14 @@ static int execute_shutdown_or_sleep(
manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
return 0;
+
+error:
+ /* Tell people that they now may take a lock again */
+ (void) send_prepare_for(m, w, false);
+
+ return r;
}
+#endif // 0
int manager_dispatch_delayed(Manager *manager, bool timeout) {
@@ -1578,7 +1574,11 @@ int manager_dispatch_delayed(Manager *manager, bool timeout) {
assert(manager);
+#if 0 /// elogind has no action_job, but a pending_action
if (manager->action_what == 0 || manager->action_job)
+#else
+ if ( (0 == manager->action_what) || (HANDLE_IGNORE == manager->pending_action) )
+#endif // 0
return 0;
if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
@@ -1596,24 +1596,31 @@ int manager_dispatch_delayed(Manager *manager, bool timeout) {
}
/* Actually do the operation */
+#if 0 /// elogind has no action_unit but a pending_action
r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
+#else
+ r = execute_shutdown_or_sleep(manager, manager->action_what, manager->pending_action, &error);
+#endif // 0
if (r < 0) {
- log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
+ log_warning("Error during inhibitor-delayed operation (already returned success to client): %s",
+ bus_error_message(&error, r));
+
+#if 0 /// elogind has no action_unit but a pending_action
manager->action_unit = NULL;
manager->action_what = 0;
return r;
+#else
+ manager->pending_action = HANDLE_IGNORE;
+ manager->action_what = 0;
+ /* It is not a critical error for elogind if suspending fails */
+#endif // 0
}
return 1;
}
-#endif // 0
-#if 0 /// elogind-dbus.c needs to access this
static int manager_inhibit_timeout_handler(
-#else
-int manager_inhibit_timeout_handler(
-#endif // 0
sd_event_source *s,
uint64_t usec,
void *userdata) {
@@ -1628,19 +1635,27 @@ int manager_inhibit_timeout_handler(
return (r < 0) ? r : 0;
}
-#if 0 /// elogind has its own variant in elogind-dbus.c
+#if 0 /// elogind does not have unit_name but action
static int delay_shutdown_or_sleep(
Manager *m,
InhibitWhat w,
const char *unit_name) {
+#else
+int delay_shutdown_or_sleep(
+ Manager *m,
+ InhibitWhat w,
+ HandleAction action) {
+#endif // 0
int r;
usec_t timeout_val;
assert(m);
assert(w >= 0);
assert(w < _INHIBIT_WHAT_MAX);
+#if 0 /// UNNEEDED by elogind
assert(unit_name);
+#endif // 0
timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
@@ -1659,64 +1674,59 @@ static int delay_shutdown_or_sleep(
return r;
}
+#if 0 /// elogind does not have unit_name but pendig_action
m->action_unit = unit_name;
- m->action_what = w;
-
- return 0;
-}
-#endif // 0
-
-#if 0 /// elogind-dbus.c needs to access this
-static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
#else
-int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
+ m->pending_action = action;
#endif // 0
+ m->action_what = w;
- static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
- [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
- [INHIBIT_SLEEP] = "PrepareForSleep"
- };
-
- int active = _active;
-
- assert(m);
- assert(w >= 0);
- assert(w < _INHIBIT_WHAT_MAX);
- assert(signal_name[w]);
-
- return sd_bus_emit_signal(m->bus,
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- signal_name[w],
- "b",
- active);
+ return 0;
}
-#if 0 /// elogind has its own variant in elogind-dbus.c
int bus_manager_shutdown_or_sleep_now_or_later(
Manager *m,
+#if 0 /// elogind has HandleAction instead of const char* unit_name
const char *unit_name,
+
+ _cleanup_free_ char *load_state = NULL;
+#else
+ HandleAction unit_name,
+#endif // 0
InhibitWhat w,
sd_bus_error *error) {
-
bool delayed;
int r;
assert(m);
+#if 0 /// for elogind only w has to be checked.
assert(unit_name);
- assert(w >= 0);
+ assert(w > 0);
assert(w <= _INHIBIT_WHAT_MAX);
assert(!m->action_job);
+ r = unit_load_state(m->bus, unit_name, &load_state);
+ if (r < 0)
+ return r;
+
+ if (!streq(load_state, "loaded")) {
+ log_notice("Unit %s is %s, refusing operation.", unit_name, load_state);
+ return -EACCES;
+ }
+#else
+ assert(w > 0);
+ assert(w <= _INHIBIT_WHAT_MAX);
+#endif // 0
+
/* Tell everybody to prepare for shutdown/sleep */
- send_prepare_for(m, w, true);
+ (void) send_prepare_for(m, w, true);
delayed =
m->inhibit_delay_max > 0 &&
manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
log_debug_elogind("%s called for %s (%sdelayed)", __FUNCTION__,
- handle_action_to_string(action),
+ handle_action_to_string(unit_name),
delayed ? "" : "NOT ");
if (delayed)
/* Shutdown is delayed, keep in mind what we
@@ -1729,13 +1739,8 @@ int bus_manager_shutdown_or_sleep_now_or_later(
return r;
}
-#endif // 0
-#if 0 /// elogind-dbus.c needs to access this
static int verify_shutdown_creds(
-#else
-int verify_shutdown_creds(
-#endif // 0
Manager *m,
sd_bus_message *message,
InhibitWhat w,
@@ -1797,11 +1802,14 @@ int verify_shutdown_creds(
return 0;
}
-#if 0 /// elogind has its own variant in elogind-dbus.c
static int method_do_shutdown_or_sleep(
Manager *m,
sd_bus_message *message,
+#if 0 /// elogind has HandleAction instead of const char* unit_name
const char *unit_name,
+#else
+ HandleAction unit_name,
+#endif // 0
InhibitWhat w,
const char *action,
const char *action_multiple_sessions,
@@ -1813,7 +1821,9 @@ static int method_do_shutdown_or_sleep(
assert(m);
assert(message);
+#if 0 /// elogind does not need this to be checked
assert(unit_name);
+#endif // 0
assert(w >= 0);
assert(w <= _INHIBIT_WHAT_MAX);
@@ -1829,19 +1839,35 @@ static int method_do_shutdown_or_sleep(
return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
if (sleep_verb) {
+#if 0 /// Within elogind the manager m must be provided, too
r = can_sleep(sleep_verb);
+ if (r == -ENOSPC)
+ return sd_bus_error_set(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED,
+ "Not enough swap space for hibernation");
+ if (r == 0)
+ return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED,
+ "Sleep verb \"%s\" not supported", sleep_verb);
+#else
+ r = can_sleep(m, sleep_verb);
+#endif // 0
if (r < 0)
return r;
-
- if (r == 0)
- return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
}
+#if 0 /// Within elogind it does not make sense to verify shutdown creds when suspending
r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
action_ignore_inhibit, error);
- log_debug_elogind("verify_shutdown_creds() returned %d", r);
if (r != 0)
return r;
+#else
+ if (IN_SET(unit_name, HANDLE_HALT, HANDLE_POWEROFF, HANDLE_REBOOT)) {
+ r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
+ action_ignore_inhibit, error);
+ log_debug_elogind("verify_shutdown_creds() returned %d", r);
+ if (r != 0)
+ return r;
+ }
+#endif // 0
r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
if (r < 0)
@@ -1856,7 +1882,11 @@ static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error
log_debug_elogind("%s called", __FUNCTION__);
return method_do_shutdown_or_sleep(
m, message,
+#if 0 /// elogind uses HandleAction instead of const char* unti names
SPECIAL_POWEROFF_TARGET,
+#else
+ HANDLE_POWEROFF,
+#endif // 0
INHIBIT_SHUTDOWN,
"org.freedesktop.login1.power-off",
"org.freedesktop.login1.power-off-multiple-sessions",
@@ -1871,7 +1901,11 @@ static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *
log_debug_elogind("%s called", __FUNCTION__);
return method_do_shutdown_or_sleep(
m, message,
+#if 0 /// elogind uses HandleAction instead of const char* unti names
SPECIAL_REBOOT_TARGET,
+#else
+ HANDLE_REBOOT,
+#endif // 0
INHIBIT_SHUTDOWN,
"org.freedesktop.login1.reboot",
"org.freedesktop.login1.reboot-multiple-sessions",
@@ -1880,13 +1914,36 @@ static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *
error);
}
+static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ Manager *m = userdata;
+
+ log_debug_elogind("%s called", __FUNCTION__);
+ return method_do_shutdown_or_sleep(
+ m, message,
+#if 0 /// elogind uses HandleAction instead of const char* unti names
+ SPECIAL_HALT_TARGET,
+#else
+ HANDLE_HALT,
+#endif // 0
+ INHIBIT_SHUTDOWN,
+ "org.freedesktop.login1.halt",
+ "org.freedesktop.login1.halt-multiple-sessions",
+ "org.freedesktop.login1.halt-ignore-inhibit",
+ NULL,
+ error);
+}
+
static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
log_debug_elogind("%s called", __FUNCTION__);
return method_do_shutdown_or_sleep(
m, message,
+#if 0 /// elogind uses HandleAction instead of const char* unti names
SPECIAL_SUSPEND_TARGET,
+#else
+ HANDLE_SUSPEND,
+#endif // 0
INHIBIT_SLEEP,
"org.freedesktop.login1.suspend",
"org.freedesktop.login1.suspend-multiple-sessions",
@@ -1894,7 +1951,62 @@ static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error
"suspend",
error);
}
+
+static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ Manager *m = userdata;
+
+ log_debug_elogind("%s called", __FUNCTION__);
+ return method_do_shutdown_or_sleep(
+ m, message,
+#if 0 /// elogind uses HandleAction instead of const char* unti names
+ SPECIAL_HIBERNATE_TARGET,
+#else
+ HANDLE_HIBERNATE,
+#endif // 0
+ INHIBIT_SLEEP,
+ "org.freedesktop.login1.hibernate",
+ "org.freedesktop.login1.hibernate-multiple-sessions",
+ "org.freedesktop.login1.hibernate-ignore-inhibit",
+ "hibernate",
+ error);
+}
+
+static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ Manager *m = userdata;
+
+ log_debug_elogind("%s called", __FUNCTION__);
+ return method_do_shutdown_or_sleep(
+ m, message,
+#if 0 /// elogind uses HandleAction instead of const char* unti names
+ SPECIAL_HYBRID_SLEEP_TARGET,
+#else
+ HANDLE_HYBRID_SLEEP,
#endif // 0
+ INHIBIT_SLEEP,
+ "org.freedesktop.login1.hibernate",
+ "org.freedesktop.login1.hibernate-multiple-sessions",
+ "org.freedesktop.login1.hibernate-ignore-inhibit",
+ "hybrid-sleep",
+ error);
+}
+
+static int method_suspend_then_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ Manager *m = userdata;
+
+ return method_do_shutdown_or_sleep(
+ m, message,
+#if 0 /// elogind uses HandleAction instead of const char* unti names
+ SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET,
+#else
+ HANDLE_SUSPEND_THEN_HIBERNATE,
+#endif // 0
+ INHIBIT_SLEEP,
+ "org.freedesktop.login1.hibernate",
+ "org.freedesktop.login1.hibernate-multiple-sessions",
+ "org.freedesktop.login1.hibernate-ignore-inhibit",
+ "hybrid-sleep",
+ error);
+}
static int nologin_timeout_handler(
sd_event_source *s,
@@ -1902,15 +2014,11 @@ static int nologin_timeout_handler(
void *userdata) {
Manager *m = userdata;
- int r;
log_info("Creating /run/nologin, blocking further logins...");
- r = write_string_file_atomic_label("/run/nologin", "System is going down.");
- if (r < 0)
- log_error_errno(r, "Failed to create /run/nologin: %m");
- else
- m->unlink_nologin = true;
+ m->unlink_nologin =
+ create_shutdown_run_nologin_or_warn() >= 0;
return 0;
}
@@ -1922,7 +2030,7 @@ static int update_schedule_file(Manager *m) {
assert(m);
- r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0);
+ r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, MKDIR_WARN_MODE);
if (r < 0)
return log_error_errno(r, "Failed to create shutdown subdirectory: %m");
@@ -1970,6 +2078,29 @@ fail:
return log_error_errno(r, "Failed to write information about scheduled shutdowns: %m");
}
+#if 0 /// elogind must access this from elogind-dbus.c
+static void reset_scheduled_shutdown(Manager *m) {
+#else
+void reset_scheduled_shutdown(Manager *m) {
+#endif // 0
+ assert(m);
+
+ m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
+ m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
+ m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
+
+ m->scheduled_shutdown_type = mfree(m->scheduled_shutdown_type);
+ m->scheduled_shutdown_timeout = 0;
+ m->shutdown_dry_run = false;
+
+ if (m->unlink_nologin) {
+ (void) unlink_or_warn("/run/nologin");
+ m->unlink_nologin = false;
+ }
+
+ (void) unlink("/run/systemd/shutdown/scheduled");
+}
+
#if 0 /// elogind has its own variant in elogind-dbus.c
static int manager_scheduled_shutdown_handler(
sd_event_source *s,
@@ -1986,18 +2117,46 @@ static int manager_scheduled_shutdown_handler(
if (isempty(m->scheduled_shutdown_type))
return 0;
- if (streq(m->scheduled_shutdown_type, "halt"))
- target = SPECIAL_HALT_TARGET;
- else if (streq(m->scheduled_shutdown_type, "poweroff"))
+ if (streq(m->scheduled_shutdown_type, "poweroff"))
target = SPECIAL_POWEROFF_TARGET;
- else
+ else if (streq(m->scheduled_shutdown_type, "reboot"))
target = SPECIAL_REBOOT_TARGET;
+ else if (streq(m->scheduled_shutdown_type, "halt"))
+ target = SPECIAL_HALT_TARGET;
+ else
+ assert_not_reached("unexpected shutdown type");
- r = execute_shutdown_or_sleep(m, 0, target, &error);
- if (r < 0)
- return log_error_errno(r, "Unable to execute transition to %s: %m", target);
+ /* Don't allow multiple jobs being executed at the same time */
+ if (m->action_what) {
+ r = -EALREADY;
+ log_error("Scheduled shutdown to %s failed: shutdown or sleep operation already in progress", target);
+ goto error;
+ }
+
+ if (m->shutdown_dry_run) {
+ /* We do not process delay inhibitors here. Otherwise, we
+ * would have to be considered "in progress" (like the check
+ * above) for some seconds after our admin has seen the final
+ * wall message. */
+
+ bus_manager_log_shutdown(m, target);
+ log_info("Running in dry run, suppressing action.");
+ reset_scheduled_shutdown(m);
+
+ return 0;
+ }
+
+ r = bus_manager_shutdown_or_sleep_now_or_later(m, target, INHIBIT_SHUTDOWN, &error);
+ if (r < 0) {
+ log_error_errno(r, "Scheduled shutdown to %s failed: %m", target);
+ goto error;
+ }
return 0;
+
+error:
+ reset_scheduled_shutdown(m);
+ return r;
}
#endif // 0
@@ -2010,6 +2169,7 @@ static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_
uint64_t elapse;
char *type;
int r;
+ bool dry_run = false;
assert(m);
assert(message);
@@ -2021,10 +2181,14 @@ static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_
if (startswith(type, "dry-")) {
type += 4;
- m->shutdown_dry_run = true;
+ dry_run = true;
}
- if (streq(type, "reboot")) {
+ if (streq(type, "poweroff")) {
+ action = "org.freedesktop.login1.power-off";
+ action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions";
+ action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit";
+ } else if (streq(type, "reboot")) {
action = "org.freedesktop.login1.reboot";
action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
@@ -2032,10 +2196,6 @@ static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_
action = "org.freedesktop.login1.halt";
action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
- } else if (streq(type, "poweroff")) {
- action = "org.freedesktop.login1.power-off";
- action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions";
- action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit";
} else
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
@@ -2065,6 +2225,8 @@ static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_
return log_oom();
}
+ m->shutdown_dry_run = dry_run;
+
if (m->nologin_timeout_source) {
r = sd_event_source_set_time(m->nologin_timeout_source, elapse);
if (r < 0)
@@ -2100,12 +2262,9 @@ static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_
if (r < 0)
return r;
- if (!isempty(type)) {
- r = update_schedule_file(m);
- if (r < 0)
- return r;
- } else
- (void) unlink("/run/systemd/shutdown/scheduled");
+ r = update_schedule_file(m);
+ if (r < 0)
+ return r;
return sd_bus_reply_method_return(message, NULL);
}
@@ -2124,7 +2283,7 @@ static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userd
cancelled = m->scheduled_shutdown_type != NULL;
reset_scheduled_shutdown(m);
- if (cancelled) {
+ if (cancelled && m->enable_wall_messages) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
const char *tty = NULL;
uid_t uid = 0;
@@ -2155,38 +2314,6 @@ static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userd
return sd_bus_reply_method_return(message, "b", cancelled);
}
-#if 0 /// elogind has its own variant in elogind-dbus.c
-static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- Manager *m = userdata;
-
- log_debug_elogind("%s called", __FUNCTION__);
- return method_do_shutdown_or_sleep(
- m, message,
- SPECIAL_HIBERNATE_TARGET,
- INHIBIT_SLEEP,
- "org.freedesktop.login1.hibernate",
- "org.freedesktop.login1.hibernate-multiple-sessions",
- "org.freedesktop.login1.hibernate-ignore-inhibit",
- "hibernate",
- error);
-}
-
-static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- Manager *m = userdata;
-
- log_debug_elogind("%s called", __FUNCTION__);
- return method_do_shutdown_or_sleep(
- m, message,
- SPECIAL_HYBRID_SLEEP_TARGET,
- INHIBIT_SLEEP,
- "org.freedesktop.login1.hibernate",
- "org.freedesktop.login1.hibernate-multiple-sessions",
- "org.freedesktop.login1.hibernate-ignore-inhibit",
- "hybrid-sleep",
- error);
-}
-#endif // 0
-
static int method_can_shutdown_or_sleep(
Manager *m,
sd_bus_message *message,
@@ -2198,6 +2325,7 @@ static int method_can_shutdown_or_sleep(
sd_bus_error *error) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+ HandleAction handle;
bool multiple_sessions, challenge, blocked;
const char *result = NULL;
uid_t uid;
@@ -2217,10 +2345,10 @@ static int method_can_shutdown_or_sleep(
#else
r = can_sleep(m, sleep_verb);
#endif // 0
+ if (IN_SET(r, 0, -ENOSPC))
+ return sd_bus_reply_method_return(message, "s", "na");
if (r < 0)
return r;
- if (r == 0)
- return sd_bus_reply_method_return(message, "s", "na");
}
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
@@ -2238,6 +2366,32 @@ static int method_can_shutdown_or_sleep(
multiple_sessions = r > 0;
blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
+ handle = handle_action_from_string(sleep_verb);
+
+ if (handle >= 0) {
+#if 0 /// elogind uses its own variant, which can use the handle directly.
+ const char *target;
+
+ target = manager_target_for_action(handle);
+ if (target) {
+ _cleanup_free_ char *load_state = NULL;
+
+ r = unit_load_state(m->bus, target, &load_state);
+ if (r < 0)
+ return r;
+
+ if (!streq(load_state, "loaded")) {
+ result = "no";
+ goto finish;
+ }
+ }
+ }
+#else
+ log_debug_elogind("CanShutDownOrSleep: %s [%d] %s blocked",
+ sleep_verb, handle, blocked ? "is" : "not");
+#endif // 0
+ }
+
if (multiple_sessions) {
r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, UID_INVALID, &challenge, error);
if (r < 0)
@@ -2249,6 +2403,8 @@ static int method_can_shutdown_or_sleep(
result = "challenge";
else
result = "no";
+ log_debug_elogind("CanShutDownOrSleep: multiple_sessions: %s = %s",
+ action_multiple_sessions, result);
}
if (blocked) {
@@ -2262,6 +2418,8 @@ static int method_can_shutdown_or_sleep(
result = "challenge";
else
result = "no";
+ log_debug_elogind("CanShutDownOrSleep: blocked : %s = %s",
+ action_ignore_inhibit, result);
}
if (!multiple_sessions && !blocked) {
@@ -2278,8 +2436,11 @@ static int method_can_shutdown_or_sleep(
result = "challenge";
else
result = "no";
+ log_debug_elogind("CanShutDownOrSleep: regular : %s = %s",
+ action, result);
}
+ finish:
return sd_bus_reply_method_return(message, "s", result);
}
@@ -2309,6 +2470,19 @@ static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_err
error);
}
+static int method_can_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ Manager *m = userdata;
+
+ return method_can_shutdown_or_sleep(
+ m, message,
+ INHIBIT_SHUTDOWN,
+ "org.freedesktop.login1.halt",
+ "org.freedesktop.login1.halt-multiple-sessions",
+ "org.freedesktop.login1.halt-ignore-inhibit",
+ NULL,
+ error);
+}
+
static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
@@ -2348,6 +2522,19 @@ static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_b
error);
}
+static int method_can_suspend_then_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ Manager *m = userdata;
+
+ return method_can_shutdown_or_sleep(
+ m, message,
+ INHIBIT_SLEEP,
+ "org.freedesktop.login1.hibernate",
+ "org.freedesktop.login1.hibernate-multiple-sessions",
+ "org.freedesktop.login1.hibernate-ignore-inhibit",
+ "suspend-then-hibernate",
+ error);
+}
+
static int property_get_reboot_to_firmware_setup(
sd_bus *bus,
const char *path,
@@ -2365,7 +2552,7 @@ static int property_get_reboot_to_firmware_setup(
r = efi_get_reboot_to_firmware();
if (r < 0 && r != -EOPNOTSUPP)
- return r;
+ log_warning_errno(r, "Failed to determine reboot-to-firmware state: %m");
return sd_bus_message_append(reply, "b", r > 0);
#else
@@ -2425,10 +2612,12 @@ static int method_can_reboot_to_firmware_setup(
assert(m);
r = efi_reboot_to_firmware_supported();
- if (r == -EOPNOTSUPP)
+ if (r < 0) {
+ if (r != -EOPNOTSUPP)
+ log_warning_errno(errno, "Failed to determine whether reboot to firmware is supported: %m");
+
return sd_bus_reply_method_return(message, "s", "na");
- else if (r < 0)
- return r;
+ }
r = bus_test_polkit(message,
CAP_SYS_ADMIN,
@@ -2461,7 +2650,7 @@ static int method_set_wall_message(
int r;
Manager *m = userdata;
char *wall_message;
- int enable_wall_messages;
+ unsigned enable_wall_messages;
assert(message);
assert(m);
@@ -2632,6 +2821,7 @@ const sd_bus_vtable manager_vtable[] = {
SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("HandleLidSwitchExternalPower", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_ep), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -2641,12 +2831,12 @@ const sd_bus_vtable manager_vtable[] = {
SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0),
SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(Manager, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("RuntimeDirectorySize", "t", bus_property_get_size, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("RuntimeDirectorySize", "t", NULL, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("InhibitorsMax", "t", NULL, offsetof(Manager, inhibitors_max), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_current_inhibitors, 0, 0),
+ SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_hashmap_size, offsetof(Manager, inhibitors), 0),
SD_BUS_PROPERTY("SessionsMax", "t", NULL, offsetof(Manager, sessions_max), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_current_sessions, 0, 0),
- SD_BUS_PROPERTY("UserTasksMax", "t", NULL, offsetof(Manager, user_tasks_max), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_hashmap_size, offsetof(Manager, sessions), 0),
+ SD_BUS_PROPERTY("UserTasksMax", "t", property_get_compat_user_tasks_max, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
@@ -2675,14 +2865,18 @@ const sd_bus_vtable manager_vtable[] = {
SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("Halt", "b", NULL, method_halt, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("SuspendThenHibernate", "b", NULL, method_suspend_then_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("CanHalt", NULL, "s", method_can_halt, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("CanSuspendThenHibernate", NULL, "s", method_can_suspend_then_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
@@ -2745,7 +2939,7 @@ int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *err
log_info("Operation '%s' finished.", inhibit_what_to_string(m->action_what));
/* Tell people that they now may take a lock again */
- send_prepare_for(m, m->action_what, false);
+ (void) send_prepare_for(m, m->action_what, false);
m->action_job = mfree(m->action_job);
m->action_unit = NULL;
@@ -2905,78 +3099,6 @@ static int strdup_job(sd_bus_message *reply, char **job) {
return 1;
}
-int manager_start_slice(
- Manager *manager,
- const char *slice,
- const char *description,
- const char *after,
- const char *after2,
- uint64_t tasks_max,
- sd_bus_error *error,
- char **job) {
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
- int r;
-
- assert(manager);
- assert(slice);
- assert(job);
-
- r = sd_bus_message_new_method_call(
- manager->bus,
- &m,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "StartTransientUnit");
- if (r < 0)
- return r;
-
- r = sd_bus_message_append(m, "ss", strempty(slice), "fail");
- if (r < 0)
- return r;
-
- r = sd_bus_message_open_container(m, 'a', "(sv)");
- if (r < 0)
- return r;
-
- if (!isempty(description)) {
- r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
- if (r < 0)
- return r;
- }
-
- if (!isempty(after)) {
- r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
- if (r < 0)
- return r;
- }
-
- if (!isempty(after2)) {
- r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
- if (r < 0)
- return r;
- }
-
- r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
- if (r < 0)
- return r;
-
- r = sd_bus_message_close_container(m);
- if (r < 0)
- return r;
-
- r = sd_bus_message_append(m, "a(sa(sv))", 0);
- if (r < 0)
- return r;
-
- r = sd_bus_call(manager->bus, m, 0, error, &reply);
- if (r < 0)
- return r;
-
- return strdup_job(reply, job);
-}
-
int manager_start_scope(
Manager *manager,
const char *scope,
@@ -2985,7 +3107,7 @@ int manager_start_scope(
const char *description,
const char *after,
const char *after2,
- uint64_t tasks_max,
+ sd_bus_message *more_properties,
sd_bus_error *error,
char **job) {
@@ -3039,13 +3161,8 @@ int manager_start_scope(
return r;
}
- /* cgroup empty notification is not available in containers
- * currently. To make this less problematic, let's shorten the
- * stop timeout for sessions, so that we don't wait
- * forever. */
-
- /* Make sure that the session shells are terminated with
- * SIGHUP since bash and friends tend to ignore SIGTERM */
+ /* Make sure that the session shells are terminated with SIGHUP since bash and friends tend to ignore
+ * SIGTERM */
r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
if (r < 0)
return r;
@@ -3054,9 +3171,17 @@ int manager_start_scope(
if (r < 0)
return r;
- r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
+ /* disable TasksMax= for the session scope, rely on the slice setting for it */
+ r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", (uint64_t)-1);
if (r < 0)
- return r;
+ return bus_log_create_error(r);
+
+ if (more_properties) {
+ /* If TasksMax also appears here, it will overwrite the default value set above */
+ r = sd_bus_message_copy(m, more_properties, true);
+ if (r < 0)
+ return r;
+ }
r = sd_bus_message_close_container(m);
if (r < 0)
diff --git a/src/login/logind-device.c b/src/login/logind-device.c
index 6537fa04b..9b5b3e879 100644
--- a/src/login/logind-device.c
+++ b/src/login/logind-device.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <string.h>
diff --git a/src/login/logind-device.h b/src/login/logind-device.h
index 927068e00..cc6e52367 100644
--- a/src/login/logind-device.h
+++ b/src/login/logind-device.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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"
diff --git a/src/login/logind-gperf.gperf b/src/login/logind-gperf.gperf
index c7f54b5f5..c8523fbdf 100644
--- a/src/login/logind-gperf.gperf
+++ b/src/login/logind-gperf.gperf
@@ -1,4 +1,7 @@
%{
+#if __GNUC__ >= 7
+_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
+#endif
#include <stddef.h>
#include "conf-parser.h"
#include "logind.h"
@@ -14,30 +17,38 @@ struct ConfigPerfItem;
%struct-type
%includes
%%
-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.InhibitDelayMaxSec, config_parse_sec, 0, offsetof(Manager, inhibit_delay_max)
-Login.HandlePowerKey, config_parse_handle_action, 0, offsetof(Manager, handle_power_key)
-Login.HandleSuspendKey, config_parse_handle_action, 0, offsetof(Manager, handle_suspend_key)
-Login.HandleHibernateKey, config_parse_handle_action, 0, offsetof(Manager, handle_hibernate_key)
-Login.HandleLidSwitch, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch)
-Login.HandleLidSwitchDocked, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_docked)
-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)
-Login.HoldoffTimeoutSec, config_parse_sec, 0, offsetof(Manager, holdoff_timeout_usec)
-Login.IdleAction, config_parse_handle_action, 0, offsetof(Manager, idle_action)
-Login.IdleActionSec, config_parse_sec, 0, offsetof(Manager, idle_action_usec)
-Login.RuntimeDirectorySize, config_parse_tmpfs_size, 0, offsetof(Manager, runtime_dir_size)
-Login.RemoveIPC, config_parse_bool, 0, offsetof(Manager, remove_ipc)
-Login.InhibitorsMax, config_parse_uint64, 0, offsetof(Manager, inhibitors_max)
-Login.SessionsMax, config_parse_uint64, 0, offsetof(Manager, sessions_max)
-Login.UserTasksMax, config_parse_user_tasks_max,0, offsetof(Manager, user_tasks_max)
+#if 1 /// Additions for elogind
Sleep.SuspendMode, config_parse_strv, 0, offsetof(Manager, suspend_mode)
Sleep.SuspendState, config_parse_strv, 0, offsetof(Manager, suspend_state)
Sleep.HibernateMode, config_parse_strv, 0, offsetof(Manager, hibernate_mode)
Sleep.HibernateState, config_parse_strv, 0, offsetof(Manager, hibernate_state)
Sleep.HybridSleepMode, config_parse_strv, 0, offsetof(Manager, hybrid_sleep_mode)
Sleep.HybridSleepState, config_parse_strv, 0, offsetof(Manager, hybrid_sleep_state)
+Sleep.HibernateDelaySec, config_parse_sec, 0, offsetof(Manager, hibernate_delay_sec),
+#endif // 1
+#if 0 /// UNNEEDED by elogind
+# Login.NAutoVTs, config_parse_n_autovts, 0, offsetof(Manager, n_autovts)
+# Login.ReserveVT, config_parse_unsigned, 0, offsetof(Manager, reserve_vt)
+#endif // 0
+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.InhibitDelayMaxSec, config_parse_sec, 0, offsetof(Manager, inhibit_delay_max)
+Login.HandlePowerKey, config_parse_handle_action, 0, offsetof(Manager, handle_power_key)
+Login.HandleSuspendKey, config_parse_handle_action, 0, offsetof(Manager, handle_suspend_key)
+Login.HandleHibernateKey, config_parse_handle_action, 0, offsetof(Manager, handle_hibernate_key)
+Login.HandleLidSwitch, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch)
+Login.HandleLidSwitchExternalPower, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_ep)
+Login.HandleLidSwitchDocked, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_docked)
+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)
+Login.HoldoffTimeoutSec, config_parse_sec, 0, offsetof(Manager, holdoff_timeout_usec)
+Login.IdleAction, config_parse_handle_action, 0, offsetof(Manager, idle_action)
+Login.IdleActionSec, config_parse_sec, 0, offsetof(Manager, idle_action_usec)
+Login.RuntimeDirectorySize, config_parse_tmpfs_size, 0, offsetof(Manager, runtime_dir_size)
+Login.RemoveIPC, config_parse_bool, 0, offsetof(Manager, remove_ipc)
+Login.InhibitorsMax, config_parse_uint64, 0, offsetof(Manager, inhibitors_max)
+Login.SessionsMax, config_parse_uint64, 0, offsetof(Manager, sessions_max)
+Login.UserTasksMax, config_parse_compat_user_tasks_max, 0, offsetof(Manager, user_tasks_max)
diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c
index 1e6f38373..b1f45baac 100644
--- a/src/login/logind-inhibit.c
+++ b/src/login/logind-inhibit.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <fcntl.h>
@@ -86,7 +69,7 @@ int inhibitor_save(Inhibitor *i) {
assert(i);
- r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0);
+ r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0, MKDIR_WARN_MODE);
if (r < 0)
goto fail;
@@ -210,7 +193,7 @@ int inhibitor_load(Inhibitor *i) {
char *cc;
int r;
- r = parse_env_file(i->state_file, NEWLINE,
+ r = parse_env_file(NULL, i->state_file, NEWLINE,
"WHAT", &what,
"UID", &uid,
"PID", &pid,
@@ -290,7 +273,7 @@ int inhibitor_create_fifo(Inhibitor *i) {
/* Create FIFO */
if (!i->fifo_path) {
- r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0);
+ r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0, MKDIR_WARN_MODE);
if (r < 0)
return r;
@@ -304,7 +287,7 @@ int inhibitor_create_fifo(Inhibitor *i) {
/* Open reading side */
if (i->fifo_fd < 0) {
- i->fifo_fd = open(i->fifo_path, O_RDONLY|O_CLOEXEC|O_NDELAY);
+ i->fifo_fd = open(i->fifo_path, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
if (i->fifo_fd < 0)
return -errno;
}
@@ -320,7 +303,7 @@ int inhibitor_create_fifo(Inhibitor *i) {
}
/* Open writing side */
- r = open(i->fifo_path, O_WRONLY|O_CLOEXEC|O_NDELAY);
+ r = open(i->fifo_path, O_WRONLY|O_CLOEXEC|O_NONBLOCK);
if (r < 0)
return -errno;
@@ -357,6 +340,8 @@ static int pid_is_active(Manager *m, pid_t pid) {
Session *s;
int r;
+ /* Get client session. This is not what you are looking for these days.
+ * FIXME #6852 */
r = manager_get_session_by_pid(m, pid, &s);
if (r < 0)
return r;
diff --git a/src/login/logind-inhibit.h b/src/login/logind-inhibit.h
index 70de199c6..d358a4855 100644
--- a/src/login/logind-inhibit.h
+++ b/src/login/logind-inhibit.h
@@ -1,27 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 Inhibitor Inhibitor;
-
typedef enum InhibitWhat {
INHIBIT_SHUTDOWN = 1,
INHIBIT_SLEEP = 2,
diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c
index f934a5326..c4d9b067c 100644
--- a/src/login/logind-seat-dbus.c
+++ b/src/login/logind-seat-dbus.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <string.h>
@@ -30,6 +13,10 @@
#include "user-util.h"
#include "util.h"
+static BUS_DEFINE_PROPERTY_GET(property_get_can_multi_session, "b", Seat, seat_can_multi_session);
+static BUS_DEFINE_PROPERTY_GET(property_get_can_tty, "b", Seat, seat_can_tty);
+static BUS_DEFINE_PROPERTY_GET(property_get_can_graphical, "b", Seat, seat_can_graphical);
+
static int property_get_active_session(
sd_bus *bus,
const char *path,
@@ -53,60 +40,6 @@ static int property_get_active_session(
return sd_bus_message_append(reply, "(so)", s->active ? s->active->id : "", p);
}
-static int property_get_can_multi_session(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Seat *s = userdata;
-
- assert(bus);
- assert(reply);
- assert(s);
-
- return sd_bus_message_append(reply, "b", seat_can_multi_session(s));
-}
-
-static int property_get_can_tty(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Seat *s = userdata;
-
- assert(bus);
- assert(reply);
- assert(s);
-
- return sd_bus_message_append(reply, "b", seat_can_tty(s));
-}
-
-static int property_get_can_graphical(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Seat *s = userdata;
-
- assert(bus);
- assert(reply);
- assert(s);
-
- return sd_bus_message_append(reply, "b", seat_can_graphical(s));
-}
-
static int property_get_sessions(
sd_bus *bus,
const char *path,
@@ -332,28 +265,15 @@ int seat_object_find(sd_bus *bus, const char *path, const char *interface, void
assert(m);
if (streq(path, "/org/freedesktop/login1/seat/self")) {
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
sd_bus_message *message;
- Session *session;
- const char *name;
message = sd_bus_get_current_message(bus);
if (!message)
return 0;
- r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
- if (r < 0)
- return r;
-
- r = sd_bus_creds_get_session(creds, &name);
+ r = manager_get_seat_from_creds(m, message, NULL, error, &seat);
if (r < 0)
return r;
-
- session = hashmap_get(m->sessions, name);
- if (!session)
- return 0;
-
- seat = session->seat;
} else {
_cleanup_free_ char *e = NULL;
const char *p;
@@ -367,11 +287,10 @@ int seat_object_find(sd_bus *bus, const char *path, const char *interface, void
return -ENOMEM;
seat = hashmap_get(m->seats, e);
+ if (!seat)
+ return 0;
}
- if (!seat)
- return 0;
-
*found = seat;
return 1;
}
@@ -432,8 +351,7 @@ int seat_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***
}
}
- *nodes = l;
- l = NULL;
+ *nodes = TAKE_PTR(l);
return 1;
}
diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c
index de27e7137..0ee5f70f5 100644
--- a/src/login/logind-seat.c
+++ b/src/login/logind-seat.c
@@ -1,24 +1,8 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <fcntl.h>
+#include <stdio_ext.h>
#include <string.h>
#include <unistd.h>
@@ -93,7 +77,7 @@ int seat_save(Seat *s) {
if (!s->started)
return 0;
- r = mkdir_safe_label("/run/systemd/seats", 0755, 0, 0);
+ r = mkdir_safe_label("/run/systemd/seats", 0755, 0, 0, MKDIR_WARN_MODE);
if (r < 0)
goto fail;
@@ -101,7 +85,8 @@ int seat_save(Seat *s) {
if (r < 0)
goto fail;
- fchmod(fileno(f), 0644);
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+ (void) fchmod(fileno(f), 0644);
fprintf(f,
"# This is private data. Do not parse.\n"
@@ -421,8 +406,7 @@ int seat_start(Seat *s) {
log_struct(LOG_INFO,
"MESSAGE_ID=" SD_MESSAGE_SEAT_START_STR,
"SEAT_ID=%s", s->id,
- LOG_MESSAGE("New seat %s.", s->id),
- NULL);
+ LOG_MESSAGE("New seat %s.", s->id));
/* Initialize VT magic stuff */
#if 0 /// elogind does not support autospawning vts
@@ -451,8 +435,7 @@ int seat_stop(Seat *s, bool force) {
log_struct(LOG_INFO,
"MESSAGE_ID=" SD_MESSAGE_SEAT_STOP_STR,
"SEAT_ID=%s", s->id,
- LOG_MESSAGE("Removed seat %s.", s->id),
- NULL);
+ LOG_MESSAGE("Removed seat %s.", s->id));
seat_stop_sessions(s, force);
@@ -563,8 +546,7 @@ void seat_complete_switch(Seat *s) {
if (!s->pending_switch)
return;
- session = s->pending_switch;
- s->pending_switch = NULL;
+ session = TAKE_PTR(s->pending_switch);
seat_set_active(s, session);
}
@@ -642,16 +624,16 @@ int seat_get_idle_hint(Seat *s, dual_timestamp *t) {
return idle_hint;
}
-bool seat_check_gc(Seat *s, bool drop_not_started) {
+bool seat_may_gc(Seat *s, bool drop_not_started) {
assert(s);
if (drop_not_started && !s->started)
- return false;
+ return true;
if (seat_is_seat0(s))
- return true;
+ return false;
- return seat_has_master_device(s);
+ return !seat_has_master_device(s);
}
void seat_add_to_gc_queue(Seat *s) {
@@ -669,8 +651,7 @@ static bool seat_name_valid_char(char c) {
(c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9') ||
- c == '-' ||
- c == '_';
+ IN_SET(c, '-', '_');
}
bool seat_name_is_valid(const char *name) {
diff --git a/src/login/logind-seat.h b/src/login/logind-seat.h
index d7096a5e3..6d4506257 100644
--- a/src/login/logind-seat.h
+++ b/src/login/logind-seat.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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"
@@ -80,7 +62,7 @@ int seat_start(Seat *s);
int seat_stop(Seat *s, bool force);
int seat_stop_sessions(Seat *s, bool force);
-bool seat_check_gc(Seat *s, bool drop_not_started);
+bool seat_may_gc(Seat *s, bool drop_not_started);
void seat_add_to_gc_queue(Seat *s);
bool seat_name_is_valid(const char *name);
diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c
index 1316c5008..8a95fc7c7 100644
--- a/src/login/logind-session-dbus.c
+++ b/src/login/logind-session-dbus.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <string.h>
@@ -98,42 +81,8 @@ static int property_get_seat(
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, session_type, SessionType);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, session_class, SessionClass);
-
-static int property_get_active(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Session *s = userdata;
-
- assert(bus);
- assert(reply);
- assert(s);
-
- return sd_bus_message_append(reply, "b", session_is_active(s));
-}
-
-static int property_get_state(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Session *s = userdata;
-
- assert(bus);
- assert(reply);
- assert(s);
-
- return sd_bus_message_append(reply, "s", session_state_to_string(session_get_state(s)));
-}
+static BUS_DEFINE_PROPERTY_GET(property_get_active, "b", Session, session_is_active);
+static BUS_DEFINE_PROPERTY_GET2(property_get_state, "s", Session, session_get_state, session_state_to_string);
static int property_get_idle_hint(
sd_bus *bus,
@@ -457,7 +406,7 @@ static int method_take_device(sd_bus_message *message, void *userdata, sd_bus_er
goto error;
session_save(s);
- return 0;
+ return 1;
error:
session_device_free(sd);
@@ -580,23 +529,15 @@ int session_object_find(sd_bus *bus, const char *path, const char *interface, vo
assert(m);
if (streq(path, "/org/freedesktop/login1/session/self")) {
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
sd_bus_message *message;
- const char *name;
message = sd_bus_get_current_message(bus);
if (!message)
return 0;
- r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
+ r = manager_get_session_from_creds(m, message, NULL, error, &session);
if (r < 0)
return r;
-
- r = sd_bus_creds_get_session(creds, &name);
- if (r < 0)
- return r;
-
- session = hashmap_get(m->sessions, name);
} else {
_cleanup_free_ char *e = NULL;
const char *p;
@@ -610,11 +551,10 @@ int session_object_find(sd_bus *bus, const char *path, const char *interface, vo
return -ENOMEM;
session = hashmap_get(m->sessions, e);
+ if (!session)
+ return 0;
}
- if (!session)
- return 0;
-
*found = session;
return 1;
}
@@ -674,8 +614,7 @@ int session_node_enumerator(sd_bus *bus, const char *path, void *userdata, char
}
}
- *nodes = l;
- l = NULL;
+ *nodes = TAKE_PTR(l);
return 1;
}
diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c
index b46644894..50e20f961 100644
--- a/src/login/logind-session-device.c
+++ b/src/login/logind-session-device.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 David Herrmann
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <fcntl.h>
#include <linux/input.h>
@@ -34,6 +17,7 @@
#include "fd-util.h"
#include "logind-session-device.h"
#include "missing.h"
+#include "parse-util.h"
#include "sd-daemon.h"
#include "util.h"
@@ -76,20 +60,25 @@ static int session_device_notify(SessionDevice *sd, enum SessionDeviceNotificati
return r;
switch (type) {
+
case SESSION_DEVICE_RESUME:
r = sd_bus_message_append(m, "uuh", major, minor, sd->fd);
if (r < 0)
return r;
break;
+
case SESSION_DEVICE_TRY_PAUSE:
t = "pause";
break;
+
case SESSION_DEVICE_PAUSE:
t = "force";
break;
+
case SESSION_DEVICE_RELEASE:
t = "gone";
break;
+
default:
return -EINVAL;
}
@@ -103,43 +92,33 @@ static int session_device_notify(SessionDevice *sd, enum SessionDeviceNotificati
return sd_bus_send(sd->session->manager->bus, m, NULL);
}
-static int sd_eviocrevoke(int fd) {
- static bool warned;
- int r;
+static void sd_eviocrevoke(int fd) {
+ static bool warned = false;
assert(fd >= 0);
- r = ioctl(fd, EVIOCREVOKE, NULL);
- if (r < 0) {
- r = -errno;
- if (r == -EINVAL && !warned) {
+ if (ioctl(fd, EVIOCREVOKE, NULL) < 0) {
+
+ if (errno == EINVAL && !warned) {
+ log_warning_errno(errno, "Kernel does not support evdev-revocation: %m");
warned = true;
- log_warning("kernel does not support evdev-revocation");
}
}
-
- return 0;
}
static int sd_drmsetmaster(int fd) {
- int r;
-
assert(fd >= 0);
- r = ioctl(fd, DRM_IOCTL_SET_MASTER, 0);
- if (r < 0)
+ if (ioctl(fd, DRM_IOCTL_SET_MASTER, 0) < 0)
return -errno;
return 0;
}
static int sd_drmdropmaster(int fd) {
- int r;
-
assert(fd >= 0);
- r = ioctl(fd, DRM_IOCTL_DROP_MASTER, 0);
- if (r < 0)
+ if (ioctl(fd, DRM_IOCTL_DROP_MASTER, 0) < 0)
return -errno;
return 0;
@@ -148,7 +127,9 @@ static int sd_drmdropmaster(int fd) {
static int session_device_open(SessionDevice *sd, bool active) {
int fd, r;
+ assert(sd);
assert(sd->type != DEVICE_TYPE_UNKNOWN);
+ assert(sd->node);
/* open device and try to get an udev_device from it */
fd = open(sd->node, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
@@ -156,28 +137,27 @@ static int session_device_open(SessionDevice *sd, bool active) {
return -errno;
switch (sd->type) {
+
case DEVICE_TYPE_DRM:
if (active) {
- /* Weird legacy DRM semantics might return an error
- * even though we're master. No way to detect that so
- * fail at all times and let caller retry in inactive
- * state. */
+ /* Weird legacy DRM semantics might return an error even though we're master. No way to detect
+ * that so fail at all times and let caller retry in inactive state. */
r = sd_drmsetmaster(fd);
if (r < 0) {
close_nointr(fd);
return r;
}
- } else {
- /* DRM-Master is granted to the first user who opens a
- * device automatically (ughh, racy!). Hence, we just
- * drop DRM-Master in case we were the first. */
- sd_drmdropmaster(fd);
- }
+ } else
+ /* DRM-Master is granted to the first user who opens a device automatically (ughh,
+ * racy!). Hence, we just drop DRM-Master in case we were the first. */
+ (void) sd_drmdropmaster(fd);
break;
+
case DEVICE_TYPE_EVDEV:
if (!active)
sd_eviocrevoke(fd);
break;
+
case DEVICE_TYPE_UNKNOWN:
default:
/* fallback for devices wihout synchronizations */
@@ -197,29 +177,35 @@ static int session_device_start(SessionDevice *sd) {
return 0;
switch (sd->type) {
+
case DEVICE_TYPE_DRM:
- /* Device is kept open. Simply call drmSetMaster() and hope
- * there is no-one else. In case it fails, we keep the device
- * paused. Maybe at some point we have a drmStealMaster(). */
+ if (sd->fd < 0) {
+ log_error("Failed to re-activate DRM fd, as the fd was lost (maybe logind restart went wrong?)");
+ return -EBADF;
+ }
+
+ /* Device is kept open. Simply call drmSetMaster() and hope there is no-one else. In case it fails, we
+ * keep the device paused. Maybe at some point we have a drmStealMaster(). */
r = sd_drmsetmaster(sd->fd);
if (r < 0)
return r;
break;
+
case DEVICE_TYPE_EVDEV:
- /* Evdev devices are revoked while inactive. Reopen it and we
- * are fine. */
+ /* Evdev devices are revoked while inactive. Reopen it and we are fine. */
r = session_device_open(sd, true);
if (r < 0)
return r;
- /* For evdev devices, the file descriptor might be left
- * uninitialized. This might happen while resuming into a
- * session and logind has been restarted right before. */
+
+ /* For evdev devices, the file descriptor might be left uninitialized. This might happen while resuming
+ * into a session and logind has been restarted right before. */
safe_close(sd->fd);
sd->fd = r;
break;
+
case DEVICE_TYPE_UNKNOWN:
default:
- /* fallback for devices wihout synchronizations */
+ /* fallback for devices without synchronizations */
break;
}
@@ -234,13 +220,20 @@ static void session_device_stop(SessionDevice *sd) {
return;
switch (sd->type) {
+
case DEVICE_TYPE_DRM:
+ if (sd->fd < 0) {
+ log_error("Failed to de-activate DRM fd, as the fd was lost (maybe logind restart went wrong?)");
+ return;
+ }
+
/* On DRM devices we simply drop DRM-Master but keep it open.
* This allows the user to keep resources allocated. The
* CAP_SYS_ADMIN restriction to DRM-Master prevents users from
* circumventing this. */
sd_drmdropmaster(sd->fd);
break;
+
case DEVICE_TYPE_EVDEV:
/* Revoke access on evdev file-descriptors during deactivation.
* This will basically prevent any operations on the fd and
@@ -248,6 +241,7 @@ static void session_device_stop(SessionDevice *sd) {
* protection this way. */
sd_eviocrevoke(sd->fd);
break;
+
case DEVICE_TYPE_UNKNOWN:
default:
/* fallback for devices without synchronization */
@@ -373,10 +367,8 @@ int session_device_new(Session *s, dev_t dev, bool open_device, SessionDevice **
goto error;
r = hashmap_put(s->devices, &sd->dev, sd);
- if (r < 0) {
- r = -ENOMEM;
+ if (r < 0)
goto error;
- }
if (open_device) {
/* Open the device for the first time. We need a valid fd to pass back
@@ -412,9 +404,26 @@ error:
void session_device_free(SessionDevice *sd) {
assert(sd);
+ /* Make sure to remove the pushed fd. */
+ if (sd->pushed_fd) {
+ _cleanup_free_ char *m = NULL;
+ const char *id;
+ int r;
+
+ /* Session ID does not contain separators. */
+ id = sd->session->id;
+ assert(*(id + strcspn(id, "-\n")) == '\0');
+
+ r = asprintf(&m, "FDSTOREREMOVE=1\n"
+ "FDNAME=session-%s-device-%u-%u\n",
+ id, major(sd->dev), minor(sd->dev));
+ if (r >= 0)
+ (void) sd_notify(false, m);
+ }
+
session_device_stop(sd);
session_device_notify(sd, SESSION_DEVICE_RELEASE);
- close_nointr(sd->fd);
+ safe_close(sd->fd);
LIST_REMOVE(sd_by_device, sd->device->session_devices, sd);
@@ -449,13 +458,15 @@ void session_device_resume_all(Session *s) {
assert(s);
HASHMAP_FOREACH(sd, s->devices, i) {
- if (!sd->active) {
- if (session_device_start(sd) < 0)
- continue;
- if (session_device_save(sd) < 0)
- continue;
- session_device_notify(sd, SESSION_DEVICE_RESUME);
- }
+ if (sd->active)
+ continue;
+
+ if (session_device_start(sd) < 0)
+ continue;
+ if (session_device_save(sd) < 0)
+ continue;
+
+ session_device_notify(sd, SESSION_DEVICE_RESUME);
}
}
@@ -466,59 +477,74 @@ void session_device_pause_all(Session *s) {
assert(s);
HASHMAP_FOREACH(sd, s->devices, i) {
- if (sd->active) {
- session_device_stop(sd);
- session_device_notify(sd, SESSION_DEVICE_PAUSE);
- }
+ if (!sd->active)
+ continue;
+
+ session_device_stop(sd);
+ session_device_notify(sd, SESSION_DEVICE_PAUSE);
}
}
unsigned int session_device_try_pause_all(Session *s) {
+ unsigned num_pending = 0;
SessionDevice *sd;
Iterator i;
- unsigned int num_pending = 0;
assert(s);
HASHMAP_FOREACH(sd, s->devices, i) {
- if (sd->active) {
- session_device_notify(sd, SESSION_DEVICE_TRY_PAUSE);
- ++num_pending;
- }
+ if (!sd->active)
+ continue;
+
+ session_device_notify(sd, SESSION_DEVICE_TRY_PAUSE);
+ num_pending++;
}
return num_pending;
}
int session_device_save(SessionDevice *sd) {
- _cleanup_free_ char *state = NULL;
+ _cleanup_free_ char *m = NULL;
+ const char *id;
int r;
assert(sd);
- /* Store device fd in PID1. It will send it back to us on
- * restart so revocation will continue to work. To make things
- * simple, send fds for all type of devices even if they don't
- * support the revocation mechanism so we don't have to handle
- * them differently later.
+ /* Store device fd in PID1. It will send it back to us on restart so revocation will continue to work. To make
+ * things simple, send fds for all type of devices even if they don't support the revocation mechanism so we
+ * don't have to handle them differently later.
*
- * Note: for device supporting revocation, PID1 will drop a
- * stored fd automatically if the corresponding device is
- * revoked. */
- r = asprintf(&state, "FDSTORE=1\n"
- "FDNAME=session-%s", sd->session->id);
+ * Note: for device supporting revocation, PID1 will drop a stored fd automatically if the corresponding device
+ * is revoked. */
+
+ if (sd->pushed_fd)
+ return 0;
+
+ /* Session ID does not contain separators. */
+ id = sd->session->id;
+ assert(*(id + strcspn(id, "-\n")) == '\0');
+
+ r = asprintf(&m, "FDSTORE=1\n"
+ "FDNAME=session-%s-device-%u-%u\n",
+ id, major(sd->dev), minor(sd->dev));
if (r < 0)
- return -ENOMEM;
+ return r;
- return sd_pid_notify_with_fds(0, false, state, &sd->fd, 1);
+ r = sd_pid_notify_with_fds(0, false, m, &sd->fd, 1);
+ if (r < 0)
+ return r;
+
+ sd->pushed_fd = true;
+ return 1;
}
void session_device_attach_fd(SessionDevice *sd, int fd, bool active) {
- assert(fd > 0);
+ assert(fd >= 0);
assert(sd);
assert(sd->fd < 0);
assert(!sd->active);
sd->fd = fd;
+ sd->pushed_fd = true;
sd->active = active;
}
diff --git a/src/login/logind-session-device.h b/src/login/logind-session-device.h
index 83aef1e18..f42c0218c 100644
--- a/src/login/logind-session-device.h
+++ b/src/login/logind-session-device.h
@@ -1,23 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 David Herrmann
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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 enum DeviceType DeviceType;
typedef struct SessionDevice SessionDevice;
@@ -38,8 +21,9 @@ struct SessionDevice {
dev_t dev;
char *node;
int fd;
- bool active;
- DeviceType type;
+ DeviceType type:3;
+ bool active:1;
+ bool pushed_fd:1;
LIST_FIELDS(struct SessionDevice, sd_by_device);
};
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index 74807d3fd..e0daa4440 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <fcntl.h>
@@ -33,7 +16,6 @@
#include "bus-error.h"
#include "bus-util.h"
#include "escape.h"
-#include "extract-word.h"
#include "fd-util.h"
#include "fileio.h"
#include "format-util.h"
@@ -47,6 +29,10 @@
#include "user-util.h"
#include "util.h"
+/// Additional includes needed by elogind
+#include "extract-word.h"
+#include "process-util.h"
+
#define RELEASE_USEC (20*USEC_PER_SEC)
static void session_remove_fifo(Session *s);
@@ -83,6 +69,7 @@ Session* session_new(Manager *m, const char *id) {
s->manager = m;
s->fifo_fd = -1;
s->vtfd = -1;
+ s->audit_id = AUDIT_SESSION_INVALID;
return s;
}
@@ -180,7 +167,7 @@ int session_save(Session *s) {
if (!s->started)
return 0;
- r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
+ r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, MKDIR_WARN_MODE);
if (r < 0)
goto fail;
@@ -269,7 +256,6 @@ int session_save(Session *s) {
if (s->desktop) {
_cleanup_free_ char *escaped;
-
escaped = cescape(s->desktop);
if (!escaped) {
r = -ENOMEM;
@@ -285,10 +271,10 @@ int session_save(Session *s) {
if (!s->vtnr)
fprintf(f, "POSITION=%u\n", s->position);
- if (s->leader > 0)
+ if (pid_is_valid(s->leader))
fprintf(f, "LEADER="PID_FMT"\n", s->leader);
- if (s->audit_id > 0)
+ if (audit_session_is_valid(s->audit_id))
fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id);
if (dual_timestamp_is_set(&s->timestamp))
@@ -381,7 +367,7 @@ int session_load(Session *s) {
assert(s);
- r = parse_env_file(s->state_file, NEWLINE,
+ r = parse_env_file(NULL, s->state_file, NEWLINE,
"REMOTE", &remote,
"SCOPE", &s->scope,
#if 0 /// elogind does not support systemd scope_jobs
@@ -466,9 +452,8 @@ int session_load(Session *s) {
}
if (leader) {
- k = parse_pid(leader, &s->leader);
- if (k >= 0)
- audit_session_from_pid(s->leader, &s->audit_id);
+ if (parse_pid(leader, &s->leader) >= 0)
+ (void) audit_session_from_pid(s->leader, &s->audit_id);
}
if (type) {
@@ -564,7 +549,7 @@ int session_activate(Session *s) {
}
#if 0 /// UNNEEDED by elogind
-static int session_start_scope(Session *s) {
+static int session_start_scope(Session *s, sd_bus_message *properties) {
int r;
assert(s);
@@ -589,7 +574,7 @@ static int session_start_scope(Session *s) {
description,
"systemd-logind.service",
"systemd-user-sessions.service",
- (uint64_t) -1, /* disable TasksMax= for the scope, rely on the slice setting for it */
+ properties,
&error,
&job);
if (r < 0) {
@@ -630,7 +615,7 @@ static int session_start_cgroup(Session *s) {
}
#endif // 0
-int session_start(Session *s) {
+int session_start(Session *s, sd_bus_message *properties) {
int r;
assert(s);
@@ -647,7 +632,7 @@ int session_start(Session *s) {
/* Create cgroup */
#if 0 /// elogind does its own session management
- r = session_start_scope(s);
+ r = session_start_scope(s, properties);
#else
r = session_start_cgroup(s);
#endif // 0
@@ -659,8 +644,7 @@ int session_start(Session *s) {
"SESSION_ID=%s", s->id,
"USER_ID=%s", s->user->name,
"LEADER="PID_FMT, s->leader,
- LOG_MESSAGE("New session %s of user %s.", s->id, s->user->name),
- NULL);
+ LOG_MESSAGE("New session %s of user %s.", s->id, s->user->name));
if (!dual_timestamp_is_set(&s->timestamp))
dual_timestamp_get(&s->timestamp);
@@ -716,9 +700,19 @@ static int session_stop_scope(Session *s, bool force) {
free(s->scope_job);
s->scope_job = job;
- } else
+ } else {
s->scope_job = mfree(s->scope_job);
+ /* With no killing, this session is allowed to persist in "closing" state indefinitely.
+ * Therefore session stop and session removal may be two distinct events.
+ * Session stop is quite significant on its own, let's log it. */
+ log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
+ "SESSION_ID=%s", s->id,
+ "USER_ID=%s", s->user->name,
+ "LEADER="PID_FMT, s->leader,
+ LOG_MESSAGE("Session %s logged out. Waiting for processes to exit.", s->id));
+ }
+
return 0;
}
#else
@@ -728,7 +722,9 @@ static int session_stop_cgroup(Session *s, bool force) {
assert(s);
- if (force || manager_shall_kill(s->manager, s->user->name)) {
+ // elogind must not kill lingering user processes alive
+ if ( (force || manager_shall_kill(s->manager, s->user->name) )
+ && (user_check_linger_file(s->user) < 1) ) {
r = session_kill(s, KILL_ALL, SIGTERM);
if (r < 0)
return r;
@@ -788,8 +784,7 @@ int session_finalize(Session *s) {
"SESSION_ID=%s", s->id,
"USER_ID=%s", s->user->name,
"LEADER="PID_FMT, s->leader,
- LOG_MESSAGE("Removed session %s.", s->id),
- NULL);
+ LOG_MESSAGE("Removed session %s.", s->id));
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
@@ -1003,7 +998,7 @@ int session_create_fifo(Session *s) {
/* Create FIFO */
if (!s->fifo_path) {
- r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
+ r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, MKDIR_WARN_MODE);
if (r < 0)
return r;
@@ -1016,7 +1011,7 @@ int session_create_fifo(Session *s) {
/* Open reading side */
if (s->fifo_fd < 0) {
- s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NDELAY);
+ s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
if (s->fifo_fd < 0)
return -errno;
@@ -1035,7 +1030,7 @@ int session_create_fifo(Session *s) {
}
/* Open writing side */
- r = open(s->fifo_path, O_WRONLY|O_CLOEXEC|O_NDELAY);
+ r = open(s->fifo_path, O_WRONLY|O_CLOEXEC|O_NONBLOCK);
if (r < 0)
return -errno;
@@ -1054,29 +1049,29 @@ static void session_remove_fifo(Session *s) {
}
}
-bool session_check_gc(Session *s, bool drop_not_started) {
+bool session_may_gc(Session *s, bool drop_not_started) {
assert(s);
if (drop_not_started && !s->started)
- return false;
+ return true;
if (!s->user)
- return false;
+ return true;
if (s->fifo_fd >= 0) {
if (pipe_eof(s->fifo_fd) <= 0)
- return true;
+ return false;
}
#if 0 /// elogind supports neither scopes nor jobs
if (s->scope_job && manager_job_is_active(s->manager, s->scope_job))
- return true;
+ return false;
if (s->scope && manager_unit_is_active(s->manager, s->scope))
- return true;
#endif // 0
+ return false;
- return false;
+ return true;
}
void session_add_to_gc_queue(Session *s) {
@@ -1214,8 +1209,7 @@ void session_restore_vt(Session *s) {
.mode = VT_AUTO,
};
- _cleanup_free_ char *utf8 = NULL;
- int vt, kb, old_fd;
+ int vt, old_fd;
/* We need to get a fresh handle to the virtual terminal,
* since the old file-descriptor is potentially in a hung-up
@@ -1223,8 +1217,7 @@ void session_restore_vt(Session *s) {
* little dance to avoid having the terminal be available
* for reuse before we've cleaned it up.
*/
- old_fd = s->vtfd;
- s->vtfd = -1;
+ old_fd = TAKE_FD(s->vtfd);
vt = session_open_vt(s);
safe_close(old_fd);
@@ -1234,12 +1227,7 @@ void session_restore_vt(Session *s) {
(void) ioctl(vt, KDSETMODE, KD_TEXT);
- if (read_one_line_file("/sys/module/vt/parameters/default_utf8", &utf8) >= 0 && *utf8 == '1')
- kb = K_UNICODE;
- else
- kb = K_XLATE;
-
- (void) ioctl(vt, KDSKBMODE, kb);
+ (void) vt_reset_keyboard(vt);
(void) ioctl(vt, VT_SETMODE, &mode);
(void) fchown(vt, 0, (gid_t) -1);
@@ -1354,8 +1342,7 @@ int session_set_controller(Session *s, const char *sender, bool force, bool prep
}
session_release_controller(s, true);
- s->controller = name;
- name = NULL;
+ s->controller = TAKE_PTR(name);
session_save(s);
return 0;
diff --git a/src/login/logind-session.h b/src/login/logind-session.h
index 1e7f3ad49..117f4683b 100644
--- a/src/login/logind-session.h
+++ b/src/login/logind-session.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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;
typedef enum KillWho KillWho;
@@ -132,7 +114,7 @@ struct Session {
Session *session_new(Manager *m, const char *id);
void session_free(Session *s);
void session_set_user(Session *s, User *u);
-bool session_check_gc(Session *s, bool drop_not_started);
+bool session_may_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);
@@ -141,7 +123,7 @@ void session_set_idle_hint(Session *s, bool b);
int session_get_locked_hint(Session *s);
void session_set_locked_hint(Session *s, bool b);
int session_create_fifo(Session *s);
-int session_start(Session *s);
+int session_start(Session *s, sd_bus_message *properties);
int session_stop(Session *s, bool force);
int session_finalize(Session *s);
int session_release(Session *s);
diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c
index 987c63014..c662a26b9 100644
--- a/src/login/logind-user-dbus.c
+++ b/src/login/logind-user-dbus.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <string.h>
@@ -29,6 +12,8 @@
#include "strv.h"
#include "user-util.h"
+static BUS_DEFINE_PROPERTY_GET2(property_get_state, "s", User, user_get_state, user_state_to_string);
+
static int property_get_display(
sd_bus *bus,
const char *path,
@@ -52,24 +37,6 @@ static int property_get_display(
return sd_bus_message_append(reply, "(so)", u->display ? u->display->id : "", p);
}
-static int property_get_state(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- User *u = userdata;
-
- assert(bus);
- assert(reply);
- assert(u);
-
- return sd_bus_message_append(reply, "s", user_state_to_string(user_get_state(u)));
-}
-
static int property_get_sessions(
sd_bus *bus,
const char *path,
@@ -270,18 +237,15 @@ int user_object_find(sd_bus *bus, const char *path, const char *interface, void
assert(m);
if (streq(path, "/org/freedesktop/login1/user/self")) {
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
sd_bus_message *message;
message = sd_bus_get_current_message(bus);
if (!message)
return 0;
- r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
+ r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
if (r < 0)
return r;
-
- r = sd_bus_creds_get_owner_uid(creds, &uid);
} else {
const char *p;
@@ -290,13 +254,13 @@ int user_object_find(sd_bus *bus, const char *path, const char *interface, void
return 0;
r = parse_uid(p, &uid);
- }
- if (r < 0)
- return 0;
+ if (r < 0)
+ return 0;
- user = hashmap_get(m->users, UID_TO_PTR(uid));
- if (!user)
- return 0;
+ user = hashmap_get(m->users, UID_TO_PTR(uid));
+ if (!user)
+ return 0;
+ }
*found = user;
return 1;
@@ -356,8 +320,7 @@ int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***
}
}
- *nodes = l;
- l = NULL;
+ *nodes = TAKE_PTR(l);
return 1;
}
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index f904ad083..dcc405e50 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -1,58 +1,37 @@
-/***
- This file is part of systemd.
+/* SPDX-License-Identifier: LGPL-2.1+ */
- 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 <sys/mount.h>
-#include <unistd.h>
+//#include <errno.h>
+//#include <string.h>
+//#include <unistd.h>
+#include <stdio_ext.h>
#include "alloc-util.h"
-#include "bus-common-errors.h"
-#include "bus-error.h"
-#include "bus-util.h"
-#include "cgroup-util.h"
+//#include "bus-common-errors.h"
+//#include "bus-error.h"
+//#include "bus-util.h"
+//#include "cgroup-util.h"
#include "clean-ipc.h"
-#include "conf-parser.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
-#include "format-util.h"
-#include "fs-util.h"
-#include "hashmap.h"
-#include "label.h"
-#include "logind-user.h"
+//#include "format-util.h"
+//#include "fs-util.h"
+//#include "hashmap.h"
+//#include "label.h"
+//#include "logind-user.h"
#include "mkdir.h"
-#include "mount-util.h"
-#include "parse-util.h"
-#include "path-util.h"
-#include "rm-rf.h"
-#include "smack-util.h"
-//#include "special.h"
+//#include "parse-util.h"
+//#include "path-util.h"
+//#include "rm-rf.h"
+#include "special.h"
#include "stdio-util.h"
#include "string-table.h"
#include "unit-name.h"
#include "user-util.h"
-#include "util.h"
+//#include "util.h"
+/// Additional includes needed by elogind
+#include "user-runtime-dir.h"
-#if 1 /// elogind uses a static value here
-# define SPECIAL_USER_SLICE "user.slice"
-#endif // 1
int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name) {
_cleanup_(user_freep) User *u = NULL;
char lu[DECIMAL_STR_MAX(uid_t) + 1];
@@ -101,8 +80,8 @@ int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name) {
if (r < 0)
return r;
- *out = u;
- u = NULL;
+ *out = TAKE_PTR(u);
+
return 0;
}
@@ -146,7 +125,7 @@ static int user_save_internal(User *u) {
assert(u);
assert(u->state_file);
- r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0);
+ r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0, MKDIR_WARN_MODE);
if (r < 0)
goto fail;
@@ -154,7 +133,8 @@ static int user_save_internal(User *u) {
if (r < 0)
goto fail;
- fchmod(fileno(f), 0644);
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+ (void) fchmod(fileno(f), 0644);
fprintf(f,
"# This is private data. Do not parse.\n"
@@ -308,7 +288,7 @@ int user_load(User *u) {
assert(u);
- r = parse_env_file(u->state_file, NEWLINE,
+ r = parse_env_file(NULL, u->state_file, NEWLINE,
#if 0 /// elogind neither supports service nor slice jobs
"SERVICE_JOB", &u->service_job,
"SLICE_JOB", &u->slice_job,
@@ -338,94 +318,6 @@ int user_load(User *u) {
return r;
}
-static int user_mkdir_runtime_path(User *u) {
- int r;
-
- assert(u);
-
- r = mkdir_safe_label("/run/user", 0755, 0, 0);
- if (r < 0)
- return log_error_errno(r, "Failed to create /run/user: %m");
-
- if (path_is_mount_point(u->runtime_path, NULL, 0) <= 0) {
- _cleanup_free_ char *t = NULL;
-
- (void) mkdir_label(u->runtime_path, 0700);
-
- if (mac_smack_use())
- r = asprintf(&t, "mode=0700,smackfsroot=*,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size);
- else
- r = asprintf(&t, "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size);
- if (r < 0) {
- r = log_oom();
- goto fail;
- }
-
- r = mount("tmpfs", u->runtime_path, "tmpfs", MS_NODEV|MS_NOSUID, t);
- if (r < 0) {
- if (errno != EPERM && errno != EACCES) {
- r = log_error_errno(errno, "Failed to mount per-user tmpfs directory %s: %m", u->runtime_path);
- goto fail;
- }
-
- log_debug_errno(errno, "Failed to mount per-user tmpfs directory %s, assuming containerized execution, ignoring: %m", u->runtime_path);
-
- r = chmod_and_chown(u->runtime_path, 0700, u->uid, u->gid);
- if (r < 0) {
- log_error_errno(r, "Failed to change runtime directory ownership and mode: %m");
- goto fail;
- }
- }
-
- r = label_fix(u->runtime_path, false, false);
- if (r < 0)
- log_warning_errno(r, "Failed to fix label of '%s', ignoring: %m", u->runtime_path);
- }
-
- return 0;
-
-fail:
- /* Try to clean up, but ignore errors */
- (void) rmdir(u->runtime_path);
- return r;
-}
-
-static int user_start_slice(User *u) {
-#if 0 /// elogind can not ask systemd via dbus to start user services
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- const char *description;
- char *job;
- int r;
-
- assert(u);
-
- u->slice_job = mfree(u->slice_job);
- description = strjoina("User Slice of ", u->name);
-
- r = manager_start_slice(
- u->manager,
- u->slice,
- description,
- "systemd-logind.service",
- "systemd-user-sessions.service",
- u->manager->user_tasks_max,
- &error,
- &job);
- if (r >= 0)
- u->slice_job = job;
- else if (!sd_bus_error_has_name(&error, BUS_ERROR_UNIT_EXISTS))
- /* we don't fail due to this, let's try to continue */
- log_error_errno(r, "Failed to start user slice %s, ignoring: %s (%s)",
- u->slice, bus_error_message(&error, r), error.name);
-#else
- assert(u);
-
- hashmap_put(u->manager->user_units, u->slice, u);
-#endif // 0
-
- return 0;
-}
-
static int user_start_service(User *u) {
#if 0 /// elogind can not ask systemd via dbus to start user services
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
@@ -441,12 +333,11 @@ static int user_start_service(User *u) {
u->service,
&error,
&job);
- if (r < 0) {
+ if (r < 0)
/* we don't fail due to this, let's try to continue */
log_error_errno(r, "Failed to start user service, ignoring: %s", bus_error_message(&error, r));
- } else {
+ else
u->service_job = job;
- }
#else
assert(u);
@@ -479,19 +370,17 @@ int user_start(User *u) {
*/
u->stopping = false;
+#if 0 /// elogind has to prepare the XDG_RUNTIME_DIR by itself
+ if (!u->started)
+ log_debug("Starting services for new user %s.", u->name);
+#else
if (!u->started) {
- log_debug("New user %s logged in.", u->name);
-
- /* Make XDG_RUNTIME_DIR */
- r = user_mkdir_runtime_path(u);
+ log_debug("Starting services for new user %s.", u->name);
+ r = user_runtime_dir("start", u);
if (r < 0)
return r;
}
-
- /* Create cgroup */
- r = user_start_slice(u);
- if (r < 0)
- return r;
+#endif // 1
/* Save the user data so far, because pam_systemd will read the
* XDG_RUNTIME_DIR out of it while starting up systemd --user.
@@ -550,36 +439,11 @@ static int user_stop_service(User *u) {
return r;
}
- free(u->service_job);
- u->service_job = job;
-
+ free_and_replace(u->service_job, job);
return r;
}
#endif // 0
-static int user_remove_runtime_path(User *u) {
- int r;
-
- assert(u);
-
- r = rm_rf(u->runtime_path, 0);
- if (r < 0)
- log_error_errno(r, "Failed to remove runtime directory %s: %m", u->runtime_path);
-
- /* Ignore cases where the directory isn't mounted, as that's
- * quite possible, if we lacked the permissions to mount
- * something */
- r = umount2(u->runtime_path, MNT_DETACH);
- if (r < 0 && errno != EINVAL && errno != ENOENT)
- log_error_errno(errno, "Failed to unmount user runtime directory %s: %m", u->runtime_path);
-
- r = rm_rf(u->runtime_path, REMOVE_ROOT);
- if (r < 0)
- log_error_errno(r, "Failed to remove runtime directory %s: %m", u->runtime_path);
-
- return r;
-}
-
int user_stop(User *u, bool force) {
Session *s;
int r = 0, k;
@@ -588,6 +452,9 @@ int user_stop(User *u, bool force) {
/* Stop jobs have already been queued */
if (u->stopping) {
user_save(u);
+#if 1 /// elogind must queue this user again
+ user_add_to_gc_queue(u);
+#endif // 1
return r;
}
@@ -634,10 +501,12 @@ int user_finalize(User *u) {
r = k;
}
+#if 1 /// elogind has to remove the XDG_RUNTIME_DIR by itself
/* Kill XDG_RUNTIME_DIR */
- k = user_remove_runtime_path(u);
+ k = user_runtime_dir("stop", u);
if (k < 0)
r = k;
+#endif // 1
/* Clean SysV + POSIX IPC objects, but only if this is not a system user. Background: in many setups cronjobs
* are run in full PAM and thus logind sessions, even if the code run doesn't belong to actual users but to
@@ -645,7 +514,7 @@ int user_finalize(User *u) {
* cases, as we shouldn't accidentally remove a system service's IPC objects while it is running, just because
* a cronjob running as the same user just finished. Hence: exclude system users generally from IPC clean-up,
* and do it only for normal users. */
- if (u->manager->remove_ipc && u->uid > SYSTEM_UID_MAX) {
+ if (u->manager->remove_ipc && !uid_is_system(u->uid)) {
k = clean_ipc_by_uid(u->uid);
if (k < 0)
r = k;
@@ -706,32 +575,32 @@ int user_check_linger_file(User *u) {
if (!cc)
return -ENOMEM;
- p = strjoina("/var/lib/systemd/linger/", cc);
+ p = strjoina("/var/lib/elogind/linger/", cc);
return access(p, F_OK) >= 0;
}
-bool user_check_gc(User *u, bool drop_not_started) {
+bool user_may_gc(User *u, bool drop_not_started) {
assert(u);
if (drop_not_started && !u->started)
- return false;
+ return true;
if (u->sessions)
- return true;
+ return false;
if (user_check_linger_file(u) > 0)
- return true;
+ return false;
#if 0 /// elogind neither supports service nor slice jobs
if (u->slice_job && manager_job_is_active(u->manager, u->slice_job))
- return true;
+ return false;
if (u->service_job && manager_job_is_active(u->manager, u->service_job))
- return true;
+ return false;
#endif // 0
- return false;
+ return true;
}
void user_add_to_gc_queue(User *u) {
@@ -894,7 +763,7 @@ int config_parse_tmpfs_size(
void *data,
void *userdata) {
- size_t *sz = data;
+ uint64_t *sz = data;
int r;
assert(filename);
@@ -923,8 +792,8 @@ int config_parse_tmpfs_size(
return 0;
}
-int config_parse_user_tasks_max(
- const char* unit,
+int config_parse_compat_user_tasks_max(
+ const char *unit,
const char *filename,
unsigned line,
const char *section,
@@ -935,45 +804,17 @@ int config_parse_user_tasks_max(
void *data,
void *userdata) {
- uint64_t *m = data;
- uint64_t k;
- int r;
-
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
- if (isempty(rvalue)) {
- *m = system_tasks_max_scale(DEFAULT_USER_TASKS_MAX_PERCENTAGE, 100U);
- return 0;
- }
-
- if (streq(rvalue, "infinity")) {
- *m = CGROUP_LIMIT_MAX;
- return 0;
- }
-
- /* Try to parse as percentage */
- r = parse_percent(rvalue);
- if (r >= 0)
- k = system_tasks_max_scale(r, 100U);
- else {
-
- /* If the passed argument was not a percentage, or out of range, parse as byte size */
-
- r = safe_atou64(rvalue, &k);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse tasks maximum, ignoring: %s", rvalue);
- return 0;
- }
- }
-
- if (k <= 0 || k >= UINT64_MAX) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Tasks maximum out of range, ignoring: %s", rvalue);
- return 0;
- }
-
- *m = k;
+ log_syntax(unit, LOG_NOTICE, filename, line, 0,
+ "Support for option %s= has been removed.",
+ lvalue);
+ log_info("Hint: try creating /etc/elogind/system/user-.slice/50-limits.conf with:\n"
+ " [Slice]\n"
+ " TasksMax=%s",
+ rvalue);
return 0;
}
diff --git a/src/login/logind-user.h b/src/login/logind-user.h
index 043870b24..afb6f4b1a 100644
--- a/src/login/logind-user.h
+++ b/src/login/logind-user.h
@@ -1,26 +1,9 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 "conf-parser.h"
#include "list.h"
#include "logind.h"
@@ -67,7 +50,7 @@ User *user_free(User *u);
DEFINE_TRIVIAL_CLEANUP_FUNC(User *, user_free);
-bool user_check_gc(User *u, bool drop_not_started);
+bool user_may_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, bool force);
@@ -93,3 +76,5 @@ UserState user_state_from_string(const char *s) _pure_;
int bus_user_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_user_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error);
+
+CONFIG_PARSER_PROTOTYPE(config_parse_compat_user_tasks_max);
diff --git a/src/login/logind-utmp.c b/src/login/logind-utmp.c
index 4fe5ff014..f18147688 100644
--- a/src/login/logind-utmp.c
+++ b/src/login/logind-utmp.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2015 Daniel Mack
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <pwd.h>
@@ -31,6 +14,7 @@
#include "bus-util.h"
#include "format-util.h"
#include "logind.h"
+#include "path-util.h"
//#include "special.h"
#include "strv.h"
#include "unit-name.h"
@@ -60,15 +44,19 @@ _const_ static usec_t when_wall(usec_t n, usec_t elapse) {
}
bool logind_wall_tty_filter(const char *tty, void *userdata) {
-
Manager *m = userdata;
+ const char *p;
assert(m);
- if (!startswith(tty, "/dev/") || !m->scheduled_shutdown_tty)
+ if (!m->scheduled_shutdown_tty)
+ return true;
+
+ p = path_startswith(tty, "/dev/");
+ if (!p)
return true;
- return !streq(tty + 5, m->scheduled_shutdown_tty);
+ return !streq(p, m->scheduled_shutdown_tty);
}
static int warn_wall(Manager *m, usec_t n) {
diff --git a/src/login/logind.c b/src/login/logind.c
index 7452c5b82..db26701dd 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <fcntl.h>
@@ -32,12 +15,15 @@
#include "alloc-util.h"
#include "bus-error.h"
#include "bus-util.h"
-#include "conf-parser.h"
+//#include "cgroup-util.h"
#include "def.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "format-util.h"
+#include "fs-util.h"
#include "logind.h"
+#include "parse-util.h"
+//#include "process-util.h"
#include "selinux-util.h"
#include "signal-util.h"
#include "strv.h"
@@ -47,49 +33,21 @@
#include "elogind.h"
#include "label.h"
#include "musl_missing.h"
+#include "process-util.h"
+#include "cgroup-util.h"
-static void manager_free(Manager *m);
-
-static void manager_reset_config(Manager *m) {
-#if 0 /// elogind does not support autospawning of vts
- m->n_autovts = 6;
- m->reserve_vt = 6;
-#endif // 0
- m->remove_ipc = true;
- 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->handle_lid_switch_docked = HANDLE_IGNORE;
- m->power_key_ignore_inhibited = false;
- m->suspend_key_ignore_inhibited = false;
- m->hibernate_key_ignore_inhibited = false;
- m->lid_switch_ignore_inhibited = true;
-
- m->holdoff_timeout_usec = 30 * USEC_PER_SEC;
-
- m->idle_action_usec = 30 * USEC_PER_MINUTE;
- m->idle_action = HANDLE_IGNORE;
-
- m->runtime_dir_size = physical_memory_scale(10U, 100U); /* 10% */
- m->user_tasks_max = system_tasks_max_scale(DEFAULT_USER_TASKS_MAX_PERCENTAGE, 100U); /* 33% */
- m->sessions_max = 8192;
- m->inhibitors_max = 8192;
-
- m->kill_user_processes = KILL_USER_PROCESSES;
-
- m->kill_only_users = strv_free(m->kill_only_users);
- m->kill_exclude_users = strv_free(m->kill_exclude_users);
-}
+static Manager* manager_unref(Manager *m);
+DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref);
-static Manager *manager_new(void) {
- Manager *m;
+static int manager_new(Manager **ret) {
+ _cleanup_(manager_unrefp) Manager *m = NULL;
int r;
+ assert(ret);
+
m = new0(Manager, 1);
if (!m)
- return NULL;
+ return -ENOMEM;
m->console_active_fd = -1;
#if 0 /// UNNEEDED by elogind
@@ -109,33 +67,38 @@ static Manager *manager_new(void) {
m->session_units = hashmap_new(&string_hash_ops);
if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->user_units || !m->session_units)
- goto fail;
+ return -ENOMEM;
#if 1 /// elogind needs some more data
r = elogind_manager_new(m);
if (r < 0)
- goto fail;
+ return r;
#endif // 1
m->udev = udev_new();
if (!m->udev)
- goto fail;
+ return -errno;
r = sd_event_default(&m->event);
if (r < 0)
- goto fail;
+ return r;
- sd_event_set_watchdog(m->event, true);
+ r = sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
+ if (r < 0)
+ return r;
- manager_reset_config(m);
+ r = sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
+ if (r < 0)
+ return r;
+
+ (void) sd_event_set_watchdog(m->event, true);
- return m;
+ manager_reset_config(m);
-fail:
- manager_free(m);
- return NULL;
+ *ret = TAKE_PTR(m);
+ return 0;
}
-static void manager_free(Manager *m) {
+static Manager* manager_unref(Manager *m) {
Session *session;
User *u;
Device *d;
@@ -144,7 +107,7 @@ static void manager_free(Manager *m) {
Button *b;
if (!m)
- return;
+ return NULL;
while ((session = hashmap_first(m->sessions)))
session_free(session);
@@ -197,7 +160,7 @@ static void manager_free(Manager *m) {
udev_unref(m->udev);
if (m->unlink_nologin)
- (void) unlink("/run/nologin");
+ (void) unlink_or_warn("/run/nologin");
bus_verify_polkit_async_registry_free(m->polkit_registry);
@@ -220,12 +183,13 @@ static void manager_free(Manager *m) {
#if 0 /// UNNEEDED by elogind
free(m->action_job);
#endif // 0
- free(m);
+
+ return mfree(m);
}
static int manager_enumerate_devices(Manager *m) {
struct udev_list_entry *item = NULL, *first = NULL;
- _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
+ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
int r;
assert(m);
@@ -251,7 +215,7 @@ static int manager_enumerate_devices(Manager *m) {
first = udev_enumerate_get_list_entry(e);
udev_list_entry_foreach(item, first) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
int k;
d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
@@ -267,7 +231,7 @@ static int manager_enumerate_devices(Manager *m) {
}
static int manager_enumerate_buttons(Manager *m) {
- _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
+ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
struct udev_list_entry *item = NULL, *first = NULL;
int r;
@@ -275,11 +239,7 @@ static int manager_enumerate_buttons(Manager *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 &&
- m->handle_lid_switch_docked == HANDLE_IGNORE)
+ if (manager_all_buttons_ignored(m))
return 0;
e = udev_enumerate_new(m->udev);
@@ -304,7 +264,7 @@ static int manager_enumerate_buttons(Manager *m) {
first = udev_enumerate_get_list_entry(e);
udev_list_entry_foreach(item, first) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
int k;
d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
@@ -347,7 +307,9 @@ static int manager_enumerate_seats(Manager *m) {
s = hashmap_get(m->seats, de->d_name);
if (!s) {
- unlinkat(dirfd(d), de->d_name, 0);
+ if (unlinkat(dirfd(d), de->d_name, 0) < 0)
+ log_warning("Failed to remove /run/systemd/seats/%s: %m",
+ de->d_name);
continue;
}
@@ -366,12 +328,12 @@ static int manager_enumerate_linger_users(Manager *m) {
assert(m);
- d = opendir("/var/lib/systemd/linger");
+ d = opendir("/var/lib/elogind/linger");
if (!d) {
if (errno == ENOENT)
return 0;
- return log_error_errno(errno, "Failed to open /var/lib/systemd/linger/: %m");
+ return log_error_errno(errno, "Failed to open /var/lib/elogind/linger/: %m");
}
FOREACH_DIRENT(de, d, return -errno) {
@@ -433,6 +395,41 @@ static int manager_enumerate_users(Manager *m) {
return r;
}
+static int parse_fdname(const char *fdname, char **session_id, dev_t *dev) {
+ _cleanup_strv_free_ char **parts = NULL;
+ _cleanup_free_ char *id = NULL;
+ unsigned int major, minor;
+ int r;
+
+ parts = strv_split(fdname, "-");
+ if (!parts)
+ return -ENOMEM;
+ if (strv_length(parts) != 5)
+ return -EINVAL;
+
+ if (!streq(parts[0], "session"))
+ return -EINVAL;
+
+ id = strdup(parts[1]);
+ if (!id)
+ return -ENOMEM;
+
+ if (!streq(parts[2], "device"))
+ return -EINVAL;
+
+ r = safe_atou(parts[3], &major);
+ if (r < 0)
+ return r;
+ r = safe_atou(parts[4], &minor);
+ if (r < 0)
+ return r;
+
+ *dev = makedev(major, minor);
+ *session_id = TAKE_PTR(id);
+
+ return 0;
+}
+
static int manager_attach_fds(Manager *m) {
_cleanup_strv_free_ char **fdnames = NULL;
int n, i, fd;
@@ -446,16 +443,21 @@ static int manager_attach_fds(Manager *m) {
return n;
for (i = 0; i < n; i++) {
+ _cleanup_free_ char *id = NULL;
+ dev_t dev;
struct stat st;
SessionDevice *sd;
Session *s;
- char *id;
+ int r;
fd = SD_LISTEN_FDS_START + i;
- id = startswith(fdnames[i], "session-");
- if (!id)
+ r = parse_fdname(fdnames[i], &id, &dev);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to parse fd name %s: %m", fdnames[i]);
+ close_nointr(fd);
continue;
+ }
s = hashmap_get(m->sessions, id);
if (!s) {
@@ -475,18 +477,24 @@ static int manager_attach_fds(Manager *m) {
continue;
}
- sd = hashmap_get(s->devices, &st.st_rdev);
+ if (!S_ISCHR(st.st_mode) || st.st_rdev != dev) {
+ log_debug("Device fd doesn't point to the expected character device node");
+ close_nointr(fd);
+ continue;
+ }
+
+ sd = hashmap_get(s->devices, &dev);
if (!sd) {
- /* Weird we got an fd for a session device which wasn't
- * recorded in the session state file... */
+ /* Weird, we got an fd for a session device which wasn't
+ * recorded in the session state file... */
log_warning("Got fd for missing session device [%u:%u] in session %s",
- major(st.st_rdev), minor(st.st_rdev), s->id);
+ major(dev), minor(dev), s->id);
close_nointr(fd);
continue;
}
log_debug("Attaching fd to session device [%u:%u] for session %s",
- major(st.st_rdev), minor(st.st_rdev), s->id);
+ major(dev), minor(dev), s->id);
session_device_attach_fd(sd, fd, s->was_active);
}
@@ -583,7 +591,7 @@ static int manager_enumerate_inhibitors(Manager *m) {
}
static int manager_dispatch_seat_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
Manager *m = userdata;
assert(m);
@@ -597,7 +605,7 @@ static int manager_dispatch_seat_udev(sd_event_source *s, int fd, uint32_t reven
}
static int manager_dispatch_device_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
Manager *m = userdata;
assert(m);
@@ -612,7 +620,7 @@ static int manager_dispatch_device_udev(sd_event_source *s, int fd, uint32_t rev
#if 0 /// UNNEEDED by elogind
static int manager_dispatch_vcsa_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
Manager *m = userdata;
const char *name;
@@ -635,7 +643,7 @@ static int manager_dispatch_vcsa_udev(sd_event_source *s, int fd, uint32_t reven
#endif // 0
static int manager_dispatch_button_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
Manager *m = userdata;
assert(m);
@@ -685,7 +693,6 @@ static int manager_reserve_vt(Manager *m) {
#endif // 0
static int manager_connect_bus(Manager *m) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(m);
@@ -724,66 +731,66 @@ static int manager_connect_bus(Manager *m) {
return log_error_errno(r, "Failed to add user enumerator: %m");
#if 0 /// elogind does not support systemd as PID 1
- r = sd_bus_add_match(m->bus,
- NULL,
- "type='signal',"
- "sender='org.freedesktop.systemd1',"
- "interface='org.freedesktop.systemd1.Manager',"
- "member='JobRemoved',"
- "path='/org/freedesktop/systemd1'",
- match_job_removed, m);
+ r = sd_bus_match_signal_async(
+ m->bus,
+ NULL,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "JobRemoved",
+ match_job_removed, NULL, m);
if (r < 0)
- return log_error_errno(r, "Failed to add match for JobRemoved: %m");
-
- r = sd_bus_add_match(m->bus,
- NULL,
- "type='signal',"
- "sender='org.freedesktop.systemd1',"
- "interface='org.freedesktop.systemd1.Manager',"
- "member='UnitRemoved',"
- "path='/org/freedesktop/systemd1'",
- match_unit_removed, m);
+ return log_error_errno(r, "Failed to request match for JobRemoved: %m");
+
+ r = sd_bus_match_signal_async(
+ m->bus,
+ NULL,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "UnitRemoved",
+ match_unit_removed, NULL, m);
if (r < 0)
- return log_error_errno(r, "Failed to add match for UnitRemoved: %m");
-
- r = sd_bus_add_match(m->bus,
- NULL,
- "type='signal',"
- "sender='org.freedesktop.systemd1',"
- "interface='org.freedesktop.DBus.Properties',"
- "member='PropertiesChanged'",
- match_properties_changed, m);
+ return log_error_errno(r, "Failed to request match for UnitRemoved: %m");
+
+ r = sd_bus_match_signal_async(
+ m->bus,
+ NULL,
+ "org.freedesktop.systemd1",
+ NULL,
+ "org.freedesktop.DBus.Properties",
+ "PropertiesChanged",
+ match_properties_changed, NULL, m);
if (r < 0)
- return log_error_errno(r, "Failed to add match for PropertiesChanged: %m");
-
- r = sd_bus_add_match(m->bus,
- NULL,
- "type='signal',"
- "sender='org.freedesktop.systemd1',"
- "interface='org.freedesktop.systemd1.Manager',"
- "member='Reloading',"
- "path='/org/freedesktop/systemd1'",
- match_reloading, m);
+ return log_error_errno(r, "Failed to request match for PropertiesChanged: %m");
+
+ r = sd_bus_match_signal_async(
+ m->bus,
+ NULL,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "Reloading",
+ match_reloading, NULL, m);
if (r < 0)
- return log_error_errno(r, "Failed to add match for Reloading: %m");
+ return log_error_errno(r, "Failed to request match for Reloading: %m");
- r = sd_bus_call_method(
+ r = sd_bus_call_method_async(
m->bus,
+ NULL,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"Subscribe",
- &error,
- NULL, NULL);
- if (r < 0) {
- log_error("Failed to enable subscription: %s", bus_error_message(&error, r));
- return r;
- }
+ NULL, NULL,
+ NULL);
#endif // 0
+ if (r < 0)
+ return log_error_errno(r, "Failed to enable subscription: %m");
- r = sd_bus_request_name(m->bus, "org.freedesktop.login1", 0);
+ r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.login1", 0, NULL, NULL);
if (r < 0)
- return log_error_errno(r, "Failed to register name: %m");
+ return log_error_errno(r, "Failed to request name: %m");
r = sd_bus_attach_event(m->bus, m->event, SD_EVENT_PRIORITY_NORMAL);
if (r < 0)
@@ -940,12 +947,7 @@ static int manager_connect_udev(Manager *m) {
return r;
/* 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->handle_lid_switch_docked != HANDLE_IGNORE) {
-
+ if (!manager_all_buttons_ignored(m)) {
m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
if (!m->udev_button_monitor)
return -ENOMEM;
@@ -1003,7 +1005,7 @@ static void manager_gc(Manager *m, bool drop_not_started) {
LIST_REMOVE(gc_queue, m->seat_gc_queue, seat);
seat->in_gc_queue = false;
- if (!seat_check_gc(seat, drop_not_started)) {
+ if (seat_may_gc(seat, drop_not_started)) {
seat_stop(seat, false);
seat_free(seat);
}
@@ -1014,14 +1016,14 @@ static void manager_gc(Manager *m, bool drop_not_started) {
session->in_gc_queue = false;
/* First, if we are not closing yet, initiate stopping */
- if (!session_check_gc(session, drop_not_started) &&
+ if (session_may_gc(session, drop_not_started) &&
session_get_state(session) != SESSION_CLOSING)
session_stop(session, false);
/* Normally, this should make the session referenced
* again, if it doesn't then let's get rid of it
* immediately */
- if (!session_check_gc(session, drop_not_started)) {
+ if (session_may_gc(session, drop_not_started)) {
session_finalize(session);
session_free(session);
}
@@ -1032,11 +1034,11 @@ static void manager_gc(Manager *m, bool drop_not_started) {
user->in_gc_queue = false;
/* First step: queue stop jobs */
- if (!user_check_gc(user, drop_not_started))
+ if (user_may_gc(user, drop_not_started))
user_stop(user, false);
/* Second step: finalize user */
- if (!user_check_gc(user, drop_not_started)) {
+ if (user_may_gc(user, drop_not_started)) {
user_finalize(user);
user_free(user);
}
@@ -1103,29 +1105,6 @@ static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *us
return 0;
}
-static int manager_parse_config_file(Manager *m) {
-#if 0 /// elogind parses its own config file
- assert(m);
-
- return config_parse_many_nulstr(PKGSYSCONFDIR "/logind.conf",
- CONF_PATHS_NULSTR("systemd/logind.conf.d"),
- "Login\0",
- config_item_perf_lookup, logind_gperf_lookup,
- false, m);
-#else
- const char* logind_conf = getenv("ELOGIND_CONF_FILE");
-
- assert(m);
-
- if (!logind_conf)
- logind_conf = PKGSYSCONFDIR "/logind.conf";
-
- return config_parse(NULL, logind_conf, NULL, "Login\0Sleep\0",
- config_item_perf_lookup, logind_gperf_lookup,
- false, false, true, m);
-#endif // 0
-}
-
static int manager_dispatch_reload_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
Manager *m = userdata;
int r;
@@ -1140,7 +1119,6 @@ static int manager_dispatch_reload_signal(sd_event_source *s, const struct signa
#if 1 /// elogind needs an Add-On for sleep configuration
elogind_manager_reset_config(m);
#endif // 1
-
return 0;
}
@@ -1155,8 +1133,6 @@ static int manager_startup(Manager *m) {
assert(m);
- assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGHUP, -1) >= 0);
-
r = sd_event_add_signal(m->event, NULL, SIGHUP, manager_dispatch_reload_signal, m);
if (r < 0)
return log_error_errno(r, "Failed to register SIGHUP handler: %m");
@@ -1164,7 +1140,6 @@ static int manager_startup(Manager *m) {
#if 1 /// elogind needs some extra preparations before connecting...
elogind_manager_startup(m);
#endif // 1
-
/* Connect to console */
r = manager_connect_console(m);
if (r < 0)
@@ -1230,7 +1205,7 @@ static int manager_startup(Manager *m) {
user_start(user);
HASHMAP_FOREACH(session, m->sessions, i)
- session_start(session);
+ session_start(session, NULL);
HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
inhibitor_start(inhibitor);
@@ -1270,20 +1245,19 @@ static int manager_run(Manager *m) {
}
int main(int argc, char *argv[]) {
- Manager *m = NULL;
+ _cleanup_(manager_unrefp) Manager *m = NULL;
int r;
#if 1 /// perform extra checks for elogind startup
r = elogind_startup(argc, argv);
if (r)
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-#endif // 0
-
+#endif // 1
elogind_set_program_name(argv[0]);
log_set_target(LOG_TARGET_AUTO);
log_set_facility(LOG_AUTH);
log_parse_environment();
-#ifdef ENABLE_DEBUG_ELOGIND
+#if ENABLE_DEBUG_ELOGIND
log_set_max_level(LOG_DEBUG);
log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
#endif // ENABLE_DEBUG_ELOGIND
@@ -1305,15 +1279,16 @@ int main(int argc, char *argv[]) {
goto finish;
}
- /* Always create the directories people can create inotify
- * watches in. Note that some applications might check for the
- * existence of /run/systemd/seats/ to determine whether
- * logind is available, so please always make sure this check
- * stays in. */
#if 0 /// elogind can not rely on systemd to help, so we need a bit more effort than this
mkdir_label("/run/systemd/seats", 0755);
mkdir_label("/run/systemd/users", 0755);
mkdir_label("/run/systemd/sessions", 0755);
+ /* Always create the directories people can create inotify watches in. Note that some applications might check
+ * for the existence of /run/systemd/seats/ to determine whether logind is available, so please always make
+ * sure these directories are created early on and unconditionally. */
+ (void) mkdir_label("/run/systemd/seats", 0755);
+ (void) mkdir_label("/run/systemd/users", 0755);
+ (void) mkdir_label("/run/systemd/sessions", 0755);
#else
r = mkdir_label("/run/systemd", 0755);
if ( (r < 0) && (-EEXIST != r) )
@@ -1332,40 +1307,39 @@ int main(int argc, char *argv[]) {
return log_error_errno(r, "Failed to create /run/systemd/machines : %m");
#endif // 0
- m = manager_new();
- if (!m) {
- r = log_oom();
+ assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGHUP, SIGTERM, SIGINT, -1) >= 0);
+
+ r = manager_new(&m);
+ if (r < 0) {
+ log_error_errno(r, "Failed to allocate manager object: %m");
goto finish;
}
- manager_parse_config_file(m);
+ (void) manager_parse_config_file(m);
#if 1 /// elogind needs an Add-On for sleep configuration
elogind_manager_reset_config(m);
#endif // 1
-
r = manager_startup(m);
if (r < 0) {
log_error_errno(r, "Failed to fully start up daemon: %m");
goto finish;
}
- log_debug("elogind running as pid "PID_FMT, getpid());
+ log_debug("elogind running as pid "PID_FMT, getpid_cached());
- sd_notify(false,
- "READY=1\n"
- "STATUS=Processing requests...");
+ (void) sd_notify(false,
+ "READY=1\n"
+ "STATUS=Processing requests...");
r = manager_run(m);
- log_debug("elogind stopped as pid "PID_FMT, getpid());
+ log_debug("elogind stopped as pid "PID_FMT, getpid_cached());
-finish:
- sd_notify(false,
- "STOPPING=1\n"
- "STATUS=Shutting down...");
-
- manager_free(m);
+ (void) sd_notify(false,
+ "STOPPING=1\n"
+ "STATUS=Shutting down...");
+finish:
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/login/logind.conf.in b/src/login/logind.conf.in
index 27b05fe8a..6da3f164d 100644
--- a/src/login/logind.conf.in
+++ b/src/login/logind.conf.in
@@ -12,6 +12,8 @@
# See logind.conf(5) for details.
[Login]
+#NAutoVTs=6
+#ReserveVT=6
#KillUserProcesses=@KILL_USER_PROCESSES@
#KillOnlyUsers=
#KillExcludeUsers=root
@@ -20,6 +22,7 @@
#HandleSuspendKey=suspend
#HandleHibernateKey=hibernate
#HandleLidSwitch=suspend
+#HandleLidSwitchExternalPower=suspend
#HandleLidSwitchDocked=ignore
#PowerKeyIgnoreInhibited=no
#SuspendKeyIgnoreInhibited=no
@@ -32,7 +35,6 @@
#RemoveIPC=yes
#InhibitorsMax=8192
#SessionsMax=8192
-#UserTasksMax=33%
[Sleep]
#SuspendState=mem standby freeze
@@ -41,3 +43,4 @@
#HibernateMode=platform shutdown
#HybridSleepState=disk
#HybridSleepMode=suspend platform shutdown
+#HibernateDelaySec=10800
diff --git a/src/login/logind.h b/src/login/logind.h
index 8f6fb72db..3f17d5d6d 100644
--- a/src/login/logind.h
+++ b/src/login/logind.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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>
#if 0 /// elogind needs the systems udev header
@@ -29,6 +11,7 @@
#include "sd-bus.h"
#include "sd-event.h"
+//#include "conf-parser.h"
#include "hashmap.h"
#include "list.h"
#include "set.h"
@@ -88,7 +71,7 @@ struct Manager {
sd_event_source *cgroups_agent_event_source;
/* Flags */
- bool test_run:1;
+ unsigned test_run_flags;
bool is_system:1; /* true if elogind is its own cgroups manager */
/* Data specific to the cgroup subsystem */
@@ -133,7 +116,7 @@ struct Manager {
char **suspend_state, **suspend_mode;
char **hibernate_state, **hibernate_mode;
char **hybrid_sleep_state, **hybrid_sleep_mode;
-
+ usec_t hibernate_delay_sec;
#endif // 0
sd_event_source *inhibit_timeout_source;
@@ -160,6 +143,7 @@ struct Manager {
HandleAction handle_suspend_key;
HandleAction handle_hibernate_key;
HandleAction handle_lid_switch;
+ HandleAction handle_lid_switch_ep;
HandleAction handle_lid_switch_docked;
bool power_key_ignore_inhibited;
@@ -174,12 +158,15 @@ struct Manager {
usec_t holdoff_timeout_usec;
sd_event_source *lid_switch_ignore_event_source;
- size_t runtime_dir_size;
+ uint64_t runtime_dir_size;
uint64_t user_tasks_max;
uint64_t sessions_max;
uint64_t inhibitors_max;
};
+void manager_reset_config(Manager *m);
+int manager_parse_config_file(Manager *m);
+
int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device);
int manager_add_button(Manager *m, const char *name, Button **_button);
int manager_add_seat(Manager *m, const char *id, Seat **_seat);
@@ -204,6 +191,8 @@ int manager_get_user_by_pid(Manager *m, pid_t pid, User **user);
int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session);
bool manager_is_docked_or_external_displays(Manager *m);
+bool manager_is_on_external_power(void);
+bool manager_all_buttons_ignored(Manager *m);
extern const sd_bus_vtable manager_vtable[];
@@ -223,8 +212,7 @@ int bus_manager_shutdown_or_sleep_now_or_later(Manager *m, HandleAction action,
int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_;
#if 0 /// UNNEEDED by elogind
-int manager_start_slice(Manager *manager, const char *slice, const char *description, const char *after, const char *after2, uint64_t tasks_max, sd_bus_error *error, char **job);
-int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, uint64_t tasks_max, sd_bus_error *error, char **job);
+int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, sd_bus_message *more_properties, sd_bus_error *error, char **job);
int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error);
@@ -238,8 +226,8 @@ const struct ConfigPerfItem* logind_gperf_lookup(const char *key, GPERF_LEN_TYPE
int manager_set_lid_switch_ignore(Manager *m, usec_t until);
-int config_parse_tmpfs_size(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_user_tasks_max(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_n_autovts);
+CONFIG_PARSER_PROTOTYPE(config_parse_tmpfs_size);
int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret);
int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret);
diff --git a/src/login/meson.build b/src/login/meson.build
new file mode 100644
index 000000000..0eac0d3cc
--- /dev/null
+++ b/src/login/meson.build
@@ -0,0 +1,169 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#if 0 /// rename to elogind
+#
+# systemd_logind_sources = files('''
+# logind.c
+# logind.h
+# '''.split())
+#else
+elogind_sources = files('''
+ elogind.c
+ elogind.h
+ logind.c
+ logind.h
+'''.split())
+#endif // 0
+
+logind_gperf_c = custom_target(
+ 'logind_gperf.c',
+ input : 'logind-gperf.gperf',
+ output : 'logind-gperf.c',
+ command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@'])
+
+liblogind_core_sources = files('''
+ logind-core.c
+ logind-device.c
+ logind-device.h
+ logind-button.c
+ logind-button.h
+ logind-action.c
+ logind-action.h
+ logind-seat.c
+ logind-seat.h
+ logind-session.c
+ logind-session.h
+ logind-session-device.c
+ logind-session-device.h
+ logind-user.c
+ logind-user.h
+ logind-inhibit.c
+ logind-inhibit.h
+ logind-dbus.c
+ logind-session-dbus.c
+ logind-seat-dbus.c
+ logind-user-dbus.c
+ logind-utmp.c
+ logind-acl.h
+'''.split())
+
+#if 1 /// elogind has some additional files:
+liblogind_core_sources += [files('''
+ elogind-dbus.c
+ elogind-dbus.h
+ user-runtime-dir.c
+'''.split()),
+ libcore_la_sources,
+ sleep_files,
+ update_utmp_files]
+#endif // 1
+liblogind_core_sources += [logind_gperf_c]
+
+logind_acl_c = files('logind-acl.c')
+if conf.get('HAVE_ACL') == 1
+ liblogind_core_sources += logind_acl_c
+endif
+
+liblogind_core = static_library(
+ 'logind-core',
+ liblogind_core_sources,
+ include_directories : includes,
+#if 0 /// elogind needs audit support for utmp inclusion
+# dependencies : [libacl])
+#else
+ dependencies : [libacl,
+ libaudit])
+#endif // 0
+
+loginctl_sources = files('''
+ loginctl.c
+ sysfs-show.h
+ sysfs-show.c
+'''.split())
+
+#if 0 /// UNNEEDED by elogind
+# user_runtime_dir_sources = files('''
+# user-runtime-dir.c
+# logind.h
+# '''.split())
+#endif // 0
+
+#if 1 /// elogind has and needs some additional files:
+loginctl_sources += files('''
+ eloginctl.c
+ eloginctl.h
+'''.split())
+#endif // 1
+
+#if 0 /// elogind builds itself unconditionally
+# if conf.get('ENABLE_LOGIND') == 1
+#endif // 0
+ logind_conf = configure_file(
+ input : 'logind.conf.in',
+ output : 'logind.conf',
+ configuration : substs)
+ install_data(logind_conf,
+ install_dir : pkgsysconfdir)
+
+ pam_elogind_sym = 'src/login/pam_elogind.sym'
+ pam_elogind_c = files('pam_elogind.c')
+
+ install_data('org.freedesktop.login1.conf',
+ install_dir : dbuspolicydir)
+#if 0 /// Works a bit differently here, as elogind allows dbus activation.
+# install_data('org.freedesktop.login1.service',
+# install_dir : dbussystemservicedir)
+#else
+ logind_service = configure_file(
+ input : 'org.freedesktop.login1.service.in',
+ output : 'org.freedesktop.login1.service',
+ configuration : substs)
+ install_data(logind_service,
+ install_dir : dbussystemservicedir)
+#endif // 0
+ install_data('org.freedesktop.login1.policy',
+ install_dir : polkitpolicydir)
+
+ install_data('70-power-switch.rules', install_dir : udevrulesdir)
+
+ if conf.get('HAVE_ACL') == 1
+ install_data('70-uaccess.rules', install_dir : udevrulesdir)
+ endif
+
+ seat_rules = configure_file(
+ input : '71-seat.rules.in',
+ output : '71-seat.rules',
+ configuration : substs)
+ install_data(seat_rules,
+ install_dir : udevrulesdir)
+
+#if 1 /// elogind needs two passes of this file
+ seat_late_rules = configure_file(
+ input : '73-seat-late.rules.in',
+ output : '73-seat-late.rules.m4',
+ configuration : substs)
+#endif // 1
+
+ custom_target(
+ '73-seat-late.rules',
+#if 0 /// elogind must configure the source
+# input : '73-seat-late.rules.m4',
+#else
+ input : seat_late_rules,
+#endif // 0
+ output: '73-seat-late.rules',
+ command : [meson_apply_m4, config_h, '@INPUT@'],
+ capture : true,
+ install : true,
+ install_dir : udevrulesdir)
+
+ custom_target(
+ 'elogind-user',
+ input : 'elogind-user.m4',
+ output: 'elogind-user',
+ command : [meson_apply_m4, config_h, '@INPUT@'],
+ capture : true,
+ install : pamconfdir != 'no',
+ install_dir : pamconfdir)
+#if 0 /// elogind builds itself unconditionally
+# endif
+#endif //0
diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf
index b11ab764c..1f81604b5 100644
--- a/src/login/org.freedesktop.login1.conf
+++ b/src/login/org.freedesktop.login1.conf
@@ -4,8 +4,10 @@
<!--
This file is part of elogind.
+ SPDX-License-Identifier: LGPL-2.1+
elogind is free software; you can redistribute it and/or modify it
+
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
@@ -134,6 +136,10 @@
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
+ send_member="Halt"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
send_member="Suspend"/>
<allow send_destination="org.freedesktop.login1"
@@ -146,6 +152,10 @@
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
+ send_member="SuspendThenHibernate"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
send_member="CanPowerOff"/>
<allow send_destination="org.freedesktop.login1"
@@ -154,6 +164,10 @@
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
+ send_member="CanHalt"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
send_member="CanSuspend"/>
<allow send_destination="org.freedesktop.login1"
@@ -166,6 +180,10 @@
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
+ send_member="CanSuspendThenHibernate"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
send_member="ScheduleShutdown"/>
<allow send_destination="org.freedesktop.login1"
diff --git a/src/login/org.freedesktop.login1.policy.in b/src/login/org.freedesktop.login1.policy
index caaf1daf2..f1d1f956d 100644
--- a/src/login/org.freedesktop.login1.policy.in
+++ b/src/login/org.freedesktop.login1.policy
@@ -3,9 +3,11 @@
"http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
<!--
- This file is part of elogind.
+ SPDX-License-Identifier: LGPL-2.1+
- elogind is free software; you can redistribute it and/or modify it
+ 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.
@@ -13,12 +15,12 @@
<policyconfig>
- <vendor>The elogind Project</vendor>
- <vendor_url>https://github.com/elogind/elogind</vendor_url>
+ <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 for an application to inhibit system shutdown.</_message>
+ <description gettext-domain="systemd">Allow applications to inhibit system shutdown</description>
+ <message gettext-domain="systemd">Authentication is required for an application to inhibit system shutdown.</message>
<defaults>
<allow_any>no</allow_any>
<allow_inactive>yes</allow_inactive>
@@ -28,8 +30,8 @@
</action>
<action id="org.freedesktop.login1.inhibit-delay-shutdown">
- <_description>Allow applications to delay system shutdown</_description>
- <_message>Authentication is required for an application to delay system shutdown.</_message>
+ <description gettext-domain="systemd">Allow applications to delay system shutdown</description>
+ <message gettext-domain="systemd">Authentication is required for an application to delay system shutdown.</message>
<defaults>
<allow_any>yes</allow_any>
<allow_inactive>yes</allow_inactive>
@@ -39,8 +41,8 @@
</action>
<action id="org.freedesktop.login1.inhibit-block-sleep">
- <_description>Allow applications to inhibit system sleep</_description>
- <_message>Authentication is required for an application to inhibit system sleep.</_message>
+ <description gettext-domain="systemd">Allow applications to inhibit system sleep</description>
+ <message gettext-domain="systemd">Authentication is required for an application to inhibit system sleep.</message>
<defaults>
<allow_any>no</allow_any>
<allow_inactive>yes</allow_inactive>
@@ -50,8 +52,8 @@
</action>
<action id="org.freedesktop.login1.inhibit-delay-sleep">
- <_description>Allow applications to delay system sleep</_description>
- <_message>Authentication is required for an application to delay system sleep.</_message>
+ <description gettext-domain="systemd">Allow applications to delay system sleep</description>
+ <message gettext-domain="systemd">Authentication is required for an application to delay system sleep.</message>
<defaults>
<allow_any>yes</allow_any>
<allow_inactive>yes</allow_inactive>
@@ -60,8 +62,8 @@
</action>
<action id="org.freedesktop.login1.inhibit-block-idle">
- <_description>Allow applications to inhibit automatic system suspend</_description>
- <_message>Authentication is required for an application to inhibit automatic system suspend.</_message>
+ <description gettext-domain="systemd">Allow applications to inhibit automatic system suspend</description>
+ <message gettext-domain="systemd">Authentication is required for an application to inhibit automatic system suspend.</message>
<defaults>
<allow_any>yes</allow_any>
<allow_inactive>yes</allow_inactive>
@@ -70,8 +72,8 @@
</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 for an application to inhibit system handling of the power key.</_message>
+ <description gettext-domain="systemd">Allow applications to inhibit system handling of the power key</description>
+ <message gettext-domain="systemd">Authentication is required for an application to inhibit system handling of the power key.</message>
<defaults>
<allow_any>no</allow_any>
<allow_inactive>yes</allow_inactive>
@@ -81,8 +83,8 @@
</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 for an application to inhibit system handling of the suspend key.</_message>
+ <description gettext-domain="systemd">Allow applications to inhibit system handling of the suspend key</description>
+ <message gettext-domain="systemd">Authentication is required for an application to inhibit system handling of the suspend key.</message>
<defaults>
<allow_any>no</allow_any>
<allow_inactive>yes</allow_inactive>
@@ -92,8 +94,8 @@
</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 for an application to inhibit system handling of the hibernate key.</_message>
+ <description gettext-domain="systemd">Allow applications to inhibit system handling of the hibernate key</description>
+ <message gettext-domain="systemd">Authentication is required for an application to inhibit system handling of the hibernate key.</message>
<defaults>
<allow_any>no</allow_any>
<allow_inactive>yes</allow_inactive>
@@ -102,8 +104,8 @@
</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 for an application to inhibit system handling of the lid switch.</_message>
+ <description gettext-domain="systemd">Allow applications to inhibit system handling of the lid switch</description>
+ <message gettext-domain="systemd">Authentication is required for an application to inhibit system handling of the lid switch.</message>
<defaults>
<allow_any>no</allow_any>
<allow_inactive>yes</allow_inactive>
@@ -112,8 +114,8 @@
</action>
<action id="org.freedesktop.login1.set-self-linger">
- <_description>Allow non-logged-in user to run programs</_description>
- <_message>Explicit request is required to run programs as a non-logged-in user.</_message>
+ <description gettext-domain="systemd">Allow non-logged-in user to run programs</description>
+ <message gettext-domain="systemd">Explicit request is required to run programs as a non-logged-in user.</message>
<defaults>
<allow_any>yes</allow_any>
<allow_inactive>yes</allow_inactive>
@@ -122,8 +124,8 @@
</action>
<action id="org.freedesktop.login1.set-user-linger">
- <_description>Allow non-logged-in users to run programs</_description>
- <_message>Authentication is required to run programs as a non-logged-in user.</_message>
+ <description gettext-domain="systemd">Allow non-logged-in users to run programs</description>
+ <message gettext-domain="systemd">Authentication is required to run programs as a non-logged-in user.</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
@@ -132,8 +134,8 @@
</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>
+ <description gettext-domain="systemd">Allow attaching devices to seats</description>
+ <message gettext-domain="systemd">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>
@@ -143,8 +145,8 @@
</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>
+ <description gettext-domain="systemd">Flush device to seat attachments</description>
+ <message gettext-domain="systemd">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>
@@ -153,8 +155,8 @@
</action>
<action id="org.freedesktop.login1.power-off">
- <_description>Power off the system</_description>
- <_message>Authentication is required for powering off the system.</_message>
+ <description gettext-domain="systemd">Power off the system</description>
+ <message gettext-domain="systemd">Authentication is required for powering off the system.</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
@@ -164,8 +166,8 @@
</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>
+ <description gettext-domain="systemd">Power off the system while other users are logged in</description>
+ <message gettext-domain="systemd">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>
@@ -175,8 +177,8 @@
</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>
+ <description gettext-domain="systemd">Power off the system while an application asked to inhibit it</description>
+ <message gettext-domain="systemd">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>
@@ -186,8 +188,8 @@
</action>
<action id="org.freedesktop.login1.reboot">
- <_description>Reboot the system</_description>
- <_message>Authentication is required for rebooting the system.</_message>
+ <description gettext-domain="systemd">Reboot the system</description>
+ <message gettext-domain="systemd">Authentication is required for rebooting the system.</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
@@ -197,8 +199,8 @@
</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>
+ <description gettext-domain="systemd">Reboot the system while other users are logged in</description>
+ <message gettext-domain="systemd">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>
@@ -208,8 +210,8 @@
</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>
+ <description gettext-domain="systemd">Reboot the system while an application asked to inhibit it</description>
+ <message gettext-domain="systemd">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>
@@ -218,9 +220,42 @@
<annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.reboot</annotate>
</action>
+ <action id="org.freedesktop.login1.halt">
+ <description gettext-domain="systemd">Halt the system</description>
+ <message gettext-domain="systemd">Authentication is required for halting the system.</message>
+ <defaults>
+ <allow_any>auth_admin_keep</allow_any>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.set-wall-message</annotate>
+ </action>
+
+ <action id="org.freedesktop.login1.halt-multiple-sessions">
+ <description gettext-domain="systemd">Halt the system while other users are logged in</description>
+ <message gettext-domain="systemd">Authentication is required for halting 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>
+ <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.halt</annotate>
+ </action>
+
+ <action id="org.freedesktop.login1.halt-ignore-inhibit">
+ <description gettext-domain="systemd">Halt the system while an application asked to inhibit it</description>
+ <message gettext-domain="systemd">Authentication is required for halting 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>
+ <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.halt</annotate>
+ </action>
+
<action id="org.freedesktop.login1.suspend">
- <_description>Suspend the system</_description>
- <_message>Authentication is required for suspending the system.</_message>
+ <description gettext-domain="systemd">Suspend the system</description>
+ <message gettext-domain="systemd">Authentication is required for suspending the system.</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
@@ -229,8 +264,8 @@
</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>
+ <description gettext-domain="systemd">Suspend the system while other users are logged in</description>
+ <message gettext-domain="systemd">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>
@@ -240,8 +275,8 @@
</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>
+ <description gettext-domain="systemd">Suspend the system while an application asked to inhibit it</description>
+ <message gettext-domain="systemd">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>
@@ -251,8 +286,8 @@
</action>
<action id="org.freedesktop.login1.hibernate">
- <_description>Hibernate the system</_description>
- <_message>Authentication is required for hibernating the system.</_message>
+ <description gettext-domain="systemd">Hibernate the system</description>
+ <message gettext-domain="systemd">Authentication is required for hibernating the system.</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
@@ -261,8 +296,8 @@
</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>
+ <description gettext-domain="systemd">Hibernate the system while other users are logged in</description>
+ <message gettext-domain="systemd">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>
@@ -272,8 +307,8 @@
</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>
+ <description gettext-domain="systemd">Hibernate the system while an application asked to inhibit it</description>
+ <message gettext-domain="systemd">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>
@@ -283,8 +318,8 @@
</action>
<action id="org.freedesktop.login1.manage">
- <_description>Manage active sessions, users and seats</_description>
- <_message>Authentication is required for managing active sessions, users and seats.</_message>
+ <description gettext-domain="systemd">Manage active sessions, users and seats</description>
+ <message gettext-domain="systemd">Authentication is required for managing active sessions, users and seats.</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
@@ -293,8 +328,8 @@
</action>
<action id="org.freedesktop.login1.lock-sessions">
- <_description>Lock or unlock active sessions</_description>
- <_message>Authentication is required to lock or unlock active sessions.</_message>
+ <description gettext-domain="systemd">Lock or unlock active sessions</description>
+ <message gettext-domain="systemd">Authentication is required to lock or unlock active sessions.</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
@@ -303,8 +338,8 @@
</action>
<action id="org.freedesktop.login1.set-reboot-to-firmware-setup">
- <_description>Allow indication to the firmware to boot to setup interface</_description>
- <_message>Authentication is required to indicate to the firmware to boot to setup interface.</_message>
+ <description gettext-domain="systemd">Allow indication to the firmware to boot to setup interface</description>
+ <message gettext-domain="systemd">Authentication is required to indicate to the firmware to boot to setup interface.</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
@@ -313,8 +348,8 @@
</action>
<action id="org.freedesktop.login1.set-wall-message">
- <_description>Set a wall message</_description>
- <_message>Authentication is required to set a wall message</_message>
+ <description gettext-domain="systemd">Set a wall message</description>
+ <message gettext-domain="systemd">Authentication is required to set a wall message</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
diff --git a/src/login/pam_elogind.c b/src/login/pam_elogind.c
index 402885d7e..88c5705ef 100644
--- a/src/login/pam_elogind.c
+++ b/src/login/pam_elogind.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <endian.h>
#include <errno.h>
@@ -41,10 +24,13 @@
#include "login-util.h"
#include "macro.h"
#include "parse-util.h"
+#include "process-util.h"
#include "socket-util.h"
#include "strv.h"
#include "terminal-util.h"
#include "util.h"
+#include "path-util.h"
+#include "cgroup-util.h"
static int parse_argv(
pam_handle_t *handle,
@@ -194,7 +180,7 @@ static int export_legacy_dbus_address(
return PAM_SUCCESS;
s = mfree(s);
- if (asprintf(&s, UNIX_USER_BUS_ADDRESS_FMT, runtime) < 0)
+ if (asprintf(&s, DEFAULT_USER_BUS_ADDRESS_FMT, runtime) < 0)
goto error;
r = pam_misc_setenv(handle, "DBUS_SESSION_BUS_ADDRESS", s, 0);
@@ -208,13 +194,93 @@ error:
return r;
}
+static int append_session_memory_max(pam_handle_t *handle, sd_bus_message *m, const char *limit) {
+ uint64_t val;
+ int r;
+
+ if (isempty(limit))
+ return 0;
+
+ if (streq(limit, "infinity")) {
+ r = sd_bus_message_append(m, "(sv)", "MemoryMax", "t", (uint64_t)-1);
+ if (r < 0) {
+ pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+ return r;
+ }
+ } else {
+ r = parse_percent(limit);
+ if (r >= 0) {
+ r = sd_bus_message_append(m, "(sv)", "MemoryMaxScale", "u", (uint32_t) (((uint64_t) UINT32_MAX * r) / 100U));
+ if (r < 0) {
+ pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+ return r;
+ }
+ } else {
+ r = parse_size(limit, 1024, &val);
+ if (r >= 0) {
+ r = sd_bus_message_append(m, "(sv)", "MemoryMax", "t", val);
+ if (r < 0) {
+ pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+ return r;
+ }
+ } else
+ pam_syslog(handle, LOG_WARNING, "Failed to parse elogind.limit: %s, ignoring.", limit);
+ }
+ }
+
+ return 0;
+}
+
+static int append_session_tasks_max(pam_handle_t *handle, sd_bus_message *m, const char *limit)
+{
+ uint64_t val;
+ int r;
+
+ /* No need to parse "infinity" here, it will be set unconditionally later in manager_start_scope() */
+ if (isempty(limit) || streq(limit, "infinity"))
+ return 0;
+
+ r = safe_atou64(limit, &val);
+ if (r >= 0) {
+ r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", val);
+ if (r < 0) {
+ pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+ return r;
+ }
+ } else
+ pam_syslog(handle, LOG_WARNING, "Failed to parse elogind.limit: %s, ignoring.", limit);
+
+ return 0;
+}
+
+static int append_session_cg_weight(pam_handle_t *handle, sd_bus_message *m, const char *limit, const char *field) {
+ uint64_t val;
+ int r;
+
+ if (!isempty(limit)) {
+ r = cg_weight_parse(limit, &val);
+ if (r >= 0) {
+ r = sd_bus_message_append(m, "(sv)", field, "t", val);
+ if (r < 0) {
+ pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+ return r;
+ }
+ } else if (streq(field, "CPUWeight"))
+ pam_syslog(handle, LOG_WARNING, "Failed to parse elogind.cpu_weight: %s, ignoring.", limit);
+ else
+ pam_syslog(handle, LOG_WARNING, "Failed to parse elogind.io_weight: %s, ignoring.", limit);
+ }
+
+ return 0;
+}
+
_public_ PAM_EXTERN int pam_sm_open_session(
pam_handle_t *handle,
int flags,
int argc, const char **argv) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
const char
*username, *id, *object_path, *runtime_path,
*service = NULL,
@@ -222,7 +288,8 @@ _public_ PAM_EXTERN int pam_sm_open_session(
*remote_user = NULL, *remote_host = NULL,
*seat = NULL,
*type = NULL, *class = NULL,
- *class_pam = NULL, *type_pam = NULL, *cvtnr = NULL, *desktop = NULL;
+ *class_pam = NULL, *type_pam = NULL, *cvtnr = NULL, *desktop = NULL,
+ *memory_max = NULL, *tasks_max = NULL, *cpu_weight = NULL, *io_weight = NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int session_fd = -1, existing, r;
bool debug = false, remote;
@@ -246,11 +313,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
return PAM_SESSION_ERR;
if (debug)
-#if 0 /// This is pam-elogind, not pam-systemd
- pam_syslog(handle, LOG_DEBUG, "pam-systemd initializing");
-#else
pam_syslog(handle, LOG_DEBUG, "pam-elogind initializing");
-#endif // 0
r = get_user_data(handle, &username, &pw);
if (r != PAM_SUCCESS) {
@@ -259,17 +322,13 @@ _public_ PAM_EXTERN int pam_sm_open_session(
}
/* Make sure we don't enter a loop by talking to
- * systemd-logind when it is actually waiting for the
+ * elogind when it is actually waiting for the
* background to finish start-up. If the service is
- * "systemd-user" we simply set XDG_RUNTIME_DIR and
+ * "elogind-user" we simply set XDG_RUNTIME_DIR and
* leave. */
pam_get_item(handle, PAM_SERVICE, (const void**) &service);
-#if 0 /// Actually it is elogind-user with elogind.
- if (streq_ptr(service, "systemd-user")) {
-#else
if (streq_ptr(service, "elogind-user")) {
-#endif // 0
_cleanup_free_ char *rt = NULL;
if (asprintf(&rt, "/run/user/"UID_FMT, pw->pw_uid) < 0)
@@ -344,7 +403,9 @@ _public_ PAM_EXTERN int pam_sm_open_session(
type ="tty";
class = "user";
tty = NULL;
- }
+ } else
+ /* Chop off leading /dev prefix that some clients specify, but others do not. */
+ tty = skip_dev_prefix(tty);
/* If this fails vtnr will be 0, that's intended */
if (!isempty(cvtnr))
@@ -371,6 +432,11 @@ _public_ PAM_EXTERN int pam_sm_open_session(
remote = !isempty(remote_host) && !is_localhost(remote_host);
+ (void) pam_get_data(handle, "elogind.memory_max", (const void **)&memory_max);
+ (void) pam_get_data(handle, "elogind.tasks_max", (const void **)&tasks_max);
+ (void) pam_get_data(handle, "elogind.cpu_weight", (const void **)&cpu_weight);
+ (void) pam_get_data(handle, "elogind.io_weight", (const void **)&io_weight);
+
/* Talk to logind over the message bus */
r = sd_bus_open_system(&bus);
@@ -379,37 +445,79 @@ _public_ PAM_EXTERN int pam_sm_open_session(
return PAM_SESSION_ERR;
}
- if (debug)
+ if (debug) {
pam_syslog(handle, LOG_DEBUG, "Asking logind to create session: "
"uid="UID_FMT" pid="PID_FMT" service=%s type=%s class=%s desktop=%s seat=%s vtnr=%"PRIu32" tty=%s display=%s remote=%s remote_user=%s remote_host=%s",
- pw->pw_uid, getpid(),
+ pw->pw_uid, getpid_cached(),
strempty(service),
type, class, strempty(desktop),
strempty(seat), vtnr, strempty(tty), strempty(display),
yes_no(remote), strempty(remote_user), strempty(remote_host));
+ pam_syslog(handle, LOG_DEBUG, "Session limits: "
+ "memory_max=%s tasks_max=%s cpu_weight=%s io_weight=%s",
+ strna(memory_max), strna(tasks_max), strna(cpu_weight), strna(io_weight));
+ }
+
+ r = sd_bus_message_new_method_call(
+ bus,
+ &m,
+ "org.freedesktop.login1",
+ "/org/freedesktop/login1",
+ "org.freedesktop.login1.Manager",
+ "CreateSession");
+ if (r < 0) {
+ pam_syslog(handle, LOG_ERR, "Failed to create CreateSession method call: %s", strerror(-r));
+ return PAM_SESSION_ERR;
+ }
+
+ r = sd_bus_message_append(m, "uusssssussbss",
+ (uint32_t) pw->pw_uid,
+ (uint32_t) getpid_cached(),
+ service,
+ type,
+ class,
+ desktop,
+ seat,
+ vtnr,
+ tty,
+ display,
+ remote,
+ remote_user,
+ remote_host);
+ if (r < 0) {
+ pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+ return PAM_SESSION_ERR;
+ }
+
+ r = sd_bus_message_open_container(m, 'a', "(sv)");
+ if (r < 0) {
+ pam_syslog(handle, LOG_ERR, "Failed to open message container: %s", strerror(-r));
+ return PAM_SYSTEM_ERR;
+ }
+
+ r = append_session_memory_max(handle, m, memory_max);
+ if (r < 0)
+ return PAM_SESSION_ERR;
+
+ r = append_session_tasks_max(handle, m, tasks_max);
+ if (r < 0)
+ return PAM_SESSION_ERR;
+
+ r = append_session_cg_weight(handle, m, cpu_weight, "CPUWeight");
+ if (r < 0)
+ return PAM_SESSION_ERR;
+
+ r = append_session_cg_weight(handle, m, io_weight, "IOWeight");
+ if (r < 0)
+ return PAM_SESSION_ERR;
+
+ r = sd_bus_message_close_container(m);
+ if (r < 0) {
+ pam_syslog(handle, LOG_ERR, "Failed to close message container: %s", strerror(-r));
+ return PAM_SYSTEM_ERR;
+ }
- r = sd_bus_call_method(bus,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "CreateSession",
- &error,
- &reply,
- "uusssssussbssa(sv)",
- (uint32_t) pw->pw_uid,
- (uint32_t) getpid(),
- service,
- type,
- class,
- desktop,
- seat,
- vtnr,
- tty,
- display,
- remote,
- remote_user,
- remote_host,
- 0);
+ r = sd_bus_call(bus, m, 0, &error, &reply);
if (r < 0) {
if (sd_bus_error_has_name(&error, BUS_ERROR_SESSION_BUSY)) {
pam_syslog(handle, LOG_DEBUG, "Cannot create session: %s", bus_error_message(&error, r));
diff --git a/src/login/pam_elogind.sym b/src/login/pam_elogind.sym
index 23ff75f68..62d5d26b0 100644
--- a/src/login/pam_elogind.sym
+++ b/src/login/pam_elogind.sym
@@ -1,5 +1,5 @@
/***
- This file is part of systemd.
+ SPDX-License-Identifier: LGPL-2.1+
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
diff --git a/src/login/sysfs-show.c b/src/login/sysfs-show.c
index cb5bb5e5f..a14c72a68 100644
--- a/src/login/sysfs-show.c
+++ b/src/login/sysfs-show.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <string.h>
@@ -41,15 +24,25 @@ static int show_sysfs_one(
struct udev_list_entry **item,
const char *sub,
const char *prefix,
- unsigned n_columns) {
+ unsigned n_columns,
+ OutputFlags flags) {
+
+ size_t max_width;
assert(udev);
assert(seat);
assert(item);
assert(prefix);
+ if (flags & OUTPUT_FULL_WIDTH)
+ max_width = (size_t) -1;
+ else if (n_columns < 10)
+ max_width = 10;
+ else
+ max_width = n_columns;
+
while (*item) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
struct udev_list_entry *next, *lookahead;
const char *sn, *name, *sysfs, *subsystem, *sysname;
_cleanup_free_ char *k = NULL, *l = NULL;
@@ -92,7 +85,7 @@ static int show_sysfs_one(
if (path_startswith(lookahead_sysfs, sub) &&
!path_startswith(lookahead_sysfs, sysfs)) {
- _cleanup_udev_device_unref_ struct udev_device *lookahead_d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *lookahead_d = NULL;
lookahead_d = udev_device_new_from_syspath(udev, lookahead_sysfs);
if (lookahead_d) {
@@ -110,7 +103,7 @@ static int show_sysfs_one(
lookahead = udev_list_entry_get_next(lookahead);
}
- k = ellipsize(sysfs, n_columns, 20);
+ k = ellipsize(sysfs, max_width, 20);
if (!k)
return -ENOMEM;
@@ -124,7 +117,7 @@ static int show_sysfs_one(
return -ENOMEM;
free(k);
- k = ellipsize(l, n_columns, 70);
+ k = ellipsize(l, max_width, 70);
if (!k)
return -ENOMEM;
@@ -138,24 +131,25 @@ static int show_sysfs_one(
if (!p)
return -ENOMEM;
- show_sysfs_one(udev, seat, item, sysfs, p, n_columns - 2);
+ show_sysfs_one(udev, seat, item, sysfs, p,
+ n_columns == (unsigned) -1 || n_columns < 2 ? n_columns : n_columns - 2,
+ flags);
}
}
return 0;
}
-int show_sysfs(const char *seat, const char *prefix, unsigned n_columns) {
- _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
- _cleanup_udev_unref_ struct udev *udev = NULL;
+int show_sysfs(const char *seat, const char *prefix, unsigned n_columns, OutputFlags flags) {
+ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
+ _cleanup_(udev_unrefp) struct udev *udev = NULL;
struct udev_list_entry *first = NULL;
int r;
if (n_columns <= 0)
n_columns = columns();
- if (!prefix)
- prefix = "";
+ prefix = strempty(prefix);
if (isempty(seat))
seat = "seat0";
@@ -185,7 +179,7 @@ int show_sysfs(const char *seat, const char *prefix, unsigned n_columns) {
first = udev_enumerate_get_list_entry(e);
if (first)
- show_sysfs_one(udev, seat, &first, "/", prefix, n_columns);
+ show_sysfs_one(udev, seat, &first, "/", prefix, n_columns, flags);
else
printf("%s%s%s\n", prefix, special_glyph(TREE_RIGHT), "(none)");
diff --git a/src/login/sysfs-show.h b/src/login/sysfs-show.h
index 3e94bc3ed..c05b97753 100644
--- a/src/login/sysfs-show.h
+++ b/src/login/sysfs-show.h
@@ -1,22 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
+#include <sys/types.h>
- Copyright 2011 Lennart Poettering
+#include "output-mode.h"
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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);
+int show_sysfs(const char *seat, const char *prefix, unsigned columns, OutputFlags flags);
diff --git a/src/login/test-inhibit.c b/src/login/test-inhibit.c
index a3cf9d293..75c9303ff 100644
--- a/src/login/test-inhibit.c
+++ b/src/login/test-inhibit.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <unistd.h>
diff --git a/src/login/test-login-shared.c b/src/login/test-login-shared.c
index 47d8bf077..602bc1ae7 100644
--- a/src/login/test-login-shared.c
+++ b/src/login/test-login-shared.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include "login-util.h"
#include "macro.h"
diff --git a/src/login/test-login-tables.c b/src/login/test-login-tables.c
index 4fbc893a9..02b871968 100644
--- a/src/login/test-login-tables.c
+++ b/src/login/test-login-tables.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd
-
- Copyright 2013 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include "logind-action.h"
#include "logind-session.h"
diff --git a/src/login/user-runtime-dir.c b/src/login/user-runtime-dir.c
new file mode 100644
index 000000000..3cd5afee3
--- /dev/null
+++ b/src/login/user-runtime-dir.c
@@ -0,0 +1,196 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <stdint.h>
+#include <sys/mount.h>
+
+#include "fs-util.h"
+#include "label.h"
+//#include "logind.h"
+#include "mkdir.h"
+#include "mount-util.h"
+#include "path-util.h"
+#include "rm-rf.h"
+#include "smack-util.h"
+#include "stdio-util.h"
+#include "string-util.h"
+#include "strv.h"
+#include "user-util.h"
+/// Additional includes needed by elogind
+#include "user-runtime-dir.h"
+
+#if 0 /// UNNEEDED by elogind
+static int gather_configuration(size_t *runtime_dir_size) {
+ Manager m = {};
+ int r;
+
+ manager_reset_config(&m);
+
+ r = manager_parse_config_file(&m);
+ if (r < 0)
+ log_warning_errno(r, "Failed to parse logind.conf: %m");
+
+ *runtime_dir_size = m.runtime_dir_size;
+ return 0;
+}
+#endif // 0
+
+static int user_mkdir_runtime_path(const char *runtime_path, uid_t uid, gid_t gid, size_t runtime_dir_size) {
+ int r;
+
+ assert(runtime_path);
+ assert(path_is_absolute(runtime_path));
+ assert(uid_is_valid(uid));
+ assert(gid_is_valid(gid));
+
+ r = mkdir_safe_label("/run/user", 0755, 0, 0, MKDIR_WARN_MODE);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create /run/user: %m");
+
+ if (path_is_mount_point(runtime_path, NULL, 0) >= 0)
+ log_debug("%s is already a mount point", runtime_path);
+ else {
+ char options[sizeof("mode=0700,uid=,gid=,size=,smackfsroot=*")
+ + DECIMAL_STR_MAX(uid_t)
+ + DECIMAL_STR_MAX(gid_t)
+ + DECIMAL_STR_MAX(size_t)];
+
+ xsprintf(options,
+ "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu%s",
+ uid, gid, runtime_dir_size,
+ mac_smack_use() ? ",smackfsroot=*" : "");
+
+ (void) mkdir_label(runtime_path, 0700);
+
+ r = mount("tmpfs", runtime_path, "tmpfs", MS_NODEV|MS_NOSUID, options);
+ if (r < 0) {
+ if (!IN_SET(errno, EPERM, EACCES)) {
+ r = log_error_errno(errno, "Failed to mount per-user tmpfs directory %s: %m", runtime_path);
+ goto fail;
+ }
+
+ log_debug_errno(errno, "Failed to mount per-user tmpfs directory %s.\n"
+ "Assuming containerized execution, ignoring: %m", runtime_path);
+
+ r = chmod_and_chown(runtime_path, 0700, uid, gid);
+ if (r < 0) {
+ log_error_errno(r, "Failed to change ownership and mode of \"%s\": %m", runtime_path);
+ goto fail;
+ }
+ }
+
+ r = label_fix(runtime_path, 0);
+ if (r < 0)
+ log_warning_errno(r, "Failed to fix label of \"%s\", ignoring: %m", runtime_path);
+ }
+
+ return 0;
+
+fail:
+ /* Try to clean up, but ignore errors */
+ (void) rmdir(runtime_path);
+ return r;
+}
+
+static int user_remove_runtime_path(const char *runtime_path) {
+ int r;
+
+ assert(runtime_path);
+ assert(path_is_absolute(runtime_path));
+
+ r = rm_rf(runtime_path, 0);
+ if (r < 0)
+ log_error_errno(r, "Failed to remove runtime directory %s (before unmounting): %m", runtime_path);
+
+ /* Ignore cases where the directory isn't mounted, as that's
+ * quite possible, if we lacked the permissions to mount
+ * something */
+ r = umount2(runtime_path, MNT_DETACH);
+ if (r < 0 && !IN_SET(errno, EINVAL, ENOENT))
+ log_error_errno(errno, "Failed to unmount user runtime directory %s: %m", runtime_path);
+
+ r = rm_rf(runtime_path, REMOVE_ROOT);
+ if (r < 0)
+ log_error_errno(r, "Failed to remove runtime directory %s (after unmounting): %m", runtime_path);
+
+ return r;
+}
+
+#if 0 /// having a User instance, elogind can ask its manager directly.
+static int do_mount(const char *runtime_path, uid_t uid, gid_t gid) {
+ size_t runtime_dir_size;
+
+ assert_se(gather_configuration(&runtime_dir_size) == 0);
+#else
+static int do_mount(const char *runtime_path, size_t runtime_dir_size, uid_t uid, gid_t gid) {
+#endif // 0
+
+ log_debug("Will mount %s owned by "UID_FMT":"GID_FMT, runtime_path, uid, gid);
+ return user_mkdir_runtime_path(runtime_path, uid, gid, runtime_dir_size);
+}
+
+static int do_umount(const char *runtime_path) {
+ log_debug("Will remove %s", runtime_path);
+ return user_remove_runtime_path(runtime_path);
+}
+
+#if 0 /// elogind does this internally as we have no unit chain being init.
+int main(int argc, char *argv[]) {
+ const char *user;
+ uid_t uid;
+ gid_t gid;
+ char runtime_path[sizeof("/run/user") + DECIMAL_STR_MAX(uid_t)];
+ int r;
+
+ log_parse_environment();
+ log_open();
+
+ if (argc != 3) {
+ log_error("This program takes two arguments.");
+ return EXIT_FAILURE;
+ }
+ if (!STR_IN_SET(argv[1], "start", "stop")) {
+ log_error("First argument must be either \"start\" or \"stop\".");
+ return EXIT_FAILURE;
+ }
+
+ umask(0022);
+
+ user = argv[2];
+ r = get_user_creds(&user, &uid, &gid, NULL, NULL);
+ if (r < 0) {
+ log_error_errno(r,
+ r == -ESRCH ? "No such user \"%s\"" :
+ r == -ENOMSG ? "UID \"%s\" is invalid or has an invalid main group"
+ : "Failed to look up user \"%s\": %m",
+ user);
+ return EXIT_FAILURE;
+ }
+ xsprintf(runtime_path, "/run/user/" UID_FMT, uid);
+
+ if (streq(argv[1], "start"))
+ r = do_mount(runtime_path, uid, gid);
+ else if (streq(argv[1], "stop"))
+ r = do_umount(runtime_path);
+ else
+ assert_not_reached("Unknown verb!");
+
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+#else
+int user_runtime_dir(const char *verb, User *u) {
+ int r;
+
+ assert_se(verb);
+ assert_se(u);
+ assert_se(u->manager);
+
+ if (streq(verb, "start"))
+ r = do_mount(u->runtime_path, u->manager->runtime_dir_size, u->uid, u->gid);
+ else if (streq(verb, "stop"))
+ r = do_umount(u->runtime_path);
+ else
+ assert_not_reached("Unknown verb!");
+
+ return r;
+}
+#endif // 0
diff --git a/src/login/user-runtime-dir.h b/src/login/user-runtime-dir.h
new file mode 100644
index 000000000..7cef5f401
--- /dev/null
+++ b/src/login/user-runtime-dir.h
@@ -0,0 +1,28 @@
+#pragma once
+#ifndef ELOGIND_SRC_LOGIN_USER_RUNTIME_DIR_H_INCLUDED
+#define ELOGIND_SRC_LOGIN_USER_RUNTIME_DIR_H_INCLUDED
+
+/***
+ This file is part of elogind.
+
+ Copyright 2017 Sven Eden
+
+ elogind is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ elogind is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with elogind; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "logind.h"
+
+int user_runtime_dir(const char *verb, User *u);
+
+#endif // ELOGIND_SRC_LOGIN_USER_RUNTIME_DIR_H_INCLUDED
diff --git a/src/shared/Makefile b/src/shared/Makefile
deleted file mode 120000
index d0b0e8e00..000000000
--- 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
index b99ecbba5..38dbf5e1c 100644
--- a/src/shared/acl-util.c
+++ b/src/shared/acl-util.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2011,2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <stdbool.h>
@@ -217,16 +200,14 @@ int acl_search_groups(const char *path, char ***ret_groups) {
r = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
}
- if (ret_groups) {
- *ret_groups = g;
- g = NULL;
- }
+ if (ret_groups)
+ *ret_groups = TAKE_PTR(g);
return ret;
}
int parse_acl(const char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask) {
- _cleanup_free_ char **a = NULL, **d = NULL; /* strings are not be freed */
+ _cleanup_free_ char **a = NULL, **d = NULL; /* strings are not freed */
_cleanup_strv_free_ char **split;
char **entry;
int r = -EINVAL;
@@ -287,9 +268,8 @@ int parse_acl(const char *text, acl_t *acl_access, acl_t *acl_default, bool want
}
}
- *acl_access = a_acl;
- *acl_default = d_acl;
- a_acl = d_acl = NULL;
+ *acl_access = TAKE_PTR(a_acl);
+ *acl_default = TAKE_PTR(d_acl);
return 0;
}
@@ -393,8 +373,8 @@ int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl) {
if (r < 0)
return -errno;
- *acl = old;
- old = NULL;
+ *acl = TAKE_PTR(old);
+
return 0;
}
diff --git a/src/shared/acl-util.h b/src/shared/acl-util.h
index 133996d77..b8d84c984 100644
--- a/src/shared/acl-util.h
+++ b/src/shared/acl-util.h
@@ -1,25 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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/>.
-***/
-
-#ifdef HAVE_ACL
+#if HAVE_ACL
#include <acl/libacl.h>
#include <stdbool.h>
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
index 485bd0885..c3be78769 100644
--- a/src/shared/bus-util.c
+++ b/src/shared/bus-util.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <fcntl.h>
@@ -39,10 +22,13 @@
#include "bus-label.h"
#include "bus-message.h"
#include "bus-util.h"
+#include "cap-list.h"
+#include "cgroup-util.h"
#include "def.h"
#include "escape.h"
#include "fd-util.h"
#include "missing.h"
+#include "mount-util.h"
#include "nsflags.h"
#include "parse-util.h"
#include "proc-cmdline.h"
@@ -65,7 +51,7 @@ static int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_
}
int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
- _cleanup_free_ char *match = NULL;
+ const char *match;
const char *unique;
int r;
@@ -82,23 +68,21 @@ int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
if (r < 0)
return r;
- r = asprintf(&match,
- "sender='org.freedesktop.DBus',"
- "type='signal',"
- "interface='org.freedesktop.DBus',"
- "member='NameOwnerChanged',"
- "path='/org/freedesktop/DBus',"
- "arg0='%s',"
- "arg1='%s',"
- "arg2=''", name, unique);
- if (r < 0)
- return -ENOMEM;
-
- r = sd_bus_add_match(bus, NULL, match, name_owner_change_callback, e);
+ match = strjoina(
+ "sender='org.freedesktop.DBus',"
+ "type='signal',"
+ "interface='org.freedesktop.DBus',"
+ "member='NameOwnerChanged',"
+ "path='/org/freedesktop/DBus',"
+ "arg0='", name, "',",
+ "arg1='", unique, "',",
+ "arg2=''");
+
+ r = sd_bus_add_match_async(bus, NULL, match, name_owner_change_callback, NULL, e);
if (r < 0)
return r;
- r = sd_bus_release_name(bus, name);
+ r = sd_bus_release_name_async(bus, NULL, name, NULL, NULL);
if (r < 0)
return r;
@@ -254,7 +238,7 @@ int bus_test_polkit(
return r;
else if (r > 0)
return 1;
-#ifdef ENABLE_POLKIT
+#if ENABLE_POLKIT
else {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *request = NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
@@ -333,7 +317,7 @@ int bus_test_polkit(
return -EACCES;
}
-#ifdef ENABLE_POLKIT
+#if ENABLE_POLKIT
typedef struct AsyncPolkitQuery {
sd_bus_message *request, *reply;
@@ -397,7 +381,7 @@ int bus_verify_polkit_async(
Hashmap **registry,
sd_bus_error *error) {
-#ifdef ENABLE_POLKIT
+#if ENABLE_POLKIT
_cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL;
AsyncPolkitQuery *q;
const char *sender, **k, **v;
@@ -415,7 +399,7 @@ int bus_verify_polkit_async(
if (r != 0)
return r;
-#ifdef ENABLE_POLKIT
+#if ENABLE_POLKIT
q = hashmap_get(*registry, call);
if (q) {
int authorized, challenge;
@@ -462,7 +446,7 @@ int bus_verify_polkit_async(
else if (r > 0)
return 1;
-#ifdef ENABLE_POLKIT
+#if ENABLE_POLKIT
if (sd_bus_get_current_message(call->bus) != call)
return -EINVAL;
@@ -551,21 +535,15 @@ int bus_verify_polkit_async(
}
void bus_verify_polkit_async_registry_free(Hashmap *registry) {
-#ifdef ENABLE_POLKIT
- AsyncPolkitQuery *q;
-
- while ((q = hashmap_steal_first(registry)))
- async_polkit_query_free(q);
-
- hashmap_free(registry);
+#if ENABLE_POLKIT
+ hashmap_free_with_destructor(registry, async_polkit_query_free);
#endif
}
#if 0 /// UNNEEDED by elogind
int bus_check_peercred(sd_bus *c) {
struct ucred ucred;
- socklen_t l;
- int fd;
+ int fd, r;
assert(c);
@@ -573,12 +551,9 @@ int bus_check_peercred(sd_bus *c) {
if (fd < 0)
return fd;
- l = sizeof(struct ucred);
- if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
- return -errno;
-
- if (l != sizeof(struct ucred))
- return -E2BIG;
+ r = getpeercred(fd, &ucred);
+ if (r < 0)
+ return r;
if (ucred.uid != 0 && ucred.uid != geteuid())
return -EPERM;
@@ -595,28 +570,8 @@ int bus_connect_system_systemd(sd_bus **_bus) {
if (geteuid() != 0)
return sd_bus_default_system(_bus);
- /* If we are root and kdbus is not available, then let's talk
- * directly to the system instance, instead of going via the
- * bus */
-
- r = sd_bus_new(&bus);
- if (r < 0)
- return r;
-
- r = sd_bus_set_address(bus, KERNEL_SYSTEM_BUS_ADDRESS);
- if (r < 0)
- return r;
-
- bus->bus_client = true;
-
- r = sd_bus_start(bus);
- if (r >= 0) {
- *_bus = bus;
- bus = NULL;
- return 0;
- }
-
- bus = sd_bus_unref(bus);
+ /* If we are root then let's talk directly to the system
+ * instance, instead of going via the bus */
r = sd_bus_new(&bus);
if (r < 0)
@@ -634,8 +589,7 @@ int bus_connect_system_systemd(sd_bus **_bus) {
if (r < 0)
return r;
- *_bus = bus;
- bus = NULL;
+ *_bus = TAKE_PTR(bus);
return 0;
}
@@ -646,28 +600,8 @@ int bus_connect_user_systemd(sd_bus **_bus) {
const char *e;
int r;
- /* Try via kdbus first, and then directly */
-
assert(_bus);
- r = sd_bus_new(&bus);
- if (r < 0)
- return r;
-
- if (asprintf(&bus->address, KERNEL_USER_BUS_ADDRESS_FMT, getuid()) < 0)
- return -ENOMEM;
-
- bus->bus_client = true;
-
- r = sd_bus_start(bus);
- if (r >= 0) {
- *_bus = bus;
- bus = NULL;
- return 0;
- }
-
- bus = sd_bus_unref(bus);
-
e = secure_getenv("XDG_RUNTIME_DIR");
if (!e)
return sd_bus_default_user(_bus);
@@ -692,8 +626,7 @@ int bus_connect_user_systemd(sd_bus **_bus) {
if (r < 0)
return r;
- *_bus = bus;
- bus = NULL;
+ *_bus = TAKE_PTR(bus);
return 0;
}
@@ -705,17 +638,17 @@ int bus_connect_user_systemd(sd_bus **_bus) {
printf(fmt "\n", __VA_ARGS__); \
else \
printf("%s=" fmt "\n", name, __VA_ARGS__); \
- } while(0)
+ } while (0)
-int bus_print_property(const char *name, sd_bus_message *property, bool value, bool all) {
+int bus_print_property(const char *name, sd_bus_message *m, bool value, bool all) {
char type;
const char *contents;
int r;
assert(name);
- assert(property);
+ assert(m);
- r = sd_bus_message_peek_type(property, &type, &contents);
+ r = sd_bus_message_peek_type(m, &type, &contents);
if (r < 0)
return r;
@@ -724,7 +657,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
case SD_BUS_TYPE_STRING: {
const char *s;
- r = sd_bus_message_read_basic(property, type, &s);
+ r = sd_bus_message_read_basic(m, type, &s);
if (r < 0)
return r;
@@ -743,7 +676,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
case SD_BUS_TYPE_BOOLEAN: {
int b;
- r = sd_bus_message_read_basic(property, type, &b);
+ r = sd_bus_message_read_basic(m, type, &b);
if (r < 0)
return r;
@@ -755,15 +688,17 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
case SD_BUS_TYPE_UINT64: {
uint64_t u;
- r = sd_bus_message_read_basic(property, type, &u);
+ r = sd_bus_message_read_basic(m, type, &u);
if (r < 0)
return r;
/* 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;
+ if (endswith(name, "Timestamp") ||
+ STR_IN_SET(name, "NextElapseUSecRealtime", "LastTriggerUSec", "TimeUSec", "RTCTimeUSec")) {
+ char timestamp[FORMAT_TIMESTAMP_MAX];
+ const char *t;
t = format_timestamp(timestamp, sizeof(timestamp), u);
if (t || all)
@@ -775,14 +710,14 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
print_property(name, "%s", format_timespan(timespan, sizeof(timespan), u, 0));
} else if (streq(name, "RestrictNamespaces")) {
_cleanup_free_ char *s = NULL;
- const char *result = NULL;
+ const char *result;
if ((u & NAMESPACE_FLAGS_ALL) == 0)
result = "yes";
else if ((u & NAMESPACE_FLAGS_ALL) == NAMESPACE_FLAGS_ALL)
result = "no";
else {
- r = namespace_flag_to_string_many(u, &s);
+ r = namespace_flags_to_string(u, &s);
if (r < 0)
return r;
@@ -790,7 +725,40 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
}
print_property(name, "%s", result);
- } else
+
+ } else if (streq(name, "MountFlags")) {
+ const char *result;
+
+ result = mount_propagation_flags_to_string(u);
+ if (!result)
+ return -EINVAL;
+
+ print_property(name, "%s", result);
+
+ } else if (STR_IN_SET(name, "CapabilityBoundingSet", "AmbientCapabilities")) {
+ _cleanup_free_ char *s = NULL;
+
+ r = capability_set_to_string_alloc(u, &s);
+ if (r < 0)
+ return r;
+
+ print_property(name, "%s", s);
+
+ } else if ((STR_IN_SET(name, "CPUWeight", "StartupCPUWeight", "IOWeight", "StartupIOWeight") && u == CGROUP_WEIGHT_INVALID) ||
+ (STR_IN_SET(name, "CPUShares", "StartupCPUShares") && u == CGROUP_CPU_SHARES_INVALID) ||
+ (STR_IN_SET(name, "BlockIOWeight", "StartupBlockIOWeight") && u == CGROUP_BLKIO_WEIGHT_INVALID) ||
+ (STR_IN_SET(name, "MemoryCurrent", "TasksCurrent") && u == (uint64_t) -1) ||
+ (endswith(name, "NSec") && u == (uint64_t) -1))
+
+ print_property(name, "%s", "[not set]");
+
+ else if ((STR_IN_SET(name, "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit") && u == CGROUP_LIMIT_MAX) ||
+ (STR_IN_SET(name, "TasksMax", "DefaultTasksMax") && u == (uint64_t) -1) ||
+ (startswith(name, "Limit") && u == (uint64_t) -1) ||
+ (startswith(name, "DefaultLimit") && u == (uint64_t) -1))
+
+ print_property(name, "%s", "infinity");
+ else
print_property(name, "%"PRIu64, u);
return 1;
@@ -799,7 +767,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
case SD_BUS_TYPE_INT64: {
int64_t i;
- r = sd_bus_message_read_basic(property, type, &i);
+ r = sd_bus_message_read_basic(m, type, &i);
if (r < 0)
return r;
@@ -811,13 +779,23 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
case SD_BUS_TYPE_UINT32: {
uint32_t u;
- r = sd_bus_message_read_basic(property, type, &u);
+ r = sd_bus_message_read_basic(m, type, &u);
if (r < 0)
return r;
if (strstr(name, "UMask") || strstr(name, "Mode"))
print_property(name, "%04o", u);
- else
+ else if (streq(name, "UID")) {
+ if (u == UID_INVALID)
+ print_property(name, "%s", "[not set]");
+ else
+ print_property(name, "%"PRIu32, u);
+ } else if (streq(name, "GID")) {
+ if (u == GID_INVALID)
+ print_property(name, "%s", "[not set]");
+ else
+ print_property(name, "%"PRIu32, u);
+ } else
print_property(name, "%"PRIu32, u);
return 1;
@@ -826,7 +804,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
case SD_BUS_TYPE_INT32: {
int32_t i;
- r = sd_bus_message_read_basic(property, type, &i);
+ r = sd_bus_message_read_basic(m, type, &i);
if (r < 0)
return r;
@@ -837,7 +815,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
case SD_BUS_TYPE_DOUBLE: {
double d;
- r = sd_bus_message_read_basic(property, type, &d);
+ r = sd_bus_message_read_basic(m, type, &d);
if (r < 0)
return r;
@@ -850,18 +828,18 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
bool first = true;
const char *str;
- r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, contents);
if (r < 0)
return r;
- while ((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
+ while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &str)) > 0) {
bool good;
if (first && !value)
printf("%s=", name);
- /* This property has multiple space-seperated values, so
- * neither spaces not newlines can be allowed in a value. */
+ /* This property has multiple space-separated values, so
+ * neither spaces nor newlines can be allowed in a value. */
good = str[strcspn(str, " \n")] == '\0';
printf("%s%s", first ? "" : " ", good ? str : "[unprintable]");
@@ -876,7 +854,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
if (!first || all)
puts("");
- r = sd_bus_message_exit_container(property);
+ r = sd_bus_message_exit_container(m);
if (r < 0)
return r;
@@ -886,7 +864,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
const uint8_t *u;
size_t n;
- r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
+ r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
if (r < 0)
return r;
@@ -908,7 +886,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
uint32_t *u;
size_t n;
- r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
+ r = sd_bus_message_read_array(m, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
if (r < 0)
return r;
@@ -933,81 +911,118 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
return 0;
}
-int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool value, bool all) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- int r;
+int bus_message_print_all_properties(
+ sd_bus_message *m,
+ bus_message_print_t func,
+ char **filter,
+ bool value,
+ bool all,
+ Set **found_properties) {
- assert(bus);
- assert(path);
+ int r;
- r = sd_bus_call_method(bus,
- dest,
- path,
- "org.freedesktop.DBus.Properties",
- "GetAll",
- &error,
- &reply,
- "s", "");
- if (r < 0)
- return r;
+ assert(m);
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
if (r < 0)
return r;
- while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
+ while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
const char *name;
const char *contents;
- r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
+ r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &name);
if (r < 0)
return r;
+ if (found_properties) {
+ r = set_ensure_allocated(found_properties, &string_hash_ops);
+ if (r < 0)
+ return log_oom();
+
+ r = set_put(*found_properties, name);
+ if (r < 0 && r != EEXIST)
+ return log_oom();
+ }
+
if (!filter || strv_find(filter, name)) {
- r = sd_bus_message_peek_type(reply, NULL, &contents);
+ r = sd_bus_message_peek_type(m, NULL, &contents);
if (r < 0)
return r;
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
if (r < 0)
return r;
- r = bus_print_property(name, reply, value, all);
+ if (func)
+ r = func(name, m, value, all);
+ if (!func || r == 0)
+ r = bus_print_property(name, m, value, all);
if (r < 0)
return r;
if (r == 0) {
if (all)
printf("%s=[unprintable]\n", name);
/* skip what we didn't read */
- r = sd_bus_message_skip(reply, contents);
+ r = sd_bus_message_skip(m, contents);
if (r < 0)
return r;
}
- r = sd_bus_message_exit_container(reply);
+ r = sd_bus_message_exit_container(m);
if (r < 0)
return r;
} else {
- r = sd_bus_message_skip(reply, "v");
+ r = sd_bus_message_skip(m, "v");
if (r < 0)
return r;
}
- r = sd_bus_message_exit_container(reply);
+ r = sd_bus_message_exit_container(m);
if (r < 0)
return r;
}
if (r < 0)
return r;
- r = sd_bus_message_exit_container(reply);
+ r = sd_bus_message_exit_container(m);
if (r < 0)
return r;
return 0;
}
+int bus_print_all_properties(
+ sd_bus *bus,
+ const char *dest,
+ const char *path,
+ bus_message_print_t func,
+ char **filter,
+ bool value,
+ bool all,
+ Set **found_properties) {
+
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ int r;
+
+ assert(bus);
+ assert(path);
+
+ r = sd_bus_call_method(bus,
+ dest,
+ path,
+ "org.freedesktop.DBus.Properties",
+ "GetAll",
+ &error,
+ &reply,
+ "s", "");
+ if (r < 0)
+ return r;
+
+ return bus_message_print_all_properties(reply, func, filter, value, all, found_properties);
+}
+
int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
sd_id128_t *p = userdata;
const void *v;
@@ -1028,7 +1043,7 @@ int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_err
return 0;
}
-static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
+static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, unsigned flags, sd_bus_error *error, void *userdata) {
char type;
int r;
@@ -1039,7 +1054,7 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
switch (type) {
case SD_BUS_TYPE_STRING: {
- char **p = userdata;
+ const char **p = userdata;
const char *s;
r = sd_bus_message_read_basic(m, type, &s);
@@ -1049,7 +1064,11 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
if (isempty(s))
s = NULL;
- return free_and_strdup(p, s);
+ if (flags & BUS_MAP_STRDUP)
+ return free_and_strdup((char **) userdata, s);
+
+ *p = s;
+ return 0;
}
case SD_BUS_TYPE_ARRAY: {
@@ -1060,21 +1079,21 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
if (r < 0)
return r;
- strv_free(*p);
- *p = l;
- l = NULL;
- return 0;
+ return strv_free_and_replace(*p, l);
}
case SD_BUS_TYPE_BOOLEAN: {
- unsigned b;
- int *p = userdata;
+ int b;
r = sd_bus_message_read_basic(m, type, &b);
if (r < 0)
return r;
- *p = b;
+ if (flags & BUS_MAP_BOOLEAN_AS_BOOL)
+ *(bool*) userdata = b;
+ else
+ *(int*) userdata = b;
+
return 0;
}
@@ -1119,6 +1138,7 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
int bus_message_map_all_properties(
sd_bus_message *m,
const struct bus_properties_map *map,
+ unsigned flags,
sd_bus_error *error,
void *userdata) {
@@ -1161,7 +1181,7 @@ int bus_message_map_all_properties(
if (map[i].set)
r = prop->set(sd_bus_message_get_bus(m), member, m, error, v);
else
- r = map_basic(sd_bus_message_get_bus(m), member, m, error, v);
+ r = map_basic(sd_bus_message_get_bus(m), member, m, flags, error, v);
if (r < 0)
return r;
@@ -1188,6 +1208,7 @@ int bus_message_map_all_properties(
int bus_message_map_properties_changed(
sd_bus_message *m,
const struct bus_properties_map *map,
+ unsigned flags,
sd_bus_error *error,
void *userdata) {
@@ -1197,7 +1218,7 @@ int bus_message_map_properties_changed(
assert(m);
assert(map);
- r = bus_message_map_all_properties(m, map, error, userdata);
+ r = bus_message_map_all_properties(m, map, flags, error, userdata);
if (r < 0)
return r;
@@ -1228,7 +1249,9 @@ int bus_map_all_properties(
const char *destination,
const char *path,
const struct bus_properties_map *map,
+ unsigned flags,
sd_bus_error *error,
+ sd_bus_message **reply,
void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
@@ -1238,6 +1261,7 @@ int bus_map_all_properties(
assert(destination);
assert(path);
assert(map);
+ assert(reply || (flags & BUS_MAP_STRDUP));
r = sd_bus_call_method(
bus,
@@ -1251,7 +1275,14 @@ int bus_map_all_properties(
if (r < 0)
return r;
- return bus_message_map_all_properties(m, map, error, userdata);
+ r = bus_message_map_all_properties(m, map, flags, error, userdata);
+ if (r < 0)
+ return r;
+
+ if (reply)
+ *reply = sd_bus_message_ref(m);
+
+ return r;
}
int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **ret) {
@@ -1271,10 +1302,18 @@ int bus_connect_transport(BusTransport transport, const char *host, bool user, s
#if 0 /// elogind does not support a user bus
if (user)
r = sd_bus_default_user(&bus);
- else
+ else {
+ if (sd_booted() <= 0) {
+ /* Print a friendly message when the local system is actually not running systemd as PID 1. */
+ log_error("System has not been booted with systemd as init system (PID 1). Can't operate.");
+
+ return -EHOSTDOWN;
+ }
#endif // 0
r = sd_bus_default_system(&bus);
-
+#if 0 /// No closing bracket with elogind... Ain't we simple? ;-)
+ }
+#endif // 0
break;
case BUS_TRANSPORT_REMOTE:
@@ -1295,8 +1334,7 @@ int bus_connect_transport(BusTransport transport, const char *host, bool user, s
if (r < 0)
return r;
- *ret = bus;
- bus = NULL;
+ *ret = TAKE_PTR(bus);
return 0;
}
@@ -1317,9 +1355,15 @@ int bus_connect_transport_systemd(BusTransport transport, const char *host, bool
case BUS_TRANSPORT_LOCAL:
if (user)
r = bus_connect_user_systemd(bus);
- else
- r = bus_connect_system_systemd(bus);
+ else {
+ if (sd_booted() <= 0) {
+ /* Print a friendly message when the local system is actually not running systemd as PID 1. */
+ log_error("System has not been booted with systemd as init system (PID 1). Can't operate.");
+ return -EHOSTDOWN;
+ }
+ r = bus_connect_system_systemd(bus);
+ }
break;
case BUS_TRANSPORT_REMOTE:
@@ -1352,6 +1396,25 @@ int bus_property_get_bool(
return sd_bus_message_append_basic(reply, 'b', &b);
}
+int bus_property_set_bool(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *value,
+ void *userdata,
+ sd_bus_error *error) {
+
+ int b, r;
+
+ r = sd_bus_message_read(value, "b", &b);
+ if (r < 0)
+ return r;
+
+ *(bool*) userdata = b;
+ return 0;
+}
+
#if 0 /// UNNEEDED by elogind
int bus_property_get_id128(
sd_bus *bus,
@@ -1566,36 +1629,40 @@ int bus_property_get_rlimit(
void *userdata,
sd_bus_error *error) {
+ const char *is_soft;
struct rlimit *rl;
uint64_t u;
rlim_t x;
- const char *is_soft;
assert(bus);
assert(reply);
assert(userdata);
is_soft = endswith(property, "Soft");
+
rl = *(struct rlimit**) userdata;
if (rl)
x = is_soft ? rl->rlim_cur : rl->rlim_max;
else {
struct rlimit buf = {};
+ const char *s, *p;
int z;
- const char *s;
+ /* Chop off "Soft" suffix */
s = is_soft ? strndupa(property, is_soft - property) : property;
- z = rlimit_from_string(strstr(s, "Limit"));
+ /* Skip over any prefix, such as "Default" */
+ assert_se(p = strstr(s, "Limit"));
+
+ z = rlimit_from_string(p + 5);
assert(z >= 0);
- getrlimit(z, &buf);
+ (void) getrlimit(z, &buf);
x = is_soft ? buf.rlim_cur : buf.rlim_max;
}
- /* rlim_t might have different sizes, let's map
- * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
- * all archs */
+ /* rlim_t might have different sizes, let's map RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on all
+ * archs */
u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x;
return sd_bus_message_append(reply, "t", u);
@@ -1620,3 +1687,253 @@ int bus_track_add_name_many(sd_bus_track *t, char **l) {
return r;
}
#endif // 0
+
+int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *description) {
+ _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
+ const char *e;
+ int r;
+
+ assert(ret);
+
+ /* Match like sd_bus_open_system(), but with the "watch_bind" feature and the Connected() signal turned on. */
+
+ r = sd_bus_new(&bus);
+ if (r < 0)
+ return r;
+
+ if (description) {
+ r = sd_bus_set_description(bus, description);
+ if (r < 0)
+ return r;
+ }
+
+ e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
+ if (!e)
+ e = DEFAULT_SYSTEM_BUS_ADDRESS;
+
+ r = sd_bus_set_address(bus, e);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_set_bus_client(bus, true);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_set_trusted(bus, true);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_negotiate_creds(bus, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_set_watch_bind(bus, true);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_set_connected_signal(bus, true);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_start(bus);
+ if (r < 0)
+ return r;
+
+ *ret = TAKE_PTR(bus);
+
+ return 0;
+}
+
+struct request_name_data {
+ unsigned n_ref;
+
+ const char *name;
+ uint64_t flags;
+ void *userdata;
+};
+
+static void request_name_destroy_callback(void *userdata) {
+ struct request_name_data *data = userdata;
+
+ assert(data);
+ assert(data->n_ref > 0);
+
+ log_info("%s n_ref=%u", __func__, data->n_ref);
+
+ data->n_ref--;
+ if (data->n_ref == 0)
+ free(data);
+}
+
+static int reload_dbus_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
+ struct request_name_data *data = userdata;
+ const sd_bus_error *e;
+ int r;
+
+ assert(data);
+ assert(data->name);
+ assert(data->n_ref > 0);
+
+ e = sd_bus_message_get_error(m);
+ if (e) {
+ log_error_errno(sd_bus_error_get_errno(e), "Failed to reload DBus configuration: %s", e->message);
+ return 1;
+ }
+
+ /* Here, use the default request name handler to avoid an infinite loop of reloading and requesting. */
+ r = sd_bus_request_name_async(sd_bus_message_get_bus(m), NULL, data->name, data->flags, NULL, data->userdata);
+ if (r < 0)
+ log_error_errno(r, "Failed to request name: %m");
+
+ return 1;
+}
+
+static int request_name_handler_may_reload_dbus(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
+ struct request_name_data *data = userdata;
+ uint32_t ret;
+ int r;
+
+ assert(m);
+ assert(data);
+
+ if (sd_bus_message_is_method_error(m, NULL)) {
+ const sd_bus_error *e = sd_bus_message_get_error(m);
+ _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL;
+
+ if (!sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED)) {
+ log_debug_errno(sd_bus_error_get_errno(e),
+ "Unable to request name, failing connection: %s",
+ e->message);
+
+ bus_enter_closing(sd_bus_message_get_bus(m));
+ return 1;
+ }
+
+ log_debug_errno(sd_bus_error_get_errno(e),
+ "Unable to request name, will retry after reloading DBus configuration: %s",
+ e->message);
+
+ /* If systemd-timesyncd.service enables DynamicUser= and dbus.service
+ * started before the dynamic user is realized, then the DBus policy
+ * about timesyncd has not been enabled yet. So, let's try to reload
+ * DBus configuration, and after that request the name again. Note that it
+ * seems that no privileges are necessary to call the following method. */
+
+ r = sd_bus_call_method_async(
+ sd_bus_message_get_bus(m),
+ &slot,
+ "org.freedesktop.DBus",
+ "/org/freedesktop/DBus",
+ "org.freedesktop.DBus",
+ "ReloadConfig",
+ reload_dbus_handler,
+ data, NULL);
+ if (r < 0) {
+ log_error_errno(r, "Failed to reload DBus configuration: %m");
+ bus_enter_closing(sd_bus_message_get_bus(m));
+ return 1;
+ }
+
+ data->n_ref ++;
+ assert_se(sd_bus_slot_set_destroy_callback(slot, request_name_destroy_callback) >= 0);
+
+ r = sd_bus_slot_set_floating(slot, true);
+ if (r < 0)
+ return r;
+
+ return 1;
+ }
+
+ r = sd_bus_message_read(m, "u", &ret);
+ if (r < 0)
+ return r;
+
+ switch (ret) {
+
+ case BUS_NAME_ALREADY_OWNER:
+ log_debug("Already owner of requested service name, ignoring.");
+ return 1;
+
+ case BUS_NAME_IN_QUEUE:
+ log_debug("In queue for requested service name.");
+ return 1;
+
+ case BUS_NAME_PRIMARY_OWNER:
+ log_debug("Successfully acquired requested service name.");
+ return 1;
+
+ case BUS_NAME_EXISTS:
+ log_debug("Requested service name already owned, failing connection.");
+ bus_enter_closing(sd_bus_message_get_bus(m));
+ return 1;
+ }
+
+ log_debug("Unexpected response from RequestName(), failing connection.");
+ bus_enter_closing(sd_bus_message_get_bus(m));
+ return 1;
+}
+
+int bus_request_name_async_may_reload_dbus(sd_bus *bus, sd_bus_slot **ret_slot, const char *name, uint64_t flags, void *userdata) {
+ _cleanup_free_ struct request_name_data *data = NULL;
+ _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL;
+ int r;
+
+ data = new(struct request_name_data, 1);
+ if (!data)
+ return -ENOMEM;
+
+ *data = (struct request_name_data) {
+ .n_ref = 1,
+ .name = name,
+ .flags = flags,
+ .userdata = userdata,
+ };
+
+ r = sd_bus_request_name_async(bus, &slot, name, flags, request_name_handler_may_reload_dbus, data);
+ if (r < 0)
+ return r;
+
+ assert_se(sd_bus_slot_set_destroy_callback(slot, request_name_destroy_callback) >= 0);
+ TAKE_PTR(data);
+
+ if (ret_slot)
+ *ret_slot = TAKE_PTR(slot);
+ else {
+ r = sd_bus_slot_set_floating(slot, true);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
+int bus_reply_pair_array(sd_bus_message *m, char **l) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ char **k, **v;
+ int r;
+
+ assert(m);
+
+ /* Reply to the specified message with a message containing a dictionary put together from the specified
+ * strv */
+
+ r = sd_bus_message_new_method_return(m, &reply);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_open_container(reply, 'a', "{ss}");
+ if (r < 0)
+ return r;
+
+ STRV_FOREACH_PAIR(k, v, l) {
+ r = sd_bus_message_append(reply, "{ss}", *k, *v);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_bus_message_close_container(reply);
+ if (r < 0)
+ return r;
+
+ return sd_bus_send(NULL, reply, NULL);
+}
diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h
index 16147ebaf..e7231bea9 100644
--- a/src/shared/bus-util.h
+++ b/src/shared/bus-util.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You 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 <stddef.h>
#include <stdint.h>
@@ -48,13 +30,19 @@ struct bus_properties_map {
size_t offset;
};
+enum {
+ BUS_MAP_STRDUP = 1 << 0, /* If set, each "s" message is duplicated. Thus, each pointer needs to be freed. */
+ BUS_MAP_BOOLEAN_AS_BOOL = 1 << 1, /* If set, each "b" message is written to a bool pointer. If not set, "b" is written to a int pointer. */
+};
+
int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata);
-int bus_message_map_all_properties(sd_bus_message *m, const struct bus_properties_map *map, sd_bus_error *error, void *userdata);
#if 0 /// UNNEEDED by elogind
-int bus_message_map_properties_changed(sd_bus_message *m, const struct bus_properties_map *map, sd_bus_error *error, void *userdata);
#endif // 0
-int bus_map_all_properties(sd_bus *bus, const char *destination, const char *path, const struct bus_properties_map *map, sd_bus_error *error, void *userdata);
+int bus_message_map_all_properties(sd_bus_message *m, const struct bus_properties_map *map, unsigned flags, sd_bus_error *error, void *userdata);
+int bus_message_map_properties_changed(sd_bus_message *m, const struct bus_properties_map *map, unsigned flags, sd_bus_error *error, void *userdata);
+int bus_map_all_properties(sd_bus *bus, const char *destination, const char *path, const struct bus_properties_map *map,
+ unsigned flags, sd_bus_error *error, sd_bus_message **reply, void *userdata);
#if 0 /// UNNEEDED by elogind
int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name);
@@ -87,10 +75,14 @@ int bus_connect_transport(BusTransport transport, const char *host, bool user, s
#endif // 0
int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus);
+typedef int (*bus_message_print_t) (const char *name, sd_bus_message *m, bool value, bool all);
+
int bus_print_property(const char *name, sd_bus_message *property, bool value, bool all);
-int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool value, bool all);
+int bus_message_print_all_properties(sd_bus_message *m, bus_message_print_t func, char **filter, bool value, bool all, Set **found_properties);
+int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, bus_message_print_t func, char **filter, bool value, bool all, Set **found_properties);
int bus_property_get_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
+int bus_property_set_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error);
#if 0 /// UNNEEDED by elogind
int bus_property_get_id128(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
#endif // 0
@@ -101,7 +93,7 @@ int bus_property_get_id128(sd_bus *bus, const char *path, const char *interface,
assert_cc(sizeof(int) == sizeof(int32_t));
#define bus_property_get_int ((sd_bus_property_get_t) NULL)
-assert_cc(sizeof(unsigned) == sizeof(unsigned));
+assert_cc(sizeof(unsigned) == sizeof(uint32_t));
#define bus_property_get_unsigned ((sd_bus_property_get_t) NULL)
/* On 64bit machines we can use the default serializer for size_t and
@@ -140,7 +132,7 @@ int bus_log_create_error(int r);
#if 0 /// UNNEEDED by elogind
#endif // 0
-#define BUS_DEFINE_PROPERTY_GET_ENUM(function, name, type) \
+#define BUS_DEFINE_PROPERTY_GET_GLOBAL(function, bus_type, val) \
int function(sd_bus *bus, \
const char *path, \
const char *interface, \
@@ -149,23 +141,41 @@ int bus_log_create_error(int r);
void *userdata, \
sd_bus_error *error) { \
\
- const char *value; \
- type *field = userdata; \
- int r; \
- \
assert(bus); \
assert(reply); \
- assert(field); \
\
- value = strempty(name##_to_string(*field)); \
+ return sd_bus_message_append(reply, bus_type, val); \
+ }
+
+#define BUS_DEFINE_PROPERTY_GET2(function, bus_type, data_type, get1, get2) \
+ int function(sd_bus *bus, \
+ const char *path, \
+ const char *interface, \
+ const char *property, \
+ sd_bus_message *reply, \
+ void *userdata, \
+ sd_bus_error *error) { \
+ \
+ data_type *data = userdata; \
\
- r = sd_bus_message_append_basic(reply, 's', value); \
- if (r < 0) \
- return r; \
+ assert(bus); \
+ assert(reply); \
+ assert(data); \
\
- return 1; \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
+ return sd_bus_message_append(reply, bus_type, \
+ get2(get1(data))); \
+ }
+
+#define ident(x) (x)
+#define BUS_DEFINE_PROPERTY_GET(function, bus_type, data_type, get1) \
+ BUS_DEFINE_PROPERTY_GET2(function, bus_type, data_type, get1, ident)
+
+#define ref(x) (*(x))
+#define BUS_DEFINE_PROPERTY_GET_REF(function, bus_type, data_type, get) \
+ BUS_DEFINE_PROPERTY_GET2(function, bus_type, data_type, ref, get)
+
+#define BUS_DEFINE_PROPERTY_GET_ENUM(function, name, type) \
+ BUS_DEFINE_PROPERTY_GET_REF(function, "s", type, name##_to_string)
#define BUS_PROPERTY_DUAL_TIMESTAMP(name, offset, flags) \
SD_BUS_PROPERTY(name, "t", bus_property_get_usec, (offset) + offsetof(struct dual_timestamp, realtime), (flags)), \
@@ -181,3 +191,12 @@ int bus_property_get_rlimit(sd_bus *bus, const char *path, const char *interface
int bus_track_add_name_many(sd_bus_track *t, char **l);
#endif // 0
+
+int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *description);
+static inline int bus_open_system_watch_bind(sd_bus **ret) {
+ return bus_open_system_watch_bind_with_description(ret, NULL);
+}
+
+int bus_request_name_async_may_reload_dbus(sd_bus *bus, sd_bus_slot **ret_slot, const char *name, uint64_t flags, void *userdata);
+
+int bus_reply_pair_array(sd_bus_message *m, char **l);
diff --git a/src/shared/clean-ipc.c b/src/shared/clean-ipc.c
index 3b4231827..52b7bb0e3 100644
--- a/src/shared/clean-ipc.c
+++ b/src/shared/clean-ipc.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <dirent.h>
#include <errno.h>
@@ -54,7 +37,7 @@ static bool match_uid_gid(uid_t subject_uid, gid_t subject_gid, uid_t delete_uid
return false;
}
-static int clean_sysvipc_shm(uid_t delete_uid, gid_t delete_gid) {
+static int clean_sysvipc_shm(uid_t delete_uid, gid_t delete_gid, bool rm) {
_cleanup_fclose_ FILE *f = NULL;
char line[LINE_MAX];
bool first = true;
@@ -92,17 +75,23 @@ static int clean_sysvipc_shm(uid_t delete_uid, gid_t delete_gid) {
if (!match_uid_gid(uid, gid, delete_uid, delete_gid))
continue;
+ if (!rm)
+ return 1;
+
if (shmctl(shmid, IPC_RMID, NULL) < 0) {
/* Ignore entries that are already deleted */
- if (errno == EIDRM || errno == EINVAL)
+ if (IN_SET(errno, EIDRM, EINVAL))
continue;
ret = log_warning_errno(errno,
"Failed to remove SysV shared memory segment %i: %m",
shmid);
- } else
+ } else {
log_debug("Removed SysV shared memory segment %i.", shmid);
+ if (ret == 0)
+ ret = 1;
+ }
}
return ret;
@@ -111,7 +100,7 @@ fail:
return log_warning_errno(errno, "Failed to read /proc/sysvipc/shm: %m");
}
-static int clean_sysvipc_sem(uid_t delete_uid, gid_t delete_gid) {
+static int clean_sysvipc_sem(uid_t delete_uid, gid_t delete_gid, bool rm) {
_cleanup_fclose_ FILE *f = NULL;
char line[LINE_MAX];
bool first = true;
@@ -144,17 +133,23 @@ static int clean_sysvipc_sem(uid_t delete_uid, gid_t delete_gid) {
if (!match_uid_gid(uid, gid, delete_uid, delete_gid))
continue;
+ if (!rm)
+ return 1;
+
if (semctl(semid, 0, IPC_RMID) < 0) {
/* Ignore entries that are already deleted */
- if (errno == EIDRM || errno == EINVAL)
+ if (IN_SET(errno, EIDRM, EINVAL))
continue;
ret = log_warning_errno(errno,
"Failed to remove SysV semaphores object %i: %m",
semid);
- } else
+ } else {
log_debug("Removed SysV semaphore %i.", semid);
+ if (ret == 0)
+ ret = 1;
+ }
}
return ret;
@@ -163,7 +158,7 @@ fail:
return log_warning_errno(errno, "Failed to read /proc/sysvipc/sem: %m");
}
-static int clean_sysvipc_msg(uid_t delete_uid, gid_t delete_gid) {
+static int clean_sysvipc_msg(uid_t delete_uid, gid_t delete_gid, bool rm) {
_cleanup_fclose_ FILE *f = NULL;
char line[LINE_MAX];
bool first = true;
@@ -197,17 +192,23 @@ static int clean_sysvipc_msg(uid_t delete_uid, gid_t delete_gid) {
if (!match_uid_gid(uid, gid, delete_uid, delete_gid))
continue;
+ if (!rm)
+ return 1;
+
if (msgctl(msgid, IPC_RMID, NULL) < 0) {
/* Ignore entries that are already deleted */
- if (errno == EIDRM || errno == EINVAL)
+ if (IN_SET(errno, EIDRM, EINVAL))
continue;
ret = log_warning_errno(errno,
"Failed to remove SysV message queue %i: %m",
msgid);
- } else
+ } else {
log_debug("Removed SysV message queue %i.", msgid);
+ if (ret == 0)
+ ret = 1;
+ }
}
return ret;
@@ -216,7 +217,7 @@ fail:
return log_warning_errno(errno, "Failed to read /proc/sysvipc/msg: %m");
}
-static int clean_posix_shm_internal(DIR *dir, uid_t uid, gid_t gid) {
+static int clean_posix_shm_internal(DIR *dir, uid_t uid, gid_t gid, bool rm) {
struct dirent *de;
int ret = 0, r;
@@ -236,9 +237,6 @@ static int clean_posix_shm_internal(DIR *dir, uid_t uid, gid_t gid) {
continue;
}
- if (!match_uid_gid(st.st_uid, st.st_gid, uid, gid))
- continue;
-
if (S_ISDIR(st.st_mode)) {
_cleanup_closedir_ DIR *kid;
@@ -247,29 +245,47 @@ static int clean_posix_shm_internal(DIR *dir, uid_t uid, gid_t gid) {
if (errno != ENOENT)
ret = log_warning_errno(errno, "Failed to enter shared memory directory %s: %m", de->d_name);
} else {
- r = clean_posix_shm_internal(kid, uid, gid);
+ r = clean_posix_shm_internal(kid, uid, gid, rm);
if (r < 0)
ret = r;
}
+ if (!match_uid_gid(st.st_uid, st.st_gid, uid, gid))
+ continue;
+
+ if (!rm)
+ return 1;
+
if (unlinkat(dirfd(dir), de->d_name, AT_REMOVEDIR) < 0) {
if (errno == ENOENT)
continue;
ret = log_warning_errno(errno, "Failed to remove POSIX shared memory directory %s: %m", de->d_name);
- } else
+ } else {
log_debug("Removed POSIX shared memory directory %s", de->d_name);
+ if (ret == 0)
+ ret = 1;
+ }
} else {
+ if (!match_uid_gid(st.st_uid, st.st_gid, uid, gid))
+ continue;
+
+ if (!rm)
+ return 1;
+
if (unlinkat(dirfd(dir), de->d_name, 0) < 0) {
if (errno == ENOENT)
continue;
ret = log_warning_errno(errno, "Failed to remove POSIX shared memory segment %s: %m", de->d_name);
- } else
+ } else {
log_debug("Removed POSIX shared memory segment %s", de->d_name);
+ if (ret == 0)
+ ret = 1;
+ }
}
}
@@ -279,7 +295,7 @@ fail:
return log_warning_errno(errno, "Failed to read /dev/shm: %m");
}
-static int clean_posix_shm(uid_t uid, gid_t gid) {
+static int clean_posix_shm(uid_t uid, gid_t gid, bool rm) {
_cleanup_closedir_ DIR *dir = NULL;
dir = opendir("/dev/shm");
@@ -290,11 +306,11 @@ static int clean_posix_shm(uid_t uid, gid_t gid) {
return log_warning_errno(errno, "Failed to open /dev/shm: %m");
}
- return clean_posix_shm_internal(dir, uid, gid);
+ return clean_posix_shm_internal(dir, uid, gid, rm);
}
#if 0 /// UNNEEDED by elogind
-static int clean_posix_mq(uid_t uid, gid_t gid) {
+static int clean_posix_mq(uid_t uid, gid_t gid, bool rm) {
_cleanup_closedir_ DIR *dir = NULL;
struct dirent *de;
int ret = 0;
@@ -327,6 +343,9 @@ static int clean_posix_mq(uid_t uid, gid_t gid) {
if (!match_uid_gid(st.st_uid, st.st_gid, uid, gid))
continue;
+ if (!rm)
+ return 1;
+
fn[0] = '/';
strcpy(fn+1, de->d_name);
@@ -337,8 +356,11 @@ static int clean_posix_mq(uid_t uid, gid_t gid) {
ret = log_warning_errno(errno,
"Failed to unlink POSIX message queue %s: %m",
fn);
- } else
+ } else {
log_debug("Removed POSIX message queue %s", fn);
+ if (ret == 0)
+ ret = 1;
+ }
}
return ret;
@@ -348,48 +370,89 @@ fail:
}
#endif // 0
-int clean_ipc(uid_t uid, gid_t gid) {
+int clean_ipc_internal(uid_t uid, gid_t gid, bool rm) {
int ret = 0, r;
+ /* If 'rm' is true, clean all IPC objects owned by either the specified UID or the specified GID. Return the
+ * last error encountered or == 0 if no matching IPC objects have been found or > 0 if matching IPC objects
+ * have been found and have been removed.
+ *
+ * If 'rm' is false, just search for IPC objects owned by either the specified UID or the specified GID. In
+ * this case we return < 0 on error, > 0 if we found a matching object, == 0 if we didn't.
+ *
+ * As special rule: if UID/GID is specified as root we'll silently not clean up things, and always claim that
+ * there are IPC objects for it. */
+
+ if (uid == 0) {
+ if (!rm)
+ return 1;
+
+ uid = UID_INVALID;
+ }
+ if (gid == 0) {
+ if (!rm)
+ return 1;
+
+ gid = GID_INVALID;
+ }
+
/* Anything to do? */
if (!uid_is_valid(uid) && !gid_is_valid(gid))
return 0;
- /* Refuse to clean IPC of the root user */
- if (uid == 0 && gid == 0)
- return 0;
-
- r = clean_sysvipc_shm(uid, gid);
- if (r < 0)
- ret = r;
+ r = clean_sysvipc_shm(uid, gid, rm);
+ if (r != 0) {
+ if (!rm)
+ return r;
+ if (ret == 0)
+ ret = r;
+ }
- r = clean_sysvipc_sem(uid, gid);
- if (r < 0)
- ret = r;
+#if 0 /// elogind does not use mq_open anywhere
+#endif // 0
+ r = clean_sysvipc_sem(uid, gid, rm);
+ if (r != 0) {
+ if (!rm)
+ return r;
+ if (ret == 0)
+ ret = r;
+ }
- r = clean_sysvipc_msg(uid, gid);
- if (r < 0)
- ret = r;
+ r = clean_sysvipc_msg(uid, gid, rm);
+ if (r != 0) {
+ if (!rm)
+ return r;
+ if (ret == 0)
+ ret = r;
+ }
- r = clean_posix_shm(uid, gid);
- if (r < 0)
- ret = r;
+ r = clean_posix_shm(uid, gid, rm);
+ if (r != 0) {
+ if (!rm)
+ return r;
+ if (ret == 0)
+ ret = r;
+ }
-#if 0 /// elogind does not use mq_open anywhere
- r = clean_posix_mq(uid, gid);
- if (r < 0)
- ret = r;
+#if 0 /// Nothing in elogind uses mqueues
+ r = clean_posix_mq(uid, gid, rm);
+ if (r != 0) {
+ if (!rm)
+ return r;
+ if (ret == 0)
+ ret = r;
+ }
#endif // 0
return ret;
}
int clean_ipc_by_uid(uid_t uid) {
- return clean_ipc(uid, GID_INVALID);
+ return clean_ipc_internal(uid, GID_INVALID, true);
}
#if 0 /// UNNEEDED by elogind
int clean_ipc_by_gid(gid_t gid) {
- return clean_ipc(UID_INVALID, gid);
+ return clean_ipc_internal(UID_INVALID, gid, true);
}
#endif // 0
diff --git a/src/shared/clean-ipc.h b/src/shared/clean-ipc.h
index 7cd896df0..7057ae6ae 100644
--- a/src/shared/clean-ipc.h
+++ b/src/shared/clean-ipc.h
@@ -1,28 +1,19 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
+#include <sys/types.h>
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+#include "user-util.h"
-#include <sys/types.h>
+int clean_ipc_internal(uid_t uid, gid_t gid, bool rm);
-int clean_ipc(uid_t uid, gid_t gid);
+/* Remove all IPC objects owned by the specified UID or GID */
int clean_ipc_by_uid(uid_t uid);
#if 0 /// UNNEEDED by elogind
int clean_ipc_by_gid(gid_t gid);
#endif // 0
+
+/* Check if any IPC object owned by the specified UID or GID exists, returns > 0 if so, == 0 if not */
+static inline int search_ipc(uid_t uid, gid_t gid) {
+ return clean_ipc_internal(uid, gid, false);
+}
diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c
index 7b3ac8999..e65fee5bc 100644
--- a/src/shared/conf-parser.c
+++ b/src/shared/conf-parser.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <limits.h>
@@ -28,21 +11,29 @@
#include "alloc-util.h"
#include "conf-files.h"
#include "conf-parser.h"
+#include "def.h"
#include "extract-word.h"
#include "fd-util.h"
+#include "fileio.h"
#include "fs-util.h"
#include "log.h"
#include "macro.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
+//#include "rlimit-util.h"
#include "signal-util.h"
+#include "socket-util.h"
#include "string-util.h"
#include "strv.h"
#include "syslog-util.h"
#include "time-util.h"
#include "utf8.h"
+/// Additional includes needed by elogind
+#include "def.h"
+#include "fileio.h"
+
int config_item_table_lookup(
const void *table,
const char *section,
@@ -118,17 +109,18 @@ int config_item_perf_lookup(
}
/* Run the user supplied parser for an assignment */
-static int next_assignment(const char *unit,
- const char *filename,
- unsigned line,
- ConfigItemLookup lookup,
- const void *table,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- const char *rvalue,
- bool relaxed,
- void *userdata) {
+static int next_assignment(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ ConfigItemLookup lookup,
+ const void *table,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ const char *rvalue,
+ ConfigParseFlags flags,
+ void *userdata) {
ConfigParserCallback func = NULL;
int ltype = 0;
@@ -154,28 +146,28 @@ static int next_assignment(const char *unit,
}
/* Warn about unknown non-extension fields. */
- if (!relaxed && !startswith(lvalue, "X-"))
+ if (!(flags & CONFIG_PARSE_RELAXED) && !startswith(lvalue, "X-"))
log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown lvalue '%s' in section '%s'", lvalue, section);
return 0;
}
-/* Parse a variable assignment line */
-static int parse_line(const char* unit,
- const char *filename,
- unsigned line,
- const char *sections,
- ConfigItemLookup lookup,
- const void *table,
- bool relaxed,
- bool allow_include,
- char **section,
- unsigned *section_line,
- bool *section_ignored,
- char *l,
- void *userdata) {
+/* Parse a single logical line */
+static int parse_line(
+ const char* unit,
+ const char *filename,
+ unsigned line,
+ const char *sections,
+ ConfigItemLookup lookup,
+ const void *table,
+ ConfigParseFlags flags,
+ char **section,
+ unsigned *section_line,
+ bool *section_ignored,
+ char *l,
+ void *userdata) {
- char *e;
+ char *e, *include;
assert(filename);
assert(line > 0);
@@ -183,14 +175,14 @@ static int parse_line(const char* unit,
assert(l);
l = strstrip(l);
-
if (!*l)
return 0;
if (strchr(COMMENTS "\n", *l))
return 0;
- if (startswith(l, ".include ")) {
+ include = first_word(l, ".include");
+ if (include) {
_cleanup_free_ char *fn = NULL;
/* .includes are a bad idea, we only support them here
@@ -202,18 +194,25 @@ static int parse_line(const char* unit,
*
* Support for them should be eventually removed. */
- if (!allow_include) {
+ if (!(flags & CONFIG_PARSE_ALLOW_INCLUDE)) {
log_syntax(unit, LOG_ERR, filename, line, 0, ".include not allowed here. Ignoring.");
return 0;
}
- fn = file_in_same_dir(filename, strstrip(l+9));
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ ".include directives are deprecated, and support for them will be removed in a future version of elogind. "
+ "Please use drop-in files instead.");
+
+ fn = file_in_same_dir(filename, strstrip(include));
if (!fn)
return -ENOMEM;
- return config_parse(unit, fn, NULL, sections, lookup, table, relaxed, false, false, userdata);
+ return config_parse(unit, fn, NULL, sections, lookup, table, flags, userdata);
}
+ if (!utf8_is_valid(l))
+ return log_syntax_invalid_utf8(unit, LOG_WARNING, filename, line, l);
+
if (*l == '[') {
size_t k;
char *n;
@@ -232,7 +231,7 @@ static int parse_line(const char* unit,
if (sections && !nulstr_contains(sections, n)) {
- if (!relaxed && !startswith(n, "X-"))
+ if (!(flags & CONFIG_PARSE_RELAXED) && !startswith(n, "X-"))
log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown section '%s'. Ignoring.", n);
free(n);
@@ -240,8 +239,7 @@ static int parse_line(const char* unit,
*section_line = 0;
*section_ignored = true;
} else {
- free(*section);
- *section = n;
+ free_and_replace(*section, n);
*section_line = line;
*section_ignored = false;
}
@@ -251,7 +249,7 @@ static int parse_line(const char* unit,
if (sections && !*section) {
- if (!relaxed && !*section_ignored)
+ if (!(flags & CONFIG_PARSE_RELAXED) && !*section_ignored)
log_syntax(unit, LOG_WARNING, filename, line, 0, "Assignment outside of section. Ignoring.");
return 0;
@@ -275,7 +273,7 @@ static int parse_line(const char* unit,
*section_line,
strstrip(l),
strstrip(e),
- relaxed,
+ flags,
userdata);
}
@@ -286,15 +284,13 @@ int config_parse(const char *unit,
const char *sections,
ConfigItemLookup lookup,
const void *table,
- bool relaxed,
- bool allow_include,
- bool warn,
+ ConfigParseFlags flags,
void *userdata) {
_cleanup_free_ char *section = NULL, *continuation = NULL;
_cleanup_fclose_ FILE *ours = NULL;
unsigned line = 0, section_line = 0;
- bool section_ignored = false, allow_bom = true;
+ bool section_ignored = false;
int r;
assert(filename);
@@ -305,9 +301,9 @@ int config_parse(const char *unit,
if (!f) {
/* Only log on request, except for ENOENT,
* since we return 0 to the caller. */
- if (warn || errno == ENOENT)
- log_full(errno == ENOENT ? LOG_DEBUG : LOG_ERR,
- "Failed to open configuration file '%s': %m", filename);
+ if ((flags & CONFIG_PARSE_WARN) || errno == ENOENT)
+ log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
+ "Failed to open configuration file '%s': %m", filename);
return errno == ENOENT ? 0 : -errno;
}
}
@@ -315,33 +311,51 @@ int config_parse(const char *unit,
fd_warn_permissions(filename, fileno(f));
for (;;) {
- char buf[LINE_MAX], *l, *p, *c = NULL, *e;
+ _cleanup_free_ char *buf = NULL;
bool escaped = false;
+ char *l, *p, *e;
- if (!fgets(buf, sizeof buf, f)) {
- if (feof(f))
- break;
+ r = read_line(f, LONG_LINE_MAX, &buf);
+ if (r == 0)
+ break;
+ if (r == -ENOBUFS) {
+ if (flags & CONFIG_PARSE_WARN)
+ log_error_errno(r, "%s:%u: Line too long", filename, line);
- return log_error_errno(errno, "Failed to read configuration file '%s': %m", filename);
+ return r;
+ }
+ if (r < 0) {
+ if (CONFIG_PARSE_WARN)
+ log_error_errno(r, "%s:%u: Error while reading configuration file: %m", filename, line);
+
+ return r;
}
l = buf;
- if (allow_bom && startswith(l, UTF8_BYTE_ORDER_MARK))
- l += strlen(UTF8_BYTE_ORDER_MARK);
- allow_bom = false;
+ if (!(flags & CONFIG_PARSE_REFUSE_BOM)) {
+ char *q;
- truncate_nl(l);
+ q = startswith(buf, UTF8_BYTE_ORDER_MARK);
+ if (q) {
+ l = q;
+ flags |= CONFIG_PARSE_REFUSE_BOM;
+ }
+ }
if (continuation) {
- c = strappend(continuation, l);
- if (!c) {
- if (warn)
+ if (strlen(continuation) + strlen(l) > LONG_LINE_MAX) {
+ if (flags & CONFIG_PARSE_WARN)
+ log_error("%s:%u: Continuation line too long", filename, line);
+ return -ENOBUFS;
+ }
+
+ if (!strextend(&continuation, l, NULL)) {
+ if (flags & CONFIG_PARSE_WARN)
log_oom();
return -ENOMEM;
}
- continuation = mfree(continuation);
- p = c;
+ p = continuation;
} else
p = l;
@@ -355,12 +369,10 @@ int config_parse(const char *unit,
if (escaped) {
*(e-1) = ' ';
- if (c)
- continuation = c;
- else {
+ if (!continuation) {
continuation = strdup(l);
if (!continuation) {
- if (warn)
+ if (flags & CONFIG_PARSE_WARN)
log_oom();
return -ENOMEM;
}
@@ -375,19 +387,37 @@ int config_parse(const char *unit,
sections,
lookup,
table,
- relaxed,
- allow_include,
+ flags,
&section,
&section_line,
&section_ignored,
p,
userdata);
- free(c);
+ if (r < 0) {
+ if (flags & CONFIG_PARSE_WARN)
+ log_warning_errno(r, "%s:%u: Failed to parse file: %m", filename, line);
+ return r;
+ }
+
+ continuation = mfree(continuation);
+ }
+ if (continuation) {
+ r = parse_line(unit,
+ filename,
+ ++line,
+ sections,
+ lookup,
+ table,
+ flags,
+ &section,
+ &section_line,
+ &section_ignored,
+ continuation,
+ userdata);
if (r < 0) {
- if (warn)
- log_warning_errno(r, "Failed to parse file '%s': %m",
- filename);
+ if (flags & CONFIG_PARSE_WARN)
+ log_warning_errno(r, "%s:%u: Failed to parse file: %m", filename, line);
return r;
}
}
@@ -401,20 +431,20 @@ static int config_parse_many_files(
const char *sections,
ConfigItemLookup lookup,
const void *table,
- bool relaxed,
+ ConfigParseFlags flags,
void *userdata) {
char **fn;
int r;
if (conf_file) {
- r = config_parse(NULL, conf_file, NULL, sections, lookup, table, relaxed, false, true, userdata);
+ r = config_parse(NULL, conf_file, NULL, sections, lookup, table, flags, userdata);
if (r < 0)
return r;
}
STRV_FOREACH(fn, files) {
- r = config_parse(NULL, *fn, NULL, sections, lookup, table, relaxed, false, true, userdata);
+ r = config_parse(NULL, *fn, NULL, sections, lookup, table, flags, userdata);
if (r < 0)
return r;
}
@@ -429,18 +459,17 @@ int config_parse_many_nulstr(
const char *sections,
ConfigItemLookup lookup,
const void *table,
- bool relaxed,
+ ConfigParseFlags flags,
void *userdata) {
_cleanup_strv_free_ char **files = NULL;
int r;
- r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
+ r = conf_files_list_nulstr(&files, ".conf", NULL, 0, conf_file_dirs);
if (r < 0)
return r;
- return config_parse_many_files(conf_file, files,
- sections, lookup, table, relaxed, userdata);
+ return config_parse_many_files(conf_file, files, sections, lookup, table, flags, userdata);
}
#if 0 /// UNNEEDED by elogind
@@ -452,7 +481,7 @@ int config_parse_many(
const char *sections,
ConfigItemLookup lookup,
const void *table,
- bool relaxed,
+ ConfigParseFlags flags,
void *userdata) {
_cleanup_strv_free_ char **dropin_dirs = NULL;
@@ -465,45 +494,16 @@ int config_parse_many(
if (r < 0)
return r;
- r = conf_files_list_strv(&files, ".conf", NULL, (const char* const*) dropin_dirs);
+ r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char* const*) dropin_dirs);
if (r < 0)
return r;
- return config_parse_many_files(conf_file, files,
- sections, lookup, table, relaxed, userdata);
+ return config_parse_many_files(conf_file, files, sections, lookup, table, flags, userdata);
}
#endif // 0
#define DEFINE_PARSER(type, vartype, conv_func) \
- int config_parse_##type( \
- const char *unit, \
- const char *filename, \
- unsigned line, \
- const char *section, \
- unsigned section_line, \
- const char *lvalue, \
- int ltype, \
- const char *rvalue, \
- void *data, \
- void *userdata) { \
- \
- vartype *i = data; \
- int r; \
- \
- assert(filename); \
- assert(lvalue); \
- assert(rvalue); \
- assert(data); \
- \
- r = conv_func(rvalue, i); \
- if (r < 0) \
- log_syntax(unit, LOG_ERR, filename, line, r, \
- "Failed to parse %s value, ignoring: %s", \
- #type, rvalue); \
- \
- return 0; \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
+ DEFINE_CONFIG_PARSE_PTR(config_parse_##type, conv_func, vartype, "Failed to parse " #type " value")
DEFINE_PARSER(int, int, safe_atoi);
DEFINE_PARSER(long, long, safe_atoli);
@@ -519,6 +519,7 @@ DEFINE_PARSER(double, double, safe_atod);
DEFINE_PARSER(nsec, nsec_t, parse_nsec);
#endif // 0
DEFINE_PARSER(sec, usec_t, parse_sec);
+#if 0 /// UNNEEDED by elogind
DEFINE_PARSER(mode, mode_t, parse_mode);
int config_parse_iec_size(const char* unit,
@@ -551,17 +552,17 @@ int config_parse_iec_size(const char* unit,
return 0;
}
-#if 0 /// UNNEEDED by elogind
-int config_parse_si_size(const char* unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_si_size(
+ const char* unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
size_t *sz = data;
uint64_t v;
@@ -582,16 +583,17 @@ int config_parse_si_size(const char* unit,
return 0;
}
-int config_parse_iec_uint64(const char* unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_iec_uint64(
+ const char* unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
uint64_t *bytes = data;
int r;
@@ -637,7 +639,7 @@ int config_parse_bool(const char* unit,
return fatal ? -ENOEXEC : 0;
}
- *b = !!k;
+ *b = k;
return 0;
}
@@ -688,32 +690,20 @@ int config_parse_string(
void *data,
void *userdata) {
- char **s = data, *n;
+ char **s = data;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
- if (!utf8_is_valid(rvalue)) {
- log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
- return 0;
- }
-
- if (isempty(rvalue))
- n = NULL;
- else {
- n = strdup(rvalue);
- if (!n)
- return log_oom();
- }
-
- free(*s);
- *s = n;
+ if (free_and_strdup(s, empty_to_null(rvalue)) < 0)
+ return log_oom();
return 0;
}
+#if 0 /// UNNEEDED by elogind
int config_parse_path(
const char *unit,
const char *filename,
@@ -726,48 +716,43 @@ int config_parse_path(
void *data,
void *userdata) {
- char **s = data, *n;
+ _cleanup_free_ char *n = NULL;
bool fatal = ltype;
+ char **s = data;
+ int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
- if (!utf8_is_valid(rvalue)) {
- log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
- return fatal ? -ENOEXEC : 0;
- }
-
- if (!path_is_absolute(rvalue)) {
- log_syntax(unit, LOG_ERR, filename, line, 0,
- "Not an absolute path%s: %s",
- fatal ? "" : ", ignoring", rvalue);
- return fatal ? -ENOEXEC : 0;
- }
+ if (isempty(rvalue))
+ goto finalize;
n = strdup(rvalue);
if (!n)
return log_oom();
- path_kill_slashes(n);
-
- free(*s);
- *s = n;
+ r = path_simplify_and_warn(n, PATH_CHECK_ABSOLUTE | (fatal ? PATH_CHECK_FATAL : 0), unit, filename, line, lvalue);
+ if (r < 0)
+ return fatal ? -ENOEXEC : 0;
- return 0;
+finalize:
+ return free_and_replace(*s, n);
}
+#endif // 0
-int config_parse_strv(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_strv(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
char ***sv = data;
int r;
@@ -778,19 +763,7 @@ int config_parse_strv(const char *unit,
assert(data);
if (isempty(rvalue)) {
- char **empty;
-
- /* Empty assignment resets the list. As a special rule
- * we actually fill in a real empty array here rather
- * than NULL, since some code wants to know if
- * something was set at all... */
- empty = new0(char*, 1);
- if (!empty)
- return log_oom();
-
- strv_free(*sv);
- *sv = empty;
-
+ *sv = strv_free(*sv);
return 0;
}
@@ -807,11 +780,6 @@ int config_parse_strv(const char *unit,
break;
}
- if (!utf8_is_valid(word)) {
- log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, word);
- free(word);
- continue;
- }
r = strv_consume(sv, word);
if (r < 0)
return log_oom();
@@ -821,7 +789,7 @@ int config_parse_strv(const char *unit,
}
#if 0 /// UNNEEDED by elogind
-int config_parse_log_facility(
+int config_parse_warn_compat(
const char *unit,
const char *filename,
unsigned line,
@@ -833,6 +801,40 @@ int config_parse_log_facility(
void *data,
void *userdata) {
+ Disabled reason = ltype;
+
+ switch(reason) {
+
+ case DISABLED_CONFIGURATION:
+ log_syntax(unit, LOG_DEBUG, filename, line, 0,
+ "Support for option %s= has been disabled at compile time and it is ignored", lvalue);
+ break;
+
+ case DISABLED_LEGACY:
+ log_syntax(unit, LOG_INFO, filename, line, 0,
+ "Support for option %s= has been removed and it is ignored", lvalue);
+ break;
+
+ case DISABLED_EXPERIMENTAL:
+ log_syntax(unit, LOG_INFO, filename, line, 0,
+ "Support for option %s= has not yet been enabled and it is ignored", lvalue);
+ break;
+ }
+
+ return 0;
+}
+
+int config_parse_log_facility(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
int *o = data, x;
@@ -851,7 +853,6 @@ int config_parse_log_facility(
return 0;
}
-#endif // 0
int config_parse_log_level(
const char *unit,
@@ -865,7 +866,6 @@ int config_parse_log_level(
void *data,
void *userdata) {
-
int *o = data, x;
assert(filename);
@@ -879,7 +879,11 @@ int config_parse_log_level(
return 0;
}
- *o = (*o & LOG_FACMASK) | x;
+ if (*o < 0) /* if it wasn't initialized so far, assume zero facility */
+ *o = x;
+ else
+ *o = (*o & LOG_FACMASK) | x;
+
return 0;
}
@@ -902,7 +906,7 @@ int config_parse_signal(
assert(rvalue);
assert(sig);
- r = signal_from_string_try_harder(rvalue);
+ r = signal_from_string(rvalue);
if (r <= 0) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse signal name, ignoring: %s", rvalue);
return 0;
@@ -912,7 +916,6 @@ int config_parse_signal(
return 0;
}
-#if 0 /// UNNEEDED by elogind
int config_parse_personality(
const char *unit,
const char *filename,
@@ -932,10 +935,14 @@ int config_parse_personality(
assert(rvalue);
assert(personality);
- p = personality_from_string(rvalue);
- if (p == PERSONALITY_INVALID) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse personality, ignoring: %s", rvalue);
- return 0;
+ if (isempty(rvalue))
+ p = PERSONALITY_INVALID;
+ else {
+ p = personality_from_string(rvalue);
+ if (p == PERSONALITY_INVALID) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse personality, ignoring: %s", rvalue);
+ return 0;
+ }
}
*personality = p;
@@ -1015,4 +1022,224 @@ int config_parse_ip_port(
return 0;
}
+
+int config_parse_join_controllers(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ char ****ret = data;
+ const char *whole_rvalue = rvalue;
+ unsigned n = 0;
+ _cleanup_(strv_free_freep) char ***controllers = NULL;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(ret);
+
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
+ char **l;
+ int r;
+
+ r = extract_first_word(&rvalue, &word, NULL, EXTRACT_QUOTES);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid value for %s: %s", lvalue, whole_rvalue);
+ return r;
+ }
+ if (r == 0)
+ break;
+
+ l = strv_split(word, ",");
+ if (!l)
+ return log_oom();
+ strv_uniq(l);
+
+ if (strv_length(l) <= 1) {
+ strv_free(l);
+ continue;
+ }
+
+ if (!controllers) {
+ controllers = new(char**, 2);
+ if (!controllers) {
+ strv_free(l);
+ return log_oom();
+ }
+
+ controllers[0] = l;
+ 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 = controllers; *a; a++)
+ if (strv_overlap(*a, l)) {
+ if (strv_extend_strv(&l, *a, false) < 0) {
+ strv_free(l);
+ strv_free_free(t);
+ return log_oom();
+ }
+
+ } 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(controllers);
+ controllers = t;
+ }
+ }
+ if (!isempty(rvalue))
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
+
+ /* As a special case, return a single empty strv, to override the default */
+ if (!controllers) {
+ controllers = new(char**, 2);
+ if (!controllers)
+ return log_oom();
+ controllers[0] = strv_new(NULL, NULL);
+ if (!controllers[0])
+ return log_oom();
+ controllers[1] = NULL;
+ }
+
+ strv_free_free(*ret);
+ *ret = TAKE_PTR(controllers);
+
+ return 0;
+}
+
+int config_parse_mtu(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ uint32_t *mtu = data;
+ int r;
+
+ assert(rvalue);
+ assert(mtu);
+
+ r = parse_mtu(ltype, rvalue, mtu);
+ if (r == -ERANGE) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Maximum transfer unit (MTU) value out of range. Permitted range is %" PRIu32 "…%" PRIu32 ", ignoring: %s",
+ (uint32_t) (ltype == AF_INET6 ? IPV6_MIN_MTU : IPV4_MIN_MTU), (uint32_t) UINT32_MAX,
+ rvalue);
+ return 0;
+ }
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to parse MTU value '%s', ignoring: %m", rvalue);
+ return 0;
+ }
+
+ return 0;
+}
+
+int config_parse_rlimit(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ struct rlimit **rl = data, d = {};
+ int r;
+
+ assert(rvalue);
+ assert(rl);
+
+ r = rlimit_parse(ltype, rvalue, &d);
+ if (r == -EILSEQ) {
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Soft resource limit chosen higher than hard limit, ignoring: %s", rvalue);
+ return 0;
+ }
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (rl[ltype])
+ *rl[ltype] = d;
+ else {
+ rl[ltype] = newdup(struct rlimit, &d, 1);
+ if (!rl[ltype])
+ return log_oom();
+ }
+
+ return 0;
+}
+
+int config_parse_permille(const char* unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ unsigned *permille = data;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(permille);
+
+ r = parse_permille(rvalue);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to parse permille value, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ *permille = (unsigned) r;
+
+ return 0;
+}
#endif // 0
diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h
index 4e5bbccae..50ddbc3a4 100644
--- a/src/shared/conf-parser.h
+++ b/src/shared/conf-parser.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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 <errno.h>
#include <stdbool.h>
#include <stddef.h>
@@ -29,20 +11,35 @@
#include "log.h"
#include "macro.h"
-/* An abstract parser for simple, line based, shallow configuration
- * files consisting of variable assignments only. */
+/* An abstract parser for simple, line based, shallow configuration files consisting of variable assignments only. */
+
+typedef enum ConfigParseFlags {
+ CONFIG_PARSE_RELAXED = 1 << 0,
+ CONFIG_PARSE_ALLOW_INCLUDE = 1 << 1,
+ CONFIG_PARSE_WARN = 1 << 2,
+ CONFIG_PARSE_REFUSE_BOM = 1 << 3,
+} ConfigParseFlags;
+
+/* Argument list for parsers of specific configuration settings. */
+#define CONFIG_PARSER_ARGUMENTS \
+ const char *unit, \
+ const char *filename, \
+ unsigned line, \
+ const char *section, \
+ unsigned section_line, \
+ const char *lvalue, \
+ int ltype, \
+ const char *rvalue, \
+ void *data, \
+ void *userdata
/* Prototype for a parser for a specific configuration setting */
-typedef int (*ConfigParserCallback)(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata);
+typedef int (*ConfigParserCallback)(CONFIG_PARSER_ARGUMENTS);
+
+/* A macro declaring the a function prototype, following the typedef above, simply because it's so cumbersomely long
+ * otherwise. (And current emacs gets irritatingly slow when editing files that contain lots of very long function
+ * prototypes on the same screen…) */
+#define CONFIG_PARSER_PROTOTYPE(name) int name(CONFIG_PARSER_ARGUMENTS)
/* Wraps information for parsing a specific configuration variable, to
* be stored in a simple array */
@@ -91,9 +88,7 @@ int config_parse(
const char *sections, /* nulstr */
ConfigItemLookup lookup,
const void *table,
- bool relaxed,
- bool allow_include,
- bool warn,
+ ConfigParseFlags flags,
void *userdata);
int config_parse_many_nulstr(
@@ -102,7 +97,7 @@ int config_parse_many_nulstr(
const char *sections, /* nulstr */
ConfigItemLookup lookup,
const void *table,
- bool relaxed,
+ ConfigParseFlags flags,
void *userdata);
#if 0 /// UNNEEDED by elogind
@@ -113,61 +108,115 @@ int config_parse_many(
const char *sections, /* nulstr */
ConfigItemLookup lookup,
const void *table,
- bool relaxed,
+ ConfigParseFlags flags,
void *userdata);
#endif // 0
-/* Generic parsers */
-int config_parse_int(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unsigned(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_long(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-#if 0 /// UNNEEDED by elogind
-int config_parse_uint8(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_uint16(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_uint32(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-#endif // 0
-int config_parse_uint64(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_double(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_iec_size(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_int);
+CONFIG_PARSER_PROTOTYPE(config_parse_unsigned);
+CONFIG_PARSER_PROTOTYPE(config_parse_long);
+CONFIG_PARSER_PROTOTYPE(config_parse_uint8);
+CONFIG_PARSER_PROTOTYPE(config_parse_uint16);
+CONFIG_PARSER_PROTOTYPE(config_parse_uint32);
+CONFIG_PARSER_PROTOTYPE(config_parse_uint64);
+CONFIG_PARSER_PROTOTYPE(config_parse_double);
#if 0 /// UNNEEDED by elogind
-int config_parse_si_size(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_iec_uint64(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_iec_size);
+CONFIG_PARSER_PROTOTYPE(config_parse_si_size);
+CONFIG_PARSER_PROTOTYPE(config_parse_iec_uint64);
#endif // 0
-int config_parse_bool(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_bool);
#if 0 /// UNNEEDED by elogind
-int config_parse_tristate(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_tristate);
#endif // 0
-int config_parse_string(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_path(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_strv(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_sec(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_string);
#if 0 /// UNNEEDED by elogind
-int config_parse_nsec(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_path);
#endif // 0
-int config_parse_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_strv);
+CONFIG_PARSER_PROTOTYPE(config_parse_sec);
#if 0 /// UNNEEDED by elogind
-int config_parse_log_facility(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-#endif // 0
-int config_parse_log_level(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_signal(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-#if 0 /// UNNEEDED by elogind
-int config_parse_personality(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_ifname(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_ip_port(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_nsec);
+CONFIG_PARSER_PROTOTYPE(config_parse_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_warn_compat);
+CONFIG_PARSER_PROTOTYPE(config_parse_log_facility);
+CONFIG_PARSER_PROTOTYPE(config_parse_log_level);
+CONFIG_PARSER_PROTOTYPE(config_parse_signal);
+CONFIG_PARSER_PROTOTYPE(config_parse_personality);
+CONFIG_PARSER_PROTOTYPE(config_parse_permille);
+CONFIG_PARSER_PROTOTYPE(config_parse_ifname);
+CONFIG_PARSER_PROTOTYPE(config_parse_ip_port);
+CONFIG_PARSER_PROTOTYPE(config_parse_join_controllers);
+CONFIG_PARSER_PROTOTYPE(config_parse_mtu);
+CONFIG_PARSER_PROTOTYPE(config_parse_rlimit);
#endif // 0
-#define DEFINE_CONFIG_PARSE_ENUM(function,name,type,msg) \
- int function(const char *unit, \
- const char *filename, \
- unsigned line, \
- const char *section, \
- unsigned section_line, \
- const char *lvalue, \
- int ltype, \
- const char *rvalue, \
- void *data, \
- void *userdata) { \
+typedef enum Disabled {
+ DISABLED_CONFIGURATION,
+ DISABLED_LEGACY,
+ DISABLED_EXPERIMENTAL,
+} Disabled;
+
+#define DEFINE_CONFIG_PARSE(function, parser, msg) \
+ CONFIG_PARSER_PROTOTYPE(function) { \
+ int *i = data, r; \
+ \
+ assert(filename); \
+ assert(lvalue); \
+ assert(rvalue); \
+ assert(data); \
+ \
+ r = parser(rvalue); \
+ if (r < 0) { \
+ log_syntax(unit, LOG_ERR, filename, line, r, \
+ msg ", ignoring: %s", rvalue); \
+ return 0; \
+ } \
+ \
+ *i = r; \
+ return 0; \
+ }
+
+#define DEFINE_CONFIG_PARSE_PTR(function, parser, type, msg) \
+ CONFIG_PARSER_PROTOTYPE(function) { \
+ type *i = data; \
+ int r; \
+ \
+ assert(filename); \
+ assert(lvalue); \
+ assert(rvalue); \
+ assert(data); \
+ \
+ r = parser(rvalue, i); \
+ if (r < 0) \
+ log_syntax(unit, LOG_ERR, filename, line, r, \
+ msg ", ignoring: %s", rvalue); \
+ \
+ return 0; \
+ }
+
+#define DEFINE_CONFIG_PARSE_ENUM(function, name, type, msg) \
+ CONFIG_PARSER_PROTOTYPE(function) { \
+ type *i = data, x; \
+ \
+ assert(filename); \
+ assert(lvalue); \
+ assert(rvalue); \
+ assert(data); \
\
+ x = name##_from_string(rvalue); \
+ if (x < 0) { \
+ log_syntax(unit, LOG_ERR, filename, line, 0, \
+ msg ", ignoring: %s", rvalue); \
+ return 0; \
+ } \
+ \
+ *i = x; \
+ return 0; \
+ }
+
+#define DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(function, name, type, default_value, msg) \
+ CONFIG_PARSER_PROTOTYPE(function) { \
type *i = data, x; \
\
assert(filename); \
@@ -175,8 +224,14 @@ int config_parse_ip_port(const char *unit, const char *filename, unsigned line,
assert(rvalue); \
assert(data); \
\
- if ((x = name##_from_string(rvalue)) < 0) { \
- log_syntax(unit, LOG_ERR, filename, line, -x, \
+ if (isempty(rvalue)) { \
+ *i = default_value; \
+ return 0; \
+ } \
+ \
+ x = name##_from_string(rvalue); \
+ if (x < 0) { \
+ log_syntax(unit, LOG_ERR, filename, line, 0, \
msg ", ignoring: %s", rvalue); \
return 0; \
} \
@@ -185,18 +240,8 @@ int config_parse_ip_port(const char *unit, const char *filename, unsigned line,
return 0; \
}
-#define DEFINE_CONFIG_PARSE_ENUMV(function,name,type,invalid,msg) \
- int function(const char *unit, \
- const char *filename, \
- unsigned line, \
- const char *section, \
- unsigned section_line, \
- const char *lvalue, \
- int ltype, \
- const char *rvalue, \
- void *data, \
- void *userdata) { \
- \
+#define DEFINE_CONFIG_PARSE_ENUMV(function, name, type, invalid, msg) \
+ CONFIG_PARSER_PROTOTYPE(function) { \
type **enums = data, x, *ys; \
_cleanup_free_ type *xs = NULL; \
const char *word, *state; \
@@ -222,17 +267,17 @@ int config_parse_ip_port(const char *unit, const char *filename, unsigned line,
return -ENOMEM; \
\
if ((x = name##_from_string(en)) < 0) { \
- log_syntax(unit, LOG_ERR, filename, line, \
- -x, msg ", ignoring: %s", en); \
+ log_syntax(unit, LOG_ERR, filename, line, 0, \
+ msg ", ignoring: %s", en); \
continue; \
} \
\
for (ys = xs; x != invalid && *ys != invalid; ys++) { \
if (*ys == x) { \
- log_syntax(unit, LOG_ERR, filename, \
- line, -x, \
- "Duplicate entry, ignoring: %s", \
- en); \
+ log_syntax(unit, LOG_NOTICE, filename, \
+ line, 0, \
+ "Duplicate entry, ignoring: %s", \
+ en); \
x = invalid; \
} \
} \
@@ -250,9 +295,6 @@ int config_parse_ip_port(const char *unit, const char *filename, unsigned line,
*(xs + i) = invalid; \
} \
\
- free(*enums); \
- *enums = xs; \
- xs = NULL; \
- \
+ free_and_replace(*enums, xs); \
return 0; \
}
diff --git a/src/shared/libshared.sym b/src/shared/libshared.sym
new file mode 100644
index 000000000..6a7495adc
--- /dev/null
+++ b/src/shared/libshared.sym
@@ -0,0 +1,3 @@
+SD_SHARED {
+ global: *;
+};
diff --git a/src/shared/meson.build b/src/shared/meson.build
new file mode 100644
index 000000000..b215e267d
--- /dev/null
+++ b/src/shared/meson.build
@@ -0,0 +1,202 @@
+# SPDX-License-Identifier: LGPL-2.1+
+
+#if 0 /// elogind has a much shorter list
+# shared_sources = files('''
+# acl-util.h
+# acpi-fpdt.c
+# acpi-fpdt.h
+# apparmor-util.c
+# apparmor-util.h
+# ask-password-api.c
+# ask-password-api.h
+# base-filesystem.c
+# base-filesystem.h
+# boot-timestamps.c
+# boot-timestamps.h
+# bootspec.c
+# bootspec.h
+# bus-unit-util.c
+# bus-unit-util.h
+# bus-util.c
+# bus-util.h
+# cgroup-show.c
+# cgroup-show.h
+# clean-ipc.c
+# clean-ipc.h
+# condition.c
+# condition.h
+# conf-parser.c
+# conf-parser.h
+# dev-setup.c
+# dev-setup.h
+# dissect-image.c
+# dissect-image.h
+# dns-domain.c
+# dns-domain.h
+# dropin.c
+# dropin.h
+# efivars.c
+# efivars.h
+# fdset.c
+# fdset.h
+# firewall-util.h
+# fstab-util.c
+# fstab-util.h
+# generator.c
+# generator.h
+# gpt.h
+# ima-util.c
+# ima-util.h
+# import-util.c
+# import-util.h
+# initreq.h
+# install.c
+# install.h
+# install-printf.c
+# install-printf.h
+# journal-util.c
+# journal-util.h
+# logs-show.c
+# logs-show.h
+# loop-util.c
+# loop-util.h
+# machine-image.c
+# machine-image.h
+# machine-pool.c
+# machine-pool.h
+# nsflags.c
+# nsflags.h
+# output-mode.c
+# output-mode.h
+# path-lookup.c
+# path-lookup.h
+# ptyfwd.c
+# ptyfwd.h
+# resolve-util.c
+# resolve-util.h
+# seccomp-util.h
+# sleep-config.c
+# sleep-config.h
+# spawn-ask-password-agent.c
+# spawn-ask-password-agent.h
+# spawn-polkit-agent.c
+# spawn-polkit-agent.h
+# specifier.c
+# specifier.h
+# switch-root.c
+# switch-root.h
+# sysctl-util.c
+# sysctl-util.h
+# tests.c
+# tests.h
+# tomoyo-util.c
+# tomoyo-util.h
+# udev-util.h
+# udev-util.c
+# uid-range.c
+# uid-range.h
+# utmp-wtmp.h
+# vlan-util.c
+# vlan-util.h
+# volatile-util.c
+# volatile-util.h
+# watchdog.c
+# watchdog.h
+# wireguard-netlink.h
+# '''.split())
+#else
+shared_sources = '''
+ bus-util.c
+ bus-util.h
+ clean-ipc.c
+ clean-ipc.h
+ conf-parser.c
+ conf-parser.h
+ musl_missing.c
+ musl_missing.h
+ nsflags.c
+ nsflags.h
+ output-mode.c
+ output-mode.h
+ sleep-config.c
+ sleep-config.h
+ spawn-polkit-agent.c
+ spawn-polkit-agent.h
+ udev-util.h
+'''.split()
+#endif // 0
+
+test_tables_h = files('test-tables.h')
+shared_sources += [test_tables_h]
+
+if conf.get('HAVE_ACL') == 1
+ shared_sources += files('acl-util.c')
+endif
+
+if conf.get('ENABLE_UTMP') == 1
+ shared_sources += files('utmp-wtmp.c')
+endif
+
+#if 0 /// UNNEEDED by elogind
+# if conf.get('HAVE_SECCOMP') == 1
+# shared_sources += files('seccomp-util.c')
+# endif
+#
+# if conf.get('HAVE_LIBIPTC') == 1
+# shared_sources += files('firewall-util.c')
+# endif
+#endif // 0
+
+libshared_name = 'elogind-shared-@0@'.format(meson.project_version())
+
+#if 0 /// elogind doesn't need all this
+# libshared_deps = [threads,
+# librt,
+# libcap,
+# libacl,
+# libcryptsetup,
+# libgcrypt,
+# libiptc,
+# libseccomp,
+# libselinux,
+# libidn,
+# libxz,
+# liblz4,
+# libblkid]
+#else
+libshared_deps = [threads,
+ libacl,
+ libcap,
+ libselinux]
+#endif // 0
+
+libshared_sym_path = '@0@/libshared.sym'.format(meson.current_source_dir())
+
+libshared_static = static_library(
+ libshared_name,
+ shared_sources,
+ include_directories : includes,
+ dependencies : libshared_deps,
+ c_args : ['-fvisibility=default'])
+
+libshared = shared_library(
+ libshared_name,
+#if 0 /// UNNEEDED by elogind
+# libudev_sources,
+#endif // 0
+ include_directories : includes,
+ link_args : ['-shared',
+ '-Wl,--version-script=' + libshared_sym_path],
+ link_whole : [libshared_static,
+ libbasic,
+#if 0 /// UNNEEDED by elogind
+# libbasic_gcrypt,
+# libsystemd_static,
+# libjournal_client],
+#else
+ libelogind_static],
+#endif // 0
+ c_args : ['-fvisibility=default'],
+ dependencies : libshared_deps,
+ install : true,
+ install_dir : rootlibexecdir)
diff --git a/src/shared/musl_missing.c b/src/shared/musl_missing.c
index 5ce787beb..ffa0ff78f 100644
--- a/src/shared/musl_missing.c
+++ b/src/shared/musl_missing.c
@@ -1,4 +1,26 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/***
+ This file is part of elogind.
+
+ Copyright 2017 Sven Eden
+
+ elogind is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ elogind is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with elogind; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <errno.h>
#include <string.h>
+
#include "alloc-util.h"
#ifndef __GLIBC__
@@ -6,29 +28,33 @@ char *program_invocation_name = NULL;
char *program_invocation_short_name = NULL;
#endif // __GLIBC__
+const char *program_arg_name = NULL;
+
#include "musl_missing.h"
static void elogind_free_program_name(void) {
- if (program_invocation_name)
+
+ if (program_invocation_name && (program_invocation_name != program_arg_name) && strlen(program_invocation_name))
program_invocation_name = mfree(program_invocation_name);
- if (program_invocation_short_name)
+ if (program_invocation_short_name && (program_invocation_short_name != program_arg_name) && strlen(program_invocation_short_name))
program_invocation_short_name = mfree(program_invocation_short_name);
}
void elogind_set_program_name(const char* pcall) {
assert(pcall && pcall[0]);
+ program_arg_name = pcall;
+
if ( ( program_invocation_name
- && strcmp(program_invocation_name, pcall))
+ && strcmp(program_invocation_name, program_arg_name))
|| ( program_invocation_short_name
- && strcmp(program_invocation_short_name, basename(pcall)) ) )
+ && strcmp(program_invocation_short_name, basename(program_arg_name)) ) )
elogind_free_program_name();
if (NULL == program_invocation_name)
- program_invocation_name = strdup(pcall);
+ program_invocation_name = strdup(program_arg_name);
if (NULL == program_invocation_short_name)
- program_invocation_short_name = strdup(basename(pcall));
-
+ program_invocation_short_name = strdup(basename(program_arg_name));
#ifndef __GLIBC__
atexit(elogind_free_program_name);
#endif // __GLIBC__
diff --git a/src/shared/musl_missing.h b/src/shared/musl_missing.h
index 6a6f1e037..15f5f8473 100644
--- a/src/shared/musl_missing.h
+++ b/src/shared/musl_missing.h
@@ -20,10 +20,10 @@
void elogind_set_program_name(const char* pcall);
#if !defined(__GLIBC__)
-#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <pthread.h> /* for pthread_atfork */
#define strerror_r(e, m, k) (strerror_r(e, m, k) < 0 ? strdup("strerror_r() failed") : m);
@@ -41,9 +41,10 @@ extern char *program_invocation_short_name;
* + test if the effective capability bit was set on the executable file
* + test if the process has a nonempty permitted capability set
*/
-#if !defined(HAVE_SECURE_GETENV) && !defined(HAVE___SECURE_GETENV)
+#if ! HAVE_SECURE_GETENV && ! HAVE___SECURE_GETENV
# define secure_getenv(name) \
(issetugid() ? NULL : getenv(name))
+# undef HAVE_SECURE_GETENV
# define HAVE_SECURE_GETENV 1
#endif // HAVE_[__]SECURE_GETENV
@@ -53,13 +54,14 @@ extern char *program_invocation_short_name;
/* strndupa may already be defined in another compatibility header */
#if !defined(strndupa)
-#define strndupa(src, n) \
- (__extension__ ({const char *in = (src); \
- size_t len = strnlen(in, (n)) + 1; \
- char *out = (char *) alloca(len); \
- out[len-1] = '\0'; \
- (char *) memcpy(out, in, len-1);}) \
- )
+#define strndupa(x_src, x_n) \
+ (__extension__ ( { \
+ const char* x_in = (x_src); \
+ size_t x_len = strnlen(x_in, (x_n)) + 1; \
+ char* x_out = (char *) alloca(x_len); \
+ x_out[x_len-1] = '\0'; \
+ (char *) memcpy(x_out, x_in, x_len-1); \
+ } ) )
#endif
/* See http://man7.org/linux/man-pages/man3/canonicalize_file_name.3.html */
@@ -86,7 +88,7 @@ typedef __compar_fn_t comparison_fn_t;
#endif
/* Make musl utmp/wtmp stubs visible if needed. */
-#ifdef HAVE_UTMP
+#if ENABLE_UTMP
# include <paths.h>
# include <utmp.h>
# include <utmpx.h>
@@ -96,7 +98,35 @@ typedef __compar_fn_t comparison_fn_t;
# if defined(_PATH_WTMP) && !defined(_PATH_WTMPX)
# define _PATH_WTMPX _PATH_WTMP
# endif
-#endif // HAVE_UTMP
+#endif // ENABLE_UTMP
+
+/*
+ * Systemd makes use of undeclared glibc-specific __register_atfork to avoid
+ * a depednency on libpthread, __register_atfork is roughly equivalent to
+ * pthread_atfork so define __register_atfork to pthread_atfork.
+ */
+#define __register_atfork(prepare,parent,child,dso) pthread_atfork(prepare,parent,child)
+
+/*
+ * Missing FTW macros in musl, define them if not defined
+ * taken from
+ * https://git.yoctoproject.org/cgit.cgi/poky/plain/meta/recipes-core/systemd/systemd/0028-add-missing-FTW_-macros-for-musl.patch
+ */
+#ifndef FTW_ACTIONRETVAL
+#define FTW_ACTIONRETVAL 16
+#endif
+
+#ifndef FTW_CONTINUE
+#define FTW_CONTINUE 0
+#endif
+
+#ifndef FTW_STOP
+#define FTW_STOP 1
+#endif
+
+#ifndef FTW_SKIP_SUBTREE
+#define FTW_SKIP_SUBTREE 2
+#endif
#endif // !defined(__GLIBC__)
diff --git a/src/shared/nsflags.c b/src/shared/nsflags.c
index 9d64b0275..fcb48abfd 100644
--- a/src/shared/nsflags.c
+++ b/src/shared/nsflags.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <sched.h>
@@ -37,33 +20,9 @@ const struct namespace_flag_map namespace_flag_map[] = {
{}
};
-const char* namespace_flag_to_string(unsigned long flag) {
- unsigned i;
-
- flag &= NAMESPACE_FLAGS_ALL;
-
- for (i = 0; namespace_flag_map[i].name; i++)
- if (flag == namespace_flag_map[i].flag)
- return namespace_flag_map[i].name;
-
- return NULL; /* either unknown namespace flag, or a combination of many. This call supports neither. */
-}
-
-unsigned long namespace_flag_from_string(const char *name) {
- unsigned i;
-
- if (isempty(name))
- return 0;
-
- for (i = 0; namespace_flag_map[i].name; i++)
- if (streq(name, namespace_flag_map[i].name))
- return namespace_flag_map[i].flag;
-
- return 0;
-}
#if 0 /// UNNEEDED by elogind
-int namespace_flag_from_string_many(const char *name, unsigned long *ret) {
+int namespace_flags_from_string(const char *name, unsigned long *ret) {
unsigned long flags = 0;
int r;
@@ -71,7 +30,8 @@ int namespace_flag_from_string_many(const char *name, unsigned long *ret) {
for (;;) {
_cleanup_free_ char *word = NULL;
- unsigned long f;
+ unsigned long f = 0;
+ unsigned i;
r = extract_first_word(&name, &word, NULL, 0);
if (r < 0)
@@ -79,7 +39,12 @@ int namespace_flag_from_string_many(const char *name, unsigned long *ret) {
if (r == 0)
break;
- f = namespace_flag_from_string(word);
+ for (i = 0; namespace_flag_map[i].name; i++)
+ if (streq(word, namespace_flag_map[i].name)) {
+ f = namespace_flag_map[i].flag;
+ break;
+ }
+
if (f == 0)
return -EINVAL;
@@ -91,7 +56,7 @@ int namespace_flag_from_string_many(const char *name, unsigned long *ret) {
}
#endif // 0
-int namespace_flag_to_string_many(unsigned long flags, char **ret) {
+int namespace_flags_to_string(unsigned long flags, char **ret) {
_cleanup_free_ char *s = NULL;
unsigned i;
@@ -99,14 +64,8 @@ int namespace_flag_to_string_many(unsigned long flags, char **ret) {
if ((flags & namespace_flag_map[i].flag) != namespace_flag_map[i].flag)
continue;
- if (!s) {
- s = strdup(namespace_flag_map[i].name);
- if (!s)
- return -ENOMEM;
- } else {
- if (!strextend(&s, " ", namespace_flag_map[i].name, NULL))
- return -ENOMEM;
- }
+ if (!strextend_with_separator(&s, " ", namespace_flag_map[i].name, NULL))
+ return -ENOMEM;
}
if (!s) {
@@ -115,8 +74,7 @@ int namespace_flag_to_string_many(unsigned long flags, char **ret) {
return -ENOMEM;
}
- *ret = s;
- s = NULL;
+ *ret = TAKE_PTR(s);
return 0;
}
diff --git a/src/shared/nsflags.h b/src/shared/nsflags.h
index 58cfdce56..4fe5b55cf 100644
--- a/src/shared/nsflags.h
+++ b/src/shared/nsflags.h
@@ -1,24 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <sched.h>
#include "missing.h"
@@ -36,12 +18,12 @@
CLONE_NEWUSER| \
CLONE_NEWUTS))
-const char* namespace_flag_to_string(unsigned long flag);
-unsigned long namespace_flag_from_string(const char *name);
#if 0 /// UNNEEDED by elogind
-int namespace_flag_from_string_many(const char *name, unsigned long *ret);
#endif // 0
-int namespace_flag_to_string_many(unsigned long flags, char **ret);
+#define NAMESPACE_FLAGS_INITIAL ((unsigned long) -1)
+
+int namespace_flags_from_string(const char *name, unsigned long *ret);
+int namespace_flags_to_string(unsigned long flags, char **ret);
struct namespace_flag_map {
unsigned long flag;
diff --git a/src/shared/output-mode.c b/src/shared/output-mode.c
new file mode 100644
index 000000000..bb33ba3d1
--- /dev/null
+++ b/src/shared/output-mode.c
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "output-mode.h"
+#include "string-table.h"
+
+static const char *const output_mode_table[_OUTPUT_MODE_MAX] = {
+ [OUTPUT_SHORT] = "short",
+ [OUTPUT_SHORT_FULL] = "short-full",
+ [OUTPUT_SHORT_ISO] = "short-iso",
+ [OUTPUT_SHORT_ISO_PRECISE] = "short-iso-precise",
+ [OUTPUT_SHORT_PRECISE] = "short-precise",
+ [OUTPUT_SHORT_MONOTONIC] = "short-monotonic",
+ [OUTPUT_SHORT_UNIX] = "short-unix",
+ [OUTPUT_VERBOSE] = "verbose",
+ [OUTPUT_EXPORT] = "export",
+ [OUTPUT_JSON] = "json",
+ [OUTPUT_JSON_PRETTY] = "json-pretty",
+ [OUTPUT_JSON_SSE] = "json-sse",
+ [OUTPUT_CAT] = "cat",
+ [OUTPUT_WITH_UNIT] = "with-unit",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode);
diff --git a/src/shared/output-mode.h b/src/shared/output-mode.h
new file mode 100644
index 000000000..fe3903b3c
--- /dev/null
+++ b/src/shared/output-mode.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "macro.h"
+
+typedef enum OutputMode {
+ OUTPUT_SHORT,
+ OUTPUT_SHORT_FULL,
+ OUTPUT_SHORT_ISO,
+ OUTPUT_SHORT_ISO_PRECISE,
+ OUTPUT_SHORT_PRECISE,
+ OUTPUT_SHORT_MONOTONIC,
+ OUTPUT_SHORT_UNIX,
+ OUTPUT_VERBOSE,
+ OUTPUT_EXPORT,
+ OUTPUT_JSON,
+ OUTPUT_JSON_PRETTY,
+ OUTPUT_JSON_SSE,
+ OUTPUT_CAT,
+ OUTPUT_WITH_UNIT,
+ _OUTPUT_MODE_MAX,
+ _OUTPUT_MODE_INVALID = -1
+} OutputMode;
+
+/* The output flags definitions are shared by the logs and process tree output. Some apply to both, some only to the
+ * logs output, others only to the process tree output. */
+
+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,
+ OUTPUT_CATALOG = 1 << 5,
+ OUTPUT_BEGIN_NEWLINE = 1 << 6,
+ OUTPUT_UTC = 1 << 7,
+ OUTPUT_KERNEL_THREADS = 1 << 8,
+ OUTPUT_NO_HOSTNAME = 1 << 9,
+} OutputFlags;
+
+const char* output_mode_to_string(OutputMode m) _const_;
+OutputMode output_mode_from_string(const char *s) _pure_;
diff --git a/src/shared/pager.h b/src/shared/pager.h
deleted file mode 100644
index 2746b1153..000000000
--- a/src/shared/pager.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdbool.h>
-
-#include "macro.h"
-
-int pager_open(bool no_pager, bool jump_to_end);
-void pager_close(void);
-bool pager_have(void) _pure_;
-
-#if 0 /// UNNEEDED by elogind
-int show_man_page(const char *page, bool null_stdio);
-#endif // 0
diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c
index 3a947fcde..77b380ca3 100644
--- a/src/shared/sleep-config.c
+++ b/src/shared/sleep-config.c
@@ -1,23 +1,10 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 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/>.
+ Copyright © 2018 Dell Inc.
***/
//#include <errno.h>
+#include <linux/fs.h>
//#include <stdbool.h>
//#include <stddef.h>
//#include <stdio.h>
@@ -39,15 +26,14 @@
#include "strv.h"
#if 0 /// UNNEEDED by elogind
-#define USE(x, y) do { (x) = (y); (y) = NULL; } while (0)
-
-int parse_sleep_config(const char *verb, char ***_modes, char ***_states) {
+int parse_sleep_config(const char *verb, char ***_modes, char ***_states, usec_t *_delay) {
_cleanup_strv_free_ char
**suspend_mode = NULL, **suspend_state = NULL,
**hibernate_mode = NULL, **hibernate_state = NULL,
**hybrid_mode = NULL, **hybrid_state = NULL;
- char **modes, **states;
+ _cleanup_strv_free_ char **modes, **states; /* always initialized below */
+ usec_t delay = 180 * USEC_PER_MINUTE;
const ConfigTableItem items[] = {
{ "Sleep", "SuspendMode", config_parse_strv, 0, &suspend_mode },
@@ -56,63 +42,69 @@ int parse_sleep_config(const char *verb, char ***_modes, char ***_states) {
{ "Sleep", "HibernateState", config_parse_strv, 0, &hibernate_state },
{ "Sleep", "HybridSleepMode", config_parse_strv, 0, &hybrid_mode },
{ "Sleep", "HybridSleepState", config_parse_strv, 0, &hybrid_state },
+ { "Sleep", "HibernateDelaySec", config_parse_sec, 0, &delay},
{}
};
- config_parse_many_nulstr(PKGSYSCONFDIR "/sleep.conf",
- CONF_PATHS_NULSTR("systemd/sleep.conf.d"),
- "Sleep\0", config_item_table_lookup, items,
- false, NULL);
+ (void) config_parse_many_nulstr(PKGSYSCONFDIR "/sleep.conf",
+ CONF_PATHS_NULSTR("elogind/sleep.conf.d"),
+ "Sleep\0", config_item_table_lookup, items,
+ CONFIG_PARSE_WARN, NULL);
if (streq(verb, "suspend")) {
/* empty by default */
- USE(modes, suspend_mode);
+ modes = TAKE_PTR(suspend_mode);
if (suspend_state)
- USE(states, suspend_state);
+ states = TAKE_PTR(suspend_state);
else
states = strv_new("mem", "standby", "freeze", NULL);
} else if (streq(verb, "hibernate")) {
if (hibernate_mode)
- USE(modes, hibernate_mode);
+ modes = TAKE_PTR(hibernate_mode);
else
modes = strv_new("platform", "shutdown", NULL);
if (hibernate_state)
- USE(states, hibernate_state);
+ states = TAKE_PTR(hibernate_state);
else
states = strv_new("disk", NULL);
} else if (streq(verb, "hybrid-sleep")) {
if (hybrid_mode)
- USE(modes, hybrid_mode);
+ modes = TAKE_PTR(hybrid_mode);
else
modes = strv_new("suspend", "platform", "shutdown", NULL);
if (hybrid_state)
- USE(states, hybrid_state);
+ states = TAKE_PTR(hybrid_state);
else
states = strv_new("disk", NULL);
- } else
+ } else if (streq(verb, "suspend-then-hibernate"))
+ modes = states = NULL;
+ else
assert_not_reached("what verb");
- if ((!modes && !streq(verb, "suspend")) || !states) {
- strv_free(modes);
- strv_free(states);
+ if ((!modes && STR_IN_SET(verb, "hibernate", "hybrid-sleep")) ||
+ (!states && !streq(verb, "suspend-then-hibernate")))
return log_oom();
- }
- *_modes = modes;
- *_states = states;
+ if (_modes)
+ *_modes = TAKE_PTR(modes);
+ if (_states)
+ *_states = TAKE_PTR(states);
+ if (_delay)
+ *_delay = delay;
+
return 0;
}
#endif // 0
#if 1 /// Only available in this file for elogind
static
-#endif // 0
+#endif // 1
int can_sleep_state(char **types) {
char **type;
int r;
@@ -144,7 +136,7 @@ int can_sleep_state(char **types) {
#if 1 /// Only available in this file for elogind
static
-#endif // 0
+#endif // 1
int can_sleep_disk(char **types) {
char **type;
int r;
@@ -183,13 +175,10 @@ int can_sleep_disk(char **types) {
#define HIBERNATION_SWAP_THRESHOLD 0.98
-static int hibernation_partition_size(size_t *size, size_t *used) {
+int find_hibernate_location(char **device, char **type, size_t *size, size_t *used) {
_cleanup_fclose_ FILE *f;
unsigned i;
- assert(size);
- assert(used);
-
f = fopen("/proc/swaps", "re");
if (!f) {
log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
@@ -201,7 +190,7 @@ static int hibernation_partition_size(size_t *size, size_t *used) {
(void) fscanf(f, "%*s %*s %*s %*s %*s\n");
for (i = 1;; i++) {
- _cleanup_free_ char *dev = NULL, *type = NULL;
+ _cleanup_free_ char *dev_field = NULL, *type_field = NULL;
size_t size_field, used_field;
int k;
@@ -211,7 +200,7 @@ static int hibernation_partition_size(size_t *size, size_t *used) {
"%zu " /* swap size */
"%zu " /* used */
"%*i\n", /* priority */
- &dev, &type, &size_field, &used_field);
+ &dev_field, &type_field, &size_field, &used_field);
if (k != 4) {
if (k == EOF)
break;
@@ -220,13 +209,18 @@ static int hibernation_partition_size(size_t *size, size_t *used) {
continue;
}
- if (streq(type, "partition") && endswith(dev, "\\040(deleted)")) {
- log_warning("Ignoring deleted swapfile '%s'.", dev);
+ if (streq(type_field, "partition") && endswith(dev_field, "\\040(deleted)")) {
+ log_warning("Ignoring deleted swapfile '%s'.", dev_field);
continue;
}
-
- *size = size_field;
- *used = used_field;
+ if (device)
+ *device = TAKE_PTR(dev_field);
+ if (type)
+ *type = TAKE_PTR(type_field);
+ if (size)
+ *size = size_field;
+ if (used)
+ *used = used_field;
return 0;
}
@@ -234,7 +228,7 @@ static int hibernation_partition_size(size_t *size, size_t *used) {
return -ENOSYS;
}
-static bool enough_memory_for_hibernation(void) {
+static bool enough_swap_for_hibernation(void) {
_cleanup_free_ char *active = NULL;
unsigned long long act = 0;
size_t size = 0, used = 0;
@@ -245,7 +239,7 @@ static bool enough_memory_for_hibernation(void) {
return true;
#endif // 0
- r = hibernation_partition_size(&size, &used);
+ r = find_hibernate_location(NULL, NULL, &size, &used);
if (r < 0)
return false;
@@ -269,47 +263,162 @@ static bool enough_memory_for_hibernation(void) {
return r;
}
-#if 0 /// elogind has to do, or better, *can* do it differently
-int can_sleep(const char *verb) {
- _cleanup_strv_free_ char **modes = NULL, **states = NULL;
- int r;
+int read_fiemap(int fd, struct fiemap **ret) {
+ _cleanup_free_ struct fiemap *fiemap = NULL, *result_fiemap = NULL;
+ struct stat statinfo;
+ uint32_t result_extents = 0;
+ uint64_t fiemap_start = 0, fiemap_length;
+ const size_t n_extra = DIV_ROUND_UP(sizeof(struct fiemap), sizeof(struct fiemap_extent));
+ size_t fiemap_allocated = n_extra, result_fiemap_allocated = n_extra;
+
+ if (fstat(fd, &statinfo) < 0)
+ return log_debug_errno(errno, "Cannot determine file size: %m");
+ if (!S_ISREG(statinfo.st_mode))
+ return -ENOTTY;
+ fiemap_length = statinfo.st_size;
+
+ /* Zero this out in case we run on a file with no extents */
+ fiemap = calloc(n_extra, sizeof(struct fiemap_extent));
+ if (!fiemap)
+ return -ENOMEM;
+
+ result_fiemap = malloc_multiply(n_extra, sizeof(struct fiemap_extent));
+ if (!result_fiemap)
+ return -ENOMEM;
+
+ /* XFS filesystem has incorrect implementation of fiemap ioctl and
+ * returns extents for only one block-group at a time, so we need
+ * to handle it manually, starting the next fiemap call from the end
+ * of the last extent
+ */
+ while (fiemap_start < fiemap_length) {
+ *fiemap = (struct fiemap) {
+ .fm_start = fiemap_start,
+ .fm_length = fiemap_length,
+ .fm_flags = FIEMAP_FLAG_SYNC,
+ };
+
+ /* Find out how many extents there are */
+ if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0)
+ return log_debug_errno(errno, "Failed to read extents: %m");
+
+ /* Nothing to process */
+ if (fiemap->fm_mapped_extents == 0)
+ break;
+
+ /* Resize fiemap to allow us to read in the extents, result fiemap has to hold all
+ * the extents for the whole file. Add space for the initial struct fiemap. */
+ if (!greedy_realloc0((void**) &fiemap, &fiemap_allocated,
+ n_extra + fiemap->fm_mapped_extents, sizeof(struct fiemap_extent)))
+ return -ENOMEM;
+
+ fiemap->fm_extent_count = fiemap->fm_mapped_extents;
+ fiemap->fm_mapped_extents = 0;
+
+ if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0)
+ return log_debug_errno(errno, "Failed to read extents: %m");
+
+ /* Resize result_fiemap to allow us to copy in the extents */
+ if (!greedy_realloc((void**) &result_fiemap, &result_fiemap_allocated,
+ n_extra + result_extents + fiemap->fm_mapped_extents, sizeof(struct fiemap_extent)))
+ return -ENOMEM;
+
+ memcpy(result_fiemap->fm_extents + result_extents,
+ fiemap->fm_extents,
+ sizeof(struct fiemap_extent) * fiemap->fm_mapped_extents);
+
+ result_extents += fiemap->fm_mapped_extents;
+
+ /* Highly unlikely that it is zero */
+ if (_likely_(fiemap->fm_mapped_extents > 0)) {
+ uint32_t i = fiemap->fm_mapped_extents - 1;
+
+ fiemap_start = fiemap->fm_extents[i].fe_logical +
+ fiemap->fm_extents[i].fe_length;
+
+ if (fiemap->fm_extents[i].fe_flags & FIEMAP_EXTENT_LAST)
+ break;
+ }
+ }
- assert(streq(verb, "suspend") ||
- streq(verb, "hibernate") ||
- streq(verb, "hybrid-sleep"));
+ memcpy(result_fiemap, fiemap, sizeof(struct fiemap));
+ result_fiemap->fm_mapped_extents = result_extents;
+ *ret = TAKE_PTR(result_fiemap);
+ return 0;
+}
- r = parse_sleep_config(verb, &modes, &states);
- if (r < 0)
- return false;
+#if 0 /// elogind has to ask the manager for some stuff
+static bool can_s2h(void) {
+#else
+static bool can_s2h(Manager *m) {
+#endif // 0
+ const char *p;
+ int r;
- if (!can_sleep_state(states) || !can_sleep_disk(modes))
+ r = access("/sys/class/rtc/rtc0/wakealarm", W_OK);
+ if (r < 0) {
+ log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
+ "/sys/class/rct/rct0/wakealarm is not writable %m");
return false;
+ }
+
+ FOREACH_STRING(p, "suspend", "hibernate") {
+#if 0 /// elogind must transport a pointer to its managers instance
+ r = can_sleep(p);
+#else
+ r = can_sleep(m, p);
+#endif // 0
+ if (IN_SET(r, 0, -ENOSPC)) {
+ log_debug("Unable to %s system.", p);
+ return false;
+ }
+ if (r < 0)
+ return log_debug_errno(r, "Failed to check if %s is possible: %m", p);
+ }
- return streq(verb, "suspend") || enough_memory_for_hibernation();
+ return true;
}
+
+
+#if 0 /// elogind has to ask the manager for some stuff
+int can_sleep(const char *verb) {
+ _cleanup_strv_free_ char **modes = NULL, **states = NULL;
+ int r;
#else
int can_sleep(Manager *m, const char *verb) {
+ assert(m);
+
+ char **modes = streq(verb, "suspend") ? m->suspend_mode :
+ streq(verb, "hibernate") ? m->hibernate_mode :
+ m->hybrid_sleep_mode;
+ char **states = streq(verb, "suspend") ? m->suspend_state :
+ streq(verb, "hibernate") ? m->hibernate_state :
+ m->hybrid_sleep_state;
+#endif // 0
- assert(streq(verb, "suspend") ||
- streq(verb, "hibernate") ||
- streq(verb, "hybrid-sleep"));
+ assert(STR_IN_SET(verb, "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate"));
- if ( streq(verb, "suspend")
- && ( !can_sleep_state(m->suspend_state)
- || !can_sleep_disk(m->suspend_mode) ) )
- return false;
+ if (streq(verb, "suspend-then-hibernate"))
+#if 0 /// elogind must transport a pointer to its managers instance
+ return can_s2h();
+#else
+ return can_s2h(m);
+#endif // 0
- if ( streq(verb, "hibernate")
- && ( !can_sleep_state(m->hibernate_state)
- || !can_sleep_disk(m->hibernate_mode) ) )
+#if 0 /// already parsed by elogind config
+ r = parse_sleep_config(verb, &modes, &states, NULL);
+ if (r < 0)
return false;
+#endif // 0
- if ( streq(verb, "hybrid-sleep")
- && ( !can_sleep_state(m->hybrid_sleep_state)
- || !can_sleep_disk(m->hybrid_sleep_mode) ) )
+ if (!can_sleep_state(states) || !can_sleep_disk(modes))
return false;
+ if (streq(verb, "suspend"))
+ return true;
+
+ if (!enough_swap_for_hibernation())
+ return -ENOSPC;
- return streq(verb, "suspend") || enough_memory_for_hibernation();
+ return true;
}
-#endif // 0
diff --git a/src/shared/sleep-config.h b/src/shared/sleep-config.h
index 238775dc4..b29165143 100644
--- a/src/shared/sleep-config.h
+++ b/src/shared/sleep-config.h
@@ -1,31 +1,20 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 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 <linux/fiemap.h>
+//#include "time-util.h"
+int read_fiemap(int fd, struct fiemap **ret);
#if 0 /// UNNEEDED by elogind
-int parse_sleep_config(const char *verb, char ***modes, char ***states);
+int parse_sleep_config(const char *verb, char ***modes, char ***states, usec_t *delay);
+#endif // 0
+int find_hibernate_location(char **device, char **type, size_t *size, size_t *used);
+#if 0 /// elogind has to transport its manager instance
int can_sleep(const char *verb);
int can_sleep_disk(char **types);
int can_sleep_state(char **types);
#else
#include <logind.h>
-int can_sleep(Manager* m, const char *verb);
+int can_sleep(Manager *m, const char *verb);
#endif // 0
diff --git a/src/shared/spawn-polkit-agent.c b/src/shared/spawn-polkit-agent.c
index 7dae4d14f..180cb7964 100644
--- a/src/shared/spawn-polkit-agent.c
+++ b/src/shared/spawn-polkit-agent.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <poll.h>
@@ -33,13 +16,12 @@
#include "time-util.h"
#include "util.h"
-#ifdef ENABLE_POLKIT
+#if ENABLE_POLKIT
static pid_t agent_pid = 0;
int polkit_agent_open(void) {
- int r;
- int pipe_fd[2];
char notify_fd[DECIMAL_STR_MAX(int) + 1];
+ int pipe_fd[2], r;
if (agent_pid > 0)
return 0;
@@ -48,18 +30,21 @@ int polkit_agent_open(void) {
if (geteuid() == 0)
return 0;
- /* We check STDIN here, not STDOUT, since this is about input,
- * not output */
+ /* We check STDIN here, not STDOUT, since this is about input, not output */
if (!isatty(STDIN_FILENO))
return 0;
+ if (!is_main_thread())
+ return -EPERM;
+
if (pipe2(pipe_fd, 0) < 0)
return -errno;
xsprintf(notify_fd, "%i", pipe_fd[1]);
- r = fork_agent(&agent_pid,
+ r = fork_agent("(polkit-agent)",
&pipe_fd[1], 1,
+ &agent_pid,
POLKIT_AGENT_BINARY_PATH,
POLKIT_AGENT_BINARY_PATH, "--notify-fd", notify_fd, "--fallback", NULL);
@@ -83,9 +68,7 @@ void polkit_agent_close(void) {
return;
/* Inform agent that we are done */
- (void) kill(agent_pid, SIGTERM);
- (void) kill(agent_pid, SIGCONT);
-
+ (void) kill_and_sigcont(agent_pid, SIGTERM);
(void) 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
index 42b2989de..190b970b6 100644
--- a/src/shared/spawn-polkit-agent.h
+++ b/src/shared/spawn-polkit-agent.h
@@ -1,23 +1,22 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
+#include "bus-util.h"
- Copyright 2012 Lennart Poettering
+int polkit_agent_open(void);
+void polkit_agent_close(void);
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
+static inline int polkit_agent_open_if_enabled(
+ BusTransport transport,
+ bool ask_password) {
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
+ /* Open the polkit agent as a child process if necessary */
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+ if (transport != BUS_TRANSPORT_LOCAL)
+ return 0;
-int polkit_agent_open(void);
-void polkit_agent_close(void);
+ if (!ask_password)
+ return 0;
+
+ return polkit_agent_open();
+}
diff --git a/src/shared/test-tables.h b/src/shared/test-tables.h
index 228e51010..000b623b8 100644
--- a/src/shared/test-tables.h
+++ b/src/shared/test-tables.h
@@ -1,24 +1,8 @@
-/***
- This file is part of systemd
-
- Copyright 2013 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <stdio.h>
#include <stdlib.h>
+//#include <string.h>
typedef const char* (*lookup_t)(int);
typedef int (*reverse_t)(const char*);
diff --git a/src/shared/tests.c b/src/shared/tests.c
deleted file mode 100644
index f300bbc66..000000000
--- a/src/shared/tests.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <alloc-util.h>
-#include <fs-util.h>
-#include <libgen.h>
-#include <stdlib.h>
-#include <util.h>
-
-#include "tests.h"
-#include "path-util.h"
-
-char* setup_fake_runtime_dir(void) {
- char t[] = "/tmp/fake-xdg-runtime-XXXXXX", *p;
-
- assert_se(mkdtemp(t));
- assert_se(setenv("XDG_RUNTIME_DIR", t, 1) >= 0);
- assert_se(p = strdup(t));
-
- return p;
-}
-
-const char* get_testdata_dir(const char *suffix) {
- const char *env;
- /* convenience: caller does not need to free result */
- static char testdir[PATH_MAX];
-
- /* if the env var is set, use that */
- env = getenv("SYSTEMD_TEST_DATA");
- testdir[sizeof(testdir) - 1] = '\0';
- if (env) {
- if (access(env, F_OK) < 0) {
- fputs("ERROR: $SYSTEMD_TEST_DATA directory does not exist\n", stderr);
- exit(1);
- }
- strncpy(testdir, env, sizeof(testdir) - 1);
- } else {
- _cleanup_free_ char *exedir = NULL;
- assert_se(readlink_and_make_absolute("/proc/self/exe", &exedir) >= 0);
-
- /* Check if we're running from the builddir. If so, use the compiled in path. */
- if (path_startswith(exedir, ABS_BUILD_DIR))
- assert_se(snprintf(testdir, sizeof(testdir), "%s/test", ABS_SRC_DIR) > 0);
- else
- /* Try relative path, according to the install-test layout */
- assert_se(snprintf(testdir, sizeof(testdir), "%s/testdata", dirname(exedir)) > 0);
-
- /* test this without the suffix, as it may contain a glob */
- if (access(testdir, F_OK) < 0) {
- fputs("ERROR: Cannot find testdata directory, set $SYSTEMD_TEST_DATA\n", stderr);
- exit(1);
- }
- }
-
- strncpy(testdir + strlen(testdir), suffix, sizeof(testdir) - strlen(testdir) - 1);
- return testdir;
-}
diff --git a/src/shared/tests.h b/src/shared/tests.h
deleted file mode 100644
index 705512499..000000000
--- a/src/shared/tests.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- 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* setup_fake_runtime_dir(void);
-const char* get_testdata_dir(const char *suffix);
diff --git a/src/shared/udev-util.c b/src/shared/udev-util.c
deleted file mode 100644
index ed32f0305..000000000
--- a/src/shared/udev-util.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2017 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 <string.h>
-
-#include "alloc-util.h"
-#include "fileio.h"
-#include "log.h"
-#include "string-util.h"
-#include "udev-util.h"
-
-int udev_parse_config(void) {
- _cleanup_free_ char *val = NULL;
- const char *log;
- size_t n;
- int r;
-
- r = parse_env_file("/etc/udev/udev.conf", NEWLINE, "udev_log", &val, NULL);
- if (r == -ENOENT || !val)
- return 0;
- if (r < 0)
- return r;
-
- /* unquote */
- n = strlen(val);
- if (n >= 2 &&
- ((val[0] == '"' && val[n-1] == '"') ||
- (val[0] == '\'' && val[n-1] == '\''))) {
- val[n - 1] = '\0';
- log = val + 1;
- } else
- log = val;
-
- /* we set the udev log level here explicitly, this is supposed
- * to regulate the code in libudev/ and udev/. */
- r = log_set_max_level_from_string_realm(LOG_REALM_UDEV, log);
- if (r < 0)
- log_debug_errno(r, "/etc/udev/udev.conf: failed to set udev log level '%s', ignoring: %m", log);
-
- return 0;
-}
diff --git a/src/shared/udev-util.h b/src/shared/udev-util.h
index bbbdd7b95..15eece97f 100644
--- a/src/shared/udev-util.h
+++ b/src/shared/udev-util.h
@@ -1,23 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2013 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/>.
-***/
#if 0 /// elogind needs the systems udev header
#include "udev.h"
@@ -38,17 +21,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl_msg*, udev_ctrl_msg_unref);
#endif // 0
DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_monitor*, udev_monitor_unref);
-#define _cleanup_udev_unref_ _cleanup_(udev_unrefp)
-#define _cleanup_udev_device_unref_ _cleanup_(udev_device_unrefp)
-#define _cleanup_udev_enumerate_unref_ _cleanup_(udev_enumerate_unrefp)
#if 0 /// UNNEEDED by elogind
-#define _cleanup_udev_event_unref_ _cleanup_(udev_event_unrefp)
-#define _cleanup_udev_rules_unref_ _cleanup_(udev_rules_unrefp)
-#define _cleanup_udev_ctrl_unref_ _cleanup_(udev_ctrl_unrefp)
-#define _cleanup_udev_ctrl_connection_unref_ _cleanup_(udev_ctrl_connection_unrefp)
-#define _cleanup_udev_ctrl_msg_unref_ _cleanup_(udev_ctrl_msg_unrefp)
-#endif // 0
-#define _cleanup_udev_monitor_unref_ _cleanup_(udev_monitor_unrefp)
-#define _cleanup_udev_list_cleanup_ _cleanup_(udev_list_cleanup)
-
int udev_parse_config(void);
+
+int udev_device_new_from_stat_rdev(struct udev *udev, const struct stat *st, struct udev_device **ret);
+#endif // 0
diff --git a/src/shared/utmp-wtmp.c b/src/shared/utmp-wtmp.c
index 9750dcd81..ef9427fa7 100644
--- a/src/shared/utmp-wtmp.c
+++ b/src/shared/utmp-wtmp.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <fcntl.h>
@@ -234,7 +217,7 @@ int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line
if (r < 0)
return r;
- if (ut_type == LOGIN_PROCESS || ut_type == USER_PROCESS) {
+ if (IN_SET(ut_type, LOGIN_PROCESS, USER_PROCESS)) {
store.ut_type = LOGIN_PROCESS;
r = write_entry_both(&store);
if (r < 0)
@@ -287,7 +270,6 @@ int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) {
return write_utmp_wtmp(&store, &store_wtmp);
}
-
int utmp_put_runlevel(int runlevel, int previous) {
struct utmpx store = {};
int r;
@@ -329,7 +311,7 @@ static int write_to_terminal(const char *tty, const char *message) {
assert(tty);
assert(message);
- fd = open(tty, O_WRONLY|O_NDELAY|O_NOCTTY|O_CLOEXEC);
+ fd = open(tty, O_WRONLY|O_NONBLOCK|O_NOCTTY|O_CLOEXEC);
if (fd < 0 || !isatty(fd))
return -errno;
@@ -424,7 +406,7 @@ int utmp_wall(
if (u->ut_type != USER_PROCESS || u->ut_user[0] == 0)
continue;
- /* this access is fine, because strlen("/dev/") << 32 (UT_LINESIZE) */
+ /* this access is fine, because STRLEN("/dev/") << 32 (UT_LINESIZE) */
if (path_startswith(u->ut_line, "/dev/"))
path = u->ut_line;
else {
diff --git a/src/shared/utmp-wtmp.h b/src/shared/utmp-wtmp.h
index 438e270a2..9e433cf73 100644
--- a/src/shared/utmp-wtmp.h
+++ b/src/shared/utmp-wtmp.h
@@ -1,31 +1,13 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
#include <stdbool.h>
#include <sys/types.h>
#include "time-util.h"
#include "util.h"
-#ifdef HAVE_UTMP
+#if ENABLE_UTMP
int utmp_get_runlevel(int *runlevel, int *previous);
int utmp_put_shutdown(void);
@@ -42,7 +24,7 @@ int utmp_wall(
bool (*match_tty)(const char *tty, void *userdata),
void *userdata);
-#else /* HAVE_UTMP */
+#else /* ENABLE_UTMP */
static inline int utmp_get_runlevel(int *runlevel, int *previous) {
return -ESRCH;
@@ -71,4 +53,4 @@ static inline int utmp_wall(
return 0;
}
-#endif /* HAVE_UTMP */
+#endif /* ENABLE_UTMP */
diff --git a/src/shared/wireguard-netlink.h b/src/shared/wireguard-netlink.h
new file mode 100644
index 000000000..eb170915a
--- /dev/null
+++ b/src/shared/wireguard-netlink.h
@@ -0,0 +1,179 @@
+#pragma once
+
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR MIT)
+ *
+ * Copyright (C) 2015-2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ *
+ * Documentation
+ * =============
+ *
+ * The below enums and macros are for interfacing with WireGuard, using generic
+ * netlink, with family WG_GENL_NAME and version WG_GENL_VERSION. It defines two
+ * methods: get and set. Note that while they share many common attributes, these
+ * two functions actually accept a slightly different set of inputs and outputs.
+ *
+ * WG_CMD_GET_DEVICE
+ * -----------------
+ *
+ * May only be called via NLM_F_REQUEST | NLM_F_DUMP. The command should contain
+ * one but not both of:
+ *
+ * WGDEVICE_A_IFINDEX: NLA_U32
+ * WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMESIZ - 1
+ *
+ * The kernel will then return several messages (NLM_F_MULTI) containing the following
+ * tree of nested items:
+ *
+ * WGDEVICE_A_IFINDEX: NLA_U32
+ * WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMESIZ - 1
+ * WGDEVICE_A_PRIVATE_KEY: len WG_KEY_LEN
+ * WGDEVICE_A_PUBLIC_KEY: len WG_KEY_LEN
+ * WGDEVICE_A_LISTEN_PORT: NLA_U16
+ * WGDEVICE_A_FWMARK: NLA_U32
+ * WGDEVICE_A_PEERS: NLA_NESTED
+ * 0: NLA_NESTED
+ * WGPEER_A_PUBLIC_KEY: len WG_KEY_LEN
+ * WGPEER_A_PRESHARED_KEY: len WG_KEY_LEN
+ * WGPEER_A_ENDPOINT: struct sockaddr_in or struct sockaddr_in6
+ * WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL: NLA_U16
+ * WGPEER_A_LAST_HANDSHAKE_TIME: struct timespec
+ * WGPEER_A_RX_BYTES: NLA_U64
+ * WGPEER_A_TX_BYTES: NLA_U64
+ * WGPEER_A_ALLOWEDIPS: NLA_NESTED
+ * 0: NLA_NESTED
+ * WGALLOWEDIP_A_FAMILY: NLA_U16
+ * WGALLOWEDIP_A_IPADDR: struct in_addr or struct in6_addr
+ * WGALLOWEDIP_A_CIDR_MASK: NLA_U8
+ * 1: NLA_NESTED
+ * ...
+ * 2: NLA_NESTED
+ * ...
+ * ...
+ * 1: NLA_NESTED
+ * ...
+ * ...
+ *
+ * It is possible that all of the allowed IPs of a single peer will not
+ * fit within a single netlink message. In that case, the same peer will
+ * be written in the following message, except it will only contain
+ * WGPEER_A_PUBLIC_KEY and WGPEER_A_ALLOWEDIPS. This may occur several
+ * times in a row for the same peer. It is then up to the receiver to
+ * coalesce adjacent peers. Likewise, it is possible that all peers will
+ * not fit within a single message. So, subsequent peers will be sent
+ * in following messages, except those will only contain WGDEVICE_A_IFNAME
+ * and WGDEVICE_A_PEERS. It is then up to the receiver to coalesce these
+ * messages to form the complete list of peers.
+ *
+ * Since this is an NLA_F_DUMP command, the final message will always be
+ * NLMSG_DONE, even if an error occurs. However, this NLMSG_DONE message
+ * contains an integer error code. It is either zero or a negative error
+ * code corresponding to the errno.
+ *
+ * WG_CMD_SET_DEVICE
+ * -----------------
+ *
+ * May only be called via NLM_F_REQUEST. The command should contain the following
+ * tree of nested items, containing one but not both of WGDEVICE_A_IFINDEX
+ * and WGDEVICE_A_IFNAME:
+ *
+ * WGDEVICE_A_IFINDEX: NLA_U32
+ * WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMESIZ - 1
+ * WGDEVICE_A_FLAGS: NLA_U32, 0 or WGDEVICE_F_REPLACE_PEERS if all current
+ * peers should be removed prior to adding the list below.
+ * WGDEVICE_A_PRIVATE_KEY: len WG_KEY_LEN, all zeros to remove
+ * WGDEVICE_A_LISTEN_PORT: NLA_U16, 0 to choose randomly
+ * WGDEVICE_A_FWMARK: NLA_U32, 0 to disable
+ * WGDEVICE_A_PEERS: NLA_NESTED
+ * 0: NLA_NESTED
+ * WGPEER_A_PUBLIC_KEY: len WG_KEY_LEN
+ * WGPEER_A_FLAGS: NLA_U32, 0 and/or WGPEER_F_REMOVE_ME if the specified peer
+ * should be removed rather than added/updated and/or
+ * WGPEER_F_REPLACE_ALLOWEDIPS if all current allowed IPs of
+ * this peer should be removed prior to adding the list below.
+ * WGPEER_A_PRESHARED_KEY: len WG_KEY_LEN, all zeros to remove
+ * WGPEER_A_ENDPOINT: struct sockaddr_in or struct sockaddr_in6
+ * WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL: NLA_U16, 0 to disable
+ * WGPEER_A_ALLOWEDIPS: NLA_NESTED
+ * 0: NLA_NESTED
+ * WGALLOWEDIP_A_FAMILY: NLA_U16
+ * WGALLOWEDIP_A_IPADDR: struct in_addr or struct in6_addr
+ * WGALLOWEDIP_A_CIDR_MASK: NLA_U8
+ * 1: NLA_NESTED
+ * ...
+ * 2: NLA_NESTED
+ * ...
+ * ...
+ * 1: NLA_NESTED
+ * ...
+ * ...
+ *
+ * It is possible that the amount of configuration data exceeds that of
+ * the maximum message length accepted by the kernel. In that case,
+ * several messages should be sent one after another, with each
+ * successive one filling in information not contained in the prior. Note
+ * that if WGDEVICE_F_REPLACE_PEERS is specified in the first message, it
+ * probably should not be specified in fragments that come after, so that
+ * the list of peers is only cleared the first time but appened after.
+ * Likewise for peers, if WGPEER_F_REPLACE_ALLOWEDIPS is specified in the
+ * first message of a peer, it likely should not be specified in subsequent
+ * fragments.
+ *
+ * If an error occurs, NLMSG_ERROR will reply containing an errno.
+ */
+
+#define WG_GENL_NAME "wireguard"
+#define WG_GENL_VERSION 1
+
+#define WG_KEY_LEN 32
+
+enum wg_cmd {
+ WG_CMD_GET_DEVICE,
+ WG_CMD_SET_DEVICE,
+ __WG_CMD_MAX
+};
+#define WG_CMD_MAX (__WG_CMD_MAX - 1)
+
+enum wgdevice_flag {
+ WGDEVICE_F_REPLACE_PEERS = 1U << 0
+};
+enum wgdevice_attribute {
+ WGDEVICE_A_UNSPEC,
+ WGDEVICE_A_IFINDEX,
+ WGDEVICE_A_IFNAME,
+ WGDEVICE_A_PRIVATE_KEY,
+ WGDEVICE_A_PUBLIC_KEY,
+ WGDEVICE_A_FLAGS,
+ WGDEVICE_A_LISTEN_PORT,
+ WGDEVICE_A_FWMARK,
+ WGDEVICE_A_PEERS,
+ __WGDEVICE_A_LAST
+};
+#define WGDEVICE_A_MAX (__WGDEVICE_A_LAST - 1)
+
+enum wgpeer_flag {
+ WGPEER_F_REMOVE_ME = 1U << 0,
+ WGPEER_F_REPLACE_ALLOWEDIPS = 1U << 1
+};
+enum wgpeer_attribute {
+ WGPEER_A_UNSPEC,
+ WGPEER_A_PUBLIC_KEY,
+ WGPEER_A_PRESHARED_KEY,
+ WGPEER_A_FLAGS,
+ WGPEER_A_ENDPOINT,
+ WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL,
+ WGPEER_A_LAST_HANDSHAKE_TIME,
+ WGPEER_A_RX_BYTES,
+ WGPEER_A_TX_BYTES,
+ WGPEER_A_ALLOWEDIPS,
+ __WGPEER_A_LAST
+};
+#define WGPEER_A_MAX (__WGPEER_A_LAST - 1)
+
+enum wgallowedip_attribute {
+ WGALLOWEDIP_A_UNSPEC,
+ WGALLOWEDIP_A_FAMILY,
+ WGALLOWEDIP_A_IPADDR,
+ WGALLOWEDIP_A_CIDR_MASK,
+ __WGALLOWEDIP_A_LAST
+};
+#define WGALLOWEDIP_A_MAX (__WGALLOWEDIP_A_LAST - 1)
diff --git a/src/sleep/Makefile b/src/sleep/Makefile
deleted file mode 120000
index d0b0e8e00..000000000
--- a/src/sleep/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/sleep/meson.build b/src/sleep/meson.build
new file mode 100644
index 000000000..6d76d101f
--- /dev/null
+++ b/src/sleep/meson.build
@@ -0,0 +1,4 @@
+sleep_files = files('''
+ sleep.c
+ sleep.h
+'''.split())
diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c
index 4b402abcd..87efd0ac7 100644
--- a/src/sleep/sleep.c
+++ b/src/sleep/sleep.c
@@ -1,36 +1,25 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
- Copyright 2013 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/>.
+ Copyright © 2010-2017 Canonical
+ Copyright © 2018 Dell Inc.
***/
//#include <errno.h>
//#include <getopt.h>
+#include <linux/fiemap.h>
//#include <stdio.h>
#include "sd-messages.h"
+#include "parse-util.h"
#include "def.h"
#include "exec-util.h"
#include "fd-util.h"
#include "fileio.h"
//#include "log.h"
-//#include "sleep-config.h"
-//#include "string-util.h"
+#include "sleep-config.h"
+#include "stdio-util.h"
+#include "string-util.h"
#include "strv.h"
//#include "util.h"
@@ -39,6 +28,67 @@
static char* arg_verb = NULL;
+static int write_hibernate_location_info(void) {
+ _cleanup_free_ char *device = NULL, *type = NULL;
+ _cleanup_free_ struct fiemap *fiemap = NULL;
+ char offset_str[DECIMAL_STR_MAX(uint64_t)];
+ char device_str[DECIMAL_STR_MAX(uint64_t)];
+ _cleanup_close_ int fd = -1;
+ struct stat stb;
+ uint64_t offset;
+ int r;
+
+ r = find_hibernate_location(&device, &type, NULL, NULL);
+ if (r < 0)
+ return log_debug_errno(r, "Unable to find hibernation location: %m");
+
+ /* if it's a swap partition, we just write the disk to /sys/power/resume */
+ if (streq(type, "partition"))
+ return write_string_file("/sys/power/resume", device, 0);
+ else if (!streq(type, "file"))
+ return log_debug_errno(EINVAL, "Invalid hibernate type %s: %m",
+ type);
+
+ /* Only available in 4.17+ */
+ if (access("/sys/power/resume_offset", F_OK) < 0) {
+ if (errno == ENOENT)
+ return 0;
+ return log_debug_errno(errno, "/sys/power/resume_offset unavailable: %m");
+ }
+
+ r = access("/sys/power/resume_offset", W_OK);
+ if (r < 0)
+ return log_debug_errno(errno, "/sys/power/resume_offset not writeable: %m");
+
+ fd = open(device, O_RDONLY | O_CLOEXEC | O_NONBLOCK);
+ if (fd < 0)
+ return log_debug_errno(errno, "Unable to open '%s': %m", device);
+ r = fstat(fd, &stb);
+ if (r < 0)
+ return log_debug_errno(errno, "Unable to stat %s: %m", device);
+ r = read_fiemap(fd, &fiemap);
+ if (r < 0)
+ return log_debug_errno(r, "Unable to read extent map for '%s': %m",
+ device);
+ if (fiemap->fm_mapped_extents == 0) {
+ log_debug("No extents found in '%s'", device);
+ return -EINVAL;
+ }
+ offset = fiemap->fm_extents[0].fe_physical / page_size();
+ xsprintf(offset_str, "%" PRIu64, offset);
+ r = write_string_file("/sys/power/resume_offset", offset_str, 0);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to write offset '%s': %m",
+ offset_str);
+
+ xsprintf(device_str, "%lx", (unsigned long)stb.st_dev);
+ r = write_string_file("/sys/power/resume", device_str, 0);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to write device '%s': %m",
+ device_str);
+ return 0;
+}
+
static int write_mode(char **modes) {
int r = 0;
char **mode;
@@ -56,9 +106,6 @@ static int write_mode(char **modes) {
r = k;
}
- if (r < 0)
- log_error_errno(r, "Failed to write mode to /sys/power/disk: %m");
-
return r;
}
@@ -69,7 +116,7 @@ static int write_state(FILE **f, char **states) {
STRV_FOREACH(state, states) {
int k;
- k = write_string_stream(*f, *state, true);
+ k = write_string_stream(*f, *state, 0);
if (k == 0)
return 0;
log_debug_errno(k, "Failed to write '%s' to /sys/power/state: %m",
@@ -80,13 +127,28 @@ static int write_state(FILE **f, char **states) {
fclose(*f);
*f = fopen("/sys/power/state", "we");
if (!*f)
- return log_error_errno(errno, "Failed to open /sys/power/state: %m");
+ return -errno;
}
return r;
}
+#if 0 /// elogind uses the values stored in its manager instance
static int execute(char **modes, char **states) {
+#else
+static int execute(Manager *m, const char *verb) {
+ assert(m);
+
+ if (verb)
+ arg_verb = (char*)verb;
+
+ char **modes = streq(arg_verb, "suspend") ? m->suspend_mode :
+ streq(arg_verb, "hibernate") ? m->hibernate_mode :
+ m->hybrid_sleep_mode;
+ char **states = streq(arg_verb, "suspend") ? m->suspend_state :
+ streq(arg_verb, "hibernate") ? m->hibernate_state :
+ m->hybrid_sleep_state;
+#endif // 0
char *arguments[] = {
NULL,
@@ -94,7 +156,10 @@ static int execute(char **modes, char **states) {
arg_verb,
NULL
};
- static const char* const dirs[] = {SYSTEM_SLEEP_PATH, NULL};
+ static const char* const dirs[] = {
+ SYSTEM_SLEEP_PATH,
+ NULL
+ };
int r;
_cleanup_fclose_ FILE *f = NULL;
@@ -106,27 +171,30 @@ static int execute(char **modes, char **states) {
return log_error_errno(errno, "Failed to open /sys/power/state: %m");
/* Configure the hibernation mode */
- r = write_mode(modes);
- if (r < 0)
- return r;
+ if (!strv_isempty(modes)) {
+ r = write_hibernate_location_info();
+ if (r < 0)
+ return log_error_errno(r, "Failed to write hibernation disk offset: %m");
+ r = write_mode(modes);
+ if (r < 0)
+ return log_error_errno(r, "Failed to write mode to /sys/power/disk: %m");;
+ }
execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments);
log_struct(LOG_INFO,
"MESSAGE_ID=" SD_MESSAGE_SLEEP_START_STR,
LOG_MESSAGE("Suspending system..."),
- "SLEEP=%s", arg_verb,
- NULL);
+ "SLEEP=%s", arg_verb);
r = write_state(&f, states);
if (r < 0)
- return r;
+ return log_error_errno(r, "Failed to write /sys/power/state: %m");
log_struct(LOG_INFO,
"MESSAGE_ID=" SD_MESSAGE_SLEEP_STOP_STR,
LOG_MESSAGE("System resumed."),
- "SLEEP=%s", arg_verb,
- NULL);
+ "SLEEP=%s", arg_verb);
arguments[1] = (char*) "post";
execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments);
@@ -134,6 +202,100 @@ static int execute(char **modes, char **states) {
return r;
}
+static int read_wakealarm(uint64_t *result) {
+ _cleanup_free_ char *t = NULL;
+
+ if (read_one_line_file("/sys/class/rtc/rtc0/since_epoch", &t) >= 0)
+ return safe_atou64(t, result);
+ return -EBADF;
+}
+
+static int write_wakealarm(const char *str) {
+
+ _cleanup_fclose_ FILE *f = NULL;
+ int r;
+
+ f = fopen("/sys/class/rtc/rtc0/wakealarm", "we");
+ if (!f)
+ return log_error_errno(errno, "Failed to open /sys/class/rtc/rtc0/wakealarm: %m");
+
+ r = write_string_stream(f, str, 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to write '%s' to /sys/class/rtc/rtc0/wakealarm: %m", str);
+
+ return 0;
+}
+
+#if 0 /// elogind uses the values stored in its manager instance
+static int execute_s2h(usec_t hibernate_delay_sec) {
+
+ _cleanup_strv_free_ char **hibernate_modes = NULL, **hibernate_states = NULL,
+ **suspend_modes = NULL, **suspend_states = NULL;
+#else
+static int execute_s2h(Manager *m) {
+ assert(m);
+
+ usec_t hibernate_delay_sec = m->hibernate_delay_sec;
+#endif // 0
+ usec_t orig_time, cmp_time;
+ char time_str[DECIMAL_STR_MAX(uint64_t)];
+ int r;
+
+#if 0 /// Already parsed by elogind config
+ r = parse_sleep_config("suspend", &suspend_modes, &suspend_states,
+ NULL);
+ if (r < 0)
+ return r;
+
+ r = parse_sleep_config("hibernate", &hibernate_modes,
+ &hibernate_states, NULL);
+ if (r < 0)
+ return r;
+#endif // 0
+
+ r = read_wakealarm(&orig_time);
+ if (r < 0)
+ return log_error_errno(errno, "Failed to read time: %d", r);
+
+ orig_time += hibernate_delay_sec / USEC_PER_SEC;
+ xsprintf(time_str, "%" PRIu64, orig_time);
+
+ r = write_wakealarm(time_str);
+ if (r < 0)
+ return r;
+
+ log_debug("Set RTC wake alarm for %s", time_str);
+
+#if 0 /// elogind uses its manager instance values
+ r = execute(suspend_modes, suspend_states);
+#else
+ r = execute(m, "suspend");
+#endif // 0
+ if (r < 0)
+ return r;
+
+ r = read_wakealarm(&cmp_time);
+ if (r < 0)
+ return log_error_errno(errno, "Failed to read time: %d", r);
+
+ /* reset RTC */
+ r = write_wakealarm("0");
+ if (r < 0)
+ return r;
+
+ log_debug("Woke up at %"PRIu64, cmp_time);
+
+ /* if woken up after alarm time, hibernate */
+ if (cmp_time >= orig_time)
+#if 0 /// elogind uses its manager instance values
+ r = execute(hibernate_modes, hibernate_states);
+#else
+ r = execute(m, "hibernate");
+#endif // 0
+
+ return r;
+}
+
#if 0 /// elogind calls execute() by itself and does not need another binary
static void help(void) {
printf("%s COMMAND\n\n"
@@ -144,6 +306,8 @@ static void help(void) {
" suspend Suspend the system\n"
" hibernate Hibernate the system\n"
" hybrid-sleep Both hibernate and suspend the system\n"
+ " suspend-then-hibernate Initially suspend and then hibernate\n"
+ " the system after a fixed period of time\n"
, program_invocation_short_name);
}
@@ -189,7 +353,8 @@ static int parse_argv(int argc, char *argv[]) {
if (!streq(arg_verb, "suspend") &&
!streq(arg_verb, "hibernate") &&
- !streq(arg_verb, "hybrid-sleep")) {
+ !streq(arg_verb, "hybrid-sleep") &&
+ !streq(arg_verb, "suspend-then-hibernate")) {
log_error("Unknown command '%s'.", arg_verb);
return -EINVAL;
}
@@ -199,6 +364,7 @@ static int parse_argv(int argc, char *argv[]) {
int main(int argc, char *argv[]) {
_cleanup_strv_free_ char **modes = NULL, **states = NULL;
+ usec_t delay = 0;
int r;
log_set_target(LOG_TARGET_AUTO);
@@ -209,19 +375,27 @@ int main(int argc, char *argv[]) {
if (r <= 0)
goto finish;
- r = parse_sleep_config(arg_verb, &modes, &states);
+ r = parse_sleep_config(arg_verb, &modes, &states, &delay);
if (r < 0)
goto finish;
- r = execute(modes, states);
-
+ if (streq(arg_verb, "suspend-then-hibernate"))
+ r = execute_s2h(delay);
+ else
+ r = execute(modes, states);
finish:
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
#else
-int do_sleep(const char *verb, char **modes, char **states) {
+int do_sleep(Manager *m, const char *verb) {
assert(verb);
+ assert(m);
+
arg_verb = (char*)verb;
- return execute(modes, states);
+
+ if (streq(arg_verb, "suspend-then-hibernate"))
+ return execute_s2h(m);
+
+ return execute(m, NULL);
}
#endif // 0
diff --git a/src/sleep/sleep.h b/src/sleep/sleep.h
index 85669fa07..eeffa21e2 100644
--- a/src/sleep/sleep.h
+++ b/src/sleep/sleep.h
@@ -21,6 +21,8 @@
along with elogind; If not, see <http://www.gnu.org/licenses/>.
***/
-int do_sleep(const char *verb, char **modes, char **states);
+#include <logind.h>
+
+int do_sleep(Manager *m, const char *verb);
#endif // ELOGIND_SRC_SLEEP_SLEEP_H_INCLUDED
diff --git a/src/systemd/Makefile b/src/systemd/Makefile
deleted file mode 120000
index d0b0e8e00..000000000
--- a/src/systemd/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/systemd/_sd-common.h b/src/systemd/_sd-common.h
index 97c394386..7b54d179e 100644
--- a/src/systemd/_sd-common.h
+++ b/src/systemd/_sd-common.h
@@ -1,10 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#ifndef foosdcommonhfoo
#define foosdcommonhfoo
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
diff --git a/src/systemd/meson.build b/src/systemd/meson.build
new file mode 100644
index 000000000..66b1737fa
--- /dev/null
+++ b/src/systemd/meson.build
@@ -0,0 +1,96 @@
+# SPDX-License-Identifier: LGPL-2.1+
+
+#if 0 /// No systemd-journal in elogind ...
+# _systemd_headers = '''
+# sd-bus.h
+# sd-bus-protocol.h
+# sd-bus-vtable.h
+# sd-daemon.h
+# sd-event.h
+# sd-id128.h
+# sd-journal.h
+# sd-login.h
+# sd-messages.h
+# '''.split()
+#else
+_systemd_headers = '''
+ sd-bus.h
+ sd-bus-protocol.h
+ sd-bus-vtable.h
+ sd-daemon.h
+ sd-event.h
+ sd-id128.h
+ sd-login.h
+ sd-messages.h
+'''.split()
+#endif // 0
+
+# https://github.com/mesonbuild/meson/issues/1633
+systemd_headers = files(_systemd_headers)
+
+# sd-device.h
+# sd-hwdb.h
+# sd-dhcp6-client.h
+# sd-dhcp6-lease.h
+# sd-dhcp-client.h
+# sd-dhcp-lease.h
+# sd-dhcp-server.h
+# sd-ipv4acd.h
+# sd-ipv4ll.h
+# sd-lldp.h
+# sd-ndisc.h
+# sd-netlink.h
+# sd-network.h
+# sd-path.h
+# sd-resolve.h
+# sd-utf8.h
+
+install_headers(
+ systemd_headers,
+ '_sd-common.h',
+#if 0 /// elogind needs them somewhere else
+# subdir : 'systemd')
+#else
+ subdir : 'elogind/systemd')
+
+meson.add_install_script(meson_symlink_headers,
+ includedir,
+ _systemd_headers,
+ '_sd-common.h')
+#endif // 0
+
+
+############################################################
+
+opts = [['c'],
+ ['c', '-ansi'],
+ ['c', '-std=iso9899:1990'],
+ ['c', '-std=iso9899:2011']]
+
+if cc.has_argument('-std=iso9899:2017')
+ opts += [['c', '-std=iso9899:2017']]
+endif
+
+cxx = find_program('c++', required : false)
+if cxx.found()
+ opts += [['c++'],
+ ['c++', '-std=c++98'],
+ ['c++', '-std=c++11']]
+ if cc.has_argument('-std=c++14')
+ opts += [['c++', '-std=c++14']]
+ endif
+ if cc.has_argument('-std=c++17')
+ opts += [['c++', '-std=c++17']]
+ endif
+endif
+
+foreach header : _systemd_headers
+ foreach opt : opts
+ name = ''.join([header, ':'] + opt)
+ test('cc-' + name,
+ check_compilation_sh,
+ args : cc.cmd_array() + ['-c', '-x'] + opt +
+ ['-Werror', '-include',
+ join_paths(meson.current_source_dir(), header)])
+ endforeach
+endforeach
diff --git a/src/systemd/sd-bus-protocol.h b/src/systemd/sd-bus-protocol.h
index 623cee0c5..acff670f7 100644
--- a/src/systemd/sd-bus-protocol.h
+++ b/src/systemd/sd-bus-protocol.h
@@ -1,10 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#ifndef foosdbusprotocolhfoo
#define foosdbusprotocolhfoo
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
diff --git a/src/systemd/sd-bus-vtable.h b/src/systemd/sd-bus-vtable.h
index 1e82cae03..126808549 100644
--- a/src/systemd/sd-bus-vtable.h
+++ b/src/systemd/sd-bus-vtable.h
@@ -1,10 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#ifndef foosdbusvtablehfoo
#define foosdbusvtablehfoo
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
@@ -156,8 +154,7 @@ struct sd_bus_vtable {
{ \
.type = _SD_BUS_VTABLE_END, \
.flags = 0, \
- .x = { \
- }, \
+ .x = { { 0 } }, \
}
_SD_END_DECLARATIONS;
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index a452cd3af..7ce69d2aa 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -1,10 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#ifndef foosdbushfoo
#define foosdbushfoo
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
@@ -32,6 +30,10 @@
_SD_BEGIN_DECLARATIONS;
+#define SD_BUS_DEFAULT ((sd_bus *) 1)
+#define SD_BUS_DEFAULT_USER ((sd_bus *) 2)
+#define SD_BUS_DEFAULT_SYSTEM ((sd_bus *) 3)
+
/* Types */
typedef struct sd_bus sd_bus;
@@ -106,6 +108,7 @@ typedef int (*sd_bus_property_set_t) (sd_bus *bus, const char *path, const char
typedef int (*sd_bus_object_find_t) (sd_bus *bus, const char *path, const char *interface, void *userdata, void **ret_found, sd_bus_error *ret_error);
typedef int (*sd_bus_node_enumerator_t) (sd_bus *bus, const char *prefix, void *userdata, char ***ret_nodes, sd_bus_error *ret_error);
typedef int (*sd_bus_track_handler_t) (sd_bus_track *track, void *userdata);
+typedef void (*sd_bus_destroy_t)(void *userdata);
#include "sd-bus-protocol.h"
#include "sd-bus-vtable.h"
@@ -117,8 +120,11 @@ int sd_bus_default_user(sd_bus **ret);
int sd_bus_default_system(sd_bus **ret);
int sd_bus_open(sd_bus **ret);
+int sd_bus_open_with_description(sd_bus **ret, const char *description);
int sd_bus_open_user(sd_bus **ret);
+int sd_bus_open_user_with_description(sd_bus **ret, const char *description);
int sd_bus_open_system(sd_bus **ret);
+int sd_bus_open_system_with_description(sd_bus **ret, const char *description);
int sd_bus_open_system_remote(sd_bus **ret, const char *host);
int sd_bus_open_system_machine(sd_bus **ret, const char *machine);
@@ -149,8 +155,14 @@ int sd_bus_set_allow_interactive_authorization(sd_bus *bus, int b);
int sd_bus_get_allow_interactive_authorization(sd_bus *bus);
int sd_bus_set_exit_on_disconnect(sd_bus *bus, int b);
int sd_bus_get_exit_on_disconnect(sd_bus *bus);
+int sd_bus_set_watch_bind(sd_bus *bus, int b);
+int sd_bus_get_watch_bind(sd_bus *bus);
+int sd_bus_set_connected_signal(sd_bus *bus, int b);
+int sd_bus_get_connected_signal(sd_bus *bus);
+int sd_bus_set_sender(sd_bus *bus, const char *sender);
+int sd_bus_get_sender(sd_bus *bus, const char **ret);
-int sd_bus_start(sd_bus *ret);
+int sd_bus_start(sd_bus *bus);
int sd_bus_try_close(sd_bus *bus);
void sd_bus_close(sd_bus *bus);
@@ -162,6 +174,7 @@ sd_bus *sd_bus_flush_close_unref(sd_bus *bus);
void sd_bus_default_flush_close(void);
int sd_bus_is_open(sd_bus *bus);
+int sd_bus_is_ready(sd_bus *bus);
int sd_bus_get_bus_id(sd_bus *bus, sd_id128_t *id);
int sd_bus_get_scope(sd_bus *bus, const char **scope);
@@ -190,8 +203,12 @@ int sd_bus_attach_event(sd_bus *bus, sd_event *e, int priority);
int sd_bus_detach_event(sd_bus *bus);
sd_event *sd_bus_get_event(sd_bus *bus);
+int sd_bus_get_n_queued_read(sd_bus *bus, uint64_t *ret);
+int sd_bus_get_n_queued_write(sd_bus *bus, uint64_t *ret);
+
int sd_bus_add_filter(sd_bus *bus, sd_bus_slot **slot, sd_bus_message_handler_t callback, void *userdata);
int sd_bus_add_match(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, void *userdata);
+int sd_bus_add_match_async(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, sd_bus_message_handler_t install_callback, void *userdata);
int sd_bus_add_object(sd_bus *bus, sd_bus_slot **slot, const char *path, sd_bus_message_handler_t callback, void *userdata);
int sd_bus_add_fallback(sd_bus *bus, sd_bus_slot **slot, const char *prefix, sd_bus_message_handler_t callback, void *userdata);
int sd_bus_add_object_vtable(sd_bus *bus, sd_bus_slot **slot, const char *path, const char *interface, const sd_bus_vtable *vtable, void *userdata);
@@ -209,6 +226,10 @@ void *sd_bus_slot_get_userdata(sd_bus_slot *slot);
void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata);
int sd_bus_slot_set_description(sd_bus_slot *slot, const char *description);
int sd_bus_slot_get_description(sd_bus_slot *slot, const char **description);
+int sd_bus_slot_get_floating(sd_bus_slot *slot);
+int sd_bus_slot_set_floating(sd_bus_slot *slot, int b);
+int sd_bus_slot_set_destroy_callback(sd_bus_slot *s, sd_bus_destroy_t callback);
+int sd_bus_slot_get_destroy_callback(sd_bus_slot *s, sd_bus_destroy_t *callback);
sd_bus_message* sd_bus_slot_get_current_message(sd_bus_slot *slot);
sd_bus_message_handler_t sd_bus_slot_get_current_handler(sd_bus_slot *bus);
@@ -216,6 +237,7 @@ void *sd_bus_slot_get_current_userdata(sd_bus_slot *slot);
/* Message object */
+int sd_bus_message_new(sd_bus *bus, sd_bus_message **m, uint8_t type);
int sd_bus_message_new_signal(sd_bus *bus, sd_bus_message **m, const char *path, const char *interface, const char *member);
int sd_bus_message_new_method_call(sd_bus *bus, sd_bus_message **m, const char *destination, const char *path, const char *interface, const char *member);
int sd_bus_message_new_method_return(sd_bus_message *call, sd_bus_message **m);
@@ -227,6 +249,8 @@ int sd_bus_message_new_method_errnof(sd_bus_message *call, sd_bus_message **m, i
sd_bus_message* sd_bus_message_ref(sd_bus_message *m);
sd_bus_message* sd_bus_message_unref(sd_bus_message *m);
+int sd_bus_message_seal(sd_bus_message *m, uint64_t cookie, uint64_t timeout_usec);
+
int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type);
int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie);
int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie);
@@ -263,6 +287,7 @@ int sd_bus_message_set_auto_start(sd_bus_message *m, int b);
int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b);
int sd_bus_message_set_destination(sd_bus_message *m, const char *destination);
+int sd_bus_message_set_sender(sd_bus_message *m, const char *sender);
int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority);
int sd_bus_message_append(sd_bus_message *m, const char *types, ...);
@@ -296,7 +321,9 @@ int sd_bus_message_rewind(sd_bus_message *m, int complete);
int sd_bus_get_unique_name(sd_bus *bus, const char **unique);
int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags);
+int sd_bus_request_name_async(sd_bus *bus, sd_bus_slot **ret_slot, const char *name, uint64_t flags, sd_bus_message_handler_t callback, void *userdata);
int sd_bus_release_name(sd_bus *bus, const char *name);
+int sd_bus_release_name_async(sd_bus *bus, sd_bus_slot **ret_slot, const char *name, sd_bus_message_handler_t callback, void *userdata);
int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable); /* free the results */
int sd_bus_get_name_creds(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **creds); /* unref the result! */
int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine);
@@ -332,6 +359,9 @@ int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *in
int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **creds);
int sd_bus_query_sender_privilege(sd_bus_message *call, int capability);
+int sd_bus_match_signal(sd_bus *bus, sd_bus_slot **ret, const char *sender, const char *path, const char *interface, const char *member, sd_bus_message_handler_t callback, void *userdata);
+int sd_bus_match_signal_async(sd_bus *bus, sd_bus_slot **ret, const char *sender, const char *path, const char *interface, const char *member, sd_bus_message_handler_t match_callback, sd_bus_message_handler_t add_callback, void *userdata);
+
/* Credential handling */
int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t creds_mask);
@@ -357,12 +387,14 @@ int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **comm);
int sd_bus_creds_get_exe(sd_bus_creds *c, const char **exe);
int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline);
int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **cgroup);
-#if 0 /// unsupported by elogind
+#if 0 /** unsupported by elogind **/
int sd_bus_creds_get_unit(sd_bus_creds *c, const char **unit);
+#endif /** 0 **/
int sd_bus_creds_get_slice(sd_bus_creds *c, const char **slice);
+#if 0 /** UNNEEDED by elogind **/
int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **unit);
+#endif /** 0 **/
int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **slice);
-#endif // 0
int sd_bus_creds_get_session(sd_bus_creds *c, const char **session);
int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid);
int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability);
@@ -454,6 +486,9 @@ const char* sd_bus_track_contains(sd_bus_track *track, const char *name);
const char* sd_bus_track_first(sd_bus_track *track);
const char* sd_bus_track_next(sd_bus_track *track);
+int sd_bus_track_set_destroy_callback(sd_bus_track *s, sd_bus_destroy_t callback);
+int sd_bus_track_get_destroy_callback(sd_bus_track *s, sd_bus_destroy_t *ret);
+
/* Define helpers so that __attribute__((cleanup(sd_bus_unrefp))) and similar may be used. */
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus, sd_bus_unref);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus, sd_bus_flush_close_unref);
diff --git a/src/systemd/sd-daemon.h b/src/systemd/sd-daemon.h
index cd9e30e9e..862ab07eb 100644
--- a/src/systemd/sd-daemon.h
+++ b/src/systemd/sd-daemon.h
@@ -1,10 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#ifndef foosddaemonhfoo
#define foosddaemonhfoo
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
@@ -22,6 +20,7 @@
#include <inttypes.h>
#include <sys/types.h>
+#include <sys/socket.h>
#include "_sd-common.h"
@@ -160,7 +159,7 @@ int sd_is_socket_sockaddr(int fd, int type, const struct sockaddr* addr, unsigne
*/
int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length);
-#if 0 /// UNNEEDED by elogind
+#if 0 /** UNNEEDED by elogind **/
/*
Helper call for identifying a passed file descriptor. Returns 1 if
the file descriptor is a POSIX Message Queue of the specified name,
@@ -170,19 +169,29 @@ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t
See sd_is_mq(3) for more information.
*/
int sd_is_mq(int fd, const char *path);
-#endif // 0
+#endif /** 0 **/
/*
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
+ MAINPID=... The main PID of a daemon, in case elogind did not
+ fork off the process itself. Example: "MAINPID=4711"
+
+ READY=1 Tells elogind that daemon startup or daemon reload
+ 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".
+ RELOADING=1 Tell elogind that the daemon began reloading its
+ configuration. When the configuration has been
+ reloaded completely, READY=1 should be sent to inform
+ elogind about this.
+
+ STOPPING=1 Tells elogind that the daemon is about to go down.
+
STATUS=... Passes a single-line status string back to systemd
that describes the daemon state. This is free-form
and can be used for various purposes: general state
@@ -197,25 +206,31 @@ int sd_is_mq(int fd, const char *path);
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. Also see
sd_watchdog_enabled() below.
+ WATCHDOG_USEC=...
+ Reset watchdog_usec value during runtime.
+ To reset watchdog_usec value, start the service again.
+ Example: "WATCHDOG_USEC=20000000"
+
FDSTORE=1 Store the file descriptors passed along with the
message in the per-service file descriptor store,
and pass them to the main process again on next
invocation. This variable is only supported with
sd_pid_notify_with_fds().
- WATCHDOG_USEC=...
- Reset watchdog_usec value during runtime.
- To reset watchdog_usec value, start the service again.
- Example: "WATCHDOG_USEC=20000000"
+ FDSTOREREMOVE=1
+ Remove one or more file descriptors from the file
+ descriptor store, identified by the name specified
+ in FDNAME=, see below.
+
+ FDNAME= A name to assign to new file descriptors stored in the
+ file descriptor store, or the name of the file descriptors
+ to remove in case of FDSTOREREMOVE=1.
Daemons can choose to send additional variables. However, it is
recommended to prefix variable names not listed above with X_.
diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h
index f8cb89566..e6f2c50a8 100644
--- a/src/systemd/sd-event.h
+++ b/src/systemd/sd-event.h
@@ -1,10 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#ifndef foosdeventhfoo
#define foosdeventhfoo
/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
@@ -23,8 +21,10 @@
#include <inttypes.h>
#include <signal.h>
#include <sys/epoll.h>
+#include <sys/inotify.h>
#include <sys/signalfd.h>
#include <sys/types.h>
+/*#include <time.h>*/
#include "_sd-common.h"
@@ -39,6 +39,8 @@
_SD_BEGIN_DECLARATIONS;
+#define SD_EVENT_DEFAULT ((sd_event *) 1)
+
typedef struct sd_event sd_event;
typedef struct sd_event_source sd_event_source;
@@ -74,6 +76,8 @@ typedef int (*sd_event_child_handler_t)(sd_event_source *s, const siginfo_t *si,
#else
typedef void* sd_event_child_handler_t;
#endif
+typedef int (*sd_event_inotify_handler_t)(sd_event_source *s, const struct inotify_event *event, void *userdata);
+typedef void (*sd_event_destroy_t)(void *userdata);
int sd_event_default(sd_event **e);
@@ -85,6 +89,7 @@ int sd_event_add_io(sd_event *e, sd_event_source **s, int fd, uint32_t events, s
int sd_event_add_time(sd_event *e, sd_event_source **s, clockid_t clock, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata);
int sd_event_add_signal(sd_event *e, sd_event_source **s, int sig, sd_event_signal_handler_t callback, void *userdata);
int sd_event_add_child(sd_event *e, sd_event_source **s, pid_t pid, int options, sd_event_child_handler_t callback, void *userdata);
+int sd_event_add_inotify(sd_event *e, sd_event_source **s, const char *path, uint32_t mask, sd_event_inotify_handler_t callback, void *userdata);
int sd_event_add_defer(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata);
int sd_event_add_post(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata);
int sd_event_add_exit(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata);
@@ -123,6 +128,8 @@ int sd_event_source_get_enabled(sd_event_source *s, int *enabled);
int sd_event_source_set_enabled(sd_event_source *s, int enabled);
int sd_event_source_get_io_fd(sd_event_source *s);
int sd_event_source_set_io_fd(sd_event_source *s, int fd);
+int sd_event_source_get_io_fd_own(sd_event_source *s);
+int sd_event_source_set_io_fd_own(sd_event_source *s, int own);
int sd_event_source_get_io_events(sd_event_source *s, uint32_t* events);
int sd_event_source_set_io_events(sd_event_source *s, uint32_t events);
int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents);
@@ -133,6 +140,9 @@ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec);
int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *clock);
int sd_event_source_get_signal(sd_event_source *s);
int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid);
+int sd_event_source_get_inotify_mask(sd_event_source *s, uint32_t *ret);
+int sd_event_source_set_destroy_callback(sd_event_source *s, sd_event_destroy_t callback);
+int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_destroy_t *ret);
/* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref);
diff --git a/src/systemd/sd-id128.h b/src/systemd/sd-id128.h
index 9b38969b7..b24fd06f0 100644
--- a/src/systemd/sd-id128.h
+++ b/src/systemd/sd-id128.h
@@ -1,10 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#ifndef foosdid128hfoo
#define foosdid128hfoo
/***
- 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
diff --git a/src/systemd/sd-login.h b/src/systemd/sd-login.h
index e3ecbd837..a4f70ef7c 100644
--- a/src/systemd/sd-login.h
+++ b/src/systemd/sd-login.h
@@ -1,10 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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
diff --git a/src/systemd/sd-messages.h b/src/systemd/sd-messages.h
index f466d9b06..2adfe1606 100644
--- a/src/systemd/sd-messages.h
+++ b/src/systemd/sd-messages.h
@@ -1,10 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#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
@@ -69,6 +67,8 @@ _SD_BEGIN_DECLARATIONS;
#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_TIMEZONE_CHANGE_STR SD_ID128_MAKE_STR(45,f8,2f,4a,ef,7a,4b,bf,94,2c,e8,61,d1,f2,09,90)
+#define SD_MESSAGE_TAINTED SD_ID128_MAKE(50,87,6a,9d,b0,0f,4c,40,bd,e1,a2,ad,38,1c,3a,1b)
+#define SD_MESSAGE_TAINTED_STR SD_ID128_MAKE_STR(50,87,6a,9d,b0,0f,4c,40,bd,e1,a2,ad,38,1c,3a,1b)
#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_STARTUP_FINISHED_STR SD_ID128_MAKE_STR(b0,7a,24,9c,d0,24,41,4a,82,dd,00,cd,18,13,78,ff)
#define SD_MESSAGE_USER_STARTUP_FINISHED \
@@ -99,6 +99,13 @@ _SD_BEGIN_DECLARATIONS;
#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_UNIT_RELOADED_STR SD_ID128_MAKE_STR(7b,05,eb,c6,68,38,42,22,ba,a8,88,11,79,cf,da,54)
+#define SD_MESSAGE_UNIT_RESTART_SCHEDULED SD_ID128_MAKE(5e,b0,34,94,b6,58,48,70,a5,36,b3,37,29,08,09,b3)
+#define SD_MESSAGE_UNIT_RESTART_SCHEDULED_STR \
+ SD_ID128_MAKE_STR(5e,b0,34,94,b6,58,48,70,a5,36,b3,37,29,08,09,b3)
+
+#define SD_MESSAGE_UNIT_RESOURCES SD_ID128_MAKE(ae,8f,7b,86,6b,03,47,b9,af,31,fe,1c,80,b1,27,c0)
+#define SD_MESSAGE_UNIT_RESOURCES_STR SD_ID128_MAKE_STR(ae,8f,7b,86,6b,03,47,b9,af,31,fe,1c,80,b1,27,c0)
+
#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_SPAWN_FAILED_STR SD_ID128_MAKE_STR(64,12,57,65,1c,1b,4e,c9,a8,62,4d,7a,40,a9,e1,e7)
diff --git a/src/test/.gitignore b/src/test/.gitignore
deleted file mode 100644
index e4c198a4f..000000000
--- a/src/test/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-test-hashmap-ordered.c
diff --git a/src/test/Makefile b/src/test/Makefile
deleted file mode 120000
index d0b0e8e00..000000000
--- a/src/test/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/test/generate-sym-test.py b/src/test/generate-sym-test.py
new file mode 100755
index 000000000..357cce8e4
--- /dev/null
+++ b/src/test/generate-sym-test.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+import sys, re
+
+print('#include <stdio.h>')
+for header in sys.argv[2:]:
+ print('#include "{}"'.format(header.split('/')[-1]))
+
+print('''
+void* functions[] = {''')
+
+for line in open(sys.argv[1]):
+ match = re.search('^ +([a-zA-Z0-9_]+);', line)
+ if match:
+ print(' {},'.format(match.group(1)))
+
+print('''};
+
+int main(void) {
+ unsigned i;
+ for (i = 0; i < sizeof(functions)/sizeof(void*); i++)
+ printf("%p\\n", functions[i]);
+ return 0;
+}''')
diff --git a/src/test/meson.build b/src/test/meson.build
new file mode 100644
index 000000000..0405fac52
--- /dev/null
+++ b/src/test/meson.build
@@ -0,0 +1,1062 @@
+# SPDX-License-Identifier: LGPL-2.1+
+
+awkscript = 'test-hashmap-ordered.awk'
+test_hashmap_ordered_c = custom_target(
+ 'test-hashmap-ordered.c',
+ input : [awkscript, 'test-hashmap-plain.c'],
+ output : 'test-hashmap-ordered.c',
+ command : [awk, '-f', '@INPUT0@', '@INPUT1@'],
+ capture : true)
+
+test_include_dir = include_directories('.')
+
+path = run_command('sh', ['-c', 'echo "$PATH"']).stdout()
+test_env = environment()
+#if 0 /// UNNEEDED in elogind
+# test_env.set('SYSTEMD_KBD_MODEL_MAP', kbd_model_map)
+# test_env.set('SYSTEMD_LANGUAGE_FALLBACK_MAP', language_fallback_map)
+#endif // 0
+test_env.set('PATH', path)
+test_env.prepend('PATH', meson.build_root())
+
+############################################################
+
+generate_sym_test_py = find_program('generate-sym-test.py')
+
+test_libelogind_sym_c = custom_target(
+ 'test-libelogind-sym.c',
+ input : [libelogind_sym_path] + systemd_headers,
+ output : 'test-libelogind-sym.c',
+ command : [generate_sym_test_py, libelogind_sym_path] + systemd_headers,
+ capture : true)
+
+#if 0 /// UNNEEDED in elogind
+# test_libudev_sym_c = custom_target(
+# 'test-libudev-sym.c',
+# input : [libudev_sym_path, libudev_h_path],
+# output : 'test-libudev-sym.c',
+# command : [generate_sym_test_py, '@INPUT0@', '@INPUT1@'],
+# capture : true)
+#endif // 0
+
+test_dlopen_c = files('test-dlopen.c')
+
+############################################################
+
+#if 0 /// UNNEEDED by elogind
+# test_systemd_tmpfiles_py = find_program('test-systemd-tmpfiles.py')
+#endif // 0
+
+############################################################
+
+tests += [
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-device-nodes.c'],
+# [],
+# []],
+#
+# [['src/test/test-engine.c',
+# 'src/test/test-helper.c'],
+# [libcore,
+# libudev,
+# libshared],
+# [threads,
+# librt,
+# libseccomp,
+# libselinux,
+# libmount,
+# libblkid]],
+#
+# [['src/test/test-job-type.c'],
+# [libcore,
+# libshared],
+# [threads,
+# librt,
+# libseccomp,
+# libselinux,
+# libmount,
+# libblkid]],
+#
+# [['src/test/test-ns.c'],
+# [libcore,
+# libshared],
+# [threads,
+# librt,
+# libseccomp,
+# libselinux,
+# libmount,
+# libblkid],
+# '', 'manual'],
+#
+# [['src/test/test-loopback.c'],
+# [libcore,
+# libshared],
+# [threads,
+# librt,
+# libseccomp,
+# libselinux,
+# libmount,
+# libblkid]],
+#
+# [['src/test/test-hostname.c'],
+# [libcore,
+# libshared],
+# [threads,
+# librt,
+# libseccomp,
+# libselinux,
+# libmount,
+# libblkid],
+# '', 'unsafe'],
+#
+# [['src/test/test-dns-domain.c'],
+# [libcore,
+# libshared,
+# libsystemd_network],
+# []],
+#
+# [['src/test/test-boot-timestamps.c'],
+# [],
+# [],
+# 'ENABLE_EFI'],
+#
+# [['src/test/test-unit-name.c',
+# 'src/test/test-helper.c'],
+# [libcore,
+# libshared],
+# [threads,
+# librt,
+# libseccomp,
+# libselinux,
+# libmount,
+# libblkid]],
+#
+# [['src/test/test-unit-file.c',
+# 'src/test/test-helper.c'],
+# [libcore,
+# libshared],
+# [threads,
+# librt,
+# libseccomp,
+# libselinux,
+# libmount,
+# libblkid]],
+#endif // 0
+
+ [['src/test/test-utf8.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-capability.c'],
+# [],
+# [libcap]],
+#
+# [['src/test/test-async.c'],
+# [],
+# [],
+# '', 'timeout=120'],
+#endif // 0
+
+ [['src/test/test-locale-util.c'],
+ [],
+ []],
+
+ [['src/test/test-copy.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-sigbus.c'],
+# [],
+# []],
+#
+# [['src/test/test-condition.c'],
+# [],
+# []],
+#
+# [['src/test/test-fdset.c'],
+# [],
+# []],
+#
+# [['src/test/test-fstab-util.c'],
+# [],
+# []],
+#endif // 0
+
+ [['src/test/test-random-util.c'],
+ [],
+ []],
+
+ [['src/test/test-format-table.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-ratelimit.c'],
+# [],
+# []],
+#endif // 0
+
+ [['src/test/test-util.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-mount-util.c'],
+# [],
+# []],
+#endif // 0
+
+ [['src/test/test-exec-util.c'],
+ [],
+ []],
+
+ [['src/test/test-hexdecoct.c'],
+ [],
+ []],
+
+ [['src/test/test-alloc-util.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-xattr-util.c'],
+# [],
+# []],
+#endif // 0
+
+ [['src/test/test-io-util.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-glob-util.c'],
+# [],
+# []],
+#endif // 0
+
+ [['src/test/test-fs-util.c'],
+ [],
+ []],
+
+ [['src/test/test-proc-cmdline.c'],
+ [],
+ []],
+
+ [['src/test/test-fd-util.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-web-util.c'],
+# [],
+# []],
+#
+# [['src/test/test-cpu-set-util.c'],
+# [],
+# []],
+#endif // 0
+
+ [['src/test/test-stat-util.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-os-util.c'],
+# [],
+# []],
+#endif // 0
+
+ [['src/test/test-escape.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-specifier.c'],
+# [],
+# []],
+#endif // 0
+
+ [['src/test/test-string-util.c'],
+ [],
+ []],
+
+ [['src/test/test-extract-word.c'],
+ [],
+ []],
+
+ [['src/test/test-parse-util.c'],
+ [],
+ []],
+
+ [['src/test/test-user-util.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-hostname-util.c'],
+# [],
+# []],
+#endif // 0
+
+ [['src/test/test-process-util.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-terminal-util.c'],
+# [],
+# []],
+#
+# [['src/test/test-path-lookup.c'],
+# [],
+# []],
+#
+# [['src/test/test-uid-range.c'],
+# [],
+# []],
+#
+# [['src/test/test-cap-list.c',
+# generated_gperf_headers],
+# [],
+# [libcap]],
+#
+# [['src/test/test-socket-util.c'],
+# [],
+# []],
+#
+# [['src/test/test-in-addr-util.c'],
+# [],
+# []],
+#
+# [['src/test/test-barrier.c'],
+# [],
+# []],
+#
+# [['src/test/test-tmpfiles.c'],
+# [],
+# []],
+#
+# [['src/test/test-namespace.c'],
+# [libcore,
+# libshared],
+# [threads,
+# libblkid]],
+#endif // 0
+
+ [['src/test/test-verbs.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-install-root.c'],
+# [],
+# []],
+#
+# [['src/test/test-acl-util.c'],
+# [],
+# [],
+# 'HAVE_ACL'],
+#
+# [['src/test/test-seccomp.c'],
+# [],
+# [libseccomp],
+# 'HAVE_SECCOMP'],
+#
+# [['src/test/test-rlimit-util.c'],
+# [],
+# []],
+#
+# [['src/test/test-ask-password-api.c'],
+# [],
+# [],
+# '', 'manual'],
+#
+# [['src/test/test-dissect-image.c'],
+# [],
+# [libblkid],
+# '', 'manual'],
+#endif // 0
+
+ [['src/test/test-signal-util.c'],
+ [],
+ []],
+
+ [['src/test/test-selinux.c'],
+ [],
+ []],
+
+ [['src/test/test-sizeof.c'],
+ [libbasic],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-bpf.c',
+# 'src/test/test-helper.c'],
+# [libcore,
+# libshared],
+# [libmount,
+# threads,
+# librt,
+# libseccomp,
+# libselinux,
+# libblkid]],
+#
+# [['src/test/test-watch-pid.c',
+# 'src/test/test-helper.c'],
+# [libcore,
+# libshared],
+# [libmount,
+# threads,
+# librt,
+# libseccomp,
+# libselinux,
+# libblkid]],
+#endif // 0
+
+ [['src/test/test-hashmap.c',
+ 'src/test/test-hashmap-plain.c',
+ test_hashmap_ordered_c],
+ [],
+ [],
+ '', 'timeout=90'],
+
+ [['src/test/test-set.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-bitmap.c'],
+# [],
+# []],
+#
+# [['src/test/test-xml.c'],
+# [],
+# []],
+#endif // 0
+
+ [['src/test/test-list.c'],
+ [],
+ []],
+
+ [['src/test/test-procfs-util.c'],
+ [],
+ []],
+
+ [['src/test/test-unaligned.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-tables.c',
+# 'src/shared/test-tables.h',
+# 'src/journal/journald-server.c',
+# 'src/journal/journald-server.h'],
+# [libcore,
+# libjournal_core,
+# libudev_core,
+# libudev_static,
+# libsystemd_network,
+# libshared],
+# [threads,
+# libseccomp,
+# libmount,
+# libxz,
+# liblz4,
+# libblkid],
+# '', '', [], libudev_core_includes],
+#endif // 0
+
+ [['src/test/test-prioq.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-fileio.c'],
+# [],
+# []],
+#
+# [['src/test/test-time-util.c'],
+# [],
+# []],
+#
+# [['src/test/test-clock.c'],
+# [],
+# []],
+#
+# [['src/test/test-architecture.c'],
+# [],
+# []],
+#endif // 0
+
+ [['src/test/test-log.c'],
+ [],
+ []],
+
+ [['src/test/test-ipcrm.c'],
+ [],
+ [],
+ '', 'unsafe'],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-btrfs.c'],
+# [],
+# [],
+# '', 'manual'],
+#
+#
+# [['src/test/test-firewall-util.c'],
+# [libshared],
+# [],
+# 'HAVE_LIBIPTC'],
+#
+# [['src/test/test-netlink-manual.c'],
+# [],
+# [libkmod],
+# 'HAVE_KMOD', 'manual'],
+#endif // 0
+
+ [['src/test/test-ellipsize.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-date.c'],
+# [],
+# []],
+#
+# [['src/test/test-sleep.c'],
+# [],
+# []],
+#
+# [['src/test/test-replace-var.c'],
+# [],
+# []],
+#
+# [['src/test/test-calendarspec.c'],
+# [],
+# []],
+#endif // 0
+
+ [['src/test/test-strip-tab-ansi.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-daemon.c'],
+# [],
+# []],
+#endif // 0
+
+ [['src/test/test-cgroup.c'],
+ [],
+ [],
+ '', 'manual'],
+
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-cgroup-mask.c',
+# 'src/test/test-helper.c'],
+# [libcore,
+# libshared],
+# [threads,
+# librt,
+# libseccomp,
+# libselinux,
+# libmount,
+# libblkid]],
+#
+# [['src/test/test-cgroup-util.c'],
+# [],
+# []],
+#
+# [['src/test/test-env-util.c'],
+# [],
+# []],
+#
+# [['src/test/test-strbuf.c'],
+# [],
+# []],
+#
+# [['src/test/test-strv.c'],
+# [],
+# []],
+#endif // 0
+
+ [['src/test/test-path-util.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-path.c',
+# 'src/test/test-helper.c'],
+# [libcore,
+# libshared],
+# [threads,
+# librt,
+# libseccomp,
+# libselinux,
+# libmount,
+# libblkid]],
+#
+# [['src/test/test-execute.c',
+# 'src/test/test-helper.c'],
+# [libcore,
+# libshared],
+# [threads,
+# librt,
+# libseccomp,
+# libselinux,
+# libmount,
+# libblkid],
+# '', 'timeout=360'],
+#endif // 0
+
+ [['src/test/test-siphash24.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-strxcpyx.c'],
+# [],
+# []],
+#
+# [['src/test/test-install.c'],
+# [libcore,
+# libshared],
+# [],
+# '', 'manual'],
+#
+# [['src/test/test-watchdog.c'],
+# [],
+# []],
+#
+# [['src/test/test-sched-prio.c',
+# 'src/test/test-helper.c'],
+# [libcore,
+# libshared],
+# [threads,
+# librt,
+# libseccomp,
+# libselinux,
+# libmount,
+# libblkid]],
+#endif // 0
+
+ [['src/test/test-conf-files.c'],
+ [],
+ []],
+
+ [['src/test/test-conf-parser.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-af-list.c',
+# generated_gperf_headers],
+# [],
+# []],
+#
+# [['src/test/test-arphrd-list.c',
+# generated_gperf_headers],
+# [],
+# []],
+#
+# [['src/test/test-journal-importer.c'],
+# [],
+# []],
+#
+# [['src/test/test-libudev.c'],
+# [libshared],
+# []],
+#
+# [['src/test/test-udev.c'],
+# [libudev_core,
+# libudev_static,
+# libsystemd_network,
+# libshared],
+# [threads,
+# librt,
+# libblkid,
+# libkmod,
+# libacl],
+# '', 'manual'],
+#endif // 0
+
+ [['src/test/test-id128.c'],
+ [],
+ []],
+
+ [['src/test/test-hash.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/test/test-gcrypt-util.c'],
+# [],
+# [],
+# 'HAVE_GCRYPT'],
+#
+# [['src/test/test-nss.c'],
+# [],
+# [libdl],
+# '', 'manual'],
+#
+# [['src/test/test-umount.c',
+# 'src/core/mount-setup.c',
+# 'src/core/mount-setup.h',
+# 'src/core/umount.c',
+# 'src/core/umount.h'],
+# [],
+# [libmount]],
+#endif // 0
+
+ [['src/test/test-bus-util.c'],
+ [],
+ []],
+]
+
+############################################################
+
+# define some tests here, because the link_with deps were not defined earlier
+
+#if 0 /// No systemd-journal in elogind, of course
+# tests += [
+# [['src/journal/test-journal.c'],
+# [libjournal_core,
+# libshared],
+# [threads,
+# libxz,
+# liblz4]],
+#
+# [['src/journal/test-journal-send.c'],
+# [libjournal_core,
+# libshared],
+# [threads,
+# libxz,
+# liblz4]],
+#
+# [['src/journal/test-journal-syslog.c'],
+# [libjournal_core,
+# libshared],
+# [threads,
+# libxz,
+# liblz4,
+# libselinux]],
+#
+# [['src/journal/test-journal-match.c'],
+# [libjournal_core,
+# libshared],
+# [threads,
+# libxz,
+# liblz4]],
+#
+# [['src/journal/test-journal-enum.c'],
+# [libjournal_core,
+# libshared],
+# [threads,
+# libxz,
+# liblz4],
+# '', 'timeout=360'],
+#
+# [['src/journal/test-journal-stream.c'],
+# [libjournal_core,
+# libshared],
+# [threads,
+# libxz,
+# liblz4]],
+#
+# [['src/journal/test-journal-flush.c'],
+# [libjournal_core,
+# libshared],
+# [threads,
+# libxz,
+# liblz4]],
+#
+# [['src/journal/test-journal-init.c'],
+# [libjournal_core,
+# libshared],
+# [threads,
+# libxz,
+# liblz4]],
+#
+# [['src/journal/test-journal-config.c'],
+# [libjournal_core,
+# libshared],
+# [libxz,
+# liblz4,
+# libselinux]],
+#
+# [['src/journal/test-journal-verify.c'],
+# [libjournal_core,
+# libshared],
+# [threads,
+# libxz,
+# liblz4]],
+#
+# [['src/journal/test-journal-interleaving.c'],
+# [libjournal_core,
+# libshared],
+# [threads,
+# libxz,
+# liblz4]],
+#
+# [['src/journal/test-mmap-cache.c'],
+# [libjournal_core,
+# libshared],
+# [threads,
+# libxz,
+# liblz4]],
+#
+# [['src/journal/test-catalog.c'],
+# [libjournal_core,
+# libshared],
+# [threads,
+# libxz,
+# liblz4],
+# '', '', '-DCATALOG_DIR="@0@"'.format(build_catalog_dir)],
+#
+# [['src/journal/test-compress.c'],
+# [libjournal_core,
+# libshared],
+# [liblz4,
+# libxz]],
+#
+# [['src/journal/test-compress-benchmark.c'],
+# [libjournal_core,
+# libshared],
+# [liblz4,
+# libxz],
+# '', 'timeout=90'],
+#
+# [['src/journal/test-audit-type.c'],
+# [libjournal_core,
+# libshared],
+# [liblz4,
+# libxz]],
+# ]
+#endif // 0
+
+############################################################
+
+tests += [
+#if 0 /// UNNEEDED in elogind
+# [['src/libelogind/sd-bus/test-bus-marshal.c'],
+# [],
+# [threads,
+# libglib,
+# libgobject,
+# libgio,
+# libdbus]],
+#endif // 0
+
+ [['src/libelogind/sd-bus/test-bus-signature.c'],
+ [],
+ [threads]],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/libsystemd/sd-bus/test-bus-watch-bind.c'],
+# [],
+# [threads], '', 'timeout=120'],
+#
+# [['src/libsystemd/sd-bus/test-bus-chat.c'],
+# [],
+# [threads]],
+#
+# [['src/libelogind/sd-bus/test-bus-cleanup.c'],
+# [],
+# [threads,
+# libseccomp]],
+#endif // 0
+
+ [['src/libelogind/sd-bus/test-bus-error.c'],
+ [libshared_static,
+ libelogind_static],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/libelogind/sd-bus/test-bus-track.c'],
+# [],
+# [libseccomp]],
+#endif // 0
+
+ [['src/libelogind/sd-bus/test-bus-server.c'],
+ [],
+ [threads]],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/libelogind/sd-bus/test-bus-objects.c'],
+# [],
+# [threads]],
+#endif // 0
+
+ [['src/libelogind/sd-bus/test-bus-vtable.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/libelogind/sd-bus/test-bus-gvariant.c'],
+# [],
+# [libglib,
+# libgobject,
+# libgio]],
+#
+# [['src/libelogind/sd-bus/test-bus-creds.c'],
+# [],
+# []],
+#endif // 0
+
+ [['src/libelogind/sd-bus/test-bus-match.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/libelogind/sd-bus/test-bus-benchmark.c'],
+# [],
+# [threads],
+# '', 'manual'],
+#endif // 0
+
+ [['src/libelogind/sd-bus/test-bus-introspect.c'],
+ [],
+ []],
+
+ [['src/libelogind/sd-event/test-event.c'],
+ [],
+ []],
+
+#if 0 /// UNNEEDED in elogind
+# [['src/libelogind/sd-netlink/test-netlink.c'],
+# [],
+# []],
+#
+# [['src/libelogind/sd-netlink/test-local-addresses.c'],
+# [],
+# []],
+#
+# [['src/libelogind/sd-resolve/test-resolve.c'],
+# [],
+# [threads]],
+#endif // 0
+
+ [['src/libelogind/sd-login/test-login.c'],
+ [],
+ []],
+]
+
+#if 0 /// UNNEEDED in elogind
+# if cxx.found()
+# tests += [
+# [['src/libelogind/sd-bus/test-bus-vtable-cc.cc'],
+# [],
+# []]
+# ]
+# endif
+#endif // 0
+
+############################################################
+
+#if 0 /// UNNEEDED in elogind
+# tests += [
+# [['src/libsystemd-network/test-dhcp-option.c',
+# 'src/libsystemd-network/dhcp-protocol.h',
+# 'src/libsystemd-network/dhcp-internal.h'],
+# [libshared,
+# libsystemd_network],
+# []],
+#
+# [['src/libsystemd-network/test-sd-dhcp-lease.c',
+# 'src/libsystemd-network/dhcp-lease-internal.h'],
+# [libshared,
+# libelogind_network],
+# []],
+#
+# [['src/libsystemd-network/test-dhcp-client.c',
+# 'src/libsystemd-network/dhcp-protocol.h',
+# 'src/libsystemd-network/dhcp-internal.h',
+# 'src/systemd/sd-dhcp-client.h'],
+# [libshared,
+# libsystemd_network],
+# []],
+#
+# [['src/libelogind-network/test-dhcp-server.c'],
+# [libshared,
+# libsystemd_network],
+# []],
+#
+# [['src/libsystemd-network/test-ipv4ll.c',
+# 'src/libsystemd-network/arp-util.h',
+# 'src/systemd/sd-ipv4ll.h'],
+# [libshared,
+# libsystemd_network],
+# []],
+#
+# [['src/libelogind-network/test-ipv4ll-manual.c',
+# 'src/systemd/sd-ipv4ll.h'],
+# [libshared,
+# libsystemd_network],
+# [],
+# '', 'manual'],
+#
+# [['src/libelogind-network/test-acd.c',
+# 'src/systemd/sd-ipv4acd.h'],
+# [libshared,
+# libelogind_network],
+# [],
+# '', 'manual'],
+#
+# [['src/libsystemd-network/test-ndisc-rs.c',
+# 'src/libsystemd-network/dhcp-identifier.h',
+# 'src/libsystemd-network/dhcp-identifier.c',
+# 'src/libsystemd-network/icmp6-util.h',
+# 'src/systemd/sd-dhcp6-client.h',
+# 'src/systemd/sd-ndisc.h'],
+# [libshared,
+# libsystemd_network],
+# []],
+#
+# [['src/libsystemd-network/test-ndisc-ra.c',
+# 'src/libsystemd-network/icmp6-util.h',
+# 'src/systemd/sd-ndisc.h'],
+# [libshared,
+# libelogind_network],
+# []],
+#
+# [['src/libsystemd-network/test-dhcp6-client.c',
+# 'src/libsystemd-network/dhcp-identifier.h',
+# 'src/libsystemd-network/dhcp-identifier.c',
+# 'src/libsystemd-network/dhcp6-internal.h',
+# 'src/systemd/sd-dhcp6-client.h'],
+# [libshared,
+# libsystemd_network],
+# []],
+#
+# [['src/libelogind-network/test-lldp.c'],
+# [libshared,
+# libelogind_network],
+# []],
+# ]
+#endif // 0
+
+############################################################
+
+tests += [
+ [['src/login/test-login-shared.c'],
+ [],
+ []],
+
+ [['src/login/test-inhibit.c'],
+ [],
+ [],
+ '', 'manual'],
+
+ [['src/login/test-login-tables.c'],
+ [liblogind_core,
+ libshared],
+#if 0 /// elogind does not include udev implicitly
+# [threads]],
+#else
+ [threads,libudev]],
+#endif // 0
+]
diff --git a/src/test/test-alloc-util.c b/src/test/test-alloc-util.c
index cc4821eaf..db8991bad 100644
--- a/src/test/test-alloc-util.c
+++ b/src/test/test-alloc-util.c
@@ -1,21 +1,6 @@
-/***
- This file is part of systemd.
+/* SPDX-License-Identifier: LGPL-2.1+ */
- 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 <stdint.h>
#include "alloc-util.h"
#include "macro.h"
@@ -34,22 +19,63 @@ static void test_alloca(void) {
assert_se(!memcmp(t, zero, 997));
}
-static void test_memdup_multiply(void) {
+static void test_memdup_multiply_and_greedy_realloc(void) {
int org[] = {1, 2, 3};
- int *dup;
-
- dup = (int*)memdup_multiply(org, sizeof(int), 3);
+ _cleanup_free_ int *dup;
+ int *p;
+ size_t i, allocated = 3;
+ dup = (int*) memdup_suffix0_multiply(org, sizeof(int), 3);
assert_se(dup);
assert_se(dup[0] == 1);
assert_se(dup[1] == 2);
assert_se(dup[2] == 3);
+ assert_se(*(uint8_t*) (dup + 3) == (uint8_t) 0);
free(dup);
+
+ dup = (int*) memdup_multiply(org, sizeof(int), 3);
+ assert_se(dup);
+ assert_se(dup[0] == 1);
+ assert_se(dup[1] == 2);
+ assert_se(dup[2] == 3);
+
+ p = dup;
+ assert_se(greedy_realloc0((void**) &dup, &allocated, 2, sizeof(int)) == p);
+
+ p = (int *) greedy_realloc0((void**) &dup, &allocated, 10, sizeof(int));
+ assert_se(p == dup);
+ assert_se(allocated >= 10);
+ assert_se(p[0] == 1);
+ assert_se(p[1] == 2);
+ assert_se(p[2] == 3);
+ for (i = 3; i < allocated; i++)
+ assert_se(p[i] == 0);
+}
+
+static void test_bool_assign(void) {
+ bool b, c, *cp = &c, d, e, f, g, h;
+
+ b = 123;
+ *cp = -11;
+ d = 0xF & 0xFF;
+ e = b & d;
+ f = 0x0;
+ g = cp; /* cast from pointer */
+ h = NULL; /* cast from pointer */
+
+ assert(b);
+ assert(c);
+ assert(d);
+ assert(e);
+ assert(!f);
+ assert(g);
+ assert(!h);
}
int main(int argc, char *argv[]) {
test_alloca();
- test_memdup_multiply();
+ test_memdup_multiply_and_greedy_realloc();
+ test_bool_assign();
return 0;
}
diff --git a/src/test/test-bus-util.c b/src/test/test-bus-util.c
new file mode 100644
index 000000000..23cd60226
--- /dev/null
+++ b/src/test/test-bus-util.c
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bus-util.h"
+#include "log.h"
+
+static void test_name_async(unsigned n_messages) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ int r;
+ unsigned i;
+
+ log_info("/* %s (%u) */", __func__, n_messages);
+
+ r = bus_open_system_watch_bind_with_description(&bus, "test-bus");
+ if (r < 0) {
+ log_error_errno(r, "Failed to connect to bus: %m");
+ return;
+ }
+
+ r = bus_request_name_async_may_reload_dbus(bus, NULL, "org.freedesktop.elogind.test-bus-util", 0, NULL);
+ if (r < 0) {
+ log_error_errno(r, "Failed to request name: %m");
+ return;
+ }
+
+ for (i = 0; i < n_messages; i++) {
+ r = sd_bus_process(bus, NULL);
+ log_debug("stage %u: sd_bus_process returned %d", i, r);
+ if (r < 0) {
+ log_notice_errno(r, "Processing failed: %m");
+ return;
+ }
+
+ if (r > 0 && i + 1 < n_messages)
+ (void) sd_bus_wait(bus, USEC_PER_SEC / 3);
+ }
+}
+
+static int callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
+ return 1;
+}
+
+static void destroy_callback(void *userdata) {
+ int *n_called = userdata;
+
+ (*n_called) ++;
+}
+
+static void test_destroy_callback(void) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ sd_bus_slot *slot = NULL;
+ sd_bus_destroy_t t;
+
+ int r, n_called = 0;
+
+ log_info("/* %s */", __func__);
+
+ r = bus_open_system_watch_bind_with_description(&bus, "test-bus");
+ if (r < 0) {
+ log_error_errno(r, "Failed to connect to bus: %m");
+ return;
+ }
+
+ r = sd_bus_request_name_async(bus, &slot, "org.freedesktop.elogind.test-bus-util", 0, callback, &n_called);
+ assert(r == 1);
+
+ assert_se(sd_bus_slot_get_destroy_callback(slot, NULL) == 0);
+ assert_se(sd_bus_slot_get_destroy_callback(slot, &t) == 0);
+
+ assert_se(sd_bus_slot_set_destroy_callback(slot, destroy_callback) == 0);
+ assert_se(sd_bus_slot_get_destroy_callback(slot, NULL) == 1);
+ assert_se(sd_bus_slot_get_destroy_callback(slot, &t) == 1);
+ assert_se(t == destroy_callback);
+
+ /* Force cleanup so we can look at n_called */
+ assert(n_called == 0);
+ sd_bus_slot_unref(slot);
+ assert(n_called == 1);
+}
+
+int main(int argc, char **argv) {
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+ log_open();
+
+ test_name_async(0);
+ test_name_async(20);
+ test_destroy_callback();
+
+ return 0;
+}
diff --git a/src/test/test-cgroup.c b/src/test/test-cgroup.c
index 5336c1965..d5bb62b4a 100644
--- a/src/test/test-cgroup.c
+++ b/src/test/test-cgroup.c
@@ -1,29 +1,15 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <string.h>
#include <unistd.h>
#include "cgroup-util.h"
#include "path-util.h"
+//#include "process-util.h"
#include "string-util.h"
#include "util.h"
+/// Additional includes needed by elogind
+#include "process-util.h"
int main(int argc, char*argv[]) {
char *path;
@@ -35,24 +21,28 @@ int main(int argc, char*argv[]) {
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_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, getpid(), &path) == 0);
+ assert_se(cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, getpid_cached(), &path) == 0);
assert_se(streq(path, "/test-b"));
free(path);
assert_se(cg_attach(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0) == 0);
- assert_se(cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, getpid(), &path) == 0);
+ assert_se(cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, getpid_cached(), &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_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, getpid(), &path) == 0);
+ assert_se(cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, getpid_cached(), &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);
+#if 0 /// elogind uses its own name
assert_se(path_equal(path, "/sys/fs/cgroup/systemd/test-b/test-d"));
+#else
+ assert_se(path_equal(path, "/sys/fs/cgroup/elogind/test-b/test-d"));
+#endif // 0
free(path);
assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, "/test-a") > 0);
diff --git a/src/test/test-conf-files.c b/src/test/test-conf-files.c
index 22b7c6120..2ec2dfc26 100644
--- a/src/test/test-conf-files.c
+++ b/src/test/test-conf-files.c
@@ -1,20 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2014 Michael Marineau
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2014 Michael Marineau
***/
#include <stdarg.h>
@@ -22,8 +8,10 @@
#include "alloc-util.h"
#include "conf-files.h"
+#include "fileio.h"
#include "fs-util.h"
#include "macro.h"
+#include "mkdir.h"
#include "parse-util.h"
#include "rm-rf.h"
#include "string-util.h"
@@ -34,12 +22,16 @@
static void setup_test_dir(char *tmp_dir, const char *files, ...) {
va_list ap;
- assert_se(mkdtemp(tmp_dir) != NULL);
+ assert_se(mkdtemp(tmp_dir));
va_start(ap, files);
- while (files != NULL) {
- _cleanup_free_ char *path = strappend(tmp_dir, files);
- assert_se(touch_file(path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID) == 0);
+ while (files) {
+ _cleanup_free_ char *path;
+
+ assert_se(path = strappend(tmp_dir, files));
+ (void) mkdir_parents(path, 0755);
+ assert_se(write_string_file(path, "foobar", WRITE_STRING_FILE_CREATE) >= 0);
+
files = va_arg(ap, const char *);
}
va_end(ap);
@@ -48,7 +40,7 @@ static void setup_test_dir(char *tmp_dir, const char *files, ...) {
static void test_conf_files_list(bool use_root) {
char tmp_dir[] = "/tmp/test-conf-files-XXXXXX";
_cleanup_strv_free_ char **found_files = NULL, **found_files2 = NULL;
- const char *root_dir, *search_1, *search_2, *expect_a, *expect_b, *expect_c;
+ const char *root_dir, *search_1, *search_2, *expect_a, *expect_b, *expect_c, *mask;
log_debug("/* %s */", __func__);
@@ -57,8 +49,12 @@ static void test_conf_files_list(bool use_root) {
"/dir2/a.conf",
"/dir2/b.conf",
"/dir2/c.foo",
+ "/dir2/d.conf",
NULL);
+ mask = strjoina(tmp_dir, "/dir1/d.conf");
+ assert_se(symlink("/dev/null", mask) >= 0);
+
if (use_root) {
root_dir = tmp_dir;
search_1 = "/dir1";
@@ -75,23 +71,23 @@ static void test_conf_files_list(bool use_root) {
log_debug("/* Check when filtered by suffix */");
- assert_se(conf_files_list(&found_files, ".conf", root_dir, search_1, search_2, NULL) == 0);
+ assert_se(conf_files_list(&found_files, ".conf", root_dir, CONF_FILES_FILTER_MASKED, search_1, search_2, NULL) == 0);
strv_print(found_files);
assert_se(found_files);
assert_se(streq_ptr(found_files[0], expect_a));
assert_se(streq_ptr(found_files[1], expect_b));
- assert_se(found_files[2] == NULL);
+ assert_se(!found_files[2]);
log_debug("/* Check when unfiltered */");
- assert_se(conf_files_list(&found_files2, NULL, root_dir, search_1, search_2, NULL) == 0);
+ assert_se(conf_files_list(&found_files2, NULL, root_dir, CONF_FILES_FILTER_MASKED, search_1, search_2, NULL) == 0);
strv_print(found_files2);
assert_se(found_files2);
assert_se(streq_ptr(found_files2[0], expect_a));
assert_se(streq_ptr(found_files2[1], expect_b));
assert_se(streq_ptr(found_files2[2], expect_c));
- assert_se(found_files2[3] == NULL);
+ assert_se(!found_files2[3]);
assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
}
diff --git a/src/test/test-conf-parser.c b/src/test/test-conf-parser.c
index a66ed1bd3..1593d3adf 100644
--- a/src/test/test-conf-parser.c
+++ b/src/test/test-conf-parser.c
@@ -1,36 +1,21 @@
-/***
- This file is part of systemd.
-
- Copyright 2015 Ronny Chevalier
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include "conf-parser.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
#include "log.h"
#include "macro.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
+#if 0 /// UNNEEDED by elogind
static void test_config_parse_path_one(const char *rvalue, const char *expected) {
- char *path = NULL;
+ _cleanup_free_ char *path = NULL;
assert_se(config_parse_path("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &path, NULL) >= 0);
assert_se(streq_ptr(expected, path));
-
- free(path);
}
static void test_config_parse_log_level_one(const char *rvalue, int expected) {
@@ -40,14 +25,12 @@ static void test_config_parse_log_level_one(const char *rvalue, int expected) {
assert_se(expected == log_level);
}
-#if 0 /// UNNEEDED by elogind
static void test_config_parse_log_facility_one(const char *rvalue, int expected) {
int log_facility = 0;
assert_se(config_parse_log_facility("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &log_facility, NULL) >= 0);
assert_se(expected == log_facility);
}
-#endif // 0
static void test_config_parse_iec_size_one(const char *rvalue, size_t expected) {
size_t iec_size = 0;
@@ -56,7 +39,6 @@ static void test_config_parse_iec_size_one(const char *rvalue, size_t expected)
assert_se(expected == iec_size);
}
-#if 0 /// UNNEEDED by elogind
static void test_config_parse_si_size_one(const char *rvalue, size_t expected) {
size_t si_size = 0;
@@ -80,20 +62,20 @@ static void test_config_parse_unsigned_one(const char *rvalue, unsigned expected
}
static void test_config_parse_strv_one(const char *rvalue, char **expected) {
- char **strv = 0;
+ _cleanup_strv_free_ char **strv = NULL;
assert_se(config_parse_strv("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &strv, NULL) >= 0);
assert_se(strv_equal(expected, strv));
-
- strv_free(strv);
}
+#if 0 /// UNNEEDED by elogind
static void test_config_parse_mode_one(const char *rvalue, mode_t expected) {
mode_t v = 0;
assert_se(config_parse_mode("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &v, NULL) >= 0);
assert_se(expected == v);
}
+#endif // 0
static void test_config_parse_sec_one(const char *rvalue, usec_t expected) {
usec_t v = 0;
@@ -109,12 +91,12 @@ static void test_config_parse_nsec_one(const char *rvalue, nsec_t expected) {
assert_se(config_parse_nsec("unit", "filename", 1, "nsection", 1, "lvalue", 0, rvalue, &v, NULL) >= 0);
assert_se(expected == v);
}
-#endif // 0
static void test_config_parse_path(void) {
test_config_parse_path_one("/path", "/path");
test_config_parse_path_one("/path//////////", "/path");
test_config_parse_path_one("///path/foo///bar////bar//", "/path/foo/bar/bar");
+ test_config_parse_path_one("/path//./////hogehoge///.", "/path/hogehoge");
test_config_parse_path_one("/path/\xc3\x80", "/path/\xc3\x80");
test_config_parse_path_one("not_absolute/path", NULL);
@@ -128,14 +110,12 @@ static void test_config_parse_log_level(void) {
test_config_parse_log_level_one("garbage", 0);
}
-#if 0 /// UNNEEDED by elogind
static void test_config_parse_log_facility(void) {
test_config_parse_log_facility_one("mail", LOG_MAIL);
test_config_parse_log_facility_one("user", LOG_USER);
test_config_parse_log_facility_one("garbage", 0);
}
-#endif // 0
static void test_config_parse_iec_size(void) {
test_config_parse_iec_size_one("1024", 1024);
@@ -150,7 +130,6 @@ static void test_config_parse_iec_size(void) {
test_config_parse_iec_size_one("garbage", 0);
}
-#if 0 /// UNNEEDED by elogind
static void test_config_parse_si_size(void) {
test_config_parse_si_size_one("1024", 1024);
test_config_parse_si_size_one("2K", 2000);
@@ -193,9 +172,10 @@ static void test_config_parse_strv(void) {
test_config_parse_strv_one("foo bar foo", STRV_MAKE("foo", "bar", "foo"));
test_config_parse_strv_one("\"foo bar\" foo", STRV_MAKE("foo bar", "foo"));
test_config_parse_strv_one("\xc3\x80", STRV_MAKE("\xc3\x80"));
- test_config_parse_strv_one("\xc3\x7f", STRV_MAKE_EMPTY);
+ test_config_parse_strv_one("\xc3\x7f", STRV_MAKE("\xc3\x7f"));
}
+#if 0 /// UNNEEDED by elogind
static void test_config_parse_mode(void) {
test_config_parse_mode_one("777", 0777);
test_config_parse_mode_one("644", 0644);
@@ -206,6 +186,7 @@ static void test_config_parse_mode(void) {
test_config_parse_mode_one("777garbage", 0);
test_config_parse_mode_one("777 garbage", 0);
}
+#endif // 0
static void test_config_parse_sec(void) {
test_config_parse_sec_one("1", 1 * USEC_PER_SEC);
@@ -237,30 +218,206 @@ static void test_config_parse_iec_uint64(void) {
assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4.5M", &offset, NULL) == 0);
}
+
+static void test_config_parse_join_controllers(void) {
+ int r;
+ _cleanup_(strv_free_freep) char ***c = NULL;
+ char ***c2;
+
+ /* Test normal operation */
+ r = config_parse_join_controllers(NULL, "example.conf", 11, "Section", 10, "JoinControllers", 0, "cpu,cpuacct net_cls,netprio", &c, NULL);
+ assert_se(r == 0);
+ assert_se(c);
+ assert_se(strv_length(c[0]) == 2);
+ assert_se(strv_equal(c[0], STRV_MAKE("cpu", "cpuacct")));
+ assert_se(strv_length(c[1]) == 2);
+ assert_se(strv_equal(c[1], STRV_MAKE("net_cls", "netprio")));
+ assert_se(c[2] == NULL);
+
+ /* Test special case of no mounted controllers */
+ r = config_parse_join_controllers(NULL, "example.conf", 12, "Section", 10, "JoinControllers", 0, "", &c, NULL);
+ assert_se(r == 0);
+ assert_se(c);
+ assert_se(strv_equal(c[0], STRV_MAKE_EMPTY));
+ assert_se(c[1] == NULL);
+
+ /* Test merging of overlapping lists */
+ r = config_parse_join_controllers(NULL, "example.conf", 13, "Section", 10, "JoinControllers", 0, "a,b b,c", &c, NULL);
+ assert_se(r == 0);
+ assert_se(c);
+ assert_se(strv_length(c[0]) == 3);
+ assert_se(strv_contains(c[0], "a"));
+ assert_se(strv_contains(c[0], "b"));
+ assert_se(strv_contains(c[0], "c"));
+ assert_se(c[1] == NULL);
+
+ /* Test ignoring of bad lines */
+ c2 = c;
+ r = config_parse_join_controllers(NULL, "example.conf", 14, "Section", 10, "JoinControllers", 0, "a,\"b ", &c, NULL);
+ assert_se(r < 0);
+ assert_se(c == c2);
+}
#endif // 0
+#define x10(x) x x x x x x x x x x
+#define x100(x) x10(x10(x))
+#define x1000(x) x10(x100(x))
+
+static const char* const config_file[] = {
+ "[Section]\n"
+ "setting1=1\n",
+
+ "[Section]\n"
+ "setting1=1", /* no terminating newline */
+
+ "\n\n\n\n[Section]\n\n\n"
+ "setting1=1", /* some whitespace, no terminating newline */
+
+ "[Section]\n"
+ "[Section]\n"
+ "setting1=1\n"
+ "setting1=2\n"
+ "setting1=1\n", /* repeated settings */
+
+ "[Section]\n"
+ "setting1=1\\\n" /* normal continuation */
+ "2\\\n"
+ "3\n",
+
+ "[Section]\n"
+ "setting1=1\\\n" /* continuation with extra trailing backslash at the end */
+ "2\\\n"
+ "3\\\n",
+
+ "[Section]\n"
+ "setting1=1\\\\\\\n" /* continuation with trailing escape symbols */
+ "\\\\2\n", /* note that C requires one level of escaping, so the
+ * parser gets "…1 BS BS BS NL BS BS 2 NL", which
+ * it translates into "…1 BS BS SP BS BS 2" */
+
+ "\n[Section]\n\n"
+ "setting1=" /* a line above LINE_MAX length */
+ x1000("ABCD")
+ "\n",
+
+ "[Section]\n"
+ "setting1=" /* a line above LINE_MAX length, with continuation */
+ x1000("ABCD") "\\\n"
+ "foobar",
+
+ "[Section]\n"
+ "setting1=" /* a line above LINE_MAX length, with continuation */
+ x1000("ABCD") "\\\n" /* and an extra trailing backslash */
+ "foobar\\\n",
+
+ "[Section]\n"
+ "setting1=" /* a line above the allowed limit: 9 + 1050000 + 1 */
+ x1000(x1000("x") x10("abcde")) "\n",
+
+ "[Section]\n"
+ "setting1=" /* many continuation lines, together above the limit */
+ x1000(x1000("x") x10("abcde") "\\\n") "xxx",
+};
+
+static void test_config_parse(unsigned i, const char *s) {
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-conf-parser.XXXXXX";
+ int fd, r;
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *setting1 = NULL;
+
+ const ConfigTableItem items[] = {
+ { "Section", "setting1", config_parse_string, 0, &setting1},
+ {}
+ };
+
+ log_info("== %s[%i] ==", __func__, i);
+
+ fd = mkostemp_safe(name);
+ assert_se(fd >= 0);
+ assert_se((size_t) write(fd, s, strlen(s)) == strlen(s));
+
+ assert_se(lseek(fd, 0, SEEK_SET) == 0);
+ assert_se(f = fdopen(fd, "r"));
+
+ /*
+ int config_parse(const char *unit,
+ const char *filename,
+ FILE *f,
+ const char *sections,
+ ConfigItemLookup lookup,
+ const void *table,
+ bool relaxed,
+ bool allow_include,
+ bool warn,
+ void *userdata)
+ */
+
+ r = config_parse(NULL, name, f,
+ "Section\0",
+ config_item_table_lookup, items,
+ CONFIG_PARSE_WARN, NULL);
+
+ switch (i) {
+ case 0 ... 3:
+ assert_se(r == 0);
+ assert_se(streq(setting1, "1"));
+ break;
+
+ case 4 ... 5:
+ assert_se(r == 0);
+ assert_se(streq(setting1, "1 2 3"));
+ break;
+
+ case 6:
+ assert_se(r == 0);
+ assert_se(streq(setting1, "1\\\\ \\\\2"));
+ break;
+
+ case 7:
+ assert_se(r == 0);
+ assert_se(streq(setting1, x1000("ABCD")));
+ break;
+
+ case 8 ... 9:
+ assert_se(r == 0);
+ assert_se(streq(setting1, x1000("ABCD") " foobar"));
+ break;
+
+ case 10 ... 11:
+ assert_se(r == -ENOBUFS);
+ assert_se(setting1 == NULL);
+ break;
+ }
+}
+
int main(int argc, char **argv) {
+ unsigned i;
+
log_parse_environment();
log_open();
+#if 0 /// UNNEEDED by elogind
test_config_parse_path();
test_config_parse_log_level();
-#if 0 /// UNNEEDED by elogind
test_config_parse_log_facility();
-#endif // 0
test_config_parse_iec_size();
-#if 0 /// UNNEEDED by elogind
test_config_parse_si_size();
#endif // 0
test_config_parse_int();
test_config_parse_unsigned();
test_config_parse_strv();
+#if 0 /// UNNEEDED by elogind
test_config_parse_mode();
+#endif // 0
test_config_parse_sec();
#if 0 /// UNNEEDED by elogind
test_config_parse_nsec();
test_config_parse_iec_uint64();
+ test_config_parse_join_controllers();
#endif // 0
+ for (i = 0; i < ELEMENTSOF(config_file); i++)
+ test_config_parse(i, config_file[i]);
+
return 0;
}
diff --git a/src/test/test-copy.c b/src/test/test-copy.c
index 0b9195113..1127ace44 100644
--- a/src/test/test-copy.c
+++ b/src/test/test-copy.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd
-
- Copyright 2014 Ronny Chevalier
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <unistd.h>
@@ -108,7 +91,7 @@ static void test_copy_tree(void) {
STRV_FOREACH(p, files) {
_cleanup_free_ char *f;
- assert_se((f = strappend(original_dir, *p)));
+ assert_se(f = strappend(original_dir, *p));
assert_se(mkdir_parents(f, 0755) >= 0);
assert_se(write_string_file(f, "file", WRITE_STRING_FILE_CREATE) == 0);
@@ -117,8 +100,8 @@ static void test_copy_tree(void) {
STRV_FOREACH_PAIR(link, p, links) {
_cleanup_free_ char *f, *l;
- assert_se((f = strappend(original_dir, *p)));
- assert_se((l = strappend(original_dir, *link)));
+ assert_se(f = strappend(original_dir, *p));
+ assert_se(l = strappend(original_dir, *link));
assert_se(mkdir_parents(l, 0755) >= 0);
assert_se(symlink(f, l) == 0);
@@ -130,10 +113,10 @@ static void test_copy_tree(void) {
assert_se(copy_tree(original_dir, copy_dir, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_MERGE) == 0);
STRV_FOREACH(p, files) {
- _cleanup_free_ char *buf = NULL, *f;
- size_t sz = 0;
+ _cleanup_free_ char *buf, *f;
+ size_t sz;
- assert_se((f = strappend(copy_dir, *p)));
+ assert_se(f = strappend(copy_dir, *p));
assert_se(access(f, F_OK) == 0);
assert_se(read_full_file(f, &buf, &sz) == 0);
@@ -141,12 +124,12 @@ static void test_copy_tree(void) {
}
STRV_FOREACH_PAIR(link, p, links) {
- _cleanup_free_ char *target = NULL, *f, *l;
+ _cleanup_free_ char *target, *f, *l;
- assert_se((f = strjoin(original_dir, *p)));
- assert_se((l = strjoin(copy_dir, *link)));
+ assert_se(f = strjoin(original_dir, *p));
+ assert_se(l = strjoin(copy_dir, *link));
- assert_se(readlink_and_canonicalize(l, NULL, &target) == 0);
+ assert_se(chase_symlinks(l, NULL, 0, &target) == 1);
assert_se(path_equal(f, target));
}
@@ -222,6 +205,14 @@ static void test_copy_bytes_regular_file(const char *src, bool try_reflink, uint
else
assert_se(IN_SET(r, 0, 1));
+ assert_se(fstat(fd, &buf) == 0);
+ assert_se(fstat(fd2, &buf2) == 0);
+ assert_se((uint64_t) buf2.st_size == MIN((uint64_t) buf.st_size, max_bytes));
+
+ if (max_bytes < (uint64_t) -1)
+ /* Make sure the file is now higher than max_bytes */
+ assert_se(ftruncate(fd2, max_bytes + 1) == 0);
+
assert_se(lseek(fd2, 0, SEEK_SET) == 0);
r = copy_bytes(fd2, fd3, max_bytes, try_reflink ? COPY_REFLINK : 0);
@@ -235,18 +226,40 @@ static void test_copy_bytes_regular_file(const char *src, bool try_reflink, uint
* are copying is exactly max_bytes bytes. */
assert_se(r == 1);
- assert_se(fstat(fd, &buf) == 0);
- assert_se(fstat(fd2, &buf2) == 0);
assert_se(fstat(fd3, &buf3) == 0);
- assert_se((uint64_t) buf2.st_size == MIN((uint64_t) buf.st_size, max_bytes));
- assert_se(buf3.st_size == buf2.st_size);
+ if (max_bytes == (uint64_t) -1)
+ assert_se(buf3.st_size == buf2.st_size);
+ else
+ assert_se((uint64_t) buf3.st_size == max_bytes);
unlink(fn2);
unlink(fn3);
}
+#if 0 /// UNNEEDED by elogind
+static void test_copy_atomic(void) {
+ _cleanup_(rm_rf_physical_and_freep) char *p = NULL;
+ const char *q;
+ int r;
+
+ assert_se(mkdtemp_malloc(NULL, &p) >= 0);
+
+ q = strjoina(p, "/fstab");
+
+ r = copy_file_atomic("/etc/fstab", q, 0644, 0, COPY_REFLINK);
+ if (r == -ENOENT)
+ return;
+
+ assert_se(copy_file_atomic("/etc/fstab", q, 0644, 0, COPY_REFLINK) == -EEXIST);
+
+ assert_se(copy_file_atomic("/etc/fstab", q, 0644, 0, COPY_REPLACE) >= 0);
+}
+#endif // 0
+
int main(int argc, char *argv[]) {
+ log_set_max_level(LOG_DEBUG);
+
#if 0 /// UNNEEDED by elogind
test_copy_file();
test_copy_file_fd();
@@ -259,6 +272,9 @@ int main(int argc, char *argv[]) {
test_copy_bytes_regular_file(argv[0], true, 1000);
test_copy_bytes_regular_file(argv[0], false, 32000); /* larger than copy buffer size */
test_copy_bytes_regular_file(argv[0], true, 32000);
+#if 0 /// UNNEEDED by elogind
+ test_copy_atomic();
+#endif // 0
return 0;
}
diff --git a/src/test/test-dlopen.c b/src/test/test-dlopen.c
new file mode 100644
index 000000000..148ebaa4d
--- /dev/null
+++ b/src/test/test-dlopen.c
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#include "macro.h"
+
+int main(int argc, char **argv) {
+ void *handle;
+
+ assert_se(handle = dlopen(argv[1], RTLD_NOW));
+ assert_se(dlclose(handle) == 0);
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/test/test-ellipsize.c b/src/test/test-ellipsize.c
index d4f09b08a..92692bd48 100644
--- a/src/test/test-ellipsize.c
+++ b/src/test/test-ellipsize.c
@@ -1,45 +1,127 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Shawn Landden
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <stdio.h>
#include "alloc-util.h"
#include "def.h"
#include "string-util.h"
+#include "strv.h"
#include "terminal-util.h"
#include "util.h"
+#include "utf8.h"
+
+static void test_ellipsize_mem_one(const char *s, size_t old_length, size_t new_length) {
+ _cleanup_free_ char *n = NULL;
+ _cleanup_free_ char *t1 = NULL, *t2 = NULL, *t3 = NULL;
+ char buf[LINE_MAX];
+ bool has_wide_chars;
+ size_t max_width;
+
+ n = memdup_suffix0(s, old_length);
+
+ if (!utf8_is_valid(n))
+ /* We don't support invalid sequences… */
+ return;
+
+ /* Report out inputs. We duplicate the data so that cellescape
+ * can properly report truncated multibyte sequences. */
+ log_info("%s \"%s\" old_length=%zu/%zu new_length=%zu", __func__,
+ cellescape(buf, sizeof buf, n),
+ old_length, utf8_console_width(n),
+ new_length);
+
+ /* To keep this test simple, any case with wide chars starts with this glyph */
+ has_wide_chars = startswith(s, "你");
+ max_width = MIN(utf8_console_width(n), new_length);
+
+ t1 = ellipsize_mem(n, old_length, new_length, 30);
+ log_info("30%% → %s utf8_console_width=%zu", t1, utf8_console_width(t1));
+ if (!has_wide_chars)
+ assert_se(utf8_console_width(t1) == max_width);
+ else
+ assert_se(utf8_console_width(t1) <= max_width);
+
+ t2 = ellipsize_mem(n, old_length, new_length, 90);
+ log_info("90%% → %s utf8_console_width=%zu", t2, utf8_console_width(t2));
+ if (!has_wide_chars)
+ assert_se(utf8_console_width(t2) == max_width);
+ else
+ assert_se(utf8_console_width(t2) <= max_width);
+
+ t3 = ellipsize_mem(n, old_length, new_length, 100);
+ log_info("100%% → %s utf8_console_width=%zu", t3, utf8_console_width(t3));
+ if (!has_wide_chars)
+ assert_se(utf8_console_width(t3) == max_width);
+ else
+ assert_se(utf8_console_width(t3) <= max_width);
+
+ if (new_length >= old_length) {
+ assert_se(streq(t1, n));
+ assert_se(streq(t2, n));
+ assert_se(streq(t3, n));
+ }
+}
-static void test_one(const char *p) {
+static void test_ellipsize_mem(void) {
+ const char *s;
+ ssize_t l, k;
+
+ FOREACH_STRING(s,
+ "_XXXXXXXXXXX_", /* ASCII */
+ "_aąęółśćńżźć_", /* two-byte utf-8 */
+ "გამარჯობა", /* multi-byte utf-8 */
+ "你好世界", /* wide characters */
+ "你გą世óoó界") /* a mix */
+
+ for (l = strlen(s); l >= 0; l--)
+ for (k = strlen(s) + 1; k >= 0; k--)
+ test_ellipsize_mem_one(s, l, k);
+}
+
+static void test_ellipsize_one(const char *p) {
_cleanup_free_ char *t;
t = ellipsize(p, columns(), 70);
puts(t);
+ free(t);
+ t = ellipsize(p, columns(), 0);
+ puts(t);
+ free(t);
+ t = ellipsize(p, columns(), 100);
+ puts(t);
+ free(t);
+ t = ellipsize(p, 0, 50);
+ puts(t);
+ free(t);
+ t = ellipsize(p, 1, 50);
+ puts(t);
+ free(t);
+ t = ellipsize(p, 2, 50);
+ puts(t);
+ free(t);
+ t = ellipsize(p, 3, 50);
+ puts(t);
+ free(t);
+ t = ellipsize(p, 4, 50);
+ puts(t);
+ free(t);
+ t = ellipsize(p, 5, 50);
+ puts(t);
+}
+
+static void test_ellipsize(void) {
+ test_ellipsize_one(DIGITS LETTERS DIGITS LETTERS);
+ test_ellipsize_one("한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어");
+ test_ellipsize_one("-日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国");
+ test_ellipsize_one("中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国-中国中国中国中国中国中国中国中国中国中国中国中国中国");
+ test_ellipsize_one("sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd");
+ test_ellipsize_one("🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮");
+ test_ellipsize_one("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.");
+ test_ellipsize_one("shórt");
}
int main(int argc, char *argv[]) {
- test_one(DIGITS LETTERS DIGITS LETTERS);
- test_one("한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어");
- test_one("-日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国");
- test_one("中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国-中国中国中国中国中国中国中国中国中国中国中国中国中国");
- test_one("sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd");
- test_one("🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮");
- test_one("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.");
- test_one("shórt");
+ test_ellipsize_mem();
+ test_ellipsize();
return 0;
}
diff --git a/src/test/test-escape.c b/src/test/test-escape.c
index e7bc49dd9..2a52d09cc 100644
--- a/src/test/test-escape.c
+++ b/src/test/test-escape.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include "alloc-util.h"
#include "escape.h"
diff --git a/src/test/test-exec-util.c b/src/test/test-exec-util.c
index 241e5237c..030328391 100644
--- a/src/test/test-exec-util.c
+++ b/src/test/test-exec-util.c
@@ -1,22 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 Thomas H.P. Andersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <string.h>
@@ -71,10 +53,14 @@ static const gather_stdout_callback_t ignore_stdout[] = {
};
static void test_execute_directory(bool gather_stdout) {
- char template_lo[] = "/tmp/test-exec-util.XXXXXXX";
- char template_hi[] = "/tmp/test-exec-util.XXXXXXX";
+ char template_lo[] = "/tmp/test-exec-util.lo.XXXXXXX";
+ char template_hi[] = "/tmp/test-exec-util.hi.XXXXXXX";
const char * dirs[] = {template_hi, template_lo, NULL};
- const char *name, *name2, *name3, *overridden, *override, *masked, *mask;
+ const char *name, *name2, *name3,
+ *overridden, *override,
+ *masked, *mask,
+ *masked2, *mask2, /* the mask is non-executable */
+ *masked2e, *mask2e; /* the mask is executable */
log_info("/* %s (%s) */", __func__, gather_stdout ? "gathering stdout" : "asynchronous");
@@ -88,6 +74,10 @@ static void test_execute_directory(bool gather_stdout) {
override = strjoina(template_hi, "/overridden");
masked = strjoina(template_lo, "/masked");
mask = strjoina(template_hi, "/masked");
+ masked2 = strjoina(template_lo, "/masked2");
+ mask2 = strjoina(template_hi, "/masked2");
+ masked2e = strjoina(template_lo, "/masked2e");
+ mask2e = strjoina(template_hi, "/masked2e");
assert_se(write_string_file(name,
"#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works",
@@ -104,7 +94,15 @@ static void test_execute_directory(bool gather_stdout) {
assert_se(write_string_file(masked,
"#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed",
WRITE_STRING_FILE_CREATE) == 0);
+ assert_se(write_string_file(masked2,
+ "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed",
+ WRITE_STRING_FILE_CREATE) == 0);
+ assert_se(write_string_file(masked2e,
+ "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed",
+ WRITE_STRING_FILE_CREATE) == 0);
assert_se(symlink("/dev/null", mask) == 0);
+ assert_se(touch(mask2) == 0);
+ assert_se(touch(mask2e) == 0);
assert_se(touch(name3) >= 0);
assert_se(chmod(name, 0755) == 0);
@@ -112,6 +110,9 @@ static void test_execute_directory(bool gather_stdout) {
assert_se(chmod(overridden, 0755) == 0);
assert_se(chmod(override, 0755) == 0);
assert_se(chmod(masked, 0755) == 0);
+ assert_se(chmod(masked2, 0755) == 0);
+ assert_se(chmod(masked2e, 0755) == 0);
+ assert_se(chmod(mask2e, 0755) == 0);
if (gather_stdout)
execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL);
@@ -229,7 +230,6 @@ const gather_stdout_callback_t gather_stdout[] = {
gather_stdout_three,
};
-
static void test_stdout_gathering(void) {
char template[] = "/tmp/test-exec-util.XXXXXXX";
const char *dirs[] = {template, NULL};
diff --git a/src/test/test-extract-word.c b/src/test/test-extract-word.c
index 8b75ebdf5..c347605a9 100644
--- a/src/test/test-extract-word.c
+++ b/src/test/test-extract-word.c
@@ -1,23 +1,6 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 Thomas H.P. Andersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#include <errno.h>
#include <stdlib.h>
#include <string.h>
diff --git a/src/test/test-fd-util.c b/src/test/test-fd-util.c
index d1d9e1d2f..638fe3db4 100644
--- a/src/test/test-fd-util.c
+++ b/src/test/test-fd-util.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <fcntl.h>
#include <unistd.h>
@@ -24,6 +7,11 @@
#include "fd-util.h"
#include "fileio.h"
#include "macro.h"
+#include "path-util.h"
+#include "process-util.h"
+#include "random-util.h"
+#include "string-util.h"
+#include "util.h"
static void test_close_many(void) {
int fds[3];
@@ -66,9 +54,9 @@ static void test_same_fd(void) {
_cleanup_close_ int a = -1, b = -1, c = -1;
assert_se(pipe2(p, O_CLOEXEC) >= 0);
- assert_se((a = dup(p[0])) >= 0);
+ assert_se((a = fcntl(p[0], F_DUPFD, 3)) >= 0);
assert_se((b = open("/dev/null", O_RDONLY|O_CLOEXEC)) >= 0);
- assert_se((c = dup(a)) >= 0);
+ assert_se((c = fcntl(a, F_DUPFD, 3)) >= 0);
assert_se(same_fd(p[0], p[0]) > 0);
assert_se(same_fd(p[1], p[1]) > 0);
@@ -102,16 +90,251 @@ static void test_open_serialization_fd(void) {
fd = open_serialization_fd("test");
assert_se(fd >= 0);
- write(fd, "test\n", 5);
+ assert_se(write(fd, "test\n", 5) == 5);
+}
+
+static void test_acquire_data_fd_one(unsigned flags) {
+ char wbuffer[196*1024 - 7];
+ char rbuffer[sizeof(wbuffer)];
+ int fd;
+
+ fd = acquire_data_fd("foo", 3, flags);
+ assert_se(fd >= 0);
+
+ zero(rbuffer);
+ assert_se(read(fd, rbuffer, sizeof(rbuffer)) == 3);
+ assert_se(streq(rbuffer, "foo"));
+
+ fd = safe_close(fd);
+
+ fd = acquire_data_fd("", 0, flags);
+ assert_se(fd >= 0);
+
+ zero(rbuffer);
+ assert_se(read(fd, rbuffer, sizeof(rbuffer)) == 0);
+ assert_se(streq(rbuffer, ""));
+
+ fd = safe_close(fd);
+
+ random_bytes(wbuffer, sizeof(wbuffer));
+
+ fd = acquire_data_fd(wbuffer, sizeof(wbuffer), flags);
+ assert_se(fd >= 0);
+
+ zero(rbuffer);
+ assert_se(read(fd, rbuffer, sizeof(rbuffer)) == sizeof(rbuffer));
+ assert_se(memcmp(rbuffer, wbuffer, sizeof(rbuffer)) == 0);
+
+ fd = safe_close(fd);
+}
+
+static void test_acquire_data_fd(void) {
+
+ test_acquire_data_fd_one(0);
+ test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL);
+ test_acquire_data_fd_one(ACQUIRE_NO_MEMFD);
+ test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD);
+ test_acquire_data_fd_one(ACQUIRE_NO_PIPE);
+ test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_PIPE);
+ test_acquire_data_fd_one(ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE);
+ test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE);
+ test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE|ACQUIRE_NO_TMPFILE);
+}
+
+static void test_fd_move_above_stdio(void) {
+ int original_stdin, new_fd;
+
+ original_stdin = fcntl(0, F_DUPFD, 3);
+ assert_se(original_stdin >= 3);
+ assert_se(close_nointr(0) != EBADF);
+
+ new_fd = open("/dev/null", O_RDONLY);
+ assert_se(new_fd == 0);
+
+ new_fd = fd_move_above_stdio(new_fd);
+ assert_se(new_fd >= 3);
+
+ assert_se(dup(original_stdin) == 0);
+ assert_se(close_nointr(original_stdin) != EBADF);
+ assert_se(close_nointr(new_fd) != EBADF);
+}
+
+static void test_rearrange_stdio(void) {
+ pid_t pid;
+ int r;
+
+ r = safe_fork("rearrange", FORK_WAIT|FORK_LOG, &pid);
+ assert_se(r >= 0);
+
+ if (r == 0) {
+ _cleanup_free_ char *path = NULL;
+ char buffer[10];
+
+ /* Child */
+
+ safe_close(STDERR_FILENO); /* Let's close an fd < 2, to make it more interesting */
+
+ assert_se(rearrange_stdio(-1, -1, -1) >= 0);
+
+ assert_se(fd_get_path(STDIN_FILENO, &path) >= 0);
+ assert_se(path_equal(path, "/dev/null"));
+ path = mfree(path);
+
+ assert_se(fd_get_path(STDOUT_FILENO, &path) >= 0);
+ assert_se(path_equal(path, "/dev/null"));
+ path = mfree(path);
+
+ assert_se(fd_get_path(STDOUT_FILENO, &path) >= 0);
+ assert_se(path_equal(path, "/dev/null"));
+ path = mfree(path);
+
+ safe_close(STDIN_FILENO);
+ safe_close(STDOUT_FILENO);
+ safe_close(STDERR_FILENO);
+
+ {
+ int pair[2];
+ assert_se(pipe(pair) >= 0);
+ assert_se(pair[0] == 0);
+ assert_se(pair[1] == 1);
+ assert_se(fd_move_above_stdio(0) == 3);
+ }
+ assert_se(open("/dev/full", O_WRONLY|O_CLOEXEC) == 0);
+ assert_se(acquire_data_fd("foobar", 6, 0) == 2);
+
+ assert_se(rearrange_stdio(2, 0, 1) >= 0);
+
+ assert_se(write(1, "x", 1) < 0 && errno == ENOSPC);
+ assert_se(write(2, "z", 1) == 1);
+ assert_se(read(3, buffer, sizeof(buffer)) == 1);
+ assert_se(buffer[0] == 'z');
+ assert_se(read(0, buffer, sizeof(buffer)) == 6);
+ assert_se(memcmp(buffer, "foobar", 6) == 0);
+
+ assert_se(rearrange_stdio(-1, 1, 2) >= 0);
+ assert_se(write(1, "a", 1) < 0 && errno == ENOSPC);
+ assert_se(write(2, "y", 1) == 1);
+ assert_se(read(3, buffer, sizeof(buffer)) == 1);
+ assert_se(buffer[0] == 'y');
+
+ assert_se(fd_get_path(0, &path) >= 0);
+ assert_se(path_equal(path, "/dev/null"));
+ path = mfree(path);
+
+ _exit(EXIT_SUCCESS);
+ }
+}
+
+#if 0 /// UNNEEDED by elogind
+static void assert_equal_fd(int fd1, int fd2) {
+
+ for (;;) {
+ uint8_t a[4096], b[4096];
+ ssize_t x, y;
+
+ x = read(fd1, a, sizeof(a));
+ assert(x >= 0);
+
+ y = read(fd2, b, sizeof(b));
+ assert(y >= 0);
+
+ assert(x == y);
+
+ if (x == 0)
+ break;
+
+ assert(memcmp(a, b, x) == 0);
+ }
+}
+
+static void test_fd_duplicate_data_fd(void) {
+ _cleanup_close_ int fd1 = -1, fd2 = -1;
+ _cleanup_(close_pairp) int sfd[2] = { -1, -1 };
+ _cleanup_(sigkill_waitp) pid_t pid = -1;
+ uint64_t i, j;
+ int r;
+
+ fd1 = open("/etc/fstab", O_RDONLY|O_CLOEXEC);
+ if (fd1 >= 0) {
+
+ fd2 = fd_duplicate_data_fd(fd1);
+ assert_se(fd2 >= 0);
+
+ assert_se(lseek(fd1, 0, SEEK_SET) == 0);
+ assert_equal_fd(fd1, fd2);
+ }
+
+ fd1 = safe_close(fd1);
+ fd2 = safe_close(fd2);
+
+ fd1 = acquire_data_fd("hallo", 6, 0);
+ assert_se(fd1 >= 0);
+
+ fd2 = fd_duplicate_data_fd(fd1);
+ assert_se(fd2 >= 0);
+
+ safe_close(fd1);
+ fd1 = acquire_data_fd("hallo", 6, 0);
+ assert_se(fd1 >= 0);
+
+ assert_equal_fd(fd1, fd2);
+
+ fd1 = safe_close(fd1);
+ fd2 = safe_close(fd2);
+
+ assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sfd) >= 0);
+
+ r = safe_fork("(sd-pipe)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
+ assert_se(r >= 0);
+
+ if (r == 0) {
+ /* child */
+
+ sfd[0] = safe_close(sfd[0]);
+
+ for (i = 0; i < 1536*1024 / sizeof(uint64_t); i++)
+ assert_se(write(sfd[1], &i, sizeof(i)) == sizeof(i));
+
+ sfd[1] = safe_close(sfd[1]);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ sfd[1] = safe_close(sfd[1]);
+
+ fd2 = fd_duplicate_data_fd(sfd[0]);
+ assert_se(fd2 >= 0);
+
+ for (i = 0; i < 1536*1024 / sizeof(uint64_t); i++) {
+ assert_se(read(fd2, &j, sizeof(j)) == sizeof(j));
+ assert_se(i == j);
+ }
+
+ assert_se(read(fd2, &j, sizeof(j)) == 0);
+}
+#endif // 0
+
+static void test_read_nr_open(void) {
+ log_info("nr-open: %i", read_nr_open());
}
int main(int argc, char *argv[]) {
+
+ log_set_max_level(LOG_DEBUG);
+
test_close_many();
test_close_nointr();
#if 0 /// UNNEEDED by elogind
test_same_fd();
#endif // 0
test_open_serialization_fd();
+ test_acquire_data_fd();
+ test_fd_move_above_stdio();
+ test_rearrange_stdio();
+#if 0 /// UNNEEDED by elogind
+ test_fd_duplicate_data_fd();
+#endif // 0
+ test_read_nr_open();
return 0;
}
diff --git a/src/test/test-format-table.c b/src/test/test-format-table.c
new file mode 100644
index 000000000..adcc41416
--- /dev/null
+++ b/src/test/test-format-table.c
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "alloc-util.h"
+#include "format-table.h"
+#include "string-util.h"
+#include "time-util.h"
+
+int main(int argc, char *argv[]) {
+
+ _cleanup_(table_unrefp) Table *t = NULL;
+ _cleanup_free_ char *formatted = NULL;
+
+ assert_se(setenv("COLUMNS", "40", 1) >= 0);
+
+ assert_se(t = table_new("ONE", "TWO", "THREE"));
+
+ assert_se(table_set_align_percent(t, TABLE_HEADER_CELL(2), 100) >= 0);
+
+ assert_se(table_add_many(t,
+ TABLE_STRING, "xxx",
+ TABLE_STRING, "yyy",
+ TABLE_BOOLEAN, true) >= 0);
+
+ assert_se(table_add_many(t,
+ TABLE_STRING, "a long field",
+ TABLE_STRING, "yyy",
+ TABLE_BOOLEAN, false) >= 0);
+
+ assert_se(table_format(t, &formatted) >= 0);
+ printf("%s\n", formatted);
+
+ assert_se(streq(formatted,
+ "ONE TWO THREE\n"
+ "xxx yyy yes\n"
+ "a long field yyy no\n"));
+
+ formatted = mfree(formatted);
+
+ table_set_width(t, 40);
+
+ assert_se(table_format(t, &formatted) >= 0);
+ printf("%s\n", formatted);
+
+ assert_se(streq(formatted,
+ "ONE TWO THREE\n"
+ "xxx yyy yes\n"
+ "a long field yyy no\n"));
+
+ formatted = mfree(formatted);
+
+ table_set_width(t, 12);
+ assert_se(table_format(t, &formatted) >= 0);
+ printf("%s\n", formatted);
+
+ assert_se(streq(formatted,
+ "ONE TWO THR…\n"
+ "xxx yyy yes\n"
+ "a … yyy no\n"));
+
+ formatted = mfree(formatted);
+
+ table_set_width(t, 5);
+ assert_se(table_format(t, &formatted) >= 0);
+ printf("%s\n", formatted);
+
+ assert_se(streq(formatted,
+ "… … …\n"
+ "… … …\n"
+ "… … …\n"));
+
+ formatted = mfree(formatted);
+
+ table_set_width(t, 3);
+ assert_se(table_format(t, &formatted) >= 0);
+ printf("%s\n", formatted);
+
+ assert_se(streq(formatted,
+ "… … …\n"
+ "… … …\n"
+ "… … …\n"));
+
+ formatted = mfree(formatted);
+
+ table_set_width(t, (size_t) -1);
+ assert_se(table_set_sort(t, (size_t) 0, (size_t) 2, (size_t) -1) >= 0);
+
+ assert_se(table_format(t, &formatted) >= 0);
+ printf("%s\n", formatted);
+
+ assert_se(streq(formatted,
+ "ONE TWO THREE\n"
+ "a long field yyy no\n"
+ "xxx yyy yes\n"));
+
+ formatted = mfree(formatted);
+
+ table_set_header(t, false);
+
+ assert_se(table_add_many(t,
+ TABLE_STRING, "fäää",
+ TABLE_STRING, "uuu",
+ TABLE_BOOLEAN, true) >= 0);
+
+ assert_se(table_add_many(t,
+ TABLE_STRING, "fäää",
+ TABLE_STRING, "zzz",
+ TABLE_BOOLEAN, false) >= 0);
+
+ assert_se(table_add_many(t,
+ TABLE_EMPTY,
+ TABLE_SIZE, (uint64_t) 4711,
+ TABLE_TIMESPAN, (usec_t) 5*USEC_PER_MINUTE) >= 0);
+
+ assert_se(table_format(t, &formatted) >= 0);
+ printf("%s\n", formatted);
+
+ assert_se(streq(formatted,
+ "a long field yyy no\n"
+ "fäää zzz no\n"
+ "fäää uuu yes\n"
+ "xxx yyy yes\n"
+ " 4.6K 5min\n"));
+
+ formatted = mfree(formatted);
+
+ assert_se(table_set_display(t, (size_t) 2, (size_t) 0, (size_t) 2, (size_t) 0, (size_t) 0, (size_t) -1) >= 0);
+
+ assert_se(table_format(t, &formatted) >= 0);
+ printf("%s\n", formatted);
+
+ assert_se(streq(formatted,
+ " no a long f… no a long f… a long fi…\n"
+ " no fäää no fäää fäää \n"
+ " yes fäää yes fäää fäää \n"
+ " yes xxx yes xxx xxx \n"
+ "5min 5min \n"));
+
+ return 0;
+}
diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c
index 6620592e4..1cd8e0503 100644
--- a/src/test/test-fs-util.c
+++ b/src/test/test-fs-util.c
@@ -1,41 +1,28 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <unistd.h>
#include "alloc-util.h"
#include "fd-util.h"
+//#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
+#include "id128-util.h"
#include "macro.h"
#include "mkdir.h"
#include "path-util.h"
#include "rm-rf.h"
+#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
+#include "user-util.h"
#include "util.h"
static void test_chase_symlinks(void) {
_cleanup_free_ char *result = NULL;
char temp[] = "/tmp/test-chase.XXXXXX";
- const char *top, *p, *q;
- int r;
+ const char *top, *p, *pslash, *q, *qslash;
+ int r, pfd;
assert_se(mkdtemp(temp));
@@ -65,93 +52,134 @@ static void test_chase_symlinks(void) {
r = chase_symlinks(p, NULL, 0, &result);
assert_se(r > 0);
assert_se(path_equal(result, "/usr"));
+ result = mfree(result);
+ pslash = strjoina(p, "/");
+ r = chase_symlinks(pslash, NULL, 0, &result);
+ assert_se(r > 0);
+ assert_se(path_equal(result, "/usr/"));
result = mfree(result);
+
r = chase_symlinks(p, temp, 0, &result);
assert_se(r == -ENOENT);
+ r = chase_symlinks(pslash, temp, 0, &result);
+ assert_se(r == -ENOENT);
+
q = strjoina(temp, "/usr");
r = chase_symlinks(p, temp, CHASE_NONEXISTENT, &result);
assert_se(r == 0);
assert_se(path_equal(result, q));
+ result = mfree(result);
- assert_se(mkdir(q, 0700) >= 0);
+ qslash = strjoina(q, "/");
+ r = chase_symlinks(pslash, temp, CHASE_NONEXISTENT, &result);
+ assert_se(r == 0);
+ assert_se(path_equal(result, qslash));
result = mfree(result);
+
+ assert_se(mkdir(q, 0700) >= 0);
+
r = chase_symlinks(p, temp, 0, &result);
assert_se(r > 0);
assert_se(path_equal(result, q));
+ result = mfree(result);
+
+ r = chase_symlinks(pslash, temp, 0, &result);
+ assert_se(r > 0);
+ assert_se(path_equal(result, qslash));
+ result = mfree(result);
p = strjoina(temp, "/slash");
assert_se(symlink("/", p) >= 0);
- result = mfree(result);
r = chase_symlinks(p, NULL, 0, &result);
assert_se(r > 0);
assert_se(path_equal(result, "/"));
-
result = mfree(result);
+
r = chase_symlinks(p, temp, 0, &result);
assert_se(r > 0);
assert_se(path_equal(result, temp));
+ result = mfree(result);
/* Paths that would "escape" outside of the "root" */
p = strjoina(temp, "/6dots");
assert_se(symlink("../../..", p) >= 0);
- result = mfree(result);
r = chase_symlinks(p, temp, 0, &result);
assert_se(r > 0 && path_equal(result, temp));
+ result = mfree(result);
p = strjoina(temp, "/6dotsusr");
assert_se(symlink("../../../usr", p) >= 0);
- result = mfree(result);
r = chase_symlinks(p, temp, 0, &result);
assert_se(r > 0 && path_equal(result, q));
+ result = mfree(result);
p = strjoina(temp, "/top/8dotsusr");
assert_se(symlink("../../../../usr", p) >= 0);
- result = mfree(result);
r = chase_symlinks(p, temp, 0, &result);
assert_se(r > 0 && path_equal(result, q));
+ result = mfree(result);
/* Paths that contain repeated slashes */
p = strjoina(temp, "/slashslash");
assert_se(symlink("///usr///", p) >= 0);
- result = mfree(result);
r = chase_symlinks(p, NULL, 0, &result);
assert_se(r > 0);
assert_se(path_equal(result, "/usr"));
-
result = mfree(result);
+
r = chase_symlinks(p, temp, 0, &result);
assert_se(r > 0);
assert_se(path_equal(result, q));
+ result = mfree(result);
/* Paths using . */
- result = mfree(result);
r = chase_symlinks("/etc/./.././", NULL, 0, &result);
assert_se(r > 0);
assert_se(path_equal(result, "/"));
-
result = mfree(result);
+
r = chase_symlinks("/etc/./.././", "/etc", 0, &result);
assert_se(r > 0 && path_equal(result, "/etc"));
+ result = mfree(result);
+
+ r = chase_symlinks("/../.././//../../etc", NULL, 0, &result);
+ assert_se(r > 0);
+ assert_se(streq(result, "/etc"));
+ result = mfree(result);
+
+ r = chase_symlinks("/../.././//../../test-chase.fsldajfl", NULL, CHASE_NONEXISTENT, &result);
+ assert_se(r == 0);
+ assert_se(streq(result, "/test-chase.fsldajfl"));
+ result = mfree(result);
+
+ r = chase_symlinks("/../.././//../../etc", "/", CHASE_PREFIX_ROOT, &result);
+ assert_se(r > 0);
+ assert_se(streq(result, "/etc"));
+ result = mfree(result);
+ r = chase_symlinks("/../.././//../../test-chase.fsldajfl", "/", CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &result);
+ assert_se(r == 0);
+ assert_se(streq(result, "/test-chase.fsldajfl"));
result = mfree(result);
+
r = chase_symlinks("/etc/machine-id/foo", NULL, 0, &result);
assert_se(r == -ENOTDIR);
+ result = mfree(result);
/* Path that loops back to self */
- result = mfree(result);
p = strjoina(temp, "/recursive-symlink");
assert_se(symlink("recursive-symlink", p) >= 0);
r = chase_symlinks(p, NULL, 0, &result);
@@ -193,6 +221,94 @@ static void test_chase_symlinks(void) {
r = chase_symlinks(p, NULL, 0, &result);
assert_se(r == -ENOENT);
+ if (geteuid() == 0) {
+ p = strjoina(temp, "/priv1");
+ assert_se(mkdir(p, 0755) >= 0);
+
+ q = strjoina(p, "/priv2");
+ assert_se(mkdir(q, 0755) >= 0);
+
+ assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) >= 0);
+
+ assert_se(chown(q, UID_NOBODY, GID_NOBODY) >= 0);
+ assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) >= 0);
+
+ assert_se(chown(p, UID_NOBODY, GID_NOBODY) >= 0);
+ assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) >= 0);
+
+ assert_se(chown(q, 0, 0) >= 0);
+ assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) == -EPERM);
+
+ assert_se(rmdir(q) >= 0);
+ assert_se(symlink("/etc/passwd", q) >= 0);
+ assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) == -EPERM);
+
+ assert_se(chown(p, 0, 0) >= 0);
+ assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) >= 0);
+ }
+
+ p = strjoina(temp, "/machine-id-test");
+ assert_se(symlink("/usr/../etc/./machine-id", p) >= 0);
+
+ pfd = chase_symlinks(p, NULL, CHASE_OPEN, NULL);
+ if (pfd != -ENOENT) {
+ _cleanup_close_ int fd = -1;
+ sd_id128_t a, b;
+
+ assert_se(pfd >= 0);
+
+ fd = fd_reopen(pfd, O_RDONLY|O_CLOEXEC);
+ assert_se(fd >= 0);
+ safe_close(pfd);
+
+ assert_se(id128_read_fd(fd, ID128_PLAIN, &a) >= 0);
+ assert_se(sd_id128_get_machine(&b) >= 0);
+ assert_se(sd_id128_equal(a, b));
+ }
+
+ /* Test CHASE_ONE */
+
+ p = strjoina(temp, "/start");
+ r = chase_symlinks(p, NULL, CHASE_STEP, &result);
+ assert_se(r == 0);
+ p = strjoina(temp, "/top/dot/dotdota");
+ assert_se(streq(p, result));
+ result = mfree(result);
+
+ r = chase_symlinks(p, NULL, CHASE_STEP, &result);
+ assert_se(r == 0);
+ p = strjoina(temp, "/top/./dotdota");
+ assert_se(streq(p, result));
+ result = mfree(result);
+
+ r = chase_symlinks(p, NULL, CHASE_STEP, &result);
+ assert_se(r == 0);
+ p = strjoina(temp, "/top/../a");
+ assert_se(streq(p, result));
+ result = mfree(result);
+
+ r = chase_symlinks(p, NULL, CHASE_STEP, &result);
+ assert_se(r == 0);
+ p = strjoina(temp, "/a");
+ assert_se(streq(p, result));
+ result = mfree(result);
+
+ r = chase_symlinks(p, NULL, CHASE_STEP, &result);
+ assert_se(r == 0);
+ p = strjoina(temp, "/b");
+ assert_se(streq(p, result));
+ result = mfree(result);
+
+ r = chase_symlinks(p, NULL, CHASE_STEP, &result);
+ assert_se(r == 0);
+ assert_se(streq("/usr", result));
+ result = mfree(result);
+
+ r = chase_symlinks("/usr", NULL, CHASE_STEP, &result);
+ assert_se(r > 0);
+ assert_se(streq("/usr", result));
+ result = mfree(result);
+
assert_se(rm_rf(temp, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
}
@@ -220,8 +336,9 @@ static void test_readlink_and_make_absolute(void) {
char name2[] = "test-readlink_and_make_absolute/original";
char name_alias[] = "/tmp/test-readlink_and_make_absolute-alias";
char *r = NULL;
+ _cleanup_free_ char *pwd = NULL;
- assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid()) >= 0);
+ assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid(), MKDIR_WARN_MODE) >= 0);
assert_se(touch(name) >= 0);
assert_se(symlink(name, name_alias) >= 0);
@@ -230,6 +347,8 @@ static void test_readlink_and_make_absolute(void) {
free(r);
assert_se(unlink(name_alias) >= 0);
+ assert_se(safe_getcwd(&pwd) >= 0);
+
assert_se(chdir(tempdir) >= 0);
assert_se(symlink(name2, name_alias) >= 0);
assert_se(readlink_and_make_absolute(name_alias, &r) >= 0);
@@ -237,6 +356,8 @@ static void test_readlink_and_make_absolute(void) {
free(r);
assert_se(unlink(name_alias) >= 0);
+ assert_se(chdir(pwd) >= 0);
+
assert_se(rm_rf(tempdir, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
}
@@ -271,9 +392,9 @@ static void test_var_tmp(void) {
assert_se(tmp_backup);
}
- assert(unsetenv("TMPDIR") >= 0);
- assert(unsetenv("TEMP") >= 0);
- assert(unsetenv("TMP") >= 0);
+ assert_se(unsetenv("TMPDIR") >= 0);
+ assert_se(unsetenv("TEMP") >= 0);
+ assert_se(unsetenv("TMP") >= 0);
assert_se(var_tmp_dir(&tmp_dir) >= 0);
assert_se(streq(tmp_dir, "/var/tmp"));
@@ -317,6 +438,154 @@ static void test_dot_or_dot_dot(void) {
assert_se(!dot_or_dot_dot("..foo"));
}
+#if 0 /// Uses functions that elogind does not need
+static void test_access_fd(void) {
+ _cleanup_(rmdir_and_freep) char *p = NULL;
+ _cleanup_close_ int fd = -1;
+
+ assert_se(mkdtemp_malloc("/tmp/access-fd.XXXXXX", &p) >= 0);
+
+ fd = open(p, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
+ assert_se(fd >= 0);
+
+ assert_se(access_fd(fd, R_OK) >= 0);
+ assert_se(access_fd(fd, F_OK) >= 0);
+ assert_se(access_fd(fd, W_OK) >= 0);
+
+ assert_se(fchmod(fd, 0000) >= 0);
+
+ assert_se(access_fd(fd, F_OK) >= 0);
+
+ if (geteuid() == 0) {
+ assert_se(access_fd(fd, R_OK) >= 0);
+ assert_se(access_fd(fd, W_OK) >= 0);
+ } else {
+ assert_se(access_fd(fd, R_OK) == -EACCES);
+ assert_se(access_fd(fd, W_OK) == -EACCES);
+ }
+}
+
+static void test_touch_file(void) {
+ uid_t test_uid, test_gid;
+ _cleanup_(rm_rf_physical_and_freep) char *p = NULL;
+ struct stat st;
+ const char *a;
+ usec_t test_mtime;
+
+ test_uid = geteuid() == 0 ? 65534 : getuid();
+ test_gid = geteuid() == 0 ? 65534 : getgid();
+
+ test_mtime = usec_sub_unsigned(now(CLOCK_REALTIME), USEC_PER_WEEK);
+
+ assert_se(mkdtemp_malloc("/dev/shm/touch-file-XXXXXX", &p) >= 0);
+
+ a = strjoina(p, "/regular");
+ assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
+ assert_se(lstat(a, &st) >= 0);
+ assert_se(st.st_uid == test_uid);
+ assert_se(st.st_gid == test_gid);
+ assert_se(S_ISREG(st.st_mode));
+ assert_se((st.st_mode & 0777) == 0640);
+ assert_se(timespec_load(&st.st_mtim) == test_mtime);
+
+ a = strjoina(p, "/dir");
+ assert_se(mkdir(a, 0775) >= 0);
+ assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
+ assert_se(lstat(a, &st) >= 0);
+ assert_se(st.st_uid == test_uid);
+ assert_se(st.st_gid == test_gid);
+ assert_se(S_ISDIR(st.st_mode));
+ assert_se((st.st_mode & 0777) == 0640);
+ assert_se(timespec_load(&st.st_mtim) == test_mtime);
+
+ a = strjoina(p, "/fifo");
+ assert_se(mkfifo(a, 0775) >= 0);
+ assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
+ assert_se(lstat(a, &st) >= 0);
+ assert_se(st.st_uid == test_uid);
+ assert_se(st.st_gid == test_gid);
+ assert_se(S_ISFIFO(st.st_mode));
+ assert_se((st.st_mode & 0777) == 0640);
+ assert_se(timespec_load(&st.st_mtim) == test_mtime);
+
+ a = strjoina(p, "/sock");
+ assert_se(mknod(a, 0775 | S_IFSOCK, 0) >= 0);
+ assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
+ assert_se(lstat(a, &st) >= 0);
+ assert_se(st.st_uid == test_uid);
+ assert_se(st.st_gid == test_gid);
+ assert_se(S_ISSOCK(st.st_mode));
+ assert_se((st.st_mode & 0777) == 0640);
+ assert_se(timespec_load(&st.st_mtim) == test_mtime);
+
+ if (geteuid() == 0) {
+ a = strjoina(p, "/cdev");
+ assert_se(mknod(a, 0775 | S_IFCHR, makedev(0, 0)) >= 0);
+ assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
+ assert_se(lstat(a, &st) >= 0);
+ assert_se(st.st_uid == test_uid);
+ assert_se(st.st_gid == test_gid);
+ assert_se(S_ISCHR(st.st_mode));
+ assert_se((st.st_mode & 0777) == 0640);
+ assert_se(timespec_load(&st.st_mtim) == test_mtime);
+
+ a = strjoina(p, "/bdev");
+ assert_se(mknod(a, 0775 | S_IFBLK, makedev(0, 0)) >= 0);
+ assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
+ assert_se(lstat(a, &st) >= 0);
+ assert_se(st.st_uid == test_uid);
+ assert_se(st.st_gid == test_gid);
+ assert_se(S_ISBLK(st.st_mode));
+ assert_se((st.st_mode & 0777) == 0640);
+ assert_se(timespec_load(&st.st_mtim) == test_mtime);
+ }
+
+ a = strjoina(p, "/lnk");
+ assert_se(symlink("target", a) >= 0);
+ assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
+ assert_se(lstat(a, &st) >= 0);
+ assert_se(st.st_uid == test_uid);
+ assert_se(st.st_gid == test_gid);
+ assert_se(S_ISLNK(st.st_mode));
+ assert_se((st.st_mode & 0777) == 0640);
+ assert_se(timespec_load(&st.st_mtim) == test_mtime);
+}
+
+static void test_unlinkat_deallocate(void) {
+ _cleanup_free_ char *p = NULL;
+ _cleanup_close_ int fd = -1;
+ struct stat st;
+
+ assert_se(tempfn_random_child(NULL, "unlink-deallocation", &p) >= 0);
+
+ fd = open(p, O_WRONLY|O_CLOEXEC|O_CREAT|O_EXCL, 0600);
+ assert_se(fd >= 0);
+
+ assert_se(write(fd, "hallo\n", 6) == 6);
+
+ assert_se(fstat(fd, &st) >= 0);
+ assert_se(st.st_size == 6);
+ assert_se(st.st_blocks > 0);
+ assert_se(st.st_nlink == 1);
+
+ assert_se(unlinkat_deallocate(AT_FDCWD, p, 0) >= 0);
+
+ assert_se(fstat(fd, &st) >= 0);
+ assert_se(IN_SET(st.st_size, 0, 6)); /* depending on whether hole punching worked the size will be 6 (it worked) or 0 (we had to resort to truncation) */
+ assert_se(st.st_blocks == 0);
+ assert_se(st.st_nlink == 0);
+}
+#endif // 0
+
+static void test_fsync_directory_of_file(void) {
+ _cleanup_close_ int fd = -1;
+
+ fd = open_tmpfile_unlinkable(NULL, O_RDWR);
+ assert_se(fd >= 0);
+
+ assert_se(fsync_directory_of_file(fd) >= 0);
+}
+
int main(int argc, char *argv[]) {
test_unlink_noerrno();
test_get_files_in_directory();
@@ -326,6 +595,12 @@ int main(int argc, char *argv[]) {
#endif // 0
test_chase_symlinks();
test_dot_or_dot_dot();
+#if 0 /// Uses functions that elogind does not need
+ test_access_fd();
+ test_touch_file();
+ test_unlinkat_deallocate();
+#endif // 0
+ test_fsync_directory_of_file();
return 0;
}
diff --git a/src/test/test-hash.c b/src/test/test-hash.c
index 02d1cfaee..f5bc13184 100644
--- a/src/test/test-hash.c
+++ b/src/test/test-hash.c
@@ -1,22 +1,6 @@
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#include <errno.h>
#include <stdio.h>
#include "alloc-util.h"
@@ -33,12 +17,15 @@ int main(int argc, char *argv[]) {
assert_se(khash_new(&h, NULL) == -EINVAL);
assert_se(khash_new(&h, "") == -EINVAL);
- r = khash_new(&h, "foobar");
- if (r == -EAFNOSUPPORT) {
+
+ r = khash_supported();
+ assert_se(r >= 0);
+ if (r == 0) {
puts("khash not supported on this kernel, skipping");
return EXIT_TEST_SKIP;
}
- assert_se(r == -EOPNOTSUPP);
+
+ assert_se(khash_new(&h, "foobar") == -EOPNOTSUPP); /* undefined hash function */
assert_se(khash_new(&h, "sha256") >= 0);
assert_se(khash_get_size(h) == 32);
diff --git a/src/test/test-hashmap-ordered.awk b/src/test/test-hashmap-ordered.awk
new file mode 100644
index 000000000..10f4386fa
--- /dev/null
+++ b/src/test/test-hashmap-ordered.awk
@@ -0,0 +1,11 @@
+BEGIN {
+ print "/* GENERATED FILE */";
+ print "#define ORDERED"
+}
+{
+ if (!match($0, "^#include"))
+ gsub(/hashmap/, "ordered_hashmap");
+ gsub(/HASHMAP/, "ORDERED_HASHMAP");
+ gsub(/Hashmap/, "OrderedHashmap");
+ print
+}
diff --git a/src/test/test-hashmap-plain.c b/src/test/test-hashmap-plain.c
index 1bd5c02f8..47e689749 100644
--- a/src/test/test-hashmap-plain.c
+++ b/src/test/test-hashmap-plain.c
@@ -1,34 +1,26 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd
-
- Copyright 2013 Daniel Buch
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Daniel Buch
***/
#include "alloc-util.h"
+#include "env-util.h"
#include "hashmap.h"
+#include "log.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
+static bool arg_slow = false;
+
void test_hashmap_funcs(void);
static void test_hashmap_replace(void) {
Hashmap *m;
char *val1, *val2, *val3, *val4, *val5, *r;
+ log_info("%s", __func__);
+
m = hashmap_new(&string_hash_ops);
val1 = strdup("val1");
@@ -67,6 +59,8 @@ static void test_hashmap_copy(void) {
Hashmap *m, *copy;
char *val1, *val2, *val3, *val4, *r;
+ log_info("%s", __func__);
+
val1 = strdup("val1");
assert_se(val1);
val2 = strdup("val2");
@@ -103,6 +97,8 @@ static void test_hashmap_get_strv(void) {
char **strv;
char *val1, *val2, *val3, *val4;
+ log_info("%s", __func__);
+
val1 = strdup("val1");
assert_se(val1);
val2 = strdup("val2");
@@ -139,6 +135,8 @@ static void test_hashmap_move_one(void) {
Hashmap *m, *n;
char *val1, *val2, *val3, *val4, *r;
+ log_info("%s", __func__);
+
val1 = strdup("val1");
assert_se(val1);
val2 = strdup("val2");
@@ -178,6 +176,8 @@ static void test_hashmap_move(void) {
Hashmap *m, *n;
char *val1, *val2, *val3, *val4, *r;
+ log_info("%s", __func__);
+
val1 = strdup("val1");
assert_se(val1);
val2 = strdup("val2");
@@ -220,6 +220,8 @@ static void test_hashmap_update(void) {
Hashmap *m;
char *val1, *val2, *r;
+ log_info("%s", __func__);
+
m = hashmap_new(&string_hash_ops);
val1 = strdup("old_value");
assert_se(val1);
@@ -250,6 +252,8 @@ static void test_hashmap_put(void) {
void *val2 = (void*) "val 2";
_cleanup_free_ char* key1 = NULL;
+ log_info("%s", __func__);
+
assert_se(hashmap_ensure_allocated(&m, &string_hash_ops) >= 0);
assert_se(m);
@@ -268,6 +272,8 @@ static void test_hashmap_remove(void) {
_cleanup_hashmap_free_ Hashmap *m = NULL;
char *r;
+ log_info("%s", __func__);
+
r = hashmap_remove(NULL, "key 1");
assert_se(r == NULL);
@@ -296,6 +302,8 @@ static void test_hashmap_remove2(void) {
char val2[] = "val 2";
void *r, *r2;
+ log_info("%s", __func__);
+
r = hashmap_remove2(NULL, "key 1", &r2);
assert_se(r == NULL);
@@ -326,6 +334,8 @@ static void test_hashmap_remove_value(void) {
char val1[] = "val 1";
char val2[] = "val 2";
+ log_info("%s", __func__);
+
r = hashmap_remove_value(NULL, "key 1", val1);
assert_se(r == NULL);
@@ -358,6 +368,8 @@ static void test_hashmap_remove_and_put(void) {
int valid;
char *r;
+ log_info("%s", __func__);
+
m = hashmap_new(&string_hash_ops);
assert_se(m);
@@ -392,6 +404,8 @@ static void test_hashmap_remove_and_replace(void) {
void *r;
int i, j;
+ log_info("%s", __func__);
+
m = hashmap_new(&trivial_hash_ops);
assert_se(m);
@@ -443,6 +457,8 @@ static void test_hashmap_ensure_allocated(void) {
Hashmap *m;
int valid_hashmap;
+ log_info("%s", __func__);
+
m = hashmap_new(&string_hash_ops);
valid_hashmap = hashmap_ensure_allocated(&m, &string_hash_ops);
@@ -464,6 +480,8 @@ static void test_hashmap_foreach_key(void) {
"key 3\0"
"key 4\0";
+ log_info("%s", __func__);
+
m = hashmap_new(&string_hash_ops);
NULSTR_FOREACH(key, key_table)
@@ -494,6 +512,8 @@ static void test_hashmap_foreach(void) {
char *val1, *val2, *val3, *val4, *s;
unsigned count;
+ log_info("%s", __func__);
+
val1 = strdup("my val1");
assert_se(val1);
val2 = strdup("my val2");
@@ -544,6 +564,8 @@ static void test_hashmap_merge(void) {
Hashmap *n;
char *val1, *val2, *val3, *val4, *r;
+ log_info("%s", __func__);
+
val1 = strdup("my val1");
assert_se(val1);
val2 = strdup("my val2");
@@ -577,6 +599,8 @@ static void test_hashmap_contains(void) {
Hashmap *m;
char *val1;
+ log_info("%s", __func__);
+
val1 = strdup("my val");
assert_se(val1);
@@ -597,6 +621,8 @@ static void test_hashmap_isempty(void) {
Hashmap *m;
char *val1;
+ log_info("%s", __func__);
+
val1 = strdup("my val");
assert_se(val1);
@@ -614,6 +640,8 @@ static void test_hashmap_size(void) {
Hashmap *m;
char *val1, *val2, *val3, *val4;
+ log_info("%s", __func__);
+
val1 = strdup("my val");
assert_se(val1);
val2 = strdup("my val");
@@ -644,6 +672,8 @@ static void test_hashmap_get(void) {
char *r;
char *val;
+ log_info("%s", __func__);
+
val = strdup("my val");
assert_se(val);
@@ -671,6 +701,8 @@ static void test_hashmap_get2(void) {
char key_orig[] = "Key 1";
void *key_copy;
+ log_info("%s", __func__);
+
val = strdup("my val");
assert_se(val);
@@ -710,14 +742,15 @@ static void test_hashmap_many(void) {
Hashmap *h;
unsigned i, j;
void *v, *k;
- static const struct {
+ const struct {
const struct hash_ops *ops;
unsigned n_entries;
} tests[] = {
- { .ops = NULL, .n_entries = 1 << 20 },
- { .ops = &crippled_hashmap_ops, .n_entries = 1 << 14 },
+ { .ops = NULL, .n_entries = arg_slow ? 1 << 20 : 240 },
+ { .ops = &crippled_hashmap_ops, .n_entries = arg_slow ? 1 << 14 : 140 },
};
+ log_info("%s (%s)", __func__, arg_slow ? "slow" : "fast");
for (j = 0; j < ELEMENTSOF(tests); j++) {
assert_se(h = hashmap_new(tests[j].ops));
@@ -748,6 +781,8 @@ static void test_hashmap_many(void) {
static void test_hashmap_first(void) {
_cleanup_hashmap_free_ Hashmap *m = NULL;
+ log_info("%s", __func__);
+
m = hashmap_new(&string_hash_ops);
assert_se(m);
@@ -765,6 +800,8 @@ static void test_hashmap_first(void) {
static void test_hashmap_first_key(void) {
_cleanup_hashmap_free_ Hashmap *m = NULL;
+ log_info("%s", __func__);
+
m = hashmap_new(&string_hash_ops);
assert_se(m);
@@ -782,6 +819,8 @@ static void test_hashmap_first_key(void) {
static void test_hashmap_steal_first_key(void) {
_cleanup_hashmap_free_ Hashmap *m = NULL;
+ log_info("%s", __func__);
+
m = hashmap_new(&string_hash_ops);
assert_se(m);
@@ -797,6 +836,8 @@ static void test_hashmap_steal_first(void) {
int seen[3] = {};
char *val;
+ log_info("%s", __func__);
+
m = hashmap_new(&string_hash_ops);
assert_se(m);
@@ -815,6 +856,8 @@ static void test_hashmap_steal_first(void) {
static void test_hashmap_clear_free_free(void) {
_cleanup_hashmap_free_ Hashmap *m = NULL;
+ log_info("%s", __func__);
+
m = hashmap_new(&string_hash_ops);
assert_se(m);
@@ -829,6 +872,8 @@ static void test_hashmap_clear_free_free(void) {
static void test_hashmap_reserve(void) {
_cleanup_hashmap_free_ Hashmap *m = NULL;
+ log_info("%s", __func__);
+
m = hashmap_new(&string_hash_ops);
assert_se(hashmap_reserve(m, 1) == 0);
@@ -844,6 +889,18 @@ static void test_hashmap_reserve(void) {
}
void test_hashmap_funcs(void) {
+#if 0 /// UNNEEDED by elogind
+ int r;
+#endif // 0
+
+ log_parse_environment();
+ log_open();
+
+#if 0 /// UNNEEDED by elogind
+ r = getenv_bool("SYSTEMD_SLOW_TESTS");
+ arg_slow = r >= 0 ? r : SYSTEMD_SLOW_TESTS_DEFAULT;
+#endif // 0
+
test_hashmap_copy();
test_hashmap_get_strv();
test_hashmap_move_one();
diff --git a/src/test/test-hashmap.c b/src/test/test-hashmap.c
index 83cea360e..b319fa6ba 100644
--- a/src/test/test-hashmap.c
+++ b/src/test/test-hashmap.c
@@ -1,20 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd
-
- Copyright 2013 Daniel Buch
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Daniel Buch
***/
#include "hashmap.h"
@@ -37,6 +23,29 @@ static void test_ordered_hashmap_next(void) {
assert_se(!ordered_hashmap_next(m, INT_TO_PTR(3)));
}
+typedef struct Item {
+ int seen;
+} Item;
+static void item_seen(Item *item) {
+ item->seen++;
+}
+
+static void test_hashmap_free_with_destructor(void) {
+ Hashmap *m;
+ struct Item items[4] = {};
+ unsigned i;
+
+ assert_se(m = hashmap_new(NULL));
+ for (i = 0; i < ELEMENTSOF(items) - 1; i++)
+ assert_se(hashmap_put(m, INT_TO_PTR(i), items + i) == 1);
+
+ m = hashmap_free_with_destructor(m, item_seen);
+ assert_se(items[0].seen == 1);
+ assert_se(items[1].seen == 1);
+ assert_se(items[2].seen == 1);
+ assert_se(items[3].seen == 0);
+}
+
static void test_uint64_compare_func(void) {
const uint64_t a = 0x100, b = 0x101;
@@ -56,12 +65,102 @@ static void test_string_compare_func(void) {
assert_se(string_compare_func("fred", "fred") == 0);
}
+static void compare_cache(Hashmap *map, IteratedCache *cache) {
+ const void **keys = NULL, **values = NULL;
+ unsigned num, idx;
+ Iterator iter;
+ void *k, *v;
+
+ assert_se(iterated_cache_get(cache, &keys, &values, &num) == 0);
+ assert_se(num == 0 || keys);
+ assert_se(num == 0 || values);
+
+ idx = 0;
+ HASHMAP_FOREACH_KEY(v, k, map, iter) {
+ assert_se(v == values[idx]);
+ assert_se(k == keys[idx]);
+
+ idx++;
+ }
+
+ assert_se(idx == num);
+}
+
+static void test_iterated_cache(void) {
+ Hashmap *m;
+ IteratedCache *c;
+
+ assert_se(m = hashmap_new(NULL));
+ assert_se(c = hashmap_iterated_cache_new(m));
+ compare_cache(m, c);
+
+ for (int stage = 0; stage < 100; stage++) {
+
+ for (int i = 0; i < 100; i++) {
+ int foo = stage * 1000 + i;
+
+ assert_se(hashmap_put(m, INT_TO_PTR(foo), INT_TO_PTR(foo + 777)) == 1);
+ }
+
+ compare_cache(m, c);
+
+ if (!(stage % 10)) {
+ for (int i = 0; i < 100; i++) {
+ int foo = stage * 1000 + i;
+
+ assert_se(hashmap_remove(m, INT_TO_PTR(foo)) == INT_TO_PTR(foo + 777));
+ }
+
+ compare_cache(m, c);
+ }
+ }
+
+ hashmap_clear(m);
+ compare_cache(m, c);
+
+ assert_se(hashmap_free(m) == NULL);
+ assert_se(iterated_cache_free(c) == NULL);
+}
+
+static void test_path_hashmap(void) {
+ _cleanup_hashmap_free_ Hashmap *h = NULL;
+
+ assert_se(h = hashmap_new(&path_hash_ops));
+
+ assert_se(hashmap_put(h, "foo", INT_TO_PTR(1)) >= 0);
+ assert_se(hashmap_put(h, "/foo", INT_TO_PTR(2)) >= 0);
+ assert_se(hashmap_put(h, "//foo", INT_TO_PTR(3)) == -EEXIST);
+ assert_se(hashmap_put(h, "//foox/", INT_TO_PTR(4)) >= 0);
+ assert_se(hashmap_put(h, "/foox////", INT_TO_PTR(5)) == -EEXIST);
+ assert_se(hashmap_put(h, "foo//////bar/quux//", INT_TO_PTR(6)) >= 0);
+ assert_se(hashmap_put(h, "foo/bar//quux/", INT_TO_PTR(8)) == -EEXIST);
+
+ assert_se(hashmap_get(h, "foo") == INT_TO_PTR(1));
+ assert_se(hashmap_get(h, "foo/") == INT_TO_PTR(1));
+ assert_se(hashmap_get(h, "foo////") == INT_TO_PTR(1));
+ assert_se(hashmap_get(h, "/foo") == INT_TO_PTR(2));
+ assert_se(hashmap_get(h, "//foo") == INT_TO_PTR(2));
+ assert_se(hashmap_get(h, "/////foo////") == INT_TO_PTR(2));
+ assert_se(hashmap_get(h, "/////foox////") == INT_TO_PTR(4));
+ assert_se(hashmap_get(h, "/foox/") == INT_TO_PTR(4));
+ assert_se(hashmap_get(h, "/foox") == INT_TO_PTR(4));
+ assert_se(!hashmap_get(h, "foox"));
+ assert_se(hashmap_get(h, "foo/bar/quux") == INT_TO_PTR(6));
+ assert_se(hashmap_get(h, "foo////bar////quux/////") == INT_TO_PTR(6));
+ assert_se(!hashmap_get(h, "/foo////bar////quux/////"));
+}
+
int main(int argc, const char *argv[]) {
test_hashmap_funcs();
test_ordered_hashmap_funcs();
test_ordered_hashmap_next();
+ test_hashmap_free_with_destructor();
test_uint64_compare_func();
test_trivial_compare_func();
test_string_compare_func();
+ test_iterated_cache();
+ test_path_hashmap();
+
+ return 0;
}
diff --git a/src/test/test-helper.h b/src/test/test-helper.h
index ddb10f88f..3e8ccd904 100644
--- a/src/test/test-helper.h
+++ b/src/test/test-helper.h
@@ -1,22 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
- This file is part of systemd.
-
- Copyright 2013 Holger Hans Peter Freyther
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Holger Hans Peter Freyther
***/
#include "sd-daemon.h"
@@ -39,3 +25,5 @@
-ENOENT, \
-ENOMEDIUM /* cannot determine cgroup */ \
)
+
+int enter_cgroup_subroot(void);
diff --git a/src/test/test-hexdecoct.c b/src/test/test-hexdecoct.c
index fcae427e7..101a78bda 100644
--- a/src/test/test-hexdecoct.c
+++ b/src/test/test-hexdecoct.c
@@ -1,27 +1,15 @@
-/***
- This file is part of systemd.
+/* SPDX-License-Identifier: LGPL-2.1+ */
- 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 "alloc-util.h"
#include "hexdecoct.h"
#include "macro.h"
#include "string-util.h"
+/// Additional includes needed by elogind
+#include "musl_missing.h"
+
static void test_hexchar(void) {
assert_se(hexchar(0xa) == 'a');
assert_se(hexchar(0x0) == '0');
@@ -86,256 +74,248 @@ static void test_undecchar(void) {
assert_se(undecchar('9') == 9);
}
-static void test_unhexmem(void) {
- const char *hex = "efa2149213";
- const char *hex_invalid = "efa214921o";
- _cleanup_free_ char *hex2 = NULL;
+static void test_unhexmem_one(const char *s, size_t l, int retval) {
+ _cleanup_free_ char *hex = NULL;
_cleanup_free_ void *mem = NULL;
size_t len;
- assert_se(unhexmem(hex_invalid, strlen(hex_invalid), &mem, &len) == -EINVAL);
- assert_se(unhexmem(hex, strlen(hex) + 1, &mem, &len) == -EINVAL);
- assert_se(unhexmem(hex, strlen(hex) - 1, &mem, &len) == -EINVAL);
- assert_se(unhexmem(hex, strlen(hex), &mem, &len) == 0);
+ assert_se(unhexmem(s, l, &mem, &len) == retval);
+ if (retval == 0) {
+ char *answer;
+
+ if (l == (size_t) -1)
+ l = strlen(s);
+
+ assert_se(hex = hexmem(mem, len));
+ answer = strndupa(s, l);
+ assert_se(streq(delete_chars(answer, WHITESPACE), hex));
+ }
+}
+
+static void test_unhexmem(void) {
+ const char *hex = "efa2149213";
+ const char *hex_space = " e f a\n 2\r 14\n\r\t9\t2 \n1\r3 \r\r\t";
+ const char *hex_invalid = "efa214921o";
- assert_se((hex2 = hexmem(mem, len)));
- assert_se(streq(hex, hex2));
+ test_unhexmem_one(NULL, 0, 0);
+ test_unhexmem_one("", 0, 0);
+ test_unhexmem_one("", (size_t) -1, 0);
+ test_unhexmem_one(" \n \t\r \t\t \n\n\n", (size_t) -1, 0);
+ test_unhexmem_one(hex_invalid, strlen(hex_invalid), -EINVAL);
+ test_unhexmem_one(hex_invalid, (size_t) - 1, -EINVAL);
+ test_unhexmem_one(hex, strlen(hex) - 1, -EPIPE);
+ test_unhexmem_one(hex, strlen(hex), 0);
+ test_unhexmem_one(hex, (size_t) -1, 0);
+ test_unhexmem_one(hex_space, strlen(hex_space), 0);
+ test_unhexmem_one(hex_space, (size_t) -1, 0);
}
/* https://tools.ietf.org/html/rfc4648#section-10 */
static void test_base32hexmem(void) {
char *b32;
- b32 = base32hexmem("", strlen(""), true);
+ b32 = base32hexmem("", STRLEN(""), true);
assert_se(b32);
assert_se(streq(b32, ""));
free(b32);
- b32 = base32hexmem("f", strlen("f"), true);
+ b32 = base32hexmem("f", STRLEN("f"), true);
assert_se(b32);
assert_se(streq(b32, "CO======"));
free(b32);
- b32 = base32hexmem("fo", strlen("fo"), true);
+ b32 = base32hexmem("fo", STRLEN("fo"), true);
assert_se(b32);
assert_se(streq(b32, "CPNG===="));
free(b32);
- b32 = base32hexmem("foo", strlen("foo"), true);
+ b32 = base32hexmem("foo", STRLEN("foo"), true);
assert_se(b32);
assert_se(streq(b32, "CPNMU==="));
free(b32);
- b32 = base32hexmem("foob", strlen("foob"), true);
+ b32 = base32hexmem("foob", STRLEN("foob"), true);
assert_se(b32);
assert_se(streq(b32, "CPNMUOG="));
free(b32);
- b32 = base32hexmem("fooba", strlen("fooba"), true);
+ b32 = base32hexmem("fooba", STRLEN("fooba"), true);
assert_se(b32);
assert_se(streq(b32, "CPNMUOJ1"));
free(b32);
- b32 = base32hexmem("foobar", strlen("foobar"), true);
+ b32 = base32hexmem("foobar", STRLEN("foobar"), true);
assert_se(b32);
assert_se(streq(b32, "CPNMUOJ1E8======"));
free(b32);
- b32 = base32hexmem("", strlen(""), false);
+ b32 = base32hexmem("", STRLEN(""), false);
assert_se(b32);
assert_se(streq(b32, ""));
free(b32);
- b32 = base32hexmem("f", strlen("f"), false);
+ b32 = base32hexmem("f", STRLEN("f"), false);
assert_se(b32);
assert_se(streq(b32, "CO"));
free(b32);
- b32 = base32hexmem("fo", strlen("fo"), false);
+ b32 = base32hexmem("fo", STRLEN("fo"), false);
assert_se(b32);
assert_se(streq(b32, "CPNG"));
free(b32);
- b32 = base32hexmem("foo", strlen("foo"), false);
+ b32 = base32hexmem("foo", STRLEN("foo"), false);
assert_se(b32);
assert_se(streq(b32, "CPNMU"));
free(b32);
- b32 = base32hexmem("foob", strlen("foob"), false);
+ b32 = base32hexmem("foob", STRLEN("foob"), false);
assert_se(b32);
assert_se(streq(b32, "CPNMUOG"));
free(b32);
- b32 = base32hexmem("fooba", strlen("fooba"), false);
+ b32 = base32hexmem("fooba", STRLEN("fooba"), false);
assert_se(b32);
assert_se(streq(b32, "CPNMUOJ1"));
free(b32);
- b32 = base32hexmem("foobar", strlen("foobar"), false);
+ b32 = base32hexmem("foobar", STRLEN("foobar"), false);
assert_se(b32);
assert_se(streq(b32, "CPNMUOJ1E8"));
free(b32);
}
-static void test_unbase32hexmem(void) {
- void *mem;
+static void test_unbase32hexmem_one(const char *hex, bool padding, int retval, const char *ans) {
+ _cleanup_free_ void *mem = NULL;
size_t len;
- assert_se(unbase32hexmem("", strlen(""), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), ""));
- free(mem);
-
- assert_se(unbase32hexmem("CO======", strlen("CO======"), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "f"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNG====", strlen("CPNG===="), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMU===", strlen("CPNMU==="), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foob"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fooba"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foobar"));
- free(mem);
-
- assert_se(unbase32hexmem("A", strlen("A"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("A=======", strlen("A======="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAA=====", strlen("AAA====="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAA==", strlen("AAAAAA=="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AB======", strlen("AB======"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAB====", strlen("AAAB===="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAB===", strlen("AAAAB==="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAAB=", strlen("AAAAAAB="), true, &mem, &len) == -EINVAL);
-
- assert_se(unbase32hexmem("XPNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CXNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPXMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNXUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMXOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUXJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUOX1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUOJX", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
-
- assert_se(unbase32hexmem("", strlen(""), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), ""));
- free(mem);
-
- assert_se(unbase32hexmem("CO", strlen("CO"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "f"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNG", strlen("CPNG"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMU", strlen("CPNMU"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOG", strlen("CPNMUOG"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foob"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fooba"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1E8", strlen("CPNMUOJ1E8"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foobar"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAA", strlen("AAA"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAA", strlen("AAAAAA"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AB", strlen("AB"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAB", strlen("AAAB"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAB", strlen("AAAAB"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAAB", strlen("AAAAAAB"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem(hex, (size_t) -1, padding, &mem, &len) == retval);
+ if (retval == 0) {
+ char *str;
+
+ str = strndupa(mem, len);
+ assert_se(streq(str, ans));
+ }
+}
+
+static void test_unbase32hexmem(void) {
+ test_unbase32hexmem_one("", true, 0, "");
+
+ test_unbase32hexmem_one("CO======", true, 0, "f");
+ test_unbase32hexmem_one("CPNG====", true, 0, "fo");
+ test_unbase32hexmem_one("CPNMU===", true, 0, "foo");
+ test_unbase32hexmem_one("CPNMUOG=", true, 0, "foob");
+ test_unbase32hexmem_one("CPNMUOJ1", true, 0, "fooba");
+ test_unbase32hexmem_one("CPNMUOJ1E8======", true, 0, "foobar");
+
+ test_unbase32hexmem_one("A", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("A=======", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAA=====", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAAAA==", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("AB======", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAB====", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAAB===", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAAAAB=", true, -EINVAL, NULL);
+
+ test_unbase32hexmem_one("XPNMUOJ1", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("CXNMUOJ1", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("CPXMUOJ1", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("CPNXUOJ1", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("CPNMXOJ1", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("CPNMUXJ1", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("CPNMUOX1", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("CPNMUOJX", true, -EINVAL, NULL);
+
+ test_unbase32hexmem_one("", false, 0, "");
+ test_unbase32hexmem_one("CO", false, 0, "f");
+ test_unbase32hexmem_one("CPNG", false, 0, "fo");
+ test_unbase32hexmem_one("CPNMU", false, 0, "foo");
+ test_unbase32hexmem_one("CPNMUOG", false, 0, "foob");
+ test_unbase32hexmem_one("CPNMUOJ1", false, 0, "fooba");
+ test_unbase32hexmem_one("CPNMUOJ1E8", false, 0, "foobar");
+ test_unbase32hexmem_one("CPNMUOG=", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("CPNMUOJ1E8======", false, -EINVAL, NULL);
+
+ test_unbase32hexmem_one("A", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("A", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAA", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAAAA", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("AB", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAB", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAAB", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAAAAB", false, -EINVAL, NULL);
}
/* https://tools.ietf.org/html/rfc4648#section-10 */
static void test_base64mem(void) {
char *b64;
- assert_se(base64mem("", strlen(""), &b64) == 0);
+ assert_se(base64mem("", STRLEN(""), &b64) == 0);
assert_se(streq(b64, ""));
free(b64);
- assert_se(base64mem("f", strlen("f"), &b64) == 4);
+ assert_se(base64mem("f", STRLEN("f"), &b64) == 4);
assert_se(streq(b64, "Zg=="));
free(b64);
- assert_se(base64mem("fo", strlen("fo"), &b64) == 4);
+ assert_se(base64mem("fo", STRLEN("fo"), &b64) == 4);
assert_se(streq(b64, "Zm8="));
free(b64);
- assert_se(base64mem("foo", strlen("foo"), &b64) == 4);
+ assert_se(base64mem("foo", STRLEN("foo"), &b64) == 4);
assert_se(streq(b64, "Zm9v"));
free(b64);
- assert_se(base64mem("foob", strlen("foob"), &b64) == 8);
+ assert_se(base64mem("foob", STRLEN("foob"), &b64) == 8);
assert_se(streq(b64, "Zm9vYg=="));
free(b64);
- assert_se(base64mem("fooba", strlen("fooba"), &b64) == 8);
+ assert_se(base64mem("fooba", STRLEN("fooba"), &b64) == 8);
assert_se(streq(b64, "Zm9vYmE="));
free(b64);
- assert_se(base64mem("foobar", strlen("foobar"), &b64) == 8);
+ assert_se(base64mem("foobar", STRLEN("foobar"), &b64) == 8);
assert_se(streq(b64, "Zm9vYmFy"));
free(b64);
}
-static void test_unbase64mem(void) {
- void *mem;
- size_t len;
-
- assert_se(unbase64mem("", strlen(""), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), ""));
- free(mem);
-
- assert_se(unbase64mem("Zg==", strlen("Zg=="), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "f"));
- free(mem);
-
- assert_se(unbase64mem("Zm8=", strlen("Zm8="), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fo"));
- free(mem);
+static void test_unbase64mem_one(const char *input, const char *output, int ret) {
+ _cleanup_free_ void *buffer = NULL;
+ size_t size = 0;
- assert_se(unbase64mem("Zm9v", strlen("Zm9v"), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foo"));
- free(mem);
+ assert_se(unbase64mem(input, (size_t) -1, &buffer, &size) == ret);
- assert_se(unbase64mem("Zm9vYg==", strlen("Zm9vYg=="), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foob"));
- free(mem);
-
- assert_se(unbase64mem("Zm9vYmE=", strlen("Zm9vYmE="), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fooba"));
- free(mem);
+ if (ret >= 0) {
+ assert_se(size == strlen(output));
+ assert_se(memcmp(buffer, output, size) == 0);
+ assert_se(((char*) buffer)[size] == 0);
+ }
+}
- assert_se(unbase64mem("Zm9vYmFy", strlen("Zm9vYmFy"), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foobar"));
- free(mem);
+static void test_unbase64mem(void) {
- assert_se(unbase64mem("A", strlen("A"), &mem, &len) == -EINVAL);
- assert_se(unbase64mem("A====", strlen("A===="), &mem, &len) == -EINVAL);
- assert_se(unbase64mem("AAB==", strlen("AAB=="), &mem, &len) == -EINVAL);
- assert_se(unbase64mem("AAAB=", strlen("AAAB="), &mem, &len) == -EINVAL);
+ test_unbase64mem_one("", "", 0);
+ test_unbase64mem_one("Zg==", "f", 0);
+ test_unbase64mem_one("Zm8=", "fo", 0);
+ test_unbase64mem_one("Zm9v", "foo", 0);
+ test_unbase64mem_one("Zm9vYg==", "foob", 0);
+ test_unbase64mem_one("Zm9vYmE=", "fooba", 0);
+ test_unbase64mem_one("Zm9vYmFy", "foobar", 0);
+
+ test_unbase64mem_one(" ", "", 0);
+ test_unbase64mem_one(" \n\r ", "", 0);
+ test_unbase64mem_one(" Zg\n== ", "f", 0);
+ test_unbase64mem_one(" Zm 8=\r", "fo", 0);
+ test_unbase64mem_one(" Zm9\n\r\r\nv ", "foo", 0);
+ test_unbase64mem_one(" Z m9vYg==\n\r", "foob", 0);
+ test_unbase64mem_one(" Zm 9vYmE= ", "fooba", 0);
+ test_unbase64mem_one(" Z m9v YmFy ", "foobar", 0);
+
+ test_unbase64mem_one("A", NULL, -EPIPE);
+ test_unbase64mem_one("A====", NULL, -EINVAL);
+ test_unbase64mem_one("AAB==", NULL, -EINVAL);
+ test_unbase64mem_one(" A A A B = ", NULL, -EINVAL);
+ test_unbase64mem_one(" Z m 8 = q u u x ", NULL, -ENAMETOOLONG);
}
static void test_hexdump(void) {
diff --git a/src/test/test-id128.c b/src/test/test-id128.c
index e5f45206f..e3d07a69f 100644
--- a/src/test/test-id128.c
+++ b/src/test/test-id128.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <string.h>
@@ -155,9 +138,9 @@ int main(int argc, char *argv[]) {
assert_se(sd_id128_equal(id, id2));
r = sd_id128_get_machine_app_specific(SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id);
- if (r == -EAFNOSUPPORT) {
+ if (r == -EOPNOTSUPP)
log_info("khash not supported on this kernel, skipping sd_id128_get_machine_app_specific() checks");
- } else {
+ else {
assert_se(r >= 0);
assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id2) >= 0);
assert_se(sd_id128_equal(id, id2));
diff --git a/src/test/test-io-util.c b/src/test/test-io-util.c
index 10bd3833b..42e632a8a 100644
--- a/src/test/test-io-util.c
+++ b/src/test/test-io-util.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <fcntl.h>
#include <stdlib.h>
diff --git a/src/test/test-ipcrm.c b/src/test/test-ipcrm.c
index 2a3852b89..391585916 100644
--- a/src/test/test-ipcrm.c
+++ b/src/test/test-ipcrm.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include "clean-ipc.h"
#include "user-util.h"
diff --git a/src/test/test-list.c b/src/test/test-list.c
index 0ccd745cc..24e0496d4 100644
--- a/src/test/test-list.c
+++ b/src/test/test-list.c
@@ -1,20 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd
-
- Copyright 2013 Jan Janssen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Jan Janssen
***/
#include "list.h"
diff --git a/src/test/test-locale-util.c b/src/test/test-locale-util.c
index 427c698d1..8ffae8ca0 100644
--- a/src/test/test-locale-util.c
+++ b/src/test/test-locale-util.c
@@ -1,22 +1,4 @@
-/***
- This file is part of systemd
-
- Copyright 2014 Ronny Chevalier
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include "locale-util.h"
#include "macro.h"
@@ -38,6 +20,8 @@ static void test_get_locales(void) {
}
static void test_locale_is_valid(void) {
+ log_info("/* %s */", __func__);
+
assert_se(locale_is_valid("en_EN.utf8"));
assert_se(locale_is_valid("fr_FR.utf8"));
assert_se(locale_is_valid("fr_FR@euro"));
@@ -50,9 +34,60 @@ static void test_locale_is_valid(void) {
assert_se(!locale_is_valid("\x01gar\x02 bage\x03"));
}
+static void test_keymaps(void) {
+ _cleanup_strv_free_ char **kmaps = NULL;
+ char **p;
+ int r;
+
+ log_info("/* %s */", __func__);
+
+ assert_se(!keymap_is_valid(""));
+ assert_se(!keymap_is_valid("/usr/bin/foo"));
+ assert_se(!keymap_is_valid("\x01gar\x02 bage\x03"));
+
+ r = get_keymaps(&kmaps);
+ if (r == -ENOENT)
+ return; /* skip test if no keymaps are installed */
+
+ assert_se(r >= 0);
+ assert_se(kmaps);
+
+ STRV_FOREACH(p, kmaps) {
+ puts(*p);
+ assert_se(keymap_is_valid(*p));
+ }
+
+ assert_se(keymap_is_valid("uk"));
+ assert_se(keymap_is_valid("de-nodeadkeys"));
+ assert_se(keymap_is_valid("ANSI-dvorak"));
+ assert_se(keymap_is_valid("unicode"));
+}
+
+#define dump_glyph(x) log_info(STRINGIFY(x) ": %s", special_glyph(x))
+static void dump_special_glyphs(void) {
+ assert_cc(ELLIPSIS + 1 == _SPECIAL_GLYPH_MAX);
+
+ log_info("/* %s */", __func__);
+
+ log_info("is_locale_utf8: %s", yes_no(is_locale_utf8()));
+
+ dump_glyph(TREE_VERTICAL);
+ dump_glyph(TREE_BRANCH);
+ dump_glyph(TREE_RIGHT);
+ dump_glyph(TREE_SPACE);
+ dump_glyph(TRIANGULAR_BULLET);
+ dump_glyph(BLACK_CIRCLE);
+ dump_glyph(ARROW);
+ dump_glyph(MDASH);
+ dump_glyph(ELLIPSIS);
+}
+
int main(int argc, char *argv[]) {
test_get_locales();
test_locale_is_valid();
+ test_keymaps();
+
+ dump_special_glyphs();
return 0;
}
diff --git a/src/test/test-log.c b/src/test/test-log.c
index 626d2c613..2f2e9799c 100644
--- a/src/test/test-log.c
+++ b/src/test/test-log.c
@@ -1,28 +1,13 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <stddef.h>
#include <unistd.h>
#include "format-util.h"
#include "log.h"
-#include "util.h"
+/// Additional includes needed by elogind
+#include "process-util.h"
+//#include "util.h"
assert_cc(LOG_REALM_REMOVE_LEVEL(LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, LOG_FTP | LOG_DEBUG))
== LOG_REALM_SYSTEMD);
@@ -33,30 +18,52 @@ assert_cc((LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, LOG_LOCAL3 | LOG_DEBUG) & LOG
assert_cc((LOG_REALM_PLUS_LEVEL(LOG_REALM_UDEV, LOG_USER | LOG_INFO) & LOG_PRIMASK)
== LOG_INFO);
-int main(int argc, char* argv[]) {
-
- log_set_target(LOG_TARGET_CONSOLE);
- log_open();
+#define X10(x) x x x x x x x x x x
+#define X100(x) X10(X10(x))
+#define X1000(x) X100(X10(x))
+static void test_log_console(void) {
log_struct(LOG_INFO,
- "MESSAGE=Waldo PID="PID_FMT, getpid(),
- "SERVICE=piepapo",
- NULL);
-
- log_set_target(LOG_TARGET_JOURNAL);
- log_open();
+ "MESSAGE=Waldo PID="PID_FMT, getpid_cached(),
+ "SERVICE=piepapo");
+}
+static void test_log_journal(void) {
log_struct(LOG_INFO,
- "MESSAGE=Foobar PID="PID_FMT, getpid(),
- "SERVICE=foobar",
- NULL);
+ "MESSAGE=Foobar PID="PID_FMT, getpid_cached(),
+ "SERVICE=foobar");
log_struct(LOG_INFO,
- "MESSAGE=Foobar PID="PID_FMT, getpid(),
+ "MESSAGE=Foobar PID="PID_FMT, getpid_cached(),
"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);
+ "SUFFIX=GOT IT");
+}
+
+static void test_long_lines(void) {
+ log_object_internal(LOG_NOTICE,
+ EUCLEAN,
+ X1000("abcd_") ".txt",
+ 1000000,
+ X1000("fff") "unc",
+ "OBJECT=",
+ X1000("obj_") "ect",
+ "EXTRA=",
+ X1000("ext_") "tra",
+ "asdfasdf %s asdfasdfa", "foobar");
+}
+
+int main(int argc, char* argv[]) {
+ int target;
+
+ for (target = 0; target < _LOG_TARGET_MAX; target++) {
+ log_set_target(target);
+ log_open();
+
+ test_log_console();
+ test_log_journal();
+ test_long_lines();
+ }
return 0;
}
diff --git a/src/test/test-os-util.c b/src/test/test-os-util.c
new file mode 100644
index 000000000..1e78f352a
--- /dev/null
+++ b/src/test/test-os-util.c
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+//#include <errno.h>
+
+//#include "log.h"
+//#include "os-util.h"
+
+static void test_path_is_os_tree(void) {
+ assert_se(path_is_os_tree("/") > 0);
+ assert_se(path_is_os_tree("/etc") == 0);
+ assert_se(path_is_os_tree("/idontexist") == -ENOENT);
+}
+
+int main(int argc, char *argv[]) {
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+ log_open();
+
+ test_path_is_os_tree();
+
+ return 0;
+}
diff --git a/src/test/test-parse-util.c b/src/test/test-parse-util.c
index 0175f3c19..19e1ed477 100644
--- a/src/test/test-parse-util.c
+++ b/src/test/test-parse-util.c
@@ -1,28 +1,15 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 Thomas H.P. Andersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#include <errno.h>
#include <locale.h>
#include <math.h>
+#include <sys/socket.h>
+#include "alloc-util.h"
+#include "errno-list.h"
#include "log.h"
#include "parse-util.h"
+#include "string-util.h"
static void test_parse_boolean(void) {
assert_se(parse_boolean("1") == 1);
@@ -79,6 +66,9 @@ static void test_parse_pid(void) {
r = parse_pid("junk", &pid);
assert_se(r == -EINVAL);
+
+ r = parse_pid("", &pid);
+ assert_se(r == -EINVAL);
}
static void test_parse_mode(void) {
@@ -98,6 +88,8 @@ static void test_parse_mode(void) {
static void test_parse_size(void) {
uint64_t bytes;
+ assert_se(parse_size("", 1024, &bytes) == -EINVAL);
+
assert_se(parse_size("111", 1024, &bytes) == 0);
assert_se(bytes == 111);
@@ -258,6 +250,10 @@ static void test_parse_range(void) {
assert_se(lower == 9999);
assert_se(upper == 9999);
+ assert_se(parse_range("-123", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
assert_se(parse_range("-111-123", &lower, &upper) == -EINVAL);
assert_se(lower == 9999);
assert_se(upper == 9999);
@@ -372,6 +368,15 @@ static void test_safe_atolli(void) {
r = safe_atolli("junk", &l);
assert_se(r == -EINVAL);
+
+ r = safe_atolli("123x", &l);
+ assert_se(r == -EINVAL);
+
+ r = safe_atolli("12.3", &l);
+ assert_se(r == -EINVAL);
+
+ r = safe_atolli("", &l);
+ assert_se(r == -EINVAL);
}
static void test_safe_atou16(void) {
@@ -400,6 +405,12 @@ static void test_safe_atou16(void) {
r = safe_atou16("123x", &l);
assert_se(r == -EINVAL);
+
+ r = safe_atou16("12.3", &l);
+ assert_se(r == -EINVAL);
+
+ r = safe_atou16("", &l);
+ assert_se(r == -EINVAL);
}
static void test_safe_atoi16(void) {
@@ -433,6 +444,50 @@ static void test_safe_atoi16(void) {
r = safe_atoi16("123x", &l);
assert_se(r == -EINVAL);
+
+ r = safe_atoi16("12.3", &l);
+ assert_se(r == -EINVAL);
+
+ r = safe_atoi16("", &l);
+ assert_se(r == -EINVAL);
+}
+
+static void test_safe_atoux16(void) {
+ int r;
+ uint16_t l;
+
+ r = safe_atoux16("1234", &l);
+ assert_se(r == 0);
+ assert_se(l == 0x1234);
+
+ r = safe_atoux16("abcd", &l);
+ assert_se(r == 0);
+ assert_se(l == 0xabcd);
+
+ r = safe_atoux16(" 1234", &l);
+ assert_se(r == 0);
+ assert_se(l == 0x1234);
+
+ r = safe_atoux16("12345", &l);
+ assert_se(r == -ERANGE);
+
+ r = safe_atoux16("-1", &l);
+ assert_se(r == -ERANGE);
+
+ r = safe_atoux16(" -1", &l);
+ assert_se(r == -ERANGE);
+
+ r = safe_atoux16("junk", &l);
+ assert_se(r == -EINVAL);
+
+ r = safe_atoux16("123x", &l);
+ assert_se(r == -EINVAL);
+
+ r = safe_atoux16("12.3", &l);
+ assert_se(r == -EINVAL);
+
+ r = safe_atoux16("", &l);
+ assert_se(r == -EINVAL);
}
static void test_safe_atou64(void) {
@@ -461,6 +516,12 @@ static void test_safe_atou64(void) {
r = safe_atou64("123x", &l);
assert_se(r == -EINVAL);
+
+ r = safe_atou64("12.3", &l);
+ assert_se(r == -EINVAL);
+
+ r = safe_atou64("", &l);
+ assert_se(r == -EINVAL);
}
static void test_safe_atoi64(void) {
@@ -494,6 +555,12 @@ static void test_safe_atoi64(void) {
r = safe_atoi64("123x", &l);
assert_se(r == -EINVAL);
+
+ r = safe_atoi64("12.3", &l);
+ assert_se(r == -EINVAL);
+
+ r = safe_atoi64("", &l);
+ assert_se(r == -EINVAL);
}
static void test_safe_atod(void) {
@@ -515,6 +582,9 @@ static void test_safe_atod(void) {
strtod("0,5", &e);
assert_se(*e == ',');
+ r = safe_atod("", &d);
+ assert_se(r == -EINVAL);
+
/* Check if this really is locale independent */
if (setlocale(LC_NUMERIC, "de_DE.utf8")) {
@@ -526,7 +596,13 @@ static void test_safe_atod(void) {
assert_se(r == -EINVAL);
errno = 0;
+/// elogind supports musl_libc, and their strtod doesn't seem to use the set locale.
+#if defined(__GLIBC__)
assert_se(fabs(strtod("0,5", &e) - 0.5) < 0.00001);
+#endif // __GLIBC__
+
+ r = safe_atod("", &d);
+ assert_se(r == -EINVAL);
}
/* And check again, reset */
@@ -542,6 +618,9 @@ static void test_safe_atod(void) {
errno = 0;
strtod("0,5", &e);
assert_se(*e == ',');
+
+ r = safe_atod("", &d);
+ assert_se(r == -EINVAL);
}
static void test_parse_percent(void) {
@@ -560,6 +639,7 @@ static void test_parse_percent(void) {
assert_se(parse_percent("%%") == -EINVAL);
assert_se(parse_percent("%1") == -EINVAL);
assert_se(parse_percent("1%%") == -EINVAL);
+ assert_se(parse_percent("3.2%") == -EINVAL);
}
static void test_parse_percent_unbounded(void) {
@@ -567,6 +647,54 @@ static void test_parse_percent_unbounded(void) {
assert_se(parse_percent_unbounded("400%") == 400);
}
+static void test_parse_permille(void) {
+ assert_se(parse_permille("") == -EINVAL);
+ assert_se(parse_permille("foo") == -EINVAL);
+ assert_se(parse_permille("0") == -EINVAL);
+ assert_se(parse_permille("50") == -EINVAL);
+ assert_se(parse_permille("100") == -EINVAL);
+ assert_se(parse_permille("-1") == -EINVAL);
+
+ assert_se(parse_permille("0‰") == 0);
+ assert_se(parse_permille("555‰") == 555);
+ assert_se(parse_permille("1000‰") == 1000);
+ assert_se(parse_permille("-7‰") == -ERANGE);
+ assert_se(parse_permille("1007‰") == -ERANGE);
+ assert_se(parse_permille("‰") == -EINVAL);
+ assert_se(parse_permille("‰‰") == -EINVAL);
+ assert_se(parse_permille("‰1") == -EINVAL);
+ assert_se(parse_permille("1‰‰") == -EINVAL);
+ assert_se(parse_permille("3.2‰") == -EINVAL);
+
+ assert_se(parse_permille("0%") == 0);
+ assert_se(parse_permille("55%") == 550);
+ assert_se(parse_permille("55.5%") == 555);
+ assert_se(parse_permille("100%") == 1000);
+ assert_se(parse_permille("-7%") == -ERANGE);
+ assert_se(parse_permille("107%") == -ERANGE);
+ assert_se(parse_permille("%") == -EINVAL);
+ assert_se(parse_permille("%%") == -EINVAL);
+ assert_se(parse_permille("%1") == -EINVAL);
+ assert_se(parse_permille("1%%") == -EINVAL);
+ assert_se(parse_permille("3.21%") == -EINVAL);
+}
+
+static void test_parse_permille_unbounded(void) {
+ assert_se(parse_permille_unbounded("1001‰") == 1001);
+ assert_se(parse_permille_unbounded("4000‰") == 4000);
+ assert_se(parse_permille_unbounded("2147483647‰") == 2147483647);
+ assert_se(parse_permille_unbounded("2147483648‰") == -ERANGE);
+ assert_se(parse_permille_unbounded("4294967295‰") == -ERANGE);
+ assert_se(parse_permille_unbounded("4294967296‰") == -ERANGE);
+
+ assert_se(parse_permille_unbounded("101%") == 1010);
+ assert_se(parse_permille_unbounded("400%") == 4000);
+ assert_se(parse_permille_unbounded("214748364.7%") == 2147483647);
+ assert_se(parse_permille_unbounded("214748364.8%") == -ERANGE);
+ assert_se(parse_permille_unbounded("429496729.5%") == -ERANGE);
+ assert_se(parse_permille_unbounded("429496729.6%") == -ERANGE);
+}
+
#if 0 /// UNNEEDED by elogind
static void test_parse_nice(void) {
int n;
@@ -583,7 +711,6 @@ static void test_parse_nice(void) {
assert_se(parse_nice("19", &n) >= 0 && n == 19);
assert_se(parse_nice("+19", &n) >= 0 && n == 19);
-
assert_se(parse_nice("", &n) == -EINVAL);
assert_se(parse_nice("-", &n) == -EINVAL);
assert_se(parse_nice("+", &n) == -EINVAL);
@@ -600,6 +727,8 @@ static void test_parse_nice(void) {
static void test_parse_dev(void) {
dev_t dev;
+ assert_se(parse_dev("", &dev) == -EINVAL);
+ assert_se(parse_dev("junk", &dev) == -EINVAL);
assert_se(parse_dev("0", &dev) == -EINVAL);
assert_se(parse_dev("5", &dev) == -EINVAL);
assert_se(parse_dev("5:", &dev) == -EINVAL);
@@ -610,6 +739,95 @@ static void test_parse_dev(void) {
assert_se(parse_dev("8:11", &dev) >= 0 && major(dev) == 8 && minor(dev) == 11);
}
+static void test_parse_errno(void) {
+ assert_se(parse_errno("EILSEQ") == EILSEQ);
+ assert_se(parse_errno("EINVAL") == EINVAL);
+ assert_se(parse_errno("0") == 0);
+ assert_se(parse_errno("1") == 1);
+ assert_se(parse_errno("4095") == 4095);
+
+ assert_se(parse_errno("-1") == -ERANGE);
+ assert_se(parse_errno("-3") == -ERANGE);
+ assert_se(parse_errno("4096") == -ERANGE);
+
+ assert_se(parse_errno("") == -EINVAL);
+ assert_se(parse_errno("12.3") == -EINVAL);
+ assert_se(parse_errno("123junk") == -EINVAL);
+ assert_se(parse_errno("junk123") == -EINVAL);
+ assert_se(parse_errno("255EILSEQ") == -EINVAL);
+ assert_se(parse_errno("EINVAL12") == -EINVAL);
+ assert_se(parse_errno("-EINVAL") == -EINVAL);
+ assert_se(parse_errno("EINVALaaa") == -EINVAL);
+}
+
+static void test_parse_syscall_and_errno(void) {
+ _cleanup_free_ char *n = NULL;
+ int e;
+
+ assert_se(parse_syscall_and_errno("uname:EILSEQ", &n, &e) >= 0);
+ assert_se(streq(n, "uname"));
+ assert_se(e == errno_from_name("EILSEQ") && e >= 0);
+ n = mfree(n);
+
+ assert_se(parse_syscall_and_errno("uname:EINVAL", &n, &e) >= 0);
+ assert_se(streq(n, "uname"));
+ assert_se(e == errno_from_name("EINVAL") && e >= 0);
+ n = mfree(n);
+
+ assert_se(parse_syscall_and_errno("@sync:4095", &n, &e) >= 0);
+ assert_se(streq(n, "@sync"));
+ assert_se(e == 4095);
+ n = mfree(n);
+
+ /* If errno is omitted, then e is set to -1 */
+ assert_se(parse_syscall_and_errno("mount", &n, &e) >= 0);
+ assert_se(streq(n, "mount"));
+ assert_se(e == -1);
+ n = mfree(n);
+
+ /* parse_syscall_and_errno() does not check the syscall name is valid or not. */
+ assert_se(parse_syscall_and_errno("hoge:255", &n, &e) >= 0);
+ assert_se(streq(n, "hoge"));
+ assert_se(e == 255);
+ n = mfree(n);
+
+ /* The function checks the syscall name is empty or not. */
+ assert_se(parse_syscall_and_errno("", &n, &e) == -EINVAL);
+ assert_se(parse_syscall_and_errno(":255", &n, &e) == -EINVAL);
+
+ /* errno must be a valid errno name or number between 0 and ERRNO_MAX == 4095 */
+ assert_se(parse_syscall_and_errno("hoge:4096", &n, &e) == -ERANGE);
+ assert_se(parse_syscall_and_errno("hoge:-3", &n, &e) == -ERANGE);
+ assert_se(parse_syscall_and_errno("hoge:12.3", &n, &e) == -EINVAL);
+ assert_se(parse_syscall_and_errno("hoge:123junk", &n, &e) == -EINVAL);
+ assert_se(parse_syscall_and_errno("hoge:junk123", &n, &e) == -EINVAL);
+ assert_se(parse_syscall_and_errno("hoge:255:EILSEQ", &n, &e) == -EINVAL);
+ assert_se(parse_syscall_and_errno("hoge:-EINVAL", &n, &e) == -EINVAL);
+ assert_se(parse_syscall_and_errno("hoge:EINVALaaa", &n, &e) == -EINVAL);
+ assert_se(parse_syscall_and_errno("hoge:", &n, &e) == -EINVAL);
+}
+
+static void test_parse_mtu(void) {
+ uint32_t mtu = 0;
+
+ assert_se(parse_mtu(AF_UNSPEC, "1500", &mtu) >= 0 && mtu == 1500);
+ assert_se(parse_mtu(AF_UNSPEC, "1400", &mtu) >= 0 && mtu == 1400);
+ assert_se(parse_mtu(AF_UNSPEC, "65535", &mtu) >= 0 && mtu == 65535);
+ assert_se(parse_mtu(AF_UNSPEC, "65536", &mtu) >= 0 && mtu == 65536);
+ assert_se(parse_mtu(AF_UNSPEC, "4294967295", &mtu) >= 0 && mtu == 4294967295);
+ assert_se(parse_mtu(AF_UNSPEC, "500", &mtu) >= 0 && mtu == 500);
+ assert_se(parse_mtu(AF_UNSPEC, "1280", &mtu) >= 0 && mtu == 1280);
+ assert_se(parse_mtu(AF_INET6, "1280", &mtu) >= 0 && mtu == 1280);
+ assert_se(parse_mtu(AF_INET6, "1279", &mtu) == -ERANGE);
+ assert_se(parse_mtu(AF_UNSPEC, "4294967296", &mtu) == -ERANGE);
+ assert_se(parse_mtu(AF_INET6, "4294967296", &mtu) == -ERANGE);
+ assert_se(parse_mtu(AF_INET6, "68", &mtu) == -ERANGE);
+ assert_se(parse_mtu(AF_UNSPEC, "68", &mtu) >= 0 && mtu == 68);
+ assert_se(parse_mtu(AF_UNSPEC, "67", &mtu) == -ERANGE);
+ assert_se(parse_mtu(AF_UNSPEC, "0", &mtu) == -ERANGE);
+ assert_se(parse_mtu(AF_UNSPEC, "", &mtu) == -EINVAL);
+}
+
int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
@@ -624,15 +842,21 @@ int main(int argc, char *argv[]) {
test_safe_atolli();
test_safe_atou16();
test_safe_atoi16();
+ test_safe_atoux16();
test_safe_atou64();
test_safe_atoi64();
test_safe_atod();
test_parse_percent();
test_parse_percent_unbounded();
+ test_parse_permille();
+ test_parse_permille_unbounded();
#if 0 /// UNNEEDED by elogind
test_parse_nice();
#endif // 0
test_parse_dev();
+ test_parse_errno();
+ test_parse_syscall_and_errno();
+ test_parse_mtu();
return 0;
}
diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
index 64f37a2cf..1b1d4c7e7 100644
--- a/src/test/test-path-util.c
+++ b/src/test/test-path-util.c
@@ -1,24 +1,6 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <stdio.h>
-#include <sys/mount.h>
#include <unistd.h>
#include "alloc-util.h"
@@ -39,6 +21,16 @@
assert_se(path_equal(b, a) == !result); \
}
+static void test_path_simplify(const char *in, const char *out, const char *out_dot) {
+ char *p;
+
+ p = strdupa(in);
+ assert_se(streq(path_simplify(p, false), out));
+
+ p = strdupa(in);
+ assert_se(streq(path_simplify(p, true), out_dot));
+}
+
static void test_path(void) {
_cleanup_close_ int fd = -1;
@@ -82,15 +74,28 @@ static void test_path(void) {
assert_se(fd >= 0);
assert_se(fd_is_mount_point(fd, "/", 0) > 0);
- {
- char p1[] = "aaa/bbb////ccc";
- char p2[] = "//aaa/.////ccc";
- char p3[] = "/./";
-
- assert_se(path_equal(path_kill_slashes(p1), "aaa/bbb/ccc"));
- assert_se(path_equal(path_kill_slashes(p2), "/aaa/./ccc"));
- assert_se(path_equal(path_kill_slashes(p3), "/./"));
- }
+ test_path_simplify("aaa/bbb////ccc", "aaa/bbb/ccc", "aaa/bbb/ccc");
+ test_path_simplify("//aaa/.////ccc", "/aaa/./ccc", "/aaa/ccc");
+ test_path_simplify("///", "/", "/");
+ test_path_simplify("///.//", "/.", "/");
+ test_path_simplify("///.//.///", "/./.", "/");
+ test_path_simplify("////.././///../.", "/.././../.", "/../..");
+ test_path_simplify(".", ".", "");
+ test_path_simplify("./", ".", "");
+ test_path_simplify(".///.//./.", "./././.", "");
+ test_path_simplify(".///.//././/", "./././.", "");
+ test_path_simplify("//./aaa///.//./.bbb/..///c.//d.dd///..eeee/.",
+ "/./aaa/././.bbb/../c./d.dd/..eeee/.",
+ "/aaa/.bbb/../c./d.dd/..eeee");
+ test_path_simplify("//./aaa///.//./.bbb/..///c.//d.dd///..eeee/..",
+ "/./aaa/././.bbb/../c./d.dd/..eeee/..",
+ "/aaa/.bbb/../c./d.dd/..eeee/..");
+ test_path_simplify(".//./aaa///.//./.bbb/..///c.//d.dd///..eeee/..",
+ "././aaa/././.bbb/../c./d.dd/..eeee/..",
+ "aaa/.bbb/../c./d.dd/..eeee/..");
+ test_path_simplify("..//./aaa///.//./.bbb/..///c.//d.dd///..eeee/..",
+ ".././aaa/././.bbb/../c./d.dd/..eeee/..",
+ "../aaa/.bbb/../c./d.dd/..eeee/..");
assert_se(PATH_IN_SET("/bin", "/", "/bin", "/foo"));
assert_se(PATH_IN_SET("/bin", "/bin"));
@@ -262,6 +267,7 @@ static void test_make_relative(void) {
assert_se(path_make_relative("some/relative/path", "/some/path", &result) < 0);
assert_se(path_make_relative("/some/path", "some/relative/path", &result) < 0);
+ assert_se(path_make_relative("/some/dotdot/../path", "/some/path", &result) < 0);
#define test(from_dir, to_path, expected) { \
_cleanup_free_ char *z = NULL; \
@@ -275,7 +281,8 @@ static void test_make_relative(void) {
test("/some/path", "/some/path/in/subdir", "in/subdir");
test("/some/path", "/", "../..");
test("/some/path", "/some/other/path", "../other/path");
- test("//extra/////slashes///won't////fool///anybody//", "////extra///slashes////are/just///fine///", "../../../are/just/fine");
+ test("/some/path/./dot", "/some/further/path", "../../further/path");
+ test("//extra.//.//./.slashes//./won't////fo.ol///anybody//", "/././/extra././/.slashes////ar.e/.just/././.fine///", "../../../ar.e/.just/.fine");
}
#endif // 0
@@ -375,143 +382,6 @@ static void test_prefix_root(void) {
test_prefix_root_one("/foo///", "//bar", "/foo/bar");
}
-static void test_path_is_mount_point(void) {
- int fd;
- char tmp_dir[] = "/tmp/test-path-is-mount-point-XXXXXX";
- _cleanup_free_ char *file1 = NULL, *file2 = NULL, *link1 = NULL, *link2 = NULL;
- _cleanup_free_ char *dir1 = NULL, *dir1file = NULL, *dirlink1 = NULL, *dirlink1file = NULL;
- _cleanup_free_ char *dir2 = NULL, *dir2file = NULL;
-
- assert_se(path_is_mount_point("/", NULL, AT_SYMLINK_FOLLOW) > 0);
- assert_se(path_is_mount_point("/", NULL, 0) > 0);
-
- assert_se(path_is_mount_point("/proc", NULL, AT_SYMLINK_FOLLOW) > 0);
- assert_se(path_is_mount_point("/proc", NULL, 0) > 0);
-
- assert_se(path_is_mount_point("/proc/1", NULL, AT_SYMLINK_FOLLOW) == 0);
- assert_se(path_is_mount_point("/proc/1", NULL, 0) == 0);
-
- assert_se(path_is_mount_point("/sys", NULL, AT_SYMLINK_FOLLOW) > 0);
- assert_se(path_is_mount_point("/sys", NULL, 0) > 0);
-
- /* we'll create a hierarchy of different kinds of dir/file/link
- * layouts:
- *
- * <tmp>/file1, <tmp>/file2
- * <tmp>/link1 -> file1, <tmp>/link2 -> file2
- * <tmp>/dir1/
- * <tmp>/dir1/file
- * <tmp>/dirlink1 -> dir1
- * <tmp>/dirlink1file -> dirlink1/file
- * <tmp>/dir2/
- * <tmp>/dir2/file
- */
-
- /* file mountpoints */
- assert_se(mkdtemp(tmp_dir) != NULL);
- file1 = path_join(NULL, tmp_dir, "file1");
- assert_se(file1);
- file2 = path_join(NULL, tmp_dir, "file2");
- assert_se(file2);
- fd = open(file1, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664);
- assert_se(fd > 0);
- close(fd);
- fd = open(file2, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664);
- assert_se(fd > 0);
- close(fd);
- link1 = path_join(NULL, tmp_dir, "link1");
- assert_se(link1);
- assert_se(symlink("file1", link1) == 0);
- link2 = path_join(NULL, tmp_dir, "link2");
- assert_se(link1);
- assert_se(symlink("file2", link2) == 0);
-
- assert_se(path_is_mount_point(file1, NULL, AT_SYMLINK_FOLLOW) == 0);
- assert_se(path_is_mount_point(file1, NULL, 0) == 0);
- assert_se(path_is_mount_point(link1, NULL, AT_SYMLINK_FOLLOW) == 0);
- assert_se(path_is_mount_point(link1, NULL, 0) == 0);
-
- /* directory mountpoints */
- dir1 = path_join(NULL, tmp_dir, "dir1");
- assert_se(dir1);
- assert_se(mkdir(dir1, 0755) == 0);
- dirlink1 = path_join(NULL, tmp_dir, "dirlink1");
- assert_se(dirlink1);
- assert_se(symlink("dir1", dirlink1) == 0);
- dirlink1file = path_join(NULL, tmp_dir, "dirlink1file");
- assert_se(dirlink1file);
- assert_se(symlink("dirlink1/file", dirlink1file) == 0);
- dir2 = path_join(NULL, tmp_dir, "dir2");
- assert_se(dir2);
- assert_se(mkdir(dir2, 0755) == 0);
-
- assert_se(path_is_mount_point(dir1, NULL, AT_SYMLINK_FOLLOW) == 0);
- assert_se(path_is_mount_point(dir1, NULL, 0) == 0);
- assert_se(path_is_mount_point(dirlink1, NULL, AT_SYMLINK_FOLLOW) == 0);
- assert_se(path_is_mount_point(dirlink1, NULL, 0) == 0);
-
- /* file in subdirectory mountpoints */
- dir1file = path_join(NULL, dir1, "file");
- assert_se(dir1file);
- fd = open(dir1file, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664);
- assert_se(fd > 0);
- close(fd);
-
- assert_se(path_is_mount_point(dir1file, NULL, AT_SYMLINK_FOLLOW) == 0);
- assert_se(path_is_mount_point(dir1file, NULL, 0) == 0);
- assert_se(path_is_mount_point(dirlink1file, NULL, AT_SYMLINK_FOLLOW) == 0);
- assert_se(path_is_mount_point(dirlink1file, NULL, 0) == 0);
-
- /* these tests will only work as root */
- if (mount(file1, file2, NULL, MS_BIND, NULL) >= 0) {
- int rt, rf, rlt, rlf, rl1t, rl1f;
-
- /* files */
- /* capture results in vars, to avoid dangling mounts on failure */
- rf = path_is_mount_point(file2, NULL, 0);
- rt = path_is_mount_point(file2, NULL, AT_SYMLINK_FOLLOW);
- rlf = path_is_mount_point(link2, NULL, 0);
- rlt = path_is_mount_point(link2, NULL, AT_SYMLINK_FOLLOW);
-
- assert_se(umount(file2) == 0);
-
- assert_se(rf == 1);
- assert_se(rt == 1);
- assert_se(rlf == 0);
- assert_se(rlt == 1);
-
- /* dirs */
- dir2file = path_join(NULL, dir2, "file");
- assert_se(dir2file);
- fd = open(dir2file, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664);
- assert_se(fd > 0);
- close(fd);
-
- assert_se(mount(dir2, dir1, NULL, MS_BIND, NULL) >= 0);
-
- rf = path_is_mount_point(dir1, NULL, 0);
- rt = path_is_mount_point(dir1, NULL, AT_SYMLINK_FOLLOW);
- rlf = path_is_mount_point(dirlink1, NULL, 0);
- rlt = path_is_mount_point(dirlink1, NULL, AT_SYMLINK_FOLLOW);
- /* its parent is a mount point, but not /file itself */
- rl1f = path_is_mount_point(dirlink1file, NULL, 0);
- rl1t = path_is_mount_point(dirlink1file, NULL, AT_SYMLINK_FOLLOW);
-
- assert_se(umount(dir1) == 0);
-
- assert_se(rf == 1);
- assert_se(rt == 1);
- assert_se(rlf == 0);
- assert_se(rlt == 1);
- assert_se(rl1f == 0);
- assert_se(rl1t == 0);
-
- } else
- printf("Skipping bind mount file test: %m\n");
-
- assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
-}
-
static void test_file_in_same_dir(void) {
char *t;
@@ -536,6 +406,25 @@ static void test_file_in_same_dir(void) {
free(t);
}
+static void test_last_path_component(void) {
+ assert_se(streq(last_path_component("a/b/c"), "c"));
+ assert_se(streq(last_path_component("a/b/c/"), "c/"));
+ assert_se(streq(last_path_component("/"), "/"));
+ assert_se(streq(last_path_component("//"), "/"));
+ assert_se(streq(last_path_component("///"), "/"));
+ assert_se(streq(last_path_component("."), "."));
+ assert_se(streq(last_path_component("./."), "."));
+ assert_se(streq(last_path_component("././"), "./"));
+ assert_se(streq(last_path_component("././/"), ".//"));
+ assert_se(streq(last_path_component("/foo/a"), "a"));
+ assert_se(streq(last_path_component("/foo/a/"), "a/"));
+ assert_se(streq(last_path_component(""), ""));
+ assert_se(streq(last_path_component("a"), "a"));
+ assert_se(streq(last_path_component("a/"), "a/"));
+ assert_se(streq(last_path_component("/a"), "a"));
+ assert_se(streq(last_path_component("/a/"), "a/"));
+}
+
static void test_filename_is_valid(void) {
char foo[FILENAME_MAX+2];
int i;
@@ -592,6 +481,34 @@ static void test_systemd_installation_has_version(const char *path) {
}
#endif // 0
+static void test_skip_dev_prefix(void) {
+
+ assert_se(streq(skip_dev_prefix("/"), "/"));
+ assert_se(streq(skip_dev_prefix("/dev"), ""));
+ assert_se(streq(skip_dev_prefix("/dev/"), ""));
+ assert_se(streq(skip_dev_prefix("/dev/foo"), "foo"));
+ assert_se(streq(skip_dev_prefix("/dev/foo/bar"), "foo/bar"));
+ assert_se(streq(skip_dev_prefix("//dev"), ""));
+ assert_se(streq(skip_dev_prefix("//dev//"), ""));
+ assert_se(streq(skip_dev_prefix("/dev///foo"), "foo"));
+ assert_se(streq(skip_dev_prefix("///dev///foo///bar"), "foo///bar"));
+ assert_se(streq(skip_dev_prefix("//foo"), "//foo"));
+ assert_se(streq(skip_dev_prefix("foo"), "foo"));
+}
+
+static void test_empty_or_root(void) {
+ assert_se(empty_or_root(NULL));
+ assert_se(empty_or_root(""));
+ assert_se(empty_or_root("/"));
+ assert_se(empty_or_root("//"));
+ assert_se(empty_or_root("///"));
+ assert_se(empty_or_root("/////////////////"));
+ assert_se(!empty_or_root("xxx"));
+ assert_se(!empty_or_root("/xxx"));
+ assert_se(!empty_or_root("/xxx/"));
+ assert_se(!empty_or_root("//yy//"));
+}
+
int main(int argc, char **argv) {
log_set_max_level(LOG_DEBUG);
log_parse_environment();
@@ -609,10 +526,12 @@ int main(int argc, char **argv) {
test_strv_resolve();
test_path_startswith();
test_prefix_root();
- test_path_is_mount_point();
test_file_in_same_dir();
+ test_last_path_component();
test_filename_is_valid();
test_hidden_or_backup_file();
+ test_skip_dev_prefix();
+ test_empty_or_root();
#if 0 /// UNNEEDED by elogind
test_systemd_installation_has_version(argv[1]); /* NULL is OK */
diff --git a/src/test/test-prioq.c b/src/test/test-prioq.c
index d81880a65..89c41d8ce 100644
--- a/src/test/test-prioq.c
+++ b/src/test/test-prioq.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <stdlib.h>
diff --git a/src/test/test-proc-cmdline.c b/src/test/test-proc-cmdline.c
index 59dcf4071..275c377cc 100644
--- a/src/test/test-proc-cmdline.c
+++ b/src/test/test-proc-cmdline.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include "alloc-util.h"
#include "log.h"
diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c
index 07c0704ef..f19875dae 100644
--- a/src/test/test-process-util.c
+++ b/src/test/test-process-util.c
@@ -1,22 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 Thomas H.P. Andersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <sched.h>
#include <sys/mount.h>
@@ -26,7 +8,7 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
-#ifdef HAVE_VALGRIND_VALGRIND_H
+#if HAVE_VALGRIND_VALGRIND_H
#include <valgrind/valgrind.h>
#endif
@@ -37,6 +19,7 @@
#include "macro.h"
#include "parse-util.h"
#include "process-util.h"
+#include "signal-util.h"
#include "stdio-util.h"
#include "string-util.h"
#include "terminal-util.h"
@@ -48,7 +31,7 @@ static void test_get_process_comm(pid_t pid) {
struct stat st;
_cleanup_free_ char *a = NULL, *c = NULL, *d = NULL, *f = NULL, *i = NULL;
_cleanup_free_ char *env = NULL;
- char path[strlen("/proc//comm") + DECIMAL_STR_MAX(pid_t)];
+ char path[STRLEN("/proc//comm") + DECIMAL_STR_MAX(pid_t)];
#if 0 /// UNNEEDED by elogind
pid_t e;
uid_t u;
@@ -104,10 +87,42 @@ static void test_get_process_comm(pid_t pid) {
if (!detect_container())
assert_se(get_ctty_devnr(pid, &h) == -ENXIO || pid != 1);
- getenv_for_pid(pid, "PATH", &i);
+ (void) getenv_for_pid(pid, "PATH", &i);
log_info("PID"PID_FMT" $PATH: '%s'", pid, strna(i));
}
+static void test_get_process_comm_escape_one(const char *input, const char *output) {
+ _cleanup_free_ char *n = NULL;
+
+ log_info("input: <%s> — output: <%s>", input, output);
+
+ assert_se(prctl(PR_SET_NAME, input) >= 0);
+ assert_se(get_process_comm(0, &n) >= 0);
+
+ log_info("got: <%s>", n);
+
+ assert_se(streq_ptr(n, output));
+}
+
+static void test_get_process_comm_escape(void) {
+ _cleanup_free_ char *saved = NULL;
+
+ assert_se(get_process_comm(0, &saved) >= 0);
+
+ test_get_process_comm_escape_one("", "");
+ test_get_process_comm_escape_one("foo", "foo");
+ test_get_process_comm_escape_one("012345678901234", "012345678901234");
+ test_get_process_comm_escape_one("0123456789012345", "012345678901234");
+ test_get_process_comm_escape_one("äöüß", "\\303\\244\\303…");
+ test_get_process_comm_escape_one("xäöüß", "x\\303\\244…");
+ test_get_process_comm_escape_one("xxäöüß", "xx\\303\\244…");
+ test_get_process_comm_escape_one("xxxäöüß", "xxx\\303\\244…");
+ test_get_process_comm_escape_one("xxxxäöüß", "xxxx\\303\\244…");
+ test_get_process_comm_escape_one("xxxxxäöüß", "xxxxx\\303…");
+
+ assert_se(prctl(PR_SET_NAME, saved) >= 0);
+}
+
static void test_pid_is_unwaited(void) {
pid_t pid;
@@ -121,7 +136,7 @@ static void test_pid_is_unwaited(void) {
waitpid(pid, &status, 0);
assert_se(!pid_is_unwaited(pid));
}
- assert_se(pid_is_unwaited(getpid()));
+ assert_se(pid_is_unwaited(getpid_cached()));
assert_se(!pid_is_unwaited(-1));
}
@@ -138,7 +153,7 @@ static void test_pid_is_alive(void) {
waitpid(pid, &status, 0);
assert_se(!pid_is_alive(pid));
}
- assert_se(pid_is_alive(getpid()));
+ assert_se(pid_is_alive(getpid_cached()));
assert_se(!pid_is_alive(-1));
}
@@ -176,7 +191,7 @@ static void test_get_process_cmdline_harder(void) {
if (geteuid() != 0)
return;
-#ifdef HAVE_VALGRIND_VALGRIND_H
+#if HAVE_VALGRIND_VALGRIND_H
/* valgrind patches open(/proc//cmdline)
* so, test_get_process_cmdline_harder fails always
* See https://github.com/systemd/systemd/pull/3555#issuecomment-226564908 */
@@ -199,6 +214,8 @@ static void test_get_process_cmdline_harder(void) {
assert_se(pid == 0);
assert_se(unshare(CLONE_NEWNS) >= 0);
+ assert_se(mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) >= 0);
+
fd = mkostemp(path, O_CLOEXEC);
assert_se(fd >= 0);
@@ -213,201 +230,231 @@ static void test_get_process_cmdline_harder(void) {
assert_se(prctl(PR_SET_NAME, "testa") >= 0);
- assert_se(get_process_cmdline(getpid(), 0, false, &line) == -ENOENT);
+ assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) == -ENOENT);
- assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
assert_se(streq(line, "[testa]"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 1, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 1, true, &line) >= 0);
assert_se(streq(line, ""));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 2, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 2, true, &line) >= 0);
assert_se(streq(line, "["));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 3, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 3, true, &line) >= 0);
assert_se(streq(line, "[."));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 4, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 4, true, &line) >= 0);
assert_se(streq(line, "[.."));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 5, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 5, true, &line) >= 0);
assert_se(streq(line, "[..."));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 6, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 6, true, &line) >= 0);
assert_se(streq(line, "[...]"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 7, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 7, true, &line) >= 0);
assert_se(streq(line, "[t...]"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 8, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 8, true, &line) >= 0);
assert_se(streq(line, "[testa]"));
line = mfree(line);
assert_se(write(fd, "\0\0\0\0\0\0\0\0\0", 10) == 10);
- assert_se(get_process_cmdline(getpid(), 0, false, &line) == -ENOENT);
+ assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) == -ENOENT);
- assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
assert_se(streq(line, "[testa]"));
line = mfree(line);
assert_se(write(fd, "foo\0bar\0\0\0\0\0", 10) == 10);
- assert_se(get_process_cmdline(getpid(), 0, false, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) >= 0);
assert_se(streq(line, "foo bar"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
assert_se(streq(line, "foo bar"));
line = mfree(line);
assert_se(write(fd, "quux", 4) == 4);
- assert_se(get_process_cmdline(getpid(), 0, false, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) >= 0);
assert_se(streq(line, "foo bar quux"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
assert_se(streq(line, "foo bar quux"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 1, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 1, true, &line) >= 0);
assert_se(streq(line, ""));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 2, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 2, true, &line) >= 0);
assert_se(streq(line, "."));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 3, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 3, true, &line) >= 0);
assert_se(streq(line, ".."));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 4, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 4, true, &line) >= 0);
assert_se(streq(line, "..."));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 5, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 5, true, &line) >= 0);
assert_se(streq(line, "f..."));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 6, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 6, true, &line) >= 0);
assert_se(streq(line, "fo..."));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 7, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 7, true, &line) >= 0);
assert_se(streq(line, "foo..."));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 8, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 8, true, &line) >= 0);
assert_se(streq(line, "foo..."));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 9, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 9, true, &line) >= 0);
assert_se(streq(line, "foo b..."));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 10, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 10, true, &line) >= 0);
assert_se(streq(line, "foo ba..."));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 11, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 11, true, &line) >= 0);
assert_se(streq(line, "foo bar..."));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 12, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 12, true, &line) >= 0);
assert_se(streq(line, "foo bar..."));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 13, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 13, true, &line) >= 0);
assert_se(streq(line, "foo bar quux"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 14, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 14, true, &line) >= 0);
assert_se(streq(line, "foo bar quux"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 1000, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 1000, true, &line) >= 0);
assert_se(streq(line, "foo bar quux"));
line = mfree(line);
assert_se(ftruncate(fd, 0) >= 0);
assert_se(prctl(PR_SET_NAME, "aaaa bbbb cccc") >= 0);
- assert_se(get_process_cmdline(getpid(), 0, false, &line) == -ENOENT);
+ assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) == -ENOENT);
- assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
assert_se(streq(line, "[aaaa bbbb cccc]"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 10, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 10, true, &line) >= 0);
assert_se(streq(line, "[aaaa...]"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 11, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 11, true, &line) >= 0);
assert_se(streq(line, "[aaaa...]"));
line = mfree(line);
- assert_se(get_process_cmdline(getpid(), 12, true, &line) >= 0);
+ assert_se(get_process_cmdline(getpid_cached(), 12, true, &line) >= 0);
assert_se(streq(line, "[aaaa b...]"));
line = mfree(line);
safe_close(fd);
- _exit(0);
+ _exit(EXIT_SUCCESS);
}
#if 0 /// UNNEEDED by elogind
-static void test_rename_process_one(const char *p, int ret) {
+static void test_rename_process_now(const char *p, int ret) {
_cleanup_free_ char *comm = NULL, *cmdline = NULL;
- pid_t pid;
int r;
- pid = fork();
- assert_se(pid >= 0);
-
- if (pid > 0) {
- siginfo_t si;
-
- assert_se(wait_for_terminate(pid, &si) >= 0);
- assert_se(si.si_code == CLD_EXITED);
- assert_se(si.si_status == EXIT_SUCCESS);
-
- return;
- }
-
- /* child */
r = rename_process(p);
-
assert_se(r == ret ||
(ret == 0 && r >= 0) ||
(ret > 0 && r > 0));
if (r < 0)
- goto finish;
+ return;
-#ifdef HAVE_VALGRIND_VALGRIND_H
+#if HAVE_VALGRIND_VALGRIND_H
/* see above, valgrind is weird, we can't verify what we are doing here */
if (RUNNING_ON_VALGRIND)
- goto finish;
+ return;
#endif
assert_se(get_process_comm(0, &comm) >= 0);
log_info("comm = <%s>", comm);
- assert_se(strneq(comm, p, 15));
+ assert_se(strneq(comm, p, TASK_COMM_LEN-1));
assert_se(get_process_cmdline(0, 0, false, &cmdline) >= 0);
- log_info("cmdline = <%s>", cmdline);
- assert_se(strneq(p, cmdline, strlen("test-process-util")));
- assert_se(startswith(p, cmdline));
+ /* we cannot expect cmdline to be renamed properly without privileges */
+ if (geteuid() == 0) {
+ log_info("cmdline = <%s>", cmdline);
+ assert_se(strneq(p, cmdline, STRLEN("test-process-util")));
+ assert_se(startswith(p, cmdline));
+ } else
+ log_info("cmdline = <%s> (not verified)", cmdline);
+}
+
+static void test_rename_process_one(const char *p, int ret) {
+ siginfo_t si;
+ pid_t pid;
+
+ pid = fork();
+ assert_se(pid >= 0);
+
+ if (pid == 0) {
+ /* child */
+ test_rename_process_now(p, ret);
+ _exit(EXIT_SUCCESS);
+ }
+
+ assert_se(wait_for_terminate(pid, &si) >= 0);
+ assert_se(si.si_code == CLD_EXITED);
+ assert_se(si.si_status == EXIT_SUCCESS);
+}
+
+static void test_rename_process_multi(void) {
+ pid_t pid;
+
+ pid = fork();
+ assert_se(pid >= 0);
+
+ if (pid > 0) {
+ siginfo_t si;
+
+ assert_se(wait_for_terminate(pid, &si) >= 0);
+ assert_se(si.si_code == CLD_EXITED);
+ assert_se(si.si_status == EXIT_SUCCESS);
+
+ return;
+ }
-finish:
+ /* child */
+ test_rename_process_now("one", 1);
+ test_rename_process_now("more", 0); /* longer than "one", hence truncated */
+ (void) setresuid(99, 99, 99); /* change uid when running privileged */
+ test_rename_process_now("time!", 0);
+ test_rename_process_now("0", 1); /* shorter than "one", should fit */
+ test_rename_process_one("", -EINVAL);
+ test_rename_process_one(NULL, -EINVAL);
_exit(EXIT_SUCCESS);
}
@@ -417,11 +464,135 @@ static void test_rename_process(void) {
test_rename_process_one("foo", 1); /* should always fit */
test_rename_process_one("this is a really really long process name, followed by some more words", 0); /* unlikely to fit */
test_rename_process_one("1234567", 1); /* should always fit */
+ test_rename_process_multi(); /* multiple invocations and dropped privileges */
}
#endif // 0
-int main(int argc, char *argv[]) {
+static void test_getpid_cached(void) {
+ siginfo_t si;
+ pid_t a, b, c, d, e, f, child;
+
+ a = raw_getpid();
+ b = getpid_cached();
+ c = getpid();
+
+ assert_se(a == b && a == c);
+
+ child = fork();
+ assert_se(child >= 0);
+ if (child == 0) {
+ /* In child */
+ a = raw_getpid();
+ b = getpid_cached();
+ c = getpid();
+
+ assert_se(a == b && a == c);
+ _exit(EXIT_SUCCESS);
+ }
+
+ d = raw_getpid();
+ e = getpid_cached();
+ f = getpid();
+
+ assert_se(a == d && a == e && a == f);
+
+ assert_se(wait_for_terminate(child, &si) >= 0);
+ assert_se(si.si_status == 0);
+ assert_se(si.si_code == CLD_EXITED);
+}
+
+#define MEASURE_ITERATIONS (10000000LLU)
+
+static void test_getpid_measure(void) {
+ unsigned long long i;
+ usec_t t, q;
+
+ t = now(CLOCK_MONOTONIC);
+ for (i = 0; i < MEASURE_ITERATIONS; i++)
+ (void) getpid();
+ q = now(CLOCK_MONOTONIC) - t;
+
+ log_info(" glibc getpid(): %llu/s\n", (unsigned long long) (MEASURE_ITERATIONS*USEC_PER_SEC/q));
+
+ t = now(CLOCK_MONOTONIC);
+ for (i = 0; i < MEASURE_ITERATIONS; i++)
+ (void) getpid_cached();
+ q = now(CLOCK_MONOTONIC) - t;
+
+ log_info("getpid_cached(): %llu/s\n", (unsigned long long) (MEASURE_ITERATIONS*USEC_PER_SEC/q));
+}
+
+static void test_safe_fork(void) {
+ siginfo_t status;
+ pid_t pid;
+ int r;
+
+ BLOCK_SIGNALS(SIGCHLD);
+
+ r = safe_fork("(test-child)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_NULL_STDIO|FORK_REOPEN_LOG, &pid);
+ assert_se(r >= 0);
+
+ if (r == 0) {
+ /* child */
+ usleep(100 * USEC_PER_MSEC);
+
+ _exit(88);
+ }
+
+ assert_se(wait_for_terminate(pid, &status) >= 0);
+ assert_se(status.si_code == CLD_EXITED);
+ assert_se(status.si_status == 88);
+}
+
+static void test_pid_to_ptr(void) {
+
+ assert_se(PTR_TO_PID(NULL) == 0);
+ assert_se(PID_TO_PTR(0) == NULL);
+
+ assert_se(PTR_TO_PID(PID_TO_PTR(1)) == 1);
+ assert_se(PTR_TO_PID(PID_TO_PTR(2)) == 2);
+ assert_se(PTR_TO_PID(PID_TO_PTR(-1)) == -1);
+ assert_se(PTR_TO_PID(PID_TO_PTR(-2)) == -2);
+
+ assert_se(PTR_TO_PID(PID_TO_PTR(INT16_MAX)) == INT16_MAX);
+ assert_se(PTR_TO_PID(PID_TO_PTR(INT16_MIN)) == INT16_MIN);
+
+#if SIZEOF_PID_T >= 4
+ assert_se(PTR_TO_PID(PID_TO_PTR(INT32_MAX)) == INT32_MAX);
+ assert_se(PTR_TO_PID(PID_TO_PTR(INT32_MIN)) == INT32_MIN);
+#endif
+}
+
+#if 0 /// UNNEEDED by elogind
+static void test_ioprio_class_from_to_string_one(const char *val, int expected) {
+ assert_se(ioprio_class_from_string(val) == expected);
+ if (expected >= 0) {
+ _cleanup_free_ char *s = NULL;
+ unsigned ret;
+
+ assert_se(ioprio_class_to_string_alloc(expected, &s) == 0);
+ /* We sometimes get a class number and sometimes a number back */
+ assert_se(streq(s, val) ||
+ safe_atou(val, &ret) == 0);
+ }
+}
+
+static void test_ioprio_class_from_to_string(void) {
+ test_ioprio_class_from_to_string_one("none", IOPRIO_CLASS_NONE);
+ test_ioprio_class_from_to_string_one("realtime", IOPRIO_CLASS_RT);
+ test_ioprio_class_from_to_string_one("best-effort", IOPRIO_CLASS_BE);
+ test_ioprio_class_from_to_string_one("idle", IOPRIO_CLASS_IDLE);
+ test_ioprio_class_from_to_string_one("0", 0);
+ test_ioprio_class_from_to_string_one("1", 1);
+ test_ioprio_class_from_to_string_one("7", 7);
+ test_ioprio_class_from_to_string_one("8", 8);
+ test_ioprio_class_from_to_string_one("9", -1);
+ test_ioprio_class_from_to_string_one("-1", -1);
+}
+#endif // 0
+
+int main(int argc, char *argv[]) {
log_set_max_level(LOG_DEBUG);
log_parse_environment();
log_open();
@@ -439,6 +610,7 @@ int main(int argc, char *argv[]) {
test_get_process_comm(getpid());
}
+ test_get_process_comm_escape();
test_pid_is_unwaited();
test_pid_is_alive();
#if 0 /// UNNEEDED by elogind
@@ -448,6 +620,13 @@ int main(int argc, char *argv[]) {
#if 0 /// UNNEEDED by elogind
test_rename_process();
#endif // 0
+ test_getpid_cached();
+ test_getpid_measure();
+ test_safe_fork();
+ test_pid_to_ptr();
+#if 0 /// UNNEEDED by elogind
+ test_ioprio_class_from_to_string();
+#endif // 0
return 0;
}
diff --git a/src/test/test-procfs-util.c b/src/test/test-procfs-util.c
new file mode 100644
index 000000000..35381f264
--- /dev/null
+++ b/src/test/test-procfs-util.c
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <errno.h>
+
+#include "log.h"
+#include "parse-util.h"
+#include "procfs-util.h"
+
+int main(int argc, char *argv[]) {
+#if 0 /// elogind only needs v
+ char buf[CONST_MAX(FORMAT_TIMESPAN_MAX, FORMAT_BYTES_MAX)];
+ nsec_t nsec;
+ uint64_t v;
+ int r;
+#else
+ uint64_t v;
+#endif // 0
+
+ log_parse_environment();
+ log_open();
+
+#if 0 /// UNSUPPORTED by elogind (we aren't init)
+ assert_se(procfs_cpu_get_usage(&nsec) >= 0);
+ log_info("Current system CPU time: %s", format_timespan(buf, sizeof(buf), nsec/NSEC_PER_USEC, 1));
+
+ assert_se(procfs_memory_get_current(&v) >= 0);
+ log_info("Current memory usage: %s", format_bytes(buf, sizeof(buf), v));
+
+ assert_se(procfs_tasks_get_current(&v) >= 0);
+ log_info("Current number of tasks: %" PRIu64, v);
+#endif // 0
+
+ assert_se(procfs_tasks_get_limit(&v) >= 0);
+ log_info("Limit of tasks: %" PRIu64, v);
+ assert_se(v > 0);
+#if 0 /// UNSUPPORTED by elogind (we aren't init)
+ assert_se(procfs_tasks_set_limit(v) >= 0);
+
+ if (v > 100) {
+ uint64_t w;
+ r = procfs_tasks_set_limit(v-1);
+ assert_se(IN_SET(r, 0, -EPERM, -EACCES, -EROFS));
+
+ assert_se(procfs_tasks_get_limit(&w) >= 0);
+ assert_se((r == 0 && w == v - 1) || (r < 0 && w == v));
+
+ assert_se(procfs_tasks_set_limit(v) >= 0);
+
+ assert_se(procfs_tasks_get_limit(&w) >= 0);
+ assert_se(v == w);
+ }
+#endif // 0
+
+ return 0;
+}
diff --git a/src/test/test-random-util.c b/src/test/test-random-util.c
index 50f4da270..a4760b54a 100644
--- a/src/test/test-random-util.c
+++ b/src/test/test-random-util.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2017 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include "hexdecoct.h"
#include "random-util.h"
diff --git a/src/test/test-selinux.c b/src/test/test-selinux.c
index 964a228a5..c58270b25 100644
--- a/src/test/test-selinux.c
+++ b/src/test/test-selinux.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2016 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <sys/stat.h>
diff --git a/src/test/test-set.c b/src/test/test-set.c
index 0ee5ddcc9..6307403e4 100644
--- a/src/test/test-set.c
+++ b/src/test/test-set.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include "set.h"
@@ -39,6 +22,29 @@ static void test_set_steal_first(void) {
assert_se(set_isempty(m));
}
+typedef struct Item {
+ int seen;
+} Item;
+static void item_seen(Item *item) {
+ item->seen++;
+}
+
+static void test_set_free_with_destructor(void) {
+ Set *m;
+ struct Item items[4] = {};
+ unsigned i;
+
+ assert_se(m = set_new(NULL));
+ for (i = 0; i < ELEMENTSOF(items) - 1; i++)
+ assert_se(set_put(m, items + i) == 1);
+
+ m = set_free_with_destructor(m, item_seen);
+ assert_se(items[0].seen == 1);
+ assert_se(items[1].seen == 1);
+ assert_se(items[2].seen == 1);
+ assert_se(items[3].seen == 0);
+}
+
static void test_set_put(void) {
_cleanup_set_free_ Set *m = NULL;
@@ -57,6 +63,7 @@ static void test_set_put(void) {
int main(int argc, const char *argv[]) {
test_set_steal_first();
+ test_set_free_with_destructor();
test_set_put();
return 0;
diff --git a/src/test/test-signal-util.c b/src/test/test-signal-util.c
index 671eb869c..9387d5804 100644
--- a/src/test/test-signal-util.c
+++ b/src/test/test-signal-util.c
@@ -1,27 +1,110 @@
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <signal.h>
#include <unistd.h>
+//#include "log.h"
#include "macro.h"
#include "signal-util.h"
+#include "stdio-util.h"
+#include "string-util.h"
+/// Additional includes needed by elogind
+#include "process-util.h"
+
+#define info(sig) log_info(#sig " = " STRINGIFY(sig) " = %d", sig)
+
+static void test_rt_signals(void) {
+ info(SIGRTMIN);
+ info(SIGRTMAX);
+
+ /* We use signals SIGRTMIN+0 to SIGRTMIN+24 unconditionally */
+ assert(SIGRTMAX - SIGRTMIN >= 24);
+}
+
+static void test_signal_to_string_one(int val) {
+ const char *p;
+
+ assert_se(p = signal_to_string(val));
+
+ assert_se(signal_from_string(p) == val);
+
+ p = strjoina("SIG", p);
+ assert_se(signal_from_string(p) == val);
+}
+
+static void test_signal_from_string_one(const char *s, int val) {
+ const char *p;
+
+ assert_se(signal_from_string(s) == val);
+
+ p = strjoina("SIG", s);
+ assert_se(signal_from_string(p) == val);
+}
+
+static void test_signal_from_string_number(const char *s, int val) {
+ const char *p;
+
+ assert_se(signal_from_string(s) == val);
+
+ p = strjoina("SIG", s);
+ assert_se(signal_from_string(p) == -EINVAL);
+}
+
+static void test_signal_from_string(void) {
+ char buf[STRLEN("RTMIN+") + DECIMAL_STR_MAX(int) + 1];
+
+ test_signal_to_string_one(SIGHUP);
+ test_signal_to_string_one(SIGTERM);
+ test_signal_to_string_one(SIGRTMIN);
+ test_signal_to_string_one(SIGRTMIN+3);
+ test_signal_to_string_one(SIGRTMAX-4);
+
+ test_signal_from_string_one("RTMIN", SIGRTMIN);
+ test_signal_from_string_one("RTMAX", SIGRTMAX);
+
+ xsprintf(buf, "RTMIN+%d", SIGRTMAX-SIGRTMIN);
+ test_signal_from_string_one(buf, SIGRTMAX);
+
+ xsprintf(buf, "RTMIN+%d", INT_MAX);
+ test_signal_from_string_one(buf, -ERANGE);
+
+ xsprintf(buf, "RTMAX-%d", SIGRTMAX-SIGRTMIN);
+ test_signal_from_string_one(buf, SIGRTMIN);
+
+ xsprintf(buf, "RTMAX-%d", INT_MAX);
+ test_signal_from_string_one(buf, -ERANGE);
+
+ test_signal_from_string_one("", -EINVAL);
+ test_signal_from_string_one("hup", -EINVAL);
+ test_signal_from_string_one("HOGEHOGE", -EINVAL);
+
+ test_signal_from_string_one("RTMIN-5", -EINVAL);
+ test_signal_from_string_one("RTMIN- 5", -EINVAL);
+ test_signal_from_string_one("RTMIN -5", -EINVAL);
+ test_signal_from_string_one("RTMIN+ 5", -EINVAL);
+ test_signal_from_string_one("RTMIN +5", -EINVAL);
+ test_signal_from_string_one("RTMIN+100", -ERANGE);
+ test_signal_from_string_one("RTMIN+-3", -EINVAL);
+ test_signal_from_string_one("RTMIN++3", -EINVAL);
+ test_signal_from_string_one("RTMIN+HUP", -EINVAL);
+ test_signal_from_string_one("RTMIN3", -EINVAL);
+
+ test_signal_from_string_one("RTMAX+5", -EINVAL);
+ test_signal_from_string_one("RTMAX+ 5", -EINVAL);
+ test_signal_from_string_one("RTMAX +5", -EINVAL);
+ test_signal_from_string_one("RTMAX- 5", -EINVAL);
+ test_signal_from_string_one("RTMAX -5", -EINVAL);
+ test_signal_from_string_one("RTMAX-100", -ERANGE);
+ test_signal_from_string_one("RTMAX-+3", -EINVAL);
+ test_signal_from_string_one("RTMAX--3", -EINVAL);
+ test_signal_from_string_one("RTMAX-HUP", -EINVAL);
+
+ test_signal_from_string_number("3", 3);
+ test_signal_from_string_number("+5", 5);
+ test_signal_from_string_number(" +5", 5);
+ test_signal_from_string_number("10000", -ERANGE);
+ test_signal_from_string_number("-2", -ERANGE);
+}
static void test_block_signals(void) {
sigset_t ss;
@@ -50,16 +133,18 @@ static void test_block_signals(void) {
static void test_ignore_signals(void) {
assert_se(ignore_signals(SIGINT, -1) >= 0);
- assert_se(kill(getpid(), SIGINT) >= 0);
+ assert_se(kill(getpid_cached(), SIGINT) >= 0);
assert_se(ignore_signals(SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0);
- assert_se(kill(getpid(), SIGUSR1) >= 0);
- assert_se(kill(getpid(), SIGUSR2) >= 0);
- assert_se(kill(getpid(), SIGTERM) >= 0);
- assert_se(kill(getpid(), SIGPIPE) >= 0);
+ assert_se(kill(getpid_cached(), SIGUSR1) >= 0);
+ assert_se(kill(getpid_cached(), SIGUSR2) >= 0);
+ assert_se(kill(getpid_cached(), SIGTERM) >= 0);
+ assert_se(kill(getpid_cached(), SIGPIPE) >= 0);
assert_se(default_signals(SIGINT, SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0);
}
int main(int argc, char *argv[]) {
+ test_rt_signals();
+ test_signal_from_string();
test_block_signals();
test_ignore_signals();
diff --git a/src/test/test-siphash24.c b/src/test/test-siphash24.c
index b74b7ad2d..218200e48 100644
--- a/src/test/test-siphash24.c
+++ b/src/test/test-siphash24.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2015 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include "siphash24.h"
#include "util.h"
diff --git a/src/test/test-sizeof.c b/src/test/test-sizeof.c
index 269adfd18..bd010c50d 100644
--- a/src/test/test-sizeof.c
+++ b/src/test/test-sizeof.c
@@ -1,23 +1,10 @@
-/***
- This file is part of systemd.
-
- Copyright 2016 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <stdio.h>
+#include <string.h>
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+//#include <float.h>
#include "time-util.h"
@@ -37,7 +24,12 @@ enum Enum {
};
enum BigEnum {
- big_enum_value = UINT64_C(-1),
+ big_enum_value = UINT64_C(1),
+};
+
+enum BigEnum2 {
+ big_enum2_pos = UINT64_C(1),
+ big_enum2_neg = UINT64_C(-1),
};
int main(void) {
@@ -48,21 +40,40 @@ int main(void) {
info(unsigned);
info(long unsigned);
info(long long unsigned);
+#ifdef __GLIBC__
info(__syscall_ulong_t);
info(__syscall_slong_t);
+#endif // ifdef __GLIBC__
info(float);
info(double);
info(long double);
+#ifdef FLT128_MAX
+ info(_Float128);
+ info(_Float64);
+ info(_Float64x);
+ info(_Float32);
+ info(_Float32x);
+#endif
+
info(size_t);
info(ssize_t);
info(time_t);
info(usec_t);
+#ifdef __GLIBC__
info(__time_t);
+#endif // ifdef __GLIBC__
+ info(pid_t);
+ info(uid_t);
+ info(gid_t);
info(enum Enum);
info(enum BigEnum);
+ info(enum BigEnum2);
+ assert_cc(sizeof(enum BigEnum2) == 8);
+ printf("big_enum2_pos → %zu\n", sizeof(big_enum2_pos));
+ printf("big_enum2_neg → %zu\n", sizeof(big_enum2_neg));
return 0;
}
diff --git a/src/test/test-stat-util.c b/src/test/test-stat-util.c
index 2825dbc52..0880db863 100644
--- a/src/test/test-stat-util.c
+++ b/src/test/test-stat-util.c
@@ -1,21 +1,4 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <fcntl.h>
#include <linux/magic.h>
@@ -61,27 +44,20 @@ static void test_is_symlink(void) {
assert_se(is_symlink(name_link) == 1);
assert_se(is_symlink("/a/file/which/does/not/exist/i/guess") < 0);
-
unlink(name);
unlink(name_link);
}
-static void test_path_is_os_tree(void) {
- assert_se(path_is_os_tree("/") > 0);
- assert_se(path_is_os_tree("/etc") == 0);
- assert_se(path_is_os_tree("/idontexist") == -ENOENT);
-}
-
-static void test_path_check_fstype(void) {
+static void test_path_is_fs_type(void) {
/* run might not be a mount point in build chroots */
if (path_is_mount_point("/run", NULL, AT_SYMLINK_FOLLOW) > 0) {
- assert_se(path_check_fstype("/run", TMPFS_MAGIC) > 0);
- assert_se(path_check_fstype("/run", BTRFS_SUPER_MAGIC) == 0);
+ assert_se(path_is_fs_type("/run", TMPFS_MAGIC) > 0);
+ assert_se(path_is_fs_type("/run", BTRFS_SUPER_MAGIC) == 0);
}
- assert_se(path_check_fstype("/proc", PROC_SUPER_MAGIC) > 0);
- assert_se(path_check_fstype("/proc", BTRFS_SUPER_MAGIC) == 0);
- assert_se(path_check_fstype("/proc", BTRFS_SUPER_MAGIC) == 0);
- assert_se(path_check_fstype("/i-dont-exist", BTRFS_SUPER_MAGIC) == -ENOENT);
+ assert_se(path_is_fs_type("/proc", PROC_SUPER_MAGIC) > 0);
+ assert_se(path_is_fs_type("/proc", BTRFS_SUPER_MAGIC) == 0);
+ assert_se(path_is_fs_type("/proc", BTRFS_SUPER_MAGIC) == 0);
+ assert_se(path_is_fs_type("/i-dont-exist", BTRFS_SUPER_MAGIC) == -ENOENT);
}
static void test_path_is_temporary_fs(void) {
@@ -97,8 +73,7 @@ int main(int argc, char *argv[]) {
test_files_same();
#if 0 /// UNNEEDED by elogind
test_is_symlink();
- test_path_is_os_tree();
- test_path_check_fstype();
+ test_path_is_fs_type();
test_path_is_temporary_fs();
#endif // 0
diff --git a/src/test/test-string-util.c b/src/test/test-string-util.c
index 54fe87d2d..202af8bcc 100644
--- a/src/test/test-string-util.c
+++ b/src/test/test-string-util.c
@@ -1,26 +1,11 @@
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include "alloc-util.h"
+#include "locale-util.h"
#include "macro.h"
#include "string-util.h"
#include "strv.h"
+#include "utf8.h"
static void test_string_erase(void) {
char *x;
@@ -91,6 +76,87 @@ static void test_ascii_strcasecmp_nn(void) {
}
#endif // 0
+static void test_cellescape(void) {
+ char buf[40];
+
+ assert_se(streq(cellescape(buf, 1, ""), ""));
+ assert_se(streq(cellescape(buf, 1, "1"), ""));
+ assert_se(streq(cellescape(buf, 1, "12"), ""));
+
+ assert_se(streq(cellescape(buf, 2, ""), ""));
+ assert_se(streq(cellescape(buf, 2, "1"), "1"));
+ assert_se(streq(cellescape(buf, 2, "12"), "."));
+ assert_se(streq(cellescape(buf, 2, "123"), "."));
+
+ assert_se(streq(cellescape(buf, 3, ""), ""));
+ assert_se(streq(cellescape(buf, 3, "1"), "1"));
+ assert_se(streq(cellescape(buf, 3, "12"), "12"));
+ assert_se(streq(cellescape(buf, 3, "123"), ".."));
+ assert_se(streq(cellescape(buf, 3, "1234"), ".."));
+
+ assert_se(streq(cellescape(buf, 4, ""), ""));
+ assert_se(streq(cellescape(buf, 4, "1"), "1"));
+ assert_se(streq(cellescape(buf, 4, "12"), "12"));
+ assert_se(streq(cellescape(buf, 4, "123"), "123"));
+ assert_se(streq(cellescape(buf, 4, "1234"), is_locale_utf8() ? "…" : "..."));
+ assert_se(streq(cellescape(buf, 4, "12345"), is_locale_utf8() ? "…" : "..."));
+
+ assert_se(streq(cellescape(buf, 5, ""), ""));
+ assert_se(streq(cellescape(buf, 5, "1"), "1"));
+ assert_se(streq(cellescape(buf, 5, "12"), "12"));
+ assert_se(streq(cellescape(buf, 5, "123"), "123"));
+ assert_se(streq(cellescape(buf, 5, "1234"), "1234"));
+ assert_se(streq(cellescape(buf, 5, "12345"), is_locale_utf8() ? "1…" : "1..."));
+ assert_se(streq(cellescape(buf, 5, "123456"), is_locale_utf8() ? "1…" : "1..."));
+
+ assert_se(streq(cellescape(buf, 1, "\020"), ""));
+ assert_se(streq(cellescape(buf, 2, "\020"), "."));
+ assert_se(streq(cellescape(buf, 3, "\020"), ".."));
+ assert_se(streq(cellescape(buf, 4, "\020"), "…"));
+ assert_se(streq(cellescape(buf, 5, "\020"), "\\020"));
+
+ assert_se(streq(cellescape(buf, 5, "1234\020"), "1…"));
+ assert_se(streq(cellescape(buf, 6, "1234\020"), "12…"));
+ assert_se(streq(cellescape(buf, 7, "1234\020"), "123…"));
+ assert_se(streq(cellescape(buf, 8, "1234\020"), "1234…"));
+ assert_se(streq(cellescape(buf, 9, "1234\020"), "1234\\020"));
+
+ assert_se(streq(cellescape(buf, 1, "\t\n"), ""));
+ assert_se(streq(cellescape(buf, 2, "\t\n"), "."));
+ assert_se(streq(cellescape(buf, 3, "\t\n"), ".."));
+ assert_se(streq(cellescape(buf, 4, "\t\n"), "…"));
+ assert_se(streq(cellescape(buf, 5, "\t\n"), "\\t\\n"));
+
+ assert_se(streq(cellescape(buf, 5, "1234\t\n"), "1…"));
+ assert_se(streq(cellescape(buf, 6, "1234\t\n"), "12…"));
+ assert_se(streq(cellescape(buf, 7, "1234\t\n"), "123…"));
+ assert_se(streq(cellescape(buf, 8, "1234\t\n"), "1234…"));
+ assert_se(streq(cellescape(buf, 9, "1234\t\n"), "1234\\t\\n"));
+
+ assert_se(streq(cellescape(buf, 4, "x\t\020\n"), "…"));
+ assert_se(streq(cellescape(buf, 5, "x\t\020\n"), "x…"));
+ assert_se(streq(cellescape(buf, 6, "x\t\020\n"), "x…"));
+ assert_se(streq(cellescape(buf, 7, "x\t\020\n"), "x\\t…"));
+ assert_se(streq(cellescape(buf, 8, "x\t\020\n"), "x\\t…"));
+ assert_se(streq(cellescape(buf, 9, "x\t\020\n"), "x\\t…"));
+ assert_se(streq(cellescape(buf, 10, "x\t\020\n"), "x\\t\\020\\n"));
+
+ assert_se(streq(cellescape(buf, 6, "1\011"), "1\\t"));
+ assert_se(streq(cellescape(buf, 6, "1\020"), "1\\020"));
+ assert_se(streq(cellescape(buf, 6, "1\020x"), is_locale_utf8() ? "1…" : "1..."));
+
+ assert_se(streq(cellescape(buf, 40, "1\020"), "1\\020"));
+ assert_se(streq(cellescape(buf, 40, "1\020x"), "1\\020x"));
+
+ assert_se(streq(cellescape(buf, 40, "\a\b\f\n\r\t\v\\\"'"), "\\a\\b\\f\\n\\r\\t\\v\\\\\\\"\\'"));
+ assert_se(streq(cellescape(buf, 6, "\a\b\f\n\r\t\v\\\"'"), is_locale_utf8() ? "\\a…" : "\\a..."));
+ assert_se(streq(cellescape(buf, 7, "\a\b\f\n\r\t\v\\\"'"), is_locale_utf8() ? "\\a…" : "\\a..."));
+ assert_se(streq(cellescape(buf, 8, "\a\b\f\n\r\t\v\\\"'"), is_locale_utf8() ? "\\a\\b…" : "\\a\\b..."));
+
+ assert_se(streq(cellescape(buf, sizeof buf, "1\020"), "1\\020"));
+ assert_se(streq(cellescape(buf, sizeof buf, "1\020x"), "1\\020x"));
+}
+
static void test_streq_ptr(void) {
assert_se(streq_ptr(NULL, NULL));
assert_se(!streq_ptr("abc", "cdef"));
@@ -105,9 +171,37 @@ static void test_strstrip(void) {
}
static void test_strextend(void) {
- _cleanup_free_ char *str = strdup("0123");
- strextend(&str, "456", "78", "9", NULL);
- assert_se(streq(str, "0123456789"));
+ _cleanup_free_ char *str = NULL;
+
+ assert_se(strextend(&str, NULL));
+ assert_se(streq_ptr(str, ""));
+ assert_se(strextend(&str, "", "0", "", "", "123", NULL));
+ assert_se(streq_ptr(str, "0123"));
+ assert_se(strextend(&str, "456", "78", "9", NULL));
+ assert_se(streq_ptr(str, "0123456789"));
+}
+
+static void test_strextend_with_separator(void) {
+ _cleanup_free_ char *str = NULL;
+
+ assert_se(strextend_with_separator(&str, NULL, NULL));
+ assert_se(streq_ptr(str, ""));
+ str = mfree(str);
+
+ assert_se(strextend_with_separator(&str, "...", NULL));
+ assert_se(streq_ptr(str, ""));
+ assert_se(strextend_with_separator(&str, "...", NULL));
+ assert_se(streq_ptr(str, ""));
+ str = mfree(str);
+
+ assert_se(strextend_with_separator(&str, "xyz", "a", "bb", "ccc", NULL));
+ assert_se(streq_ptr(str, "axyzbbxyzccc"));
+ str = mfree(str);
+
+ assert_se(strextend_with_separator(&str, ",", "start", "", "1", "234", NULL));
+ assert_se(streq_ptr(str, "start,,1,234"));
+ assert_se(strextend_with_separator(&str, ";", "more", "5", "678", NULL));
+ assert_se(streq_ptr(str, "start,,1,234;more;5;678"));
}
static void test_strrep(void) {
@@ -121,7 +215,6 @@ static void test_strrep(void) {
assert_se(streq(zero, ""));
}
-
static void test_strappend(void) {
_cleanup_free_ char *t1, *t2, *t3, *t4;
@@ -291,15 +384,62 @@ static void test_endswith_no_case(void) {
assert_se(!endswith_no_case("foobar", "FOOBARFOOFOO"));
}
-#if 0 /// UNNEEDED by elogind
static void test_delete_chars(void) {
- char *r;
- char input[] = " hello, waldo. abc";
+ char *s, input[] = " hello, waldo. abc";
- r = delete_chars(input, WHITESPACE);
- assert_se(streq(r, "hello,waldo.abc"));
+ s = delete_chars(input, WHITESPACE);
+ assert_se(streq(s, "hello,waldo.abc"));
+ assert_se(s == input);
+}
+
+static void test_delete_trailing_chars(void) {
+
+ char *s,
+ input1[] = " \n \r k \n \r ",
+ input2[] = "kkkkthiskkkiskkkaktestkkk",
+ input3[] = "abcdef";
+
+ s = delete_trailing_chars(input1, WHITESPACE);
+ assert_se(streq(s, " \n \r k"));
+ assert_se(s == input1);
+
+ s = delete_trailing_chars(input2, "kt");
+ assert_se(streq(s, "kkkkthiskkkiskkkaktes"));
+ assert_se(s == input2);
+
+ s = delete_trailing_chars(input3, WHITESPACE);
+ assert_se(streq(s, "abcdef"));
+ assert_se(s == input3);
+
+ s = delete_trailing_chars(input3, "fe");
+ assert_se(streq(s, "abcd"));
+ assert_se(s == input3);
+}
+
+static void test_delete_trailing_slashes(void) {
+ char s1[] = "foobar//",
+ s2[] = "foobar/",
+ s3[] = "foobar",
+ s4[] = "";
+
+ assert_se(streq(delete_trailing_chars(s1, "_"), "foobar//"));
+ assert_se(streq(delete_trailing_chars(s1, "/"), "foobar"));
+ assert_se(streq(delete_trailing_chars(s2, "/"), "foobar"));
+ assert_se(streq(delete_trailing_chars(s3, "/"), "foobar"));
+ assert_se(streq(delete_trailing_chars(s4, "/"), ""));
+}
+
+static void test_skip_leading_chars(void) {
+ char input1[] = " \n \r k \n \r ",
+ input2[] = "kkkkthiskkkiskkkaktestkkk",
+ input3[] = "abcdef";
+
+ assert_se(streq(skip_leading_chars(input1, WHITESPACE), "k \n \r "));
+ assert_se(streq(skip_leading_chars(input2, "k"), "thiskkkiskkkaktestkkk"));
+ assert_se(streq(skip_leading_chars(input2, "tk"), "hiskkkiskkkaktestkkk"));
+ assert_se(streq(skip_leading_chars(input3, WHITESPACE), "abcdef"));
+ assert_se(streq(skip_leading_chars(input3, "bcaef"), "def"));
}
-#endif // 0
static void test_in_charset(void) {
assert_se(in_charset("dddaaabbbcccc", "abcd"));
@@ -342,15 +482,35 @@ static void test_first_word(void) {
assert_se(!first_word("Hellooo", "Hello"));
}
+static void test_strlen_ptr(void) {
+ assert_se(strlen_ptr("foo") == 3);
+ assert_se(strlen_ptr("") == 0);
+ assert_se(strlen_ptr(NULL) == 0);
+}
+
+static void test_memory_startswith(void) {
+ assert_se(streq(memory_startswith("", 0, ""), ""));
+ assert_se(streq(memory_startswith("", 1, ""), ""));
+ assert_se(streq(memory_startswith("x", 2, ""), "x"));
+ assert_se(!memory_startswith("", 1, "x"));
+ assert_se(!memory_startswith("", 1, "xxxxxxxx"));
+ assert_se(streq(memory_startswith("xxx", 4, "x"), "xx"));
+ assert_se(streq(memory_startswith("xxx", 4, "xx"), "x"));
+ assert_se(streq(memory_startswith("xxx", 4, "xxx"), ""));
+ assert_se(!memory_startswith("xxx", 4, "xxxx"));
+}
+
int main(int argc, char *argv[]) {
test_string_erase();
#if 0 /// UNNEEDED by elogind
test_ascii_strcasecmp_n();
test_ascii_strcasecmp_nn();
#endif // 0
+ test_cellescape();
test_streq_ptr();
test_strstrip();
test_strextend();
+ test_strextend_with_separator();
test_strrep();
test_strappend();
test_string_has_cc();
@@ -364,12 +524,15 @@ int main(int argc, char *argv[]) {
test_foreach_word_quoted();
test_endswith();
test_endswith_no_case();
-#if 0 /// UNNEEDED by elogind
test_delete_chars();
-#endif // 0
+ test_delete_trailing_chars();
+ test_delete_trailing_slashes();
+ test_skip_leading_chars();
test_in_charset();
test_split_pair();
test_first_word();
+ test_strlen_ptr();
+ test_memory_startswith();
return 0;
}
diff --git a/src/test/test-strip-tab-ansi.c b/src/test/test-strip-tab-ansi.c
index 72b0f6fc1..27e2a240e 100644
--- a/src/test/test-strip-tab-ansi.c
+++ b/src/test/test-strip-tab-ansi.c
@@ -1,52 +1,63 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <stdio.h>
+#include "alloc-util.h"
#include "string-util.h"
#include "terminal-util.h"
#include "util.h"
int main(int argc, char *argv[]) {
+#if 0 /// urlified and z are UNNEEDED by elogind
+ _cleanup_free_ char *urlified = NULL, *q = NULL, *qq = NULL;
+ char *p, *z;
+#else
+ _cleanup_free_ char *q = NULL, *qq = NULL;
char *p;
+#endif // 0
assert_se(p = strdup("\tFoobar\tbar\twaldo\t"));
- assert_se(strip_tab_ansi(&p, NULL));
+ assert_se(strip_tab_ansi(&p, NULL, NULL));
fprintf(stdout, "<%s>\n", p);
assert_se(streq(p, " Foobar bar waldo "));
free(p);
assert_se(p = strdup(ANSI_HIGHLIGHT "Hello" ANSI_NORMAL ANSI_HIGHLIGHT_RED " world!" ANSI_NORMAL));
- assert_se(strip_tab_ansi(&p, NULL));
+ assert_se(strip_tab_ansi(&p, NULL, NULL));
fprintf(stdout, "<%s>\n", p);
assert_se(streq(p, "Hello world!"));
free(p);
assert_se(p = strdup("\x1B[\x1B[\t\x1B[" ANSI_HIGHLIGHT "\x1B[" "Hello" ANSI_NORMAL ANSI_HIGHLIGHT_RED " world!" ANSI_NORMAL));
- assert_se(strip_tab_ansi(&p, NULL));
+ assert_se(strip_tab_ansi(&p, NULL, NULL));
assert_se(streq(p, "\x1B[\x1B[ \x1B[\x1B[Hello world!"));
free(p);
assert_se(p = strdup("\x1B[waldo"));
- assert_se(strip_tab_ansi(&p, NULL));
+ assert_se(strip_tab_ansi(&p, NULL, NULL));
assert_se(streq(p, "\x1B[waldo"));
free(p);
+#if 0 /// UNNEEDED by elogind
+ assert_se(terminal_urlify_path("/etc/fstab", "i am a fabulous link", &urlified) >= 0);
+ assert_se(p = strjoin("something ", urlified, " something-else"));
+ assert_se(q = strdup(p));
+ printf("<%s>\n", p);
+ assert_se(strip_tab_ansi(&p, NULL, NULL));
+ printf("<%s>\n", p);
+ assert_se(streq(p, "something i am a fabulous link something-else"));
+ p = mfree(p);
+
+ /* Truncate the formatted string in the middle of an ANSI sequence (in which case we shouldn't touch the
+ * incomplete sequence) */
+ z = strstr(q, "fstab");
+ if (z) {
+ *z = 0;
+ assert_se(qq = strdup(q));
+ assert_se(strip_tab_ansi(&q, NULL, NULL));
+ assert_se(streq(q, qq));
+ }
+#endif // 0
+
return 0;
}
diff --git a/src/test/test-unaligned.c b/src/test/test-unaligned.c
index 4f6439894..96d6b22be 100644
--- a/src/test/test-unaligned.c
+++ b/src/test/test-unaligned.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd
-
- Copyright 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include "sparse-endian.h"
#include "unaligned.h"
diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c
index d79c0781b..bf8dfd0de 100644
--- a/src/test/test-user-util.c
+++ b/src/test/test-user-util.c
@@ -1,39 +1,36 @@
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include "alloc-util.h"
+//#include "log.h"
#include "macro.h"
#include "string-util.h"
#include "user-util.h"
#include "util.h"
+#include "path-util.h"
static void test_uid_to_name_one(uid_t uid, const char *name) {
_cleanup_free_ char *t = NULL;
+ log_info("/* %s("UID_FMT", \"%s\") */", __func__, uid, name);
+
assert_se(t = uid_to_name(uid));
+ if (!synthesize_nobody() && streq(name, NOBODY_USER_NAME)) {
+ log_info("(skipping detailed tests because nobody is not synthesized)");
+ return;
+ }
assert_se(streq_ptr(t, name));
}
static void test_gid_to_name_one(gid_t gid, const char *name) {
_cleanup_free_ char *t = NULL;
+ log_info("/* %s("GID_FMT", \"%s\") */", __func__, gid, name);
+
assert_se(t = gid_to_name(gid));
+ if (!synthesize_nobody() && streq(name, NOBODY_GROUP_NAME)) {
+ log_info("(skipping detailed tests because nobody is not synthesized)");
+ return;
+ }
assert_se(streq_ptr(t, name));
}
@@ -41,6 +38,8 @@ static void test_parse_uid(void) {
int r;
uid_t uid;
+ log_info("/* %s */", __func__);
+
r = parse_uid("100", &uid);
assert_se(r == 0);
assert_se(uid == 100);
@@ -53,6 +52,7 @@ static void test_parse_uid(void) {
}
static void test_uid_ptr(void) {
+ log_info("/* %s */", __func__);
assert_se(UID_TO_PTR(0) != NULL);
assert_se(UID_TO_PTR(1000) != NULL);
@@ -62,6 +62,8 @@ static void test_uid_ptr(void) {
}
static void test_valid_user_group_name(void) {
+ log_info("/* %s */", __func__);
+
assert_se(!valid_user_group_name(NULL));
assert_se(!valid_user_group_name(""));
assert_se(!valid_user_group_name("1"));
@@ -88,6 +90,8 @@ static void test_valid_user_group_name(void) {
}
static void test_valid_user_group_name_or_id(void) {
+ log_info("/* %s */", __func__);
+
assert_se(!valid_user_group_name_or_id(NULL));
assert_se(!valid_user_group_name_or_id(""));
assert_se(valid_user_group_name_or_id("0"));
@@ -117,6 +121,7 @@ static void test_valid_user_group_name_or_id(void) {
}
static void test_valid_gecos(void) {
+ log_info("/* %s */", __func__);
assert_se(!valid_gecos(NULL));
assert_se(valid_gecos(""));
@@ -127,6 +132,7 @@ static void test_valid_gecos(void) {
}
static void test_valid_home(void) {
+ log_info("/* %s */", __func__);
assert_se(!valid_home(NULL));
assert_se(!valid_home(""));
@@ -143,19 +149,76 @@ static void test_valid_home(void) {
assert_se(valid_home("/home/foo"));
}
-int main(int argc, char*argv[]) {
+static void test_get_user_creds_one(const char *id, const char *name, uid_t uid, gid_t gid, const char *home, const char *shell) {
+ const char *rhome = NULL;
+ const char *rshell = NULL;
+ uid_t ruid = UID_INVALID;
+ gid_t rgid = GID_INVALID;
+ int r;
+
+ log_info("/* %s(\"%s\", \"%s\", "UID_FMT", "GID_FMT", \"%s\", \"%s\") */",
+ __func__, id, name, uid, gid, home, shell);
+
+ r = get_user_creds(&id, &ruid, &rgid, &rhome, &rshell);
+ log_info_errno(r, "got \"%s\", "UID_FMT", "GID_FMT", \"%s\", \"%s\": %m",
+ id, ruid, rgid, strnull(rhome), strnull(rshell));
+ if (!synthesize_nobody() && streq(name, NOBODY_USER_NAME)) {
+ log_info("(skipping detailed tests because nobody is not synthesized)");
+ return;
+ }
+ assert_se(r == 0);
+ assert_se(streq_ptr(id, name));
+ assert_se(ruid == uid);
+ assert_se(rgid == gid);
+ assert_se(path_equal(rhome, home));
+ assert_se(path_equal(rshell, shell));
+}
+
+#if 0 /// UNNEEDED by elogind
+static void test_get_group_creds_one(const char *id, const char *name, gid_t gid) {
+ gid_t rgid = GID_INVALID;
+ int r;
+
+ log_info("/* %s(\"%s\", \"%s\", "GID_FMT") */", __func__, id, name, gid);
+
+ r = get_group_creds(&id, &rgid);
+ log_info_errno(r, "got \"%s\", "GID_FMT": %m", id, rgid);
+ if (!synthesize_nobody() && streq(name, NOBODY_GROUP_NAME)) {
+ log_info("(skipping detailed tests because nobody is not synthesized)");
+ return;
+ }
+ assert_se(r == 0);
+ assert_se(streq_ptr(id, name));
+ assert_se(rgid == gid);
+}
+#endif // 0
+int main(int argc, char*argv[]) {
test_uid_to_name_one(0, "root");
+ test_uid_to_name_one(UID_NOBODY, NOBODY_USER_NAME);
test_uid_to_name_one(0xFFFF, "65535");
test_uid_to_name_one(0xFFFFFFFF, "4294967295");
test_gid_to_name_one(0, "root");
#if 0 /// UNNEEDED by elogind
+ test_gid_to_name_one(GID_NOBODY, NOBODY_GROUP_NAME);
test_gid_to_name_one(TTY_GID, "tty");
#endif // 0
test_gid_to_name_one(0xFFFF, "65535");
test_gid_to_name_one(0xFFFFFFFF, "4294967295");
+ test_get_user_creds_one("root", "root", 0, 0, "/root", "/bin/sh");
+ test_get_user_creds_one("0", "root", 0, 0, "/root", "/bin/sh");
+ test_get_user_creds_one(NOBODY_USER_NAME, NOBODY_USER_NAME, UID_NOBODY, GID_NOBODY, "/", "/sbin/nologin");
+ test_get_user_creds_one("65534", NOBODY_USER_NAME, UID_NOBODY, GID_NOBODY, "/", "/sbin/nologin");
+
+#if 0 /// UNNEEDED by elogind
+ test_get_group_creds_one("root", "root", 0);
+ test_get_group_creds_one("0", "root", 0);
+ test_get_group_creds_one(NOBODY_GROUP_NAME, NOBODY_GROUP_NAME, GID_NOBODY);
+ test_get_group_creds_one("65534", NOBODY_GROUP_NAME, GID_NOBODY);
+#endif // 0
+
test_parse_uid();
test_uid_ptr();
diff --git a/src/test/test-utf8.c b/src/test/test-utf8.c
index 1ce5a5a24..fe3db314a 100644
--- a/src/test/test-utf8.c
+++ b/src/test/test-utf8.c
@@ -1,20 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
- Copyright 2013 Dave Reisner
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ Copyright © 2013 Dave Reisner
***/
#include "alloc-util.h"
@@ -36,11 +22,21 @@ static void test_utf8_is_valid(void) {
}
static void test_ascii_is_valid(void) {
- assert_se(ascii_is_valid("alsdjf\t\vbarr\nba z"));
+ assert_se( ascii_is_valid("alsdjf\t\vbarr\nba z"));
assert_se(!ascii_is_valid("\342\204\242"));
assert_se(!ascii_is_valid("\341\204"));
}
+static void test_ascii_is_valid_n(void) {
+ assert_se( ascii_is_valid_n("alsdjf\t\vbarr\nba z", 17));
+ assert_se( ascii_is_valid_n("alsdjf\t\vbarr\nba z", 16));
+ assert_se(!ascii_is_valid_n("alsdjf\t\vbarr\nba z", 18));
+ assert_se(!ascii_is_valid_n("\342\204\242", 3));
+ assert_se(!ascii_is_valid_n("\342\204\242", 2));
+ assert_se(!ascii_is_valid_n("\342\204\242", 1));
+ assert_se( ascii_is_valid_n("\342\204\242", 0));
+}
+
static void test_utf8_encoded_valid_unichar(void) {
assert_se(utf8_encoded_valid_unichar("\342\204\242") == 3);
assert_se(utf8_encoded_valid_unichar("\302\256") == 2);
@@ -105,14 +101,35 @@ static void test_utf16_to_utf8(void) {
free(a);
}
+static void test_utf8_n_codepoints(void) {
+ assert_se(utf8_n_codepoints("abc") == 3);
+ assert_se(utf8_n_codepoints("zażółcić gęślą jaźń") == 19);
+ assert_se(utf8_n_codepoints("串") == 1);
+ assert_se(utf8_n_codepoints("") == 0);
+ assert_se(utf8_n_codepoints("…👊🔪💐…") == 5);
+ assert_se(utf8_n_codepoints("\xF1") == (size_t) -1);
+}
+
+static void test_utf8_console_width(void) {
+ assert_se(utf8_console_width("abc") == 3);
+ assert_se(utf8_console_width("zażółcić gęślą jaźń") == 19);
+ assert_se(utf8_console_width("串") == 2);
+ assert_se(utf8_console_width("") == 0);
+ assert_se(utf8_console_width("…👊🔪💐…") == 8);
+ assert_se(utf8_console_width("\xF1") == (size_t) -1);
+}
+
int main(int argc, char *argv[]) {
test_utf8_is_valid();
test_utf8_is_printable();
test_ascii_is_valid();
+ test_ascii_is_valid_n();
test_utf8_encoded_valid_unichar();
test_utf8_escaping();
test_utf8_escaping_printable();
test_utf16_to_utf8();
+ test_utf8_n_codepoints();
+ test_utf8_console_width();
return 0;
}
diff --git a/src/test/test-util.c b/src/test/test-util.c
index 6e5f90756..36dfeb5c3 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -1,22 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 Thomas H.P. Andersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <string.h>
@@ -27,7 +9,8 @@
#include "fileio.h"
#include "fs-util.h"
#include "parse-util.h"
-//#include "raw-clone.h"
+#include "process-util.h"
+#include "raw-clone.h"
#include "rm-rf.h"
#include "string-util.h"
#include "util.h"
@@ -104,6 +87,11 @@ static void test_max(void) {
assert_se(CLAMP(CLAMP(0, -10, 10), CLAMP(-5, 10, 20), CLAMP(100, -5, 20)) == 10);
}
+#pragma GCC diagnostic push
+#ifdef __clang__
+# pragma GCC diagnostic ignored "-Waddress-of-packed-member"
+#endif
+
static void test_container_of(void) {
struct mytype {
uint8_t pad1[3];
@@ -122,6 +110,8 @@ static void test_container_of(void) {
v1) == &myval);
}
+#pragma GCC diagnostic pop
+
static void test_div_round_up(void) {
int div;
@@ -219,6 +209,10 @@ static void test_raw_clone(void) {
waitpid(pid, &status, __WCLONE);
assert_se(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS);
}
+
+ errno = 0;
+ assert_se(raw_clone(CLONE_FS|CLONE_NEWNS) == -1);
+ assert_se(errno == EINVAL);
}
#endif // 0
diff --git a/src/test/test-verbs.c b/src/test/test-verbs.c
index 0fcdd9e78..efb9664b3 100644
--- a/src/test/test-verbs.c
+++ b/src/test/test-verbs.c
@@ -1,21 +1,4 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 systemd developers
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include "macro.h"
#include "strv.h"
diff --git a/src/uaccess-command/uaccess-command.c b/src/uaccess-command/uaccess-command.c
new file mode 100644
index 000000000..df790e134
--- /dev/null
+++ b/src/uaccess-command/uaccess-command.c
@@ -0,0 +1,98 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * manage device node user ACL
+ *
+ * Copyright 2010-2012 Kay Sievers <kay@vrfy.org>
+ * Copyright 2010 Lennart Poettering
+ *
+ * This program 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.
+ *
+ * This program is distributed in the hope that 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "sd-login.h"
+
+#include "login-util.h"
+#include "logind-acl.h"
+#include "util.h"
+
+/*
+ * Copy of builtin_uaccess() from
+ * systemd/src/udev/udev-builtin-uaccess.c
+ */
+static int dev_uaccess(const char *path, const char *seat) {
+ int r;
+ bool changed_acl = false;
+ uid_t uid;
+
+ umask(0022);
+
+ /* don't muck around with ACLs when the system is not running logind */
+ if (!logind_running())
+ return 0;
+
+ if (!seat || !strlen(seat))
+ seat = "seat0";
+
+ r = sd_seat_get_active(seat, NULL, &uid);
+ if (IN_SET(r, -ENXIO, -ENODATA)) {
+ /* 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_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_ERR, r, "Failed to apply ACL on %s: %m", path);
+ goto finish;
+ }
+
+ changed_acl = true;
+ r = 0;
+
+finish:
+ if (path && !changed_acl) {
+ int k;
+
+ /* Better be safe than sorry and reset ACL */
+ k = devnode_acl(path, true, false, 0, false, 0);
+ if (k < 0) {
+ log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, k, "Failed to reset ACL on %s: %m", path);
+ if (r >= 0)
+ r = k;
+ }
+ }
+
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+int main(int argc, char *argv[]) {
+
+ if (argc < 2) {
+ printf("Usage: %s DEVPATH [SEAT]\n", argv[0]);
+ return 0;
+ }
+
+ elogind_set_program_name(argv[0]);
+ log_set_target(LOG_TARGET_AUTO);
+ log_parse_environment();
+ log_open();
+
+ return dev_uaccess(argv[1], argc > 2 ? argv[2] : NULL);
+}
diff --git a/src/update-utmp/Makefile b/src/update-utmp/Makefile
deleted file mode 120000
index d0b0e8e00..000000000
--- a/src/update-utmp/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/update-utmp/meson.build b/src/update-utmp/meson.build
new file mode 100644
index 000000000..c2070bb9a
--- /dev/null
+++ b/src/update-utmp/meson.build
@@ -0,0 +1,4 @@
+update_utmp_files = files('''
+ update-utmp.c
+ update-utmp.h
+'''.split())
diff --git a/src/update-utmp/update-utmp.c b/src/update-utmp/update-utmp.c
index 5e2d2c60e..d42cf55b6 100644
--- a/src/update-utmp/update-utmp.c
+++ b/src/update-utmp/update-utmp.c
@@ -1,27 +1,10 @@
-/***
- 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/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <string.h>
#include <unistd.h>
-#ifdef HAVE_AUDIT
+#if HAVE_AUDIT
#include <libaudit.h>
#endif
@@ -30,10 +13,12 @@
//#include "alloc-util.h"
#include "bus-error.h"
//#include "bus-util.h"
-//#include "formats-util.h"
+//#include "format-util.h"
//#include "log.h"
//#include "macro.h"
+#include "process-util.h"
//#include "special.h"
+#include "strv.h"
//#include "unit-name.h"
//#include "util.h"
#include "utmp-wtmp.h"
@@ -44,7 +29,7 @@
#include "update-utmp.h"
typedef struct Context {
sd_bus *bus;
-#ifdef HAVE_AUDIT
+#if HAVE_AUDIT
int audit_fd;
#endif
} Context;
@@ -129,7 +114,7 @@ static int on_reboot(Context *c) {
/* We finished start-up, so let's write the utmp
* record and send the audit msg */
-#ifdef HAVE_AUDIT
+#if HAVE_AUDIT
if (c->audit_fd >= 0)
if (audit_log_user_comm_message(c->audit_fd, AUDIT_SYSTEM_BOOT, "", "systemd-update-utmp", NULL, NULL, NULL, 1) < 0 &&
errno != EPERM) {
@@ -162,7 +147,7 @@ static int on_shutdown(Context *c) {
/* We started shut-down, so let's write the utmp
* record and send the audit msg */
-#ifdef HAVE_AUDIT
+#if HAVE_AUDIT
if (c->audit_fd >= 0)
if (audit_log_user_comm_message(c->audit_fd, AUDIT_SYSTEM_SHUTDOWN, "", "systemd-update-utmp", NULL, NULL, NULL, 1) < 0 &&
errno != EPERM) {
@@ -192,7 +177,7 @@ static int on_runlevel(Context *c) {
q = utmp_get_runlevel(&previous, NULL);
if (q < 0) {
- if (q != -ESRCH && q != -ENOENT)
+ if (!IN_SET(q, -ESRCH, -ENOENT))
return log_error_errno(q, "Failed to get current runlevel: %m");
previous = 0;
@@ -207,7 +192,7 @@ static int on_runlevel(Context *c) {
if (previous == runlevel)
return 0;
-#ifdef HAVE_AUDIT
+#if HAVE_AUDIT
if (c->audit_fd >= 0) {
_cleanup_free_ char *s = NULL;
@@ -222,7 +207,7 @@ static int on_runlevel(Context *c) {
#endif
q = utmp_put_runlevel(runlevel, previous);
- if (q < 0 && q != -ESRCH && q != -ENOENT) {
+ if (q < 0 && !IN_SET(q, -ESRCH, -ENOENT)) {
log_error_errno(q, "Failed to write utmp record: %m");
r = q;
}
@@ -234,10 +219,10 @@ static int on_runlevel(Context *c) {
#if 0 /// elogind needs this to be a callable function
int main(int argc, char *argv[]) {
#else
-void update_utmp(int argc, char* argv[], sd_bus *bus) {
+void update_utmp(int argc, char* argv[]) {
#endif // 0
Context c = {
-#ifdef HAVE_AUDIT
+#if HAVE_AUDIT
.audit_fd = -1
#endif
};
@@ -262,14 +247,13 @@ void update_utmp(int argc, char* argv[], sd_bus *bus) {
#else
assert(2 == argc);
assert(argv[1]);
- assert(bus);
#endif // 0
-#ifdef HAVE_AUDIT
+#if HAVE_AUDIT
/* If the kernel lacks netlink or audit support,
* don't worry about it. */
c.audit_fd = audit_open();
- if (c.audit_fd < 0 && errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT)
+ if (c.audit_fd < 0 && !IN_SET(errno, EAFNOSUPPORT, EPROTONOSUPPORT))
log_error_errno(errno, "Failed to connect to audit log: %m");
#endif
#if 0 /// UNNEEDED by elogind
@@ -280,7 +264,7 @@ void update_utmp(int argc, char* argv[], sd_bus *bus) {
goto finish;
}
- log_debug("systemd-update-utmp running as pid "PID_FMT, getpid());
+ log_debug("systemd-update-utmp running as pid "PID_FMT, getpid_cached());
if (streq(argv[1], "reboot"))
r = on_reboot(&c);
@@ -293,23 +277,22 @@ void update_utmp(int argc, char* argv[], sd_bus *bus) {
r = -EINVAL;
}
- log_debug("systemd-update-utmp stopped as pid "PID_FMT, getpid());
+ log_debug("systemd-update-utmp stopped as pid "PID_FMT, getpid_cached());
finish:
#else
- c.bus = bus;
if (streq(argv[1], "reboot"))
(void)on_reboot(&c);
else if (streq(argv[1], "shutdown"))
(void)on_shutdown(&c);
#endif // 0
-#ifdef HAVE_AUDIT
+#if HAVE_AUDIT
if (c.audit_fd >= 0)
audit_close(c.audit_fd);
#endif
- sd_bus_flush_close_unref(c.bus);
#if 0 /// UNNEEDED by elogind
+ sd_bus_flush_close_unref(c.bus);
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
#endif // 0
}
diff --git a/src/update-utmp/update-utmp.h b/src/update-utmp/update-utmp.h
index 7d7d43101..97b046e7e 100644
--- a/src/update-utmp/update-utmp.h
+++ b/src/update-utmp/update-utmp.h
@@ -6,7 +6,7 @@
* Make the old main() from update-utmp.c visible as update_utmp() *
******************************************************************/
-void update_utmp(int argc, char* argv[], sd_bus *bus);
+void update_utmp(int argc, char* argv[]);
#endif // ELOGIND_SRC_UPDATE_UTMP_UPDATE_UTMP_H_INCLUDED
diff --git a/tools/add-git-hook.sh b/tools/add-git-hook.sh
new file mode 100755
index 000000000..c1db99b18
--- /dev/null
+++ b/tools/add-git-hook.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+set -eu
+
+cd "$MESON_SOURCE_ROOT"
+
+if [ ! -f .git/hooks/pre-commit.sample -o -f .git/hooks/pre-commit ]; then
+ exit 2 # not needed
+fi
+
+cp -p .git/hooks/pre-commit.sample .git/hooks/pre-commit
+chmod +x .git/hooks/pre-commit
+echo 'Activated pre-commit hook'
diff --git a/tools/check-includes.pl b/tools/check-includes.pl
index bf23929d4..7f049da6d 100755
--- a/tools/check-includes.pl
+++ b/tools/check-includes.pl
@@ -1,23 +1,46 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
#
# checkincludes: Find files included more than once in (other) files.
# Copyright abandoned, 2000, Niels Kristian Bech Jensen <nkbj@image.dk>.
-foreach $file (@ARGV) {
- open(FILE, $file) or die "Cannot open $file: $!.\n";
+#if 0 // 5 errors and 2 warnings are inaccaptable for elogind - See PerlCritic.
+# foreach $file (@ARGV) {
+# open(FILE, $file) or die "Cannot open $file: $!.\n";
+#
+# my %includedfiles = ();
+#
+# while (<FILE>) {
+# if (m/^\s*#\s*include\s*[<"](\S*)[>"]/o) {
+# ++$includedfiles{$1};
+# }
+# }
+# foreach $filename (keys %includedfiles) {
+# if ($includedfiles{$filename} > 1) {
+# print "$file: $filename is included more than once.\n";
+# }
+# }
+#
+# close(FILE);
+# }
+#else
+use strict;
+use warnings;
+foreach my $file (@ARGV) {
my %includedfiles = ();
- while (<FILE>) {
+ open(my $FILE, "<", $file) or die "Cannot open $file: $!.\n";
+ while (<$FILE>) {
if (m/^\s*#\s*include\s*[<"](\S*)[>"]/o) {
++$includedfiles{$1};
}
}
- foreach $filename (keys %includedfiles) {
+ close($FILE);
+
+ foreach my $filename (keys %includedfiles) {
if ($includedfiles{$filename} > 1) {
print "$file: $filename is included more than once.\n";
}
}
-
- close(FILE);
}
+#endif // 0
diff --git a/tools/find-double-newline.sh b/tools/find-double-newline.sh
new file mode 100644
index 000000000..6a6790b4b
--- /dev/null
+++ b/tools/find-double-newline.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1+
+
+TOP=`git rev-parse --show-toplevel`
+
+case "$1" in
+
+ recdiff)
+ if [ "$2" = "" ] ; then
+ DIR="$TOP"
+ else
+ DIR="$2"
+ fi
+
+ find $DIR -type f \( -name '*.[ch]' -o -name '*.xml' \) -exec $0 diff \{\} \;
+ ;;
+
+ recpatch)
+ if [ "$2" = "" ] ; then
+ DIR="$TOP"
+ else
+ DIR="$2"
+ fi
+
+ find $DIR -type f \( -name '*.[ch]' -o -name '*.xml' \) -exec $0 patch \{\} \;
+ ;;
+
+ diff)
+ T=`mktemp`
+ sed '/^$/N;/^\n$/D' < "$2" > "$T"
+ diff -u "$2" "$T"
+ rm -f "$T"
+ ;;
+
+ patch)
+ sed -i '/^$/N;/^\n$/D' "$2"
+ ;;
+
+ *)
+ echo "Expected recdiff|recpatch|diff|patch as verb." >&2
+ ;;
+esac
diff --git a/tools/gdb-sd_dump_hashmaps.py b/tools/gdb-sd_dump_hashmaps.py
index 62ce8006f..27572bebb 100644..100755
--- a/tools/gdb-sd_dump_hashmaps.py
+++ b/tools/gdb-sd_dump_hashmaps.py
@@ -1,27 +1,11 @@
#!/usr/bin/env python3
# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
-#
-# This file is part of systemd.
-#
-# Copyright 2014 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/>.
+# SPDX-License-Identifier: LGPL-2.1+
import gdb
class sd_dump_hashmaps(gdb.Command):
- "dump systemd's hashmaps"
+ "dump elogind's hashmaps"
def __init__(self):
super(sd_dump_hashmaps, self).__init__("sd_dump_hashmaps", gdb.COMMAND_DATA, gdb.COMPLETE_NONE)
@@ -50,7 +34,7 @@ class sd_dump_hashmaps(gdb.Command):
t = ["plain", "ordered", "set"][int(h["type"])]
- print "%s, %s, %s, %d, %d, %d, %s (%s:%d)" % (t, h["hash_ops"], bool(h["has_indirect"]), n_entries, d["max_entries"], n_buckets, d["func"], d["file"], d["line"])
+ print "{}, {}, {}, {}, {}, {}, {} ({}:{})".format(t, h["hash_ops"], bool(h["has_indirect"]), n_entries, d["max_entries"], n_buckets, d["func"], d["file"], d["line"])
if arg != "" and n_entries > 0:
dib_raw_addr = storage_ptr + (all_entry_sizes[h["type"]] * n_buckets)
@@ -62,10 +46,10 @@ class sd_dump_hashmaps(gdb.Command):
for dib in sorted(iter(histogram)):
if dib != 255:
- print "%3d %8d %f%% of entries" % (dib, histogram[dib], 100.0*histogram[dib]/n_entries)
+ print "{:>3} {:>8} {} of entries".format(dib, histogram[dib], 100.0*histogram[dib]/n_entries)
else:
- print "%3d %8d %f%% of slots" % (dib, histogram[dib], 100.0*histogram[dib]/n_buckets)
- print "mean DIB of entries: %f" % (sum([dib*histogram[dib] for dib in iter(histogram) if dib != 255])*1.0/n_entries)
+ print "{:>3} {:>8} {} of slots".format(dib, histogram[dib], 100.0*histogram[dib]/n_buckets)
+ print "mean DIB of entries: {}".format(sum([dib*histogram[dib] for dib in iter(histogram) if dib != 255])*1.0/n_entries)
blocks = []
current_len = 1
@@ -86,9 +70,9 @@ class sd_dump_hashmaps(gdb.Command):
if len(blocks) > 1 and blocks[0][0] == blocks[0][1] and blocks[-1][0] == n_buckets - 1:
blocks[0][1] += blocks[-1][1]
blocks = blocks[0:-1]
- print "max block: %s" % max(blocks, key=lambda a: a[1])
- print "sum block lens: %d" % sum(b[1] for b in blocks)
- print "mean block len: %f" % (1.0 * sum(b[1] for b in blocks) / len(blocks))
+ print "max block: {}".format(max(blocks, key=lambda a: a[1]))
+ print "sum block lens: {}".format(sum(b[1] for b in blocks))
+ print "mean block len: {}".format((1.0 * sum(b[1] for b in blocks) / len(blocks)))
d = d["debug_list_next"]
diff --git a/tools/make-directive-index.py b/tools/make-directive-index.py
index 193f7416f..620a67e97 100755
--- a/tools/make-directive-index.py
+++ b/tools/make-directive-index.py
@@ -1,26 +1,11 @@
+#!/usr/bin/env python3
# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
-#
-# This file is part of elogind.
-#
-# Copyright 2012-2013 Zbigniew Jędrzejewski-Szmek
-#
-# elogind is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# elogind is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with elogind; If not, see <http://www.gnu.org/licenses/>.
+# SPDX-License-Identifier: LGPL-2.1+
import sys
import collections
import re
-from xml_helper import *
+from xml_helper import xml_parse, xml_print, tree
from copy import deepcopy
TEMPLATE = '''\
@@ -29,15 +14,6 @@ TEMPLATE = '''\
<refentryinfo>
<title>elogind.directives</title>
<productname>elogind</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Zbigniew</firstname>
- <surname>Jędrzejewski-Szmek</surname>
- <email>zbyszek@in.waw.pl</email>
- </author>
- </authorgroup>
</refentryinfo>
<refmeta>
@@ -51,6 +27,24 @@ TEMPLATE = '''\
</refnamediv>
<refsect1>
+ <title>Unit directives</title>
+
+ <para>Directives for configuring units, used in unit
+ files.</para>
+
+ <variablelist id='unit-directives' />
+ </refsect1>
+
+ <refsect1>
+ <title>Options on the kernel command line</title>
+
+ <para>Kernel boot options for configuring the behaviour of the
+ elogind process.</para>
+
+ <variablelist id='kernel-commandline-options' />
+ </refsect1>
+
+ <refsect1>
<title>Environment variables</title>
<para>Environment variables understood by the elogind
@@ -60,6 +54,33 @@ TEMPLATE = '''\
</refsect1>
<refsect1>
+ <title>UDEV directives</title>
+
+ <para>Directives for configuring elogind units through the
+ udev database.</para>
+
+ <variablelist id='udev-directives' />
+ </refsect1>
+
+ <refsect1>
+ <title>Network directives</title>
+
+ <para>Directives for configuring network links through the
+ net-setup-link udev builtin and networks through
+ elogind-networkd.</para>
+
+ <variablelist id='network-directives' />
+ </refsect1>
+
+ <refsect1>
+ <title>Journal fields</title>
+
+ <para>Fields in the journal events with a well known meaning.</para>
+
+ <variablelist id='journal-directives' />
+ </refsect1>
+
+ <refsect1>
<title>PAM configuration directives</title>
<para>Directives for configuring PAM behaviour.</para>
@@ -68,6 +89,25 @@ TEMPLATE = '''\
</refsect1>
<refsect1>
+ <title><filename>/etc/crypttab</filename> and
+ <filename>/etc/fstab</filename> options</title>
+
+ <para>Options which influence mounted filesystems and
+ encrypted volumes.</para>
+
+ <variablelist id='fstab-options' />
+ </refsect1>
+
+ <refsect1>
+ <title>System manager directives</title>
+
+ <para>Directives for configuring the behaviour of the
+ elogind process.</para>
+
+ <variablelist id='elogind-directives' />
+ </refsect1>
+
+ <refsect1>
<title>command line options</title>
<para>Command-line options accepted by programs in the
diff --git a/tools/make-man-index.py b/tools/make-man-index.py
index d07308005..246ce5f8e 100755
--- a/tools/make-man-index.py
+++ b/tools/make-man-index.py
@@ -1,28 +1,11 @@
#!/usr/bin/env python3
# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
-#
-# This file is part of systemd.
-#
-# Copyright 2012 Lennart Poettering
-# Copyright 2013 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/>.
+# SPDX-License-Identifier: LGPL-2.1+
import collections
import sys
import re
-from xml_helper import *
+from xml_helper import xml_parse, xml_print, tree
MDASH = ' — ' if sys.version_info.major >= 3 else ' -- '
@@ -32,15 +15,14 @@ TEMPLATE = '''\
<refentryinfo>
<title>elogind.index</title>
<productname>elogind</productname>
-
- <authorgroup>
+ <!-- 1 /// Must add elogind authors for the additions and changes -->
<author>
<contrib>Developer</contrib>
- <firstname>Lennart</firstname>
- <surname>Poettering</surname>
- <email>lennart@poettering.net</email>
+ <firstname>Sven</firstname>
+ <surname>Eden</surname>
+ <email>sven.eden@gmx.de</email>
</author>
- </authorgroup>
+ <!-- // 1 -->
</refentryinfo>
<refmeta>
diff --git a/tools/make-man-rules.py b/tools/make-man-rules.py
index e9e39f10a..42a48bc98 100755
--- a/tools/make-man-rules.py
+++ b/tools/make-man-rules.py
@@ -1,79 +1,19 @@
#!/usr/bin/env python3
# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
-#
-# This file is part of systemd.
-#
-# Copyright 2013, 2017 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/>.
+# SPDX-License-Identifier: LGPL-2.1+
from __future__ import print_function
import collections
import sys
import os.path
import pprint
-from xml_helper import *
-
-SECTION = '''\
-MANPAGES += \\
- {manpages}
-MANPAGES_ALIAS += \\
- {aliases}
-{rules}
-{htmlrules}
-'''
-
-CONDITIONAL = '''\
-if {conditional}
-''' \
-+ SECTION + \
-'''\
-endif
-'''
-
-HEADER = '''\
-# Do not edit. Generated by make-man-rules.py.
-# To regenerate:
-# 1. Create, update, or remove source .xml files in man/
-# 2. Run 'make update-man-list'
-# 3. Run 'make man' to generate manpages
-#
-# To make a man page conditional on a configure switch add
-# attribute conditional="ENABLE_WHAT" or conditional="WITH_WHAT"
-# to <refentry> element.
-'''
-
-HTML_ALIAS_RULE = '''\
-{}.html: {}.html
- $(html-alias)
-'''
-
-FOOTER = '''\
-
-# Really, do not edit this file.
-
-EXTRA_DIST += \\
- {dist_files}
-'''
-
-meson = False
+from xml_helper import xml_parse
def man(page, number):
- return ('man/' if not meson else '') + '{}.{}'.format(page, number)
+ return '{}.{}'.format(page, number)
def xml(file):
- return ('man/' if not meson else '') + os.path.basename(file)
+ return os.path.basename(file)
def add_rules(rules, name):
xml = xml_parse(name)
@@ -110,21 +50,6 @@ def create_rules(xml_files):
def mjoin(files):
return ' \\\n\t'.join(sorted(files) or '#')
-def make_makefile(rules, dist_files):
- return HEADER + '\n'.join(
- (CONDITIONAL if conditional else SECTION).format(
- manpages=mjoin(set(rulegroup.values())),
- aliases=mjoin(k for k,v in rulegroup.items() if k != v),
- rules='\n'.join('{}: {}'.format(k,v)
- for k,v in sorted(rulegroup.items())
- if k != v),
- htmlrules='\n'.join(HTML_ALIAS_RULE.format(k[:-2],v[:-2])
- for k,v in sorted(rulegroup.items())
- if k != v),
- conditional=conditional)
- for conditional,rulegroup in sorted(rules.items())
- ) + FOOTER.format(dist_files=mjoin(sorted(dist_files)))
-
MESON_HEADER = '''\
# Do not edit. Generated by make-man-rules.py.
manpages = ['''
@@ -151,14 +76,10 @@ def make_mesonfile(rules, dist_files):
return '\n'.join((MESON_HEADER, pprint.pformat(lines)[1:-1], MESON_FOOTER))
if __name__ == '__main__':
- meson = sys.argv[1] == '--meson'
- pages = sys.argv[1+meson:]
+ pages = sys.argv[1:]
rules = create_rules(pages)
dist_files = (xml(file) for file in pages
if not file.endswith(".directives.xml") and
not file.endswith(".index.xml"))
- if meson:
- print(make_mesonfile(rules, dist_files))
- else:
- print(make_makefile(rules, dist_files), end='')
+ print(make_mesonfile(rules, dist_files))
diff --git a/tools/meson-apply-m4.sh b/tools/meson-apply-m4.sh
new file mode 100644
index 000000000..6abe177ac
--- /dev/null
+++ b/tools/meson-apply-m4.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+set -eu
+
+CONFIG=$1
+TARGET=$2
+
+if [ $# -ne 2 ]; then
+ echo 'Invalid number of arguments.'
+ exit 1
+fi
+
+if [ ! -f $CONFIG ]; then
+ echo "$CONFIG not found."
+ exit 2
+fi
+
+if [ ! -f $TARGET ]; then
+ echo "$TARGET not found."
+ exit 3
+fi
+
+DEFINES=$(awk '$1 == "#define" && $3 == "1" { printf "-D%s ", $2 }' $CONFIG)
+
+m4 -P $DEFINES $TARGET
diff --git a/tools/meson-build.sh b/tools/meson-build.sh
new file mode 100755
index 000000000..304a75567
--- /dev/null
+++ b/tools/meson-build.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+set -eux
+
+src="$1"
+dst="$2"
+target="$3"
+options="$4"
+
+[ -d "$dst" ] || meson "$src" "$dst" $options
+
+# Locate ninja binary, on CentOS 7 it is called ninja-build, so
+# use that name if available.
+ninja=ninja
+if which ninja-build >/dev/null 2>&1 ; then
+ ninja=ninja-build
+fi
+
+"$ninja" -C "$dst" "$target"
diff --git a/tools/meson-check-api-docs.sh b/tools/meson-check-api-docs.sh
new file mode 100755
index 000000000..5bc808c1e
--- /dev/null
+++ b/tools/meson-check-api-docs.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+set -eu
+
+for symbol in `nm -g --defined-only "$@" | grep " T " | cut -d" " -f3 | sort -u` ; do
+ if test -f ${MESON_BUILD_ROOT}/man/$symbol.3 ; then
+ echo "✓ Symbol $symbol() is documented."
+ else
+ printf " \x1b[1;31mSymbol $symbol() lacks documentation.\x1b[0m\n"
+ fi
+done
diff --git a/tools/meson-check-compilation.sh b/tools/meson-check-compilation.sh
new file mode 100755
index 000000000..ce39e1684
--- /dev/null
+++ b/tools/meson-check-compilation.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+set -eu
+
+"$@" '-' -o/dev/null </dev/null
diff --git a/tools/meson-check-help.sh b/tools/meson-check-help.sh
new file mode 100755
index 000000000..69157105f
--- /dev/null
+++ b/tools/meson-check-help.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+set -eu
+
+export SYSTEMD_LOG_LEVEL=info
+
+# output width
+if "$1" --help | grep -v 'default:' | grep -E -q '.{80}.'; then
+ echo "$(basename "$1") --help output is too wide:"
+ "$1" --help | awk 'length > 80' | grep -E --color=yes '.{80}'
+ exit 1
+fi
+
+# no --help output to stdout
+if "$1" --help 2>&1 1>/dev/null | grep .; then
+ echo "$(basename "$1") --help prints to stderr"
+ exit 2
+fi
+
+# error output to stderr
+if ! "$1" --no-such-parameter 2>&1 1>/dev/null | grep -q .; then
+ echo "$(basename "$1") with an unknown parameter does not print to stderr"
+ exit 3
+fi
diff --git a/tools/meson-get-cg-controller.sh b/tools/meson-get-cg-controller.sh
new file mode 100755
index 000000000..98ba37a7f
--- /dev/null
+++ b/tools/meson-get-cg-controller.sh
@@ -0,0 +1,18 @@
+#!/bin/sh -eu
+
+if test -f /proc/self/cgroup; then
+ # If the init system is a cgroup controler, it will be position 1.
+ # Secondary controllers, like cgmanager, do not work.
+ with_cgroupctrl=$(grep "^1:name=" /proc/self/cgroup | \
+ sed -n 's/.*=//p' | sed -e 's/:.*$//')
+ if test -z "$with_cgroupctrl"; then
+ # Try to be our own cgroup controller
+ with_cgroupctrl="elogind"
+ fi
+else
+ # 'auto' but no cgroup fs is a problem.
+ with_cgroupctrl=""
+fi
+
+echo "$with_cgroupctrl"
+exit 0
diff --git a/tools/meson-git-contrib.sh b/tools/meson-git-contrib.sh
new file mode 100755
index 000000000..514daa094
--- /dev/null
+++ b/tools/meson-git-contrib.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+set -eu
+
+git shortlog -s `git describe --abbrev=0`.. | \
+ cut -c8- | \
+ sed 's/ / /g' | \
+ awk '{ print $$0 "," }' | \
+ sed -e 's/ / /g' | \
+ sort -u
diff --git a/tools/meson-link-test.c b/tools/meson-link-test.c
new file mode 100644
index 000000000..825bbff05
--- /dev/null
+++ b/tools/meson-link-test.c
@@ -0,0 +1 @@
+int main(void) {return 0;}
diff --git a/tools/meson-symlink_headers.sh b/tools/meson-symlink_headers.sh
new file mode 100755
index 000000000..32388d06f
--- /dev/null
+++ b/tools/meson-symlink_headers.sh
@@ -0,0 +1,9 @@
+#!/bin/sh -eu
+
+INCDIR="$1"
+shift 1
+
+while [ $# -gt 0 ] ; do
+ ln -vfs "systemd/$1" "${DESTDIR:-}/${INCDIR}/elogind/$1"
+ shift 1
+done
diff --git a/tools/xml_helper.py b/tools/xml_helper.py
index 0088be5bd..19e343b4e 100755
--- a/tools/xml_helper.py
+++ b/tools/xml_helper.py
@@ -1,22 +1,6 @@
#!/usr/bin/env python3
# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
-#
-# This file is part of systemd.
-#
-# Copyright 2012-2013 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/>.
+# SPDX-License-Identifier: LGPL-2.1+
from lxml import etree as tree
@@ -27,9 +11,11 @@ class CustomResolver(tree.Resolver):
_parser = tree.XMLParser()
_parser.resolvers.add(CustomResolver())
+
def xml_parse(page):
doc = tree.parse(page, _parser)
doc.xinclude()
return doc
+
def xml_print(xml):
return tree.tostring(xml, pretty_print=True, encoding='utf-8')