summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Sherwood <paul.sherwood@codethink.co.uk>2013-11-17 18:32:22 +0000
committerPaul Sherwood <paul.sherwood@codethink.co.uk>2013-11-17 18:32:22 +0000
commitaf04dc70741e58c16a3b2c003ef9779d7863827c (patch)
tree23b608397f1ccb73a34d5fa7cc8d6377554f952f
parentdc8ee9a30e2df2568f2b37e3fb61e4b0bb601b13 (diff)
parent1434ae6fd49f8377b0ddbd4c675736e0d3226ea6 (diff)
downloadsystemd-baserock/ps/update-linux-v3.12-systemd-v208.tar.gz
systemd 208
-rw-r--r--.gitignore24
-rw-r--r--.travis.yml14
-rw-r--r--.ycm_extra_conf.py81
-rw-r--r--Makefile-man.am80
-rw-r--r--Makefile.am895
-rw-r--r--NEWS429
-rw-r--r--README19
-rw-r--r--TODO251
-rwxr-xr-xautogen.sh2
-rw-r--r--catalog/systemd.catalog20
-rw-r--r--configure.ac213
-rw-r--r--hwdb/20-OUI.hwdb2985
-rw-r--r--hwdb/20-acpi-vendor.hwdb3
-rw-r--r--hwdb/20-pci-vendor-model.hwdb5169
-rw-r--r--hwdb/20-usb-vendor-model.hwdb869
-rw-r--r--hwdb/60-keyboard.hwdb1088
l---------hwdb/Makefile1
-rw-r--r--keymaps-force-release/common-volume-keys3
-rw-r--r--keymaps-force-release/dell-touchpad1
-rw-r--r--keymaps-force-release/dell-xps1
-rw-r--r--keymaps-force-release/hp-other3
-rw-r--r--keymaps-force-release/samsung-other10
-rw-r--r--keymaps-force-release/samsung-series-96
-rw-r--r--keymaps/acer22
-rw-r--r--keymaps/acer-aspire_57205
-rw-r--r--keymaps/acer-aspire_5920g5
-rw-r--r--keymaps/acer-aspire_69205
-rw-r--r--keymaps/acer-aspire_89305
-rw-r--r--keymaps/acer-travelmate_c3005
-rw-r--r--keymaps/asus3
-rw-r--r--keymaps/compaq-e_evo4
-rw-r--r--keymaps/dell29
-rw-r--r--keymaps/dell-latitude-xt24
-rw-r--r--keymaps/everex-xt50007
-rw-r--r--keymaps/fujitsu-amilo_li_27323
-rw-r--r--keymaps/fujitsu-amilo_pa_25483
-rw-r--r--keymaps/fujitsu-amilo_pro_edition_v35054
-rw-r--r--keymaps/fujitsu-amilo_pro_v32052
-rw-r--r--keymaps/fujitsu-amilo_si_15206
-rw-r--r--keymaps/fujitsu-esprimo_mobile_v54
-rw-r--r--keymaps/fujitsu-esprimo_mobile_v62
-rw-r--r--keymaps/genius-slimstar-32035
-rw-r--r--keymaps/hewlett-packard12
-rw-r--r--keymaps/hewlett-packard-2510p_2530p2
-rw-r--r--keymaps/hewlett-packard-compaq_elitebook2
-rw-r--r--keymaps/hewlett-packard-hdx9494nr3
-rw-r--r--keymaps/hewlett-packard-pavilion3
-rw-r--r--keymaps/hewlett-packard-presario-21003
-rw-r--r--keymaps/hewlett-packard-tablet6
-rw-r--r--keymaps/hewlett-packard-tx23
-rw-r--r--keymaps/hewlett-packard_elitebook-8440p5
-rw-r--r--keymaps/hewlett-packard_elitebook-8460p3
-rw-r--r--keymaps/ibm-thinkpad-usb-keyboard-trackpoint7
-rw-r--r--keymaps/inventec-symphony_6.0_7.02
-rw-r--r--keymaps/lenovo-30005
-rw-r--r--keymaps/lenovo-ideapad8
-rw-r--r--keymaps/lenovo-thinkpad-usb-keyboard-trackpoint13
-rw-r--r--keymaps/lenovo-thinkpad_x200_tablet6
-rw-r--r--keymaps/lenovo-thinkpad_x6_tablet8
-rw-r--r--keymaps/lg-x11012
-rw-r--r--keymaps/logitech-wave16
-rw-r--r--keymaps/logitech-wave-cordless15
-rw-r--r--keymaps/logitech-wave-pro-cordless12
-rw-r--r--keymaps/maxdata-pro_70009
-rw-r--r--keymaps/medion-fid20602
-rw-r--r--keymaps/medionnb-a5554
-rw-r--r--keymaps/micro-star13
-rw-r--r--keymaps/module-asus-w3j11
-rw-r--r--keymaps/module-ibm16
-rw-r--r--keymaps/module-lenovo17
-rw-r--r--keymaps/module-sony8
-rw-r--r--keymaps/module-sony-old2
-rw-r--r--keymaps/module-sony-vgn8
-rw-r--r--keymaps/module-sony-vpc4
-rw-r--r--keymaps/olpc-xo74
-rw-r--r--keymaps/onkyo14
-rw-r--r--keymaps/oqo-model25
-rw-r--r--keymaps/samsung-other14
-rw-r--r--keymaps/samsung-series-95
-rw-r--r--keymaps/samsung-sq1us7
-rw-r--r--keymaps/samsung-sx20s4
-rw-r--r--keymaps/toshiba-satellite_a1002
-rw-r--r--keymaps/toshiba-satellite_a11010
-rw-r--r--keymaps/toshiba-satellite_m30x6
-rw-r--r--keymaps/zepto-znote11
-rw-r--r--m4/attributes.m424
-rwxr-xr-xmake-directive-index.py38
-rw-r--r--man/binfmt.d.xml14
-rw-r--r--man/bootchart.conf.xml8
-rw-r--r--man/bootup.xml27
-rw-r--r--man/crypttab.xml308
-rw-r--r--man/custom-html.xsl6
-rw-r--r--man/custom-man.xsl9
-rw-r--r--man/daemon.xml144
-rw-r--r--man/halt.xml8
-rw-r--r--man/hostname.xml16
-rw-r--r--man/hostnamectl.xml78
-rw-r--r--man/journalctl.xml421
-rw-r--r--man/journald.conf.xml146
-rw-r--r--man/kernel-command-line.xml43
-rw-r--r--man/kernel-install.xml8
-rw-r--r--man/locale.conf.xml6
-rw-r--r--man/localectl.xml27
-rw-r--r--man/localtime.xml14
-rw-r--r--man/loginctl.xml86
-rw-r--r--man/logind.conf.xml148
-rw-r--r--man/machine-id.xml28
-rw-r--r--man/machine-info.xml12
-rw-r--r--man/machinectl.xml301
-rw-r--r--man/modules-load.d.xml4
-rw-r--r--man/nss-myhostname.xml14
-rw-r--r--man/os-release.xml30
-rw-r--r--man/pam_systemd.xml148
-rw-r--r--man/runlevel.xml2
-rw-r--r--man/sd-daemon.xml5
-rw-r--r--man/sd-id128.xml35
-rw-r--r--man/sd-journal.xml3
-rw-r--r--man/sd-login.xml7
-rw-r--r--man/sd_booted.xml5
-rw-r--r--man/sd_get_seats.xml7
-rw-r--r--man/sd_id128_get_machine.xml13
-rw-r--r--man/sd_id128_randomize.xml16
-rw-r--r--man/sd_id128_to_string.xml30
-rw-r--r--man/sd_is_fifo.xml48
-rw-r--r--man/sd_journal_add_match.xml15
-rw-r--r--man/sd_journal_get_catalog.xml9
-rw-r--r--man/sd_journal_get_cursor.xml5
-rw-r--r--man/sd_journal_get_cutoff_realtime_usec.xml24
-rw-r--r--man/sd_journal_get_data.xml7
-rw-r--r--man/sd_journal_get_fd.xml55
-rw-r--r--man/sd_journal_get_realtime_usec.xml36
-rw-r--r--man/sd_journal_get_usage.xml7
-rw-r--r--man/sd_journal_next.xml3
-rw-r--r--man/sd_journal_open.xml85
-rw-r--r--man/sd_journal_print.xml35
-rw-r--r--man/sd_journal_query_unique.xml3
-rw-r--r--man/sd_journal_seek_head.xml25
-rw-r--r--man/sd_journal_stream_fd.xml23
-rw-r--r--man/sd_listen_fds.xml21
-rw-r--r--man/sd_login_monitor_new.xml33
-rw-r--r--man/sd_notify.xml15
-rw-r--r--man/sd_pid_get_session.xml51
-rw-r--r--man/sd_readahead.xml2
-rw-r--r--man/sd_seat_get_active.xml29
-rw-r--r--man/sd_session_is_active.xml27
-rw-r--r--man/sd_uid_get_state.xml13
-rw-r--r--man/shutdown.xml11
-rw-r--r--man/sysctl.d.xml16
-rw-r--r--man/systemctl.xml1601
-rw-r--r--man/systemd-activate.xml4
-rw-r--r--man/systemd-analyze.xml116
-rw-r--r--man/systemd-ask-password.xml4
-rw-r--r--man/systemd-backlight@.service.xml73
-rw-r--r--man/systemd-bootchart.xml2
-rw-r--r--man/systemd-cat.xml8
-rw-r--r--man/systemd-cgls.xml17
-rw-r--r--man/systemd-cgtop.xml40
-rw-r--r--man/systemd-coredumpctl.xml4
-rw-r--r--man/systemd-cryptsetup-generator.xml27
-rw-r--r--man/systemd-delta.xml9
-rw-r--r--man/systemd-detect-virt.xml7
-rw-r--r--man/systemd-efi-boot-generator.xml88
-rw-r--r--man/systemd-fsck@.service.xml2
-rw-r--r--man/systemd-fstab-generator.xml2
-rw-r--r--man/systemd-gpt-auto-generator.xml104
-rw-r--r--man/systemd-halt.service.xml10
-rw-r--r--man/systemd-hostnamed.service.xml8
-rw-r--r--man/systemd-inhibit.xml16
-rw-r--r--man/systemd-journald.service.xml71
-rw-r--r--man/systemd-logind.service.xml10
-rw-r--r--man/systemd-machine-id-setup.xml4
-rw-r--r--man/systemd-machined.service.xml85
-rw-r--r--man/systemd-modules-load.service.xml5
-rw-r--r--man/systemd-notify.xml6
-rw-r--r--man/systemd-nspawn.xml63
-rw-r--r--man/systemd-random-seed.service.xml (renamed from man/systemd-random-seed-load.service.xml)21
-rw-r--r--man/systemd-readahead-replay.service.xml26
-rw-r--r--man/systemd-run.xml219
-rw-r--r--man/systemd-suspend.service.xml16
-rw-r--r--man/systemd-sysctl.service.xml1
-rw-r--r--man/systemd-system.conf.xml71
-rw-r--r--man/systemd-timedated.service.xml4
-rw-r--r--man/systemd-tmpfiles.xml20
-rw-r--r--man/systemd-udevd.service.xml2
-rw-r--r--man/systemd-update-utmp.service.xml (renamed from man/systemd-update-utmp-runlevel.service.xml)16
-rw-r--r--man/systemd.automount.xml14
-rw-r--r--man/systemd.device.xml8
-rw-r--r--man/systemd.exec.xml535
-rw-r--r--man/systemd.journal-fields.xml263
-rw-r--r--man/systemd.kill.xml46
-rw-r--r--man/systemd.mount.xml41
-rw-r--r--man/systemd.path.xml12
-rw-r--r--man/systemd.preset.xml27
-rw-r--r--man/systemd.resource-control.xml353
-rw-r--r--man/systemd.scope.xml100
-rw-r--r--man/systemd.service.xml118
-rw-r--r--man/systemd.slice.xml121
-rw-r--r--man/systemd.snapshot.xml4
-rw-r--r--man/systemd.socket.xml112
-rw-r--r--man/systemd.special.xml76
-rw-r--r--man/systemd.swap.xml18
-rw-r--r--man/systemd.target.xml2
-rw-r--r--man/systemd.time.xml83
-rw-r--r--man/systemd.timer.xml8
-rw-r--r--man/systemd.unit.xml266
-rw-r--r--man/systemd.xml193
-rw-r--r--man/telinit.xml2
-rw-r--r--man/timedatectl.xml34
-rw-r--r--man/tmpfiles.d.xml118
-rw-r--r--man/udev.xml178
-rw-r--r--po/POTFILES.skip2
-rw-r--r--rules/60-keyboard.rules22
-rw-r--r--rules/75-net-description.rules4
-rw-r--r--rules/75-tty-description.rules3
-rw-r--r--rules/80-drivers.rules2
-rw-r--r--rules/80-net-name-slot.rules2
-rw-r--r--rules/99-systemd.rules.in6
l---------rules/Makefile1
-rw-r--r--shell-completion/bash/hostnamectl7
-rw-r--r--shell-completion/bash/journalctl17
-rw-r--r--shell-completion/bash/kernel-install50
-rw-r--r--shell-completion/bash/localectl7
-rw-r--r--shell-completion/bash/loginctl7
-rw-r--r--shell-completion/bash/systemctl24
-rw-r--r--shell-completion/bash/systemd-analyze16
-rw-r--r--shell-completion/bash/systemd-coredumpctl7
-rw-r--r--shell-completion/bash/systemd-run63
-rw-r--r--shell-completion/bash/timedatectl7
-rw-r--r--shell-completion/bash/udevadm104
-rw-r--r--shell-completion/systemd-zsh-completion.zsh1052
-rw-r--r--shell-completion/zsh/_hostnamectl32
-rw-r--r--shell-completion/zsh/_journalctl98
-rw-r--r--shell-completion/zsh/_kernel-install26
-rw-r--r--shell-completion/zsh/_localectl83
-rw-r--r--shell-completion/zsh/_loginctl106
-rw-r--r--shell-completion/zsh/_machinectl47
-rw-r--r--shell-completion/zsh/_sd_hosts_or_user_at_host5
-rw-r--r--shell-completion/zsh/_systemctl347
-rw-r--r--shell-completion/zsh/_systemd83
-rw-r--r--shell-completion/zsh/_systemd-analyze43
-rw-r--r--shell-completion/zsh/_systemd-coredumpctl36
-rw-r--r--shell-completion/zsh/_systemd-delta15
-rw-r--r--shell-completion/zsh/_systemd-inhibit33
-rw-r--r--shell-completion/zsh/_systemd-nspawn24
-rw-r--r--shell-completion/zsh/_systemd-tmpfiles10
-rw-r--r--shell-completion/zsh/_timedatectl65
-rw-r--r--shell-completion/zsh/_udevadm141
-rw-r--r--src/.gitignore2
-rw-r--r--src/activate/activate.c9
-rw-r--r--src/analyze/systemd-analyze.c255
l---------src/backlight/Makefile (renamed from src/timestamp/Makefile)0
-rw-r--r--src/backlight/backlight.c132
-rw-r--r--src/boot/boot-efi.c2
-rw-r--r--src/bootchart/bootchart.c2
-rw-r--r--src/bootchart/bootchart.h2
-rw-r--r--[-rwxr-xr-x]src/bootchart/store.c2
-rw-r--r--src/bootchart/store.h2
-rw-r--r--src/bootchart/svg.c2
-rw-r--r--src/bootchart/svg.h2
-rw-r--r--src/cgls/cgls.c22
-rw-r--r--src/cgroups-agent/cgroups-agent.c19
-rw-r--r--src/cgtop/cgtop.c6
-rw-r--r--src/core/async.c (renamed from src/core/sync.c)23
-rw-r--r--src/core/async.h (renamed from src/core/sync.h)1
-rw-r--r--src/core/automount.c39
-rw-r--r--src/core/automount.h2
-rw-r--r--src/core/bus-errors.h1
-rw-r--r--src/core/cgroup-attr.c132
-rw-r--r--src/core/cgroup-attr.h50
-rw-r--r--src/core/cgroup-semantics.c333
-rw-r--r--src/core/cgroup-semantics.h43
-rw-r--r--src/core/cgroup.c917
-rw-r--r--src/core/cgroup.h115
-rw-r--r--src/core/condition.c43
-rw-r--r--src/core/condition.h8
-rw-r--r--src/core/dbus-cgroup.c554
-rw-r--r--src/core/dbus-cgroup.h45
-rw-r--r--src/core/dbus-execute.c35
-rw-r--r--src/core/dbus-execute.h18
-rw-r--r--src/core/dbus-job.c53
-rw-r--r--src/core/dbus-kill.c76
-rw-r--r--src/core/dbus-kill.h8
-rw-r--r--src/core/dbus-manager.c359
-rw-r--r--src/core/dbus-mount.c47
-rw-r--r--src/core/dbus-mount.h3
-rw-r--r--src/core/dbus-scope.c189
-rw-r--r--src/core/dbus-scope.h33
-rw-r--r--src/core/dbus-service.c193
-rw-r--r--src/core/dbus-service.h3
-rw-r--r--src/core/dbus-slice.c93
-rw-r--r--src/core/dbus-slice.h33
-rw-r--r--src/core/dbus-socket.c51
-rw-r--r--src/core/dbus-socket.h3
-rw-r--r--src/core/dbus-swap.c46
-rw-r--r--src/core/dbus-swap.h3
-rw-r--r--src/core/dbus-unit.c816
-rw-r--r--src/core/dbus-unit.h48
-rw-r--r--src/core/dbus.c141
-rw-r--r--src/core/dbus.h6
-rw-r--r--src/core/execute.c191
-rw-r--r--src/core/execute.h17
-rw-r--r--src/core/job.c9
-rw-r--r--src/core/kill.c7
-rw-r--r--src/core/kill.h1
-rw-r--r--src/core/killall.c5
-rw-r--r--src/core/load-fragment-gperf.gperf.m441
-rw-r--r--src/core/load-fragment.c751
-rw-r--r--src/core/load-fragment.h11
-rw-r--r--src/core/locale-setup.c44
-rw-r--r--src/core/locale-setup.h2
-rw-r--r--src/core/macros.systemd.in5
-rw-r--r--src/core/main.c197
-rw-r--r--src/core/manager.c294
-rw-r--r--src/core/manager.h41
-rw-r--r--src/core/mount-setup.c10
-rw-r--r--src/core/mount.c350
-rw-r--r--src/core/mount.h4
-rw-r--r--src/core/namespace.c12
-rw-r--r--src/core/org.freedesktop.systemd1.conf4
-rw-r--r--src/core/path.c32
-rw-r--r--src/core/path.h4
-rw-r--r--src/core/scope.c482
-rw-r--r--src/core/scope.h69
-rw-r--r--src/core/selinux-access.c8
-rw-r--r--src/core/selinux-access.h8
-rw-r--r--src/core/service.c180
-rw-r--r--src/core/service.h2
-rw-r--r--src/core/shutdown.c18
-rw-r--r--src/core/slice.c322
-rw-r--r--src/core/slice.h46
-rw-r--r--src/core/smack-setup.c12
-rw-r--r--src/core/snapshot.c34
-rw-r--r--src/core/snapshot.h1
-rw-r--r--src/core/socket.c131
-rw-r--r--src/core/socket.h9
-rw-r--r--src/core/special.h6
-rw-r--r--src/core/swap.c86
-rw-r--r--src/core/swap.h3
-rw-r--r--src/core/system.conf4
-rw-r--r--src/core/systemd.pc.in3
-rw-r--r--src/core/transaction.c18
-rw-r--r--src/core/unit-printf.c216
-rw-r--r--src/core/unit-printf.h6
-rw-r--r--src/core/unit.c1013
-rw-r--r--src/core/unit.h89
-rw-r--r--src/core/user.conf1
-rw-r--r--src/cryptsetup/cryptsetup-generator.c95
-rw-r--r--src/cryptsetup/cryptsetup.c443
-rw-r--r--src/delta/delta.c215
-rw-r--r--src/efi-boot-generator/efi-boot-generator.c2
-rw-r--r--src/fstab-generator/fstab-generator.c149
-rw-r--r--src/getty-generator/getty-generator.c37
l---------src/gpt-auto-generator/Makefile1
-rw-r--r--src/gpt-auto-generator/gpt-auto-generator.c527
-rw-r--r--src/hostname/hostnamectl.c118
-rw-r--r--src/hostname/hostnamed.c3
-rw-r--r--src/initctl/initctl.c12
-rw-r--r--src/journal/coredump.c13
-rw-r--r--src/journal/coredumpctl.c10
-rw-r--r--src/journal/fsprg.c6
-rw-r--r--src/journal/journal-authenticate.c10
-rw-r--r--src/journal/journal-file.c114
-rw-r--r--src/journal/journal-file.h18
-rw-r--r--src/journal/journal-gatewayd.c16
-rw-r--r--src/journal/journal-internal.h22
-rw-r--r--src/journal/journal-qrcode.c6
-rw-r--r--src/journal/journal-send.c28
-rw-r--r--src/journal/journal-vacuum.c59
-rw-r--r--src/journal/journal-verify.c277
-rw-r--r--src/journal/journalctl.c536
-rw-r--r--src/journal/journald-kmsg.c5
-rw-r--r--src/journal/journald-native.c50
-rw-r--r--src/journal/journald-server.c404
-rw-r--r--src/journal/journald-server.h10
-rw-r--r--src/journal/journald-stream.c6
-rw-r--r--src/journal/journald-syslog.c14
-rw-r--r--src/journal/journald-syslog.h2
-rw-r--r--src/journal/journald.conf4
-rw-r--r--src/journal/libsystemd-journal.sym5
-rw-r--r--src/journal/mmap-cache.c4
-rw-r--r--src/journal/sd-journal.c372
-rw-r--r--src/journal/test-catalog.c20
-rw-r--r--src/journal/test-journal-init.c60
-rw-r--r--src/journal/test-journal-interleaving.c303
-rw-r--r--src/journal/test-journal-stream.c6
-rw-r--r--src/journal/test-journal-verify.c8
-rw-r--r--src/journal/test-journal.c64
-rw-r--r--src/kernel-install/90-loaderentry.install16
-rw-r--r--src/kernel-install/kernel-install12
-rw-r--r--src/libsystemd-bus/bus-bloom.c2
-rw-r--r--src/libsystemd-bus/bus-control.c246
-rw-r--r--src/libsystemd-bus/bus-control.h4
-rw-r--r--src/libsystemd-bus/bus-error.c80
-rw-r--r--src/libsystemd-bus/bus-internal.h44
-rw-r--r--src/libsystemd-bus/bus-kernel.c407
-rw-r--r--src/libsystemd-bus/bus-kernel.h38
-rw-r--r--src/libsystemd-bus/bus-match.c116
-rw-r--r--src/libsystemd-bus/bus-match.h16
-rw-r--r--src/libsystemd-bus/bus-message.c1110
-rw-r--r--src/libsystemd-bus/bus-message.h61
-rw-r--r--src/libsystemd-bus/bus-socket.c66
-rw-r--r--src/libsystemd-bus/bus-type.c17
-rw-r--r--src/libsystemd-bus/bus-type.h1
-rw-r--r--src/libsystemd-bus/kdbus.h136
-rw-r--r--src/libsystemd-bus/sd-bus.c358
-rw-r--r--src/libsystemd-bus/sd-memfd.c231
-rw-r--r--src/libsystemd-bus/test-bus-chat.c10
-rw-r--r--src/libsystemd-bus/test-bus-kernel-benchmark.c302
-rw-r--r--src/libsystemd-bus/test-bus-kernel-bloom.c112
-rw-r--r--src/libsystemd-bus/test-bus-kernel.c34
-rw-r--r--src/libsystemd-bus/test-bus-marshal.c18
-rw-r--r--src/libsystemd-bus/test-bus-match.c70
-rw-r--r--src/libsystemd-bus/test-bus-memfd.c174
-rw-r--r--src/libsystemd-bus/test-bus-server.c4
-rw-r--r--src/libsystemd-bus/test-bus-zero-copy.c183
-rw-r--r--src/libudev/libudev-device.c4
-rw-r--r--src/libudev/libudev-enumerate.c40
-rw-r--r--src/libudev/libudev-hwdb.c18
-rw-r--r--src/libudev/libudev-util.c172
-rw-r--r--src/libudev/libudev.h2
-rw-r--r--src/libudev/libudev.sym1
-rw-r--r--src/locale/localectl.c19
-rw-r--r--src/login/70-uaccess.rules3
-rw-r--r--src/login/libsystemd-login.sym10
-rw-r--r--src/login/login-shared.c29
-rw-r--r--src/login/login-shared.h24
-rw-r--r--src/login/loginctl.c221
-rw-r--r--src/login/logind-acl.c68
-rw-r--r--src/login/logind-action.c2
-rw-r--r--src/login/logind-core.c514
-rw-r--r--src/login/logind-dbus.c724
-rw-r--r--src/login/logind-device.c39
-rw-r--r--src/login/logind-device.h5
-rw-r--r--src/login/logind-gperf.gperf2
-rw-r--r--src/login/logind-seat-dbus.c6
-rw-r--r--src/login/logind-seat.c75
-rw-r--r--src/login/logind-seat.h6
-rw-r--r--src/login/logind-session-dbus.c282
-rw-r--r--src/login/logind-session-device.c483
-rw-r--r--src/login/logind-session-device.h59
-rw-r--r--src/login/logind-session.c630
-rw-r--r--src/login/logind-session.h34
-rw-r--r--src/login/logind-user-dbus.c30
-rw-r--r--src/login/logind-user.c358
-rw-r--r--src/login/logind-user.h9
-rw-r--r--src/login/logind.c847
-rw-r--r--src/login/logind.conf2
-rw-r--r--src/login/logind.h35
-rw-r--r--src/login/org.freedesktop.login1.conf4
-rw-r--r--src/login/org.freedesktop.login1.policy.in2
-rw-r--r--src/login/pam-module.c187
-rw-r--r--src/login/sd-login.c87
-rw-r--r--src/login/systemd-user8
-rw-r--r--src/login/test-login-shared.c (renamed from src/timestamp/timestamp.c)26
-rw-r--r--src/login/test-login-tables.c35
-rw-r--r--src/login/test-login.c9
-rw-r--r--src/login/user-sessions.c20
l---------src/machine/Makefile1
-rw-r--r--src/machine/machine-dbus.c364
-rw-r--r--src/machine/machine.c414
-rw-r--r--src/machine/machine.h109
-rw-r--r--src/machine/machinectl.c816
-rw-r--r--src/machine/machined-dbus.c1042
-rw-r--r--src/machine/machined.c386
-rw-r--r--src/machine/machined.h73
-rw-r--r--src/machine/org.freedesktop.machine1.conf50
-rw-r--r--src/machine/org.freedesktop.machine1.service12
-rw-r--r--src/machine/test-machine-tables.c30
-rw-r--r--src/notify/notify.c3
-rw-r--r--src/nspawn/nspawn.c221
-rw-r--r--src/python-systemd/_daemon.c120
-rw-r--r--src/python-systemd/_reader.c173
-rw-r--r--src/python-systemd/daemon.py1
-rw-r--r--src/python-systemd/docs/journal.rst5
-rw-r--r--src/python-systemd/docs/login.rst23
-rw-r--r--src/python-systemd/journal.py35
-rw-r--r--src/python-systemd/login.c211
-rw-r--r--src/python-systemd/pyutil.c60
-rw-r--r--src/python-systemd/pyutil.h5
-rw-r--r--src/random-seed/random-seed.c87
-rw-r--r--src/readahead/readahead-collect.c6
l---------src/run/Makefile1
-rw-r--r--src/run/run.c376
-rw-r--r--src/shared/acl-util.c28
-rw-r--r--src/shared/acl-util.h1
-rw-r--r--src/shared/acpi-fpdt.c155
-rw-r--r--src/shared/acpi-fpdt.h26
-rw-r--r--src/shared/boot-timestamps.c65
-rw-r--r--src/shared/boot-timestamps.h27
-rw-r--r--src/shared/cgroup-label.c77
-rw-r--r--src/shared/cgroup-show.c1
-rw-r--r--src/shared/cgroup-util.c763
-rw-r--r--src/shared/cgroup-util.h36
-rw-r--r--src/shared/conf-parser.c10
-rw-r--r--src/shared/dbus-common.c6
-rw-r--r--src/shared/def.h7
-rw-r--r--src/shared/dev-setup.c8
-rw-r--r--src/shared/device-nodes.c74
-rw-r--r--src/shared/device-nodes.h25
-rw-r--r--src/shared/efivars.c41
-rw-r--r--src/shared/efivars.h5
-rw-r--r--src/shared/env-util.c5
-rw-r--r--src/shared/fileio.c166
-rw-r--r--src/shared/fileio.h4
-rw-r--r--src/shared/hashmap.c214
-rw-r--r--src/shared/hashmap.h1
-rw-r--r--src/shared/hwclock.c2
-rw-r--r--src/shared/install-printf.c58
-rw-r--r--src/shared/install-printf.h2
-rw-r--r--src/shared/install.c199
-rw-r--r--src/shared/install.h2
-rw-r--r--src/shared/label.c4
-rw-r--r--src/shared/label.h2
-rw-r--r--src/shared/list.h9
-rw-r--r--src/shared/log.c12
-rw-r--r--src/shared/logs-show.c396
-rw-r--r--src/shared/logs-show.h8
-rw-r--r--src/shared/macro.h31
-rw-r--r--src/shared/missing.h60
-rw-r--r--src/shared/mkdir-label.c53
-rw-r--r--src/shared/mkdir.c82
-rw-r--r--src/shared/mkdir.h19
-rw-r--r--src/shared/output-mode.h2
-rw-r--r--src/shared/path-util.c61
-rw-r--r--src/shared/path-util.h18
-rw-r--r--src/shared/polkit.c31
-rw-r--r--src/shared/refcnt.h34
-rw-r--r--src/shared/replace-var.c3
-rw-r--r--src/shared/set.c5
-rw-r--r--src/shared/sleep-config.c92
-rw-r--r--src/shared/socket-util.c8
-rw-r--r--src/shared/socket-util.h2
-rw-r--r--src/shared/specifier.c111
-rw-r--r--src/shared/specifier.h13
-rw-r--r--src/shared/strv.c37
-rw-r--r--src/shared/strv.h1
-rw-r--r--src/shared/test-tables.h51
-rw-r--r--src/shared/time-util.c22
-rw-r--r--src/shared/time-util.h1
-rw-r--r--src/shared/unit-name.c70
-rw-r--r--src/shared/unit-name.h8
-rw-r--r--src/shared/utf8.c278
-rw-r--r--src/shared/utf8.h9
-rw-r--r--src/shared/util.c335
-rw-r--r--src/shared/util.h36
-rw-r--r--src/shared/virt.c13
-rw-r--r--src/stdio-bridge/stdio-bridge.c4
-rw-r--r--src/sysctl/sysctl.c16
-rw-r--r--src/systemctl/systemctl.c1317
-rw-r--r--src/systemd/sd-bus.h36
-rw-r--r--src/systemd/sd-journal.h5
-rw-r--r--src/systemd/sd-login.h8
-rw-r--r--src/systemd/sd-memfd.h58
-rw-r--r--src/systemd/sd-messages.h7
-rw-r--r--src/test/test-boot-timestamps.c98
-rw-r--r--src/test/test-cgroup-util.c131
-rw-r--r--src/test/test-cgroup.c8
-rw-r--r--src/test/test-device-nodes.c55
-rw-r--r--src/test/test-efivars.c47
-rw-r--r--src/test/test-engine.c2
-rw-r--r--src/test/test-fileio.c165
-rw-r--r--src/test/test-hashmap.c36
-rw-r--r--src/test/test-helper.h31
-rw-r--r--src/test/test-id128.c11
-rw-r--r--src/test/test-libudev.c2
-rw-r--r--src/test/test-list.c109
-rw-r--r--src/test/test-path-util.c79
-rw-r--r--src/test/test-sched-prio.c6
-rw-r--r--src/test/test-sleep.c28
-rw-r--r--src/test/test-strv.c138
-rw-r--r--src/test/test-tables.c105
-rw-r--r--src/test/test-unit-file.c25
-rw-r--r--src/test/test-unit-name.c19
-rw-r--r--src/test/test-utf8.c76
-rw-r--r--src/test/test-util.c205
-rw-r--r--src/timedate/timedatectl.c22
-rw-r--r--src/timedate/timedated.c4
-rw-r--r--src/tmpfiles/tmpfiles.c160
-rw-r--r--src/udev/.gitignore4
-rw-r--r--src/udev/collect/collect.c6
-rw-r--r--src/udev/keymap/.gitignore5
-rw-r--r--src/udev/keymap/95-keyboard-force-release.rules57
-rw-r--r--src/udev/keymap/95-keymap.rules183
-rw-r--r--src/udev/keymap/README.keymap.txt97
-rwxr-xr-xsrc/udev/keymap/check-keymaps.sh38
-rwxr-xr-xsrc/udev/keymap/findkeyboards68
-rwxr-xr-xsrc/udev/keymap/keyboard-force-release.sh.in22
-rw-r--r--src/udev/keymap/keymap.c453
-rw-r--r--src/udev/udev-builtin-blkid.c3
-rw-r--r--src/udev/udev-builtin-hwdb.c79
-rw-r--r--src/udev/udev-builtin-keyboard.c163
-rw-r--r--src/udev/udev-builtin-net_id.c22
-rw-r--r--src/udev/udev-builtin-path_id.c1
-rw-r--r--src/udev/udev-builtin.c1
-rw-r--r--src/udev/udev-rules.c119
-rw-r--r--src/udev/udev.h7
-rw-r--r--src/udev/udevadm-hwdb.c139
-rw-r--r--src/udev/udevadm-info.c6
-rw-r--r--src/udev/udevd.c79
-rw-r--r--src/update-utmp/update-utmp.c2
-rwxr-xr-xtest/TEST-01-BASIC/test.sh6
-rwxr-xr-xtest/TEST-02-CRYPTSETUP/test.sh6
-rwxr-xr-xtest/TEST-03-JOBS/test.sh8
-rwxr-xr-xtest/rule-syntax-check.py21
-rwxr-xr-xtest/rules-test.sh13
-rw-r--r--tmpfiles.d/systemd.conf6
-rw-r--r--units/.gitignore8
-rw-r--r--units/basic.target4
-rw-r--r--units/console-getty.service.m4.in5
-rw-r--r--units/console-shell.service.m4.in5
-rw-r--r--units/emergency.service.in5
-rw-r--r--units/getty@.service.m413
-rw-r--r--units/initrd-fs.target2
-rw-r--r--units/initrd-root-fs.target2
-rw-r--r--units/kmod-static-nodes.service.in19
-rw-r--r--units/local-fs.target2
-rw-r--r--units/machine.slice11
-rw-r--r--units/remote-fs.target2
-rw-r--r--units/rescue.service.m4.in6
-rw-r--r--units/serial-getty@.service.m47
-rw-r--r--units/slices.target12
-rw-r--r--units/system.slice (renamed from units/systemd-random-seed-save.service.in)14
-rw-r--r--units/systemd-backlight@.service.in21
-rw-r--r--units/systemd-fsck-root.service.in6
-rw-r--r--units/systemd-fsck@.service.in2
-rw-r--r--units/systemd-journald.socket2
-rw-r--r--units/systemd-logind.service.in6
-rw-r--r--units/systemd-machined.service.in20
-rw-r--r--units/systemd-nspawn@.service.in1
-rw-r--r--units/systemd-random-seed.service.in (renamed from units/systemd-random-seed-load.service.in)9
-rw-r--r--units/systemd-sysctl.service.in1
-rw-r--r--units/systemd-tmpfiles-setup-dev.service.in3
-rw-r--r--units/systemd-tmpfiles-setup.service.in3
-rw-r--r--units/systemd-udev-settle.service.in2
-rw-r--r--units/systemd-udev-trigger.service.in2
-rw-r--r--units/systemd-udevd-control.socket2
-rw-r--r--units/systemd-udevd-kernel.socket2
-rw-r--r--units/systemd-udevd.service.in4
-rw-r--r--units/systemd-update-utmp-runlevel.service.in8
-rw-r--r--units/systemd-update-utmp-shutdown.service.in19
-rw-r--r--units/systemd-update-utmp.service.in21
-rw-r--r--units/user.slice11
-rw-r--r--units/user@.service.in14
-rw-r--r--units/x-.slice12
644 files changed, 43192 insertions, 16806 deletions
diff --git a/.gitignore b/.gitignore
index c1fe85d656..5b38c0b2e9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,14 +7,15 @@
/busctl
/cdrom_id
/collect
+/coverage/
/gtk-doc.make
/hostnamectl
/install-tree
/journalctl
-/keymap
/libtool
/localectl
/loginctl
+/machinectl
/mtd_probe
/org.freedesktop.hostname1.xml
/org.freedesktop.locale1.xml
@@ -28,6 +29,7 @@
/systemd-ac-power
/systemd-analyze
/systemd-ask-password
+/systemd-backlight
/systemd-binfmt
/systemd-bootchart
/systemd-cat
@@ -45,6 +47,7 @@
/systemd-fstab-generator
/systemd-getty-generator
/systemd-gnome-ask-password-agent
+/systemd-gpt-auto-generator
/systemd-hostnamed
/systemd-inhibit
/systemd-initctl
@@ -54,6 +57,7 @@
/systemd-localed
/systemd-logind
/systemd-machine-id-setup
+/systemd-machined
/systemd-modules-load
/systemd-multi-seat-x
/systemd-notify
@@ -65,6 +69,7 @@
/systemd-remount-api-vfs
/systemd-remount-fs
/systemd-reply-password
+/systemd-run
/systemd-shutdown
/systemd-shutdownd
/systemd-sleep
@@ -72,7 +77,6 @@
/systemd-sysctl
/systemd-system-update-generator
/systemd-timedated
-/systemd-timestamp
/systemd-tmpfiles
/systemd-tty-ask-password-agent
/systemd-uaccess
@@ -81,22 +85,28 @@
/systemd-user-sessions
/systemd-vconsole-setup
/tags
+/test-boot-timestamp
/test-bus-chat
/test-bus-kernel
+/test-bus-kernel-bloom
+/test-bus-kernel-benchmark
/test-bus-marshal
/test-bus-match
+/test-bus-memfd
/test-bus-signature
/test-bus-server
+/test-bus-zero-copy
/test-calendarspec
/test-catalog
/test-cgroup
/test-cgroup-util
/test-daemon
/test-date
-/test-efivars
+/test-device-nodes
/test-engine
/test-env-replace
/test-fileio
+/test-hashmap
/test-hostname
/test-id128
/test-inhibit
@@ -104,14 +114,18 @@
/test-job-type
/test-journal
/test-journal-enum
+/test-journal-interleaving
/test-journal-match
/test-journal-send
/test-journal-stream
+/test-journal-init
/test-journal-syslog
/test-journal-verify
/test-libudev
+/test-list
/test-log
/test-login
+/test-login-shared
/test-loopback
/test-mmap-cache
/test-ns
@@ -124,10 +138,14 @@
/test-strbuf
/test-strv
/test-strxcpyx
+/test-tables
+/test-login-tables
+/test-machine-tables
/test-time
/test-udev
/test-unit-file
/test-unit-name
+/test-utf8
/test-util
/test-watchdog
/timedatectl
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000000..7e5251cfb0
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,14 @@
+language: c
+compiler:
+ - gcc
+before_install:
+ - sudo apt-get update -qq
+ - sudo apt-get install autotools-dev automake autoconf libtool libdbus-1-dev libcap-dev libblkid-dev libpam-dev libcryptsetup-dev libaudit-dev libacl1-dev libattr1-dev libselinux-dev liblzma-dev libgcrypt-dev libqrencode-dev libmicrohttpd-dev gtk-doc-tools gperf python2.7-dev
+script: ./autogen.sh && ./configure --enable-gtk-doc --enable-gtk-doc-pdf && make V=1 && sudo ./systemd-machine-id-setup && make check && make distcheck
+after_failure: cat test-suite.log
+notifications:
+ irc:
+ channels:
+ - "irc.freenode.org#systemd"
+ on_success: change
+ on_failure: always
diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py
new file mode 100644
index 0000000000..06a2344661
--- /dev/null
+++ b/.ycm_extra_conf.py
@@ -0,0 +1,81 @@
+import os
+import ycm_core
+from clang_helpers import PrepareClangFlags
+
+compilation_database_folder = ''
+
+flags = [
+'-include',
+'./config.h',
+'-I',
+'/usr/include/dbus-1.0',
+'-I',
+'./src/shared',
+'-Wall',
+'-Wextra',
+'-Werror',
+'-Wno-long-long',
+'-Wno-variadic-macros',
+'-fexceptions',
+'-DNDEBUG',
+'-DUSE_CLANG_COMPLETER',
+'-D_GNU_SOURCE',
+'-std=c99',
+]
+
+if compilation_database_folder:
+ database = ycm_core.CompilationDatabase(compilation_database_folder)
+else:
+ database = None
+
+
+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):
+ if database:
+ compilation_info = database.GetCompilationInfoForFile(filename)
+ final_flags = PrepareClangFlags(
+ MakeRelativePathsInFlagsAbsolute(
+ compilation_info.compiler_flags_,
+ compilation_info.compiler_working_dir_),
+ filename)
+
+ else:
+ relative_to = DirectoryOfThisScript()
+ final_flags = MakeRelativePathsInFlagsAbsolute(flags, relative_to)
+
+ return {
+ 'flags': final_flags,
+ 'do_cache': True
+ }
diff --git a/Makefile-man.am b/Makefile-man.am
index 481423a963..c8a4342396 100644
--- a/Makefile-man.am
+++ b/Makefile-man.am
@@ -52,9 +52,11 @@ MANPAGES += \
man/systemd-cgtop.1 \
man/systemd-delta.1 \
man/systemd-detect-virt.1 \
+ man/systemd-efi-boot-generator.8 \
man/systemd-fsck@.service.8 \
man/systemd-fstab-generator.8 \
man/systemd-getty-generator.8 \
+ man/systemd-gpt-auto-generator.8 \
man/systemd-halt.service.8 \
man/systemd-inhibit.1 \
man/systemd-initctl.service.8 \
@@ -63,6 +65,7 @@ MANPAGES += \
man/systemd-notify.1 \
man/systemd-nspawn.1 \
man/systemd-remount-fs.service.8 \
+ man/systemd-run.1 \
man/systemd-shutdownd.service.8 \
man/systemd-sleep.conf.5 \
man/systemd-suspend.service.8 \
@@ -72,7 +75,7 @@ MANPAGES += \
man/systemd-tmpfiles.8 \
man/systemd-tty-ask-password-agent.1 \
man/systemd-udevd.service.8 \
- man/systemd-update-utmp-runlevel.service.8 \
+ man/systemd-update-utmp.service.8 \
man/systemd.1 \
man/systemd.automount.5 \
man/systemd.device.5 \
@@ -82,7 +85,10 @@ MANPAGES += \
man/systemd.mount.5 \
man/systemd.path.5 \
man/systemd.preset.5 \
+ man/systemd.resource-control.5 \
+ man/systemd.scope.5 \
man/systemd.service.5 \
+ man/systemd.slice.5 \
man/systemd.snapshot.5 \
man/systemd.socket.5 \
man/systemd.special.7 \
@@ -107,6 +113,7 @@ MANPAGES_ALIAS += \
man/SD_ID128_MAKE.3 \
man/SD_INFO.3 \
man/SD_JOURNAL_APPEND.3 \
+ man/SD_JOURNAL_CURRENT_USER.3 \
man/SD_JOURNAL_FOREACH.3 \
man/SD_JOURNAL_FOREACH_BACKWARDS.3 \
man/SD_JOURNAL_FOREACH_DATA.3 \
@@ -116,7 +123,7 @@ MANPAGES_ALIAS += \
man/SD_JOURNAL_NOP.3 \
man/SD_JOURNAL_RUNTIME_ONLY.3 \
man/SD_JOURNAL_SUPPRESS_LOCATION.3 \
- man/SD_JOURNAL_SYSTEM_ONLY.3 \
+ man/SD_JOURNAL_SYSTEM.3 \
man/SD_LISTEN_FDS_START.3 \
man/SD_NOTICE.3 \
man/SD_WARNING.3 \
@@ -146,6 +153,7 @@ MANPAGES_ALIAS += \
man/sd_journal_get_timeout.3 \
man/sd_journal_next_skip.3 \
man/sd_journal_open_directory.3 \
+ man/sd_journal_open_files.3 \
man/sd_journal_perror.3 \
man/sd_journal_previous.3 \
man/sd_journal_previous_skip.3 \
@@ -191,7 +199,7 @@ MANPAGES_ALIAS += \
man/systemd-udevd-control.socket.8 \
man/systemd-udevd-kernel.socket.8 \
man/systemd-udevd.8 \
- man/systemd-update-utmp-shutdown.service.8 \
+ man/systemd-update-utmp-runlevel.service.8 \
man/systemd-update-utmp.8 \
man/systemd-user.conf.5
man/SD_ALERT.3: man/sd-daemon.3
@@ -205,6 +213,7 @@ man/SD_ID128_FORMAT_VAL.3: man/sd-id128.3
man/SD_ID128_MAKE.3: man/sd-id128.3
man/SD_INFO.3: man/sd-daemon.3
man/SD_JOURNAL_APPEND.3: man/sd_journal_get_fd.3
+man/SD_JOURNAL_CURRENT_USER.3: man/sd_journal_open.3
man/SD_JOURNAL_FOREACH.3: man/sd_journal_next.3
man/SD_JOURNAL_FOREACH_BACKWARDS.3: man/sd_journal_next.3
man/SD_JOURNAL_FOREACH_DATA.3: man/sd_journal_get_data.3
@@ -214,7 +223,7 @@ man/SD_JOURNAL_LOCAL_ONLY.3: man/sd_journal_open.3
man/SD_JOURNAL_NOP.3: man/sd_journal_get_fd.3
man/SD_JOURNAL_RUNTIME_ONLY.3: man/sd_journal_open.3
man/SD_JOURNAL_SUPPRESS_LOCATION.3: man/sd_journal_print.3
-man/SD_JOURNAL_SYSTEM_ONLY.3: man/sd_journal_open.3
+man/SD_JOURNAL_SYSTEM.3: man/sd_journal_open.3
man/SD_LISTEN_FDS_START.3: man/sd_listen_fds.3
man/SD_NOTICE.3: man/sd-daemon.3
man/SD_WARNING.3: man/sd-daemon.3
@@ -244,6 +253,7 @@ man/sd_journal_get_monotonic_usec.3: man/sd_journal_get_realtime_usec.3
man/sd_journal_get_timeout.3: man/sd_journal_get_fd.3
man/sd_journal_next_skip.3: man/sd_journal_next.3
man/sd_journal_open_directory.3: man/sd_journal_open.3
+man/sd_journal_open_files.3: man/sd_journal_open.3
man/sd_journal_perror.3: man/sd_journal_print.3
man/sd_journal_previous.3: man/sd_journal_next.3
man/sd_journal_previous_skip.3: man/sd_journal_next.3
@@ -289,8 +299,8 @@ man/systemd-tmpfiles-setup.service.8: man/systemd-tmpfiles.8
man/systemd-udevd-control.socket.8: man/systemd-udevd.service.8
man/systemd-udevd-kernel.socket.8: man/systemd-udevd.service.8
man/systemd-udevd.8: man/systemd-udevd.service.8
-man/systemd-update-utmp-shutdown.service.8: man/systemd-update-utmp-runlevel.service.8
-man/systemd-update-utmp.8: man/systemd-update-utmp-runlevel.service.8
+man/systemd-update-utmp-runlevel.service.8: man/systemd-update-utmp.service.8
+man/systemd-update-utmp.8: man/systemd-update-utmp.service.8
man/systemd-user.conf.5: man/systemd-system.conf.5
man/SD_ALERT.html: man/sd-daemon.html
$(html-alias)
@@ -325,6 +335,9 @@ man/SD_INFO.html: man/sd-daemon.html
man/SD_JOURNAL_APPEND.html: man/sd_journal_get_fd.html
$(html-alias)
+man/SD_JOURNAL_CURRENT_USER.html: man/sd_journal_open.html
+ $(html-alias)
+
man/SD_JOURNAL_FOREACH.html: man/sd_journal_next.html
$(html-alias)
@@ -352,7 +365,7 @@ man/SD_JOURNAL_RUNTIME_ONLY.html: man/sd_journal_open.html
man/SD_JOURNAL_SUPPRESS_LOCATION.html: man/sd_journal_print.html
$(html-alias)
-man/SD_JOURNAL_SYSTEM_ONLY.html: man/sd_journal_open.html
+man/SD_JOURNAL_SYSTEM.html: man/sd_journal_open.html
$(html-alias)
man/SD_LISTEN_FDS_START.html: man/sd_listen_fds.html
@@ -442,6 +455,9 @@ man/sd_journal_next_skip.html: man/sd_journal_next.html
man/sd_journal_open_directory.html: man/sd_journal_open.html
$(html-alias)
+man/sd_journal_open_files.html: man/sd_journal_open.html
+ $(html-alias)
+
man/sd_journal_perror.html: man/sd_journal_print.html
$(html-alias)
@@ -577,16 +593,27 @@ man/systemd-udevd-kernel.socket.html: man/systemd-udevd.service.html
man/systemd-udevd.html: man/systemd-udevd.service.html
$(html-alias)
-man/systemd-update-utmp-shutdown.service.html: man/systemd-update-utmp-runlevel.service.html
+man/systemd-update-utmp-runlevel.service.html: man/systemd-update-utmp.service.html
$(html-alias)
-man/systemd-update-utmp.html: man/systemd-update-utmp-runlevel.service.html
+man/systemd-update-utmp.html: man/systemd-update-utmp.service.html
$(html-alias)
man/systemd-user.conf.html: man/systemd-system.conf.html
$(html-alias)
+if ENABLE_BACKLIGHT
+MANPAGES += \
+ man/systemd-backlight@.service.8
+MANPAGES_ALIAS += \
+ man/systemd-backlight.8
+man/systemd-backlight.8: man/systemd-backlight@.service.8
+man/systemd-backlight.html: man/systemd-backlight@.service.html
+ $(html-alias)
+
+endif
+
if ENABLE_BINFMT
MANPAGES += \
man/binfmt.d.5 \
@@ -644,6 +671,7 @@ endif
if ENABLE_LOGIND
MANPAGES += \
+ man/loginctl.1 \
man/logind.conf.5 \
man/systemd-logind.service.8
MANPAGES_ALIAS += \
@@ -654,6 +682,18 @@ man/systemd-logind.html: man/systemd-logind.service.html
endif
+if ENABLE_MACHINED
+MANPAGES += \
+ man/machinectl.1 \
+ man/systemd-machined.service.8
+MANPAGES_ALIAS += \
+ man/systemd-machined.8
+man/systemd-machined.8: man/systemd-machined.service.8
+man/systemd-machined.html: man/systemd-machined.service.html
+ $(html-alias)
+
+endif
+
if ENABLE_QUOTACHECK
MANPAGES += \
man/systemd-quotacheck.service.8
@@ -667,16 +707,11 @@ endif
if ENABLE_RANDOMSEED
MANPAGES += \
- man/systemd-random-seed-load.service.8
+ man/systemd-random-seed.service.8
MANPAGES_ALIAS += \
- man/systemd-random-seed-save.service.8 \
man/systemd-random-seed.8
-man/systemd-random-seed-save.service.8: man/systemd-random-seed-load.service.8
-man/systemd-random-seed.8: man/systemd-random-seed-load.service.8
-man/systemd-random-seed-save.service.html: man/systemd-random-seed-load.service.html
- $(html-alias)
-
-man/systemd-random-seed.html: man/systemd-random-seed-load.service.html
+man/systemd-random-seed.8: man/systemd-random-seed.service.8
+man/systemd-random-seed.html: man/systemd-random-seed.service.html
$(html-alias)
endif
@@ -785,7 +820,6 @@ endif
if HAVE_PAM
MANPAGES += \
- man/loginctl.1 \
man/pam_systemd.8 \
man/sd-login.3 \
man/sd_get_seats.3 \
@@ -807,6 +841,7 @@ MANPAGES_ALIAS += \
man/sd_login_monitor_unref.3 \
man/sd_pid_get_machine_name.3 \
man/sd_pid_get_owner_uid.3 \
+ man/sd_pid_get_slice.3 \
man/sd_pid_get_unit.3 \
man/sd_pid_get_user_unit.3 \
man/sd_seat_can_multi_session.3 \
@@ -819,6 +854,7 @@ MANPAGES_ALIAS += \
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_uid_get_seats.3 \
man/sd_uid_get_sessions.3 \
man/sd_uid_is_on_seat.3 \
@@ -834,6 +870,7 @@ 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_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_pid_get_slice.3: man/sd_pid_get_session.3
man/sd_pid_get_unit.3: man/sd_pid_get_session.3
man/sd_pid_get_user_unit.3: man/sd_pid_get_session.3
man/sd_seat_can_multi_session.3: man/sd_seat_get_active.3
@@ -846,6 +883,7 @@ 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_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
@@ -883,6 +921,9 @@ man/sd_pid_get_machine_name.html: man/sd_pid_get_session.html
man/sd_pid_get_owner_uid.html: man/sd_pid_get_session.html
$(html-alias)
+man/sd_pid_get_slice.html: man/sd_pid_get_session.html
+ $(html-alias)
+
man/sd_pid_get_unit.html: man/sd_pid_get_session.html
$(html-alias)
@@ -919,6 +960,9 @@ man/sd_session_get_type.html: man/sd_session_is_active.html
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_uid_get_seats.html: man/sd_uid_get_state.html
$(html-alias)
diff --git a/Makefile.am b/Makefile.am
index 3a196a65e7..8d9c58758f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -31,29 +31,32 @@ SUBDIRS = . po
# keep intermediate files
.SECONDARY:
-LIBUDEV_CURRENT=4
-LIBUDEV_REVISION=5
-LIBUDEV_AGE=3
+# Keep the test-suite.log
+.PRECIOUS: $(TEST_SUITE_LOG) Makefile
+
+LIBUDEV_CURRENT=5
+LIBUDEV_REVISION=0
+LIBUDEV_AGE=4
LIBGUDEV_CURRENT=1
LIBGUDEV_REVISION=3
LIBGUDEV_AGE=1
-LIBSYSTEMD_LOGIN_CURRENT=7
+LIBSYSTEMD_LOGIN_CURRENT=9
LIBSYSTEMD_LOGIN_REVISION=1
-LIBSYSTEMD_LOGIN_AGE=7
+LIBSYSTEMD_LOGIN_AGE=9
LIBSYSTEMD_DAEMON_CURRENT=0
LIBSYSTEMD_DAEMON_REVISION=10
LIBSYSTEMD_DAEMON_AGE=0
LIBSYSTEMD_ID128_CURRENT=0
-LIBSYSTEMD_ID128_REVISION=23
+LIBSYSTEMD_ID128_REVISION=26
LIBSYSTEMD_ID128_AGE=0
-LIBSYSTEMD_JOURNAL_CURRENT=10
-LIBSYSTEMD_JOURNAL_REVISION=2
-LIBSYSTEMD_JOURNAL_AGE=10
+LIBSYSTEMD_JOURNAL_CURRENT=11
+LIBSYSTEMD_JOURNAL_REVISION=3
+LIBSYSTEMD_JOURNAL_AGE=11
# Dirs of external packages
dbuspolicydir=@dbuspolicydir@
@@ -61,11 +64,13 @@ dbussessionservicedir=@dbussessionservicedir@
dbussystemservicedir=@dbussystemservicedir@
dbusinterfacedir=@dbusinterfacedir@
pamlibdir=@pamlibdir@
+pamconfdir=@pamconfdir@
pkgconfigdatadir=$(datadir)/pkgconfig
pkgconfiglibdir=$(libdir)/pkgconfig
polkitpolicydir=$(datadir)/polkit-1/actions
bashcompletiondir=@bashcompletiondir@
-rpmmacrosdir=$(sysconfdir)/rpm
+zshcompletiondir=@zshcompletiondir@
+rpmmacrosdir=$(prefix)/lib/rpm/macros.d
sysvinitdir=$(SYSTEM_SYSVINIT_PATH)
sysvrcnddir=$(SYSTEM_SYSVRCND_PATH)
varlogdir=$(localstatedir)/log
@@ -78,9 +83,9 @@ userunitdir=$(prefix)/lib/systemd/user
userpresetdir=$(prefix)/lib/systemd/user-preset
tmpfilesdir=$(prefix)/lib/tmpfiles.d
sysctldir=$(prefix)/lib/sysctl.d
-usergeneratordir=$(prefix)/lib/systemd/user-generators
pkgincludedir=$(includedir)/systemd
systemgeneratordir=$(rootlibexecdir)/system-generators
+usergeneratordir=$(prefix)/lib/systemd/user-generators
systemshutdowndir=$(rootlibexecdir)/system-shutdown
systemsleepdir=$(rootlibexecdir)/system-sleep
systemunitdir=$(rootprefix)/lib/systemd/system
@@ -154,7 +159,7 @@ AM_CPPFLAGS = \
-DSYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH=\"$(rootbindir)/systemd-tty-ask-password-agent\" \
-DSYSTEMD_STDIO_BRIDGE_BINARY_PATH=\"$(bindir)/systemd-stdio-bridge\" \
-DROOTPREFIX=\"$(rootprefix)\" \
- -DRANDOM_SEED=\"$(localstatedir)/lib/random-seed\" \
+ -DRANDOM_SEED=\"$(localstatedir)/lib/systemd/random-seed\" \
-DSYSTEMD_CRYPTSETUP_PATH=\"$(rootlibexecdir)/systemd-cryptsetup\" \
-DSYSTEM_GENERATOR_PATH=\"$(systemgeneratordir)\" \
-DUSER_GENERATOR_PATH=\"$(usergeneratordir)\" \
@@ -165,6 +170,7 @@ AM_CPPFLAGS = \
-DUDEVLIBEXECDIR=\"$(udevlibexecdir)\" \
-DPOLKIT_AGENT_BINARY_PATH=\"$(bindir)/pkttyagent\" \
-DQUOTACHECK=\"$(QUOTACHECK)\" \
+ -DKEXEC=\"$(KEXEC)\" \
-I $(top_srcdir)/src \
-I $(top_srcdir)/src/shared \
-I $(top_srcdir)/src/login \
@@ -174,6 +180,7 @@ AM_CPPFLAGS = \
-I $(top_srcdir)/src/core \
-I $(top_srcdir)/src/libudev \
-I $(top_srcdir)/src/udev \
+ -I $(top_builddir)/src/udev \
-I $(top_srcdir)/src/libsystemd-bus \
$(OUR_CPPFLAGS)
@@ -222,6 +229,7 @@ install-target-wants-hook:
what="$(SYSINIT_TARGET_WANTS)" && wants=sysinit.target && $(add-wants)
what="$(SOCKETS_TARGET_WANTS)" && wants=sockets.target && $(add-wants)
what="$(TIMERS_TARGET_WANTS)" && wants=timers.target && $(add-wants)
+ what="$(SLICES_TARGET_WANTS)" && wants=slices.target && $(add-wants)
define add-wants
[ -z "$$what" ] || ( \
@@ -280,7 +288,6 @@ rootbin_PROGRAMS = \
systemd-notify \
systemd-ask-password \
systemd-tty-ask-password-agent \
- systemd-tmpfiles \
systemd-machine-id-setup
bin_PROGRAMS = \
@@ -290,7 +297,8 @@ bin_PROGRAMS = \
systemd-nspawn \
systemd-detect-virt \
systemd-delta \
- systemd-analyze
+ systemd-analyze \
+ systemd-run
dist_bin_SCRIPTS = \
src/kernel-install/kernel-install
@@ -309,7 +317,6 @@ rootlibexec_PROGRAMS = \
systemd-remount-fs \
systemd-reply-password \
systemd-fsck \
- systemd-timestamp \
systemd-ac-power \
systemd-sysctl \
systemd-sleep
@@ -334,21 +341,24 @@ dist_bashcompletion_DATA = \
shell-completion/bash/journalctl \
shell-completion/bash/systemctl \
shell-completion/bash/systemd-analyze \
- shell-completion/bash/udevadm
-
-dist_tmpfiles_DATA = \
- tmpfiles.d/systemd.conf \
- tmpfiles.d/tmp.conf \
- tmpfiles.d/x11.conf
+ shell-completion/bash/systemd-run \
+ shell-completion/bash/udevadm \
+ shell-completion/bash/kernel-install
+
+dist_zshcompletion_DATA = \
+ shell-completion/zsh/_systemctl \
+ shell-completion/zsh/_journalctl \
+ shell-completion/zsh/_udevadm \
+ shell-completion/zsh/_kernel-install \
+ shell-completion/zsh/_systemd-nspawn \
+ shell-completion/zsh/_systemd-analyze \
+ shell-completion/zsh/_sd_hosts_or_user_at_host \
+ shell-completion/zsh/_systemd-delta \
+ shell-completion/zsh/_systemd
dist_sysctl_DATA = \
sysctl.d/50-default.conf
-if HAVE_SYSV_COMPAT
-dist_tmpfiles_DATA += \
- tmpfiles.d/legacy.conf
-endif
-
dist_systemunit_DATA = \
units/graphical.target \
units/multi-user.target \
@@ -387,6 +397,9 @@ dist_systemunit_DATA = \
units/paths.target \
units/suspend.target \
units/swap.target \
+ units/slices.target \
+ units/system.slice \
+ units/x-.slice \
units/systemd-initctl.socket \
units/systemd-shutdownd.socket \
units/syslog.socket \
@@ -400,8 +413,6 @@ dist_systemunit_DATA = \
units/sound.target \
units/bluetooth.target \
units/smartcard.target \
- units/systemd-tmpfiles-clean.timer \
- units/quotaon.service \
units/systemd-ask-password-wall.path \
units/systemd-ask-password-console.path \
units/systemd-udevd-control.socket \
@@ -417,11 +428,8 @@ nodist_systemunit_DATA = \
units/systemd-initctl.service \
units/systemd-shutdownd.service \
units/systemd-remount-fs.service \
+ units/systemd-update-utmp.service \
units/systemd-update-utmp-runlevel.service \
- units/systemd-update-utmp-shutdown.service \
- units/systemd-tmpfiles-setup-dev.service \
- units/systemd-tmpfiles-setup.service \
- units/systemd-tmpfiles-clean.service \
units/systemd-ask-password-wall.service \
units/systemd-ask-password-console.service \
units/systemd-sysctl.service \
@@ -463,11 +471,8 @@ EXTRA_DIST += \
units/systemd-initctl.service.in \
units/systemd-shutdownd.service.in \
units/systemd-remount-fs.service.in \
+ units/systemd-update-utmp.service.in \
units/systemd-update-utmp-runlevel.service.in \
- units/systemd-update-utmp-shutdown.service.in \
- units/systemd-tmpfiles-setup-dev.service.in \
- units/systemd-tmpfiles-setup.service.in \
- units/systemd-tmpfiles-clean.service.in \
units/systemd-ask-password-wall.service.in \
units/systemd-ask-password-console.service.in \
units/systemd-sysctl.service.in \
@@ -513,6 +518,17 @@ EXTRA_DIST += \
units/rc-local.service.in \
units/halt-local.service.in
+# automake is broken and can't handle files with a dash in front
+# http://debbugs.gnu.org/cgi/bugreport.cgi?bug=14728#8
+units-install-hook:
+ mv $(DESTDIR)$(systemunitdir)/x-.slice $(DESTDIR)/$(systemunitdir)/-.slice
+
+units-uninstall-hook:
+ rm -f $(DESTDIR)/$(systemunitdir)/-.slice
+
+INSTALL_DATA_HOOKS += units-install-hook
+UNINSTALL_DATA_HOOKS += units-uninstall-hook
+
dist_doc_DATA = \
README \
NEWS \
@@ -530,6 +546,9 @@ MANPAGES_ALIAS =
include Makefile-man.am
+.PHONY: man
+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 = \
@@ -605,7 +624,7 @@ EXTRA_DIST += \
$(XML_FILES) \
$(HTML_FILES) \
$(HTML_ALIAS) \
- $(dist_MANS) \
+ $(man_MANS) \
make-man-index.py \
make-directive-index.py \
xml_helper.py
@@ -623,6 +642,8 @@ libsystemd_shared_la_SOURCES = \
src/shared/list.h \
src/shared/macro.h \
src/shared/def.h \
+ src/shared/device-nodes.c \
+ src/shared/device-nodes.h \
src/shared/sparse-endian.h \
src/shared/util.c \
src/shared/util.h \
@@ -695,7 +716,14 @@ libsystemd_shared_la_SOURCES = \
src/shared/fileio.h \
src/shared/output-mode.h \
src/shared/MurmurHash3.c \
- src/shared/MurmurHash3.h
+ src/shared/MurmurHash3.h \
+ src/shared/acpi-fpdt.h \
+ src/shared/acpi-fpdt.c \
+ src/shared/boot-timestamps.h \
+ src/shared/boot-timestamps.c \
+ src/shared/refcnt.h \
+ src/shared/mkdir.c \
+ src/shared/mkdir.h
#-------------------------------------------------------------------------------
noinst_LTLIBRARIES += \
@@ -739,14 +767,12 @@ noinst_LTLIBRARIES += \
libsystemd-label.la
libsystemd_label_la_SOURCES = \
- src/shared/cgroup-label.c \
src/shared/socket-label.c \
src/shared/label.c \
src/shared/label.h \
src/shared/selinux-util.c \
src/shared/selinux-util.h \
- src/shared/mkdir.c \
- src/shared/mkdir.h \
+ src/shared/mkdir-label.c \
src/shared/ask-password-api.c \
src/shared/ask-password-api.h \
src/shared/fileio-label.c \
@@ -858,6 +884,10 @@ libsystemd_core_la_SOURCES = \
src/core/timer.h \
src/core/path.c \
src/core/path.h \
+ src/core/slice.c \
+ src/core/slice.h \
+ src/core/scope.c \
+ src/core/scope.h \
src/core/load-dropin.c \
src/core/load-dropin.h \
src/core/execute.c \
@@ -890,12 +920,18 @@ libsystemd_core_la_SOURCES = \
src/core/dbus-snapshot.h \
src/core/dbus-device.c \
src/core/dbus-device.h \
+ src/core/dbus-path.c \
+ src/core/dbus-path.h \
+ src/core/dbus-slice.c \
+ src/core/dbus-slice.h \
+ src/core/dbus-scope.c \
+ src/core/dbus-scope.h \
src/core/dbus-execute.c \
src/core/dbus-execute.h \
src/core/dbus-kill.c \
src/core/dbus-kill.h \
- src/core/dbus-path.c \
- src/core/dbus-path.h \
+ src/core/dbus-cgroup.c \
+ src/core/dbus-cgroup.h \
src/core/cgroup.c \
src/core/cgroup.h \
src/core/selinux-access.c \
@@ -922,10 +958,6 @@ libsystemd_core_la_SOURCES = \
src/core/namespace.h \
src/core/tcpwrap.c \
src/core/tcpwrap.h \
- src/core/cgroup-attr.c \
- src/core/cgroup-attr.h \
- src/core/cgroup-semantics.c \
- src/core/cgroup-semantics.h \
src/core/securebits.h \
src/core/initreq.h \
src/core/special.h \
@@ -940,8 +972,8 @@ libsystemd_core_la_SOURCES = \
src/core/syscall-list.h \
src/core/audit-fd.c \
src/core/audit-fd.h \
- src/core/sync.c \
- src/core/sync.h
+ src/core/async.c \
+ src/core/async.h
if HAVE_KMOD
libsystemd_core_la_SOURCES += \
@@ -1000,7 +1032,7 @@ BUILT_SOURCES += \
src/core/syscall-list.txt: Makefile
$(AM_V_at)$(MKDIR_P) $(dir $@)
- $(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM -include sys/syscall.h - < /dev/null | $(AWK) '/^#define[ \t]+__NR_[^ ]+[ \t]+[0-9(]/ { sub(/__NR_/, "", $$2); print $$2; }' > $@
+ $(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM -include sys/syscall.h - < /dev/null | $(AWK) '/^#define[ \t]+__NR_[^ ]+[ \t]+[0-9(]/ { sub(/__NR_/, "", $$2); if ($$2 !~ /SYSCALL_BASE/) print $$2; }' > $@
src/core/syscall-from-name.gperf: src/core/syscall-list.txt Makefile
$(AM_V_at)$(MKDIR_P) $(dir $@)
@@ -1096,6 +1128,7 @@ tests += \
test-strxcpyx \
test-unit-name \
test-unit-file \
+ test-utf8 \
test-util \
test-date \
test-sleep \
@@ -1107,7 +1140,10 @@ tests += \
test-prioq \
test-fileio \
test-time \
- test-hashmap
+ test-hashmap \
+ test-list \
+ test-tables \
+ test-device-nodes
EXTRA_DIST += \
test/sched_idle_bad.service \
@@ -1116,6 +1152,15 @@ EXTRA_DIST += \
test/sched_rr_ok.service \
test/sched_rr_change.service
+EXTRA_DIST += \
+ src/test/test-helper.h
+
+test_device_nodes_SOURCES = \
+ src/test/test-device-nodes.c
+
+test_device_nodes_LDADD = \
+ libsystemd-shared.la
+
test_engine_SOURCES = \
src/test/test-engine.c
@@ -1145,6 +1190,10 @@ test_ns_SOURCES = \
test_ns_LDADD = \
libsystemd-core.la
+test_ns_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(DBUS_CFLAGS)
+
test_loopback_SOURCES = \
src/test/test-loopback.c
@@ -1160,12 +1209,12 @@ test_hostname_LDADD = \
if ENABLE_EFI
manual_tests += \
- test-efivars
+ test-boot-timestamp
-test_efivars_SOURCES = \
- src/test/test-efivars.c
+test_boot_timestamp_SOURCES = \
+ src/test/test-boot-timestamps.c
-test_efivars_LDADD = \
+test_boot_timestamp_LDADD = \
libsystemd-shared.la
endif
@@ -1189,6 +1238,15 @@ test_unit_file_CFLAGS = \
test_unit_file_LDADD = \
libsystemd-core.la
+test_utf8_SOURCES = \
+ src/test/test-utf8.c
+
+test_utf8_CFLAGS = \
+ $(AM_CFLAGS)
+
+test_utf8_LDADD = \
+ libsystemd-shared.la
+
test_util_SOURCES = \
src/test/test-util.c
@@ -1207,6 +1265,27 @@ test_hashmap_CFLAGS = \
test_hashmap_LDADD = \
libsystemd-core.la
+test_list_SOURCES = \
+ src/test/test-list.c
+
+test_list_CFLAGS = \
+ $(AM_CFLAGS)
+
+test_list_LDADD = \
+ libsystemd-core.la
+
+test_tables_SOURCES = \
+ src/test/test-tables.c \
+ src/shared/test-tables.h
+
+test_tables_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(DBUS_CFLAGS)
+
+test_tables_LDADD = \
+ libsystemd-core.la \
+ libsystemd-logs.la
+
test_prioq_SOURCES = \
src/test/test-prioq.c
@@ -1289,7 +1368,8 @@ test_cgroup_util_SOURCES = \
test_cgroup_util_LDADD = \
libsystemd-label.la \
- libsystemd-shared.la
+ libsystemd-shared.la \
+ libsystemd-daemon.la
test_env_replace_SOURCES = \
src/test/test-env-replace.c
@@ -1355,6 +1435,44 @@ test_sched_prio_LDADD = \
libsystemd-daemon.la
# ------------------------------------------------------------------------------
+## .PHONY so it always rebuilds it
+.PHONY: coverage lcov-run lcov-report
+
+# run lcov from scratch, always
+coverage:
+ $(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
+ genhtml -t "systemd test coverage" -o $(coverage_dir) $(coverage_dir)/.lcov.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
+
+# ------------------------------------------------------------------------------
systemd_initctl_SOURCES = \
src/initctl/initctl.c
@@ -1430,19 +1548,72 @@ nodist_systemunit_DATA += \
SYSINIT_TARGET_WANTS += \
systemd-modules-load.service
+if ENABLE_TMPFILES
+nodist_systemunit_DATA += \
+ units/kmod-static-nodes.service
+
+SYSINIT_TARGET_WANTS += \
+ kmod-static-nodes.service
+endif
endif
EXTRA_DIST += \
- units/systemd-modules-load.service.in
+ units/systemd-modules-load.service.in \
+ units/kmod-static-nodes.service.in
# ------------------------------------------------------------------------------
+if ENABLE_TMPFILES
systemd_tmpfiles_SOURCES = \
- src/tmpfiles/tmpfiles.c
+ src/tmpfiles/tmpfiles.c \
+ src/shared/specifier.c \
+ src/shared/specifier.h
systemd_tmpfiles_LDADD = \
libsystemd-label.la \
libsystemd-shared.la \
- libsystemd-capability.la
+ libsystemd-capability.la \
+ libsystemd-id128-internal.la
+
+rootbin_PROGRAMS += \
+ systemd-tmpfiles
+
+dist_systemunit_DATA += \
+ units/systemd-tmpfiles-clean.timer
+
+nodist_systemunit_DATA += \
+ units/systemd-tmpfiles-setup-dev.service \
+ units/systemd-tmpfiles-setup.service \
+ units/systemd-tmpfiles-clean.service
+
+dist_tmpfiles_DATA = \
+ tmpfiles.d/systemd.conf \
+ tmpfiles.d/tmp.conf \
+ tmpfiles.d/x11.conf
+
+if HAVE_SYSV_COMPAT
+dist_tmpfiles_DATA += \
+ tmpfiles.d/legacy.conf
+endif
+
+SYSINIT_TARGET_WANTS += \
+ systemd-tmpfiles-setup-dev.service \
+ systemd-tmpfiles-setup.service
+
+dist_zshcompletion_DATA += \
+ shell-completion/zsh/_systemd-tmpfiles
+
+TIMERS_TARGET_WANTS += \
+ systemd-tmpfiles-clean.timer
+
+INSTALL_DIRS += \
+ $(tmpfilesdir) \
+ $(sysconfdir)/tmpfiles.d
+endif
+
+EXTRA_DIST += \
+ units/systemd-tmpfiles-setup-dev.service.in \
+ units/systemd-tmpfiles-setup.service.in \
+ units/systemd-tmpfiles-clean.service.in
# ------------------------------------------------------------------------------
systemd_machine_id_setup_SOURCES = \
@@ -1483,13 +1654,6 @@ systemd_fsck_LDADD = \
libudev.la
# ------------------------------------------------------------------------------
-systemd_timestamp_SOURCES = \
- src/timestamp/timestamp.c
-
-systemd_timestamp_LDADD = \
- libsystemd-shared.la
-
-# ------------------------------------------------------------------------------
systemd_ac_power_SOURCES = \
src/ac-power/ac-power.c
@@ -1542,8 +1706,8 @@ systemd_system_update_generator_LDADD = \
libsystemd-label.la \
libsystemd-shared.la
-# ------------------------------------------------------------------------------
if ENABLE_EFI
+# ------------------------------------------------------------------------------
systemgenerator_PROGRAMS += \
systemd-efi-boot-generator
@@ -1553,6 +1717,42 @@ systemd_efi_boot_generator_SOURCES = \
systemd_efi_boot_generator_LDADD = \
libsystemd-label.la \
libsystemd-shared.la
+
+# ------------------------------------------------------------------------------
+bootctl_SOURCES = \
+ src/boot/boot.h \
+ src/boot/boot-loader.h \
+ src/boot/bootctl.c \
+ src/boot/boot-loader.c \
+ src/boot/boot-efi.c
+
+bootctl_LDADD = \
+ libsystemd-shared.la \
+ libsystemd-id128.la \
+ libsystemd-daemon.la
+
+bin_PROGRAMS += \
+ bootctl
+endif
+
+# ------------------------------------------------------------------------------
+if HAVE_BLKID
+systemgenerator_PROGRAMS += \
+ systemd-gpt-auto-generator
+
+systemd_gpt_auto_generator_SOURCES = \
+ src/gpt-auto-generator/gpt-auto-generator.c
+
+systemd_gpt_auto_generator_LDADD = \
+ libsystemd-label.la \
+ libsystemd-shared.la \
+ libsystemd-id128-internal.la \
+ libudev-private.la \
+ $(BLKID_LIBS)
+
+systemd_gpt_auto_generator_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(BLKID_CFLAGS)
endif
# ------------------------------------------------------------------------------
@@ -1652,7 +1852,20 @@ systemd_nspawn_LDADD = \
libsystemd-capability.la \
libsystemd-shared.la \
libsystemd-daemon.la \
- libsystemd-id128-internal.la
+ libsystemd-id128-internal.la \
+ libsystemd-bus.la
+
+# ------------------------------------------------------------------------------
+systemd_run_SOURCES = \
+ src/run/run.c
+
+systemd_run_LDADD = \
+ libsystemd-label.la \
+ libsystemd-capability.la \
+ libsystemd-shared.la \
+ libsystemd-daemon.la \
+ libsystemd-id128-internal.la \
+ libsystemd-bus.la
# ------------------------------------------------------------------------------
systemd_stdio_bridge_SOURCES = \
@@ -1688,6 +1901,9 @@ libsystemd_daemon_la_LDFLAGS = \
-version-info $(LIBSYSTEMD_DAEMON_CURRENT):$(LIBSYSTEMD_DAEMON_REVISION):$(LIBSYSTEMD_DAEMON_AGE) \
-Wl,--version-script=$(top_srcdir)/src/libsystemd-daemon/libsystemd-daemon.sym
+libsystemd_daemon_la_LIBADD = \
+ $(RT_LIBS)
+
pkginclude_HEADERS += \
src/systemd/sd-daemon.h
@@ -1718,6 +1934,7 @@ EXTRA_DIST += \
libsystemd_bus_la_SOURCES = \
src/systemd/sd-bus.h \
src/systemd/sd-bus-protocol.h \
+ src/systemd/sd-memfd.h \
src/libsystemd-bus/sd-bus.c \
src/libsystemd-bus/bus-control.c \
src/libsystemd-bus/bus-control.h \
@@ -1739,13 +1956,18 @@ libsystemd_bus_la_SOURCES = \
src/libsystemd-bus/bus-match.h \
src/libsystemd-bus/bus-bloom.c \
src/libsystemd-bus/bus-bloom.h \
- src/libsystemd-bus/kdbus.h
+ src/libsystemd-bus/kdbus.h \
+ src/libsystemd-bus/sd-memfd.c
libsystemd_bus_la_LIBADD = \
libsystemd-id128-internal.la \
libsystemd-shared.la \
libsystemd-daemon.la
+libsystemd_bus_la_CFLAGS = \
+ $(AM_CFLAGS) \
+ -pthread
+
noinst_LTLIBRARIES += \
libsystemd-bus.la
@@ -1755,7 +1977,11 @@ tests += \
test-bus-chat \
test-bus-server \
test-bus-match \
- test-bus-kernel
+ test-bus-kernel \
+ test-bus-kernel-bloom \
+ test-bus-kernel-benchmark \
+ test-bus-memfd \
+ test-bus-zero-copy
noinst_PROGRAMS += \
busctl
@@ -1827,6 +2053,48 @@ test_bus_kernel_LDADD = \
libsystemd-bus.la \
libsystemd-id128-internal.la
+test_bus_kernel_bloom_SOURCES = \
+ src/libsystemd-bus/test-bus-kernel-bloom.c
+
+test_bus_kernel_bloom_CFLAGS = \
+ $(AM_CFLAGS)
+
+test_bus_kernel_bloom_LDADD = \
+ libsystemd-shared.la \
+ libsystemd-bus.la \
+ libsystemd-id128-internal.la
+
+test_bus_kernel_benchmark_SOURCES = \
+ src/libsystemd-bus/test-bus-kernel-benchmark.c
+
+test_bus_kernel_benchmark_CFLAGS = \
+ $(AM_CFLAGS)
+
+test_bus_kernel_benchmark_LDADD = \
+ libsystemd-shared.la \
+ libsystemd-bus.la \
+ libsystemd-id128-internal.la
+
+test_bus_memfd_SOURCES = \
+ src/libsystemd-bus/test-bus-memfd.c
+
+test_bus_memfd_CFLAGS = \
+ $(AM_CFLAGS)
+
+test_bus_memfd_LDADD = \
+ libsystemd-shared.la \
+ libsystemd-bus.la
+
+test_bus_zero_copy_SOURCES = \
+ src/libsystemd-bus/test-bus-zero-copy.c
+
+test_bus_zero_copy_CFLAGS = \
+ $(AM_CFLAGS)
+
+test_bus_zero_copy_LDADD = \
+ libsystemd-shared.la \
+ libsystemd-bus.la
+
busctl_SOURCES = \
src/libsystemd-bus/busctl.c
@@ -1873,7 +2141,9 @@ libudev_la_LDFLAGS = \
libudev_la_LIBADD = \
libsystemd-shared.la \
+ libsystemd-label.la \
libsystemd-daemon-internal.la \
+ $(RT_LIBS) \
libsystemd-id128-internal.la
pkgconfiglib_DATA += \
@@ -1931,6 +2201,7 @@ dist_udevrules_DATA += \
rules/99-systemd.rules \
rules/42-usb-hid-pm.rules \
rules/50-udev-default.rules \
+ rules/60-keyboard.rules \
rules/60-persistent-storage-tape.rules \
rules/60-persistent-serial.rules \
rules/60-persistent-input.rules \
@@ -1950,7 +2221,8 @@ dist_udevhwdb_DATA = \
hwdb/20-usb-classes.hwdb \
hwdb/20-bluetooth-vendor-product.hwdb \
hwdb/20-acpi-vendor.hwdb \
- hwdb/20-OUI.hwdb
+ hwdb/20-OUI.hwdb \
+ hwdb/60-keyboard.hwdb
udevconfdir = $(sysconfdir)/udev
dist_udevconf_DATA = \
@@ -1994,6 +2266,19 @@ rootlibexec_PROGRAMS += \
noinst_LTLIBRARIES += \
libudev-core.la
+src/udev/keyboard-keys.txt: Makefile
+ $(AM_V_at)$(MKDIR_P) $(dir $@)
+ $(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM -include linux/input.h - < /dev/null | $(AWK) '/^#define[ \t]+KEY_[^ ]+[ \t]+[0-9]/ { if ($$2 != "KEY_MAX") { print $$2 } }' | sed 's/^KEY_COFFEE$$/KEY_SCREENLOCK/' > $@
+
+src/udev/keyboard-keys-from-name.gperf: src/udev/keyboard-keys.txt Makefile
+ $(AM_V_GEN)$(AWK) 'BEGIN{ print "struct key { const char* name; unsigned short id; };"; print "%null-strings"; print "%%";} { print tolower(substr($$1 ,5)) ", " $$1 }' < $< > $@
+
+src/udev/keyboard-keys-from-name.h: src/udev/keyboard-keys-from-name.gperf Makefile
+ $(AM_V_GPERF)$(GPERF) -L ANSI-C -t -N keyboard_lookup_key -H hash_key_name -p -C < $< > $@
+
+src/udev/keyboard-keys-to-name.h: src/udev/keyboard-keys.txt Makefile
+ $(AM_V_GEN)$(AWK) 'BEGIN{ print "const char* const key_names[KEY_CNT] = { "} { print "[" $$1 "] = \"" $$1 "\"," } END{print "};"}' < $< > $@
+
libudev_core_la_SOURCES = \
src/udev/udev.h \
src/udev/udev-event.c \
@@ -2005,10 +2290,22 @@ libudev_core_la_SOURCES = \
src/udev/udev-builtin-btrfs.c \
src/udev/udev-builtin-hwdb.c \
src/udev/udev-builtin-input_id.c \
+ src/udev/udev-builtin-keyboard.c \
src/udev/udev-builtin-net_id.c \
src/udev/udev-builtin-path_id.c \
src/udev/udev-builtin-usb_id.c
+nodist_libudev_core_la_SOURCES = \
+ src/udev/keyboard-keys-from-name.h \
+ src/udev/keyboard-keys-to-name.h
+
+BUILT_SOURCES += \
+ $(nodist_libudev_core_la_SOURCES)
+
+CLEANFILES += \
+ src/udev/keyboard-keys-from-name.gperf \
+ src/udev/keyboard-keys.txt
+
libudev_core_la_CFLAGS = \
$(AM_CFLAGS) \
$(BLKID_CFLAGS) \
@@ -2018,6 +2315,7 @@ libudev_core_la_LIBADD = \
libudev-private.la \
libsystemd-label.la \
libsystemd-daemon-internal.la \
+ $(RT_LIBS) \
libsystemd-shared.la \
$(BLKID_LIBS) \
$(KMOD_LIBS)
@@ -2051,7 +2349,10 @@ if HAVE_ACL
libudev_core_la_SOURCES += \
src/udev/udev-builtin-uaccess.c \
src/login/logind-acl.c \
- src/login/sd-login.c
+ src/login/sd-login.c \
+ src/systemd/sd-login.h \
+ src/login/login-shared.c \
+ src/login/login-shared.h
libudev_core_la_LIBADD += \
libsystemd-acl.la
@@ -2374,138 +2675,6 @@ EXTRA_DIST += \
src/gudev/seed-example.js
# ------------------------------------------------------------------------------
-if ENABLE_KEYMAP
-keymap_SOURCES = \
- src/udev/keymap/keymap.c
-
-keymap_CPPFLAGS = \
- $(AM_CPPFLAGS) -I src/udev/keymap
-
-keymap_LDADD = \
- libsystemd-shared.la
-
-nodist_keymap_SOURCES = \
- src/udev/keymap/keys-from-name.h \
- src/udev/keymap/keys-to-name.h
-
-BUILT_SOURCES += \
- $(nodist_keymap_SOURCES)
-
-udevlibexec_PROGRAMS += \
- keymap
-
-dist_doc_DATA += \
- src/udev/keymap/README.keymap.txt
-
-dist_udevrules_DATA += \
- src/udev/keymap/95-keymap.rules \
- src/udev/keymap/95-keyboard-force-release.rules
-
-dist_udevhome_SCRIPTS = \
- src/udev/keymap/findkeyboards \
- src/udev/keymap/keyboard-force-release.sh
-
-TESTS += \
- src/udev/keymap/check-keymaps.sh
-
-CLEANFILES += \
- src/udev/keymap/keys.txt \
- src/udev/keymap/keys-from-name.gperf \
- src/udev/keymap/keyboard-force-release.sh
-
-udevkeymapdir = $(udevlibexecdir)/keymaps
-dist_udevkeymap_DATA = \
- keymaps/acer \
- keymaps/acer-aspire_5720 \
- keymaps/acer-aspire_8930 \
- keymaps/acer-aspire_5920g \
- keymaps/acer-aspire_6920 \
- keymaps/acer-travelmate_c300 \
- keymaps/asus \
- keymaps/compaq-e_evo \
- keymaps/dell \
- keymaps/dell-latitude-xt2 \
- keymaps/everex-xt5000 \
- keymaps/fujitsu-amilo_li_2732 \
- keymaps/fujitsu-amilo_pa_2548 \
- keymaps/fujitsu-amilo_pro_edition_v3505 \
- keymaps/fujitsu-amilo_pro_v3205 \
- keymaps/fujitsu-amilo_si_1520 \
- keymaps/fujitsu-esprimo_mobile_v5 \
- keymaps/fujitsu-esprimo_mobile_v6 \
- keymaps/genius-slimstar-320 \
- keymaps/hewlett-packard \
- keymaps/hewlett-packard-2510p_2530p \
- keymaps/hewlett-packard-compaq_elitebook \
- keymaps/hewlett-packard-pavilion \
- keymaps/hewlett-packard-presario-2100 \
- keymaps/hewlett-packard-tablet \
- keymaps/hewlett-packard-tx2 \
- keymaps/hewlett-packard_elitebook-8440p \
- keymaps/hewlett-packard_elitebook-8460p \
- keymaps/hewlett-packard-hdx9494nr \
- keymaps/ibm-thinkpad-usb-keyboard-trackpoint \
- keymaps/inventec-symphony_6.0_7.0 \
- keymaps/lenovo-3000 \
- keymaps/lenovo-ideapad \
- keymaps/lenovo-thinkpad-usb-keyboard-trackpoint \
- keymaps/lenovo-thinkpad_x6_tablet \
- keymaps/lenovo-thinkpad_x200_tablet \
- keymaps/lg-x110 \
- keymaps/logitech-wave \
- keymaps/logitech-wave-cordless \
- keymaps/logitech-wave-pro-cordless \
- keymaps/maxdata-pro_7000 \
- keymaps/medion-fid2060 \
- keymaps/medionnb-a555 \
- keymaps/micro-star \
- keymaps/module-asus-w3j \
- keymaps/module-ibm \
- keymaps/module-lenovo \
- keymaps/module-sony \
- keymaps/module-sony-old \
- keymaps/module-sony-vgn \
- keymaps/module-sony-vpc \
- keymaps/olpc-xo \
- keymaps/onkyo \
- keymaps/oqo-model2 \
- keymaps/samsung-other \
- keymaps/samsung-series-9 \
- keymaps/samsung-sq1us \
- keymaps/samsung-sx20s \
- keymaps/toshiba-satellite_a100 \
- keymaps/toshiba-satellite_a110 \
- keymaps/toshiba-satellite_m30x \
- keymaps/zepto-znote
-
-udevkeymapforcereldir = $(udevlibexecdir)/keymaps/force-release
-dist_udevkeymapforcerel_DATA = \
- keymaps-force-release/dell-touchpad \
- keymaps-force-release/dell-xps \
- keymaps-force-release/hp-other \
- keymaps-force-release/samsung-other \
- keymaps-force-release/samsung-series-9 \
- keymaps-force-release/common-volume-keys
-
-src/udev/keymap/keys.txt: Makefile
- $(AM_V_at)$(MKDIR_P) $(dir $@)
- $(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM -include linux/input.h - < /dev/null | $(AWK) '/^#define[ \t]+KEY_[^ ]+[ \t]+[0-9]/ { if ($$2 != "KEY_MAX") { print $$2 } }' | sed 's/^KEY_COFFEE$$/KEY_SCREENLOCK/' > $@
-
-src/udev/keymap/keys-from-name.gperf: src/udev/keymap/keys.txt Makefile
- $(AM_V_GEN)$(AWK) 'BEGIN{ print "struct key { const char* name; unsigned short id; };"; print "%null-strings"; print "%%";} { print $$1 ", " $$1 }' < $< > $@
-
-src/udev/keymap/keys-from-name.h: src/udev/keymap/keys-from-name.gperf Makefile
- $(AM_V_GPERF)$(GPERF) -L ANSI-C -t --ignore-case -N lookup_key -H hash_key_name -p -C < $< > $@
-
-src/udev/keymap/keys-to-name.h: src/udev/keymap/keys.txt Makefile
- $(AM_V_GEN)$(AWK) 'BEGIN{ print "const char* const key_names[KEY_CNT] = { "} { print "[" $$1 "] = \"" $$1 "\"," } END{print "};"}' < $< > $@
-endif
-
-EXTRA_DIST += \
- src/udev/keymap/check-keymaps.sh \
- src/udev/keymap/keyboard-force-release.sh.in
-
-# ------------------------------------------------------------------------------
mtd_probe_SOURCES = \
src/udev/mtd_probe/mtd_probe.c \
src/udev/mtd_probe/mtd_probe.h \
@@ -2535,7 +2704,9 @@ libsystemd_id128_la_LDFLAGS = \
libsystemd_id128_la_LIBADD = \
libsystemd-shared.la \
- libsystemd-daemon-internal.la
+ libsystemd-label.la \
+ libsystemd-daemon-internal.la \
+ $(RT_LIBS)
libsystemd_id128_internal_la_SOURCES = \
$(libsystemd_id128_la_SOURCES)
@@ -2545,7 +2716,8 @@ test_id128_SOURCES = \
test_id128_LDADD = \
libsystemd-shared.la \
- libsystemd-id128-internal.la
+ libsystemd-id128-internal.la \
+ libsystemd-daemon.la
tests += \
test-id128
@@ -2682,6 +2854,15 @@ test_journal_stream_LDADD = \
libsystemd-journal-internal.la \
libsystemd-id128-internal.la
+test_journal_init_SOURCES = \
+ src/journal/test-journal-init.c
+
+test_journal_init_LDADD = \
+ libsystemd-shared.la \
+ libsystemd-daemon-internal.la \
+ $(RT_LIBS) \
+ libsystemd-journal.la
+
test_journal_verify_SOURCES = \
src/journal/test-journal-verify.c
@@ -2690,6 +2871,14 @@ test_journal_verify_LDADD = \
libsystemd-journal-internal.la \
libsystemd-id128-internal.la
+test_journal_interleaving_SOURCES = \
+ src/journal/test-journal-interleaving.c
+
+test_journal_interleaving_LDADD = \
+ libsystemd-shared.la \
+ libsystemd-journal-internal.la \
+ libsystemd-id128-internal.la
+
test_mmap_cache_SOURCES = \
src/journal/test-mmap-cache.c
@@ -2700,6 +2889,10 @@ test_mmap_cache_LDADD = \
test_catalog_SOURCES = \
src/journal/test-catalog.c
+test_catalog_CFLAGS = \
+ $(AM_CFLAGS) \
+ -DCATALOG_DIR=\"$(abs_top_srcdir)/catalog\"
+
test_catalog_LDADD = \
libsystemd-shared.la \
libsystemd-label.la \
@@ -2738,6 +2931,7 @@ libsystemd_journal_la_LIBADD = \
libsystemd-shared.la \
libsystemd-label.la \
libsystemd-daemon-internal.la \
+ $(RT_LIBS) \
libsystemd-id128-internal.la
libsystemd_journal_internal_la_SOURCES = \
@@ -2864,7 +3058,9 @@ tests += \
test-journal-syslog \
test-journal-match \
test-journal-stream \
+ test-journal-init \
test-journal-verify \
+ test-journal-interleaving \
test-mmap-cache \
test-catalog
@@ -2982,7 +3178,9 @@ systemd_coredumpctl_SOURCES = \
systemd_coredumpctl_LDADD = \
libsystemd-shared.la \
- libsystemd-journal.la
+ libsystemd-journal.la \
+ libsystemd-journal-internal.la \
+ libsystemd-id128-internal.la
bin_PROGRAMS += \
systemd-coredumpctl
@@ -2990,6 +3188,9 @@ bin_PROGRAMS += \
dist_bashcompletion_DATA += \
shell-completion/bash/systemd-coredumpctl
+dist_zshcompletion_DATA += \
+ shell-completion/zsh/_systemd-coredumpctl
+
sysctl_DATA = \
sysctl.d/50-coredump.conf
@@ -3138,8 +3339,7 @@ rootlibexec_PROGRAMS += \
systemd-random-seed
nodist_systemunit_DATA += \
- units/systemd-random-seed-save.service \
- units/systemd-random-seed-load.service
+ units/systemd-random-seed.service
systemd_random_seed_SOURCES = \
src/random-seed/random-seed.c
@@ -3148,16 +3348,33 @@ systemd_random_seed_LDADD = \
libsystemd-label.la \
libsystemd-shared.la
-SHUTDOWN_TARGET_WANTS += \
- systemd-random-seed-save.service
SYSINIT_TARGET_WANTS += \
- systemd-random-seed-load.service
+ systemd-random-seed.service
+
+endif
+
+EXTRA_DIST += \
+ units/systemd-random-seed.service.in
+# ------------------------------------------------------------------------------
+if ENABLE_BACKLIGHT
+rootlibexec_PROGRAMS += \
+ systemd-backlight
+
+nodist_systemunit_DATA += \
+ units/systemd-backlight@.service
+
+systemd_backlight_SOURCES = \
+ src/backlight/backlight.c
+
+systemd_backlight_LDADD = \
+ libsystemd-label.la \
+ libsystemd-shared.la \
+ libudev-private.la
endif
EXTRA_DIST += \
- units/systemd-random-seed-save.service.in \
- units/systemd-random-seed-load.service.in
+ units/systemd-backlight@.service.in
# ------------------------------------------------------------------------------
if HAVE_LIBCRYPTSETUP
@@ -3254,6 +3471,9 @@ bin_PROGRAMS += \
dist_bashcompletion_DATA += \
shell-completion/bash/hostnamectl
+dist_zshcompletion_DATA += \
+ shell-completion/zsh/_hostnamectl
+
endif
polkitpolicy_in_files += \
@@ -3330,6 +3550,9 @@ bin_PROGRAMS += \
dist_bashcompletion_DATA += \
shell-completion/bash/localectl
+dist_zshcompletion_DATA += \
+ shell-completion/zsh/_localectl
+
endif
polkitpolicy_in_files += \
@@ -3399,6 +3622,9 @@ bin_PROGRAMS += \
dist_bashcompletion_DATA += \
shell-completion/bash/timedatectl
+
+dist_zshcompletion_DATA += \
+ shell-completion/zsh/_timedatectl
endif
polkitpolicy_in_files += \
@@ -3408,24 +3634,6 @@ EXTRA_DIST += \
units/systemd-timedated.service.in
# ------------------------------------------------------------------------------
-if ENABLE_EFI
-bootctl_SOURCES = \
- src/boot/boot.h \
- src/boot/boot-loader.h \
- src/boot/bootctl.c \
- src/boot/boot-loader.c \
- src/boot/boot-efi.c
-
-bootctl_LDADD = \
- libsystemd-shared.la \
- libsystemd-id128.la \
- libsystemd-daemon.la
-
-bin_PROGRAMS += \
- bootctl
-endif
-
-# ------------------------------------------------------------------------------
if HAVE_MYHOSTNAME
libnss_myhostname_la_SOURCES = \
src/nss-myhostname/nss-myhostname.c \
@@ -3448,10 +3656,112 @@ lib_LTLIBRARIES += \
endif
# ------------------------------------------------------------------------------
+if ENABLE_MACHINED
+systemd_machined_SOURCES = \
+ src/machine/machined.c \
+ src/machine/machined.h
+
+systemd_machined_CFLAGS = \
+ $(libsystemd_machine_core_la_CFLAGS)
+
+systemd_machined_LDADD = \
+ libsystemd-machine-core.la \
+ $(libsystemd_machine_core_la_LIBADD)
+
+rootlibexec_PROGRAMS += \
+ systemd-machined
+
+libsystemd_machine_core_la_SOURCES = \
+ src/machine/machined-dbus.c \
+ src/machine/machine.c \
+ src/machine/machine.h \
+ src/machine/machine-dbus.c
+
+libsystemd_machine_core_la_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(DBUS_CFLAGS)
+
+libsystemd_machine_core_la_LIBADD = \
+ libsystemd-label.la \
+ libsystemd-audit.la \
+ libsystemd-shared.la \
+ libsystemd-daemon.la \
+ libsystemd-dbus.la \
+ libsystemd-id128-internal.la \
+ libudev.la
+
+noinst_LTLIBRARIES += \
+ libsystemd-machine-core.la
+
+machinectl_SOURCES = \
+ src/machine/machinectl.c
+
+machinectl_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(DBUS_CFLAGS)
+
+machinectl_LDADD = \
+ libsystemd-shared.la \
+ libsystemd-dbus.la \
+ libudev.la
+
+rootbin_PROGRAMS += \
+ machinectl
+
+test_machine_tables_SOURCES = \
+ src/machine/test-machine-tables.c
+
+test_machine_tables_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(DBUS_CFLAGS)
+
+test_machine_tables_LDADD = \
+ libsystemd-machine-core.la
+
+tests += \
+ test-machine-tables
+
+nodist_systemunit_DATA += \
+ units/systemd-machined.service
+
+dist_systemunit_DATA += \
+ units/machine.slice
+
+dist_dbussystemservice_DATA += \
+ src/machine/org.freedesktop.machine1.service
+
+dist_dbuspolicy_DATA += \
+ src/machine/org.freedesktop.machine1.conf
+
+dist_zshcompletion_DATA += \
+ shell-completion/zsh/_machinectl
+
+SYSTEM_UNIT_ALIASES += \
+ systemd-machined.service dbus-org.freedesktop.machine1.service
+
+EXTRA_DIST += \
+ units/systemd-machined.service.in
+
+endif
+
+# ------------------------------------------------------------------------------
if ENABLE_LOGIND
systemd_logind_SOURCES = \
src/login/logind.c \
- src/login/logind.h \
+ src/login/logind.h
+
+nodist_systemd_logind_SOURCES = \
+ src/login/logind-gperf.c
+
+systemd_logind_CFLAGS = \
+ $(libsystemd_logind_core_la_CFLAGS)
+
+systemd_logind_LDADD = \
+ libsystemd-logind-core.la \
+ $(libsystemd_logind_core_la_LIBADD)
+
+libsystemd_logind_core_la_SOURCES = \
+ src/login/logind-core.c \
src/login/logind-dbus.c \
src/login/logind-device.c \
src/login/logind-device.h \
@@ -3463,6 +3773,8 @@ systemd_logind_SOURCES = \
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 \
@@ -3470,31 +3782,34 @@ systemd_logind_SOURCES = \
src/login/logind-session-dbus.c \
src/login/logind-seat-dbus.c \
src/login/logind-user-dbus.c \
- src/login/logind-acl.h
-
-nodist_systemd_logind_SOURCES = \
- src/login/logind-gperf.c
+ src/login/logind-acl.h \
+ src/login/login-shared.c \
+ src/login/login-shared.h
-systemd_logind_CFLAGS = \
+libsystemd_logind_core_la_CFLAGS = \
$(AM_CFLAGS) \
- $(DBUS_CFLAGS)
+ $(DBUS_CFLAGS)
-systemd_logind_LDADD = \
+libsystemd_logind_core_la_LIBADD = \
libsystemd-label.la \
libsystemd-audit.la \
libsystemd-shared.la \
libsystemd-daemon.la \
libsystemd-dbus.la \
+ libsystemd-id128-internal.la \
libudev.la
if HAVE_ACL
-systemd_logind_SOURCES += \
+libsystemd_logind_core_la_SOURCES += \
src/login/logind-acl.c
-systemd_logind_LDADD += \
+libsystemd_logind_core_la_LIBADD += \
libsystemd-acl.la
endif
+noinst_LTLIBRARIES += \
+ libsystemd-logind-core.la
+
systemd_user_sessions_SOURCES = \
src/login/user-sessions.c
@@ -3524,6 +3839,10 @@ rootbin_PROGRAMS += \
dist_bashcompletion_DATA += \
shell-completion/bash/loginctl
+dist_zshcompletion_DATA += \
+ shell-completion/zsh/_loginctl \
+ shell-completion/zsh/_systemd-inhibit
+
systemd_inhibit_SOURCES = \
src/login/inhibit.c
@@ -3545,6 +3864,13 @@ test_login_LDADD = \
libsystemd-login-internal.la \
libsystemd-shared.la
+test_login_shared_SOURCES = \
+ src/login/test-login-shared.c
+
+test_login_shared_LDADD = \
+ libsystemd-login-internal.la \
+ libsystemd-shared.la
+
test_inhibit_SOURCES = \
src/login/test-inhibit.c
@@ -3556,12 +3882,29 @@ test_inhibit_CFLAGS = \
$(AM_CFLAGS) \
$(DBUS_CFLAGS)
+test_login_tables_SOURCES = \
+ src/login/test-login-tables.c
+
+test_login_tables_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(DBUS_CFLAGS)
+
+test_login_tables_LDADD = \
+ libsystemd-logind-core.la
+
manual_tests += \
test-login \
test-inhibit
+tests += \
+ test-login-tables \
+ test-login-shared
+
libsystemd_login_la_SOURCES = \
- src/login/sd-login.c
+ src/login/sd-login.c \
+ src/systemd/sd-login.h \
+ src/login/login-shared.c \
+ src/login/login-shared.h
libsystemd_login_la_CFLAGS = \
$(AM_CFLAGS) \
@@ -3574,7 +3917,8 @@ libsystemd_login_la_LDFLAGS = \
libsystemd_login_la_LIBADD = \
libsystemd-shared.la \
- libsystemd-daemon-internal.la
+ libsystemd-daemon-internal.la \
+ $(RT_LIBS)
libsystemd_login_internal_la_SOURCES = \
$(libsystemd_login_la_SOURCES)
@@ -3602,10 +3946,14 @@ pam_systemd_la_LIBADD = \
libsystemd-dbus.la \
libsystemd-shared.la \
libsystemd-daemon-internal.la \
+ $(RT_LIBS) \
$(PAM_LIBS)
pamlib_LTLIBRARIES = \
pam_systemd.la
+
+dist_pamconf_DATA = \
+ src/login/systemd-user
endif
# move lib from $(libdir) to $(rootlibdir) and update devel link, if needed
@@ -3622,6 +3970,9 @@ nodist_systemunit_DATA += \
units/systemd-logind.service \
units/systemd-user-sessions.service
+dist_systemunit_DATA += \
+ units/user.slice
+
dist_dbussystemservice_DATA += \
src/login/org.freedesktop.login1.service
@@ -3707,7 +4058,7 @@ _journal_la_SOURCES = \
_journal_la_CFLAGS = \
$(AM_CFLAGS) \
-fvisibility=default \
- $(PYTHON_CFLAGS)
+ $(PYTHON_DEVEL_CFLAGS)
_journal_la_LDFLAGS = \
$(AM_LDFLAGS) \
@@ -3716,7 +4067,7 @@ _journal_la_LDFLAGS = \
-avoid-version
_journal_la_LIBADD = \
- $(PYTHON_LIBS) \
+ $(PYTHON_DEVEL_LIBS) \
libsystemd-journal.la
id128_la_SOURCES = \
@@ -3728,7 +4079,7 @@ id128_la_SOURCES = \
id128_la_CFLAGS = \
$(AM_CFLAGS) \
-fvisibility=default \
- $(PYTHON_CFLAGS) \
+ $(PYTHON_DEVEL_CFLAGS) \
-I$(top_builddir)/src/python-systemd
id128_la_LDFLAGS = \
@@ -3738,7 +4089,7 @@ id128_la_LDFLAGS = \
-avoid-version
id128_la_LIBADD = \
- $(PYTHON_LIBS) \
+ $(PYTHON_DEVEL_LIBS) \
libsystemd-id128.la
_daemon_la_SOURCES = \
@@ -3749,7 +4100,7 @@ _daemon_la_SOURCES = \
_daemon_la_CFLAGS = \
$(AM_CFLAGS) \
-fvisibility=default \
- $(PYTHON_CFLAGS) \
+ $(PYTHON_DEVEL_CFLAGS) \
-I$(top_builddir)/src/python-systemd
_daemon_la_LDFLAGS = \
@@ -3759,7 +4110,7 @@ _daemon_la_LDFLAGS = \
-avoid-version
_daemon_la_LIBADD = \
- $(PYTHON_LIBS) \
+ $(PYTHON_DEVEL_LIBS) \
libsystemd-daemon.la
_reader_la_SOURCES = \
@@ -3770,7 +4121,7 @@ _reader_la_SOURCES = \
_reader_la_CFLAGS = \
$(AM_CFLAGS) \
-fvisibility=default \
- $(PYTHON_CFLAGS)
+ $(PYTHON_DEVEL_CFLAGS)
_reader_la_LDFLAGS = \
$(AM_LDFLAGS) \
@@ -3779,11 +4130,12 @@ _reader_la_LDFLAGS = \
-avoid-version
_reader_la_LIBADD = \
- $(PYTHON_LIBS) \
+ $(PYTHON_DEVEL_LIBS) \
libsystemd-journal.la \
libsystemd-id128.la \
libsystemd-shared.la \
- libsystemd-daemon-internal.la
+ libsystemd-daemon-internal.la \
+ $(RT_LIBS)
login_la_SOURCES = \
src/python-systemd/login.c \
@@ -3793,7 +4145,7 @@ login_la_SOURCES = \
login_la_CFLAGS = \
$(AM_CFLAGS) \
-fvisibility=default \
- $(PYTHON_CFLAGS)
+ $(PYTHON_DEVEL_CFLAGS)
login_la_LDFLAGS = \
$(AM_LDFLAGS) \
@@ -3802,11 +4154,12 @@ login_la_LDFLAGS = \
-avoid-version
login_la_LIBADD = \
- $(PYTHON_LIBS) \
+ $(PYTHON_DEVEL_LIBS) \
libsystemd-journal.la \
libsystemd-login.la \
libsystemd-shared.la \
- libsystemd-daemon-internal.la
+ libsystemd-daemon-internal.la \
+ $(RT_LIBS)
dist_pkgpyexec_PYTHON = \
src/python-systemd/journal.py \
@@ -3826,6 +4179,10 @@ sphinx-%:
$(AM_V_GEN)PYTHONPATH=$(DESTDIR)$(pyexecdir) LD_LIBRARY_PATH=$(DESTDIR)$(libdir) $(SPHINX_BUILD) -b $* $(SPHINXOPTS) $(top_srcdir)/src/python-systemd/docs $(top_builddir)/docs/html/python-systemd/
$(AM_V_at)echo Output has been generated in $(abs_top_builddir)/docs/html/python-systemd/
+python-shell:
+ $(AM_V_at)echo "Starting python with $(DESTDIR)$(pyexecdir)"
+ $(AM_V_at)PYTHONPATH=$(DESTDIR)$(pyexecdir) LD_LIBRARY_PATH=$(DESTDIR)$(libdir) $(PYTHON)
+
destdir-sphinx: all
dir="$$(mktemp -d /tmp/systemd-install.XXXXXX)" && \
$(MAKE) DESTDIR="$$dir" install && \
@@ -3839,6 +4196,11 @@ CLEAN_LOCAL_HOOKS += clean-sphinx
clean-sphinx:
-rm -rf docs/html/python-systemd/
+# Remove Python stuff, e.g. to force rebuilding for a different Python version.
+clean-python:
+ -rm -rf src/python-systemd/.libs src/python-systemd/*.l[ao]
+ -rm -f _daemon.la id128.la _journal.la login.la _reader.la
+
# ------------------------------------------------------------------------------
substitutions = \
'|rootlibexecdir=$(rootlibexecdir)|' \
@@ -3859,10 +4221,12 @@ substitutions = \
'|catalogdir=$(catalogdir)|' \
'|tmpfilesdir=$(tmpfilesdir)|' \
'|sysctldir=$(sysctldir)|' \
+ '|systemgeneratordir=$(systemgeneratordir)|' \
+ '|usergeneratordir=$(usergeneratordir)|' \
'|PACKAGE_VERSION=$(PACKAGE_VERSION)|' \
'|PACKAGE_NAME=$(PACKAGE_NAME)|' \
'|PACKAGE_URL=$(PACKAGE_URL)|' \
- '|RANDOM_SEED=$(localstatedir)/lib/random-seed|' \
+ '|RANDOM_SEED=$(localstatedir)/lib/systemd/random-seed|' \
'|prefix=$(prefix)|' \
'|exec_prefix=$(exec_prefix)|' \
'|libdir=$(libdir)|' \
@@ -3873,6 +4237,8 @@ substitutions = \
'|SUSHELL=$(SUSHELL)|' \
'|DEBUGTTY=$(DEBUGTTY)|' \
'|KILL=$(KILL)|' \
+ '|KMOD=$(KMOD)|' \
+ '|MKDIR_P=$(MKDIR_P)|' \
'|QUOTAON=$(QUOTAON)|' \
'|QUOTACHECK=$(QUOTACHECK)|' \
'|SYSTEM_SYSVINIT_PATH=$(sysvinitdir)|' \
@@ -4027,9 +4393,6 @@ EXTRA_DIST += \
docs/sysvinit/README.in \
docs/var-log/README.in
-EXTRA_DIST += \
- shell-completion/systemd-zsh-completion.zsh
-
SOCKETS_TARGET_WANTS += \
systemd-initctl.socket \
systemd-shutdownd.socket
@@ -4046,8 +4409,8 @@ RUNLEVEL4_TARGET_WANTS += \
RUNLEVEL5_TARGET_WANTS += \
systemd-update-utmp-runlevel.service
endif
-SHUTDOWN_TARGET_WANTS += \
- systemd-update-utmp-shutdown.service
+SYSINIT_TARGET_WANTS += \
+ systemd-update-utmp.service
LOCAL_FS_TARGET_WANTS += \
systemd-remount-fs.service \
systemd-fsck-root.service \
@@ -4061,12 +4424,8 @@ SYSINIT_TARGET_WANTS += \
sys-kernel-config.mount \
sys-kernel-debug.mount \
sys-fs-fuse-connections.mount \
- systemd-tmpfiles-setup-dev.service \
- systemd-tmpfiles-setup.service \
systemd-sysctl.service \
systemd-ask-password-console.path
-TIMERS_TARGET_WANTS += \
- systemd-tmpfiles-clean.timer
if HAVE_SYSV_COMPAT
SYSTEM_UNIT_ALIASES += \
@@ -4110,8 +4469,6 @@ INSTALL_DIRS += \
endif
INSTALL_DIRS += \
- $(tmpfilesdir) \
- $(sysconfdir)/tmpfiles.d \
$(prefix)/lib/modules-load.d \
$(sysconfdir)/modules-load.d \
$(prefix)/lib/sysctl.d \
@@ -4150,7 +4507,9 @@ DISTCHECK_CONFIGURE_FLAGS = \
--with-dbussystemservicedir=$$dc_install_base/$(dbussystemservicedir) \
--with-dbusinterfacedir=$$dc_install_base/$(dbusinterfacedir) \
--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 \
--disable-split-usr
diff --git a/NEWS b/NEWS
index 6cfe0dfc59..557774dc1f 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,432 @@
systemd System and Service Manager
+CHANGES WITH 208:
+
+ * logind has gained support for facilitating privileged input
+ and drm device access for unprivileged clients. This work is
+ useful to allow Wayland display servers (and similar
+ programs, such as kmscon) to run under the user's ID and
+ access input and drm devices which are normally
+ protected. When this is used (and the kernel is new enough)
+ logind will "mute" IO on the file descriptors passed to
+ Wayland as long as it is in the background and "unmute" it
+ if it returns into the foreground. This allows secure
+ session switching without allowing background sessions to
+ eavesdrop on input and display data. This also introduces
+ session switching support if VT support is turned off in the
+ kernel, and on seats that are not seat0.
+
+ * A new kernel command line option luks.options= is understood
+ now which allows specifiying LUKS options for usage for LUKS
+ encrypted partitions specified with luks.uuid=.
+
+ * tmpfiles.d(5) snippets may now use specifier expansion in
+ path names. More specifically %m, %b, %H, %v, are now
+ replaced by the local machine id, boot id, hostname, and
+ kernel version number.
+
+ * A new tmpfiles.d(5) command "m" has been introduced which
+ may be used to change the owner/group/access mode of a file
+ or directory if it exists, but do nothing if it doesn't.
+
+ * This release removes high-level support for the
+ MemorySoftLimit= cgroup setting. The underlying kernel
+ cgroup attribute memory.soft_limit= is currently badly
+ designed and likely to be removed from the kernel API in its
+ current form, hence we shouldn't expose it for now.
+
+ * The memory.use_hierarchy cgroup attribute is now enabled for
+ all cgroups systemd creates in the memory cgroup
+ hierarchy. This option is likely to be come the built-in
+ default in the kernel anyway, and the non-hierarchial mode
+ never made much sense in the intrinsically hierarchial
+ cgroup system.
+
+ * A new field _SYSTEMD_SLICE= is logged along with all journal
+ messages containing the slice a message was generated
+ from. This is useful to allow easy per-customer filtering of
+ logs among other things.
+
+ * systemd-journald will no longer adjust the group of journal
+ files it creates to the "systemd-journal" group. Instead we
+ rely on the journal directory to be owned by the
+ "systemd-journal" group, and its setgid bit set, so that the
+ kernel file system layer will automatically enforce that
+ journal files inherit this group assignment. The reason for
+ this change is that we cannot allow NSS look-ups from
+ journald which would be necessary to resolve
+ "systemd-journal" to a numeric GID, because this might
+ create deadlocks if NSS involves synchronous queries to
+ other daemons (such as nscd, or sssd) which in turn are
+ logging clients of journald and might block on it, which
+ would then dead lock. A tmpfiles.d(5) snippet included in
+ systemd will make sure the setgid bit and group are
+ properly set on the journal directory if it exists on every
+ boot. However, we recommend adjusting it manually after
+ upgrades too (or from RPM scriptlets), so that the change is
+ not delayed until next reboot.
+
+ * Backlight and random seed files in /var/lib/ have moved into
+ the /var/lib/systemd/ directory, in order to centralize all
+ systemd generated files in one directory.
+
+ * Boot time performance measurements (as displayed by
+ "systemd-analyze" for example) will now read ACPI 5.0 FPDT
+ performance information if that's available to determine how
+ much time BIOS and boot loader initialization required. With
+ a sufficiently new BIOS you hence no longer need to boot
+ with Gummiboot to get access to such information.
+
+ Contributions from: Andrey Borzenkov, Chen Jie, Colin Walters,
+ Cristian Rodríguez, Dave Reisner, David Herrmann, David
+ Mackey, David Strauss, Eelco Dolstra, Evan Callicoat, Gao
+ feng, Harald Hoyer, Jimmie Tauriainen, Kay Sievers, Lennart
+ Poettering, Lukas Nykryn, Mantas Mikulėnas, Martin Pitt,
+ Michael Scherer, Michał Górny, Mike Gilbert, Patrick McCarty,
+ Sebastian Ott, Tom Gundersen, Zbigniew Jędrzejewski-Szmek
+
+ -- Berlin, 2013-10-02
+
+CHANGES WITH 207:
+
+ * The Restart= option for services now understands a new
+ on-watchdog setting, which will restart the service
+ automatically if the service stops sending out watchdog keep
+ alive messages (as configured with WatchdogSec=).
+
+ * The getty generator (which is responsible for bringing up a
+ getty on configured serial consoles) will no longer only
+ start a getty on the primary kernel console but on all
+ others, too. This makes the order in which console= is
+ specified on the kernel command line less important.
+
+ * libsystemd-logind gained a new sd_session_get_vt() call to
+ retrieve the VT number of a session.
+
+ * If the option "tries=0" is set for an entry of /etc/crypttab
+ its passphrase is queried indefinitely instead of any
+ maximum number of tries.
+
+ * If a service with a configure PID file terminates its PID
+ file will now be removed automatically if it still exists
+ afterwards. This should put an end to stale PID files.
+
+ * systemd-run will now also take relative binary path names
+ for execution and no longer insists on absolute paths.
+
+ * InaccessibleDirectories= and ReadOnlyDirectories= now take
+ paths that are optionally prefixed with "-" to indicate that
+ it should not be considered a failure if they don't exist.
+
+ * journalctl -o (and similar commands) now understands a new
+ output mode "short-precise", it is similar to "short" but
+ shows timestamps with usec accuracy.
+
+ * The option "discard" (as known from Debian) is now
+ synonymous to "allow-discards" in /etc/crypttab. In fact,
+ "discard" is preferred now (since it is easier to remember
+ and type).
+
+ * Some licensing clean-ups were made, so that more code is now
+ LGPL-2.1 licensed than before.
+
+ * A minimal tool to save/restore the display backlight
+ brightness across reboots has been added. It will store the
+ backlight setting as late as possible at shutdown, and
+ restore it as early as possible during reboot.
+
+ * A logic to automatically discover and enable home and swap
+ partitions on GPT disks has been added. With this in place
+ /etc/fstab becomes optional for many setups as systemd can
+ discover certain partitions located on the root disk
+ automatically. Home partitions are recognized under their
+ GPT type ID 933ac7e12eb44f13b8440e14e2aef915. Swap
+ partitions are recognized under their GPT type ID
+ 0657fd6da4ab43c484e50933c84b4f4f.
+
+ * systemd will no longer pass any environment from the kernel
+ or initrd to system services. If you want to set an
+ environment for all services, do so via the kernel command
+ line systemd.setenv= assignment.
+
+ * The systemd-sysctl tool no longer natively reads the file
+ /etc/sysctl.conf. If desired, the file should be symlinked
+ from /etc/sysctl.d/99-sysctl.conf. Apart from providing
+ legacy support by a symlink rather than built-in code, it
+ also makes the otherwise hidden order of application of the
+ different files visible. (Note that this partly reverts to a
+ pre-198 application order of sysctl knobs!)
+
+ * The "systemctl set-log-level" and "systemctl dump" commands
+ have been moved to systemd-analyze.
+
+ * systemd-run learned the new --remain-after-exit switch,
+ which causes the scope unit not to be cleaned up
+ automatically after the process terminated.
+
+ * tmpfiles learned a new --exclude-prefix= switch to exclude
+ certain paths from operation.
+
+ * journald will now automatically flush all messages to disk
+ as soon as a message of the log priorities CRIT, ALERT or
+ EMERG is received.
+
+ Contributions from: Andrew Cook, Brandon Philips, Christian
+ Hesse, Christoph Junghans, Colin Walters, Daniel Schaal,
+ Daniel Wallace, Dave Reisner, David Herrmann, Gao feng, George
+ McCollister, Giovanni Campagna, Hannes Reinecke, Harald Hoyer,
+ Herczeg Zsolt, Holger Hans Peter Freyther, Jan Engelhardt,
+ Jesper Larsen, Kay Sievers, Khem Raj, Lennart Poettering,
+ Lukas Nykryn, Maciej Wereski, Mantas Mikulėnas, Marcel
+ Holtmann, Martin Pitt, Michael Biebl, Michael Marineau,
+ Michael Scherer, Michael Stapelberg, Michal Sekletar, Michał
+ Górny, Olivier Brunel, Ondrej Balaz, Ronny Chevalier, Shawn
+ Landden, Steven Hiscocks, Thomas Bächler, Thomas Hindoe
+ Paaboel Andersen, Tom Gundersen, Umut Tezduyar, WANG Chao,
+ William Giokas, Zbigniew Jędrzejewski-Szmek
+
+ -- Berlin, 2013-09-13
+
+CHANGES WITH 206:
+
+ * The documentation has been updated to cover the various new
+ concepts introduced with 205.
+
+ * Unit files now understand the new %v specifier which
+ resolves to the kernel version string as returned by "uname
+ -r".
+
+ * systemctl now supports filtering the unit list output by
+ load state, active state and sub state, using the new
+ --state= parameter.
+
+ * "systemctl status" will now show the results of the
+ condition checks (like ConditionPathExists= and similar) of
+ the last start attempts of the unit. They are also logged to
+ the journal.
+
+ * "journalctl -b" may now be used to look for boot output of a
+ specific boot. Try "journalctl -b -1" for the previous boot,
+ but the syntax is substantially more powerful.
+
+ * "journalctl --show-cursor" has been added which prints the
+ cursor string the last shown log line. This may then be used
+ with the new "journalctl --after-cursor=" switch to continue
+ browsing logs from that point on.
+
+ * "journalctl --force" may now be used to force regeneration
+ of an FSS key.
+
+ * Creation of "dead" device nodes has been moved from udev
+ into kmod and tmpfiles. Previously, udev would read the kmod
+ databases to pre-generate dead device nodes based on meta
+ information contained in kernel modules, so that these would
+ be auto-loaded on access rather then at boot. As this
+ doesn't really have much to do with the exposing actual
+ kernel devices to userspace this has always been slightly
+ alien in the udev codebase. Following the new scheme kmod
+ will now generate a runtime snippet for tmpfiles from the
+ module meta information and it now is tmpfiles' job to the
+ create the nodes. This also allows overriding access and
+ other parameters for the nodes using the usual tmpfiles
+ facilities. As side effect this allows us to remove the
+ CAP_SYS_MKNOD capability bit from udevd entirely.
+
+ * logind's device ACLs may now be applied to these "dead"
+ devices nodes too, thus finally allowing managed access to
+ devices such as /dev/snd/sequencer whithout loading the
+ backing module right-away.
+
+ * A new RPM macro has been added that may be used to apply
+ tmpfiles configuration during package installation.
+
+ * systemd-detect-virt and ConditionVirtualization= now can
+ detect User-Mode-Linux machines (UML).
+
+ * journald will now implicitly log the effective capabilities
+ set of processes in the message metadata.
+
+ * systemd-cryptsetup has gained support for TrueCrypt volumes.
+
+ * The initrd interface has been simplified (more specifically,
+ support for passing performance data via environment
+ variables and fsck results via files in /run has been
+ removed). These features were non-essential, and are
+ nowadays available in a much nicer way by having systemd in
+ the initrd serialize its state and have the hosts systemd
+ deserialize it again.
+
+ * The udev "keymap" data files and tools to apply keyboard
+ specific mappings of scan to key codes, and force-release
+ scan code lists have been entirely replaced by a udev
+ "keyboard" builtin and a hwdb data file.
+
+ * systemd will now honour the kernel's "quiet" command line
+ argument also during late shutdown, resulting in a
+ completely silent shutdown when used.
+
+ * There's now an option to control the SO_REUSEPORT socket
+ option in .socket units.
+
+ * Instance units will now automatically get a per-template
+ subslice of system.slice unless something else is explicitly
+ configured. For example, instances of sshd@.service will now
+ implicitly be placed in system-sshd.slice rather than
+ system.slice as before.
+
+ * Test coverage support may now be enabled at build time.
+
+ Contributions from: Dave Reisner, Frederic Crozat, Harald
+ Hoyer, Holger Hans Peter Freyther, Jan Engelhardt, Jan
+ Janssen, Jason St. John, Jesper Larsen, Kay Sievers, Lennart
+ Poettering, Lukas Nykryn, Maciej Wereski, Martin Pitt, Michael
+ Olbrich, Ramkumar Ramachandra, Ross Lagerwall, Shawn Landden,
+ Thomas H.P. Andersen, Tom Gundersen, Tomasz Torcz, William
+ Giokas, Zbigniew Jędrzejewski-Szmek
+
+ -- Berlin, 2013-07-23
+
+CHANGES WITH 205:
+
+ * Two new unit types have been introduced:
+
+ Scope units are very similar to service units, however, are
+ created out of pre-existing processes -- instead of PID 1
+ forking off the processes. By using scope units it is
+ possible for system services and applications to group their
+ own child processes (worker processes) in a powerful way
+ which then maybe used to organize them, or kill them
+ together, or apply resource limits on them.
+
+ Slice units may be used to partition system resources in an
+ hierarchial fashion and then assign other units to them. By
+ default there are now three slices: system.slice (for all
+ system services), user.slice (for all user sessions),
+ machine.slice (for VMs and containers).
+
+ Slices and scopes have been introduced primarily in
+ context of the work to move cgroup handling to a
+ single-writer scheme, where only PID 1
+ creates/removes/manages cgroups.
+
+ * There's a new concept of "transient" units. In contrast to
+ normal units these units are created via an API at runtime,
+ not from configuration from disk. More specifically this
+ means it is now possible to run arbitrary programs as
+ independent services, with all execution parameters passed
+ in via bus APIs rather than read from disk. Transient units
+ make systemd substantially more dynamic then it ever was,
+ and useful as a general batch manager.
+
+ * logind has been updated to make use of scope and slice units
+ for managing user sessions. As a user logs in he will get
+ his own private slice unit, to which all sessions are added
+ as scope units. We also added support for automatically
+ adding an instance of user@.service for the user into the
+ slice. Effectively logind will no longer create cgroup
+ hierarchies on its own now, it will defer entirely to PID 1
+ for this by means of scope, service and slice units. Since
+ user sessions this way become entities managed by PID 1
+ the output of "systemctl" is now a lot more comprehensive.
+
+ * A new mini-daemon "systemd-machined" has been added which
+ may be used by virtualization managers to register local
+ VMs/containers. nspawn has been updated accordingly, and
+ libvirt will be updated shortly. machined will collect a bit
+ of meta information about the VMs/containers, and assign
+ them their own scope unit (see above). The collected
+ meta-data is then made available via the "machinectl" tool,
+ and exposed in "ps" and similar tools. machined/machinectl
+ is compile-time optional.
+
+ * As discussed earlier, the low-level cgroup configuration
+ options ControlGroup=, ControlGroupModify=,
+ ControlGroupPersistent=, ControlGroupAttribute= have been
+ removed. Please use high-level attribute settings instead as
+ well as slice units.
+
+ * A new bus call SetUnitProperties() has been added to alter
+ various runtime parameters of a unit. This is primarily
+ useful to alter cgroup parameters dynamically in a nice way,
+ but will be extended later on to make more properties
+ modifiable at runtime. systemctl gained a new set-properties
+ command that wraps this call.
+
+ * A new tool "systemd-run" has been added which can be used to
+ run arbitrary command lines as transient services or scopes,
+ while configuring a number of settings via the command
+ line. This tool is currently very basic, however already
+ very useful. We plan to extend this tool to even allow
+ queuing of execution jobs with time triggers from the
+ command line, similar in fashion to "at".
+
+ * nspawn will now inform the user explicitly that kernels with
+ audit enabled break containers, and suggest the user to turn
+ off audit.
+
+ * Support for detecting the IMA and AppArmor security
+ frameworks with ConditionSecurity= has been added.
+
+ * journalctl gained a new "-k" switch for showing only kernel
+ messages, mimicking dmesg output; in addition to "--user"
+ and "--system" switches for showing only user's own logs
+ and system logs.
+
+ * systemd-delta can now show information about drop-in
+ snippets extending unit files.
+
+ * libsystemd-bus has been substantially updated but is still
+ not available as public API.
+
+ * systemd will now look for the "debug" argument on the kernel
+ command line and enable debug logging, similar to
+ "systemd.log_level=debug" already did before.
+
+ * "systemctl set-default", "systemctl get-default" has been
+ added to configure the default.target symlink, which
+ controls what to boot into by default.
+
+ * "systemctl set-log-level" has been added as a convenient
+ way to raise and lower systemd logging threshold.
+
+ * "systemd-analyze plot" will now show the time the various
+ generators needed for execution, as well as information
+ about the unit file loading.
+
+ * libsystemd-journal gained a new sd_journal_open_files() call
+ for opening specific journal files. journactl also gained a
+ new switch to expose this new functionality. Previously we
+ only supported opening all files from a directory, or all
+ files from the system, as opening individual files only is
+ racy due to journal file rotation.
+
+ * systemd gained the new DefaultEnvironment= setting in
+ /etc/systemd/system.conf to set environment variables for
+ all services.
+
+ * If a privileged process logs a journal message with the
+ OBJECT_PID= field set, then journald will automatically
+ augment this with additional OBJECT_UID=, OBJECT_GID=,
+ OBJECT_COMM=, OBJECT_EXE=, ... fields. This is useful if
+ system services want to log events about specific client
+ processes. journactl/systemctl has been updated to make use
+ of this information if all log messages regarding a specific
+ unit is requested.
+
+ Contributions from: Auke Kok, Chengwei Yang, Colin Walters,
+ Cristian Rodríguez, Daniel Albers, Daniel Wallace, Dave
+ Reisner, David Coppa, David King, David Strauss, Eelco
+ Dolstra, Gabriel de Perthuis, Harald Hoyer, Jan Alexander
+ Steffens, Jan Engelhardt, Jan Janssen, Jason St. John, Johan
+ Heikkilä, Karel Zak, Karol Lewandowski, Kay Sievers, Lennart
+ Poettering, Lukas Nykryn, Mantas Mikulėnas, Marius Vollmer,
+ Martin Pitt, Michael Biebl, Michael Olbrich, Michael Tremer,
+ Michal Schmidt, Michał Bartoszkiewicz, Nirbheek Chauhan,
+ Pierre Neidhardt, Ross Burton, Ross Lagerwall, Sean McGovern,
+ Thomas Hindoe Paaboel Andersen, Tom Gundersen, Umut Tezduyar,
+ Václav Pavlín, Zachary Cook, Zbigniew Jędrzejewski-Szmek,
+ Łukasz Stelmach, 장동준
+
CHANGES WITH 204:
* The Python bindings gained some minimal support for the APIs
@@ -1798,7 +2225,7 @@ CHANGES WITH 41:
understood to set system wide environment variables
dynamically at boot.
- * We now limit the set of capabilities of systemd-journald.
+ * We now limit the set of capabilities of systemd-journald.
* We now set SIGPIPE to ignore by default, since it only is
useful in shell pipelines, and has little use in general
diff --git a/README b/README
index b8d1f42e25..b39cd377df 100644
--- a/README
+++ b/README
@@ -31,10 +31,12 @@ AUTHOR:
LICENSE:
LGPLv2.1+ for all code
- except sd-daemon.[ch] and sd-readahead.[ch] which are MIT
- - except src/udev/ which is (currently still) GPLv2+
+ - except src/shared/MurmurHash3.c which is Public Domain
+ - except src/journal/lookup3.c which is Public Domain
+ - except src/udev/* which is (currently still) GPLv2, GPLv2+
REQUIREMENTS:
- Linux kernel >= 2.6.39
+ Linux kernel >= 3.0
CONFIG_DEVTMPFS
CONFIG_CGROUPS (it's OK to disable all controllers)
CONFIG_INOTIFY_USER
@@ -62,6 +64,10 @@ REQUIREMENTS:
Mount and bind mount handling might require it:
CONFIG_FHANDLE
+ Support for some SCSI devices serial number retrieval, to
+ create additional symlinks in /dev/disk/ and /dev/tape:
+ CONFIG_BLK_DEV_BSG
+
Optional but strongly recommended:
CONFIG_IPV6
CONFIG_AUTOFS4_FS
@@ -79,10 +85,17 @@ REQUIREMENTS:
CONFIG_EFI_VARS
CONFIG_EFI_PARTITION
+ Note that kernel auditing is broken when used with systemd's
+ container code. When using systemd in conjunction with
+ containers please make sure to either turn off auditing at
+ runtime using the kernel command line option "audit=0", or
+ turn it off at kernel compile time using:
+ CONFIG_AUDIT=n
+
dbus >= 1.4.0
libcap
libblkid >= 2.20 (from util-linux) (optional)
- libkmod >= 5 (optional)
+ libkmod >= 14 (optional)
PAM >= 1.1.2 (optional)
libcryptsetup (optional)
libaudit (optional)
diff --git a/TODO b/TODO
index 4f5af140f0..07269f47d2 100644
--- a/TODO
+++ b/TODO
@@ -1,6 +1,9 @@
Bugfixes:
-* systemctl status *.path shows all logs, not only the ones since the unit is
- active
+
+* enabling an instance unit creates pointless link, and
+ the unit will be started with getty@getty.service:
+ $ systemctl enable getty@.service
+ ln -s '/usr/lib/systemd/system/getty@.service' '/etc/systemd/system/getty.target.wants/getty@.service'
* check systemd-tmpfiles for selinux context hookup for mknod(), symlink() and similar
@@ -14,30 +17,193 @@ Bugfixes:
* properly handle .mount unit state tracking when two mount points are stacked one on top of another on the exact same mount point.
-Fedora 19:
+* ellipsize_mem must take into account multi-byte unicode characters, and
+ - make the resulting line the requested number of *characters*, not *bytes*,
+ - avoid truncuating multi-byte sequences in the middle.
+
+* When we detect invalid UTF-8, we cant't use it in an error message:
+ log...("Path is not UTF-8 clean, ignoring assignment: %s", rvalue);
+
+* shorten the message to sane length:
-* external: maybe it is time to patch procps so that "ps" links to
- libsystemd-logind to print a pretty service name, seat name, session
- name in its output. Currently it only shows cgroup membership, but
- that's sometimes kinda hard to parse for a human.
+ Cannot add dependency job for unit display-manager.service, ignoring: Unit display-manager.service failed to load: No such file or directory. See system logs and 'systemctl status display-manager.service' for details.
-* cgroup attrs:
- - update dbus interface docs in wiki
+Fedora 20:
+
+* external: ps should gain colums for slice and machine
* localed:
- localectl: support new converted x11→console keymaps
+* when installing fedora with yum --installroot /var/run is a directory, not a symlink
+ https://bugzilla.redhat.com/show_bug.cgi?id=975864
+
+CGroup Rework Completion:
+
+* introduce "mainpid" for scopes (or maybe not?)
+
+* implement system-wide DefaultCPUAccounting=1 switch (and similar for blockio, memory?)
+
+* implement per-slice CPUFairScheduling=1 switch
+
+* handle jointly mounted controllers correctly
+
+* introduce high-level settings for RT budget, swappiness
+
+* wiki: guidelines how to make use of new cgroup apis
+
Features:
+* set $SHELL where we set $HOME and $USER when User= is set of a service, drop its manual setting from user@.service
+
+* we probably should replace the left-over uses of strv_append() and replace them by strv_push() or strv_extend()
+
+* move config_parse_path_strv() out of conf-parser.c
+
+* libdsystemd-bus should expose utf8 validation calls
+
+* After coming back from hibernation reset hibernation swap partition
+
+* If we try to find a unit via a dangling symlink generate a clean
+ error. Currently we just ignore it and read the unit from the search
+ path anyway.
+
+* When a Type=forking service fails and needed another service that
+ service is not cleaned up again when it has StopWhenUnneeded=yes
+ http://lists.freedesktop.org/archives/systemd-devel/2013-July/012141.html
+
+* backlight: properly handle multiple backlight devices for the same
+ hardware: at shutdown we should only save the backlight setting for
+ the "best" way to access the backlight. Strategy should be: at
+ shutdown, ignore all backlights that are connected to a non-eDP or
+ non-LVDS port, and then prefer the firmware device over platform
+ device over raw device per-PCI card. Delete all old data. At boot
+ simply apply whatever data we find. Also see
+ http://cgit.freedesktop.org/libbacklight/tree/libbacklight.c#n194
+
+* rfkill: save/restore soft rfkill status across reboots
+
+* refuse boot if /etc/os-release is missing or /etc/machine-id cannot be set up
+
+* ensure scope units may be started only a single time
+
+* document that in instead of FsckPassNo= people should just add a manual dep to systemd-fsck@.service to their mount units.
+
+* better error message if you run systemctl without systemd running
+
+* systemctl status output should should include list of triggering units and their status
+
+* for transient units, instead of writing out drop-ins for all properties consider serializing them in the normal serialization stream
+
+* logind: when logging out, remove user-owned sysv and posix IPC objects
+
+* session scopes/user unit: add RequiresMountsFor for the home directory of the user
+
+* add a man page containing packaging guidelines and recommending usage of things like Documentation=, PrivateTmp=, PrivateNetwork= and ReadOnlyDirectories=/etc /usr.
+
+* journalctl: instead --after-cursor= maybe have a --cursor=XYZ+1 syntax?
+
+* given that logind/machined now let PID 1 do all nasty work we can
+ probably reduce the capability set they retain substantially.
+
+* btrfs raid assembly: some .device jobs stay stuck in the queue
+
+* Fedora: add an rpmlint check that verifies that all unit files in the RPM are listed in %systemd_post macros.
+
+* Fedora: post FPC ticket to move add %tmpfiles_create to the packaging guidelines
+
+* make sure gdm doesn't use multi-user-x but the new default X configuration file, and then remove multi-user-x from systemd
+
+* when parsing calendar timestamps support the UTC timezone (even if we won't support arbitrary timezone specs, support UTC itself certainly makes sense), also support syntaxes such as +0200
+
+* when a kernel driver logs in a tight loop we should ratelimit that too.
+
+* "systemctl disable" of a unit instance removes all symlinks, should
+ only remove the instance symlink (systemctl disable of a template
+ unit however should remove them all).
+
+* journald: optionally, log debug messages to /run but everything else to /var
+
+* systemctl list-unit-files should list generated files (and probably with a new state "generated" for them, or so)
+
+* 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.
+
+* man: the documentation of Restart= currently is very misleading and suggests the tools from ExecStartPre= might get restarted.
+
+* load .d/*.conf dropins for device units
+
+* add a fixed dbus path for "my own unit", "my own session", ... to PID1, logind, ...
+
+* service_coldplug() appears to reinstall the wrong stop timeout watch?
+
+* transient units: allow creating auxiliary units with the same call
+
+* how to reset dynamically changed attributes sanely?
+
+* when reloading configuration, apply new cgroup configuration
+
+* journald: make sure ratelimit is actually really per-service with the new cgroup changes
+
+* gparted needs to disable auto-activation of mount units somehow, or
+ maybe we should stop doing auto-activation of this after boot
+ entirely. https://bugzilla.gnome.org/show_bug.cgi?id=701676
+ Maybe take a BSD lock at the disk device node and teach udev to
+ check for that and suppress event handling.
+
+* when recursively showing the cgroup hierarchy, optionally also show
+ the hierarchies of child processes
+
+* document logic of auto/noauto and fail/nofail in fstab in systemd.mount or systemd-fstab-generator man page
+
+* we should properly escape ssh hostnames we add into dbus server strings
+
+* something pulls in pcre as so dep into our daemons such as hostnamed.
+
+* document systemd-journal-flush.service properly
+
+* 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 don't keep /var busy. This needs to happen synchronously,
+ hence doing this via signals is not going to work.
+
+* allow implementation of InaccessibleDirectories=/ plus
+ ReadOnlyDirectories=... for whitelisting files for a service.
+
+* libsystemd-bus:
+ - default policy (allow uid == 0 and our own uid)
+ - enforce alignment of pointers passed in
+ - when kdbus doesn't take our message without memfds, try again with memfds
+ - implement translator service
+ - port systemd to new library
+ - implement busname unit type in systemd
+ - move to gvariant
+ - merge busctl into systemctl or so?
+ - synthesize sd_bus_message objects from kernel messages
+ - properly implement name registry ioctls for kdbus
+ - get rid of object hash table, use decision tree everyhwere instead?
+ - implement monitor logic
+ - object vtable logic
+ - longer term:
+ * priority queues
+ * priority inheritance
+
+* in the final killing spree, detect processes from the root directory, and
+ complain loudly if they have argv[0][0] == '@' set.
+ https://bugzilla.redhat.com/show_bug.cgi?id=961044
+
+* add an option to nspawn that uses seccomp to make socket(AF_NETLINK,
+ SOCK_RAW, NETLINK_AUDIT) fail the the appropriate error code that
+ makes the audit userspace to think auditing is not available in the
+ kernel.
+
* Introduce a way how we can kill the main process of a service with KillSignal, but all processes with SIGKILL later on
https://bugzilla.redhat.com/show_bug.cgi?id=952634
-* maybe add a warning to the unit file parses whern the acces mode of unit files is non-sensical.
-
-* investigate endianess issues of UUID vs. GUID
+* maybe add a warning to the unit file parses where the access mode of unit files is nonsensical.
-* see if we can fix https://bugs.freedesktop.org/show_bug.cgi?id=63672
- without dropping the location cache entirely.
+* investigate endianness issues of UUID vs. GUID
* dbus: when a unit failed to load (i.e. is in UNIT_ERROR state), we
should be able to safely try another attempt when the bus call LoadUnit() is invoked.
@@ -57,10 +223,6 @@ Features:
* logind: add Suspend() bus calls which take timestamps to fix double suspend issues when somebody hits suspend and closes laptop quickly.
-* we need dynamic units
-
-* add s.th. like "systemctl set-log-level debug"
-
* cgtop: make cgtop useful in a container
* test/:
@@ -68,41 +230,24 @@ Features:
- make stuff in test/ work with separate output dir
- remove all the duplicated code in test/
-* suppress log output on shutdown when "quiet" is used
-
* systemctl delete x.snapshot leaves no trace in logs (at least at default level).
* make the coredump collector tool move itself into the user's cgroup
so that the coredump is properly written to the user's own journal
file.
-* move /usr/lib/modules/$(uname -r)/modules.devname parsing from udevd to
- kmod static-nodes
- call kmod as an early service, and drop CAP_MKNOD from udevd.service
-
-* systemd-delta needs to be made aware of *.d/*.conf drop-in files for
- units.
-
* seems that when we follow symlinks to units we prefer the symlink
destination path over /etc and /usr. We shouldn't do that. Instead
/etc should always override /run+/usr and also any symlink
destination.
-* remove duplicate default deps logic from fstab-generator vs. mount.c
-
* when isolating, try to figure out a way how we implicitly can order
all units we stop before the isolating unit...
-* teach udev + logind's uaccess to somehow handle the "dead" device nodes from:
- /lib/modules/$(uname -r)/modules.devname
- and apply ACLs to them if they have TAG=="uaccess" in udev rules.
-
* add ConditionArchitecture= or so
* teach ConditionKernelCommandLine= globs or regexes (in order to match foobar={no,0,off})
-* we should log capabilities too
-
* Support SO_REUSEPORT with socket activation:
- Let systemd maintain a pool of servers.
- Use for seamless upgrades, by running the new server before stopping the
@@ -123,7 +268,7 @@ Features:
and we might want to requeue the mounts local-fs acquired through
that automatically.
-* rework specifier logic so that we can distuingish OOM errors from other errors
+* rework specifier logic so that we can distinguish OOM errors from other errors
* systemd-inhibit: make taking delay locks useful: support sending SIGINT or SIGTERM on PrepareForSleep()
@@ -133,13 +278,13 @@ Features:
* documentation: recommend to connect the timer units of a service to the service via Also= in [Install]
-* add a tool that lists active timer units plus their next elapstion and the time the units ran last
+* add a tool that lists active timer units plus their next elapse and the time the units ran last
* man: document the very specific env the shutdown drop-in tools live in
* shutdown logging: store to EFI var, and store to USB stick?
-* man: extend runlevel(8) to mention that runlevels suck, and are dead. Maybe add runlevel(7) with a note about that too
+* man: extend runlevel(8) to mention that runlevels suck, and are dead. Maybe add runlevel(7) with a note about that too
* systemctl: maybe add "systemctl add-wants" or so...
@@ -160,9 +305,6 @@ Features:
* timedate: have global on/off switches for auto-time (NTP), and auto-timezone that connman can subscribe to.
-* Honour "-" prefix for InaccessibleDirectories= and ReadOnlyDirectories= to
- suppress errors of the specified path doesn't exist
-
* dev-setup.c: when running in a container, create a tiny stub udev
database with the systemd tag set for all network interfaces found,
so that libudev reports them as present, and systemd's .device units
@@ -177,7 +319,7 @@ Features:
- write man page for efi boot generator
- honor language efi variables for default language selection (if there are any?)
- honor timezone efi variables for default timezone selection (if there are any?)
- - introduce bootctl (backed by systemd-bootd) to control temporary and persistent default boot goal plus efi variables
+ - change bootctl to be backed by systemd-bootd to control temporary and persistent default boot goal plus efi variables
* maybe do not install getty@tty1.service symlink in /etc but in /usr?
@@ -196,7 +338,6 @@ Features:
- logind: wakelock/opportunistic suspend support
- Add pretty name for seats in logind
- logind: allow showing logout dialog from system?
- - logind: spawn user@..service on login
- logind: non-local X11 server handling
- logind: add equivalent to sd_pid_get_owner_uid() to the D-Bus API
- pam: when leaving a session explicitly exclude the ReleaseSession() caller process from the killing spree
@@ -205,8 +346,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.
-* DeviceAllow/DeviceDeny: disallow everything by default, but whitelist /dev/zero, /dev/null and friends
-
* service: watchdog logic: for testing purposes allow ping, but do not require pong
* journal:
@@ -235,14 +374,13 @@ Features:
- journal-send.c, log.c: when the log socket is clogged, and we drop, count this and write a message about this when it gets unclogged again.
- journal: find a way to allow dropping history early, based on priority, other rules
- journal: When used on NFS, check payload hashes
- - Introduce journalctl -b <nr> to show journal messages of a previous boot
- journald: check whether it is OK if the client can still modify delivered journal entries
- journal live copy, based on libneon (client) and libmicrohttpd (server)
- journald: add kernel cmdline option to disable ratelimiting for debug purposes
- refuse taking lower-case variable names in sd_journal_send() and friends.
- journald: we currently rotate only after MaxUse+MaxFilesize has been reached.
- journal: deal nicely with byte-by-byte copied files, especially regards header
- - journalctl: show multiline log messages sanely, expand tabs, and show all valid utf8 messages
+ - journalctl: expand tabs
- journal: store euid in journal if it differs from uid
- journal: sanely deal with entries which are larger than the individual file size, but where the components would fit
- Replace utmp, wtmp, btmp, and lastlog completely with journal
@@ -295,10 +433,6 @@ Features:
mode, it will never touch the RTC if the no reliable time source is active or the
user did not request anything like it.
-* hwdb:
- - implement conditional properties (dmi matches)
- - hwdb --filter=ID_DRIVE_*
-
* if booted in "quiet" mode, and an error happens, turn on status
output again, so that the emergency mode isn't totally
surprising. Also, terminate plymouth.
@@ -386,8 +520,6 @@ Features:
* Query Paul Moore about relabelling socket fds while they are open
-* system.conf should have controls for cgroups
-
* allow writing multiple conditions in unit files on one line
* explore multiple service instances per listening socket idea
@@ -405,8 +537,6 @@ Features:
when done. That means clients don't get a successful method reply,
but much rather a disconnect on success.
-* remember which condition failed for services, not just the fact that something failed
-
* use opterr = 0 for all getopt tools
* properly handle loop back mounts via fstab, especially regards to fsck/passno
@@ -454,12 +584,9 @@ Features:
* ExecOnFailure=/usr/bin/foo
-* ConditionSecurity= should learn about IMA and SMACK
-
* udev:
- remove src/udev/udev-builtin-firmware.c (CONFIG_FW_LOADER_USER_HELPER=n)
- move to LGPL
- - unify utf8 validator code with shared/
- kill scsi_id
- add trigger --subsystem-match=usb/usb_device device
@@ -483,10 +610,6 @@ Features:
* support crash reporting operation modes (https://live.gnome.org/GnomeOS/Design/Whiteboards/ProblemReporting)
-* clean up session cgroups that remain after logout (think sshd), but eventually run empty
-
-* when an instanced service exits, remove its parent cgroup too if possible.
-
* default to actual 32bit PIDs, via /proc/sys/kernel/pid_max
* be able to specify a forced restart of service A where service B depends on, in case B
@@ -520,6 +643,8 @@ Features:
when we start a service in order to avoid confusion when a user
assumes starting a service is enough to make it accessible
+* support User= and Group= attributes for AF_UNIX sockets.
+
* Make it possible to set the keymap independently from the font on
the kernel cmdline. Right now setting one resets also the other.
@@ -597,6 +722,8 @@ Features:
- document initcall_debug
- kernel cmdline "bootchart" option for simplicity?
+* systemd-run is missing zsh completion scripts
+
External:
* dbus:
diff --git a/autogen.sh b/autogen.sh
index 86fe9b3785..eeb0c1b5e3 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -25,7 +25,7 @@ if [ -f .git/hooks/pre-commit.sample ] && [ ! -f .git/hooks/pre-commit ]; then
fi
if which gtkdocize >/dev/null 2>/dev/null; then
- gtkdocize --docdir docs/
+ gtkdocize --docdir docs/ --flavour no-tmpl
gtkdocargs=--enable-gtk-doc
else
echo "You don't have gtk-doc installed, and thus won't be able to generate the documentation."
diff --git a/catalog/systemd.catalog b/catalog/systemd.catalog
index 62635c87b0..892b2adf78 100644
--- a/catalog/systemd.catalog
+++ b/catalog/systemd.catalog
@@ -138,7 +138,7 @@ Subject: Time zone change to @TIMEZONE@
Defined-By: systemd
Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
-The system time zone has been changed to @TIMEZONE@.
+The system timezone has been changed to @TIMEZONE@.
-- b07a249cd024414a82dd00cd181378ff
Subject: System start-up is now complete
@@ -269,3 +269,21 @@ This does not interfere with mounting, but the pre-exisiting files in
this directory become inaccessible. To see those over-mounted files,
please manually mount the underlying file system to a secondary
location.
+
+-- 24d8d4452573402496068381a6312df2
+Subject: A virtual machine or container has been started
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+Documentation: http://www.freedesktop.org/wiki/Software/systemd/catalog/@MESSAGE_ID@
+
+The virtual machine @NAME@ with its leader PID @LEADER@ has been
+started is now ready to use.
+
+-- 58432bd3bace477cb514b56381b8a758
+Subject: A virtual machine or container has been terminated
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+Documentation: http://www.freedesktop.org/wiki/Software/systemd/catalog/@MESSAGE_ID@
+
+The virtual machine @NAME@ with its leader PID @LEADER@ has been
+shut down.
diff --git a/configure.ac b/configure.ac
index 0e5d90c066..a3d55f59cb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -20,7 +20,7 @@
AC_PREREQ([2.64])
AC_INIT([systemd],
- [204],
+ [208],
[http://bugs.freedesktop.org/enter_bug.cgi?product=systemd],
[systemd],
[http://www.freedesktop.org/wiki/Software/systemd])
@@ -44,6 +44,9 @@ AS_IF([test "x$host_cpu" = "xmips" || test "x$host_cpu" = "xmipsel" ||
LT_PREREQ(2.2)
LT_INIT([disable-static])
+AS_IF([test "x$enable_static" = "xyes"], [AC_MSG_ERROR([--enable-static is not supported by systemd])])
+AS_IF([test "x$enable_largefile" = "xno"], [AC_MSG_ERROR([--disable-largefile is not supported by systemd])])
+
# i18n stuff for the PolicyKit policy files
IT_PROG_INTLTOOL([0.40.0])
@@ -71,10 +74,15 @@ AC_PATH_PROG([SETCAP], [setcap], [/usr/sbin/setcap])
AC_PATH_PROG([KILL], [kill], [/usr/bin/kill])
+AC_PATH_PROG([KMOD], [kmod], [/usr/bin/kmod])
+
+AC_PATH_PROG([KEXEC], [kexec], [/usr/sbin/kexec])
+
# gtkdocize greps for '^GTK_DOC_CHECK', so it needs to be on its own line
m4_ifdef([GTK_DOC_CHECK], [
-GTK_DOC_CHECK([1.18],[--flavour no-tmpl])
-], [AM_CONDITIONAL([ENABLE_GTK_DOC], [false])])
+GTK_DOC_CHECK([1.18],[--flavour no-tmpl])],
+ [AM_CONDITIONAL([ENABLE_GTK_DOC], [false])
+ enable_gtk_doc=no])
AS_IF([test "x$enable_gtk_doc" = "xyes" -a "x$XSLTPROC" = x], [
AC_MSG_ERROR([*** GTK doc requested but xsltproc not found])
@@ -93,6 +101,20 @@ if test -z "$GPERF" ; then
AC_MSG_ERROR([*** gperf not found])
fi
+# ------------------------------------------------------------------------------
+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"
+ ])
+
CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\
-pipe \
-Wall \
@@ -127,20 +149,20 @@ CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\
-ffast-math \
-fno-common \
-fdiagnostics-show-option \
+ -fdiagnostics-color \
-fno-strict-aliasing \
-fvisibility=hidden \
-ffunction-sections \
-fdata-sections \
-fstack-protector \
--param=ssp-buffer-size=4])
-AC_SUBST([OUR_CFLAGS], $with_cflags)
+AC_SUBST([OUR_CFLAGS], "$with_cflags $address_sanitizer_cflags")
-AS_CASE([$CFLAGS], [*-O[[12345g\ ]]*], [
- CC_CHECK_FLAGS_APPEND([with_cppflags], [CPPFLAGS], [\
- -Wp,-D_FORTIFY_SOURCE=2])], [
- python_extra_cflags=-Wp,-U_FORTIFY_SOURCE
- AC_MSG_RESULT([skipping -D_FORTIFY_SOURCE, optimization not enabled])])
-AC_SUBST([OUR_CPPFLAGS], $with_cppflags)
+AS_CASE([$CFLAGS], [*-O[[12345g\ ]]*],
+ [CC_CHECK_FLAGS_APPEND([with_cppflags], [CPPFLAGS], [\
+ -Wp,-D_FORTIFY_SOURCE=2])],
+ [AC_MSG_RESULT([skipping -D_FORTIFY_SOURCE, optimization not enabled])])
+AC_SUBST([OUR_CPPFLAGS], "$with_cppflags $address_sanitizer_cppflags")
CC_CHECK_FLAGS_APPEND([with_ldflags], [LDFLAGS], [\
-Wl,--as-needed \
@@ -148,13 +170,11 @@ CC_CHECK_FLAGS_APPEND([with_ldflags], [LDFLAGS], [\
-Wl,--gc-sections \
-Wl,-z,relro \
-Wl,-z,now])
-AC_SUBST([OUR_LDFLAGS], $with_ldflags)
+AC_SUBST([OUR_LDFLAGS], "$with_ldflags $address_sanitizer_ldflags")
# ------------------------------------------------------------------------------
# we use python to build the man page index, and for systemd-python
have_python=no
-have_python_devel=no
-
AC_ARG_WITH([python],
[AS_HELP_STRING([--without-python], [Disable building the man page index and systemd-python (default: test)])])
@@ -169,32 +189,44 @@ AS_IF([test "x$PYTHON_BINARY" = "x"],
[PYTHON_BINARY=/usr/bin/python])])
AC_ARG_VAR(PYTHON_BINARY, [Python binary used to launch installed scripts])
-AS_IF([test "x$with_python" != "xno"], [
- AC_PATH_PROG(PYTHON_CONFIG, python${PYTHON_VERSION}-config)
- AS_IF([test -n "$PYTHON_CONFIG"], [
- have_python_devel=yes
- PYTHON_CFLAGS="$($PYTHON_CONFIG --cflags) $python_extra_cflags"
- PYTHON_LIBS="$($PYTHON_CONFIG --ldflags)"
- AC_SUBST(PYTHON_CFLAGS)
- AC_SUBST(PYTHON_LIBS)
- AC_PATH_PROGS(SPHINX_BUILD, sphinx-build-${PYTHON_VERSION} sphinx-build)
- ])
+AS_IF([test "x$have_python" != "xyes" -a "x$enable_python_devel" = "xyes"],
+ [AC_MSG_ERROR([*** python-devel support requires --with-python])])
+
+have_python_devel=no
+AC_ARG_ENABLE(python_devel, AS_HELP_STRING([--disable-python-devel], [Do not build python modules]))
+AS_IF([test "x$have_python" = "xyes" -a "x$enable_python_devel" != "xno"], [
+ PKG_CHECK_MODULES([PYTHON_DEVEL], [python-${PYTHON_VERSION}],
+ [have_python_devel=yes],
+ [PKG_CHECK_MODULES([PYTHON_DEVEL], [python],
+ [have_python_devel=yes],
+ [have_python_devel=no])])
+ AS_IF([test "x$have_python_devel" = xno -a "x$enable_python_devel" = xyes],
+ [AC_MSG_ERROR([*** python-devel support requested but libraries not found])])
+ AC_PATH_PROGS(SPHINX_BUILD, sphinx-build-${PYTHON_VERSION} sphinx-build)
])
AM_CONDITIONAL([HAVE_PYTHON_DEVEL], [test "$have_python_devel" = "yes"])
# ------------------------------------------------------------------------------
-AC_SEARCH_LIBS([mq_open], [rt], [], [AC_MSG_ERROR([*** POSIX RT library not found])])
AC_SEARCH_LIBS([dlsym], [dl], [], [AC_MSG_ERROR([*** Dynamic linking loader library not found])])
+AC_CHECK_HEADERS([sys/capability.h], [], [AC_MSG_ERROR([*** POSIX caps headers not found])])
+AC_CHECK_HEADERS([linux/btrfs.h], [], [])
+
+# unconditionally pull-in librt with old glibc versions
+AC_SEARCH_LIBS([clock_gettime], [rt], [], [])
save_LIBS="$LIBS"
LIBS=
AC_SEARCH_LIBS([cap_init], [cap], [], [AC_MSG_ERROR([*** POSIX caps library not found])])
-AC_CHECK_HEADERS([sys/capability.h], [], [AC_MSG_ERROR([*** POSIX caps headers not found])])
CAP_LIBS="$LIBS"
-LIBS="$save_LIBS"
AC_SUBST(CAP_LIBS)
+LIBS=
+AC_SEARCH_LIBS([mq_open], [rt], [], [AC_MSG_ERROR([*** POSIX RT library not found])])
+RT_LIBS="$LIBS"
+AC_SUBST(RT_LIBS)
+LIBS="$save_LIBS"
+
AC_CHECK_FUNCS([fanotify_init fanotify_mark])
AC_CHECK_FUNCS([__secure_getenv secure_getenv])
AC_CHECK_DECLS([gettid, pivot_root, name_to_handle_at], [], [], [[#include <sys/types.h>
@@ -207,14 +239,42 @@ m4_pattern_forbid([^_?PKG_[A-Z_]+$],[*** pkg.m4 missing, please install pkg-conf
PKG_CHECK_MODULES(DBUS, [dbus-1 >= 1.3.2])
+
+# ------------------------------------------------------------------------------
+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_kmod=no
AC_ARG_ENABLE(kmod, AS_HELP_STRING([--disable-kmod], [disable loadable modules support]))
if test "x$enable_kmod" != "xno"; then
- PKG_CHECK_MODULES(KMOD, [ libkmod >= 5 ],
- [AC_DEFINE(HAVE_KMOD, 1, [Define if kmod is available]) have_kmod=yes], have_kmod=no)
+ PKG_CHECK_EXISTS([ libkmod ], have_kmod=yes, have_kmod=no)
+ if test "x$have_kmod" = "xyes"; then
+ PKG_CHECK_MODULES(KMOD, [ libkmod >= 14 ],
+ [AC_DEFINE(HAVE_KMOD, 1, [Define if kmod is available])],
+ AC_MSG_ERROR([*** kmod version >= 14 not found]))
+ fi
if test "x$have_kmod" = xno -a "x$enable_kmod" = xyes; then
- AC_MSG_ERROR([*** kmod support requested but libraries not found])
+ AC_MSG_ERROR([*** kmod support requested, but libraries not found])
fi
fi
AM_CONDITIONAL(HAVE_KMOD, [test "$have_kmod" = "yes"])
@@ -444,6 +504,31 @@ AC_SUBST(XATTR_LIBS)
AM_CONDITIONAL([HAVE_XATTR], [test "x$have_xattr" != 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_xattr}" = xno; then
+ if test "x${have_smack}" = xyes; then
+ AC_MSG_ERROR(SMACK requires xattr support)
+ else
+ have_smack=no
+ fi
+else
+ if test "x${have_smack}" = xauto; then
+ have_smack=yes
+ fi
+fi
+
+if test "x${have_smack}" = xyes ; then
+ AC_DEFINE(HAVE_SMACK, 1, [Define if SMACK is available])
+fi
+
+# ------------------------------------------------------------------------------
AC_ARG_ENABLE([gcrypt],
AS_HELP_STRING([--disable-gcrypt],[Disable optional GCRYPT support]),
[case "${enableval}" in
@@ -517,7 +602,7 @@ AC_SUBST(AUDIT_LIBS)
have_libcryptsetup=no
AC_ARG_ENABLE(libcryptsetup, AS_HELP_STRING([--disable-libcryptsetup], [disable libcryptsetup tools]))
if test "x$enable_libcryptsetup" != "xno"; then
- PKG_CHECK_MODULES(LIBCRYPTSETUP, [ libcryptsetup >= 1.4.2 ],
+ PKG_CHECK_MODULES(LIBCRYPTSETUP, [ libcryptsetup >= 1.6.0 ],
[AC_DEFINE(HAVE_LIBCRYPTSETUP, 1, [Define if libcryptsetup is available]) have_libcryptsetup=yes], have_libcryptsetup=no)
if test "x$have_libcryptsetup" = xno -a "x$enable_libcryptsetup" = xyes; then
AC_MSG_ERROR([*** libcryptsetup support requested but libraries not found])
@@ -590,6 +675,14 @@ fi
AM_CONDITIONAL(ENABLE_QUOTACHECK, [test "$have_quotacheck" = "yes"])
# ------------------------------------------------------------------------------
+have_tmpfiles=no
+AC_ARG_ENABLE(tmpfiles, AS_HELP_STRING([--disable-tmpfiles], [disable tmpfiles support]))
+if test "x$enable_tmpfiles" != "xno"; then
+ have_tmpfiles=yes
+fi
+AM_CONDITIONAL(ENABLE_TMPFILES, [test "$have_tmpfiles" = "yes"])
+
+# ------------------------------------------------------------------------------
have_randomseed=no
AC_ARG_ENABLE(randomseed, AS_HELP_STRING([--disable-randomseed], [disable randomseed tools]))
if test "x$enable_randomseed" != "xno"; then
@@ -598,6 +691,14 @@ fi
AM_CONDITIONAL(ENABLE_RANDOMSEED, [test "$have_randomseed" = "yes"])
# ------------------------------------------------------------------------------
+have_backlight=no
+AC_ARG_ENABLE(backlight, AS_HELP_STRING([--disable-backlight], [disable backlight tools]))
+if test "x$enable_backlight" != "xno"; then
+ have_backlight=yes
+fi
+AM_CONDITIONAL(ENABLE_BACKLIGHT, [test "$have_backlight" = "yes"])
+
+# ------------------------------------------------------------------------------
have_logind=no
AC_ARG_ENABLE(logind, AS_HELP_STRING([--disable-logind], [disable login daemon]))
if test "x$enable_logind" != "xno"; then
@@ -607,6 +708,15 @@ AM_CONDITIONAL(ENABLE_LOGIND, [test "$have_logind" = "yes"])
AS_IF([test "$have_logind" = "yes"], [ AC_DEFINE(HAVE_LOGIND, [1], [Logind support available]) ])
# ------------------------------------------------------------------------------
+have_machined=no
+AC_ARG_ENABLE(machined, AS_HELP_STRING([--disable-machined], [disable machine daemon]))
+if test "x$enable_machined" != "xno"; then
+ have_machined=yes
+fi
+AM_CONDITIONAL(ENABLE_MACHINED, [test "$have_machined" = "yes"])
+AS_IF([test "$have_machined" = "yes"], [ AC_DEFINE(HAVE_MACHINED, [1], [Machined support available]) ])
+
+# ------------------------------------------------------------------------------
have_hostnamed=no
AC_ARG_ENABLE(hostnamed, AS_HELP_STRING([--disable-hostnamed], [disable hostname daemon]))
if test "x$enable_hostnamed" != "xno"; then
@@ -698,7 +808,7 @@ AC_ARG_WITH(telinit,
AS_HELP_STRING([--with-telinit=PATH],
[Path to telinit]),
[TELINIT="$withval"],
- [TELINIT="/lib/upstart/telinit"])
+ [TELINIT="/lib/sysvinit/telinit"])
AC_DEFINE_UNQUOTED(TELINIT, ["$TELINIT"], [Path to telinit])
@@ -711,7 +821,7 @@ have_myhostname=no
AC_ARG_ENABLE(myhostname, AS_HELP_STRING([--disable-myhostname], [disable nss-myhostname support]))
if test "x$enable_myhostname" != "xno"; then
AC_HEADER_STDC
- AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/time.h unistd.h nss.h sys/ioctl.h])
+ AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/time.h unistd.h nss.h sys/ioctl.h sys/auxv.h])
AC_C_CONST
AC_TYPE_SIZE_T
@@ -753,21 +863,6 @@ AM_CONDITIONAL([ENABLE_GUDEV], [test "x$enable_gudev" = "xyes"])
AS_IF([test "x$enable_gudev" = "xyes"], [ AC_DEFINE(HAVE_GLIB, 1, [Define if glib is available]) ])
# ------------------------------------------------------------------------------
-AC_ARG_ENABLE([keymap],
- AS_HELP_STRING([--disable-keymap], [disable keymap fixup support @<:@default=enabled@:>@]),
- [], [enable_keymap=yes])
-AS_IF([test "x$enable_keymap" = "xyes"], [
- AC_PATH_PROG([GPERF], [gperf])
- if test -z "$GPERF"; then
- AC_MSG_ERROR([gperf is needed])
- fi
-
- AC_CHECK_HEADER([linux/input.h], [:], AC_MSG_ERROR([kernel headers not found]))
- AC_SUBST([INCLUDE_PREFIX], [$(echo '#include <linux/input.h>' | eval $ac_cpp -E - | sed -n '/linux\/input.h/ {s:.*"\(.*\)/linux/input.h".*:\1:; p; q}')])
-])
-AM_CONDITIONAL([ENABLE_KEYMAP], [test "x$enable_keymap" = "xyes"])
-
-# ------------------------------------------------------------------------------
have_manpages=no
AC_ARG_ENABLE(manpages, AS_HELP_STRING([--disable-manpages], [disable manpages]))
AS_IF([test "x$enable_manpages" != xno], [
@@ -848,6 +943,10 @@ AC_ARG_WITH([bashcompletiondir],
with_bashcompletiondir=${datadir}/bash-completion/completions
])])
+AC_ARG_WITH([zshcompletiondir],
+ AS_HELP_STRING([--with-zshcompletiondir=DIR], [Zsh completions directory]),
+ [], [with_zshcompletiondir=${datadir}/zsh/site-functions])
+
AC_ARG_WITH([rootprefix],
AS_HELP_STRING([--with-rootprefix=DIR], [rootfs directory prefix for config files and kernel modules]),
[], [with_rootprefix=${ac_default_prefix}])
@@ -862,6 +961,11 @@ AC_ARG_WITH([pamlibdir],
[],
[with_pamlibdir=${with_rootlibdir}/security])
+AC_ARG_WITH([pamconfdir],
+ AS_HELP_STRING([--with-pamconfdir=DIR], [Directory for PAM configuration]),
+ [],
+ [with_pamconfdir=${sysconfdir}/pam.d])
+
AC_ARG_ENABLE([split-usr],
AS_HELP_STRING([--enable-split-usr], [Assume that /bin, /sbin aren\'t symlinks into /usr]),
[],
@@ -892,7 +996,9 @@ AC_SUBST([dbussessionservicedir], [$with_dbussessionservicedir])
AC_SUBST([dbussystemservicedir], [$with_dbussystemservicedir])
AC_SUBST([dbusinterfacedir], [$with_dbusinterfacedir])
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])
@@ -914,6 +1020,7 @@ AC_MSG_RESULT([
AUDIT: ${have_audit}
IMA: ${have_ima}
SELinux: ${have_selinux}
+ SMACK: ${have_smack}
XZ: ${have_xz}
ACL: ${have_acl}
XATTR: ${have_xattr}
@@ -926,8 +1033,11 @@ AC_MSG_RESULT([
readahead: ${have_readahead}
bootchart: ${have_bootchart}
quotacheck: ${have_quotacheck}
+ tmpfiles: ${have_tmpfiles}
randomseed: ${have_randomseed}
+ backlight: ${have_backlight}
logind: ${have_logind}
+ machined: ${have_machined}
hostnamed: ${have_hostnamed}
timedated: ${have_timedated}
localed: ${have_localed}
@@ -939,11 +1049,11 @@ AC_MSG_RESULT([
nss-myhostname: ${have_myhostname}
gudev: ${enable_gudev}
gintrospection: ${enable_introspection}
- keymap: ${enable_keymap}
Python: ${have_python}
Python Headers: ${have_python_devel}
man pages: ${have_manpages}
gtk-doc: ${enable_gtk_doc}
+ test coverage: ${have_coverage}
Split /usr: ${enable_split_usr}
SysV compatibility: ${SYSTEM_SYSV_COMPAT}
@@ -959,13 +1069,16 @@ AC_MSG_RESULT([
SysV rc?.d directories: ${SYSTEM_SYSVRCND_PATH}
Build Python: ${PYTHON}
Installation Python: ${PYTHON_BINARY}
+ sphinx binary: ${SPHINX_BUILD}
firmware path: ${FIRMWARE_PATH}
PAM modules dir: ${with_pamlibdir}
+ PAM configuration dir: ${with_pamconfdir}
D-Bus policy dir: ${with_dbuspolicydir}
D-Bus session dir: ${with_dbussessionservicedir}
D-Bus system dir: ${with_dbussystemservicedir}
D-Bus interfaces dir: ${with_dbusinterfacedir}
Bash completions dir: ${with_bashcompletiondir}
+ Zsh completions dir: ${with_zshcompletiondir}
Extra start script: ${RC_LOCAL_SCRIPT_PATH_START}
Extra stop script: ${RC_LOCAL_SCRIPT_PATH_STOP}
Debug shell: ${SUSHELL} @ ${DEBUGTTY}
@@ -973,6 +1086,6 @@ AC_MSG_RESULT([
CFLAGS: ${OUR_CFLAGS} ${CFLAGS}
CPPFLAGS: ${OUR_CPPFLAGS} ${CPPFLAGS}
LDFLAGS: ${OUR_LDFLAGS} ${LDFLAGS}
- PYTHON_CFLAGS: ${PYTHON_CFLAGS}
- PYTHON_LIBS: ${PYTHON_LIBS}
+ PYTHON_CFLAGS: ${PYTHON_DEVEL_CFLAGS}
+ PYTHON_LIBS: ${PYTHON_DEVEL_LIBS}
])
diff --git a/hwdb/20-OUI.hwdb b/hwdb/20-OUI.hwdb
index 72795c6a6d..e913b28203 100644
--- a/hwdb/20-OUI.hwdb
+++ b/hwdb/20-OUI.hwdb
@@ -602,7 +602,7 @@ OUI:0050C20CF*
ID_OUI_FROM_DATABASE=PCSC
OUI:0050C20D0*
- ID_OUI_FROM_DATABASE=Telegrang AB
+ ID_OUI_FROM_DATABASE=Telefrang AB
OUI:0050C20D1*
ID_OUI_FROM_DATABASE=Renaissance Networking, Inc.
@@ -2468,7 +2468,7 @@ OUI:0050C2340*
ID_OUI_FROM_DATABASE=Virtu
OUI:0050C2341*
- ID_OUI_FROM_DATABASE=Novx Systems Canada Inc.
+ ID_OUI_FROM_DATABASE=Novx Systems
OUI:0050C2342*
ID_OUI_FROM_DATABASE=St. Michael Strategies
@@ -2519,7 +2519,7 @@ OUI:0050C2351*
ID_OUI_FROM_DATABASE=Finesystem Co., Ltd
OUI:0050C2352*
- ID_OUI_FROM_DATABASE=edixia
+ ID_OUI_FROM_DATABASE=LUCEO
OUI:0050C2353*
ID_OUI_FROM_DATABASE=Crossing Informationssysteme GmbH
@@ -3665,7 +3665,7 @@ OUI:0050C24CF*
ID_OUI_FROM_DATABASE=Ziehl-Abegg AG
OUI:0050C24D0*
- ID_OUI_FROM_DATABASE=Radford Control Systems
+ ID_OUI_FROM_DATABASE=RCS Energy Management Ltd
OUI:0050C24D1*
ID_OUI_FROM_DATABASE=SLICAN sp. z o.o.
@@ -4070,7 +4070,7 @@ OUI:0050C2556*
ID_OUI_FROM_DATABASE=Freiburger BlickZentrum
OUI:0050C2557*
- ID_OUI_FROM_DATABASE=TOYO RADIO SYSTEMS CO., LTD.
+ ID_OUI_FROM_DATABASE=Netcomsec Co Ltd
OUI:0050C2558*
ID_OUI_FROM_DATABASE=Bedo Elektronik GmbH
@@ -7295,7 +7295,7 @@ OUI:0050C298C*
ID_OUI_FROM_DATABASE=MGM-Devices Oy
OUI:0050C298D*
- ID_OUI_FROM_DATABASE=Mecos Traxler AG
+ ID_OUI_FROM_DATABASE=Mecos AG
OUI:0050C298E*
ID_OUI_FROM_DATABASE=Link Technologies, Inc
@@ -10565,7 +10565,7 @@ OUI:0050C2DDA*
ID_OUI_FROM_DATABASE=rbz robot design s.l.
OUI:0050C2DDB*
- ID_OUI_FROM_DATABASE=EDIXIA
+ ID_OUI_FROM_DATABASE=LUCEO
OUI:0050C2DDC*
ID_OUI_FROM_DATABASE=Vision & Control GmbH
@@ -12916,6 +12916,414 @@ OUI:40D8550EF*
OUI:40D8550F0*
ID_OUI_FROM_DATABASE=Redwood Systems
+OUI:40D8550F1*
+ ID_OUI_FROM_DATABASE=Grossenbacher Systeme AG
+
+OUI:40D8550F2*
+ ID_OUI_FROM_DATABASE=SigmaPhi Electronics
+
+OUI:40D8550F3*
+ ID_OUI_FROM_DATABASE=ECON Systems Inc.
+
+OUI:40D8550F4*
+ ID_OUI_FROM_DATABASE=MB Connect Line GmbH
+
+OUI:40D8550F5*
+ ID_OUI_FROM_DATABASE=CST Group
+
+OUI:40D8550F7*
+ ID_OUI_FROM_DATABASE=Comline Elektronik Elektrotechnik GmbH
+
+OUI:40D8550F8*
+ ID_OUI_FROM_DATABASE=Better Place
+
+OUI:40D8550F9*
+ ID_OUI_FROM_DATABASE=Invisua Lighting BV
+
+OUI:40D8550FA*
+ ID_OUI_FROM_DATABASE=Marmitek BV
+
+OUI:40D8550FB*
+ ID_OUI_FROM_DATABASE=InfoMac Sp. z o. o. Sp. k.
+
+OUI:40D8550FC*
+ ID_OUI_FROM_DATABASE=eumig industrie-tv GmbH
+
+OUI:40D8550FD*
+ ID_OUI_FROM_DATABASE=MONOGRAM technologies ltd
+
+OUI:40D8550FE*
+ ID_OUI_FROM_DATABASE=Cytech Technology Pte Ltd
+
+OUI:40D8550FF*
+ ID_OUI_FROM_DATABASE=YUYAMA MFG.CO.,LTD.
+
+OUI:40D855100*
+ ID_OUI_FROM_DATABASE=TASK SISTEMAS DE COMPUTACAO S.A.
+
+OUI:40D855101*
+ ID_OUI_FROM_DATABASE=e.p.g. Elettronica Srl
+
+OUI:40D855102*
+ ID_OUI_FROM_DATABASE=Power Electronics
+
+OUI:40D855103*
+ ID_OUI_FROM_DATABASE=Peek Traffic Corporation
+
+OUI:40D855104*
+ ID_OUI_FROM_DATABASE=IMPLE SISTEMAS ELETRONICOS EMBARCADOS LTDA
+
+OUI:40D855105*
+ ID_OUI_FROM_DATABASE=Tieline Research Pty Ltd
+
+OUI:40D855106*
+ ID_OUI_FROM_DATABASE=Orbital A/S
+
+OUI:40D855107*
+ ID_OUI_FROM_DATABASE=Smith Meter, Inc
+
+OUI:40D855108*
+ ID_OUI_FROM_DATABASE=ALPHA DESIGN CO.,LTD.
+
+OUI:40D855109*
+ ID_OUI_FROM_DATABASE=Rosslare Enterprises Limited
+
+OUI:40D85510A*
+ ID_OUI_FROM_DATABASE=DAVIS DERBY LIMITED
+
+OUI:40D85510B*
+ ID_OUI_FROM_DATABASE=So-Cool Corporation.
+
+OUI:40D85510C*
+ ID_OUI_FROM_DATABASE=Contrans TI sp. z o.o.
+
+OUI:40D85510D*
+ ID_OUI_FROM_DATABASE=Rite-Tech Industrial CO., Ltd.
+
+OUI:40D85510E*
+ ID_OUI_FROM_DATABASE=HKS-Prozesstechnik GmbH
+
+OUI:40D85510F*
+ ID_OUI_FROM_DATABASE=CAVALRY STORAGE INC
+
+OUI:40D855110*
+ ID_OUI_FROM_DATABASE=Aplex Technology Inc.
+
+OUI:40D855111*
+ ID_OUI_FROM_DATABASE=Grupo Epelsa S.L.
+
+OUI:40D855112*
+ ID_OUI_FROM_DATABASE=Halliburton - Sperry Drilling Service
+
+OUI:40D855113*
+ ID_OUI_FROM_DATABASE=Testbook Ltd
+
+OUI:40D855114*
+ ID_OUI_FROM_DATABASE=GENERAL DYNAMICS C4 SYSTEMS
+
+OUI:40D855115*
+ ID_OUI_FROM_DATABASE=MESA Electronic GmbH
+
+OUI:40D855116*
+ ID_OUI_FROM_DATABASE=Uniscan LLC
+
+OUI:40D855117*
+ ID_OUI_FROM_DATABASE=RCS Energy Management Limited
+
+OUI:40D855118*
+ ID_OUI_FROM_DATABASE=University of Nebraska -- Lincoln
+
+OUI:40D855119*
+ ID_OUI_FROM_DATABASE=OOO Group of Industrial Technologies
+
+OUI:40D85511A*
+ ID_OUI_FROM_DATABASE=Sicon srl
+
+OUI:40D85511B*
+ ID_OUI_FROM_DATABASE=nanoTRONIC GmbH
+
+OUI:40D85511C*
+ ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH
+
+OUI:40D85511D*
+ ID_OUI_FROM_DATABASE=ACD Elektronik GmBH
+
+OUI:40D85511E*
+ ID_OUI_FROM_DATABASE=CEMSI, Inc.
+
+OUI:40D85511F*
+ ID_OUI_FROM_DATABASE=KOMPAN Pawel Sokolowski
+
+OUI:40D855120*
+ ID_OUI_FROM_DATABASE=ObjectFab GmbH
+
+OUI:40D855121*
+ ID_OUI_FROM_DATABASE=shanghai Anjian Information technology co. , ltd.
+
+OUI:40D855122*
+ ID_OUI_FROM_DATABASE=ATX Networks Ltd.
+
+OUI:40D855123*
+ ID_OUI_FROM_DATABASE=ZAO NPC Kompjuternie Technologii
+
+OUI:40D855124*
+ ID_OUI_FROM_DATABASE=Debug s.r.l.
+
+OUI:40D855125*
+ ID_OUI_FROM_DATABASE=Scandyna A/S
+
+OUI:40D855126*
+ ID_OUI_FROM_DATABASE=TTI LTD
+
+OUI:40D855127*
+ ID_OUI_FROM_DATABASE=LIGHTSTAR
+
+OUI:40D855128*
+ ID_OUI_FROM_DATABASE=Akse srl
+
+OUI:40D855129*
+ ID_OUI_FROM_DATABASE=DSP DESIGN
+
+OUI:40D85512A*
+ ID_OUI_FROM_DATABASE=Jadpod Communication Company Limited
+
+OUI:40D85512B*
+ ID_OUI_FROM_DATABASE=Mango DSP, Inc.
+
+OUI:40D85512C*
+ ID_OUI_FROM_DATABASE=NSP Europe Ltd
+
+OUI:40D85512D*
+ ID_OUI_FROM_DATABASE=Biotage Sweden AB
+
+OUI:40D85512E*
+ ID_OUI_FROM_DATABASE=Canfield Scientific, Inc.
+
+OUI:40D855130*
+ ID_OUI_FROM_DATABASE=GSP Sprachtechnologie GmbH
+
+OUI:40D855131*
+ ID_OUI_FROM_DATABASE=EMAC, INC.
+
+OUI:40D855132*
+ ID_OUI_FROM_DATABASE=AeroVision Avionics, Inc
+
+OUI:40D855133*
+ ID_OUI_FROM_DATABASE=Tattile srl
+
+OUI:40D855134*
+ ID_OUI_FROM_DATABASE=digitech GmbH &amp; Co. KG
+
+OUI:40D855135*
+ ID_OUI_FROM_DATABASE=GLOBALCOM ENGINEERING SRL
+
+OUI:40D855136*
+ ID_OUI_FROM_DATABASE=Devriecom B.V.
+
+OUI:40D855137*
+ ID_OUI_FROM_DATABASE=GDE Polska
+
+OUI:40D855138*
+ ID_OUI_FROM_DATABASE=Calon Associates Limited
+
+OUI:40D855139*
+ ID_OUI_FROM_DATABASE=WOW System
+
+OUI:40D85513A*
+ ID_OUI_FROM_DATABASE=Supplier Ind. e Com de Eletroeletrônicos
+
+OUI:40D85513B*
+ ID_OUI_FROM_DATABASE=Davin Technologies Co.,Ltd
+
+OUI:40D85513C*
+ ID_OUI_FROM_DATABASE=shanghai anjian Information technology co. , ltd.
+
+OUI:40D85513D*
+ ID_OUI_FROM_DATABASE=Perm Scientific-Industrial Instrument Making Company JSC
+
+OUI:40D85513E*
+ ID_OUI_FROM_DATABASE=hanatech
+
+OUI:40D85513F*
+ ID_OUI_FROM_DATABASE=Zhejiang Wellsun Electric Meter Co.,Ltd
+
+OUI:40D855140*
+ ID_OUI_FROM_DATABASE=InnoTrans Communications, Inc
+
+OUI:40D855141*
+ ID_OUI_FROM_DATABASE=Key Systems, Inc.
+
+OUI:40D855142*
+ ID_OUI_FROM_DATABASE=Tetracore, Inc.
+
+OUI:40D855143*
+ ID_OUI_FROM_DATABASE=Tokyo Drawing Ltd.
+
+OUI:40D855144*
+ ID_OUI_FROM_DATABASE=Venco
+
+OUI:40D855145*
+ ID_OUI_FROM_DATABASE=Weber Marking Systems GmbH
+
+OUI:40D855146*
+ ID_OUI_FROM_DATABASE=Pleiger Elektronik GmbH and Co. KG
+
+OUI:40D855147*
+ ID_OUI_FROM_DATABASE=Aplex Technology Inc.
+
+OUI:40D855148*
+ ID_OUI_FROM_DATABASE=SEIKO TIME SYSTEMS INC.
+
+OUI:40D855149*
+ ID_OUI_FROM_DATABASE=Engage Technologies
+
+OUI:40D85514A*
+ ID_OUI_FROM_DATABASE=GENERAL DYNAMICS C4 SYSTEMS
+
+OUI:40D85514C*
+ ID_OUI_FROM_DATABASE=PLT
+
+OUI:40D85514D*
+ ID_OUI_FROM_DATABASE=SOMFY SAS
+
+OUI:40D85514E*
+ ID_OUI_FROM_DATABASE=Marposs S.p.A
+
+OUI:40D85514F*
+ ID_OUI_FROM_DATABASE=TDS Software Solutions Pty Ltd
+
+OUI:40D855150*
+ ID_OUI_FROM_DATABASE=SHIKINO HIGH-TECH
+
+OUI:40D855151*
+ ID_OUI_FROM_DATABASE=Progress Rail Services, Inspection and Information Systems
+
+OUI:40D855152*
+ ID_OUI_FROM_DATABASE=Home Automation Europe
+
+OUI:40D855153*
+ ID_OUI_FROM_DATABASE=BlinkPipe Ltd
+
+OUI:40D855154*
+ ID_OUI_FROM_DATABASE=iart
+
+OUI:40D855155*
+ ID_OUI_FROM_DATABASE=Telefrang AB
+
+OUI:40D855156*
+ ID_OUI_FROM_DATABASE=Emphysys, Inc.
+
+OUI:40D855157*
+ ID_OUI_FROM_DATABASE=Hitachi Power Solutions Co., Ltd.
+
+OUI:40D855158*
+ ID_OUI_FROM_DATABASE=Exibea AB
+
+OUI:40D855159*
+ ID_OUI_FROM_DATABASE=PLATINUM GmbH
+
+OUI:40D85515A*
+ ID_OUI_FROM_DATABASE=DORLET S.A.U
+
+OUI:40D85515B*
+ ID_OUI_FROM_DATABASE=SQF Spezialelektronik GmbH
+
+OUI:40D85515C*
+ ID_OUI_FROM_DATABASE=Spectratech Inc.
+
+OUI:40D85515D*
+ ID_OUI_FROM_DATABASE=Actronic Technologies
+
+OUI:40D85515E*
+ ID_OUI_FROM_DATABASE=Prodco International Inc.
+
+OUI:40D85515F*
+ ID_OUI_FROM_DATABASE=CT COMPANY
+
+OUI:40D855160*
+ ID_OUI_FROM_DATABASE=Thermo Fisher Sceintific
+
+OUI:40D855161*
+ ID_OUI_FROM_DATABASE=Solidscape Inc
+
+OUI:40D855162*
+ ID_OUI_FROM_DATABASE=LUNA-NEXUS
+
+OUI:40D855163*
+ ID_OUI_FROM_DATABASE=KMtronic LTD
+
+OUI:40D855164*
+ ID_OUI_FROM_DATABASE=NFT Automatisierungssysteme GmbH
+
+OUI:40D855165*
+ ID_OUI_FROM_DATABASE=TECHBOARD SRL
+
+OUI:40D855166*
+ ID_OUI_FROM_DATABASE=Anhui Jiante Network Technology Co., Ltd.
+
+OUI:40D855167*
+ ID_OUI_FROM_DATABASE=Assembly Contracts Ltd
+
+OUI:40D855168*
+ ID_OUI_FROM_DATABASE=OPASCA Systems GmbH
+
+OUI:40D855169*
+ ID_OUI_FROM_DATABASE=Photop Koncent
+
+OUI:40D85516A*
+ ID_OUI_FROM_DATABASE=Aplex Technology Inc.
+
+OUI:40D85516B*
+ ID_OUI_FROM_DATABASE=TECHWAY
+
+OUI:40D85516D*
+ ID_OUI_FROM_DATABASE=GENERAL DYNAMICS C4 SYSTEMS
+
+OUI:40D85516E*
+ ID_OUI_FROM_DATABASE=Secuinfo Co.Ltd
+
+OUI:40D85516F*
+ ID_OUI_FROM_DATABASE=BrightLeaf Power
+
+OUI:40D855170*
+ ID_OUI_FROM_DATABASE=ICS Eletronics
+
+OUI:40D855171*
+ ID_OUI_FROM_DATABASE=Sicon srl
+
+OUI:40D855172*
+ ID_OUI_FROM_DATABASE=YAWATA ELECTRIC INDUSTRIAL CO.,LTD.
+
+OUI:40D855173*
+ ID_OUI_FROM_DATABASE=Contec Steuerungstechnik & Automation GmbH
+
+OUI:40D855174*
+ ID_OUI_FROM_DATABASE=EcoGuard AB
+
+OUI:40D855175*
+ ID_OUI_FROM_DATABASE=AHB Systeme GmbH
+
+OUI:40D855176*
+ ID_OUI_FROM_DATABASE=Schneider Electric Motion, Inc. USA
+
+OUI:40D855177*
+ ID_OUI_FROM_DATABASE=TRI Engineering co.,ltd.
+
+OUI:40D855178*
+ ID_OUI_FROM_DATABASE=REDER Domotic GmbH
+
+OUI:40D855179*
+ ID_OUI_FROM_DATABASE=Servo-Robot Inc.
+
+OUI:40D85517A*
+ ID_OUI_FROM_DATABASE=ARGUS-SPECTRUM
+
+OUI:40D85517B*
+ ID_OUI_FROM_DATABASE=LUCEO
+
+OUI:40D85517C*
+ ID_OUI_FROM_DATABASE=Critical Link
+
OUI:000000*
ID_OUI_FROM_DATABASE=XEROX CORPORATION
@@ -14492,7 +14900,7 @@ OUI:00020D*
ID_OUI_FROM_DATABASE=Micronpc.com
OUI:00020E*
- ID_OUI_FROM_DATABASE=ECI Telecom, Ltd., NSD-US
+ ID_OUI_FROM_DATABASE=ECI Telecom, Ltd
OUI:00020F*
ID_OUI_FROM_DATABASE=AATR
@@ -15266,7 +15674,7 @@ OUI:00030F*
ID_OUI_FROM_DATABASE=Digital China (Shanghai) Networks Ltd.
OUI:000310*
- ID_OUI_FROM_DATABASE=ITX E-Globaledge Corporation
+ ID_OUI_FROM_DATABASE=E-Globaledge Corporation
OUI:000311*
ID_OUI_FROM_DATABASE=Micro Technology Co., Ltd.
@@ -15659,7 +16067,7 @@ OUI:000392*
ID_OUI_FROM_DATABASE=Hyundai Teletek Co., Ltd.
OUI:000393*
- ID_OUI_FROM_DATABASE=Apple Computer, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:000394*
ID_OUI_FROM_DATABASE=Connect One
@@ -15890,7 +16298,7 @@ OUI:0003DF*
ID_OUI_FROM_DATABASE=Desana Systems
OUI:0003E0*
- ID_OUI_FROM_DATABASE=Motorola, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0003E1*
ID_OUI_FROM_DATABASE=Winmate Communication, Inc.
@@ -16286,7 +16694,7 @@ OUI:000463*
ID_OUI_FROM_DATABASE=Bosch Security Systems
OUI:000464*
- ID_OUI_FROM_DATABASE=Fantasma Networks, Inc.
+ ID_OUI_FROM_DATABASE=Pulse-Link Inc
OUI:000465*
ID_OUI_FROM_DATABASE=i.s.t isdn-support technik GmbH
@@ -16553,7 +16961,7 @@ OUI:0004BC*
ID_OUI_FROM_DATABASE=Giantec, Inc.
OUI:0004BD*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0004BE*
ID_OUI_FROM_DATABASE=OptXCon, Inc.
@@ -16601,7 +17009,7 @@ OUI:0004CC*
ID_OUI_FROM_DATABASE=Peek Traffic B.V.
OUI:0004CD*
- ID_OUI_FROM_DATABASE=Informedia Research Group
+ ID_OUI_FROM_DATABASE=Extenway Solutions Inc
OUI:0004CE*
ID_OUI_FROM_DATABASE=Patria Ailon
@@ -16760,7 +17168,7 @@ OUI:000501*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
OUI:000502*
- ID_OUI_FROM_DATABASE=APPLE COMPUTER
+ ID_OUI_FROM_DATABASE=Apple
OUI:000503*
ID_OUI_FROM_DATABASE=ICONAG
@@ -17663,7 +18071,7 @@ OUI:000630*
ID_OUI_FROM_DATABASE=Adtranz Sweden
OUI:000631*
- ID_OUI_FROM_DATABASE=Optical Solutions, Inc.
+ ID_OUI_FROM_DATABASE=Calix
OUI:000632*
ID_OUI_FROM_DATABASE=Mesco Engineering GmbH
@@ -19094,7 +19502,7 @@ OUI:00080D*
ID_OUI_FROM_DATABASE=Toshiba
OUI:00080E*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:00080F*
ID_OUI_FROM_DATABASE=Proximion Fiber Optics AB
@@ -20621,7 +21029,7 @@ OUI:000A26*
ID_OUI_FROM_DATABASE=CEIA S.p.A.
OUI:000A27*
- ID_OUI_FROM_DATABASE=Apple Computer, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:000A28*
ID_OUI_FROM_DATABASE=Motorola
@@ -20783,7 +21191,7 @@ OUI:000A5C*
ID_OUI_FROM_DATABASE=Carel s.p.a.
OUI:000A5D*
- ID_OUI_FROM_DATABASE=PUC Founder (MSC) Berhad
+ ID_OUI_FROM_DATABASE=FingerTec Worldwide Sdn Bhd
OUI:000A5E*
ID_OUI_FROM_DATABASE=3COM Corporation
@@ -20951,7 +21359,7 @@ OUI:000A94*
ID_OUI_FROM_DATABASE=ShangHai cellink CO., LTD
OUI:000A95*
- ID_OUI_FROM_DATABASE=Apple Computer, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:000A96*
ID_OUI_FROM_DATABASE=MEWTEL TECHNOLOGY INC.
@@ -21290,7 +21698,7 @@ OUI:000B05*
ID_OUI_FROM_DATABASE=Pacific Broadband Networks
OUI:000B06*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:000B07*
ID_OUI_FROM_DATABASE=Voxpath Networks
@@ -22502,7 +22910,7 @@ OUI:000C9C*
ID_OUI_FROM_DATABASE=Chongho information & communications
OUI:000C9D*
- ID_OUI_FROM_DATABASE=AirWalk Communications, Inc.
+ ID_OUI_FROM_DATABASE=UbeeAirWalk, Inc.
OUI:000C9E*
ID_OUI_FROM_DATABASE=MemoryLink Corp.
@@ -22718,7 +23126,7 @@ OUI:000CE4*
ID_OUI_FROM_DATABASE=NeuroCom International, Inc.
OUI:000CE5*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:000CE6*
ID_OUI_FROM_DATABASE=Meru Networks Inc
@@ -22778,7 +23186,7 @@ OUI:000CF8*
ID_OUI_FROM_DATABASE=Nortel Networks
OUI:000CF9*
- ID_OUI_FROM_DATABASE=ITT Flygt AB
+ ID_OUI_FROM_DATABASE=Xylem Water Solutions
OUI:000CFA*
ID_OUI_FROM_DATABASE=Digital Systems Corp
@@ -23237,7 +23645,7 @@ OUI:000D92*
ID_OUI_FROM_DATABASE=Arima Communication Corporation
OUI:000D93*
- ID_OUI_FROM_DATABASE=Apple Computer
+ ID_OUI_FROM_DATABASE=Apple
OUI:000D94*
ID_OUI_FROM_DATABASE=AFAR Communications,Inc
@@ -23564,7 +23972,7 @@ OUI:000E02*
ID_OUI_FROM_DATABASE=Advantech AMT Inc.
OUI:000E03*
- ID_OUI_FROM_DATABASE=Emulex
+ ID_OUI_FROM_DATABASE=Emulex Corporation
OUI:000E04*
ID_OUI_FROM_DATABASE=CMA/Microdialysis AB
@@ -23687,7 +24095,7 @@ OUI:000E2E*
ID_OUI_FROM_DATABASE=Edimax Technology Co., Ltd.
OUI:000E2F*
- ID_OUI_FROM_DATABASE=Disetronic Medical Systems AG
+ ID_OUI_FROM_DATABASE=Roche Diagnostics GmbH
OUI:000E30*
ID_OUI_FROM_DATABASE=AERAS Networks, Inc.
@@ -23822,7 +24230,7 @@ OUI:000E5B*
ID_OUI_FROM_DATABASE=ParkerVision - Direct2Data
OUI:000E5C*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:000E5D*
ID_OUI_FROM_DATABASE=Triple Play Technologies A/S
@@ -23876,7 +24284,7 @@ OUI:000E6D*
ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
OUI:000E6E*
- ID_OUI_FROM_DATABASE=MICRELEC ELECTRONICS S.A
+ ID_OUI_FROM_DATABASE=MAT S.A. (Mircrelec Advanced Technology)
OUI:000E6F*
ID_OUI_FROM_DATABASE=IRIS Corporation Berhad
@@ -24458,7 +24866,7 @@ OUI:000F31*
ID_OUI_FROM_DATABASE=Allied Vision Technologies Canada Inc
OUI:000F32*
- ID_OUI_FROM_DATABASE=Lootom Optoelectronic Technology (Wuxi) Co Ltd
+ ID_OUI_FROM_DATABASE=Lootom Telcovideo Network Wuxi Co Ltd
OUI:000F33*
ID_OUI_FROM_DATABASE=DUALi Inc.
@@ -24785,7 +25193,7 @@ OUI:000F9E*
ID_OUI_FROM_DATABASE=Murrelektronik GmbH
OUI:000F9F*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:000FA0*
ID_OUI_FROM_DATABASE=CANON KOREA BUSINESS SOLUTIONS INC.
@@ -24794,7 +25202,7 @@ OUI:000FA1*
ID_OUI_FROM_DATABASE=Gigabit Systems Inc.
OUI:000FA2*
- ID_OUI_FROM_DATABASE=Digital Path Networks
+ ID_OUI_FROM_DATABASE=2xWireless
OUI:000FA3*
ID_OUI_FROM_DATABASE=Alpha Networks Inc.
@@ -25427,7 +25835,7 @@ OUI:001074*
ID_OUI_FROM_DATABASE=ATEN INTERNATIONAL CO., LTD.
OUI:001075*
- ID_OUI_FROM_DATABASE=Maxtor Corporation
+ ID_OUI_FROM_DATABASE=Segate Technology LLC
OUI:001076*
ID_OUI_FROM_DATABASE=EUREM GmbH
@@ -25795,6 +26203,9 @@ OUI:0010EE*
OUI:0010EF*
ID_OUI_FROM_DATABASE=DBTEL INCORPORATED
+OUI:0010F0*
+ ID_OUI_FROM_DATABASE=RITTAL-WERK RUDOLF LOH GmbH & Co.
+
OUI:0010F1*
ID_OUI_FROM_DATABASE=I-O CORPORATION
@@ -25817,13 +26228,13 @@ OUI:0010F7*
ID_OUI_FROM_DATABASE=IRIICHI TECHNOLOGIES Inc.
OUI:0010F8*
- ID_OUI_FROM_DATABASE=Niikke Techno System Co. Ltd
+ ID_OUI_FROM_DATABASE=TEXIO TECHNOLOGY CORPORATION
OUI:0010F9*
ID_OUI_FROM_DATABASE=UNIQUE SYSTEMS, INC.
OUI:0010FA*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:0010FB*
ID_OUI_FROM_DATABASE=ZIDA TECHNOLOGIES LIMITED
@@ -25919,7 +26330,7 @@ OUI:001119*
ID_OUI_FROM_DATABASE=Solteras, Inc.
OUI:00111A*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:00111B*
ID_OUI_FROM_DATABASE=Targa Systems Div L-3 Communications Canada
@@ -25949,7 +26360,7 @@ OUI:001123*
ID_OUI_FROM_DATABASE=Appointech, Inc.
OUI:001124*
- ID_OUI_FROM_DATABASE=Apple Computer
+ ID_OUI_FROM_DATABASE=Apple
OUI:001125*
ID_OUI_FROM_DATABASE=IBM Corp
@@ -26225,7 +26636,7 @@ OUI:00117F*
ID_OUI_FROM_DATABASE=Neotune Information Technology Corporation,.LTD
OUI:001180*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001181*
ID_OUI_FROM_DATABASE=InterEnergy Co.Ltd,
@@ -26363,7 +26774,7 @@ OUI:0011AD*
ID_OUI_FROM_DATABASE=Shanghai Ruijie Technology
OUI:0011AE*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0011AF*
ID_OUI_FROM_DATABASE=Medialink-i,Inc
@@ -26720,7 +27131,7 @@ OUI:001224*
ID_OUI_FROM_DATABASE=NexQL Corporation
OUI:001225*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001226*
ID_OUI_FROM_DATABASE=Japan Direx Corporation
@@ -26846,7 +27257,7 @@ OUI:00124E*
ID_OUI_FROM_DATABASE=XAC AUTOMATION CORP.
OUI:00124F*
- ID_OUI_FROM_DATABASE=Tyco Thermal Controls LLC.
+ ID_OUI_FROM_DATABASE=Pentair Thermal Management
OUI:001250*
ID_OUI_FROM_DATABASE=Tokyo Aircaft Instrument Co., Ltd.
@@ -27023,7 +27434,7 @@ OUI:001289*
ID_OUI_FROM_DATABASE=Advance Sterilization Products
OUI:00128A*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:00128B*
ID_OUI_FROM_DATABASE=Sensory Networks Inc
@@ -27212,7 +27623,7 @@ OUI:0012C8*
ID_OUI_FROM_DATABASE=Perfect tech
OUI:0012C9*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0012CA*
ID_OUI_FROM_DATABASE=Mechatronic Brick Aps
@@ -27716,7 +28127,7 @@ OUI:001370*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
OUI:001371*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001372*
ID_OUI_FROM_DATABASE=Dell ESG PCBA Test
@@ -28157,7 +28568,7 @@ OUI:001403*
ID_OUI_FROM_DATABASE=Renasis, LLC
OUI:001404*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001405*
ID_OUI_FROM_DATABASE=OpenIB, Inc.
@@ -28232,7 +28643,7 @@ OUI:00141C*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
OUI:00141D*
- ID_OUI_FROM_DATABASE=Lust Antriebstechnik GmbH
+ ID_OUI_FROM_DATABASE=LTi DRIVES GmbH
OUI:00141E*
ID_OUI_FROM_DATABASE=P.A. Semi, Inc.
@@ -28388,7 +28799,7 @@ OUI:001450*
ID_OUI_FROM_DATABASE=Heim Systems GmbH
OUI:001451*
- ID_OUI_FROM_DATABASE=Apple Computer Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:001452*
ID_OUI_FROM_DATABASE=CALCULEX,INC.
@@ -28607,7 +29018,7 @@ OUI:001499*
ID_OUI_FROM_DATABASE=Helicomm Inc
OUI:00149A*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:00149B*
ID_OUI_FROM_DATABASE=Nokota Communications, LLC
@@ -28841,7 +29252,7 @@ OUI:0014E7*
ID_OUI_FROM_DATABASE=Stolinx,. Inc
OUI:0014E8*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0014E9*
ID_OUI_FROM_DATABASE=Nortech International
@@ -29054,7 +29465,7 @@ OUI:00152E*
ID_OUI_FROM_DATABASE=PacketHop, Inc.
OUI:00152F*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001530*
ID_OUI_FROM_DATABASE=EMC Corporation
@@ -29375,7 +29786,7 @@ OUI:001599*
ID_OUI_FROM_DATABASE=Samsung Electronics Co., LTD
OUI:00159A*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:00159B*
ID_OUI_FROM_DATABASE=Nortel
@@ -29417,7 +29828,7 @@ OUI:0015A7*
ID_OUI_FROM_DATABASE=Robatech AG
OUI:0015A8*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0015A9*
ID_OUI_FROM_DATABASE=KWANG WOO I&C CO.,LTD
@@ -29795,7 +30206,7 @@ OUI:001625*
ID_OUI_FROM_DATABASE=Impinj, Inc.
OUI:001626*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001627*
ID_OUI_FROM_DATABASE=embedded-logic DESIGN AND MORE GmbH
@@ -30032,7 +30443,7 @@ OUI:001674*
ID_OUI_FROM_DATABASE=EuroCB (Phils.), Inc.
OUI:001675*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001676*
ID_OUI_FROM_DATABASE=Intel Corporate
@@ -30221,7 +30632,7 @@ OUI:0016B3*
ID_OUI_FROM_DATABASE=Photonicbridges (China) Co., Ltd.
OUI:0016B5*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0016B6*
ID_OUI_FROM_DATABASE=Cisco-Linksys
@@ -30287,7 +30698,7 @@ OUI:0016CA*
ID_OUI_FROM_DATABASE=Nortel
OUI:0016CB*
- ID_OUI_FROM_DATABASE=Apple Computer
+ ID_OUI_FROM_DATABASE=Apple
OUI:0016CC*
ID_OUI_FROM_DATABASE=Xcute Mobile Corp.
@@ -30446,7 +30857,7 @@ OUI:0016FF*
ID_OUI_FROM_DATABASE=Wamin Optocomm Mfg Corp
OUI:001700*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001701*
ID_OUI_FROM_DATABASE=KDE, Inc.
@@ -30733,9 +31144,6 @@ OUI:00175F*
OUI:001760*
ID_OUI_FROM_DATABASE=Naito Densei Machida MFG.CO.,LTD
-OUI:001761*
- ID_OUI_FROM_DATABASE=ZKSoftware Inc.
-
OUI:001762*
ID_OUI_FROM_DATABASE=Solar Technology, Inc.
@@ -30839,7 +31247,7 @@ OUI:001783*
ID_OUI_FROM_DATABASE=Texas Instruments
OUI:001784*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001785*
ID_OUI_FROM_DATABASE=Sparr Electronics Ltd
@@ -31121,7 +31529,7 @@ OUI:0017E1*
ID_OUI_FROM_DATABASE=DACOS Technologies Co., Ltd.
OUI:0017E2*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0017E3*
ID_OUI_FROM_DATABASE=Texas Instruments
@@ -31157,7 +31565,7 @@ OUI:0017ED*
ID_OUI_FROM_DATABASE=WooJooIT Ltd.
OUI:0017EE*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0017EF*
ID_OUI_FROM_DATABASE=IBM Corp
@@ -31169,7 +31577,7 @@ OUI:0017F1*
ID_OUI_FROM_DATABASE=Renu Electronics Pvt Ltd
OUI:0017F2*
- ID_OUI_FROM_DATABASE=Apple Computer
+ ID_OUI_FROM_DATABASE=Apple
OUI:0017F3*
ID_OUI_FROM_DATABASE=Harris Corparation
@@ -31700,7 +32108,7 @@ OUI:0018A3*
ID_OUI_FROM_DATABASE=ZIPPY TECHNOLOGY CORP.
OUI:0018A4*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0018A5*
ID_OUI_FROM_DATABASE=ADigit Technologies Corp.
@@ -31784,7 +32192,7 @@ OUI:0018BF*
ID_OUI_FROM_DATABASE=Essence Technology Solution, Inc.
OUI:0018C0*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0018C1*
ID_OUI_FROM_DATABASE=Almitec Informática e Comércio
@@ -32108,7 +32516,7 @@ OUI:00192B*
ID_OUI_FROM_DATABASE=Aclara RF Systems Inc.
OUI:00192C*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:00192D*
ID_OUI_FROM_DATABASE=Nokia Corporation
@@ -32135,7 +32543,7 @@ OUI:001934*
ID_OUI_FROM_DATABASE=TRENDON TOUCH TECHNOLOGY CORP.
OUI:001935*
- ID_OUI_FROM_DATABASE=DÜRR DENTAL AG
+ ID_OUI_FROM_DATABASE=DUERR DENTAL AG
OUI:001936*
ID_OUI_FROM_DATABASE=STERLITE OPTICAL TECHNOLOGIES LIMITED
@@ -32258,7 +32666,7 @@ OUI:00195D*
ID_OUI_FROM_DATABASE=ShenZhen XinHuaTong Opto Electronics Co.,Ltd
OUI:00195E*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:00195F*
ID_OUI_FROM_DATABASE=Valemount Networks Corporation
@@ -32474,7 +32882,7 @@ OUI:0019A5*
ID_OUI_FROM_DATABASE=RadarFind Corporation
OUI:0019A6*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0019A7*
ID_OUI_FROM_DATABASE=ITU-T
@@ -32552,7 +32960,7 @@ OUI:0019BF*
ID_OUI_FROM_DATABASE=Citiway technology Co.,ltd
OUI:0019C0*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0019C1*
ID_OUI_FROM_DATABASE=Alps Electric Co., Ltd
@@ -32657,7 +33065,7 @@ OUI:0019E2*
ID_OUI_FROM_DATABASE=Juniper Networks
OUI:0019E3*
- ID_OUI_FROM_DATABASE=Apple Computer Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:0019E4*
ID_OUI_FROM_DATABASE=2Wire, Inc
@@ -32825,7 +33233,7 @@ OUI:001A1A*
ID_OUI_FROM_DATABASE=Gentex Corporation/Electro-Acoustic Products
OUI:001A1B*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001A1C*
ID_OUI_FROM_DATABASE=GT&T Engineering Pte Ltd
@@ -33050,7 +33458,7 @@ OUI:001A65*
ID_OUI_FROM_DATABASE=Seluxit
OUI:001A66*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001A67*
ID_OUI_FROM_DATABASE=Infinite QL Sdn Bhd
@@ -33101,7 +33509,7 @@ OUI:001A76*
ID_OUI_FROM_DATABASE=SDT information Technology Co.,LTD.
OUI:001A77*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001A78*
ID_OUI_FROM_DATABASE=ubtos
@@ -33263,7 +33671,7 @@ OUI:001AAC*
ID_OUI_FROM_DATABASE=Corelatus AB
OUI:001AAD*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001AAE*
ID_OUI_FROM_DATABASE=Savant Systems LLC
@@ -33401,7 +33809,7 @@ OUI:001ADA*
ID_OUI_FROM_DATABASE=Biz-2-Me Inc.
OUI:001ADB*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001ADC*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
@@ -33410,7 +33818,7 @@ OUI:001ADD*
ID_OUI_FROM_DATABASE=PePWave Ltd
OUI:001ADE*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001ADF*
ID_OUI_FROM_DATABASE=Interactivetv Pty Limited
@@ -33758,7 +34166,7 @@ OUI:001B51*
ID_OUI_FROM_DATABASE=Vector Technology Corp.
OUI:001B52*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001B53*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
@@ -33809,7 +34217,7 @@ OUI:001B62*
ID_OUI_FROM_DATABASE=JHT Optoelectronics Co.,Ltd.
OUI:001B63*
- ID_OUI_FROM_DATABASE=Apple Computer Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:001B64*
ID_OUI_FROM_DATABASE=IsaacLandKorea Co., Ltd,
@@ -33821,7 +34229,7 @@ OUI:001B66*
ID_OUI_FROM_DATABASE=Sennheiser electronic GmbH & Co. KG
OUI:001B67*
- ID_OUI_FROM_DATABASE=Ubiquisys Ltd
+ ID_OUI_FROM_DATABASE=Cisco Systems Inc
OUI:001B68*
ID_OUI_FROM_DATABASE=Modnnet Co., Ltd
@@ -34175,7 +34583,7 @@ OUI:001BDC*
ID_OUI_FROM_DATABASE=Vencer Co., Ltd.
OUI:001BDD*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001BDE*
ID_OUI_FROM_DATABASE=Renkus-Heinz, Inc.
@@ -34331,10 +34739,10 @@ OUI:001C10*
ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC
OUI:001C11*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001C12*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001C13*
ID_OUI_FROM_DATABASE=OPTSYS TECHNOLOGY CO., LTD.
@@ -34817,7 +35225,7 @@ OUI:001CB2*
ID_OUI_FROM_DATABASE=BPT SPA
OUI:001CB3*
- ID_OUI_FROM_DATABASE=APPLE, INC
+ ID_OUI_FROM_DATABASE=Apple
OUI:001CB4*
ID_OUI_FROM_DATABASE=Iridium Satellite LLC
@@ -34859,7 +35267,7 @@ OUI:001CC0*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:001CC1*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001CC2*
ID_OUI_FROM_DATABASE=Part II Research, Inc.
@@ -35033,7 +35441,7 @@ OUI:001CFA*
ID_OUI_FROM_DATABASE=Alarm.com
OUI:001CFB*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001CFC*
ID_OUI_FROM_DATABASE=Suminet Communication Technologies (Shanghai) Co., Ltd.
@@ -35285,7 +35693,7 @@ OUI:001D4E*
ID_OUI_FROM_DATABASE=TCM Mobile LLC
OUI:001D4F*
- ID_OUI_FROM_DATABASE=Apple Computer Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:001D50*
ID_OUI_FROM_DATABASE=SPINETIX SA
@@ -35369,7 +35777,7 @@ OUI:001D6A*
ID_OUI_FROM_DATABASE=Alpha Networks Inc.
OUI:001D6B*
- ID_OUI_FROM_DATABASE=Motorola (formerly Netopia, Inc
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001D6C*
ID_OUI_FROM_DATABASE=ClariPhy Communications, Inc.
@@ -35618,7 +36026,7 @@ OUI:001DBD*
ID_OUI_FROM_DATABASE=Versamed Inc.
OUI:001DBE*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001DBF*
ID_OUI_FROM_DATABASE=Radiient Technologies, Inc.
@@ -36026,7 +36434,7 @@ OUI:001E45*
ID_OUI_FROM_DATABASE=Sony Ericsson Mobile Communications AB
OUI:001E46*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001E47*
ID_OUI_FROM_DATABASE=PT. Hariff Daya Tunggal Engineering
@@ -36062,7 +36470,7 @@ OUI:001E51*
ID_OUI_FROM_DATABASE=Converter Industry Srl
OUI:001E52*
- ID_OUI_FROM_DATABASE=Apple Computer Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:001E53*
ID_OUI_FROM_DATABASE=Further Tech Co., LTD
@@ -36086,7 +36494,7 @@ OUI:001E59*
ID_OUI_FROM_DATABASE=Silicon Turnkey Express, LLC
OUI:001E5A*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001E5B*
ID_OUI_FROM_DATABASE=Unitron Company, Inc.
@@ -36155,7 +36563,7 @@ OUI:001E70*
ID_OUI_FROM_DATABASE=Cobham Defence Communications Ltd
OUI:001E71*
- ID_OUI_FROM_DATABASE=Igeacare Solutions Inc.
+ ID_OUI_FROM_DATABASE=MIrcom Group of Companies
OUI:001E72*
ID_OUI_FROM_DATABASE=PCS
@@ -36239,7 +36647,7 @@ OUI:001E8C*
ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
OUI:001E8D*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001E8E*
ID_OUI_FROM_DATABASE=Hunkeler AG
@@ -36398,7 +36806,7 @@ OUI:001EC1*
ID_OUI_FROM_DATABASE=3COM EUROPE LTD
OUI:001EC2*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:001EC3*
ID_OUI_FROM_DATABASE=Kozio, Inc.
@@ -36413,79 +36821,79 @@ OUI:001EC6*
ID_OUI_FROM_DATABASE=Obvius Holdings LLC
OUI:001EC7*
- ID_OUI_FROM_DATABASE=2Wire
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001EC8*
- ID_OUI_FROM_DATABASE=Rapid Mobile (Pty) Ltd
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001EC9*
- ID_OUI_FROM_DATABASE=Dell Inc
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001ECA*
- ID_OUI_FROM_DATABASE=Nortel
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001ECB*
- ID_OUI_FROM_DATABASE="RPC "Energoautomatika" Ltd
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001ECC*
- ID_OUI_FROM_DATABASE=CDVI
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001ECD*
- ID_OUI_FROM_DATABASE=KYLAND
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001ECE*
- ID_OUI_FROM_DATABASE=BISA Technologies (Hong Kong) Limited
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001ECF*
- ID_OUI_FROM_DATABASE=PHILIPS ELECTRONICS UK LTD
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001ED0*
- ID_OUI_FROM_DATABASE=Ingespace
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001ED1*
- ID_OUI_FROM_DATABASE=Keyprocessor B.V.
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001ED2*
- ID_OUI_FROM_DATABASE=Ray Shine Video Technology Inc
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001ED3*
- ID_OUI_FROM_DATABASE=Dot Technology Int'l Co., Ltd.
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001ED4*
- ID_OUI_FROM_DATABASE=Doble Engineering
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001ED5*
- ID_OUI_FROM_DATABASE=Tekon-Automatics
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001ED6*
- ID_OUI_FROM_DATABASE=Alentec & Orion AB
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001ED7*
- ID_OUI_FROM_DATABASE=H-Stream Wireless, Inc.
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001ED8*
- ID_OUI_FROM_DATABASE=Digital United Inc.
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001ED9*
- ID_OUI_FROM_DATABASE=Mitsubishi Precision Co.,LTd.
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001EDA*
- ID_OUI_FROM_DATABASE=Wesemann Elektrotechniek B.V.
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001EDB*
- ID_OUI_FROM_DATABASE=Giken Trastem Co., Ltd.
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001EDC*
- ID_OUI_FROM_DATABASE=Sony Ericsson Mobile Communications AB
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001EDD*
- ID_OUI_FROM_DATABASE=WASKO S.A.
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001EDE*
- ID_OUI_FROM_DATABASE=BYD COMPANY LIMITED
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001EDF*
- ID_OUI_FROM_DATABASE=Master Industrialization Center Kista
+ ID_OUI_FROM_DATABASE=2Wire, Inc.
OUI:001EE0*
ID_OUI_FROM_DATABASE=Urmet Domus SpA
@@ -36857,7 +37265,7 @@ OUI:001F5A*
ID_OUI_FROM_DATABASE=Beckwith Electric Co.
OUI:001F5B*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:001F5C*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
@@ -36962,7 +37370,7 @@ OUI:001F7D*
ID_OUI_FROM_DATABASE=embedded wireless GmbH
OUI:001F7E*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001F7F*
ID_OUI_FROM_DATABASE=Phabrix Limited
@@ -37172,7 +37580,7 @@ OUI:001FC3*
ID_OUI_FROM_DATABASE=SmartSynch, Inc
OUI:001FC4*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:001FC5*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
@@ -37313,7 +37721,7 @@ OUI:001FF2*
ID_OUI_FROM_DATABASE=VIA Technologies, Inc.
OUI:001FF3*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:001FF4*
ID_OUI_FROM_DATABASE=Power Monitors, Inc.
@@ -37544,7 +37952,7 @@ OUI:00203F*
ID_OUI_FROM_DATABASE=JUKI CORPORATION
OUI:002040*
- ID_OUI_FROM_DATABASE=Motorola Broadband Communications Sector
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:002041*
ID_OUI_FROM_DATABASE=DATA NET
@@ -38207,7 +38615,7 @@ OUI:00211D*
ID_OUI_FROM_DATABASE=Dataline AB
OUI:00211E*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:00211F*
ID_OUI_FROM_DATABASE=SHINSUNG DELTATECH CO.,LTD.
@@ -38279,7 +38687,7 @@ OUI:002135*
ID_OUI_FROM_DATABASE=ALCATEL-LUCENT
OUI:002136*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:002137*
ID_OUI_FROM_DATABASE=Bay Controls, LLC
@@ -38318,7 +38726,7 @@ OUI:002142*
ID_OUI_FROM_DATABASE=Advanced Control Systems doo
OUI:002143*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:002144*
ID_OUI_FROM_DATABASE=SS Telecoms
@@ -38501,7 +38909,7 @@ OUI:00217F*
ID_OUI_FROM_DATABASE=Intraco Technology Pte Ltd
OUI:002180*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:002181*
ID_OUI_FROM_DATABASE=Si2 Microsystems Limited
@@ -38660,7 +39068,7 @@ OUI:0021B4*
ID_OUI_FROM_DATABASE=APRO MEDIA CO., LTD
OUI:0021B5*
- ID_OUI_FROM_DATABASE=Vyro Games Limited
+ ID_OUI_FROM_DATABASE=Galvanic Ltd
OUI:0021B6*
ID_OUI_FROM_DATABASE=Triacta Power Technologies Inc.
@@ -38816,7 +39224,7 @@ OUI:0021E8*
ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
OUI:0021E9*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:0021EA*
ID_OUI_FROM_DATABASE=Bystronic Laser AG
@@ -38933,7 +39341,7 @@ OUI:00220F*
ID_OUI_FROM_DATABASE=MoCA (Multimedia over Coax Alliance)
OUI:002210*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:002211*
ID_OUI_FROM_DATABASE=Rohati Systems
@@ -39077,7 +39485,7 @@ OUI:002240*
ID_OUI_FROM_DATABASE=Universal Telecom S/A
OUI:002241*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:002242*
ID_OUI_FROM_DATABASE=Alacron Inc.
@@ -39422,7 +39830,7 @@ OUI:0022B3*
ID_OUI_FROM_DATABASE=Sei S.p.A.
OUI:0022B4*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0022B5*
ID_OUI_FROM_DATABASE=NOVITA
@@ -39680,7 +40088,7 @@ OUI:00230A*
ID_OUI_FROM_DATABASE=ARBURG GmbH & Co KG
OUI:00230B*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:00230C*
ID_OUI_FROM_DATABASE=CLOVER ELECTRONICS CO.,LTD.
@@ -39701,7 +40109,7 @@ OUI:002311*
ID_OUI_FROM_DATABASE=Gloscom Co., Ltd.
OUI:002312*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:002313*
ID_OUI_FROM_DATABASE=Qool Technologies Ltd.
@@ -39797,7 +40205,7 @@ OUI:002331*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
OUI:002332*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:002333*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
@@ -39968,7 +40376,7 @@ OUI:00236B*
ID_OUI_FROM_DATABASE=Xembedded, Inc.
OUI:00236C*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:00236D*
ID_OUI_FROM_DATABASE=ResMed Ltd
@@ -39992,10 +40400,10 @@ OUI:002373*
ID_OUI_FROM_DATABASE=GridIron Systems, Inc.
OUI:002374*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:002375*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:002376*
ID_OUI_FROM_DATABASE=HTC Corporation
@@ -40088,7 +40496,7 @@ OUI:002394*
ID_OUI_FROM_DATABASE=Samjeon
OUI:002395*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:002396*
ID_OUI_FROM_DATABASE=ANDES TECHNOLOGY CORPORATION
@@ -40127,10 +40535,10 @@ OUI:0023A1*
ID_OUI_FROM_DATABASE=Trend Electronics Ltd
OUI:0023A2*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0023A3*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0023A4*
ID_OUI_FROM_DATABASE=New Concepts Development Corp.
@@ -40166,7 +40574,7 @@ OUI:0023AE*
ID_OUI_FROM_DATABASE=Dell Inc.
OUI:0023AF*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0023B0*
ID_OUI_FROM_DATABASE=COMXION Technology Inc.
@@ -40310,7 +40718,7 @@ OUI:0023DE*
ID_OUI_FROM_DATABASE=Ansync Inc.
OUI:0023DF*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:0023E0*
ID_OUI_FROM_DATABASE=INO Therapeutics LLC
@@ -40352,10 +40760,10 @@ OUI:0023EC*
ID_OUI_FROM_DATABASE=Algorithmix GmbH
OUI:0023ED*
- ID_OUI_FROM_DATABASE=Motorola CHS
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0023EE*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0023EF*
ID_OUI_FROM_DATABASE=Zuend Systemtechnik AG
@@ -40562,7 +40970,7 @@ OUI:002435*
ID_OUI_FROM_DATABASE=WIDE CORPORATION
OUI:002436*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:002437*
ID_OUI_FROM_DATABASE=Motorola - BSG
@@ -40835,13 +41243,13 @@ OUI:002492*
ID_OUI_FROM_DATABASE=Motorola, Broadband Solutions Group
OUI:002493*
- ID_OUI_FROM_DATABASE=Motorola, Inc
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:002494*
ID_OUI_FROM_DATABASE=Shenzhen Baoxin Tech CO., Ltd.
OUI:002495*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:002496*
ID_OUI_FROM_DATABASE=Ginzinger electronic systems
@@ -40874,10 +41282,10 @@ OUI:00249F*
ID_OUI_FROM_DATABASE=RIM Testing Services
OUI:0024A0*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0024A1*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0024A2*
ID_OUI_FROM_DATABASE=Hong Kong Middleware Technology Limited
@@ -40973,7 +41381,7 @@ OUI:0024C0*
ID_OUI_FROM_DATABASE=NTI COMODO INC
OUI:0024C1*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0024C2*
ID_OUI_FROM_DATABASE=Asumo Co.,Ltd.
@@ -41159,7 +41567,7 @@ OUI:0024FF*
ID_OUI_FROM_DATABASE=QLogic Corporation
OUI:002500*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:002501*
ID_OUI_FROM_DATABASE=JSC "Supertel"
@@ -41378,7 +41786,7 @@ OUI:00254A*
ID_OUI_FROM_DATABASE=RingCube Technologies, Inc.
OUI:00254B*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:00254C*
ID_OUI_FROM_DATABASE=Videon Central, Inc.
@@ -41714,7 +42122,7 @@ OUI:0025BB*
ID_OUI_FROM_DATABASE=INNERINT Co., Ltd.
OUI:0025BC*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:0025BD*
ID_OUI_FROM_DATABASE=Italdata Ingegneria dell'Idea S.p.A.
@@ -41870,10 +42278,10 @@ OUI:0025F0*
ID_OUI_FROM_DATABASE=Suga Electronics Limited
OUI:0025F1*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0025F2*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0025F3*
ID_OUI_FROM_DATABASE=Nordwestdeutsche Zählerrevision
@@ -41936,7 +42344,7 @@ OUI:002607*
ID_OUI_FROM_DATABASE=Enabling Technology Pty Ltd
OUI:002608*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:002609*
ID_OUI_FROM_DATABASE=Phyllis Co., Ltd.
@@ -42074,7 +42482,7 @@ OUI:002635*
ID_OUI_FROM_DATABASE=Bluetechnix GmbH
OUI:002636*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:002637*
ID_OUI_FROM_DATABASE=Samsung Electro-Mechanics
@@ -42107,10 +42515,10 @@ OUI:002640*
ID_OUI_FROM_DATABASE=Baustem Broadband Technologies, Ltd.
OUI:002641*
- ID_OUI_FROM_DATABASE=Motorola, Inc
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:002642*
- ID_OUI_FROM_DATABASE=Motorola, Inc
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:002643*
ID_OUI_FROM_DATABASE=Alps Electric Co., Ltd
@@ -42131,7 +42539,7 @@ OUI:002648*
ID_OUI_FROM_DATABASE=Emitech Corp.
OUI:00264A*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:00264C*
ID_OUI_FROM_DATABASE=Shanghai DigiVision Technology Co., Ltd.
@@ -42431,7 +42839,7 @@ OUI:0026AF*
ID_OUI_FROM_DATABASE=Duelco A/S
OUI:0026B0*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:0026B1*
ID_OUI_FROM_DATABASE=Navis Auto Motive Systems, Inc.
@@ -42461,10 +42869,10 @@ OUI:0026B9*
ID_OUI_FROM_DATABASE=Dell Inc
OUI:0026BA*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0026BB*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:0026BC*
ID_OUI_FROM_DATABASE=General Jack Technology Ltd.
@@ -43091,7 +43499,7 @@ OUI:003064*
ID_OUI_FROM_DATABASE=ADLINK TECHNOLOGY, INC.
OUI:003065*
- ID_OUI_FROM_DATABASE=APPLE COMPUTER, INC.
+ ID_OUI_FROM_DATABASE=Apple
OUI:003066*
ID_OUI_FROM_DATABASE=RFM
@@ -43601,7 +44009,7 @@ OUI:003D41*
ID_OUI_FROM_DATABASE=Hatteland Computer AS
OUI:003EE1*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:004000*
ID_OUI_FROM_DATABASE=PCI COMPONENTES DA AMZONIA LTD
@@ -44114,7 +44522,7 @@ OUI:0040A9*
ID_OUI_FROM_DATABASE=DATACOM INC.
OUI:0040AA*
- ID_OUI_FROM_DATABASE=VALMET AUTOMATION INC.
+ ID_OUI_FROM_DATABASE=Metso Automation
OUI:0040AB*
ID_OUI_FROM_DATABASE=ROLAND DG CORPORATION
@@ -45020,10 +45428,10 @@ OUI:0050E2*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
OUI:0050E3*
- ID_OUI_FROM_DATABASE=Motorola, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:0050E4*
- ID_OUI_FROM_DATABASE=APPLE COMPUTER, INC.
+ ID_OUI_FROM_DATABASE=Apple
OUI:0050E6*
ID_OUI_FROM_DATABASE=HAKUSAN CORPORATION
@@ -45904,12 +46312,21 @@ OUI:0070B0*
OUI:0070B3*
ID_OUI_FROM_DATABASE=DATA RECALL LTD.
+OUI:00738D*
+ ID_OUI_FROM_DATABASE=Tinno Mobile Technology Corp
+
+OUI:0073E0*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:0075E1*
ID_OUI_FROM_DATABASE=Ampt, LLC
OUI:00789E*
ID_OUI_FROM_DATABASE=SAGEMCOM
+OUI:007DFA*
+ ID_OUI_FROM_DATABASE=Volkswagen Group of America
+
OUI:007F28*
ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc
@@ -46214,7 +46631,7 @@ OUI:008063*
ID_OUI_FROM_DATABASE=Hirschmann Automation and Control GmbH
OUI:008064*
- ID_OUI_FROM_DATABASE=Tattile SRL
+ ID_OUI_FROM_DATABASE=WYSE TECHNOLOGY LLC
OUI:008065*
ID_OUI_FROM_DATABASE=CYBERGRAPHIC SYSTEMS PTY LTD.
@@ -47069,7 +47486,7 @@ OUI:009079*
ID_OUI_FROM_DATABASE=ClearOne, Inc.
OUI:00907A*
- ID_OUI_FROM_DATABASE=Polycom, Inc.
+ ID_OUI_FROM_DATABASE=Spectralink, Inc
OUI:00907B*
ID_OUI_FROM_DATABASE=E-TECH, INC.
@@ -47171,7 +47588,7 @@ OUI:00909B*
ID_OUI_FROM_DATABASE=MARKEM-IMAJE
OUI:00909C*
- ID_OUI_FROM_DATABASE=Motorola, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:00909D*
ID_OUI_FROM_DATABASE=NovaTech Process Solutions, LLC
@@ -47453,7 +47870,7 @@ OUI:0090F9*
ID_OUI_FROM_DATABASE=LEITCH
OUI:0090FA*
- ID_OUI_FROM_DATABASE=EMULEX Corp
+ ID_OUI_FROM_DATABASE=Emulex Corporation
OUI:0090FB*
ID_OUI_FROM_DATABASE=PORTWELL, INC.
@@ -47684,7 +48101,7 @@ OUI:00A03F*
ID_OUI_FROM_DATABASE=COMPUTER SOCIETY MICROPROCESSOR & MICROPROCESSOR STANDARDS C
OUI:00A040*
- ID_OUI_FROM_DATABASE=APPLE COMPUTER
+ ID_OUI_FROM_DATABASE=Apple
OUI:00A041*
ID_OUI_FROM_DATABASE=INFICON
@@ -48259,6 +48676,9 @@ OUI:00A1DE*
OUI:00A2DA*
ID_OUI_FROM_DATABASE=INAT GmbH
+OUI:00A2FF*
+ ID_OUI_FROM_DATABASE=abatec group AG
+
OUI:00AA00*
ID_OUI_FROM_DATABASE=INTEL CORPORATION
@@ -49199,7 +49619,7 @@ OUI:00C5DB*
ID_OUI_FROM_DATABASE=Datatech Sistemas Digitales Avanzados SL
OUI:00C610*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:00CBBD*
ID_OUI_FROM_DATABASE=Cambridge Broadband Networks Ltd.
@@ -49619,7 +50039,7 @@ OUI:00D087*
ID_OUI_FROM_DATABASE=MICROFIRST INC.
OUI:00D088*
- ID_OUI_FROM_DATABASE=Motorola, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:00D089*
ID_OUI_FROM_DATABASE=DYNACOLOR, INC.
@@ -50372,7 +50792,7 @@ OUI:00E06B*
ID_OUI_FROM_DATABASE=W&G SPECIAL PRODUCTS
OUI:00E06C*
- ID_OUI_FROM_DATABASE=AEP Systems International Ltd
+ ID_OUI_FROM_DATABASE=Ultra Electronics Limited (AEP Networks)
OUI:00E06D*
ID_OUI_FROM_DATABASE=COMPUWARE CORPORATION
@@ -50381,7 +50801,7 @@ OUI:00E06E*
ID_OUI_FROM_DATABASE=FAR SYSTEMS S.p.A.
OUI:00E06F*
- ID_OUI_FROM_DATABASE=Motorola, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:00E070*
ID_OUI_FROM_DATABASE=DH TECHNOLOGY
@@ -50663,7 +51083,7 @@ OUI:00E0CC*
ID_OUI_FROM_DATABASE=HERO SYSTEMS, LTD.
OUI:00E0CD*
- ID_OUI_FROM_DATABASE=SENSIS CORPORATION
+ ID_OUI_FROM_DATABASE=SAAB SENSIS CORPORATION
OUI:00E0CE*
ID_OUI_FROM_DATABASE=ARN
@@ -50818,6 +51238,9 @@ OUI:00E0FF*
OUI:00E175*
ID_OUI_FROM_DATABASE=AK-Systems Ltd
+OUI:00E3B2*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:00E666*
ID_OUI_FROM_DATABASE=ARIMA Communications Corp.
@@ -50837,7 +51260,7 @@ OUI:00F403*
ID_OUI_FROM_DATABASE=Orbis Systems Oy
OUI:00F4B9*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:00F860*
ID_OUI_FROM_DATABASE=PT. Panggung Electric Citrabuana
@@ -50900,7 +51323,7 @@ OUI:040AE0*
ID_OUI_FROM_DATABASE=XMIT AG COMPUTER NETWORKS
OUI:040CCE*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:040EC2*
ID_OUI_FROM_DATABASE=ViewSonic Mobile China Limited
@@ -50914,6 +51337,12 @@ OUI:04180F*
OUI:0418D6*
ID_OUI_FROM_DATABASE=Ubiquiti Networks
+OUI:041A04*
+ ID_OUI_FROM_DATABASE=WaveIP
+
+OUI:041B94*
+ ID_OUI_FROM_DATABASE=Host Mobility AB
+
OUI:041BBA*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
@@ -50921,7 +51350,7 @@ OUI:041D10*
ID_OUI_FROM_DATABASE=Dream Ware Inc.
OUI:041E64*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:04209A*
ID_OUI_FROM_DATABASE=Panasonic AVC Networks Company
@@ -50947,6 +51376,12 @@ OUI:0432F4*
OUI:043604*
ID_OUI_FROM_DATABASE=Gyeyoung I&T
+OUI:043D98*
+ ID_OUI_FROM_DATABASE=ChongQing QingJia Electronics CO.,LTD
+
+OUI:0444A1*
+ ID_OUI_FROM_DATABASE=TELECON GALICIA,S.A.
+
OUI:044665*
ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
@@ -50959,11 +51394,14 @@ OUI:044BFF*
OUI:044CEF*
ID_OUI_FROM_DATABASE=Fujian Sanao Technology Co.,Ltd
+OUI:044F8B*
+ ID_OUI_FROM_DATABASE=Adapteva, Inc.
+
OUI:044FAA*
ID_OUI_FROM_DATABASE=Ruckus Wireless
OUI:045453*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:0455CA*
ID_OUI_FROM_DATABASE=BriView (Xiamen) Corp.
@@ -51013,6 +51451,9 @@ OUI:047D7B*
OUI:0481AE*
ID_OUI_FROM_DATABASE=Clack Corporation
+OUI:04848A*
+ ID_OUI_FROM_DATABASE=7INOVA TECHNOLOGY LIMITED
+
OUI:04888C*
ID_OUI_FROM_DATABASE=Eifelwerk Butler Systeme GmbH
@@ -51079,18 +51520,27 @@ OUI:04C5A4*
OUI:04C880*
ID_OUI_FROM_DATABASE=Samtec Inc
+OUI:04CB1D*
+ ID_OUI_FROM_DATABASE=Traka plc
+
OUI:04CE14*
ID_OUI_FROM_DATABASE=Wilocity LTD.
OUI:04CF25*
ID_OUI_FROM_DATABASE=MANYCOLORS, INC.
+OUI:04D437*
+ ID_OUI_FROM_DATABASE=ZNV
+
OUI:04D783*
ID_OUI_FROM_DATABASE=Y&H E&C Co.,LTD.
OUI:04DAD2*
ID_OUI_FROM_DATABASE=Cisco
+OUI:04DB56*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:04DD4C*
ID_OUI_FROM_DATABASE=Velocytech
@@ -51167,7 +51617,7 @@ OUI:080006*
ID_OUI_FROM_DATABASE=SIEMENS AG
OUI:080007*
- ID_OUI_FROM_DATABASE=APPLE COMPUTER INC.
+ ID_OUI_FROM_DATABASE=Apple
OUI:080008*
ID_OUI_FROM_DATABASE=BOLT BERANEK AND NEWMAN INC.
@@ -51530,7 +51980,7 @@ OUI:080080*
ID_OUI_FROM_DATABASE=AES DATA INC.
OUI:080081*
- ID_OUI_FROM_DATABASE=,ASTECH INC.
+ ID_OUI_FROM_DATABASE=ASTECH INC.
OUI:080082*
ID_OUI_FROM_DATABASE=VERITAS SOFTWARE
@@ -51643,6 +52093,9 @@ OUI:082AD0*
OUI:082E5F*
ID_OUI_FROM_DATABASE=Hewlett Packard
+OUI:083571*
+ ID_OUI_FROM_DATABASE=CASwell INC.
+
OUI:08373D*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
@@ -51661,6 +52114,9 @@ OUI:083E0C*
OUI:083E8E*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind.Co.Ltd
+OUI:084027*
+ ID_OUI_FROM_DATABASE=Gridstore Inc.
+
OUI:08482C*
ID_OUI_FROM_DATABASE=Raycore Taiwan Co., LTD.
@@ -51673,6 +52129,9 @@ OUI:084EBF*
OUI:08512E*
ID_OUI_FROM_DATABASE=Orion Diagnostica Oy
+OUI:085240*
+ ID_OUI_FROM_DATABASE=EbV Elektronikbau- und Vertriebs GmbH
+
OUI:085B0E*
ID_OUI_FROM_DATABASE=Fortinet, Inc.
@@ -51730,9 +52189,18 @@ OUI:08863B*
OUI:088DC8*
ID_OUI_FROM_DATABASE=Ryowa Electronics Co.,Ltd
+OUI:088E4F*
+ ID_OUI_FROM_DATABASE=SF Software Solutions
+
OUI:088F2C*
ID_OUI_FROM_DATABASE=Hills Sound Vision & Lighting
+OUI:0896D7*
+ ID_OUI_FROM_DATABASE=AVM GmbH
+
+OUI:089758*
+ ID_OUI_FROM_DATABASE=Shenzhen Strong Rising Electronics Co.,Ltd DongGuan Subsidiary
+
OUI:089E01*
ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC.
@@ -51763,9 +52231,15 @@ OUI:08B7EC*
OUI:08BBCC*
ID_OUI_FROM_DATABASE=AK-NORD EDV VERTRIEBSGES. mbH
+OUI:08BD43*
+ ID_OUI_FROM_DATABASE=NETGEAR INC.,
+
OUI:08BE09*
ID_OUI_FROM_DATABASE=Astrol Electronic AG
+OUI:08CA45*
+ ID_OUI_FROM_DATABASE=Toyou Feiji Electronics Co., Ltd.
+
OUI:08CC68*
ID_OUI_FROM_DATABASE=Cisco
@@ -51802,6 +52276,9 @@ OUI:08EBED*
OUI:08EDB9*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:08EF3B*
+ ID_OUI_FROM_DATABASE=MCS Logic Inc.
+
OUI:08F1B7*
ID_OUI_FROM_DATABASE=Towerstream Corpration
@@ -51862,6 +52339,9 @@ OUI:0C2AE7*
OUI:0C2D89*
ID_OUI_FROM_DATABASE=QiiQ Communications Inc.
+OUI:0C3021*
+ ID_OUI_FROM_DATABASE=Apple
+
OUI:0C37DC*
ID_OUI_FROM_DATABASE=Huawei Technologies Co., Ltd
@@ -51874,9 +52354,15 @@ OUI:0C3C65*
OUI:0C469D*
ID_OUI_FROM_DATABASE=MS Sedco
+OUI:0C473D*
+ ID_OUI_FROM_DATABASE=Hitron Technologies. Inc
+
OUI:0C4C39*
ID_OUI_FROM_DATABASE=Mitrastar Technology
+OUI:0C4DE9*
+ ID_OUI_FROM_DATABASE=Apple
+
OUI:0C51F7*
ID_OUI_FROM_DATABASE=CHAUVIN ARNOUX
@@ -51892,6 +52378,9 @@ OUI:0C57EB*
OUI:0C5A19*
ID_OUI_FROM_DATABASE=Axtion Sdn Bhd
+OUI:0C5CD8*
+ ID_OUI_FROM_DATABASE=DOLI Elektronik GmbH
+
OUI:0C6076*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
@@ -51908,13 +52397,13 @@ OUI:0C722C*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
OUI:0C74C2*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:0C7523*
ID_OUI_FROM_DATABASE=BEIJING GEHUA CATV NETWORK CO.,LTD
OUI:0C771A*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:0C7D7C*
ID_OUI_FROM_DATABASE=Kexiang Information Technology Co, Ltd.
@@ -51940,6 +52429,9 @@ OUI:0C84DC*
OUI:0C8525*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
+OUI:0C8910*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,LTD
+
OUI:0C8BFD*
ID_OUI_FROM_DATABASE=Intel Corporate
@@ -51952,12 +52444,18 @@ OUI:0C8D98*
OUI:0C924E*
ID_OUI_FROM_DATABASE=Rice Lake Weighing Systems
+OUI:0C9301*
+ ID_OUI_FROM_DATABASE=PT. Prasimax Inovasi Teknologi
+
OUI:0C93FB*
ID_OUI_FROM_DATABASE=BNS Solutions
OUI:0C96BF*
ID_OUI_FROM_DATABASE=Huawei Technologies Co., Ltd
+OUI:0C9B13*
+ ID_OUI_FROM_DATABASE=Shanghai Magic Mobile Telecommunication Co.Ltd.
+
OUI:0C9D56*
ID_OUI_FROM_DATABASE=Consort Controls Ltd
@@ -51976,12 +52474,18 @@ OUI:0CA402*
OUI:0CA42A*
ID_OUI_FROM_DATABASE=OB Telecom Electronic Technology Co., Ltd
+OUI:0CA694*
+ ID_OUI_FROM_DATABASE=Sunitec Enterprise Co.,Ltd
+
OUI:0CAF5A*
ID_OUI_FROM_DATABASE=GENUS POWER INFRASTRUCTURES LIMITED
OUI:0CB4EF*
ID_OUI_FROM_DATABASE=Digience Co.,Ltd.
+OUI:0CBD51*
+ ID_OUI_FROM_DATABASE=TCT Mobile Limited
+
OUI:0CBF15*
ID_OUI_FROM_DATABASE=Genetec
@@ -52009,6 +52513,9 @@ OUI:0CC81F*
OUI:0CC9C6*
ID_OUI_FROM_DATABASE=Samwin Hong Kong Limited
+OUI:0CCB8D*
+ ID_OUI_FROM_DATABASE=ASCO Numatics GmbH
+
OUI:0CCDD3*
ID_OUI_FROM_DATABASE=EASTRIVER TECHNOLOGY CO., LTD.
@@ -52150,6 +52657,9 @@ OUI:101DC0*
OUI:101F74*
ID_OUI_FROM_DATABASE=Hewlett-Packard Company
+OUI:102279*
+ ID_OUI_FROM_DATABASE=ZeroDesktop, Inc.
+
OUI:102831*
ID_OUI_FROM_DATABASE=Morion Inc.
@@ -52159,14 +52669,20 @@ OUI:102D96*
OUI:102EAF*
ID_OUI_FROM_DATABASE=Texas Instruments
+OUI:103378*
+ ID_OUI_FROM_DATABASE=FLECTRON Co., LTD
+
OUI:103711*
ID_OUI_FROM_DATABASE=Simlink AS
+OUI:103B59*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:103DEA*
ID_OUI_FROM_DATABASE=HFC Technology (Beijing) Ltd. Co.
OUI:1040F3*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:104369*
ID_OUI_FROM_DATABASE=Soundmax Electronic Limited
@@ -52214,7 +52730,7 @@ OUI:1064E2*
ID_OUI_FROM_DATABASE=ADFweb.com s.r.l.
OUI:1065A3*
- ID_OUI_FROM_DATABASE=Panamax Inc.
+ ID_OUI_FROM_DATABASE=Core Brands LLC
OUI:1065CF*
ID_OUI_FROM_DATABASE=IQSIM
@@ -52249,6 +52765,9 @@ OUI:1078D2*
OUI:107A86*
ID_OUI_FROM_DATABASE=U&U ENGINEERING INC.
+OUI:107BEF*
+ ID_OUI_FROM_DATABASE=ZyXEL Communications Corp
+
OUI:1083D2*
ID_OUI_FROM_DATABASE=Microseven Systems, LLC
@@ -52259,13 +52778,13 @@ OUI:108CCF*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
OUI:1093E9*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:109AB9*
ID_OUI_FROM_DATABASE=Tosibox Oy
OUI:109ADD*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:109FA9*
ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc
@@ -52273,12 +52792,18 @@ OUI:109FA9*
OUI:10A13B*
ID_OUI_FROM_DATABASE=FUJIKURA RUBBER LTD.
+OUI:10A5D0*
+ ID_OUI_FROM_DATABASE=Murata Manufacturing Co.,Ltd.
+
OUI:10A743*
ID_OUI_FROM_DATABASE=SK Mtek Limited
OUI:10A932*
ID_OUI_FROM_DATABASE=Beijing Cyber Cloud Technology Co. ,Ltd.
+OUI:10B26B*
+ ID_OUI_FROM_DATABASE=base Co.,Ltd.
+
OUI:10B7F6*
ID_OUI_FROM_DATABASE=Plastoform Industries Ltd.
@@ -52375,8 +52900,11 @@ OUI:1407E0*
OUI:140C76*
ID_OUI_FROM_DATABASE=FREEBOX SAS
+OUI:140D4F*
+ ID_OUI_FROM_DATABASE=Flextronics International
+
OUI:14109F*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:141330*
ID_OUI_FROM_DATABASE=Anakreon UK LLP
@@ -52396,6 +52924,9 @@ OUI:141BF0*
OUI:1423D7*
ID_OUI_FROM_DATABASE=EUTRONIX CO., LTD.
+OUI:142BD2*
+ ID_OUI_FROM_DATABASE=Armtel Ltd.
+
OUI:142D8B*
ID_OUI_FROM_DATABASE=Incipio Technologies, Inc
@@ -52429,6 +52960,9 @@ OUI:1441E2*
OUI:144319*
ID_OUI_FROM_DATABASE=Creative&Link Technology Limited
+OUI:1446E4*
+ ID_OUI_FROM_DATABASE=AVISTEL
+
OUI:144978*
ID_OUI_FROM_DATABASE=Digital Control Incorporated
@@ -52442,10 +52976,13 @@ OUI:145412*
ID_OUI_FROM_DATABASE=Entis Co., Ltd.
OUI:145A05*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:145BD1*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:146080*
+ ID_OUI_FROM_DATABASE=zte corporation
OUI:146308*
ID_OUI_FROM_DATABASE=JABIL CIRCUIT (SHANGHAI) LTD.
@@ -52478,7 +53015,7 @@ OUI:148A70*
ID_OUI_FROM_DATABASE=ADS GmbH
OUI:148FC6*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:149090*
ID_OUI_FROM_DATABASE=KongTop industrial(shen zhen)CO.,LTD
@@ -52501,6 +53038,9 @@ OUI:14A9E3*
OUI:14ABF0*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+OUI:14B126*
+ ID_OUI_FROM_DATABASE=Industrial Software Co
+
OUI:14B1C8*
ID_OUI_FROM_DATABASE=InfiniWing, Inc.
@@ -52510,6 +53050,9 @@ OUI:14B73D*
OUI:14C21D*
ID_OUI_FROM_DATABASE=Sabtech Industries
+OUI:14CC20*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD
+
OUI:14CF8D*
ID_OUI_FROM_DATABASE=OHSUNG ELECTRONICS CO., LTD.
@@ -52543,6 +53086,9 @@ OUI:14E6E4*
OUI:14EB33*
ID_OUI_FROM_DATABASE=BSMediasoft Co., Ltd.
+OUI:14EDA5*
+ ID_OUI_FROM_DATABASE=Wächter GmbH Sicherheitssysteme
+
OUI:14EE9D*
ID_OUI_FROM_DATABASE=AirNav Systems LLC
@@ -52579,12 +53125,18 @@ OUI:180675*
OUI:180B52*
ID_OUI_FROM_DATABASE=Nanotron Technologies GmbH
+OUI:180C14*
+ ID_OUI_FROM_DATABASE=iSonea Limited
+
OUI:180C77*
ID_OUI_FROM_DATABASE=Westinghouse Electric Company, LLC
OUI:180CAC*
ID_OUI_FROM_DATABASE=CANON INC.
+OUI:18104E*
+ ID_OUI_FROM_DATABASE=CEDINT-UPM
+
OUI:181420*
ID_OUI_FROM_DATABASE=TEB SAS
@@ -52600,11 +53152,17 @@ OUI:181725*
OUI:18193F*
ID_OUI_FROM_DATABASE=Tamtron Oy
+OUI:181BEB*
+ ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc
+
OUI:181EB0*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:182012*
+ ID_OUI_FROM_DATABASE=Aztech Associates Inc.
+
OUI:182032*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:182666*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
@@ -52628,7 +53186,7 @@ OUI:18339D*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
OUI:183451*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:1836FC*
ID_OUI_FROM_DATABASE=Elecsys International Corporation
@@ -52651,6 +53209,9 @@ OUI:183F47*
OUI:18422F*
ID_OUI_FROM_DATABASE=Alcatel Lucent
+OUI:184462*
+ ID_OUI_FROM_DATABASE=Riava Networks, Inc.
+
OUI:184617*
ID_OUI_FROM_DATABASE=Samsung Electronics
@@ -52675,6 +53236,12 @@ OUI:185933*
OUI:185AE8*
ID_OUI_FROM_DATABASE=Zenotech.Co.,Ltd
+OUI:18622C*
+ ID_OUI_FROM_DATABASE=SAGEMCOM SAS
+
+OUI:186472*
+ ID_OUI_FROM_DATABASE=Aruba Networks
+
OUI:1866E3*
ID_OUI_FROM_DATABASE=Veros Systems, Inc.
@@ -52696,6 +53263,9 @@ OUI:187A93*
OUI:187C81*
ID_OUI_FROM_DATABASE=Valeo Vision Systems
+OUI:187ED5*
+ ID_OUI_FROM_DATABASE=shenzhen kaism technology Co. Ltd
+
OUI:1880CE*
ID_OUI_FROM_DATABASE=Barberry Solutions Ltd
@@ -52729,12 +53299,21 @@ OUI:1897FF*
OUI:189A67*
ID_OUI_FROM_DATABASE=CSE-Servelec Limited
+OUI:189C5D*
+ ID_OUI_FROM_DATABASE=Cisco
+
OUI:189EFC*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:18A905*
ID_OUI_FROM_DATABASE=Hewlett-Packard Company
+OUI:18A99B*
+ ID_OUI_FROM_DATABASE=Dell Inc PCBA Test
+
+OUI:18AA45*
+ ID_OUI_FROM_DATABASE=Fon Technology
+
OUI:18ABF5*
ID_OUI_FROM_DATABASE=Ultra Electronics - Electrics
@@ -52744,6 +53323,12 @@ OUI:18AD4D*
OUI:18AEBB*
ID_OUI_FROM_DATABASE=Siemens Convergence Creators GmbH&Co.KG
+OUI:18AF61*
+ ID_OUI_FROM_DATABASE=Apple, Inc
+
+OUI:18AF8F*
+ ID_OUI_FROM_DATABASE=Apple
+
OUI:18AF9F*
ID_OUI_FROM_DATABASE=DIGITRONIC Automationsanlagen GmbH
@@ -52768,6 +53353,9 @@ OUI:18C086*
OUI:18C451*
ID_OUI_FROM_DATABASE=Tucson Embedded Systems
+OUI:18C8E7*
+ ID_OUI_FROM_DATABASE=Shenzhen Hualistone Technology Co.,Ltd
+
OUI:18D071*
ID_OUI_FROM_DATABASE=DASAN SMC, Inc.
@@ -52790,7 +53378,7 @@ OUI:18E2C2*
ID_OUI_FROM_DATABASE=Samsung Electronics
OUI:18E7F4*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:18E80F*
ID_OUI_FROM_DATABASE=Viking Electronics Inc.
@@ -52838,7 +53426,7 @@ OUI:1C129D*
ID_OUI_FROM_DATABASE=IEEE PES PSRC/SUB
OUI:1C1448*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:1C17D3*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
@@ -52873,6 +53461,9 @@ OUI:1C3DE7*
OUI:1C3E84*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:1C4158*
+ ID_OUI_FROM_DATABASE=Gemalto M2M GmbH
+
OUI:1C43EC*
ID_OUI_FROM_DATABASE=JAPAN CIRCUIT CO.,LTD
@@ -52885,6 +53476,9 @@ OUI:1C48F9*
OUI:1C4AF7*
ID_OUI_FROM_DATABASE=AMON INC
+OUI:1C4BB9*
+ ID_OUI_FROM_DATABASE=SMG ENTERPRISE, LLC
+
OUI:1C4BD6*
ID_OUI_FROM_DATABASE=AzureWave
@@ -52912,6 +53506,9 @@ OUI:1C5FFF*
OUI:1C62B8*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:1C63B7*
+ ID_OUI_FROM_DATABASE=OpenProducts 237 AB
+
OUI:1C659D*
ID_OUI_FROM_DATABASE=Liteon Technology Corporation
@@ -52936,6 +53533,12 @@ OUI:1C7508*
OUI:1C76CA*
ID_OUI_FROM_DATABASE=Terasic Technologies Inc.
+OUI:1C7839*
+ ID_OUI_FROM_DATABASE=Shenzhen Tencent Computer System Co., Ltd.
+
+OUI:1C7B21*
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+
OUI:1C7C11*
ID_OUI_FROM_DATABASE=EID
@@ -52954,6 +53557,9 @@ OUI:1C83B0*
OUI:1C8464*
ID_OUI_FROM_DATABASE=FORMOSA WIRELESS COMMUNICATION CORP.
+OUI:1C86AD*
+ ID_OUI_FROM_DATABASE=MCT CO., LTD.
+
OUI:1C8E8E*
ID_OUI_FROM_DATABASE=DB Communication & Systems Co., ltd.
@@ -52975,11 +53581,20 @@ OUI:1C959F*
OUI:1C973D*
ID_OUI_FROM_DATABASE=PRICOM Design
+OUI:1C994C*
+ ID_OUI_FROM_DATABASE=Murata Manufactuaring Co.,Ltd.
+
+OUI:1CA770*
+ ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LT
+
OUI:1CAA07*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
OUI:1CABA7*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
+
+OUI:1CAF05*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:1CAFF7*
ID_OUI_FROM_DATABASE=D-LINK INTERNATIONAL PTE LIMITED
@@ -53005,6 +53620,9 @@ OUI:1CBD0E*
OUI:1CBDB9*
ID_OUI_FROM_DATABASE=D-LINK INTERNATIONAL PTE LIMITED
+OUI:1CC11A*
+ ID_OUI_FROM_DATABASE=Wavetronix
+
OUI:1CC1DE*
ID_OUI_FROM_DATABASE=Hewlett-Packard Company
@@ -53062,6 +53680,9 @@ OUI:2005E8*
OUI:200A5E*
ID_OUI_FROM_DATABASE=Xiangshan Giant Eagle Technology Developing co.,LTD
+OUI:200BC7*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:20107A*
ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd.
@@ -53074,6 +53695,9 @@ OUI:2013E0*
OUI:2016D8*
ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+OUI:20180E*
+ ID_OUI_FROM_DATABASE=Shenzhen Sunchip Technology Co., Ltd
+
OUI:201A06*
ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD.
@@ -53131,6 +53755,9 @@ OUI:204E7F*
OUI:205476*
ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+OUI:205721*
+ ID_OUI_FROM_DATABASE=Salix Technology CO., Ltd.
+
OUI:2059A0*
ID_OUI_FROM_DATABASE=Paragon Technologies Inc.
@@ -53218,6 +53845,9 @@ OUI:20BFDB*
OUI:20C1AF*
ID_OUI_FROM_DATABASE=i Wit Digital Co., Limited
+OUI:20C60D*
+ ID_OUI_FROM_DATABASE=Shanghai annijie Information technology Co.,LTD
+
OUI:20C6EB*
ID_OUI_FROM_DATABASE=Panasonic Corporation AVC Networks Company
@@ -53225,11 +53855,23 @@ OUI:20C8B3*
ID_OUI_FROM_DATABASE=SHENZHEN BUL-TECH CO.,LTD.
OUI:20C9D0*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
+
+OUI:20CD39*
+ ID_OUI_FROM_DATABASE=Texas Instruments, Inc
+
+OUI:20CEC4*
+ ID_OUI_FROM_DATABASE=Peraso Technologies
OUI:20CF30*
ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
+OUI:20D21F*
+ ID_OUI_FROM_DATABASE=Wincal Technology Corp.
+
+OUI:20D390*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:20D5AB*
ID_OUI_FROM_DATABASE=Korea Infocom Co.,Ltd.
@@ -53255,7 +53897,10 @@ OUI:20E52A*
ID_OUI_FROM_DATABASE=NETGEAR INC.,
OUI:20E564*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:20E791*
+ ID_OUI_FROM_DATABASE=Siemens Healthcare Diagnostics, Inc
OUI:20EEC6*
ID_OUI_FROM_DATABASE=Elefirst Science & Tech Co ., ltd
@@ -53344,6 +53989,9 @@ OUI:245FDF*
OUI:246278*
ID_OUI_FROM_DATABASE=sysmocom - systems for mobile communications GmbH
+OUI:2464EF*
+ ID_OUI_FROM_DATABASE=CYG SUNRI CO.,LTD.
+
OUI:246511*
ID_OUI_FROM_DATABASE=AVM GmbH
@@ -53362,6 +54010,9 @@ OUI:24767D*
OUI:247703*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:248000*
+ ID_OUI_FROM_DATABASE=Westcontrol AS
+
OUI:2481AA*
ID_OUI_FROM_DATABASE=KSH International Co., Ltd.
@@ -53374,6 +54025,9 @@ OUI:2486F4*
OUI:248707*
ID_OUI_FROM_DATABASE=SEnergy Corporation
+OUI:2493CA*
+ ID_OUI_FROM_DATABASE=Voxtronic Technology Computer-Systeme GmbH
+
OUI:249442*
ID_OUI_FROM_DATABASE=OPEN ROAD SOLUTIONS , INC.
@@ -53386,11 +54040,14 @@ OUI:24A42C*
OUI:24A43C*
ID_OUI_FROM_DATABASE=Ubiquiti Networks, INC
+OUI:24A495*
+ ID_OUI_FROM_DATABASE=Thales Canada Inc.
+
OUI:24A937*
ID_OUI_FROM_DATABASE=PURE Storage
OUI:24AB81*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:24AF4A*
ID_OUI_FROM_DATABASE=Alcatel-Lucent-IPD
@@ -53428,6 +54085,12 @@ OUI:24BE05*
OUI:24C0B3*
ID_OUI_FROM_DATABASE=RSF
+OUI:24C696*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:24C848*
+ ID_OUI_FROM_DATABASE=mywerk system GmbH
+
OUI:24C86E*
ID_OUI_FROM_DATABASE=Chaney Instrument Co.
@@ -53461,6 +54124,9 @@ OUI:24DBAD*
OUI:24DEC6*
ID_OUI_FROM_DATABASE=Aruba Networks
+OUI:24E271*
+ ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd
+
OUI:24E6BA*
ID_OUI_FROM_DATABASE=JSC Zavod im. Kozitsky
@@ -53473,6 +54139,9 @@ OUI:24EB65*
OUI:24EC99*
ID_OUI_FROM_DATABASE=Askey Computer Corp
+OUI:24ECD6*
+ ID_OUI_FROM_DATABASE=CSG Science & Technology Co.,Ltd.Hefei
+
OUI:24EE3A*
ID_OUI_FROM_DATABASE=Chengdu Yingji Electronic Hi-tech Co Ltd
@@ -53482,6 +54151,9 @@ OUI:24F0FF*
OUI:24F2DD*
ID_OUI_FROM_DATABASE=Radiant Zemax LLC
+OUI:24F5AA*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,LTD
+
OUI:24FD52*
ID_OUI_FROM_DATABASE=Liteon Technology Corporation
@@ -53494,6 +54166,9 @@ OUI:28061E*
OUI:28068D*
ID_OUI_FROM_DATABASE=ITL, LLC
+OUI:280B5C*
+ ID_OUI_FROM_DATABASE=Apple
+
OUI:280CB8*
ID_OUI_FROM_DATABASE=Mikrosay Yazilim ve Elektronik A.S.
@@ -53521,6 +54196,9 @@ OUI:2818FD*
OUI:2826A6*
ID_OUI_FROM_DATABASE=PBR electronics GmbH
+OUI:28285D*
+ ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation
+
OUI:2829D9*
ID_OUI_FROM_DATABASE=GlobalBeiMing technology (Beijing)Co. Ltd
@@ -53534,7 +54212,7 @@ OUI:283410*
ID_OUI_FROM_DATABASE=Enigma Diagnostics Limited
OUI:283737*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:2838CF*
ID_OUI_FROM_DATABASE=Gen2wave
@@ -53551,18 +54229,30 @@ OUI:28401A*
OUI:284121*
ID_OUI_FROM_DATABASE=OptiSense Network, LLC
+OUI:284430*
+ ID_OUI_FROM_DATABASE=GenesisTechnical Systems (UK) Ltd
+
+OUI:2847AA*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
+
OUI:284846*
ID_OUI_FROM_DATABASE=GridCentric Inc.
OUI:284C53*
ID_OUI_FROM_DATABASE=Intune Networks
+OUI:284D92*
+ ID_OUI_FROM_DATABASE=Luminator
+
OUI:284FCE*
ID_OUI_FROM_DATABASE=Liaoning Wontel Science and Technology Development Co.,Ltd.
OUI:285132*
ID_OUI_FROM_DATABASE=Shenzhen Prayfly Technology Co.,Ltd
+OUI:285767*
+ ID_OUI_FROM_DATABASE=Echostar Technologies Corp
+
OUI:285FDB*
ID_OUI_FROM_DATABASE=Shenzhen Huawei Communication Technologies Co., Ltd
@@ -53573,10 +54263,13 @@ OUI:286094*
ID_OUI_FROM_DATABASE=CAPELEC
OUI:286AB8*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:286ABA*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
+
+OUI:286D97*
+ ID_OUI_FROM_DATABASE=SAMJIN Co., Ltd.
OUI:286ED4*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
@@ -53599,6 +54292,9 @@ OUI:28852D*
OUI:288915*
ID_OUI_FROM_DATABASE=CashGuard Sverige AB
+OUI:288A1C*
+ ID_OUI_FROM_DATABASE=Juniper networks
+
OUI:2891D0*
ID_OUI_FROM_DATABASE=Stage Tec Entwicklungsgesellschaft für professionelle Audiotechnik mbH
@@ -53611,6 +54307,9 @@ OUI:2893FE*
OUI:28940F*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
+OUI:2894AF*
+ ID_OUI_FROM_DATABASE=Samhwa Telecom
+
OUI:28987B*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
@@ -53626,6 +54325,12 @@ OUI:28A186*
OUI:28A192*
ID_OUI_FROM_DATABASE=GERP Solution
+OUI:28A1EB*
+ ID_OUI_FROM_DATABASE=ETEK TECHNOLOGY (SHENZHEN) CO.,LTD
+
+OUI:28A241*
+ ID_OUI_FROM_DATABASE=exlar corp
+
OUI:28A574*
ID_OUI_FROM_DATABASE=Miller Electric Mfg. Co.
@@ -53644,12 +54349,18 @@ OUI:28B3AB*
OUI:28BA18*
ID_OUI_FROM_DATABASE=NextNav, LLC
+OUI:28BAB5*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:28BE9B*
ID_OUI_FROM_DATABASE=Technicolor USA Inc.
OUI:28C0DA*
ID_OUI_FROM_DATABASE=Juniper Networks
+OUI:28C671*
+ ID_OUI_FROM_DATABASE=Yota Devices OY
+
OUI:28C68E*
ID_OUI_FROM_DATABASE=NETGEAR INC.,
@@ -53678,7 +54389,7 @@ OUI:28CD9C*
ID_OUI_FROM_DATABASE=Shenzhen Dynamax Software Development Co.,Ltd.
OUI:28CFDA*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:28CFE9*
ID_OUI_FROM_DATABASE=Apple
@@ -53692,6 +54403,9 @@ OUI:28D244*
OUI:28D576*
ID_OUI_FROM_DATABASE=Premier Wireless, Inc.
+OUI:28D93E*
+ ID_OUI_FROM_DATABASE=Telecor Inc.
+
OUI:28D997*
ID_OUI_FROM_DATABASE=Yuduan Mobile Co., Ltd.
@@ -53699,6 +54413,9 @@ OUI:28DB81*
ID_OUI_FROM_DATABASE=Shanghai Guao Electronic Technology Co., Ltd
OUI:28E02C*
+ ID_OUI_FROM_DATABASE=Apple
+
+OUI:28E14C*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:28E297*
@@ -53711,7 +54428,7 @@ OUI:28E794*
ID_OUI_FROM_DATABASE=Microtime Computer Inc.
OUI:28E7CF*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:28ED58*
ID_OUI_FROM_DATABASE=JAG Jakob AG
@@ -53731,6 +54448,9 @@ OUI:28F606*
OUI:28FBD3*
ID_OUI_FROM_DATABASE=Ragentek Technology Group
+OUI:28FC51*
+ ID_OUI_FROM_DATABASE=The Electric Controller and Manufacturing Co., LLC
+
OUI:2C002C*
ID_OUI_FROM_DATABASE=UNOWHY
@@ -53746,6 +54466,9 @@ OUI:2C0623*
OUI:2C10C1*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
+OUI:2C18AE*
+ ID_OUI_FROM_DATABASE=Trend Electronics Co., Ltd.
+
OUI:2C1984*
ID_OUI_FROM_DATABASE=IDN Telecom, Inc.
@@ -53785,6 +54508,9 @@ OUI:2C36A0*
OUI:2C36F8*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
+OUI:2C3731*
+ ID_OUI_FROM_DATABASE=ShenZhen Yifang Digital Technology Co.,LTD
+
OUI:2C3996*
ID_OUI_FROM_DATABASE=SAGEMCOM
@@ -53815,12 +54541,21 @@ OUI:2C44FD*
OUI:2C542D*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
+OUI:2C553C*
+ ID_OUI_FROM_DATABASE=Gainspeed, Inc.
+
OUI:2C59E5*
ID_OUI_FROM_DATABASE=Hewlett Packard
OUI:2C5AA3*
ID_OUI_FROM_DATABASE=PROMATE ELECTRONIC CO.LTD
+OUI:2C5D93*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:2C5FF3*
+ ID_OUI_FROM_DATABASE=Pertronic Industries
+
OUI:2C625A*
ID_OUI_FROM_DATABASE=Finest Security Systems Co., Ltd
@@ -53836,6 +54571,9 @@ OUI:2C69BA*
OUI:2C6BF5*
ID_OUI_FROM_DATABASE=Juniper networks
+OUI:2C7155*
+ ID_OUI_FROM_DATABASE=HiveMotion
+
OUI:2C72C3*
ID_OUI_FROM_DATABASE=Soundmatters
@@ -53848,6 +54586,9 @@ OUI:2C768A*
OUI:2C7B5A*
ID_OUI_FROM_DATABASE=Milper Ltd
+OUI:2C7B84*
+ ID_OUI_FROM_DATABASE=OOO Petr Telegin
+
OUI:2C7ECF*
ID_OUI_FROM_DATABASE=Onzo Ltd
@@ -53873,7 +54614,7 @@ OUI:2C9717*
ID_OUI_FROM_DATABASE=I.C.Y. B.V.
OUI:2C9E5F*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:2C9EFC*
ID_OUI_FROM_DATABASE=CANON INC.
@@ -53911,12 +54652,18 @@ OUI:2CBE97*
OUI:2CC260*
ID_OUI_FROM_DATABASE=Ravello Systems
+OUI:2CCC15*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
+
OUI:2CCD27*
ID_OUI_FROM_DATABASE=Precor Inc
OUI:2CCD43*
ID_OUI_FROM_DATABASE=Summit Technology Group
+OUI:2CCD69*
+ ID_OUI_FROM_DATABASE=Aqavi.com
+
OUI:2CD05A*
ID_OUI_FROM_DATABASE=Liteon Technology Corporation
@@ -53938,6 +54685,9 @@ OUI:2CE2A8*
OUI:2CE412*
ID_OUI_FROM_DATABASE=SAGEMCOM SAS
+OUI:2CE6CC*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
OUI:2CE871*
ID_OUI_FROM_DATABASE=Alert Metalguard ApS
@@ -53962,6 +54712,9 @@ OUI:300B9C*
OUI:300ED5*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind.Co.Ltd
+OUI:3010E4*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:30142D*
ID_OUI_FROM_DATABASE=Piciorgros GmbH
@@ -53980,6 +54733,9 @@ OUI:3017C8*
OUI:3018CF*
ID_OUI_FROM_DATABASE=DEOS control systems GmbH
+OUI:301966*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:301A28*
ID_OUI_FROM_DATABASE=Mako Networks Ltd
@@ -54010,6 +54766,9 @@ OUI:303955*
OUI:3039F2*
ID_OUI_FROM_DATABASE=ADB Broadband Italia
+OUI:303A64*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:303D08*
ID_OUI_FROM_DATABASE=GLINTT TES S.A.
@@ -54034,6 +54793,9 @@ OUI:304C7E*
OUI:304EC3*
ID_OUI_FROM_DATABASE=Tianjin Techua Technology Co., Ltd.
+OUI:3051F8*
+ ID_OUI_FROM_DATABASE=BYK-Gardner GmbH
+
OUI:30525A*
ID_OUI_FROM_DATABASE=NST Co., LTD
@@ -54046,6 +54808,12 @@ OUI:3057AC*
OUI:305D38*
ID_OUI_FROM_DATABASE=Beissbarth
+OUI:306023*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:306112*
+ ID_OUI_FROM_DATABASE=PAV GmbH
+
OUI:306118*
ID_OUI_FROM_DATABASE=Paradom Inc.
@@ -54067,6 +54835,9 @@ OUI:306E5C*
OUI:3071B2*
ID_OUI_FROM_DATABASE=Hangzhou Prevail Optoelectronic Equipment Co.,LTD.
+OUI:30766F*
+ ID_OUI_FROM_DATABASE=LG Electronics
+
OUI:30786B*
ID_OUI_FROM_DATABASE=TIANJIN Golden Pentagon Electronics Co., Ltd.
@@ -54097,6 +54868,9 @@ OUI:3090AB*
OUI:3092F6*
ID_OUI_FROM_DATABASE=SHANGHAI SUNMON COMMUNICATION TECHNOGY CO.,LTD
+OUI:309BAD*
+ ID_OUI_FROM_DATABASE=BBK Electronics Corp., Ltd.,
+
OUI:30AABD*
ID_OUI_FROM_DATABASE=Shanghai Reallytek Information Technology Co.,Ltd
@@ -54124,6 +54898,9 @@ OUI:30D357*
OUI:30D46A*
ID_OUI_FROM_DATABASE=Autosales Incorporated
+OUI:30D6C9*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:30DE86*
ID_OUI_FROM_DATABASE=Cedac Software S.r.l.
@@ -54163,8 +54940,11 @@ OUI:3407FB*
OUI:340804*
ID_OUI_FROM_DATABASE=D-Link Corporation
+OUI:3413E8*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:34159E*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:341A4C*
ID_OUI_FROM_DATABASE=SHENZHEN WEIBU ELECTRONICS CO.,LTD.
@@ -54175,6 +54955,9 @@ OUI:341B22*
OUI:342109*
ID_OUI_FROM_DATABASE=Jensen Scandinavia AS
+OUI:342387*
+ ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+
OUI:3423BA*
ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co.,LTD.
@@ -54187,6 +54970,9 @@ OUI:3429EA*
OUI:342F6E*
ID_OUI_FROM_DATABASE=Anywire corporation
+OUI:343111*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:3440B5*
ID_OUI_FROM_DATABASE=IBM
@@ -54196,15 +54982,24 @@ OUI:344B3D*
OUI:344B50*
ID_OUI_FROM_DATABASE=ZTE Corporation
+OUI:344F3F*
+ ID_OUI_FROM_DATABASE=IO-Power Technology Co., Ltd.
+
OUI:344F69*
ID_OUI_FROM_DATABASE=EKINOPS SAS
OUI:3451C9*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:345B11*
ID_OUI_FROM_DATABASE=EVI HEAT AB
+OUI:345C40*
+ ID_OUI_FROM_DATABASE=Cargt Holdings LLC
+
+OUI:346178*
+ ID_OUI_FROM_DATABASE=The Boeing Company
+
OUI:34684A*
ID_OUI_FROM_DATABASE=Teraworks Co., Ltd.
@@ -54244,6 +55039,12 @@ OUI:348446*
OUI:34862A*
ID_OUI_FROM_DATABASE=Heinz Lackmann GmbH & Co KG
+OUI:34885D*
+ ID_OUI_FROM_DATABASE=Logitech Far East
+
+OUI:348AAE*
+ ID_OUI_FROM_DATABASE=SAGEMCOM SAS
+
OUI:3495DB*
ID_OUI_FROM_DATABASE=Logitec Corporation
@@ -54265,9 +55066,15 @@ OUI:349D90*
OUI:34A183*
ID_OUI_FROM_DATABASE=AWare, Inc
+OUI:34A3BF*
+ ID_OUI_FROM_DATABASE=Terewave. Inc.
+
OUI:34A55D*
ID_OUI_FROM_DATABASE=TECHNOSOFT INTERNATIONAL SRL
+OUI:34A5E1*
+ ID_OUI_FROM_DATABASE=Sensorist ApS
+
OUI:34A68C*
ID_OUI_FROM_DATABASE=Shine Profit Development Limited
@@ -54283,6 +55090,9 @@ OUI:34A843*
OUI:34A84E*
ID_OUI_FROM_DATABASE=Cisco
+OUI:34AA8B*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:34AA99*
ID_OUI_FROM_DATABASE=Alcatel-Lucent
@@ -54322,6 +55132,9 @@ OUI:34BDF9*
OUI:34BDFA*
ID_OUI_FROM_DATABASE=Cisco SPVTG
+OUI:34BE00*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:34BF90*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
@@ -54361,6 +55174,9 @@ OUI:34D2C4*
OUI:34D7B4*
ID_OUI_FROM_DATABASE=Tributary Systems, Inc.
+OUI:34DBFD*
+ ID_OUI_FROM_DATABASE=Cisco
+
OUI:34DF2A*
ID_OUI_FROM_DATABASE=Fujikon Industrial Co.,Limited
@@ -54403,6 +55219,9 @@ OUI:380A0A*
OUI:380A94*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:380B40*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:380DD4*
ID_OUI_FROM_DATABASE=Primax Electronics LTD.
@@ -54445,6 +55264,9 @@ OUI:383F10*
OUI:384233*
ID_OUI_FROM_DATABASE=Wildeboer Bauteile GmbH
+OUI:3842A6*
+ ID_OUI_FROM_DATABASE=Ingenieurbuero Stahlkopf
+
OUI:384369*
ID_OUI_FROM_DATABASE=Patrol Products Consortium LLC
@@ -54466,9 +55288,15 @@ OUI:38521A*
OUI:38580C*
ID_OUI_FROM_DATABASE=Panaccess Systems GmbH
+OUI:3859F8*
+ ID_OUI_FROM_DATABASE=MindMade sp. z o.o.
+
OUI:3859F9*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:385AA8*
+ ID_OUI_FROM_DATABASE=Beijing Zhongdun Security Technology Development Co.
+
OUI:385FC3*
ID_OUI_FROM_DATABASE=Yu Jeong System, Co.Ltd
@@ -54485,7 +55313,7 @@ OUI:386793*
ID_OUI_FROM_DATABASE=Asia Optical Co., Inc.
OUI:386BBB*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:386E21*
ID_OUI_FROM_DATABASE=Wasion Group Ltd.
@@ -54496,6 +55324,9 @@ OUI:3872C0*
OUI:388345*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO., LTD.
+OUI:3889DC*
+ ID_OUI_FROM_DATABASE=Opticon Sensors Europe B.V.
+
OUI:388AB7*
ID_OUI_FROM_DATABASE=ITC Networks
@@ -54511,6 +55342,9 @@ OUI:389592*
OUI:389F83*
ID_OUI_FROM_DATABASE=OTN Systems N.V.
+OUI:38A53C*
+ ID_OUI_FROM_DATABASE=Veenstra Instruments
+
OUI:38A5B6*
ID_OUI_FROM_DATABASE=SHENZHEN MEGMEET ELECTRICAL CO.,LTD
@@ -54532,12 +55366,18 @@ OUI:38B12D*
OUI:38B5BD*
ID_OUI_FROM_DATABASE=E.G.O. Elektro-Ger
+OUI:38B74D*
+ ID_OUI_FROM_DATABASE=Fijowave Limited
+
OUI:38BB23*
ID_OUI_FROM_DATABASE=OzVision America LLC
OUI:38BC1A*
ID_OUI_FROM_DATABASE=Meizu technology co.,ltd
+OUI:38BF2F*
+ ID_OUI_FROM_DATABASE=Espec Corp.
+
OUI:38BF33*
ID_OUI_FROM_DATABASE=NEC CASIO Mobile Communications
@@ -54550,9 +55390,15 @@ OUI:38C7BA*
OUI:38C85C*
ID_OUI_FROM_DATABASE=Cisco SPVTG
+OUI:38CA97*
+ ID_OUI_FROM_DATABASE=Contour Design LLC
+
OUI:38D135*
ID_OUI_FROM_DATABASE=EasyIO Corporation Sdn. Bhd.
+OUI:38DBBB*
+ ID_OUI_FROM_DATABASE=Sunbow Telecom Co., Ltd.
+
OUI:38DE60*
ID_OUI_FROM_DATABASE=Mohlenhoff GmbH
@@ -54574,6 +55420,9 @@ OUI:38E98C*
OUI:38EAA7*
ID_OUI_FROM_DATABASE=Hewlett Packard
+OUI:38EC11*
+ ID_OUI_FROM_DATABASE=Novatek Microelectronics Corp.
+
OUI:38ECE4*
ID_OUI_FROM_DATABASE=Samsung Electronics
@@ -54599,7 +55448,7 @@ OUI:3C05AB*
ID_OUI_FROM_DATABASE=Product Creation Studio
OUI:3C0754*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:3C0771*
ID_OUI_FROM_DATABASE=Sony Corporation
@@ -54613,15 +55462,27 @@ OUI:3C096D*
OUI:3C0FC1*
ID_OUI_FROM_DATABASE=KBC Networks
+OUI:3C1040*
+ ID_OUI_FROM_DATABASE=daesung network
+
OUI:3C106F*
ID_OUI_FROM_DATABASE=ALBAHITH TECHNOLOGIES
+OUI:3C15EA*
+ ID_OUI_FROM_DATABASE=TESCOM CO., LTD.
+
+OUI:3C18A0*
+ ID_OUI_FROM_DATABASE=Luxshare Precision Industry Co.,Ltd.
+
OUI:3C1915*
ID_OUI_FROM_DATABASE=GFI Chrono Time
OUI:3C197D*
ID_OUI_FROM_DATABASE=Ericsson AB
+OUI:3C1A57*
+ ID_OUI_FROM_DATABASE=Cardiopulmonary Corp
+
OUI:3C1A79*
ID_OUI_FROM_DATABASE=Huayuan Technology CO.,LTD
@@ -54640,6 +55501,9 @@ OUI:3C2DB7*
OUI:3C2F3A*
ID_OUI_FROM_DATABASE=SFORZATO Corp.
+OUI:3C300C*
+ ID_OUI_FROM_DATABASE=Dewar Electronics Pty Ltd
+
OUI:3C363D*
ID_OUI_FROM_DATABASE=Nokia Corporation
@@ -54652,8 +55516,11 @@ OUI:3C39C3*
OUI:3C3A73*
ID_OUI_FROM_DATABASE=Avaya, Inc
+OUI:3C404F*
+ ID_OUI_FROM_DATABASE=Guangdong Pisen Electronics Co. Ltd.
+
OUI:3C438E*
- ID_OUI_FROM_DATABASE=Motorola Mobility, LLC.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:3C4A92*
ID_OUI_FROM_DATABASE=Hewlett-Packard Company
@@ -54676,6 +55543,9 @@ OUI:3C5A37*
OUI:3C5F01*
ID_OUI_FROM_DATABASE=Synerchip Co., Ltd.
+OUI:3C6104*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
OUI:3C6200*
ID_OUI_FROM_DATABASE=Samsung electronics CO., LTD
@@ -54688,6 +55558,9 @@ OUI:3C672C*
OUI:3C6A7D*
ID_OUI_FROM_DATABASE=Niigata Power Systems Co., Ltd.
+OUI:3C6E63*
+ ID_OUI_FROM_DATABASE=Mitron OY
+
OUI:3C6F45*
ID_OUI_FROM_DATABASE=Fiberpro Inc.
@@ -54701,7 +55574,10 @@ OUI:3C7437*
ID_OUI_FROM_DATABASE=RIM
OUI:3C754A*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:3C77E6*
+ ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
OUI:3C7DB1*
ID_OUI_FROM_DATABASE=Texas Instruments
@@ -54784,11 +55660,14 @@ OUI:3CC243*
OUI:3CC99E*
ID_OUI_FROM_DATABASE=Huiyang Technology Co., Ltd
+OUI:3CCA87*
+ ID_OUI_FROM_DATABASE=Iders Incorporated
+
OUI:3CCE73*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
OUI:3CD0F8*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:3CD16E*
ID_OUI_FROM_DATABASE=Telepower Communication Co., Ltd
@@ -54829,6 +55708,9 @@ OUI:3CF52C*
OUI:3CF72A*
ID_OUI_FROM_DATABASE=Nokia Corporation
+OUI:3CF748*
+ ID_OUI_FROM_DATABASE=Shenzhen Linsn Technology Development Co.,Ltd
+
OUI:3CFB96*
ID_OUI_FROM_DATABASE=Emcraft Systems LLC
@@ -54887,7 +55769,7 @@ OUI:402CF4*
ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd.
OUI:403004*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:40336C*
ID_OUI_FROM_DATABASE=Godrej & Boyce Mfg. co. ltd
@@ -54896,7 +55778,7 @@ OUI:4037AD*
ID_OUI_FROM_DATABASE=Macro Image Technology, Inc.
OUI:403CFC*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:404022*
ID_OUI_FROM_DATABASE=ZIV
@@ -54953,17 +55835,26 @@ OUI:406AAB*
ID_OUI_FROM_DATABASE=RIM
OUI:406C8F*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:406F2A*
ID_OUI_FROM_DATABASE=Research In Motion
+OUI:407009*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
OUI:40704A*
ID_OUI_FROM_DATABASE=Power Idea Technology Limited
OUI:407074*
ID_OUI_FROM_DATABASE=Life Technology (China) Co., Ltd
+OUI:407496*
+ ID_OUI_FROM_DATABASE=aFUN TECHNOLOGY INC.
+
+OUI:407A80*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
+
OUI:407B1B*
ID_OUI_FROM_DATABASE=Mettle Networks Inc.
@@ -55007,7 +55898,7 @@ OUI:40A6A4*
ID_OUI_FROM_DATABASE=PassivSystems Ltd
OUI:40A6D9*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:40AC8D*
ID_OUI_FROM_DATABASE=Data Management, Inc.
@@ -55028,7 +55919,7 @@ OUI:40B4F0*
ID_OUI_FROM_DATABASE=Juniper Networks
OUI:40B7F3*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:40BA61*
ID_OUI_FROM_DATABASE=Arima Communications Corp.
@@ -55061,7 +55952,7 @@ OUI:40CD3A*
ID_OUI_FROM_DATABASE=Z3 Technology
OUI:40D32D*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:40D40E*
ID_OUI_FROM_DATABASE=Biodata Ltd
@@ -55100,7 +55991,7 @@ OUI:40F52E*
ID_OUI_FROM_DATABASE=Leica Microsystems (Schweiz) AG
OUI:40FC89*
- ID_OUI_FROM_DATABASE=Motorola Mobility, LLC.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:4403A7*
ID_OUI_FROM_DATABASE=Cisco
@@ -55127,11 +56018,17 @@ OUI:4425BB*
ID_OUI_FROM_DATABASE=Bamboo Entertainment Corporation
OUI:442A60*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
+
+OUI:442AFF*
+ ID_OUI_FROM_DATABASE=E3 Technology, Inc.
OUI:442B03*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
+OUI:443192*
+ ID_OUI_FROM_DATABASE=Hewlett Packard
+
OUI:44322A*
ID_OUI_FROM_DATABASE=Avaya, Inc
@@ -55159,6 +56056,9 @@ OUI:443839*
OUI:4439C4*
ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co.,Ltd
+OUI:443C9C*
+ ID_OUI_FROM_DATABASE=Pintsch Tiefenbach GmbH
+
OUI:443D21*
ID_OUI_FROM_DATABASE=Nuvolt
@@ -55169,7 +56069,7 @@ OUI:444A65*
ID_OUI_FROM_DATABASE=Silverflare Ltd.
OUI:444C0C*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:444E1A*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
@@ -55207,6 +56107,9 @@ OUI:446132*
OUI:44619C*
ID_OUI_FROM_DATABASE=FONsystem co. ltd.
+OUI:446755*
+ ID_OUI_FROM_DATABASE=Orbit Irrigation
+
OUI:4468AB*
ID_OUI_FROM_DATABASE=JUIN COMPANY, LIMITED
@@ -55216,6 +56119,12 @@ OUI:446C24*
OUI:446D57*
ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+OUI:44700B*
+ ID_OUI_FROM_DATABASE=IFFU
+
+OUI:447BC4*
+ ID_OUI_FROM_DATABASE=DualShine Technology(SZ)Co.,Ltd
+
OUI:447C7F*
ID_OUI_FROM_DATABASE=Innolight Technology Corporation
@@ -55234,6 +56143,9 @@ OUI:448500*
OUI:4487FC*
ID_OUI_FROM_DATABASE=ELITEGROUP COMPUTER SYSTEM CO., LTD.
+OUI:448A5B*
+ ID_OUI_FROM_DATABASE=Micro-Star INT'L CO., LTD.
+
OUI:448C52*
ID_OUI_FROM_DATABASE=KTIS CO., Ltd
@@ -55310,7 +56222,7 @@ OUI:44D832*
ID_OUI_FROM_DATABASE=Azurewave Technologies, Inc.
OUI:44D884*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:44DC91*
ID_OUI_FROM_DATABASE=PLANEX COMMUNICATIONS INC.
@@ -55333,6 +56245,9 @@ OUI:44E8A5*
OUI:44ED57*
ID_OUI_FROM_DATABASE=Longicorn, inc.
+OUI:44EE30*
+ ID_OUI_FROM_DATABASE=Budelmann Elektronik GmbH
+
OUI:44F459*
ID_OUI_FROM_DATABASE=Samsung Electronics
@@ -55381,6 +56296,9 @@ OUI:4844F7*
OUI:4846F1*
ID_OUI_FROM_DATABASE=Uros Oy
+OUI:4846FB*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:485261*
ID_OUI_FROM_DATABASE=SOREEL
@@ -55394,7 +56312,7 @@ OUI:485D60*
ID_OUI_FROM_DATABASE=Azurewave Technologies, Inc.
OUI:4860BC*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:4861A3*
ID_OUI_FROM_DATABASE=Concern "Axion" JSC
@@ -55402,6 +56320,9 @@ OUI:4861A3*
OUI:486B91*
ID_OUI_FROM_DATABASE=Fleetwood Group Inc.
+OUI:486E73*
+ ID_OUI_FROM_DATABASE=Pica8, Inc.
+
OUI:486FD2*
ID_OUI_FROM_DATABASE=StorSimple Inc
@@ -55426,6 +56347,9 @@ OUI:489D24*
OUI:48A22D*
ID_OUI_FROM_DATABASE=Shenzhen Huaxuchang Telecom Technology Co.,Ltd
+OUI:48A2B7*
+ ID_OUI_FROM_DATABASE=Kodofon JSC
+
OUI:48A6D2*
ID_OUI_FROM_DATABASE=GJsun Optical Science and Tech Co.,Ltd.
@@ -55456,6 +56380,9 @@ OUI:48C8B6*
OUI:48CB6E*
ID_OUI_FROM_DATABASE=Cello Electronics (UK) Ltd
+OUI:48D224*
+ ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+
OUI:48D54C*
ID_OUI_FROM_DATABASE=Jeda Networks
@@ -55534,6 +56461,9 @@ OUI:4C0FC7*
OUI:4C1480*
ID_OUI_FROM_DATABASE=NOREGON SYSTEMS, INC
+OUI:4C14A3*
+ ID_OUI_FROM_DATABASE=TCL Technoly Electronics (Huizhou) Co., Ltd.
+
OUI:4C17EB*
ID_OUI_FROM_DATABASE=SAGEMCOM
@@ -55546,6 +56476,9 @@ OUI:4C1A95*
OUI:4C1FCC*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:4C21D0*
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+
OUI:4C2258*
ID_OUI_FROM_DATABASE=cozybit, Inc.
@@ -55573,6 +56506,9 @@ OUI:4C3910*
OUI:4C3B74*
ID_OUI_FROM_DATABASE=VOGTEC(H.K.) Co., Ltd
+OUI:4C3C16*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:4C4B68*
ID_OUI_FROM_DATABASE=Mobile Device, Inc.
@@ -55597,6 +56533,9 @@ OUI:4C55CC*
OUI:4C5DCD*
ID_OUI_FROM_DATABASE=Oy Finnish Electric Vehicle Technologies Ltd
+OUI:4C5E0C*
+ ID_OUI_FROM_DATABASE=Routerboard.com
+
OUI:4C5FD2*
ID_OUI_FROM_DATABASE=Alcatel-Lucent
@@ -55682,11 +56621,14 @@ OUI:4CB16C*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:4CB199*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:4CB4EA*
ID_OUI_FROM_DATABASE=HRD (S) PTE., LTD.
+OUI:4CB81C*
+ ID_OUI_FROM_DATABASE=SAM Electronics GmbH
+
OUI:4CB9C8*
ID_OUI_FROM_DATABASE=CONET CO., LTD.
@@ -55708,12 +56650,18 @@ OUI:4CC94F*
OUI:4CCA53*
ID_OUI_FROM_DATABASE=Skyera, Inc.
+OUI:4CCBF5*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:4CCC34*
ID_OUI_FROM_DATABASE=Motorola Solutions Inc.
OUI:4CD637*
ID_OUI_FROM_DATABASE=Qsono Electronics Co., Ltd
+OUI:4CDF3D*
+ ID_OUI_FROM_DATABASE=TEAM ENGINEERS ADVANCE TECHNOLOGIES INDIA PVT LTD
+
OUI:4CE676*
ID_OUI_FROM_DATABASE=Buffalo Inc.
@@ -55723,6 +56671,9 @@ OUI:4CEB42*
OUI:4CEDDE*
ID_OUI_FROM_DATABASE=Askey Computer Corp
+OUI:4CF02E*
+ ID_OUI_FROM_DATABASE=Vifa Denmark A/S
+
OUI:4CF737*
ID_OUI_FROM_DATABASE=SamJi Electronics Co., Ltd
@@ -55747,6 +56698,12 @@ OUI:500E6D*
OUI:5011EB*
ID_OUI_FROM_DATABASE=SilverNet Ltd
+OUI:5017FF*
+ ID_OUI_FROM_DATABASE=Cisco
+
+OUI:50206B*
+ ID_OUI_FROM_DATABASE=Emerson Climate Technologies Transportation Solutions
+
OUI:502267*
ID_OUI_FROM_DATABASE=PixeLINK
@@ -55756,6 +56713,9 @@ OUI:50252B*
OUI:502690*
ID_OUI_FROM_DATABASE=Fujitsu Limited
+OUI:5027C7*
+ ID_OUI_FROM_DATABASE=TECHNART Co.,Ltd
+
OUI:502A7E*
ID_OUI_FROM_DATABASE=Smart electronic GmbH
@@ -55771,6 +56731,9 @@ OUI:502DA2*
OUI:502DF4*
ID_OUI_FROM_DATABASE=Phytec Messtechnik GmbH
+OUI:502E5C*
+ ID_OUI_FROM_DATABASE=HTC Corporation
+
OUI:502ECE*
ID_OUI_FROM_DATABASE=Asahi Electronics Co.,Ltd
@@ -55780,6 +56743,9 @@ OUI:503275*
OUI:503955*
ID_OUI_FROM_DATABASE=Cisco SPVTG
+OUI:503CC4*
+ ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd.
+
OUI:503DE5*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
@@ -55831,6 +56797,9 @@ OUI:5070E5*
OUI:50724D*
ID_OUI_FROM_DATABASE=BEG Brueck Electronic GmbH
+OUI:507691*
+ ID_OUI_FROM_DATABASE=Tekpea, Inc.
+
OUI:5076A6*
ID_OUI_FROM_DATABASE=Ecil Informatica Ind. Com. Ltda
@@ -55894,15 +56863,27 @@ OUI:50AF73*
OUI:50B7C3*
ID_OUI_FROM_DATABASE=Samsung Electronics CO., LTD
+OUI:50B888*
+ ID_OUI_FROM_DATABASE=wi2be Tecnologia S/A
+
OUI:50B8A2*
ID_OUI_FROM_DATABASE=ImTech Technologies LLC,
+OUI:50C006*
+ ID_OUI_FROM_DATABASE=Carmanah Signs
+
+OUI:50C271*
+ ID_OUI_FROM_DATABASE=SECURETECH INC
+
OUI:50C58D*
ID_OUI_FROM_DATABASE=Juniper Networks
OUI:50C971*
ID_OUI_FROM_DATABASE=GN Netcom A/S
+OUI:50C9A0*
+ ID_OUI_FROM_DATABASE=SKIPPER Electronics AS
+
OUI:50CCF8*
ID_OUI_FROM_DATABASE=Samsung Electro Mechanics
@@ -55918,15 +56899,21 @@ OUI:50D274*
OUI:50D6D7*
ID_OUI_FROM_DATABASE=Takahata Precision
+OUI:50E0C7*
+ ID_OUI_FROM_DATABASE=TurControlSystme AG
+
OUI:50E549*
ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
OUI:50EAD6*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:50EB1A*
ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+OUI:50ED78*
+ ID_OUI_FROM_DATABASE=Changzhou Yongse Infotech Co.,Ltd
+
OUI:50ED94*
ID_OUI_FROM_DATABASE=Egatel SL
@@ -55945,6 +56932,9 @@ OUI:50FAAB*
OUI:50FC30*
ID_OUI_FROM_DATABASE=Treehouse Labs
+OUI:50FC9F*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:5403F5*
ID_OUI_FROM_DATABASE=EBN Technology Corp.
@@ -55954,6 +56944,9 @@ OUI:540496*
OUI:5404A6*
ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
+OUI:540536*
+ ID_OUI_FROM_DATABASE=Vivago Oy
+
OUI:54055F*
ID_OUI_FROM_DATABASE=Alcatel Lucent
@@ -55963,6 +56956,9 @@ OUI:54112F*
OUI:54115F*
ID_OUI_FROM_DATABASE=Atamo Pty Ltd
+OUI:541B5D*
+ ID_OUI_FROM_DATABASE=Techno-Innov
+
OUI:541DFB*
ID_OUI_FROM_DATABASE=Freestyle Energy Ltd
@@ -55975,6 +56971,9 @@ OUI:542018*
OUI:542160*
ID_OUI_FROM_DATABASE=Resolution Products
+OUI:5422F8*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:542696*
ID_OUI_FROM_DATABASE=Apple
@@ -55984,6 +56983,9 @@ OUI:542A9C*
OUI:542CEA*
ID_OUI_FROM_DATABASE=PROTECTRON
+OUI:542F89*
+ ID_OUI_FROM_DATABASE=Euclid Laboratories, Inc.
+
OUI:543131*
ID_OUI_FROM_DATABASE=Raster Vision Ltd
@@ -55999,6 +57001,9 @@ OUI:543D37*
OUI:544249*
ID_OUI_FROM_DATABASE=Sony Corporation
+OUI:544408*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
+
OUI:54466B*
ID_OUI_FROM_DATABASE=Shenzhen CZTIC Electronic Technology Co., Ltd
@@ -56059,6 +57064,9 @@ OUI:548998*
OUI:5492BE*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:549359*
+ ID_OUI_FROM_DATABASE=SHENZHEN TWOWING TECHNOLOGIES CO.,LTD.
+
OUI:549478*
ID_OUI_FROM_DATABASE=Silvershore Technology Partners
@@ -56077,6 +57085,9 @@ OUI:54A04F*
OUI:54A51B*
ID_OUI_FROM_DATABASE=Shenzhen Huawei Communication Technologies Co., Ltd
+OUI:54A54B*
+ ID_OUI_FROM_DATABASE=NSC Communications Siberia Ltd
+
OUI:54A619*
ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd
@@ -56086,6 +57097,9 @@ OUI:54A9D4*
OUI:54B620*
ID_OUI_FROM_DATABASE=SUHDOL E&C Co.Ltd.
+OUI:54BEF7*
+ ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+
OUI:54CDA7*
ID_OUI_FROM_DATABASE=Fujian Shenzhou Electronic Co.,Ltd
@@ -56104,18 +57118,30 @@ OUI:54DF63*
OUI:54E032*
ID_OUI_FROM_DATABASE=Juniper Networks
+OUI:54E3B0*
+ ID_OUI_FROM_DATABASE=JVL Industri Elektronik
+
+OUI:54E43A*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:54E63F*
ID_OUI_FROM_DATABASE=ShenZhen LingKeWeiEr Technology Co., Ltd.
OUI:54E6FC*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO., LTD.
+OUI:54EAA8*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:54F5B6*
ID_OUI_FROM_DATABASE=ORIENTAL PACIFIC INTERNATIONAL LIMITED
OUI:54F666*
ID_OUI_FROM_DATABASE=Berthold Technologies GmbH and Co.KG
+OUI:54FB58*
+ ID_OUI_FROM_DATABASE=WISEWARE, Lda
+
OUI:54FDBF*
ID_OUI_FROM_DATABASE=Scheidt & Bachmann GmbH
@@ -56144,7 +57170,7 @@ OUI:581D91*
ID_OUI_FROM_DATABASE=Advanced Mobile Telecom co.,ltd.
OUI:581FAA*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:581FEF*
ID_OUI_FROM_DATABASE=Tuttnaer LTD
@@ -56167,6 +57193,9 @@ OUI:583CC6*
OUI:5842E4*
ID_OUI_FROM_DATABASE=Sigma International General Medical Apparatus, LLC.
+OUI:58468F*
+ ID_OUI_FROM_DATABASE=Koncar Electronics and Informatics
+
OUI:5846E1*
ID_OUI_FROM_DATABASE=Baxter Healthcare
@@ -56189,14 +57218,17 @@ OUI:5850E6*
ID_OUI_FROM_DATABASE=Best Buy Corporation
OUI:5855CA*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:5856E8*
- ID_OUI_FROM_DATABASE=Motorola Mobility Inc
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:58570D*
ID_OUI_FROM_DATABASE=Danfoss Solar Inverters
+OUI:58639A*
+ ID_OUI_FROM_DATABASE=TPL SYSTEMES
+
OUI:5865E6*
ID_OUI_FROM_DATABASE=INFOMARK CO., LTD.
@@ -56269,15 +57301,21 @@ OUI:589835*
OUI:58986F*
ID_OUI_FROM_DATABASE=Revolution Display
+OUI:58A2B5*
+ ID_OUI_FROM_DATABASE=LG Electronics
+
OUI:58A76F*
ID_OUI_FROM_DATABASE=iD corporation
OUI:58B035*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:58B0D4*
ID_OUI_FROM_DATABASE=ZuniData Systems Inc.
+OUI:58B961*
+ ID_OUI_FROM_DATABASE=SOLEM Electronique
+
OUI:58B9E1*
ID_OUI_FROM_DATABASE=Crystalfontz America, Inc.
@@ -56287,6 +57325,9 @@ OUI:58BC27*
OUI:58BDA3*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
+OUI:58BDF9*
+ ID_OUI_FROM_DATABASE=Sigrand
+
OUI:58BFEA*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
@@ -56350,6 +57391,9 @@ OUI:58F98E*
OUI:58FD20*
ID_OUI_FROM_DATABASE=Bravida Sakerhet AB
+OUI:5C026A*
+ ID_OUI_FROM_DATABASE=Applied Vision Corporation
+
OUI:5C076F*
ID_OUI_FROM_DATABASE=Thought Creator
@@ -56362,6 +57406,9 @@ OUI:5C0CBB*
OUI:5C0E8B*
ID_OUI_FROM_DATABASE=Motorola
+OUI:5C1193*
+ ID_OUI_FROM_DATABASE=Seal One AG
+
OUI:5C1437*
ID_OUI_FROM_DATABASE=Thyssenkrupp Aufzugswerke GmbH
@@ -56392,6 +57439,9 @@ OUI:5C2479*
OUI:5C260A*
ID_OUI_FROM_DATABASE=Dell Inc.
+OUI:5C3327*
+ ID_OUI_FROM_DATABASE=Spazio Italia srl
+
OUI:5C335C*
ID_OUI_FROM_DATABASE=Swissphone Telecom AG
@@ -56404,6 +57454,9 @@ OUI:5C353B*
OUI:5C35DA*
ID_OUI_FROM_DATABASE=There Corporation Oy
+OUI:5C36B8*
+ ID_OUI_FROM_DATABASE=TCL King Electrical Appliances (Huizhou) Ltd.
+
OUI:5C38E0*
ID_OUI_FROM_DATABASE=Shanghai Super Electronics Technology Co.,LTD
@@ -56438,7 +57491,7 @@ OUI:5C57C8*
ID_OUI_FROM_DATABASE=Nokia Corporation
OUI:5C5948*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:5C5EAB*
ID_OUI_FROM_DATABASE=Juniper Networks
@@ -56480,7 +57533,7 @@ OUI:5C89D4*
ID_OUI_FROM_DATABASE=Beijing Banner Electric Co.,Ltd
OUI:5C95AE*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:5C969D*
ID_OUI_FROM_DATABASE=Apple
@@ -56530,12 +57583,18 @@ OUI:5CD41B*
OUI:5CD4AB*
ID_OUI_FROM_DATABASE=Zektor
+OUI:5CD61F*
+ ID_OUI_FROM_DATABASE=Qardio, Inc
+
OUI:5CD998*
ID_OUI_FROM_DATABASE=D-Link Corporation
OUI:5CDAD4*
ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
+OUI:5CDD70*
+ ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited
+
OUI:5CE0CA*
ID_OUI_FROM_DATABASE=FeiTian United (Beijing) System Technology Co., Ltd.
@@ -56575,15 +57634,24 @@ OUI:5CF6DC*
OUI:5CF8A1*
ID_OUI_FROM_DATABASE=Murata Manufactuaring Co.,Ltd.
+OUI:5CF938*
+ ID_OUI_FROM_DATABASE=Apple, Inc
+
OUI:5CF9DD*
ID_OUI_FROM_DATABASE=Dell Inc
OUI:5CFF35*
ID_OUI_FROM_DATABASE=Wistron Corporation
+OUI:5CFFFF*
+ ID_OUI_FROM_DATABASE=Shenzhen Kezhonglong Optoelectronic Technology Co., Ltd
+
OUI:6002B4*
ID_OUI_FROM_DATABASE=Wistron NeWeb Corp.
+OUI:600347*
+ ID_OUI_FROM_DATABASE=Billion Electric Co. Ltd.
+
OUI:600F77*
ID_OUI_FROM_DATABASE=SilverPlus, Inc
@@ -56611,6 +57679,9 @@ OUI:601E02*
OUI:6021C0*
ID_OUI_FROM_DATABASE=Murata Manufactuaring Co.,Ltd.
+OUI:6024C1*
+ ID_OUI_FROM_DATABASE=Jiangsu Zhongxun Electronic Technology Co., Ltd
+
OUI:602A54*
ID_OUI_FROM_DATABASE=CardioTek B.V.
@@ -56621,7 +57692,7 @@ OUI:6032F0*
ID_OUI_FROM_DATABASE=Mplus technology
OUI:60334B*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:603553*
ID_OUI_FROM_DATABASE=Buwon Technology
@@ -56659,15 +57730,24 @@ OUI:6052D0*
OUI:605464*
ID_OUI_FROM_DATABASE=Eyedro Green Solutions Inc.
+OUI:605718*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:60601F*
ID_OUI_FROM_DATABASE=SZ DJI TECHNOLOGY CO.,LTD
OUI:6063FD*
ID_OUI_FROM_DATABASE=Transcend Communication Beijing Co.,Ltd.
+OUI:6064A1*
+ ID_OUI_FROM_DATABASE=RADiflow Ltd.
+
OUI:606720*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:606944*
+ ID_OUI_FROM_DATABASE=Apple, Inc
+
OUI:60699B*
ID_OUI_FROM_DATABASE=isepos GmbH
@@ -56728,6 +57808,9 @@ OUI:60A10A*
OUI:60A44C*
ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
+OUI:60A9B0*
+ ID_OUI_FROM_DATABASE=Merchandising Technologies, Inc
+
OUI:60B185*
ID_OUI_FROM_DATABASE=ATH system
@@ -56752,11 +57835,14 @@ OUI:60BC4C*
OUI:60BD91*
ID_OUI_FROM_DATABASE=Move Innovation
+OUI:60BEB5*
+ ID_OUI_FROM_DATABASE=Motorola Mobility LLC
+
OUI:60C397*
- ID_OUI_FROM_DATABASE=2 Wire Inc
+ ID_OUI_FROM_DATABASE=2Wire Inc
OUI:60C547*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:60C5A8*
ID_OUI_FROM_DATABASE=Beijing LT Honway Technology Co.,Ltd
@@ -56788,6 +57874,9 @@ OUI:60D819*
OUI:60DA23*
ID_OUI_FROM_DATABASE=Estech Co.,Ltd
+OUI:60DB2A*
+ ID_OUI_FROM_DATABASE=HNS
+
OUI:60DE44*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
@@ -56822,10 +57911,10 @@ OUI:60F673*
ID_OUI_FROM_DATABASE=TERUMO CORPORATION
OUI:60FACD*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:60FB42*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:60FE1E*
ID_OUI_FROM_DATABASE=China Palms Telecom.Ltd
@@ -56833,12 +57922,21 @@ OUI:60FE1E*
OUI:60FEC5*
ID_OUI_FROM_DATABASE=Apple
+OUI:60FEF9*
+ ID_OUI_FROM_DATABASE=Thomas & Betts
+
OUI:6400F1*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
+OUI:6405BE*
+ ID_OUI_FROM_DATABASE=NEW LIGHT LED
+
OUI:64094C*
ID_OUI_FROM_DATABASE=Beijing Superbee Wireless Technology Co.,Ltd
+OUI:640B4A*
+ ID_OUI_FROM_DATABASE=Digital Telecom Technology Limited
+
OUI:640E36*
ID_OUI_FROM_DATABASE=TAZTAG
@@ -56867,7 +57965,10 @@ OUI:641E81*
ID_OUI_FROM_DATABASE=Dowslake Microsystems
OUI:64200C*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
+
+OUI:642184*
+ ID_OUI_FROM_DATABASE=Nippon Denki Kagaku Co.,LTD
OUI:642216*
ID_OUI_FROM_DATABASE=Shandong Taixin Electronic co.,Ltd
@@ -56890,6 +57991,12 @@ OUI:64317E*
OUI:643409*
ID_OUI_FROM_DATABASE=BITwave Pte Ltd
+OUI:643F5F*
+ ID_OUI_FROM_DATABASE=Exablaze
+
+OUI:644214*
+ ID_OUI_FROM_DATABASE=Swisscom Energy Solutions AG
+
OUI:644346*
ID_OUI_FROM_DATABASE=GuangDong Quick Network Computer CO.,LTD
@@ -56909,7 +58016,7 @@ OUI:64517E*
ID_OUI_FROM_DATABASE=LONG BEN (DONGGUAN) ELECTRONIC TECHNOLOGY CO.,LTD.
OUI:645299*
- ID_OUI_FROM_DATABASE=Chamberlain
+ ID_OUI_FROM_DATABASE=The Chamberlain Group, Inc
OUI:64535D*
ID_OUI_FROM_DATABASE=Frauscher Sensortechnik
@@ -56923,6 +58030,9 @@ OUI:645563*
OUI:64557F*
ID_OUI_FROM_DATABASE=NSFOCUS Information Technology Co., Ltd.
+OUI:645601*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD
+
OUI:645A04*
ID_OUI_FROM_DATABASE=Chicony Electronics Co., Ltd.
@@ -56956,6 +58066,9 @@ OUI:6469BC*
OUI:646E6C*
ID_OUI_FROM_DATABASE=Radio Datacom LLC
+OUI:646EEA*
+ ID_OUI_FROM_DATABASE=Iskratel d.o.o.
+
OUI:647002*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO., LTD.
@@ -57056,7 +58169,10 @@ OUI:64B64A*
ID_OUI_FROM_DATABASE=ViVOtech, Inc.
OUI:64B9E8*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
+
+OUI:64BABD*
+ ID_OUI_FROM_DATABASE=SDJ Technologies, Inc.
OUI:64BC11*
ID_OUI_FROM_DATABASE=CombiQ AB
@@ -57082,6 +58198,9 @@ OUI:64D1A3*
OUI:64D241*
ID_OUI_FROM_DATABASE=Keith & Koep GmbH
+OUI:64D4BD*
+ ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD.
+
OUI:64D4DA*
ID_OUI_FROM_DATABASE=Intel Corporate
@@ -57110,7 +58229,7 @@ OUI:64E599*
ID_OUI_FROM_DATABASE=EFM Networks
OUI:64E682*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:64E84F*
ID_OUI_FROM_DATABASE=Serialway Communication Technology Co. Ltd
@@ -57118,8 +58237,11 @@ OUI:64E84F*
OUI:64E8E6*
ID_OUI_FROM_DATABASE=global moisture management system
+OUI:64E950*
+ ID_OUI_FROM_DATABASE=Cisco
+
OUI:64ED57*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:64ED62*
ID_OUI_FROM_DATABASE=WOORI SYSTEMS Co., Ltd
@@ -57143,7 +58265,10 @@ OUI:6805CA*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:680927*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
+
+OUI:680AD7*
+ ID_OUI_FROM_DATABASE=Yancheng Kecheng Optoelectronic Technology Co., Ltd
OUI:68122D*
ID_OUI_FROM_DATABASE=Special Instrument Development Co., Ltd.
@@ -57160,12 +58285,18 @@ OUI:681605*
OUI:681729*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:68193F*
+ ID_OUI_FROM_DATABASE=Digital Airways
+
OUI:681AB2*
ID_OUI_FROM_DATABASE=zte corporation
OUI:681CA2*
ID_OUI_FROM_DATABASE=Rosewill Inc.
+OUI:681D64*
+ ID_OUI_FROM_DATABASE=Sunwave Communications Co., Ltd
+
OUI:681E8B*
ID_OUI_FROM_DATABASE=InfoSight Corporation
@@ -57175,6 +58306,9 @@ OUI:681FD8*
OUI:68234B*
ID_OUI_FROM_DATABASE=Nihon Dengyo Kousaku
+OUI:682DDC*
+ ID_OUI_FROM_DATABASE=Wuhan Changjiang Electro-Communication Equipment CO.,LTD
+
OUI:683B1E*
ID_OUI_FROM_DATABASE=Countwise LTD
@@ -57203,7 +58337,7 @@ OUI:68597F*
ID_OUI_FROM_DATABASE=Alcatel Lucent
OUI:685B35*
- ID_OUI_FROM_DATABASE=Apple inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:685B36*
ID_OUI_FROM_DATABASE=POWERTECH INDUSTRIAL CO., LTD.
@@ -57217,6 +58351,9 @@ OUI:685E6B*
OUI:686359*
ID_OUI_FROM_DATABASE=Advanced Digital Broadcast SA
+OUI:68692E*
+ ID_OUI_FROM_DATABASE=Zycoo Co.,Ltd
+
OUI:6869F2*
ID_OUI_FROM_DATABASE=ComAp s.r.o.
@@ -57226,6 +58363,9 @@ OUI:686E23*
OUI:687251*
ID_OUI_FROM_DATABASE=Ubiquiti Networks
+OUI:68764F*
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+
OUI:68784C*
ID_OUI_FROM_DATABASE=Nortel Networks
@@ -57259,6 +58399,9 @@ OUI:6886E7*
OUI:68876B*
ID_OUI_FROM_DATABASE=INQ Mobile Limited
+OUI:688AB5*
+ ID_OUI_FROM_DATABASE=EDP Servicos
+
OUI:689234*
ID_OUI_FROM_DATABASE=Ruckus Wireless
@@ -57266,7 +58409,7 @@ OUI:689423*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
OUI:68967B*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:68974B*
ID_OUI_FROM_DATABASE=Shenzhen Costar Electronics Co. Ltd.
@@ -57290,7 +58433,7 @@ OUI:68A40E*
ID_OUI_FROM_DATABASE=BSH Bosch and Siemens Home Appliances GmbH
OUI:68A86D*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:68AAD2*
ID_OUI_FROM_DATABASE=DATECS LTD.,
@@ -57379,6 +58522,9 @@ OUI:68F895*
OUI:68FB95*
ID_OUI_FROM_DATABASE=Generalplus Technology Inc.
+OUI:68FCB3*
+ ID_OUI_FROM_DATABASE=Next Level Security Systems, Inc.
+
OUI:6C0460*
ID_OUI_FROM_DATABASE=RBH Access Technologies Inc.
@@ -57388,6 +58534,9 @@ OUI:6C0E0D*
OUI:6C0F6A*
ID_OUI_FROM_DATABASE=JDC Tech Co., Ltd.
+OUI:6C15F9*
+ ID_OUI_FROM_DATABASE=Nautronix Limited
+
OUI:6C1811*
ID_OUI_FROM_DATABASE=Decatur Electronics
@@ -57425,7 +58574,7 @@ OUI:6C3BE5*
ID_OUI_FROM_DATABASE=Hewlett Packard
OUI:6C3E6D*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:6C3E9C*
ID_OUI_FROM_DATABASE=KE Knestel Elektronik GmbH
@@ -57436,6 +58585,9 @@ OUI:6C40C6*
OUI:6C416A*
ID_OUI_FROM_DATABASE=Cisco
+OUI:6C4B7F*
+ ID_OUI_FROM_DATABASE=Vossloh-Schwabe Deutschland GmbH
+
OUI:6C504D*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
@@ -57445,6 +58597,9 @@ OUI:6C5779*
OUI:6C5A34*
ID_OUI_FROM_DATABASE=Shenzhen Haitianxiong Electronic Co., Ltd.
+OUI:6C5AB5*
+ ID_OUI_FROM_DATABASE=TCL Technoly Electronics (Huizhou) Co., Ltd.
+
OUI:6C5CDE*
ID_OUI_FROM_DATABASE=SunReports, Inc.
@@ -57475,6 +58630,9 @@ OUI:6C81FE*
OUI:6C8336*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:6C8366*
+ ID_OUI_FROM_DATABASE=Nanjing SAC Power Grid Automation Co., Ltd.
+
OUI:6C8686*
ID_OUI_FROM_DATABASE=Technonia
@@ -57490,9 +58648,15 @@ OUI:6C8CDB*
OUI:6C8D65*
ID_OUI_FROM_DATABASE=Wireless Glue Networks, Inc.
+OUI:6C90B1*
+ ID_OUI_FROM_DATABASE=SanLogic Inc
+
OUI:6C92BF*
ID_OUI_FROM_DATABASE=Inspur Electronic Information Industry Co.,Ltd.
+OUI:6C98EB*
+ ID_OUI_FROM_DATABASE=Xyne GmbH
+
OUI:6C9AC9*
ID_OUI_FROM_DATABASE=Valentine Research, Inc.
@@ -57529,12 +58693,18 @@ OUI:6CAD3F*
OUI:6CADEF*
ID_OUI_FROM_DATABASE=KZ Broadband Technologies, Ltd.
+OUI:6CADF8*
+ ID_OUI_FROM_DATABASE=Azurewave Technologies, Inc.
+
OUI:6CAE8B*
ID_OUI_FROM_DATABASE=IBM Corporation
OUI:6CB311*
ID_OUI_FROM_DATABASE=Shenzhen Lianrui Electronics Co.,Ltd
+OUI:6CB350*
+ ID_OUI_FROM_DATABASE=Anhui comhigher tech co.,ltd
+
OUI:6CB7F4*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
@@ -57542,10 +58712,10 @@ OUI:6CBEE9*
ID_OUI_FROM_DATABASE=Alcatel-Lucent-IPD
OUI:6CC1D2*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:6CC26B*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:6CD032*
ID_OUI_FROM_DATABASE=LG Electronics
@@ -57553,6 +58723,9 @@ OUI:6CD032*
OUI:6CD146*
ID_OUI_FROM_DATABASE=Smartek d.o.o.
+OUI:6CD1B0*
+ ID_OUI_FROM_DATABASE=WING SING ELECTRONICS HONG KONG LIMITED
+
OUI:6CD68A*
ID_OUI_FROM_DATABASE=LG Electronics Inc
@@ -57586,6 +58759,9 @@ OUI:6CF373*
OUI:6CF37F*
ID_OUI_FROM_DATABASE=Aruba Networks
+OUI:6CF97C*
+ ID_OUI_FROM_DATABASE=Nanoptix Inc.
+
OUI:6CFA58*
ID_OUI_FROM_DATABASE=Avaya, Inc
@@ -57616,12 +58792,18 @@ OUI:701124*
OUI:701404*
ID_OUI_FROM_DATABASE=Limited Liability Company
+OUI:70188B*
+ ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+
OUI:701A04*
ID_OUI_FROM_DATABASE=Liteon Tech Corp.
OUI:701AED*
ID_OUI_FROM_DATABASE=ADVAS CO., LTD.
+OUI:701D7F*
+ ID_OUI_FROM_DATABASE=Comtech Technology Co., Ltd.
+
OUI:702393*
ID_OUI_FROM_DATABASE=fos4X GmbH
@@ -57643,6 +58825,9 @@ OUI:702F97*
OUI:703018*
ID_OUI_FROM_DATABASE=Avaya, Inc
+OUI:70305E*
+ ID_OUI_FROM_DATABASE=Nanjing Zhongke Menglian Information Technology Co.,LTD
+
OUI:703187*
ID_OUI_FROM_DATABASE=ACX GmbH
@@ -57676,9 +58861,15 @@ OUI:704AAE*
OUI:704AE4*
ID_OUI_FROM_DATABASE=Rinstrum Pty Ltd
+OUI:704CED*
+ ID_OUI_FROM_DATABASE=TMRG, Inc.
+
OUI:7052C5*
ID_OUI_FROM_DATABASE=Avaya, Inc.
+OUI:70533F*
+ ID_OUI_FROM_DATABASE=Alfa Instrumentos Eletronicos Ltda.
+
OUI:7054D2*
ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
@@ -57686,11 +58877,17 @@ OUI:7054F5*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:705681*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:705812*
ID_OUI_FROM_DATABASE=Panasonic AVC Networks Company
+OUI:705957*
+ ID_OUI_FROM_DATABASE=Medallion Instrumentation Systems
+
+OUI:705986*
+ ID_OUI_FROM_DATABASE=OOO TTV
+
OUI:705AB6*
ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD.
@@ -57700,6 +58897,12 @@ OUI:705CAD*
OUI:705EAA*
ID_OUI_FROM_DATABASE=Action Target, Inc.
+OUI:7060DE*
+ ID_OUI_FROM_DATABASE=LaVision GmbH
+
+OUI:706173*
+ ID_OUI_FROM_DATABASE=Calantec GmbH
+
OUI:706417*
ID_OUI_FROM_DATABASE=ORBIS TECNOLOGIA ELECTRICA S.A.
@@ -57719,7 +58922,10 @@ OUI:7072CF*
ID_OUI_FROM_DATABASE=EdgeCore Networks
OUI:7073CB*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
+
+OUI:707630*
+ ID_OUI_FROM_DATABASE=Pace plc.
OUI:7076DD*
ID_OUI_FROM_DATABASE=Oxyguard International A/S
@@ -57731,7 +58937,7 @@ OUI:707BE8*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:707E43*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:707EDE*
ID_OUI_FROM_DATABASE=NASTEC LTD.
@@ -57745,9 +58951,15 @@ OUI:70820E*
OUI:70828E*
ID_OUI_FROM_DATABASE=OleumTech Corporation
+OUI:7085C6*
+ ID_OUI_FROM_DATABASE=Pace plc.
+
OUI:708B78*
ID_OUI_FROM_DATABASE=citygrow technology co., ltd
+OUI:708D09*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
+
OUI:7093F8*
ID_OUI_FROM_DATABASE=Space Monkey, Inc.
@@ -57760,6 +58972,12 @@ OUI:709A0B*
OUI:709BA5*
ID_OUI_FROM_DATABASE=Shenzhen Y&D Electronics Co.,LTD.
+OUI:709BFC*
+ ID_OUI_FROM_DATABASE=Bryton Inc.
+
+OUI:709E29*
+ ID_OUI_FROM_DATABASE=Sony Computer Entertainment Inc.
+
OUI:709E86*
ID_OUI_FROM_DATABASE=X6D Limited
@@ -57772,6 +58990,9 @@ OUI:70A41C*
OUI:70A66A*
ID_OUI_FROM_DATABASE=Prox Dynamics AS
+OUI:70A8E3*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:70AAB2*
ID_OUI_FROM_DATABASE=Research In Motion
@@ -57800,7 +59021,7 @@ OUI:70CA9B*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
OUI:70CD60*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:70D4F2*
ID_OUI_FROM_DATABASE=RIM
@@ -57821,7 +59042,7 @@ OUI:70DDA1*
ID_OUI_FROM_DATABASE=Tellabs
OUI:70DEE2*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:70E027*
ID_OUI_FROM_DATABASE=HONGYU COMMUNICATION TECHNOLOGY LIMITED
@@ -57832,12 +59053,18 @@ OUI:70E139*
OUI:70E24C*
ID_OUI_FROM_DATABASE=SAE IT-systems GmbH & Co. KG
+OUI:70E284*
+ ID_OUI_FROM_DATABASE=Wistron InfoComm(Zhongshan) Corporation
+
OUI:70E843*
ID_OUI_FROM_DATABASE=Beijing C&W Optical Communication Technology Co.,Ltd.
OUI:70EE50*
ID_OUI_FROM_DATABASE=Netatmo
+OUI:70F176*
+ ID_OUI_FROM_DATABASE=Data Modul AG
+
OUI:70F1A1*
ID_OUI_FROM_DATABASE=Liteon Technology Corporation
@@ -57850,9 +59077,15 @@ OUI:70F395*
OUI:70F927*
ID_OUI_FROM_DATABASE=Samsung Electronics
+OUI:70FF76*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
OUI:740ABC*
ID_OUI_FROM_DATABASE=JSJS Designs (Europe) Limited
+OUI:740EDB*
+ ID_OUI_FROM_DATABASE=Optowiz Co., Ltd
+
OUI:741489*
ID_OUI_FROM_DATABASE=SRT Wireless
@@ -57874,6 +59107,9 @@ OUI:7427EA*
OUI:742B0F*
ID_OUI_FROM_DATABASE=Infinidat Ltd.
+OUI:742B62*
+ ID_OUI_FROM_DATABASE=Fujitsu Limited
+
OUI:742D0A*
ID_OUI_FROM_DATABASE=Norfolk Elektronik AG
@@ -57911,7 +59147,7 @@ OUI:745327*
ID_OUI_FROM_DATABASE=COMMSEN CO., LIMITED
OUI:745612*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:745798*
ID_OUI_FROM_DATABASE=TRUMPF Laser GmbH + Co. KG
@@ -57931,6 +59167,9 @@ OUI:7463DF*
OUI:7465D1*
ID_OUI_FROM_DATABASE=Atlinks
+OUI:746630*
+ ID_OUI_FROM_DATABASE=T:mi Ytti
+
OUI:746A89*
ID_OUI_FROM_DATABASE=Rezolt Corporation
@@ -57988,6 +59227,9 @@ OUI:749DDC*
OUI:74A4A7*
ID_OUI_FROM_DATABASE=QRS Music Technologies, Inc.
+OUI:74A4B5*
+ ID_OUI_FROM_DATABASE=Powerleader Science and Technology Co. Ltd.
+
OUI:74A722*
ID_OUI_FROM_DATABASE=LG Electronics
@@ -58027,6 +59269,9 @@ OUI:74D02B*
OUI:74D0DC*
ID_OUI_FROM_DATABASE=ERICSSON AB
+OUI:74D435*
+ ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
+
OUI:74D675*
ID_OUI_FROM_DATABASE=WYMA Tecnologia
@@ -58040,10 +59285,10 @@ OUI:74E06E*
ID_OUI_FROM_DATABASE=Ergophone GmbH
OUI:74E1B6*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:74E2F5*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:74E424*
ID_OUI_FROM_DATABASE=APISTE CORPORATION
@@ -58058,7 +59303,7 @@ OUI:74E543*
ID_OUI_FROM_DATABASE=Liteon Technology Corporation
OUI:74E7C6*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:74EA3A*
ID_OUI_FROM_DATABASE=TP-LINK Technologies Co.,Ltd.
@@ -58076,7 +59321,7 @@ OUI:74F102*
ID_OUI_FROM_DATABASE=Beijing HCHCOM Technology Co., Ltd
OUI:74F612*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:74F726*
ID_OUI_FROM_DATABASE=Neuron Robotics
@@ -58150,6 +59395,9 @@ OUI:78324F*
OUI:783CE3*
ID_OUI_FROM_DATABASE=Kai-EE
+OUI:783D5B*
+ ID_OUI_FROM_DATABASE=TELNET Redes Inteligentes S.A.
+
OUI:783F15*
ID_OUI_FROM_DATABASE=EasySYNC Ltd.
@@ -58168,6 +59416,9 @@ OUI:7846C4*
OUI:78471D*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:78491D*
+ ID_OUI_FROM_DATABASE=The Will-Burt Company
+
OUI:784B08*
ID_OUI_FROM_DATABASE=f.robotics acquisitions ltd
@@ -58195,6 +59446,9 @@ OUI:78593E*
OUI:78595E*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:785968*
+ ID_OUI_FROM_DATABASE=Hon Hai Precision Ind.Co.,Ltd.
+
OUI:785C72*
ID_OUI_FROM_DATABASE=Hioso Technology Co., Ltd.
@@ -58246,6 +59500,9 @@ OUI:78998F*
OUI:789ED0*
ID_OUI_FROM_DATABASE=Samsung Electronics
+OUI:789F4C*
+ ID_OUI_FROM_DATABASE=HOERBIGER Elektronik GmbH
+
OUI:789F87*
ID_OUI_FROM_DATABASE=Siemens AG I IA PP PRM
@@ -58262,7 +59519,7 @@ OUI:78A2A0*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
OUI:78A3E4*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:78A5DD*
ID_OUI_FROM_DATABASE=Shenzhen Smarteye Digital Electronics Co., Ltd
@@ -58285,9 +59542,15 @@ OUI:78ABBB*
OUI:78ACC0*
ID_OUI_FROM_DATABASE=Hewlett-Packard Company
+OUI:78AE0C*
+ ID_OUI_FROM_DATABASE=Far South Networks
+
OUI:78B3CE*
ID_OUI_FROM_DATABASE=Elo touch solutions
+OUI:78B5D2*
+ ID_OUI_FROM_DATABASE=Ever Treasure Industrial Limited
+
OUI:78B6C1*
ID_OUI_FROM_DATABASE=AOBO Telecom Co.,Ltd
@@ -58319,7 +59582,13 @@ OUI:78CA04*
ID_OUI_FROM_DATABASE=Nokia Corporation
OUI:78CA39*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
+
+OUI:78CA5E*
+ ID_OUI_FROM_DATABASE=ELNO
+
+OUI:78CB33*
+ ID_OUI_FROM_DATABASE=DHC Software Co.,Ltd
OUI:78CD8E*
ID_OUI_FROM_DATABASE=SMC Networks Inc
@@ -58342,6 +59611,12 @@ OUI:78D5B5*
OUI:78D6F0*
ID_OUI_FROM_DATABASE=Samsung Electro Mechanics
+OUI:78D99F*
+ ID_OUI_FROM_DATABASE=NuCom HK Ltd.
+
+OUI:78DA6E*
+ ID_OUI_FROM_DATABASE=Cisco
+
OUI:78DAB3*
ID_OUI_FROM_DATABASE=GBO Technology
@@ -58363,6 +59638,9 @@ OUI:78E400*
OUI:78E7D1*
ID_OUI_FROM_DATABASE=Hewlett-Packard Company
+OUI:78E8B6*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:78EC22*
ID_OUI_FROM_DATABASE=Shanghai Qihui Telecom Technology Co., LTD
@@ -58384,6 +59662,9 @@ OUI:78F7D0*
OUI:78FE3D*
ID_OUI_FROM_DATABASE=Juniper Networks
+OUI:78FE41*
+ ID_OUI_FROM_DATABASE=Socus networks
+
OUI:78FF57*
ID_OUI_FROM_DATABASE=Intel Corporate
@@ -58405,8 +59686,11 @@ OUI:7C0507*
OUI:7C051E*
ID_OUI_FROM_DATABASE=RAFAEL LTD.
+OUI:7C0623*
+ ID_OUI_FROM_DATABASE=Ultra Electronics, CIS
+
OUI:7C08D9*
- ID_OUI_FROM_DATABASE=Shanghai Engineering Research Center for Broadband Technologies and Applications
+ ID_OUI_FROM_DATABASE=Shanghai B-Star Technology Co
OUI:7C092B*
ID_OUI_FROM_DATABASE=Bekey A/S
@@ -58415,7 +59699,7 @@ OUI:7C0A50*
ID_OUI_FROM_DATABASE=J-MEX Inc.
OUI:7C11BE*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:7C1476*
ID_OUI_FROM_DATABASE=Damall Technologies SAS
@@ -58423,12 +59707,18 @@ OUI:7C1476*
OUI:7C160D*
ID_OUI_FROM_DATABASE=Saia-Burgess Controls AG
+OUI:7C1AFC*
+ ID_OUI_FROM_DATABASE=Dalian Co-Edifice Video Technology Co., Ltd
+
OUI:7C1E52*
ID_OUI_FROM_DATABASE=Microsoft
OUI:7C1EB3*
ID_OUI_FROM_DATABASE=2N TELEKOMUNIKACE a.s.
+OUI:7C2048*
+ ID_OUI_FROM_DATABASE=KoamTac
+
OUI:7C2064*
ID_OUI_FROM_DATABASE=Alcatel Lucent IPD
@@ -58459,6 +59749,9 @@ OUI:7C3E9D*
OUI:7C438F*
ID_OUI_FROM_DATABASE=E-Band Communications Corp.
+OUI:7C49B9*
+ ID_OUI_FROM_DATABASE=Plexus Manufacturing Sdn Bhd
+
OUI:7C4A82*
ID_OUI_FROM_DATABASE=Portsmith LLC
@@ -58486,6 +59779,15 @@ OUI:7C6097*
OUI:7C6193*
ID_OUI_FROM_DATABASE=HTC Corporation
+OUI:7C669D*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
+OUI:7C69F6*
+ ID_OUI_FROM_DATABASE=Cisco
+
+OUI:7C6AB3*
+ ID_OUI_FROM_DATABASE=IBC TECHNOLOGIES INC.
+
OUI:7C6ADB*
ID_OUI_FROM_DATABASE=SafeTone Technology Co.,Ltd
@@ -58502,11 +59804,17 @@ OUI:7C6C8F*
ID_OUI_FROM_DATABASE=AMS NEVE LTD
OUI:7C6D62*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:7C6F06*
ID_OUI_FROM_DATABASE=Caterpillar Trimble Control Technologies
+OUI:7C6FF8*
+ ID_OUI_FROM_DATABASE=ShenZhen ACTO Digital Video Technology Co.,Ltd.
+
+OUI:7C72E4*
+ ID_OUI_FROM_DATABASE=Unikey Technologies
+
OUI:7C7673*
ID_OUI_FROM_DATABASE=ENMAS GmbH
@@ -58522,12 +59830,21 @@ OUI:7C7D41*
OUI:7C822D*
ID_OUI_FROM_DATABASE=Nortec
+OUI:7C8306*
+ ID_OUI_FROM_DATABASE=Glen Dimplex Nordic as
+
OUI:7C8EE4*
ID_OUI_FROM_DATABASE=Texas Instruments
OUI:7C94B2*
ID_OUI_FROM_DATABASE=Philips Healthcare PCCI
+OUI:7C95F3*
+ ID_OUI_FROM_DATABASE=Cisco
+
+OUI:7C9763*
+ ID_OUI_FROM_DATABASE=Openmatics s.r.o.
+
OUI:7C9A9B*
ID_OUI_FROM_DATABASE=VSE valencia smart energy
@@ -58558,17 +59875,29 @@ OUI:7CB232*
OUI:7CB542*
ID_OUI_FROM_DATABASE=ACES Technology
+OUI:7CB733*
+ ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP
+
+OUI:7CB77B*
+ ID_OUI_FROM_DATABASE=Paradigm Electronics Inc
+
OUI:7CBB6F*
ID_OUI_FROM_DATABASE=Cosco Electronics Co., Ltd.
+OUI:7CBD06*
+ ID_OUI_FROM_DATABASE=AE REFUsol
+
+OUI:7CBF88*
+ ID_OUI_FROM_DATABASE=Mobilicom LTD
+
OUI:7CBFB1*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:7CC3A1*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:7CC537*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:7CC8AB*
ID_OUI_FROM_DATABASE=Acro Associates, Inc.
@@ -58582,11 +59911,14 @@ OUI:7CC8D7*
OUI:7CCB0D*
ID_OUI_FROM_DATABASE=Antaira Technologies, LLC
+OUI:7CCD3C*
+ ID_OUI_FROM_DATABASE=Guangzhou Juzing Technology Co., Ltd
+
OUI:7CCFCF*
ID_OUI_FROM_DATABASE=Shanghai SEARI Intelligent System Co., Ltd
OUI:7CD1C3*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:7CD762*
ID_OUI_FROM_DATABASE=Freestyle Technology Pty Ltd
@@ -58612,6 +59944,9 @@ OUI:7CDD90*
OUI:7CE044*
ID_OUI_FROM_DATABASE=NEON Inc
+OUI:7CE56B*
+ ID_OUI_FROM_DATABASE=ESEN Optoelectronics Technology Co.,Ltd.
+
OUI:7CE9D3*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
@@ -58628,7 +59963,7 @@ OUI:7CEF8A*
ID_OUI_FROM_DATABASE=Inhon International Ltd.
OUI:7CF05F*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:7CF098*
ID_OUI_FROM_DATABASE=Bee Beans Technologies, Inc.
@@ -58651,6 +59986,9 @@ OUI:80000B*
OUI:800010*
ID_OUI_FROM_DATABASE=ATT BELL LABORATORIES
+OUI:8005DF*
+ ID_OUI_FROM_DATABASE=Montage Technology Group Limited
+
OUI:8007A2*
ID_OUI_FROM_DATABASE=Esson Technology Inc.
@@ -58717,8 +60055,11 @@ OUI:80427C*
OUI:804731*
ID_OUI_FROM_DATABASE=Packet Design, Inc.
+OUI:8048A5*
+ ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOM CO.,LTD
+
OUI:804971*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:804B20*
ID_OUI_FROM_DATABASE=Ventilation Control
@@ -58729,6 +60070,12 @@ OUI:804F58*
OUI:80501B*
ID_OUI_FROM_DATABASE=Nokia Corporation
+OUI:8056F2*
+ ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+
+OUI:805719*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:8058C5*
ID_OUI_FROM_DATABASE=NovaTec Kommunikationstechnik GmbH
@@ -58756,6 +60103,9 @@ OUI:80711F*
OUI:807693*
ID_OUI_FROM_DATABASE=Newag SA
+OUI:8079AE*
+ ID_OUI_FROM_DATABASE=ShanDong Tecsunrise Co.,Ltd
+
OUI:807A7F*
ID_OUI_FROM_DATABASE=ABB Genway Xiamen Electrical Equipment CO., LTD
@@ -58799,7 +60149,7 @@ OUI:80946C*
ID_OUI_FROM_DATABASE=TOKYO RADAR CORPORATION
OUI:8096B1*
- ID_OUI_FROM_DATABASE=Motorola Mobility, LLC.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:80971B*
ID_OUI_FROM_DATABASE=Altenergy Power System,Inc.
@@ -58813,6 +60163,9 @@ OUI:80A1D7*
OUI:80AAA4*
ID_OUI_FROM_DATABASE=USAG
+OUI:80B219*
+ ID_OUI_FROM_DATABASE=ELEKTRON TECHNOLOGY UK LIMITED
+
OUI:80B289*
ID_OUI_FROM_DATABASE=Forworld Electronics Ltd.
@@ -58867,6 +60220,9 @@ OUI:80DB31*
OUI:80EE73*
ID_OUI_FROM_DATABASE=Shuttle Inc.
+OUI:80F25E*
+ ID_OUI_FROM_DATABASE=Kyynel
+
OUI:80F593*
ID_OUI_FROM_DATABASE=IRCO Sistemas de Telecomunicación S.A.
@@ -58888,12 +60244,18 @@ OUI:8400D2*
OUI:840B2D*
ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS CO., LTD
+OUI:840F45*
+ ID_OUI_FROM_DATABASE=Shanghai GMT Digital Technologies Co., Ltd
+
OUI:841715*
ID_OUI_FROM_DATABASE=GP Electronics (HK) Ltd.
OUI:841888*
ID_OUI_FROM_DATABASE=Juniper Networks
+OUI:841B38*
+ ID_OUI_FROM_DATABASE=Shenzhen Excelsecu Data Technology Co.,Ltd
+
OUI:841B5E*
ID_OUI_FROM_DATABASE=NETGEAR
@@ -58906,9 +60268,15 @@ OUI:842141*
OUI:84248D*
ID_OUI_FROM_DATABASE=Motorola Solutions Inc
+OUI:84253F*
+ ID_OUI_FROM_DATABASE=Silex Technology, Inc
+
OUI:8425DB*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:84262B*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
+
OUI:8427CE*
ID_OUI_FROM_DATABASE=Corporation of the Presiding Bishop of The Church of Jesus Christ of Latter-day Saints
@@ -58916,7 +60284,7 @@ OUI:842914*
ID_OUI_FROM_DATABASE=EMPORIA TELECOM Produktions- und VertriebsgesmbH & Co KG
OUI:842999*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:842B2B*
ID_OUI_FROM_DATABASE=Dell Inc.
@@ -58957,12 +60325,21 @@ OUI:844915*
OUI:844BF5*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:844F03*
+ ID_OUI_FROM_DATABASE=Ablelink Electronics Ltd
+
OUI:845181*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:84569C*
+ ID_OUI_FROM_DATABASE=Coho Data, Inc.,
+
OUI:845787*
ID_OUI_FROM_DATABASE=DVR C&C Co., Ltd.
+OUI:845C93*
+ ID_OUI_FROM_DATABASE=Chabrier Services
+
OUI:845DD7*
ID_OUI_FROM_DATABASE=Shenzhen Netcom Electronics Co.,Ltd
@@ -58981,6 +60358,9 @@ OUI:846EB1*
OUI:84742A*
ID_OUI_FROM_DATABASE=zte corporation
+OUI:847616*
+ ID_OUI_FROM_DATABASE=Addat S.r.o.
+
OUI:8478AC*
ID_OUI_FROM_DATABASE=Cisco
@@ -58997,7 +60377,7 @@ OUI:848371*
ID_OUI_FROM_DATABASE=Avaya, Inc
OUI:848506*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:848D84*
ID_OUI_FROM_DATABASE=Rajant Corporation
@@ -59023,6 +60403,9 @@ OUI:849DC5*
OUI:84A6C8*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:84A783*
+ ID_OUI_FROM_DATABASE=Alcatel Lucent
+
OUI:84A8E4*
ID_OUI_FROM_DATABASE=Shenzhen Huawei Communication Technologies Co., Ltd
@@ -59101,6 +60484,9 @@ OUI:880905*
OUI:881036*
ID_OUI_FROM_DATABASE=Panodic(ShenZhen) Electronics Limted
+OUI:88124E*
+ ID_OUI_FROM_DATABASE=Qualcomm Atheros
+
OUI:88142B*
ID_OUI_FROM_DATABASE=Protonic Holland
@@ -59140,12 +60526,24 @@ OUI:88329B*
OUI:883314*
ID_OUI_FROM_DATABASE=Texas Instruments
+OUI:88354C*
+ ID_OUI_FROM_DATABASE=Transics
+
+OUI:883612*
+ ID_OUI_FROM_DATABASE=SRC Computers, LLC
+
OUI:8841C1*
ID_OUI_FROM_DATABASE=ORBISAT DA AMAZONIA IND E AEROL SA
+OUI:8841FC*
+ ID_OUI_FROM_DATABASE=AirTies Wireless Netowrks
+
OUI:8843E1*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
+OUI:8844F6*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
+
OUI:88462A*
ID_OUI_FROM_DATABASE=Telechips Inc.
@@ -59164,6 +60562,12 @@ OUI:885395*
OUI:8853D4*
ID_OUI_FROM_DATABASE=Huawei Technologies Co., Ltd
+OUI:88576D*
+ ID_OUI_FROM_DATABASE=XTA Electronics Ltd
+
+OUI:885A92*
+ ID_OUI_FROM_DATABASE=Cisco
+
OUI:885C4F*
ID_OUI_FROM_DATABASE=Alcatel Lucent
@@ -59182,6 +60586,12 @@ OUI:887398*
OUI:887556*
ID_OUI_FROM_DATABASE=Cisco
+OUI:88789C*
+ ID_OUI_FROM_DATABASE=Game Technologies SA
+
+OUI:888603*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:8886A0*
ID_OUI_FROM_DATABASE=Simton Technologies, Ltd.
@@ -59200,6 +60610,9 @@ OUI:888B5D*
OUI:888C19*
ID_OUI_FROM_DATABASE=Brady Corp Asia Pacific Ltd
+OUI:889166*
+ ID_OUI_FROM_DATABASE=Viewcooper Corp.
+
OUI:8891DD*
ID_OUI_FROM_DATABASE=Racktivity
@@ -59252,7 +60665,7 @@ OUI:88C36E*
ID_OUI_FROM_DATABASE=Beijing Ereneben lnformation Technology Limited
OUI:88C663*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:88CB87*
ID_OUI_FROM_DATABASE=Apple
@@ -59296,12 +60709,24 @@ OUI:88F490*
OUI:88FD15*
ID_OUI_FROM_DATABASE=LINEEYE CO., LTD
+OUI:88FED6*
+ ID_OUI_FROM_DATABASE=ShangHai WangYong Software Co., Ltd.
+
+OUI:8C006D*
+ ID_OUI_FROM_DATABASE=Apple
+
OUI:8C04FF*
ID_OUI_FROM_DATABASE=Technicolor USA Inc.
OUI:8C078C*
ID_OUI_FROM_DATABASE=FLOW DATA INC
+OUI:8C088B*
+ ID_OUI_FROM_DATABASE=Remote Solution
+
+OUI:8C09F4*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
OUI:8C0C90*
ID_OUI_FROM_DATABASE=Ruckus Wireless
@@ -59327,7 +60752,10 @@ OUI:8C278A*
ID_OUI_FROM_DATABASE=Vocollect Inc
OUI:8C2DAA*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
+
+OUI:8C2F39*
+ ID_OUI_FROM_DATABASE=IBA Dosimetry GmbH
OUI:8C3330*
ID_OUI_FROM_DATABASE=EmFirst Co., Ltd.
@@ -59344,6 +60772,9 @@ OUI:8C4435*
OUI:8C4AEE*
ID_OUI_FROM_DATABASE=GIGA TMS INC
+OUI:8C4B59*
+ ID_OUI_FROM_DATABASE=3D Imaging & Simulations Corp
+
OUI:8C4CDC*
ID_OUI_FROM_DATABASE=PLANEX COMMUNICATIONS INC.
@@ -59366,7 +60797,7 @@ OUI:8C57FD*
ID_OUI_FROM_DATABASE=LVX Western
OUI:8C5877*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:8C598B*
ID_OUI_FROM_DATABASE=C Technologies AB
@@ -59414,7 +60845,7 @@ OUI:8C7716*
ID_OUI_FROM_DATABASE=LONGCHEER TELECOMMUNICATION LIMITED
OUI:8C7B9D*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:8C7CB5*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
@@ -59455,9 +60886,15 @@ OUI:8CA982*
OUI:8CAE4C*
ID_OUI_FROM_DATABASE=Plugable Technologies
+OUI:8CAE89*
+ ID_OUI_FROM_DATABASE=Y-cam Solutions Ltd
+
OUI:8CB64F*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
+OUI:8CB7F7*
+ ID_OUI_FROM_DATABASE=Shenzhen UniStrong Science & Technology Co., Ltd
+
OUI:8CB82C*
ID_OUI_FROM_DATABASE=IPitomy Communications
@@ -59479,6 +60916,9 @@ OUI:8CC7D0*
OUI:8CC8CD*
ID_OUI_FROM_DATABASE=Samsung Electronics Co., LTD
+OUI:8CCDA2*
+ ID_OUI_FROM_DATABASE=ACTP, Inc.
+
OUI:8CCDE8*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
@@ -59519,7 +60959,7 @@ OUI:8CF9C9*
ID_OUI_FROM_DATABASE=MESADA Technology Co.,Ltd.
OUI:8CFABA*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:8CFDF0*
ID_OUI_FROM_DATABASE=QUALCOMM Incorporated
@@ -59530,6 +60970,9 @@ OUI:90004E*
OUI:90013B*
ID_OUI_FROM_DATABASE=SAGEMCOM
+OUI:90028A*
+ ID_OUI_FROM_DATABASE=Shenzhen Shidean Legrand Electronic Products Co.,Ltd
+
OUI:9002A9*
ID_OUI_FROM_DATABASE=ZHEJIANG DAHUA TECHNOLOGY CO.,LTD
@@ -59560,6 +61003,9 @@ OUI:9018AE*
OUI:901900*
ID_OUI_FROM_DATABASE=SCS SA
+OUI:901ACA*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
OUI:901B0E*
ID_OUI_FROM_DATABASE=Fujitsu Technology Solutions GmbH
@@ -59569,11 +61015,14 @@ OUI:901D27*
OUI:901EDD*
ID_OUI_FROM_DATABASE=GREAT COMPUTER CORPORATION
+OUI:902083*
+ ID_OUI_FROM_DATABASE=General Engine Management Systems Ltd.
+
OUI:902155*
ID_OUI_FROM_DATABASE=HTC Corporation
OUI:9027E4*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:902B34*
ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
@@ -59587,6 +61036,9 @@ OUI:90342B*
OUI:9034FC*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:90356E*
+ ID_OUI_FROM_DATABASE=Vodafone Omnitel N.V.
+
OUI:9038DF*
ID_OUI_FROM_DATABASE=Changzhou Tiannengbo System Co. Ltd.
@@ -59602,12 +61054,18 @@ OUI:903D5A*
OUI:903D6B*
ID_OUI_FROM_DATABASE=Zicon Technology Corp.
+OUI:903EAB*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
OUI:9046B7*
ID_OUI_FROM_DATABASE=Vadaro Pte Ltd
OUI:904716*
ID_OUI_FROM_DATABASE=RORZE CORPORATION
+OUI:9049FA*
+ ID_OUI_FROM_DATABASE=Intel Corporation
+
OUI:904CE5*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
@@ -59641,6 +61099,9 @@ OUI:905F8D*
OUI:90610C*
ID_OUI_FROM_DATABASE=Fida International (S) Pte Ltd
+OUI:906717*
+ ID_OUI_FROM_DATABASE=Alphion India Private Limited
+
OUI:9067B5*
ID_OUI_FROM_DATABASE=Alcatel-Lucent
@@ -59656,6 +61117,18 @@ OUI:906EBB*
OUI:907025*
ID_OUI_FROM_DATABASE=Garea Microsys Co.,Ltd.
+OUI:907240*
+ ID_OUI_FROM_DATABASE=Apple
+
+OUI:907990*
+ ID_OUI_FROM_DATABASE=Benchmark Electronics Romania SRL
+
+OUI:907A0A*
+ ID_OUI_FROM_DATABASE=Gebr. Bode GmbH & Co KG
+
+OUI:907A28*
+ ID_OUI_FROM_DATABASE=Beijing Morncloud Information And Technology Co. Ltd.
+
OUI:907AF1*
ID_OUI_FROM_DATABASE=SNUPI Technologies
@@ -59666,14 +61139,20 @@ OUI:908260*
ID_OUI_FROM_DATABASE=IEEE 1904.1 Working Group
OUI:90840D*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:9088A2*
ID_OUI_FROM_DATABASE=IONICS TECHNOLOGY ME LTDA
+OUI:908C44*
+ ID_OUI_FROM_DATABASE=H.K ZONGMU TECHNOLOGY CO., LTD.
+
OUI:908D1D*
ID_OUI_FROM_DATABASE=GH Technologies
+OUI:908F93*
+ ID_OUI_FROM_DATABASE=MakerBot Industries
+
OUI:908FCF*
ID_OUI_FROM_DATABASE=UNO System Co., Ltd
@@ -59689,9 +61168,15 @@ OUI:9092B4*
OUI:9094E4*
ID_OUI_FROM_DATABASE=D-Link International
+OUI:909916*
+ ID_OUI_FROM_DATABASE=ELVEES NeoTek OJSC
+
OUI:909DE0*
ID_OUI_FROM_DATABASE=Newland Design + Assoc. Inc.
+OUI:909F43*
+ ID_OUI_FROM_DATABASE=Accutron Instruments Inc.
+
OUI:90A2DA*
ID_OUI_FROM_DATABASE=GHEO SA
@@ -59711,7 +61196,10 @@ OUI:90B11C*
ID_OUI_FROM_DATABASE=Dell Inc.
OUI:90B134*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:90B21F*
+ ID_OUI_FROM_DATABASE=Apple
OUI:90B8D0*
ID_OUI_FROM_DATABASE=Joyent, Inc.
@@ -59767,6 +61255,9 @@ OUI:90EA60*
OUI:90F278*
ID_OUI_FROM_DATABASE=Radius Gateway
+OUI:90F3B7*
+ ID_OUI_FROM_DATABASE=Kirisun Communications Co., Ltd.
+
OUI:90F4C1*
ID_OUI_FROM_DATABASE=Rand McNally
@@ -59791,12 +61282,21 @@ OUI:940070*
OUI:940149*
ID_OUI_FROM_DATABASE=AutoHotBox
+OUI:9401C2*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:940B2D*
ID_OUI_FROM_DATABASE=NetView Technologies(Shenzhen) Co., Ltd
+OUI:940BD5*
+ ID_OUI_FROM_DATABASE=Himax Technologies, Inc
+
OUI:940C6D*
ID_OUI_FROM_DATABASE=TP-LINK Technologies Co.,Ltd.
+OUI:94103E*
+ ID_OUI_FROM_DATABASE=Belkin International Inc.
+
OUI:9411DA*
ID_OUI_FROM_DATABASE=ITF Fröschl GmbH
@@ -59827,6 +61327,9 @@ OUI:94319B*
OUI:9433DD*
ID_OUI_FROM_DATABASE=Taco Electronic Solutions, Inc.
+OUI:94350A*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:9436E0*
ID_OUI_FROM_DATABASE=Sichuan Bihong Broadcast &amp; Television New Technologies Co.,Ltd
@@ -59836,6 +61339,9 @@ OUI:9439E5*
OUI:943AF0*
ID_OUI_FROM_DATABASE=Nokia Corporation
+OUI:943BB1*
+ ID_OUI_FROM_DATABASE=KAONMEDIA
+
OUI:9440A2*
ID_OUI_FROM_DATABASE=Anywave Communication Technologies, Inc.
@@ -59875,12 +61381,21 @@ OUI:9471AC*
OUI:94756E*
ID_OUI_FROM_DATABASE=QinetiQ North America
+OUI:947C3E*
+ ID_OUI_FROM_DATABASE=Polewall Norge AS
+
OUI:9481A4*
ID_OUI_FROM_DATABASE=Azuray Technologies
OUI:94857A*
ID_OUI_FROM_DATABASE=Evantage Industries Corp
+OUI:9486D4*
+ ID_OUI_FROM_DATABASE=Surveillance Pro Corporation
+
+OUI:94877C*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
OUI:948854*
ID_OUI_FROM_DATABASE=Texas Instruments
@@ -59923,9 +61438,24 @@ OUI:94AE61*
OUI:94B8C5*
ID_OUI_FROM_DATABASE=RuggedCom Inc.
+OUI:94B9B4*
+ ID_OUI_FROM_DATABASE=Aptos Technology
+
OUI:94BA31*
ID_OUI_FROM_DATABASE=Visiontec da Amazônia Ltda.
+OUI:94BA56*
+ ID_OUI_FROM_DATABASE=Shenzhen Coship Electronics Co., Ltd.
+
+OUI:94BF1E*
+ ID_OUI_FROM_DATABASE=eflow Inc. / Smart Device Planning and Development Division
+
+OUI:94C150*
+ ID_OUI_FROM_DATABASE=2Wire Inc
+
+OUI:94C3E4*
+ ID_OUI_FROM_DATABASE=SCA Schucker Gmbh & Co KG
+
OUI:94C4E9*
ID_OUI_FROM_DATABASE=PowerLayer Microsystems HongKong Limited
@@ -59942,7 +61472,7 @@ OUI:94CA0F*
ID_OUI_FROM_DATABASE=Honeywell Analytics
OUI:94CCB9*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:94CDAC*
ID_OUI_FROM_DATABASE=Creowave Oy
@@ -59977,6 +61507,9 @@ OUI:94DE0E*
OUI:94DE80*
ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
+OUI:94DF4E*
+ ID_OUI_FROM_DATABASE=Wistron InfoComm(Kunshan)Co.,Ltd.
+
OUI:94DF58*
ID_OUI_FROM_DATABASE=IJ Electron CO.,Ltd.
@@ -59992,6 +61525,12 @@ OUI:94E711*
OUI:94E848*
ID_OUI_FROM_DATABASE=FYLDE MICRO LTD
+OUI:94E98C*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
+
+OUI:94EB2C*
+ ID_OUI_FROM_DATABASE=Google Inc.
+
OUI:94EBCD*
ID_OUI_FROM_DATABASE=Research In Motion Limited
@@ -60020,7 +61559,7 @@ OUI:9803A0*
ID_OUI_FROM_DATABASE=ABB n.v. Power Quality Products
OUI:9803D8*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:980C82*
ID_OUI_FROM_DATABASE=Samsung Electro Mechanics
@@ -60070,6 +61609,9 @@ OUI:983F9F*
OUI:984246*
ID_OUI_FROM_DATABASE=SOL INDUSTRY PTE., LTD
+OUI:9843DA*
+ ID_OUI_FROM_DATABASE=INTERTECH
+
OUI:98473C*
ID_OUI_FROM_DATABASE=SHANGHAI SUNMON COMMUNICATION TECHNOGY CO.,LTD
@@ -60077,7 +61619,7 @@ OUI:984A47*
ID_OUI_FROM_DATABASE=CHG Hospital Beds
OUI:984B4A*
- ID_OUI_FROM_DATABASE=Motorola Mobility, LLC.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:984BE1*
ID_OUI_FROM_DATABASE=Hewlett-Packard Company
@@ -60109,6 +61651,9 @@ OUI:985945*
OUI:985C93*
ID_OUI_FROM_DATABASE=SBG Systems SAS
+OUI:985D46*
+ ID_OUI_FROM_DATABASE=PeopleNet Communication
+
OUI:985E1B*
ID_OUI_FROM_DATABASE=ConversDigital Co., Ltd.
@@ -60118,12 +61663,18 @@ OUI:986022*
OUI:9866EA*
ID_OUI_FROM_DATABASE=Industrial Control Communications, Inc.
+OUI:986CF5*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:986DC8*
ID_OUI_FROM_DATABASE=TOSHIBA MITSUBISHI-ELECTRIC INDUSTRIAL SYSTEMS CORPORATION
OUI:9873C4*
ID_OUI_FROM_DATABASE=Sage Electronic Engineering LLC
+OUI:9876B6*
+ ID_OUI_FROM_DATABASE=Adafruit
+
OUI:988217*
ID_OUI_FROM_DATABASE=Disruptive Ltd
@@ -60142,6 +61693,9 @@ OUI:988BAD*
OUI:988E34*
ID_OUI_FROM_DATABASE=ZHEJIANG BOXSAM ELECTRONIC CO.,LTD
+OUI:988E4A*
+ ID_OUI_FROM_DATABASE=NOXUS(BEIJING) TECHNOLOGY CO.,LTD
+
OUI:988EDD*
ID_OUI_FROM_DATABASE=TE Connectivity Limerick
@@ -60175,11 +61729,17 @@ OUI:98BC99*
OUI:98C845*
ID_OUI_FROM_DATABASE=PacketAccess
+OUI:98CDB4*
+ ID_OUI_FROM_DATABASE=Virident Systems, Inc.
+
+OUI:98D331*
+ ID_OUI_FROM_DATABASE=Shenzhen Bolutek Technology Co.,Ltd.
+
OUI:98D686*
ID_OUI_FROM_DATABASE=Chyi Lee industry Co., ltd.
OUI:98D6BB*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:98D6F7*
ID_OUI_FROM_DATABASE=LG Electronics
@@ -60202,9 +61762,15 @@ OUI:98EC65*
OUI:98F537*
ID_OUI_FROM_DATABASE=zte corporation
+OUI:98F8C1*
+ ID_OUI_FROM_DATABASE=IDT Technology Limited
+
OUI:98F8DB*
ID_OUI_FROM_DATABASE=Marini Impianti Industriali s.r.l.
+OUI:98FB12*
+ ID_OUI_FROM_DATABASE=Grand Electronics (HK) Ltd
+
OUI:98FC11*
ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC
@@ -60212,7 +61778,10 @@ OUI:98FE03*
ID_OUI_FROM_DATABASE=Ericsson - North America
OUI:98FE94*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
+
+OUI:98FFD0*
+ ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd.
OUI:9C0111*
ID_OUI_FROM_DATABASE=Shenzhen Newabel Electronic Co., Ltd.
@@ -60220,6 +61789,9 @@ OUI:9C0111*
OUI:9C0298*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:9C039E*
+ ID_OUI_FROM_DATABASE=Beijing Winchannel Software Technology Co., Ltd
+
OUI:9C0473*
ID_OUI_FROM_DATABASE=Tecmobile (International) Ltd.
@@ -60245,11 +61817,17 @@ OUI:9C1FDD*
ID_OUI_FROM_DATABASE=Accupix Inc.
OUI:9C207B*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
+
+OUI:9C216A*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
OUI:9C220E*
ID_OUI_FROM_DATABASE=TASCAN Service GmbH
+OUI:9C2840*
+ ID_OUI_FROM_DATABASE=Discovery Technology,LTD..
+
OUI:9C28BF*
ID_OUI_FROM_DATABASE=Continental Automotive Czech Republic s.r.o.
@@ -60268,6 +61846,9 @@ OUI:9C3AAF*
OUI:9C417C*
ID_OUI_FROM_DATABASE=Hame Technology Co., Limited
+OUI:9C443D*
+ ID_OUI_FROM_DATABASE=CHENGDU XUGUANG TECHNOLOGY CO, LTD
+
OUI:9C4563*
ID_OUI_FROM_DATABASE=DIMEP Sistemas
@@ -60346,6 +61927,9 @@ OUI:9C7BD2*
OUI:9C807D*
ID_OUI_FROM_DATABASE=SYSCABLE Korea Inc.
+OUI:9C8888*
+ ID_OUI_FROM_DATABASE=Simac Techniek NV
+
OUI:9C8BF1*
ID_OUI_FROM_DATABASE=The Warehouse Limited
@@ -60373,6 +61957,9 @@ OUI:9C9811*
OUI:9C9C1D*
ID_OUI_FROM_DATABASE=Starkey Labs Inc.
+OUI:9CA10A*
+ ID_OUI_FROM_DATABASE=SCLE SFE
+
OUI:9CA134*
ID_OUI_FROM_DATABASE=Nike, Inc.
@@ -60382,6 +61969,9 @@ OUI:9CA3BA*
OUI:9CA577*
ID_OUI_FROM_DATABASE=Osorno Enterprises Inc.
+OUI:9CA9E4*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:9CADEF*
ID_OUI_FROM_DATABASE=Obihai Technology, Inc.
@@ -60394,12 +61984,18 @@ OUI:9CB008*
OUI:9CB206*
ID_OUI_FROM_DATABASE=PROCENTEC
+OUI:9CB654*
+ ID_OUI_FROM_DATABASE=Hewlett Packard
+
OUI:9CB70D*
ID_OUI_FROM_DATABASE=Liteon Technology Corporation
OUI:9CB793*
ID_OUI_FROM_DATABASE=Creatcomm Technology Inc.
+OUI:9CBB98*
+ ID_OUI_FROM_DATABASE=Shen Zhen RND Electronic Co.,LTD
+
OUI:9CC077*
ID_OUI_FROM_DATABASE=PrintCounts, LLC
@@ -60424,6 +62020,9 @@ OUI:9CD24B*
OUI:9CD36D*
ID_OUI_FROM_DATABASE=NETGEAR INC.,
+OUI:9CD643*
+ ID_OUI_FROM_DATABASE=D-Link International
+
OUI:9CDF03*
ID_OUI_FROM_DATABASE=Harman/Becker Automotive Systems GmbH
@@ -60439,6 +62038,9 @@ OUI:9CE635*
OUI:9CE6E7*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:9CE7BD*
+ ID_OUI_FROM_DATABASE=Winduskorea co., Ltd
+
OUI:9CEBE8*
ID_OUI_FROM_DATABASE=BizLink (Kunshan) Co.,Ltd
@@ -60448,6 +62050,9 @@ OUI:9CF61A*
OUI:9CF67D*
ID_OUI_FROM_DATABASE=Ricardo Prague, s.r.o.
+OUI:9CF8DB*
+ ID_OUI_FROM_DATABASE=shenzhen eyunmei technology co,.ltd
+
OUI:9CF938*
ID_OUI_FROM_DATABASE=AREVA NP GmbH
@@ -60472,11 +62077,17 @@ OUI:A00BBA*
OUI:A00CA1*
ID_OUI_FROM_DATABASE=SKTB SKiT
+OUI:A01290*
+ ID_OUI_FROM_DATABASE=Avaya, Inc
+
OUI:A0133B*
ID_OUI_FROM_DATABASE=Copyright © HiTi Digital, Inc.
+OUI:A0143D*
+ ID_OUI_FROM_DATABASE=PARROT SA
+
OUI:A0165C*
- ID_OUI_FROM_DATABASE=TangoTec Ltd.
+ ID_OUI_FROM_DATABASE=Triteka LTD
OUI:A01859*
ID_OUI_FROM_DATABASE=Shenzhen Yidashi Electronics Co Ltd
@@ -60511,6 +62122,9 @@ OUI:A036FA*
OUI:A03A75*
ID_OUI_FROM_DATABASE=PSS Belgium N.V.
+OUI:A03B1B*
+ ID_OUI_FROM_DATABASE=Inspire Tech
+
OUI:A04025*
ID_OUI_FROM_DATABASE=Actioncable, Inc.
@@ -60523,6 +62137,9 @@ OUI:A041A7*
OUI:A0423F*
ID_OUI_FROM_DATABASE=Tyan Computer Corp
+OUI:A0481C*
+ ID_OUI_FROM_DATABASE=Hewlett Packard
+
OUI:A04CC1*
ID_OUI_FROM_DATABASE=Helixtech Corp.
@@ -60553,6 +62170,9 @@ OUI:A05DE7*
OUI:A05E6B*
ID_OUI_FROM_DATABASE=MELPER Co., Ltd.
+OUI:A067BE*
+ ID_OUI_FROM_DATABASE=Sicon s.r.l.
+
OUI:A06986*
ID_OUI_FROM_DATABASE=Wellav Technologies Ltd
@@ -60628,9 +62248,15 @@ OUI:A09BBD*
OUI:A0A130*
ID_OUI_FROM_DATABASE=DLI Taiwan Branch office
+OUI:A0A23C*
+ ID_OUI_FROM_DATABASE=GPMS
+
OUI:A0A763*
ID_OUI_FROM_DATABASE=Polytron Vertrieb GmbH
+OUI:A0A8CD*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:A0AAFD*
ID_OUI_FROM_DATABASE=EraThink Technologies Corp.
@@ -60652,15 +62278,27 @@ OUI:A0B9ED*
OUI:A0BAB8*
ID_OUI_FROM_DATABASE=Pixon Imaging
+OUI:A0BF50*
+ ID_OUI_FROM_DATABASE=S.C. ADD-PRODUCTION S.R.L.
+
OUI:A0BFA5*
ID_OUI_FROM_DATABASE=CORESYS
OUI:A0C3DE*
ID_OUI_FROM_DATABASE=Triton Electronic Systems Ltd.
+OUI:A0C6EC*
+ ID_OUI_FROM_DATABASE=ShenZhen ANYK Technology Co.,LTD
+
+OUI:A0CEC8*
+ ID_OUI_FROM_DATABASE=CE LINK LIMITED
+
OUI:A0CF5B*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
+OUI:A0D3C1*
+ ID_OUI_FROM_DATABASE=Hewlett Packard
+
OUI:A0DC04*
ID_OUI_FROM_DATABASE=Becker-Antriebe GmbH
@@ -60685,6 +62323,9 @@ OUI:A0E295*
OUI:A0E534*
ID_OUI_FROM_DATABASE=Stratec Biomedical AG
+OUI:A0E5E9*
+ ID_OUI_FROM_DATABASE=enimai Inc
+
OUI:A0E9DB*
ID_OUI_FROM_DATABASE=Ningbo FreeWings Technologies Co.,Ltd
@@ -60721,6 +62362,12 @@ OUI:A0FE91*
OUI:A40130*
ID_OUI_FROM_DATABASE=ABIsystems Co., LTD
+OUI:A4059E*
+ ID_OUI_FROM_DATABASE=STA Infinity LLP
+
+OUI:A409CB*
+ ID_OUI_FROM_DATABASE=Alfred Kaercher GmbH &amp; Co KG
+
OUI:A40BED*
ID_OUI_FROM_DATABASE=Carry Technology Co.,Ltd
@@ -60748,9 +62395,15 @@ OUI:A41F72*
OUI:A4218A*
ID_OUI_FROM_DATABASE=Nortel Networks
+OUI:A42305*
+ ID_OUI_FROM_DATABASE=Open Networking Laboratory
+
OUI:A424B3*
ID_OUI_FROM_DATABASE=FlatFrog Laboratories AB
+OUI:A42940*
+ ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd
+
OUI:A429B7*
ID_OUI_FROM_DATABASE=bluesky
@@ -60803,16 +62456,19 @@ OUI:A45D36*
ID_OUI_FROM_DATABASE=Hewlett Packard
OUI:A46706*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:A46E79*
ID_OUI_FROM_DATABASE=DFT System Co.Ltd
+OUI:A47760*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
+
OUI:A479E4*
ID_OUI_FROM_DATABASE=KLINFO Corp
OUI:A47AA4*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:A47ACF*
ID_OUI_FROM_DATABASE=VIBICOM COMMUNICATIONS INC.
@@ -60826,6 +62482,9 @@ OUI:A47C1F*
OUI:A4856B*
ID_OUI_FROM_DATABASE=Q Electronics Ltd
+OUI:A4895B*
+ ID_OUI_FROM_DATABASE=ARK INFOSOLUTIONS PVT LTD
+
OUI:A49005*
ID_OUI_FROM_DATABASE=CHINA GREATWALL COMPUTER SHENZHEN CO.,LTD
@@ -60847,6 +62506,9 @@ OUI:A49B13*
OUI:A49EDB*
ID_OUI_FROM_DATABASE=AutoCrib, Inc.
+OUI:A49F89*
+ ID_OUI_FROM_DATABASE=Shanghai Rui Rui Communication Technology Co.Ltd.
+
OUI:A4A24A*
ID_OUI_FROM_DATABASE=Cisco SPVTG
@@ -60866,7 +62528,7 @@ OUI:A4B121*
ID_OUI_FROM_DATABASE=Arantia 2010 S.L.
OUI:A4B197*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:A4B1E9*
ID_OUI_FROM_DATABASE=Technicolor
@@ -60892,12 +62554,21 @@ OUI:A4BADB*
OUI:A4BE61*
ID_OUI_FROM_DATABASE=EutroVision System, Inc.
+OUI:A4C0C7*
+ ID_OUI_FROM_DATABASE=ShenZhen Hitom Communication Technology Co..LTD
+
OUI:A4C0E1*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
OUI:A4C2AB*
ID_OUI_FROM_DATABASE=Hangzhou LEAD-IT Information & Technology Co.,Ltd
+OUI:A4C361*
+ ID_OUI_FROM_DATABASE=Apple
+
+OUI:A4C7DE*
+ ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd.
+
OUI:A4D094*
ID_OUI_FROM_DATABASE=Erwin Peters Systemtechnik GmbH
@@ -60908,7 +62579,7 @@ OUI:A4D1D1*
ID_OUI_FROM_DATABASE=ECOtality North America
OUI:A4D1D2*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:A4D3B5*
ID_OUI_FROM_DATABASE=GLITEL Stropkov, s.r.o.
@@ -60922,6 +62593,9 @@ OUI:A4DA3F*
OUI:A4DB2E*
ID_OUI_FROM_DATABASE=Kingspan Environmental Ltd
+OUI:A4DB30*
+ ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+
OUI:A4DE50*
ID_OUI_FROM_DATABASE=Total Walther GmbH
@@ -60934,6 +62608,9 @@ OUI:A4E32E*
OUI:A4E391*
ID_OUI_FROM_DATABASE=DENY FONTAINE
+OUI:A4E4B8*
+ ID_OUI_FROM_DATABASE=BlackBerry Limited
+
OUI:A4E731*
ID_OUI_FROM_DATABASE=Nokia Corporation
@@ -60943,11 +62620,14 @@ OUI:A4E7E4*
OUI:A4E991*
ID_OUI_FROM_DATABASE=SISTEMAS AUDIOVISUALES ITELSIS S.L.
+OUI:A4E9A3*
+ ID_OUI_FROM_DATABASE=Honest Technology Co., Ltd
+
OUI:A4EBD3*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
OUI:A4ED4E*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:A4EE57*
ID_OUI_FROM_DATABASE=SEIKO EPSON CORPORATION
@@ -60958,6 +62638,9 @@ OUI:A4EF52*
OUI:A4F3C1*
ID_OUI_FROM_DATABASE=Open Source Robotics Foundation, Inc.
+OUI:A4F522*
+ ID_OUI_FROM_DATABASE=CHOFU SEISAKUSHO CO.,LTD
+
OUI:A4F7D0*
ID_OUI_FROM_DATABASE=LAN Accessories Co., Ltd.
@@ -60989,7 +62672,7 @@ OUI:A81FAF*
ID_OUI_FROM_DATABASE=KRYPTON POLSKA
OUI:A82066*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:A826D9*
ID_OUI_FROM_DATABASE=HTC Corporation
@@ -61054,6 +62737,9 @@ OUI:A870A5*
OUI:A875D6*
ID_OUI_FROM_DATABASE=FreeTek International Co., Ltd.
+OUI:A875E2*
+ ID_OUI_FROM_DATABASE=Aventura Technologies, Inc.
+
OUI:A8776F*
ID_OUI_FROM_DATABASE=Zonoff
@@ -61063,15 +62749,24 @@ OUI:A87B39*
OUI:A87E33*
ID_OUI_FROM_DATABASE=Nokia Danmark A/S
+OUI:A886DD*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:A88792*
ID_OUI_FROM_DATABASE=Broadband Antenna Tracking Systems
OUI:A887ED*
ID_OUI_FROM_DATABASE=ARC Wireless LLC
+OUI:A88808*
+ ID_OUI_FROM_DATABASE=Apple
+
OUI:A88CEE*
ID_OUI_FROM_DATABASE=MicroMade Galka i Drozdz sp.j.
+OUI:A88D7B*
+ ID_OUI_FROM_DATABASE=SunDroid Global limited.
+
OUI:A8922C*
ID_OUI_FROM_DATABASE=LG Electronics
@@ -61105,6 +62800,9 @@ OUI:A8B0AE*
OUI:A8B1D4*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
+OUI:A8BBCF*
+ ID_OUI_FROM_DATABASE=Apple
+
OUI:A8BD1A*
ID_OUI_FROM_DATABASE=Honey Bee (Hong Kong) Limited
@@ -61114,6 +62812,9 @@ OUI:A8C222*
OUI:A8CB95*
ID_OUI_FROM_DATABASE=EAST BEST CO., LTD.
+OUI:A8CCC5*
+ ID_OUI_FROM_DATABASE=Saab AB (publ)
+
OUI:A8CE90*
ID_OUI_FROM_DATABASE=CVC
@@ -61207,6 +62908,9 @@ OUI:AC199F*
OUI:AC20AA*
ID_OUI_FROM_DATABASE=DMATEK Co., Ltd.
+OUI:AC220B*
+ ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
+
OUI:AC2FA8*
ID_OUI_FROM_DATABASE=Humannix Co.,Ltd.
@@ -61255,6 +62959,9 @@ OUI:AC4E91*
OUI:AC4FFC*
ID_OUI_FROM_DATABASE=SVS-VISTEK GmbH
+OUI:AC5036*
+ ID_OUI_FROM_DATABASE=Pi-Coral Inc
+
OUI:AC5135*
ID_OUI_FROM_DATABASE=MPI TECH
@@ -61303,6 +63010,9 @@ OUI:AC7A42*
OUI:AC7BA1*
ID_OUI_FROM_DATABASE=Intel Corporate
+OUI:AC7F3E*
+ ID_OUI_FROM_DATABASE=Apple
+
OUI:AC80D6*
ID_OUI_FROM_DATABASE=Hexatronic AB
@@ -61318,6 +63028,9 @@ OUI:AC8317*
OUI:AC83F0*
ID_OUI_FROM_DATABASE=ImmediaTV Corporation
+OUI:AC853D*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:AC8674*
ID_OUI_FROM_DATABASE=Open Mesh, Inc.
@@ -61381,6 +63094,9 @@ OUI:ACC935*
OUI:ACCA54*
ID_OUI_FROM_DATABASE=Telldus Technologies AB
+OUI:ACCA8E*
+ ID_OUI_FROM_DATABASE=ODA Technologies
+
OUI:ACCABA*
ID_OUI_FROM_DATABASE=Midokura Co., Ltd.
@@ -61402,6 +63118,9 @@ OUI:ACD180*
OUI:ACD364*
ID_OUI_FROM_DATABASE=ABB SPA, ABB SACE DIV.
+OUI:ACD657*
+ ID_OUI_FROM_DATABASE=Shaanxi Guolian Digital TV Technology Co., Ltd.
+
OUI:ACD9D6*
ID_OUI_FROM_DATABASE=tci GmbH
@@ -61414,6 +63133,9 @@ OUI:ACE215*
OUI:ACE348*
ID_OUI_FROM_DATABASE=MadgeTech, Inc
+OUI:ACE42E*
+ ID_OUI_FROM_DATABASE=SK hynix
+
OUI:ACE64B*
ID_OUI_FROM_DATABASE=Shenzhen Baojia Battery Technology Co., Ltd.
@@ -61450,6 +63172,9 @@ OUI:ACF7F3*
OUI:ACF97E*
ID_OUI_FROM_DATABASE=ELESYS INC.
+OUI:B00594*
+ ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+
OUI:B01203*
ID_OUI_FROM_DATABASE=Dynamics Hong Kong Limited
@@ -61480,6 +63205,9 @@ OUI:B03850*
OUI:B0435D*
ID_OUI_FROM_DATABASE=NuLEDs, Inc.
+OUI:B04545*
+ ID_OUI_FROM_DATABASE=YACOUB Automation GmbH
+
OUI:B046FC*
ID_OUI_FROM_DATABASE=MitraStar Technology Corp.
@@ -61508,7 +63236,7 @@ OUI:B06563*
ID_OUI_FROM_DATABASE=Shanghai Railway Communication Factory
OUI:B065BD*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:B06CBF*
ID_OUI_FROM_DATABASE=3ality Digital Systems GmbH
@@ -61520,7 +63248,10 @@ OUI:B075D5*
ID_OUI_FROM_DATABASE=ZTE Corporation
OUI:B077AC*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:B07908*
+ ID_OUI_FROM_DATABASE=Cummings Engineering
OUI:B0793C*
ID_OUI_FROM_DATABASE=Revolv Inc
@@ -61564,6 +63295,9 @@ OUI:B09AE2*
OUI:B09BD4*
ID_OUI_FROM_DATABASE=GNH Software India Private Limited
+OUI:B09FBA*
+ ID_OUI_FROM_DATABASE=Apple
+
OUI:B0A10A*
ID_OUI_FROM_DATABASE=Pivotal Systems Corporation
@@ -61618,6 +63352,9 @@ OUI:B0C8AD*
OUI:B0C95B*
ID_OUI_FROM_DATABASE=Beijing Symtech CO.,LTD
+OUI:B0CE18*
+ ID_OUI_FROM_DATABASE=Zhejiang shenghui lighting co.,Ltd
+
OUI:B0CF4D*
ID_OUI_FROM_DATABASE=MI-Zone Technology Ireland
@@ -61627,6 +63364,9 @@ OUI:B0D09C*
OUI:B0D2F5*
ID_OUI_FROM_DATABASE=Vello Systems, Inc.
+OUI:B0DF3A*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:B0E39D*
ID_OUI_FROM_DATABASE=CAT SYSTEM CO.,LTD.
@@ -61696,6 +63436,9 @@ OUI:B4211D*
OUI:B4218A*
ID_OUI_FROM_DATABASE=Dog Hunter LLC
+OUI:B424E7*
+ ID_OUI_FROM_DATABASE=Codetek Technology Co.,Ltd
+
OUI:B428F1*
ID_OUI_FROM_DATABASE=E-Prime Co., Ltd.
@@ -61726,6 +63469,9 @@ OUI:B439D6*
OUI:B43DB2*
ID_OUI_FROM_DATABASE=Degreane Horizon
+OUI:B43E3B*
+ ID_OUI_FROM_DATABASE=Viableware, Inc
+
OUI:B4417A*
ID_OUI_FROM_DATABASE=ShenZhen Gongjin Electronics Co.,Ltd
@@ -61741,6 +63487,9 @@ OUI:B45253*
OUI:B4527D*
ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+OUI:B4527E*
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+
OUI:B45570*
ID_OUI_FROM_DATABASE=Borea
@@ -61759,18 +63508,27 @@ OUI:B46238*
OUI:B46293*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:B462AD*
+ ID_OUI_FROM_DATABASE=raytest GmbH
+
OUI:B467E9*
ID_OUI_FROM_DATABASE=Qingdao GoerTek Technology Co., Ltd.
OUI:B4749F*
ID_OUI_FROM_DATABASE=askey computer corp
+OUI:B4750E*
+ ID_OUI_FROM_DATABASE=Belkin International Inc.
+
OUI:B47F5E*
ID_OUI_FROM_DATABASE=Foresight Manufacture (S) Pte Ltd
OUI:B48255*
ID_OUI_FROM_DATABASE=Research Products Corporation
+OUI:B4827B*
+ ID_OUI_FROM_DATABASE=AKG Acoustics GmbH
+
OUI:B482C5*
ID_OUI_FROM_DATABASE=Relay2, Inc.
@@ -61804,6 +63562,9 @@ OUI:B4A4E3*
OUI:B4A5A9*
ID_OUI_FROM_DATABASE=MODI GmbH
+OUI:B4A82B*
+ ID_OUI_FROM_DATABASE=Histar
+
OUI:B4A95A*
ID_OUI_FROM_DATABASE=Avaya, Inc
@@ -61840,6 +63601,9 @@ OUI:B4C799*
OUI:B4C810*
ID_OUI_FROM_DATABASE=UMPI Elettronica
+OUI:B4CCE9*
+ ID_OUI_FROM_DATABASE=PROSYST
+
OUI:B4CFDB*
ID_OUI_FROM_DATABASE=Shenzhen Jiuzhou Electric Co.,LTD
@@ -61901,10 +63665,10 @@ OUI:B81413*
ID_OUI_FROM_DATABASE=Keen High Holding(HK) Ltd.
OUI:B81619*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:B817C2*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:B81999*
ID_OUI_FROM_DATABASE=Nesys
@@ -61918,6 +63682,9 @@ OUI:B82410*
OUI:B8241A*
ID_OUI_FROM_DATABASE=SWEDA INFORMATICA LTDA
+OUI:B8266C*
+ ID_OUI_FROM_DATABASE=ANOV France
+
OUI:B826D4*
ID_OUI_FROM_DATABASE=Furukawa Industrial S.A. Produtos Elétricos
@@ -61957,6 +63724,9 @@ OUI:B83E59*
OUI:B8415F*
ID_OUI_FROM_DATABASE=ASP AG
+OUI:B847C6*
+ ID_OUI_FROM_DATABASE=SanJet Technology Corp.
+
OUI:B85510*
ID_OUI_FROM_DATABASE=Zioncom Electronics (Shenzhen) Ltd.
@@ -61969,6 +63739,9 @@ OUI:B85AF7*
OUI:B85AFE*
ID_OUI_FROM_DATABASE=Handaer Communication Technology (Beijing) Co., Ltd
+OUI:B85E7B*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:B86091*
ID_OUI_FROM_DATABASE=Onnet Technologies and Innovations LLC
@@ -62014,6 +63787,9 @@ OUI:B8797E*
OUI:B8871E*
ID_OUI_FROM_DATABASE=Good Mind Industries Co., Ltd.
+OUI:B887A8*
+ ID_OUI_FROM_DATABASE=Step Ahead Innovations Inc.
+
OUI:B888E3*
ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD
@@ -62024,7 +63800,7 @@ OUI:B88A60*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:B88D12*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:B88E3A*
ID_OUI_FROM_DATABASE=Infinite Technologies JLT
@@ -62095,6 +63871,9 @@ OUI:B8BB6D*
OUI:B8BEBF*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
+OUI:B8C1A2*
+ ID_OUI_FROM_DATABASE=Dragon Path Technologies Co., Limited
+
OUI:B8C46F*
ID_OUI_FROM_DATABASE=PRIMMCON INDUSTRIES INC
@@ -62105,7 +63884,7 @@ OUI:B8C716*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
OUI:B8C75D*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:B8C855*
ID_OUI_FROM_DATABASE=Shanghai GBCOM Communication Technology Co.,Ltd.
@@ -62134,6 +63913,12 @@ OUI:B8DAF1*
OUI:B8DAF7*
ID_OUI_FROM_DATABASE=Advanced Photonics, Inc.
+OUI:B8DC87*
+ ID_OUI_FROM_DATABASE=IAI Corporation
+
+OUI:B8DF6B*
+ ID_OUI_FROM_DATABASE=SpotCam Co., Ltd.
+
OUI:B8E589*
ID_OUI_FROM_DATABASE=Payter BV
@@ -62143,6 +63928,9 @@ OUI:B8E625*
OUI:B8E779*
ID_OUI_FROM_DATABASE=9Solutions Oy
+OUI:B8E856*
+ ID_OUI_FROM_DATABASE=Apple
+
OUI:B8E937*
ID_OUI_FROM_DATABASE=Sonos, Inc.
@@ -62156,11 +63944,14 @@ OUI:B8F5E7*
ID_OUI_FROM_DATABASE=WayTools, LLC
OUI:B8F6B1*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:B8F732*
ID_OUI_FROM_DATABASE=Aryaka Networks Inc
+OUI:B8F828*
+ ID_OUI_FROM_DATABASE=Changshu Gaoshida Optoelectronic Technology Co. Ltd.
+
OUI:B8F934*
ID_OUI_FROM_DATABASE=Sony Ericsson Mobile Communications AB
@@ -62168,7 +63959,7 @@ OUI:B8FD32*
ID_OUI_FROM_DATABASE=Zhejiang ROICX Microelectronics
OUI:B8FF61*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:B8FF6F*
ID_OUI_FROM_DATABASE=Shanghai Typrotech Technology Co.Ltd
@@ -62215,9 +64006,18 @@ OUI:BC2846*
OUI:BC28D6*
ID_OUI_FROM_DATABASE=Rowley Associates Limited
+OUI:BC2B6B*
+ ID_OUI_FROM_DATABASE=Beijing Haier IC Design Co.,Ltd
+
+OUI:BC2BD7*
+ ID_OUI_FROM_DATABASE=Revogi Innovation Co., Ltd.
+
OUI:BC2C55*
ID_OUI_FROM_DATABASE=Bear Flag Design, Inc.
+OUI:BC2D98*
+ ID_OUI_FROM_DATABASE=ThinGlobal LLC
+
OUI:BC305B*
ID_OUI_FROM_DATABASE=Dell Inc.
@@ -62236,9 +64036,15 @@ OUI:BC3BAF*
OUI:BC3E13*
ID_OUI_FROM_DATABASE=Accordance Systems Inc.
+OUI:BC4100*
+ ID_OUI_FROM_DATABASE=Codaco Electronic s.r.o.
+
OUI:BC4377*
ID_OUI_FROM_DATABASE=Hang Zhou Huite Technology Co.,ltd.
+OUI:BC4486*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:BC4760*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
@@ -62252,7 +64058,7 @@ OUI:BC51FE*
ID_OUI_FROM_DATABASE=Swann Communications Pty Ltd
OUI:BC52B7*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:BC5FF4*
ID_OUI_FROM_DATABASE=ASRock Incorporation
@@ -62261,7 +64067,7 @@ OUI:BC629F*
ID_OUI_FROM_DATABASE=Telenet Systems P. Ltd.
OUI:BC6778*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:BC6784*
ID_OUI_FROM_DATABASE=Environics Oy
@@ -62314,12 +64120,24 @@ OUI:BC851F*
OUI:BC8556*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:BC8893*
+ ID_OUI_FROM_DATABASE=VILLBAU Ltd.
+
OUI:BC8B55*
ID_OUI_FROM_DATABASE=NPP ELIKS America Inc. DBA T&M Atlantic
+OUI:BC8CCD*
+ ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co.,LTD.
+
OUI:BC926B*
ID_OUI_FROM_DATABASE=Apple
+OUI:BC9680*
+ ID_OUI_FROM_DATABASE=Shenzhen Gongjin Electronics Co.,Ltd
+
+OUI:BC9889*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
+
OUI:BC99BC*
ID_OUI_FROM_DATABASE=FonSee Technology Inc.
@@ -62392,6 +64210,9 @@ OUI:BCEA2B*
OUI:BCF2AF*
ID_OUI_FROM_DATABASE=devolo AG
+OUI:BCF5AC*
+ ID_OUI_FROM_DATABASE=LG Electronics
+
OUI:BCF685*
ID_OUI_FROM_DATABASE=D-Link International
@@ -62422,6 +64243,9 @@ OUI:C01E9B*
OUI:C02506*
ID_OUI_FROM_DATABASE=AVM GmbH
+OUI:C0255C*
+ ID_OUI_FROM_DATABASE=Cisco
+
OUI:C027B9*
ID_OUI_FROM_DATABASE=Beijing National Railway Research & Design Institute of Signal & Communication Co., Ltd.
@@ -62440,6 +64264,9 @@ OUI:C02C7A*
OUI:C034B4*
ID_OUI_FROM_DATABASE=Gigastone Corporation
+OUI:C03580*
+ ID_OUI_FROM_DATABASE=A&R TECH
+
OUI:C035BD*
ID_OUI_FROM_DATABASE=Velocytech Aps
@@ -62458,6 +64285,9 @@ OUI:C03F0E*
OUI:C03F2A*
ID_OUI_FROM_DATABASE=Biscotti, Inc.
+OUI:C03FD5*
+ ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co., LTD
+
OUI:C041F6*
ID_OUI_FROM_DATABASE=LG Electronics Inc
@@ -62476,6 +64306,9 @@ OUI:C04A00*
OUI:C04DF7*
ID_OUI_FROM_DATABASE=SERELEC
+OUI:C057BC*
+ ID_OUI_FROM_DATABASE=Avaya, Inc
+
OUI:C058A7*
ID_OUI_FROM_DATABASE=Pico Systems Co., Ltd.
@@ -62488,15 +64321,24 @@ OUI:C05E79*
OUI:C0626B*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
+OUI:C06394*
+ ID_OUI_FROM_DATABASE=Apple
+
OUI:C06599*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:C067AF*
+ ID_OUI_FROM_DATABASE=Cisco
+
OUI:C06C0F*
ID_OUI_FROM_DATABASE=Dobbs Stanford
OUI:C06C6D*
ID_OUI_FROM_DATABASE=MagneMotion, Inc.
+OUI:C07BBC*
+ ID_OUI_FROM_DATABASE=Cisco
+
OUI:C07E40*
ID_OUI_FROM_DATABASE=SHENZHEN XDK COMMUNICATION EQUIPMENT CO.,LTD
@@ -62507,7 +64349,7 @@ OUI:C0830A*
ID_OUI_FROM_DATABASE=2Wire
OUI:C0847A*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:C0885B*
ID_OUI_FROM_DATABASE=SnD Tech Co., Ltd.
@@ -62518,17 +64360,26 @@ OUI:C08ADE*
OUI:C08B6F*
ID_OUI_FROM_DATABASE=S I Sistemas Inteligentes Eletrônicos Ltda
+OUI:C08C60*
+ ID_OUI_FROM_DATABASE=Cisco
+
OUI:C09132*
ID_OUI_FROM_DATABASE=Patriot Memory
OUI:C09134*
ID_OUI_FROM_DATABASE=ProCurve Networking by HP
+OUI:C098E5*
+ ID_OUI_FROM_DATABASE=University of Michigan
+
OUI:C09C92*
ID_OUI_FROM_DATABASE=COBY
OUI:C09F42*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
+
+OUI:C0A0BB*
+ ID_OUI_FROM_DATABASE=D-Link International
OUI:C0A0C7*
ID_OUI_FROM_DATABASE=FAIRFIELD INDUSTRIES
@@ -62545,6 +64396,9 @@ OUI:C0A26D*
OUI:C0A364*
ID_OUI_FROM_DATABASE=3D Systems Massachusetts
+OUI:C0A39E*
+ ID_OUI_FROM_DATABASE=EarthCam, Inc.
+
OUI:C0AA68*
ID_OUI_FROM_DATABASE=OSASI Technos Inc.
@@ -62575,6 +64429,9 @@ OUI:C0C3B6*
OUI:C0C520*
ID_OUI_FROM_DATABASE=Ruckus Wireless
+OUI:C0C687*
+ ID_OUI_FROM_DATABASE=Cisco SPVTG
+
OUI:C0C946*
ID_OUI_FROM_DATABASE=MITSUYA LABORATORIES INC.
@@ -62608,6 +64465,9 @@ OUI:C0EAE4*
OUI:C0F8DA*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:C0F991*
+ ID_OUI_FROM_DATABASE=GME Standard Communications P/L
+
OUI:C40142*
ID_OUI_FROM_DATABASE=MaxMedia Technology Limited
@@ -62617,6 +64477,12 @@ OUI:C4017C*
OUI:C401B1*
ID_OUI_FROM_DATABASE=SeekTech INC
+OUI:C40415*
+ ID_OUI_FROM_DATABASE=NETGEAR INC.,
+
+OUI:C40938*
+ ID_OUI_FROM_DATABASE=Fujian Star-net Communication Co., Ltd
+
OUI:C40ACB*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
@@ -62641,6 +64507,9 @@ OUI:C419EC*
OUI:C41ECE*
ID_OUI_FROM_DATABASE=HMI Sources Ltd.
+OUI:C421C8*
+ ID_OUI_FROM_DATABASE=KYOCERA Corporation
+
OUI:C4237A*
ID_OUI_FROM_DATABASE=WhizNets Inc.
@@ -62650,8 +64519,11 @@ OUI:C4242E*
OUI:C42628*
ID_OUI_FROM_DATABASE=Airo Wireless
+OUI:C42795*
+ ID_OUI_FROM_DATABASE=Technicolor USA Inc.
+
OUI:C42C03*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:C436DA*
ID_OUI_FROM_DATABASE=Rusteletech Ltd.
@@ -62677,6 +64549,9 @@ OUI:C4438F*
OUI:C44567*
ID_OUI_FROM_DATABASE=SAMBON PRECISON and ELECTRONICS
+OUI:C445EC*
+ ID_OUI_FROM_DATABASE=Shanghai Yali Electron Co.,LTD
+
OUI:C44619*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
@@ -62708,7 +64583,7 @@ OUI:C458C2*
ID_OUI_FROM_DATABASE=Shenzhen TATFOOK Technology Co., Ltd.
OUI:C45976*
- ID_OUI_FROM_DATABASE=Fugoo
+ ID_OUI_FROM_DATABASE=Fugoo Coorporation
OUI:C45DD8*
ID_OUI_FROM_DATABASE=HDMI Forum
@@ -62716,6 +64591,9 @@ OUI:C45DD8*
OUI:C46044*
ID_OUI_FROM_DATABASE=Everex Electronics Limited
+OUI:C462EA*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:C46354*
ID_OUI_FROM_DATABASE=U-Raku, Inc.
@@ -62731,6 +64609,9 @@ OUI:C46AB7*
OUI:C46DF1*
ID_OUI_FROM_DATABASE=DataGravity
+OUI:C46E1F*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD
+
OUI:C47130*
ID_OUI_FROM_DATABASE=Fon Technology S.L.
@@ -62773,6 +64654,9 @@ OUI:C49300*
OUI:C49313*
ID_OUI_FROM_DATABASE=100fio networks technology llc
+OUI:C49380*
+ ID_OUI_FROM_DATABASE=Speedytel technology
+
OUI:C495A2*
ID_OUI_FROM_DATABASE=SHENZHEN WEIJIU INDUSTRY AND TRADE DEVELOPMENT CO., LTD
@@ -62806,6 +64690,9 @@ OUI:C4CD45*
OUI:C4D489*
ID_OUI_FROM_DATABASE=JiangSu Joyque Information Industry Co.,Ltd
+OUI:C4D655*
+ ID_OUI_FROM_DATABASE=Tercel technology co.,ltd
+
OUI:C4D987*
ID_OUI_FROM_DATABASE=Intel Corporate
@@ -62821,6 +64708,9 @@ OUI:C4E17C*
OUI:C4E7BE*
ID_OUI_FROM_DATABASE=SCSpro Co.,Ltd
+OUI:C4E92F*
+ ID_OUI_FROM_DATABASE=AB Sciex
+
OUI:C4EBE3*
ID_OUI_FROM_DATABASE=RRCN SAS
@@ -62860,6 +64750,9 @@ OUI:C80E77*
OUI:C80E95*
ID_OUI_FROM_DATABASE=OmniLync Inc.
+OUI:C81479*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:C819F7*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
@@ -62879,7 +64772,7 @@ OUI:C8292A*
ID_OUI_FROM_DATABASE=Barun Electronics
OUI:C82A14*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:C82E94*
ID_OUI_FROM_DATABASE=Halfa Enterprise Co., Ltd.
@@ -62888,7 +64781,7 @@ OUI:C83232*
ID_OUI_FROM_DATABASE=Hunting Innova
OUI:C8334B*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:C835B8*
ID_OUI_FROM_DATABASE=Ericsson, EAB/RWI/K
@@ -62923,6 +64816,9 @@ OUI:C84C75*
OUI:C85645*
ID_OUI_FROM_DATABASE=Intermas France
+OUI:C85663*
+ ID_OUI_FROM_DATABASE=Sunflex Europe GmbH
+
OUI:C86000*
ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
@@ -63014,7 +64910,7 @@ OUI:C8A729*
ID_OUI_FROM_DATABASE=SYStronics Co., Ltd.
OUI:C8AA21*
- ID_OUI_FROM_DATABASE=Motorola Mobility, LLC.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:C8AE9C*
ID_OUI_FROM_DATABASE=Shanghai TYD Elecronic Technology Co. Ltd
@@ -63025,11 +64921,14 @@ OUI:C8AF40*
OUI:C8B373*
ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC
+OUI:C8B5B7*
+ ID_OUI_FROM_DATABASE=Apple
+
OUI:C8BBD3*
ID_OUI_FROM_DATABASE=Embrane
OUI:C8BCC8*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:C8BE19*
ID_OUI_FROM_DATABASE=D-Link International
@@ -63088,12 +64987,18 @@ OUI:C8E1A7*
OUI:C8EE08*
ID_OUI_FROM_DATABASE=TANGTOP TECHNOLOGY CO.,LTD
+OUI:C8EE75*
+ ID_OUI_FROM_DATABASE=Pishion International Co. Ltd
+
OUI:C8EEA6*
ID_OUI_FROM_DATABASE=Shenzhen SHX Technology Co., Ltd
OUI:C8EF2E*
ID_OUI_FROM_DATABASE=Beijing Gefei Tech. Co., Ltd
+OUI:C8F36B*
+ ID_OUI_FROM_DATABASE=Yamato Scale Co.,Ltd.
+
OUI:C8F386*
ID_OUI_FROM_DATABASE=Shenzhen Xiaoniao Technology Co.,Ltd
@@ -63130,8 +65035,11 @@ OUI:CC04B4*
OUI:CC051B*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:CC07AB*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:CC08E0*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:CC09C8*
ID_OUI_FROM_DATABASE=IMAQLIQ LTD
@@ -63160,15 +65068,24 @@ OUI:CC2218*
OUI:CC262D*
ID_OUI_FROM_DATABASE=Verifi, LLC
+OUI:CC2A80*
+ ID_OUI_FROM_DATABASE=Micro-Biz intelligence solutions Co.,Ltd
+
OUI:CC2D8C*
ID_OUI_FROM_DATABASE=LG ELECTRONICS INC
OUI:CC33BB*
ID_OUI_FROM_DATABASE=SAGEMCOM SAS
+OUI:CC3429*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
OUI:CC34D7*
ID_OUI_FROM_DATABASE=GEWISS S.P.A.
+OUI:CC3540*
+ ID_OUI_FROM_DATABASE=Technicolor USA Inc.
+
OUI:CC3A61*
ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD.
@@ -63181,6 +65098,12 @@ OUI:CC3E5F*
OUI:CC43E3*
ID_OUI_FROM_DATABASE=Trump s.a.
+OUI:CC4703*
+ ID_OUI_FROM_DATABASE=Intercon Systems Co., Ltd.
+
+OUI:CC4AE1*
+ ID_OUI_FROM_DATABASE=Fourtec -Fourier Technologies
+
OUI:CC4BFB*
ID_OUI_FROM_DATABASE=Hellberg Safety AB
@@ -63235,6 +65158,12 @@ OUI:CC6DA0*
OUI:CC6DEF*
ID_OUI_FROM_DATABASE=TJK Tietolaite Oy
+OUI:CC720F*
+ ID_OUI_FROM_DATABASE=Viscount Systems Inc.
+
+OUI:CC7498*
+ ID_OUI_FROM_DATABASE=Filmetrics Inc.
+
OUI:CC7669*
ID_OUI_FROM_DATABASE=SEETECH
@@ -63244,8 +65173,11 @@ OUI:CC785F*
OUI:CC7A30*
ID_OUI_FROM_DATABASE=CMAX Wireless Co., Ltd.
+OUI:CC7B35*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:CC7D37*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:CC7EE7*
ID_OUI_FROM_DATABASE=Panasonic AVC Networks Company
@@ -63355,6 +65287,9 @@ OUI:CCEF48*
OUI:CCF3A5*
ID_OUI_FROM_DATABASE=Chi Mei Communication Systems, Inc
+OUI:CCF407*
+ ID_OUI_FROM_DATABASE=EUKREA ELECTROMATIQUE SARL
+
OUI:CCF67A*
ID_OUI_FROM_DATABASE=Ayecka Communication Systems LTD
@@ -63370,6 +65305,9 @@ OUI:CCF954*
OUI:CCF9E8*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:CCFB65*
+ ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
+
OUI:CCFC6D*
ID_OUI_FROM_DATABASE=RIZ TRANSMITTERS
@@ -63400,12 +65338,18 @@ OUI:D01AA7*
OUI:D01CBB*
ID_OUI_FROM_DATABASE=Beijing Ctimes Digital Technology Co., Ltd.
+OUI:D022BE*
+ ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co.,LTD.
+
OUI:D023DB*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:D02788*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind.Co.Ltd
+OUI:D02C45*
+ ID_OUI_FROM_DATABASE=littleBits Electronics, Inc.
+
OUI:D02DB3*
ID_OUI_FROM_DATABASE=Huawei Technologies Co., Ltd
@@ -63415,6 +65359,9 @@ OUI:D03110*
OUI:D03761*
ID_OUI_FROM_DATABASE=Texas Instruments
+OUI:D03972*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
OUI:D046DC*
ID_OUI_FROM_DATABASE=Southwest Research Institute
@@ -63463,6 +65410,9 @@ OUI:D067E5*
OUI:D0699E*
ID_OUI_FROM_DATABASE=LUMINEX Lighting Control Equipment
+OUI:D0737F*
+ ID_OUI_FROM_DATABASE=Mini-Circuits
+
OUI:D0738E*
ID_OUI_FROM_DATABASE=DONG OH PRECISION CO., LTD.
@@ -63481,6 +65431,9 @@ OUI:D07E28*
OUI:D08999*
ID_OUI_FROM_DATABASE=APCON, Inc.
+OUI:D08A55*
+ ID_OUI_FROM_DATABASE=Skullcandy
+
OUI:D08B7E*
ID_OUI_FROM_DATABASE=Passif Semiconductor
@@ -63493,9 +65446,15 @@ OUI:D08CFF*
OUI:D093F8*
ID_OUI_FROM_DATABASE=Stonestreet One LLC
+OUI:D095C7*
+ ID_OUI_FROM_DATABASE=Pantech Co., Ltd.
+
OUI:D09B05*
ID_OUI_FROM_DATABASE=Emtronix
+OUI:D09D0A*
+ ID_OUI_FROM_DATABASE=LINKCOM
+
OUI:D0A311*
ID_OUI_FROM_DATABASE=Neuberger Gebäudeautomation GmbH
@@ -63511,6 +65470,9 @@ OUI:D0B33F*
OUI:D0B498*
ID_OUI_FROM_DATABASE=Robert Bosch LLC Automotive Electronics
+OUI:D0B523*
+ ID_OUI_FROM_DATABASE=Bestcare Cloucal Corp.
+
OUI:D0B53D*
ID_OUI_FROM_DATABASE=SEPRO ROBOTIQUE
@@ -63526,6 +65488,9 @@ OUI:D0C1B1*
OUI:D0C282*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
+OUI:D0C42F*
+ ID_OUI_FROM_DATABASE=Tamagawa Seiki Co.,Ltd.
+
OUI:D0C789*
ID_OUI_FROM_DATABASE=Cisco
@@ -63595,6 +65560,9 @@ OUI:D0F27F*
OUI:D0F73B*
ID_OUI_FROM_DATABASE=Helmut Mauell GmbH
+OUI:D0FF50*
+ ID_OUI_FROM_DATABASE=Texas Instruments, Inc
+
OUI:D4000D*
ID_OUI_FROM_DATABASE=Phoenix Broadband Technologies, LLC.
@@ -63682,6 +65650,9 @@ OUI:D44B5E*
OUI:D44C24*
ID_OUI_FROM_DATABASE=Vuppalamritha Magnetic Components LTD
+OUI:D44C9C*
+ ID_OUI_FROM_DATABASE=Shenzhen YOOBAO Technology Co.Ltd
+
OUI:D44CA7*
ID_OUI_FROM_DATABASE=Informtekhnika & Communication, LLC
@@ -63718,9 +65689,15 @@ OUI:D466A8*
OUI:D467E7*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
+OUI:D46867*
+ ID_OUI_FROM_DATABASE=Neoventus Design Group
+
OUI:D46A91*
ID_OUI_FROM_DATABASE=Snap AV
+OUI:D46AA8*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:D46CBF*
ID_OUI_FROM_DATABASE=Goodrich ISR
@@ -63776,7 +65753,7 @@ OUI:D496DF*
ID_OUI_FROM_DATABASE=SUNGJIN C&T CO.,LTD
OUI:D49A20*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:D49C28*
ID_OUI_FROM_DATABASE=JayBird Gear LLC
@@ -63805,6 +65782,9 @@ OUI:D4AAFF*
OUI:D4AC4E*
ID_OUI_FROM_DATABASE=BODi rS, LLC
+OUI:D4AD2D*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
+
OUI:D4AE52*
ID_OUI_FROM_DATABASE=Dell Inc
@@ -63856,6 +65836,9 @@ OUI:D4D748*
OUI:D4D898*
ID_OUI_FROM_DATABASE=Korea CNO Tech Co., Ltd
+OUI:D4D919*
+ ID_OUI_FROM_DATABASE=GoPro
+
OUI:D4DF57*
ID_OUI_FROM_DATABASE=Alpinion Medical Systems
@@ -63931,6 +65914,9 @@ OUI:D824BD*
OUI:D826B9*
ID_OUI_FROM_DATABASE=Guangdong Coagent Electronics S &T Co., Ltd.
+OUI:D8270C*
+ ID_OUI_FROM_DATABASE=MaxTronic International Co., Ltd.
+
OUI:D828C9*
ID_OUI_FROM_DATABASE=General Electric Consumer and Industrial
@@ -63943,11 +65929,14 @@ OUI:D82986*
OUI:D82A7E*
ID_OUI_FROM_DATABASE=Nokia Corporation
+OUI:D82D9B*
+ ID_OUI_FROM_DATABASE=Shenzhen G.Credit Communication Technology Co., Ltd
+
OUI:D82DE1*
ID_OUI_FROM_DATABASE=Tricascade Inc.
OUI:D83062*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:D831CF*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
@@ -63961,9 +65950,15 @@ OUI:D842AC*
OUI:D84606*
ID_OUI_FROM_DATABASE=Silicon Valley Global Marketing
+OUI:D8490B*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
OUI:D84B2A*
ID_OUI_FROM_DATABASE=Cognitas Technologies, Inc.
+OUI:D850E6*
+ ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
+
OUI:D8543A*
ID_OUI_FROM_DATABASE=Texas Instruments
@@ -63985,6 +65980,9 @@ OUI:D866C6*
OUI:D867D9*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
+OUI:D86960*
+ ID_OUI_FROM_DATABASE=Steinsvik
+
OUI:D86BF7*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
@@ -64009,12 +66007,18 @@ OUI:D87988*
OUI:D88A3B*
ID_OUI_FROM_DATABASE=UNIT-EM
+OUI:D890E8*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:D8952F*
ID_OUI_FROM_DATABASE=Texas Instruments
OUI:D89685*
ID_OUI_FROM_DATABASE=GoPro
+OUI:D89695*
+ ID_OUI_FROM_DATABASE=Apple
+
OUI:D8973B*
ID_OUI_FROM_DATABASE=Emerson Network Power Embedded Power
@@ -64028,10 +66032,10 @@ OUI:D89DB9*
ID_OUI_FROM_DATABASE=eMegatech International Corp.
OUI:D89E3F*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:D8A25E*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:D8AE90*
ID_OUI_FROM_DATABASE=Itibia Technologies
@@ -64138,6 +66142,9 @@ OUI:DC0265*
OUI:DC028E*
ID_OUI_FROM_DATABASE=zte corporation
+OUI:DC0575*
+ ID_OUI_FROM_DATABASE=SIEMENS ENERGY AUTOMATION
+
OUI:DC05ED*
ID_OUI_FROM_DATABASE=Nabtesco Corporation
@@ -64156,6 +66163,9 @@ OUI:DC16A2*
OUI:DC175A*
ID_OUI_FROM_DATABASE=Hitachi High-Technologies Corporation
+OUI:DC1792*
+ ID_OUI_FROM_DATABASE=Captivate Network
+
OUI:DC1D9F*
ID_OUI_FROM_DATABASE=U & B tech
@@ -64172,7 +66182,7 @@ OUI:DC2A14*
ID_OUI_FROM_DATABASE=Shanghai Longjing Technology Co.
OUI:DC2B61*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:DC2B66*
ID_OUI_FROM_DATABASE=InfoBLOCK S.A. de C.V.
@@ -64207,8 +66217,11 @@ OUI:DC3C84*
OUI:DC3E51*
ID_OUI_FROM_DATABASE=Solberg & Andersen AS
+OUI:DC3EF8*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
+
OUI:DC4517*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:DC49C9*
ID_OUI_FROM_DATABASE=CASCO SIGNAL LTD
@@ -64219,9 +66232,15 @@ OUI:DC4EDE*
OUI:DC5726*
ID_OUI_FROM_DATABASE=Power-One
+OUI:DC5E36*
+ ID_OUI_FROM_DATABASE=Paterson Technology
+
OUI:DC647C*
ID_OUI_FROM_DATABASE=C.R.S. iiMotion GmbH
+OUI:DC6F00*
+ ID_OUI_FROM_DATABASE=Livescribe, Inc.
+
OUI:DC6F08*
ID_OUI_FROM_DATABASE=Bay Storage Technology
@@ -64237,6 +66256,9 @@ OUI:DC825B*
OUI:DC85DE*
ID_OUI_FROM_DATABASE=Azurewave Technologies., inc.
+OUI:DC86D8*
+ ID_OUI_FROM_DATABASE=Apple, Inc
+
OUI:DC9B1E*
ID_OUI_FROM_DATABASE=Intercom, Inc.
@@ -64249,6 +66271,9 @@ OUI:DC9FA4*
OUI:DC9FDB*
ID_OUI_FROM_DATABASE=Ubiquiti Networks, Inc.
+OUI:DCA5F4*
+ ID_OUI_FROM_DATABASE=Cisco
+
OUI:DCA6BD*
ID_OUI_FROM_DATABASE=Beijing Lanbo Technology Co., Ltd.
@@ -64264,6 +66289,12 @@ OUI:DCA971*
OUI:DCA989*
ID_OUI_FROM_DATABASE=MACANDC
+OUI:DCAD9E*
+ ID_OUI_FROM_DATABASE=GreenPriz
+
+OUI:DCAE04*
+ ID_OUI_FROM_DATABASE=CELOXICA Ltd
+
OUI:DCB058*
ID_OUI_FROM_DATABASE=Burkert Werke GmbH
@@ -64279,12 +66310,18 @@ OUI:DCC0DB*
OUI:DCC101*
ID_OUI_FROM_DATABASE=SOLiD Technologies, Inc.
+OUI:DCC422*
+ ID_OUI_FROM_DATABASE=Systembase Limited
+
OUI:DCCBA8*
ID_OUI_FROM_DATABASE=Explora Technologies Inc
OUI:DCCE41*
ID_OUI_FROM_DATABASE=FE GLOBAL HONG KONG LIMITED
+OUI:DCCEBC*
+ ID_OUI_FROM_DATABASE=Shenzhen JSR Technology Co.,Ltd.
+
OUI:DCCF94*
ID_OUI_FROM_DATABASE=Beijing Rongcheng Hutong Technology Co., Ltd.
@@ -64315,12 +66352,18 @@ OUI:DCE71C*
OUI:DCF05D*
ID_OUI_FROM_DATABASE=Letta Teknoloji
+OUI:DCF755*
+ ID_OUI_FROM_DATABASE=SITRONIK
+
OUI:DCF858*
ID_OUI_FROM_DATABASE=Lorent Networks, Inc.
OUI:DCFAD5*
ID_OUI_FROM_DATABASE=STRONG Ges.m.b.H.
+OUI:DCFB02*
+ ID_OUI_FROM_DATABASE=Buffalo Inc.
+
OUI:E005C5*
ID_OUI_FROM_DATABASE=TP-LINK Technologies Co.,Ltd.
@@ -64387,6 +66430,9 @@ OUI:E039D7*
OUI:E03C5B*
ID_OUI_FROM_DATABASE=SHENZHEN JIAXINJIE ELECTRON CO.,LTD
+OUI:E03E4A*
+ ID_OUI_FROM_DATABASE=Cavanagh Group International
+
OUI:E03E7D*
ID_OUI_FROM_DATABASE=data-complex GmbH
@@ -64396,6 +66442,9 @@ OUI:E0469A*
OUI:E05597*
ID_OUI_FROM_DATABASE=Emergent Vision Technologies Inc.
+OUI:E056F4*
+ ID_OUI_FROM_DATABASE=AxesNetwork Solutions inc.
+
OUI:E0589E*
ID_OUI_FROM_DATABASE=Laerdal Medical
@@ -64459,12 +66508,18 @@ OUI:E09467*
OUI:E09579*
ID_OUI_FROM_DATABASE=ORTHOsoft inc, d/b/a Zimmer CAS
+OUI:E097F2*
+ ID_OUI_FROM_DATABASE=Atomax Inc.
+
OUI:E09D31*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:E09DB8*
ID_OUI_FROM_DATABASE=PLANEX COMMUNICATIONS INC.
+OUI:E0A198*
+ ID_OUI_FROM_DATABASE=NOJA Power Switchgear Pty Ltd
+
OUI:E0A1D7*
ID_OUI_FROM_DATABASE=SFR
@@ -64483,9 +66538,18 @@ OUI:E0ABFE*
OUI:E0AE5E*
ID_OUI_FROM_DATABASE=ALPS Co,. Ltd.
+OUI:E0AEB2*
+ ID_OUI_FROM_DATABASE=Bender GmbH &amp; Co.KG
+
OUI:E0AEED*
ID_OUI_FROM_DATABASE=LOENK
+OUI:E0AF4B*
+ ID_OUI_FROM_DATABASE=Pluribus Networks, Inc.
+
+OUI:E0B2F1*
+ ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED
+
OUI:E0B7B1*
ID_OUI_FROM_DATABASE=Pace plc
@@ -64493,7 +66557,7 @@ OUI:E0B9A5*
ID_OUI_FROM_DATABASE=Azurewave
OUI:E0B9BA*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:E0BC43*
ID_OUI_FROM_DATABASE=C2 Microsystems, Inc.
@@ -64517,7 +66581,7 @@ OUI:E0C922*
ID_OUI_FROM_DATABASE=Jireh Energy Tech., Ltd.
OUI:E0C97A*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:E0CA4D*
ID_OUI_FROM_DATABASE=Shenzhen Unistar Communication Co.,LTD
@@ -64537,6 +66601,9 @@ OUI:E0CF2D*
OUI:E0D10A*
ID_OUI_FROM_DATABASE=Katoudenkikougyousyo co ltd
+OUI:E0D1E6*
+ ID_OUI_FROM_DATABASE=Aliph dba Jawbone
+
OUI:E0D7BA*
ID_OUI_FROM_DATABASE=Texas Instruments
@@ -64552,6 +66619,9 @@ OUI:E0DB55*
OUI:E0DCA0*
ID_OUI_FROM_DATABASE=Siemens Electrical Apparatus Ltd., Suzhou Chengdu Branch
+OUI:E0E631*
+ ID_OUI_FROM_DATABASE=SNB TECHNOLOGIES LIMITED
+
OUI:E0E751*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
@@ -64577,17 +66647,20 @@ OUI:E0F379*
ID_OUI_FROM_DATABASE=Vaddio
OUI:E0F5C6*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:E0F5CA*
ID_OUI_FROM_DATABASE=CHENG UEI PRECISION INDUSTRY CO.,LTD.
OUI:E0F847*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:E0F9BE*
ID_OUI_FROM_DATABASE=Cloudena Corp.
+OUI:E0FAEC*
+ ID_OUI_FROM_DATABASE=Platan sp. z o.o. sp. k.
+
OUI:E4115B*
ID_OUI_FROM_DATABASE=Hewlett Packard
@@ -64615,6 +66688,9 @@ OUI:E42AD3*
OUI:E42C56*
ID_OUI_FROM_DATABASE=Lilee Systems, Ltd.
+OUI:E42D02*
+ ID_OUI_FROM_DATABASE=TCT Mobile Limited
+
OUI:E42F26*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Tech.Co.,Ltd.
@@ -64639,6 +66715,9 @@ OUI:E438F2*
OUI:E43FA2*
ID_OUI_FROM_DATABASE=Wuxi DSP Technologies Inc.
+OUI:E440E2*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:E441E6*
ID_OUI_FROM_DATABASE=Ottec Technology GmbH
@@ -64667,7 +66746,7 @@ OUI:E457A8*
ID_OUI_FROM_DATABASE=Stuart Manufacturing, Inc.
OUI:E46449*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:E467BA*
ID_OUI_FROM_DATABASE=Danish Interpretation Systems A/S
@@ -64684,6 +66763,9 @@ OUI:E47185*
OUI:E4751E*
ID_OUI_FROM_DATABASE=Getinge Sterilization AB
+OUI:E47723*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:E4776B*
ID_OUI_FROM_DATABASE=AARTESYS AG
@@ -64700,7 +66782,7 @@ OUI:E481B3*
ID_OUI_FROM_DATABASE=Shenzhen ACT Industrial Co.,Ltd.
OUI:E48399*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:E48AD5*
ID_OUI_FROM_DATABASE=RF WINDOW CO., LTD.
@@ -64714,12 +66796,18 @@ OUI:E49069*
OUI:E492E7*
ID_OUI_FROM_DATABASE=Gridlink Tech. Co.,Ltd.
+OUI:E492FB*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:E496AE*
ID_OUI_FROM_DATABASE=ALTOGRAPHICS Inc.
OUI:E497F0*
ID_OUI_FROM_DATABASE=Shanghai VLC Technologies Ltd. Co.
+OUI:E498D6*
+ ID_OUI_FROM_DATABASE=Apple, Inc
+
OUI:E4A5EF*
ID_OUI_FROM_DATABASE=TRON LINK ELECTRONICS CO., LTD.
@@ -64741,14 +66829,20 @@ OUI:E4B021*
OUI:E4C146*
ID_OUI_FROM_DATABASE=Objetivos y Servicios de Valor A
+OUI:E4C63D*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:E4C6E6*
ID_OUI_FROM_DATABASE=Mophie, LLC
+OUI:E4C722*
+ ID_OUI_FROM_DATABASE=Cisco
+
OUI:E4C806*
ID_OUI_FROM_DATABASE=Ceiec Electric Technology Inc.
OUI:E4CE8F*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:E4D3F1*
ID_OUI_FROM_DATABASE=Cisco
@@ -64793,7 +66887,7 @@ OUI:E8039A*
ID_OUI_FROM_DATABASE=Samsung Electronics CO., LTD
OUI:E8040B*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:E80462*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
@@ -64805,7 +66899,7 @@ OUI:E8056D*
ID_OUI_FROM_DATABASE=Nortel Networks
OUI:E80688*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:E80B13*
ID_OUI_FROM_DATABASE=Akib Systems Taiwan, INC
@@ -64870,9 +66964,15 @@ OUI:E8481F*
OUI:E84E06*
ID_OUI_FROM_DATABASE=EDUP INTERNATIONAL (HK) CO., LTD
+OUI:E84E84*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:E84ECE*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
+OUI:E8516E*
+ ID_OUI_FROM_DATABASE=TSMART Inc.
+
OUI:E8519D*
ID_OUI_FROM_DATABASE=Yeonhab Precision Co.,LTD
@@ -64894,11 +66994,14 @@ OUI:E85BF0*
OUI:E85E53*
ID_OUI_FROM_DATABASE=Infratec Datentechnik GmbH
+OUI:E8611F*
+ ID_OUI_FROM_DATABASE=Dawning Information Industry Co.,Ltd
+
OUI:E86CDA*
ID_OUI_FROM_DATABASE=Supercomputers and Neurocomputers Research Center
OUI:E86D52*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:E86D54*
ID_OUI_FROM_DATABASE=Digit Mobile Inc
@@ -64975,6 +67078,12 @@ OUI:E8B748*
OUI:E8BA70*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
+OUI:E8BB3D*
+ ID_OUI_FROM_DATABASE=Sino Prime-Tech Limited
+
+OUI:E8BBA8*
+ ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD.
+
OUI:E8BE81*
ID_OUI_FROM_DATABASE=SAGEMCOM
@@ -65002,6 +67111,9 @@ OUI:E8D0FA*
OUI:E8D483*
ID_OUI_FROM_DATABASE=ULTIMATE Europe Transportation Equipment GmbH
+OUI:E8D4E0*
+ ID_OUI_FROM_DATABASE=Beijing BenyWave Technology Co., Ltd.
+
OUI:E8DA96*
ID_OUI_FROM_DATABASE=Zhuhai Tianrui Electrical Power Tech. Co., Ltd.
@@ -65029,15 +67141,27 @@ OUI:E8E5D6*
OUI:E8E732*
ID_OUI_FROM_DATABASE=Alcatel-Lucent
+OUI:E8E770*
+ ID_OUI_FROM_DATABASE=Warp9 Tech Design, Inc.
+
OUI:E8E776*
ID_OUI_FROM_DATABASE=Shenzhen Kootion Technology Co., Ltd
OUI:E8E875*
ID_OUI_FROM_DATABASE=iS5 Communications Inc.
+OUI:E8EADA*
+ ID_OUI_FROM_DATABASE=Denkovi Assembly Electroncs LTD
+
+OUI:E8EDF3*
+ ID_OUI_FROM_DATABASE=Cisco
+
OUI:E8F1B0*
ID_OUI_FROM_DATABASE=SAGEMCOM SAS
+OUI:E8F226*
+ ID_OUI_FROM_DATABASE=MILLSON CUSTOM SOLUTIONS INC.
+
OUI:E8F928*
ID_OUI_FROM_DATABASE=RFTECH SRL
@@ -65056,12 +67180,21 @@ OUI:EC172F*
OUI:EC1A59*
ID_OUI_FROM_DATABASE=Belkin International Inc.
+OUI:EC219F*
+ ID_OUI_FROM_DATABASE=VidaBox LLC
+
+OUI:EC2257*
+ ID_OUI_FROM_DATABASE=JiangSu NanJing University Electronic Information Technology Co.,Ltd
+
OUI:EC233D*
ID_OUI_FROM_DATABASE=Huawei Technologies Co., Ltd
OUI:EC2368*
ID_OUI_FROM_DATABASE=IntelliVoice Co.,Ltd.
+OUI:EC2AF0*
+ ID_OUI_FROM_DATABASE=Ypsomed AG
+
OUI:EC2C49*
ID_OUI_FROM_DATABASE=University of Tokyo
@@ -65069,11 +67202,14 @@ OUI:EC3091*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
OUI:EC3586*
- ID_OUI_FROM_DATABASE=Apple`
+ ID_OUI_FROM_DATABASE=Apple
OUI:EC3BF0*
ID_OUI_FROM_DATABASE=NovelSat
+OUI:EC3E09*
+ ID_OUI_FROM_DATABASE=PERFORMANCE DESIGNED PRODUCTS, LLC
+
OUI:EC3F05*
ID_OUI_FROM_DATABASE=Institute 706, The Second Academy China Aerospace Science & Industry Corp
@@ -65125,6 +67261,9 @@ OUI:EC66D1*
OUI:EC6C9F*
ID_OUI_FROM_DATABASE=Chengdu Volans Technology CO.,LTD
+OUI:EC71DB*
+ ID_OUI_FROM_DATABASE=Shenzhen Baichuan Digital Technology Co., Ltd.
+
OUI:EC7C74*
ID_OUI_FROM_DATABASE=Justone Technologies Co., Ltd.
@@ -65135,7 +67274,7 @@ OUI:EC836C*
ID_OUI_FROM_DATABASE=RM Tech Co., Ltd.
OUI:EC852F*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:EC888F*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO., LTD.
@@ -65218,6 +67357,9 @@ OUI:ECDE3D*
OUI:ECE09B*
ID_OUI_FROM_DATABASE=Samsung electronics CO., LTD
+OUI:ECE1A9*
+ ID_OUI_FROM_DATABASE=Cisco
+
OUI:ECE555*
ID_OUI_FROM_DATABASE=Hirschmann Automation
@@ -65242,6 +67384,9 @@ OUI:ECF00E*
OUI:ECF236*
ID_OUI_FROM_DATABASE=NEOMONTANA ELECTRONICS
+OUI:ECF35B*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
+
OUI:ECFAAA*
ID_OUI_FROM_DATABASE=The IMS Company
@@ -65305,6 +67450,9 @@ OUI:F02A61*
OUI:F02FD8*
ID_OUI_FROM_DATABASE=Bi2-Vision
+OUI:F037A1*
+ ID_OUI_FROM_DATABASE=Huike Electronics (SHENZHEN) CO., LTD.
+
OUI:F03A55*
ID_OUI_FROM_DATABASE=Omega Elektronik AS
@@ -65353,6 +67501,9 @@ OUI:F06853*
OUI:F06BCA*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:F0728C*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:F073AE*
ID_OUI_FROM_DATABASE=PEAK-System Technik
@@ -65374,12 +67525,21 @@ OUI:F07F0C*
OUI:F081AF*
ID_OUI_FROM_DATABASE=IRZ AUTOMATION TECHNOLOGIES LTD
+OUI:F0842F*
+ ID_OUI_FROM_DATABASE=ADB Broadband Italia
+
OUI:F084C9*
ID_OUI_FROM_DATABASE=zte corporation
OUI:F08BFE*
ID_OUI_FROM_DATABASE=COSTEL.,CO.LTD
+OUI:F08EDB*
+ ID_OUI_FROM_DATABASE=VeloCloud Networks
+
+OUI:F0921C*
+ ID_OUI_FROM_DATABASE=Hewlett Packard
+
OUI:F0933A*
ID_OUI_FROM_DATABASE=NxtConect
@@ -65405,7 +67565,7 @@ OUI:F0AE51*
ID_OUI_FROM_DATABASE=Xi3 Corp
OUI:F0B479*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:F0B6EB*
ID_OUI_FROM_DATABASE=Poslab Technology Co., Ltd.
@@ -65419,6 +67579,9 @@ OUI:F0BDF1*
OUI:F0BF97*
ID_OUI_FROM_DATABASE=Sony Corporation
+OUI:F0C1F1*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:F0C24C*
ID_OUI_FROM_DATABASE=Zhejiang FeiYue Digital Technology Co., Ltd
@@ -65429,7 +67592,7 @@ OUI:F0C88C*
ID_OUI_FROM_DATABASE=LeddarTech Inc.
OUI:F0CBA1*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:F0D14F*
ID_OUI_FROM_DATABASE=LINEAR LLC
@@ -65437,6 +67600,9 @@ OUI:F0D14F*
OUI:F0D1A9*
ID_OUI_FROM_DATABASE=Apple
+OUI:F0D3A7*
+ ID_OUI_FROM_DATABASE=CobaltRay Co., Ltd
+
OUI:F0D3E7*
ID_OUI_FROM_DATABASE=Sensometrix SA
@@ -65450,7 +67616,7 @@ OUI:F0DB30*
ID_OUI_FROM_DATABASE=Yottabyte
OUI:F0DCE2*
- ID_OUI_FROM_DATABASE=Apple Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:F0DE71*
ID_OUI_FROM_DATABASE=Shanghai EDO Technologies Co.,Ltd.
@@ -65467,6 +67633,9 @@ OUI:F0E5C3*
OUI:F0E77E*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:F0EBD0*
+ ID_OUI_FROM_DATABASE=Shanghai Feixun Communication Co.,Ltd.
+
OUI:F0EC39*
ID_OUI_FROM_DATABASE=Essec
@@ -65482,6 +67651,9 @@ OUI:F0F002*
OUI:F0F260*
ID_OUI_FROM_DATABASE=Mobitec AB
+OUI:F0F5AE*
+ ID_OUI_FROM_DATABASE=Adaptrum Inc.
+
OUI:F0F644*
ID_OUI_FROM_DATABASE=Whitesky Science & Technology Co.,Ltd.
@@ -65530,6 +67702,12 @@ OUI:F41F0B*
OUI:F41FC2*
ID_OUI_FROM_DATABASE=Cisco
+OUI:F42012*
+ ID_OUI_FROM_DATABASE=Cuciniale GmbH
+
+OUI:F42896*
+ ID_OUI_FROM_DATABASE=SPECTO PAINEIS ELETRONICOS LTDA
+
OUI:F436E1*
ID_OUI_FROM_DATABASE=Abilis Systems SARL
@@ -65584,6 +67762,9 @@ OUI:F455E0*
OUI:F45842*
ID_OUI_FROM_DATABASE=Boxx TV Ltd
+OUI:F45F69*
+ ID_OUI_FROM_DATABASE=Matsufu Electronics distribution Company
+
OUI:F45FD4*
ID_OUI_FROM_DATABASE=Cisco SPVTG
@@ -65596,6 +67777,9 @@ OUI:F4600D*
OUI:F46349*
ID_OUI_FROM_DATABASE=Diffon Corporation
+OUI:F46ABC*
+ ID_OUI_FROM_DATABASE=Adonit Corp. Ltd.
+
OUI:F46D04*
ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
@@ -65608,6 +67792,9 @@ OUI:F473CA*
OUI:F47626*
ID_OUI_FROM_DATABASE=Viltechmeda UAB
+OUI:F47A4E*
+ ID_OUI_FROM_DATABASE=Woojeon&Handan
+
OUI:F47ACC*
ID_OUI_FROM_DATABASE=SolidFire, Inc.
@@ -65641,6 +67828,9 @@ OUI:F499AC*
OUI:F49F54*
ID_OUI_FROM_DATABASE=Samsung Electronics
+OUI:F4A294*
+ ID_OUI_FROM_DATABASE=EAGLE WORLD DEVELOPMENT CO., LIMITED
+
OUI:F4A52A*
ID_OUI_FROM_DATABASE=Hawa Technologies Inc
@@ -65662,6 +67852,9 @@ OUI:F4B72A*
OUI:F4B7E2*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:F4BD7C*
+ ID_OUI_FROM_DATABASE=Chengdu jinshi communication Co., LTD
+
OUI:F4C6D7*
ID_OUI_FROM_DATABASE=blackned GmbH
@@ -65674,6 +67867,9 @@ OUI:F4C795*
OUI:F4CAE5*
ID_OUI_FROM_DATABASE=FREEBOX SA
+OUI:F4CD90*
+ ID_OUI_FROM_DATABASE=Vispiron Rotec GmbH
+
OUI:F4CE46*
ID_OUI_FROM_DATABASE=Hewlett-Packard Company
@@ -65720,7 +67916,7 @@ OUI:F8051C*
ID_OUI_FROM_DATABASE=DRS Imaging and Targeting Solutions
OUI:F80BBE*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:F80BD0*
ID_OUI_FROM_DATABASE=Datang Telecom communication terminal (Tianjin) Co., Ltd.
@@ -65740,18 +67936,30 @@ OUI:F80F84*
OUI:F81037*
ID_OUI_FROM_DATABASE=Atopia Systems, LP
+OUI:F81547*
+ ID_OUI_FROM_DATABASE=Avaya, Inc
+
+OUI:F81654*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
OUI:F81A67*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO., LTD.
+OUI:F81CE5*
+ ID_OUI_FROM_DATABASE=Telefonbau Behnke GmbH
+
OUI:F81D93*
ID_OUI_FROM_DATABASE=Longdhua(Beijing) Controls Technology Co.,Ltd
OUI:F81EDF*
- ID_OUI_FROM_DATABASE=Apple, Inc
+ ID_OUI_FROM_DATABASE=Apple
OUI:F82285*
ID_OUI_FROM_DATABASE=Cypress Technology CO., LTD.
+OUI:F82793*
+ ID_OUI_FROM_DATABASE=Apple, Inc
+
OUI:F82BC8*
ID_OUI_FROM_DATABASE=Jiangsu Switter Co., Ltd
@@ -65779,12 +67987,18 @@ OUI:F83553*
OUI:F835DD*
ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd.
+OUI:F83D4E*
+ ID_OUI_FROM_DATABASE=Softlink Automation System Co., Ltd
+
OUI:F83DFF*
ID_OUI_FROM_DATABASE=Huawei Technologies Co., Ltd
OUI:F842FB*
ID_OUI_FROM_DATABASE=Yasuda Joho Co.,ltd.
+OUI:F845AD*
+ ID_OUI_FROM_DATABASE=Konka Group Co., Ltd.
+
OUI:F8462D*
ID_OUI_FROM_DATABASE=SYNTEC Incorporation
@@ -65794,6 +68008,15 @@ OUI:F8472D*
OUI:F84897*
ID_OUI_FROM_DATABASE=Hitachi, Ltd.
+OUI:F84A7F*
+ ID_OUI_FROM_DATABASE=Innometriks Inc
+
+OUI:F84ABF*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:F84F57*
+ ID_OUI_FROM_DATABASE=Cisco
+
OUI:F85063*
ID_OUI_FROM_DATABASE=Verathon
@@ -65803,9 +68026,21 @@ OUI:F8516D*
OUI:F852DF*
ID_OUI_FROM_DATABASE=VNL Europe AB
+OUI:F854AF*
+ ID_OUI_FROM_DATABASE=ECI Telecom Ltd.
+
+OUI:F8572E*
+ ID_OUI_FROM_DATABASE=Core Brands, LLC
+
+OUI:F85BC9*
+ ID_OUI_FROM_DATABASE=M-Cube Spa
+
OUI:F85F2A*
ID_OUI_FROM_DATABASE=Nokia Corporation
+OUI:F862AA*
+ ID_OUI_FROM_DATABASE=xn systems
+
OUI:F866F2*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
@@ -65828,7 +68063,7 @@ OUI:F87B62*
ID_OUI_FROM_DATABASE=FASTWEL INTERNATIONAL CO., LTD. Taiwan Branch
OUI:F87B7A*
- ID_OUI_FROM_DATABASE=Motorola Mobility, Inc.
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:F87B8C*
ID_OUI_FROM_DATABASE=Amped Wireless
@@ -65854,6 +68089,9 @@ OUI:F8912A*
OUI:F893F3*
ID_OUI_FROM_DATABASE=VOLANS
+OUI:F89550*
+ ID_OUI_FROM_DATABASE=Proton Products Chengdu Ltd
+
OUI:F897CF*
ID_OUI_FROM_DATABASE=DAESHIN-INFORMATION TECHNOLOGY CO., LTD.
@@ -65863,9 +68101,18 @@ OUI:F89955*
OUI:F89D0D*
ID_OUI_FROM_DATABASE=Control Technology Inc.
+OUI:F89FB8*
+ ID_OUI_FROM_DATABASE=YAZAKI Energy System Corporation
+
OUI:F8A03D*
ID_OUI_FROM_DATABASE=Dinstar Technologies Co., Ltd.
+OUI:F8A45F*
+ ID_OUI_FROM_DATABASE=Beijing Xiaomi communications co.,ltd
+
+OUI:F8A963*
+ ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD.
+
OUI:F8A9DE*
ID_OUI_FROM_DATABASE=PUISSANCE PLUS
@@ -65875,9 +68122,15 @@ OUI:F8AA8A*
OUI:F8AC6D*
ID_OUI_FROM_DATABASE=Deltenna Ltd
+OUI:F8B156*
+ ID_OUI_FROM_DATABASE=Dell Inc PCBA Test
+
OUI:F8B599*
ID_OUI_FROM_DATABASE=Guangzhou CHNAVS Digital Technology Co.,Ltd
+OUI:F8BC12*
+ ID_OUI_FROM_DATABASE=Dell Inc PCBA Test
+
OUI:F8C001*
ID_OUI_FROM_DATABASE=Juniper Networks
@@ -65923,6 +68176,9 @@ OUI:F8DB4C*
OUI:F8DB7F*
ID_OUI_FROM_DATABASE=HTC Corporation
+OUI:F8DB88*
+ ID_OUI_FROM_DATABASE=Dell Inc PCBA Test
+
OUI:F8DC7A*
ID_OUI_FROM_DATABASE=Variscite LTD
@@ -65948,7 +68204,10 @@ OUI:F8F014*
ID_OUI_FROM_DATABASE=RackWare Inc.
OUI:F8F082*
- ID_OUI_FROM_DATABASE=NAG LLC
+ ID_OUI_FROM_DATABASE=Orion Networks International, Inc
+
+OUI:F8F1B6*
+ ID_OUI_FROM_DATABASE=Motorola Mobility LLC
OUI:F8F25A*
ID_OUI_FROM_DATABASE=G-Lab GmbH
@@ -65968,9 +68227,15 @@ OUI:F8FE5C*
OUI:F8FEA8*
ID_OUI_FROM_DATABASE=Technico Japan Corporation
+OUI:F8FF5F*
+ ID_OUI_FROM_DATABASE=Shenzhen Communication Technology Co.,Ltd
+
OUI:FC0012*
ID_OUI_FROM_DATABASE=Toshiba Samsung Storage Technolgoy Korea Corporation
+OUI:FC019E*
+ ID_OUI_FROM_DATABASE=VIEVU
+
OUI:FC01CD*
ID_OUI_FROM_DATABASE=FUNDACION TEKNIKER
@@ -65995,9 +68260,18 @@ OUI:FC1186*
OUI:FC1794*
ID_OUI_FROM_DATABASE=InterCreative Co., Ltd
+OUI:FC19D0*
+ ID_OUI_FROM_DATABASE=Cloud Vision Networks Technology Co.,Ltd.
+
+OUI:FC1BFF*
+ ID_OUI_FROM_DATABASE=V-ZUG AG
+
OUI:FC1D59*
ID_OUI_FROM_DATABASE=I Smart Cities HK Ltd
+OUI:FC1E16*
+ ID_OUI_FROM_DATABASE=IPEVO corp
+
OUI:FC1F19*
ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS CO., LTD.
@@ -66008,7 +68282,7 @@ OUI:FC229C*
ID_OUI_FROM_DATABASE=Han Kyung I Net Co.,Ltd.
OUI:FC253F*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+ ID_OUI_FROM_DATABASE=Apple
OUI:FC2A54*
ID_OUI_FROM_DATABASE=Connected Data, Inc.
@@ -66025,6 +68299,9 @@ OUI:FC3598*
OUI:FC35E6*
ID_OUI_FROM_DATABASE=Visteon corp
+OUI:FC3FAB*
+ ID_OUI_FROM_DATABASE=Henan Lanxin Technology Co., Ltd
+
OUI:FC4463*
ID_OUI_FROM_DATABASE=Universal Audio
@@ -66124,6 +68401,9 @@ OUI:FCAD0F*
OUI:FCAF6A*
ID_OUI_FROM_DATABASE=Conemtech AB
+OUI:FCB0C4*
+ ID_OUI_FROM_DATABASE=Shanghai DareGlobal Technologies Co., Ltd
+
OUI:FCC23D*
ID_OUI_FROM_DATABASE=Atmel Corporation
@@ -66148,6 +68428,9 @@ OUI:FCD4F6*
OUI:FCD6BD*
ID_OUI_FROM_DATABASE=Robert Bosch GmbH
+OUI:FCD817*
+ ID_OUI_FROM_DATABASE=Beijing Hesun Technologies Co.Ltd.
+
OUI:FCDB96*
ID_OUI_FROM_DATABASE=ENERVALLEY CO., LTD
@@ -66157,6 +68440,9 @@ OUI:FCDD55*
OUI:FCE192*
ID_OUI_FROM_DATABASE=Sichuan Jinwangtong Electronic Science&Technology Co,.Ltd
+OUI:FCE1D9*
+ ID_OUI_FROM_DATABASE=Stable Imaging Solutions LLC
+
OUI:FCE23F*
ID_OUI_FROM_DATABASE=CLAY PAKY SPA
@@ -66183,3 +68469,6 @@ OUI:FCFAF7*
OUI:FCFBFB*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
+
+OUI:FCFE77*
+ ID_OUI_FROM_DATABASE=Hitachi Reftechno, Inc.
diff --git a/hwdb/20-acpi-vendor.hwdb b/hwdb/20-acpi-vendor.hwdb
index 09fc3bddc1..9b3b0094d5 100644
--- a/hwdb/20-acpi-vendor.hwdb
+++ b/hwdb/20-acpi-vendor.hwdb
@@ -4546,9 +4546,6 @@ acpi:PNG*:
acpi:PNL*:
ID_VENDOR_FROM_DATABASE=Panelview, Inc.
-acpi:PNP*:
- ID_VENDOR_FROM_DATABASE=Microsoft
-
acpi:PNR*:
ID_VENDOR_FROM_DATABASE=Planar Systems, Inc.
diff --git a/hwdb/20-pci-vendor-model.hwdb b/hwdb/20-pci-vendor-model.hwdb
index a8dcc31776..fdb534d7e8 100644
--- a/hwdb/20-pci-vendor-model.hwdb
+++ b/hwdb/20-pci-vendor-model.hwdb
@@ -926,12 +926,45 @@ pci:v00001000d0000005C*
pci:v00001000d0000005D*
ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader]
+pci:v00001000d0000005Dsv00001028sd00001F41*
+ ID_MODEL_FROM_DATABASE=PERC H830 Adapter
+
+pci:v00001000d0000005Dsv00001028sd00001F42*
+ ID_MODEL_FROM_DATABASE=PERC H730P Adapter
+
+pci:v00001000d0000005Dsv00001028sd00001F43*
+ ID_MODEL_FROM_DATABASE=PERC H730 Adapter
+
+pci:v00001000d0000005Dsv00001028sd00001F47*
+ ID_MODEL_FROM_DATABASE=PERC H730P Mini
+
+pci:v00001000d0000005Dsv00001028sd00001F48*
+ ID_MODEL_FROM_DATABASE=PERC H730P Mini (for blades)
+
+pci:v00001000d0000005Dsv00001028sd00001F49*
+ ID_MODEL_FROM_DATABASE=PERC H730 Mini
+
+pci:v00001000d0000005Dsv00001028sd00001F4A*
+ ID_MODEL_FROM_DATABASE=PERC H730 Mini (for blades)
+
pci:v00001000d0000005E*
ID_MODEL_FROM_DATABASE=SAS1066 PCI-X Fusion-MPT SAS
pci:v00001000d0000005F*
ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3008 [Fury]
+pci:v00001000d0000005Fsv00001028sd00001F44*
+ ID_MODEL_FROM_DATABASE=PERC H330 Adapter
+
+pci:v00001000d0000005Fsv00001028sd00001F4B*
+ ID_MODEL_FROM_DATABASE=PERC H330 Mini
+
+pci:v00001000d0000005Fsv00001028sd00001F4C*
+ ID_MODEL_FROM_DATABASE=PERC H330 Mini (for blades)
+
+pci:v00001000d0000005Fsv00001028sd00001F4D*
+ ID_MODEL_FROM_DATABASE=PERC H330 Embedded (for monolithic)
+
pci:v00001000d00000060*
ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078
@@ -1307,6 +1340,12 @@ pci:v00001000d00000096*
pci:v00001000d00000097*
ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3
+pci:v00001000d00000097sv00001028sd00001F45*
+ ID_MODEL_FROM_DATABASE=12GB/s HBA internal
+
+pci:v00001000d00000097sv00001028sd00001F46*
+ ID_MODEL_FROM_DATABASE=12GB/s HBA external
+
pci:v00001000d00000407*
ID_MODEL_FROM_DATABASE=MegaRAID
@@ -1604,11 +1643,53 @@ pci:v00001002d00001306*
pci:v00001002d00001307*
ID_MODEL_FROM_DATABASE=Kaveri
+pci:v00001002d00001309*
+ ID_MODEL_FROM_DATABASE=Kaveri
+
+pci:v00001002d0000130A*
+ ID_MODEL_FROM_DATABASE=Kaveri
+
+pci:v00001002d0000130B*
+ ID_MODEL_FROM_DATABASE=Kaveri
+
+pci:v00001002d0000130C*
+ ID_MODEL_FROM_DATABASE=Kaveri
+
+pci:v00001002d0000130D*
+ ID_MODEL_FROM_DATABASE=Kaveri
+
+pci:v00001002d0000130E*
+ ID_MODEL_FROM_DATABASE=Kaveri
+
+pci:v00001002d0000130F*
+ ID_MODEL_FROM_DATABASE=Kaveri
+
+pci:v00001002d00001310*
+ ID_MODEL_FROM_DATABASE=Kaveri
+
+pci:v00001002d00001311*
+ ID_MODEL_FROM_DATABASE=Kaveri
+
+pci:v00001002d00001313*
+ ID_MODEL_FROM_DATABASE=Kaveri
+
pci:v00001002d00001314*
- ID_MODEL_FROM_DATABASE=Wrestler HDMI Audio [Radeon HD 6250/6310]
+ ID_MODEL_FROM_DATABASE=Wrestler HDMI Audio
pci:v00001002d00001314sv0000174Bsd00001001*
- ID_MODEL_FROM_DATABASE=Sapphire PURE Fusion Mini
+ ID_MODEL_FROM_DATABASE=PURE Fusion Mini
+
+pci:v00001002d00001315*
+ ID_MODEL_FROM_DATABASE=Kaveri
+
+pci:v00001002d00001316*
+ ID_MODEL_FROM_DATABASE=Kaveri
+
+pci:v00001002d0000131B*
+ ID_MODEL_FROM_DATABASE=Kaveri
+
+pci:v00001002d0000131C*
+ ID_MODEL_FROM_DATABASE=Kaveri
pci:v00001002d00001714*
ID_MODEL_FROM_DATABASE=BeaverCreek HDMI Audio [Radeon HD 6500D and 6400G-6600G series]
@@ -1677,19 +1758,19 @@ pci:v00001002d00004150sv00001002sd00004722*
ID_MODEL_FROM_DATABASE=All-in-Wonder 2006 AGP Edition
pci:v00001002d00004150sv00001458sd00004024*
- ID_MODEL_FROM_DATABASE=Giga-Byte GV-R96128D (Primary)
+ ID_MODEL_FROM_DATABASE=GV-R96128D
pci:v00001002d00004150sv0000148Csd00002064*
- ID_MODEL_FROM_DATABASE=PowerColor R96A-C3N
+ ID_MODEL_FROM_DATABASE=R96A-C3N
pci:v00001002d00004150sv0000148Csd00002066*
- ID_MODEL_FROM_DATABASE=PowerColor R96A-C3N
+ ID_MODEL_FROM_DATABASE=R96A-C3N
pci:v00001002d00004150sv0000174Bsd00007C19*
- ID_MODEL_FROM_DATABASE=Sapphire Atlantis Radeon 9600 Pro
+ ID_MODEL_FROM_DATABASE=Atlantis Radeon 9600 Pro
pci:v00001002d00004150sv0000174Bsd00007C29*
- ID_MODEL_FROM_DATABASE=GC-R9600PRO [Sapphire] (Primary)
+ ID_MODEL_FROM_DATABASE=GC-R9600PRO
pci:v00001002d00004150sv000017EEsd00002002*
ID_MODEL_FROM_DATABASE=Radeon 9600 256Mb Primary
@@ -1722,7 +1803,7 @@ pci:v00001002d00004152sv00001462sd00009510*
ID_MODEL_FROM_DATABASE=RX9600XT (MS-8951)
pci:v00001002d00004152sv0000174Bsd00007C29*
- ID_MODEL_FROM_DATABASE=Sapphire Radeon 9600XT
+ ID_MODEL_FROM_DATABASE=Radeon 9600XT
pci:v00001002d00004152sv00001787sd00004002*
ID_MODEL_FROM_DATABASE=Radeon 9600 XT
@@ -1746,7 +1827,7 @@ pci:v00001002d00004157*
ID_MODEL_FROM_DATABASE=RV350 GL [FireGL T2]
pci:v00001002d00004158*
- ID_MODEL_FROM_DATABASE=68800AX [Mach32]
+ ID_MODEL_FROM_DATABASE=68800AX [Graphics Ultra Pro PCI]
pci:v00001002d00004164*
ID_MODEL_FROM_DATABASE=R300 [Radeon 9500 PRO] (Secondary)
@@ -1770,13 +1851,13 @@ pci:v00001002d00004170sv00001002sd00004723*
ID_MODEL_FROM_DATABASE=All-in-Wonder 2006 AGP Edition (Secondary)
pci:v00001002d00004170sv00001458sd00004025*
- ID_MODEL_FROM_DATABASE=Giga-Byte GV-R96128D (Secondary)
+ ID_MODEL_FROM_DATABASE=GV-R96128D (Secondary)
pci:v00001002d00004170sv0000148Csd00002067*
- ID_MODEL_FROM_DATABASE=PowerColor R96A-C3N (Secondary)
+ ID_MODEL_FROM_DATABASE=R96A-C3N (Secondary)
pci:v00001002d00004170sv0000174Bsd00007C28*
- ID_MODEL_FROM_DATABASE=GC-R9600PRO [Sapphire] (Secondary)
+ ID_MODEL_FROM_DATABASE=GC-R9600PRO (Secondary)
pci:v00001002d00004170sv000017EEsd00002003*
ID_MODEL_FROM_DATABASE=Radeon 9600 256Mb (Secondary)
@@ -1806,7 +1887,7 @@ pci:v00001002d00004172sv00001043sd0000C01B*
ID_MODEL_FROM_DATABASE=A9600XT/TD (Secondary)
pci:v00001002d00004172sv0000174Bsd00007C28*
- ID_MODEL_FROM_DATABASE=Sapphire Radeon 9600XT (Secondary)
+ ID_MODEL_FROM_DATABASE=Radeon 9600XT (Secondary)
pci:v00001002d00004172sv00001787sd00004003*
ID_MODEL_FROM_DATABASE=Radeon 9600 XT (Secondary)
@@ -1823,6 +1904,9 @@ pci:v00001002d00004242*
pci:v00001002d00004242sv00001002sd000002AA*
ID_MODEL_FROM_DATABASE=Radeon 8500 AIW DV Edition
+pci:v00001002d00004243*
+ ID_MODEL_FROM_DATABASE=R200 PCI Bridge [All-in-Wonder Radeon 8500DV]
+
pci:v00001002d00004336*
ID_MODEL_FROM_DATABASE=RS100 [Radeon IGP 320M]
@@ -1908,7 +1992,7 @@ pci:v00001002d00004370sv00001462sd00000131*
ID_MODEL_FROM_DATABASE=MS-1013 Notebook
pci:v00001002d00004371*
- ID_MODEL_FROM_DATABASE=IXP SB400 PCI-PCI Bridge
+ ID_MODEL_FROM_DATABASE=IXP SB4x0 PCI-PCI Bridge
pci:v00001002d00004371sv0000103Csd0000308B*
ID_MODEL_FROM_DATABASE=MX6125
@@ -1917,7 +2001,7 @@ pci:v00001002d00004371sv00001462sd00007217*
ID_MODEL_FROM_DATABASE=Aspire L250
pci:v00001002d00004372*
- ID_MODEL_FROM_DATABASE=IXP SB400 SMBus Controller
+ ID_MODEL_FROM_DATABASE=IXP SB4x0 SMBus Controller
pci:v00001002d00004372sv00001025sd00000080*
ID_MODEL_FROM_DATABASE=Aspire 5024WLMMi
@@ -1935,7 +2019,7 @@ pci:v00001002d00004372sv00001462sd00007217*
ID_MODEL_FROM_DATABASE=Aspire L250
pci:v00001002d00004373*
- ID_MODEL_FROM_DATABASE=IXP SB400 USB2 Host Controller
+ ID_MODEL_FROM_DATABASE=IXP SB4x0 USB2 Host Controller
pci:v00001002d00004373sv00001025sd00000080*
ID_MODEL_FROM_DATABASE=Aspire 5024WLMMi
@@ -1950,7 +2034,7 @@ pci:v00001002d00004373sv00001462sd00007217*
ID_MODEL_FROM_DATABASE=Aspire L250
pci:v00001002d00004374*
- ID_MODEL_FROM_DATABASE=IXP SB400 USB Host Controller
+ ID_MODEL_FROM_DATABASE=IXP SB4x0 USB Host Controller
pci:v00001002d00004374sv0000103Csd00002A20*
ID_MODEL_FROM_DATABASE=Pavilion t3030.de Desktop PC
@@ -1962,7 +2046,7 @@ pci:v00001002d00004374sv00001462sd00007217*
ID_MODEL_FROM_DATABASE=Aspire L250
pci:v00001002d00004375*
- ID_MODEL_FROM_DATABASE=IXP SB400 USB Host Controller
+ ID_MODEL_FROM_DATABASE=IXP SB4x0 USB Host Controller
pci:v00001002d00004375sv00001025sd00000080*
ID_MODEL_FROM_DATABASE=Aspire 5024WLMMi
@@ -1977,7 +2061,7 @@ pci:v00001002d00004375sv00001462sd00007217*
ID_MODEL_FROM_DATABASE=Aspire L250
pci:v00001002d00004376*
- ID_MODEL_FROM_DATABASE=IXP SB400 IDE Controller
+ ID_MODEL_FROM_DATABASE=IXP SB4x0 IDE Controller
pci:v00001002d00004376sv00001025sd00000080*
ID_MODEL_FROM_DATABASE=Aspire 5024WLMMi
@@ -1995,7 +2079,7 @@ pci:v00001002d00004376sv00001462sd00007217*
ID_MODEL_FROM_DATABASE=Aspire L250
pci:v00001002d00004377*
- ID_MODEL_FROM_DATABASE=IXP SB400 PCI-ISA Bridge
+ ID_MODEL_FROM_DATABASE=IXP SB4x0 PCI-ISA Bridge
pci:v00001002d00004377sv00001025sd00000080*
ID_MODEL_FROM_DATABASE=Aspire 5024WLMi
@@ -2022,7 +2106,7 @@ pci:v00001002d00004378sv00001462sd00000131*
ID_MODEL_FROM_DATABASE=MS-1013 Notebook
pci:v00001002d00004379*
- ID_MODEL_FROM_DATABASE=IXP SB400 Serial ATA Controller
+ ID_MODEL_FROM_DATABASE=IXP SB4x0 Serial ATA Controller
pci:v00001002d00004379sv00001462sd00007141*
ID_MODEL_FROM_DATABASE=Aspire L250
@@ -2076,7 +2160,7 @@ pci:v00001002d00004380sv000017F2sd00005999*
ID_MODEL_FROM_DATABASE=KI690-AM2 Motherboard
pci:v00001002d00004381*
- ID_MODEL_FROM_DATABASE=SB400 SATA Controller (RAID 5 mode)
+ ID_MODEL_FROM_DATABASE=SB600 SATA Controller (RAID 5 mode)
pci:v00001002d00004382*
ID_MODEL_FROM_DATABASE=SB600 AC97 Audio
@@ -2148,7 +2232,7 @@ pci:v00001002d00004385sv000015D9sd0000A811*
ID_MODEL_FROM_DATABASE=H8DGU
pci:v00001002d00004385sv0000174Bsd00001001*
- ID_MODEL_FROM_DATABASE=Sapphire PURE Fusion Mini
+ ID_MODEL_FROM_DATABASE=PURE Fusion Mini
pci:v00001002d00004385sv000017F2sd00005000*
ID_MODEL_FROM_DATABASE=KI690-AM2 Motherboard
@@ -2307,7 +2391,7 @@ pci:v00001002d00004391sv00001043sd00008443*
ID_MODEL_FROM_DATABASE=M5A88-V EVO
pci:v00001002d00004391sv0000174Bsd00001001*
- ID_MODEL_FROM_DATABASE=Sapphire PURE Fusion Mini
+ ID_MODEL_FROM_DATABASE=PURE Fusion Mini
pci:v00001002d00004392*
ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [Non-RAID5 mode]
@@ -2340,7 +2424,7 @@ pci:v00001002d00004396sv000015D9sd0000A811*
ID_MODEL_FROM_DATABASE=H8DGU
pci:v00001002d00004396sv0000174Bsd00001001*
- ID_MODEL_FROM_DATABASE=Sapphire PURE Fusion Mini
+ ID_MODEL_FROM_DATABASE=PURE Fusion Mini
pci:v00001002d00004397*
ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI0 Controller
@@ -2361,7 +2445,7 @@ pci:v00001002d00004397sv000015D9sd0000A811*
ID_MODEL_FROM_DATABASE=H8DGU
pci:v00001002d00004397sv0000174Bsd00001001*
- ID_MODEL_FROM_DATABASE=Sapphire PURE Fusion Mini
+ ID_MODEL_FROM_DATABASE=PURE Fusion Mini
pci:v00001002d00004398*
ID_MODEL_FROM_DATABASE=SB7x0 USB OHCI1 Controller
@@ -2388,7 +2472,7 @@ pci:v00001002d00004399sv00001043sd00008443*
ID_MODEL_FROM_DATABASE=M5A88-V EVO
pci:v00001002d00004399sv0000174Bsd00001001*
- ID_MODEL_FROM_DATABASE=Sapphire PURE Fusion Mini
+ ID_MODEL_FROM_DATABASE=PURE Fusion Mini
pci:v00001002d0000439C*
ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 IDE Controller
@@ -2415,7 +2499,7 @@ pci:v00001002d0000439Dsv00001043sd00008443*
ID_MODEL_FROM_DATABASE=M5A88-V EVO
pci:v00001002d0000439Dsv0000174Bsd00001001*
- ID_MODEL_FROM_DATABASE=Sapphire PURE Fusion Mini
+ ID_MODEL_FROM_DATABASE=PURE Fusion Mini
pci:v00001002d000043A0*
ID_MODEL_FROM_DATABASE=SB700/SB800/SB900 PCI to PCI bridge (PCIE port 0)
@@ -2628,7 +2712,7 @@ pci:v00001002d00004754*
ID_MODEL_FROM_DATABASE=3D Rage II/II+ PCI [Mach64 GT]
pci:v00001002d00004755*
- ID_MODEL_FROM_DATABASE=3D Rage II+ PCI [Mach64 GTB]
+ ID_MODEL_FROM_DATABASE=Mach64 GTB [3D Rage II+ DVD]
pci:v00001002d00004756*
ID_MODEL_FROM_DATABASE=3D Rage IIC PCI [Mach64 GT IIC]
@@ -2691,7 +2775,7 @@ pci:v00001002d00004966sv00001681sd00000040*
ID_MODEL_FROM_DATABASE=RV250 If [3D prophet 9000]
pci:v00001002d00004966sv0000174Bsd00007176*
- ID_MODEL_FROM_DATABASE=RV250 If [Sapphire Radeon 9000 Pro]
+ ID_MODEL_FROM_DATABASE=Radeon 9000 Pro
pci:v00001002d00004966sv0000174Bsd00007192*
ID_MODEL_FROM_DATABASE=RV250 If [Radeon 9000 "Atlantis"]
@@ -3171,7 +3255,7 @@ pci:v00001002d0000514Csv00001681sd00000010*
ID_MODEL_FROM_DATABASE=Radeon 8500 [3D Prophet 8500 128Mb]
pci:v00001002d0000514Csv0000174Bsd00007149*
- ID_MODEL_FROM_DATABASE=Radeon R200 QL [Sapphire Radeon 8500 LE]
+ ID_MODEL_FROM_DATABASE=Radeon 8500 LE
pci:v00001002d0000514Csv00001787sd00000F08*
ID_MODEL_FROM_DATABASE=Radeon R200 QL [PowerMagic Radeon 8500]
@@ -3207,7 +3291,7 @@ pci:v00001002d00005157sv0000174Bsd00007146*
ID_MODEL_FROM_DATABASE=RV200 QW [Radeon 7500 LE]
pci:v00001002d00005157sv0000174Bsd00007147*
- ID_MODEL_FROM_DATABASE=RV200 QW [Sapphire Radeon 7500LE]
+ ID_MODEL_FROM_DATABASE=Radeon 7500 LE
pci:v00001002d00005157sv0000174Bsd00007161*
ID_MODEL_FROM_DATABASE=Radeon RV200 QW [Radeon 7500 LE]
@@ -3276,10 +3360,10 @@ pci:v00001002d00005159sv0000174Bsd00000280*
ID_MODEL_FROM_DATABASE=Radeon RV100 QY [Radeon 7000/VE]
pci:v00001002d00005159sv0000174Bsd00007112*
- ID_MODEL_FROM_DATABASE=RV100 QY [Sapphire Radeon VE 7000]
+ ID_MODEL_FROM_DATABASE=Radeon VE 7000
pci:v00001002d00005159sv0000174Bsd00007C28*
- ID_MODEL_FROM_DATABASE=Sapphire Radeon VE 7000 DDR
+ ID_MODEL_FROM_DATABASE=Radeon VE 7000 DDR
pci:v00001002d00005159sv00001787sd00000202*
ID_MODEL_FROM_DATABASE=RV100 QY [Excalibur Radeon 7000]
@@ -3579,16 +3663,16 @@ pci:v00001002d00005941*
ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (Secondary)
pci:v00001002d00005941sv00001458sd00004019*
- ID_MODEL_FROM_DATABASE=Gigabyte Radeon 9200
+ ID_MODEL_FROM_DATABASE=Radeon 9200
pci:v00001002d00005941sv0000174Bsd00007C12*
- ID_MODEL_FROM_DATABASE=Sapphire Radeon 9200
+ ID_MODEL_FROM_DATABASE=Radeon 9200
pci:v00001002d00005941sv000017AFsd0000200D*
ID_MODEL_FROM_DATABASE=Excalibur Radeon 9200
pci:v00001002d00005941sv000018BCsd00000050*
- ID_MODEL_FROM_DATABASE=GeXcube GC-R9200-C3 (Secondary)
+ ID_MODEL_FROM_DATABASE=GC-R9200-C3 (Secondary)
pci:v00001002d00005944*
ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE PCI]
@@ -3669,10 +3753,10 @@ pci:v00001002d00005961sv000012ABsd00005961*
ID_MODEL_FROM_DATABASE=YUAN SMARTVGA Radeon 9200
pci:v00001002d00005961sv00001458sd00004018*
- ID_MODEL_FROM_DATABASE=Gigabyte Radeon 9200
+ ID_MODEL_FROM_DATABASE=Radeon 9200
pci:v00001002d00005961sv0000174Bsd00007C13*
- ID_MODEL_FROM_DATABASE=Sapphire Radeon 9200
+ ID_MODEL_FROM_DATABASE=Radeon 9200
pci:v00001002d00005961sv000017AFsd0000200C*
ID_MODEL_FROM_DATABASE=Excalibur Radeon 9200
@@ -3681,7 +3765,7 @@ pci:v00001002d00005961sv000018BCsd00000050*
ID_MODEL_FROM_DATABASE=Radeon 9200 Game Buster
pci:v00001002d00005961sv000018BCsd00000051*
- ID_MODEL_FROM_DATABASE=GeXcube GC-R9200-C3
+ ID_MODEL_FROM_DATABASE=GC-R9200-C3
pci:v00001002d00005961sv000018BCsd00000053*
ID_MODEL_FROM_DATABASE=Radeon 9200 Game Buster VIVO
@@ -3696,7 +3780,7 @@ pci:v00001002d00005964sv00001002sd00005964*
ID_MODEL_FROM_DATABASE=Radeon 9200 SE, 64-bit 128MB DDR, 200/166MHz
pci:v00001002d00005964sv00001043sd0000C006*
- ID_MODEL_FROM_DATABASE=ASUS Radeon 9200 SE / TD / 128M
+ ID_MODEL_FROM_DATABASE=Radeon 9200 SE / TD / 128M
pci:v00001002d00005964sv00001458sd00004018*
ID_MODEL_FROM_DATABASE=Radeon 9200 SE
@@ -3711,7 +3795,7 @@ pci:v00001002d00005964sv0000148Csd00002073*
ID_MODEL_FROM_DATABASE=CN-AG92E
pci:v00001002d00005964sv0000174Bsd00007C13*
- ID_MODEL_FROM_DATABASE=Sapphire Radeon 9200 SE
+ ID_MODEL_FROM_DATABASE=Radeon 9200 SE
pci:v00001002d00005964sv00001787sd00005964*
ID_MODEL_FROM_DATABASE=Excalibur 9200SE VIVO 128M
@@ -3741,7 +3825,7 @@ pci:v00001002d00005975*
ID_MODEL_FROM_DATABASE=RS482M [Mobility Radeon Xpress 200]
pci:v00001002d00005978*
- ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (external gfx0 port A)
+ ID_MODEL_FROM_DATABASE=RX780/RD790 PCI to PCI bridge (external gfx0 port A)
pci:v00001002d00005978sv00001849sd00005957*
ID_MODEL_FROM_DATABASE=A770CrossFire Motherboard
@@ -3753,13 +3837,13 @@ pci:v00001002d0000597A*
ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (PCI express gpp port A)
pci:v00001002d0000597B*
- ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (PCI express gpp port B)
+ ID_MODEL_FROM_DATABASE=RX780/RD790 PCI to PCI bridge (PCI express gpp port B)
pci:v00001002d0000597C*
ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (PCI express gpp port C)
pci:v00001002d0000597D*
- ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (PCI express gpp port D)
+ ID_MODEL_FROM_DATABASE=RX780/RD790 PCI to PCI bridge (PCI express gpp port D)
pci:v00001002d0000597E*
ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (PCI express gpp port E)
@@ -3845,26 +3929,29 @@ pci:v00001002d00005A20*
pci:v00001002d00005A23*
ID_MODEL_FROM_DATABASE=RD990 I/O Memory Management Unit (IOMMU)
+pci:v00001002d00005A31*
+ ID_MODEL_FROM_DATABASE=RC410 Host Bridge
+
pci:v00001002d00005A33*
- ID_MODEL_FROM_DATABASE=Radeon Xpress 200 Host Bridge
+ ID_MODEL_FROM_DATABASE=RS400 Host Bridge
pci:v00001002d00005A34*
- ID_MODEL_FROM_DATABASE=RS480 PCI-X Root Port
+ ID_MODEL_FROM_DATABASE=RS4xx PCI Express Port [ext gfx]
pci:v00001002d00005A36*
- ID_MODEL_FROM_DATABASE=RS480 PCI Bridge
+ ID_MODEL_FROM_DATABASE=RC4xx/RS4xx PCI Express Port 1
pci:v00001002d00005A37*
- ID_MODEL_FROM_DATABASE=RS480 PCI Bridge
+ ID_MODEL_FROM_DATABASE=RC4xx/RS4xx PCI Express Port 2
pci:v00001002d00005A38*
- ID_MODEL_FROM_DATABASE=RS480 PCI Bridge
+ ID_MODEL_FROM_DATABASE=RC4xx/RS4xx PCI Express Port 3
pci:v00001002d00005A39*
- ID_MODEL_FROM_DATABASE=RS480 PCI Bridge
+ ID_MODEL_FROM_DATABASE=RC4xx/RS4xx PCI Express Port 4
pci:v00001002d00005A3F*
- ID_MODEL_FROM_DATABASE=RS480 PCI Bridge
+ ID_MODEL_FROM_DATABASE=RC4xx/RS4xx PCI Bridge [int gfx]
pci:v00001002d00005A3Fsv00001462sd00007217*
ID_MODEL_FROM_DATABASE=Aspire L250
@@ -3927,7 +4014,7 @@ pci:v00001002d00005B70sv00001462sd00000403*
ID_MODEL_FROM_DATABASE=Radeon X300 SE 128MB DDR
pci:v00001002d00005B70sv0000174Bsd00000501*
- ID_MODEL_FROM_DATABASE=Sapphire Radeon X300 SE
+ ID_MODEL_FROM_DATABASE=Radeon X300 SE
pci:v00001002d00005B70sv0000196Dsd00001087*
ID_MODEL_FROM_DATABASE=Radeon X300 SE HyperMemory
@@ -3969,7 +4056,7 @@ pci:v00001002d00005D44sv0000147Bsd00006190*
ID_MODEL_FROM_DATABASE=R9200SE-DT (Secondary)
pci:v00001002d00005D44sv0000174Bsd00007C12*
- ID_MODEL_FROM_DATABASE=Sapphire Radeon 9200 SE (Secondary)
+ ID_MODEL_FROM_DATABASE=Radeon 9200 SE (Secondary)
pci:v00001002d00005D44sv00001787sd00005965*
ID_MODEL_FROM_DATABASE=Excalibur 9200SE VIVO 128M (Secondary)
@@ -4013,9 +4100,6 @@ pci:v00001002d00005D52*
pci:v00001002d00005D52sv00001002sd00000B12*
ID_MODEL_FROM_DATABASE=PowerColor X850XT PCIe (Primary)
-pci:v00001002d00005D52sv00001002sd00000B13*
- ID_MODEL_FROM_DATABASE=PowerColor X850XT PCIe (Secondary)
-
pci:v00001002d00005D57*
ID_MODEL_FROM_DATABASE=R423 [Radeon X800 XT]
@@ -4028,6 +4112,9 @@ pci:v00001002d00005D6F*
pci:v00001002d00005D72*
ID_MODEL_FROM_DATABASE=R480 [Radeon X850 XT] (Secondary)
+pci:v00001002d00005D72sv00001002sd00000B13*
+ ID_MODEL_FROM_DATABASE=PowerColor X850XT PCIe (Secondary)
+
pci:v00001002d00005D77*
ID_MODEL_FROM_DATABASE=R423 [Radeon X800 XT] (Secondary)
@@ -4050,7 +4137,7 @@ pci:v00001002d00005E4D*
ID_MODEL_FROM_DATABASE=RV410 [Radeon X700]
pci:v00001002d00005E4Dsv0000148Csd00002116*
- ID_MODEL_FROM_DATABASE=PowerColor Bravo X700
+ ID_MODEL_FROM_DATABASE=Bravo X700
pci:v00001002d00005E4F*
ID_MODEL_FROM_DATABASE=RV410 [Radeon X700]
@@ -4065,7 +4152,7 @@ pci:v00001002d00005E6D*
ID_MODEL_FROM_DATABASE=RV410 [Radeon X700] (Secondary)
pci:v00001002d00005E6Dsv0000148Csd00002117*
- ID_MODEL_FROM_DATABASE=PowerColor Bravo X700
+ ID_MODEL_FROM_DATABASE=Bravo X700 (Secondary)
pci:v00001002d00005F57*
ID_MODEL_FROM_DATABASE=R423 [Radeon X800 XT]
@@ -4092,7 +4179,7 @@ pci:v00001002d00006610*
ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8600 Series]
pci:v00001002d00006611*
- ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8500 Series]
+ ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570]
pci:v00001002d00006613*
ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8500 Series]
@@ -4110,7 +4197,7 @@ pci:v00001002d00006631*
ID_MODEL_FROM_DATABASE=Oland
pci:v00001002d00006640*
- ID_MODEL_FROM_DATABASE=Saturn XT
+ ID_MODEL_FROM_DATABASE=Saturn [Radeon HD 8950]
pci:v00001002d00006641*
ID_MODEL_FROM_DATABASE=Saturn PRO
@@ -4125,7 +4212,7 @@ pci:v00001002d00006651*
ID_MODEL_FROM_DATABASE=Bonaire
pci:v00001002d00006658*
- ID_MODEL_FROM_DATABASE=Bonaire
+ ID_MODEL_FROM_DATABASE=Bonaire XTX [Radeon R7 260X]
pci:v00001002d0000665C*
ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770]
@@ -4148,17 +4235,26 @@ pci:v00001002d0000665Csv0000174Bsd0000E253*
pci:v00001002d0000665Csv00001787sd00002329*
ID_MODEL_FROM_DATABASE=Radeon HD 7790 TurboDuo
+pci:v00001002d0000665D*
+ ID_MODEL_FROM_DATABASE=Bonaire
+
pci:v00001002d00006660*
- ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8600M Series]
+ ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A]
pci:v00001002d00006663*
ID_MODEL_FROM_DATABASE=Sun PRO [Radeon HD 8500M Series]
+pci:v00001002d00006664*
+ ID_MODEL_FROM_DATABASE=Jet XT [Radeon R5 M200 Series]
+
+pci:v00001002d00006665*
+ ID_MODEL_FROM_DATABASE=Jet PRO [Radeon R5 M200 Series]
+
pci:v00001002d00006667*
- ID_MODEL_FROM_DATABASE=Sun
+ ID_MODEL_FROM_DATABASE=Jet ULT [Radeon R5 M200 Series]
pci:v00001002d0000666F*
- ID_MODEL_FROM_DATABASE=Sun LE
+ ID_MODEL_FROM_DATABASE=Sun [Radeon HD 8500M]
pci:v00001002d00006670*
ID_MODEL_FROM_DATABASE=Hainan
@@ -4250,21 +4346,474 @@ pci:v00001002d0000673Esv0000148Csd00007720*
pci:v00001002d00006740*
ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT]
+pci:v00001002d00006740sv00001019sd0000238C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6730M
+
+pci:v00001002d00006740sv00001019sd0000238E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6730M
+
+pci:v00001002d00006740sv00001019sd00002391*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6730M
+
+pci:v00001002d00006740sv00001019sd00002392*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6770M
+
pci:v00001002d00006740sv00001028sd000004A3*
ID_MODEL_FROM_DATABASE=Precision M4600
+pci:v00001002d00006740sv00001028sd0000053E*
+ ID_MODEL_FROM_DATABASE=FirePro M5950
+
+pci:v00001002d00006740sv0000103Csd00001630*
+ ID_MODEL_FROM_DATABASE=FirePro M5950
+
+pci:v00001002d00006740sv0000103Csd00001631*
+ ID_MODEL_FROM_DATABASE=FirePro M5950
+
+pci:v00001002d00006740sv0000103Csd0000164B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6730M
+
+pci:v00001002d00006740sv0000103Csd0000164E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6730M
+
+pci:v00001002d00006740sv0000103Csd00001657*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6770M
+
+pci:v00001002d00006740sv0000103Csd00001658*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6770M
+
+pci:v00001002d00006740sv0000103Csd0000165A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6770M
+
+pci:v00001002d00006740sv0000103Csd0000165B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6770M
+
+pci:v00001002d00006740sv0000103Csd00001688*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6770M
+
+pci:v00001002d00006740sv0000103Csd00001689*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6770M
+
+pci:v00001002d00006740sv0000103Csd0000168A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6770M
+
+pci:v00001002d00006740sv0000103Csd0000185E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7690M XT
+
+pci:v00001002d00006740sv0000103Csd00003388*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6770M
+
+pci:v00001002d00006740sv0000103Csd00003389*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6770M
+
+pci:v00001002d00006740sv0000103Csd00003582*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6770M
+
+pci:v00001002d00006740sv0000103Csd0000366C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6730M
+
+pci:v00001002d00006740sv00001043sd00001D02*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6730M
+
+pci:v00001002d00006740sv00001043sd00001D12*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6730M
+
+pci:v00001002d00006740sv0000104Dsd00009084*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6730M
+
+pci:v00001002d00006740sv0000104Dsd00009085*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6730M
+
+pci:v00001002d00006740sv0000144Dsd0000B074*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6730M
+
+pci:v00001002d00006740sv0000144Dsd0000B077*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6730M
+
+pci:v00001002d00006740sv0000144Dsd0000B084*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6730M
+
+pci:v00001002d00006740sv0000144Dsd0000B088*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6730M
+
+pci:v00001002d00006740sv000017AAsd00003982*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6730M
+
pci:v00001002d00006741*
- ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6600M/6700M/7600M Series]
+ ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M]
+
+pci:v00001002d00006741sv00001019sd0000238E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001019sd0000238F*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd00000379*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd0000037B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd0000037E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd00000382*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd00000384*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd00000385*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd00000386*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd00000387*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd00000388*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd00000442*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd00000451*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd00000489*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd0000048B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd0000048C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd0000050A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd0000050B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd0000050C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd0000050E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd0000050F*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd00000513*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd00000514*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd00000515*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd00000516*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd0000051E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd0000051F*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd00000520*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd00000521*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd0000052A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd00000555*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd00000556*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd0000055D*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd0000055E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd0000056D*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd0000059A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd0000059B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd0000059E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd0000059F*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd00000600*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd00000605*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd00000606*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001025sd00000619*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001028sd000004C1*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6630M
+
+pci:v00001002d00006741sv00001028sd000004C5*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6630M
+
+pci:v00001002d00006741sv00001028sd000004CD*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6630M
+
+pci:v00001002d00006741sv00001028sd000004D7*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6630M
+
+pci:v00001002d00006741sv00001028sd000004D9*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6630M
+
+pci:v00001002d00006741sv00001028sd0000052D*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6630M
+
+pci:v00001002d00006741sv0000103Csd00001617*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv0000103Csd00001646*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6750M
+
+pci:v00001002d00006741sv0000103Csd00001647*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv0000103Csd0000164B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv0000103Csd0000164E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv0000103Csd00001688*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6750M
+
+pci:v00001002d00006741sv0000103Csd00001689*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6750M
+
+pci:v00001002d00006741sv0000103Csd0000168A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6750M
+
+pci:v00001002d00006741sv0000103Csd00001860*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7690M
+
+pci:v00001002d00006741sv0000103Csd00003385*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6630M
+
+pci:v00001002d00006741sv0000103Csd00003560*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6750M
+
+pci:v00001002d00006741sv0000103Csd0000358D*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6750M
+
+pci:v00001002d00006741sv0000103Csd00003590*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6750M
+
+pci:v00001002d00006741sv0000103Csd00003593*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6750M
+
+pci:v00001002d00006741sv0000103Csd0000366C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001043sd00001CD2*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001043sd00002121*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001043sd00002122*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001043sd00002123*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001043sd00002125*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006741sv00001043sd00002127*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006741sv0000104Dsd0000907B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6630M
+
+pci:v00001002d00006741sv0000104Dsd00009080*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6630M
+
+pci:v00001002d00006741sv0000104Dsd00009081*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6630M
pci:v00001002d00006741sv0000106Bsd000000E2*
ID_MODEL_FROM_DATABASE=MacBookPro8,2 [Core i7, 15", Late 2011]
+pci:v00001002d00006741sv00001179sd0000FD63*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6630M
+
+pci:v00001002d00006741sv00001179sd0000FD65*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6630M
+
+pci:v00001002d00006741sv0000144Dsd0000C093*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv0000144Dsd0000C0AC*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv0000144Dsd0000C0B3*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6750M
+
+pci:v00001002d00006741sv0000144Dsd0000C539*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6630M
+
+pci:v00001002d00006741sv0000144Dsd0000C609*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6630M
+
+pci:v00001002d00006741sv0000152Dsd00000914*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv000017AAsd000021E1*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6630M
+
+pci:v00001002d00006741sv000017AAsd00003970*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv000017AAsd00003976*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
+pci:v00001002d00006741sv00001854sd00000907*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650M
+
pci:v00001002d00006742*
ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M]
+pci:v00001002d00006742sv00001002sd00006570*
+ ID_MODEL_FROM_DATABASE=Turks [Radeon HD 6570]
+
+pci:v00001002d00006742sv00001019sd00002393*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6610M
+
pci:v00001002d00006742sv00001043sd00001D82*
ID_MODEL_FROM_DATABASE=K53SK Laptop Radeon HD 7610M
+pci:v00001002d00006742sv00001179sd0000FB22*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FB23*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FB27*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FB2A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FB2C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FB30*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FB31*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FB32*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FB38*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FB39*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FB3A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FB3B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FB40*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FB41*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FB47*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FB48*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FB49*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FB51*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FB52*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FB53*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FB56*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FB81*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FB82*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FB83*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FC56*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FCD4*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001179sd0000FCEE*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7610M
+
+pci:v00001002d00006742sv00001458sd00006570*
+ ID_MODEL_FROM_DATABASE=Turks [Radeon HD 6570]
+
+pci:v00001002d00006742sv00001462sd00006570*
+ ID_MODEL_FROM_DATABASE=Turks [Radeon HD 6570]
+
+pci:v00001002d00006742sv0000148Csd00006570*
+ ID_MODEL_FROM_DATABASE=Turks [Radeon HD 6570]
+
+pci:v00001002d00006742sv00001682sd00006570*
+ ID_MODEL_FROM_DATABASE=Turks [Radeon HD 6570]
+
+pci:v00001002d00006742sv0000174Bsd00006570*
+ ID_MODEL_FROM_DATABASE=Turks [Radeon HD 6570]
+
+pci:v00001002d00006742sv00001787sd00006570*
+ ID_MODEL_FROM_DATABASE=Turks [Radeon HD 6570]
+
+pci:v00001002d00006742sv000017AFsd00006570*
+ ID_MODEL_FROM_DATABASE=Turks [Radeon HD 6570]
+
pci:v00001002d00006742sv00008086sd00002111*
ID_MODEL_FROM_DATABASE=Radeon HD 6625M
@@ -4278,38 +4827,155 @@ pci:v00001002d0000674A*
ID_MODEL_FROM_DATABASE=Turks GL [FirePro V3900]
pci:v00001002d00006750*
- ID_MODEL_FROM_DATABASE=Onega [Radeon HD 6650A / 7650A]
+ ID_MODEL_FROM_DATABASE=Onega [Radeon HD 6650A/7650A]
+
+pci:v00001002d00006750sv00001462sd00002670*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6670A
+
+pci:v00001002d00006750sv000017AAsd00003079*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650A
+
+pci:v00001002d00006750sv000017AAsd0000307A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650A
+
+pci:v00001002d00006750sv000017AAsd00003087*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650A
+
+pci:v00001002d00006750sv000017AAsd00003618*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650A
+
+pci:v00001002d00006750sv000017AAsd00003623*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650A
+
+pci:v00001002d00006750sv000017AAsd00003627*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6650A
pci:v00001002d00006751*
- ID_MODEL_FROM_DATABASE=Turks XT [Radeon HD 7670A]
+ ID_MODEL_FROM_DATABASE=Turks [Radeon HD 7650A/7670A]
+
+pci:v00001002d00006751sv00001028sd00000548*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650A
+
+pci:v00001002d00006751sv00001462sd00002671*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670A
+
+pci:v00001002d00006751sv00001462sd00002672*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670A
+
+pci:v00001002d00006751sv00001462sd00002680*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650A
+
+pci:v00001002d00006751sv00001462sd00002681*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650A
+
+pci:v00001002d00006751sv000017AAsd00003087*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650A
pci:v00001002d00006758*
- ID_MODEL_FROM_DATABASE=Turks XT [Radeon HD 6670]
+ ID_MODEL_FROM_DATABASE=Turks XT [Radeon HD 6670/7670]
+
+pci:v00001002d00006758sv00001028sd00000B0E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6670
+
+pci:v00001002d00006758sv0000103Csd00006882*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6670
+
+pci:v00001002d00006758sv00001462sd0000250A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670
+
+pci:v00001002d00006758sv0000148Csd00007670*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670
+
+pci:v00001002d00006758sv00001545sd00007670*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670
+
+pci:v00001002d00006758sv00001682sd00003300*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670
+
+pci:v00001002d00006758sv0000174Bsd00007670*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670
+
+pci:v00001002d00006758sv0000174Bsd0000E181*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6670
pci:v00001002d00006759*
- ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570]
+ ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570]
+
+pci:v00001002d00006759sv0000103Csd00003130*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6570
+
+pci:v00001002d00006759sv00001462sd00002500*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6570
+
+pci:v00001002d00006759sv00001462sd00002509*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7570
pci:v00001002d00006759sv0000148Csd00007570*
ID_MODEL_FROM_DATABASE=Radeon HD 7570
+pci:v00001002d00006759sv00001642sd00003A67*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6570
+
+pci:v00001002d00006759sv00001682sd00003280*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7570
+
pci:v00001002d00006759sv0000174Bsd00007570*
ID_MODEL_FROM_DATABASE=Radeon HD 7570
+pci:v00001002d00006759sv0000174Bsd0000E142*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6570
+
+pci:v00001002d00006759sv0000174Bsd0000E181*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6570
+
+pci:v00001002d00006759sv00001B0Asd0000908F*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6570
+
+pci:v00001002d00006759sv00001B0Asd00009090*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6570
+
+pci:v00001002d00006759sv00001B0Asd00009091*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6570
+
+pci:v00001002d00006759sv00001B0Asd00009092*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6570
+
+pci:v00001002d00006759sv00001B0Asd0000909E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6570
+
+pci:v00001002d00006759sv00001B0Asd000090B5*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7570
+
+pci:v00001002d00006759sv00001B0Asd000090B6*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7570
+
pci:v00001002d0000675D*
ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 7570]
pci:v00001002d0000675F*
- ID_MODEL_FROM_DATABASE=Turks LE [Radeon HD 5570/6510/7510]
+ ID_MODEL_FROM_DATABASE=Turks LE [Radeon HD 5570/6510/7510/8510]
pci:v00001002d0000675Fsv0000148Csd00006510*
ID_MODEL_FROM_DATABASE=Radeon HD 6510
+pci:v00001002d0000675Fsv0000148Csd00006530*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6530
+
+pci:v00001002d0000675Fsv0000148Csd00007510*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7510
+
+pci:v00001002d0000675Fsv00001545sd00007570*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7570
+
pci:v00001002d0000675Fsv0000174Bsd00006510*
ID_MODEL_FROM_DATABASE=Radeon HD 6510
pci:v00001002d0000675Fsv0000174Bsd00007510*
ID_MODEL_FROM_DATABASE=Radeon HD 7510
+pci:v00001002d0000675Fsv0000174Bsd00008510*
+ ID_MODEL_FROM_DATABASE=Radeon HD 8510
+
pci:v00001002d0000675Fsv00001787sd00002012*
ID_MODEL_FROM_DATABASE=Radeon HD 5570 2GB GDDR3
@@ -4319,11 +4985,497 @@ pci:v00001002d0000675Fsv00001787sd00002314*
pci:v00001002d00006760*
ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series]
+pci:v00001002d00006760sv00001002sd00000124*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001002sd00000134*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001019sd0000238B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001019sd0000238E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001019sd00002390*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001019sd00009985*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001028sd000004C1*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001028sd000004C3*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001028sd000004CA*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001028sd000004CB*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
pci:v00001002d00006760sv00001028sd000004CC*
ID_MODEL_FROM_DATABASE=Vostro 3350
+pci:v00001002d00006760sv00001028sd000004D1*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001028sd000004D3*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001028sd000004D7*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001028sd00000502*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001028sd00000503*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001028sd00000506*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001028sd00000507*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001028sd00000514*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001028sd0000051C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450M
+
+pci:v00001002d00006760sv00001028sd0000051D*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450M
+
+pci:v00001002d00006760sv0000103Csd0000161A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd0000161B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd0000161E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd0000161F*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd00001622*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450M
+
+pci:v00001002d00006760sv0000103Csd00001623*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450M
+
+pci:v00001002d00006760sv0000103Csd0000164A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd0000164D*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd00001651*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd00001656*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6490M
+
+pci:v00001002d00006760sv0000103Csd00001658*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6490M
+
+pci:v00001002d00006760sv0000103Csd00001659*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6490M
+
+pci:v00001002d00006760sv0000103Csd0000165B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6490M
+
+pci:v00001002d00006760sv0000103Csd0000165D*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd0000165F*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd00001661*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd00001663*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd00001665*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd00001667*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd00001669*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd0000166B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd0000166C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd0000166E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd00001670*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd00001672*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd0000167A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd0000167B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd0000167D*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6490M
+
+pci:v00001002d00006760sv0000103Csd0000167F*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6490M
+
+pci:v00001002d00006760sv0000103Csd0000168C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd0000168F*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd00001694*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd00001696*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd00001698*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd0000169A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd0000169C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6490M
+
+pci:v00001002d00006760sv0000103Csd00001855*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7450M
+
+pci:v00001002d00006760sv0000103Csd00001859*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7450M
+
+pci:v00001002d00006760sv0000103Csd0000185C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7450M
+
+pci:v00001002d00006760sv0000103Csd0000185D*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv0000103Csd0000185F*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv0000103Csd00001863*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7450M
+
+pci:v00001002d00006760sv0000103Csd0000355C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6490M
+
+pci:v00001002d00006760sv0000103Csd0000355F*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6490M
+
+pci:v00001002d00006760sv0000103Csd00003563*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd00003565*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd00003567*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd00003569*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd00003581*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6490M
+
+pci:v00001002d00006760sv0000103Csd00003584*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd0000358C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6490M
+
+pci:v00001002d00006760sv0000103Csd0000358F*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6490M
+
+pci:v00001002d00006760sv0000103Csd00003592*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6490M
+
+pci:v00001002d00006760sv0000103Csd00003596*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6490M
+
+pci:v00001002d00006760sv0000103Csd0000366B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000103Csd00003671*
+ ID_MODEL_FROM_DATABASE=FirePro M3900
+
+pci:v00001002d00006760sv0000103Csd00003673*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001043sd0000100A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001043sd0000100C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001043sd0000101B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001043sd0000101C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001043sd0000102A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7450M
+
+pci:v00001002d00006760sv00001043sd0000102C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001043sd0000104B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001043sd0000105D*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001043sd0000106B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001043sd0000106D*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001043sd0000107D*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001043sd00001CB2*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001043sd00001D22*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001043sd00001D32*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001043sd00002001*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001043sd00002002*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001043sd00002107*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001043sd00002108*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001043sd00002109*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
pci:v00001002d00006760sv00001043sd000084A0*
- ID_MODEL_FROM_DATABASE=Seymour XT [Radeon HD 6470M]
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001043sd000084E9*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001043sd00008515*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001043sd00008517*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001043sd0000855A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv0000104Dsd0000907B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000104Dsd00009081*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000104Dsd00009084*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000104Dsd00009085*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001179sd00000001*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450M
+
+pci:v00001002d00006760sv00001179sd00000003*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450M
+
+pci:v00001002d00006760sv00001179sd00000004*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450M
+
+pci:v00001002d00006760sv00001179sd0000FB22*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FB23*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FB2C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FB31*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FB32*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FB33*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FB38*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FB39*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FB3A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FB40*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FB41*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FB42*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FB47*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FB48*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FB51*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FB52*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FB53*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FB81*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FB82*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FB83*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FC51*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001179sd0000FC52*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FC56*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FCD3*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FCD4*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FCEE*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv00001179sd0000FDEE*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv0000144Dsd0000B074*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000144Dsd0000B084*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000144Dsd0000C095*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000144Dsd0000C0B3*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6490M
+
+pci:v00001002d00006760sv0000144Dsd0000C538*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000144Dsd0000C581*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000144Dsd0000C589*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000144Dsd0000C609*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv0000144Dsd0000C625*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv0000144Dsd0000C636*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7450M
+
+pci:v00001002d00006760sv00001462sd000010AC*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv0000152Dsd00000916*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv000017AAsd000021E5*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv000017AAsd00003900*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7450M
+
+pci:v00001002d00006760sv000017AAsd00003902*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7450M
+
+pci:v00001002d00006760sv000017AAsd00003969*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv000017AAsd00003970*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7450M
+
+pci:v00001002d00006760sv000017AAsd00003976*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv000017AAsd0000397B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv000017AAsd0000397D*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv000017AAsd00005101*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470M
+
+pci:v00001002d00006760sv000017AAsd00005102*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7450M
+
+pci:v00001002d00006760sv000017AAsd00005103*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7450M
+
+pci:v00001002d00006760sv000017AAsd00005106*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7450M
+
+pci:v00001002d00006760sv00001854sd00000897*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001854sd00000900*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001854sd00000908*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
+
+pci:v00001002d00006760sv00001854sd00002015*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6470M
pci:v00001002d00006761*
ID_MODEL_FROM_DATABASE=Seymour LP [Radeon HD 6430M]
@@ -4349,6 +5501,24 @@ pci:v00001002d00006768*
pci:v00001002d00006770*
ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450A/7450A]
+pci:v00001002d00006770sv000017AAsd0000308D*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7450A
+
+pci:v00001002d00006770sv000017AAsd00003623*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450A
+
+pci:v00001002d00006770sv000017AAsd00003627*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450A
+
+pci:v00001002d00006770sv000017AAsd00003629*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450A
+
+pci:v00001002d00006770sv000017AAsd0000363C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450A
+
+pci:v00001002d00006770sv000017AAsd00003658*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470A
+
pci:v00001002d00006771*
ID_MODEL_FROM_DATABASE=Caicos XTX [Radeon HD 8490]
@@ -4356,26 +5526,134 @@ pci:v00001002d00006772*
ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 7450A]
pci:v00001002d00006778*
- ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470]
+ ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470]
+
+pci:v00001002d00006778sv00001019sd00000024*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470
+
+pci:v00001002d00006778sv00001019sd00000027*
+ ID_MODEL_FROM_DATABASE=Radeon HD 8470
+
+pci:v00001002d00006778sv00001028sd00002120*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470
+
+pci:v00001002d00006778sv00001462sd0000B491*
+ ID_MODEL_FROM_DATABASE=Radeon HD 8470
+
+pci:v00001002d00006778sv00001462sd0000B492*
+ ID_MODEL_FROM_DATABASE=Radeon HD 8470
pci:v00001002d00006778sv00001462sd0000B493*
ID_MODEL_FROM_DATABASE=Radeon HD 8470 OEM
+pci:v00001002d00006778sv00001642sd00003C65*
+ ID_MODEL_FROM_DATABASE=Radeon HD 8470
+
+pci:v00001002d00006778sv00001642sd00003C75*
+ ID_MODEL_FROM_DATABASE=Radeon HD 8470
+
+pci:v00001002d00006778sv0000174Bsd00008145*
+ ID_MODEL_FROM_DATABASE=Radeon HD 8470
+
+pci:v00001002d00006778sv0000174Bsd0000E145*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470
+
pci:v00001002d00006779*
- ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450]
+ ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450]
+
+pci:v00001002d00006779sv00001019sd00000016*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450
+
+pci:v00001002d00006779sv00001019sd00000017*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450
+
+pci:v00001002d00006779sv00001019sd00000018*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450
+
+pci:v00001002d00006779sv00001028sd00002120*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450
+
+pci:v00001002d00006779sv0000103Csd00002128*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450
+
+pci:v00001002d00006779sv0000103Csd00002AEE*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7450A
+
+pci:v00001002d00006779sv00001462sd00002346*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7450
+
+pci:v00001002d00006779sv00001462sd00002490*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450
+
+pci:v00001002d00006779sv00001462sd00002494*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450
+
+pci:v00001002d00006779sv00001462sd00002496*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7450
+
+pci:v00001002d00006779sv0000148Csd00007450*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7450
pci:v00001002d00006779sv0000148Csd00008450*
ID_MODEL_FROM_DATABASE=Radeon HD 8450 OEM
+pci:v00001002d00006779sv00001545sd00007470*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7470
+
+pci:v00001002d00006779sv00001642sd00003A65*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450
+
+pci:v00001002d00006779sv00001642sd00003A66*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7450
+
+pci:v00001002d00006779sv00001642sd00003A75*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450
+
+pci:v00001002d00006779sv00001642sd00003A76*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7450
+
+pci:v00001002d00006779sv00001682sd00003200*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7450
+
pci:v00001002d00006779sv0000174Bsd00007450*
ID_MODEL_FROM_DATABASE=Radeon HD 7450
+pci:v00001002d00006779sv0000174Bsd0000E127*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450
+
+pci:v00001002d00006779sv0000174Bsd0000E153*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450
+
pci:v00001002d00006779sv0000174Bsd0000E164*
ID_MODEL_FROM_DATABASE=Radeon HD 6450 1 GB DDR3
+pci:v00001002d00006779sv0000174Bsd0000E180*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450
+
+pci:v00001002d00006779sv0000174Bsd0000E201*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450
+
pci:v00001002d00006779sv000017AFsd00008450*
ID_MODEL_FROM_DATABASE=Radeon HD 8450 OEM
+pci:v00001002d00006779sv00001B0Asd00009096*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450
+
+pci:v00001002d00006779sv00001B0Asd00009097*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450
+
+pci:v00001002d00006779sv00001B0Asd000090A8*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450A
+
+pci:v00001002d00006779sv00001B0Asd000090B1*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450
+
+pci:v00001002d00006779sv00001B0Asd000090B3*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7450A
+
+pci:v00001002d00006779sv00001B0Asd000090BB*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7450A
+
pci:v00001002d0000677B*
ID_MODEL_FROM_DATABASE=Caicos PRO [Radeon HD 7450]
@@ -4418,6 +5696,9 @@ pci:v00001002d00006798*
pci:v00001002d00006798sv00001002sd00003000*
ID_MODEL_FROM_DATABASE=Tahiti XT2 [Radeon HD 7970 GHz Edition]
+pci:v00001002d00006798sv00001002sd00004000*
+ ID_MODEL_FROM_DATABASE=Radeon HD 8970 OEM
+
pci:v00001002d00006798sv00001043sd0000041C*
ID_MODEL_FROM_DATABASE=HD 7970 DirectCU II
@@ -4481,12 +5762,42 @@ pci:v00001002d0000679Asv00001462sd00003000*
pci:v00001002d0000679B*
ID_MODEL_FROM_DATABASE=Malta [Radeon HD 7990]
+pci:v00001002d0000679Bsv00001002sd00000B28*
+ ID_MODEL_FROM_DATABASE=Radeon HD 8990 OEM
+
+pci:v00001002d0000679Bsv00001002sd00000B2A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7990
+
+pci:v00001002d0000679Bsv00001462sd00008036*
+ ID_MODEL_FROM_DATABASE=Radeon HD 8990 OEM
+
pci:v00001002d0000679E*
ID_MODEL_FROM_DATABASE=Tahiti LE [Radeon HD 7870 XT]
pci:v00001002d0000679F*
ID_MODEL_FROM_DATABASE=Tahiti
+pci:v00001002d000067A0*
+ ID_MODEL_FROM_DATABASE=Hawaii XT GL
+
+pci:v00001002d000067A1*
+ ID_MODEL_FROM_DATABASE=Hawaii GL
+
+pci:v00001002d000067A2*
+ ID_MODEL_FROM_DATABASE=Hawaii GL
+
+pci:v00001002d000067B0*
+ ID_MODEL_FROM_DATABASE=Hawaii XT [Radeon R9 290X]
+
+pci:v00001002d000067B1*
+ ID_MODEL_FROM_DATABASE=Hawaii PRO [Radeon R9 290]
+
+pci:v00001002d000067B9*
+ ID_MODEL_FROM_DATABASE=Vesuvius
+
+pci:v00001002d000067BE*
+ ID_MODEL_FROM_DATABASE=Hawaii LE
+
pci:v00001002d00006800*
ID_MODEL_FROM_DATABASE=Wimbledon XT [Radeon HD 7970M]
@@ -4527,10 +5838,10 @@ pci:v00001002d00006809*
ID_MODEL_FROM_DATABASE=Pitcairn LE GL [FirePro W5000]
pci:v00001002d00006810*
- ID_MODEL_FROM_DATABASE=Pitcairn
+ ID_MODEL_FROM_DATABASE=Curacao XT [Radeon R9 270X]
pci:v00001002d00006811*
- ID_MODEL_FROM_DATABASE=Pitcairn
+ ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R9 270]
pci:v00001002d00006816*
ID_MODEL_FROM_DATABASE=Pitcairn
@@ -4542,26 +5853,32 @@ pci:v00001002d00006818*
ID_MODEL_FROM_DATABASE=Pitcairn XT [Radeon HD 7870 GHz Edition]
pci:v00001002d00006818sv00001002sd00000B05*
- ID_MODEL_FROM_DATABASE=Pitcairn XT [Radeon HD 8870 OEM]
+ ID_MODEL_FROM_DATABASE=Radeon HD 8870 OEM
+
+pci:v00001002d00006818sv0000174Bsd00008B04*
+ ID_MODEL_FROM_DATABASE=Radeon HD 8860
pci:v00001002d00006819*
ID_MODEL_FROM_DATABASE=Pitcairn PRO [Radeon HD 7850]
pci:v00001002d00006819sv0000174Bsd0000E221*
- ID_MODEL_FROM_DATABASE=Sapphire Radeon HD 7850 2 GB GDDR5 DVI-I/DVI-D/HDMI/DP
+ ID_MODEL_FROM_DATABASE=Radeon HD 7850 2GB GDDR5 DVI-I/DVI-D/HDMI/DP
pci:v00001002d00006820*
ID_MODEL_FROM_DATABASE=Venus XTX [Radeon HD 8800M Series]
+pci:v00001002d00006820sv0000103Csd00001851*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7750M
+
pci:v00001002d00006821*
ID_MODEL_FROM_DATABASE=Venus XT [Radeon HD 8800M Series]
+pci:v00001002d00006822*
+ ID_MODEL_FROM_DATABASE=Venus PRO
+
pci:v00001002d00006823*
ID_MODEL_FROM_DATABASE=Venus PRO [Radeon HD 8800M Series]
-pci:v00001002d00006824*
- ID_MODEL_FROM_DATABASE=Chelsea [Radeon HD 7700M Series]
-
pci:v00001002d00006825*
ID_MODEL_FROM_DATABASE=Heathrow XT [Radeon HD 7870M]
@@ -4580,6 +5897,9 @@ pci:v00001002d00006828*
pci:v00001002d00006829*
ID_MODEL_FROM_DATABASE=Cape Verde
+pci:v00001002d0000682A*
+ ID_MODEL_FROM_DATABASE=Venus PRO
+
pci:v00001002d0000682B*
ID_MODEL_FROM_DATABASE=Venus LE [Radeon HD 8800M Series]
@@ -4589,14 +5909,29 @@ pci:v00001002d0000682D*
pci:v00001002d0000682F*
ID_MODEL_FROM_DATABASE=Chelsea LP [Radeon HD 7730M]
+pci:v00001002d0000682Fsv0000103Csd00001851*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7750M
+
pci:v00001002d00006830*
ID_MODEL_FROM_DATABASE=Cape Verde [Radeon HD 7800M Series]
pci:v00001002d00006831*
ID_MODEL_FROM_DATABASE=Cape Verde [AMD Radeon HD 7700M Series]
+pci:v00001002d00006835*
+ ID_MODEL_FROM_DATABASE=Cape Verde PRX [Radeon R7 200 Series]
+
pci:v00001002d00006837*
- ID_MODEL_FROM_DATABASE=Cape Verde LE [Radeon HD 7730]
+ ID_MODEL_FROM_DATABASE=Cape Verde LE [Radeon HD 7730/8730]
+
+pci:v00001002d00006837sv00001462sd00002796*
+ ID_MODEL_FROM_DATABASE=Radeon HD 8730
+
+pci:v00001002d00006837sv00001462sd00008092*
+ ID_MODEL_FROM_DATABASE=Radeon HD 8730
+
+pci:v00001002d00006837sv0000148Csd00008730*
+ ID_MODEL_FROM_DATABASE=Radeon HD 8730
pci:v00001002d00006837sv00001787sd00003000*
ID_MODEL_FROM_DATABASE=Radeon HD 6570
@@ -4626,10 +5961,325 @@ pci:v00001002d0000683F*
ID_MODEL_FROM_DATABASE=Cape Verde PRO [Radeon HD 7750]
pci:v00001002d00006840*
- ID_MODEL_FROM_DATABASE=Thames XT [Radeon HD 7670M]
+ ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series]
+
+pci:v00001002d00006840sv00001025sd0000050E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001025sd0000050F*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001025sd00000513*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001025sd00000514*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001025sd0000056D*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001025sd0000059A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001025sd0000059B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001025sd0000059E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001025sd00000600*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001025sd00000606*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001025sd00000696*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650M
+
+pci:v00001002d00006840sv00001025sd00000697*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650M
+
+pci:v00001002d00006840sv00001025sd00000698*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650M
+
+pci:v00001002d00006840sv00001025sd00000699*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650M
+
+pci:v00001002d00006840sv00001025sd00000757*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001028sd0000056A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001028sd0000056E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001028sd00000598*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001028sd0000059D*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001028sd000005A3*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001028sd000005B9*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001028sd000005BB*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv0000103Csd000017F1*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7570M
+
+pci:v00001002d00006840sv0000103Csd000017F4*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650M
+
+pci:v00001002d00006840sv0000103Csd00001813*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7590M
+
+pci:v00001002d00006840sv0000103Csd0000182F*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv0000103Csd00001830*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv0000103Csd00001835*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv0000103Csd0000183A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv0000103Csd0000183C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv0000103Csd0000183E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv0000103Csd00001840*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv0000103Csd00001842*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv0000103Csd00001844*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv0000103Csd00001848*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv0000103Csd0000184A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv0000103Csd0000184C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv0000103Csd00001895*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv0000103Csd00001897*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv0000103Csd000018A5*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv0000103Csd000018A7*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv0000103Csd000018F4*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001043sd0000100A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001043sd0000104B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001043sd000010DC*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001043sd00002121*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001043sd00002122*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001043sd00002123*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001043sd00002125*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001043sd00002127*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001179sd0000FB11*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001179sd0000FB22*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001179sd0000FB23*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001179sd0000FB2C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001179sd0000FB31*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001179sd0000FB32*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001179sd0000FB38*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001179sd0000FB39*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001179sd0000FB3A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001179sd0000FB40*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001179sd0000FB41*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001179sd0000FB47*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001179sd0000FB48*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001179sd0000FB51*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001179sd0000FB52*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001179sd0000FB53*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001179sd0000FB81*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001179sd0000FB82*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001179sd0000FB83*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001179sd0000FC56*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001179sd0000FCD4*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv00001179sd0000FCEE*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv0000144Dsd0000C0C5*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7690M
+
+pci:v00001002d00006840sv0000144Dsd0000C0CE*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv0000144Dsd0000C0DA*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv000017AAsd00003970*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv000017AAsd0000397B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv000017AAsd00005101*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv000017AAsd00005102*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
+
+pci:v00001002d00006840sv000017AAsd00005103*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7670M
pci:v00001002d00006841*
- ID_MODEL_FROM_DATABASE=Thames [Radeon 7550M/7570M/7650M]
+ ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M]
+
+pci:v00001002d00006841sv00001028sd00000561*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650M
+
+pci:v00001002d00006841sv00001028sd0000056C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650M
+
+pci:v00001002d00006841sv00001028sd0000057F*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7570M
+
+pci:v00001002d00006841sv0000103Csd000017F1*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7570M
+
+pci:v00001002d00006841sv0000103Csd000017F4*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650M
+
+pci:v00001002d00006841sv0000103Csd00001813*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7570M
+
+pci:v00001002d00006841sv0000103Csd0000183A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650M
+
+pci:v00001002d00006841sv0000103Csd0000183C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650M
+
+pci:v00001002d00006841sv0000103Csd0000183E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650M
+
+pci:v00001002d00006841sv0000103Csd00001840*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650M
+
+pci:v00001002d00006841sv0000103Csd00001842*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650M
+
+pci:v00001002d00006841sv0000103Csd00001844*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650M
+
+pci:v00001002d00006841sv00001043sd0000100A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650M
+
+pci:v00001002d00006841sv00001043sd0000104B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650M
+
+pci:v00001002d00006841sv00001043sd000010DC*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650M
+
+pci:v00001002d00006841sv00001043sd00002134*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7650M
+
+pci:v00001002d00006841sv00001179sd00000001*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7570M
+
+pci:v00001002d00006841sv00001179sd00000002*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7570M
+
+pci:v00001002d00006841sv00001179sd0000FB43*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7550M
+
+pci:v00001002d00006841sv00001179sd0000FB91*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7550M
+
+pci:v00001002d00006841sv00001179sd0000FB92*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7550M
+
+pci:v00001002d00006841sv00001179sd0000FB93*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7550M
+
+pci:v00001002d00006841sv00001179sd0000FBA2*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7550M
+
+pci:v00001002d00006841sv00001179sd0000FBA3*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7550M
+
+pci:v00001002d00006841sv0000144Dsd0000C0C7*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7550M
pci:v00001002d00006842*
ID_MODEL_FROM_DATABASE=Thames LE [Radeon HD 7000M Series]
@@ -4637,12 +6287,6 @@ pci:v00001002d00006842*
pci:v00001002d00006843*
ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7670M]
-pci:v00001002d00006849*
- ID_MODEL_FROM_DATABASE=Lombok [AMD Radeon HD 7400 Series]
-
-pci:v00001002d00006880*
- ID_MODEL_FROM_DATABASE=Cypress
-
pci:v00001002d00006888*
ID_MODEL_FROM_DATABASE=Cypress XT [FirePro V8800]
@@ -4724,9 +6368,66 @@ pci:v00001002d000068A1sv0000106Bsd000000CC*
pci:v00001002d000068A8*
ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M]
+pci:v00001002d000068A8sv00001025sd00000442*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6850M
+
+pci:v00001002d000068A8sv00001025sd00000451*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6850M
+
+pci:v00001002d000068A8sv00001025sd0000050A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6850M
+
+pci:v00001002d000068A8sv00001025sd0000050B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6850M
+
+pci:v00001002d000068A8sv00001025sd0000050C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6850M
+
+pci:v00001002d000068A8sv00001025sd0000050E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6850M
+
+pci:v00001002d000068A8sv00001025sd0000050F*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6850M
+
+pci:v00001002d000068A8sv00001025sd00000513*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6850M
+
+pci:v00001002d000068A8sv00001025sd00000514*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6850M
+
+pci:v00001002d000068A8sv00001025sd00000515*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6850M
+
+pci:v00001002d000068A8sv00001025sd00000516*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6850M
+
+pci:v00001002d000068A8sv00001025sd00000525*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6850M
+
+pci:v00001002d000068A8sv00001025sd00000526*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6850M
+
+pci:v00001002d000068A8sv00001025sd0000056D*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6850M
+
+pci:v00001002d000068A8sv00001028sd0000048F*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6870M
+
+pci:v00001002d000068A8sv00001028sd00000490*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6870M
+
+pci:v00001002d000068A8sv00001028sd000004B9*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6870M
+
+pci:v00001002d000068A8sv00001028sd000004BA*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6870M
+
pci:v00001002d000068A8sv0000103Csd0000159B*
ID_MODEL_FROM_DATABASE=Radeon HD 6850M
+pci:v00001002d000068A8sv0000144Dsd0000C0AD*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6850M
+
pci:v00001002d000068A9*
ID_MODEL_FROM_DATABASE=Juniper XT [FirePro V5800]
@@ -4757,6 +6458,21 @@ pci:v00001002d000068BFsv0000174Bsd00006750*
pci:v00001002d000068C0*
ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M]
+pci:v00001002d000068C0sv00001019sd00002383*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5730
+
+pci:v00001002d000068C0sv00001028sd000002A2*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5730
+
+pci:v00001002d000068C0sv00001028sd000002FE*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5730
+
+pci:v00001002d000068C0sv00001028sd00000419*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5730
+
+pci:v00001002d000068C0sv0000103Csd0000147D*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5730
+
pci:v00001002d000068C0sv0000103Csd00001521*
ID_MODEL_FROM_DATABASE=Madison XT [FirePro M5800]
@@ -4769,21 +6485,429 @@ pci:v00001002d000068C0sv0000103Csd00001596*
pci:v00001002d000068C0sv0000103Csd00001599*
ID_MODEL_FROM_DATABASE=Mobility Radeon HD 6570
+pci:v00001002d000068C0sv00001043sd00001C22*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5730
+
+pci:v00001002d000068C0sv000017AAsd00003927*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5730
+
+pci:v00001002d000068C0sv000017AAsd00003952*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5730
+
+pci:v00001002d000068C0sv000017AAsd00003978*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6570M
+
pci:v00001002d000068C1*
- ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6550M]
+ ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M]
+
+pci:v00001002d000068C1sv00001025sd00000205*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000293*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000294*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000296*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000308*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000030A*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000311*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000312*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000031C*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000031D*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
pci:v00001002d000068C1sv00001025sd0000033D*
ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+pci:v00001002d000068C1sv00001025sd0000033E*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000033F*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000346*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
pci:v00001002d000068C1sv00001025sd00000347*
ID_MODEL_FROM_DATABASE=Aspire 7740G
+pci:v00001002d000068C1sv00001025sd00000348*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000356*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000357*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000358*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000359*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000035A*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000035B*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000035C*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000035D*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000035E*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000360*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000362*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000364*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000365*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000366*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000367*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000368*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000036C*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000036D*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000036E*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000036F*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000372*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000373*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000377*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000378*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000379*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000037A*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000037B*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000037E*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000037F*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000382*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000383*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000384*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000385*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000386*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000387*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000388*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000038B*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000038C*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000039A*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000411*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000412*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000418*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000419*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000420*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000421*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000425*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000042A*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000042E*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000042F*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000432*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000433*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000442*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000044C*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd0000044E*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000451*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000454*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000455*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000475*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000476*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000487*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000489*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000498*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001025sd00000517*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6550M
+
+pci:v00001002d000068C1sv00001025sd0000051A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6550M
+
+pci:v00001002d000068C1sv00001025sd0000051B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6550M
+
+pci:v00001002d000068C1sv00001025sd0000051C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6550M
+
+pci:v00001002d000068C1sv00001025sd0000051D*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6550M
+
+pci:v00001002d000068C1sv00001025sd00000525*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6550M
+
+pci:v00001002d000068C1sv00001025sd00000526*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6550M
+
+pci:v00001002d000068C1sv00001025sd0000052B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6550M
+
+pci:v00001002d000068C1sv00001025sd0000052C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6550M
+
+pci:v00001002d000068C1sv00001025sd0000053C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6550M
+
+pci:v00001002d000068C1sv00001025sd0000053D*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6550M
+
+pci:v00001002d000068C1sv00001025sd0000053E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6550M
+
+pci:v00001002d000068C1sv00001025sd0000053F*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6550M
+
+pci:v00001002d000068C1sv00001025sd00000607*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6550M
+
+pci:v00001002d000068C1sv00001028sd0000041B*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001028sd00000447*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001028sd00000448*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001028sd00000456*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001028sd00000457*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv0000103Csd00001436*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv0000103Csd00001437*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv0000103Csd00001440*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv0000103Csd00001448*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv0000103Csd00001449*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv0000103Csd0000144A*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv0000103Csd0000144B*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv0000103Csd0000147B*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv0000103Csd0000149C*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv0000103Csd0000149E*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
pci:v00001002d000068C1sv0000103Csd00001521*
ID_MODEL_FROM_DATABASE=Madison Pro [FirePro M5800]
+pci:v00001002d000068C1sv00001043sd00001BC2*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv0000104Dsd00009071*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv0000104Dsd00009077*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv0000104Dsd00009081*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001179sd0000FD00*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001179sd0000FD12*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001179sd0000FD1A*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001179sd0000FD30*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001179sd0000FD31*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001179sd0000FD50*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001179sd0000FD52*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6530M
+
+pci:v00001002d000068C1sv00001179sd0000FD63*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6530M
+
+pci:v00001002d000068C1sv00001179sd0000FD65*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6530M
+
+pci:v00001002d000068C1sv00001179sd0000FDD0*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv00001179sd0000FDD2*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6530M
+
+pci:v00001002d000068C1sv0000144Dsd0000C07E*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv0000144Dsd0000C085*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv000014C0sd00000043*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv000014C0sd0000004D*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv000017AAsd00003928*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv000017AAsd00003951*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5650
+
+pci:v00001002d000068C1sv000017AAsd00003977*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6550M
+
pci:v00001002d000068C7*
ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5570/6550A]
+pci:v00001002d000068C7sv00001462sd00002241*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5570
+
+pci:v00001002d000068C7sv00001462sd00002243*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5570
+
+pci:v00001002d000068C7sv00001462sd00002244*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5570
+
+pci:v00001002d000068C7sv00001462sd00002245*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6550A
+
+pci:v00001002d000068C7sv00001462sd00002246*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6550A
+
pci:v00001002d000068C8*
ID_MODEL_FROM_DATABASE=Redwood XT GL [FirePro V4800]
@@ -4791,13 +6915,46 @@ pci:v00001002d000068C9*
ID_MODEL_FROM_DATABASE=Redwood PRO GL [FirePro V3800]
pci:v00001002d000068D8*
- ID_MODEL_FROM_DATABASE=Redwood XT [Radeon HD 5670]
+ ID_MODEL_FROM_DATABASE=Redwood XT [Radeon HD 5670/5690/5730]
+
+pci:v00001002d000068D8sv00001028sd000068E0*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5670
+
+pci:v00001002d000068D8sv0000174Bsd00005690*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5690
+
+pci:v00001002d000068D8sv0000174Bsd00005730*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5730
+
+pci:v00001002d000068D8sv0000174Bsd0000E151*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5670
pci:v00001002d000068D8sv00001787sd00003000*
ID_MODEL_FROM_DATABASE=Radeon HD 5730
+pci:v00001002d000068D8sv000017AFsd00003010*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5730
+
+pci:v00001002d000068D8sv000017AFsd00003011*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5690
+
pci:v00001002d000068D9*
- ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5570]
+ ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570]
+
+pci:v00001002d000068D9sv0000103Csd00006870*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5570
+
+pci:v00001002d000068D9sv0000103Csd00006872*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5570
+
+pci:v00001002d000068D9sv00001043sd000003CE*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5550
+
+pci:v00001002d000068D9sv00001462sd00002151*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5570
+
+pci:v00001002d000068D9sv00001462sd00002240*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5570
pci:v00001002d000068D9sv0000148Csd00003000*
ID_MODEL_FROM_DATABASE=Radeon HD 6510
@@ -4805,8 +6962,41 @@ pci:v00001002d000068D9sv0000148Csd00003000*
pci:v00001002d000068D9sv0000148Csd00003001*
ID_MODEL_FROM_DATABASE=Radeon HD 6610
+pci:v00001002d000068D9sv00001545sd00005550*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5550
+
+pci:v00001002d000068D9sv00001545sd00007570*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7570
+
+pci:v00001002d000068D9sv00001642sd00003985*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5570
+
+pci:v00001002d000068D9sv00001642sd00003996*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5570
+
+pci:v00001002d000068D9sv0000174Bsd00003000*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6510
+
+pci:v00001002d000068D9sv0000174Bsd00006510*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6510
+
+pci:v00001002d000068D9sv0000174Bsd00006610*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6610
+
+pci:v00001002d000068D9sv0000174Bsd0000E142*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5570
+
+pci:v00001002d000068D9sv00001787sd00003000*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6510
+
+pci:v00001002d000068D9sv000017AFsd00003000*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6510
+
+pci:v00001002d000068D9sv000017AFsd00003010*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5630
+
pci:v00001002d000068DA*
- ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550]
+ ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570]
pci:v00001002d000068DAsv0000148Csd00003000*
ID_MODEL_FROM_DATABASE=Radeon HD 6390
@@ -4814,30 +7004,156 @@ pci:v00001002d000068DAsv0000148Csd00003000*
pci:v00001002d000068DAsv0000148Csd00003001*
ID_MODEL_FROM_DATABASE=Radeon HD 6490
+pci:v00001002d000068DAsv00001545sd00007570*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7570
+
+pci:v00001002d000068DAsv0000174Bsd00003000*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6390
+
+pci:v00001002d000068DAsv0000174Bsd00005570*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5570
+
+pci:v00001002d000068DAsv0000174Bsd00005630*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5630
+
+pci:v00001002d000068DAsv0000174Bsd00006490*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6490
+
+pci:v00001002d000068DAsv00001787sd00003000*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5630
+
+pci:v00001002d000068DAsv000017AFsd00003000*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6390
+
+pci:v00001002d000068DAsv000017AFsd00003010*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5630
+
pci:v00001002d000068DE*
ID_MODEL_FROM_DATABASE=Redwood
pci:v00001002d000068E0*
ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470]
+pci:v00001002d000068E0sv00001028sd00000404*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5450
+
+pci:v00001002d000068E0sv00001028sd00000414*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5450
+
+pci:v00001002d000068E0sv00001028sd00000434*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5450
+
+pci:v00001002d000068E0sv0000103Csd00001433*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5450
+
+pci:v00001002d000068E0sv0000103Csd00001434*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5450
+
+pci:v00001002d000068E0sv0000103Csd00001469*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5450
+
+pci:v00001002d000068E0sv0000103Csd0000146B*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5450
+
pci:v00001002d000068E0sv0000103Csd00001486*
ID_MODEL_FROM_DATABASE=TouchSmart tm2-2050er discrete GPU (Mobility Radeon HD 5450)
+pci:v00001002d000068E0sv0000103Csd00001622*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5450
+
+pci:v00001002d000068E0sv0000103Csd00001623*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5450
+
+pci:v00001002d000068E0sv0000103Csd0000EEEE*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5450
+
+pci:v00001002d000068E0sv0000104Dsd00009076*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 5450
+
+pci:v00001002d000068E0sv00001682sd0000304E*
+ ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 5450]
+
+pci:v00001002d000068E0sv00001682sd00006000*
+ ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 5450]
+
+pci:v00001002d000068E0sv000017AAsd00009E52*
+ ID_MODEL_FROM_DATABASE=FirePro M3800
+
+pci:v00001002d000068E0sv000017AAsd00009E53*
+ ID_MODEL_FROM_DATABASE=FirePro M3800
+
pci:v00001002d000068E1*
ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430]
+pci:v00001002d000068E1sv00001043sd0000041F*
+ ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 7350]
+
+pci:v00001002d000068E1sv00001043sd00003000*
+ ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 5450]
+
+pci:v00001002d000068E1sv0000148Csd00003000*
+ ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 5450]
+
+pci:v00001002d000068E1sv0000148Csd00003001*
+ ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6230]
+
+pci:v00001002d000068E1sv0000148Csd00003002*
+ ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6250]
+
+pci:v00001002d000068E1sv0000148Csd00003003*
+ ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6350]
+
pci:v00001002d000068E1sv0000148Csd00007350*
ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 7350]
+pci:v00001002d000068E1sv0000148Csd00008350*
+ ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 8350]
+
pci:v00001002d000068E1sv00001545sd00005450*
ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 5450]
+pci:v00001002d000068E1sv00001545sd00007350*
+ ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 7350]
+
+pci:v00001002d000068E1sv00001682sd00003000*
+ ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 5450]
+
+pci:v00001002d000068E1sv00001682sd00006000*
+ ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 5450]
+
+pci:v00001002d000068E1sv00001682sd00007350*
+ ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 7350]
+
+pci:v00001002d000068E1sv0000174Bsd00003000*
+ ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 5450]
+
pci:v00001002d000068E1sv0000174Bsd00005470*
ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 5470]
+pci:v00001002d000068E1sv0000174Bsd00006000*
+ ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 5450]
+
+pci:v00001002d000068E1sv0000174Bsd00006230*
+ ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6230]
+
pci:v00001002d000068E1sv0000174Bsd00006350*
ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6350]
+pci:v00001002d000068E1sv0000174Bsd00007350*
+ ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 7350]
+
+pci:v00001002d000068E1sv00001787sd00003000*
+ ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 5450]
+
+pci:v00001002d000068E1sv000017AFsd00003000*
+ ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 5450]
+
+pci:v00001002d000068E1sv000017AFsd00003001*
+ ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6230]
+
+pci:v00001002d000068E1sv000017AFsd00003014*
+ ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6350]
+
pci:v00001002d000068E1sv000017AFsd00003015*
ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 7350]
@@ -4847,11 +7163,221 @@ pci:v00001002d000068E1sv000017AFsd00008350*
pci:v00001002d000068E4*
ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M]
+pci:v00001002d000068E4sv00001019sd00002386*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6350M
+
+pci:v00001002d000068E4sv00001019sd00002387*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6350M
+
+pci:v00001002d000068E4sv00001019sd0000238D*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv00001019sd0000238E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv00001025sd00000382*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv00001025sd00000489*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv00001025sd0000048A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv00001025sd0000048B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv00001025sd0000048C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv00001028sd000004C1*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv00001028sd000004CA*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv00001028sd000004CC*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv00001028sd000004CD*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv00001028sd000004D7*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd00001411*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd00001421*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd00001426*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd00001428*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd0000142A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd0000142B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd0000143A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd0000143C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd00001445*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd0000162C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd0000162D*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd0000162E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd0000162F*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd00001639*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd0000163A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd0000163B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd0000163C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd0000163D*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd0000163E*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd0000163F*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd00001641*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd00001643*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd00003578*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd0000357A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd00003673*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000103Csd00003675*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv00001043sd00001C92*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv00001043sd000084A1*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv00001043sd000084AD*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000104Dsd00009081*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv00001545sd00007350*
+ ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350]
+
+pci:v00001002d000068E4sv00001558sd00004510*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv00001558sd00005505*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv0000174Bsd00005450*
+ ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5450]
+
+pci:v00001002d000068E4sv000017AAsd000021DD*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv000017AAsd000021E9*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv000017AAsd00003971*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M
+
+pci:v00001002d000068E4sv000017AAsd00003972*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7370M
+
+pci:v00001002d000068E4sv000017AAsd0000397A*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M/7370M
+
+pci:v00001002d000068E4sv000017AAsd0000397B*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6370M/7370M
+
+pci:v00001002d000068E4sv000017AAsd0000397F*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7370M
+
pci:v00001002d000068E5*
ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M]
+pci:v00001002d000068E5sv00001179sd0000FD3C*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6330M
+
+pci:v00001002d000068E5sv00001179sd0000FD50*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6330M
+
+pci:v00001002d000068E5sv00001179sd0000FD52*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6330M
+
+pci:v00001002d000068E5sv00001179sd0000FD63*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6330M
+
+pci:v00001002d000068E5sv00001179sd0000FD65*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6330M
+
+pci:v00001002d000068E5sv00001179sd0000FD73*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6330M
+
+pci:v00001002d000068E5sv00001179sd0000FD75*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6330M
+
+pci:v00001002d000068E5sv00001179sd0000FDD0*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6330M
+
+pci:v00001002d000068E5sv00001179sd0000FDD2*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6330M
+
+pci:v00001002d000068E5sv00001179sd0000FDEA*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6330M
+
+pci:v00001002d000068E5sv00001179sd0000FDF8*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6330M
+
+pci:v00001002d000068E5sv0000148Csd00005450*
+ ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5450]
+
+pci:v00001002d000068E5sv0000148Csd00006350*
+ ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 6350]
+
pci:v00001002d000068E5sv0000148Csd00007350*
- ID_MODEL_FROM_DATABASE=Radeon HD 7350
+ ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350]
+
+pci:v00001002d000068E5sv0000148Csd00008350*
+ ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 8350]
+
+pci:v00001002d000068E5sv00001545sd00007350*
+ ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350]
pci:v00001002d000068E8*
ID_MODEL_FROM_DATABASE=Cedar
@@ -4869,20 +7395,74 @@ pci:v00001002d000068F8*
ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7300 Series]
pci:v00001002d000068F9*
- ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350 Series]
+ ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series]
pci:v00001002d000068F9sv00001019sd00000001*
ID_MODEL_FROM_DATABASE=Radeon HD 5450
+pci:v00001002d000068F9sv00001019sd00000002*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5450
+
pci:v00001002d000068F9sv00001019sd00000019*
ID_MODEL_FROM_DATABASE=Radeon HD 6350
+pci:v00001002d000068F9sv00001025sd00000518*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5450
+
+pci:v00001002d000068F9sv00001025sd00000519*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5450
+
pci:v00001002d000068F9sv00001028sd0000010E*
ID_MODEL_FROM_DATABASE=XPS 8300
+pci:v00001002d000068F9sv00001028sd00002126*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6350
+
+pci:v00001002d000068F9sv0000103Csd00002126*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6350
+
+pci:v00001002d000068F9sv0000103Csd00002AAC*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5450
+
+pci:v00001002d000068F9sv0000103Csd00002AAE*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5450
+
+pci:v00001002d000068F9sv0000103Csd00003580*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5450
+
pci:v00001002d000068F9sv00001043sd000003C2*
ID_MODEL_FROM_DATABASE=EAH5450 SILENT/DI/512MD2 (LP)
+pci:v00001002d000068F9sv00001462sd00002130*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5450
+
+pci:v00001002d000068F9sv00001462sd00002131*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5450
+
+pci:v00001002d000068F9sv00001462sd00002133*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6350
+
+pci:v00001002d000068F9sv00001462sd00002180*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5450
+
+pci:v00001002d000068F9sv00001462sd00002181*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5450
+
+pci:v00001002d000068F9sv00001462sd00002182*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6350
+
+pci:v00001002d000068F9sv00001462sd00002183*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6350
+
+pci:v00001002d000068F9sv00001462sd00002230*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5450
+
+pci:v00001002d000068F9sv00001462sd00002231*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5450
+
+pci:v00001002d000068F9sv00001462sd00002495*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6350
+
pci:v00001002d000068F9sv0000148Csd00003001*
ID_MODEL_FROM_DATABASE=Radeon HD 5530/6250
@@ -4898,6 +7478,39 @@ pci:v00001002d000068F9sv0000148Csd00003004*
pci:v00001002d000068F9sv0000148Csd00007350*
ID_MODEL_FROM_DATABASE=Radeon HD 7350
+pci:v00001002d000068F9sv0000148Csd00008350*
+ ID_MODEL_FROM_DATABASE=Radeon HD 8350
+
+pci:v00001002d000068F9sv00001545sd00007350*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7350
+
+pci:v00001002d000068F9sv00001642sd00003983*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5450
+
+pci:v00001002d000068F9sv00001642sd00003984*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6350
+
+pci:v00001002d000068F9sv00001642sd00003987*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6350
+
+pci:v00001002d000068F9sv00001642sd00003997*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5450
+
+pci:v00001002d000068F9sv00001642sd00003A05*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5450
+
+pci:v00001002d000068F9sv00001642sd00003B31*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6350A
+
+pci:v00001002d000068F9sv00001682sd00003270*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7350
+
+pci:v00001002d000068F9sv0000174Bsd00003000*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6230
+
+pci:v00001002d000068F9sv0000174Bsd00003987*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6350
+
pci:v00001002d000068F9sv0000174Bsd00005470*
ID_MODEL_FROM_DATABASE=Radeon HD 5470
@@ -4907,11 +7520,131 @@ pci:v00001002d000068F9sv0000174Bsd00005490*
pci:v00001002d000068F9sv0000174Bsd00005530*
ID_MODEL_FROM_DATABASE=Radeon HD 5530
+pci:v00001002d000068F9sv0000174Bsd00006230*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6230
+
+pci:v00001002d000068F9sv0000174Bsd00006250*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6250
+
+pci:v00001002d000068F9sv0000174Bsd00006290*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6290
+
+pci:v00001002d000068F9sv0000174Bsd00006350*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6350
+
pci:v00001002d000068F9sv0000174Bsd00007350*
ID_MODEL_FROM_DATABASE=Radeon HD 7350
+pci:v00001002d000068F9sv0000174Bsd00008350*
+ ID_MODEL_FROM_DATABASE=Radeon HD 8350
+
+pci:v00001002d000068F9sv0000174Bsd0000E127*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5450
+
+pci:v00001002d000068F9sv0000174Bsd0000E145*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5450
+
+pci:v00001002d000068F9sv0000174Bsd0000E153*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5450
+
+pci:v00001002d000068F9sv00001787sd00003000*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5470
+
+pci:v00001002d000068F9sv00001787sd00003001*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5530
+
+pci:v00001002d000068F9sv00001787sd00003002*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5490
+
+pci:v00001002d000068F9sv000017AAsd00003602*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5450
+
+pci:v00001002d000068F9sv000017AAsd00003603*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5450
+
+pci:v00001002d000068F9sv000017AAsd0000360F*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5450
+
+pci:v00001002d000068F9sv000017AAsd00003619*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5450
+
+pci:v00001002d000068F9sv000017AFsd00003000*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6250
+
+pci:v00001002d000068F9sv000017AFsd00003001*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6230
+
+pci:v00001002d000068F9sv000017AFsd00003002*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6290
+
+pci:v00001002d000068F9sv000017AFsd00003011*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5470
+
+pci:v00001002d000068F9sv000017AFsd00003012*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5490
+
+pci:v00001002d000068F9sv000017AFsd00003013*
+ ID_MODEL_FROM_DATABASE=Radeon HD 5470
+
+pci:v00001002d000068F9sv000017AFsd00003014*
+ ID_MODEL_FROM_DATABASE=Radeon HD 6350
+
pci:v00001002d000068FA*
- ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350]
+ ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350]
+
+pci:v00001002d000068FAsv00001019sd00000019*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7350
+
+pci:v00001002d000068FAsv00001019sd00000021*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7350
+
+pci:v00001002d000068FAsv00001019sd00000022*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7350
+
+pci:v00001002d000068FAsv00001019sd00000026*
+ ID_MODEL_FROM_DATABASE=Radeon HD 8350
+
+pci:v00001002d000068FAsv0000103Csd00002ADF*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7350A
+
+pci:v00001002d000068FAsv0000103Csd00002AE8*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7350A
+
+pci:v00001002d000068FAsv00001043sd00008350*
+ ID_MODEL_FROM_DATABASE=Radeon HD 8350
+
+pci:v00001002d000068FAsv00001462sd00002128*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7350
+
+pci:v00001002d000068FAsv00001462sd00002184*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7350
+
+pci:v00001002d000068FAsv00001462sd00002186*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7350
+
+pci:v00001002d000068FAsv00001462sd00002495*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7350
+
+pci:v00001002d000068FAsv00001462sd0000B490*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7350
+
+pci:v00001002d000068FAsv00001642sd00003985*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7350
+
+pci:v00001002d000068FAsv0000174Bsd00007350*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7350
+
+pci:v00001002d000068FAsv0000174Bsd00008153*
+ ID_MODEL_FROM_DATABASE=Radeon HD 8350
+
+pci:v00001002d000068FAsv0000174Bsd0000E127*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7350
+
+pci:v00001002d000068FAsv0000174Bsd0000E153*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7350
+
+pci:v00001002d000068FAsv0000174Bsd0000E180*
+ ID_MODEL_FROM_DATABASE=Radeon HD 7350
pci:v00001002d000068FAsv000017AFsd00003015*
ID_MODEL_FROM_DATABASE=Radeon HD 7350
@@ -4919,6 +7652,9 @@ pci:v00001002d000068FAsv000017AFsd00003015*
pci:v00001002d000068FE*
ID_MODEL_FROM_DATABASE=Cedar LE
+pci:v00001002d00006920*
+ ID_MODEL_FROM_DATABASE=Tonga
+
pci:v00001002d0000700F*
ID_MODEL_FROM_DATABASE=RS100 AGP Bridge
@@ -5418,7 +8154,7 @@ pci:v00001002d00009442sv00001002sd00000502*
ID_MODEL_FROM_DATABASE=MSI Radeon HD 4850 512MB GDDR3
pci:v00001002d00009442sv0000174Bsd0000E810*
- ID_MODEL_FROM_DATABASE=Sapphire Radeon HD 4850 512MB GDDR3
+ ID_MODEL_FROM_DATABASE=Radeon HD 4850 512MB GDDR3
pci:v00001002d00009443*
ID_MODEL_FROM_DATABASE=R700 [Radeon HD 4850 X2]
@@ -5442,7 +8178,7 @@ pci:v00001002d0000944E*
ID_MODEL_FROM_DATABASE=RV770 CE [Radeon HD 4710]
pci:v00001002d0000944Esv0000174Bsd00003261*
- ID_MODEL_FROM_DATABASE=Sapphire Radeon HD 4810
+ ID_MODEL_FROM_DATABASE=Radeon HD 4810
pci:v00001002d00009450*
ID_MODEL_FROM_DATABASE=RV770 GL [FireStream 9270]
@@ -5469,7 +8205,7 @@ pci:v00001002d00009480*
ID_MODEL_FROM_DATABASE=RV730/M96 [Mobility Radeon HD 4650/5165]
pci:v00001002d00009480sv0000103Csd00003628*
- ID_MODEL_FROM_DATABASE=ATI Mobility Radeon HD 4650 [dv6-1190en]
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 4650 [dv6-1190en]
pci:v00001002d00009488*
ID_MODEL_FROM_DATABASE=RV730/M96-XT [Mobility Radeon HD 4670]
@@ -5481,7 +8217,7 @@ pci:v00001002d00009490*
ID_MODEL_FROM_DATABASE=RV730 XT [Radeon HD 4670]
pci:v00001002d00009490sv0000174Bsd0000E880*
- ID_MODEL_FROM_DATABASE=Radeon HD 4670 512MB DDR3
+ ID_MODEL_FROM_DATABASE=Radeon HD 4670 512MB GDDR3 Dual DVI-I/TVO
pci:v00001002d00009491*
ID_MODEL_FROM_DATABASE=RV730/M96-CSP [Radeon E4690]
@@ -5547,10 +8283,10 @@ pci:v00001002d000094C3sv00001028sd00000302*
ID_MODEL_FROM_DATABASE=Radeon HD 2400 Pro
pci:v00001002d000094C3sv0000174Bsd0000E400*
- ID_MODEL_FROM_DATABASE=Sapphire Radeon HD 2400 PRO
+ ID_MODEL_FROM_DATABASE=Radeon HD 2400 PRO
pci:v00001002d000094C3sv000018BCsd00003550*
- ID_MODEL_FROM_DATABASE=GeCube Radeon HD 2400 PRO
+ ID_MODEL_FROM_DATABASE=Radeon HD 2400 PRO
pci:v00001002d000094C4*
ID_MODEL_FROM_DATABASE=RV610 LE [Radeon HD 2400 PRO AGP]
@@ -5583,7 +8319,7 @@ pci:v00001002d00009501*
ID_MODEL_FROM_DATABASE=RV670 [Radeon HD 3870]
pci:v00001002d00009501sv0000174Bsd0000E620*
- ID_MODEL_FROM_DATABASE=Sapphire Radeon HD 3870 PCIe 2.0
+ ID_MODEL_FROM_DATABASE=Radeon HD 3870
pci:v00001002d00009504*
ID_MODEL_FROM_DATABASE=RV670/M88 [Mobility Radeon HD 3850]
@@ -5657,6 +8393,45 @@ pci:v00001002d00009552sv0000174Bsd00003000*
pci:v00001002d00009553*
ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v]
+pci:v00001002d00009553sv00001025sd0000015E*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 4570
+
+pci:v00001002d00009553sv00001025sd0000017D*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 4570
+
+pci:v00001002d00009553sv00001025sd00000205*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 4570
+
+pci:v00001002d00009553sv00001025sd00000206*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 4570
+
+pci:v00001002d00009553sv00001025sd00000237*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 4570
+
+pci:v00001002d00009553sv00001028sd000002BE*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 4570
+
+pci:v00001002d00009553sv00001028sd000002E8*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 4530
+
+pci:v00001002d00009553sv0000103Csd00003624*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 4530
+
+pci:v00001002d00009553sv0000103Csd00003628*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 4530
+
+pci:v00001002d00009553sv0000103Csd00003636*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 4530
+
+pci:v00001002d00009553sv00001043sd00001B32*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 4570
+
+pci:v00001002d00009553sv00001043sd00001B42*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 4570
+
+pci:v00001002d00009553sv0000104Dsd00009056*
+ ID_MODEL_FROM_DATABASE=Mobility Radeon HD 4570
+
pci:v00001002d00009553sv00001179sd0000FF82*
ID_MODEL_FROM_DATABASE=Satellite L505-13T GPU (Mobility Radeon HD 5145)
@@ -5898,7 +8673,7 @@ pci:v00001002d00009802*
ID_MODEL_FROM_DATABASE=Wrestler [Radeon HD 6310]
pci:v00001002d00009802sv0000174Bsd00001001*
- ID_MODEL_FROM_DATABASE=Sapphire PURE Fusion Mini
+ ID_MODEL_FROM_DATABASE=PURE Fusion Mini
pci:v00001002d00009803*
ID_MODEL_FROM_DATABASE=Wrestler [Radeon HD 6310]
@@ -5964,7 +8739,7 @@ pci:v00001002d0000983C*
ID_MODEL_FROM_DATABASE=Kabini
pci:v00001002d0000983D*
- ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8250]
+ ID_MODEL_FROM_DATABASE=Temash [Radeon HD 8250/8280G]
pci:v00001002d0000983E*
ID_MODEL_FROM_DATABASE=Kabini
@@ -5972,6 +8747,54 @@ pci:v00001002d0000983E*
pci:v00001002d0000983F*
ID_MODEL_FROM_DATABASE=Kabini
+pci:v00001002d00009850*
+ ID_MODEL_FROM_DATABASE=Mullins [Radeon APU A6-6200 with R3 Graphics]
+
+pci:v00001002d00009851*
+ ID_MODEL_FROM_DATABASE=Mullins [Radeon APU A4-6000 with R2 Graphics]
+
+pci:v00001002d00009852*
+ ID_MODEL_FROM_DATABASE=Mullins [Radeon APU A4-6000 with R2 Graphics]
+
+pci:v00001002d00009853*
+ ID_MODEL_FROM_DATABASE=Mullins [Radeon APU E2-4000 with R2 Graphics]
+
+pci:v00001002d00009854*
+ ID_MODEL_FROM_DATABASE=Mullins [Radeon APU E2-3700 with R2 Graphics]
+
+pci:v00001002d00009855*
+ ID_MODEL_FROM_DATABASE=Mullins [Radeon APU XX-2450M with R3 Graphics]
+
+pci:v00001002d00009856*
+ ID_MODEL_FROM_DATABASE=Mullins [Radeon APU XX-2200M with R2 Graphics]
+
+pci:v00001002d00009857*
+ ID_MODEL_FROM_DATABASE=Mullins [Radeon APU XX-2200M with R2 Graphics]
+
+pci:v00001002d00009858*
+ ID_MODEL_FROM_DATABASE=Mullins
+
+pci:v00001002d00009859*
+ ID_MODEL_FROM_DATABASE=Mullins
+
+pci:v00001002d0000985A*
+ ID_MODEL_FROM_DATABASE=Mullins
+
+pci:v00001002d0000985B*
+ ID_MODEL_FROM_DATABASE=Mullins
+
+pci:v00001002d0000985C*
+ ID_MODEL_FROM_DATABASE=Mullins
+
+pci:v00001002d0000985D*
+ ID_MODEL_FROM_DATABASE=Mullins
+
+pci:v00001002d0000985E*
+ ID_MODEL_FROM_DATABASE=Mullins
+
+pci:v00001002d0000985F*
+ ID_MODEL_FROM_DATABASE=Mullins
+
pci:v00001002d00009901*
ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7660D]
@@ -6093,10 +8916,10 @@ pci:v00001002d0000AA10*
ID_MODEL_FROM_DATABASE=RV610 HDMI Audio [Radeon HD 2350/2400 Series]
pci:v00001002d0000AA10sv0000174Bsd0000AA10*
- ID_MODEL_FROM_DATABASE=Sapphire HD 2400 PRO audio device
+ ID_MODEL_FROM_DATABASE=Radeon HD 2400 PRO
pci:v00001002d0000AA10sv000018BCsd0000AA10*
- ID_MODEL_FROM_DATABASE=GeCube Radeon HD 2400 PRO HDCP-capable digital-only audio device
+ ID_MODEL_FROM_DATABASE=Radeon HD 2400 PRO
pci:v00001002d0000AA18*
ID_MODEL_FROM_DATABASE=RV670/680 HDMI Audio [Radeon HD 3690/3800 Series]
@@ -6111,16 +8934,13 @@ pci:v00001002d0000AA30*
ID_MODEL_FROM_DATABASE=RV770 HDMI Audio [Radeon HD 4850/4870]
pci:v00001002d0000AA30sv0000174Bsd0000AA30*
- ID_MODEL_FROM_DATABASE=Sapphire HD 4850 512MB GDDR3 PCI-E Dual Slot Fansink
+ ID_MODEL_FROM_DATABASE=Radeon HD 4850 512MB GDDR3 PCI-E Dual Slot Fansink
pci:v00001002d0000AA38*
ID_MODEL_FROM_DATABASE=RV710/730 HDMI Audio [Radeon HD 4000 series]
pci:v00001002d0000AA38sv0000103Csd00003628*
- ID_MODEL_FROM_DATABASE=ATI RV710/730 [dv6-1190en]
-
-pci:v00001002d0000AA38sv0000174Bsd0000AA38*
- ID_MODEL_FROM_DATABASE=R700 Audio Device [Radeon HD 4000 Series]
+ ID_MODEL_FROM_DATABASE=dv6-1190en
pci:v00001002d0000AA50*
ID_MODEL_FROM_DATABASE=Cypress HDMI Audio [Radeon HD 5800 Series]
@@ -6159,7 +8979,7 @@ pci:v00001002d0000AA98*
ID_MODEL_FROM_DATABASE=Caicos HDMI Audio [Radeon HD 6400 Series]
pci:v00001002d0000AA98sv0000174Bsd0000AA98*
- ID_MODEL_FROM_DATABASE=Sapphire HD 6450 1GB DDR3
+ ID_MODEL_FROM_DATABASE=Radeon HD 6450 1GB DDR3
pci:v00001002d0000AAA0*
ID_MODEL_FROM_DATABASE=Tahiti XT HDMI Audio [Radeon HD 7970 Series]
@@ -7370,6 +10190,27 @@ pci:v00001014d0000034Asv00001014sd0000035E*
pci:v00001014d0000034Asv00001014sd000003FB*
ID_MODEL_FROM_DATABASE=PCIe3 28GB Cache RAID SAS Enclosure 6Gb x 16 (57D5)
+pci:v00001014d0000034Asv00001014sd000003FE*
+ ID_MODEL_FROM_DATABASE=PCIe3 x8 Cache SAS RAID Internal Adapter 6Gb (57D8)
+
+pci:v00001014d0000034Asv00001014sd000003FF*
+ ID_MODEL_FROM_DATABASE=PCIe3 x8 SAS RAID Internal Adapter 6Gb (57D7)
+
+pci:v00001014d0000034Asv00001014sd00000474*
+ ID_MODEL_FROM_DATABASE=PCIe3 x16 Cache SAS RAID Internal Adapter 6Gb (57EB)
+
+pci:v00001014d0000034Asv00001014sd00000475*
+ ID_MODEL_FROM_DATABASE=PCIe3 x16 SAS RAID Internal Adapter 6Gb (57EC)
+
+pci:v00001014d0000034Asv00001014sd00000499*
+ ID_MODEL_FROM_DATABASE=PCIe3 x16 Cache SAS RAID Internal Adapter 6Gb (57ED)
+
+pci:v00001014d0000034Asv00001014sd0000049A*
+ ID_MODEL_FROM_DATABASE=PCIe3 x16 SAS RAID Internal Adapter 6Gb (57EE)
+
+pci:v00001014d000004AA*
+ ID_MODEL_FROM_DATABASE=Flash Adapter 90 (PCIe2 0.9TB)
+
pci:v00001014d00003022*
ID_MODEL_FROM_DATABASE=QLA3022 Network Adapter
@@ -7674,14 +10515,11 @@ pci:v00001022d00001510*
ID_MODEL_FROM_DATABASE=Family 14h Processor Root Complex
pci:v00001022d00001510sv0000174Bsd00001001*
- ID_MODEL_FROM_DATABASE=Sapphire PURE Fusion Mini
+ ID_MODEL_FROM_DATABASE=PURE Fusion Mini
pci:v00001022d00001512*
ID_MODEL_FROM_DATABASE=Family 14h Processor Root Port
-pci:v00001022d00001512sv0000174Bsd00001001*
- ID_MODEL_FROM_DATABASE=Sapphire PURE Fusion Mini
-
pci:v00001022d00001513*
ID_MODEL_FROM_DATABASE=Family 14h Processor Root Port
@@ -8126,6 +10964,9 @@ pci:v00001022d0000780C*
pci:v00001022d0000780D*
ID_MODEL_FROM_DATABASE=FCH Azalia Controller
+pci:v00001022d0000780Dsv00001043sd00008444*
+ ID_MODEL_FROM_DATABASE=F2A85-M Series
+
pci:v00001022d0000780E*
ID_MODEL_FROM_DATABASE=FCH LPC Bridge
@@ -8141,6 +10982,12 @@ pci:v00001022d00007813*
pci:v00001022d00007814*
ID_MODEL_FROM_DATABASE=FCH USB XHCI Controller
+pci:v00001022d00007900*
+ ID_MODEL_FROM_DATABASE=CZ SATA Controller [IDE mode]
+
+pci:v00001022d0000790B*
+ ID_MODEL_FROM_DATABASE=CZ SMBus Controller
+
pci:v00001022d00009600*
ID_MODEL_FROM_DATABASE=RS780 Host Bridge
@@ -8172,7 +11019,7 @@ pci:v00001022d00009606*
ID_MODEL_FROM_DATABASE=RS780 PCI to PCI bridge (PCIE port 2)
pci:v00001022d00009607*
- ID_MODEL_FROM_DATABASE=RS780 PCI to PCI bridge (PCIE port 3)
+ ID_MODEL_FROM_DATABASE=RS780/RS880 PCI to PCI bridge (PCIE port 3)
pci:v00001022d00009608*
ID_MODEL_FROM_DATABASE=RS780/RS880 PCI to PCI bridge (PCIE port 4)
@@ -10731,31 +13578,28 @@ pci:v0000103Cd0000323C*
ID_MODEL_FROM_DATABASE=Smart Array Gen8+ Controllers
pci:v0000103Cd0000323Csv0000103Csd00001920*
- ID_MODEL_FROM_DATABASE=Smart Array
+ ID_MODEL_FROM_DATABASE=P430i
pci:v0000103Cd0000323Csv0000103Csd00001921*
- ID_MODEL_FROM_DATABASE=Smart Array
+ ID_MODEL_FROM_DATABASE=P830i
pci:v0000103Cd0000323Csv0000103Csd00001922*
- ID_MODEL_FROM_DATABASE=Smart Array
+ ID_MODEL_FROM_DATABASE=P430
pci:v0000103Cd0000323Csv0000103Csd00001923*
- ID_MODEL_FROM_DATABASE=Smart Array
+ ID_MODEL_FROM_DATABASE=P431
pci:v0000103Cd0000323Csv0000103Csd00001924*
- ID_MODEL_FROM_DATABASE=Smart Array
+ ID_MODEL_FROM_DATABASE=P830
pci:v0000103Cd0000323Csv0000103Csd00001925*
ID_MODEL_FROM_DATABASE=Smart Array
pci:v0000103Cd0000323Csv0000103Csd00001926*
- ID_MODEL_FROM_DATABASE=Smart Array
-
-pci:v0000103Cd0000323Csv0000103Csd00001927*
- ID_MODEL_FROM_DATABASE=Smart Array
+ ID_MODEL_FROM_DATABASE=P731m
pci:v0000103Cd0000323Csv0000103Csd00001928*
- ID_MODEL_FROM_DATABASE=Smart Array
+ ID_MODEL_FROM_DATABASE=P230i
pci:v0000103Cd00003300*
ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Virtual USB Controller
@@ -11430,7 +14274,7 @@ pci:v0000104Cd00008023sv0000103Csd0000088C*
ID_MODEL_FROM_DATABASE=NC8000 laptop
pci:v0000104Cd00008023sv00001043sd0000808B*
- ID_MODEL_FROM_DATABASE=K8N4-E Mainboard
+ ID_MODEL_FROM_DATABASE=K8N4/A8N Series Mainboard
pci:v0000104Cd00008023sv00001043sd0000815B*
ID_MODEL_FROM_DATABASE=P5W DH Deluxe Motherboard
@@ -11673,7 +14517,7 @@ pci:v0000104Cd00008201*
ID_MODEL_FROM_DATABASE=PCI1620 Firmware Loading Function
pci:v0000104Cd00008204*
- ID_MODEL_FROM_DATABASE=PCI7410,7510,7610 PCI Firmware Loading Function
+ ID_MODEL_FROM_DATABASE=PCI7410/7510/7610 PCI Firmware Loading Function
pci:v0000104Cd00008204sv00001028sd00000139*
ID_MODEL_FROM_DATABASE=Latitude D400
@@ -11949,7 +14793,7 @@ pci:v0000104Cd0000AC49*
ID_MODEL_FROM_DATABASE=PCI7410 PC Card Cardbus Controller
pci:v0000104Cd0000AC4A*
- ID_MODEL_FROM_DATABASE=PCI7510,7610 PC card Cardbus Controller
+ ID_MODEL_FROM_DATABASE=PCI7510/7610 CardBus Bridge
pci:v0000104Cd0000AC4Asv00001028sd00000139*
ID_MODEL_FROM_DATABASE=Latitude D400
@@ -12063,7 +14907,7 @@ pci:v0000104Cd0000AC8Esv00001028sd0000018D*
ID_MODEL_FROM_DATABASE=Inspiron 700m/710m
pci:v0000104Cd0000AC8F*
- ID_MODEL_FROM_DATABASE=PCI7420/7620 Combo CardBus, 1394a-2000 OHCI and SD/MS-Pro Controller
+ ID_MODEL_FROM_DATABASE=PCI7420/7620 SD/MS-Pro Controller
pci:v0000104Cd0000AC8Fsv00001028sd0000018D*
ID_MODEL_FROM_DATABASE=Inspiron 700m/710m
@@ -13520,6 +16364,9 @@ pci:v00001077d00002432*
pci:v00001077d00002532*
ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA
+pci:v00001077d00002532sv0000103Csd00003262*
+ ID_MODEL_FROM_DATABASE=StorageWorks 81Q
+
pci:v00001077d00002532sv00001077sd00000167*
ID_MODEL_FROM_DATABASE=QME2572 Dual Port FC8 HBA Mezzanine
@@ -13766,9 +16613,6 @@ pci:v00001083d00000001*
pci:v00001084*
ID_VENDOR_FROM_DATABASE=Parador
-pci:v00001085*
- ID_VENDOR_FROM_DATABASE=Tulip Computers Int.B.V.
-
pci:v00001086*
ID_VENDOR_FROM_DATABASE=J. Bond Computer Systems
@@ -14465,6 +17309,9 @@ pci:v00001095d00003112sv00009005sd00000250*
pci:v00001095d00003114*
ID_MODEL_FROM_DATABASE=SiI 3114 [SATALink/SATARaid] Serial ATA Controller
+pci:v00001095d00003114sv00001043sd00008167*
+ ID_MODEL_FROM_DATABASE=A8N-SLI Deluxe/Premium Mainboard
+
pci:v00001095d00003114sv00001095sd00003114*
ID_MODEL_FROM_DATABASE=SiI 3114 SATALink Controller
@@ -16488,7 +19335,7 @@ pci:v000010B9d00001689*
ID_MODEL_FROM_DATABASE=M1689 K8 Northbridge [Super K8 Single Chip]
pci:v000010B9d00001695*
- ID_MODEL_FROM_DATABASE=M1695 K8 Northbridge [PCI Express and HyperTransport]
+ ID_MODEL_FROM_DATABASE=M1695 Host Bridge
pci:v000010B9d00001697*
ID_MODEL_FROM_DATABASE=M1697 HTT Host Bridge
@@ -17447,6 +20294,9 @@ pci:v000010DEd00000044*
pci:v000010DEd00000045*
ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 GT]
+pci:v000010DEd00000045sv00001043sd0000817D*
+ ID_MODEL_FROM_DATABASE=V9999GT
+
pci:v000010DEd00000045sv00001458sd00003140*
ID_MODEL_FROM_DATABASE=GV-N68T256D
@@ -17466,7 +20316,7 @@ pci:v000010DEd00000050*
ID_MODEL_FROM_DATABASE=CK804 ISA Bridge
pci:v000010DEd00000050sv00001043sd0000815A*
- ID_MODEL_FROM_DATABASE=K8N4-E or A8N-E Mainboard
+ ID_MODEL_FROM_DATABASE=K8N4/A8N Series Mainboard
pci:v000010DEd00000050sv000010F1sd00002865*
ID_MODEL_FROM_DATABASE=Tomcat K8E (S2865)
@@ -17499,7 +20349,7 @@ pci:v000010DEd00000052sv00001028sd00000225*
ID_MODEL_FROM_DATABASE=PowerEdge T105 SMBus
pci:v000010DEd00000052sv00001043sd0000815A*
- ID_MODEL_FROM_DATABASE=K8N4-E or A8N-E Mainboard
+ ID_MODEL_FROM_DATABASE=K8N4/A8N Series Mainboard
pci:v000010DEd00000052sv000010F1sd00002865*
ID_MODEL_FROM_DATABASE=Tomcat K8E (S2865)
@@ -17523,7 +20373,7 @@ pci:v000010DEd00000053*
ID_MODEL_FROM_DATABASE=CK804 IDE
pci:v000010DEd00000053sv00001043sd0000815A*
- ID_MODEL_FROM_DATABASE=K8N4-E or A8N-E Mainboard
+ ID_MODEL_FROM_DATABASE=K8N4/A8N Series Mainboard
pci:v000010DEd00000053sv000010F1sd00002865*
ID_MODEL_FROM_DATABASE=Tomcat K8E (S2865)
@@ -17550,7 +20400,7 @@ pci:v000010DEd00000054sv00001028sd00000225*
ID_MODEL_FROM_DATABASE=PowerEdge T105 Serial ATA
pci:v000010DEd00000054sv00001043sd0000815A*
- ID_MODEL_FROM_DATABASE=A8N-E Mainboard
+ ID_MODEL_FROM_DATABASE=A8N Series Mainboard
pci:v000010DEd00000054sv000010F1sd00002865*
ID_MODEL_FROM_DATABASE=Tomcat K8E (S2865)
@@ -17577,7 +20427,7 @@ pci:v000010DEd00000055sv00001028sd00000225*
ID_MODEL_FROM_DATABASE=PowerEdge T105 Serial ATA
pci:v000010DEd00000055sv00001043sd0000815A*
- ID_MODEL_FROM_DATABASE=K8N4-E or A8N-E Mainboard
+ ID_MODEL_FROM_DATABASE=K8N4/A8N Series Mainboard
pci:v000010DEd00000055sv000010F1sd00002865*
ID_MODEL_FROM_DATABASE=Tomcat K8E (S2865)
@@ -17601,7 +20451,7 @@ pci:v000010DEd00000057*
ID_MODEL_FROM_DATABASE=CK804 Ethernet Controller
pci:v000010DEd00000057sv00001043sd00008141*
- ID_MODEL_FROM_DATABASE=K8N4-E or A8N-E Mainboard
+ ID_MODEL_FROM_DATABASE=K8N4/A8N Series Mainboard
pci:v000010DEd00000057sv000010DEsd0000CB84*
ID_MODEL_FROM_DATABASE=NF4 Lanparty
@@ -17631,7 +20481,7 @@ pci:v000010DEd00000059*
ID_MODEL_FROM_DATABASE=CK804 AC'97 Audio Controller
pci:v000010DEd00000059sv00001043sd0000812A*
- ID_MODEL_FROM_DATABASE=K8N4-E or A8N-E Mainboard
+ ID_MODEL_FROM_DATABASE=K8N4/A8N Series Mainboard
pci:v000010DEd00000059sv000010F1sd00002865*
ID_MODEL_FROM_DATABASE=Tomcat K8E (S2865)
@@ -17652,7 +20502,7 @@ pci:v000010DEd0000005Asv00001028sd00000225*
ID_MODEL_FROM_DATABASE=PowerEdge T105 onboard USB
pci:v000010DEd0000005Asv00001043sd0000815A*
- ID_MODEL_FROM_DATABASE=K8N4-E or A8N-E Mainboard
+ ID_MODEL_FROM_DATABASE=K8N4/A8N Series Mainboard
pci:v000010DEd0000005Asv000010F1sd00002865*
ID_MODEL_FROM_DATABASE=Tomcat K8E (S2865)
@@ -17679,7 +20529,7 @@ pci:v000010DEd0000005Bsv00001028sd00000225*
ID_MODEL_FROM_DATABASE=PowerEdge T105 onboard USB
pci:v000010DEd0000005Bsv00001043sd0000815A*
- ID_MODEL_FROM_DATABASE=K8N4-E or A8N-E Mainboard
+ ID_MODEL_FROM_DATABASE=K8N4/A8N Series Mainboard
pci:v000010DEd0000005Bsv000010F1sd00002865*
ID_MODEL_FROM_DATABASE=Tomcat K8E (S2865)
@@ -17712,7 +20562,7 @@ pci:v000010DEd0000005Esv00001028sd00000225*
ID_MODEL_FROM_DATABASE=PowerEdge T105 Memory Controller
pci:v000010DEd0000005Esv00001043sd0000815A*
- ID_MODEL_FROM_DATABASE=A8N-E Mainboard
+ ID_MODEL_FROM_DATABASE=A8N Series Mainboard
pci:v000010DEd0000005Esv000010DEsd0000005E*
ID_MODEL_FROM_DATABASE=ECS Elitegroup NFORCE3-A939 motherboard.
@@ -19865,6 +22715,9 @@ pci:v000010DEd00000391*
pci:v000010DEd00000391sv00001458sd00003427*
ID_MODEL_FROM_DATABASE=GV-NX76T128D-RH
+pci:v000010DEd00000391sv00001462sd00000452*
+ ID_MODEL_FROM_DATABASE=NX7600GT-VT2D256E
+
pci:v000010DEd00000392*
ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GS]
@@ -20687,6 +23540,9 @@ pci:v000010DEd000005E2*
pci:v000010DEd000005E3*
ID_MODEL_FROM_DATABASE=GT200b [GeForce GTX 285]
+pci:v000010DEd000005E3sv00001682sd00002490*
+ ID_MODEL_FROM_DATABASE=GX-285N-ZDF
+
pci:v000010DEd000005E6*
ID_MODEL_FROM_DATABASE=GT200b [GeForce GTX 275]
@@ -21674,6 +24530,9 @@ pci:v000010DEd00000862*
pci:v000010DEd00000863*
ID_MODEL_FROM_DATABASE=C79 [GeForce 9400M]
+pci:v000010DEd00000863sv0000106Bsd000000AA*
+ ID_MODEL_FROM_DATABASE=MacBook5,1
+
pci:v000010DEd00000864*
ID_MODEL_FROM_DATABASE=C79 [GeForce 9300]
@@ -21719,9 +24578,30 @@ pci:v000010DEd00000871*
pci:v000010DEd00000872*
ID_MODEL_FROM_DATABASE=C79 [GeForce G102M]
+pci:v000010DEd00000872sv00001043sd000019B4*
+ ID_MODEL_FROM_DATABASE=GeForce G102M
+
+pci:v000010DEd00000872sv00001043sd00001AA2*
+ ID_MODEL_FROM_DATABASE=GeForce G102M
+
+pci:v000010DEd00000872sv00001043sd00001C02*
+ ID_MODEL_FROM_DATABASE=GeForce G102M
+
+pci:v000010DEd00000872sv00001043sd00001C42*
+ ID_MODEL_FROM_DATABASE=GeForce G205M
+
pci:v000010DEd00000873*
ID_MODEL_FROM_DATABASE=C79 [GeForce G102M]
+pci:v000010DEd00000873sv00001043sd000019B4*
+ ID_MODEL_FROM_DATABASE=GeForce G102M
+
+pci:v000010DEd00000873sv00001043sd00001C12*
+ ID_MODEL_FROM_DATABASE=GeForce G102M
+
+pci:v000010DEd00000873sv00001043sd00001C52*
+ ID_MODEL_FROM_DATABASE=GeForce G205M
+
pci:v000010DEd00000874*
ID_MODEL_FROM_DATABASE=C79 [ION]
@@ -21884,6 +24764,123 @@ pci:v000010DEd00000A78*
pci:v000010DEd00000A7A*
ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M]
+pci:v000010DEd00000A7Asv0000104Dsd0000907E*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv00001179sd0000FC50*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv00001179sd0000FC61*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv00001179sd0000FC71*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv00001179sd0000FC90*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv00001179sd0000FCC0*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv00001179sd0000FCD0*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv00001179sd0000FCE2*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv00001179sd0000FCF2*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv00001179sd0000FD16*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv00001179sd0000FD40*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv00001179sd0000FD50*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv00001179sd0000FD52*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv00001179sd0000FD61*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv00001179sd0000FD71*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv00001179sd0000FD92*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv00001179sd0000FD96*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv00001179sd0000FDD0*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv00001179sd0000FDD2*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv00001179sd0000FDFE*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv0000144Dsd0000C0A2*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv0000144Dsd0000C0B2*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv0000144Dsd0000C581*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv0000144Dsd0000C587*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv0000144Dsd0000C588*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv0000144Dsd0000C597*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv0000144Dsd0000C606*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv00001462sd0000AA51*
+ ID_MODEL_FROM_DATABASE=GeForce 405
+
+pci:v000010DEd00000A7Asv00001462sd0000AA58*
+ ID_MODEL_FROM_DATABASE=GeForce 405
+
+pci:v000010DEd00000A7Asv00001462sd0000AC71*
+ ID_MODEL_FROM_DATABASE=GeForce 405
+
+pci:v000010DEd00000A7Asv00001462sd0000AC81*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv00001462sd0000AC82*
+ ID_MODEL_FROM_DATABASE=GeForce 405
+
+pci:v000010DEd00000A7Asv00001462sd0000AE33*
+ ID_MODEL_FROM_DATABASE=GeForce 405
+
+pci:v000010DEd00000A7Asv000017AAsd00003950*
+ ID_MODEL_FROM_DATABASE=GeForce 405M
+
+pci:v000010DEd00000A7Asv000017AAsd0000397D*
+ ID_MODEL_FROM_DATABASE=GeForce 405M
+
+pci:v000010DEd00000A7Asv00001B0Asd00002091*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
+pci:v000010DEd00000A7Asv00001BFDsd00000003*
+ ID_MODEL_FROM_DATABASE=GeForce 405
+
+pci:v000010DEd00000A7Asv00001BFDsd00008006*
+ ID_MODEL_FROM_DATABASE=GeForce 405
+
+pci:v000010DEd00000A7Asv00001BFDsd00008007*
+ ID_MODEL_FROM_DATABASE=GeForce 315M
+
pci:v000010DEd00000A7B*
ID_MODEL_FROM_DATABASE=GT218 [GeForce 505]
@@ -22427,11 +25424,14 @@ pci:v000010DEd00000E09*
pci:v000010DEd00000E0A*
ID_MODEL_FROM_DATABASE=GK104 HDMI Audio Controller
+pci:v000010DEd00000E0B*
+ ID_MODEL_FROM_DATABASE=GK106 HDMI Audio Controller
+
pci:v000010DEd00000E0C*
ID_MODEL_FROM_DATABASE=GF114 HDMI Audio Controller
pci:v000010DEd00000E1A*
- ID_MODEL_FROM_DATABASE=GK110 HDMI Audio [GeForce GTX Titan]
+ ID_MODEL_FROM_DATABASE=GK110 HDMI Audio
pci:v000010DEd00000E1B*
ID_MODEL_FROM_DATABASE=GK107 HDMI Audio Controller
@@ -22484,6 +25484,9 @@ pci:v000010DEd00000FC6*
pci:v000010DEd00000FC6sv00001043sd00008428*
ID_MODEL_FROM_DATABASE=GTX650-DC-1GD5
+pci:v000010DEd00000FCD*
+ ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 755M]
+
pci:v000010DEd00000FD1*
ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 650M]
@@ -22505,6 +25508,18 @@ pci:v000010DEd00000FD1sv00001043sd00002141*
pci:v000010DEd00000FD2*
ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 640M]
+pci:v000010DEd00000FD2sv00001028sd0000054F*
+ ID_MODEL_FROM_DATABASE=GeForce GT 640M
+
+pci:v000010DEd00000FD2sv00001028sd0000055F*
+ ID_MODEL_FROM_DATABASE=GeForce GT 640M
+
+pci:v000010DEd00000FD2sv00001028sd00000595*
+ ID_MODEL_FROM_DATABASE=GeForce GT 640M LE
+
+pci:v000010DEd00000FD2sv00001028sd000005B2*
+ ID_MODEL_FROM_DATABASE=GeForce GT 640M LE
+
pci:v000010DEd00000FD3*
ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 640M LE]
@@ -22524,7 +25539,7 @@ pci:v000010DEd00000FDF*
ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 740M]
pci:v000010DEd00000FE0*
- ID_MODEL_FROM_DATABASE=GK107M [GeForce GTX 660M OEM]
+ ID_MODEL_FROM_DATABASE=GK107M [GeForce GTX 660M Mac Edition]
pci:v000010DEd00000FE1*
ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 730M]
@@ -22532,6 +25547,9 @@ pci:v000010DEd00000FE1*
pci:v000010DEd00000FE3*
ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 745M]
+pci:v000010DEd00000FE3sv000017AAsd00003675*
+ ID_MODEL_FROM_DATABASE=GeForce GT 745A
+
pci:v000010DEd00000FE4*
ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 750M]
@@ -22541,6 +25559,12 @@ pci:v000010DEd00000FE5*
pci:v000010DEd00000FE6*
ID_MODEL_FROM_DATABASE=GK107 [NVS K1 USM]
+pci:v000010DEd00000FE7*
+ ID_MODEL_FROM_DATABASE=GK107GL [GRID K1]
+
+pci:v000010DEd00000FE7sv000010DEsd0000101E*
+ ID_MODEL_FROM_DATABASE=GRID K100
+
pci:v000010DEd00000FEF*
ID_MODEL_FROM_DATABASE=GK107GL [GRID K340]
@@ -22553,9 +25577,18 @@ pci:v000010DEd00000FF2*
pci:v000010DEd00000FF5*
ID_MODEL_FROM_DATABASE=GK107GL [Tesla K1 USM]
+pci:v000010DEd00000FF6*
+ ID_MODEL_FROM_DATABASE=GK107GLM [Quadro K1100M]
+
pci:v000010DEd00000FF7*
ID_MODEL_FROM_DATABASE=GK107GL [Quadro K1 USM]
+pci:v000010DEd00000FF7sv000010DEsd00001037*
+ ID_MODEL_FROM_DATABASE=GRID K140Q
+
+pci:v000010DEd00000FF8*
+ ID_MODEL_FROM_DATABASE=GK107GLM [Quadro K500M]
+
pci:v000010DEd00000FF9*
ID_MODEL_FROM_DATABASE=GK107GL [Quadro K2000D]
@@ -22580,6 +25613,9 @@ pci:v000010DEd00000FFF*
pci:v000010DEd00001003*
ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX Titan LE]
+pci:v000010DEd00001004*
+ ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX 780]
+
pci:v000010DEd00001005*
ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX Titan]
@@ -22622,6 +25658,9 @@ pci:v000010DEd00001026*
pci:v000010DEd00001028*
ID_MODEL_FROM_DATABASE=GK110GL [Tesla K20m]
+pci:v000010DEd0000103A*
+ ID_MODEL_FROM_DATABASE=GK110GL [Quadro K6000]
+
pci:v000010DEd00001040*
ID_MODEL_FROM_DATABASE=GF119 [GeForce GT 520]
@@ -22688,6 +25727,9 @@ pci:v000010DEd0000105Asv00001043sd00002112*
pci:v000010DEd0000105B*
ID_MODEL_FROM_DATABASE=GF119M [GeForce 705M]
+pci:v000010DEd0000105Bsv0000103Csd00002AFB*
+ ID_MODEL_FROM_DATABASE=GeForce 705A
+
pci:v000010DEd0000107C*
ID_MODEL_FROM_DATABASE=GF119 [NVS 315]
@@ -22775,27 +25817,132 @@ pci:v000010DEd000010D8*
pci:v000010DEd00001140*
ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M / GT 620M/625M/630M/720M]
+pci:v000010DEd00001140sv00001025sd00000600*
+ ID_MODEL_FROM_DATABASE=GeForce GT 620M
+
+pci:v000010DEd00001140sv00001025sd00000606*
+ ID_MODEL_FROM_DATABASE=GeForce GT 620M
+
pci:v000010DEd00001140sv00001025sd0000064A*
ID_MODEL_FROM_DATABASE=GeForce GT 620M
pci:v000010DEd00001140sv00001025sd0000064C*
ID_MODEL_FROM_DATABASE=GeForce GT 620M
+pci:v000010DEd00001140sv00001025sd0000067A*
+ ID_MODEL_FROM_DATABASE=GeForce GT 620M
+
+pci:v000010DEd00001140sv00001025sd00000680*
+ ID_MODEL_FROM_DATABASE=GeForce GT 620M
+
+pci:v000010DEd00001140sv00001025sd00000686*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001025sd00000689*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001025sd0000068B*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001025sd0000068D*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001025sd0000068E*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
pci:v000010DEd00001140sv00001025sd00000691*
ID_MODEL_FROM_DATABASE=GeForce 710M
+pci:v000010DEd00001140sv00001025sd00000692*
+ ID_MODEL_FROM_DATABASE=GeForce GT 620M
+
+pci:v000010DEd00001140sv00001025sd00000694*
+ ID_MODEL_FROM_DATABASE=GeForce GT 620M
+
+pci:v000010DEd00001140sv00001025sd00000702*
+ ID_MODEL_FROM_DATABASE=GeForce GT 620M
+
pci:v000010DEd00001140sv00001025sd00000719*
ID_MODEL_FROM_DATABASE=GeForce GT 620M
pci:v000010DEd00001140sv00001025sd00000725*
ID_MODEL_FROM_DATABASE=GeForce GT 620M
+pci:v000010DEd00001140sv00001025sd00000728*
+ ID_MODEL_FROM_DATABASE=GeForce GT 620M
+
pci:v000010DEd00001140sv00001025sd0000072B*
ID_MODEL_FROM_DATABASE=GeForce GT 620M
+pci:v000010DEd00001140sv00001025sd0000072E*
+ ID_MODEL_FROM_DATABASE=GeForce GT 620M
+
+pci:v000010DEd00001140sv00001025sd00000732*
+ ID_MODEL_FROM_DATABASE=GeForce GT 620M
+
+pci:v000010DEd00001140sv00001025sd00000763*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
pci:v000010DEd00001140sv00001025sd00000773*
ID_MODEL_FROM_DATABASE=GeForce 710M
+pci:v000010DEd00001140sv00001025sd00000774*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001025sd00000776*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv00001025sd0000077A*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001025sd0000077B*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001025sd0000077C*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001025sd0000077D*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001025sd0000077E*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001025sd0000077F*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001025sd00000781*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv00001025sd00000798*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv00001025sd00000799*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv00001025sd0000079B*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv00001025sd0000079C*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv00001025sd00000807*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv00001025sd00000821*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv00001025sd00000823*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv00001025sd00000830*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv00001025sd00000837*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv00001025sd00000841*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
pci:v000010DEd00001140sv00001028sd0000054D*
ID_MODEL_FROM_DATABASE=GeForce GT 630M
@@ -22811,6 +25958,60 @@ pci:v000010DEd00001140sv00001028sd00000557*
pci:v000010DEd00001140sv00001028sd00000565*
ID_MODEL_FROM_DATABASE=GeForce GT 630M
+pci:v000010DEd00001140sv00001028sd00000568*
+ ID_MODEL_FROM_DATABASE=GeForce GT 630M
+
+pci:v000010DEd00001140sv00001028sd00000590*
+ ID_MODEL_FROM_DATABASE=GeForce GT 630M
+
+pci:v000010DEd00001140sv00001028sd00000592*
+ ID_MODEL_FROM_DATABASE=GeForce GT 625M
+
+pci:v000010DEd00001140sv00001028sd00000594*
+ ID_MODEL_FROM_DATABASE=GeForce GT 625M
+
+pci:v000010DEd00001140sv00001028sd00000595*
+ ID_MODEL_FROM_DATABASE=GeForce GT 625M
+
+pci:v000010DEd00001140sv00001028sd000005A2*
+ ID_MODEL_FROM_DATABASE=GeForce GT 625M
+
+pci:v000010DEd00001140sv00001028sd000005B1*
+ ID_MODEL_FROM_DATABASE=GeForce GT 625M
+
+pci:v000010DEd00001140sv00001028sd000005B3*
+ ID_MODEL_FROM_DATABASE=GeForce GT 625M
+
+pci:v000010DEd00001140sv00001028sd000005DA*
+ ID_MODEL_FROM_DATABASE=GeForce GT 630M
+
+pci:v000010DEd00001140sv00001028sd000005E8*
+ ID_MODEL_FROM_DATABASE=GeForce GT 630M
+
+pci:v000010DEd00001140sv00001028sd000005F4*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv0000103Csd000018EF*
+ ID_MODEL_FROM_DATABASE=GeForce GT 630M
+
+pci:v000010DEd00001140sv0000103Csd000018F9*
+ ID_MODEL_FROM_DATABASE=GeForce GT 630M
+
+pci:v000010DEd00001140sv0000103Csd000018FB*
+ ID_MODEL_FROM_DATABASE=GeForce GT 630M
+
+pci:v000010DEd00001140sv0000103Csd000018FD*
+ ID_MODEL_FROM_DATABASE=GeForce GT 630M
+
+pci:v000010DEd00001140sv0000103Csd000018FF*
+ ID_MODEL_FROM_DATABASE=GeForce GT 630M
+
+pci:v000010DEd00001140sv0000103Csd00002AEF*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720A
+
+pci:v000010DEd00001140sv0000103Csd00002AF9*
+ ID_MODEL_FROM_DATABASE=GeForce 710A
+
pci:v000010DEd00001140sv00001043sd000010DD*
ID_MODEL_FROM_DATABASE=NVS 5200M
@@ -22826,6 +26027,9 @@ pci:v000010DEd00001140sv00001043sd0000124D*
pci:v000010DEd00001140sv00001043sd0000126D*
ID_MODEL_FROM_DATABASE=GeForce GT 720M
+pci:v000010DEd00001140sv00001043sd0000131D*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
pci:v000010DEd00001140sv00001043sd000014C7*
ID_MODEL_FROM_DATABASE=GeForce GT 720M
@@ -22847,45 +26051,285 @@ pci:v000010DEd00001140sv00001043sd000021FA*
pci:v000010DEd00001140sv00001043sd0000220A*
ID_MODEL_FROM_DATABASE=GeForce GT 720M
+pci:v000010DEd00001140sv00001043sd0000221A*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv00001043sd0000223A*
+ ID_MODEL_FROM_DATABASE=GeForce GT 710M
+
+pci:v000010DEd00001140sv00001043sd0000224A*
+ ID_MODEL_FROM_DATABASE=GeForce GT 710M
+
+pci:v000010DEd00001140sv00001043sd00008595*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv000010CFsd000017F5*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv00001179sd0000FA01*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001179sd0000FA02*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001179sd0000FA03*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001179sd0000FA05*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001179sd0000FA11*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001179sd0000FA13*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001179sd0000FA18*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001179sd0000FA19*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001179sd0000FA21*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001179sd0000FA23*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001179sd0000FA2A*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001179sd0000FA32*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001179sd0000FA33*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001179sd0000FA36*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001179sd0000FA38*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001179sd0000FA42*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001179sd0000FA43*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001179sd0000FA45*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001179sd0000FA47*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001179sd0000FA49*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001179sd0000FA58*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001179sd0000FA59*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001179sd0000FA88*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001179sd0000FA89*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv0000144Dsd0000B092*
+ ID_MODEL_FROM_DATABASE=GeForce GT 620M
+
+pci:v000010DEd00001140sv0000144Dsd0000C0D5*
+ ID_MODEL_FROM_DATABASE=GeForce GT 630M
+
pci:v000010DEd00001140sv0000144Dsd0000C0D7*
ID_MODEL_FROM_DATABASE=GeForce GT 620M
+pci:v000010DEd00001140sv0000144Dsd0000C0E2*
+ ID_MODEL_FROM_DATABASE=NVS 5200M
+
+pci:v000010DEd00001140sv0000144Dsd0000C0E3*
+ ID_MODEL_FROM_DATABASE=NVS 5200M
+
+pci:v000010DEd00001140sv0000144Dsd0000C0E4*
+ ID_MODEL_FROM_DATABASE=NVS 5200M
+
pci:v000010DEd00001140sv0000144Dsd0000C652*
ID_MODEL_FROM_DATABASE=GeForce GT 620M
+pci:v000010DEd00001140sv0000144Dsd0000C709*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv0000144Dsd0000C711*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001462sd000010B8*
+ ID_MODEL_FROM_DATABASE=GeForce GT 710M
+
+pci:v000010DEd00001140sv00001462sd000010E9*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv00001462sd0000AA33*
+ ID_MODEL_FROM_DATABASE=GeForce 720M
+
+pci:v000010DEd00001140sv00001462sd0000AAA2*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv00001462sd0000AE71*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv0000152Dsd00000926*
+ ID_MODEL_FROM_DATABASE=GeForce 620M
+
+pci:v000010DEd00001140sv0000152Dsd00000982*
+ ID_MODEL_FROM_DATABASE=GeForce GT 630M
+
+pci:v000010DEd00001140sv0000152Dsd00000983*
+ ID_MODEL_FROM_DATABASE=GeForce GT 630M
+
+pci:v000010DEd00001140sv0000152Dsd00001030*
+ ID_MODEL_FROM_DATABASE=GeForce GT 630M
+
+pci:v000010DEd00001140sv0000152Dsd00001055*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
pci:v000010DEd00001140sv000017AAsd00002200*
ID_MODEL_FROM_DATABASE=NVS 5200M
+pci:v000010DEd00001140sv000017AAsd00003656*
+ ID_MODEL_FROM_DATABASE=GeForce GT 620M
+
+pci:v000010DEd00001140sv000017AAsd00003800*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv000017AAsd00003801*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv000017AAsd00003802*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv000017AAsd00003803*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv000017AAsd00003804*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
pci:v000010DEd00001140sv000017AAsd00003901*
ID_MODEL_FROM_DATABASE=GeForce 610M / GT 620M
+pci:v000010DEd00001140sv000017AAsd00003902*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv000017AAsd00003903*
+ ID_MODEL_FROM_DATABASE=GeForce 610M/710M
+
pci:v000010DEd00001140sv000017AAsd00003904*
ID_MODEL_FROM_DATABASE=GeForce GT 620M/625M
+pci:v000010DEd00001140sv000017AAsd00003905*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv000017AAsd00003910*
+ ID_MODEL_FROM_DATABASE=GeForce 720M
+
+pci:v000010DEd00001140sv000017AAsd00003912*
+ ID_MODEL_FROM_DATABASE=GeForce 720M
+
+pci:v000010DEd00001140sv000017AAsd00003977*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
pci:v000010DEd00001140sv000017AAsd00003983*
ID_MODEL_FROM_DATABASE=GeForce 610M
+pci:v000010DEd00001140sv000017AAsd00005003*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
pci:v000010DEd00001140sv000017AAsd0000500D*
ID_MODEL_FROM_DATABASE=GeForce GT 620M
+pci:v000010DEd00001140sv000017AAsd00005014*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv000017AAsd00005017*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv000017AAsd00005019*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv000017AAsd0000501A*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv000017AAsd0000501F*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv000017AAsd00005025*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv000017AAsd00005027*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv000017AAsd0000502A*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv000017AAsd0000502B*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv000017AAsd0000502D*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv000017AAsd0000502E*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv000017AAsd0000502F*
+ ID_MODEL_FROM_DATABASE=GeForce GT 720M
+
+pci:v000010DEd00001140sv00001854sd00000177*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001854sd00000180*
+ ID_MODEL_FROM_DATABASE=GeForce 710M
+
+pci:v000010DEd00001140sv00001B0Asd000020DD*
+ ID_MODEL_FROM_DATABASE=GeForce GT 620M
+
+pci:v000010DEd00001140sv00001B0Asd000020DF*
+ ID_MODEL_FROM_DATABASE=GeForce GT 620M
+
pci:v000010DEd00001180*
ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 680]
pci:v000010DEd00001180sv00003842sd00003682*
ID_MODEL_FROM_DATABASE=GeForce GTX 680 Mac Edition
+pci:v000010DEd00001182*
+ ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 760 Ti]
+
pci:v000010DEd00001183*
ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 660 Ti]
+pci:v000010DEd00001184*
+ ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 770]
+
pci:v000010DEd00001185*
ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 660 OEM]
+pci:v000010DEd00001185sv000010DEsd0000106F*
+ ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 760 OEM]
+
+pci:v000010DEd00001187*
+ ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 760]
+
pci:v000010DEd00001188*
ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 690]
pci:v000010DEd00001189*
ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 670]
+pci:v000010DEd00001189sv000010DEsd00001074*
+ ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 760 Ti OEM]
+
pci:v000010DEd0000118A*
ID_MODEL_FROM_DATABASE=GK104GL [GRID K520]
@@ -22895,9 +26339,24 @@ pci:v000010DEd0000118B*
pci:v000010DEd0000118C*
ID_MODEL_FROM_DATABASE=GK104 [NVS K2 USM]
+pci:v000010DEd0000118D*
+ ID_MODEL_FROM_DATABASE=GK104GL [GRID K2]
+
+pci:v000010DEd0000118Dsv000010DEsd0000101D*
+ ID_MODEL_FROM_DATABASE=GRID K200
+
+pci:v000010DEd0000118E*
+ ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 760 OEM]
+
pci:v000010DEd0000118F*
ID_MODEL_FROM_DATABASE=GK104GL [Tesla K10]
+pci:v000010DEd0000119D*
+ ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 775M]
+
+pci:v000010DEd0000119E*
+ ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 780M]
+
pci:v000010DEd0000119F*
ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 780M]
@@ -22913,15 +26372,33 @@ pci:v000010DEd000011A2*
pci:v000010DEd000011A3*
ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 680MX]
+pci:v000010DEd000011A3sv0000106Bsd0000010D*
+ ID_MODEL_FROM_DATABASE=iMac 13,2
+
pci:v000010DEd000011A7*
ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 675MX]
pci:v000010DEd000011B0*
ID_MODEL_FROM_DATABASE=GK104GL [Quadro K2 USM]
+pci:v000010DEd000011B0sv000010DEsd0000101A*
+ ID_MODEL_FROM_DATABASE=GRID K240Q
+
+pci:v000010DEd000011B0sv000010DEsd0000101B*
+ ID_MODEL_FROM_DATABASE=GRID K260Q
+
pci:v000010DEd000011B1*
ID_MODEL_FROM_DATABASE=GK104GL [Tesla K2 USM]
+pci:v000010DEd000011B6*
+ ID_MODEL_FROM_DATABASE=GK104GLM [Quadro K3100M]
+
+pci:v000010DEd000011B7*
+ ID_MODEL_FROM_DATABASE=GK104GLM [Quadro K4100M]
+
+pci:v000010DEd000011B8*
+ ID_MODEL_FROM_DATABASE=GK104GLM [Quadro K5100M]
+
pci:v000010DEd000011BA*
ID_MODEL_FROM_DATABASE=GK104GL [Quadro K5000]
@@ -22976,9 +26453,18 @@ pci:v000010DEd000011C4*
pci:v000010DEd000011C6*
ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 Ti]
+pci:v000010DEd000011C7*
+ ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 750 Ti]
+
+pci:v000010DEd000011C8*
+ ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 OEM]
+
pci:v000010DEd000011E0*
ID_MODEL_FROM_DATABASE=GK106M [GeForce GTX 770M]
+pci:v000010DEd000011E1*
+ ID_MODEL_FROM_DATABASE=GK106M [GeForce GTX 765M]
+
pci:v000010DEd000011E2*
ID_MODEL_FROM_DATABASE=GK106M [GeForce GTX 765M]
@@ -22988,6 +26474,9 @@ pci:v000010DEd000011E3*
pci:v000010DEd000011FA*
ID_MODEL_FROM_DATABASE=GK106GL [Quadro K4000]
+pci:v000010DEd000011FC*
+ ID_MODEL_FROM_DATABASE=GK106GLM [Quadro K2100M]
+
pci:v000010DEd00001200*
ID_MODEL_FROM_DATABASE=GF114 [GeForce GTX 560 Ti]
@@ -23060,8 +26549,38 @@ pci:v000010DEd00001247sv00001043sd0000212B*
pci:v000010DEd00001247sv00001043sd0000212C*
ID_MODEL_FROM_DATABASE=GeForce GT 635M
+pci:v000010DEd00001247sv0000152Dsd00000930*
+ ID_MODEL_FROM_DATABASE=GeForce GT 635M
+
pci:v000010DEd00001248*
- ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M]
+ ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M]
+
+pci:v000010DEd00001248sv0000152Dsd00000930*
+ ID_MODEL_FROM_DATABASE=GeForce GT 635M
+
+pci:v000010DEd00001248sv000017C0sd000010E7*
+ ID_MODEL_FROM_DATABASE=GeForce GT 555M
+
+pci:v000010DEd00001248sv000017C0sd000010E8*
+ ID_MODEL_FROM_DATABASE=GeForce GT 555M
+
+pci:v000010DEd00001248sv000017C0sd000010EA*
+ ID_MODEL_FROM_DATABASE=GeForce GT 555M
+
+pci:v000010DEd00001248sv00001854sd00000890*
+ ID_MODEL_FROM_DATABASE=GeForce GT 555M
+
+pci:v000010DEd00001248sv00001854sd00000891*
+ ID_MODEL_FROM_DATABASE=GeForce GT 555M
+
+pci:v000010DEd00001248sv00001854sd00001795*
+ ID_MODEL_FROM_DATABASE=GeForce GT 555M
+
+pci:v000010DEd00001248sv00001854sd00001796*
+ ID_MODEL_FROM_DATABASE=GeForce GT 555M
+
+pci:v000010DEd00001248sv00001854sd00003005*
+ ID_MODEL_FROM_DATABASE=GeForce GT 555M
pci:v000010DEd00001249*
ID_MODEL_FROM_DATABASE=GF116 [GeForce GTS 450 Rev. 3]
@@ -23072,30 +26591,81 @@ pci:v000010DEd0000124B*
pci:v000010DEd0000124D*
ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M]
+pci:v000010DEd0000124Dsv00001028sd00000491*
+ ID_MODEL_FROM_DATABASE=GeForce GT 555M
+
+pci:v000010DEd0000124Dsv00001028sd00000570*
+ ID_MODEL_FROM_DATABASE=GeForce GT 555M
+
+pci:v000010DEd0000124Dsv00001028sd00000571*
+ ID_MODEL_FROM_DATABASE=GeForce GT 555M
+
+pci:v000010DEd0000124Dsv00001462sd0000108D*
+ ID_MODEL_FROM_DATABASE=GeForce GT 555M
+
+pci:v000010DEd0000124Dsv00001462sd000010CC*
+ ID_MODEL_FROM_DATABASE=GeForce GT 635M
+
pci:v000010DEd00001251*
ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 560M]
pci:v000010DEd00001280*
ID_MODEL_FROM_DATABASE=GK208 [GeForce GT 635]
+pci:v000010DEd00001282*
+ ID_MODEL_FROM_DATABASE=GK208 [GeForce GT 640 Rev. 2]
+
+pci:v000010DEd00001284*
+ ID_MODEL_FROM_DATABASE=GK208 [GeForce GT 630 Rev. 2]
+
pci:v000010DEd00001290*
ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 730M]
+pci:v000010DEd00001290sv0000103Csd00002AFA*
+ ID_MODEL_FROM_DATABASE=GeForce GT 730A
+
+pci:v000010DEd00001290sv0000103Csd00002B04*
+ ID_MODEL_FROM_DATABASE=GeForce GT 730A
+
+pci:v000010DEd00001290sv00001043sd000013AD*
+ ID_MODEL_FROM_DATABASE=GeForce GT 730M
+
+pci:v000010DEd00001290sv00001043sd000013CD*
+ ID_MODEL_FROM_DATABASE=GeForce GT 730M
+
pci:v000010DEd00001291*
ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 735M]
pci:v000010DEd00001292*
ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 740M]
+pci:v000010DEd00001292sv000017AAsd00003675*
+ ID_MODEL_FROM_DATABASE=GeForce GT 740A
+
+pci:v000010DEd00001292sv000017AAsd00003684*
+ ID_MODEL_FROM_DATABASE=GeForce GT 740A
+
pci:v000010DEd00001293*
ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 730M]
pci:v000010DEd00001294*
ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 740M]
+pci:v000010DEd00001295*
+ ID_MODEL_FROM_DATABASE=GK208M [GeForce 710M]
+
+pci:v000010DEd00001298*
+ ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 720M]
+
pci:v000010DEd000012A0*
ID_MODEL_FROM_DATABASE=GK208
+pci:v000010DEd000012B9*
+ ID_MODEL_FROM_DATABASE=GK208GLM [Quadro K610M]
+
+pci:v000010DEd000012BA*
+ ID_MODEL_FROM_DATABASE=GK208GLM [Quadro K510M]
+
pci:v000010DF*
ID_VENDOR_FROM_DATABASE=Emulex Corporation
@@ -23531,6 +27101,9 @@ pci:v000010ECd00005209*
pci:v000010ECd00005229*
ID_MODEL_FROM_DATABASE=RTS5229 PCI Express Card Reader
+pci:v000010ECd00005229sv00001025sd00000813*
+ ID_MODEL_FROM_DATABASE=Aspire R7-571
+
pci:v000010ECd00005288*
ID_MODEL_FROM_DATABASE=Barossa PCI Express Card Reader
@@ -23562,7 +27135,7 @@ pci:v000010ECd00008129sv000010ECsd00008129*
ID_MODEL_FROM_DATABASE=RT8129 Fast Ethernet Adapter
pci:v000010ECd00008129sv000011ECsd00008129*
- ID_MODEL_FROM_DATABASE=RT8129 Fast Ethernet Adapter
+ ID_MODEL_FROM_DATABASE=RTL8111/8168 PCIe Gigabit Ethernet (misconfigured)
pci:v000010ECd00008136*
ID_MODEL_FROM_DATABASE=RTL8101E/RTL8102E PCI Express Fast Ethernet controller
@@ -23739,7 +27312,7 @@ pci:v000010ECd00008167sv00001462sd0000236C*
ID_MODEL_FROM_DATABASE=945P Neo3-F motherboard
pci:v000010ECd00008168*
- ID_MODEL_FROM_DATABASE=RTL8111/8168 PCI Express Gigabit Ethernet controller
+ ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller
pci:v000010ECd00008168sv00001019sd00008168*
ID_MODEL_FROM_DATABASE=RTL8111/8168 PCI Express Gigabit Ethernet controller
@@ -27908,6 +31481,15 @@ pci:v00001137d00000045sv00001137sd0000004F*
pci:v00001137d0000004E*
ID_MODEL_FROM_DATABASE=VIC 82 PCIe Upstream Port
+pci:v00001137d00000071*
+ ID_MODEL_FROM_DATABASE=VIC SR-IOV VF
+
+pci:v00001137d00000084*
+ ID_MODEL_FROM_DATABASE=VIC 1240 MLOM FCoE HBA
+
+pci:v00001137d00000085*
+ ID_MODEL_FROM_DATABASE=VIC 1225 PCIe FCOE HBA
+
pci:v00001137d000000CF*
ID_MODEL_FROM_DATABASE=VIC Userspace NIC
@@ -29183,6 +32765,9 @@ pci:v00001180d00000476sv000017AAsd0000201C*
pci:v00001180d00000476sv000017AAsd000020C4*
ID_MODEL_FROM_DATABASE=ThinkPad T61
+pci:v00001180d00000476sv000017AAsd000020C6*
+ ID_MODEL_FROM_DATABASE=ThinkPad R61
+
pci:v00001180d00000477*
ID_MODEL_FROM_DATABASE=RL5c477
@@ -29372,6 +32957,9 @@ pci:v00001180d00000832sv0000103Csd000030CC*
pci:v00001180d00000832sv0000103Csd000030CF*
ID_MODEL_FROM_DATABASE=Pavilion dv9668eg Laptop
+pci:v00001180d00000832sv000017AAsd000020C7*
+ ID_MODEL_FROM_DATABASE=ThinkPad R61
+
pci:v00001180d00000841*
ID_MODEL_FROM_DATABASE=R5C841 CardBus/SD/SDIO/MMC/MS/MSPro/xD/IEEE1394
@@ -29915,9 +33503,18 @@ pci:v000011ABd00002A30*
pci:v000011ABd00002A40*
ID_MODEL_FROM_DATABASE=88W8366 [TopDog] 802.11n Wireless
+pci:v000011ABd00002A41*
+ ID_MODEL_FROM_DATABASE=88W8366 [TopDog] 802.11n Wireless
+
+pci:v000011ABd00002A42*
+ ID_MODEL_FROM_DATABASE=88W8366 [TopDog] 802.11n Wireless
+
pci:v000011ABd00002A43*
ID_MODEL_FROM_DATABASE=88W8366 [TopDog] 802.11n Wireless
+pci:v000011ABd00002B36*
+ ID_MODEL_FROM_DATABASE=88W8764 [Avastar] 802.11n Wireless
+
pci:v000011ABd00004101*
ID_MODEL_FROM_DATABASE=OLPC Cafe Controller Secure Digital Controller
@@ -32130,13 +35727,28 @@ pci:v0000123E*
ID_VENDOR_FROM_DATABASE=Simutech, Inc.
pci:v0000123F*
- ID_VENDOR_FROM_DATABASE=C-Cube Microsystems
+ ID_VENDOR_FROM_DATABASE=LSI Logic
pci:v0000123Fd000000E4*
ID_MODEL_FROM_DATABASE=MPEG
pci:v0000123Fd00008120*
- ID_MODEL_FROM_DATABASE=E4?
+ ID_MODEL_FROM_DATABASE=DVxplore Codec
+
+pci:v0000123Fd00008120sv000010DEsd000001E1*
+ ID_MODEL_FROM_DATABASE=NVTV PAL
+
+pci:v0000123Fd00008120sv000010DEsd000001E2*
+ ID_MODEL_FROM_DATABASE=NVTV NTSC
+
+pci:v0000123Fd00008120sv000010DEsd000001E3*
+ ID_MODEL_FROM_DATABASE=NVTV PAL
+
+pci:v0000123Fd00008120sv000010DEsd00000248*
+ ID_MODEL_FROM_DATABASE=NVTV NTSC
+
+pci:v0000123Fd00008120sv000010DEsd00000249*
+ ID_MODEL_FROM_DATABASE=NVTV PAL
pci:v0000123Fd00008120sv000011BDsd00000006*
ID_MODEL_FROM_DATABASE=DV500 E4
@@ -32702,6 +36314,9 @@ pci:v0000126Fd00000710*
pci:v0000126Fd00000712*
ID_MODEL_FROM_DATABASE=SM712 LynxEM+
+pci:v0000126Fd00000718*
+ ID_MODEL_FROM_DATABASE=SM718 LynxSE+
+
pci:v0000126Fd00000720*
ID_MODEL_FROM_DATABASE=SM720 Lynx3DM
@@ -34229,6 +37844,9 @@ pci:v000012EBd00000001sv000012EBsd00000001*
pci:v000012EBd00000001sv00005053sd00003355*
ID_MODEL_FROM_DATABASE=Montego
+pci:v000012EBd00000001sv000050B2sd00001111*
+ ID_MODEL_FROM_DATABASE=XLerate
+
pci:v000012EBd00000002*
ID_MODEL_FROM_DATABASE=Vortex 2
@@ -37319,6 +40937,9 @@ pci:v00001425d00004086*
pci:v00001425d00004087*
ID_MODEL_FROM_DATABASE=T440T-4087 Unified Wire Ethernet Controller
+pci:v00001425d00004088*
+ ID_MODEL_FROM_DATABASE=T440-4088 Unified Wire Ethernet Controller
+
pci:v00001425d00004401*
ID_MODEL_FROM_DATABASE=T420-CR Unified Wire Ethernet Controller
@@ -37388,6 +41009,9 @@ pci:v00001425d00004486*
pci:v00001425d00004487*
ID_MODEL_FROM_DATABASE=T440T-4087 Unified Wire Ethernet Controller
+pci:v00001425d00004488*
+ ID_MODEL_FROM_DATABASE=T440-4088 Unified Wire Ethernet Controller
+
pci:v00001425d00004501*
ID_MODEL_FROM_DATABASE=T420-CR Unified Wire Storage Controller
@@ -37457,6 +41081,9 @@ pci:v00001425d00004586*
pci:v00001425d00004587*
ID_MODEL_FROM_DATABASE=T440T-4087 Unified Wire Storage Controller
+pci:v00001425d00004588*
+ ID_MODEL_FROM_DATABASE=T440-4088 Unified Wire Storage Controller
+
pci:v00001425d00004601*
ID_MODEL_FROM_DATABASE=T420-CR Unified Wire Storage Controller
@@ -37526,6 +41153,9 @@ pci:v00001425d00004686*
pci:v00001425d00004687*
ID_MODEL_FROM_DATABASE=T440T-4087 Unified Wire Storage Controller
+pci:v00001425d00004688*
+ ID_MODEL_FROM_DATABASE=T440-4088 Unified Wire Storage Controller
+
pci:v00001425d00004701*
ID_MODEL_FROM_DATABASE=T420-CR Unified Wire Ethernet Controller
@@ -37595,6 +41225,9 @@ pci:v00001425d00004786*
pci:v00001425d00004787*
ID_MODEL_FROM_DATABASE=T440T-4087 Unified Wire Ethernet Controller
+pci:v00001425d00004788*
+ ID_MODEL_FROM_DATABASE=T440-4088 Unified Wire Ethernet Controller
+
pci:v00001425d00004801*
ID_MODEL_FROM_DATABASE=T420-CR Unified Wire Ethernet Controller
@@ -37664,6 +41297,9 @@ pci:v00001425d00004886*
pci:v00001425d00004887*
ID_MODEL_FROM_DATABASE=T440T-4087 Unified Wire Ethernet Controller
+pci:v00001425d00004888*
+ ID_MODEL_FROM_DATABASE=T440-4088 Unified Wire Ethernet Controller
+
pci:v00001425d00005001*
ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Ethernet Controller
@@ -37721,6 +41357,15 @@ pci:v00001425d00005012*
pci:v00001425d00005013*
ID_MODEL_FROM_DATABASE=T580-CR Unified Wire Ethernet Controller
+pci:v00001425d00005014*
+ ID_MODEL_FROM_DATABASE=T580-LP-SO-CR Unified Wire Ethernet Controller
+
+pci:v00001425d00005080*
+ ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Ethernet Controller
+
+pci:v00001425d00005081*
+ ID_MODEL_FROM_DATABASE=T540-5081 Unified Wire Ethernet Controller
+
pci:v00001425d00005401*
ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Ethernet Controller
@@ -37778,6 +41423,15 @@ pci:v00001425d00005412*
pci:v00001425d00005413*
ID_MODEL_FROM_DATABASE=T580-CR Unified Wire Ethernet Controller
+pci:v00001425d00005414*
+ ID_MODEL_FROM_DATABASE=T580-LP-SO-CR Unified Wire Ethernet Controller
+
+pci:v00001425d00005480*
+ ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Ethernet Controller
+
+pci:v00001425d00005481*
+ ID_MODEL_FROM_DATABASE=T540-5081 Unified Wire Ethernet Controller
+
pci:v00001425d00005501*
ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Storage Controller
@@ -37835,6 +41489,15 @@ pci:v00001425d00005512*
pci:v00001425d00005513*
ID_MODEL_FROM_DATABASE=T580-CR Unified Wire Storage Controller
+pci:v00001425d00005514*
+ ID_MODEL_FROM_DATABASE=T580-LP-SO-CR Unified Wire Storage Controller
+
+pci:v00001425d00005580*
+ ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Storage Controller
+
+pci:v00001425d00005581*
+ ID_MODEL_FROM_DATABASE=T540-5081 Unified Wire Storage Controller
+
pci:v00001425d00005601*
ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Storage Controller
@@ -37892,6 +41555,15 @@ pci:v00001425d00005612*
pci:v00001425d00005613*
ID_MODEL_FROM_DATABASE=T580-CR Unified Wire Storage Controller
+pci:v00001425d00005614*
+ ID_MODEL_FROM_DATABASE=T580-LP-SO-CR Unified Wire Storage Controller
+
+pci:v00001425d00005680*
+ ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Storage Controller
+
+pci:v00001425d00005681*
+ ID_MODEL_FROM_DATABASE=T540-5081 Unified Wire Storage Controller
+
pci:v00001425d00005701*
ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Ethernet Controller
@@ -37949,6 +41621,15 @@ pci:v00001425d00005712*
pci:v00001425d00005713*
ID_MODEL_FROM_DATABASE=T580-CR Unified Wire Ethernet Controller
+pci:v00001425d00005714*
+ ID_MODEL_FROM_DATABASE=T580-LP-SO-CR Unified Wire Ethernet Controller
+
+pci:v00001425d00005780*
+ ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Ethernet Controller
+
+pci:v00001425d00005781*
+ ID_MODEL_FROM_DATABASE=T540-5081 Unified Wire Ethernet Controller
+
pci:v00001425d00005801*
ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Ethernet Controller
@@ -38006,6 +41687,15 @@ pci:v00001425d00005812*
pci:v00001425d00005813*
ID_MODEL_FROM_DATABASE=T580-CR Unified Wire Ethernet Controller
+pci:v00001425d00005814*
+ ID_MODEL_FROM_DATABASE=T580-LP-SO-CR Unified Wire Ethernet Controller
+
+pci:v00001425d00005880*
+ ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Ethernet Controller
+
+pci:v00001425d00005881*
+ ID_MODEL_FROM_DATABASE=T540-5081 Unified Wire Ethernet Controller
+
pci:v00001425d0000A000*
ID_MODEL_FROM_DATABASE=PE10K Unified Wire Ethernet Controller
@@ -38412,7 +42102,7 @@ pci:v0000148B*
ID_VENDOR_FROM_DATABASE=INNOMEDIALOGIC Inc.
pci:v0000148C*
- ID_VENDOR_FROM_DATABASE=C.P. Technology Co. Ltd
+ ID_VENDOR_FROM_DATABASE=Tul Corporation / PowerColor
pci:v0000148D*
ID_VENDOR_FROM_DATABASE=DIGICOM Systems, Inc.
@@ -38475,7 +42165,10 @@ pci:v00001498d00003064*
ID_MODEL_FROM_DATABASE=TPCI100 (2 Slot IndustryPack PCI Carrier)
pci:v00001498d000030C8*
- ID_MODEL_FROM_DATABASE=TPCI200
+ ID_MODEL_FROM_DATABASE=TPCI200 4 Slot IndustryPack PCI Carrier
+
+pci:v00001498d000070C8*
+ ID_MODEL_FROM_DATABASE=TPCE200 4 Slot IndustryPack PCIe Carrier
pci:v00001499*
ID_VENDOR_FROM_DATABASE=EMTEC CO., Ltd
@@ -39005,6 +42698,9 @@ pci:v000014E4d0000163Asv0000103Csd0000171D*
pci:v000014E4d0000163Asv0000103Csd00007056*
ID_MODEL_FROM_DATABASE=NC382i Integrated Quad Port PCI Express Gigabit Server Adapter
+pci:v000014E4d0000163Asv00001259sd00002984*
+ ID_MODEL_FROM_DATABASE=AT-2973SX
+
pci:v000014E4d0000163B*
ID_MODEL_FROM_DATABASE=NetXtreme II BCM5716 Gigabit Ethernet
@@ -39845,6 +43541,9 @@ pci:v000014E4d000016B0*
pci:v000014E4d000016B1*
ID_MODEL_FROM_DATABASE=NetLink BCM57781 Gigabit Ethernet PCIe
+pci:v000014E4d000016B1sv00001849sd000096B1*
+ ID_MODEL_FROM_DATABASE=Z77 Extreme4 motherboard
+
pci:v000014E4d000016B2*
ID_MODEL_FROM_DATABASE=NetLink BCM57791 Gigabit Ethernet PCIe
@@ -39864,7 +43563,13 @@ pci:v000014E4d000016B7*
ID_MODEL_FROM_DATABASE=NetXtreme BCM57782 Gigabit Ethernet PCIe
pci:v000014E4d000016BC*
- ID_MODEL_FROM_DATABASE=NetXtreme BCM57765 Memory Card Reader
+ ID_MODEL_FROM_DATABASE=BCM57765/57785 SDXC/MMC Card Reader
+
+pci:v000014E4d000016BE*
+ ID_MODEL_FROM_DATABASE=BCM57765/57785 MS Card Reader
+
+pci:v000014E4d000016BF*
+ ID_MODEL_FROM_DATABASE=BCM57765/57785 xD-Picture Card Reader
pci:v000014E4d000016C6*
ID_MODEL_FROM_DATABASE=NetXtreme BCM5702A3 Gigabit Ethernet
@@ -40487,6 +44192,9 @@ pci:v000014E4d00004365*
pci:v000014E4d00004365sv00001028sd00000016*
ID_MODEL_FROM_DATABASE=Wireless 1704 802.11n + BT 4.0
+pci:v000014E4d000043A0*
+ ID_MODEL_FROM_DATABASE=BCM4360 802.11ac Wireless Network Adapter
+
pci:v000014E4d000043B1*
ID_MODEL_FROM_DATABASE=BCM4352 802.11ac Wireless Network Adapter
@@ -40572,7 +44280,7 @@ pci:v000014E4d00004714*
ID_MODEL_FROM_DATABASE=BCM47xx Sentry5 External Interface
pci:v000014E4d00004715*
- ID_MODEL_FROM_DATABASE=Sentry5 USB Controller
+ ID_MODEL_FROM_DATABASE=BCM47xx Sentry5 USB / Ethernet Controller
pci:v000014E4d00004716*
ID_MODEL_FROM_DATABASE=BCM47xx Sentry5 USB Host Controller
@@ -40590,7 +44298,7 @@ pci:v000014E4d00004720*
ID_MODEL_FROM_DATABASE=BCM4712 MIPS CPU
pci:v000014E4d00004727*
- ID_MODEL_FROM_DATABASE=BCM4313 802.11b/g/n Wireless LAN Controller
+ ID_MODEL_FROM_DATABASE=BCM4313 802.11bgn Wireless Network Adapter
pci:v000014E4d00004727sv00001028sd00000010*
ID_MODEL_FROM_DATABASE=Inspiron M5010 / XPS 8300
@@ -40862,6 +44570,9 @@ pci:v000014F1d00001055*
pci:v000014F1d00001056*
ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (Worldwide)
+pci:v000014F1d00001056sv0000122Dsd00004035*
+ ID_MODEL_FROM_DATABASE=MDP3900V-W
+
pci:v000014F1d00001057*
ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (Worldwide)
@@ -42078,7 +45789,13 @@ pci:v00001555*
ID_VENDOR_FROM_DATABASE=GESYTEC GmBH
pci:v00001556*
- ID_VENDOR_FROM_DATABASE=PLD APPLICATIONS
+ ID_VENDOR_FROM_DATABASE=PLDA
+
+pci:v00001556d00001100*
+ ID_MODEL_FROM_DATABASE=PCI Express Core Reference Design
+
+pci:v00001556d0000110F*
+ ID_MODEL_FROM_DATABASE=PCI Express Core Reference Design Virtual Function
pci:v00001557*
ID_VENDOR_FROM_DATABASE=MEDIASTAR Co Ltd
@@ -42575,6 +46292,12 @@ pci:v000015B3d00001015*
pci:v000015B3d00001016*
ID_MODEL_FROM_DATABASE=MT27631 Family
+pci:v000015B3d00001017*
+ ID_MODEL_FROM_DATABASE=MT27640 Family
+
+pci:v000015B3d00001018*
+ ID_MODEL_FROM_DATABASE=MT27641 Family
+
pci:v000015B3d00005274*
ID_MODEL_FROM_DATABASE=MT21108 InfiniBridge
@@ -43100,6 +46823,9 @@ pci:v00001619d00000640*
pci:v00001619d00001610*
ID_MODEL_FROM_DATABASE=FarSync TE1 (T1,E1)
+pci:v00001619d00001612*
+ ID_MODEL_FROM_DATABASE=FarSync TE1 PCI Express (T1,E1)
+
pci:v00001619d00002610*
ID_MODEL_FROM_DATABASE=FarSync DSL-S1 (SHDSL)
@@ -43112,6 +46838,15 @@ pci:v00001619d00004620*
pci:v00001619d00004640*
ID_MODEL_FROM_DATABASE=FarSync T4Ue PCI Express (4-port X.21/V.35/V.24)
+pci:v00001619d00005621*
+ ID_MODEL_FROM_DATABASE=FarSync T2Ee PCI Express (2 port X.21/V.35/V.24)
+
+pci:v00001619d00005641*
+ ID_MODEL_FROM_DATABASE=FarSync T4Ee PCI Express (4 port X.21/V.35/V.24)
+
+pci:v00001619d00006620*
+ ID_MODEL_FROM_DATABASE=FarSync T2U-PMC PCI Express (2 port X.21/V.35/V.24)
+
pci:v0000161F*
ID_VENDOR_FROM_DATABASE=Rioworks
@@ -43157,6 +46892,9 @@ pci:v0000163Cd00005449*
pci:v00001641*
ID_VENDOR_FROM_DATABASE=MKNet Corp.
+pci:v00001642*
+ ID_VENDOR_FROM_DATABASE=Bitland(ShenZhen) Information Technology Co., Ltd.
+
pci:v00001657*
ID_VENDOR_FROM_DATABASE=Brocade Communications Systems, Inc.
@@ -43197,7 +46935,7 @@ pci:v00001657d00000021*
ID_MODEL_FROM_DATABASE=804 8Gbps FC HBA for HP Bladesystem c-class
pci:v00001657d00000022*
- ID_MODEL_FROM_DATABASE=1867/1860: 16Gbps/10Gbps Fabric Adapter
+ ID_MODEL_FROM_DATABASE=1860 16Gbps/10Gbps Fabric Adapter
pci:v00001657d00000022sv00001657sd00000022*
ID_MODEL_FROM_DATABASE=10Gbps CNA - FCOE
@@ -43208,6 +46946,9 @@ pci:v00001657d00000022sv00001657sd00000023*
pci:v00001657d00000022sv00001657sd00000024*
ID_MODEL_FROM_DATABASE=16Gbps FC HBA
+pci:v00001657d00000023*
+ ID_MODEL_FROM_DATABASE=1867/1869 16Gbps FC HBA
+
pci:v00001657d00000646*
ID_MODEL_FROM_DATABASE=400 4Gbps PCIe FC HBA
@@ -43223,6 +46964,9 @@ pci:v0000165Ad0000D200*
pci:v0000165Ad0000D300*
ID_MODEL_FROM_DATABASE=PIXCI(R) D3X Digital Video Capture Board [custom QL5232]
+pci:v0000165Ad0000EB01*
+ ID_MODEL_FROM_DATABASE=PIXCI(R) EB1 PCI Camera Link Video Capture Board
+
pci:v0000165D*
ID_VENDOR_FROM_DATABASE=Hsing Tech. Enterprise Co., Ltd.
@@ -44415,7 +48159,7 @@ pci:v00001749*
ID_VENDOR_FROM_DATABASE=RLX Technologies
pci:v0000174B*
- ID_VENDOR_FROM_DATABASE=PC Partner Limited
+ ID_VENDOR_FROM_DATABASE=PC Partner Limited / Sapphire Technology
pci:v0000174D*
ID_VENDOR_FROM_DATABASE=WellX Telecom SA
@@ -44429,6 +48173,12 @@ pci:v0000175E*
pci:v00001760*
ID_VENDOR_FROM_DATABASE=TEDIA spol. s r. o.
+pci:v00001760d00000101*
+ ID_MODEL_FROM_DATABASE=PCD-7004 Digital Bi-Directional Ports PCI Card
+
+pci:v00001760d00000102*
+ ID_MODEL_FROM_DATABASE=PCD-7104 Digital Input & Output PCI Card
+
pci:v00001771*
ID_VENDOR_FROM_DATABASE=InnoVISION Multimedia Ltd.
@@ -45432,7 +49182,7 @@ pci:v000018B8d0000B001*
ID_MODEL_FROM_DATABASE=AMSO 1100 iWARP/RDMA Gigabit Ethernet Coprocessor
pci:v000018BC*
- ID_VENDOR_FROM_DATABASE=Info-Tek Corp.
+ ID_VENDOR_FROM_DATABASE=GeCube Technologies, Inc.
pci:v000018C3*
ID_VENDOR_FROM_DATABASE=Micronas Semiconductor Holding AG
@@ -45482,6 +49232,9 @@ pci:v000018DD*
pci:v000018DDd00004C6F*
ID_MODEL_FROM_DATABASE=Artimi RTMI-100 UWB adapter
+pci:v000018DF*
+ ID_VENDOR_FROM_DATABASE=LeWiz Communications
+
pci:v000018E6*
ID_VENDOR_FROM_DATABASE=MPL AG
@@ -45692,6 +49445,18 @@ pci:v000018F4d000000E5*
pci:v000018F4d000000F5*
ID_MODEL_FROM_DATABASE=NT4E2-4T-BP Network Adapter 4x1Gb with Electrical Bypass
+pci:v000018F4d00000105*
+ ID_MODEL_FROM_DATABASE=NT4E2-4-PTP Network Adapter 4x1Gb
+
+pci:v000018F4d00000115*
+ ID_MODEL_FROM_DATABASE=NT20E2-PTP Network Adapter 2x10Gb
+
+pci:v000018F4d00000125*
+ ID_MODEL_FROM_DATABASE=NT4E2-4-PTP Network Adapter 4x1Gb
+
+pci:v000018F4d00000135*
+ ID_MODEL_FROM_DATABASE=NT20E2-PTP Network Adapter 2x10Gb
+
pci:v000018F6*
ID_VENDOR_FROM_DATABASE=NextIO
@@ -45791,6 +49556,18 @@ pci:v000018F7d00000021*
pci:v000018F7d00000022*
ID_MODEL_FROM_DATABASE=SuperFSCC/4-LVDS Serial PCIe Adapter [Fastcom]
+pci:v000018F7d00000023*
+ ID_MODEL_FROM_DATABASE=SuperFSCC/4 Serial cPCI Adapter [Fastcom]
+
+pci:v000018F7d00000025*
+ ID_MODEL_FROM_DATABASE=SuperFSCC/4-LVDS Serial PCI Adapter [Fastcom]
+
+pci:v000018F7d00000026*
+ ID_MODEL_FROM_DATABASE=SuperFSCC-LVDS Serial PCI Adapter [Fastcom]
+
+pci:v000018F7d00000027*
+ ID_MODEL_FROM_DATABASE=FSCC/4 Serial PCIe Adapter [Fastcom]
+
pci:v000018FB*
ID_VENDOR_FROM_DATABASE=Resilience Corporation
@@ -45938,6 +49715,24 @@ pci:v00001924d00000710sv00001924sd00005202*
pci:v00001924d00000803*
ID_MODEL_FROM_DATABASE=SFC9020 [Solarstorm]
+pci:v00001924d00000803sv00001014sd00000478*
+ ID_MODEL_FROM_DATABASE=2-port 10GbE Low-Latency (R7)
+
+pci:v00001924d00000803sv00001014sd00000479*
+ ID_MODEL_FROM_DATABASE=2-port 10GbE OpenOnload (R7)
+
+pci:v00001924d00000803sv00001014sd000004A7*
+ ID_MODEL_FROM_DATABASE=Solarflare 10Gb Low-latency Dual-port HBA (R7)
+
+pci:v00001924d00000803sv00001014sd000004A8*
+ ID_MODEL_FROM_DATABASE=Solarflare 10Gb Dual-port HBA (R7)
+
+pci:v00001924d00000803sv0000103Csd00002132*
+ ID_MODEL_FROM_DATABASE=Ethernet 10Gb 2-port 570FLR-SFP+ Adapter (R1)
+
+pci:v00001924d00000803sv0000103Csd00002136*
+ ID_MODEL_FROM_DATABASE=Ethernet 10Gb 2-port 570SFP+ Adapter (R7)
+
pci:v00001924d00000803sv00001924sd00001201*
ID_MODEL_FROM_DATABASE=SFA6902F-R1 SFP+ AOE Adapter
@@ -46034,6 +49829,15 @@ pci:v00001924d00000813sv00001924sd00007104*
pci:v00001924d00000813sv00001924sd00007904*
ID_MODEL_FROM_DATABASE=SFN5151T-R4 10GBASE-T Server Adapter
+pci:v00001924d00000903*
+ ID_MODEL_FROM_DATABASE=SFC9120
+
+pci:v00001924d00000903sv00001924sd00008002*
+ ID_MODEL_FROM_DATABASE=SFN7122F-R1 SFP+ Server Adapter
+
+pci:v00001924d00000903sv00001924sd00008006*
+ ID_MODEL_FROM_DATABASE=SFN7022F-R1 SFP+ Server Adapter
+
pci:v00001924d00001803*
ID_MODEL_FROM_DATABASE=SFC9020 Virtual Function [Solarstorm]
@@ -46905,7 +50709,10 @@ pci:v00001A41d00000002*
ID_MODEL_FROM_DATABASE=TILEPro processor
pci:v00001A41d00000200*
- ID_MODEL_FROM_DATABASE=TILE-Gx36 processor
+ ID_MODEL_FROM_DATABASE=TILE-Gx processor
+
+pci:v00001A41d00002000*
+ ID_MODEL_FROM_DATABASE=TILE-Gx PCI Express Bridge
pci:v00001A4A*
ID_VENDOR_FROM_DATABASE=SLAC National Accelerator Lab PPA-REG
@@ -46919,6 +50726,9 @@ pci:v00001A4Ad00001010*
pci:v00001A4Ad00002000*
ID_MODEL_FROM_DATABASE=PGPCard - 4 Lane
+pci:v00001A4Ad00002001*
+ ID_MODEL_FROM_DATABASE=PGPCard - 8 Lane Plus EVR
+
pci:v00001A4Ad00002010*
ID_MODEL_FROM_DATABASE=PCI-Express EVR
@@ -47033,6 +50843,12 @@ pci:v00001A78d00000031sv00001A78sd00000039*
pci:v00001A78d00000040*
ID_MODEL_FROM_DATABASE=FlashMAX II
+pci:v00001A78d00000041*
+ ID_MODEL_FROM_DATABASE=FlashMAX II
+
+pci:v00001A78d00000042*
+ ID_MODEL_FROM_DATABASE=FlashMAX II
+
pci:v00001A84*
ID_VENDOR_FROM_DATABASE=Commex Technologies
@@ -47091,7 +50907,7 @@ pci:v00001AB9*
ID_VENDOR_FROM_DATABASE=Espia Srl
pci:v00001ACC*
- ID_VENDOR_FROM_DATABASE=Point of View B.V
+ ID_VENDOR_FROM_DATABASE=Point of View BV
pci:v00001AD7*
ID_VENDOR_FROM_DATABASE=Spectracom Corporation
@@ -47132,6 +50948,21 @@ pci:v00001AE8d00000A44*
pci:v00001AE8d00000E44*
ID_MODEL_FROM_DATABASE=microEnable IV-GigE x4
+pci:v00001AE9*
+ ID_VENDOR_FROM_DATABASE=Wilocity Ltd.
+
+pci:v00001AE9d00000101*
+ ID_MODEL_FROM_DATABASE=Wil6200 PCI Express Root Port
+
+pci:v00001AE9d00000200*
+ ID_MODEL_FROM_DATABASE=Wil6200 PCI Express Port
+
+pci:v00001AE9d00000201*
+ ID_MODEL_FROM_DATABASE=Wil6200 Wireless PCI Express Port
+
+pci:v00001AE9d00000301*
+ ID_MODEL_FROM_DATABASE=Wil6200 802.11ad Wireless Network Adapter
+
pci:v00001AEC*
ID_VENDOR_FROM_DATABASE=Wolfson Microelectronics
@@ -47219,6 +51050,9 @@ pci:v00001B03d00006100*
pci:v00001B08*
ID_VENDOR_FROM_DATABASE=MSC Vertriebs GmbH
+pci:v00001B0A*
+ ID_VENDOR_FROM_DATABASE=Pegatron
+
pci:v00001B13*
ID_VENDOR_FROM_DATABASE=Jaton Corp
@@ -47237,12 +51071,24 @@ pci:v00001B21d00000611*
pci:v00001B21d00000612*
ID_MODEL_FROM_DATABASE=ASM1062 Serial ATA Controller
+pci:v00001B21d00000612sv00001849sd00000612*
+ ID_MODEL_FROM_DATABASE=Motherboard
+
pci:v00001B21d00001042*
ID_MODEL_FROM_DATABASE=ASM1042 SuperSpeed USB Host Controller
+pci:v00001B21d00001042sv00001849sd00001042*
+ ID_MODEL_FROM_DATABASE=Motherboard
+
pci:v00001B21d00001080*
ID_MODEL_FROM_DATABASE=ASM1083/1085 PCIe to PCI Bridge
+pci:v00001B21d00001080sv00001849sd00001080*
+ ID_MODEL_FROM_DATABASE=Motherboard
+
+pci:v00001B2C*
+ ID_VENDOR_FROM_DATABASE=Opal-RT Technologies Inc.
+
pci:v00001B36*
ID_VENDOR_FROM_DATABASE=Red Hat, Inc.
@@ -47316,7 +51162,7 @@ pci:v00001B4Bd00009192*
ID_MODEL_FROM_DATABASE=88SE9172 SATA III 6Gb/s RAID Controller
pci:v00001B4Bd000091A0*
- ID_MODEL_FROM_DATABASE=88SE91A0 SATA 6Gb/s Controller
+ ID_MODEL_FROM_DATABASE=88SE912x SATA 6Gb/s Controller [IDE mode]
pci:v00001B4Bd000091A4*
ID_MODEL_FROM_DATABASE=88SE912x IDE Controller
@@ -47327,6 +51173,9 @@ pci:v00001B4Bd00009230*
pci:v00001B4Bd00009480*
ID_MODEL_FROM_DATABASE=88SE9480 SAS/SATA 6Gb/s RAID controller
+pci:v00001B4Bd00009485*
+ ID_MODEL_FROM_DATABASE=88SE9485 SAS/SATA 6Gb/s controller
+
pci:v00001B55*
ID_VENDOR_FROM_DATABASE=NetUP Inc.
@@ -47405,6 +51254,9 @@ pci:v00001BB0*
pci:v00001BB0d00000002*
ID_MODEL_FROM_DATABASE=OmniCube Accelerator OA-3000
+pci:v00001BB0d00000010*
+ ID_MODEL_FROM_DATABASE=OmniCube Accelerator OA-3000-2
+
pci:v00001BB3*
ID_VENDOR_FROM_DATABASE=Bluecherry
@@ -47450,6 +51302,9 @@ pci:v00001BBFd00000004*
pci:v00001BF4*
ID_VENDOR_FROM_DATABASE=VTI Instruments Corporation
+pci:v00001BFD*
+ ID_VENDOR_FROM_DATABASE=EeeTOP
+
pci:v00001C1C*
ID_VENDOR_FROM_DATABASE=Symphony
@@ -47492,6 +51347,12 @@ pci:v00001C8Ad00000001*
pci:v00001CB1*
ID_VENDOR_FROM_DATABASE=Collion UG & Co.KG
+pci:v00001CC5*
+ ID_VENDOR_FROM_DATABASE=Embedded Intelligence, Inc.
+
+pci:v00001CC5d00000100*
+ ID_MODEL_FROM_DATABASE=CAN-PCIe-02
+
pci:v00001D44*
ID_VENDOR_FROM_DATABASE=DPT
@@ -48626,9 +52487,6 @@ pci:v00005053d00002010*
pci:v000050B2*
ID_VENDOR_FROM_DATABASE=TerraTec Electronic GmbH
-pci:v000050B2d00001111*
- ID_MODEL_FROM_DATABASE=Terratec XLerate
-
pci:v00005136*
ID_VENDOR_FROM_DATABASE=S S Technologies
@@ -49229,6 +53087,18 @@ pci:v00006666d00004000*
pci:v00006688*
ID_VENDOR_FROM_DATABASE=Zycoo Co., Ltd
+pci:v00006688d00001200*
+ ID_MODEL_FROM_DATABASE=CooVOX TDM Analog Module
+
+pci:v00006688d00001400*
+ ID_MODEL_FROM_DATABASE=CooVOX TDM GSM Module
+
+pci:v00006688d00001600*
+ ID_MODEL_FROM_DATABASE=CooVOX TDM E1/T1 Module
+
+pci:v00006688d00001800*
+ ID_MODEL_FROM_DATABASE=CooVOX TDM BRI Module
+
pci:v00006900*
ID_VENDOR_FROM_DATABASE=Red Hat, Inc.
@@ -49583,6 +53453,9 @@ pci:v00008086d00000150*
pci:v00008086d00000150sv00001043sd000084CA*
ID_MODEL_FROM_DATABASE=P8H77-I Motherboard
+pci:v00008086d00000150sv00001849sd00000150*
+ ID_MODEL_FROM_DATABASE=Motherboard
+
pci:v00008086d00000151*
ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port
@@ -49607,6 +53480,12 @@ pci:v00008086d00000153sv00001043sd00001517*
pci:v00008086d00000154*
ID_MODEL_FROM_DATABASE=3rd Gen Core processor DRAM Controller
+pci:v00008086d00000154sv00001025sd00000813*
+ ID_MODEL_FROM_DATABASE=Aspire R7-571
+
+pci:v00008086d00000154sv0000103Csd000017F6*
+ ID_MODEL_FROM_DATABASE=ProBook 4540s
+
pci:v00008086d00000154sv00001043sd00001477*
ID_MODEL_FROM_DATABASE=N56VZ
@@ -49640,6 +53519,9 @@ pci:v00008086d0000015E*
pci:v00008086d00000162*
ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller
+pci:v00008086d00000162sv00001849sd00000162*
+ ID_MODEL_FROM_DATABASE=Motherboard
+
pci:v00008086d00000166*
ID_MODEL_FROM_DATABASE=3rd Gen Core processor Graphics Controller
@@ -49734,22 +53616,28 @@ pci:v00008086d00000374*
ID_MODEL_FROM_DATABASE=80333 Address Translation Unit
pci:v00008086d00000402*
- ID_MODEL_FROM_DATABASE=Haswell Integrated Graphics Controller
+ ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor Integrated Graphics Controller
pci:v00008086d00000406*
- ID_MODEL_FROM_DATABASE=Haswell Integrated Graphics Controller
+ ID_MODEL_FROM_DATABASE=4th Gen Core Processor Integrated Graphics Controller
pci:v00008086d0000040A*
- ID_MODEL_FROM_DATABASE=Haswell Integrated Graphics Controller
+ ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3 Processor Integrated Graphics Controller
pci:v00008086d00000412*
- ID_MODEL_FROM_DATABASE=Haswell Integrated Graphics Controller
+ ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor Integrated Graphics Controller
pci:v00008086d00000416*
- ID_MODEL_FROM_DATABASE=Haswell Integrated Graphics Controller
+ ID_MODEL_FROM_DATABASE=4th Gen Core Processor Integrated Graphics Controller
pci:v00008086d0000041A*
- ID_MODEL_FROM_DATABASE=Haswell Integrated Graphics Controller
+ ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3 Processor Integrated Graphics Controller
+
+pci:v00008086d00000433*
+ ID_MODEL_FROM_DATABASE=Coleto Creek ACC - ME/CPM interface
+
+pci:v00008086d00000435*
+ ID_MODEL_FROM_DATABASE=Coleto Creek PCIe Endpoint
pci:v00008086d00000436*
ID_MODEL_FROM_DATABASE=DH8900CC Null Device
@@ -50349,25 +54237,25 @@ pci:v00008086d00000BF7*
ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx DRAM Controller
pci:v00008086d00000C00*
- ID_MODEL_FROM_DATABASE=Haswell DRAM Controller
+ ID_MODEL_FROM_DATABASE=4th Gen Core Processor DRAM Controller
pci:v00008086d00000C01*
- ID_MODEL_FROM_DATABASE=Haswell PCI Express x16 Controller
+ ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor PCI Express x16 Controller
pci:v00008086d00000C04*
- ID_MODEL_FROM_DATABASE=Haswell DRAM Controller
+ ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor DRAM Controller
pci:v00008086d00000C05*
- ID_MODEL_FROM_DATABASE=Haswell PCI Express x8 Controller
+ ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor PCI Express x8 Controller
pci:v00008086d00000C08*
- ID_MODEL_FROM_DATABASE=Haswell DRAM Controller
+ ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3 Processor DRAM Controller
pci:v00008086d00000C09*
- ID_MODEL_FROM_DATABASE=Haswell PCI Express x4 Controller
+ ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor PCI Express x4 Controller
pci:v00008086d00000C0C*
- ID_MODEL_FROM_DATABASE=Haswell HD Audio Controller
+ ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor HD Audio Controller
pci:v00008086d00000C46*
ID_MODEL_FROM_DATABASE=Atom Processor S1200 PCI Express Root Port 1
@@ -50493,352 +54381,397 @@ pci:v00008086d00000D36*
ID_MODEL_FROM_DATABASE=Crystal Well Integrated Graphics Controller
pci:v00008086d00000E00*
- ID_MODEL_FROM_DATABASE=Ivytown DMI2
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 DMI2
pci:v00008086d00000E01*
- ID_MODEL_FROM_DATABASE=Ivytown PCI Express Root Port in DMI2 Mode
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 PCI Express Root Port in DMI2 Mode
pci:v00008086d00000E02*
- ID_MODEL_FROM_DATABASE=Ivytown PCI Express Root Port 1a
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 PCI Express Root Port 1a
pci:v00008086d00000E03*
- ID_MODEL_FROM_DATABASE=Ivytown PCI Express Root Port 1b
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 PCI Express Root Port 1b
pci:v00008086d00000E04*
- ID_MODEL_FROM_DATABASE=Ivytown PCI Express Root Port 2a
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 PCI Express Root Port 2a
pci:v00008086d00000E05*
- ID_MODEL_FROM_DATABASE=Ivytown PCI Express Root Port 2b
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 PCI Express Root Port 2b
pci:v00008086d00000E06*
- ID_MODEL_FROM_DATABASE=Ivytown PCI Express Root Port 2c
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 PCI Express Root Port 2c
pci:v00008086d00000E07*
- ID_MODEL_FROM_DATABASE=Ivytown PCI Express Root Port 2d
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 PCI Express Root Port 2d
pci:v00008086d00000E08*
- ID_MODEL_FROM_DATABASE=Ivytown PCI Express Root Port 3a
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 PCI Express Root Port 3a
pci:v00008086d00000E09*
- ID_MODEL_FROM_DATABASE=Ivytown PCI Express Root Port 3b
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 PCI Express Root Port 3b
pci:v00008086d00000E0A*
- ID_MODEL_FROM_DATABASE=Ivytown PCI Express Root Port 3c
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 PCI Express Root Port 3c
pci:v00008086d00000E0B*
- ID_MODEL_FROM_DATABASE=Ivytown PCI Express Root Port 3d
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 PCI Express Root Port 3d
+
+pci:v00008086d00000E10*
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 IIO Configuration Registers
+
+pci:v00008086d00000E13*
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 IIO Configuration Registers
+
+pci:v00008086d00000E17*
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 IIO Configuration Registers
+
+pci:v00008086d00000E18*
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 IIO Configuration Registers
pci:v00008086d00000E1C*
- ID_MODEL_FROM_DATABASE=Ivytown Debug and Error Injection Related Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 IIO Configuration Registers
pci:v00008086d00000E1D*
- ID_MODEL_FROM_DATABASE=Ivytown R2PCIe
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 R2PCIe
pci:v00008086d00000E1E*
- ID_MODEL_FROM_DATABASE=Ivytown Semaphore and Scratchpad Configuration Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 UBOX Registers
pci:v00008086d00000E1F*
- ID_MODEL_FROM_DATABASE=Ivytown Semaphore and Scratchpad Configuration Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 UBOX Registers
pci:v00008086d00000E20*
- ID_MODEL_FROM_DATABASE=Ivytown Crystal Beach DMA Channel 0
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Crystal Beach DMA Channel 0
pci:v00008086d00000E21*
- ID_MODEL_FROM_DATABASE=Ivytown Crystal Beach DMA Channel 1
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Crystal Beach DMA Channel 1
pci:v00008086d00000E22*
- ID_MODEL_FROM_DATABASE=Ivytown Crystal Beach DMA Channel 2
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Crystal Beach DMA Channel 2
pci:v00008086d00000E23*
- ID_MODEL_FROM_DATABASE=Ivytown Crystal Beach DMA Channel 3
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Crystal Beach DMA Channel 3
pci:v00008086d00000E24*
- ID_MODEL_FROM_DATABASE=Ivytown Crystal Beach DMA Channel 4
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Crystal Beach DMA Channel 4
pci:v00008086d00000E25*
- ID_MODEL_FROM_DATABASE=Ivytown Crystal Beach DMA Channel 5
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Crystal Beach DMA Channel 5
pci:v00008086d00000E26*
- ID_MODEL_FROM_DATABASE=Ivytown Crystal Beach DMA Channel 6
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Crystal Beach DMA Channel 6
pci:v00008086d00000E27*
- ID_MODEL_FROM_DATABASE=Ivytown Crystal Beach DMA Channel 7
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Crystal Beach DMA Channel 7
pci:v00008086d00000E28*
- ID_MODEL_FROM_DATABASE=Ivytown VTd/Memory Map/Misc
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 VTd/Memory Map/Misc
pci:v00008086d00000E29*
- ID_MODEL_FROM_DATABASE=Ivytown Memory Hotplug
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Memory Hotplug
pci:v00008086d00000E2A*
- ID_MODEL_FROM_DATABASE=Ivytown IIO RAS
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 IIO RAS
pci:v00008086d00000E2C*
- ID_MODEL_FROM_DATABASE=Ivytown IOAPIC
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 IOAPIC
pci:v00008086d00000E2E*
- ID_MODEL_FROM_DATABASE=Ivytown CBDMA
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 CBDMA
pci:v00008086d00000E2F*
- ID_MODEL_FROM_DATABASE=Ivytown CBDMA
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 CBDMA
pci:v00008086d00000E30*
- ID_MODEL_FROM_DATABASE=Ivytown Home Agent 0
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Home Agent 0
pci:v00008086d00000E32*
- ID_MODEL_FROM_DATABASE=Ivytown QPI Link 0
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 QPI Link 0
pci:v00008086d00000E33*
- ID_MODEL_FROM_DATABASE=Ivytown QPI Link 1
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 QPI Link 1
pci:v00008086d00000E34*
- ID_MODEL_FROM_DATABASE=Ivytown PCI Express Ring Performance Monitoring
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 R2PCIe
pci:v00008086d00000E36*
- ID_MODEL_FROM_DATABASE=Ivytown QPI Ring Performance Ring Monitoring
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 QPI Ring Performance Ring Monitoring
pci:v00008086d00000E37*
- ID_MODEL_FROM_DATABASE=Ivytown QPI Ring Performance Ring Monitoring
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 QPI Ring Performance Ring Monitoring
pci:v00008086d00000E38*
- ID_MODEL_FROM_DATABASE=Ivytown Home Agent 1
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Home Agent 1
pci:v00008086d00000E3A*
- ID_MODEL_FROM_DATABASE=Ivytown QPI Link 2
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 QPI Link 2
pci:v00008086d00000E3E*
- ID_MODEL_FROM_DATABASE=Ivytown QPI Ring Performance Ring Monitoring
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 QPI Ring Performance Ring Monitoring
pci:v00008086d00000E3F*
- ID_MODEL_FROM_DATABASE=Ivytown QPI Ring Performance Ring Monitoring
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 QPI Ring Performance Ring Monitoring
pci:v00008086d00000E40*
- ID_MODEL_FROM_DATABASE=Ivytown QPI Link 2
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 QPI Link 2
pci:v00008086d00000E41*
- ID_MODEL_FROM_DATABASE=Ivytown QPI Ring Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 QPI Ring Registers
pci:v00008086d00000E43*
- ID_MODEL_FROM_DATABASE=Ivytown QPI Link Reut 2
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 QPI Link Reut 2
pci:v00008086d00000E44*
- ID_MODEL_FROM_DATABASE=Ivytown QPI Link Reut 2
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 QPI Link Reut 2
pci:v00008086d00000E60*
- ID_MODEL_FROM_DATABASE=Ivytown Home Agent 1
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Home Agent 1
pci:v00008086d00000E68*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 1 Target Address/Thermal Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 1 Target Address/Thermal Registers
pci:v00008086d00000E6A*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 1 Channel Target Address Decoder Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder Registers
pci:v00008086d00000E6B*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 1 Channel Target Address Decoder Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder Registers
pci:v00008086d00000E6C*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 1 Channel Target Address Decoder Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder Registers
pci:v00008086d00000E6D*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 1 Channel Target Address Decoder Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder Registers
pci:v00008086d00000E71*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 0 RAS Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 0 RAS Registers
+
+pci:v00008086d00000E74*
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 R2PCIe
+
+pci:v00008086d00000E75*
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 R2PCIe
+
+pci:v00008086d00000E77*
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 QPI Ring Registers
pci:v00008086d00000E79*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 1 RAS Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 1 RAS Registers
+
+pci:v00008086d00000E7D*
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 UBOX Registers
+
+pci:v00008086d00000E7F*
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 QPI Ring Registers
pci:v00008086d00000E80*
- ID_MODEL_FROM_DATABASE=Ivytown QPI Link 0
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 QPI Link 0
pci:v00008086d00000E81*
- ID_MODEL_FROM_DATABASE=Ivytown QPI Ring Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 QPI Ring Registers
pci:v00008086d00000E83*
- ID_MODEL_FROM_DATABASE=Ivytown QPI Link Reut 0
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 QPI Link Reut 0
pci:v00008086d00000E84*
- ID_MODEL_FROM_DATABASE=Ivytown QPI Link Reut 0
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 QPI Link Reut 0
+
+pci:v00008086d00000E87*
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 QPI Registers
pci:v00008086d00000E90*
- ID_MODEL_FROM_DATABASE=Ivytown QPI Link 1
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 QPI Link 1
pci:v00008086d00000E93*
- ID_MODEL_FROM_DATABASE=Ivytown QPI Link 1
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 QPI Link 1
pci:v00008086d00000E94*
- ID_MODEL_FROM_DATABASE=Ivytown QPI Link Reut 1
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 QPI Link Reut 1
pci:v00008086d00000EA0*
- ID_MODEL_FROM_DATABASE=Ivytown Home Agent 0
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Home Agent 0
pci:v00008086d00000EA8*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 0 Target Address/Thermal Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 0 Target Address/Thermal Registers
pci:v00008086d00000EAA*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 0 Channel Target Address Decoder Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder Registers
pci:v00008086d00000EAB*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 0 Channel Target Address Decoder Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder Registers
pci:v00008086d00000EAC*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 0 Channel Target Address Decoder Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder Registers
pci:v00008086d00000EAD*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 0 Channel Target Address Decoder Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder Registers
+
+pci:v00008086d00000EAE*
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 DDRIO Registers
+
+pci:v00008086d00000EAF*
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 DDRIO Registers
pci:v00008086d00000EB0*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 1 Channel 0-3 Thermal Control 0
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 Thermal Control 0
pci:v00008086d00000EB1*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 1 Channel 0-3 Thermal Control 1
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 Thermal Control 1
pci:v00008086d00000EB2*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 1 Channel 0-3 ERROR Registers 0
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 ERROR Registers 0
pci:v00008086d00000EB3*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 1 Channel 0-3 ERROR Registers 1
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 ERROR Registers 1
pci:v00008086d00000EB4*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 1 Channel 0-3 Thermal Control 2
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 Thermal Control 2
pci:v00008086d00000EB5*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 1 Channel 0-3 Thermal Control 3
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 Thermal Control 3
pci:v00008086d00000EB6*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 1 Channel 0-3 ERROR Registers 2
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 ERROR Registers 2
pci:v00008086d00000EB7*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 1 Channel 0-3 ERROR Registers 3
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 ERROR Registers 3
+
+pci:v00008086d00000EBC*
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 DDRIO Registers
+
+pci:v00008086d00000EBE*
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 DDRIO Registers
+
+pci:v00008086d00000EBF*
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 DDRIO Registers
pci:v00008086d00000EC0*
- ID_MODEL_FROM_DATABASE=Ivytown Power Control Unit 0
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Power Control Unit 0
pci:v00008086d00000EC1*
- ID_MODEL_FROM_DATABASE=Ivytown Power Control Unit 1
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Power Control Unit 1
pci:v00008086d00000EC2*
- ID_MODEL_FROM_DATABASE=Ivytown Power Control Unit 2
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Power Control Unit 2
pci:v00008086d00000EC3*
- ID_MODEL_FROM_DATABASE=Ivytown Power Control Unit 3
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Power Control Unit 3
pci:v00008086d00000EC4*
- ID_MODEL_FROM_DATABASE=Ivytown Power Control Unit 4
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Power Control Unit 4
pci:v00008086d00000EC8*
- ID_MODEL_FROM_DATABASE=Ivytown System Address Decoder
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 System Address Decoder
pci:v00008086d00000EC9*
- ID_MODEL_FROM_DATABASE=Ivytown Broadcast Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Broadcast Registers
pci:v00008086d00000ECA*
- ID_MODEL_FROM_DATABASE=Ivytown Broadcast Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Broadcast Registers
pci:v00008086d00000ED8*
- ID_MODEL_FROM_DATABASE=Ivytown DDRIO
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 DDRIO
pci:v00008086d00000ED9*
- ID_MODEL_FROM_DATABASE=Ivytown DDRIO
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 DDRIO
pci:v00008086d00000EDC*
- ID_MODEL_FROM_DATABASE=Ivytown DDRIO
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 DDRIO
pci:v00008086d00000EDD*
- ID_MODEL_FROM_DATABASE=Ivytown DDRIO
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 DDRIO
pci:v00008086d00000EDE*
- ID_MODEL_FROM_DATABASE=Ivytown DDRIO
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 DDRIO
pci:v00008086d00000EDF*
- ID_MODEL_FROM_DATABASE=Ivytown DDRIO
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 DDRIO
pci:v00008086d00000EE0*
- ID_MODEL_FROM_DATABASE=Ivytown Unicast Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Unicast Registers
pci:v00008086d00000EE1*
- ID_MODEL_FROM_DATABASE=Ivytown Unicast Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Unicast Registers
pci:v00008086d00000EE2*
- ID_MODEL_FROM_DATABASE=Ivytown Unicast Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Unicast Registers
pci:v00008086d00000EE3*
- ID_MODEL_FROM_DATABASE=Ivytown Unicast Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Unicast Registers
pci:v00008086d00000EE4*
- ID_MODEL_FROM_DATABASE=Ivytown Unicast Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Unicast Registers
pci:v00008086d00000EE5*
- ID_MODEL_FROM_DATABASE=Ivytown Unicast Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Unicast Registers
pci:v00008086d00000EE6*
- ID_MODEL_FROM_DATABASE=Ivytown Unicast Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Unicast Registers
pci:v00008086d00000EE7*
- ID_MODEL_FROM_DATABASE=Ivytown Unicast Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Unicast Registers
pci:v00008086d00000EE8*
- ID_MODEL_FROM_DATABASE=Ivytown Unicast Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Unicast Registers
pci:v00008086d00000EE9*
- ID_MODEL_FROM_DATABASE=Ivytown Unicast Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Unicast Registers
pci:v00008086d00000EEA*
- ID_MODEL_FROM_DATABASE=Ivytown Unicast Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Unicast Registers
pci:v00008086d00000EEB*
- ID_MODEL_FROM_DATABASE=Ivytown Unicast Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Unicast Registers
pci:v00008086d00000EEC*
- ID_MODEL_FROM_DATABASE=Ivytown Unicast Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Unicast Registers
pci:v00008086d00000EED*
- ID_MODEL_FROM_DATABASE=Ivytown Unicast Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Unicast Registers
pci:v00008086d00000EEE*
- ID_MODEL_FROM_DATABASE=Ivytown Unicast Registers
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Unicast Registers
pci:v00008086d00000EF0*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 0 Channel 0-3 Thermal Control 0
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 Thermal Control 0
pci:v00008086d00000EF1*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 0 Channel 0-3 Thermal Control 1
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 Thermal Control 1
pci:v00008086d00000EF2*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 0 Channel 0-3 ERROR Registers 0
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 ERROR Registers 0
pci:v00008086d00000EF3*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 0 Channel 0-3 ERROR Registers 1
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 ERROR Registers 1
pci:v00008086d00000EF4*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 0 Channel 0-3 Thermal Control 2
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 Thermal Control 2
pci:v00008086d00000EF5*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 0 Channel 0-3 Thermal Control 3
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 Thermal Control 3
pci:v00008086d00000EF6*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 0 Channel 0-3 ERROR Registers 2
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 ERROR Registers 2
pci:v00008086d00000EF7*
- ID_MODEL_FROM_DATABASE=Ivytown Integrated Memory Controller 0 Channel 0-3 ERROR Registers 3
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 ERROR Registers 3
pci:v00008086d00000EF8*
- ID_MODEL_FROM_DATABASE=Ivytown DDRIO
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 DDRIO
pci:v00008086d00000EF9*
- ID_MODEL_FROM_DATABASE=Ivytown DDRIO
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 DDRIO
pci:v00008086d00000EFA*
- ID_MODEL_FROM_DATABASE=Ivytown DDRIO
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 DDRIO
pci:v00008086d00000EFB*
- ID_MODEL_FROM_DATABASE=Ivytown DDRIO
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 DDRIO
pci:v00008086d00000EFC*
- ID_MODEL_FROM_DATABASE=Ivytown DDRIO
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 DDRIO
pci:v00008086d00000EFD*
- ID_MODEL_FROM_DATABASE=Ivytown DDRIO
+ ID_MODEL_FROM_DATABASE=Xeon E5 v2/Core i7 DDRIO
pci:v00008086d00000F00*
ID_MODEL_FROM_DATABASE=ValleyView SSA-CUnit
@@ -51668,6 +55601,9 @@ pci:v00008086d0000105Esv00001775sd00001100*
pci:v00008086d0000105Esv00001775sd00006003*
ID_MODEL_FROM_DATABASE=Telum GE-QT
+pci:v00008086d0000105Esv000018DFsd00001214*
+ ID_MODEL_FROM_DATABASE=2x 1GbE, PCIe x1, dual Intel 82571EB chips
+
pci:v00008086d0000105Esv00008086sd0000005E*
ID_MODEL_FROM_DATABASE=PRO/1000 PT Dual Port Server Connection
@@ -52413,7 +56349,7 @@ pci:v00008086d000010F9*
ID_MODEL_FROM_DATABASE=82599 10 Gigabit Dual Port Network Connection
pci:v00008086d000010FB*
- ID_MODEL_FROM_DATABASE=82599EB 10-Gigabit SFI/SFP+ Network Connection
+ ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection
pci:v00008086d000010FBsv00001028sd00001F72*
ID_MODEL_FROM_DATABASE=Ethernet 10G 4P X520/I350 rNDC
@@ -52448,6 +56384,9 @@ pci:v00008086d000010FBsv00008086sd00000003*
pci:v00008086d000010FBsv00008086sd00000006*
ID_MODEL_FROM_DATABASE=Ethernet Server Adapter X520-1
+pci:v00008086d000010FBsv00008086sd00000008*
+ ID_MODEL_FROM_DATABASE=Ethernet OCP Server Adapter X520-2
+
pci:v00008086d000010FBsv00008086sd0000000A*
ID_MODEL_FROM_DATABASE=Ethernet Server Adapter X520-1
@@ -53291,6 +57230,12 @@ pci:v00008086d00001522sv00008086sd00000003*
pci:v00008086d00001522sv00008086sd00000004*
ID_MODEL_FROM_DATABASE=Ethernet Server Adapter I350-F2
+pci:v00008086d00001522sv00008086sd00000005*
+ ID_MODEL_FROM_DATABASE=Ethernet Server Adapter I350-F1
+
+pci:v00008086d00001522sv00008086sd000000A2*
+ ID_MODEL_FROM_DATABASE=Ethernet Server Adapter I350-T2
+
pci:v00008086d00001522sv00008086sd000000A3*
ID_MODEL_FROM_DATABASE=Ethernet Server Adapter I350-F4
@@ -53441,18 +57386,54 @@ pci:v00008086d0000154Dsv00008086sd00007B11*
pci:v00008086d00001557*
ID_MODEL_FROM_DATABASE=82599 10 Gigabit Network Connection
+pci:v00008086d00001557sv00008086sd00000001*
+ ID_MODEL_FROM_DATABASE=Ethernet OCP Server Adapter X520-1
+
+pci:v00008086d00001558*
+ ID_MODEL_FROM_DATABASE=Ethernet Converged Network Adapter X520-Q1
+
+pci:v00008086d00001558sv00008086sd0000011A*
+ ID_MODEL_FROM_DATABASE=Ethernet Converged Network Adapter X520-Q1
+
+pci:v00008086d00001558sv00008086sd0000011B*
+ ID_MODEL_FROM_DATABASE=Ethernet Converged Network Adapter X520-Q1
+
pci:v00008086d00001559*
ID_MODEL_FROM_DATABASE=Ethernet Connection I218-V
pci:v00008086d0000155A*
ID_MODEL_FROM_DATABASE=Ethernet Connection I218-LM
+pci:v00008086d0000155C*
+ ID_MODEL_FROM_DATABASE=Ethernet Server Bypass Adapter
+
+pci:v00008086d0000155Csv00008086sd00000001*
+ ID_MODEL_FROM_DATABASE=Ethernet Server Bypass Adapter X540-T2
+
+pci:v00008086d0000155D*
+ ID_MODEL_FROM_DATABASE=Ethernet Server Bypass Adapter
+
+pci:v00008086d0000155Dsv00008086sd00000001*
+ ID_MODEL_FROM_DATABASE=Ethernet Server Bypass Adapter X520-SR2
+
pci:v00008086d00001560*
- ID_MODEL_FROM_DATABASE=Ethernet Controller X540-AT1
+ ID_MODEL_FROM_DATABASE=Ethernet Controller X540
pci:v00008086d0000157B*
ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection
+pci:v00008086d000015A0*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection (2) I218-LM
+
+pci:v00008086d000015A1*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection (2) I218-V
+
+pci:v00008086d000015A2*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection (3) I218-LM
+
+pci:v00008086d000015A3*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection (3) I218-V
+
pci:v00008086d00001960*
ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor
@@ -54140,6 +58121,9 @@ pci:v00008086d00001E02*
pci:v00008086d00001E02sv00001043sd000084CA*
ID_MODEL_FROM_DATABASE=P8H77-I Motherboard
+pci:v00008086d00001E02sv00001849sd00001E02*
+ ID_MODEL_FROM_DATABASE=Motherboard
+
pci:v00008086d00001E03*
ID_MODEL_FROM_DATABASE=7 Series Chipset Family 6-port SATA Controller [AHCI mode]
@@ -54182,6 +58166,9 @@ pci:v00008086d00001E10sv00001043sd00001517*
pci:v00008086d00001E10sv00001043sd000084CA*
ID_MODEL_FROM_DATABASE=P8H77-I Motherboard
+pci:v00008086d00001E10sv00001849sd00001E10*
+ ID_MODEL_FROM_DATABASE=Motherboard
+
pci:v00008086d00001E12*
ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 2
@@ -54200,21 +58187,33 @@ pci:v00008086d00001E16*
pci:v00008086d00001E16sv00001043sd00001477*
ID_MODEL_FROM_DATABASE=N56VZ
+pci:v00008086d00001E16sv00001849sd00001618*
+ ID_MODEL_FROM_DATABASE=Z77 Extreme4 motherboard
+
pci:v00008086d00001E18*
ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 5
pci:v00008086d00001E18sv00001043sd000084CA*
ID_MODEL_FROM_DATABASE=P8H77-I Motherboard
+pci:v00008086d00001E18sv00001849sd00001E18*
+ ID_MODEL_FROM_DATABASE=Motherboard
+
pci:v00008086d00001E1A*
ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 6
+pci:v00008086d00001E1Asv00001849sd00001E1A*
+ ID_MODEL_FROM_DATABASE=Motherboard
+
pci:v00008086d00001E1C*
ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 7
pci:v00008086d00001E1E*
ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 8
+pci:v00008086d00001E1Esv00001849sd00001E1E*
+ ID_MODEL_FROM_DATABASE=Motherboard
+
pci:v00008086d00001E20*
ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family High Definition Audio Controller
@@ -54227,6 +58226,9 @@ pci:v00008086d00001E20sv00001043sd00001517*
pci:v00008086d00001E20sv00001043sd00008415*
ID_MODEL_FROM_DATABASE=P8H77-I Motherboard
+pci:v00008086d00001E20sv00001849sd00001898*
+ ID_MODEL_FROM_DATABASE=Z77 Extreme4 motherboard
+
pci:v00008086d00001E22*
ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SMBus Controller
@@ -54239,6 +58241,9 @@ pci:v00008086d00001E22sv00001043sd00001517*
pci:v00008086d00001E22sv00001043sd000084CA*
ID_MODEL_FROM_DATABASE=P8H77-I Motherboard
+pci:v00008086d00001E22sv00001849sd00001E22*
+ ID_MODEL_FROM_DATABASE=Motherboard
+
pci:v00008086d00001E24*
ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family Thermal Management Controller
@@ -54260,6 +58265,9 @@ pci:v00008086d00001E26sv00001043sd00001517*
pci:v00008086d00001E26sv00001043sd000084CA*
ID_MODEL_FROM_DATABASE=P8H77-I Motherboard
+pci:v00008086d00001E26sv00001849sd00001E26*
+ ID_MODEL_FROM_DATABASE=Motherboard
+
pci:v00008086d00001E2D*
ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #2
@@ -54272,6 +58280,9 @@ pci:v00008086d00001E2Dsv00001043sd00001517*
pci:v00008086d00001E2Dsv00001043sd000084CA*
ID_MODEL_FROM_DATABASE=P8H77-I Motherboard
+pci:v00008086d00001E2Dsv00001849sd00001E2D*
+ ID_MODEL_FROM_DATABASE=Motherboard
+
pci:v00008086d00001E31*
ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB xHCI Host Controller
@@ -54284,6 +58295,9 @@ pci:v00008086d00001E31sv00001043sd00001517*
pci:v00008086d00001E31sv00001043sd000084CA*
ID_MODEL_FROM_DATABASE=P8H77-I Motherboard
+pci:v00008086d00001E31sv00001849sd00001E31*
+ ID_MODEL_FROM_DATABASE=Motherboard
+
pci:v00008086d00001E33*
ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family LAN Controller
@@ -54299,6 +58313,9 @@ pci:v00008086d00001E3Asv00001043sd00001517*
pci:v00008086d00001E3Asv00001043sd000084CA*
ID_MODEL_FROM_DATABASE=P8H77-I Motherboard
+pci:v00008086d00001E3Asv00001849sd00001E3A*
+ ID_MODEL_FROM_DATABASE=Motherboard
+
pci:v00008086d00001E3B*
ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family MEI Controller #2
@@ -54320,6 +58337,9 @@ pci:v00008086d00001E43*
pci:v00008086d00001E44*
ID_MODEL_FROM_DATABASE=Z77 Express Chipset LPC Controller
+pci:v00008086d00001E44sv00001849sd00001E44*
+ ID_MODEL_FROM_DATABASE=Motherboard
+
pci:v00008086d00001E45*
ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller
@@ -54411,181 +58431,184 @@ pci:v00008086d00001E5F*
ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller
pci:v00008086d00001F00*
- ID_MODEL_FROM_DATABASE=Avoton SSA-Cunit
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router
pci:v00008086d00001F01*
- ID_MODEL_FROM_DATABASE=Avoton SSA-Cunit
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router
pci:v00008086d00001F02*
- ID_MODEL_FROM_DATABASE=Avoton SSA-Cunit
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router
pci:v00008086d00001F03*
- ID_MODEL_FROM_DATABASE=Avoton SSA-Cunit
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router
pci:v00008086d00001F04*
- ID_MODEL_FROM_DATABASE=Avoton SSA-Cunit
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router
pci:v00008086d00001F05*
- ID_MODEL_FROM_DATABASE=Avoton SSA-Cunit
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router
pci:v00008086d00001F06*
- ID_MODEL_FROM_DATABASE=Avoton SSA-Cunit
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router
pci:v00008086d00001F07*
- ID_MODEL_FROM_DATABASE=Avoton SSA-Cunit
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router
pci:v00008086d00001F08*
- ID_MODEL_FROM_DATABASE=Avoton SSA-Cunit
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router
pci:v00008086d00001F09*
- ID_MODEL_FROM_DATABASE=Avoton SSA-Cunit
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router
pci:v00008086d00001F0A*
- ID_MODEL_FROM_DATABASE=Avoton SSA-Cunit
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router
pci:v00008086d00001F0B*
- ID_MODEL_FROM_DATABASE=Avoton SSA-Cunit
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router
pci:v00008086d00001F0C*
- ID_MODEL_FROM_DATABASE=Avoton SSA-Cunit
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router
pci:v00008086d00001F0D*
- ID_MODEL_FROM_DATABASE=Avoton SSA-Cunit
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router
pci:v00008086d00001F0E*
- ID_MODEL_FROM_DATABASE=Avoton SSA-Cunit
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router
pci:v00008086d00001F0F*
- ID_MODEL_FROM_DATABASE=Avoton SSA-Cunit
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router
pci:v00008086d00001F10*
- ID_MODEL_FROM_DATABASE=Avoton PCIe Root Port 1
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 PCIe Root Port 1
pci:v00008086d00001F11*
- ID_MODEL_FROM_DATABASE=Avoton PCIe Root Port 2
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 PCIe Root Port 2
pci:v00008086d00001F12*
- ID_MODEL_FROM_DATABASE=Avoton PCIe Root Port 3
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 PCIe Root Port 3
pci:v00008086d00001F13*
- ID_MODEL_FROM_DATABASE=Avoton PCIe Root Port 4
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 PCIe Root Port 4
pci:v00008086d00001F14*
- ID_MODEL_FROM_DATABASE=Avoton RAS
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 RAS
pci:v00008086d00001F15*
- ID_MODEL_FROM_DATABASE=Avoton SMBus 2.0
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 SMBus 2.0
pci:v00008086d00001F16*
- ID_MODEL_FROM_DATABASE=Avoton RCEC
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 RCEC
pci:v00008086d00001F18*
- ID_MODEL_FROM_DATABASE=Avoton nCPM
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 nCPM
pci:v00008086d00001F19*
- ID_MODEL_FROM_DATABASE=Avoton nCPM
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 nCPM
pci:v00008086d00001F20*
- ID_MODEL_FROM_DATABASE=Avoton 4-Port IDE SATA2 Controller
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 4-Port IDE SATA2 Controller
pci:v00008086d00001F21*
- ID_MODEL_FROM_DATABASE=Avoton 4-Port IDE SATA2 Controller
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 4-Port IDE SATA2 Controller
pci:v00008086d00001F22*
- ID_MODEL_FROM_DATABASE=Avoton AHCI SATA2 Controller
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 AHCI SATA2 Controller
pci:v00008086d00001F23*
- ID_MODEL_FROM_DATABASE=Avoton AHCI SATA2 Controller
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 AHCI SATA2 Controller
pci:v00008086d00001F24*
- ID_MODEL_FROM_DATABASE=Avoton RAID SATA2 Controller
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA2 Controller
pci:v00008086d00001F25*
- ID_MODEL_FROM_DATABASE=Avoton RAID SATA2 Controller
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA2 Controller
pci:v00008086d00001F26*
- ID_MODEL_FROM_DATABASE=Avoton RAID SATA2 Controller
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA2 Controller
pci:v00008086d00001F27*
- ID_MODEL_FROM_DATABASE=Avoton RAID SATA2 Controller
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA2 Controller
pci:v00008086d00001F2C*
- ID_MODEL_FROM_DATABASE=Avoton USB Enhanced Host Controller
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 USB Enhanced Host Controller
pci:v00008086d00001F2E*
- ID_MODEL_FROM_DATABASE=Avoton RAID SATA2 Controller
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA2 Controller
pci:v00008086d00001F2F*
- ID_MODEL_FROM_DATABASE=Avoton RAID SATA2 Controller
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA2 Controller
pci:v00008086d00001F30*
- ID_MODEL_FROM_DATABASE=Avoton 2-Port IDE SATA3 Controller
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 2-Port IDE SATA3 Controller
pci:v00008086d00001F31*
- ID_MODEL_FROM_DATABASE=Avoton 2-Port IDE SATA3 Controller
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 2-Port IDE SATA3 Controller
pci:v00008086d00001F32*
- ID_MODEL_FROM_DATABASE=Avoton AHCI SATA3 Controller
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 AHCI SATA3 Controller
pci:v00008086d00001F33*
- ID_MODEL_FROM_DATABASE=Avoton AHCI SATA3 Controller
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 AHCI SATA3 Controller
pci:v00008086d00001F34*
- ID_MODEL_FROM_DATABASE=Avoton RAID SATA3 Controller
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA3 Controller
pci:v00008086d00001F35*
- ID_MODEL_FROM_DATABASE=Avoton RAID SATA3 Controller
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA3 Controller
pci:v00008086d00001F36*
- ID_MODEL_FROM_DATABASE=Avoton RAID SATA3 Controller
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA3 Controller
pci:v00008086d00001F37*
- ID_MODEL_FROM_DATABASE=Avoton RAID SATA3 Controller
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA3 Controller
pci:v00008086d00001F38*
- ID_MODEL_FROM_DATABASE=Avoton PCU
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 PCU
pci:v00008086d00001F39*
- ID_MODEL_FROM_DATABASE=Avoton PCU
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 PCU
pci:v00008086d00001F3A*
- ID_MODEL_FROM_DATABASE=Avoton PCU
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 PCU
pci:v00008086d00001F3B*
- ID_MODEL_FROM_DATABASE=Avoton PCU
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 PCU
pci:v00008086d00001F3C*
- ID_MODEL_FROM_DATABASE=Avoton PCU SMBus
-
-pci:v00008086d00001F3D*
- ID_MODEL_FROM_DATABASE=Avoton PCU SMBus
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 PCU SMBus
pci:v00008086d00001F3E*
- ID_MODEL_FROM_DATABASE=Avoton RAID SATA3 Controller
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA3 Controller
pci:v00008086d00001F3F*
- ID_MODEL_FROM_DATABASE=Avoton RAID SATA3 Controller
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA3 Controller
pci:v00008086d00001F40*
- ID_MODEL_FROM_DATABASE=Avoton GbE x4 1000base-KX
+ ID_MODEL_FROM_DATABASE=Ethernet Connection I354 1.0 GbE Backplane
+
+pci:v00008086d00001F40sv00001028sd000010F1*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection I354 1.0 GbE Backplane
pci:v00008086d00001F41*
- ID_MODEL_FROM_DATABASE=Avoton GbE x4 SGMII
+ ID_MODEL_FROM_DATABASE=Ethernet Connection I354
pci:v00008086d00001F42*
- ID_MODEL_FROM_DATABASE=Avoton GbE
-
-pci:v00008086d00001F43*
- ID_MODEL_FROM_DATABASE=Avoton GbE EEPROM-less
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 GbE
pci:v00008086d00001F44*
- ID_MODEL_FROM_DATABASE=Avoton GbE Virtual Function
+ ID_MODEL_FROM_DATABASE=Atom processor C2000 GbE Virtual Function
pci:v00008086d00001F45*
- ID_MODEL_FROM_DATABASE=Avoton GbE 2500base-KX
+ ID_MODEL_FROM_DATABASE=Ethernet Connection I354 2.5 GbE Backplane
pci:v00008086d00002250*
- ID_MODEL_FROM_DATABASE=Xeon Phi Coprocessor 5110P
+ ID_MODEL_FROM_DATABASE=Xeon Phi coprocessor 5100 series
+
+pci:v00008086d0000225C*
+ ID_MODEL_FROM_DATABASE=Xeon Phi coprocessor SE10/7120 series
+
+pci:v00008086d0000225D*
+ ID_MODEL_FROM_DATABASE=Xeon Phi coprocessor 3120 series
pci:v00008086d00002310*
ID_MODEL_FROM_DATABASE=DH89xxCC LPC Controller
@@ -54641,6 +58664,66 @@ pci:v00008086d00002364*
pci:v00008086d00002365*
ID_MODEL_FROM_DATABASE=DH89xxCC MEI 1
+pci:v00008086d00002390*
+ ID_MODEL_FROM_DATABASE=Coleto Creek LPC Controller
+
+pci:v00008086d000023A1*
+ ID_MODEL_FROM_DATABASE=Coleto Creek 2-Port SATA Controller [IDE Mode]
+
+pci:v00008086d000023A3*
+ ID_MODEL_FROM_DATABASE=Coleto Creek 4-Port SATA Controller [AHCI Mode]
+
+pci:v00008086d000023A6*
+ ID_MODEL_FROM_DATABASE=Coleto Creek 2-Port SATA Controller [IDE Mode]
+
+pci:v00008086d000023B0*
+ ID_MODEL_FROM_DATABASE=Coleto Creek SMBus Controller
+
+pci:v00008086d000023B1*
+ ID_MODEL_FROM_DATABASE=Coleto Creek CHAP Counter
+
+pci:v00008086d000023B2*
+ ID_MODEL_FROM_DATABASE=Coleto Creek Thermal Management Controller
+
+pci:v00008086d000023B4*
+ ID_MODEL_FROM_DATABASE=Coleto Creek USB2 Enhanced Host Controller #1
+
+pci:v00008086d000023B5*
+ ID_MODEL_FROM_DATABASE=Coleto Creek USB2 Enhanced Host Controller #1
+
+pci:v00008086d000023C2*
+ ID_MODEL_FROM_DATABASE=Coleto Creek PCI Express Root Port #1
+
+pci:v00008086d000023C3*
+ ID_MODEL_FROM_DATABASE=Coleto Creek PCI Express Root Port #1
+
+pci:v00008086d000023C4*
+ ID_MODEL_FROM_DATABASE=Coleto Creek PCI Express Root Port #2
+
+pci:v00008086d000023C5*
+ ID_MODEL_FROM_DATABASE=Coleto Creek PCI Express Root Port #2
+
+pci:v00008086d000023C6*
+ ID_MODEL_FROM_DATABASE=Coleto Creek PCI Express Root Port #3
+
+pci:v00008086d000023C7*
+ ID_MODEL_FROM_DATABASE=Coleto Creek PCI Express Root Port #3
+
+pci:v00008086d000023C8*
+ ID_MODEL_FROM_DATABASE=Coleto Creek PCI Express Root Port #4
+
+pci:v00008086d000023C9*
+ ID_MODEL_FROM_DATABASE=Coleto Creek PCI Express Root Port #4
+
+pci:v00008086d000023E0*
+ ID_MODEL_FROM_DATABASE=Coleto Creek Watchdog Timer
+
+pci:v00008086d000023E4*
+ ID_MODEL_FROM_DATABASE=Coleto Creek MEI Controller #1
+
+pci:v00008086d000023E5*
+ ID_MODEL_FROM_DATABASE=Coleto Creek MEI Controller #2
+
pci:v00008086d00002410*
ID_MODEL_FROM_DATABASE=82801AA ISA Bridge (LPC)
@@ -54912,7 +58995,7 @@ pci:v00008086d00002448sv00001734sd00001055*
ID_MODEL_FROM_DATABASE=Amilo M1420
pci:v00008086d00002448sv000017AAsd000020AE*
- ID_MODEL_FROM_DATABASE=ThinkPad T61
+ ID_MODEL_FROM_DATABASE=ThinkPad T61/R61
pci:v00008086d00002448sv00008086sd0000544B*
ID_MODEL_FROM_DATABASE=Desktop Board D425KT
@@ -58761,7 +62844,7 @@ pci:v00008086d00002811sv0000103Csd000030C1*
ID_MODEL_FROM_DATABASE=Compaq 6910p
pci:v00008086d00002811sv000017AAsd000020B6*
- ID_MODEL_FROM_DATABASE=T61
+ ID_MODEL_FROM_DATABASE=ThinkPad T61/R61
pci:v00008086d00002811sv0000E4BFsd0000CC47*
ID_MODEL_FROM_DATABASE=CCG-RUMBA
@@ -58875,7 +62958,7 @@ pci:v00008086d00002829sv0000104Dsd0000902D*
ID_MODEL_FROM_DATABASE=VAIO VGN-NR120E
pci:v00008086d00002829sv000017AAsd000020A7*
- ID_MODEL_FROM_DATABASE=ThinkPad T61
+ ID_MODEL_FROM_DATABASE=ThinkPad T61/R61
pci:v00008086d00002829sv0000E4BFsd0000CC47*
ID_MODEL_FROM_DATABASE=CCG-RUMBA
@@ -58926,7 +63009,7 @@ pci:v00008086d00002830sv00001462sd00007235*
ID_MODEL_FROM_DATABASE=P965 Neo MS-7235 mainboard
pci:v00008086d00002830sv000017AAsd000020AA*
- ID_MODEL_FROM_DATABASE=ThinkPad T61
+ ID_MODEL_FROM_DATABASE=ThinkPad T61/R61
pci:v00008086d00002830sv0000E4BFsd0000CC47*
ID_MODEL_FROM_DATABASE=CCG-RUMBA
@@ -58968,7 +63051,7 @@ pci:v00008086d00002831sv00001462sd00007235*
ID_MODEL_FROM_DATABASE=P965 Neo MS-7235 mainboard
pci:v00008086d00002831sv000017AAsd000020AA*
- ID_MODEL_FROM_DATABASE=ThinkPad T61
+ ID_MODEL_FROM_DATABASE=ThinkPad T61/R61
pci:v00008086d00002831sv0000E4BFsd0000CC47*
ID_MODEL_FROM_DATABASE=CCG-RUMBA
@@ -59007,7 +63090,7 @@ pci:v00008086d00002832sv0000104Dsd0000902D*
ID_MODEL_FROM_DATABASE=VAIO VGN-NR120E
pci:v00008086d00002832sv000017AAsd000020AA*
- ID_MODEL_FROM_DATABASE=ThinkPad T61
+ ID_MODEL_FROM_DATABASE=ThinkPad T61/R61
pci:v00008086d00002832sv0000E4BFsd0000CC47*
ID_MODEL_FROM_DATABASE=CCG-RUMBA
@@ -59052,7 +63135,7 @@ pci:v00008086d00002834sv00001462sd00007235*
ID_MODEL_FROM_DATABASE=P965 Neo MS-7235 mainboard
pci:v00008086d00002834sv000017AAsd000020AA*
- ID_MODEL_FROM_DATABASE=ThinkPad T61
+ ID_MODEL_FROM_DATABASE=ThinkPad T61/R61
pci:v00008086d00002834sv0000E4BFsd0000CC47*
ID_MODEL_FROM_DATABASE=CCG-RUMBA
@@ -59088,7 +63171,7 @@ pci:v00008086d00002835sv0000104Dsd0000902D*
ID_MODEL_FROM_DATABASE=VAIO VGN-NR120E
pci:v00008086d00002835sv000017AAsd000020AA*
- ID_MODEL_FROM_DATABASE=ThinkPad T60
+ ID_MODEL_FROM_DATABASE=Thinkpad T61/R61
pci:v00008086d00002835sv0000E4BFsd0000CC47*
ID_MODEL_FROM_DATABASE=CCG-RUMBA
@@ -59130,7 +63213,7 @@ pci:v00008086d00002836sv00001462sd00007235*
ID_MODEL_FROM_DATABASE=P965 Neo MS-7235 mainboard
pci:v00008086d00002836sv000017AAsd000020AB*
- ID_MODEL_FROM_DATABASE=ThinkPad T61
+ ID_MODEL_FROM_DATABASE=ThinkPad T61/R61
pci:v00008086d00002836sv0000E4BFsd0000CC47*
ID_MODEL_FROM_DATABASE=CCG-RUMBA
@@ -59166,7 +63249,7 @@ pci:v00008086d0000283Asv0000104Dsd0000902D*
ID_MODEL_FROM_DATABASE=VAIO VGN-NR120E
pci:v00008086d0000283Asv000017AAsd000020AB*
- ID_MODEL_FROM_DATABASE=ThinkPad T61
+ ID_MODEL_FROM_DATABASE=ThinkPad T61/R61
pci:v00008086d0000283Asv0000E4BFsd0000CC47*
ID_MODEL_FROM_DATABASE=CCG-RUMBA
@@ -59202,7 +63285,7 @@ pci:v00008086d0000283Esv00001462sd00007235*
ID_MODEL_FROM_DATABASE=P965 Neo MS-7235 mainboard
pci:v00008086d0000283Esv000017AAsd000020A9*
- ID_MODEL_FROM_DATABASE=ThinkPad T61
+ ID_MODEL_FROM_DATABASE=ThinkPad T61/R61
pci:v00008086d0000283Esv0000E4BFsd0000CC47*
ID_MODEL_FROM_DATABASE=CCG-RUMBA
@@ -59220,7 +63303,7 @@ pci:v00008086d0000283Fsv0000104Dsd0000902D*
ID_MODEL_FROM_DATABASE=VAIO VGN-NR120E
pci:v00008086d0000283Fsv000017AAsd000020AD*
- ID_MODEL_FROM_DATABASE=ThinkPad T61
+ ID_MODEL_FROM_DATABASE=ThinkPad T61/R61
pci:v00008086d00002841*
ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 2
@@ -59232,7 +63315,7 @@ pci:v00008086d00002841sv0000104Dsd0000902D*
ID_MODEL_FROM_DATABASE=VAIO VGN-NR120E
pci:v00008086d00002841sv000017AAsd000020AD*
- ID_MODEL_FROM_DATABASE=ThinkPad T61
+ ID_MODEL_FROM_DATABASE=ThinkPad T61/R61
pci:v00008086d00002843*
ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 3
@@ -59241,13 +63324,13 @@ pci:v00008086d00002843sv0000104Dsd0000902D*
ID_MODEL_FROM_DATABASE=VAIO VGN-NR120E
pci:v00008086d00002843sv000017AAsd000020AD*
- ID_MODEL_FROM_DATABASE=ThinkPad T61
+ ID_MODEL_FROM_DATABASE=ThinkPad T61/R61
pci:v00008086d00002845*
ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 4
pci:v00008086d00002845sv000017AAsd000020AD*
- ID_MODEL_FROM_DATABASE=ThinkPad T61
+ ID_MODEL_FROM_DATABASE=ThinkPad T61/R61
pci:v00008086d00002847*
ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 5
@@ -59259,7 +63342,7 @@ pci:v00008086d00002847sv0000103Csd000030C1*
ID_MODEL_FROM_DATABASE=Compaq 6910p
pci:v00008086d00002847sv000017AAsd000020AD*
- ID_MODEL_FROM_DATABASE=ThinkPad T61
+ ID_MODEL_FROM_DATABASE=ThinkPad T61/R61
pci:v00008086d00002849*
ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 6
@@ -59325,7 +63408,7 @@ pci:v00008086d0000284Bsv000014F1sd00005051*
ID_MODEL_FROM_DATABASE=Presario C700
pci:v00008086d0000284Bsv000017AAsd000020AC*
- ID_MODEL_FROM_DATABASE=ThinkPad T61
+ ID_MODEL_FROM_DATABASE=ThinkPad T61/R61
pci:v00008086d0000284Bsv00008384sd00007616*
ID_MODEL_FROM_DATABASE=Dell Vostro 1400
@@ -59364,7 +63447,7 @@ pci:v00008086d00002850sv0000104Dsd0000902D*
ID_MODEL_FROM_DATABASE=VAIO VGN-NR120E
pci:v00008086d00002850sv000017AAsd000020A6*
- ID_MODEL_FROM_DATABASE=ThinkPad T61
+ ID_MODEL_FROM_DATABASE=ThinkPad T61/R61
pci:v00008086d00002850sv0000E4BFsd0000CC47*
ID_MODEL_FROM_DATABASE=CCG-RUMBA
@@ -61118,6 +65201,45 @@ pci:v00008086d00002F0A*
pci:v00008086d00002F0B*
ID_MODEL_FROM_DATABASE=Haswell-E PCI Express Root Port 3
+pci:v00008086d00002F10*
+ ID_MODEL_FROM_DATABASE=Haswell-E IIO Debug
+
+pci:v00008086d00002F11*
+ ID_MODEL_FROM_DATABASE=Haswell-E IIO Debug
+
+pci:v00008086d00002F12*
+ ID_MODEL_FROM_DATABASE=Haswell-E IIO Debug
+
+pci:v00008086d00002F13*
+ ID_MODEL_FROM_DATABASE=Haswell-E IIO Debug
+
+pci:v00008086d00002F14*
+ ID_MODEL_FROM_DATABASE=Haswell-E IIO Debug
+
+pci:v00008086d00002F15*
+ ID_MODEL_FROM_DATABASE=Haswell-E IIO Debug
+
+pci:v00008086d00002F16*
+ ID_MODEL_FROM_DATABASE=Haswell-E IIO Debug
+
+pci:v00008086d00002F17*
+ ID_MODEL_FROM_DATABASE=Haswell-E IIO Debug
+
+pci:v00008086d00002F18*
+ ID_MODEL_FROM_DATABASE=Haswell-E IIO Debug
+
+pci:v00008086d00002F19*
+ ID_MODEL_FROM_DATABASE=Haswell-E IIO Debug
+
+pci:v00008086d00002F1A*
+ ID_MODEL_FROM_DATABASE=Haswell-E IIO Debug
+
+pci:v00008086d00002F1B*
+ ID_MODEL_FROM_DATABASE=Haswell-E IIO Debug
+
+pci:v00008086d00002F1C*
+ ID_MODEL_FROM_DATABASE=Haswell-E IIO Debug
+
pci:v00008086d00002F1D*
ID_MODEL_FROM_DATABASE=Haswell-E PCIe Ring Interface
@@ -61208,6 +65330,15 @@ pci:v00008086d00002F41*
pci:v00008086d00002F43*
ID_MODEL_FROM_DATABASE=Haswell-E QPI Link 2
+pci:v00008086d00002F45*
+ ID_MODEL_FROM_DATABASE=Haswell-E QPI Link 2 Debug
+
+pci:v00008086d00002F46*
+ ID_MODEL_FROM_DATABASE=Haswell-E QPI Link 2 Debug
+
+pci:v00008086d00002F47*
+ ID_MODEL_FROM_DATABASE=Haswell-E QPI Link 2 Debug
+
pci:v00008086d00002F60*
ID_MODEL_FROM_DATABASE=Haswell-E Home Agent 1
@@ -61238,6 +65369,9 @@ pci:v00008086d00002F70*
pci:v00008086d00002F71*
ID_MODEL_FROM_DATABASE=Haswell-E Integrated Memory Controller 0 Target Address, Thermal & RAS Registers
+pci:v00008086d00002F76*
+ ID_MODEL_FROM_DATABASE=Haswell-E E3 QPI Link Debug
+
pci:v00008086d00002F78*
ID_MODEL_FROM_DATABASE=Haswell-E Home Agent 1 Debug
@@ -61247,6 +65381,9 @@ pci:v00008086d00002F79*
pci:v00008086d00002F7D*
ID_MODEL_FROM_DATABASE=Haswell-E Scratchpad & Semaphore Registers
+pci:v00008086d00002F7E*
+ ID_MODEL_FROM_DATABASE=Haswell-E E3 QPI Link Debug
+
pci:v00008086d00002F80*
ID_MODEL_FROM_DATABASE=Haswell-E QPI Link 0
@@ -61256,12 +65393,45 @@ pci:v00008086d00002F81*
pci:v00008086d00002F83*
ID_MODEL_FROM_DATABASE=Haswell-E QPI Link 0
+pci:v00008086d00002F85*
+ ID_MODEL_FROM_DATABASE=Haswell-E QPI Link 0 Debug
+
+pci:v00008086d00002F86*
+ ID_MODEL_FROM_DATABASE=Haswell-E QPI Link 0 Debug
+
+pci:v00008086d00002F87*
+ ID_MODEL_FROM_DATABASE=Haswell-E QPI Link 0 Debug
+
+pci:v00008086d00002F88*
+ ID_MODEL_FROM_DATABASE=Haswell-E VCU
+
+pci:v00008086d00002F8A*
+ ID_MODEL_FROM_DATABASE=Haswell-E VCU
+
pci:v00008086d00002F90*
ID_MODEL_FROM_DATABASE=Haswell-E QPI Link 1
pci:v00008086d00002F93*
ID_MODEL_FROM_DATABASE=Haswell-E QPI Link 1
+pci:v00008086d00002F95*
+ ID_MODEL_FROM_DATABASE=Haswell-E QPI Link 1 Debug
+
+pci:v00008086d00002F96*
+ ID_MODEL_FROM_DATABASE=Haswell-E QPI Link 1 Debug
+
+pci:v00008086d00002F98*
+ ID_MODEL_FROM_DATABASE=Haswell-E Power Control Unit
+
+pci:v00008086d00002F99*
+ ID_MODEL_FROM_DATABASE=Haswell-E Power Control Unit
+
+pci:v00008086d00002F9A*
+ ID_MODEL_FROM_DATABASE=Haswell-E Power Control Unit
+
+pci:v00008086d00002F9C*
+ ID_MODEL_FROM_DATABASE=Haswell-E Power Control Unit
+
pci:v00008086d00002FA0*
ID_MODEL_FROM_DATABASE=Haswell-E Home Agent 0
@@ -61304,6 +65474,12 @@ pci:v00008086d00002FB4*
pci:v00008086d00002FB5*
ID_MODEL_FROM_DATABASE=Haswell-E Integrated Memory Controller 0 Channel 3 Thermal Control
+pci:v00008086d00002FB6*
+ ID_MODEL_FROM_DATABASE=Haswell-E Integrated Memory Controller 0 Channel 2 ERROR Registers
+
+pci:v00008086d00002FB7*
+ ID_MODEL_FROM_DATABASE=Haswell-E Integrated Memory Controller 0 Channel 3 ERROR Registers
+
pci:v00008086d00002FB8*
ID_MODEL_FROM_DATABASE=Haswell-E DDRIO (VMSE) 2 & 3
@@ -61335,16 +65511,16 @@ pci:v00008086d00002FC1*
ID_MODEL_FROM_DATABASE=Haswell-E Power Control Unit
pci:v00008086d00002FC2*
- ID_MODEL_FROM_DATABASE=Power Control Unit
+ ID_MODEL_FROM_DATABASE=Haswell-E Power Control Unit
pci:v00008086d00002FC3*
- ID_MODEL_FROM_DATABASE=Power Control Unit
+ ID_MODEL_FROM_DATABASE=Haswell-E Power Control Unit
pci:v00008086d00002FC4*
- ID_MODEL_FROM_DATABASE=Power Control Unit
+ ID_MODEL_FROM_DATABASE=Haswell-E Power Control Unit
pci:v00008086d00002FC5*
- ID_MODEL_FROM_DATABASE=Power Control Unit
+ ID_MODEL_FROM_DATABASE=Haswell-E Power Control Unit
pci:v00008086d00002FD0*
ID_MODEL_FROM_DATABASE=Haswell-E Integrated Memory Controller 1 Channel 0 Thermal Control
@@ -62484,7 +66660,7 @@ pci:v00008086d00003A3Csv00001043sd000082D4*
ID_MODEL_FROM_DATABASE=P5Q Deluxe Motherboard
pci:v00008086d00003A3Csv00001458sd00005006*
- ID_MODEL_FROM_DATABASE=GA-EP45-DS5 Motherboard
+ ID_MODEL_FROM_DATABASE=Motherboard
pci:v00008086d00003A3E*
ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) HD Audio Controller
@@ -64206,226 +68382,226 @@ pci:v00008086d00008819*
ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T IEEE 1588 Hardware Assist
pci:v00008086d00008C00*
- ID_MODEL_FROM_DATABASE=Lynx Point 4-port SATA Controller 1 [IDE mode]
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 4-port SATA Controller 1 [IDE mode]
pci:v00008086d00008C01*
- ID_MODEL_FROM_DATABASE=Lynx Point 4-port SATA Controller 1 [IDE mode]
+ ID_MODEL_FROM_DATABASE=8 Series Chipset Family 4-port SATA Controller 1 [IDE mode] - Mobile
pci:v00008086d00008C02*
- ID_MODEL_FROM_DATABASE=Lynx Point 6-port SATA Controller 1 [AHCI mode]
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode]
pci:v00008086d00008C03*
- ID_MODEL_FROM_DATABASE=Lynx Point 6-port SATA Controller 1 [AHCI mode]
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode]
pci:v00008086d00008C04*
- ID_MODEL_FROM_DATABASE=Lynx Point SATA Controller 1 [RAID mode]
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode]
pci:v00008086d00008C05*
- ID_MODEL_FROM_DATABASE=Lynx Point SATA Controller 1 [RAID mode]
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode]
pci:v00008086d00008C06*
- ID_MODEL_FROM_DATABASE=Lynx Point SATA Controller 1 [RAID mode]
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode]
pci:v00008086d00008C07*
- ID_MODEL_FROM_DATABASE=Lynx Point SATA Controller 1 [RAID mode]
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode]
pci:v00008086d00008C08*
- ID_MODEL_FROM_DATABASE=Lynx Point 2-port SATA Controller 2 [IDE mode]
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 2-port SATA Controller 2 [IDE mode]
pci:v00008086d00008C09*
- ID_MODEL_FROM_DATABASE=Lynx Point 2-port SATA Controller 2 [IDE mode]
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 2-port SATA Controller 2 [IDE mode]
pci:v00008086d00008C0E*
- ID_MODEL_FROM_DATABASE=Lynx Point SATA Controller 1 [RAID mode]
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode]
pci:v00008086d00008C0F*
- ID_MODEL_FROM_DATABASE=Lynx Point SATA Controller 1 [RAID mode]
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode]
pci:v00008086d00008C10*
- ID_MODEL_FROM_DATABASE=Lynx Point PCI Express Root Port #1
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #1
pci:v00008086d00008C11*
- ID_MODEL_FROM_DATABASE=Lynx Point PCI Express Root Port #1
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #1
pci:v00008086d00008C12*
- ID_MODEL_FROM_DATABASE=Lynx Point PCI Express Root Port #2
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #2
pci:v00008086d00008C13*
- ID_MODEL_FROM_DATABASE=Lynx Point PCI Express Root Port #2
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #2
pci:v00008086d00008C14*
- ID_MODEL_FROM_DATABASE=Lynx Point PCI Express Root Port #3
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #3
pci:v00008086d00008C15*
- ID_MODEL_FROM_DATABASE=Lynx Point PCI Express Root Port #3
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #3
pci:v00008086d00008C16*
- ID_MODEL_FROM_DATABASE=Lynx Point PCI Express Root Port #4
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #4
pci:v00008086d00008C17*
- ID_MODEL_FROM_DATABASE=Lynx Point PCI Express Root Port #4
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #4
pci:v00008086d00008C18*
- ID_MODEL_FROM_DATABASE=Lynx Point PCI Express Root Port #5
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #5
pci:v00008086d00008C19*
- ID_MODEL_FROM_DATABASE=Lynx Point PCI Express Root Port #5
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #5
pci:v00008086d00008C1A*
- ID_MODEL_FROM_DATABASE=Lynx Point PCI Express Root Port #6
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #6
pci:v00008086d00008C1B*
- ID_MODEL_FROM_DATABASE=Lynx Point PCI Express Root Port #6
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #6
pci:v00008086d00008C1C*
- ID_MODEL_FROM_DATABASE=Lynx Point PCI Express Root Port #7
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #7
pci:v00008086d00008C1D*
- ID_MODEL_FROM_DATABASE=Lynx Point PCI Express Root Port #7
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #7
pci:v00008086d00008C1E*
- ID_MODEL_FROM_DATABASE=Lynx Point PCI Express Root Port #8
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #8
pci:v00008086d00008C1F*
- ID_MODEL_FROM_DATABASE=Lynx Point PCI Express Root Port #8
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #8
pci:v00008086d00008C20*
- ID_MODEL_FROM_DATABASE=Lynx Point High Definition Audio Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset High Definition Audio Controller
pci:v00008086d00008C21*
- ID_MODEL_FROM_DATABASE=Lynx Point High Definition Audio Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset High Definition Audio Controller
pci:v00008086d00008C22*
- ID_MODEL_FROM_DATABASE=Lynx Point SMBus Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SMBus Controller
pci:v00008086d00008C23*
- ID_MODEL_FROM_DATABASE=Lynx Point CHAP Counters
+ ID_MODEL_FROM_DATABASE=8 Series Chipset Family CHAP Counters
pci:v00008086d00008C24*
- ID_MODEL_FROM_DATABASE=Lynx Point Thermal Management Controller
+ ID_MODEL_FROM_DATABASE=8 Series Chipset Family Thermal Management Controller
pci:v00008086d00008C26*
- ID_MODEL_FROM_DATABASE=Lynx Point USB Enhanced Host Controller #1
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #1
pci:v00008086d00008C2D*
- ID_MODEL_FROM_DATABASE=Lynx Point USB Enhanced Host Controller #2
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #2
pci:v00008086d00008C31*
- ID_MODEL_FROM_DATABASE=Lynx Point USB xHCI Host Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB xHCI
pci:v00008086d00008C33*
- ID_MODEL_FROM_DATABASE=Lynx Point LAN Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LAN Controller
pci:v00008086d00008C34*
- ID_MODEL_FROM_DATABASE=Lynx Point NAND Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family NAND Controller
pci:v00008086d00008C3A*
- ID_MODEL_FROM_DATABASE=Lynx Point MEI Controller #1
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family MEI Controller #1
pci:v00008086d00008C3B*
- ID_MODEL_FROM_DATABASE=Lynx Point MEI Controller #2
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family MEI Controller #2
pci:v00008086d00008C3C*
- ID_MODEL_FROM_DATABASE=Lynx Point IDE-r Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family IDE-r Controller
pci:v00008086d00008C3D*
- ID_MODEL_FROM_DATABASE=Lynx Point KT Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family KT Controller
pci:v00008086d00008C40*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller
pci:v00008086d00008C41*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=8 Series Chipset Family Mobile Super SKU LPC Controller
pci:v00008086d00008C42*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family Desktop Super SKU LPC Controller
pci:v00008086d00008C43*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller
pci:v00008086d00008C44*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=Z87 Express LPC Controller
pci:v00008086d00008C45*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller
pci:v00008086d00008C46*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=Z85 Express LPC Controller
pci:v00008086d00008C47*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller
pci:v00008086d00008C48*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller
pci:v00008086d00008C49*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=HM86 Express LPC Controller
pci:v00008086d00008C4A*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=H87 Express LPC Controller
pci:v00008086d00008C4B*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=HM87 Express LPC Controller
pci:v00008086d00008C4C*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=Q85 Express LPC Controller
pci:v00008086d00008C4D*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller
pci:v00008086d00008C4E*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=Q87 Express LPC Controller
pci:v00008086d00008C4F*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=QM87 Express LPC Controller
pci:v00008086d00008C50*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=B85 Express LPC Controller
pci:v00008086d00008C51*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller
pci:v00008086d00008C52*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=C222 Series Chipset Family Server Essential SKU LPC Controller
pci:v00008086d00008C53*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller
pci:v00008086d00008C54*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=C224 Series Chipset Family Server Standard SKU LPC Controller
pci:v00008086d00008C55*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller
pci:v00008086d00008C56*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=C226 Series Chipset Family Server Advanced SKU LPC Controller
pci:v00008086d00008C57*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller
pci:v00008086d00008C58*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family WS SKU LPC Controller
pci:v00008086d00008C59*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller
pci:v00008086d00008C5A*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller
pci:v00008086d00008C5B*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller
pci:v00008086d00008C5C*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=C220 Series Chipset Family H81 Express LPC Controller
pci:v00008086d00008C5D*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller
pci:v00008086d00008C5E*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller
pci:v00008086d00008C5F*
- ID_MODEL_FROM_DATABASE=Lynx Point LPC Controller
+ ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller
pci:v00008086d00008D00*
ID_MODEL_FROM_DATABASE=Wellsburg 4-port SATA Controller [IDE mode]
@@ -64599,7 +68775,7 @@ pci:v00008086d00008D6E*
ID_MODEL_FROM_DATABASE=Wellsburg sSATA Controller [RAID mode]
pci:v00008086d00008D7C*
- ID_MODEL_FROM_DATABASE=Wellsburg EPSS
+ ID_MODEL_FROM_DATABASE=Wellsburg SPSR
pci:v00008086d00008D7D*
ID_MODEL_FROM_DATABASE=Wellsburg MS SMBus 0
@@ -66332,8 +70508,35 @@ pci:v0000BD11*
pci:v0000BDBD*
ID_VENDOR_FROM_DATABASE=Blackmagic Design
+pci:v0000BDBDd0000A117*
+ ID_MODEL_FROM_DATABASE=Intensity Pro
+
+pci:v0000BDBDd0000A11A*
+ ID_MODEL_FROM_DATABASE=DeckLink HD Extreme 2
+
pci:v0000BDBDd0000A11B*
- ID_MODEL_FROM_DATABASE=DeckLink SDI
+ ID_MODEL_FROM_DATABASE=DeckLink SDI/Duo/Quad
+
+pci:v0000BDBDd0000A11C*
+ ID_MODEL_FROM_DATABASE=DeckLink HD Extreme 3
+
+pci:v0000BDBDd0000A11D*
+ ID_MODEL_FROM_DATABASE=DeckLink Studio
+
+pci:v0000BDBDd0000A11E*
+ ID_MODEL_FROM_DATABASE=DeckLink Optical Fibre
+
+pci:v0000BDBDd0000A121*
+ ID_MODEL_FROM_DATABASE=DeckLink HD Extreme 3D/3D+
+
+pci:v0000BDBDd0000A12E*
+ ID_MODEL_FROM_DATABASE=DeckLink 4K Extreme
+
+pci:v0000BDBDd0000A12F*
+ ID_MODEL_FROM_DATABASE=DeckLink Mini Monitor
+
+pci:v0000BDBDd0000A130*
+ ID_MODEL_FROM_DATABASE=DeckLink Mini Recorder
pci:v0000C001*
ID_VENDOR_FROM_DATABASE=TSI Telsys
@@ -66464,6 +70667,12 @@ pci:v0000D161d00008007*
pci:v0000D161d00008008*
ID_MODEL_FROM_DATABASE=Hx8 Series 8-port Base Card (PCI-Express)
+pci:v0000D161d0000800A*
+ ID_MODEL_FROM_DATABASE=Wildcard TE133 single-span T1/E1/J1 card (PCI Express)
+
+pci:v0000D161d0000800B*
+ ID_MODEL_FROM_DATABASE=Wildcard TE134 single-span T1/E1/J1 card
+
pci:v0000D161d0000B410*
ID_MODEL_FROM_DATABASE=Wildcard B410 quad-BRI card
@@ -66501,8 +70710,44 @@ pci:v0000DD01*
ID_VENDOR_FROM_DATABASE=Digital Devices GmbH
pci:v0000DD01d00000003*
+ ID_MODEL_FROM_DATABASE=Octopus DVB Adapter
+
+pci:v0000DD01d00000003sv0000DD01sd00000001*
+ ID_MODEL_FROM_DATABASE=Octopus DVB adapter
+
+pci:v0000DD01d00000003sv0000DD01sd00000002*
ID_MODEL_FROM_DATABASE=Octopus LE DVB adapter
+pci:v0000DD01d00000003sv0000DD01sd00000003*
+ ID_MODEL_FROM_DATABASE=Octopus OEM
+
+pci:v0000DD01d00000003sv0000DD01sd00000004*
+ ID_MODEL_FROM_DATABASE=Octopus V3 DVB adapter
+
+pci:v0000DD01d00000003sv0000DD01sd00000010*
+ ID_MODEL_FROM_DATABASE=Octopus Mini
+
+pci:v0000DD01d00000003sv0000DD01sd00000020*
+ ID_MODEL_FROM_DATABASE=Cine S2 V6 DVB adapter
+
+pci:v0000DD01d00000003sv0000DD01sd00000021*
+ ID_MODEL_FROM_DATABASE=Cine S2 V6.5 DVB adapter
+
+pci:v0000DD01d00000003sv0000DD01sd00000030*
+ ID_MODEL_FROM_DATABASE=Cine CT V6.1 DVB adapter
+
+pci:v0000DD01d00000003sv0000DD01sd0000DB03*
+ ID_MODEL_FROM_DATABASE=Mystique SaTiX-S2 V3 DVB adapter
+
+pci:v0000DD01d00000011*
+ ID_MODEL_FROM_DATABASE=Octopus CI DVB Adapter
+
+pci:v0000DD01d00000011sv0000DD01sd00000040*
+ ID_MODEL_FROM_DATABASE=Octopus CI
+
+pci:v0000DD01d00000011sv0000DD01sd00000041*
+ ID_MODEL_FROM_DATABASE=Octopus CI Single
+
pci:v0000DEAD*
ID_VENDOR_FROM_DATABASE=Indigita Corporation
diff --git a/hwdb/20-usb-vendor-model.hwdb b/hwdb/20-usb-vendor-model.hwdb
index 8c9584b358..da8385ef91 100644
--- a/hwdb/20-usb-vendor-model.hwdb
+++ b/hwdb/20-usb-vendor-model.hwdb
@@ -266,6 +266,12 @@ usb:v03EBp2310*
usb:v03EBp2FE4*
ID_MODEL_FROM_DATABASE=ATxmega32A4U DFU bootloader
+usb:v03EBp2FF0*
+ ID_MODEL_FROM_DATABASE=atmega32u2 DFU bootloader
+
+usb:v03EBp2FFA*
+ ID_MODEL_FROM_DATABASE=at90usb162 DFU bootloader
+
usb:v03EBp2FFB*
ID_MODEL_FROM_DATABASE=at90usb AVR DFU bootloader
@@ -599,6 +605,9 @@ usb:v03F0p0917*
usb:v03F0p0924*
ID_MODEL_FROM_DATABASE=Modular Smartcard Keyboard
+usb:v03F0p094A*
+ ID_MODEL_FROM_DATABASE=Optical Mouse [672662-001]
+
usb:v03F0p0A01*
ID_MODEL_FROM_DATABASE=ScanJet 2400c
@@ -2009,6 +2018,9 @@ usb:v0403p8040*
usb:v0403p8070*
ID_MODEL_FROM_DATABASE=7 Port Hub
+usb:v0403p8210*
+ ID_MODEL_FROM_DATABASE=MGTimer - MGCC (Vic) Timing System
+
usb:v0403p8370*
ID_MODEL_FROM_DATABASE=7 Port Hub
@@ -2924,9 +2936,15 @@ usb:v040Ap1001*
usb:v040Ap4000*
ID_MODEL_FROM_DATABASE=InkJet Color Printer
+usb:v040Ap4021*
+ ID_MODEL_FROM_DATABASE=Photo Printer 6800
+
usb:v040Ap4022*
ID_MODEL_FROM_DATABASE=1400 Digital Photo Printer
+usb:v040Ap4034*
+ ID_MODEL_FROM_DATABASE=805 Photo Printer
+
usb:v040Ap4056*
ID_MODEL_FROM_DATABASE=ESP 7200 Series AiO
@@ -4293,7 +4311,7 @@ usb:v0424p7500*
ID_MODEL_FROM_DATABASE=LAN7500 Ethernet 10/100/1000 Adapter
usb:v0424p9512*
- ID_MODEL_FROM_DATABASE=LAN9500 Ethernet 10/100 Adapter / SMSC9512/9514 Hub
+ ID_MODEL_FROM_DATABASE=SMC9512/9514 USB Hub
usb:v0424pA700*
ID_MODEL_FROM_DATABASE=2 Port Hub
@@ -4877,6 +4895,9 @@ usb:v043Dp010F*
usb:v043Dp0142*
ID_MODEL_FROM_DATABASE=X3650 (Printer, Scanner, Copier)
+usb:v043Dp01FA*
+ ID_MODEL_FROM_DATABASE=S310 series
+
usb:v043Dp4303*
ID_MODEL_FROM_DATABASE=Xerox WorkCentre Pro 412
@@ -4898,6 +4919,9 @@ usb:v043Ep7001*
usb:v043Ep7013*
ID_MODEL_FROM_DATABASE=MP3 Player
+usb:v043Ep70F5*
+ ID_MODEL_FROM_DATABASE=External HDD
+
usb:v043Ep8484*
ID_MODEL_FROM_DATABASE=LPC-U30 Webcam II
@@ -5157,7 +5181,7 @@ usb:v0451pDBC0*
ID_MODEL_FROM_DATABASE=Device Bay Controller
usb:v0451pE001*
- ID_MODEL_FROM_DATABASE=GraphLink
+ ID_MODEL_FROM_DATABASE=GraphLink [SilverLink]
usb:v0451pE003*
ID_MODEL_FROM_DATABASE=TI-84 Plus Calculator
@@ -5168,6 +5192,9 @@ usb:v0451pE004*
usb:v0451pE008*
ID_MODEL_FROM_DATABASE=TI-84 Plus Silver Calculator
+usb:v0451pE012*
+ ID_MODEL_FROM_DATABASE=TI-Nspire Calculator
+
usb:v0451pF430*
ID_MODEL_FROM_DATABASE=MSP-FET430UIF JTAG Tool
@@ -5894,6 +5921,9 @@ usb:v045Ep029E*
usb:v045Ep02A0*
ID_MODEL_FROM_DATABASE=Xbox360 Big Button IR
+usb:v045Ep02A1*
+ ID_MODEL_FROM_DATABASE=Xbox 360 Wireless Receiver for Windows
+
usb:v045Ep02A8*
ID_MODEL_FROM_DATABASE=Xbox360 Wireless N Networking Adapter [Atheros AR7010+AR9280]
@@ -5906,6 +5936,9 @@ usb:v045Ep02AE*
usb:v045Ep02B0*
ID_MODEL_FROM_DATABASE=Xbox NUI Motor
+usb:v045Ep02B6*
+ ID_MODEL_FROM_DATABASE=Xbox 360 / Bluetooth Wireless Headset
+
usb:v045Ep0400*
ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002
@@ -6371,6 +6404,9 @@ usb:v045Ep0779*
usb:v045Ep930A*
ID_MODEL_FROM_DATABASE=ISOUSB.SYS Intel 82930 Isochronous IO Test Board
+usb:v045EpFFCA*
+ ID_MODEL_FROM_DATABASE=Catalina
+
usb:v045EpFFF8*
ID_MODEL_FROM_DATABASE=Keyboard
@@ -6626,6 +6662,9 @@ usb:v046Ap002D*
usb:v046Ap003E*
ID_MODEL_FROM_DATABASE=SmartTerminal ST-2xxx
+usb:v046Ap0041*
+ ID_MODEL_FROM_DATABASE=G86 6240 Keyboard
+
usb:v046Ap0080*
ID_MODEL_FROM_DATABASE=eHealth Terminal ST 1503
@@ -7043,6 +7082,9 @@ usb:v046Dp0A17*
usb:v046Dp0A1F*
ID_MODEL_FROM_DATABASE=G930
+usb:v046Dp0A29*
+ ID_MODEL_FROM_DATABASE=H600 [Wireless Headset]
+
usb:v046Dp0B02*
ID_MODEL_FROM_DATABASE=C-UV35 [Bluetooth Mini-Receiver] (HID proxy mode)
@@ -7232,6 +7274,9 @@ usb:v046DpC062*
usb:v046DpC063*
ID_MODEL_FROM_DATABASE=DELL Laser Mouse
+usb:v046DpC066*
+ ID_MODEL_FROM_DATABASE=G9x Laser Mouse
+
usb:v046DpC068*
ID_MODEL_FROM_DATABASE=G500 Laser Mouse
@@ -7266,7 +7311,7 @@ usb:v046DpC121*
ID_MODEL_FROM_DATABASE=Harmony One Remote
usb:v046DpC122*
- ID_MODEL_FROM_DATABASE=Harmony 700 Remote
+ ID_MODEL_FROM_DATABASE=Harmony 650/700 Remote
usb:v046DpC124*
ID_MODEL_FROM_DATABASE=Harmony 300 Remote
@@ -7274,6 +7319,9 @@ usb:v046DpC124*
usb:v046DpC125*
ID_MODEL_FROM_DATABASE=Harmony 200 Remote
+usb:v046DpC126*
+ ID_MODEL_FROM_DATABASE=Harmony Link
+
usb:v046DpC201*
ID_MODEL_FROM_DATABASE=WingMan Extreme Joystick with Throttle
@@ -7592,6 +7640,9 @@ usb:v046DpC529*
usb:v046DpC52B*
ID_MODEL_FROM_DATABASE=Unifying Receiver
+usb:v046DpC52E*
+ ID_MODEL_FROM_DATABASE=MK260 Wireless Combo Receiver
+
usb:v046DpC52F*
ID_MODEL_FROM_DATABASE=Unifying Receiver
@@ -7610,6 +7661,9 @@ usb:v046DpC626*
usb:v046DpC627*
ID_MODEL_FROM_DATABASE=3Dconnexion Space Explorer 3D Mouse
+usb:v046DpC629*
+ ID_MODEL_FROM_DATABASE=3Dconnexion SpacePilot Pro 3D Mouse
+
usb:v046DpC702*
ID_MODEL_FROM_DATABASE=Cordless Presenter
@@ -8024,6 +8078,9 @@ usb:v0471p20D0*
usb:v0471p20E3*
ID_MODEL_FROM_DATABASE=GoGear Raga
+usb:v0471p20E4*
+ ID_MODEL_FROM_DATABASE=GoGear ViBE 8GB
+
usb:v0471p262C*
ID_MODEL_FROM_DATABASE=SPC230NC Webcam
@@ -8423,6 +8480,9 @@ usb:v047FpAC01*
usb:v047FpAD01*
ID_MODEL_FROM_DATABASE=GameCom 777 5.1 Headset
+usb:v047FpC00E*
+ ID_MODEL_FROM_DATABASE=Blackwire C310 headset
+
usb:v0480*
ID_VENDOR_FROM_DATABASE=Toshiba America Info. Systems, Inc.
@@ -8438,6 +8498,9 @@ usb:v0480p0011*
usb:v0480p0014*
ID_MODEL_FROM_DATABASE=InTouch Module
+usb:v0480pA006*
+ ID_MODEL_FROM_DATABASE=External Disk 1.5TB
+
usb:v0480pA007*
ID_MODEL_FROM_DATABASE=External Disk USB 3.0
@@ -8450,6 +8513,9 @@ usb:v0482*
usb:v0482p000E*
ID_MODEL_FROM_DATABASE=FS-1020D Printer
+usb:v0482p000F*
+ ID_MODEL_FROM_DATABASE=FS-1920 Mono Printer
+
usb:v0482p0100*
ID_MODEL_FROM_DATABASE=Finecam S3x
@@ -9701,6 +9767,9 @@ usb:v04A9p1721*
usb:v04A9p1723*
ID_MODEL_FROM_DATABASE=MP470 ser
+usb:v04A9p1724*
+ ID_MODEL_FROM_DATABASE=PIXMA MP520 series
+
usb:v04A9p1725*
ID_MODEL_FROM_DATABASE=MP610 ser
@@ -9719,6 +9788,9 @@ usb:v04A9p1729*
usb:v04A9p172B*
ID_MODEL_FROM_DATABASE=MP140 ser
+usb:v04A9p173B*
+ ID_MODEL_FROM_DATABASE=PIXMA MP270 All-In-One Printer
+
usb:v04A9p173E*
ID_MODEL_FROM_DATABASE=MP560
@@ -10442,9 +10514,15 @@ usb:v04A9p310B*
usb:v04A9p310E*
ID_MODEL_FROM_DATABASE=Digital IXUS 50 (PTP mode)
+usb:v04A9p310F*
+ ID_MODEL_FROM_DATABASE=PowerShot A420
+
usb:v04A9p3110*
ID_MODEL_FROM_DATABASE=EOS Digital Rebel XTi
+usb:v04A9p3115*
+ ID_MODEL_FROM_DATABASE=PowerShot SD900 / Digital IXUS 900 Ti / IXY DIGITAL 1000
+
usb:v04A9p3116*
ID_MODEL_FROM_DATABASE=Digital IXUS 750 / PowerShot SD550 (PTP mode)
@@ -10454,9 +10532,21 @@ usb:v04A9p3117*
usb:v04A9p3119*
ID_MODEL_FROM_DATABASE=PowerShot SD700 IS / Digital IXUS 800 IS / IXY Digital 800 IS
+usb:v04A9p311A*
+ ID_MODEL_FROM_DATABASE=PowerShot S3 IS
+
usb:v04A9p311B*
ID_MODEL_FROM_DATABASE=PowerShot A540
+usb:v04A9p311C*
+ ID_MODEL_FROM_DATABASE=PowerShot SD600 DIGITAL ELPH / DIGITAL IXUS 60 / IXY DIGITAL 70
+
+usb:v04A9p3125*
+ ID_MODEL_FROM_DATABASE=PowerShot G7
+
+usb:v04A9p3126*
+ ID_MODEL_FROM_DATABASE=PowerShot A530
+
usb:v04A9p3127*
ID_MODEL_FROM_DATABASE=SELPHY CP710
@@ -10466,9 +10556,21 @@ usb:v04A9p3128*
usb:v04A9p312D*
ID_MODEL_FROM_DATABASE=Elura 100
+usb:v04A9p3136*
+ ID_MODEL_FROM_DATABASE=PowerShot SD800 IS / Digital IXUS 850 IS / IXY DIGITAL 900 IS
+
+usb:v04A9p3137*
+ ID_MODEL_FROM_DATABASE=PowerShot SD40 / Digital IXUS i7 IXY / DIGITAL L4
+
usb:v04A9p3138*
ID_MODEL_FROM_DATABASE=PowerShot A710 IS
+usb:v04A9p3139*
+ ID_MODEL_FROM_DATABASE=PowerShot A640
+
+usb:v04A9p313A*
+ ID_MODEL_FROM_DATABASE=PowerShot A630
+
usb:v04A9p3141*
ID_MODEL_FROM_DATABASE=SELPHY ES1
@@ -10481,11 +10583,35 @@ usb:v04A9p3143*
usb:v04A9p3145*
ID_MODEL_FROM_DATABASE=EOS 450D
+usb:v04A9p3146*
+ ID_MODEL_FROM_DATABASE=EOS 40D
+
usb:v04A9p3147*
ID_MODEL_FROM_DATABASE=EOS 1Ds Mark III
+usb:v04A9p3148*
+ ID_MODEL_FROM_DATABASE=PowerShot S5 IS
+
+usb:v04A9p3149*
+ ID_MODEL_FROM_DATABASE=PowerShot A460
+
+usb:v04A9p314B*
+ ID_MODEL_FROM_DATABASE=PowerShot SD850 IS DIGITAL ELPH / Digital IXUS 950 IS / IXY DIGITAL 810 IS
+
+usb:v04A9p314C*
+ ID_MODEL_FROM_DATABASE=PowerShot A570 IS
+
+usb:v04A9p314D*
+ ID_MODEL_FROM_DATABASE=PowerShot A560
+
+usb:v04A9p314E*
+ ID_MODEL_FROM_DATABASE=PowerShot SD750 DIGITAL ELPH / DIGITAL IXUS 75 / IXY DIGITAL 90
+
usb:v04A9p314F*
- ID_MODEL_FROM_DATABASE=Powershot SD1000
+ ID_MODEL_FROM_DATABASE=PowerShot SD1000 DIGITAL ELPH / DIGITAL IXUS 70 / IXY DIGITAL 10
+
+usb:v04A9p3150*
+ ID_MODEL_FROM_DATABASE=PowerShot A550
usb:v04A9p3155*
ID_MODEL_FROM_DATABASE=PowerShot A450
@@ -10493,9 +10619,18 @@ usb:v04A9p3155*
usb:v04A9p315A*
ID_MODEL_FROM_DATABASE=PowerShot G9
+usb:v04A9p315B*
+ ID_MODEL_FROM_DATABASE=PowerShot A650 IS
+
usb:v04A9p315D*
ID_MODEL_FROM_DATABASE=PowerShot A720
+usb:v04A9p315E*
+ ID_MODEL_FROM_DATABASE=PowerShot SX100 IS
+
+usb:v04A9p315F*
+ ID_MODEL_FROM_DATABASE=PowerShot SD950 IS DIGITAL ELPH / DIGITAL IXUS 960 IS / IXY DIGITAL 2000 IS
+
usb:v04A9p3160*
ID_MODEL_FROM_DATABASE=Digital IXUS 860 IS
@@ -10505,12 +10640,21 @@ usb:v04A9p3170*
usb:v04A9p3171*
ID_MODEL_FROM_DATABASE=SELPHY CP740
+usb:v04A9p3173*
+ ID_MODEL_FROM_DATABASE=PowerShot SD890 IS DIGITAL ELPH / Digital IXUS 970 IS / IXY DIGITAL 820 IS
+
+usb:v04A9p3174*
+ ID_MODEL_FROM_DATABASE=PowerShot SD790 IS DIGITAL ELPH / Digital IXUS 90 IS / IXY DIGITAL 95 IS
+
usb:v04A9p3175*
ID_MODEL_FROM_DATABASE=IXY Digital 25 IS
usb:v04A9p3176*
ID_MODEL_FROM_DATABASE=PowerShot A590
+usb:v04A9p3177*
+ ID_MODEL_FROM_DATABASE=PowerShot A580
+
usb:v04A9p317A*
ID_MODEL_FROM_DATABASE=PC1267 [Powershot A470]
@@ -10523,9 +10667,30 @@ usb:v04A9p3185*
usb:v04A9p3186*
ID_MODEL_FROM_DATABASE=SELPHY ES20
+usb:v04A9p318D*
+ ID_MODEL_FROM_DATABASE=PowerShot SX100 IS
+
+usb:v04A9p318E*
+ ID_MODEL_FROM_DATABASE=PowerShot A1000 IS
+
+usb:v04A9p318F*
+ ID_MODEL_FROM_DATABASE=PowerShot G10
+
+usb:v04A9p3191*
+ ID_MODEL_FROM_DATABASE=PowerShot A2000 IS
+
usb:v04A9p3192*
ID_MODEL_FROM_DATABASE=PowerShot SX110 IS
+usb:v04A9p3193*
+ ID_MODEL_FROM_DATABASE=PowerShot SD990 IS DIGITAL ELPH / Digital IXUS 980 IS / IXY DIGITAL 3000 IS
+
+usb:v04A9p3195*
+ ID_MODEL_FROM_DATABASE=PowerShot SX1 IS
+
+usb:v04A9p3196*
+ ID_MODEL_FROM_DATABASE=PowerShot SD880 IS DIGITAL ELPH / Digital IXUS 870 IS / IXY DIGITAL 920 IS
+
usb:v04A9p319A*
ID_MODEL_FROM_DATABASE=EOS 7D
@@ -10550,24 +10715,66 @@ usb:v04A9p31B1*
usb:v04A9p31BC*
ID_MODEL_FROM_DATABASE=PowerShot D10
+usb:v04A9p31BD*
+ ID_MODEL_FROM_DATABASE=PowerShot SD960 IS DIGITAL ELPH / Digital IXUS 110 IS / IXY DIGITAL 510 IS
+
+usb:v04A9p31BE*
+ ID_MODEL_FROM_DATABASE=PowerShot A2100 IS
+
usb:v04A9p31BF*
ID_MODEL_FROM_DATABASE=PowerShot A480
usb:v04A9p31C0*
ID_MODEL_FROM_DATABASE=PowerShot SX200 IS
+usb:v04A9p31C1*
+ ID_MODEL_FROM_DATABASE=PowerShot SD970 IS DIGITAL ELPH / Digital IXUS 990 IS / IXY DIGITAL 830 IS
+
+usb:v04A9p31C2*
+ ID_MODEL_FROM_DATABASE=PowerShot SD780 IS DIGITAL ELPH / Digital IXUS 100 IS / IXY DIGITAL 210 IS
+
+usb:v04A9p31C3*
+ ID_MODEL_FROM_DATABASE=PowerShot A1100 IS
+
+usb:v04A9p31C4*
+ ID_MODEL_FROM_DATABASE=PowerShot SD1200 IS DIGITAL ELPH / Digital IXUS 95 IS / IXY DIGITAL 110 IS
+
+usb:v04A9p31CF*
+ ID_MODEL_FROM_DATABASE=EOS Rebel T1i / EOS 500D / EOS Kiss X3
+
usb:v04A9p31DD*
ID_MODEL_FROM_DATABASE=SELPHY CP780
+usb:v04A9p31DF*
+ ID_MODEL_FROM_DATABASE=PowerShot G11
+
+usb:v04A9p31E0*
+ ID_MODEL_FROM_DATABASE=PowerShot SX120 IS
+
+usb:v04A9p31E1*
+ ID_MODEL_FROM_DATABASE=PowerShot S90
+
+usb:v04A9p31E4*
+ ID_MODEL_FROM_DATABASE=PowerShot SX20 IS
+
usb:v04A9p31E5*
ID_MODEL_FROM_DATABASE=Digital IXUS 200 IS
+usb:v04A9p31E6*
+ ID_MODEL_FROM_DATABASE=PowerShot SD940 IS DIGITAL ELPH / Digital IXUS 120 IS / IXY DIGITAL 220 IS
+
+usb:v04A9p31EA*
+ ID_MODEL_FROM_DATABASE=EOS Rebel T2i / EOS 550D / EOS Kiss X4
+
usb:v04A9p31EE*
ID_MODEL_FROM_DATABASE=SELPHY ES40
usb:v04A9p31EF*
ID_MODEL_FROM_DATABASE=PowerShot A495
+usb:v04A9p31F0*
+ ID_MODEL_FROM_DATABASE=PowerShot A490
+
usb:v04A9p31F1*
ID_MODEL_FROM_DATABASE=PowerShot A3100 IS / PowerShot A3150 IS
@@ -10598,6 +10805,9 @@ usb:v04A9p31FF*
usb:v04A9p3209*
ID_MODEL_FROM_DATABASE=Vixia HF S21 A
+usb:v04A9p320F*
+ ID_MODEL_FROM_DATABASE=PowerShot G12
+
usb:v04A9p3210*
ID_MODEL_FROM_DATABASE=Powershot SX30 IS
@@ -10619,9 +10829,15 @@ usb:v04A9p3223*
usb:v04A9p3224*
ID_MODEL_FROM_DATABASE=PowerShot A3200 IS
+usb:v04A9p3225*
+ ID_MODEL_FROM_DATABASE=PowerShot ELPH 500 HS / IXUS 310 HS
+
usb:v04A9p3226*
ID_MODEL_FROM_DATABASE=PowerShow A800
+usb:v04A9p3227*
+ ID_MODEL_FROM_DATABASE=PowerShot ELPH 100 HS / IXUS 115 HS
+
usb:v04A9p3228*
ID_MODEL_FROM_DATABASE=PowerShot SX230 HS
@@ -10634,6 +10850,9 @@ usb:v04A9p322A*
usb:v04A9p322B*
ID_MODEL_FROM_DATABASE=Powershot A1200
+usb:v04A9p322C*
+ ID_MODEL_FROM_DATABASE=PowerShot SX220 HS
+
usb:v04A9p3233*
ID_MODEL_FROM_DATABASE=PowerShot G1 X
@@ -10664,6 +10883,9 @@ usb:v04A9p3240*
usb:v04A9p3241*
ID_MODEL_FROM_DATABASE=PowerShot ELPH 110 HS / IXUS 125 HS
+usb:v04A9p3242*
+ ID_MODEL_FROM_DATABASE=PowerShot D20
+
usb:v04A9p3243*
ID_MODEL_FROM_DATABASE=PowerShot A4000 IS
@@ -10706,6 +10928,18 @@ usb:v04A9p325B*
usb:v04A9p325C*
ID_MODEL_FROM_DATABASE=PowerShot SX500 IS
+usb:v04A9p325F*
+ ID_MODEL_FROM_DATABASE=PowerShot SX280 HS
+
+usb:v04A9p3260*
+ ID_MODEL_FROM_DATABASE=PowerShot SX270 HS
+
+usb:v04A9p3264*
+ ID_MODEL_FROM_DATABASE=PowerShot A1400
+
+usb:v04A9p3268*
+ ID_MODEL_FROM_DATABASE=PowerShot ELPH 330 HS / IXUS 255 HS
+
usb:v04AA*
ID_VENDOR_FROM_DATABASE=DaeWoo Telecom, Ltd
@@ -10916,12 +11150,18 @@ usb:v04B0p041E*
usb:v04B0p0422*
ID_MODEL_FROM_DATABASE=D700 (ptp)
+usb:v04B0p0423*
+ ID_MODEL_FROM_DATABASE=D5000
+
usb:v04B0p0424*
ID_MODEL_FROM_DATABASE=D3000
usb:v04B0p0425*
ID_MODEL_FROM_DATABASE=D300S
+usb:v04B0p0428*
+ ID_MODEL_FROM_DATABASE=D7000
+
usb:v04B0p042A*
ID_MODEL_FROM_DATABASE=D800 (ptp)
@@ -11042,6 +11282,9 @@ usb:v04B4p0002*
usb:v04B4p0033*
ID_MODEL_FROM_DATABASE=Mouse
+usb:v04B4p0060*
+ ID_MODEL_FROM_DATABASE=Wireless optical mouse
+
usb:v04B4p0100*
ID_MODEL_FROM_DATABASE=Cino FuzzyScan F760-B
@@ -11996,6 +12239,9 @@ usb:v04C5p1042*
usb:v04C5p105B*
ID_MODEL_FROM_DATABASE=AH-F401U Air H device
+usb:v04C5p1084*
+ ID_MODEL_FROM_DATABASE=PalmSecure Sensor V2
+
usb:v04C5p1096*
ID_MODEL_FROM_DATABASE=fi-5110EOX
@@ -12065,6 +12311,9 @@ usb:v04CA*
usb:v04CAp1766*
ID_MODEL_FROM_DATABASE=HID Monitor Controls
+usb:v04CAp2004*
+ ID_MODEL_FROM_DATABASE=Bluetooth 4.0 [Broadcom BCM20702A0]
+
usb:v04CAp9304*
ID_MODEL_FROM_DATABASE=Hub
@@ -12500,6 +12749,9 @@ usb:v04D8p8101*
usb:v04D8p8107*
ID_MODEL_FROM_DATABASE=Microstick II
+usb:v04D8p9004*
+ ID_MODEL_FROM_DATABASE=Microchip REAL ICE
+
usb:v04D8p900A*
ID_MODEL_FROM_DATABASE=PICkit3
@@ -12563,6 +12815,9 @@ usb:v04D9p2221*
usb:v04D9p2323*
ID_MODEL_FROM_DATABASE=Keyboard
+usb:v04D9p2519*
+ ID_MODEL_FROM_DATABASE=Shenzhen LogoTech 2.4GHz receiver
+
usb:v04D9p2832*
ID_MODEL_FROM_DATABASE=1channel Telephone line recorder
@@ -12842,6 +13097,9 @@ usb:v04E1p0201*
usb:v04E2*
ID_VENDOR_FROM_DATABASE=Exar Corp.
+usb:v04E2p1410*
+ ID_MODEL_FROM_DATABASE=XR21V1410 USB-UART IC
+
usb:v04E3*
ID_VENDOR_FROM_DATABASE=Zilog, Inc.
@@ -13098,7 +13356,7 @@ usb:v04E8p0111*
ID_MODEL_FROM_DATABASE=Connect3D Flash Drive
usb:v04E8p0300*
- ID_MODEL_FROM_DATABASE=E2530 Phone (Mass storage mode)
+ ID_MODEL_FROM_DATABASE=E2530 / GT-C3350 Phones (Mass storage mode)
usb:v04E8p1003*
ID_MODEL_FROM_DATABASE=MP3 Player and Recorder
@@ -13508,12 +13766,18 @@ usb:v04E8p5F05*
usb:v04E8p6032*
ID_MODEL_FROM_DATABASE=G2 Portable hard drive
+usb:v04E8p6034*
+ ID_MODEL_FROM_DATABASE=G2 Portable hard drive
+
usb:v04E8p60B3*
ID_MODEL_FROM_DATABASE=M2 Portable Hard Drive
usb:v04E8p60C4*
ID_MODEL_FROM_DATABASE=M2 Portable Hard Drive USB 3.0
+usb:v04E8p61B6*
+ ID_MODEL_FROM_DATABASE=M3 Portable Hard Drive 1TB
+
usb:v04E8p6601*
ID_MODEL_FROM_DATABASE=Mobile Phone
@@ -13632,7 +13896,7 @@ usb:v04E8p685D*
ID_MODEL_FROM_DATABASE=GT-I9100 Phone [Galaxy S II] (Download mode)
usb:v04E8p685E*
- ID_MODEL_FROM_DATABASE=GT-I9100 Phone [Galaxy S II] (USB Debugging mode)
+ ID_MODEL_FROM_DATABASE=GT-I9100 / GT-C3350 Phones (USB Debugging mode)
usb:v04E8p6860*
ID_MODEL_FROM_DATABASE=GT-I9100 Phone [Galaxy S II], GT-I9300 Phone [Galaxy S III], GT-P7500 [Galaxy Tab 10.1]
@@ -13910,6 +14174,9 @@ usb:v04F2pB059*
usb:v04F2pB071*
ID_MODEL_FROM_DATABASE=2.0M UVC Webcam / CNF7129
+usb:v04F2pB083*
+ ID_MODEL_FROM_DATABASE=CKF7063 Webcam (HP)
+
usb:v04F2pB091*
ID_MODEL_FROM_DATABASE=Webcam
@@ -13943,6 +14210,9 @@ usb:v04F2pB1CF*
usb:v04F2pB1D6*
ID_MODEL_FROM_DATABASE=CNF9055 Toshiba Webcam
+usb:v04F2pB1E4*
+ ID_MODEL_FROM_DATABASE=Toshiba Integrated Webcam
+
usb:v04F2pB213*
ID_MODEL_FROM_DATABASE=Fujitsu Integrated Camera
@@ -13976,6 +14246,9 @@ usb:v04F2pB2EA*
usb:v04F2pB330*
ID_MODEL_FROM_DATABASE=Asus 720p CMOS webcam
+usb:v04F2pB354*
+ ID_MODEL_FROM_DATABASE=UVC 1.00 device HD UVC WebCam
+
usb:v04F3*
ID_VENDOR_FROM_DATABASE=Elan Microelectronics Corp.
@@ -14624,6 +14897,9 @@ usb:v04F9p201B*
usb:v04F9p2027*
ID_MODEL_FROM_DATABASE=QL-560 P-Touch Label Printer
+usb:v04F9p202B*
+ ID_MODEL_FROM_DATABASE=PT-7600 P-Touch Label Printer
+
usb:v04F9p2100*
ID_MODEL_FROM_DATABASE=Card Reader Writer
@@ -14777,6 +15053,9 @@ usb:v0502p3202*
usb:v0502p3203*
ID_MODEL_FROM_DATABASE=Liquid (Debug mode)
+usb:v0502p3230*
+ ID_MODEL_FROM_DATABASE=BeTouch E120
+
usb:v0502p3317*
ID_MODEL_FROM_DATABASE=Liquid
@@ -14987,6 +15266,9 @@ usb:v050Dp0307*
usb:v050Dp0409*
ID_MODEL_FROM_DATABASE=F5U409 Serial
+usb:v050Dp0416*
+ ID_MODEL_FROM_DATABASE=Staples 12416 7 port desktop hub
+
usb:v050Dp0551*
ID_MODEL_FROM_DATABASE=F6C550-AVR UPS
@@ -15294,7 +15576,7 @@ usb:v0525pA4A4*
ID_MODEL_FROM_DATABASE=Linux-USB user-mode bulk source/sink
usb:v0525pA4A5*
- ID_MODEL_FROM_DATABASE=Linux-USB File Storage Gadget
+ ID_MODEL_FROM_DATABASE=Pocketbook Pro 903
usb:v0525pA4A6*
ID_MODEL_FROM_DATABASE=Linux-USB Serial Gadget
@@ -15482,6 +15764,9 @@ usb:v053A*
usb:v053Ap0B00*
ID_MODEL_FROM_DATABASE=Hub
+usb:v053Ap0B01*
+ ID_MODEL_FROM_DATABASE=Preh MCI 3100
+
usb:v053B*
ID_VENDOR_FROM_DATABASE=Global Village Communication
@@ -15683,6 +15968,9 @@ usb:v0547p2750*
usb:v0547p2810*
ID_MODEL_FROM_DATABASE=Cypress ATAPI Bridge
+usb:v0547p4D90*
+ ID_MODEL_FROM_DATABASE=AmScope MD1900 camera
+
usb:v0547p7777*
ID_MODEL_FROM_DATABASE=Bluetooth Device
@@ -16022,6 +16310,9 @@ usb:v054Cp01D5*
usb:v054Cp01DE*
ID_MODEL_FROM_DATABASE=VRD-VC10 [Video Capture]
+usb:v054Cp01E8*
+ ID_MODEL_FROM_DATABASE=UP-DR150 Photo Printer
+
usb:v054Cp01E9*
ID_MODEL_FROM_DATABASE=Net MD
@@ -16358,6 +16649,9 @@ usb:v0557p7000*
usb:v0557p7820*
ID_MODEL_FROM_DATABASE=UC-2322 2xSerial Ports [mos7820]
+usb:v0557p8021*
+ ID_MODEL_FROM_DATABASE=CS1764A [CubiQ DVI KVMP Switch]
+
usb:v0558*
ID_VENDOR_FROM_DATABASE=Truevision, Inc.
@@ -16904,6 +17198,9 @@ usb:v056Ap00DB*
usb:v056Ap00DD*
ID_MODEL_FROM_DATABASE=Bamboo Pen (CTL-470)
+usb:v056Ap00DE*
+ ID_MODEL_FROM_DATABASE=CTH-470 [Bamboo Fun Pen & Touch]
+
usb:v056Ap00F6*
ID_MODEL_FROM_DATABASE=Cintiq 24HD touch (DTH-2400) touchscreen
@@ -18686,6 +18983,9 @@ usb:v059Fp0421*
usb:v059Fp0641*
ID_MODEL_FROM_DATABASE=Mobile Hard Drive
+usb:v059Fp100C*
+ ID_MODEL_FROM_DATABASE=Rugged Triple Interface Mobile Hard Drive
+
usb:v059Fp1010*
ID_MODEL_FROM_DATABASE=Desktop Hard Drive
@@ -18749,6 +19049,12 @@ usb:v05A4p9731*
usb:v05A4p9783*
ID_MODEL_FROM_DATABASE=Wireless Keypad
+usb:v05A4p9837*
+ ID_MODEL_FROM_DATABASE=Targus Number Keypad
+
+usb:v05A4p9862*
+ ID_MODEL_FROM_DATABASE=Targus Number Keypad (Composite Device)
+
usb:v05A4p9881*
ID_MODEL_FROM_DATABASE=IR receiver [VRC-1100 Vista MCE Remote Control]
@@ -19097,6 +19403,9 @@ usb:v05ACp1105*
usb:v05ACp1107*
ID_MODEL_FROM_DATABASE=Thunderbolt Display Audio
+usb:v05ACp1112*
+ ID_MODEL_FROM_DATABASE=FaceTime HD Camera (Display)
+
usb:v05ACp1201*
ID_MODEL_FROM_DATABASE=3G iPod
@@ -19304,6 +19613,9 @@ usb:v05ACp8241*
usb:v05ACp8242*
ID_MODEL_FROM_DATABASE=Built-in IR Receiver
+usb:v05ACp8281*
+ ID_MODEL_FROM_DATABASE=Bluetooth Host Controller
+
usb:v05ACp8286*
ID_MODEL_FROM_DATABASE=Bluetooth Host Controller
@@ -20672,6 +20984,9 @@ usb:v05E3p0726*
usb:v05E3p0727*
ID_MODEL_FROM_DATABASE=microSD Reader/Writer
+usb:v05E3p0731*
+ ID_MODEL_FROM_DATABASE=GL3310 SATA 3Gb/s Bridge Controller
+
usb:v05E3p0736*
ID_MODEL_FROM_DATABASE=microSD Reader/Writer
@@ -20825,9 +21140,15 @@ usb:v05F9*
usb:v05F9p1104*
ID_MODEL_FROM_DATABASE=Magellan 2200VS
+usb:v05F9p2202*
+ ID_MODEL_FROM_DATABASE=Point of Sale Handheld Scanner
+
usb:v05F9p2206*
ID_MODEL_FROM_DATABASE=Datalogic Gryphon GFS4170
+usb:v05F9p2601*
+ ID_MODEL_FROM_DATABASE=Datalogin Magellan 1000i Barcode Scanner
+
usb:v05F9p2602*
ID_MODEL_FROM_DATABASE=Datalogic Magellan 1100i Barcode Scanner
@@ -21137,6 +21458,15 @@ usb:v0623*
usb:v0624*
ID_VENDOR_FROM_DATABASE=Avocent Corp.
+usb:v0624p0248*
+ ID_MODEL_FROM_DATABASE=Virtual Hub
+
+usb:v0624p0249*
+ ID_MODEL_FROM_DATABASE=Virtual Keyboard/Mouse
+
+usb:v0624p0251*
+ ID_MODEL_FROM_DATABASE=Virtual Mass Storage
+
usb:v0624p0294*
ID_MODEL_FROM_DATABASE=Dell 03R874 KVM dongle
@@ -21311,6 +21641,9 @@ usb:v0644p800D*
usb:v0644p800E*
ID_MODEL_FROM_DATABASE=TASCAM US-122L
+usb:v0644p801D*
+ ID_MODEL_FROM_DATABASE=DR-100
+
usb:v0644p8021*
ID_MODEL_FROM_DATABASE=TASCAM US-122mkII
@@ -21407,6 +21740,9 @@ usb:v064EpC107*
usb:v064EpD101*
ID_MODEL_FROM_DATABASE=Acer CrystalEye Webcam
+usb:v064EpD217*
+ ID_MODEL_FROM_DATABASE=HP TrueVision HD
+
usb:v064EpE201*
ID_MODEL_FROM_DATABASE=Lenovo Integrated Webcam
@@ -21489,7 +21825,7 @@ usb:v065A*
ID_VENDOR_FROM_DATABASE=Optoelectronics Co., Ltd
usb:v065Ap0001*
- ID_MODEL_FROM_DATABASE=Barcode scanner / NLV-1001 (keyboard mode)
+ ID_MODEL_FROM_DATABASE=Opticon OPR-2001 / NLV-1001 (keyboard mode)
usb:v065Ap0009*
ID_MODEL_FROM_DATABASE=NLV-1001 (serial mode) / OPN-2001 [Opticon]
@@ -22070,6 +22406,9 @@ usb:v067Bp2528*
usb:v067Bp25A1*
ID_MODEL_FROM_DATABASE=PL25A1 Host-Host Bridge
+usb:v067Bp2773*
+ ID_MODEL_FROM_DATABASE=PL2773 SATAII bridge controller
+
usb:v067Bp3400*
ID_MODEL_FROM_DATABASE=Hi-Speed Flash Disk with TruePrint AES3400
@@ -22862,6 +23201,21 @@ usb:v06BCp000B*
usb:v06BCp0027*
ID_MODEL_FROM_DATABASE=Okipage 14e
+usb:v06BCp00F7*
+ ID_MODEL_FROM_DATABASE=OKI B4600 Mono Printer
+
+usb:v06BCp015E*
+ ID_MODEL_FROM_DATABASE=OKIPOS 411/412 POS Printer
+
+usb:v06BCp01C9*
+ ID_MODEL_FROM_DATABASE=OKI B430 Mono Printer
+
+usb:v06BCp020B*
+ ID_MODEL_FROM_DATABASE=OKI ES4140 Mono Printer
+
+usb:v06BCp02BB*
+ ID_MODEL_FROM_DATABASE=OKI PT390 POS Printer
+
usb:v06BCp0A91*
ID_MODEL_FROM_DATABASE=B2500MFP (printer+scanner)
@@ -23222,6 +23576,9 @@ usb:v06D1*
usb:v06D3*
ID_VENDOR_FROM_DATABASE=Mitsubishi Electric Corp.
+usb:v06D3p0284*
+ ID_MODEL_FROM_DATABASE=FX-USB-AW/-BD RS482 Converters
+
usb:v06D3p0380*
ID_MODEL_FROM_DATABASE=CP8000D Port
@@ -23339,6 +23696,9 @@ usb:v06DE*
usb:v06E0*
ID_VENDOR_FROM_DATABASE=Multi-Tech Systems, Inc.
+usb:v06E0p0319*
+ ID_MODEL_FROM_DATABASE=MT9234ZBA-USB MultiModem ZBA
+
usb:v06E0pF101*
ID_MODEL_FROM_DATABASE=MT5634ZBA-USB MultiModemUSB (old firmware)
@@ -23351,6 +23711,9 @@ usb:v06E0pF104*
usb:v06E0pF107*
ID_MODEL_FROM_DATABASE=MT5634ZBA-USB-V92 MultiModemUSB
+usb:v06E0pF120*
+ ID_MODEL_FROM_DATABASE=MT9234ZBA-USB-CDC-ACM-XR MultiModem ZBA CDC-ACM-XR
+
usb:v06E1*
ID_VENDOR_FROM_DATABASE=ADS Technologies, Inc.
@@ -25154,6 +25517,12 @@ usb:v0798*
usb:v0798p0001*
ID_MODEL_FROM_DATABASE=Braille Voyager
+usb:v0798p0640*
+ ID_MODEL_FROM_DATABASE=BC640
+
+usb:v0798p0680*
+ ID_MODEL_FROM_DATABASE=BC680
+
usb:v0799*
ID_VENDOR_FROM_DATABASE=Altera
@@ -25163,6 +25532,12 @@ usb:v0799p7651*
usb:v079B*
ID_VENDOR_FROM_DATABASE=Sagem
+usb:v079Bp0024*
+ ID_MODEL_FROM_DATABASE=MSO300/MSO301 Fingerprint Sensor
+
+usb:v079Bp0026*
+ ID_MODEL_FROM_DATABASE=MSO350/MSO351 Fingerprint Sensor & SmartCard Reader
+
usb:v079Bp0027*
ID_MODEL_FROM_DATABASE=USB-Serial Controller
@@ -25175,12 +25550,18 @@ usb:v079Bp0030*
usb:v079Bp0042*
ID_MODEL_FROM_DATABASE=Mobile
+usb:v079Bp0047*
+ ID_MODEL_FROM_DATABASE=CBM/MSO1300 Fingerprint Sensor
+
usb:v079Bp004A*
ID_MODEL_FROM_DATABASE=XG-760A 802.11bg
usb:v079Bp004B*
ID_MODEL_FROM_DATABASE=Wi-Fi 11g adapter
+usb:v079Bp0052*
+ ID_MODEL_FROM_DATABASE=MSO1350 Fingerprint Sensor & SmartCard Reader
+
usb:v079Bp0056*
ID_MODEL_FROM_DATABASE=Agfa AP1100 Photo Printer
@@ -25553,6 +25934,9 @@ usb:v07B4p0118*
usb:v07B4p0184*
ID_MODEL_FROM_DATABASE=P-S100 port
+usb:v07B4p0202*
+ ID_MODEL_FROM_DATABASE=Foot Switch RS-26
+
usb:v07B4p0203*
ID_MODEL_FROM_DATABASE=Digital Voice Recorder DW-90
@@ -25565,12 +25949,24 @@ usb:v07B4p0207*
usb:v07B4p0209*
ID_MODEL_FROM_DATABASE=Digital Voice Recorder DM-20
+usb:v07B4p020B*
+ ID_MODEL_FROM_DATABASE=Digital Voice Recorder DS-4000
+
usb:v07B4p020D*
ID_MODEL_FROM_DATABASE=Digital Voice Recorder VN-240PC
+usb:v07B4p0211*
+ ID_MODEL_FROM_DATABASE=Digital Voice Recorder DS-2300
+
+usb:v07B4p0218*
+ ID_MODEL_FROM_DATABASE=Foot Switch RS-28
+
usb:v07B4p0244*
ID_MODEL_FROM_DATABASE=Digital Voice Recorder VN-8500PC
+usb:v07B4p024F*
+ ID_MODEL_FROM_DATABASE=Digital Voice Recorder DS-7000
+
usb:v07B4p0280*
ID_MODEL_FROM_DATABASE=m:robe 100
@@ -25664,6 +26060,9 @@ usb:v07B8p5301*
usb:v07B8p6001*
ID_MODEL_FROM_DATABASE=802.11bg
+usb:v07B8p8188*
+ ID_MODEL_FROM_DATABASE=AboCom Systems Inc [WN2001 Prolink Wireless-N Nano Adapter]
+
usb:v07B8pA001*
ID_MODEL_FROM_DATABASE=WUG2200 802.11g Wireless Adapter [Envara WiND512]
@@ -27071,6 +27470,9 @@ usb:v0846p1020*
usb:v0846p1040*
ID_MODEL_FROM_DATABASE=FA120 Fast Ethernet USB 2.0 [Asix AX88172 / AX8817x]
+usb:v0846p1100*
+ ID_MODEL_FROM_DATABASE=Managed Switch M4100 series, M5300 series, M7100 series
+
usb:v0846p4110*
ID_MODEL_FROM_DATABASE=MA111(v1) 802.11b Wireless [Intersil Prism 3.0]
@@ -27945,7 +28347,7 @@ usb:v08E5*
ID_VENDOR_FROM_DATABASE=Litronic
usb:v08E6*
- ID_VENDOR_FROM_DATABASE=Gemplus
+ ID_VENDOR_FROM_DATABASE=Gemalto (was Gemplus)
usb:v08E6p0001*
ID_MODEL_FROM_DATABASE=GemPC-Touch 430
@@ -27986,6 +28388,9 @@ usb:v08E6p4433*
usb:v08E6p5501*
ID_MODEL_FROM_DATABASE=GemProx-PU Contactless Smart Card Reader
+usb:v08E6p5503*
+ ID_MODEL_FROM_DATABASE=Prox-DU Contactless Interface
+
usb:v08E6pACE0*
ID_MODEL_FROM_DATABASE=UA HYBRID TOKEN
@@ -28901,6 +29306,9 @@ usb:v0930p0B05*
usb:v0930p0B09*
ID_MODEL_FROM_DATABASE=PX1396E-3T01 External hard drive
+usb:v0930p0B1A*
+ ID_MODEL_FROM_DATABASE=STOR.E ALU 2S
+
usb:v0930p1300*
ID_MODEL_FROM_DATABASE=Wireless Broadband (CDMA EV-DO) SM-Bus Minicard Status Port
@@ -29087,6 +29495,9 @@ usb:v0934*
usb:v0936*
ID_VENDOR_FROM_DATABASE=NuTesla
+usb:v0936p000C*
+ ID_MODEL_FROM_DATABASE=Rhythmedics 6 BioData Integrator
+
usb:v0936p0030*
ID_MODEL_FROM_DATABASE=Composite Device, Mass Storage Device (Flash Drive) amd HID
@@ -29135,6 +29546,9 @@ usb:v093Ap2500*
usb:v093Ap2510*
ID_MODEL_FROM_DATABASE=Optical Mouse
+usb:v093Ap2521*
+ ID_MODEL_FROM_DATABASE=Optical Mouse
+
usb:v093Ap2600*
ID_MODEL_FROM_DATABASE=Typhoon Easycam USB 330K (newer)/Typhoon Easycam USB 2.0 VGA 1.3M/Sansun SN-508
@@ -29375,6 +29789,15 @@ usb:v0955p7030*
usb:v0955p7100*
ID_MODEL_FROM_DATABASE=Notion Ink Adam
+usb:v0955p7820*
+ ID_MODEL_FROM_DATABASE=Tegra 2 AC100 developer mode
+
+usb:v0955pB400*
+ ID_MODEL_FROM_DATABASE=SHIELD (debug)
+
+usb:v0955pB401*
+ ID_MODEL_FROM_DATABASE=SHIELD
+
usb:v0956*
ID_VENDOR_FROM_DATABASE=BSquare Corp.
@@ -29483,6 +29906,9 @@ usb:v0978*
usb:v0979*
ID_VENDOR_FROM_DATABASE=Jeilin Technology Corp., Ltd
+usb:v0979p0222*
+ ID_MODEL_FROM_DATABASE=Keychain Display
+
usb:v0979p0224*
ID_MODEL_FROM_DATABASE=JL2005A Toy Camera
@@ -29816,8 +30242,11 @@ usb:v09DAp8090*
usb:v09DAp9033*
ID_MODEL_FROM_DATABASE=X-718BK Optical Mouse
+usb:v09DAp9066*
+ ID_MODEL_FROM_DATABASE=F3 V-Track Gaming Mouse
+
usb:v09DAp9090*
- ID_MODEL_FROM_DATABASE=XL-750BK Laser Mouse
+ ID_MODEL_FROM_DATABASE=XL-730K / XL-750BK / XL-755BK Mice
usb:v09DB*
ID_VENDOR_FROM_DATABASE=Measurement Computing Corp.
@@ -30626,6 +31055,9 @@ usb:v0A5Fp0081*
usb:v0A5Fp008B*
ID_MODEL_FROM_DATABASE=HC100 wristbands Printer
+usb:v0A5Fp00D1*
+ ID_MODEL_FROM_DATABASE=Zebra GC420d Label Printer
+
usb:v0A5Fp930A*
ID_MODEL_FROM_DATABASE=Printer
@@ -31157,6 +31589,9 @@ usb:v0AC8pC326*
usb:v0AC8pC33F*
ID_MODEL_FROM_DATABASE=Webcam
+usb:v0AC8pC429*
+ ID_MODEL_FROM_DATABASE=Lenovo ThinkCentre Web Camera
+
usb:v0AC9*
ID_VENDOR_FROM_DATABASE=Micro Solutions, Inc.
@@ -31202,6 +31637,9 @@ usb:v0ACDp0401*
usb:v0ACDp0630*
ID_MODEL_FROM_DATABASE=Spectrum III Mag-Only Insert Reader (SPT3-355 Series) USB-CDC
+usb:v0ACDp0810*
+ ID_MODEL_FROM_DATABASE=SecurePIN (IDPA-506100Y) PIN Pad
+
usb:v0ACE*
ID_VENDOR_FROM_DATABASE=ZyDAS
@@ -31604,12 +32042,18 @@ usb:v0B0Dp0000*
usb:v0B0E*
ID_VENDOR_FROM_DATABASE=GN Netcom
+usb:v0B0Ep0420*
+ ID_MODEL_FROM_DATABASE=Jabra SPEAK 510
+
usb:v0B0Ep1022*
ID_MODEL_FROM_DATABASE=Jabra PRO 9450, Type 9400BS (DECT Headset)
usb:v0B0Ep620C*
ID_MODEL_FROM_DATABASE=Jabra BT620s
+usb:v0B0Ep9330*
+ ID_MODEL_FROM_DATABASE=Jabra GN9330 Headset
+
usb:v0B0F*
ID_VENDOR_FROM_DATABASE=AVID Technology
@@ -31913,6 +32357,18 @@ usb:v0B64*
usb:v0B65*
ID_VENDOR_FROM_DATABASE=Expert Magnetics Corp.
+usb:v0B66*
+ ID_VENDOR_FROM_DATABASE=Cybiko Inc.
+
+usb:v0B66p0041*
+ ID_MODEL_FROM_DATABASE=Xtreme
+
+usb:v0B67*
+ ID_VENDOR_FROM_DATABASE=Fairbanks Scales
+
+usb:v0B67p555E*
+ ID_MODEL_FROM_DATABASE=SCB-R9000
+
usb:v0B69*
ID_VENDOR_FROM_DATABASE=CacheVision
@@ -32421,7 +32877,7 @@ usb:v0BB4p0A4F*
ID_MODEL_FROM_DATABASE=PocketPC Sync
usb:v0BB4p0A50*
- ID_MODEL_FROM_DATABASE=HTC SmartPhone Sync
+ ID_MODEL_FROM_DATABASE=SmartPhone (MTP)
usb:v0BB4p0A51*
ID_MODEL_FROM_DATABASE=SPV C400 / T-Mobile SDA GSM/GPRS Pocket PC
@@ -32789,6 +33245,9 @@ usb:v0BC2p0503*
usb:v0BC2p2000*
ID_MODEL_FROM_DATABASE=Storage Adapter V3 (TPP)
+usb:v0BC2p2100*
+ ID_MODEL_FROM_DATABASE=FreeAgent Go
+
usb:v0BC2p2200*
ID_MODEL_FROM_DATABASE=FreeAgent Go FW
@@ -32798,6 +33257,9 @@ usb:v0BC2p2300*
usb:v0BC2p2320*
ID_MODEL_FROM_DATABASE=USB 3.0 bridge [Portable Expansion Drive]
+usb:v0BC2p3008*
+ ID_MODEL_FROM_DATABASE=FreeAgent Desk 1TB
+
usb:v0BC2p3320*
ID_MODEL_FROM_DATABASE=SRD00F2 [Expansion Desktop Drive]
@@ -32825,6 +33287,12 @@ usb:v0BC2p5161*
usb:v0BC2pA003*
ID_MODEL_FROM_DATABASE=Backup Plus
+usb:v0BC2pA0A1*
+ ID_MODEL_FROM_DATABASE=Backup Plus Desktop
+
+usb:v0BC2pA0A4*
+ ID_MODEL_FROM_DATABASE=Backup Plus Desktop Drive
+
usb:v0BC3*
ID_VENDOR_FROM_DATABASE=IPWireless, Inc.
@@ -33029,6 +33497,9 @@ usb:v0BDAp8176*
usb:v0BDAp8178*
ID_MODEL_FROM_DATABASE=RTL8192CU 802.11n WLAN Adapter
+usb:v0BDAp8179*
+ ID_MODEL_FROM_DATABASE=RTL8188EUS 802.11n Wireless Network Adapter
+
usb:v0BDAp817F*
ID_MODEL_FROM_DATABASE=RTL8188RU 802.11n WLAN Adapter
@@ -33185,6 +33656,9 @@ usb:v0BF8p100C*
usb:v0BF8p100F*
ID_MODEL_FROM_DATABASE=miniCard D2301 802.11bg Wireless Module [SiS 163U]
+usb:v0BF8p1017*
+ ID_MODEL_FROM_DATABASE=Keyboard KB SCR
+
usb:v0BFD*
ID_VENDOR_FROM_DATABASE=Kvaser AB
@@ -33414,7 +33888,7 @@ usb:v0C2Ep0007*
ID_MODEL_FROM_DATABASE=Metrologic MS7120 Barcode Scanner (IBM SurePOS mode)
usb:v0C2Ep0200*
- ID_MODEL_FROM_DATABASE=Metrologic Scanner
+ ID_MODEL_FROM_DATABASE=MS7120 Barcode Scanner
usb:v0C2Ep0204*
ID_MODEL_FROM_DATABASE=Metrologic MS7120 Barcode Scanner (keyboard mode)
@@ -33842,6 +34316,9 @@ usb:v0C45p62E0*
usb:v0C45p6310*
ID_MODEL_FROM_DATABASE=Sonix USB 2.0 Camera
+usb:v0C45p6341*
+ ID_MODEL_FROM_DATABASE=Defender G-Lens 2577 HD720p Camera
+
usb:v0C45p63E0*
ID_MODEL_FROM_DATABASE=Sonix Integrated Webcam
@@ -33860,6 +34337,9 @@ usb:v0C45p6413*
usb:v0C45p6417*
ID_MODEL_FROM_DATABASE=Integrated Webcam
+usb:v0C45p6419*
+ ID_MODEL_FROM_DATABASE=Integrated Webcam
+
usb:v0C45p641D*
ID_MODEL_FROM_DATABASE=1.3 MPixel Integrated Webcam
@@ -34553,6 +35033,9 @@ usb:v0CCDp00A9*
usb:v0CCDp00B3*
ID_MODEL_FROM_DATABASE=NOXON DAB/DAB+ Stick
+usb:v0CCDp00E0*
+ ID_MODEL_FROM_DATABASE=NOXON DAB/DAB+ Stick V2
+
usb:v0CCDp10A7*
ID_MODEL_FROM_DATABASE=TerraTec G3
@@ -34707,7 +35190,7 @@ usb:v0CF3p1001*
ID_MODEL_FROM_DATABASE=Thomson TG121N [Atheros AR9001U-(2)NG]
usb:v0CF3p1002*
- ID_MODEL_FROM_DATABASE=TP-Link TL-WN821N v2 802.11n [Atheros AR9170]
+ ID_MODEL_FROM_DATABASE=TP-Link TL-WN821N v2 / TL-WN822N v1 802.11n [Atheros AR9170]
usb:v0CF3p1006*
ID_MODEL_FROM_DATABASE=TP-Link TL-WN322G v3 / TL-WN422G v2 802.11g [Atheros AR9271]
@@ -34731,7 +35214,7 @@ usb:v0CF3p3008*
ID_MODEL_FROM_DATABASE=Bluetooth (AR3011)
usb:v0CF3p7015*
- ID_MODEL_FROM_DATABASE=TP-Link TL-WN821N v3 802.11n [Atheros AR7010+AR9287]
+ ID_MODEL_FROM_DATABASE=TP-Link TL-WN821N v3 / TL-WN822N v2 802.11n [Atheros AR7010+AR9287]
usb:v0CF3p9170*
ID_MODEL_FROM_DATABASE=AR9170 802.11n
@@ -35024,6 +35507,9 @@ usb:v0D50*
usb:v0D50p0011*
ID_MODEL_FROM_DATABASE=USB-Temp2 Thermometer
+usb:v0D50p0040*
+ ID_MODEL_FROM_DATABASE=F4 foot switch
+
usb:v0D51*
ID_VENDOR_FROM_DATABASE=Volex (Asia) Pte., Ltd
@@ -36578,6 +37064,9 @@ usb:v0E79p1416*
usb:v0E79p1417*
ID_MODEL_FROM_DATABASE=A43 IT
+usb:v0E79p14AD*
+ ID_MODEL_FROM_DATABASE=97 Titanium HD
+
usb:v0E79p150E*
ID_MODEL_FROM_DATABASE=80 G9
@@ -37133,6 +37622,9 @@ usb:v0F53*
usb:v0F54*
ID_VENDOR_FROM_DATABASE=Kawai Musical Instruments Mfg. Co., Ltd
+usb:v0F54p0101*
+ ID_MODEL_FROM_DATABASE=MP6 Stage Piano
+
usb:v0F55*
ID_VENDOR_FROM_DATABASE=AmbiCom, Inc.
@@ -37427,6 +37919,9 @@ usb:v0FCEp015A*
usb:v0FCEp0166*
ID_MODEL_FROM_DATABASE=Xperia Mini Pro
+usb:v0FCEp0167*
+ ID_MODEL_FROM_DATABASE=ST15i (Xperia mini)
+
usb:v0FCEp0169*
ID_MODEL_FROM_DATABASE=Xperia S
@@ -37472,15 +37967,24 @@ usb:v0FCEp3149*
usb:v0FCEp5177*
ID_MODEL_FROM_DATABASE=Xperia Ion [Debug Mode]
+usb:v0FCEp518C*
+ ID_MODEL_FROM_DATABASE=C1605 [Xperia E dual] MTD mode
+
usb:v0FCEp614F*
ID_MODEL_FROM_DATABASE=Xperia X12 (debug mode)
usb:v0FCEp6166*
ID_MODEL_FROM_DATABASE=Xperia Mini Pro
+usb:v0FCEp618C*
+ ID_MODEL_FROM_DATABASE=C1605 [Xperia E dual] MSC mode
+
usb:v0FCEp715A*
ID_MODEL_FROM_DATABASE=Xperia Pro [Tethering]
+usb:v0FCEp7166*
+ ID_MODEL_FROM_DATABASE=Xperia Mini Pro (Tethering mode)
+
usb:v0FCEp7177*
ID_MODEL_FROM_DATABASE=Xperia Ion [Tethering]
@@ -37643,6 +38147,12 @@ usb:v0FD0*
usb:v0FD1*
ID_VENDOR_FROM_DATABASE=Giant Electronics Ltd.
+usb:v0FD2*
+ ID_VENDOR_FROM_DATABASE=Seac Banche
+
+usb:v0FD2p0001*
+ ID_MODEL_FROM_DATABASE=RDS 6000
+
usb:v0FD4*
ID_VENDOR_FROM_DATABASE=Tenovis GmbH & Co., KG
@@ -37811,9 +38321,30 @@ usb:v1004p61C6*
usb:v1004p61CC*
ID_MODEL_FROM_DATABASE=Optimus S
+usb:v1004p61F1*
+ ID_MODEL_FROM_DATABASE=Optimus Android Phone [LG Software mode]
+
+usb:v1004p61F9*
+ ID_MODEL_FROM_DATABASE=V909 G-Slate
+
usb:v1004p61FC*
ID_MODEL_FROM_DATABASE=Optimus 3
+usb:v1004p61FE*
+ ID_MODEL_FROM_DATABASE=Optimus Android Phone [USB tethering mode]
+
+usb:v1004p6300*
+ ID_MODEL_FROM_DATABASE=Optimus Android Phone
+
+usb:v1004p631C*
+ ID_MODEL_FROM_DATABASE=Optimus Android Phone [MTP mode]
+
+usb:v1004p631E*
+ ID_MODEL_FROM_DATABASE=Optimus Android Phone [Camera/PTP mode]
+
+usb:v1004p6356*
+ ID_MODEL_FROM_DATABASE=Optimus Android Phone [Virtual CD mode]
+
usb:v1004p6800*
ID_MODEL_FROM_DATABASE=CDMA Modem
@@ -38027,6 +38558,9 @@ usb:v1038*
usb:v1038p0100*
ID_MODEL_FROM_DATABASE=Zboard
+usb:v1038p1361*
+ ID_MODEL_FROM_DATABASE=Sensei
+
usb:v1039*
ID_VENDOR_FROM_DATABASE=devolo AG
@@ -38174,6 +38708,15 @@ usb:v1050*
usb:v1050p0010*
ID_MODEL_FROM_DATABASE=Yubikey
+usb:v1050p0110*
+ ID_MODEL_FROM_DATABASE=Yubikey NEO OTP
+
+usb:v1050p0111*
+ ID_MODEL_FROM_DATABASE=Yubikey NEO OTP+CCID
+
+usb:v1050p0211*
+ ID_MODEL_FROM_DATABASE=Gnubby
+
usb:v1053*
ID_VENDOR_FROM_DATABASE=Immanuel Electronics Co., Ltd
@@ -38217,7 +38760,10 @@ usb:v1058p070A*
ID_MODEL_FROM_DATABASE=My Passport Essential SE
usb:v1058p071A*
- ID_MODEL_FROM_DATABASE=My Passport 1TB
+ ID_MODEL_FROM_DATABASE=My Passport
+
+usb:v1058p0730*
+ ID_MODEL_FROM_DATABASE=My Passport
usb:v1058p0740*
ID_MODEL_FROM_DATABASE=My Passport
@@ -38573,6 +39119,9 @@ usb:v1082*
usb:v1083*
ID_VENDOR_FROM_DATABASE=Canon Electronics, Inc.
+usb:v1083p161B*
+ ID_MODEL_FROM_DATABASE=DR-2010C Scanner
+
usb:v1083p162C*
ID_MODEL_FROM_DATABASE=P-150 Scanner
@@ -38786,6 +39335,9 @@ usb:v10C4p87BE*
usb:v10C4p8863*
ID_MODEL_FROM_DATABASE=C8051F34x Bootloader
+usb:v10C4p8897*
+ ID_MODEL_FROM_DATABASE=C8051F38x HDMI Splitter [UHBX]
+
usb:v10C4pEA60*
ID_MODEL_FROM_DATABASE=CP210x UART Bridge / myAVR mySmartUSB light
@@ -38822,6 +39374,9 @@ usb:v10CD*
usb:v10CE*
ID_VENDOR_FROM_DATABASE=Silicon Labs
+usb:v10CEp000E*
+ ID_MODEL_FROM_DATABASE=Shinko/Sinfonia CHC-S2145
+
usb:v10CEpEA6A*
ID_MODEL_FROM_DATABASE=MobiData EDGE USB Modem
@@ -38861,6 +39416,9 @@ usb:v10D4*
usb:v10D5*
ID_VENDOR_FROM_DATABASE=Uni Class Technology Co., Ltd
+usb:v10D5p0004*
+ ID_MODEL_FROM_DATABASE=PS/2 Converter
+
usb:v10D5p5552*
ID_MODEL_FROM_DATABASE=KVM Human Interface Composite Device (Keyboard/Mouse ports)
@@ -39578,6 +40136,9 @@ usb:v120Fp5260*
usb:v1210*
ID_VENDOR_FROM_DATABASE=DigiTech
+usb:v1210p0016*
+ ID_MODEL_FROM_DATABASE=RP500 Guitar Multi-Effects Processor
+
usb:v1210p001B*
ID_MODEL_FROM_DATABASE=RP155 Guitar Multi-Effects Processor
@@ -39593,6 +40154,15 @@ usb:v121Ep3403*
usb:v1223*
ID_VENDOR_FROM_DATABASE=SKYCABLE ENTERPRISE. CO., LTD.
+usb:v1228*
+ ID_VENDOR_FROM_DATABASE=Datapaq Limited
+
+usb:v1228p0012*
+ ID_MODEL_FROM_DATABASE=Q18 Data Logger
+
+usb:v1228p0015*
+ ID_MODEL_FROM_DATABASE=TPaq21/MPaq21 Datalogger
+
usb:v1230*
ID_VENDOR_FROM_DATABASE=Chipidea-Microelectronica, S.A.
@@ -40037,6 +40607,9 @@ usb:v12D1p14C8*
usb:v12D1p14C9*
ID_MODEL_FROM_DATABASE=K3770 3G Modem
+usb:v12D1p14CF*
+ ID_MODEL_FROM_DATABASE=K3772
+
usb:v12D1p14D1*
ID_MODEL_FROM_DATABASE=K3770 3G Modem (Mass Storage Mode)
@@ -40050,7 +40623,7 @@ usb:v12D1p1505*
ID_MODEL_FROM_DATABASE=E398 LTE/UMTS/GSM Modem/Networkcard
usb:v12D1p1506*
- ID_MODEL_FROM_DATABASE=E398 LTE/UMTS/GSM Modem/Networkcard
+ ID_MODEL_FROM_DATABASE=Modem/Networkcard
usb:v12D1p150A*
ID_MODEL_FROM_DATABASE=E398 LTE/UMTS/GSM Modem/Networkcard
@@ -40061,6 +40634,9 @@ usb:v12D1p1520*
usb:v12D1p1521*
ID_MODEL_FROM_DATABASE=K4505 HSPA+
+usb:v12D1p155A*
+ ID_MODEL_FROM_DATABASE=R205 Mobile WiFi (CD-ROM mode)
+
usb:v12D1p1805*
ID_MODEL_FROM_DATABASE=AT&T Go Phone U2800A phone
@@ -40070,6 +40646,9 @@ usb:v12D1p1C05*
usb:v12D1p1C0B*
ID_MODEL_FROM_DATABASE=E173s 3G broadband stick (modem off)
+usb:v12D1p1C20*
+ ID_MODEL_FROM_DATABASE=R205 Mobile WiFi (Charging)
+
usb:v12D1p1D50*
ID_MODEL_FROM_DATABASE=ET302s TD-SCDMA/TD-HSDPA Mobile Broadband
@@ -40475,6 +41054,9 @@ usb:v138Ap0018*
usb:v138Ap003C*
ID_MODEL_FROM_DATABASE=VFS471 Fingerprint Reader
+usb:v138Ap003D*
+ ID_MODEL_FROM_DATABASE=VFS491
+
usb:v138E*
ID_VENDOR_FROM_DATABASE=Jungo LTD
@@ -40916,6 +41498,15 @@ usb:v1403*
usb:v1403p0001*
ID_MODEL_FROM_DATABASE=Digital Photo Frame
+usb:v1409*
+ ID_VENDOR_FROM_DATABASE=IDS Imaging Development Systems GmbH
+
+usb:v1409p1000*
+ ID_MODEL_FROM_DATABASE=generic (firmware not loaded yet)
+
+usb:v1409p1485*
+ ID_MODEL_FROM_DATABASE=uEye UI1485
+
usb:v140E*
ID_VENDOR_FROM_DATABASE=Telechips, Inc.
@@ -41069,6 +41660,9 @@ usb:v1446*
usb:v1446p6A73*
ID_MODEL_FROM_DATABASE=Stamps.com Model 510 5LB Scale
+usb:v1446p6A78*
+ ID_MODEL_FROM_DATABASE=DYMO Endicia 75lb Digital Scale
+
usb:v1453*
ID_VENDOR_FROM_DATABASE=Radio Shack
@@ -41183,6 +41777,9 @@ usb:v147ApE03A*
usb:v147ApE03C*
ID_MODEL_FROM_DATABASE=eHome Infrared Receiver
+usb:v147ApE03D*
+ ID_MODEL_FROM_DATABASE=2 Channel Audio
+
usb:v147ApE03E*
ID_MODEL_FROM_DATABASE=Infrared Receiver [IR605A/Q]
@@ -41465,6 +42062,12 @@ usb:v14DD*
usb:v14DDp1007*
ID_MODEL_FROM_DATABASE=D2CIM-VUSB KVM connector
+usb:v14E0*
+ ID_VENDOR_FROM_DATABASE=WiNRADiO Communications
+
+usb:v14E0p0501*
+ ID_MODEL_FROM_DATABASE=WR-G528e 'CHEETAH'
+
usb:v14E1*
ID_VENDOR_FROM_DATABASE=Dialogue Technology Corp.
@@ -41591,6 +42194,9 @@ usb:v152D*
usb:v152Dp0539*
ID_MODEL_FROM_DATABASE=JMS539 SuperSpeed SATA II 3.0G Bridge
+usb:v152Dp0770*
+ ID_MODEL_FROM_DATABASE=Alienware Integrated Webcam
+
usb:v152Dp2329*
ID_MODEL_FROM_DATABASE=JM20329 SATA Bridge
@@ -41651,6 +42257,9 @@ usb:v1532p001C*
usb:v1532p0024*
ID_MODEL_FROM_DATABASE=Razer Mamba
+usb:v1532p002E*
+ ID_MODEL_FROM_DATABASE=RZ01-0058 Gaming Mouse [Naga]
+
usb:v1532p0036*
ID_MODEL_FROM_DATABASE=RZ01-0075, Gaming Mouse [Naga Hex]
@@ -41813,6 +42422,9 @@ usb:v1598*
usb:v15A2*
ID_VENDOR_FROM_DATABASE=Freescale Semiconductor, Inc.
+usb:v15A2p0038*
+ ID_MODEL_FROM_DATABASE=9S08JS Bootloader
+
usb:v15A2p003B*
ID_MODEL_FROM_DATABASE=USB2CAN Application for ColdFire DEMOJM board
@@ -42038,6 +42650,9 @@ usb:v15E4*
usb:v15E4p0024*
ID_MODEL_FROM_DATABASE=Mixtrack
+usb:v15E4p0140*
+ ID_MODEL_FROM_DATABASE=ION VCR 2 PC / Video 2 PC
+
usb:v15E8*
ID_VENDOR_FROM_DATABASE=SohoWare
@@ -43037,6 +43652,9 @@ usb:v16D0p054B*
usb:v16D0p05BE*
ID_MODEL_FROM_DATABASE=EasyLogic Board
+usb:v16D0p06F9*
+ ID_MODEL_FROM_DATABASE=Gabotronics Xminilab
+
usb:v16D0p0753*
ID_MODEL_FROM_DATABASE=Digistump DigiSpark
@@ -43046,6 +43664,9 @@ usb:v16D0p075C*
usb:v16D0p075D*
ID_MODEL_FROM_DATABASE=AB-1.x UAC2 [Audio Widget]
+usb:v16D0p080A*
+ ID_MODEL_FROM_DATABASE=S2E1 Interface
+
usb:v16D3*
ID_VENDOR_FROM_DATABASE=Frontline Test Equipment, Inc.
@@ -43361,6 +43982,12 @@ usb:v1753*
usb:v1753pC901*
ID_MODEL_FROM_DATABASE=PPC900 Pinpad Terminal
+usb:v1756*
+ ID_VENDOR_FROM_DATABASE=ENENSYS Technologies
+
+usb:v1756p0006*
+ ID_MODEL_FROM_DATABASE=DiviPitch
+
usb:v1759*
ID_VENDOR_FROM_DATABASE=LucidPort Technology, Inc.
@@ -43490,12 +44117,21 @@ usb:v17A0p0200*
usb:v17A0p0201*
ID_MODEL_FROM_DATABASE=StudioDock monitors (audio)
+usb:v17A0p0210*
+ ID_MODEL_FROM_DATABASE=StudioGT monitors
+
usb:v17A0p0301*
ID_MODEL_FROM_DATABASE=Q2U handheld microphone with XLR
usb:v17A0p0302*
ID_MODEL_FROM_DATABASE=GoMic compact condenser microphone
+usb:v17A0p0304*
+ ID_MODEL_FROM_DATABASE=Q2U handheld mic with XLR
+
+usb:v17A0p0305*
+ ID_MODEL_FROM_DATABASE=GoMic compact condenser mic
+
usb:v17A0p0310*
ID_MODEL_FROM_DATABASE=Meteor condenser microphone
@@ -43529,6 +44165,12 @@ usb:v17B3*
usb:v17B3p0004*
ID_MODEL_FROM_DATABASE=Linux-USB Midi Gadget
+usb:v17B5*
+ ID_VENDOR_FROM_DATABASE=Lunatone
+
+usb:v17B5p0010*
+ ID_MODEL_FROM_DATABASE=MFT Sensor
+
usb:v17BA*
ID_VENDOR_FROM_DATABASE=SAURIS GmbH
@@ -43610,6 +44252,9 @@ usb:v17E9*
usb:v17E9p0051*
ID_MODEL_FROM_DATABASE=USB VGA Adaptor
+usb:v17E9p030B*
+ ID_MODEL_FROM_DATABASE=HP T100
+
usb:v17E9p0377*
ID_MODEL_FROM_DATABASE=Plugable UD-160-A (M)
@@ -43634,6 +44279,9 @@ usb:v17E9p037D*
usb:v17E9p430A*
ID_MODEL_FROM_DATABASE=HP Port Replicator (Composite Device)
+usb:v17E9p4312*
+ ID_MODEL_FROM_DATABASE=S2340T
+
usb:v17EB*
ID_VENDOR_FROM_DATABASE=Cornice, Inc.
@@ -43646,6 +44294,9 @@ usb:v17EFp1003*
usb:v17EFp1004*
ID_MODEL_FROM_DATABASE=Integrated Webcam
+usb:v17EFp1008*
+ ID_MODEL_FROM_DATABASE=Hub
+
usb:v17EFp100A*
ID_MODEL_FROM_DATABASE=ThinkPad Mini Dock Plus Series 3
@@ -43688,12 +44339,18 @@ usb:v17EFp4814*
usb:v17EFp4815*
ID_MODEL_FROM_DATABASE=Integrated Webcam [R5U877]
+usb:v17EFp4816*
+ ID_MODEL_FROM_DATABASE=Integrated Webcam
+
usb:v17EFp481C*
ID_MODEL_FROM_DATABASE=Integrated Webcam
usb:v17EFp481D*
ID_MODEL_FROM_DATABASE=Integrated Webcam
+usb:v17EFp6004*
+ ID_MODEL_FROM_DATABASE=ISD-V4 Tablet Pen
+
usb:v17EFp6007*
ID_MODEL_FROM_DATABASE=Smartcard Keyboard
@@ -43829,6 +44486,9 @@ usb:v1873pEE93*
usb:v187C*
ID_VENDOR_FROM_DATABASE=Alienware Corporation
+usb:v187Cp0511*
+ ID_MODEL_FROM_DATABASE=AlienFX Mobile lighting
+
usb:v187Cp0600*
ID_MODEL_FROM_DATABASE=Dual Compatible Game Pad
@@ -43905,7 +44565,7 @@ usb:v18A5p0237*
ID_MODEL_FROM_DATABASE=Portable Harddrive (500 GB)
usb:v18A5p0302*
- ID_MODEL_FROM_DATABASE=32GB Flash Drive
+ ID_MODEL_FROM_DATABASE=Flash Drive
usb:v18B1*
ID_VENDOR_FROM_DATABASE=Petalynx
@@ -43992,16 +44652,16 @@ usb:v18D1p4E40*
ID_MODEL_FROM_DATABASE=Nexus 7 (fastboot)
usb:v18D1p4E41*
- ID_MODEL_FROM_DATABASE=ASUS Nexus 7 (MTP modus)
+ ID_MODEL_FROM_DATABASE=Nexus 7 (MTP)
usb:v18D1p4E42*
ID_MODEL_FROM_DATABASE=Nexus 7 (debug)
usb:v18D1p4E43*
- ID_MODEL_FROM_DATABASE=ASUS Nexus 7 (PTP modus)
+ ID_MODEL_FROM_DATABASE=Nexus 7 (PTP)
usb:v18D1p4EE1*
- ID_MODEL_FROM_DATABASE=Nexus 4
+ ID_MODEL_FROM_DATABASE=Nexus 4 / 10
usb:v18D1p4EE2*
ID_MODEL_FROM_DATABASE=Nexus 4 (debug)
@@ -44018,6 +44678,12 @@ usb:v18D1p7102*
usb:v18D1pB004*
ID_MODEL_FROM_DATABASE=Pandigital / B&N Novel 9" tablet
+usb:v18D1pD109*
+ ID_MODEL_FROM_DATABASE=LG G2x MTP
+
+usb:v18D1pD10A*
+ ID_MODEL_FROM_DATABASE=LG G2x MTP (debug)
+
usb:v18D5*
ID_VENDOR_FROM_DATABASE=Starline International Group Limited
@@ -44108,6 +44774,9 @@ usb:v1914*
usb:v1915*
ID_VENDOR_FROM_DATABASE=Nordic Semiconductor ASA
+usb:v1915p000C*
+ ID_MODEL_FROM_DATABASE=Wireless Desktop nRF24L01 CX-1766
+
usb:v1915p2233*
ID_MODEL_FROM_DATABASE=Linksys WUSB11 v2.8 802.11b Adapter [Atmel AT76C505]
@@ -44120,6 +44789,12 @@ usb:v1915p2235*
usb:v1915p2236*
ID_MODEL_FROM_DATABASE=Linksys WUSB11 v3.0 802.11b Adapter [Intersil PRISM 3]
+usb:v1923*
+ ID_VENDOR_FROM_DATABASE=FitLinxx
+
+usb:v1923p0002*
+ ID_MODEL_FROM_DATABASE=Personal SyncPoint
+
usb:v1926*
ID_VENDOR_FROM_DATABASE=NextWindow
@@ -44207,6 +44882,9 @@ usb:v1926p0086*
usb:v1926p0087*
ID_MODEL_FROM_DATABASE=1950 HID Touchscreen
+usb:v1926p0DC2*
+ ID_MODEL_FROM_DATABASE=HID Touchscreen
+
usb:v192F*
ID_VENDOR_FROM_DATABASE=Avago Technologies, Pte.
@@ -44300,6 +44978,9 @@ usb:v1951*
usb:v1953*
ID_VENDOR_FROM_DATABASE=Ironkey Inc.
+usb:v1953p0202*
+ ID_MODEL_FROM_DATABASE=S200 2GB Rev. 1
+
usb:v1954*
ID_VENDOR_FROM_DATABASE=Radiient Technologies
@@ -44537,6 +45218,12 @@ usb:v19D2pFFF2*
usb:v19D2pFFF3*
ID_MODEL_FROM_DATABASE=Gobi Wireless Modem
+usb:v19DB*
+ ID_VENDOR_FROM_DATABASE=KFI Printers
+
+usb:v19DBp02F1*
+ ID_MODEL_FROM_DATABASE=NAUT324C
+
usb:v19E1*
ID_VENDOR_FROM_DATABASE=WeiDuan Electronic Accessory (S.Z.) Co., Ltd.
@@ -44567,6 +45254,9 @@ usb:v19FFp0102*
usb:v19FFp0201*
ID_MODEL_FROM_DATABASE=Rocketfish Wireless 2.4G Laser Mouse
+usb:v19FFp0238*
+ ID_MODEL_FROM_DATABASE=DX-WRM1401 Mouse
+
usb:v1A08*
ID_VENDOR_FROM_DATABASE=Bellwood International, Inc.
@@ -44619,7 +45309,7 @@ usb:v1A40*
ID_VENDOR_FROM_DATABASE=Terminus Technology Inc.
usb:v1A40p0101*
- ID_MODEL_FROM_DATABASE=4-Port HUB
+ ID_MODEL_FROM_DATABASE=Hub
usb:v1A40p0201*
ID_MODEL_FROM_DATABASE=FE 2.1 7-port Hub
@@ -44669,6 +45359,12 @@ usb:v1A72p1008*
usb:v1A79*
ID_VENDOR_FROM_DATABASE=Bayer Health Care LLC
+usb:v1A79p6002*
+ ID_MODEL_FROM_DATABASE=Contour
+
+usb:v1A79p7410*
+ ID_MODEL_FROM_DATABASE=Contour Next
+
usb:v1A7B*
ID_VENDOR_FROM_DATABASE=Lumberg Connect GmbH & Co. KG
@@ -44765,6 +45461,12 @@ usb:v1AB1p0588*
usb:v1ACB*
ID_VENDOR_FROM_DATABASE=Salcomp Plc
+usb:v1ACC*
+ ID_VENDOR_FROM_DATABASE=Midiplus Co, Ltd.
+
+usb:v1ACCp0103*
+ ID_MODEL_FROM_DATABASE=AudioLink plus 4x4 2.9.28
+
usb:v1AD1*
ID_VENDOR_FROM_DATABASE=Desay Wire Co., Ltd.
@@ -45191,6 +45893,75 @@ usb:v1B47p0001*
usb:v1B48*
ID_VENDOR_FROM_DATABASE=Plastron Precision Co., Ltd.
+usb:v1B52*
+ ID_VENDOR_FROM_DATABASE=ARH Inc.
+
+usb:v1B52p2101*
+ ID_MODEL_FROM_DATABASE=FXMC Neural Network Controller
+
+usb:v1B52p2102*
+ ID_MODEL_FROM_DATABASE=FXMC Neural Network Controller V2
+
+usb:v1B52p2103*
+ ID_MODEL_FROM_DATABASE=FXMC Neural Network Controller V3
+
+usb:v1B52p4101*
+ ID_MODEL_FROM_DATABASE=Passport Reader CLR device
+
+usb:v1B52p4201*
+ ID_MODEL_FROM_DATABASE=Passport Reader PRM device
+
+usb:v1B52p4202*
+ ID_MODEL_FROM_DATABASE=Passport Reader PRM extension device
+
+usb:v1B52p4203*
+ ID_MODEL_FROM_DATABASE=Passport Reader PRM DSP device
+
+usb:v1B52p4204*
+ ID_MODEL_FROM_DATABASE=Passport Reader PRMC device
+
+usb:v1B52p4205*
+ ID_MODEL_FROM_DATABASE=Passport Reader CSHR device
+
+usb:v1B52p4206*
+ ID_MODEL_FROM_DATABASE=Passport Reader PRMC V2 device
+
+usb:v1B52p4301*
+ ID_MODEL_FROM_DATABASE=Passport Reader MRZ device
+
+usb:v1B52p4302*
+ ID_MODEL_FROM_DATABASE=Passport Reader MRZ DSP device
+
+usb:v1B52p4303*
+ ID_MODEL_FROM_DATABASE=Passport Reader CSLR device
+
+usb:v1B52p4401*
+ ID_MODEL_FROM_DATABASE=Card Reader
+
+usb:v1B52p4501*
+ ID_MODEL_FROM_DATABASE=Passport Reader RFID device
+
+usb:v1B52p4502*
+ ID_MODEL_FROM_DATABASE=Passport Reader RFID AIG device
+
+usb:v1B52p6101*
+ ID_MODEL_FROM_DATABASE=Neural Network Controller
+
+usb:v1B52p6202*
+ ID_MODEL_FROM_DATABASE=Fingerprint Reader device
+
+usb:v1B52p6203*
+ ID_MODEL_FROM_DATABASE=Fingerprint Scanner device
+
+usb:v1B52p8101*
+ ID_MODEL_FROM_DATABASE=Camera V1
+
+usb:v1B52p8102*
+ ID_MODEL_FROM_DATABASE=Recovery / Camera V2
+
+usb:v1B52p8103*
+ ID_MODEL_FROM_DATABASE=Camera V3
+
usb:v1B59*
ID_VENDOR_FROM_DATABASE=K.S. Terminals Inc.
@@ -45344,6 +46115,12 @@ usb:v1BAEp0002*
usb:v1BBB*
ID_VENDOR_FROM_DATABASE=T & A Mobile Phones
+usb:v1BBBp011E*
+ ID_MODEL_FROM_DATABASE=Alcatel One Touch L100V / Telekom Speedstick LTE II
+
+usb:v1BBBpF017*
+ ID_MODEL_FROM_DATABASE=Alcatel One Touch L100V / Telekom Speedstick LTE II
+
usb:v1BC4*
ID_VENDOR_FROM_DATABASE=Ford Motor Co.
@@ -45351,7 +46128,7 @@ usb:v1BC5*
ID_VENDOR_FROM_DATABASE=AVIXE Technology (China) Ltd.
usb:v1BC7*
- ID_VENDOR_FROM_DATABASE=Telit
+ ID_VENDOR_FROM_DATABASE=Telit Wireless Solutions
usb:v1BC7p0020*
ID_MODEL_FROM_DATABASE=HE863
@@ -45359,6 +46136,9 @@ usb:v1BC7p0020*
usb:v1BC7p0021*
ID_MODEL_FROM_DATABASE=HE910
+usb:v1BC7p0023*
+ ID_MODEL_FROM_DATABASE=HE910-D ECM
+
usb:v1BC7p1003*
ID_MODEL_FROM_DATABASE=UC864-E
@@ -45374,6 +46154,12 @@ usb:v1BC7p1006*
usb:v1BC7p1010*
ID_MODEL_FROM_DATABASE=DE910-DUAL
+usb:v1BC7p1011*
+ ID_MODEL_FROM_DATABASE=CE910-DUAL
+
+usb:v1BC7p1200*
+ ID_MODEL_FROM_DATABASE=LE920
+
usb:v1BCE*
ID_VENDOR_FROM_DATABASE=Contac Cable Industrial Limited
@@ -45401,6 +46187,9 @@ usb:v1BCFp2885*
usb:v1BCFp2888*
ID_MODEL_FROM_DATABASE=HP Universal Camera
+usb:v1BCFp2B83*
+ ID_MODEL_FROM_DATABASE=Laptop Integrated Webcam FHD
+
usb:v1BD0*
ID_VENDOR_FROM_DATABASE=Hangzhou Riyue Electronic Co., Ltd.
@@ -45656,6 +46445,9 @@ usb:v1CBEp00FD*
usb:v1CBEp00FF*
ID_MODEL_FROM_DATABASE=Stellaris ROM DFU Bootloader
+usb:v1CBEp0166*
+ ID_MODEL_FROM_DATABASE=CANAL USB2CAN
+
usb:v1CBF*
ID_VENDOR_FROM_DATABASE=FORTAT SKYMARK INDUSTRIAL COMPANY
@@ -45821,6 +46613,12 @@ usb:v1D34p000D*
usb:v1D34p0013*
ID_MODEL_FROM_DATABASE=Dream Cheeky LED Message Board
+usb:v1D45*
+ ID_VENDOR_FROM_DATABASE=Touch
+
+usb:v1D45p1D45*
+ ID_MODEL_FROM_DATABASE=Foxlink Optical touch sensor
+
usb:v1D4D*
ID_VENDOR_FROM_DATABASE=PEGATRON CORPORATION
@@ -45842,6 +46640,9 @@ usb:v1D50p5119*
usb:v1D50p602B*
ID_MODEL_FROM_DATABASE=FPGALink
+usb:v1D50p6053*
+ ID_MODEL_FROM_DATABASE=Darkgame Controller
+
usb:v1D57*
ID_VENDOR_FROM_DATABASE=Xenta
@@ -45908,6 +46709,12 @@ usb:v1D6Bp0105*
usb:v1D6Bp0200*
ID_MODEL_FROM_DATABASE=Qemu Audio Device
+usb:v1D90*
+ ID_VENDOR_FROM_DATABASE=Citizen
+
+usb:v1D90p201E*
+ ID_MODEL_FROM_DATABASE=PPU-700
+
usb:v1DE1*
ID_VENDOR_FROM_DATABASE=Actions Microelectronics Co.
@@ -46037,6 +46844,9 @@ usb:v1E68*
usb:v1E68p001B*
ID_MODEL_FROM_DATABASE=DataStation maxi g.u
+usb:v1E68p0050*
+ ID_MODEL_FROM_DATABASE=DataStation maxi light
+
usb:v1E71*
ID_VENDOR_FROM_DATABASE=NZXT
@@ -46121,9 +46931,18 @@ usb:v1EE8p0014*
usb:v1EF6*
ID_VENDOR_FROM_DATABASE=EADS Deutschland GmbH
+usb:v1EF6p2233*
+ ID_MODEL_FROM_DATABASE=Cassidian NH90 STTE
+
usb:v1EF6p5064*
ID_MODEL_FROM_DATABASE=FDR Interface
+usb:v1EF6p5523*
+ ID_MODEL_FROM_DATABASE=Cassidian SSDC Adapter II
+
+usb:v1EF6p5545*
+ ID_MODEL_FROM_DATABASE=Cassidian SSDC Adapter III
+
usb:v1EF6p5648*
ID_MODEL_FROM_DATABASE=RIU CSMU/BSD
@@ -46139,6 +46958,12 @@ usb:v1F28p0020*
usb:v1F28p0021*
ID_MODEL_FROM_DATABASE=CD INSTALLER USB Device
+usb:v1F3A*
+ ID_VENDOR_FROM_DATABASE=Onda (unverified)
+
+usb:v1F3ApEFE8*
+ ID_MODEL_FROM_DATABASE=V972 tablet in flashing mode
+
usb:v1F44*
ID_VENDOR_FROM_DATABASE=The Neat Company
diff --git a/hwdb/60-keyboard.hwdb b/hwdb/60-keyboard.hwdb
new file mode 100644
index 0000000000..20d398f7d9
--- /dev/null
+++ b/hwdb/60-keyboard.hwdb
@@ -0,0 +1,1088 @@
+# This file is part of systemd.
+#
+# Keyboard mapping of scan codes to key codes, and
+# scan codes to add to the AT keyboard's 'force-release' list.
+#
+# The lookup keys are composed in:
+# 60-keyboard.rules
+#
+# Note: The format of the "keyboard:" prefix match key is a
+# contract between the rules file and the hardware data, it might
+# change in later revisions to support more or better matches, it
+# is not necessarily expected to be a stable ABI.
+#
+# Supported hardware matches are:
+# - USB keyboards identified by the usb kernel modalias:
+# keyboard:usb:vXXXXpYYYY*
+# XXXX is the 4-digit hex uppercase vendor, and YYYY
+# the 4-digit hex uppercase product.
+#
+# - AT keyboard DMI data matches:
+# keyboard:dmi:bvn*:bvr*:bd*:svn<vendor>:pn<product>:pvr*
+# <vendor> and <product> are the firmware-provided strings
+# exported by the kernel DMI modalias.
+#
+# - Platform driver device name and DMI data match:
+# keyboard:name:<input device name>:dmi:bvn*:bvr*:bd*:svn<vendor>:pn*
+# <input device name> is the name device specified by the
+# driver, <vendor> is the firmware-provided string exported
+# by the kernel DMI modalias.
+#
+# Scan codes are specified as:
+# KEYBOARD_KEY_<hex scan code>=<key code identifier>
+# The scan code should be expressed in hex lowercase and in
+# full bytes, a multiple of 2 digits. The key codes are retrieved
+# and normalized from the kernel input API header.
+#
+# A '!' as the first charcter of the key identifier string
+# will add the scan code to the AT keyboard's list of scan codes
+# where the driver will synthesize a release event and not expect
+# it to be generated by the hardware.
+#
+# To debug key presses and access scan code mapping data of
+# an input device use the commonly available tool: evtest(1).
+
+##########################################
+# Acer
+##########################################
+
+# Acer platform kernel driver
+keyboard:name:Acer WMI hotkeys:dmi:bvn*:bvr*:bd*:svn*:pnAcer*:pvr*
+ KEYBOARD_KEY_82=f21
+
+# Aspire 5720
+keyboard:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*5720*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnAcer*:pnZG8*:pvr*
+ KEYBOARD_KEY_84=bluetooth # sent when bluetooth module missing, and key pressed
+ KEYBOARD_KEY_92=media # Acer arcade
+ KEYBOARD_KEY_d4=bluetooth # Bluetooth on
+ KEYBOARD_KEY_d9=bluetooth # Bluetooth off
+ KEYBOARD_KEY_f4=prog3 # e-key
+
+# Aspire 5920g
+keyboard:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*5920G:*
+ KEYBOARD_KEY_8a=media
+ KEYBOARD_KEY_92=media
+ KEYBOARD_KEY_a6=setup
+ KEYBOARD_KEY_b2=www
+ KEYBOARD_KEY_d9=bluetooth # (toggle) on-to-off
+
+# Aspire 6920
+keyboard:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*6920:*
+ KEYBOARD_KEY_d9=bluetooth # (toggle) on-to-off
+ KEYBOARD_KEY_92=media
+ KEYBOARD_KEY_9e=back
+ KEYBOARD_KEY_83=rewind
+ KEYBOARD_KEY_89=fastforward
+
+# Aspire 8930
+keyboard:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*8930:*
+ KEYBOARD_KEY_ca=prog3 # key 'HOLD' on CineDash Media Console
+ KEYBOARD_KEY_83=rewind
+ KEYBOARD_KEY_89=fastforward
+ KEYBOARD_KEY_92=media # key 'ARCADE' on CineDash Media Console
+ KEYBOARD_KEY_9e=back
+
+# Travelmate C300
+keyboard:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*C3[01]0*:pvr*
+ KEYBOARD_KEY_67=f24 # FIXME: rotate screen
+ KEYBOARD_KEY_68=up
+ KEYBOARD_KEY_69=down
+ KEYBOARD_KEY_6b=fn
+ KEYBOARD_KEY_6c=screenlock # FIXME: lock tablet device/buttons
+
+#
+keyboard:dmi:bvn*:bvr*:bd*:svnAcer*:pn*
+keyboard:dmi:bvn*:bvr*:bd*:svnGateway*:pnA0A1*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svneMachines:pneMachines*E725:pvr*
+ KEYBOARD_KEY_a5=help # Fn+F1
+ KEYBOARD_KEY_a6=setup # Fn+F2 Acer eSettings
+ KEYBOARD_KEY_a7=battery # Fn+F3 Power Management
+ KEYBOARD_KEY_a9=switchvideomode # Fn+F5
+ KEYBOARD_KEY_b3=euro
+ KEYBOARD_KEY_b4=dollar
+ KEYBOARD_KEY_ce=brightnessup # Fn+Right
+ KEYBOARD_KEY_d4=bluetooth # (toggle) off-to-on
+ KEYBOARD_KEY_d5=wlan # (toggle) on-to-off
+ KEYBOARD_KEY_d6=wlan # (toggle) off-to-on
+ KEYBOARD_KEY_d7=bluetooth # (toggle) on-to-off
+ KEYBOARD_KEY_d8=bluetooth # (toggle) off-to-on
+ KEYBOARD_KEY_d9=brightnessup # Fn+Right
+ KEYBOARD_KEY_ee=brightnessup # Fn+Right
+ KEYBOARD_KEY_ef=brightnessdown # Fn+Left
+ KEYBOARD_KEY_f1=f22 # Fn+F7 Touchpad toggle (off-to-on)
+ KEYBOARD_KEY_f2=f23 # Fn+F7 Touchpad toggle (on-to-off)
+ KEYBOARD_KEY_f3=prog2 # "P2" programmable button
+ KEYBOARD_KEY_f4=prog1 # "P1" programmable button
+ KEYBOARD_KEY_f5=presentation
+ KEYBOARD_KEY_f8=fn
+ KEYBOARD_KEY_f9=prog1 # Launch NTI shadow
+
+#
+keyboard:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5210*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5220*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5610*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5620*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5720*:pvr*
+ KEYBOARD_KEY_ee=screenlock
+
+#
+keyboard:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*6292*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*8471*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*4720*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*7720*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*1810T*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnAcer*:pnAO751h:*
+keyboard:dmi:bvn*:bvr*:bd*:svnAcer*:pnAO531h:*
+ KEYBOARD_KEY_d9=bluetooth
+
+#
+keyboard:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*4720*:pvr*
+ KEYBOARD_KEY_b2=www
+ KEYBOARD_KEY_ee=screenlock
+
+#
+keyboard:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*6593:*
+keyboard:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*1640:*
+ KEYBOARD_KEY_b2=www
+ KEYBOARD_KEY_ee=screenlock
+
+###########################################################
+# Alienware
+###########################################################
+
+keyboard:dmi:bvn*:bvr*:bd*:svnAlienware*:pn*
+ KEYBOARD_KEY_8a=ejectcd
+
+###########################################################
+# Asus
+###########################################################
+
+keyboard:dmi:bvn*:bvr*:bd*:svnASUS:pn*
+ KEYBOARD_KEY_ed=volumeup
+ KEYBOARD_KEY_ee=volumedown
+ KEYBOARD_KEY_ef=mute
+
+keyboard:name:Asus WMI hotkeys:dmi:bvn*:bvr*:bd*:svnASUS*:pn*:pvr*
+ KEYBOARD_KEY_6b=f21 # Touchpad Toggle
+
+###########################################################
+# BenQ
+###########################################################
+
+keyboard:dmi:bvn*:bvr*:bd*:svn*BenQ*:pn*Joybook*R22*:pvr*
+ KEYBOARD_KEY_6e=wlan
+
+###########################################################
+# Compal
+###########################################################
+
+keyboard:dmi:bvn*:bvr*:bd*:svnCOMPAL:pnHEL80I:*
+ KEYBOARD_KEY_84=wlan
+
+###########################################################
+# COMPAQ
+###########################################################
+
+keyboard:dmi:bvn*:bvr*:bd*:svnCompaq*:pn*E500*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnCompaq*:pn*Evo*N*:pvr*
+ KEYBOARD_KEY_a3=www # I key
+ KEYBOARD_KEY_9a=search
+ KEYBOARD_KEY_9e=email
+ KEYBOARD_KEY_9f=homepage
+
+###########################################################
+# Dell
+###########################################################
+
+keyboard:dmi:bvn*:bvr*:bd*:svnDell*:pn*
+ KEYBOARD_KEY_81=playpause # Play/Pause
+ KEYBOARD_KEY_82=stopcd # Stop
+ KEYBOARD_KEY_83=previoussong # Previous song
+ KEYBOARD_KEY_84=nextsong # Next song
+ KEYBOARD_KEY_85=brightnessdown # Fn+Down Brightness Down
+ KEYBOARD_KEY_86=brightnessup # Fn+Up Brightness Up
+ KEYBOARD_KEY_87=battery # Fn+F3 battery icon
+ KEYBOARD_KEY_88=unknown # Fn+F2 Turn On/Off Wireless - handled in hardware
+ KEYBOARD_KEY_89=ejectclosecd # Fn+F10 Eject CD
+ KEYBOARD_KEY_8a=suspend # Fn+F1 hibernate
+ KEYBOARD_KEY_8b=switchvideomode # Fn+F8 CRT/LCD (high keycode: "displaytoggle")
+ KEYBOARD_KEY_8c=unknown # Fn+Right Auto Brightness
+ KEYBOARD_KEY_8F=switchvideomode # Fn+F7 aspect ratio
+ KEYBOARD_KEY_90=previoussong # Front panel previous song
+ KEYBOARD_KEY_91=prog1 # Wi-Fi Catcher (Dell-specific)
+ KEYBOARD_KEY_92=media # MediaDirect button (house icon)
+ KEYBOARD_KEY_93=unknown # FIXME Fn+Left Auto Brightness
+ KEYBOARD_KEY_95=camera # Shutter button - Takes a picture if optional camera available
+ KEYBOARD_KEY_97=email # Tablet email button
+ KEYBOARD_KEY_98=f21 # FIXME: Tablet screen rotation
+ KEYBOARD_KEY_99=nextsong # Front panel next song
+ KEYBOARD_KEY_9a=setup # Tablet tools button
+ KEYBOARD_KEY_9b=switchvideomode # Display toggle button
+ KEYBOARD_KEY_9e=f21 # Touchpad toggle
+ KEYBOARD_KEY_a2=playpause # Front panel play/pause
+ KEYBOARD_KEY_a4=stopcd # Front panel stop
+ KEYBOARD_KEY_ed=media # MediaDirect button
+ KEYBOARD_KEY_d8=screenlock # FIXME: Tablet lock button
+ KEYBOARD_KEY_d9=f21 # Touchpad toggle
+
+#
+keyboard:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*910:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*101[012]:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*1110:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*1210:pvr*
+ KEYBOARD_KEY_84=wlan
+
+# Latitude XT2
+keyboard:dmi:bvn*:bvr*:bd*:svnDell*:pnLatitude*XT2:pvr*
+ KEYBOARD_KEY_9b=up # tablet rocker up
+ KEYBOARD_KEY_9e=enter # tablet rocker press
+ KEYBOARD_KEY_9f=back # tablet back
+ KEYBOARD_KEY_a3=down # tablet rocker down
+
+keyboard:dmi:bvn*:bvr*:bd*:svnDell*:pnStudio*155[78]:pvr*
+ KEYBOARD_KEY_a0=! # mute
+ KEYBOARD_KEY_ae=! # volume down
+ KEYBOARD_KEY_b0=! # volume up
+
+# Dell Touchpad
+keyboard:dmi:bvn*:bvr*:bd*:svnDell*:pnLatitude*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnDell*:pnPrecision*:pvr*
+ KEYBOARD_KEY_9e=!f21
+
+# Dell XPS
+keyboard:dmi:bvn*:bvr*:bd*:svnDell*:pnXPS*:pvr*
+ KEYBOARD_KEY_8c=!unknown
+
+###########################################################
+# Everex
+###########################################################
+
+keyboard:dmi:bvn*:bvr*:bd*:svnEverex:pnXT5000*:pvr*
+ KEYBOARD_KEY_5c=media
+ KEYBOARD_KEY_65=f21 # Fn+F5 Touchpad toggle
+ KEYBOARD_KEY_67=prog3 # Fan speed control button
+ KEYBOARD_KEY_6f=brightnessup
+ KEYBOARD_KEY_7f=brightnessdown
+ KEYBOARD_KEY_b2=www
+ KEYBOARD_KEY_ec=mail
+
+##########################################
+# Fujitsu
+##########################################
+
+keyboard:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pnAMILO*M*:pvr*
+ KEYBOARD_KEY_97=prog2
+ KEYBOARD_KEY_9f=prog1
+
+keyboard:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pnAmilo*Li*1718:*
+ KEYBOARD_KEY_d6=wlan
+
+# Amilo Li 2732
+keyboard:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pnAMILO*Li*2732:*
+ KEYBOARD_KEY_d9=brightnessdown # Fn+F8 brightness down
+ KEYBOARD_KEY_ef=brightnessup # Fn+F9 brightness up
+ KEYBOARD_KEY_a9=switchvideomode # Fn+F10 Cycle between available video outputs
+
+# Amilo Pa 2548
+keyboard:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*AMILO*Pa*2548*:pvr*
+ KEYBOARD_KEY_e0=volumedown
+ KEYBOARD_KEY_e1=volumeup
+ KEYBOARD_KEY_e5=prog1
+
+# Amilo Pro Edition V3505
+keyboard:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*AMILO*Pro*Edition*V3505*:pvr*
+ KEYBOARD_KEY_a5=help # Fn+F1
+ KEYBOARD_KEY_a9=switchvideomode # Fn+F3
+ KEYBOARD_KEY_d9=brightnessdown # Fn+F8
+ KEYBOARD_KEY_e0=brightnessup # Fn+F9
+
+# Amilo Pro v3205
+keyboard:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*AMILO*Pro*V3205*:pvr*
+ KEYBOARD_KEY_f4=f21 # FIXME: silent-mode decrease CPU/GPU clock
+ KEYBOARD_KEY_f7=switchvideomode # Fn+F3
+
+# Amilo Si 1520
+keyboard:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*Amilo*Si*1520*:pvr*
+ KEYBOARD_KEY_e1=wlan
+ KEYBOARD_KEY_f3=wlan
+ KEYBOARD_KEY_ee=brightnessdown
+ KEYBOARD_KEY_e0=brightnessup
+ KEYBOARD_KEY_e2=bluetooth
+ KEYBOARD_KEY_f7=video
+
+# Esprimo Mobile V5
+keyboard:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*ESPRIMO*Mobile*V5*:pvr*
+ KEYBOARD_KEY_a9=switchvideomode
+ KEYBOARD_KEY_d9=brightnessdown
+ KEYBOARD_KEY_df=sleep
+ KEYBOARD_KEY_ef=brightnessup
+
+# Esprimo Mobile V6
+keyboard:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*ESPRIMO*Mobile*V6*:pvr*
+ KEYBOARD_KEY_ce=brightnessup
+ KEYBOARD_KEY_ef=brightnessdown
+
+###########################################################
+# GIGABYTE
+###########################################################
+
+keyboard:dmi:bvn*:bvr*:bd*:svnGIGABYTE:pnU2442:*
+ KEYBOARD_KEY_a0=! # mute
+
+###########################################################
+# Genius
+###########################################################
+
+# Slimstar 320
+keyboard:usb:v0458p0708d*dc*dsc*dp*ic*isc*ip*in01*
+ KEYBOARD_KEY_0900f0=scrollup
+ KEYBOARD_KEY_0900f1=scrolldown
+ KEYBOARD_KEY_0900f3=back
+ KEYBOARD_KEY_0900f2=forward
+ KEYBOARD_KEY_0900f5=wordprocessor
+ KEYBOARD_KEY_0900f6=spreadsheet
+ KEYBOARD_KEY_0900f4=presentation
+ KEYBOARD_KEY_0c0223=www
+ KEYBOARD_KEY_0900f7=chat
+ KEYBOARD_KEY_0900fb=prog1
+ KEYBOARD_KEY_0900f8=close
+ KEYBOARD_KEY_0900f9=graphicseditor
+ KEYBOARD_KEY_0900fd=scale
+ KEYBOARD_KEY_0900fc=screenlock
+
+###########################################################
+# Hewlett Packard
+###########################################################
+
+keyboard:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*:pvr*
+ KEYBOARD_KEY_81=fn_esc
+ KEYBOARD_KEY_89=battery # Fn+F8
+ KEYBOARD_KEY_8a=screenlock # Fn+F6
+ KEYBOARD_KEY_8b=camera
+ KEYBOARD_KEY_8c=media # music
+ KEYBOARD_KEY_8e=dvd
+ KEYBOARD_KEY_b1=help
+ KEYBOARD_KEY_b3=unknown # FIXME: Auto brightness
+ KEYBOARD_KEY_d7=wlan
+ KEYBOARD_KEY_92=brightnessdown # Fn+F7 (Fn+F9 on 6730b)
+ KEYBOARD_KEY_97=brightnessup # Fn+F8 (Fn+F10 on 6730b)
+ KEYBOARD_KEY_ee=switchvideomode # Fn+F4
+
+# Tablet
+keyboard:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[tT][aA][bB][lL][eE][tT]*:pvr*
+ KEYBOARD_KEY_82=prog2 # Funny Key
+ KEYBOARD_KEY_83=prog1 # Q
+ KEYBOARD_KEY_84=tab
+ KEYBOARD_KEY_85=esc
+ KEYBOARD_KEY_86=pageup
+ KEYBOARD_KEY_87=pagedown
+
+# Pavilion
+keyboard:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[pP][aA][vV][iI][lL][iI][oO][nN]*:pvr*
+ KEYBOARD_KEY_88=media # FIXME: quick play
+ KEYBOARD_KEY_b7=print
+ KEYBOARD_KEY_d8=!f23 # touchpad off
+ KEYBOARD_KEY_d9=!f22 # touchpad on
+
+keyboard:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*Pavilion*dv7*Notebook*PC:pvr*
+ KEYBOARD_KEY_b7=print
+ KEYBOARD_KEY_c2=media # FIXME: quick play
+ KEYBOARD_KEY_c6=break
+ KEYBOARD_KEY_94=0
+
+# Elitebook
+keyboard:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*Compaq*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*EliteBook*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*2230s*:pvr*
+ KEYBOARD_KEY_88=presentation
+ KEYBOARD_KEY_d9=help # I key (high keycode: "info")
+
+# Presario
+keyboard:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*Presario*CQ*:pvr*
+ KEYBOARD_KEY_d8=f21
+ KEYBOARD_KEY_d9=f21
+
+# 2510p 2530p
+keyboard:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*2510p*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*2530p*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*G60*Notebook*PC:pvr*
+ KEYBOARD_KEY_d8=!f23 # touchpad off
+ KEYBOARD_KEY_d9=!f22 # touchpad on
+
+# 2570p
+keyboard:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*2570p*:pvr*
+ KEYBOARD_KEY_f8=wlan # Wireless HW switch button
+
+# TX2
+keyboard:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[tT][xX]2*:pvr*
+ KEYBOARD_KEY_c2=media
+ KEYBOARD_KEY_d8=!f23 # Toggle touchpad button on tx2 (OFF)
+ KEYBOARD_KEY_d9=!f22 # Toggle touchpad button on tx2 (ON)
+
+# Presario 2100
+keyboard:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnPresario*2100*:pvr*
+ KEYBOARD_KEY_f0=help
+ KEYBOARD_KEY_f1=screenlock
+ KEYBOARD_KEY_f3=search
+
+# Elitebook 8440p
+keyboard:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*EliteBook*8440p:pvr*
+ KEYBOARD_KEY_88=www
+ KEYBOARD_KEY_a0=mute
+ KEYBOARD_KEY_ae=volumedown
+ KEYBOARD_KEY_b0=volumeup
+ KEYBOARD_KEY_ec=mail
+
+# Elitebook 8460p
+keyboard:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*EliteBook*8460p:pvr*
+ KEYBOARD_KEY_f8=wlan # Wireless HW switch button
+ KEYBOARD_KEY_b3=prog1 # Fn+F11 - Ambient Light Sensor button
+ KEYBOARD_KEY_b1=prog2 # Fn+ESC - System information button
+
+# HDX9494nr
+keyboard:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHDX9494NR:pvr*
+ KEYBOARD_KEY_b2=www # Fn+F3
+ KEYBOARD_KEY_d8=!f23 # touchpad off
+ KEYBOARD_KEY_d9=!f22 # touchpad on
+
+###########################################################
+# IBM
+###########################################################
+
+# thinkpad_acpi driver
+keyboard:name:ThinkPad Extra Buttons:dmi:bvn*:bvr*:bd*:svnIBM*:pn*:pvr*
+ KEYBOARD_KEY_01=battery # Fn+F2
+ KEYBOARD_KEY_02=screenlock # Fn+F3
+ KEYBOARD_KEY_03=sleep # Fn+F4
+ KEYBOARD_KEY_04=wlan # Fn+F5
+ KEYBOARD_KEY_06=switchvideomode # Fn+F7
+ KEYBOARD_KEY_07=zoom # Fn+F8 screen expand
+ KEYBOARD_KEY_08=f24 # Fn+F9 undock
+ KEYBOARD_KEY_0b=suspend # Fn+F12
+ KEYBOARD_KEY_0f=brightnessup # Fn+Home
+ KEYBOARD_KEY_10=brightnessdown # Fn+End
+ KEYBOARD_KEY_11=kbdillumtoggle # Fn+PgUp - ThinkLight
+ KEYBOARD_KEY_13=zoom # Fn+Space
+ KEYBOARD_KEY_14=volumeup
+ KEYBOARD_KEY_15=volumedown
+ KEYBOARD_KEY_16=mute
+ KEYBOARD_KEY_17=prog1 # ThinkPad/ThinkVantage button (high keycode: "vendor")
+
+# IBM Thinkpad USB Keyboard Trackpoint
+keyboard:usb:v04B3p301[89]*
+ KEYBOARD_KEY_900f0=screenlock
+ KEYBOARD_KEY_900f1=wlan
+ KEYBOARD_KEY_900f2=switchvideomode
+ KEYBOARD_KEY_900f3=suspend
+ KEYBOARD_KEY_900f4=brightnessup
+ KEYBOARD_KEY_900f5=brightnessdown
+ KEYBOARD_KEY_900f8=zoom
+
+###########################################################
+# Inventec
+###########################################################
+
+# Symphony
+keyboard:dmi:bvn*:bvr*:bd*:svnINVENTEC:pnSYMPHONY*6.0/7.0:pvr*
+ KEYBOARD_KEY_f3=prog2
+ KEYBOARD_KEY_f4=prog1
+
+###########################################################
+# Lenovo
+###########################################################
+
+# thinkpad_acpi driver
+keyboard:name:ThinkPad Extra Buttons:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*
+ KEYBOARD_KEY_01=screenlock
+ KEYBOARD_KEY_02=battery
+ KEYBOARD_KEY_03=sleep
+ KEYBOARD_KEY_04=wlan
+ KEYBOARD_KEY_06=switchvideomode
+ KEYBOARD_KEY_07=f21
+ KEYBOARD_KEY_08=f24
+ KEYBOARD_KEY_0b=suspend
+ KEYBOARD_KEY_0f=brightnessup
+ KEYBOARD_KEY_10=brightnessdown
+ KEYBOARD_KEY_11=kbdillumtoggle
+ KEYBOARD_KEY_13=zoom
+ KEYBOARD_KEY_14=volumeup
+ KEYBOARD_KEY_15=volumedown
+ KEYBOARD_KEY_16=mute
+ KEYBOARD_KEY_17=prog1
+ KEYBOARD_KEY_1a=f20
+
+#
+keyboard:name:Ideapad extra buttons:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*
+ KEYBOARD_KEY_42=f23
+ KEYBOARD_KEY_43=f22
+
+# ThinkPad Keyboard with TrackPoint
+keyboard:usb:v17EFp6009*
+ KEYBOARD_KEY_090012=screenlock # Fn+F2
+ KEYBOARD_KEY_090013=battery # Fn+F3
+ KEYBOARD_KEY_090014=wlan # Fn+F5
+ KEYBOARD_KEY_090016=switchvideomode # Fn+F7
+ KEYBOARD_KEY_090017=f21 # Fn+F8 touchpad toggle
+ KEYBOARD_KEY_090019=suspend # Fn+F12
+ KEYBOARD_KEY_09001a=brightnessup # Fn+Home
+ KEYBOARD_KEY_09001b=brightnessdown # Fn+End
+ KEYBOARD_KEY_09001d=zoom # Fn+Space
+ KEYBOARD_KEY_090011=prog1 # ThinkVantage button
+ KEYBOARD_KEY_090015=camera # Fn+F6 headset/camera VoIP key ??
+ KEYBOARD_KEY_090010=f20 # Microphone mute button; should be micmute
+
+# Lenovo 3000
+keyboard:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*3000*:pvr*
+ KEYBOARD_KEY_8b=switchvideomode # Fn+F7 video
+ KEYBOARD_KEY_96=wlan # Fn+F5 wireless
+ KEYBOARD_KEY_97=sleep # Fn+F4 suspend
+ KEYBOARD_KEY_98=suspend # Fn+F12 hibernate
+ KEYBOARD_KEY_b4=prog1 # Lenovo Care
+
+# lenovo-ideapad
+keyboard:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*IdeaPad*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnLENOVO*:pnS10-*:pvr*
+ KEYBOARD_KEY_81=rfkill # does nothing in BIOS
+ KEYBOARD_KEY_83=display_off # BIOS toggles screen state
+ KEYBOARD_KEY_b9=brightnessup # does nothing in BIOS
+ KEYBOARD_KEY_ba=brightnessdown # does nothing in BIOS
+ KEYBOARD_KEY_f1=camera # BIOS toggles camera power
+ KEYBOARD_KEY_f2=f21 # touchpad toggle (key alternately emits F2 and F3)
+ KEYBOARD_KEY_f3=f21
+
+# Thinkpad X200_Tablet
+keyboard:dmi:bvn*:bvr*:bd*:svnLENOVO*:pnThinkPad*X2*Tablet*:pvr*
+ KEYBOARD_KEY_5d=menu
+ KEYBOARD_KEY_63=fn
+ KEYBOARD_KEY_66=screenlock
+ KEYBOARD_KEY_67=cyclewindows # bezel circular arrow
+ KEYBOARD_KEY_68=setup # bezel setup / menu
+ KEYBOARD_KEY_6c=direction # rotate screen
+
+# ThinkPad X6 Tablet
+keyboard:dmi:bvn*:bvr*:bd*:svnLENOVO*:pnThinkPad*X6*:pvr*
+ KEYBOARD_KEY_6c=f21 # rotate
+ KEYBOARD_KEY_68=screenlock # screenlock
+ KEYBOARD_KEY_6b=esc # escape
+ KEYBOARD_KEY_6d=right # right on d-pad
+ KEYBOARD_KEY_6e=left # left on d-pad
+ KEYBOARD_KEY_71=up # up on d-pad
+ KEYBOARD_KEY_6f=down # down on d-pad
+ KEYBOARD_KEY_69=enter # enter on d-pad
+
+# IdeaPad
+keyboard:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*IdeaPad*Y550*:pvr*
+ KEYBOARD_KEY_95=media
+ KEYBOARD_KEY_a3=play
+
+# V480
+keyboard:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*Lenovo*V480*:pvr*
+ KEYBOARD_KEY_f1=f21
+
+# IdeaPad
+keyboard:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*IdeaPad*U300s*:pvr*
+ KEYBOARD_KEY_f1=f21
+ KEYBOARD_KEY_ce=f20
+
+###########################################################
+# Logitech
+###########################################################
+
+# iTouch
+keyboard:usb:v046DpC308*
+ KEYBOARD_KEY_90001=shop # Shopping
+ KEYBOARD_KEY_90002=config # iTouch
+ KEYBOARD_KEY_90003=finance # Finance
+ KEYBOARD_KEY_90004=prog1 # My Sites
+ KEYBOARD_KEY_90005=prog2 # Community
+ KEYBOARD_KEY_C0183=media # Media
+
+# Cordless Desktop S510
+keyboard:usb:v046DpC50C*
+ KEYBOARD_KEY_d4=zoomin
+ KEYBOARD_KEY_cc=zoomout
+
+# Wave cordless
+keyboard:usb:v046DpC317*
+ KEYBOARD_KEY_9001c=scale # expo
+ KEYBOARD_KEY_9001f=zoomout
+ KEYBOARD_KEY_90020=zoomin
+ KEYBOARD_KEY_9003d=prog1 # gadget
+ KEYBOARD_KEY_90005=camera
+ KEYBOARD_KEY_90018=media
+ KEYBOARD_KEY_90041=wordprocessor
+ KEYBOARD_KEY_90042=spreadsheet
+ KEYBOARD_KEY_90043=calendar
+ KEYBOARD_KEY_90044=prog2 # fn+f4 (program a)
+ KEYBOARD_KEY_90045=prog3 # fn+f5 (program b)
+ KEYBOARD_KEY_90046=prog4 # fn+f6 (program c)
+ KEYBOARD_KEY_90048=messenger # fn+f8 (msn messenger)
+ KEYBOARD_KEY_9002d=search # fn+f10 (search www)
+ KEYBOARD_KEY_9004b=find # fn+f11 (search pc)
+ KEYBOARD_KEY_9004c=ejectclosecd
+
+# Wave cordless
+keyboard:usb:v046DpC517*
+ KEYBOARD_KEY_c101f=zoomout
+ KEYBOARD_KEY_c1020=zoomin
+ KEYBOARD_KEY_c1005=camera
+ KEYBOARD_KEY_c0183=media
+ KEYBOARD_KEY_c1041=wordprocessor
+ KEYBOARD_KEY_c1042=spreadsheet
+ KEYBOARD_KEY_c1043=calendar
+ KEYBOARD_KEY_c1044=prog2 # fn+f4 (program a)
+ KEYBOARD_KEY_c1045=prog3 # fn+f5 (program b)
+ KEYBOARD_KEY_c1046=prog4 # fn+f6 (program c)
+ KEYBOARD_KEY_c1048=messenger # fn+f8 (msn messenger)
+ KEYBOARD_KEY_c104a=find # fn+f10 (search www)
+ KEYBOARD_KEY_c104c=ejectclosecd
+
+# Cordless Wave Pro
+keyboard:usb:v046DpC52[9B]*
+ KEYBOARD_KEY_0c01b6=camera
+ KEYBOARD_KEY_0c0183=media
+ KEYBOARD_KEY_0c0184=wordprocessor
+ KEYBOARD_KEY_0c0186=spreadsheet
+ KEYBOARD_KEY_0c018e=calendar
+ KEYBOARD_KEY_0c0223=homepage
+ KEYBOARD_KEY_0c01bc=messenger
+ KEYBOARD_KEY_0c018a=mail
+ KEYBOARD_KEY_0c0221=search
+ KEYBOARD_KEY_0c00b8=ejectcd
+ KEYBOARD_KEY_0c022d=zoomin
+ KEYBOARD_KEY_0c022e=zoomout
+
+# Logitech Presenter R400
+keyboard:usb:v046DpC52Dd*dc*dsc*dp*ic*isc*ip*in00*
+ KEYBOARD_KEY_070029=presentation
+ KEYBOARD_KEY_07003e=presentation
+ KEYBOARD_KEY_070037=displaytoggle
+
+# Internet Navigator
+keyboard:usb:v046DpC309*
+ KEYBOARD_KEY_90001=chat # Messenger/SMS
+ KEYBOARD_KEY_90002=camera # webcam
+ KEYBOARD_KEY_90003=prog1 # iTouch
+ KEYBOARD_KEY_90004=shop # Shopping
+ KEYBOARD_KEY_C0201=new # New (F1)
+ KEYBOARD_KEY_C0289=reply # Reply mail (F2)
+ KEYBOARD_KEY_C028B=forwardmail # Forward mail (F3)
+ KEYBOARD_KEY_C028C=send # Send (F4)
+ KEYBOARD_KEY_C021A=undo # Undo (F5).
+ KEYBOARD_KEY_C0279=redo # Redo (F6).
+ KEYBOARD_KEY_C0208=print # Print (F7)
+ KEYBOARD_KEY_C0207=save # Save (F8)
+ KEYBOARD_KEY_C0194=file # My Computer (F9)
+ KEYBOARD_KEY_C01A7=documents # My Documents (F10)
+ KEYBOARD_KEY_C01B6=images # My Pictures (F11) ??
+ KEYBOARD_KEY_C01B7=sound # My Music (F12) ??
+
+
+###########################################################
+# Maxdata
+###########################################################
+
+# Pro 7000
+keyboard:dmi:bvn*:bvr*:bd*:svnMAXDATA:pnPro*7000*:pvr*
+ KEYBOARD_KEY_97=prog2
+ KEYBOARD_KEY_9f=prog1
+ KEYBOARD_KEY_a0=mute # Fn+F5
+ KEYBOARD_KEY_82=www
+ KEYBOARD_KEY_ec=email
+ KEYBOARD_KEY_ae=volumedown # Fn+Down
+ KEYBOARD_KEY_b0=volumeup # Fn+Up
+ KEYBOARD_KEY_df=suspend # Fn+F2
+ KEYBOARD_KEY_f5=help
+
+###########################################################
+# Medion
+###########################################################
+
+# FID2060
+keyboard:dmi:bvn*:bvr*:bd*:svnMEDION*:pn*FID2060*:pvr*
+ KEYBOARD_KEY_6b=channeldown # Thottle Down
+ KEYBOARD_KEY_6d=channelup # Thottle Up
+
+# NB-A555
+keyboard:dmi:bvn*:bvr*:bd*:svnMEDIONNB:pnA555*:pvr*
+ KEYBOARD_KEY_63=www # N button
+ KEYBOARD_KEY_66=prog1 # link 1 button
+ KEYBOARD_KEY_67=email # envelope button
+ KEYBOARD_KEY_69=prog2 # link 2 button
+
+###########################################################
+# Microsoft
+###########################################################
+
+# Microsoft Natural Ergonomic Keyboard 4000
+keyboard:usb:v045Ep00DB*
+ KEYBOARD_KEY_c022d=zoomin
+ KEYBOARD_KEY_c022e=zoomout
+
+###########################################################
+# Micro Star
+###########################################################
+
+keyboard:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pn*
+keyboard:dmi:bvn*:bvr*:bd*:svnMicro-Star*:pn*
+ KEYBOARD_KEY_a0=mute # Fn+F9
+ KEYBOARD_KEY_ae=volumedown # Fn+F7
+ KEYBOARD_KEY_b0=volumeup # Fn+F8
+ KEYBOARD_KEY_b2=www # e button
+ KEYBOARD_KEY_df=sleep # Fn+F12
+ KEYBOARD_KEY_e2=bluetooth # satellite dish2
+ KEYBOARD_KEY_e4=f21 # Fn+F3 Touchpad disable
+ KEYBOARD_KEY_ec=email # envelope button
+ KEYBOARD_KEY_ee=camera # Fn+F6 camera disable
+ KEYBOARD_KEY_f6=wlan # satellite dish1
+ KEYBOARD_KEY_f7=brightnessdown # Fn+F4
+ KEYBOARD_KEY_f8=brightnessup # Fn+F5
+ KEYBOARD_KEY_f9=search
+
+#
+keyboard:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pnGE60*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pnGE70*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnMicro-Star*:pn*:pvr*
+ KEYBOARD_KEY_c2=ejectcd
+
+#
+keyboard:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pn*U-100*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pn*U100*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pn*N033:*
+ KEYBOARD_KEY_f7=reserved
+ KEYBOARD_KEY_f8=reserved
+
+#
+keyboard:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pnU90/U100:*
+ KEYBOARD_KEY_e4=reserved
+
+###########################################################
+# MSI
+###########################################################
+
+keyboard:name:MSI Laptop hotkeys:dmi:bvn*:bvr*:bd*:svn*:pnM[iI][cC][rR][oO]-S[tT][aA][rR]*:pvr*
+ KEYBOARD_KEY_0213=f22
+ KEYBOARD_KEY_0214=f23
+
+###########################################################
+# OLPC
+###########################################################
+
+# XO
+keyboard:dmi:bvn*:bvr*:bd*:svnOLPC:pnXO:*
+ KEYBOARD_KEY_59=fn
+ KEYBOARD_KEY_81=fn_esc
+ KEYBOARD_KEY_f9=camera
+ KEYBOARD_KEY_f8=sound # Fn+CAMERA = Mic
+ KEYBOARD_KEY_43=brightnessdown
+ KEYBOARD_KEY_44=brightnessup
+ KEYBOARD_KEY_57=volumedown
+ KEYBOARD_KEY_58=volumeup
+ KEYBOARD_KEY_bb=f1
+ KEYBOARD_KEY_bc=f2
+ KEYBOARD_KEY_bd=f3
+ KEYBOARD_KEY_be=f4
+ KEYBOARD_KEY_bf=f5
+ KEYBOARD_KEY_c0=f6
+ KEYBOARD_KEY_c1=f7
+ KEYBOARD_KEY_c2=f8
+ KEYBOARD_KEY_c3=f9
+ KEYBOARD_KEY_c4=f10
+ KEYBOARD_KEY_c7=f11
+ KEYBOARD_KEY_d8=f12
+ KEYBOARD_KEY_f7=f13
+ KEYBOARD_KEY_f6=f14
+ KEYBOARD_KEY_f5=f15
+ KEYBOARD_KEY_f4=f16
+ KEYBOARD_KEY_f3=f17
+ KEYBOARD_KEY_f2=f18
+ KEYBOARD_KEY_f1=f19
+ KEYBOARD_KEY_f0=f20
+ KEYBOARD_KEY_ef=f21
+ KEYBOARD_KEY_ee=chat
+ KEYBOARD_KEY_e4=chat
+ KEYBOARD_KEY_dd=menu # Frame
+ KEYBOARD_KEY_da=prog1 # Fn+Frame
+ KEYBOARD_KEY_d3=delete
+ KEYBOARD_KEY_d2=insert
+ KEYBOARD_KEY_c9=pageup
+ KEYBOARD_KEY_d1=pagedown
+ KEYBOARD_KEY_c7=home
+ KEYBOARD_KEY_cF=end
+ KEYBOARD_KEY_73=hp
+ KEYBOARD_KEY_7e=hp
+ KEYBOARD_KEY_db=leftmeta # left grab
+ KEYBOARD_KEY_dc=rightmeta # right grab
+ KEYBOARD_KEY_85=rightmeta # Right grab releases on a different scancode
+ KEYBOARD_KEY_d6=kbdillumtoggle # Fn+Space
+ KEYBOARD_KEY_69=switchvideomode # Brightness key
+ KEYBOARD_KEY_65=kp8 # up
+ KEYBOARD_KEY_66=kp2 # down
+ KEYBOARD_KEY_67=kp4 # left
+ KEYBOARD_KEY_68=kp6 # right
+ KEYBOARD_KEY_e5=kp9 # pgup
+ KEYBOARD_KEY_e6=kp3 # pgdn
+ KEYBOARD_KEY_e7=kp7 # home
+ KEYBOARD_KEY_e8=kp1 # end
+
+###########################################################
+# Onkyo
+###########################################################
+
+keyboard:dmi:bvn*:bvr*:bd*:svnONKYO*CORPORATION:pnONKYOPC:*
+ KEYBOARD_KEY_a0=mute # Fn+D
+ KEYBOARD_KEY_ae=volumedown # Fn+F
+ KEYBOARD_KEY_b0=volumeup # Fn+G
+ KEYBOARD_KEY_df=sleep # Fn+W
+ KEYBOARD_KEY_e0=bluetooth # Fn+H
+ KEYBOARD_KEY_e2=cyclewindows # Fn+Esc
+ KEYBOARD_KEY_ee=battery # Fn+Q
+ KEYBOARD_KEY_f0=media # Fn+R
+ KEYBOARD_KEY_f5=switchvideomode # Fn+E
+ KEYBOARD_KEY_f6=camera # Fn+T
+ KEYBOARD_KEY_f7=f21 # Fn+Y (touchpad toggle)
+ KEYBOARD_KEY_f8=brightnessup # Fn+S
+ KEYBOARD_KEY_f9=brightnessdown # Fn+A
+ KEYBOARD_KEY_fb=wlan # Fn+J
+
+###########################################################
+# OQO
+###########################################################
+
+# Model 2
+keyboard:dmi:bvn*:bvr*:bd*:svnOQO*Inc.*:pnOQO*Model*2*:pvr*
+ KEYBOARD_KEY_8e=wlan
+ KEYBOARD_KEY_f0=switchvideomode
+ KEYBOARD_KEY_f1=mute
+ KEYBOARD_KEY_f2=volumedown
+ KEYBOARD_KEY_f3=volumeup
+
+###########################################################
+# Quanta
+###########################################################
+
+keyboard:dmi:bvn*:bvr*:bd*:svn*:pn*:pvr*:rvnQuanta:rn30B7:rvr65.2B:*
+ KEYBOARD_KEY_88=media # "quick play
+
+###########################################################
+# Samsung
+###########################################################
+
+keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*
+ KEYBOARD_KEY_74=prog1 # User key
+ KEYBOARD_KEY_75=www
+ KEYBOARD_KEY_78=mail
+ KEYBOARD_KEY_82=!switchvideomode # Fn+F4 CRT/LCD (high keycode: "displaytoggle")
+ KEYBOARD_KEY_83=!battery # Fn+F2
+ KEYBOARD_KEY_84=!prog1 # Fn+F5 backlight on/off
+ KEYBOARD_KEY_86=!wlan # Fn+F9
+ KEYBOARD_KEY_88=!brightnessup # Fn+Up
+ KEYBOARD_KEY_89=!brightnessdown # Fn+Down
+ KEYBOARD_KEY_b1=!prog2 # Fn+F7 run Samsung Magic Doctor (keypressed event is generated twice)
+ KEYBOARD_KEY_b3=!prog3 # Fn+F8 switch power mode (battery/dynamic/performance)
+ KEYBOARD_KEY_b4=!wlan # Fn+F9 (X60P)
+ KEYBOARD_KEY_c5=!prog3 # Fn+F8 switch power mode (battery/dynamic/performance)
+ KEYBOARD_KEY_d5=!wlan # Fn+F12 wlan/airplane switch
+ KEYBOARD_KEY_f7=!f22 # Fn+F10 Touchpad on
+ KEYBOARD_KEY_f9=!f23 # Fn+F10 Touchpad off
+
+# Series 3
+keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*300E[457]*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*200E[45]*:pvr*
+ KEYBOARD_KEY_ce=! # Fn+F1 launch control setting
+
+# Series 5
+keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*530U*:pvr*
+ KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings
+ KEYBOARD_KEY_a8=! # Fn Lock - Function lock on
+ KEYBOARD_KEY_a9=! # Fn Lock - Function lock off
+
+keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*550P*:pvr*
+ KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings
+ KEYBOARD_KEY_a8=! # Fn Lock - Function lock on
+ KEYBOARD_KEY_a9=! # Fn Lock - Function lock off
+
+keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700Z*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*940X3G*:pvr*
+ KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings
+ KEYBOARD_KEY_a0=!mute # Fn+F6 mute
+ KEYBOARD_KEY_ae=!volumedown # Fn+F7
+ KEYBOARD_KEY_b0=!volumeup # Fn+F8
+ KEYBOARD_KEY_97=!kbdillumdown # Fn+F9 keyboard backlight down
+ KEYBOARD_KEY_96=!kbdillumup # Fn+F10 keyboard backlight up
+ KEYBOARD_KEY_b3=!prog3 # Fn+F11 fan/cooling mode changer
+
+# Series 9
+keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*90X3A*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*900X[34]*:pvr*
+ KEYBOARD_KEY_ce=! # Fn+F8 keyboard backlight up
+ KEYBOARD_KEY_8d=! # Fn+F7 keyboard backlight down
+ KEYBOARD_KEY_96=! # Fn+F1 performance mode (?)
+ KEYBOARD_KEY_97=! # Fn+F12 Wi-Fi toggle
+ KEYBOARD_KEY_d5=! # Fn+F6 battery life extender
+
+# SQ1US
+keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pnSQ1US:pvr*
+ KEYBOARD_KEY_d4=menu
+ KEYBOARD_KEY_d8=f1
+ KEYBOARD_KEY_d9=f10
+ KEYBOARD_KEY_d6=f3
+ KEYBOARD_KEY_d7=f9
+ KEYBOARD_KEY_e4=f5
+ KEYBOARD_KEY_ee=f11
+
+# SX20S
+keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*SX20S*:pvr*
+ KEYBOARD_KEY_74=mute
+ KEYBOARD_KEY_75=mute
+ KEYBOARD_KEY_77=f22 # Touchpad on
+ KEYBOARD_KEY_79=f23 # Touchpad off
+
+keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700Z*:pvr*
+ KEYBOARD_KEY_ba=ejectcd
+ KEYBOARD_KEY_96=keyboardbrightnessup
+ KEYBOARD_KEY_97=keyboardbrightnessdown
+
+keyboard:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700T*:pvr*
+ KEYBOARD_KEY_ad=leftmeta
+
+###########################################################
+# SONY
+###########################################################
+
+# sony-laptop driver
+keyboard:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*
+ KEYBOARD_KEY_06=mute # Fn+F2
+ KEYBOARD_KEY_07=volumedown # Fn+F3
+ KEYBOARD_KEY_08=volumeup # Fn+F4
+ KEYBOARD_KEY_09=brightnessdown # Fn+F5
+ KEYBOARD_KEY_0a=brightnessup # Fn+F6
+ KEYBOARD_KEY_0b=switchvideomode # Fn+F7
+ KEYBOARD_KEY_0e=zoom # Fn+F10
+ KEYBOARD_KEY_10=suspend # Fn+F12
+
+keyboard:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-C1*:pvr*
+keyboard:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-K25*:pvr*
+keyboard:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-F[1-6]*:pvr*
+keyboard:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-FX*:pvr*
+keyboard:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-FRV*:pvr*
+keyboard:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-GR*:pvr*
+keyboard:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-TR*:pvr*
+keyboard:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-NV*:pvr*
+keyboard:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-Z*:pvr*
+keyboard:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*VGN-S360*:pvr*
+ KEYBOARD_KEY_06=battery
+ KEYBOARD_KEY_07=mute
+
+keyboard:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVGN-AR71*:pvr*
+keyboard:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVGN-FW*:pvr*
+keyboard:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVGN-Z21*:pvr*
+ KEYBOARD_KEY_00=brightnessdown # Fn+F5
+ KEYBOARD_KEY_10=brightnessup # Fn+F6
+ KEYBOARD_KEY_11=switchvideomode # Fn+F7
+ KEYBOARD_KEY_12=zoomout
+ KEYBOARD_KEY_14=zoomin
+ KEYBOARD_KEY_15=suspend # Fn+F12
+ KEYBOARD_KEY_17=prog1
+ KEYBOARD_KEY_20=media
+
+keyboard:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVPC*:pvr*
+ KEYBOARD_KEY_05=f21 # Fn+F1 -> KEY_F21 (The actual touchpad toggle)
+ KEYBOARD_KEY_0d=zoomout # Fn+F9
+ KEYBOARD_KEY_0e=zoomin # Fn+F10
+
+###########################################################
+# Toshiba
+###########################################################
+
+# Satellite A100
+keyboard:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSATELLITE*A100:pvr*
+ KEYBOARD_KEY_a4=stopcd
+ KEYBOARD_KEY_b2=www
+
+# Satellite A110
+keyboard:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSatellite*A110:pvr*
+ KEYBOARD_KEY_92=stop
+ KEYBOARD_KEY_93=www
+ KEYBOARD_KEY_94=media
+ KEYBOARD_KEY_9e=f22 # Touchpad on
+ KEYBOARD_KEY_9f=f23 # Touchpad off
+ KEYBOARD_KEY_b9=nextsong
+ KEYBOARD_KEY_d9=brightnessup
+ KEYBOARD_KEY_ee=screenlock
+ KEYBOARD_KEY_f4=previoussong
+ KEYBOARD_KEY_f7=playpause
+
+# Satellite M30X
+keyboard:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSatellite*M30X:pvr*
+ KEYBOARD_KEY_ef=brightnessdown
+ KEYBOARD_KEY_d9=brightnessup
+ KEYBOARD_KEY_ee=screenlock
+ KEYBOARD_KEY_93=media
+ KEYBOARD_KEY_9e=f22 # touchpad enable
+ KEYBOARD_KEY_9f=f23 # touchpad disable
+
+# Satellite P75-A
+keyboard:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSatellite*P75-A:pvr*
+ KEYBOARD_KEY_ef=brightnessdown
+ KEYBOARD_KEY_ee=brightnessup
+ KEYBOARD_KEY_a9=switchvideomode # switch display outputs
+ KEYBOARD_KEY_d4=wlan # RF Switch Off
+
+###########################################################
+# VIA
+###########################################################
+
+keyboard:dmi:bvn*:bvr*:bd*:svnVIA:pnK8N800:pvr*
+ KEYBOARD_KEY_81=prog1
+
+###########################################################
+# Zepto
+###########################################################
+
+# Znote
+keyboard:dmi:bvn*:bvr*:bd*:svnZepto:pnZnote:*
+ KEYBOARD_KEY_93=switchvideomode # Fn+F3 Toggle Video Output
+ KEYBOARD_KEY_95=brightnessdown # Fn+F4 Brightness Down
+ KEYBOARD_KEY_91=brightnessup # Fn+F5 Brightness Up
+ KEYBOARD_KEY_a5=f23 # Fn+F6 Disable Touchpad
+ KEYBOARD_KEY_a6=f22 # Fn+F6 Enable Touchpad
+ KEYBOARD_KEY_a7=bluetooth # Fn+F10 Enable Bluetooth
+ KEYBOARD_KEY_a9=bluetooth # Fn+F10 Disable Bluetooth
+ KEYBOARD_KEY_f1=wlan # RF Switch Off
+ KEYBOARD_KEY_f2=wlan # RF Switch On
+ KEYBOARD_KEY_f4=prog1 # P1 Button
+ KEYBOARD_KEY_f3=prog2 # P2 Button
+ KEYBOARD_KEY_a0=! # mute
+ KEYBOARD_KEY_ae=! # volume down
+ KEYBOARD_KEY_b0=! # volume up
+
+# Znote 6615WD
+keyboard:dmi:bvn*:bvr*:bd*:svnZepto:pnZnote*6615WD:*
+ KEYBOARD_KEY_a0=! # mute
+ KEYBOARD_KEY_ae=! # volume down
+ KEYBOARD_KEY_b0=! # volume up
+
+###########################################################
+# Other
+###########################################################
+
+# Common Volume Keys
+keyboard:dmi:bvn*:bvr*:bd*:svnFUJITSU*SIEMENS:pnAMILO*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnFOXCONN:pnQBOOK:*
+keyboard:dmi:bvn*:bvr*:bd*:svnMTC:pn*:pvrA0:*
+keyboard:dmi:bvn*:bvr*:bd*:svnMio*Technology:pnN890:*
+keyboard:dmi:bvn*:bvr*:bd*:svnPEGATRON*CORP.:pnSpring*Peak:*
+keyboard:dmi:bvn*:bvr*:bd*:svnTOSHIBA:pnSatellite*[uU]30[05]*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnTOSHIBA:pnSatellite*Pro*[uU]300*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnTOSHIBA:pnSATELLITE*[uU]500*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnViooo*Corporation:pnPT17:*
+keyboard:dmi:bvn*:bvr*:bd*:svnHANNspree:pnSN10E100:*
+keyboard:dmi:bvn*:bvr*:bd*:svnGIGABYTE:pni1520M:*
+keyboard:dmi:bvn*:bvr*:bd*:svnBenQ:pn*nScreen*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnBenQ:pnJoybook*Lite*:pvr*
+keyboard:dmi:bvn*:bvr*:bd*:svnDIXONSP:pnDIXON*:pvr*
+ KEYBOARD_KEY_a0=! # mute
+ KEYBOARD_KEY_ae=! # volume down
+ KEYBOARD_KEY_b0=! # volume up
diff --git a/hwdb/Makefile b/hwdb/Makefile
new file mode 120000
index 0000000000..bd1047548b
--- /dev/null
+++ b/hwdb/Makefile
@@ -0,0 +1 @@
+../src/Makefile \ No newline at end of file
diff --git a/keymaps-force-release/common-volume-keys b/keymaps-force-release/common-volume-keys
deleted file mode 100644
index 3a7654d735..0000000000
--- a/keymaps-force-release/common-volume-keys
+++ /dev/null
@@ -1,3 +0,0 @@
-0xa0 #mute
-0xae #volume down
-0xb0 #volume up
diff --git a/keymaps-force-release/dell-touchpad b/keymaps-force-release/dell-touchpad
deleted file mode 100644
index 18e9bdee66..0000000000
--- a/keymaps-force-release/dell-touchpad
+++ /dev/null
@@ -1 +0,0 @@
-0x9E
diff --git a/keymaps-force-release/dell-xps b/keymaps-force-release/dell-xps
deleted file mode 100644
index 69f7899ad7..0000000000
--- a/keymaps-force-release/dell-xps
+++ /dev/null
@@ -1 +0,0 @@
-0x8C
diff --git a/keymaps-force-release/hp-other b/keymaps-force-release/hp-other
deleted file mode 100644
index 6621370095..0000000000
--- a/keymaps-force-release/hp-other
+++ /dev/null
@@ -1,3 +0,0 @@
-# list of scancodes (hex or decimal), optional comment
-0xd8 # Touchpad off
-0xd9 # Touchpad on
diff --git a/keymaps-force-release/samsung-other b/keymaps-force-release/samsung-other
deleted file mode 100644
index c51123a0b6..0000000000
--- a/keymaps-force-release/samsung-other
+++ /dev/null
@@ -1,10 +0,0 @@
-# list of scancodes (hex or decimal), optional comment
-0x82 # Fn+F4 CRT/LCD
-0x83 # Fn+F2 battery
-0x84 # Fn+F5 backlight on/off
-0x86 # Fn+F9 WLAN
-0x88 # Fn-Up brightness up
-0x89 # Fn-Down brightness down
-0xB3 # Fn+F8 switch power mode (battery/dynamic/performance)
-0xF7 # Fn+F10 Touchpad on
-0xF9 # Fn+F10 Touchpad off
diff --git a/keymaps-force-release/samsung-series-9 b/keymaps-force-release/samsung-series-9
deleted file mode 100644
index 65707effb7..0000000000
--- a/keymaps-force-release/samsung-series-9
+++ /dev/null
@@ -1,6 +0,0 @@
-# list of scancodes (hex or decimal), optional comment
-0xCE # Fn+F8 keyboard backlit up
-0x8D # Fn+F7 keyboard backlit down
-0x97 # Fn+F12 wifi on/off
-0x96 # Fn+F1 performance mode (?)
-0xD5 # Fn+F6 battery life extender
diff --git a/keymaps/acer b/keymaps/acer
deleted file mode 100644
index 4e7c297dea..0000000000
--- a/keymaps/acer
+++ /dev/null
@@ -1,22 +0,0 @@
-0xA5 help # Fn+F1
-0xA6 setup # Fn+F2 Acer eSettings
-0xA7 battery # Fn+F3 Power Management
-0xA9 switchvideomode # Fn+F5
-0xB3 euro
-0xB4 dollar
-0xCE brightnessup # Fn+Right
-0xD4 bluetooth # (toggle) off-to-on
-0xD5 wlan # (toggle) on-to-off
-0xD6 wlan # (toggle) off-to-on
-0xD7 bluetooth # (toggle) on-to-off
-0xD8 bluetooth # (toggle) off-to-on
-0xD9 brightnessup # Fn+Right
-0xEE brightnessup # Fn+Right
-0xEF brightnessdown # Fn+Left
-0xF1 f22 # Fn+F7 Touchpad toggle (off-to-on)
-0xF2 f23 # Fn+F7 Touchpad toggle (on-to-off)
-0xF3 prog2 # "P2" programmable button
-0xF4 prog1 # "P1" programmable button
-0xF5 presentation
-0xF8 fn
-0xF9 f23 # Launch NTI shadow
diff --git a/keymaps/acer-aspire_5720 b/keymaps/acer-aspire_5720
deleted file mode 100644
index 3ff9de3f32..0000000000
--- a/keymaps/acer-aspire_5720
+++ /dev/null
@@ -1,5 +0,0 @@
-0x84 bluetooth # sent when bluetooth module missing, and key pressed
-0x92 media # acer arcade
-0xD4 bluetooth # bluetooth on
-0xD9 bluetooth # bluetooth off
-0xF4 prog3 # e-key
diff --git a/keymaps/acer-aspire_5920g b/keymaps/acer-aspire_5920g
deleted file mode 100644
index 633c4e854c..0000000000
--- a/keymaps/acer-aspire_5920g
+++ /dev/null
@@ -1,5 +0,0 @@
-0x8A media
-0x92 media
-0xA6 setup
-0xB2 www
-0xD9 bluetooth # (toggle) on-to-off
diff --git a/keymaps/acer-aspire_6920 b/keymaps/acer-aspire_6920
deleted file mode 100644
index 699c954b4e..0000000000
--- a/keymaps/acer-aspire_6920
+++ /dev/null
@@ -1,5 +0,0 @@
-0xD9 bluetooth # (toggle) on-to-off
-0x92 media
-0x9E back
-0x83 rewind
-0x89 fastforward
diff --git a/keymaps/acer-aspire_8930 b/keymaps/acer-aspire_8930
deleted file mode 100644
index fb27bfb4f5..0000000000
--- a/keymaps/acer-aspire_8930
+++ /dev/null
@@ -1,5 +0,0 @@
-0xCA prog3 # key 'HOLD' on cine dash media console
-0x83 rewind
-0x89 fastforward
-0x92 media # key 'ARCADE' on cine dash media console
-0x9E back
diff --git a/keymaps/acer-travelmate_c300 b/keymaps/acer-travelmate_c300
deleted file mode 100644
index bfef4cf868..0000000000
--- a/keymaps/acer-travelmate_c300
+++ /dev/null
@@ -1,5 +0,0 @@
-0x67 f24 # FIXME: rotate screen
-0x68 up
-0x69 down
-0x6B fn
-0x6C screenlock # FIXME: lock tablet device/buttons
diff --git a/keymaps/asus b/keymaps/asus
deleted file mode 100644
index 2a5995f982..0000000000
--- a/keymaps/asus
+++ /dev/null
@@ -1,3 +0,0 @@
-0xED volumeup
-0xEE volumedown
-0xEF mute
diff --git a/keymaps/compaq-e_evo b/keymaps/compaq-e_evo
deleted file mode 100644
index 5fbc573aa4..0000000000
--- a/keymaps/compaq-e_evo
+++ /dev/null
@@ -1,4 +0,0 @@
-0xA3 www # I key
-0x9A search
-0x9E email
-0x9F homepage
diff --git a/keymaps/dell b/keymaps/dell
deleted file mode 100644
index 4f907b3eef..0000000000
--- a/keymaps/dell
+++ /dev/null
@@ -1,29 +0,0 @@
-0x81 playpause # Play/Pause
-0x82 stopcd # Stop
-0x83 previoussong # Previous song
-0x84 nextsong # Next song
-0x85 brightnessdown # Fn+Down arrow Brightness Down
-0x86 brightnessup # Fn+Up arrow Brightness Up
-0x87 battery # Fn+F3 battery icon
-0x88 unknown # Fn+F2 Turn On/Off Wireless - handled in hardware
-0x89 ejectclosecd # Fn+F10 Eject CD
-0x8A suspend # Fn+F1 hibernate
-0x8B switchvideomode # Fn+F8 CRT/LCD (high keycode: "displaytoggle")
-0x8C f23 # Fn+Right arrow Auto Brightness
-0x8F switchvideomode # Fn+F7 aspect ratio
-0x90 previoussong # Front panel previous song
-0x91 prog1 # Wifi Catcher (DELL Specific)
-0x92 media # MediaDirect button (house icon)
-0x93 f23 # FIXME Fn+Left arrow Auto Brightness
-0x95 camera # Shutter button Takes a picture if optional camera available
-0x97 email # Tablet email button
-0x98 f21 # FIXME: Tablet screen rotatation
-0x99 nextsong # Front panel next song
-0x9A setup # Tablet tools button
-0x9B switchvideomode # Display Toggle button
-0x9E f21 #touchpad toggle
-0xA2 playpause # Front panel play/pause
-0xA4 stopcd # Front panel stop
-0xED media # MediaDirect button
-0xD8 screenlock # FIXME: Tablet lock button
-0xD9 f21 # touchpad toggle
diff --git a/keymaps/dell-latitude-xt2 b/keymaps/dell-latitude-xt2
deleted file mode 100644
index 39872f559d..0000000000
--- a/keymaps/dell-latitude-xt2
+++ /dev/null
@@ -1,4 +0,0 @@
-0x9B up # tablet rocker up
-0x9E enter # tablet rocker press
-0x9F back # tablet back
-0xA3 down # tablet rocker down
diff --git a/keymaps/everex-xt5000 b/keymaps/everex-xt5000
deleted file mode 100644
index 4823a832f5..0000000000
--- a/keymaps/everex-xt5000
+++ /dev/null
@@ -1,7 +0,0 @@
-0x5C media
-0x65 f21 # Fn+F5 Touchpad toggle
-0x67 prog3 # Fan Speed Control button
-0x6F brightnessup
-0x7F brightnessdown
-0xB2 www
-0xEC mail
diff --git a/keymaps/fujitsu-amilo_li_2732 b/keymaps/fujitsu-amilo_li_2732
deleted file mode 100644
index 9b8b36a170..0000000000
--- a/keymaps/fujitsu-amilo_li_2732
+++ /dev/null
@@ -1,3 +0,0 @@
-0xD9 brightnessdown # Fn+F8 brightness down
-0xEF brightnessup # Fn+F9 brightness up
-0xA9 switchvideomode # Fn+F10 Cycle between available video outputs
diff --git a/keymaps/fujitsu-amilo_pa_2548 b/keymaps/fujitsu-amilo_pa_2548
deleted file mode 100644
index f7b0c52444..0000000000
--- a/keymaps/fujitsu-amilo_pa_2548
+++ /dev/null
@@ -1,3 +0,0 @@
-0xE0 volumedown
-0xE1 volumeup
-0xE5 prog1
diff --git a/keymaps/fujitsu-amilo_pro_edition_v3505 b/keymaps/fujitsu-amilo_pro_edition_v3505
deleted file mode 100644
index d2e38cbb23..0000000000
--- a/keymaps/fujitsu-amilo_pro_edition_v3505
+++ /dev/null
@@ -1,4 +0,0 @@
-0xA5 help # Fn-F1
-0xA9 switchvideomode # Fn-F3
-0xD9 brightnessdown # Fn-F8
-0xE0 brightnessup # Fn-F9
diff --git a/keymaps/fujitsu-amilo_pro_v3205 b/keymaps/fujitsu-amilo_pro_v3205
deleted file mode 100644
index 43e3199d59..0000000000
--- a/keymaps/fujitsu-amilo_pro_v3205
+++ /dev/null
@@ -1,2 +0,0 @@
-0xF4 f21 # FIXME: silent-mode decrease CPU/GPU clock
-0xF7 switchvideomode # Fn+F3
diff --git a/keymaps/fujitsu-amilo_si_1520 b/keymaps/fujitsu-amilo_si_1520
deleted file mode 100644
index 1419bd9b5e..0000000000
--- a/keymaps/fujitsu-amilo_si_1520
+++ /dev/null
@@ -1,6 +0,0 @@
-0xE1 wlan
-0xF3 wlan
-0xEE brightnessdown
-0xE0 brightnessup
-0xE2 bluetooth
-0xF7 video
diff --git a/keymaps/fujitsu-esprimo_mobile_v5 b/keymaps/fujitsu-esprimo_mobile_v5
deleted file mode 100644
index d3d056b366..0000000000
--- a/keymaps/fujitsu-esprimo_mobile_v5
+++ /dev/null
@@ -1,4 +0,0 @@
-0xA9 switchvideomode
-0xD9 brightnessdown
-0xDF sleep
-0xEF brightnessup
diff --git a/keymaps/fujitsu-esprimo_mobile_v6 b/keymaps/fujitsu-esprimo_mobile_v6
deleted file mode 100644
index 52c70c50cb..0000000000
--- a/keymaps/fujitsu-esprimo_mobile_v6
+++ /dev/null
@@ -1,2 +0,0 @@
-0xCE brightnessup
-0xEF brightnessdown
diff --git a/keymaps/genius-slimstar-320 b/keymaps/genius-slimstar-320
deleted file mode 100644
index d0a3656dd8..0000000000
--- a/keymaps/genius-slimstar-320
+++ /dev/null
@@ -1,35 +0,0 @@
-# Genius SlimStar 320
-#
-# Only buttons which are not properly mapped yet are configured below
-
-# "Scroll wheel", a circular up/down/left/right button. Aimed for scolling,
-# but since there are no scrollleft/scrollright, let's map to back/forward.
-0x900f0 scrollup
-0x900f1 scrolldown
-0x900f3 back
-0x900f2 forward
-
-# Multimedia buttons, left side (from left to right)
-# [W]
-0x900f5 wordprocessor
-# [Ex]
-0x900f6 spreadsheet
-# [P]
-0x900f4 presentation
-# Other five (calculator, playpause, stop, mute and eject) are OK
-
-# Right side, from left to right
-# [e]
-0xc0223 www
-# "man"
-0x900f7 chat
-# "Y"
-0x900fb prog1
-# [X]
-0x900f8 close
-# "picture"
-0x900f9 graphicseditor
-# "two windows"
-0x900fd scale
-# "lock"
-0x900fc screenlock
diff --git a/keymaps/hewlett-packard b/keymaps/hewlett-packard
deleted file mode 100644
index 4461fa2ce5..0000000000
--- a/keymaps/hewlett-packard
+++ /dev/null
@@ -1,12 +0,0 @@
-0x81 fn_esc
-0x89 battery # FnF8
-0x8A screenlock # FnF6
-0x8B camera
-0x8C media # music
-0x8E dvd
-0xB1 help
-0xB3 f23 # FIXME: Auto brightness
-0xD7 wlan
-0x92 brightnessdown # FnF7 (FnF9 on 6730b)
-0x97 brightnessup # FnF8 (FnF10 on 6730b)
-0xEE switchvideomode # FnF4
diff --git a/keymaps/hewlett-packard-2510p_2530p b/keymaps/hewlett-packard-2510p_2530p
deleted file mode 100644
index 41ad2e9b5a..0000000000
--- a/keymaps/hewlett-packard-2510p_2530p
+++ /dev/null
@@ -1,2 +0,0 @@
-0xD8 f23 # touchpad off
-0xD9 f22 # touchpad on
diff --git a/keymaps/hewlett-packard-compaq_elitebook b/keymaps/hewlett-packard-compaq_elitebook
deleted file mode 100644
index 42007c5483..0000000000
--- a/keymaps/hewlett-packard-compaq_elitebook
+++ /dev/null
@@ -1,2 +0,0 @@
-0x88 presentation
-0xD9 help # I key (high keycode: "info")
diff --git a/keymaps/hewlett-packard-hdx9494nr b/keymaps/hewlett-packard-hdx9494nr
deleted file mode 100644
index 92217879c8..0000000000
--- a/keymaps/hewlett-packard-hdx9494nr
+++ /dev/null
@@ -1,3 +0,0 @@
-0xB2 www # FnF3
-0xD8 f23 # touchpad off
-0xD9 f22 # touchpad on
diff --git a/keymaps/hewlett-packard-pavilion b/keymaps/hewlett-packard-pavilion
deleted file mode 100644
index 3d3cefc8e6..0000000000
--- a/keymaps/hewlett-packard-pavilion
+++ /dev/null
@@ -1,3 +0,0 @@
-0x88 media # FIXME: quick play
-0xD8 f23 # touchpad off
-0xD9 f22 # touchpad on
diff --git a/keymaps/hewlett-packard-presario-2100 b/keymaps/hewlett-packard-presario-2100
deleted file mode 100644
index 1df39dcbd2..0000000000
--- a/keymaps/hewlett-packard-presario-2100
+++ /dev/null
@@ -1,3 +0,0 @@
-0xF0 help
-0xF1 screenlock
-0xF3 search
diff --git a/keymaps/hewlett-packard-tablet b/keymaps/hewlett-packard-tablet
deleted file mode 100644
index d19005ab90..0000000000
--- a/keymaps/hewlett-packard-tablet
+++ /dev/null
@@ -1,6 +0,0 @@
-0x82 prog2 # Funny Key
-0x83 prog1 # Q
-0x84 tab
-0x85 esc
-0x86 pageup
-0x87 pagedown
diff --git a/keymaps/hewlett-packard-tx2 b/keymaps/hewlett-packard-tx2
deleted file mode 100644
index 36a690fcf6..0000000000
--- a/keymaps/hewlett-packard-tx2
+++ /dev/null
@@ -1,3 +0,0 @@
-0xC2 media
-0xD8 f23 # Toggle touchpad button on tx2 (OFF)
-0xD9 f22 # Toggle touchpad button on tx2 (ON)
diff --git a/keymaps/hewlett-packard_elitebook-8440p b/keymaps/hewlett-packard_elitebook-8440p
deleted file mode 100644
index e0c2a1a859..0000000000
--- a/keymaps/hewlett-packard_elitebook-8440p
+++ /dev/null
@@ -1,5 +0,0 @@
-0x88 www
-0xA0 mute
-0xAE volumedown
-0xB0 volumeup
-0xEC mail
diff --git a/keymaps/hewlett-packard_elitebook-8460p b/keymaps/hewlett-packard_elitebook-8460p
deleted file mode 100644
index 1fe1b7237c..0000000000
--- a/keymaps/hewlett-packard_elitebook-8460p
+++ /dev/null
@@ -1,3 +0,0 @@
-0xF8 wlan # Wireless HW switch button
-0xB3 prog1 # Fn+F11 - Ambient Light Sensor button
-0xB1 prog2 # Fn+ESC - System information button
diff --git a/keymaps/ibm-thinkpad-usb-keyboard-trackpoint b/keymaps/ibm-thinkpad-usb-keyboard-trackpoint
deleted file mode 100644
index 027e50bf88..0000000000
--- a/keymaps/ibm-thinkpad-usb-keyboard-trackpoint
+++ /dev/null
@@ -1,7 +0,0 @@
-0x900f0 screenlock
-0x900f1 wlan
-0x900f2 switchvideomode
-0x900f3 suspend
-0x900f4 brightnessup
-0x900f5 brightnessdown
-0x900f8 zoom
diff --git a/keymaps/inventec-symphony_6.0_7.0 b/keymaps/inventec-symphony_6.0_7.0
deleted file mode 100644
index 4a8b4ba5a7..0000000000
--- a/keymaps/inventec-symphony_6.0_7.0
+++ /dev/null
@@ -1,2 +0,0 @@
-0xF3 prog2
-0xF4 prog1
diff --git a/keymaps/lenovo-3000 b/keymaps/lenovo-3000
deleted file mode 100644
index 5bd165654a..0000000000
--- a/keymaps/lenovo-3000
+++ /dev/null
@@ -1,5 +0,0 @@
-0x8B switchvideomode # Fn+F7 video
-0x96 wlan # Fn+F5 wireless
-0x97 sleep # Fn+F4 suspend
-0x98 suspend # Fn+F12 hibernate
-0xB4 prog1 # Lenovo Care
diff --git a/keymaps/lenovo-ideapad b/keymaps/lenovo-ideapad
deleted file mode 100644
index fc339839f2..0000000000
--- a/keymaps/lenovo-ideapad
+++ /dev/null
@@ -1,8 +0,0 @@
-# Key codes observed on S10-3, assumed valid on other IdeaPad models
-0x81 rfkill # does nothing in BIOS
-0x83 display_off # BIOS toggles screen state
-0xB9 brightnessup # does nothing in BIOS
-0xBA brightnessdown # does nothing in BIOS
-0xF1 camera # BIOS toggles camera power
-0xf2 f21 # touchpad toggle (key alternately emits f2 and f3)
-0xf3 f21
diff --git a/keymaps/lenovo-thinkpad-usb-keyboard-trackpoint b/keymaps/lenovo-thinkpad-usb-keyboard-trackpoint
deleted file mode 100644
index d87549e445..0000000000
--- a/keymaps/lenovo-thinkpad-usb-keyboard-trackpoint
+++ /dev/null
@@ -1,13 +0,0 @@
-0x90012 screenlock # Fn+F2
-0x90013 battery # Fn+F3
-0x90014 wlan # Fn+F5
-0x90016 switchvideomode # Fn+F7
-0x90017 f21 # Fn+F8 touchpadtoggle
-0x90019 suspend # Fn+F12
-0x9001A brightnessup # Fn+Home
-0x9001B brightnessdown # Fn+End
-0x9001D zoom # Fn+Space
-0x90011 prog1 # Thinkvantage button
-
-0x90015 camera # Fn+F6 headset/camera VoIP key ??
-0x90010 f20 # Microphone mute button; should be micmute, but see https://mail.gnome.org/archives/commits-list/2013-January/msg05822.html
diff --git a/keymaps/lenovo-thinkpad_x200_tablet b/keymaps/lenovo-thinkpad_x200_tablet
deleted file mode 100644
index 31ea3b2c70..0000000000
--- a/keymaps/lenovo-thinkpad_x200_tablet
+++ /dev/null
@@ -1,6 +0,0 @@
-0x5D menu
-0x63 fn
-0x66 screenlock
-0x67 cyclewindows # bezel circular arrow
-0x68 setup # bezel setup / menu
-0x6c direction # rotate screen
diff --git a/keymaps/lenovo-thinkpad_x6_tablet b/keymaps/lenovo-thinkpad_x6_tablet
deleted file mode 100644
index 6fd16b5662..0000000000
--- a/keymaps/lenovo-thinkpad_x6_tablet
+++ /dev/null
@@ -1,8 +0,0 @@
-0x6C f21 # rotate
-0x68 screenlock # screenlock
-0x6B esc # escape
-0x6D right # right on d-pad
-0x6E left # left on d-pad
-0x71 up # up on d-pad
-0x6F down # down on d-pad
-0x69 enter # enter on d-pad
diff --git a/keymaps/lg-x110 b/keymaps/lg-x110
deleted file mode 100644
index ba08cba3fe..0000000000
--- a/keymaps/lg-x110
+++ /dev/null
@@ -1,12 +0,0 @@
-0xA0 mute # Fn-F9
-0xAE volumedown # Fn-Left
-0xAF search # Fn-F3
-0xB0 volumeup # Fn-Right
-0xB1 battery # Fn-F10 Info
-0xB3 suspend # Fn-F12
-0xDF sleep # Fn-F4
-# 0xE2 bluetooth # satellite dish2
-0xE4 f21 # Fn-F5 Touchpad disable
-0xF6 wlan # Fn-F6
-0xF7 reserved # brightnessdown # Fn-Down
-0xF8 reserved # brightnessup # Fn-Up
diff --git a/keymaps/logitech-wave b/keymaps/logitech-wave
deleted file mode 100644
index caa5d5d310..0000000000
--- a/keymaps/logitech-wave
+++ /dev/null
@@ -1,16 +0,0 @@
-0x9001C scale #expo
-0x9001F zoomout #zoom out
-0x90020 zoomin #zoom in
-0x9003D prog1 #gadget
-0x90005 camera #camera
-0x90018 media #media center
-0x90041 wordprocessor #fn+f1 (word)
-0x90042 spreadsheet #fn+f2 (excel)
-0x90043 calendar #fn+f3 (calendar)
-0x90044 prog2 #fn+f4 (program a)
-0x90045 prog3 #fn+f5 (program b)
-0x90046 prog4 #fn+f6 (program c)
-0x90048 messenger #fn+f8 (msn messenger)
-0x9002D find #fn+f10 (search www)
-0x9004B search #fn+f11 (search pc)
-0x9004C ejectclosecd #fn+f12 (eject)
diff --git a/keymaps/logitech-wave-cordless b/keymaps/logitech-wave-cordless
deleted file mode 100644
index a10dad5e4d..0000000000
--- a/keymaps/logitech-wave-cordless
+++ /dev/null
@@ -1,15 +0,0 @@
-0xD4 zoomin
-0xCC zoomout
-0xC0183 media
-0xC1005 camera
-0xC101F zoomout
-0xC1020 zoomin
-0xC1041 wordprocessor
-0xC1042 spreadsheet
-0xC1043 calendar
-0xC1044 prog2 #fn+f4 (program a)
-0xC1045 prog3 #fn+f5 (program b)
-0xC1046 prog4 #fn+f6 (program c)
-0xC1048 messenger
-0xC104A find #fn+f10 (search www)
-0xC104C ejectclosecd
diff --git a/keymaps/logitech-wave-pro-cordless b/keymaps/logitech-wave-pro-cordless
deleted file mode 100644
index e7aa02206c..0000000000
--- a/keymaps/logitech-wave-pro-cordless
+++ /dev/null
@@ -1,12 +0,0 @@
-0xC01B6 camera
-0xC0183 media
-0xC0184 wordprocessor
-0xC0186 spreadsheet
-0xC018E calendar
-0xC0223 homepage
-0xC01BC messenger
-0xC018A mail
-0xC0221 search
-0xC00B8 ejectcd
-0xC022D zoomin
-0xC022E zoomout
diff --git a/keymaps/maxdata-pro_7000 b/keymaps/maxdata-pro_7000
deleted file mode 100644
index c0e4f77af4..0000000000
--- a/keymaps/maxdata-pro_7000
+++ /dev/null
@@ -1,9 +0,0 @@
-0x97 prog2
-0x9F prog1
-0xA0 mute # Fn-F5
-0x82 www
-0xEC email
-0xAE volumedown # Fn-Down
-0xB0 volumeup # Fn-Up
-0xDF suspend # Fn+F2
-0xF5 help
diff --git a/keymaps/medion-fid2060 b/keymaps/medion-fid2060
deleted file mode 100644
index 5a76c76799..0000000000
--- a/keymaps/medion-fid2060
+++ /dev/null
@@ -1,2 +0,0 @@
-0x6B channeldown # Thottle Down
-0x6D channelup # Thottle Up
diff --git a/keymaps/medionnb-a555 b/keymaps/medionnb-a555
deleted file mode 100644
index c3b5dfa60b..0000000000
--- a/keymaps/medionnb-a555
+++ /dev/null
@@ -1,4 +0,0 @@
-0x63 www # N button
-0x66 prog1 # link 1 button
-0x67 email # envelope button
-0x69 prog2 # link 2 button
diff --git a/keymaps/micro-star b/keymaps/micro-star
deleted file mode 100644
index 4a438698ed..0000000000
--- a/keymaps/micro-star
+++ /dev/null
@@ -1,13 +0,0 @@
-0xA0 mute # Fn-F9
-0xAE volumedown # Fn-F7
-0xB0 volumeup # Fn-F8
-0xB2 www # e button
-0xDF sleep # Fn-F12
-0xE2 bluetooth # satellite dish2
-0xE4 f21 # Fn-F3 Touchpad disable
-0xEC email # envelope button
-0xEE camera # Fn-F6 camera disable
-0xF6 wlan # satellite dish1
-0xF7 brightnessdown # Fn-F4
-0xF8 brightnessup # Fn-F5
-0xF9 search
diff --git a/keymaps/module-asus-w3j b/keymaps/module-asus-w3j
deleted file mode 100644
index 773e0b3e82..0000000000
--- a/keymaps/module-asus-w3j
+++ /dev/null
@@ -1,11 +0,0 @@
-0x41 nextsong
-0x45 playpause
-0x43 stopcd
-0x40 previoussong
-0x4C ejectclosecd
-0x32 mute
-0x31 volumedown
-0x30 volumeup
-0x5D wlan
-0x7E bluetooth
-0x8A media # high keycode: "tv"
diff --git a/keymaps/module-ibm b/keymaps/module-ibm
deleted file mode 100644
index a92dfa2506..0000000000
--- a/keymaps/module-ibm
+++ /dev/null
@@ -1,16 +0,0 @@
-0x01 battery # Fn+F2
-0x02 screenlock # Fn+F3
-0x03 sleep # Fn+F4
-0x04 wlan # Fn+F5
-0x06 switchvideomode # Fn+F7
-0x07 zoom # Fn+F8 screen expand
-0x08 f24 # Fn+F9 undock
-0x0B suspend # Fn+F12
-0x0F brightnessup # Fn+Home
-0x10 brightnessdown # Fn+End
-0x11 kbdillumtoggle # Fn+PgUp - ThinkLight
-0x13 zoom # Fn+Space
-0x14 volumeup
-0x15 volumedown
-0x16 mute
-0x17 prog1 # ThinkPad/ThinkVantage button (high keycode: "vendor")
diff --git a/keymaps/module-lenovo b/keymaps/module-lenovo
deleted file mode 100644
index 573a6a774b..0000000000
--- a/keymaps/module-lenovo
+++ /dev/null
@@ -1,17 +0,0 @@
-0x1 screenlock # Fn+F2
-0x2 battery # Fn+F3
-0x3 sleep # Fn+F4
-0x4 wlan # Fn+F5
-0x6 switchvideomode # Fn+F7
-0x7 f21 # Fn+F8 touchpadtoggle
-0x8 f24 # Fn+F9 undock
-0xB suspend # Fn+F12
-0xF brightnessup # Fn+Home
-0x10 brightnessdown # Fn+End
-0x11 kbdillumtoggle # Fn+PgUp - ThinkLight
-0x13 zoom # Fn+Space
-0x14 volumeup
-0x15 volumedown
-0x16 mute
-0x17 prog1 # ThinkPad/ThinkVantage button (high keycode: "vendor")
-0x1A f20 # Microphone mute button; should be micmute, but see https://mail.gnome.org/archives/commits-list/2013-January/msg05822.html
diff --git a/keymaps/module-sony b/keymaps/module-sony
deleted file mode 100644
index 7c000131d1..0000000000
--- a/keymaps/module-sony
+++ /dev/null
@@ -1,8 +0,0 @@
-0x06 mute # Fn+F2
-0x07 volumedown # Fn+F3
-0x08 volumeup # Fn+F4
-0x09 brightnessdown # Fn+F5
-0x0A brightnessup # Fn+F6
-0x0B switchvideomode # Fn+F7
-0x0E zoom # Fn+F10
-0x10 suspend # Fn+F12
diff --git a/keymaps/module-sony-old b/keymaps/module-sony-old
deleted file mode 100644
index 596a34258a..0000000000
--- a/keymaps/module-sony-old
+++ /dev/null
@@ -1,2 +0,0 @@
-0x06 battery
-0x07 mute
diff --git a/keymaps/module-sony-vgn b/keymaps/module-sony-vgn
deleted file mode 100644
index c8ba001516..0000000000
--- a/keymaps/module-sony-vgn
+++ /dev/null
@@ -1,8 +0,0 @@
-0x00 brightnessdown # Fn+F5
-0x10 brightnessup # Fn+F6
-0x11 switchvideomode # Fn+F7
-0x12 zoomout
-0x14 zoomin
-0x15 suspend # Fn+F12
-0x17 prog1
-0x20 media
diff --git a/keymaps/module-sony-vpc b/keymaps/module-sony-vpc
deleted file mode 100644
index 681082c59e..0000000000
--- a/keymaps/module-sony-vpc
+++ /dev/null
@@ -1,4 +0,0 @@
-# 0x05 touchpad_toggle # fn_f1 -> KEY_TOUCHPAD_TOGGLE
-0x05 f21 # fn_f1 -> KEY_F21 (The actual touchpad toggle)
-0x0d zoomout # fn_f9
-0x0e zoomin # fn_f10
diff --git a/keymaps/olpc-xo b/keymaps/olpc-xo
deleted file mode 100644
index 34434a121d..0000000000
--- a/keymaps/olpc-xo
+++ /dev/null
@@ -1,74 +0,0 @@
-0x59 fn
-0x81 fn_esc
-0xF9 camera
-0xF8 sound # Fn-CAMERA = Mic
-
-
-# Function key mappings, as per
-# http://dev.laptop.org/ticket/10213#comment:20
-#
-# Unmodified F1-F8 produce F1-F8, so no remap necessary.
-# Unmodified F9-F12 control brightness and volume.
-0x43 brightnessdown
-0x44 brightnessup
-0x57 volumedown
-0x58 volumeup
-
-# fn-modified fkeys all produce the unmodified version of the key.
-0xBB f1
-0xBC f2
-0xBD f3
-0xBE f4
-0xBF f5
-0xC0 f6
-0xC1 f7
-0xC2 f8
-0xC3 f9
-0xC4 f10
-0xD7 f11
-0xD8 f12
-
-
-# Using F13-F21 for the .5 F keys right now.
-0xF7 f13
-0xF6 f14
-0xF5 f15
-0xF4 f16
-0xF3 f17
-0xF2 f18
-0xF1 f19
-0xF0 f20
-0xEF f21
-
-0xEE chat
-0xE4 chat # Just mapping Fn-Chat to Chat for now
-0xDD menu # Frame
-0xDA prog1 # Fn-Frame
-
-# The FN of some keys is other keys
-0xD3 delete
-0xD2 insert
-0xC9 pageup
-0xD1 pagedown
-0xC7 home
-0xCF end
-
-# Language key - don't ask what they are doing as KEY_HP
-0x73 hp
-0x7E hp
-
-0xDB leftmeta # left grab
-0xDC rightmeta # right grab
-0x85 rightmeta # Right grab releases on a different scancode
-0xD6 kbdillumtoggle # Fn-space
-0x69 switchvideomode # Brightness key
-
-# Game keys
-0x65 kp8 # up
-0x66 kp2 # down
-0x67 kp4 # left
-0x68 kp6 # right
-0xE5 kp9 # pgup
-0xE6 kp3 # pgdn
-0xE7 kp7 # home
-0xE8 kp1 # end
diff --git a/keymaps/onkyo b/keymaps/onkyo
deleted file mode 100644
index ee864ade4d..0000000000
--- a/keymaps/onkyo
+++ /dev/null
@@ -1,14 +0,0 @@
-0xA0 mute # Fn+D
-0xAE volumedown # Fn+F
-0xB0 volumeup # Fn+G
-0xDF sleep # Fn+W
-0xE0 bluetooth # Fn+H
-0xE2 cyclewindows # Fn+Esc
-0xEE battery # Fn+Q
-0xF0 media # Fn+R
-0xF5 switchvideomode # Fn+E
-0xF6 camera # Fn+T
-0xF7 f21 # Fn+Y (touchpad toggle)
-0xF8 brightnessup # Fn+S
-0xF9 brightnessdown # Fn+A
-0xFB wlan # Fn+J
diff --git a/keymaps/oqo-model2 b/keymaps/oqo-model2
deleted file mode 100644
index b7f4851abe..0000000000
--- a/keymaps/oqo-model2
+++ /dev/null
@@ -1,5 +0,0 @@
-0x8E wlan
-0xF0 switchvideomode
-0xF1 mute
-0xF2 volumedown
-0xF3 volumeup
diff --git a/keymaps/samsung-other b/keymaps/samsung-other
deleted file mode 100644
index 3ac0c2f10c..0000000000
--- a/keymaps/samsung-other
+++ /dev/null
@@ -1,14 +0,0 @@
-0x74 prog1 # User key
-0x75 www
-0x78 mail
-0x82 switchvideomode # Fn+F4 CRT/LCD (high keycode: "displaytoggle")
-0x83 battery # Fn+F2
-0x84 prog1 # Fn+F5 backlight on/off
-0x86 wlan # Fn+F9
-0x88 brightnessup # Fn-Up
-0x89 brightnessdown # Fn-Down
-0xB1 prog2 # Fn+F7 run Samsung Magic Doctor (keypressed event is generated twice)
-0xB3 prog3 # Fn+F8 switch power mode (battery/dynamic/performance)
-0xB4 wlan # Fn+F9 (X60P)
-0xF7 f22 # Fn+F10 Touchpad on
-0xF9 f23 # Fn+F10 Touchpad off
diff --git a/keymaps/samsung-series-9 b/keymaps/samsung-series-9
deleted file mode 100644
index 3b65735fa0..0000000000
--- a/keymaps/samsung-series-9
+++ /dev/null
@@ -1,5 +0,0 @@
-0x96 kbdillumup # Fn+F8 keyboard backlit up
-0x97 kbdillumdown # Fn+F7 keyboard backlit down
-0xD5 wlan # Fn+F12 wifi on/off
-0xCE prog1 # Fn+F1 performance mode
-0x8D prog2 # Fn+F6 battery life extender
diff --git a/keymaps/samsung-sq1us b/keymaps/samsung-sq1us
deleted file mode 100644
index ea2141ef84..0000000000
--- a/keymaps/samsung-sq1us
+++ /dev/null
@@ -1,7 +0,0 @@
-0xD4 menu
-0xD8 f1
-0xD9 f10
-0xD6 f3
-0xD7 f9
-0xE4 f5
-0xEE f11
diff --git a/keymaps/samsung-sx20s b/keymaps/samsung-sx20s
deleted file mode 100644
index 9d954ee415..0000000000
--- a/keymaps/samsung-sx20s
+++ /dev/null
@@ -1,4 +0,0 @@
-0x74 mute
-0x75 mute
-0x77 f22 # Touchpad on
-0x79 f23 # Touchpad off
diff --git a/keymaps/toshiba-satellite_a100 b/keymaps/toshiba-satellite_a100
deleted file mode 100644
index 22007be71b..0000000000
--- a/keymaps/toshiba-satellite_a100
+++ /dev/null
@@ -1,2 +0,0 @@
-0xA4 stopcd
-0xB2 www
diff --git a/keymaps/toshiba-satellite_a110 b/keymaps/toshiba-satellite_a110
deleted file mode 100644
index 1429409351..0000000000
--- a/keymaps/toshiba-satellite_a110
+++ /dev/null
@@ -1,10 +0,0 @@
-0x92 stop
-0x93 www
-0x94 media
-0x9E f22 # Touchpad on
-0x9F f23 # Touchpad off
-0xB9 nextsong
-0xD9 brightnessup
-0xEE screenlock
-0xF4 previoussong
-0xF7 playpause
diff --git a/keymaps/toshiba-satellite_m30x b/keymaps/toshiba-satellite_m30x
deleted file mode 100644
index ae8e34941b..0000000000
--- a/keymaps/toshiba-satellite_m30x
+++ /dev/null
@@ -1,6 +0,0 @@
-0xef brightnessdown
-0xd9 brightnessup
-0xee screenlock
-0x93 media
-0x9e f22 #touchpad_enable
-0x9f f23 #touchpad_disable
diff --git a/keymaps/zepto-znote b/keymaps/zepto-znote
deleted file mode 100644
index cf72fda47b..0000000000
--- a/keymaps/zepto-znote
+++ /dev/null
@@ -1,11 +0,0 @@
-0x93 switchvideomode # Fn+F3 Toggle Video Output
-0x95 brightnessdown # Fn+F4 Brightness Down
-0x91 brightnessup # Fn+F5 Brightness Up
-0xA5 f23 # Fn+F6 Disable Touchpad
-0xA6 f22 # Fn+F6 Enable Touchpad
-0xA7 bluetooth # Fn+F10 Enable Bluetooth
-0XA9 bluetooth # Fn+F10 Disable Bluetooth
-0xF1 wlan # RF Switch Off
-0xF2 wlan # RF Switch On
-0xF4 prog1 # P1 Button
-0xF3 prog2 # P2 Button
diff --git a/m4/attributes.m4 b/m4/attributes.m4
index f0bcf24211..aa53ef2380 100644
--- a/m4/attributes.m4
+++ b/m4/attributes.m4
@@ -40,12 +40,12 @@ dnl CC_CHECK_FLAG_APPEND([WHERE-TO-APPEND], [ENV-VAR], [FLAG])
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])='-Werror $3'"
- AC_COMPILE_IFELSE([AC_LANG_SOURCE([int a = 0; int main(void) { return a; } ])],
- [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'"])
+ [eval "AS_TR_SH([cc_save_$2])='${$2}'"
+ eval "AS_TR_SH([$2])='-Werror $3'"
+ AC_LINK_IFELSE([AC_LANG_SOURCE([int a = 0; int main(void) { return a; } ])],
+ [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'"])
@@ -92,10 +92,10 @@ AC_DEFUN([CC_NOUNDEFINED], [
dnl for a much more readable commandline, 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
+ CC_CHECK_LDFLAGS([$possible_flags], [LDFLAGS_NOUNDEFINED="$possible_flags"])
+ break
done
- ;;
+ ;;
esac
AC_SUBST([LDFLAGS_NOUNDEFINED])
@@ -231,8 +231,8 @@ AC_DEFUN([CC_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')
+ 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"],
@@ -252,7 +252,7 @@ AC_DEFUN([CC_FUNC_EXPECT], [
[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"
diff --git a/make-directive-index.py b/make-directive-index.py
index 396947b303..b43fea0b99 100755
--- a/make-directive-index.py
+++ b/make-directive-index.py
@@ -21,6 +21,7 @@ import sys
import collections
import re
from xml_helper import *
+from copy import deepcopy
TEMPLATE = '''\
<refentry id="systemd.directives" conditional="HAVE_PYTHON">
@@ -138,6 +139,14 @@ TEMPLATE = '''\
</refsect1>
<refsect1>
+ <title>Constants</title>
+
+ <para>Various constant used and/or defined by systemd.</para>
+
+ <variablelist id='constants' />
+ </refsect1>
+
+ <refsect1>
<title>Miscellaneous options and directives</title>
<para>Other configuration elements which don't fit in
@@ -221,24 +230,35 @@ def _extract_directives(directive_groups, formatting, page):
storfile[text].append((pagename, section))
formatting[text] = name
+ storfile = directive_groups['constants']
+ for name in t.iterfind('.//constant'):
+ if name.attrib.get('noindex'):
+ continue
+ name.tail = ''
+ if name.text.startswith('('): # a cast, strip it
+ name.text = name.text.partition(' ')[2]
+ storfile[name.text].append((pagename, section))
+ formatting[name.text] = name
+
def _make_section(template, name, directives, formatting):
varlist = template.find(".//*[@id='{}']".format(name))
for varname, manpages in sorted(directives.items()):
entry = tree.SubElement(varlist, 'varlistentry')
term = tree.SubElement(entry, 'term')
- term.append(formatting[varname])
+ display = deepcopy(formatting[varname])
+ term.append(display)
para = tree.SubElement(tree.SubElement(entry, 'listitem'), 'para')
b = None
for manpage, manvolume in sorted(set(manpages)):
- if b is not None:
- b.tail = ', '
- b = tree.SubElement(para, 'citerefentry')
- c = tree.SubElement(b, 'refentrytitle')
- c.text = manpage
- d = tree.SubElement(b, 'manvolnum')
- d.text = manvolume
+ if b is not None:
+ b.tail = ', '
+ b = tree.SubElement(para, 'citerefentry')
+ c = tree.SubElement(b, 'refentrytitle')
+ c.text = manpage
+ d = tree.SubElement(b, 'manvolnum')
+ d.text = manvolume
entry.tail = '\n\n'
def _make_colophon(template, groups):
@@ -264,7 +284,7 @@ def _make_page(template, directive_groups, formatting):
}
"""
for name, directives in directive_groups.items():
- _make_section(template, name, directives, formatting)
+ _make_section(template, name, directives, formatting)
_make_colophon(template, directive_groups.values())
diff --git a/man/binfmt.d.xml b/man/binfmt.d.xml
index 762d1fc66e..94f97e0ed4 100644
--- a/man/binfmt.d.xml
+++ b/man/binfmt.d.xml
@@ -67,7 +67,7 @@
<para>Each file contains a list of binfmt_misc kernel
binary format rules. Consult <ulink
- url="http://www.kernel.org/doc/Documentation/binfmt_misc.txt">binfmt_misc.txt</ulink>
+ url="https://www.kernel.org/doc/Documentation/binfmt_misc.txt">binfmt_misc.txt</ulink>
for more information on registration of additional
binary formats and how to write rules.</para>
@@ -88,17 +88,17 @@
administrator, who may use this logic to override the
configuration files installed from vendor
packages. All files are sorted by their filename in
- alphabetical order, regardless in which of the
- directories they reside, to guarantee that a specific
- configuration file takes precedence over another file
- with an alphabetically later name.</para>
+ lexicographic order, regardless in which of the
+ directories they reside. If multiple files specify
+ the same binary type name, the entry in the file with
+ the lexicographically latest name will be applied.</para>
<para>If the administrator wants to disable a
- configuration file supplied by the vendor the
+ configuration file supplied by the vendor, the
recommended way is to place a symlink to
<filename>/dev/null</filename> in
<filename>/etc/binfmt.d/</filename> bearing the
- same file name.</para>
+ same filename.</para>
</refsect1>
<refsect1>
diff --git a/man/bootchart.conf.xml b/man/bootchart.conf.xml
index 1e440eb2cc..68d10d4415 100644
--- a/man/bootchart.conf.xml
+++ b/man/bootchart.conf.xml
@@ -72,7 +72,7 @@
<varlistentry>
<term><varname>Samples=500</varname></term>
<listitem><para>Configure the amount of samples to
- record total before bootchart exits. Each sample will
+ record in total before bootchart exits. Each sample will
record at intervals defined by Frequency=.</para></listitem>
</varlistentry>
@@ -87,7 +87,7 @@
<varlistentry>
<term><varname>Relative=no</varname></term>
<listitem><para>Configures whether the left axis of the
- output graph equals time=0.0 (CLOCK_MONOTONIC start). This
+ output graph equals time=0.0 (<constant>CLOCK_MONOTONIC</constant> start). This
is useful for using bootchart at post-boot time to profile
an already booted system, otherwise the graph would become
extremely large. If set to yes, the horizontal axis starts
@@ -107,7 +107,7 @@
<varlistentry>
<term><varname>Output=[path]</varname></term>
- <listitem><para>Configures the output folder for writing
+ <listitem><para>Configures the output directory for writing
the graphs. By default, bootchart writes the graphs to
<filename>/run/log</filename>.</para></listitem>
</varlistentry>
@@ -124,7 +124,7 @@
<varlistentry>
<term><varname>PlotMemoryUsage=no</varname></term>
<listitem><para>If set to yes, enables logging and graphing
- of processes PSS memory consumption.</para></listitem>
+ of processes' PSS memory consumption.</para></listitem>
</varlistentry>
<varlistentry>
diff --git a/man/bootup.xml b/man/bootup.xml
index a596e85b70..65c2cee70e 100644
--- a/man/bootup.xml
+++ b/man/bootup.xml
@@ -56,26 +56,27 @@
and hand control over to a boot loader stored on a
persistent storage device. This boot loader will then
invoke an OS kernel from disk (or the network). In the
- Linux case this kernel (optionally) extracts and
- executes an initial RAM disk image (initrd) such as
- <citerefentry><refentrytitle>dracut</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ Linux case, this kernel (optionally) extracts and
+ executes an initial RAM disk image (initrd), such as
+ generated by
+ <citerefentry><refentrytitle>dracut</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
which looks for the root file system (possibly using
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
for this). After the root file system is found and
- mounted the initrd hands over control to the host's
+ mounted, the initrd hands over control to the host's
system manager (such as
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>)
- stored on the OS image which is then responsible for
+ stored on the OS image, which is then responsible for
probing all remaining hardware, mounting all necessary
file systems and spawning all configured
services.</para>
- <para>On shutdown the system manager stops all
+ <para>On shutdown, the system manager stops all
services, unmounts all file systems (detaching the
storage technologies backing them), and then
(optionally) jumps back into the initrd code which
unmounts/detaches the root file system and the storage
- it resides on. As last step the system is powered down.</para>
+ it resides on. As a last step, the system is powered down.</para>
<para>Additional information about the system boot
process may be found in
@@ -90,7 +91,7 @@
systems, services and drivers that are necessary for
operation of the system. On
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- systems this process is split up in various discrete
+ systems, this process is split up in various discrete
steps which are exposed as target units. (See
<citerefentry><refentrytitle>systemd.target</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for detailed information about target units.) The
@@ -99,17 +100,17 @@
deterministic, but still adheres to a limited amount
of ordering structure.</para>
- <para>When systemd starts up the system it will
+ <para>When systemd starts up the system, it will
activate all units that are dependencies of
<filename>default.target</filename> (as well as
recursively all dependencies of these
- dependencies). Usually
+ dependencies). Usually,
<filename>default.target</filename> is simply an alias
of <filename>graphical.target</filename> or
- <filename>multi-user.target</filename> depending on
+ <filename>multi-user.target</filename>, depending on
whether the system is configured for a graphical UI or
only for a text console. To enforce minimal ordering
- between the units pulled in a number of well-known
+ between the units pulled in, a number of well-known
target units are available, as listed on
<citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
@@ -178,7 +179,7 @@
<refsect1>
<title>Bootup in the Initial RAM Disk (initrd)</title>
<para>The initial RAM disk implementation (initrd) can
- be set up using systemd as well. In this case boot up
+ be set up using systemd as well. In this case, boot up
inside the initrd follows the following
structure.</para>
diff --git a/man/crypttab.xml b/man/crypttab.xml
index deb577b9de..90d8ce95fe 100644
--- a/man/crypttab.xml
+++ b/man/crypttab.xml
@@ -68,30 +68,36 @@
describes encrypted block devices that are set up
during system boot.</para>
- <para>Empty lines and lines starting with the #
+ <para>Empty lines and lines starting with the <literal>#</literal>
character are ignored. Each of the remaining lines
describes one encrypted block device, fields on the
line are delimited by white space. The first two
fields are mandatory, the remaining two are
optional.</para>
+ <para>Setting up encrypted block devices using this file
+ supports three encryption modes: LUKS, TrueCrypt and plain.
+ See <citerefentry><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ for more information about each mode. When no mode is specified
+ in the options field and the block device contains a LUKS
+ signature, it is opened as a LUKS device; otherwise, it is
+ assumed to be in raw dm-crypt (plain mode) format.</para>
+
<para>The first field contains the name of the
resulting encrypted block device; the device is set up
within <filename>/dev/mapper/</filename>.</para>
<para>The second field contains a path to the
- underlying block device, or a specification of a block
+ underlying block device or file, or a specification of a block
device via <literal>UUID=</literal> followed by the
- UUID. If the block device contains a LUKS signature,
- it is opened as a LUKS encrypted partition; otherwise
- it is assumed to be a raw dm-crypt partition.</para>
+ UUID.</para>
<para>The third field specifies the encryption
password. If the field is not present or the password
- is set to none, the password has to be manually
- entered during system boot. Otherwise the field is
- interpreted as a path to a file containing the
- encryption password. For swap encryption
+ is set to <literal>none</literal> or <literal>-</literal>,
+ the password has to be manually entered during system boot.
+ Otherwise, the field is interpreted as a absolute path to
+ a file containing the encryption password. For swap encryption,
<filename>/dev/urandom</filename> or the hardware
device <filename>/dev/hw_random</filename> can be used
as the password file; using
@@ -104,185 +110,243 @@
options are recognized:</para>
<variablelist class='crypttab-options'>
+
+ <varlistentry>
+ <term><varname>discard</varname></term>
+
+ <listitem><para>Allow discard requests to be
+ passed through the encrypted block device. This
+ improves performance on SSD storage but has
+ security implications.</para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>cipher=</varname></term>
- <listitem><para>Specifies the cipher
- to use; see
+ <listitem><para>Specifies the cipher to use. See
<citerefentry><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- for possible values and the default
- value of this option. A cipher with
- unpredictable IV values, such as
- <literal>aes-cbc-essiv:sha256</literal>,
- is recommended. </para></listitem>
+ for possible values and the default value of
+ this option. A cipher with unpredictable IV
+ values, such as <literal>aes-cbc-essiv:sha256</literal>,
+ is recommended.</para></listitem>
</varlistentry>
-
<varlistentry>
- <term><varname>size=</varname></term>
+ <term><varname>hash=</varname></term>
- <listitem><para>Specifies the key size
- in bits; see
+ <listitem><para>Specifies the hash to use for
+ password hashing. See
<citerefentry><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- for possible values and the default
- value of this
- option. </para></listitem>
+ for possible values and the default value of
+ this option.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>keyfile-offset=</varname></term>
+
+ <listitem><para>Specifies the number of bytes to
+ skip at the start of the key file. See
+ <citerefentry><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ for possible values and the default value of
+ this option.</para></listitem>
+ </varlistentry>
<varlistentry>
<term><varname>keyfile-size=</varname></term>
<listitem><para>Specifies the maximum number
- of bytes to read from the keyfile; see
+ of bytes to read from the key file. See
<citerefentry><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- for possible values and the default
- value of this option. This option is ignored
- in plain encryption mode, as the keyfile-size is then given by the key size.</para></listitem>
+ for possible values and the default value of
+ this option. This option is ignored in plain
+ encryption mode, as the key file size is then
+ given by the key size.</para></listitem>
</varlistentry>
-
<varlistentry>
- <term><varname>keyfile-offset=</varname></term>
+ <term><varname>luks</varname></term>
- <listitem><para>Specifies the number
- of bytes to skip at the start of
- the keyfile; see
- <citerefentry><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- for possible values and the default
- value of this option.</para></listitem>
+ <listitem><para>Force LUKS mode. When this mode
+ is used, the following options are ignored since
+ they are provided by the LUKS header on the
+ device: <varname>cipher=</varname>,
+ <varname>hash=</varname>,
+ <varname>size=</varname>.</para></listitem>
</varlistentry>
-
<varlistentry>
- <term><varname>hash=</varname></term>
+ <term><varname>noauto</varname></term>
- <listitem><para>Specifies the hash to
- use for password hashing; see
- <citerefentry><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry> for possible values and
- the default value of this
- option. </para></listitem>
+ <listitem><para>This device will not be
+ automatically unlocked on boot.</para></listitem>
</varlistentry>
<varlistentry>
- <term><varname>tries=</varname></term>
+ <term><varname>nofail</varname></term>
- <listitem><para>Specifies the maximum
- number of times the user is queried
- for a password.</para></listitem>
+ <listitem><para>The system will not wait for the
+ device to show up and be unlocked at boot, and
+ not fail the boot if it does not show up.</para></listitem>
</varlistentry>
<varlistentry>
- <term><varname>verify</varname></term>
+ <term><varname>plain</varname></term>
- <listitem><para> If the encryption
- password is read from console, it has
- to be entered twice (to prevent
- typos). </para></listitem>
+ <listitem><para>Force plain encryption mode.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>read-only</varname></term><term><varname>readonly</varname></term>
- <listitem><para>Set up the encrypted
- block device in read-only
- mode.</para></listitem>
+ <listitem><para>Set up the encrypted block
+ device in read-only mode.</para></listitem>
</varlistentry>
<varlistentry>
- <term><varname>allow-discards</varname></term>
-
- <listitem><para>Allow discard requests
- to be passed through the encrypted
- block device. This improves
- performance on SSD storage but has
- security
- implications.</para></listitem>
+ <term><varname>size=</varname></term>
+
+ <listitem><para>Specifies the key size
+ in bits. See
+ <citerefentry><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ for possible values and the default value of
+ this option.</para></listitem>
</varlistentry>
<varlistentry>
- <term><varname>luks</varname></term>
+ <term><varname>swap</varname></term>
- <listitem><para>Force LUKS mode.</para></listitem>
+ <listitem><para>The encrypted block device will
+ be used as a swap device, and will be formatted
+ accordingly after setting up the encrypted
+ block device, with
+ <citerefentry><refentrytitle>mkswap</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+ This option implies <varname>plain</varname>.</para>
+
+ <para>WARNING: Using the <varname>swap</varname>
+ option will destroy the contents of the named
+ partition during every boot, so make sure the
+ underlying block device is specified correctly.</para></listitem>
</varlistentry>
<varlistentry>
- <term><varname>plain</varname></term>
+ <term><varname>tcrypt</varname></term>
+
+ <listitem><para>Use TrueCrypt encryption mode.
+ When this mode is used, the following options are
+ ignored since they are provided by the TrueCrypt
+ header on the device or do not apply:
+ <varname>cipher=</varname>,
+ <varname>hash=</varname>,
+ <varname>keyfile-offset=</varname>,
+ <varname>keyfile-size=</varname>,
+ <varname>size=</varname>.</para>
+
+ <para>When this mode is used, the passphrase is
+ read from the key file given in the third field.
+ Only the first line of this file is read,
+ excluding the new line character.</para>
+
+ <para>Note that the TrueCrypt format uses both
+ passphrase and key files to derive a password
+ for the volume. Therefore, the passphrase and
+ all key files need to be provided. Use
+ <varname>tcrypt-keyfile=</varname> to provide
+ the absolute path to all key files. When using
+ an empty passphrase in combination with one or
+ more key files, use <literal>/dev/null</literal>
+ as the password file in the third field.</para></listitem>
+ </varlistentry>
- <listitem><para>Force plain encryption
- mode.</para></listitem>
+ <varlistentry>
+ <term><varname>tcrypt-hidden</varname></term>
+
+ <listitem><para>Use the hidden TrueCrypt volume.
+ This implies <varname>tcrypt</varname>.</para>
+
+ <para>This will map the hidden volume that is
+ inside of the volume provided in the second
+ field. Please note that there is no protection
+ for the hidden volume if the outer volume is
+ mounted instead. See
+ <citerefentry><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ for more information on this limitation.</para></listitem>
</varlistentry>
<varlistentry>
- <term><varname>timeout=</varname></term>
+ <term><varname>tcrypt-keyfile=</varname></term>
+
+ <listitem><para>Specifies the absolute path to a
+ key file to use for a TrueCrypt volume. This
+ implies <varname>tcrypt</varname> and can be
+ used more than once to provide several key
+ files.</para>
- <listitem><para>Specify the timeout
- for querying for a password. If no
- unit is specified seconds is used.
- Supported units are s, ms, us, min, h,
- d. A timeout of 0 waits indefinitely
- (which is the
- default).</para></listitem>
+ <para>See the entry for <varname>tcrypt</varname>
+ on the behavior of the passphrase and key files
+ when using TrueCrypt encryption mode.</para></listitem>
</varlistentry>
<varlistentry>
- <term><varname>noauto</varname></term>
+ <term><varname>tcrypt-system</varname></term>
+
+ <listitem><para>Use TrueCrypt in system
+ encryption mode. This implies
+ <varname>tcrypt</varname>.</para>
+
+ <para>Please note that when using this mode, the
+ whole device needs to be given in the second
+ field instead of the partition. For example: if
+ <literal>/dev/sda2</literal> is the system
+ encrypted TrueCrypt patition, <literal>/dev/sda</literal>
+ has to be given.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>timeout=</varname></term>
- <listitem><para> This device will not
- be automatically unlocked on
- boot. </para></listitem>
+ <listitem><para>Specifies the timeout for
+ querying for a password. If no unit is
+ specified, seconds is used. Supported units are
+ s, ms, us, min, h, d. A timeout of 0 waits
+ indefinitely (which is the default).</para></listitem>
</varlistentry>
<varlistentry>
- <term><varname>nofail</varname></term>
+ <term><varname>tmp</varname></term>
+
+ <listitem><para>The encrypted block device will
+ be prepared for using it as <filename>/tmp</filename>;
+ it will be formatted using
+ <citerefentry><refentrytitle>mke2fs</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+ This option implies <varname>plain</varname>.</para>
- <listitem><para>The system will not
- wait for the device to show up and be
- unlocked at boot, and not fail the
- boot if it doesn't show
- up.</para></listitem>
+ <para>WARNING: Using the <varname>tmp</varname>
+ option will destroy the contents of the named
+ partition during every boot, so make sure the
+ underlying block device is specified correctly.</para></listitem>
</varlistentry>
<varlistentry>
- <term><varname>swap</varname></term>
+ <term><varname>tries=</varname></term>
- <listitem><para> The encrypted block
- device will be used as a swap
- partition, and will be formatted as a
- swap partition after setting up the
- encrypted block device, with
- <citerefentry><refentrytitle>mkswap</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
-
- <para>WARNING: Using the
- <varname>swap</varname> option will
- destroy the contents of the named
- partition during every boot, so make
- sure the underlying block device is
- specified
- correctly. </para></listitem>
+ <listitem><para>Specifies the maximum number of
+ times the user is queried for a password.
+ The default is 3. If set to 0, the user is
+ queried for a password indefinitely.</para></listitem>
</varlistentry>
<varlistentry>
- <term><varname>tmp</varname></term>
+ <term><varname>verify</varname></term>
- <listitem><para>The encrypted block
- device will be prepared for using it
- as <filename>/tmp</filename>
- partition: it will be formatted using
- <citerefentry><refentrytitle>mke2fs</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
-
- <para>WARNING: Using the
- <varname>tmp</varname> option will
- destroy the contents of the named
- partition during every boot, so make
- sure the underlying block device is
- specified
- correctly. </para></listitem>
+ <listitem><para> If the encryption password is
+ read from console, it has to be entered twice to
+ prevent typos.</para></listitem>
</varlistentry>
+
</variablelist>
<para>At early boot and when the system manager
- configuration is reloaded this file is translated into
+ configuration is reloaded, this file is translated into
native systemd units
by <citerefentry><refentrytitle>systemd-cryptsetup-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
</refsect1>
@@ -291,12 +355,14 @@
<title>Example</title>
<example>
<title>/etc/crypttab example</title>
- <para>Set up two encrypted block devices with
- LUKS: one normal one for storage, and another
- one for usage as swap device.</para>
-
- <programlisting>luks-2505567a-9e27-4efe-a4d5-15ad146c258b UUID=2505567a-9e27-4efe-a4d5-15ad146c258b - timeout=0
-swap /dev/sda7 /dev/urandom swap</programlisting>
+ <para>Set up four encrypted block devices. One using
+ LUKS for normal storage, another one for usage as a swap
+ device and two TrueCrypt volumes.</para>
+
+ <programlisting>luks UUID=2505567a-9e27-4efe-a4d5-15ad146c258b
+swap /dev/sda7 /dev/urandom swap
+truecrypt /dev/sda2 /etc/container_password tcrypt
+hidden /mnt/tc_hidden /null tcrypt-hidden,tcrypt-keyfile=/etc/keyfile</programlisting>
</example>
</refsect1>
diff --git a/man/custom-html.xsl b/man/custom-html.xsl
index dde9d7af0e..060af2e56a 100644
--- a/man/custom-html.xsl
+++ b/man/custom-html.xsl
@@ -172,6 +172,12 @@
<hr/>
</xsl:template>
+<xsl:template match="literal">
+ <xsl:text>"</xsl:text>
+ <xsl:call-template name="inline.monoseq"/>
+ <xsl:text>"</xsl:text>
+</xsl:template>
+
<!-- Switch things to UTF-8, ISO-8859-1 is soo yesteryear -->
<xsl:output method="html" encoding="UTF-8" indent="no"/>
diff --git a/man/custom-man.xsl b/man/custom-man.xsl
index 753e5715e3..e1b8d3618a 100644
--- a/man/custom-man.xsl
+++ b/man/custom-man.xsl
@@ -52,4 +52,13 @@
<xsl:call-template name="mark.subheading"/>
</xsl:template>
+<xsl:template match="literal">
+ <xsl:if test="$man.hyphenate.computer.inlines = 0">
+ <xsl:call-template name="suppress.hyphenation"/>
+ </xsl:if>
+ <xsl:text>"</xsl:text>
+ <xsl:call-template name="inline.monoseq"/>
+ <xsl:text>"</xsl:text>
+</xsl:template>
+
</xsl:stylesheet>
diff --git a/man/daemon.xml b/man/daemon.xml
index 0d29e7aa1c..7790420c6e 100644
--- a/man/daemon.xml
+++ b/man/daemon.xml
@@ -79,7 +79,7 @@
descriptors 0, 1, 2). This ensures
that no accidentally passed file
descriptor stays around in the daemon
- process. On Linux this is best
+ process. On Linux, this is best
implemented by iterating through
<filename>/proc/self/fd</filename>,
with a fallback of iterating from file
@@ -92,7 +92,7 @@
best done by iterating through the
available signals up to the limit of
_NSIG and resetting them to
- SIG_DFL.</para></listitem>
+ <constant>SIG_DFL</constant>.</para></listitem>
<listitem><para>Reset the signal mask
using
@@ -115,7 +115,7 @@
<listitem><para>In the child, call
<function>fork()</function> again, to
- ensure the daemon can never re-acquire
+ ensure that the daemon can never re-acquire
a terminal again.</para></listitem>
<listitem><para>Call <function>exit()</function> in the
@@ -150,15 +150,15 @@
<function>getpid()</function>) to a
PID file, for example
<filename>/var/run/foobar.pid</filename>
- (for a hypothetical daemon "foobar"),
+ (for a hypothetical daemon "foobar")
to ensure that the daemon cannot be
started more than once. This must be
implemented in race-free fashion so
that the PID file is only updated when
- at the same time it is verified that
+ it is verified at the same time that
the PID previously stored in the PID
file no longer exists or belongs to a
- foreign process. Commonly some kind of
+ foreign process. Commonly, some kind of
file locking is employed to implement
this logic.</para></listitem>
@@ -167,7 +167,7 @@
applicable.</para></listitem>
<listitem><para>From the daemon
- process notify the original process
+ process, notify the original process
started that initialization is
complete. This can be implemented via
an unnamed pipe or similar
@@ -197,7 +197,7 @@
implement the scheme pointed out
above. However, it is recommended to make this
behavior optional and configurable via a
- command line argument, to ease debugging as
+ command line argument to ease debugging as
well as to simplify integration into systems
using systemd.</para>
</refsect2>
@@ -211,20 +211,20 @@
runtime and simplifies their
implementation.</para>
- <para>For developing a new-style daemon none
+ <para>For developing a new-style daemon, none
of the initialization steps recommended for
SysV daemons need to be implemented. New-style
init systems such as systemd make all of them
redundant. Moreover, since some of these steps
interfere with process monitoring, file
descriptor passing and other functionality of
- the init system it is recommended not to
+ the init system, it is recommended not to
execute them when run as new-style
service.</para>
<para>Note that new-style init systems
guarantee execution of daemon processes in
- clean process contexts: it is guaranteed that
+ a clean process context: it is guaranteed that
the environment block is sanitized, that the
signal handlers and mask is reset and that no
left-over file descriptors are passed. Daemons
@@ -237,11 +237,11 @@
to implement the following:</para>
<orderedlist>
- <listitem><para>If SIGTERM is
+ <listitem><para>If <constant>SIGTERM</constant> is
received, shut down the daemon and
exit cleanly.</para></listitem>
- <listitem><para>If SIGHUP is received,
+ <listitem><para>If <constant>SIGHUP</constant> is received,
reload the configuration files, if
this applies.</para></listitem>
@@ -256,7 +256,7 @@
scripts</ulink>.</para></listitem>
<listitem><para>If possible and
- applicable expose the daemon's control
+ applicable, expose the daemon's control
interface via the D-Bus IPC system and
grab a bus name as last step of
initialization.</para></listitem>
@@ -274,7 +274,7 @@
rely on the init system's
functionality to limit the access of
the daemon to files, services and
- other resources. i.e. in the case of
+ other resources, i.e. in the case of
systemd, rely on systemd's resource
limit control instead of implementing
your own, rely on systemd's privilege
@@ -285,7 +285,7 @@
controls.</para></listitem>
<listitem><para>If D-Bus is used, make
- your daemon bus-activatable, via
+ your daemon bus-activatable by
supplying a D-Bus service activation
configuration file. This has multiple
advantages: your daemon may be started
@@ -293,7 +293,7 @@
parallel to other daemons requiring it
-- which maximizes parallelization and
boot-up speed; your daemon can be
- restarted on failure, without losing
+ restarted on failure without losing
any bus requests, as the bus queues
requests for activatable services. See
below for details.</para></listitem>
@@ -304,17 +304,17 @@
socket, it should be made
socket-activatable following the
scheme pointed out below. Like D-Bus
- activation this enables on-demand
+ activation, this enables on-demand
starting of services as well as it
allows improved parallelization of
service start-up. Also, for state-less
- protocols (such as syslog, DNS) a
+ protocols (such as syslog, DNS), a
daemon implementing socket-based
activation can be restarted without
losing a single request. See below for
details.</para></listitem>
- <listitem><para>If applicable a daemon
+ <listitem><para>If applicable, a daemon
should notify the init system about
startup completion or status updates
via the
@@ -327,7 +327,7 @@
choose to simply log to STDERR via
<function>fprintf()</function>, which is then forwarded to
syslog by the init system. If log
- priorities are necessary these can be
+ priorities are necessary, these can be
encoded by prefixing individual log
lines with strings like "&lt;4&gt;"
(for log priority 4 "WARNING" in the
@@ -343,7 +343,7 @@
kind of logging may be enabled by
setting
<varname>StandardError=syslog</varname>
- in the service unit file. For details
+ in the service unit file. For details,
see
<citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>3</manvolnum></citerefentry>
and
@@ -374,9 +374,9 @@
when a printer is plugged in, or when a file is queued
in the printer spool directory. Even for services that
are intended to be started on system bootup
- unconditionally it is a good idea to implement some of
+ unconditionally, it is a good idea to implement some of
the various activation schemes outlined below, in
- order to maximize parallelization: if a daemon
+ order to maximize parallelization. If a daemon
implements a D-Bus service or listening socket,
implementing the full bus and socket activation scheme
allows starting of the daemon with its clients in
@@ -384,7 +384,7 @@
communication channels are established already, and no
request is lost because client requests will be queued
by the bus system (in case of D-Bus) or the kernel (in
- case of sockets), until the activation is
+ case of sockets) until the activation is
completed.</para>
<refsect2>
@@ -399,7 +399,7 @@
Specification</ulink>. This method of
activation is supported ubiquitously on Linux
init systems, both old-style and new-style
- systems. Among other issues SysV init scripts
+ systems. Among other issues, SysV init scripts
have the disadvantage of involving shell
scripts in the boot process. New-style init
systems generally employ updated versions of
@@ -409,7 +409,7 @@
<para>In systemd, if the developer or
administrator wants to make sure a service or
- other unit is activated automatically on boot
+ other unit is activated automatically on boot,
it is recommended to place a symlink to the
unit file in the <filename>.wants/</filename>
directory of either
@@ -434,25 +434,25 @@
recommended for all new-style daemons that
communicate via listening sockets to employ
socket-based activation. In a socket-based
- activation scheme the creation and binding of
+ activation scheme, the creation and binding of
the listening socket as primary communication
channel of daemons to local (and sometimes
remote) clients is moved out of the daemon
code and into the init system. Based on
- per-daemon configuration the init system
+ per-daemon configuration, the init system
installs the sockets and then hands them off
to the spawned process as soon as the
respective daemon is to be started.
- Optionally activation of the service can be
+ Optionally, activation of the service can be
delayed until the first inbound traffic
- arrives at the socket, to implement on-demand
+ arrives at the socket to implement on-demand
activation of daemons. However, the primary
advantage of this scheme is that all providers
and all consumers of the sockets can be
started in parallel as soon as all sockets
- are established. In addition to that daemons
+ are established. In addition to that, daemons
can be restarted with losing only a minimal
- number of client transactions or even any
+ number of client transactions, or even any
client request at all (the latter is
particularly true for state-less protocols,
such as DNS or syslog), because the socket
@@ -462,16 +462,16 @@
<para>New-style daemons which support socket
activation must be able to receive their
- sockets from the init system, instead of
+ sockets from the init system instead of
creating and binding them themselves. For
details about the programming interfaces for
- this scheme provided by systemd see
+ this scheme provided by systemd, see
<citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>
and
<citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>3</manvolnum></citerefentry>. For
details about porting existing daemons to
- socket-based activation see below. With
- minimal effort it is possible to implement
+ socket-based activation, see below. With
+ minimal effort, it is possible to implement
socket-based activation in addition to
traditional internal socket creation in the
same codebase in order to support both
@@ -483,20 +483,20 @@
units, which are described in
<citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>. When
configuring socket units for socket-based
- activation it is essential that all listening
+ activation, it is essential that all listening
sockets are pulled in by the special target
unit <filename>sockets.target</filename>. It
is recommended to place a
<varname>WantedBy=sockets.target</varname>
directive in the <literal>[Install]</literal>
- section, to automatically add such a
+ section to automatically add such a
dependency on installation of a socket
unit. Unless
<varname>DefaultDependencies=no</varname> is
- set the necessary ordering dependencies are
+ set, the necessary ordering dependencies are
implicitly created for all socket units. For
more information about
- <filename>sockets.target</filename> see
+ <filename>sockets.target</filename>, see
<citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>. It
is not necessary or recommended to place any
additional dependencies on socket units (for
@@ -518,16 +518,16 @@
service files (not to be confused with systemd
service unit files!). To ensure that D-Bus
uses systemd to start-up and maintain the
- daemon use the
+ daemon, use the
<varname>SystemdService=</varname> directive
- in these service files, to configure the
+ in these service files to configure the
matching systemd service for a D-Bus
- service. e.g.: for a D-Bus service whose D-Bus
+ service. e.g.: For a D-Bus service whose D-Bus
activation file is named
<filename>org.freedesktop.RealtimeKit.service</filename>,
make sure to set
<varname>SystemdService=rtkit-daemon.service</varname>
- in that file, to bind it to the systemd
+ in that file to bind it to the systemd
service
<filename>rtkit-daemon.service</filename>. This
is needed to make sure that the daemon is
@@ -542,23 +542,23 @@
type of hardware should be activated only when
the hardware of the respective kind is plugged
in or otherwise becomes available. In a
- new-style init system it is possible to bind
+ new-style init system, it is possible to bind
activation to hardware plug/unplug events. In
systemd, kernel devices appearing in the
sysfs/udev device tree can be exposed as units
if they are tagged with the string
- "<literal>systemd</literal>". Like any other
- kind of unit they may then pull in other units
- when activated (i.e. Plugged in) and thus
- implement device-based activation. Systemd
+ <literal>systemd</literal>. Like any other
+ kind of unit, they may then pull in other units
+ when activated (i.e. plugged in) and thus
+ implement device-based activation. systemd
dependencies may be encoded in the udev
database via the
<varname>SYSTEMD_WANTS=</varname>
property. See
<citerefentry><refentrytitle>systemd.device</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- for details. Often it is nicer to pull in
+ for details. Often, it is nicer to pull in
services from devices only indirectly via
- dedicated targets. Example: instead of pulling
+ dedicated targets. Example: Instead of pulling
in <filename>bluetoothd.service</filename>
from all the various bluetooth dongles and
other hardware available, pull in
@@ -610,10 +610,10 @@
<para>Other forms of activation have been
suggested and implemented in some
- systems. However, often there are simpler or
+ systems. However, there are often simpler or
better alternatives, or they can be put
together of combinations of the schemes
- above. Example: sometimes it appears useful to
+ above. Example: Sometimes, it appears useful to
start daemons or <filename>.socket</filename>
units when a specific IP address is configured
on a network interface, because network
@@ -634,7 +634,7 @@
service activation is low system
load. However, here too, a more convincing
approach might be to make proper use of
- features of the operating system: in
+ features of the operating system, in
particular, the CPU or IO scheduler of
Linux. Instead of scheduling jobs from
userspace based on monitoring the OS
@@ -668,7 +668,7 @@
suggestions:</para>
<orderedlist>
- <listitem><para>If possible do not use
+ <listitem><para>If possible, do not use
the <varname>Type=forking</varname>
setting in service files. But if you
do, make sure to set the PID file path
@@ -711,15 +711,15 @@
information for the unit file. See
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details. To activate your service
- on boot make sure to add a
+ on boot, make sure to add a
<varname>WantedBy=multi-user.target</varname>
or
<varname>WantedBy=graphical.target</varname>
directive. To activate your socket on
boot, make sure to add
- <varname>WantedBy=sockets.target</varname>. Usually
+ <varname>WantedBy=sockets.target</varname>. Usually,
you also want to make sure that when
- your service is installed your socket
+ your service is installed, your socket
is installed too, hence add
<varname>Also=foo.socket</varname> in
your service file
@@ -735,7 +735,7 @@
<para>At the build installation time
(e.g. <command>make install</command> during
- package build) packages are recommended to
+ package build), packages are recommended to
install their systemd unit files in the
directory returned by <command>pkg-config
systemd
@@ -748,12 +748,12 @@
request but not activate them automatically
during boot. Optionally, during package
installation (e.g. <command>rpm -i</command>
- by the administrator) symlinks should be
+ by the administrator), symlinks should be
created in the systemd configuration
directories via the <command>enable</command>
command of the
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- tool, to activate them automatically on
+ tool to activate them automatically on
boot.</para>
<para>Packages using
@@ -801,7 +801,7 @@ endif</programlisting>
<para>In the
<citerefentry><refentrytitle>rpm</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- <filename>.spec</filename> file use snippets
+ <filename>.spec</filename> file, use snippets
like the following to enable/disable the
service during
installation/deinstallation. This makes use of
@@ -827,7 +827,7 @@ endif</programlisting>
%systemd_postun</programlisting>
<para>If the service shall be restarted during
- upgrades replace the
+ upgrades, replace the
<literal>%postun</literal> scriptlet above
with the following:</para>
@@ -859,7 +859,7 @@ fi</programlisting>
<para>Where 0.47.11-1 is the first package
version that includes the native unit
file. This fragment will ensure that the first
- time the unit file is installed it will be
+ time the unit file is installed, it will be
enabled if and only if the SysV init script is
enabled, thus making sure that the enable
status is not changed. Note that
@@ -875,13 +875,13 @@ fi</programlisting>
<title>Porting Existing Daemons</title>
<para>Since new-style init systems such as systemd are
- compatible with traditional SysV init systems it is
+ compatible with traditional SysV init systems, it is
not strictly necessary to port existing daemons to the
- new style. However doing so offers additional
+ new style. However, doing so offers additional
functionality to the daemons as well as simplifying
integration into new-style init systems.</para>
- <para>To port an existing SysV compatible daemon the
+ <para>To port an existing SysV compatible daemon, the
following steps are recommended:</para>
<orderedlist>
@@ -894,9 +894,9 @@ fi</programlisting>
<listitem><para>If the daemon offers
interfaces to other software running on the
- local system via local AF_UNIX sockets,
+ local system via local <constant>AF_UNIX</constant> sockets,
consider implementing socket-based activation
- (see above). Usually a minimal patch is
+ (see above). Usually, a minimal patch is
sufficient to implement this: Extend the
socket creation in the daemon code so that
<citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>
@@ -905,8 +905,8 @@ fi</programlisting>
<function>sd_listen_fds()</function> returns a
positive value), skip the socket creation step
and use the passed sockets. Secondly, ensure
- that the file-system socket nodes for local
- AF_UNIX sockets used in the socket-based
+ that the file system socket nodes for local
+ <constant>AF_UNIX</constant> sockets used in the socket-based
activation are not removed when the daemon
shuts down, if sockets have been
passed. Third, if the daemon normally closes
diff --git a/man/halt.xml b/man/halt.xml
index 8473965194..2a13d3c635 100644
--- a/man/halt.xml
+++ b/man/halt.xml
@@ -114,7 +114,7 @@
<term><option>--force</option></term>
<listitem><para>Force immediate halt,
- power-off, reboot. Don't contact the
+ power-off, reboot. Do not contact the
init system.</para></listitem>
</varlistentry>
@@ -123,7 +123,7 @@
<term><option>--wtmp-only</option></term>
<listitem><para>Only write wtmp
- shutdown entry, don't actually halt,
+ shutdown entry, do not actually halt,
power-off, reboot.</para></listitem>
</varlistentry>
@@ -131,14 +131,14 @@
<term><option>-d</option></term>
<term><option>--no-wtmp</option></term>
- <listitem><para>Don't write wtmp
+ <listitem><para>Do not write wtmp
shutdown entry.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--no-wall</option></term>
- <listitem><para>Don't send wall
+ <listitem><para>Do not send wall
message before
halt, power-off, reboot.</para></listitem>
</varlistentry>
diff --git a/man/hostname.xml b/man/hostname.xml
index f89332e983..a8648c5291 100644
--- a/man/hostname.xml
+++ b/man/hostname.xml
@@ -44,7 +44,7 @@
<refnamediv>
<refname>hostname</refname>
- <refpurpose>Local host name configuration file</refpurpose>
+ <refpurpose>Local hostname configuration file</refpurpose>
</refnamediv>
<refsynopsisdiv>
@@ -56,20 +56,20 @@
<para>The <filename>/etc/hostname</filename> file
configures the name of the local system that is set
- during boot, with the
+ during boot using the
<citerefentry><refentrytitle>sethostname</refentrytitle><manvolnum>2</manvolnum></citerefentry>
system call. It should contain a single
- newline-terminated host name string. The
- host name may be a free-form string up to 64 characters
- in length, however it is recommended that it consists
- only of 7bit ASCII lower-case characters and no spaces or dots,
+ newline-terminated hostname string. The
+ hostname may be a free-form string up to 64 characters
+ in length; however, it is recommended that it consists
+ only of 7-bit ASCII lower-case characters and no spaces or dots,
and limits itself to the format allowed for DNS domain
name labels, even though this is not a
strict requirement.</para>
- <para>Depending on the operating system other
+ <para>Depending on the operating system, other
configuration files might be checked for configuration
- of the host name as well, however only as fallback.</para>
+ of the hostname as well, however only as fallback.</para>
<para>You may use
<citerefentry><refentrytitle>hostnamectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
diff --git a/man/hostnamectl.xml b/man/hostnamectl.xml
index 9efe220119..b39fb5502b 100644
--- a/man/hostnamectl.xml
+++ b/man/hostnamectl.xml
@@ -49,7 +49,9 @@
<refsynopsisdiv>
<cmdsynopsis>
- <command>hostnamectl <arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="req">COMMAND</arg></command>
+ <command>hostnamectl</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="req">COMMAND</arg>
</cmdsynopsis>
</refsynopsisdiv>
@@ -60,9 +62,9 @@
query and change the system hostname and related
settings.</para>
- <para>This tool distinguishes three different host
- names: the high-level "pretty" hostname which might
- include all kinds of special characters
+ <para>This tool distinguishes three different
+ hostnames: the high-level "pretty" hostname which
+ might include all kinds of special characters
(e.g. "Lennart's Laptop"), the static hostname which
is used to initialize the kernel hostname at boot
(e.g. "lennarts-laptop"), and the transient hostname
@@ -75,13 +77,13 @@
<para>Note that the pretty hostname has little
restrictions on the characters used, while the static
and transient hostnames are limited to the usually
- accepted characters of internet domain names.</para>
+ accepted characters of Internet domain names.</para>
- <para>The static host name is stored in
+ <para>The static hostname is stored in
<filename>/etc/hostname</filename>, see
<citerefentry><refentrytitle>hostname</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- for more information. The pretty host name, chassis
- type and icon name are stored in
+ for more information. The pretty hostname, chassis
+ type, and icon name are stored in
<filename>/etc/machine-info</filename>, see
<citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
</refsect1>
@@ -110,18 +112,26 @@
<varlistentry>
<term><option>--no-ask-password</option></term>
- <listitem><para>Don't query the user
+ <listitem><para>Do not query the user
for authentication for privileged
operations.</para></listitem>
</varlistentry>
<varlistentry>
+ <term><option>-P</option></term>
+ <term><option>--privileged</option></term>
+
+ <listitem><para>Acquire privileges via PolicyKit
+ before executing the operation.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>-H</option></term>
<term><option>--host</option></term>
<listitem><para>Execute the operation
remotely. Specify a hostname, or
- username and hostname separated by @,
+ username and hostname separated by <literal>@</literal>,
to connect to. This will use SSH to
talk to a remote
system.</para></listitem>
@@ -133,11 +143,20 @@
<term><option>--pretty</option></term>
<listitem><para>If
- <command>set-hostname</command> is
- invoked and one or more of these
- options are passed only the selected
- hostnames is
- updated.</para></listitem>
+ <command>status</command> is used (or
+ no explicit command is given) and one
+ of those fields is given,
+ <command>hostnamectl</command> will
+ print out just this selected
+ hostname.</para>
+
+ <para>If used with
+ <command>set-hostname</command>, only
+ the selected hostname(s) will be
+ updated. When more than one of those
+ options is used, all the specified
+ hostnames will be updated.
+ </para></listitem>
</varlistentry>
</variablelist>
@@ -156,34 +175,35 @@
<term><command>set-hostname [NAME]</command></term>
<listitem><para>Set the system
- hostname. By default this will alter
+ hostname. By default, this will alter
the pretty, the static, and the
- transient hostname alike, however if
+ transient hostname alike; however, if
one or more of
<option>--static</option>,
<option>--transient</option>,
- <option>--pretty</option> are used
+ <option>--pretty</option> are used,
only the selected hostnames are
changed. If the pretty hostname is
being set, and static or transient are
- being set as well the specified host
- name will be simplified in regards to
- the character set used before the
+ being set as well, the specified
+ hostname will be simplified in regards
+ to the character set used before the
latter are updated. This is done by
- replacing spaces by "-" and removing
+ replacing spaces with
+ <literal>-</literal> and removing
special characters. This ensures that
- the pretty and the static hostname
- are always closely related while still
+ the pretty and the static hostname are
+ always closely related while still
following the validity rules of the
specific name. This simplification of
the hostname string is not done if
only the transient and/or static host
names are set, and the pretty host
name is left untouched. Pass the empty
- string "" as hostname to reset the
- selected hostnames to their default
- (usually
- "localhost").</para></listitem>
+ string <literal></literal> as the
+ hostname to reset the selected
+ hostnames to their default (usually
+ <literal>localhost</literal>).</para></listitem>
</varlistentry>
<varlistentry>
@@ -198,7 +218,7 @@
Naming Specification</ulink>. Pass an
empty string to this operation to
reset the icon name to the default
- value which is determined from chassis
+ value, which is determined from chassis
type (see below) and possibly other
parameters.</para></listitem>
</varlistentry>
diff --git a/man/journalctl.xml b/man/journalctl.xml
index cc7d1a0533..b5a0c539ca 100644
--- a/man/journalctl.xml
+++ b/man/journalctl.xml
@@ -64,11 +64,11 @@
journal as written by
<citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
- <para>If called without parameter it will show the full
+ <para>If called without parameters, it will show the full
contents of the journal, starting with the oldest
entry collected.</para>
- <para>If one or more match arguments are passed the
+ <para>If one or more match arguments are passed, the
output is filtered accordingly. A match is in the
format <literal>FIELD=VALUE</literal>,
e.g. <literal>_SYSTEMD_UNIT=httpd.service</literal>,
@@ -76,7 +76,7 @@
entry. See
<citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</manvolnum></citerefentry>
for a list of well-known fields. If multiple matches
- are specified matching different fields the log
+ are specified matching different fields, the log
entries are filtered by both, i.e. the resulting output
will show only entries matching all the specified
matches of this kind. If two matches apply to the same
@@ -84,29 +84,43 @@
alternatives, i.e. the resulting output will show
entries matching any of the specified matches for the
same field. Finally, if the character
- "<literal>+</literal>" appears as separate word on the
- command line all matches before and after are combined
+ <literal>+</literal> appears as separate word on the
+ command line, all matches before and after are combined
in a disjunction (i.e. logical OR).</para>
<para>As shortcuts for a few types of field/value
- matches file paths may be specified. If a file path
+ matches, file paths may be specified. If a file path
refers to an executable file, this is equivalent to an
<literal>_EXE=</literal> match for the canonicalized
- binary path. Similar, if a path refers to a device
+ binary path. Similarly, if a path refers to a device
node, this is equivalent to a
<literal>_KERNEL_DEVICE=</literal> match for the
device.</para>
<para>Output is interleaved from all accessible
journal files, whether they are rotated or currently
- being written, and regardless whether they belong to the
+ being written, and regardless of whether they belong to the
system itself or are accessible user journals.</para>
<para>All users are granted access to their private
- per-user journals. However, by default only root and
- users who are members of the <literal>adm</literal>
+ per-user journals. However, by default, only root and
+ users who are members of the <literal>systemd-journal</literal>
group get access to the system journal and the
journals of other users.</para>
+
+ <para>The output is paged through
+ <command>less</command> by default, and long lines are
+ "truncated" to screen width. The hidden part can be
+ viewed by using the left-arrow and right-arrow
+ keys. Paging can be disabled, see
+ <option>--no-pager</option> and section Environment
+ below.</para>
+
+ <para>When outputing to a tty, lines are colored
+ according to priority: lines of level ERROR and higher
+ are colored red, lines of level NOTICE and higher are
+ highlighted, and other lines are displayed normally.
+ </para>
</refsect1>
<refsect1>
@@ -138,6 +152,7 @@
</varlistentry>
<varlistentry>
+ <term><option>-l</option></term>
<term><option>--full</option></term>
<listitem><para>Show all (printable) fields in
@@ -172,7 +187,7 @@
the end of the journal inside the
implied pager tool. This implies
<option>-n1000</option> to guarantee
- that the pager won't buffer logs of
+ that the pager will not buffer logs of
unbounded size. This may be overridden
with an explicit <option>-n</option>
with some other numeric value on the
@@ -218,53 +233,150 @@
<listitem><para>Controls the
formatting of the journal entries that
- are shown. Takes one of
- <literal>short</literal>,
- <literal>short-monotonic</literal>,
- <literal>verbose</literal>,
- <literal>export</literal>,
- <literal>json</literal>,
- <literal>json-pretty</literal>,
- <literal>json-sse</literal>,
- <literal>cat</literal>. <literal>short</literal>
- is the default and generates an output
- that is mostly identical to the
- formatting of classic syslog log
- files, showing one line per journal
- entry. <literal>short-monotonic</literal>
- is very similar but shows monotonic
- timestamps instead of wallclock
- timestamps. <literal>verbose</literal>
- shows the full structured entry items
- with all
- fields. <literal>export</literal>
- serializes the journal into a binary
- (but mostly text-based) stream
- suitable for backups and network
- transfer (see <ulink
- url="http://www.freedesktop.org/wiki/Software/systemd/export">Journal
- Export Format</ulink> for more
- information). <literal>json</literal>
- formats entries as JSON data
- structures, one per
- line (see <ulink
- url="http://www.freedesktop.org/wiki/Software/systemd/json">Journal
- JSON Format</ulink> for more
- information). <literal>json-pretty</literal>
- also formats entries as JSON data
- structures, but formats them in
- multiple lines in order to make them
- more readable for
- humans. <literal>json-sse</literal>
- also formats entries as JSON data
- structures, but wraps them in a format
- suitable for <ulink
- url="https://developer.mozilla.org/en-US/docs/Server-sent_events/Using_server-sent_events">Server-Sent
- Events</ulink>. <literal>cat</literal>
- generates a very terse output only
- showing the actual message of each
- journal entry with no meta data, not
- even a timestamp.</para></listitem>
+ are shown. Takes one of the following options:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term>
+ <option>short</option>
+ </term>
+ <listitem>
+ <para>is the default
+ and generates an output
+ that is mostly identical
+ to the formatting of
+ classic syslog files,
+ showing one line per
+ journal entry.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>short-iso</option>
+ </term>
+ <listitem>
+ <para>is very similar,
+ but shows ISO 8601
+ wallclock timestamps.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>short-precise</option>
+ </term>
+ <listitem>
+ <para>is very similar,
+ but shows timestamps
+ with full microsecond
+ precision.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>short-monotonic</option>
+ </term>
+ <listitem>
+ <para>is very similar,
+ but shows monotonic
+ timestamps instead of
+ wallclock timestamps.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>verbose</option>
+ </term>
+ <listitem>
+ <para>shows the
+ full-structured entry
+ items with all fields.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>export</option>
+ </term>
+ <listitem>
+ <para>serializes the
+ journal into a binary
+ (but mostly text-based)
+ stream suitable for
+ backups and network
+ transfer (see <ulink
+ url="http://www.freedesktop.org/wiki/Software/systemd/export">Journal
+ Export Format</ulink>
+ for more
+ information).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>json</option>
+ </term>
+ <listitem>
+ <para>formats entries
+ as JSON data structures,
+ one per line (see <ulink
+ url="http://www.freedesktop.org/wiki/Software/systemd/json">Journal
+ JSON Format</ulink> for
+ more information).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>json-pretty</option>
+ </term>
+ <listitem>
+ <para>formats entries as
+ JSON data structures,
+ but formats them in
+ multiple lines in order
+ to make them more
+ readable for humans.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>json-sse</option>
+ </term>
+ <listitem>
+ <para>formats entries as
+ JSON data structures,
+ but wraps them in a
+ format suitable for <ulink
+ url="https://developer.mozilla.org/en-US/docs/Server-sent_events/Using_server-sent_events">Server-Sent
+ Events</ulink>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>cat</option>
+ </term>
+ <listitem>
+ <para>generates a very
+ terse output only
+ showing the actual
+ message of each journal
+ entry with no meta data,
+ not even a timestamp.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </listitem>
</varlistentry>
<varlistentry>
@@ -280,15 +392,22 @@
context of an error or log event,
possible solutions, as well as
pointers to support forums, developer
- documentation and any other relevant
+ documentation, and any other relevant
manuals. Note that help texts are not
available for all messages, but only
for selected ones. For more
- information on the message catalog
+ information on the message catalog,
please refer to the <ulink
url="http://www.freedesktop.org/wiki/Software/systemd/catalog">Message
Catalog Developer
- Documentation</ulink>.</para></listitem>
+ Documentation</ulink>.</para>
+
+ <para>Note: when attaching
+ <command>journalctl</command> output
+ to bug reports, please do
+ <emphasis>not</emphasis> use
+ <option>-x</option>.</para>
+ </listitem>
</varlistentry>
<varlistentry>
@@ -312,14 +431,60 @@
</varlistentry>
<varlistentry>
- <term><option>-b</option></term>
- <term><option>--this-boot</option></term>
+ <term><option>-b <optional><replaceable>ID</replaceable></optional><optional><replaceable>±offset</replaceable></optional></option></term>
+ <term><option>--boot=<optional><replaceable>ID</replaceable></optional><optional><replaceable>±offset</replaceable></optional></option></term>
+
+ <listitem><para>Show messages from a specific
+ boot. This will add a match for
+ <literal>_BOOT_ID=</literal>.</para>
+
+ <para>The argument may be empty, in which case
+ logs for the current boot will be shown.</para>
+
+ <para>If the boot ID is omitted, a positive
+ <replaceable>offset</replaceable> will look up
+ the boots starting from the beginning of the
+ journal, and a equal-or-less-than zero
+ <replaceable>offset</replaceable> will look up
+ boots starting from the end of the
+ journal. Thus, <constant>1</constant> means the
+ first boot found in the journal in the
+ chronological order, <constant>2</constant> the
+ second and so on; while <constant>-0</constant>
+ is the last boot, <constant>-1</constant> the
+ boot before that, and so on. An empty
+ <replaceable>offset</replaceable> is equivalent
+ to specifying <constant>-0</constant>, except
+ when the current boot is not the last boot
+ (e.g. because <option>--directory</option> was
+ specified to look at logs from a different
+ machine).</para>
+
+ <para>If the 32 character
+ <replaceable>ID</replaceable> is specified, it
+ may optionally be followed by
+ <replaceable>offset</replaceable> which
+ identifies the boot relative to the one given by
+ boot <replaceable>ID</replaceable>. Negative
+ values mean earlier boots and a positive values
+ mean later boots. If
+ <replaceable>offset</replaceable> is not
+ specified, a value of zero is assumed and the
+ logs for the boot given by
+ <replaceable>ID</replaceable> are shown.
+ </para>
- <listitem><para>Show data only from
- current boot. This will add a match
- for <literal>_BOOT_ID=</literal> for
- the current boot ID of the
- kernel.</para></listitem>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-k</option></term>
+ <term><option>--dmesg</option></term>
+
+ <listitem><para>Show only kernel messages. This
+ implies <option>-b</option> and adds the match
+ <literal>_TRANSPORT=kernel</literal>.
+ </para></listitem>
</varlistentry>
<varlistentry>
@@ -375,10 +540,10 @@
<literal>notice</literal> (5),
<literal>info</literal> (6),
<literal>debug</literal> (7). If a
- single log level is specified all
+ single log level is specified, all
messages with this log level or a
lower (hence more important) log level
- are shown. If a range is specified all
+ are shown. If a range is specified, all
messages within the range are shown,
including both the start and the end
value of the range. This will add
@@ -398,20 +563,31 @@
</varlistentry>
<varlistentry>
+ <term><option>--after-cursor=</option></term>
+
+ <listitem><para>Start showing entries from the
+ location in the journal
+ <emphasis>after</emphasis> the location
+ specified by the this cursor.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>--since=</option></term>
<term><option>--until=</option></term>
<listitem><para>Start showing entries
on or newer than the specified date,
or on or older than the specified
- date, respectively. Date specifications should be of
- the format "2012-10-30 18:17:16". If
- the time part is omitted, 00:00:00 is
- assumed. If only the seconds component
- is omitted, :00 is assumed. If the
- date component is omitted, the
- current day is assumed. Alternatively
- the strings
+ date, respectively. Date specifications
+ should be of the format
+ <literal>2012-10-30 18:17:16</literal>.
+ If the time part is omitted,
+ <literal>00:00:00</literal> is assumed.
+ If only the seconds component is omitted,
+ <literal>:00</literal> is assumed. If the
+ date component is omitted, the current
+ day is assumed. Alternatively the strings
<literal>yesterday</literal>,
<literal>today</literal>,
<literal>tomorrow</literal> are
@@ -438,22 +614,50 @@
</varlistentry>
<varlistentry>
- <term><option>-D</option></term>
- <term><option>--directory=</option></term>
+ <term><option>--system</option></term>
+ <term><option>--user</option></term>
- <listitem><para>Takes a
- directory path as argument. If
- specified journalctl will operate on the
- specified journal directory instead of
- the default runtime and system journal
- paths.</para></listitem>
+ <listitem><para>Show messages from
+ system services and the kernel (with
+ <option>--system</option>). Show
+ messages from service of current user
+ (with <option>--user</option>).
+ If neither is specified, show all
+ messages that the user can see.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-D <replaceable>DIR</replaceable></option></term>
+ <term><option>--directory=<replaceable>DIR</replaceable></option></term>
+
+ <listitem><para>Takes a directory path
+ as argument. If specified, journalctl
+ will operate on the specified journal
+ directory
+ <replaceable>DIR</replaceable> instead
+ of the default runtime and system
+ journal paths.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--file=<replaceable>GLOB</replaceable></option></term>
+
+ <listitem><para>Takes a file glob as
+ argument. If specified, journalctl will
+ operate on the specified journal files
+ matching <replaceable>GLOB</replaceable>
+ instead of the default runtime and
+ system journal paths. May be specified
+ multiple times, in which case files will
+ be suitably interleaved.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--root=<replaceable>ROOT</replaceable></option></term>
<listitem><para>Takes a directory path
- as argument. If specified journalctl
+ as argument. If specified, journalctl
will operate on catalog file hierarchy
underneath the specified directory
instead of the root directory
@@ -467,13 +671,13 @@
<term><option>--new-id128</option></term>
<listitem><para>Instead of showing
- journal contents generate a new 128
+ journal contents, generate a new 128
bit ID suitable for identifying
messages. This is intended for usage
by developers who need a new
identifier for a new message they
introduce and want to make
- recognizable. Will print the new ID in
+ recognizable. This will print the new ID in
three different formats which can be
copied into source code or
similar.</para></listitem>
@@ -483,7 +687,7 @@
<term><option>--header</option></term>
<listitem><para>Instead of showing
- journal contents show internal header
+ journal contents, show internal header
information of the journal fields
accessed.</para></listitem>
</varlistentry>
@@ -547,21 +751,32 @@
<term><option>--setup-keys</option></term>
<listitem><para>Instead of showing
- journal contents generate a new key
+ journal contents, generate a new key
pair for Forward Secure Sealing
(FSS). This will generate a sealing
key and a verification key. The
sealing key is stored in the journal
data directory and shall remain on the
host. The verification key should be
- stored externally.</para></listitem>
+ stored externally. Also see the
+ <option>Seal=</option> option in
+ <citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for details.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--force</option></term>
+
+ <listitem><para>When --setup-keys is passed and
+ Forward Secure Sealing has already been set up,
+ recreate FSS keys.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--interval=</option></term>
<listitem><para>Specifies the change
- interval for the sealing key, when
+ interval for the sealing key when
generating an FSS key pair with
<option>--setup-keys</option>. Shorter
intervals increase CPU consumption but
@@ -577,9 +792,9 @@
<listitem><para>Check the journal file
for internal consistency. If the
file has been generated with FSS
- enabled, and the FSS verification key
+ enabled and the FSS verification key
has been specified with
- <option>--verify-key=</option>
+ <option>--verify-key=</option>,
authenticity of the journal file is
verified.</para></listitem>
</varlistentry>
@@ -599,7 +814,7 @@
<refsect1>
<title>Exit status</title>
- <para>On success 0 is returned, a non-zero failure
+ <para>On success, 0 is returned, a non-zero failure
code otherwise.</para>
</refsect1>
@@ -622,24 +837,24 @@
<refsect1>
<title>Examples</title>
- <para>Without arguments all collected logs are shown
+ <para>Without arguments, all collected logs are shown
unfiltered:</para>
<programlisting>journalctl</programlisting>
- <para>With one match specified all entries with a field matching the expression are shown:</para>
+ <para>With one match specified, all entries with a field matching the expression are shown:</para>
<programlisting>journalctl _SYSTEMD_UNIT=avahi-daemon.service</programlisting>
- <para>If two different fields are matched only entries matching both expressions at the same time are shown:</para>
+ <para>If two different fields are matched, only entries matching both expressions at the same time are shown:</para>
<programlisting>journalctl _SYSTEMD_UNIT=avahi-daemon.service _PID=28097</programlisting>
- <para>If two matches refer to the same field all entries matching either expression are shown:</para>
+ <para>If two matches refer to the same field, all entries matching either expression are shown:</para>
<programlisting>journalctl _SYSTEMD_UNIT=avahi-daemon.service _SYSTEMD_UNIT=dbus.service</programlisting>
- <para>If the separator "<literal>+</literal>" is used
+ <para>If the separator <literal>+</literal> is used,
two expressions may be combined in a logical OR. The
following will show all messages from the Avahi
service process with the PID 28097 plus all messages
@@ -656,6 +871,10 @@
<programlisting>journalctl /dev/sda</programlisting>
+ <para>Show all kernel logs from previous boot:</para>
+
+ <programlisting>journalctl -k -b -1</programlisting>
+
</refsect1>
<refsect1>
diff --git a/man/journald.conf.xml b/man/journald.conf.xml
index 6d54c94b57..7aa2e78ed3 100644
--- a/man/journald.conf.xml
+++ b/man/journald.conf.xml
@@ -54,8 +54,8 @@
<refsect1>
<title>Description</title>
- <para>This files configures various parameters of the
- systemd journal service
+ <para>This file configures various parameters of the
+ systemd journal service,
<citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
</refsect1>
@@ -77,13 +77,13 @@
<literal>persistent</literal>,
<literal>auto</literal> and
<literal>none</literal>. If
- <literal>volatile</literal> journal
+ <literal>volatile</literal>, journal
log data will be stored only in
memory, i.e. below the
<filename>/run/log/journal</filename>
hierarchy (which is created if
needed). If
- <literal>persistent</literal> data will
+ <literal>persistent</literal>, data will
be stored preferably on disk,
i.e. below the
<filename>/var/log/journal</filename>
@@ -112,7 +112,7 @@
<term><varname>Compress=</varname></term>
<listitem><para>Takes a boolean
- value. If enabled (the default) data
+ value. If enabled (the default), data
objects that shall be stored in the
journal and are larger than a certain
threshold are compressed with the XZ
@@ -125,14 +125,20 @@
<term><varname>Seal=</varname></term>
<listitem><para>Takes a boolean
- value. If enabled (the default) and a
+ value. If enabled (the default), and a
sealing key is available (as created
by
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
<option>--setup-keys</option>
- command), forward secure sealing (FSS) for
- all persistent journal files is
- enabled.</para></listitem>
+ command), forward secure sealing (FSS)
+ for all persistent journal files is
+ enabled. FSS is based on <ulink
+ url="https://eprint.iacr.org/2013/397">Seekable
+ Sequential Key Generators</ulink> by
+ G. A. Marson and B. Poettering and
+ may be used to protect journal files
+ from unnoticed
+ alteration.</para></listitem>
</varlistentry>
<varlistentry>
@@ -143,23 +149,23 @@
of <literal>login</literal>,
<literal>uid</literal> and
<literal>none</literal>. If
- <literal>login</literal> each logged
- in user will get his own journal
+ <literal>login</literal>, each logged-in
+ user will get his own journal
files, but systemd user IDs will log
into the system journal. If
- <literal>uid</literal> any user ID
+ <literal>uid</literal>, any user ID
will get his own journal files
regardless whether it belongs to a
system service or refers to a real
logged in user. If
- <literal>none</literal> journal files
- are not split up per-user and all
- messages are stored in the single
+ <literal>none</literal>, journal files
+ are not split up by user and all
+ messages are instead stored in the single
system journal. Note that splitting
- up journal files per-user is only
- available of journals are stored
+ up journal files by user is only
+ available for journals stored
persistently. If journals are stored
- on volatile storage (see above) only a
+ on volatile storage (see above), only a
single journal file for all user IDs
is kept. Defaults to
<literal>login</literal>.</para></listitem>
@@ -171,14 +177,14 @@
<listitem><para>Configures the rate
limiting that is applied to all
- messages generated on the system. If
+ messages generated on the system. If,
in the time interval defined by
- <varname>RateLimitInterval=</varname>
+ <varname>RateLimitInterval=</varname>,
more messages than specified in
<varname>RateLimitBurst=</varname> are
- logged by a service all further
+ logged by a service, all further
messages within the interval are
- dropped, until the interval is over. A
+ dropped until the interval is over. A
message about the number of dropped
messages is generated. This rate
limiting is applied per-service, so
@@ -221,17 +227,27 @@
<filename>/run/log/journal</filename>. The
former is used only when
<filename>/var</filename> is mounted,
- writable and the directory
+ writable, and the directory
<filename>/var/log/journal</filename>
- exists. Otherwise only the latter
+ exists. Otherwise, only the latter
applies. Note that this means that
during early boot and if the
administrator disabled persistent
- logging only the latter options apply,
+ logging, only the latter options apply,
while the former apply if persistent
logging is enabled and the system is
fully booted
- up. <varname>SystemMaxUse=</varname>
+ up. <command>journalctl</command> and
+ <command>systemd-journald</command>
+ ignore all files with names not ending
+ with <literal>.journal</literal> or
+ <literal>.journal~</literal>, so only
+ such files, located in the appropriate
+ directories, are taken into account
+ when calculating current disk usage.
+ </para>
+
+ <para><varname>SystemMaxUse=</varname>
and <varname>RuntimeMaxUse=</varname>
control how much disk space the
journal may use up at
@@ -240,15 +256,14 @@
system. <varname>SystemKeepFree=</varname>
and
<varname>RuntimeKeepFree=</varname>
- control how much disk space the
- journal shall always leave free for
- other uses if less than the disk space
- configured in
- <varname>SystemMaxUse=</varname> and
- <varname>RuntimeMaxUse=</varname> is
- available. Defaults to 15% of the size
- of the respective file
- system. <varname>SystemMaxFileSize=</varname>
+ control how much disk space
+ systemd-journald shall always leave
+ free for other uses. Defaults to 15%
+ of the size of the respective file
+ system. systemd-journald will respect
+ both limits, i.e. use the smaller of
+ the two values.
+ <varname>SystemMaxFileSize=</varname>
and
<varname>RuntimeMaxFileSize=</varname>
control how large individual journal
@@ -263,12 +278,13 @@
that usually seven rotated journal
files are kept as history. Specify
values in bytes or use K, M, G, T, P,
- E as units for the specified
- sizes. Note that size limits are
- enforced synchronously to journal
- files as they are extended, and need
- no explicit rotation step triggered by
- time.</para></listitem>
+ E as units for the specified sizes
+ (equal to 1024, 1024²,... bytes).
+ Note that size limits are enforced
+ synchronously when journal files are
+ extended, and no explicit rotation
+ step triggered by time is
+ needed.</para></listitem>
</varlistentry>
<varlistentry>
@@ -276,23 +292,26 @@
<listitem><para>The maximum time to
store entries in a single journal
- file, before rotating to the next
- one. Normally time-based rotation
+ file before rotating to the next
+ one. Normally, time-based rotation
should not be required as size-based
rotation with options such as
<varname>SystemMaxFileSize=</varname>
should be sufficient to ensure that
- journal files don't grow without
+ journal files do not grow without
bounds. However, to ensure that not
too much data is lost at once when old
- journal files are deleted it might
+ journal files are deleted, it might
make sense to change this value from
the default of one month. Set to 0 to
turn off this feature. This setting
takes time values which may be
- suffixed with the units year, month,
- week, day, h, m to override the
- default time unit of
+ suffixed with the units
+ <literal>year</literal>,
+ <literal>month</literal>,
+ <literal>week</literal>, <literal>day</literal>,
+ <literal>h</literal> or <literal>m</literal>
+ to override the default time unit of
seconds.</para></listitem>
</varlistentry>
@@ -304,31 +323,42 @@
controls whether journal files
containing entries older then the
specified time span are
- deleted. Normally time-based deletion
+ deleted. Normally, time-based deletion
of old journal files should not be
required as size-based deletion with
options such as
<varname>SystemMaxUse=</varname>
should be sufficient to ensure that
- journal files don't grow without
+ journal files do not grow without
bounds. However, to enforce data
- retention policies it might make sense
+ retention policies, it might make sense
to change this value from the
default of 0 (which turns off this
feature). This setting also takes
time values which may be suffixed with
- the units year, month, week, day, h, m
+ the units <literal>year</literal>,
+ <literal>month</literal>,
+ <literal>week</literal>, <literal>day</literal>,
+ <literal>h</literal> or <literal> m</literal>
to override the default time unit of
- seconds. </para></listitem>
+ seconds.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>SyncIntervalSec=</varname></term>
- <listitem><para>The timeout before syncing journal
- data to disk. After syncing journal files have
- OFFLINE state. Default timeout is 5 minutes.
+ <listitem><para>The timeout before
+ synchronizing journal files to
+ disk. After syncing, journal files are
+ placed in the OFFLINE state. Note that
+ syncing is unconditionally done
+ immediately after a log message of
+ priority CRIT, ALERT or EMERG has been
+ logged. This setting hence applies
+ only to messages of the levels ERR,
+ WARNING, NOTICE, INFO, DEBUG. The
+ default timeout is 5 minutes.
</para></listitem>
</varlistentry>
@@ -345,8 +375,8 @@
system console. These options take
boolean arguments. If forwarding to
syslog is enabled but no syslog daemon
- is running the respective option has
- no effect. By default only forwarding
+ is running, the respective option has
+ no effect. By default, only forwarding
to syslog is enabled. These settings
may be overridden at boot time with
the kernel command line options
diff --git a/man/kernel-command-line.xml b/man/kernel-command-line.xml
index 6d064f6373..cc267a3ecc 100644
--- a/man/kernel-command-line.xml
+++ b/man/kernel-command-line.xml
@@ -59,7 +59,7 @@
kernel command line arguments.</para>
<para>For command line parameters understood by the
- kernel please see <ulink
+ kernel, please see <ulink
url="https://www.kernel.org/doc/Documentation/kernel-parameters.txt"><filename>kernel-parameters.txt</filename></ulink>
and
<citerefentry><refentrytitle>bootparam</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
@@ -93,7 +93,7 @@
<listitem>
<para>Parameters understood by
the system and service manager
- to control system behavior. For details see
+ to control system behavior. For details, see
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
@@ -105,7 +105,19 @@
both the kernel and the system
and service manager to control
console log verbosity. For
- details see
+ details, see
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>debug</varname></term>
+ <listitem>
+ <para>Parameter understood by
+ both the kernel and the system
+ and service manager to control
+ console log verbosity. For
+ details, see
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
@@ -124,7 +136,7 @@
<para>Parameters understood by
the system and service
manager, as compatibility
- options. For details see
+ options. For details, see
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
@@ -148,7 +160,7 @@
<para>Parameters understood by
the system and service manager
to control locale and language
- settings. For details see
+ settings. For details, see
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
@@ -159,7 +171,7 @@
<listitem>
<para>Parameter understood by
the file system checker
- services. For details see
+ services. For details, see
<citerefentry><refentrytitle>systemd-fsck@.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
@@ -170,7 +182,7 @@
<listitem>
<para>Parameter understood by
the file quota checker
- service. For details see
+ service. For details, see
<citerefentry><refentrytitle>systemd-quotacheck.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
@@ -183,7 +195,7 @@
<listitem>
<para>Parameters understood by
the journal service. For
- details see
+ details, see
<citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
@@ -198,7 +210,7 @@
<listitem>
<para>Parameters understood by
the virtual console setup logic. For
- details see
+ details, see
<citerefentry><refentrytitle>systemd-vconsole-setup.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
@@ -210,11 +222,12 @@
<term><varname>rd.udev.children-max=</varname></term>
<term><varname>udev.exec-delay=</varname></term>
<term><varname>rd.udev.exec-delay=</varname></term>
+ <term><varname>net.ifnames=</varname></term>
<listitem>
<para>Parameters understood by
the device event managing daemon. For
- details see
+ details, see
<citerefentry><refentrytitle>systemd-udevd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
@@ -225,7 +238,7 @@
<listitem>
<para>May be used to disable
the Plymouth boot splash. For
- details see
+ details, see
<citerefentry><refentrytitle>plymouth</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
@@ -237,13 +250,15 @@
<term><varname>rd.luks.crypttab=</varname></term>
<term><varname>luks.uuid=</varname></term>
<term><varname>rd.luks.uuid=</varname></term>
+ <term><varname>luks.options=</varname></term>
+ <term><varname>rd.luks.options=</varname></term>
<term><varname>luks.key=</varname></term>
<term><varname>rd.luks.key=</varname></term>
<listitem>
<para>Configures the LUKS
full-disk encryption logic at
- boot. For details see
+ boot. For details, see
<citerefentry><refentrytitle>systemd-cryptsetup-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
@@ -255,7 +270,7 @@
<listitem>
<para>Configures the
<filename>/etc/fstab</filename>
- logic at boot. For details see
+ logic at boot. For details, see
<citerefentry><refentrytitle>systemd-fstab-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
@@ -267,7 +282,7 @@
<listitem>
<para>Load a specific kernel
module early at boot. For
- details see
+ details, see
<citerefentry><refentrytitle>systemd-modules-load.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
diff --git a/man/kernel-install.xml b/man/kernel-install.xml
index 8c2abc747c..929ceef4af 100644
--- a/man/kernel-install.xml
+++ b/man/kernel-install.xml
@@ -67,13 +67,13 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
located in the directory <filename>/usr/lib/kernel/install.d/</filename>
and the local administration directory <filename>/etc/kernel/install.d/</filename>.
All files are collectively sorted and executed in lexical order, regardless of the directory in
- which they live. However, files with identical file names replace each other.
+ which they live. However, files with identical filenames replace each other.
Files in <filename>/etc/kernel/install.d/</filename> take precedence over files with the same name
in <filename>/usr/lib/kernel/install.d/</filename>. This can be used to override a system-supplied
executables with a local file if needed; a symbolic link in <filename>/etc/kernel/install.d/</filename>
with the same name as an executable in <filename>/usr/lib/kernel/install.d/</filename>,
pointing to /dev/null, disables the executable entirely. Executables must have the
- extension .install; other extensions are ignored.</para>
+ extension <literal>.install</literal>; other extensions are ignored.</para>
</refsect1>
@@ -112,7 +112,7 @@ add <replaceable>KERNEL-VERSION</replaceable> <filename>/boot/<replaceable>MACHI
<varlistentry>
<term><command>remove <replaceable>KERNEL-VERSION</replaceable></command></term>
<listitem>
- <para>calls every executable <filename>/usr/lib/kernel/install.d/*.install</filename>
+ <para>Calls every executable <filename>/usr/lib/kernel/install.d/*.install</filename>
and <filename>/etc/kernel/install.d/*.install</filename> with the arguments
<programlisting>
remove <replaceable>KERNEL-VERSION</replaceable> <filename>/boot/<replaceable>MACHINE-ID</replaceable>/<replaceable>KERNEL-VERSION</replaceable>/</filename>
@@ -145,7 +145,7 @@ remove <replaceable>KERNEL-VERSION</replaceable> <filename>/boot/<replaceable>MA
<filename>/etc/kernel/install.d/*.install</filename>
</term>
<listitem>
- <para>Drop-in files, which are executed by kernel-install.</para>
+ <para>Drop-in files which are executed by kernel-install.</para>
</listitem>
</varlistentry>
<varlistentry>
diff --git a/man/locale.conf.xml b/man/locale.conf.xml
index 42634febac..e97092102c 100644
--- a/man/locale.conf.xml
+++ b/man/locale.conf.xml
@@ -64,7 +64,7 @@
newline-separated list of environment-like
shell-compatible variable assignments. It is possible
to source the configuration from shell scripts,
- however, beyond mere variable assignments no shell
+ however, beyond mere variable assignments, no shell
features are supported, allowing applications to read
the file without implementing a shell compatible
execution engine.</para>
@@ -92,7 +92,7 @@
overridden or unset by individual programs or
individual users.</para>
- <para>Depending on the operating system other
+ <para>Depending on the operating system, other
configuration files might be checked for locale
configuration as well, however only as
fallback.</para>
@@ -132,7 +132,7 @@
<para><filename>/etc/locale.conf</filename>:</para>
<programlisting>LANG=de_DE.UTF-8
-LC_MESSAGES=C</programlisting>
+LC_MESSAGES=en_US.UTF-8</programlisting>
</example>
</refsect1>
diff --git a/man/localectl.xml b/man/localectl.xml
index 0b13c111a5..ad4f3d41f0 100644
--- a/man/localectl.xml
+++ b/man/localectl.xml
@@ -49,7 +49,9 @@
<refsynopsisdiv>
<cmdsynopsis>
- <command>localectl <arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="req">COMMAND</arg></command>
+ <command>localectl</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="req">COMMAND</arg>
</cmdsynopsis>
</refsynopsisdiv>
@@ -103,18 +105,26 @@
<varlistentry>
<term><option>--no-ask-password</option></term>
- <listitem><para>Don't query the user
+ <listitem><para>Do not query the user
for authentication for privileged
operations.</para></listitem>
</varlistentry>
<varlistentry>
+ <term><option>-P</option></term>
+ <term><option>--privileged</option></term>
+
+ <listitem><para>Acquire privileges via PolicyKit
+ before executing the operation.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>-H</option></term>
<term><option>--host</option></term>
<listitem><para>Execute the operation
remotely. Specify a hostname, or
- username and hostname separated by @,
+ username and hostname separated by <literal>@</literal>,
to connect to. This will use SSH to
talk to a remote
system.</para></listitem>
@@ -126,7 +136,7 @@
<listitem><para>If
<command>set-keymap</command> or
<command>set-x11-keymap</command> is
- invoked and this option is passed then
+ invoked and this option is passed, then
the keymap will not be converted from
the console to X11, or X11 to console,
respectively.</para></listitem>
@@ -178,7 +188,7 @@
one to define a toggle keyboard
mapping. Unless
<option>--no-convert</option> is
- passed the selected setting is also
+ passed, the selected setting is also
applied to the default keyboard
mapping of X11, after converting it to
the closest matching X11 keyboard
@@ -208,7 +218,7 @@
<citerefentry><refentrytitle>kbd</refentrytitle><manvolnum>4</manvolnum></citerefentry>
for details. Unless
<option>--no-convert</option> is
- passed the selected setting is also
+ passed, the selected setting is also
applied to the system console keyboard
mapping, after converting it to the
closest matching console keyboard
@@ -239,7 +249,7 @@
<refsect1>
<title>Exit status</title>
- <para>On success 0 is returned, a non-zero failure
+ <para>On success, 0 is returned, a non-zero failure
code otherwise.</para>
</refsect1>
@@ -268,6 +278,9 @@
<citerefentry><refentrytitle>vconsole.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>loadkeys</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>kbd</refentrytitle><manvolnum>4</manvolnum></citerefentry>,
+ <ulink url="http://www.x.org/releases/current/doc/xorg-docs/input/XKB-Config.html">
+ The XKB Configuration Guide
+ </ulink>,
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-localed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
diff --git a/man/localtime.xml b/man/localtime.xml
index d3da4ed277..b7fd1ba15d 100644
--- a/man/localtime.xml
+++ b/man/localtime.xml
@@ -51,7 +51,7 @@
<refnamediv>
<refname>localtime</refname>
- <refpurpose>Local time zone configuration file</refpurpose>
+ <refpurpose>Local timezone configuration file</refpurpose>
</refnamediv>
<refsynopsisdiv>
@@ -62,24 +62,24 @@
<title>Description</title>
<para>The <filename>/etc/localtime</filename> file
- configures the system-wide time zone of the local
+ configures the system-wide timezone of the local
system that is used by applications for presentation
to the user. It should be an absolute or relative
symbolic link pointing to
<filename>/usr/share/zoneinfo/</filename>, followed by
- a time zone identifier such as
+ a timezone identifier such as
<literal>Europe/Berlin</literal> or
<literal>Etc/UTC</literal>. The resulting link should
lead to the corresponding binary
<citerefentry><refentrytitle>tzfile</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- time zone data for the configured time zone.</para>
+ timezone data for the configured timezone.</para>
- <para>As the time zone identifier is extracted from
+ <para>Because the timezone identifier is extracted from
the symlink target name of
- <filename>/etc/localtime</filename> this file may not
+ <filename>/etc/localtime</filename>, this file may not
be a normal file or hardlink.</para>
- <para>The time zone may be overridden for individual
+ <para>The timezone may be overridden for individual
programs by using the TZ environment variable. See
<citerefentry><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
diff --git a/man/loginctl.xml b/man/loginctl.xml
index 2c8d982eda..1b54ff7dc3 100644
--- a/man/loginctl.xml
+++ b/man/loginctl.xml
@@ -21,7 +21,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="loginctl" conditional='HAVE_PAM'>
+<refentry id="loginctl" conditional='ENABLE_LOGIND'>
<refentryinfo>
<title>loginctl</title>
@@ -49,7 +49,10 @@
<refsynopsisdiv>
<cmdsynopsis>
- <command>loginctl <arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="req">COMMAND</arg> <arg choice="opt" rep="repeat">NAME</arg></command>
+ <command>loginctl</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="req">COMMAND</arg>
+ <arg choice="opt" rep="repeat">NAME</arg>
</cmdsynopsis>
</refsynopsisdiv>
@@ -88,14 +91,14 @@
<term><option>--property=</option></term>
<listitem><para>When showing
- session/user properties, limit
+ session/user/seat properties, limit
display to certain properties as
specified as argument. If not
- specified all set properties are
+ specified, all set properties are
shown. The argument should be a
property name, such as
<literal>Sessions</literal>. If
- specified more than once all
+ specified more than once, all
properties with the specified names
are shown.</para></listitem>
</varlistentry>
@@ -105,16 +108,17 @@
<term><option>--all</option></term>
<listitem><para>When showing
- unit/job/manager properties, show all
+ session/user/seat properties, show all
properties regardless whether they are
set or not.</para></listitem>
</varlistentry>
<varlistentry>
+ <term><option>-l</option></term>
<term><option>--full</option></term>
- <listitem><para>Do not ellipsize cgroup
- members.</para>
+ <listitem><para>Do not ellipsize
+ process tree entries.</para>
</listitem>
</varlistentry>
@@ -128,7 +132,7 @@
<varlistentry>
<term><option>--no-ask-password</option></term>
- <listitem><para>Don't query the user
+ <listitem><para>Do not query the user
for authentication for privileged
operations.</para></listitem>
</varlistentry>
@@ -143,7 +147,7 @@
<option>all</option> to select whether
to kill only the leader process of the
session or all processes of the
- session. If omitted defaults to
+ session. If omitted, defaults to
<option>all</option>.</para></listitem>
</varlistentry>
@@ -156,10 +160,12 @@
<command>kill-user</command>, choose
which signal to send to selected
processes. Must be one of the well
- known signal specifiers such as
- SIGTERM, SIGINT or SIGSTOP. If omitted
- defaults to
- <option>SIGTERM</option>.</para></listitem>
+ known signal specifiers, such as
+ <constant>SIGTERM</constant>,
+ <constant>SIGINT</constant> or
+ <constant>SIGSTOP</constant>. If
+ omitted, defaults to
+ <constant>SIGTERM</constant>.</para></listitem>
</varlistentry>
<varlistentry>
@@ -168,7 +174,7 @@
<listitem><para>Execute operation
remotely. Specify a hostname, or
- username and hostname separated by @,
+ username and hostname separated by <literal>@</literal>,
to connect to. This will use SSH to
talk to the remote login manager
instance.</para></listitem>
@@ -211,14 +217,14 @@
<listitem><para>Show properties of one
or more sessions or the manager
- itself. If no argument is specified
+ itself. If no argument is specified,
properties of the manager will be
- shown. If a session ID is specified
- properties of the session is shown. By
+ shown. If a session ID is specified,
+ properties of the session are shown. By
default, empty properties are
suppressed. Use <option>--all</option>
to show those too. To select specific
- properties to show use
+ properties to show, use
<option>--property=</option>. This
command is intended to be used
whenever computer-parsable output is
@@ -307,14 +313,14 @@
<listitem><para>Show properties of one
or more users or the manager
- itself. If no argument is specified
+ itself. If no argument is specified,
properties of the manager will be
- shown. If a user is specified
- properties of the user is shown. By
+ shown. If a user is specified,
+ properties of the user are shown. By
default, empty properties are
suppressed. Use <option>--all</option>
to show those too. To select specific
- properties to show use
+ properties to show, use
<option>--property=</option>. This
command is intended to be used
whenever computer-parsable output is
@@ -331,10 +337,10 @@
<listitem><para>Enable/disable user
lingering for one or more users. If
- enabled for a specific user a user
+ enabled for a specific user, a user
manager is spawned for him/her at
- boot, and kept around after
- logouts. This allows users who aren't
+ boot and kept around after
+ logouts. This allows users who are not
logged in to run long-running
services.</para></listitem>
</varlistentry>
@@ -385,14 +391,14 @@
<listitem><para>Show properties of one
or more seats or the manager
- itself. If no argument is specified
+ itself. If no argument is specified,
properties of the manager will be
- shown. If a seat is specified
+ shown. If a seat is specified,
properties of the seat are shown. By
default, empty properties are
suppressed. Use <option>--all</option>
to show those too. To select specific
- properties to show use
+ properties to show, use
<option>--property=</option>. This
command is intended to be used
whenever computer-parsable output is
@@ -410,16 +416,18 @@
one or more devices to a seat. The
devices should be specified via device
paths in the <filename>/sys</filename>
- file system. To create a new seat
+ file system. To create a new seat,
attach at least one graphics card to a
previously unused seat name. Seat
names may consist only of a-z, A-Z,
- 0-9, "-" and "_" and must be prefixed
- with "seat". To drop assignment of a
- device to a specific seat just
- reassign it to a different seat, or
- use
- <command>flush-devices</command>.</para></listitem>
+ 0-9, <literal>-</literal> and
+ <literal>_</literal> and must be
+ prefixed with <literal>seat</literal>.
+ To drop assignment of a device to a
+ specific seat, just reassign it to a
+ different seat, or use
+ <command>flush-devices</command>.
+ </para></listitem>
</varlistentry>
<varlistentry>
@@ -428,8 +436,8 @@
<listitem><para>Removes all device
assignments previously created with
<command>attach</command>. After this
- call only automatically generated
- seats will remain and all seat
+ call, only automatically generated
+ seats will remain, and all seat
hardware is assigned to
them.</para></listitem>
</varlistentry>
@@ -450,7 +458,7 @@
<refsect1>
<title>Exit status</title>
- <para>On success 0 is returned, a non-zero failure
+ <para>On success, 0 is returned, a non-zero failure
code otherwise.</para>
</refsect1>
diff --git a/man/logind.conf.xml b/man/logind.conf.xml
index 47ee0e73ff..54cc379048 100644
--- a/man/logind.conf.xml
+++ b/man/logind.conf.xml
@@ -54,7 +54,7 @@
<refsect1>
<title>Description</title>
- <para>This file configures various parameters of the systemd login manager <citerefentry><refentrytitle>systemd-logind.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+ <para>This file configures various parameters of the systemd login manager, <citerefentry><refentrytitle>systemd-logind.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
</refsect1>
@@ -72,8 +72,8 @@
<listitem><para>Takes a positive
integer. Configures how many virtual
terminals (VTs) to allocate by default
- that -- when switched to and
- previously unused --
+ that, when switched to and are
+ previously unused,
<literal>autovt</literal> services are
automatically spawned on. These
services are instantiated from the
@@ -81,7 +81,7 @@
<filename>autovt@.service</filename>
for the respective VT TTY name,
e.g. <filename>autovt@tty4.service</filename>. By
- default
+ default,
<filename>autovt@.service</filename>
is linked to
<filename>getty@.service</filename>,
@@ -92,7 +92,7 @@
<literal>gettys</literal> are
available on the VTs. If a VT is
already used by some other subsystem
- (for example a graphical login) this
+ (for example a graphical login), this
kind of activation will not be
attempted. Note that the VT configured
in <varname>ReserveVT=</varname> is
@@ -103,7 +103,7 @@
directive. Defaults to 6. When set to
0, automatic spawning of
<literal>autovt</literal> services is
- disabled. </para></listitem>
+ disabled.</para></listitem>
</varlistentry>
<varlistentry>
@@ -116,14 +116,14 @@
<filename>autovt@.service</filename>
activation (see above). The VT
selected with this option will be
- marked busy unconditionally so that no
+ marked busy unconditionally, so that no
other subsystem will allocate it. This
functionality is useful to ensure that
- regardless how many VTs are allocated
- by other subsystems one login
+ regardless of how many VTs are allocated
+ by other subsystems, one login
<literal>getty</literal> is always
- available. Defaults to 6 (with other
- words: there'll always be a
+ 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
@@ -138,7 +138,34 @@
processes of a user should be killed
when she or he completely logs out (i.e. after
her/his last session ended). Defaults to
- <literal>no</literal>.</para></listitem>
+ <literal>no</literal>.</para>
+
+ <para>Note that setting
+ <varname>KillUserProcesses=1</varname>
+ will break tools like
+ <citerefentry><refentrytitle>screen</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</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>
@@ -161,11 +188,11 @@
user sessions correctly report the
idle status to the system. The system
will execute the action after all
- sessions reported that they are idle,
- and no idle inhibitor lock is active,
- and subsequently the time configured
+ sessions report that they are idle,
+ no idle inhibitor lock is active,
+ and subsequently, the time configured
with <varname>IdleActionSec=</varname>
- (see below) has passed.</para>
+ (see below) has expired.</para>
</listitem>
</varlistentry>
@@ -180,71 +207,14 @@
</varlistentry>
<varlistentry>
- <term><varname>KillOnlyUsers=</varname></term>
- <term><varname>KillExcludeUsers=</varname></term>
-
- <listitem><para>These settings take
- space separated lists of user names
- 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>Controllers=</varname></term>
- <term><varname>ResetControllers=</varname></term>
-
- <listitem><para>These settings control
- the default control group hierarchies
- users logging in are added to, in
- addition to the
- <literal>name=systemd</literal> named
- hierarchy. These settings take space
- separated lists of controller
- names. Pass the empty string to ensure
- that logind does not touch any
- hierarchies but systemd's own. When
- logging in user sessions will get
- private control groups in all
- hierarchies listed in
- <varname>Controllers=</varname> and be
- reset to the root control group in all
- hierarchies listed in
- <varname>ResetControllers=</varname>. <varname>Controllers=</varname>
- defaults to the empty list,
- <varname>ResetControllers=</varname>
- defaults to
- <literal>cpu</literal>. Note that for
- all controllers that are not listed in
- either <varname>Controllers=</varname>
- nor
- <varname>ResetControllers=</varname>
- newly created sessions will be part of
- the control groups of the system
- service that created the
- session.</para></listitem>
- </varlistentry>
-
- <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 it is ignored
- and the operation executed
+ being active before the inhibitor is
+ ignored and the operation executes
anyway. Defaults to
5s.</para></listitem>
</varlistentry>
@@ -269,11 +239,11 @@
<literal>hibernate</literal>,
<literal>hybrid-sleep</literal> and
<literal>lock</literal>. If
- <literal>ignore</literal> logind will
+ <literal>ignore</literal>, logind will
never handle these keys. If
- <literal>lock</literal> all running
- sessions will be screen
- locked. Otherwise the specified action
+ <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
@@ -301,17 +271,17 @@
sleep keys and the lid switch are
subject to inhibitor locks. These
settings take boolean arguments. If
- <literal>off</literal> the inhibitor
+ <literal>off</literal>, the inhibitor
locks taken by applications in order
to block the requested operation are
- respected, if <literal>on</literal>
+ respected. If <literal>on</literal>,
the requested operation is executed in
any
case. <varname>PowerKeyIgnoreInhibited=</varname>,
<varname>SuspendKeyIgnoreInhibited=</varname>
and
<varname>HibernateKeyIgnoreInhibited=</varname>
- defaults to <literal>off</literal>,
+ default to <literal>off</literal>.
<varname>LidSwitchIgnoreInhibited=</varname>
defaults to
<literal>yes</literal>. This means
@@ -322,20 +292,6 @@
</varlistentry>
</variablelist>
-
- <para>Note that setting
- <varname>KillUserProcesses=1</varname> will break tools
- like
- <citerefentry><refentrytitle>screen</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para>
-
- <para>Note that <varname>KillUserProcesses=1</varname>
- is a weaker version of
- <varname>kill-session-processes=1</varname> which may
- be configured per-service for
- <citerefentry><refentrytitle>pam_systemd</refentrytitle><manvolnum>8</manvolnum></citerefentry>. The
- latter kills processes of a session as soon as it
- ends, the former kills processes as soon as the last
- session of the user ends.</para>
</refsect1>
<refsect1>
diff --git a/man/machine-id.xml b/man/machine-id.xml
index 1e558a6178..4b4759e48d 100644
--- a/man/machine-id.xml
+++ b/man/machine-id.xml
@@ -55,21 +55,21 @@
<title>Description</title>
<para>The <filename>/etc/machine-id</filename> file
- contains the unique machine id of the local system
+ contains the unique machine ID of the local system
that is set during installation. The machine ID is a
- single newline-terminated, hexadecimal, lowercase 32
- character machine ID string. (When decoded from
- hexadecimal this corresponds with a 16 byte/128 bit
- string.)</para>
+ single newline-terminated, hexadecimal, 32-character,
+ lowercase machine ID string. When decoded from
+ hexadecimal, this corresponds with a 16-byte/128-bit
+ string.</para>
<para>The machine ID is usually generated from a
random source during system installation and stays
constant for all subsequent boots. Optionally, for
- stateless systems it is generated during runtime at
+ stateless systems, it is generated during runtime at
boot if it is found to be empty.</para>
<para>The machine ID does not change based on user
- configuration, or when hardware is replaced.</para>
+ configuration or when hardware is replaced.</para>
<para>This machine ID adheres to the same format and
logic as the D-Bus machine ID.</para>
@@ -77,10 +77,10 @@
<para>Programs may use this ID to identify the host
with a globally unique ID in the network, which does
not change even if the local network configuration
- changes. Due to this and its greater length it is
+ changes. Due to this and its greater length, it is
a more useful replacement for the
<citerefentry><refentrytitle>gethostid</refentrytitle><manvolnum>3</manvolnum></citerefentry>
- call POSIX specifies.</para>
+ call that POSIX specifies.</para>
<para>The
<citerefentry><refentrytitle>systemd-machine-id-setup</refentrytitle><manvolnum>1</manvolnum></citerefentry>
@@ -93,9 +93,9 @@
<para>Note that the machine ID historically is not an
OSF UUID as defined by <ulink
- url="http://tools.ietf.org/html/rfc4122">RFC
- 4122</ulink>, nor a Microsoft GUID. Starting with
- systemd v30 newly generated machine IDs however do
+ url="https://tools.ietf.org/html/rfc4122">RFC
+ 4122</ulink>, nor a Microsoft GUID; however, starting with
+ systemd v30, newly generated machine IDs do
qualify as v4 UUIDs.</para>
<para>In order to maintain compatibility with existing
@@ -113,7 +113,7 @@ id[8] = (id[8] &amp; 0x3F) | 0x80;</programlisting>
<para>(This code is inspired by
<literal>generate_random_uuid()</literal> of
<filename>drivers/char/random.c</filename> from the
- kernel sources.)</para>
+ Linux kernel sources.)</para>
</refsect1>
@@ -123,7 +123,7 @@ id[8] = (id[8] &amp; 0x3F) | 0x80;</programlisting>
<para>The simple configuration file format of
<filename>/etc/machine-id</filename> originates in the
<filename>/var/lib/dbus/machine-id</filename> file
- introduced by D-Bus. In fact this latter file might be a
+ introduced by D-Bus. In fact, this latter file might be a
symlink to
<varname>/etc/machine-id</varname>.</para>
</refsect1>
diff --git a/man/machine-info.xml b/man/machine-info.xml
index 1c3a21c643..ddf8f8b3d0 100644
--- a/man/machine-info.xml
+++ b/man/machine-info.xml
@@ -94,22 +94,22 @@
<term><varname>PRETTY_HOSTNAME=</varname></term>
<listitem><para>A pretty
- human-readable UTF8 machine identifier
+ human-readable UTF-8 machine identifier
string. This should contain a name
like <literal>Lennart's
Laptop</literal> which is useful to
present to the user and does not
suffer by the syntax limitations of
- internet domain names. If possible the
- internet host name as configured in
+ internet domain names. If possible, the
+ internet hostname as configured in
<filename>/etc/hostname</filename>
should be kept similar to this
one. Example: if this value is
<literal>Lennart's Computer</literal>
- an Internet host name of
+ an Internet hostname of
<literal>lennarts-computer</literal>
might be a good choice. If this
- parameter is not set an application
+ parameter is not set, an application
should fall back to the Internet host
name for presentation
purposes.</para></listitem>
@@ -122,7 +122,7 @@
this machine according to the <ulink
url="http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html">XDG
Icon Naming Specification</ulink>. If
- this parameter is not set an
+ this parameter is not set, an
application should fall back to
<literal>computer</literal> or a
similar icon name.</para></listitem>
diff --git a/man/machinectl.xml b/man/machinectl.xml
new file mode 100644
index 0000000000..2ed9f2e8a1
--- /dev/null
+++ b/man/machinectl.xml
@@ -0,0 +1,301 @@
+<?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">
+
+<!--
+ 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/>.
+-->
+
+<refentry id="machinectl" conditional='ENABLE_MACHINED'>
+
+ <refentryinfo>
+ <title>machinectl</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>machinectl</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>machinectl</refname>
+ <refpurpose>Control the systemd machine manager</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>machinectl</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="req">COMMAND</arg>
+ <arg choice="opt" rep="repeat">NAME</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><command>machinectl</command> may be used to
+ introspect and control the state of the
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ virtual machine and container registration manager <citerefentry><refentrytitle>systemd-machined.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Options</title>
+
+ <para>The following options are understood:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>-h</option></term>
+ <term><option>--help</option></term>
+
+ <listitem><para>Prints a short help
+ text and exits.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--version</option></term>
+
+ <listitem><para>Prints a short version
+ string and exits.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-p</option></term>
+ <term><option>--property=</option></term>
+
+ <listitem><para>When showing
+ machine properties, limit the
+ output to certain properties as
+ specified by the argument. If not
+ specified, all set properties are
+ shown. The argument should be a
+ property name, such as
+ <literal>Name</literal>. If
+ specified more than once, all
+ properties with the specified names
+ are shown.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-a</option></term>
+ <term><option>--all</option></term>
+
+ <listitem><para>When showing
+ machine properties, show all
+ properties regardless of whether they are
+ set or not.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-l</option></term>
+ <term><option>--full</option></term>
+
+ <listitem><para>Do not ellipsize
+ process tree entries.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--no-pager</option></term>
+
+ <listitem><para>Do not pipe output into a
+ pager.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--no-ask-password</option></term>
+
+ <listitem><para>Do not query the user
+ for authentication for privileged
+ operations.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--kill-who=</option></term>
+
+ <listitem><para>When used with
+ <command>kill-machine</command>,
+ choose which processes to kill. Must
+ be one of <option>leader</option>, or
+ <option>all</option> to select whether
+ to kill only the leader process of the
+ machine or all processes of the
+ machine. If omitted, defaults to
+ <option>all</option>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-s</option></term>
+ <term><option>--signal=</option></term>
+
+ <listitem><para>When used with
+ <command>kill-machine</command>, choose
+ which signal to send to selected
+ processes. Must be one of the
+ well-known signal specifiers, such as
+ <constant>SIGTERM</constant>,
+ <constant>SIGINT</constant> or
+ <constant>SIGSTOP</constant>. If
+ omitted, defaults to
+ <constant>SIGTERM</constant>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-H</option></term>
+ <term><option>--host</option></term>
+
+ <listitem><para>Execute operation
+ remotely. Specify a hostname, or
+ username and hostname separated by <literal>@</literal>,
+ to connect to. This will use SSH to
+ talk to the remote machine manager
+ instance.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-P</option></term>
+ <term><option>--privileged</option></term>
+
+ <listitem><para>Acquire privileges via
+ PolicyKit before executing the
+ operation.</para></listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>The following commands are understood:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><command>list</command></term>
+
+ <listitem><para>List currently running
+ virtual machines and containers.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>status [ID...]</command></term>
+
+ <listitem><para>Show terse runtime
+ status information about one or more
+ virtual machines and containers. This
+ function is intended to generate
+ human-readable output. If you are
+ looking for computer-parsable output,
+ use <command>show</command> instead.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>show [ID...]</command></term>
+
+ <listitem><para>Show properties of one
+ or more registered virtual machines or
+ containers or the manager itself. If
+ no argument is specified, properties
+ of the manager will be shown. If an
+ ID is specified, properties of this
+ virtual machine or container are
+ shown. By default, empty properties
+ are suppressed. Use
+ <option>--all</option> to show those
+ too. To select specific properties to
+ show, use
+ <option>--property=</option>. This
+ command is intended to be used
+ whenever computer-parsable output is
+ required. Use
+ <command>status</command> if you are
+ looking for formatted human-readable
+ output.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>terminate [ID...]</command></term>
+
+ <listitem><para>Terminates a virtual
+ machine or container. This kills all
+ processes of the virtual machine or
+ container and deallocates all
+ resources attached to that
+ instance.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>kill [ID...]</command></term>
+
+ <listitem><para>Send a signal to one
+ or more processes of the virtual
+ machine or container. This means
+ processes as seen by the host, not the
+ processes inside the virtual machine
+ or container.
+ Use <option>--kill-who=</option> to
+ select which process to kill. Use
+ <option>--signal=</option> to select
+ the signal to send.</para></listitem>
+ </varlistentry>
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1>
+ <title>Exit status</title>
+
+ <para>On success, 0 is returned, a non-zero failure
+ code otherwise.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Environment</title>
+
+ <variablelist class='environment-variables'>
+ <varlistentry>
+ <term><varname>$SYSTEMD_PAGER</varname></term>
+ <listitem><para>Pager to use when
+ <option>--no-pager</option> is not given;
+ overrides <varname>$PAGER</varname>. Setting
+ this to an empty string or the value
+ <literal>cat</literal> is equivalent to passing
+ <option>--no-pager</option>.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd-machined.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-logind.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/modules-load.d.xml b/man/modules-load.d.xml
index ce94bef7a7..33c466f926 100644
--- a/man/modules-load.d.xml
+++ b/man/modules-load.d.xml
@@ -90,11 +90,11 @@
packages.</para>
<para>If the administrator wants to disable a
- configuration file supplied by the vendor the
+ configuration file supplied by the vendor, the
recommended way is to place a symlink to
<filename>/dev/null</filename> in
<filename>/etc/modules-load.d/</filename> bearing the
- same file name.</para>
+ same filename.</para>
</refsect1>
<refsect1>
diff --git a/man/nss-myhostname.xml b/man/nss-myhostname.xml
index c0e2b828be..efbadac33f 100644
--- a/man/nss-myhostname.xml
+++ b/man/nss-myhostname.xml
@@ -45,7 +45,7 @@
<refnamediv>
<refname>nss-myhostname</refname>
- <refpurpose>Provide host name resolution for the locally
+ <refpurpose>Provide hostname resolution for the locally
configured system hostname.</refpurpose>
</refnamediv>
@@ -58,17 +58,17 @@
<para><command>nss-myhostname</command> is a plugin for the GNU Name Service Switch
(NSS) functionality of the GNU C Library (<command>glibc</command>)
- providing host name resolution for the locally configured system
+ providing hostname resolution for the locally configured system
hostname as returned by
<citerefentry><refentrytitle>gethostname</refentrytitle><manvolnum>2</manvolnum></citerefentry>.
- Various software relies on an always resolvable local host name. When
- using dynamic hostnames this is usually achieved by patching
+ Various software relies on an always-resolvable local hostname. When
+ using dynamic hostnames, this is usually achieved by patching
<filename>/etc/hosts</filename> at the same time as changing the host
name. This however is not ideal since it requires a writable
<filename>/etc</filename> file system and is fragile because the file
might be edited by the administrator at the same time. <command>nss-myhostname</command>
- simply returns all locally configure public IP addresses, or -- if none
- are configured -- the IPv4 address 127.0.0.2 (which is on the local
+ simply returns all locally configured public IP addresses, or, if none
+ are configured, the IPv4 address 127.0.0.2 (which is on the local
loopback) and the IPv6 address ::1 (which is the local host) for
whatever system hostname is configured locally. Patching
<filename>/etc/hosts</filename> is thus no longer necessary.</para>
@@ -116,7 +116,7 @@ $ getent ahosts `hostname`
127.0.0.2 RAW
</programlisting>
- <para>In this case the local host name is <varname>omega</varname>.</para>
+ <para>In this case the local hostname is <varname>omega</varname>.</para>
</refsect1>
diff --git a/man/os-release.xml b/man/os-release.xml
index 45babd61b9..c1dd62f715 100644
--- a/man/os-release.xml
+++ b/man/os-release.xml
@@ -62,7 +62,7 @@
list of environment-like shell-compatible variable
assignments. It is possible to source the
configuration from shell scripts, however, beyond mere
- variable assignments no shell features are supported
+ variable assignments, no shell features are supported
(this means variable expansion is explicitly not
supported), allowing applications to read the file
without implementing a shell compatible execution
@@ -72,7 +72,7 @@
a-z, 0-9. All strings should be in UTF-8 format, and
non-printable characters should not be used. If double
or single quotes or backslashes are to be used within
- variable assignments they should be escaped with
+ variable assignments, they should be escaped with
backslashes, following shell style. It is not
supported to concatenate multiple individually quoted
strings. Lines beginning with "#" shall be ignored as
@@ -110,7 +110,7 @@
<listitem><para>A string identifying
the operating system, without a
version component, and suitable for
- presentation to the user. If not set
+ presentation to the user. If not set,
defaults to
<literal>NAME=Linux</literal>. Example:
<literal>NAME=Fedora</literal> or
@@ -142,8 +142,8 @@
identifying the operating system,
excluding any version information and
suitable for processing by scripts or
- usage in generated file names. If not
- set defaults to
+ usage in generated filenames. If not
+ set, defaults to
<literal>ID=linux</literal>. Example:
<literal>ID=fedora</literal> or
<literal>ID=debian</literal>.</para></listitem>
@@ -155,7 +155,7 @@
<listitem><para>A space-separated list
of operating system identifiers in the
same syntax as the
- <varname>ID=</varname> setting. Should
+ <varname>ID=</varname> setting. It should
list identifiers of operating systems
that are closely related to the local
operating system in regards to
@@ -165,8 +165,8 @@
OS is a derivative from. An
OS should generally only list other OS
identifiers it itself is a derivative
- from, and not any OSes that
- are derived from it, but symmetric
+ of, and not any OSes that
+ are derived from it, though symmetric
relationships are possible. Build
scripts and similar should check this
variable if they need to identify the
@@ -179,11 +179,11 @@
closest. This field is
optional. Example: for an operating
system with
- <literal>ID=centos</literal> an
+ <literal>ID=centos</literal>, an
assignment of <literal>ID_LIKE="rhel
fedora"</literal> would be
appropriate. For an operating system
- with <literal>ID=ubuntu</literal> an
+ with <literal>ID=ubuntu</literal>, an
assignment of
<literal>ID_LIKE=debian</literal> is
appropriate.</para></listitem>
@@ -199,7 +199,7 @@
system version, excluding any OS name
information or release code name, and
suitable for processing by scripts or
- usage in generated file names. This
+ usage in generated filenames. This
field is optional. Example:
<literal>VERSION_ID=17</literal> or
<literal>VERSION_ID=11.04</literal>.</para></listitem>
@@ -213,7 +213,7 @@
presentation to the user. May or may
not contain a release code name or OS
version of some kind, as suitable. If
- not set defaults to
+ not set, defaults to
<literal>PRETTY_NAME="Linux"</literal>. Example:
<literal>PRETTY_NAME="Fedora 17 (Beefy
Miracle)"</literal>.</para></listitem>
@@ -241,7 +241,7 @@
<listitem><para>A CPE name for the
operating system, following the <ulink
- url="http://cpe.mitre.org/specification/">Common
+ url="https://cpe.mitre.org/specification/">Common
Platform Enumeration
Specification</ulink> as proposed by
the MITRE Corporation. This field
@@ -290,7 +290,7 @@
<literal>tel:</literal>. Only one URL
shall be listed in each setting. If
multiple resources need to be
- referenced it is recommended to
+ referenced, it is recommended to
provide an online landing page linking
all available resources. Examples:
<literal>HOME_URL="https://fedoraproject.org/"</literal>
@@ -332,7 +332,7 @@
<para>Note that operating system vendors may choose
not to provide version information, for example to
- accommodate for rolling releases. In this case VERSION
+ accommodate for rolling releases. In this case, VERSION
and VERSION_ID may be unset. Applications should not
rely on these fields to be set.</para>
diff --git a/man/pam_systemd.xml b/man/pam_systemd.xml
index 2dc6651885..0e25a4ac9f 100644
--- a/man/pam_systemd.xml
+++ b/man/pam_systemd.xml
@@ -55,7 +55,7 @@
<title>Description</title>
<para><command>pam_systemd</command> registers user
- sessions in the systemd login manager
+ sessions with the systemd login manager
<citerefentry><refentrytitle>systemd-logind.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
and hence the systemd control group hierarchy.</para>
@@ -80,29 +80,32 @@
an independent session counter is
used.</para></listitem>
- <listitem><para>A new control group
- <filename>/user/$USER/$XDG_SESSION_ID</filename>
- is created and the login process moved into
- it.</para></listitem>
+ <listitem><para>A new systemd scope unit is
+ created for the session. If this is the first
+ concurrent session of the user, an implicit
+ slice below <filename>user.slice</filename> is
+ automatically created and the scope placed in
+ it. In instance of the system service
+ <filename>user@.service</filename> which runs
+ the systemd user manager
+ instance.</para></listitem>
</orderedlist>
<para>On logout, this module ensures the following:</para>
<orderedlist>
- <listitem><para>If
- <varname>$XDG_SESSION_ID</varname> is set and
- <option>kill-session-processes=1</option> specified, all
- remaining processes in the
- <filename>/user/$USER/$XDG_SESSION_ID</filename>
- control group are killed and the control group
- is removed.</para></listitem>
-
- <listitem><para>If the last subgroup of the
- <filename>/user/$USER</filename> control group
- was removed the
+ <listitem><para>If this is enabled, all
+ processes of the session are terminated. If
+ the last concurrent session of a user ends, his
+ user systemd instance will be terminated too,
+ and so will the user's slice
+ unit.</para></listitem>
+
+ <listitem><para>If the last concurrent session
+ of a user ends, the
<varname>$XDG_RUNTIME_DIR</varname> directory
- and all its contents are
- removed, too.</para></listitem>
+ and all its contents are removed,
+ too.</para></listitem>
</orderedlist>
<para>If the system was not booted up with systemd as
@@ -117,79 +120,6 @@
<para>The following options are understood:</para>
<variablelist class='pam-directives'>
- <varlistentry>
- <term><option>kill-session-processes=</option></term>
-
- <listitem><para>Takes a boolean
- argument. If true, all processes
- created by the user during his session
- and from his session will be
- terminated when he logs out from his
- session.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>kill-only-users=</option></term>
-
- <listitem><para>Takes a comma
- separated list of user names or
- numeric user ids as argument. If this
- option is used the effect of the
- <option>kill-session-processes=</option> options
- will apply only to the listed
- users. If this option is not used the
- option applies to all local
- users. Note that
- <option>kill-exclude-users=</option>
- takes precedence over this list and is
- hence subtracted from the list
- specified here.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>kill-exclude-users=</option></term>
-
- <listitem><para>Takes a comma
- separated list of user names or
- numeric user ids as argument. Users
- listed in this argument will not be
- subject to the effect of
- <option>kill-session-processes=</option>. Note
- that this option takes precedence
- over
- <option>kill-only-users=</option>, and
- hence whatever is listed for
- <option>kill-exclude-users=</option>
- is guaranteed to never be killed by
- this PAM module, independent of any
- other configuration
- setting.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>controllers=</option></term>
-
- <listitem><para>Takes a comma
- separated list of control group
- controllers in which hierarchies a
- user/session control group will be
- created by default for each user
- logging in, in addition to the control
- group in the named 'name=systemd'
- hierarchy. If omitted, defaults to an
- empty list.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>reset-controllers=</option></term>
-
- <listitem><para>Takes a comma
- separated list of control group
- controllers in which hierarchies the
- logged in processes will be reset to
- the root control
- group.</para></listitem>
- </varlistentry>
<varlistentry>
<term><option>class=</option></term>
@@ -209,29 +139,6 @@
operates.</para></listitem>
</varlistentry>
</variablelist>
-
- <para>Note that setting
- <varname>kill-session-processes=1</varname> will break tools
- like
- <citerefentry><refentrytitle>screen</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para>
-
- <para>Note that
- <varname>kill-session-processes=1</varname> is a
- stricter version of
- <varname>KillUserProcesses=1</varname> which may be
- configured system-wide in
- <citerefentry><refentrytitle>logind.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>. The
- former kills processes of a session as soon as it
- ends, the latter kills processes as soon as the last
- session of the user ends.</para>
-
- <para>If the options are omitted they default to
- <option>kill-session-processes=0</option>,
- <option>kill-only-users=</option>,
- <option>kill-exclude-users=</option>,
- <option>controllers=</option>,
- <option>reset-controllers=</option>,
- <option>debug=no</option>.</para>
</refsect1>
<refsect1>
@@ -250,7 +157,7 @@
<term><varname>$XDG_SESSION_ID</varname></term>
<listitem><para>A session identifier,
- suitable to be used in file names. The
+ suitable to be used in filenames. The
string itself should be considered
opaque, although often it is just the
audit session ID as reported by
@@ -281,11 +188,11 @@
applications should not rely on this
behavior and must be able to deal with
stale files. To store session-private
- data in this directory the user should
+ data in this directory, the user should
include the value of <varname>$XDG_SESSION_ID</varname>
in the filename. This directory shall
be used for runtime file system
- objects such as AF_UNIX sockets,
+ objects such as <constant>AF_UNIX</constant> sockets,
FIFOs, PID files and similar. It is
guaranteed that this directory is
local and offers the greatest possible
@@ -306,7 +213,7 @@ account required pam_unix.so
password required pam_unix.so
session required pam_unix.so
session required pam_loginuid.so
-session required pam_systemd.so kill-session-processes=1</programlisting>
+session required pam_systemd.so</programlisting>
</refsect1>
<refsect1>
@@ -319,7 +226,10 @@ session required pam_systemd.so kill-session-processes=1</programlisting>
<citerefentry><refentrytitle>pam.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>pam.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>pam_loginuid</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>pam_loginuid</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.scope</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/runlevel.xml b/man/runlevel.xml
index 6d9fe85726..5efb340df5 100644
--- a/man/runlevel.xml
+++ b/man/runlevel.xml
@@ -111,7 +111,7 @@
<term><varname>$PREVLEVEL</varname></term>
<listitem><para>If
- <varname>$PREVLEVEL</varname> is set
+ <varname>$PREVLEVEL</varname> is set,
<command>runlevel</command> will print
this value as previous runlevel and
ignore utmp.</para></listitem>
diff --git a/man/sd-daemon.xml b/man/sd-daemon.xml
index a3bf662fe9..6e804e1a6c 100644
--- a/man/sd-daemon.xml
+++ b/man/sd-daemon.xml
@@ -99,7 +99,7 @@
conjunction with STDERR-based logging as implemented
by systemd. If a systemd service definition file is
configured with <varname>StandardError=syslog</varname>
- or <varname>StandardError=kmsg</varname> these
+ or <varname>StandardError=kmsg</varname>, these
prefixes can be used to encode a log level in lines
printed. This is similar to the kernel
<function>printk()</function>-style logging. See
@@ -146,8 +146,7 @@
<filename>sd-daemon.h</filename> files. These
interfaces are available as shared library, which can
be compiled and linked to with the
- <literal>libsystemd-daemon</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-daemon</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file. Alternatively, applications consuming these APIs
may copy the implementation into their source tree,
either verbatim or in excerpts.</para>
diff --git a/man/sd-id128.xml b/man/sd-id128.xml
index ac2000e275..3a5e13306d 100644
--- a/man/sd-id128.xml
+++ b/man/sd-id128.xml
@@ -50,7 +50,7 @@
<refname>SD_ID128_FORMAT_STR</refname>
<refname>SD_ID128_FORMAT_VAL</refname>
<refname>sd_id128_equal</refname>
- <refpurpose>APIs for processing 128 bit IDs</refpurpose>
+ <refpurpose>APIs for processing 128-bit IDs</refpurpose>
</refnamediv>
<refsynopsisdiv>
@@ -68,12 +68,12 @@
<title>Description</title>
<para><filename>sd-id128.h</filename> provides APIs to
- process and generate 128 bit ID values. The 128 bit ID
+ process and generate 128-bit ID values. The 128-bit ID
values processed and generated by these APIs are a
generalization of OSF UUIDs as defined by <ulink
- url="http://tools.ietf.org/html/rfc4122">RFC
- 4122</ulink>, though use a simpler string
- formatting. These functions impose no structure on the
+ url="https://tools.ietf.org/html/rfc4122">RFC
+ 4122</ulink> but use a simpler string
+ format. These functions impose no structure on the
used IDs, much unlike OSF UUIDs or Microsoft GUIDs,
but are fully compatible with those types of IDs.
</para>
@@ -85,7 +85,7 @@
for more information about the implemented
functions.</para>
- <para>A 128 bit ID is implemented as the following
+ <para>A 128-bit ID is implemented as the following
union type:</para>
<programlisting>typedef union sd_id128 {
@@ -93,26 +93,26 @@
uint64_t qwords[2];
} sd_id128_t;</programlisting>
- <para>This union type allows accessing the 128 bit ID
- as 16 separate bytes or two 64 bit words. It is generally
- safer to access the ID components by their 8 bit array
+ <para>This union type allows accessing the 128-bit ID
+ as 16 separate bytes or two 64-bit words. It is generally
+ safer to access the ID components by their 8-bit array
to avoid endianness issues. This union is intended to
be passed call-by-value (as opposed to
call-by-reference) and may be directly manipulated by
clients.</para>
<para>A couple of macros are defined to denote and
- decode 128 bit IDs:</para>
+ decode 128-bit IDs:</para>
<para><function>SD_ID128_MAKE()</function> may be used
- to denote a constant 128 bit ID in source code. A
- commonly used idiom is to assign a name to a 128 bit
+ to denote a constant 128-bit ID in source code. A
+ commonly used idiom is to assign a name to a 128-bit
ID using this macro:</para>
<programlisting>#define SD_MESSAGE_COREDUMP SD_ID128_MAKE(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1)</programlisting>
<para><function>SD_ID128_CONST_STR()</function> may be
- used to convert constant 128bit IDs into constant
+ used to convert constant 128-bit IDs into constant
strings for output. The following example code will
output the string
"fc2e22bc6ee647b6b90729ab34a250b1":</para>
@@ -122,7 +122,7 @@
<para><function>SD_ID128_FORMAT_STR</function> and
<function>SD_ID128_FORMAT_VAL()</function> may be used
- to format a 128 bit ID in a
+ to format a 128-bit ID in a
<citerefentry><refentrytitle>printf</refentrytitle><manvolnum>3</manvolnum></citerefentry>
format string, as shown in the following
example:</para>
@@ -134,7 +134,7 @@
return 0;
}</programlisting>
- <para>Use <function>sd_id128_equal()</function> to compare two 128 bit IDs:</para>
+ <para>Use <function>sd_id128_equal()</function> to compare two 128-bit IDs:</para>
<programlisting>int main(int argc, char *argv[]) {
sd_id128_t a, b, c;
@@ -149,7 +149,7 @@
<para>Note that new, randomized IDs may be generated
with
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
- <literal>--new-id</literal> option.</para>
+ <option>--new-id</option> option.</para>
</refsect1>
<refsect1>
@@ -157,8 +157,7 @@
<para>These APIs are implemented as a shared library,
which can be compiled and linked to with the
- <literal>libsystemd-id128</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <literal>libsystemd-id128</literal> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/sd-journal.xml b/man/sd-journal.xml
index a7220ec6bc..6d39611447 100644
--- a/man/sd-journal.xml
+++ b/man/sd-journal.xml
@@ -100,8 +100,7 @@
<para>These APIs are implemented as shared library,
which can be compiled and linked to with the
- <literal>libsystemd-journal</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-journal</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/sd-login.xml b/man/sd-login.xml
index 697259564d..251b35b06f 100644
--- a/man/sd-login.xml
+++ b/man/sd-login.xml
@@ -95,7 +95,7 @@
each other.</para>
<para>If the functions return string arrays, these are
- generally NULL terminated and need to be freed by the
+ generally <constant>NULL</constant> terminated and need to be freed by the
caller with the libc
<citerefentry><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use, including the strings referenced
@@ -103,7 +103,7 @@
be freed, as well.</para>
<para>As a special exception, instead of an empty
- string array NULL may be returned, which should be
+ string array <constant>NULL</constant> may be returned, which should be
treated equivalent to an empty string array.</para>
<para>See
@@ -122,8 +122,7 @@
<para>These APIs are implemented as shared library,
which can be compiled and linked to with the
- <literal>libsystemd-login</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-login</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/sd_booted.xml b/man/sd_booted.xml
index ce5a34dc86..64c0cd9d3d 100644
--- a/man/sd_booted.xml
+++ b/man/sd_booted.xml
@@ -102,8 +102,7 @@
<filename>sd-daemon.h</filename> files. These
interfaces are available as shared library, which can
be compiled and linked to with the
- <literal>libsystemd-daemon</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-daemon</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file. Alternatively, applications consuming these APIs
may copy the implementation into their source
tree. For more details about the reference
@@ -112,7 +111,7 @@
<para>If the reference implementation is used as
drop-in files and -DDISABLE_SYSTEMD is set during
- compilation this function will always return 0 and
+ compilation, this function will always return 0 and
otherwise become a NOP.</para>
</refsect1>
diff --git a/man/sd_get_seats.xml b/man/sd_get_seats.xml
index 9bc866dc68..8254b7cae4 100644
--- a/man/sd_get_seats.xml
+++ b/man/sd_get_seats.xml
@@ -82,12 +82,12 @@
<para><function>sd_get_seats()</function> may be used
to determine all currently available local
- seats. Returns a NULL terminated array of seat
+ seats. Returns a <constant>NULL</constant> terminated array of seat
identifiers. The returned array and all strings it
references need to be freed with the libc
<citerefentry><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use. Note that instead of an empty array
- NULL may be returned and should be considered
+ <constant>NULL</constant> may be returned and should be considered
equivalent to an empty array.</para>
<para>Similar, <function>sd_get_sessions()</function> may
@@ -124,8 +124,7 @@
<function>sd_get_machine_names()</function> interfaces
are available as shared library, which can be compiled
and linked to with the
- <literal>libsystemd-login</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-login</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/sd_id128_get_machine.xml b/man/sd_id128_get_machine.xml
index 039c1dd64c..6bee7ad9c1 100644
--- a/man/sd_id128_get_machine.xml
+++ b/man/sd_id128_get_machine.xml
@@ -45,7 +45,7 @@
<refnamediv>
<refname>sd_id128_get_machine</refname>
<refname>sd_id128_get_boot</refname>
- <refpurpose>Retrieve 128 bit IDs</refpurpose>
+ <refpurpose>Retrieve 128-bit IDs</refpurpose>
</refnamediv>
<refsynopsisdiv>
@@ -92,10 +92,10 @@
<function>sd_id128_get_boot()</function> always returns
a UUID v4 compatible
ID. <function>sd_id128_get_machine()</function> will
- also return a UUID v4 compatible ID on new
- installations, but might not on older. It is possible
- to convert the machine ID into an UUID v4 compatible
- one. For more information see
+ also return a UUID v4-compatible ID on new
+ installations but might not on older. It is possible
+ to convert the machine ID into a UUID v4-compatible
+ one. For more information, see
<citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
<para>For more information about the
@@ -118,8 +118,7 @@
and <function>sd_id128_get_boot()</function>
interfaces are available as shared library, which can
be compiled and linked to with the
- <literal>libsystemd-id128</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <literal>libsystemd-id128</literal> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/sd_id128_randomize.xml b/man/sd_id128_randomize.xml
index be74937dd0..0b9580308a 100644
--- a/man/sd_id128_randomize.xml
+++ b/man/sd_id128_randomize.xml
@@ -44,7 +44,7 @@
<refnamediv>
<refname>sd_id128_randomize</refname>
- <refpurpose>Generate 128 bit IDs</refpurpose>
+ <refpurpose>Generate 128-bit IDs</refpurpose>
</refnamediv>
<refsynopsisdiv>
@@ -63,7 +63,7 @@
<title>Description</title>
<para><function>sd_id128_randomize()</function>
- generates a new randomized 128 bit ID and returns it
+ generates a new randomized 128-bit ID and returns it
in <parameter>ret</parameter>. Every invocation
returns a new randomly generated ID. This uses the
<filename>/dev/urandom</filename> kernel random number
@@ -71,16 +71,15 @@
<para>Note that
<function>sd_id128_randomize()</function> always returns
- a UUID v4 compatible
- ID.</para>
+ a UUID v4-compatible ID.</para>
<para>For more information about the
- <literal>sd_id128_t</literal> type see
+ <literal>sd_id128_t</literal> type, see
<citerefentry><refentrytitle>sd-id128</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
<para><citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
- <literal>--new-id</literal> command may be used as
- command line front-end for
+ <option>--new-id</option> option may be used as a
+ command-line front-end for
<function>sd_id128_randomize()</function>.</para>
</refsect1>
@@ -98,8 +97,7 @@
<para>The <function>sd_id128_randomize()</function> interface
is available as shared library, which can be compiled
and linked to with the
- <literal>libsystemd-id128</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <literal>libsystemd-id128</literal> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/sd_id128_to_string.xml b/man/sd_id128_to_string.xml
index 593d0752d5..71cf82a6cd 100644
--- a/man/sd_id128_to_string.xml
+++ b/man/sd_id128_to_string.xml
@@ -45,7 +45,7 @@
<refnamediv>
<refname>sd_id128_to_string</refname>
<refname>sd_id128_from_string</refname>
- <refpurpose>Format or parse 128 bit IDs as strings</refpurpose>
+ <refpurpose>Format or parse 128-bit IDs as strings</refpurpose>
</refnamediv>
<refsynopsisdiv>
@@ -69,19 +69,20 @@
<title>Description</title>
<para><function>sd_id128_to_string()</function>
- formats a 128 bit ID as character string. It expects
+ formats a 128-bit ID as a character string. It expects
the ID and a string array capable of storing 33
characters. The ID will be formatted as 32 lowercase
- hexadecimal digits and be terminated by a NUL
- byte.</para>
+ hexadecimal digits and be terminated by a
+ <constant>NUL</constant> byte.</para>
<para><function>sd_id128_from_string()</function>
implements the reverse operation: it takes a 33
- character string with 32 hexadecimal digits
- (either lowercase or uppercase, terminated by NUL) and parses them back into an 128
- bit ID returned in
+ character string with 32 hexadecimal digits (either
+ lowercase or uppercase, terminated by
+ <constant>NUL</constant>) and parses them back into a
+ 128-bit ID returned in
<parameter>ret</parameter>. Alternatively, this call
- can also parse a 37 character string with a 128bit ID
+ can also parse a 37-character string with a 128-bit ID
formatted as RFC UUID.</para>
<para>For more information about the
@@ -89,9 +90,9 @@
<citerefentry><refentrytitle>sd-id128</refentrytitle><manvolnum>3</manvolnum></citerefentry>. Note
that these calls operate the same way on all
architectures, i.e. the results do not depend on
- endianess.</para>
+ endianness.</para>
- <para>When formatting a 128 bit ID into a string it is
+ <para>When formatting a 128-bit ID into a string, it is
often easier to use a format string for
<citerefentry><refentrytitle>printf</refentrytitle><manvolnum>3</manvolnum></citerefentry>. This
is easily done using the
@@ -106,9 +107,9 @@
<para><function>sd_id128_to_string()</function> always
succeeds and returns a pointer to the string array
- passed in. <function>sd_id128_from_string</function>
- returns 0 on success (in which case
- <parameter>ret</parameter> is filled in), or a negative
+ passed in. <function>sd_id128_from_string</function>
+ returns 0 on success, in which case
+ <parameter>ret</parameter> is filled in, or a negative
errno-style error code.</para>
</refsect1>
@@ -118,8 +119,7 @@
<para>The <function>sd_id128_to_string()</function>
and <function>sd_id128_from_string()</function> interfaces are
available as shared library, which can be compiled and
- linked to with the <literal>libsystemd-id128</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ linked to with the <literal>libsystemd-id128</literal> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/sd_is_fifo.xml b/man/sd_is_fifo.xml
index 595c8f112d..2bc860c373 100644
--- a/man/sd_is_fifo.xml
+++ b/man/sd_is_fifo.xml
@@ -102,19 +102,22 @@
<para><function>sd_is_fifo()</function> may be called
to check whether the specified file descriptor refers
to a FIFO or pipe. If the <parameter>path</parameter>
- parameter is not NULL, it is checked whether the FIFO
- is bound to the specified file system path.</para>
+ parameter is not <constant>NULL</constant>, it is
+ checked whether the FIFO is bound to the specified
+ file system path.</para>
<para><function>sd_is_socket()</function> may be
called to check whether the specified file descriptor
refers to a socket. If the
<parameter>family</parameter> parameter is not
- AF_UNSPEC it is checked whether the socket is of the
- specified family (AF_UNIX, AF_INET, ...). If the
- <parameter>type</parameter> parameter is not 0 it is
+ <constant>AF_UNSPEC</constant>, it is checked whether
+ the socket is of the specified family (AF_UNIX,
+ <constant>AF_INET</constant>, ...). If the
+ <parameter>type</parameter> parameter is not 0, it is
checked whether the socket is of the specified type
- (SOCK_STREAM, SOCK_DGRAM, ...). If the
- <parameter>listening</parameter> parameter is positive
+ (<constant>SOCK_STREAM</constant>,
+ <constant>SOCK_DGRAM</constant>, ...). If the
+ <parameter>listening</parameter> parameter is positive,
it is checked whether the socket is in accepting mode,
i.e. <function>listen()</function> has been called for
it. If <parameter>listening</parameter> is 0, it is
@@ -129,27 +132,27 @@
optionally checks the IPv4 or IPv6 port number the
socket is bound to, unless <parameter>port</parameter>
is zero. For this call <parameter>family</parameter>
- must be passed as either AF_UNSPEC, AF_INET, or
- AF_INET6.</para>
+ must be passed as either <constant>AF_UNSPEC</constant>, <constant>AF_INET</constant>, or
+ <constant>AF_INET6</constant>.</para>
<para><function>sd_is_socket_unix()</function> is
- similar to <function>sd_is_socket()</function>, but
- optionally checks the AF_UNIX path the socket is bound
+ similar to <function>sd_is_socket()</function> but
+ optionally checks the <constant>AF_UNIX</constant> path the socket is bound
to, unless the <parameter>path</parameter> parameter
- is NULL. For normal file system AF_UNIX sockets set
- the <parameter>length</parameter> parameter to 0. For
- Linux abstract namespace sockets set the
+ is <constant>NULL</constant>. For normal file system <constant>AF_UNIX</constant> sockets,
+ set the <parameter>length</parameter> parameter to 0. For
+ Linux abstract namespace sockets, set the
<parameter>length</parameter> to the size of the
- address, including the initial 0 byte and set
+ address, including the initial 0 byte, and set the
<parameter>path</parameter> to the initial 0 byte of
the socket address.</para>
<para><function>sd_is_mq()</function> may be called to
check whether the specified file descriptor refers to
a POSIX message queue. If the
- <parameter>path</parameter> parameter is not NULL, it
- is checked whether the message queue is bound to the
- specified name.</para>
+ <parameter>path</parameter> parameter is not
+ <constant>NULL</constant>, it is checked whether the
+ message queue is bound to the specified name.</para>
</refsect1>
<refsect1>
@@ -157,7 +160,7 @@
<para>On failure, these calls return a negative
errno-style error code. If the file descriptor is of
- the specified type and bound to the specified address
+ the specified type and bound to the specified address,
a positive return value is returned, otherwise
zero.</para>
</refsect1>
@@ -168,7 +171,7 @@
<para>These functions are provided by the reference
implementation of APIs for new-style daemons and
distributed with the systemd package. The algorithms
- they implement are simple, and can easily be
+ they implement are simple, and they can easily be
reimplemented in daemons if it is important to support
this interface without using the reference
implementation.</para>
@@ -178,7 +181,7 @@
<filename>getsockname()</filename> to check the file
descriptor type and where it is bound to.</para>
- <para>For details about the algorithms check the
+ <para>For details about the algorithms, check the
liberally licensed reference implementation sources:
<ulink url="http://cgit.freedesktop.org/systemd/systemd/plain/src/libsystemd-daemon/sd-daemon.c"/>
and <ulink
@@ -190,8 +193,7 @@
<filename>sd-daemon.h</filename> files. These
interfaces are available as shared library, which can
be compiled and linked to with the
- <literal>libsystemd-daemon</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-daemon</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file. Alternatively, applications consuming these APIs
may copy the implementation into their source
tree. For more details about the reference
diff --git a/man/sd_journal_add_match.xml b/man/sd_journal_add_match.xml
index 549785ca83..b6c7b06f2e 100644
--- a/man/sd_journal_add_match.xml
+++ b/man/sd_journal_add_match.xml
@@ -94,11 +94,11 @@
only of 0-9, A-Z and the underscore. It may not begin
with two underscores or be the empty string. The value
part may be any value, including binary. If a match is
- applied only entries with this field set will be
+ applied, only entries with this field set will be
iterated. Multiple matches may be active at the same
- time: if they apply to different fields only entries
- with both fields set like this will be iterated, if
- they apply to the same fields only entries where the
+ time: If they apply to different fields, only entries
+ with both fields set like this will be iterated. If
+ they apply to the same fields, only entries where the
field takes one of the specified values will be
iterated. Well known fields are documented in
<citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</manvolnum></citerefentry>. Whenever
@@ -110,7 +110,7 @@
<para><function>sd_journal_add_disjunction()</function>
may be used to insert a disjunction (i.e. logical OR)
- in the match list. If this call is invoked all
+ in the match list. If this call is invoked, all
previously added matches since the last invocation of
<function>sd_journal_add_disjunction()</function> or
<function>sd_journal_add_conjunction()</function> are
@@ -123,7 +123,7 @@
<para><function>sd_journal_add_conjunction()</function>
may be used to insert a conjunction (i.e. logical AND)
- in the match list. If this call is invoked all
+ in the match list. If this call is invoked, all
previously added matches since the last invocation of
<function>sd_journal_add_conjunction()</function> are
combined in an AND with all matches added afterwards,
@@ -176,8 +176,7 @@
<function>sd_journal_flush_matches()</function>
interfaces are available as shared library, which can
be compiled and linked to with the
- <literal>libsystemd-journal</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-journal</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/sd_journal_get_catalog.xml b/man/sd_journal_get_catalog.xml
index 719d77f723..4a7e0a1f8c 100644
--- a/man/sd_journal_get_catalog.xml
+++ b/man/sd_journal_get_catalog.xml
@@ -80,8 +80,8 @@
field names in the catalog entry text enclosed in "@"
will be replaced by the respective field values of the
current entry. If a field name referenced in the
- message catalog entry does not exist it the current
- journal entry the "@" will be removed but the field
+ message catalog entry does not exist, in the current
+ journal entry, the "@" will be removed, but the field
name otherwise left untouched.</para>
<para><function>sd_journal_get_catalog_for_message_id()</function>
@@ -104,7 +104,7 @@
and
<function>sd_journal_get_catalog_for_message_id()</function>
return 0 on success or a negative errno-style error
- code. If no matching message catalog entry is found
+ code. If no matching message catalog entry is found,
-ENOENT is returned.</para>
<para>On successful return, <parameter>ret</parameter>
@@ -120,8 +120,7 @@
<function>sd_journal_get_catalog_for_message_id()</function>
interfaces are available as shared library, which can
be compiled and linked to with the
- <literal>libsystemd-journal</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-journal</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/sd_journal_get_cursor.xml b/man/sd_journal_get_cursor.xml
index 1b0e775bb4..4cee7d5b63 100644
--- a/man/sd_journal_get_cursor.xml
+++ b/man/sd_journal_get_cursor.xml
@@ -120,7 +120,7 @@
returns 0 on success or a negative errno-style error
code. <function>sd_journal_test_cursor()</function>
returns positive if the current entry matches the
- specified cursor, 0 if it doesn't match the specified
+ specified cursor, 0 if it does not match the specified
cursor or a negative errno-style error code on
failure.</para>
</refsect1>
@@ -132,8 +132,7 @@
and <function>sd_journal_test_cursor()</function>
interfaces are available as shared library, which can
be compiled and linked to with the
- <literal>libsystemd-journal</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-journal</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/sd_journal_get_cutoff_realtime_usec.xml b/man/sd_journal_get_cutoff_realtime_usec.xml
index ed014cb509..9bf8220d11 100644
--- a/man/sd_journal_get_cutoff_realtime_usec.xml
+++ b/man/sd_journal_get_cutoff_realtime_usec.xml
@@ -77,20 +77,23 @@
gets the realtime (wallclock) timestamps of the first
and last entries accessible in the journal. It takes
three arguments: the journal context object and two
- pointers to 64 Bit unsigned integers to store the
+ pointers to 64-bit unsigned integers to store the
timestamps in. The timestamps are in microseconds
- since the epoch, i.e. CLOCK_REALTIME. Either one of
- the two timestamp arguments may be passed as NULL in
- case the timestamp is not needed, but not both.</para>
+ since the epoch,
+ i.e. <constant>CLOCK_REALTIME</constant>. Either one
+ of the two timestamp arguments may be passed as
+ <constant>NULL</constant> in case the timestamp is not
+ needed, but not both.</para>
<para><function>sd_journal_get_cutoff_monotonic_usec()</function>
gets the monotonic timestamps of the first and last
entries accessible in the journal. It takes three
- arguments: the journal context object, a 128 Bit
- identifier for the boot, and two pointers to 64 Bit
+ arguments: the journal context object, a 128-bit
+ identifier for the boot, and two pointers to 64-bit
unsigned integers to store the timestamps. The
timestamps are in microseconds since boot-up of the
- specific boot, i.e. CLOCK_MONOTONIC. Since the
+ specific boot,
+ i.e. <constant>CLOCK_MONOTONIC</constant>. Since the
monotonic clock begins new with every reboot it only
defines a well-defined point in time when used
together with an identifier identifying the boot, see
@@ -98,8 +101,8 @@
for more information. The function will return the
timestamps for the boot identified by the passed boot
ID. Either one of the two timestamp arguments may be
- passed as NULL in case the timestamp is not needed,
- but not both.</para>
+ passed as <constant>NULL</constant> in case the
+ timestamp is not needed, but not both.</para>
</refsect1>
<refsect1>
@@ -121,8 +124,7 @@
<function>sd_journal_get_cutoff_monotonic_usec()</function>
interfaces are available as shared library, which can
be compiled and linked to with the
- <literal>libsystemd-journal</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-journal</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/sd_journal_get_data.xml b/man/sd_journal_get_data.xml
index 1259b0cdbe..0e1111e05d 100644
--- a/man/sd_journal_get_data.xml
+++ b/man/sd_journal_get_data.xml
@@ -179,9 +179,9 @@
<para><function>sd_journal_get_data()</function>
returns 0 on success or a negative errno-style error
code. If the current entry does not include the
- specified field -ENOENT is returned. If
+ specified field, -ENOENT is returned. If
<citerefentry><refentrytitle>sd_journal_next</refentrytitle><manvolnum>3</manvolnum></citerefentry>
- has not been called at least once -EADDRNOTAVAIL is
+ has not been called at least once, -EADDRNOTAVAIL is
returned. <function>sd_journal_enumerate_data()</function>
returns a positive integer if the next field has been
read, 0 when no more fields are known, or a negative
@@ -205,8 +205,7 @@
<function>sd_journal_get_data_threshold()</function>
interfaces are available as shared library, which can
be compiled and linked to with the
- <literal>libsystemd-journal</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-journal</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/sd_journal_get_fd.xml b/man/sd_journal_get_fd.xml
index 33d2980b3b..764f716a17 100644
--- a/man/sd_journal_get_fd.xml
+++ b/man/sd_journal_get_fd.xml
@@ -123,22 +123,28 @@
<para><function>sd_journal_get_events()</function>
will return the <function>poll()</function> mask to
wait for. This function will return a combination of
- <literal>POLLIN</literal> and
- <literal>POLLOUT</literal> and similar to fill into
+ <constant>POLLIN</constant> and
+ <constant>POLLOUT</constant> and similar to fill into
the <literal>.events</literal> field of
- <literal>struct pollfd</literal>.</para>
+ <varname>struct pollfd</varname>.</para>
<para><function>sd_journal_get_timeout()</function>
- will return a timeout value for usage in <function>poll()</function>. This returns a value in microseconds since the epoch of CLOCK_MONOTONIC for timing out <function>poll()</function> in <literal>timeout_usec</literal>. See
+ will return a timeout value for usage in
+ <function>poll()</function>. This returns a value in
+ microseconds since the epoch of
+ <constant>CLOCK_MONOTONIC</constant> for timing out
+ <function>poll()</function> in
+ <varname>timeout_usec</varname>. See
<citerefentry><refentrytitle>clock_gettime</refentrytitle><manvolnum>2</manvolnum></citerefentry>
for details about
- <literal>CLOCK_MONOTONIC</literal>. If there's no
- timeout to wait for this will fill in
- <literal>(uint64_t) -1</literal> instead. Note that
+ <constant>CLOCK_MONOTONIC</constant>. If there is no
+ timeout to wait for, this will fill in
+ <constant>(uint64_t) -1</constant> instead. Note that
<function>poll()</function> takes a relative timeout
in milliseconds rather than an absolute timeout in
- microseconds. To convert the absolute 'us' timeout into
- relative 'ms', use code like the following:</para>
+ microseconds. To convert the absolute 'us' timeout
+ into relative 'ms', use code like the
+ following:</para>
<programlisting>uint64_t t;
int msec;
@@ -154,7 +160,7 @@ else {
}</programlisting>
<para>The code above does not do any error checking
- for brevity's sake. The calculated <literal>msec</literal>
+ for brevity's sake. The calculated <varname>msec</varname>
integer can be passed directly as
<function>poll()</function>'s timeout
parameter.</para>
@@ -174,7 +180,7 @@ else {
synchronously wait until the journal gets changed. The
maximum time this call sleeps may be controlled with
the <parameter>timeout_usec</parameter>
- parameter. Pass <literal>(uint64_t) -1</literal> to
+ parameter. Pass <constant>(uint64_t) -1</constant> to
wait indefinitely. Internally this call simply
combines <function>sd_journal_get_fd()</function>,
<function>sd_journal_get_events()</function>,
@@ -209,8 +215,8 @@ else {
errno-style error code.</para>
<para><function>sd_journal_get_events()</function>
- returns a combination of <literal>POLLIN</literal>,
- <literal>POLLOUT</literal> and suchlike on success or
+ returns a combination of <constant>POLLIN</constant>,
+ <constant>POLLOUT</constant> and suchlike on success or
a negative errno-style error code.</para>
<para><function>sd_journal_reliable_fd()</function>
@@ -222,19 +228,19 @@ else {
<para><function>sd_journal_process()</function> and
<function>sd_journal_wait()</function> return one of
- <literal>SD_JOURNAL_NOP</literal>,
- <literal>SD_JOURNAL_APPEND</literal> or
- <literal>SD_JOURNAL_INVALIDATE</literal> on success or
+ <constant>SD_JOURNAL_NOP</constant>,
+ <constant>SD_JOURNAL_APPEND</constant> or
+ <constant>SD_JOURNAL_INVALIDATE</constant> on success or
a negative errno-style error code. If
- <literal>SD_JOURNAL_NOP</literal> is returned the
- journal didn't change since the last invocation. If
- <literal>SD_JOURNAL_APPEND</literal> is returned new
+ <constant>SD_JOURNAL_NOP</constant> is returned, the
+ journal did not change since the last invocation. If
+ <constant>SD_JOURNAL_APPEND</constant> is returned, new
entries have been appended to the end of the
- journal. If <literal>SD_JOURNAL_INVALIDATE</literal>
+ journal. If <constant>SD_JOURNAL_INVALIDATE</constant>,
journal files were added or removed (possibly due to
- rotation). In the latter event live-view UIs should
- probably refresh their entire display while in the
- case of <literal>SD_JOURNAL_APPEND</literal> it is
+ rotation). In the latter event, live-view UIs should
+ probably refresh their entire display, while in the
+ case of <constant>SD_JOURNAL_APPEND</constant>, it is
sufficient to simply continue reading at the previous
end of the journal.</para>
</refsect1>
@@ -249,8 +255,7 @@ else {
<function>sd_journal_wait()</function> interfaces are
available as shared library, which can be compiled and
linked to with the
- <literal>libsystemd-journal</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-journal</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/sd_journal_get_realtime_usec.xml b/man/sd_journal_get_realtime_usec.xml
index 515932c6d8..8870c29e30 100644
--- a/man/sd_journal_get_realtime_usec.xml
+++ b/man/sd_journal_get_realtime_usec.xml
@@ -73,28 +73,29 @@
<para><function>sd_journal_get_realtime_usec()</function>
gets the realtime (wallclock) timestamp of the
- current journal entry. It takes two arguments: the
- journal context object and a pointer to a 64 Bit
+ current journal entry. It takes two arguments: the
+ journal context object and a pointer to a 64-bit
unsigned integer to store the timestamp in. The
timestamp is in microseconds since the epoch,
- i.e. CLOCK_REALTIME.</para>
+ i.e. <constant>CLOCK_REALTIME</constant>.</para>
<para><function>sd_journal_get_monotonic_usec()</function>
- gets the monotonic timestamp of the current
- journal entry. It takes three arguments: the journal
- context object, a pointer to a 64 Bit unsigned integer
- to store the timestamp in as well as a 128 Bit ID
- buffer to store the boot ID of the monotonic timestamp
- in. The timestamp is in microseconds since boot-up of
- the specific boot, i.e. CLOCK_MONOTONIC. Since the
- monotonic clock begins new with every reboot it only
+ gets the monotonic timestamp of the current journal
+ entry. It takes three arguments: the journal context
+ object, a pointer to a 64-bit unsigned integer to
+ store the timestamp in, as well as a 128-bit ID buffer
+ to store the boot ID of the monotonic timestamp.
+ The timestamp is in microseconds since boot-up of
+ the specific boot,
+ i.e. <constant>CLOCK_MONOTONIC</constant>. Since the
+ monotonic clock begins new with every reboot, it only
defines a well-defined point in time when used
- together with an identifier identifying the boot, see
+ together with an identifier identifying the boot. See
<citerefentry><refentrytitle>sd_id128_get_boot</refentrytitle><manvolnum>3</manvolnum></citerefentry>
for more information. If the boot ID parameter is
- passed NULL the function will fail if the monotonic
- timestamp of the current entry is not of the current
- system boot.</para>
+ passed <constant>NULL</constant>, the function will
+ fail if the monotonic timestamp of the current entry
+ is not of the current system boot.</para>
<para>Note that these functions will not work before
<citerefentry><refentrytitle>sd_journal_next</refentrytitle><manvolnum>3</manvolnum></citerefentry>
@@ -109,7 +110,7 @@
and
<function>sd_journal_get_monotonic_usec()</function>
returns 0 on success or a negative errno-style error
- code. If the boot ID parameter was passed NULL and the
+ code. If the boot ID parameter was passed <constant>NULL</constant> and the
monotonic timestamp of the current journal entry is
not of the current system boot, -ESTALE is returned by <function>sd_journal_get_monotonic_usec()</function>.</para>
</refsect1>
@@ -123,8 +124,7 @@
<function>sd_journal_get_monotonic_usec()</function>
interfaces are available as shared library, which can
be compiled and linked to with the
- <literal>libsystemd-journal</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-journal</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/sd_journal_get_usage.xml b/man/sd_journal_get_usage.xml
index a2b868f218..180d8b2ffd 100644
--- a/man/sd_journal_get_usage.xml
+++ b/man/sd_journal_get_usage.xml
@@ -66,8 +66,8 @@
<para><function>sd_journal_get_usage()</function>
determines the total disk space currently used by
journal files (in bytes). If
- <literal>SD_JOURNAL_LOCAL_ONLY</literal> was passed
- when opening the journal this value will only reflect
+ <constant>SD_JOURNAL_LOCAL_ONLY</constant> was passed
+ when opening the journal, this value will only reflect
the size of journal files of the local host, otherwise
of all hosts.</para>
</refsect1>
@@ -86,8 +86,7 @@
<para>The <function>sd_journal_get_usage()</function>
interface is available as shared library, which can be
compiled and linked to with the
- <literal>libsystemd-journal</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-journal</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/sd_journal_next.xml b/man/sd_journal_next.xml
index 9b1cb1fc46..6e437d1822 100644
--- a/man/sd_journal_next.xml
+++ b/man/sd_journal_next.xml
@@ -158,8 +158,7 @@
<function>sd_journal_previous_skip()</function> interfaces are
available as shared library, which can be compiled and
linked to with the
- <literal>libsystemd-journal</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-journal</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/sd_journal_open.xml b/man/sd_journal_open.xml
index 76b857b991..bb3703d015 100644
--- a/man/sd_journal_open.xml
+++ b/man/sd_journal_open.xml
@@ -45,11 +45,13 @@
<refnamediv>
<refname>sd_journal_open</refname>
<refname>sd_journal_open_directory</refname>
+ <refname>sd_journal_open_files</refname>
<refname>sd_journal_close</refname>
<refname>sd_journal</refname>
<refname>SD_JOURNAL_LOCAL_ONLY</refname>
<refname>SD_JOURNAL_RUNTIME_ONLY</refname>
- <refname>SD_JOURNAL_SYSTEM_ONLY</refname>
+ <refname>SD_JOURNAL_SYSTEM</refname>
+ <refname>SD_JOURNAL_CURRENT_USER</refname>
<refpurpose>Open the system journal for reading</refpurpose>
</refnamediv>
@@ -71,6 +73,13 @@
</funcprototype>
<funcprototype>
+ <funcdef>int <function>sd_journal_open_files</function></funcdef>
+ <paramdef>sd_journal** <parameter>ret</parameter></paramdef>
+ <paramdef>const char** <parameter>paths</parameter></paramdef>
+ <paramdef>int <parameter>flags</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
<funcdef>void <function>sd_journal_close</function></funcdef>
<paramdef>sd_journal* <parameter>j</parameter></paramdef>
</funcprototype>
@@ -84,19 +93,23 @@
the log journal for reading. It will find all journal
files automatically and interleave them automatically
when reading. As first argument it takes a pointer to
- a <literal>sd_journal</literal> pointer, which on
- success will contain journal context object afterwards. The
+ a <varname>sd_journal</varname> pointer, which on
+ success will contain a journal context object. The
second argument is a flags field, which may consist of
the following flags ORed together:
- <literal>SD_JOURNAL_LOCAL_ONLY</literal> makes sure
+ <constant>SD_JOURNAL_LOCAL_ONLY</constant> makes sure
only journal files generated on the local machine will
- be opened. <literal>SD_JOURNAL_RUNTIME_ONLY</literal>
+ be opened. <constant>SD_JOURNAL_RUNTIME_ONLY</constant>
makes sure only volatile journal files will be opened,
excluding those which are stored on persistent
- storage. <literal>SD_JOURNAL_SYSTEM_ONLY</literal>
- will ensure that only journal files of system services
- and the kernel (in opposition to user session processes) will
- be opened.</para>
+ storage. <constant>SD_JOURNAL_SYSTEM</constant>
+ will cause journal files of system services and the
+ kernel (in opposition to user session processes) to
+ be opened. <constant>SD_JOURNAL_CURRENT_USER</constant>
+ will cause journal files of the current user to be
+ opened. If neither <constant>SD_JOURNAL_SYSTEM</constant>
+ nor <constant>SD_JOURNAL_CURRENT_USER</constant> are
+ specified, all journal file types will be opened.</para>
<para><function>sd_journal_open_directory()</function>
is similar to <function>sd_journal_open()</function>
@@ -106,6 +119,25 @@
flags argument, but it must be passed as 0 as no flags
are currently understood for this call.</para>
+ <para><function>sd_journal_open_files()</function>
+ is similar to <function>sd_journal_open()</function>
+ but takes a <constant>NULL</constant>-terminated list
+ of file paths to open. All files will be opened and
+ interleaved automatically. This call also takes a
+ flags argument, but it must be passed as 0 as no flags
+ are currently understood for this call. Please note
+ that in the case of a live journal, this function is only
+ useful for debugging, because individual journal files
+ can be rotated at any moment, and the opening of
+ specific files is inherently racy.</para>
+
+ <para><varname>sd_journal</varname> objects cannot be
+ used in the child after a fork. Functions which take a
+ journal object as an argument
+ (<function>sd_journal_next()</function> and others)
+ will return <constant>-ECHILD</constant> after a fork.
+ </para>
+
<para><function>sd_journal_close()</function> will
close the journal context allocated with
<function>sd_journal_open()</function> or
@@ -114,12 +146,12 @@
<para>When opening the journal only journal files
accessible to the calling user will be opened. If
- journal files are not accessible to the caller this
+ journal files are not accessible to the caller, this
will be silently ignored.</para>
<para>See
<citerefentry><refentrytitle>sd_journal_next</refentrytitle><manvolnum>3</manvolnum></citerefentry>
- for an example how to iterate through the journal
+ for an example of how to iterate through the journal
after opening it with
<function>sd_journal_open()</function>.</para>
@@ -150,8 +182,9 @@
<refsect1>
<title>Return Value</title>
- <para>The <function>sd_journal_open()</function> and
- <function>sd_journal_open_directory()</function> calls
+ <para>The <function>sd_journal_open()</function>,
+ <function>sd_journal_open_directory()</function>, and
+ <function>sd_journal_open_files()</function> calls
return 0 on success or a negative errno-style error
code. <function>sd_journal_close()</function> returns
nothing.</para>
@@ -163,14 +196,34 @@
<para>The <function>sd_journal_open()</function>,
<function>sd_journal_open_directory()</function> and
<function>sd_journal_close()</function> interfaces are
- available as shared library, which can be compiled and
+ available as a shared library, which can be compiled and
linked to with the
- <literal>libsystemd-journal</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-journal</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
<refsect1>
+ <title>History</title>
+
+ <para><function>sd_journal_open()</function>,
+ <function>sd_journal_close()</function>,
+ <constant>SD_JOURNAL_LOCAL_ONLY</constant>,
+ <constant>SD_JOURNAL_RUNTIME_ONLY</constant>,
+ <constant>SD_JOURNAL_SYSTEM_ONLY</constant> were added
+ in systemd-38.</para>
+
+ <para><function>sd_journal_open_directory()</function>
+ was added in systemd-187.</para>
+
+ <para><constant>SD_JOURNAL_SYSTEM</constant>,
+ <constant>SD_JOURNAL_CURRENT_USER</constant>,
+ and <function>sd_journal_open_files()</function>
+ were added in systemd-205.
+ <constant>SD_JOURNAL_SYSTEM_ONLY</constant>
+ was deprecated.</para>
+ </refsect1>
+
+ <refsect1>
<title>See Also</title>
<para>
diff --git a/man/sd_journal_print.xml b/man/sd_journal_print.xml
index 7742268f5d..e61a648703 100644
--- a/man/sd_journal_print.xml
+++ b/man/sd_journal_print.xml
@@ -102,14 +102,14 @@
or
<citerefentry><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>. The
priority value is one of
- <literal>LOG_EMERG</literal>,
- <literal>LOG_ALERT</literal>,
- <literal>LOG_CRIT</literal>,
- <literal>LOG_ERR</literal>,
- <literal>LOG_WARNING</literal>,
- <literal>LOG_NOTICE</literal>,
- <literal>LOG_INFO</literal>,
- <literal>LOG_DEBUG</literal>, as defined in
+ <constant>LOG_EMERG</constant>,
+ <constant>LOG_ALERT</constant>,
+ <constant>LOG_CRIT</constant>,
+ <constant>LOG_ERR</constant>,
+ <constant>LOG_WARNING</constant>,
+ <constant>LOG_NOTICE</constant>,
+ <constant>LOG_INFO</constant>,
+ <constant>LOG_DEBUG</constant>, as defined in
<filename>syslog.h</filename>, see
<citerefentry><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>
for details. It is recommended to use this call to
@@ -120,7 +120,7 @@
<para><function>sd_journal_printv()</function> is
similar to <function>sd_journal_print()</function> but
takes a variable argument list encapsulated in an
- object of type <literal>va_list</literal> (see
+ object of type <varname>va_list</varname> (see
<citerefentry><refentrytitle>stdarg</refentrytitle><manvolnum>3</manvolnum></citerefentry>
for more information) instead of the format string. It
is otherwise equivalent in behavior.</para>
@@ -129,7 +129,7 @@
used to submit structured log entries to the system
journal. It takes a series of format strings, each
immediately followed by their associated parameters,
- terminated by NULL. The strings passed should be of
+ terminated by <constant>NULL</constant>. The strings passed should be of
the format <literal>VARIABLE=value</literal>. The
variable name must be in uppercase and consist only of
characters, numbers and underscores, and may not begin
@@ -138,7 +138,7 @@
of any size and format. It is highly recommended to
submit text strings formatted in the UTF-8 character
encoding only, and submit binary fields only when
- formatting in UTf-8 strings is not sensible. A number
+ formatting in UTF-8 strings is not sensible. A number
of well known fields are defined, see
<citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</manvolnum></citerefentry>
for details, but additional application defined fields
@@ -147,7 +147,7 @@
<para><function>sd_journal_sendv()</function> is
similar to <function>sd_journal_send()</function> but
- takes an array of <literal>struct iovec</literal> (as
+ takes an array of <varname>struct iovec</varname> (as
defined in <filename>uio.h</filename>, see
<citerefentry><refentrytitle>readv</refentrytitle><manvolnum>3</manvolnum></citerefentry>
for details) instead of the format string. Each
@@ -166,12 +166,12 @@
readable representation of the current error code
stored in
<citerefentry><refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum></citerefentry>. If
- the message string is passed as NULL or empty string
+ the message string is passed as <constant>NULL</constant> or empty string,
only the error string representation will be written,
prefixed with nothing. An additional journal field
ERRNO= is included in the entry containing the numeric
error code formatted as decimal string. The log
- priority used is <literal>LOG_ERR</literal> (3).</para>
+ priority used is <constant>LOG_ERR</constant> (3).</para>
<para>Note that <function>sd_journal_send()</function>
is a wrapper around
@@ -189,7 +189,7 @@ sd_journal_send("MESSAGE=Hello World, this is PID %lu!", (unsigned long) getpid(
<para>Note that these calls implicitly add fields for
the source file, function name and code line where
invoked. This is implemented with macros. If this is
- not desired it can be turned off by defining
+ not desired, it can be turned off by defining
SD_JOURNAL_SUPPRESS_LOCATION before including
<filename>sd-journal.h</filename>.</para>
@@ -202,7 +202,7 @@ sd_journal_send("MESSAGE=Hello World, this is PID %lu!", (unsigned long) getpid(
chronological ordering between the two streams cannot
be guaranteed. Using
<function>sd_journal_print()</function> has the
- benefit of logging source code line, file names, and
+ benefit of logging source code line, filenames, and
functions as meta data along all entries, and
guaranteeing chronological ordering with structured
log entries that are generated via
@@ -229,8 +229,7 @@ sd_journal_send("MESSAGE=Hello World, this is PID %lu!", (unsigned long) getpid(
<function>sd_journal_sendv()</function> interfaces
are available as shared library, which can be compiled
and linked to with the
- <literal>libsystemd-journal</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-journal</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/sd_journal_query_unique.xml b/man/sd_journal_query_unique.xml
index 502a7e08c2..f5d9d2bfb5 100644
--- a/man/sd_journal_query_unique.xml
+++ b/man/sd_journal_query_unique.xml
@@ -158,8 +158,7 @@
<function>sd_journal_restart_unique()</function>
interfaces are available as shared library, which can
be compiled and linked to with the
- <literal>libsystemd-journal</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-journal</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/sd_journal_seek_head.xml b/man/sd_journal_seek_head.xml
index d24b2f30ee..03de30a383 100644
--- a/man/sd_journal_seek_head.xml
+++ b/man/sd_journal_seek_head.xml
@@ -101,38 +101,40 @@
<para><function>sd_journal_seek_monotonic_usec()</function>
seeks to the entry with the specified monotonic
- timestamp, i.e. CLOCK_MONOTONIC. Since monotonic time
- restarts on every reboot a boot ID needs to be
- specified as well.</para>
+ timestamp,
+ i.e. <constant>CLOCK_MONOTONIC</constant>. Since
+ monotonic time restarts on every reboot a boot ID
+ needs to be specified as well.</para>
<para><function>sd_journal_seek_realtime_usec()</function>
seeks to the entry with the specified realtime
- (wallclock) timestamp, i.e. CLOCK_REALTIME. Note that
+ (wallclock) timestamp,
+ i.e. <constant>CLOCK_REALTIME</constant>. Note that
the realtime clock is not necessarily monotonic. If a
- realtime timestamp is ambiguous it is not defined
+ realtime timestamp is ambiguous, it is not defined
which position is sought to.</para>
<para><function>sd_journal_seek_cursor()</function>
seeks to the entry located at the specified cursor
- string. For details on cursors see
+ string. For details on cursors, see
<citerefentry><refentrytitle>sd_journal_get_cursor</refentrytitle><manvolnum>3</manvolnum></citerefentry>. If
no entry matching the specified cursor is found the
call will seek to the next closest entry (in terms of
time) instead. To verify whether the newly selected
- entry actually matches the cursor use
+ entry actually matches the cursor, use
<citerefentry><refentrytitle>sd_journal_test_cursor</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
<para>Note that these calls do not actually make any
entry the new current entry, this needs to be done in
a separate step with a subsequent
<citerefentry><refentrytitle>sd_journal_next</refentrytitle><manvolnum>3</manvolnum></citerefentry>
- invocation (or a similar call). Only then entry data
+ invocation (or a similar call). Only then, entry data
may be retrieved via
<citerefentry><refentrytitle>sd_journal_get_data</refentrytitle><manvolnum>3</manvolnum></citerefentry>. If
no entry exists that matches exactly the specified
- seek address the next closest is sought to. If
+ seek address, the next closest is sought to. If
<citerefentry><refentrytitle>sd_journal_next</refentrytitle><manvolnum>3</manvolnum></citerefentry>
- is used the closest following entry will be sought to,
+ is used, the closest following entry will be sought to,
if
<citerefentry><refentrytitle>sd_journal_previous</refentrytitle><manvolnum>3</manvolnum></citerefentry>
is used the closest preceding entry is sought
@@ -156,8 +158,7 @@
and <function>sd_journal_seek_cursor()</function>
interfaces are available as shared library, which can
be compiled and linked to with the
- <literal>libsystemd-journal</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-journal</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/sd_journal_stream_fd.xml b/man/sd_journal_stream_fd.xml
index 4407296b40..4bd0abc3b4 100644
--- a/man/sd_journal_stream_fd.xml
+++ b/man/sd_journal_stream_fd.xml
@@ -67,7 +67,7 @@
<para><function>sd_journal_stream_fd()</function> may
be used to create a log stream file descriptor. Log
messages written to this file descriptor as simple
- newline separated text strings are written to the
+ newline-separated text strings are written to the
journal. This file descriptor can be used internally
by applications or be made STDOUT/STDERR of other
processes executed.</para>
@@ -79,19 +79,19 @@
<citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</manvolnum></citerefentry>
for more information). The second argument shall be
the default priority level for all messages. The
- priority level is one of <literal>LOG_EMERG</literal>,
- <literal>LOG_ALERT</literal>,
- <literal>LOG_CRIT</literal>,
- <literal>LOG_ERR</literal>,
- <literal>LOG_WARNING</literal>,
- <literal>LOG_NOTICE</literal>,
- <literal>LOG_INFO</literal>,
- <literal>LOG_DEBUG</literal>, as defined in
+ priority level is one of <constant>LOG_EMERG</constant>,
+ <constant>LOG_ALERT</constant>,
+ <constant>LOG_CRIT</constant>,
+ <constant>LOG_ERR</constant>,
+ <constant>LOG_WARNING</constant>,
+ <constant>LOG_NOTICE</constant>,
+ <constant>LOG_INFO</constant>,
+ <constant>LOG_DEBUG</constant>, as defined in
<filename>syslog.h</filename>, see
<citerefentry><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>
for details. The third argument is a boolean: if true
kernel-style log priority level prefixes (such as
- <literal>SD_WARNING</literal>) are interpreted, see
+ <constant>SD_WARNING</constant>) are interpreted, see
<citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>3</manvolnum></citerefentry>
for more information.</para>
@@ -114,8 +114,7 @@
<para>The <function>sd_journal_stream_fd()</function>
interface is available as shared library, which can
be compiled and linked to with the
- <literal>libsystemd-journal</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-journal</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/sd_listen_fds.xml b/man/sd_listen_fds.xml
index 9c8fdbccaf..240300dcb0 100644
--- a/man/sd_listen_fds.xml
+++ b/man/sd_listen_fds.xml
@@ -70,7 +70,7 @@
activation logic.</para>
<para>If the <parameter>unset_environment</parameter>
- parameter is non-zero
+ parameter is non-zero,
<function>sd_listen_fds()</function> will unset the
<varname>$LISTEN_FDS</varname>/<varname>$LISTEN_PID</varname>
environment variables before returning (regardless
@@ -83,16 +83,16 @@
<para>If a daemon receives more than one file
descriptor, they will be passed in the same order as
configured in the systemd socket definition
- file. Nonetheless it is recommended to verify the
+ file. Nonetheless, it is recommended to verify the
correct socket types before using them. To simplify
- this checking the functions
+ this checking, the functions
<citerefentry><refentrytitle>sd_is_fifo</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_is_socket</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_is_socket_inet</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_is_socket_unix</refentrytitle><manvolnum>3</manvolnum></citerefentry>
- are provided. In order to maximize flexibility it is
+ are provided. In order to maximize flexibility, it is
recommended to make these checks as loose as possible
- without allowing incorrect setups. i.e. often the
+ without allowing incorrect setups. i.e. often, the
actual port number a socket is bound to matters little
for the service to work, hence it should not be
verified. On the other hand, whether a socket is a
@@ -112,7 +112,7 @@
<varname>$LISTEN_FDS</varname>/<varname>$LISTEN_PID</varname>
was not set or was not correctly set for this daemon and
hence no file descriptors were received, 0 is
- returned. Otherwise the number of file descriptors
+ returned. Otherwise, the number of file descriptors
passed is returned. The application may find them
starting with file descriptor SD_LISTEN_FDS_START,
i.e. file descriptor 3.</para>
@@ -132,11 +132,11 @@
<para>Internally, this function checks whether the
<varname>$LISTEN_PID</varname> environment variable
equals the daemon PID. If not, it returns
- immediately. Otherwise it parses the number passed in
+ immediately. Otherwise, it parses the number passed in
the <varname>$LISTEN_FDS</varname> environment
variable, then sets the FD_CLOEXEC flag for the parsed
number of file descriptors starting from
- SD_LISTEN_FDS_START. Finally it returns the parsed
+ SD_LISTEN_FDS_START. Finally, it returns the parsed
number.</para>
<para>For details about the algorithm check the
@@ -151,8 +151,7 @@
<filename>sd-daemon.h</filename> files. These
interfaces are available as shared library, which can
be compiled and linked to with the
- <literal>libsystemd-daemon</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-daemon</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file. Alternatively, applications consuming these APIs
may copy the implementation into their source
tree. For more details about the reference
@@ -161,7 +160,7 @@
<para>If the reference implementation is used as
drop-in files and -DDISABLE_SYSTEMD is set during
- compilation this function will always return 0 and
+ compilation, this function will always return 0 and
otherwise become a NOP.</para>
</refsect1>
diff --git a/man/sd_login_monitor_new.xml b/man/sd_login_monitor_new.xml
index 26af0ea247..909a3d9bfd 100644
--- a/man/sd_login_monitor_new.xml
+++ b/man/sd_login_monitor_new.xml
@@ -96,7 +96,7 @@
<title>Description</title>
<para><function>sd_login_monitor_new()</function> may
- be used to monitor login sessions, users, seats and
+ be used to monitor login sessions, users, seats, and
virtual machines/containers. Via a monitor object a
file descriptor can be integrated into an application
defined event loop which is woken up each time a user
@@ -112,7 +112,7 @@
logins) or <literal>machine</literal> (to get only
notifications when a virtual machine or container is
started or stopped). If notifications shall be
- generated in all these conditions, NULL may be
+ generated in all these conditions, <constant>NULL</constant> may be
passed. Note that in the future additional categories
may be defined. The second parameter returns a monitor
object and needs to be freed with the
@@ -129,7 +129,7 @@
object. Whenever an event causes the monitor to wake
up the event loop via the file descriptor this
function needs to be called to reset the wake-up
- state. If this call is not invoked the file descriptor
+ state. If this call is not invoked, the file descriptor
will immediately wake up the event loop again.</para>
<para><function>sd_login_monitor_get_fd()</function>
@@ -154,22 +154,22 @@
<para><function>sd_login_monitor_get_events()</function>
will return the <function>poll()</function> mask to
wait for. This function will return a combination of
- <literal>POLLIN</literal>, <literal>POLLOUT</literal>
+ <constant>POLLIN</constant>, <constant>POLLOUT</constant>
and similar to fill into the
- <literal>.events</literal> field of <literal>struct
- pollfd</literal>.</para>
+ <literal>.events</literal> field of <varname>struct
+ pollfd</varname>.</para>
<para><function>sd_login_monitor_get_timeout()</function>
will return a timeout value for usage in
<function>poll()</function>. This returns a value in
- microseconds since the epoch of CLOCK_MONOTONIC for
- timing out <function>poll()</function> in
- <literal>timeout_usec</literal>. See
+ microseconds since the epoch of <constant>CLOCK_MONOTONIC</constant>
+ for timing out <function>poll()</function> in
+ <varname>timeout_usec</varname>. See
<citerefentry><refentrytitle>clock_gettime</refentrytitle><manvolnum>2</manvolnum></citerefentry>
for details about
- <literal>CLOCK_MONOTONIC</literal>. If there's no
+ <constant>CLOCK_MONOTONIC</constant>. If there is no
timeout to wait for this will fill in
- <literal>(uint64_t) -1</literal> instead. Note that
+ <constant>(uint64_t) -1</constant> instead. Note that
<function>poll()</function> takes a relative timeout
in milliseconds rather than an absolute timeout in
microseconds. To convert the absolute 'us' timeout into
@@ -189,7 +189,7 @@ else {
}</programlisting>
<para>The code above does not do any error checking
- for brevity's sake. The calculated <literal>msec</literal>
+ for brevity's sake. The calculated <varname>msec</varname>
integer can be passed directly as
<function>poll()</function>'s timeout
parameter.</para>
@@ -206,13 +206,13 @@ else {
<function>sd_login_monitor_get_fd()</function> returns
a Unix file descriptor. On success
<function>sd_login_monitor_get_events()</function>
- returns a combination of <literal>POLLIN</literal>,
- <literal>POLLOUT</literal> and suchlike. On failure,
+ returns a combination of <constant>POLLIN</constant>,
+ <constant>POLLOUT</constant> and suchlike. On failure,
these calls return a negative errno-style error
code.</para>
<para><function>sd_login_monitor_unref()</function>
- always returns NULL.</para>
+ always returns <constant>NULL</constant>.</para>
</refsect1>
<refsect1>
@@ -226,8 +226,7 @@ else {
<function>sd_login_monitor_get_timeout()</function>
interfaces are available as shared library, which can
be compiled and linked to with the
- <literal>libsystemd-login</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-login</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/sd_notify.xml b/man/sd_notify.xml
index 81f74aa843..55965ffce4 100644
--- a/man/sd_notify.xml
+++ b/man/sd_notify.xml
@@ -77,7 +77,7 @@
notification.</para>
<para>If the <parameter>unset_environment</parameter>
- parameter is non-zero <function>sd_notify()</function>
+ parameter is non-zero, <function>sd_notify()</function>
will unset the <varname>$NOTIFY_SOCKET</varname>
environment variable before returning (regardless
whether the function call itself succeeded or
@@ -197,10 +197,10 @@
errno-style error code. If
<varname>$NOTIFY_SOCKET</varname> was not set and
hence no status data could be sent, 0 is returned. If
- the status was sent these functions return with a
+ the status was sent, these functions return with a
positive return value. In order to support both, init
systems that implement this scheme and those which
- don't, it is generally recommended to ignore the return
+ do not, it is generally recommended to ignore the return
value of this call.</para>
</refsect1>
@@ -217,10 +217,10 @@
<para>Internally, these functions send a single
datagram with the state string as payload to the
- AF_UNIX socket referenced in the
+ <constant>AF_UNIX</constant> socket referenced in the
<varname>$NOTIFY_SOCKET</varname> environment
variable. If the first character of
- <varname>$NOTIFY_SOCKET</varname> is @ the string is
+ <varname>$NOTIFY_SOCKET</varname> is <literal>@</literal>, the string is
understood as Linux abstract namespace socket. The
datagram is accompanied by the process credentials of
the sending daemon, using SCM_CREDENTIALS.</para>
@@ -238,8 +238,7 @@
<filename>sd-daemon.h</filename> files. These
interfaces are available as shared library, which can
be compiled and linked to with the
- <literal>libsystemd-daemon</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-daemon</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file. Alternatively, applications consuming these APIs
may copy the implementation into their source tree. For
more details about the reference implementation see
@@ -247,7 +246,7 @@
<para>If the reference implementation is used as
drop-in files and -DDISABLE_SYSTEMD is set during
- compilation these functions will always return 0 and
+ compilation, these functions will always return 0 and
otherwise become a NOP.</para>
</refsect1>
diff --git a/man/sd_pid_get_session.xml b/man/sd_pid_get_session.xml
index 543a5c0c72..e5c77090dd 100644
--- a/man/sd_pid_get_session.xml
+++ b/man/sd_pid_get_session.xml
@@ -48,7 +48,10 @@
<refname>sd_pid_get_user_unit</refname>
<refname>sd_pid_get_owner_uid</refname>
<refname>sd_pid_get_machine_name</refname>
- <refpurpose>Determine session, service, owner of a session or container/VM of a specific PID</refpurpose>
+ <refname>sd_pid_get_slice</refname>
+ <refpurpose>Determine session, service, owner of a
+ session, container/VM or slice of a specific
+ PID</refpurpose>
</refnamediv>
<refsynopsisdiv>
@@ -84,6 +87,12 @@
<paramdef>pid_t <parameter>pid</parameter></paramdef>
<paramdef>char** <parameter>name</parameter></paramdef>
</funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_pid_get_slice</function></funcdef>
+ <paramdef>pid_t <parameter>pid</parameter></paramdef>
+ <paramdef>char** <parameter>slice</parameter></paramdef>
+ </funcprototype>
</funcsynopsis>
</refsynopsisdiv>
@@ -138,23 +147,32 @@
and not being a shared process of a user this function
will fail.</para>
- <para><function>sd_pid_machine_name()</function> may
- be used to determine the name of the VM or container
- is a member of. The machine name is a short string,
- suitable for usage in file system paths. The returned
- string needs to be freed with the libc
+ <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 machine name is a short
+ string, suitable for usage in file system paths. The
+ returned string needs to be freed with the libc
+ <citerefentry><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ call after use.</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><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use.</para>
- <para>If the <literal>pid</literal> parameter of any
- of these functions is passed as 0 the operation is
+ <para>If the <varname>pid</varname> parameter of any
+ of these functions is passed as 0, the operation is
executed for the calling process.</para>
</refsect1>
<refsect1>
<title>Return Value</title>
- <para>On success these calls return 0 or a positive
+ <para>On success, these calls return 0 or a positive
integer. On failure, these calls return a negative
errno-style error code.</para>
</refsect1>
@@ -165,12 +183,12 @@
<para>The <function>sd_pid_get_session()</function>,
<function>sd_pid_get_unit()</function>,
<function>sd_pid_get_user_unit()</function>,
- <function>sd_pid_get_owner_uid()</function> and
- <function>sd_pid_get_machine_name()</function>
- interfaces are available as shared library, which can
- be compiled and linked to with the
- <literal>libsystemd-login</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <function>sd_pid_get_owner_uid()</function>,
+ <function>sd_pid_get_machine_name()</function> and
+ <function>sd_pid_get_slice()</function> interfaces are
+ available as shared library, which can be compiled and
+ linked to with the
+ <constant>libsystemd-login</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
<para>Note that the login session identifier as
@@ -187,7 +205,8 @@
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-login</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_session_is_active</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>getsid</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>getsid</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/sd_readahead.xml b/man/sd_readahead.xml
index c26d5c63e3..bb01bcfd89 100644
--- a/man/sd_readahead.xml
+++ b/man/sd_readahead.xml
@@ -142,7 +142,7 @@
details about the reference implementation see
<citerefentry><refentrytitle>sd-readahead</refentrytitle><manvolnum>3</manvolnum></citerefentry></para>
- <para>If -DDISABLE_SYSTEMD is set during compilation
+ <para>If -DDISABLE_SYSTEMD is set during compilation,
this function will always return 0 and otherwise
become a NOP.</para>
</refsect1>
diff --git a/man/sd_seat_get_active.xml b/man/sd_seat_get_active.xml
index 07e018de13..1610d3efe8 100644
--- a/man/sd_seat_get_active.xml
+++ b/man/sd_seat_get_active.xml
@@ -65,7 +65,7 @@
<paramdef>const char* <parameter>seat</parameter></paramdef>
<paramdef>char*** <parameter>sessions</parameter></paramdef>
<paramdef>uid_t** <parameter>uid</parameter></paramdef>
- <paramdef>unsigned* <parameter>n_uids</parameter></paramdef>
+ <paramdef>unsigned int* <parameter>n_uids</parameter></paramdef>
</funcprototype>
<funcprototype>
@@ -93,26 +93,27 @@
a seat, if there is any. Returns the session
identifier and the user identifier of the Unix user
the session is belonging to. Either the session or the
- user identifier parameter can be passed NULL, in
- case only one of the parameters shall be queried. The
- returned string needs to be freed with the libc
+ user identifier parameter can be passed
+ <constant>NULL</constant>, in case only one of the
+ parameters shall be queried. The returned string needs
+ to be freed with the libc
<citerefentry><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use.</para>
<para><function>sd_seat_get_sessions()</function> may
be used to determine all sessions on the specified
- seat. Returns two arrays, one (NULL terminated) with
+ seat. Returns two arrays, one (<constant>NULL</constant> terminated) with
the session identifiers of the sessions and one with
the user identifiers of the Unix users the sessions
belong to. An additional parameter may be used to
return the number of entries in the latter array. The
two arrays and the latter parameter may be passed as
- NULL in case these values need not to be
+ <constant>NULL</constant> in case these values need not to be
determined. The arrays and the strings referenced by
them need to be freed with the libc
<citerefentry><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use. Note that instead of an empty array
- NULL may be returned and should be considered
+ <constant>NULL</constant> may be returned and should be considered
equivalent to an empty array.</para>
<para><function>sd_seat_can_multi_session()</function>
@@ -130,10 +131,11 @@
graphics functionality, i.e. is useful as a graphics
display.</para>
- <para>If the <literal>seat</literal> parameter of any
- of these functions is passed as NULL the operation is
- executed for the seat of the session of the calling
- process, if there is any.</para>
+ <para>If the <varname>seat</varname> parameter of any
+ of these functions is passed as
+ <constant>NULL</constant>, the operation is executed
+ for the seat of the session of the calling process, if
+ there is any.</para>
</refsect1>
<refsect1>
@@ -144,7 +146,7 @@
returns 0 or a positive integer. On success
<function>sd_seat_get_sessions()</function> returns
the number of entries in the session identifier
- array. If the test succeeds
+ array. If the test succeeds,
<function>sd_seat_can_multi_session</function>,
<function>sd_seat_can_tty</function> and
<function>sd_seat_can_graphical</function> return a
@@ -162,8 +164,7 @@
<function>sd_seat_can_grapical()</function> interfaces
are available as shared library, which can be compiled
and linked to with the
- <literal>libsystemd-login</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-login</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/sd_session_is_active.xml b/man/sd_session_is_active.xml
index 6fa803bfa2..293ce71642 100644
--- a/man/sd_session_is_active.xml
+++ b/man/sd_session_is_active.xml
@@ -52,6 +52,7 @@
<refname>sd_session_get_class</refname>
<refname>sd_session_get_display</refname>
<refname>sd_session_get_tty</refname>
+ <refname>sd_session_get_vt</refname>
<refpurpose>Determine state of a specific session</refpurpose>
</refnamediv>
@@ -111,6 +112,12 @@
<paramdef>const char* <parameter>session</parameter></paramdef>
<paramdef>char** <parameter>tty</parameter></paramdef>
</funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_session_get_vt</function></funcdef>
+ <paramdef>const char* <parameter>session</parameter></paramdef>
+ <paramdef>unsigned int* <parameter>vt</parameter></paramdef>
+ </funcprototype>
</funcsynopsis>
</refsynopsisdiv>
@@ -202,16 +209,23 @@
<citerefentry><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use.</para>
- <para>If the <literal>session</literal> parameter of
- any of these functions is passed as NULL the operation
- is executed for the session the calling process is a
- member of, if there is any.</para>
+ <para><function>sd_session_get_vt()</function>
+ may be used to determine the VT number of the
+ session identified by the specified session
+ identifier. This function will return an error if
+ the seat does not support VTs.</para>
+
+ <para>If the <varname>session</varname> parameter of
+ any of these functions is passed as
+ <constant>NULL</constant>, the operation is executed
+ for the session the calling process is a member of, if
+ there is any.</para>
</refsect1>
<refsect1>
<title>Return Value</title>
- <para>If the test succeeds
+ <para>If the test succeeds,
<function>sd_session_is_active()</function> returns a
positive integer, if it fails 0. On success
<function>sd_session_get_state()</function>,
@@ -240,8 +254,7 @@
<function>sd_session_get_tty()</function>
interfaces are available as shared library, which can
be compiled and linked to with the
- <literal>libsystemd-login</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <constant>libsystemd-login</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/sd_uid_get_state.xml b/man/sd_uid_get_state.xml
index cc8fc0f5b6..d4d23f4f1d 100644
--- a/man/sd_uid_get_state.xml
+++ b/man/sd_uid_get_state.xml
@@ -111,7 +111,7 @@
or active on a specific seat. Accepts a Unix user
identifier and a seat identifier string as
parameters. The <parameter>require_active</parameter>
- parameter is a boolean value. If non-zero (true) this
+ parameter is a boolean value. If non-zero (true), this
function will test if the user is active (i.e. has a
session that is in the foreground and accepting user
input) on the specified seat, otherwise (false) only
@@ -127,15 +127,15 @@
currently active (&gt; 0), where the user is currently
online but possibly inactive (= 0), or
logged in at all but possibly closing the session (&lt; 0). The call returns a
- NULL terminated string array of session identifiers in
+ <constant>NULL</constant> terminated string array of session identifiers in
<parameter>sessions</parameter> which needs to be
freed by the caller with the libc
<citerefentry><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use, including all the strings
referenced. If the string array parameter is passed as
- NULL the array will not be filled in, but the return
+ <constant>NULL</constant>, the array will not be filled in, but the return
code still indicates the number of current
- sessions. Note that instead of an empty array NULL may
+ sessions. Note that instead of an empty array <constant>NULL</constant> may
be returned and should be considered equivalent to an
empty array.</para>
@@ -154,7 +154,7 @@
<para>On success
<function>sd_uid_get_state()</function> returns 0 or a
- positive integer. If the test succeeds
+ positive integer. If the test succeeds,
<function>sd_uid_is_on_seat()</function> returns a
positive integer, if it fails
0. <function>sd_uid_get_sessions()</function> and
@@ -172,8 +172,7 @@
<function>sd_uid_get_sessions()</function>, and
<function>sd_uid_get_seats()</function> interfaces are
available as shared library, which can be compiled and
- linked to with the <literal>libsystemd-login</literal>
- <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ linked to with the <constant>libsystemd-login</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
diff --git a/man/shutdown.xml b/man/shutdown.xml
index 570383319b..795fb66328 100644
--- a/man/shutdown.xml
+++ b/man/shutdown.xml
@@ -133,7 +133,7 @@
<varlistentry>
<term><option>-k</option></term>
- <listitem><para>Don't halt, power-off,
+ <listitem><para>Do not halt, power-off,
reboot, just write wall
message.</para></listitem>
</varlistentry>
@@ -141,7 +141,7 @@
<varlistentry>
<term><option>--no-wall</option></term>
- <listitem><para>Don't send wall
+ <listitem><para>Do not send wall
message before
halt, power-off, reboot.</para></listitem>
</varlistentry>
@@ -169,13 +169,6 @@
</refsect1>
<refsect1>
- <title>Notes</title>
-
- <para>This is a legacy command available for
- compatibility only.</para>
- </refsect1>
-
- <refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
diff --git a/man/sysctl.d.xml b/man/sysctl.d.xml
index 759b8740f5..854864cffc 100644
--- a/man/sysctl.d.xml
+++ b/man/sysctl.d.xml
@@ -89,18 +89,20 @@
administrator, who may use this logic to override the
configuration files installed by vendor packages. All
configuration files are sorted by their filename in
- alphabetical order, regardless in which of the
- directories they reside, to guarantee that a specific
- configuration file takes precedence over another file
- with an alphabetically later name, if both files
- contain the same variable setting.</para>
+ lexicographic order, regardless in which of the
+ directories they reside. If multiple files specify the
+ same variable name, the entry in the file with the
+ lexicographically latest name will be applied. 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
+ configuration file supplied by the vendor, the
recommended way is to place a symlink to
<filename>/dev/null</filename> in
<filename>/etc/sysctl.d/</filename> bearing the
- same file name.</para>
+ same filename.</para>
</refsect1>
<refsect1>
diff --git a/man/systemctl.xml b/man/systemctl.xml
index 0afb0cc626..e789d4b629 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -92,21 +92,15 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
<term><option>--type=</option></term>
<listitem>
- <para>The argument should be a comma separated list of unit
+ <para>The argument should be a comma-separated list of unit
types such as <option>service</option> and
- <option>socket</option>, or unit load states such as
- <option>loaded</option> and <option>masked</option>
- (types and states can be mixed).</para>
+ <option>socket</option>.
+ </para>
<para>If one of the arguments is a unit type, when listing
- units, limit display to certain unit types. Otherwise units
+ units, limit display to certain unit types. Otherwise, units
of all types will be shown.</para>
- <para>If one of the arguments is a unit load state, when
- listing units, limit display to certain unit
- types. Otherwise units of in all load states will be
- shown.</para>
-
<para>As a special case, if one of the arguments is
<option>help</option>, a list of allowed values will be
printed and the program will exit.</para>
@@ -114,16 +108,26 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
</varlistentry>
<varlistentry>
+ <term><option>--state=</option></term>
+
+ <listitem>
+ <para>The argument should be a comma-separated list of unit LOAD,
+ SUB, or ACTIVE states. When listing units, show only those
+ in specified states.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>-p</option></term>
<term><option>--property=</option></term>
<listitem>
<para>When showing unit/job/manager properties with the
<command>show</command> command, limit display to certain
- properties as specified as argument. If not specified all
+ properties as specified as argument. If not specified, all
set properties are shown. The argument should be a
comma-separated list of property names, such as
- <literal>MainPID</literal>. If specified more than once all
+ <literal>MainPID</literal>. If specified more than once, all
properties with the specified names are shown.</para>
</listitem>
</varlistentry>
@@ -159,26 +163,18 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
<term><option>--before</option></term>
<listitem>
- <para>Show which units are started after, resp. before
- with <command>list-dependencies</command>.
+ <para>Show which units are started after or before
+ with <command>list-dependencies</command>, respectively.
</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--failed</option></term>
-
- <listitem>
- <para>When listing units, show only failed units. Do not
- confuse with <option>--fail</option>.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
+ <term><option>-l</option></term>
<term><option>--full</option></term>
<listitem>
- <para>Do not ellipsize unit names, cgroup members, and
+ <para>Do not ellipsize unit names, process tree entries, and
truncate unit descriptions in the output of
<command>list-units</command> and
<command>list-jobs</command>.</para>
@@ -190,7 +186,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
<listitem>
<para>If the requested operation conflicts with a pending
- unfinished job, fail the command. If this is not specified
+ unfinished job, fail the command. If this is not specified,
the requested operation will replace the pending job, if
necessary. Do not confuse with
<option>--failed</option>.</para>
@@ -220,8 +216,8 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
<term><option>--ignore-dependencies</option></term>
<listitem>
- <para>When enqueuing a new job ignore all its dependencies
- and execute it immediately. If passed no required units of
+ <para>When enqueuing a new job, ignore all its dependencies
+ and execute it immediately. If passed, no required units of
the unit passed will be pulled in, and no ordering
dependencies will be honored. This is mostly a debugging and
rescue tool for the administrator and should not be used by
@@ -242,8 +238,8 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
users may override these locks. If any locks are taken,
shutdown and sleep state requests will normally fail
(regardless if privileged or not) and a list of active locks
- is printed. However if <option>--ignore-inhibitors</option>
- is specified the locks are ignored and not printed, and the
+ is printed. However, if <option>--ignore-inhibitors</option>
+ is specified, the locks are ignored and not printed, and the
operation attempted anyway, possibly requiring additional
privileges.</para>
</listitem>
@@ -268,9 +264,9 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
<listitem>
<para>Do not synchronously wait for the requested operation
- to finish. If this is not specified the job will be
+ to finish. If this is not specified, the job will be
verified, enqueued and <command>systemctl</command> will
- wait until it is completed. By passing this argument it is
+ wait until it is completed. By passing this argument, it is
only verified and enqueued.</para>
</listitem>
</varlistentry>
@@ -313,7 +309,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
<term><option>--no-wall</option></term>
<listitem>
- <para>Don't send wall message before halt, power-off,
+ <para>Do not send wall message before halt, power-off,
reboot.</para>
</listitem>
</varlistentry>
@@ -348,10 +344,10 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
may require input of a password or passphrase string, for
example to unlock system hard disks or cryptographic
certificates. Unless this option is specified and the
- command is invoked from a terminal
+ command is invoked from a terminal,
<command>systemctl</command> will query the user on the
terminal for the necessary secrets. Use this option to
- switch this behavior off. In this case the password must be
+ switch this behavior off. In this case, the password must be
supplied by some other means (for example graphical password
agents) or the service might fail. This also disables
querying the user for authentication for privileged
@@ -368,7 +364,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
processes to kill. Must be one of <option>main</option>,
<option>control</option> or <option>all</option> to select
whether to kill only the main process of the unit, the
- control process or all processes of the unit. If omitted
+ control process or all processes of the unit. If omitted,
defaults to <option>all</option>.</para>
</listitem>
@@ -381,8 +377,8 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
<listitem>
<para>When used with <command>kill</command>, choose which
signal to send to selected processes. Must be one of the
- well known signal specifiers such as SIGTERM, SIGINT or
- SIGSTOP. If omitted defaults to
+ well known signal specifiers such as <constant>SIGTERM</constant>, <constant>SIGINT</constant> or
+ <constant>SIGSTOP</constant>. If omitted, defaults to
<option>SIGTERM</option>.</para>
</listitem>
</varlistentry>
@@ -397,7 +393,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
<para>When used with <command>halt</command>,
<command>poweroff</command>, <command>reboot</command> or
- <command>kexec</command> execute the selected operation
+ <command>kexec</command>, execute the selected operation
without shutting down all units. However, all processes will
be killed forcibly and all file systems are unmounted or
remounted read-only. This is hence a drastic but relatively
@@ -437,10 +433,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
is lost on reboot, the changes are lost too.</para>
<para>Similar, when used with
- <command>set-cgroup-attr</command>,
- <command>unset-cgroup-attr</command>,
- <command>set-cgroup</command> and
- <command>unset-cgroup</command>, make changes only
+ <command>set-property</command>, make changes only
temporarily, so that they are lost on the next
reboot.</para>
</listitem>
@@ -452,7 +445,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
<listitem>
<para>Execute operation remotely. Specify a hostname, or
- username and hostname separated by @, to connect to. This
+ username and hostname separated by <literal>@</literal>, to connect to. This
will use SSH to talk to the remote systemd
instance.</para>
</listitem>
@@ -473,7 +466,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
<term><option>--lines=</option></term>
<listitem>
- <para>When used with <command>status</command> controls the
+ <para>When used with <command>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>
@@ -485,9 +478,9 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
<term><option>--output=</option></term>
<listitem>
- <para>When used with <command>status</command> controls the
+ <para>When used with <command>status</command>, controls the
formatting of the journal entries that are shown. For the
- available choices see
+ available choices, see
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
Defaults to <literal>short</literal>.</para>
</listitem>
@@ -497,7 +490,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
<term><option>--plain</option></term>
<listitem>
- <para>When used with <command>list-dependencies</command>
+ <para>When used with <command>list-dependencies</command>,
the output is printed as a list instead of a tree.</para>
</listitem>
</varlistentry>
@@ -510,25 +503,28 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
<para>The following commands are understood:</para>
- <variablelist>
- <varlistentry>
- <term><command>list-units</command></term>
+ <refsect2>
+ <title>Unit Commands</title>
- <listitem>
- <para>List known units (subject to limitations specified
- with <option>-t</option>).</para>
+ <variablelist>
+ <varlistentry>
+ <term><command>list-units</command></term>
- <para>This is the default command.</para>
- </listitem>
- </varlistentry>
+ <listitem>
+ <para>List known units (subject to limitations specified
+ with <option>-t</option>).</para>
- <varlistentry>
- <term><command>list-sockets</command></term>
+ <para>This is the default command.</para>
+ </listitem>
+ </varlistentry>
- <listitem>
- <para>List socket units ordered by the listening address. Produces output
- similar to
- <programlisting>
+ <varlistentry>
+ <term><command>list-sockets</command></term>
+
+ <listitem>
+ <para>List socket units ordered by the listening address. Produces output
+ similar to
+ <programlisting>
LISTEN UNIT ACTIVATES
/dev/initctl systemd-initctl.socket systemd-initctl.service
...
@@ -536,769 +532,735 @@ LISTEN UNIT ACTIVATES
kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
5 sockets listed.
- </programlisting>
- Note: because the addresses might contains spaces, this output
- is not suitable for programatic consumption.
- </para>
-
- <para>See also the options <option>--show-types</option>,
- <option>--all</option>, and <option>--failed</option>.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>start <replaceable>NAME</replaceable>...</command></term>
-
- <listitem>
- <para>Start (activate) one or more units specified on the
- command line.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>stop <replaceable>NAME</replaceable>...</command></term>
-
- <listitem>
- <para>Stop (deactivate) one or more units specified on the
- command line.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>reload <replaceable>NAME</replaceable>...</command></term>
-
- <listitem>
- <para>Asks all units listed on the command line to reload
- their configuration. Note that this will reload the
- service-specific configuration, not the unit configuration
- file of systemd. If you want systemd to reload the
- configuration file of a unit use the
- <command>daemon-reload</command> command. In other words:
- for the example case of Apache, this will reload Apache's
- <filename>httpd.conf</filename> in the web server, not the
- <filename>apache.service</filename> systemd unit
- file. </para>
-
- <para>This command should not be confused with the
- <command>daemon-reload</command> or <command>load</command>
- commands.</para>
- </listitem>
-
- </varlistentry>
- <varlistentry>
- <term><command>restart <replaceable>NAME</replaceable>...</command></term>
-
- <listitem>
- <para>Restart one or more units specified on the command
- line. If the units are not running yet they will be
- started.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>try-restart <replaceable>NAME</replaceable>...</command></term>
-
- <listitem>
- <para>Restart one or more units specified on the command
- line if the units are running. Do nothing if units are not
- running. Note that for compatibility with Red Hat init
- scripts <command>condrestart</command> is equivalent to this
- command.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>reload-or-restart <replaceable>NAME</replaceable>...</command></term>
-
- <listitem>
- <para>Reload one or more units if they support it. If not,
- restart them instead. If the units are not running yet they
- will be started.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>reload-or-try-restart <replaceable>NAME</replaceable>...</command></term>
-
- <listitem>
- <para>Reload one or more units if they support it. If not,
- restart them instead. Do nothing if the units are not
- running. Note that for compatibility with SysV init scripts
- <command>force-reload</command> is equivalent to this
- command.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>isolate <replaceable>NAME</replaceable></command></term>
-
- <listitem>
- <para>Start the unit specified on the command line and its
- dependencies and stop all others.</para>
-
- <para>This is similar to changing the runlevel in a
- traditional init system. The <command>isolate</command>
- command will immediately stop processes that are not enabled
- in the new unit, possibly including the graphical
- environment or terminal you are currently using.</para>
-
- <para>Note that this is allowed only on units where
- <option>AllowIsolate=</option> is enabled. See
- <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- for details.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>kill <replaceable>NAME</replaceable>...</command></term>
-
- <listitem>
- <para>Send a signal to one or more processes of the
- unit. Use <option>--kill-who=</option> to select which
- process to kill. Use <option>--kill-mode=</option> to select
- the kill mode and <option>--signal=</option> to select the
- signal to send.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>is-active <replaceable>NAME</replaceable>...</command></term>
-
- <listitem>
- <para>Check whether any of the specified units are active
- (i.e. running). Returns an exit code 0 if at least one is
- active, non-zero otherwise. Unless <option>--quiet</option>
- is specified this will also print the current unit state to
- STDOUT.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>is-failed <replaceable>NAME</replaceable>...</command></term>
-
- <listitem>
- <para>Check whether any of the specified units are failed.
- Returns an exit code 0 if at least one is failed, non-zero
- otherwise. Unless <option>--quiet</option> is specified this
- will also print the current unit state to
- STDOUT.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>status [<replaceable>NAME</replaceable>...|<replaceable>PID</replaceable>...]</command></term>
-
- <listitem>
- <para>Show terse runtime status information about one or
- more units, followed by most recent log data from the
- journal. If no units are specified, show all units (subject
- to limitations specified with <option>-t</option>). If a PID
- is passed show information about the unit the process
- belongs to.</para>
-
- <para>This function is intended to generate human-readable
- output. If you are looking for computer-parsable output, use
- <command>show</command> instead.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>show [<replaceable>NAME</replaceable>...|<replaceable>JOB</replaceable>...]</command></term>
-
- <listitem>
- <para>Show properties of one or more units, jobs, or the
- manager itself. If no argument is specified properties of
- the manager will be shown. If a unit name is specified
- properties of the unit is shown, and if a job id is
- specified properties of the job is shown. By default, empty
- properties are suppressed. Use <option>--all</option> to
- show those too. To select specific properties to show use
- <option>--property=</option>. This command is intended to be
- used whenever computer-parsable output is required. Use
- <command>status</command> if you are looking for formatted
- human-readable output.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>get-cgroup-attr <replaceable>NAME</replaceable> <replaceable>ATTRIBUTE</replaceable>...</command></term>
-
- <listitem>
- <para>Retrieve the specified control group attributes of the
- specified unit. Takes a unit name and one or more attribute
- names such as <literal>cpu.shares</literal>. This will
- output the current values of the specified attributes,
- separated by new-lines. For attributes that take list of
- items the output will be new-line separated, too. This
- operation will always try to retrieve the data in question
- from the kernel first, and if that is not available use the
- configured values instead. Instead of low-level control
- group attribute names high-level pretty names may be used,
- as used for unit execution environment configuration, see
- <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- for details. For example, passing
- <literal>memory.limit_in_bytes</literal> and
- <literal>MemoryLimit</literal> is equivalent.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>set-cgroup-attr <replaceable>NAME</replaceable> <replaceable>ATTRIBUTE</replaceable> <replaceable>VALUE</replaceable>...</command></term>
-
- <listitem>
- <para>Set the specified control group attribute of the
- specified unit to the specified value. Takes a unit
- name and an attribute name such as
- <literal>cpu.shares</literal>, plus one or more values
- (multiple values may only be used for attributes that take
- multiple values). This operation will immediately update the
- kernel attribute for this unit and persistently store this
- setting for later reboots (unless <option>--runtime</option>
- is passed, in which case the setting is not saved
- persistently and only valid until the next reboot.) Instead
- of low-level control group attribute names high-level pretty
- names may be used, as used for unit execution environment
- configuration, see
- <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- for details. For example, passing
- <literal>memory.limit_in_bytes</literal> and
- <literal>MemoryLimit</literal> is equivalent. This operation
- will implicitly create a control group for the unit in the
- controller the attribute belongs to, if needed. For
- attributes that take multiple values, this operation will
- append the specified values to the previously set values
- list (use <command>unset-cgroup-attr</command> to reset the
- list explicitly). For attributes that take a single value
- only the list will be reset implicitly.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>unset-cgroup-attr <replaceable>NAME</replaceable> <replaceable>ATTRIBUTE</replaceable>...</command></term>
-
- <listitem><para>Unset the specified control group attributes
- of the specified unit. Takes a unit name and one or more
- attribut names such as <literal>cpu.shares</literal>. This
- operation might or might not have an immediate effect on the
- current kernel attribute value. This will remove any
- persistently stored configuration values for this attribute
- (as set with <command>set-cgroup-attr</command> before),
- unless <option>--runtime</option> is passed, in which case the
- configuration is reset only until the next reboot. Again,
- high-level control group attributes may be used instead of the
- low-level kernel ones. For attributes which take multiple
- values, all currently set values are reset.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>set-cgroup <replaceable>NAME</replaceable> <replaceable>CGROUP</replaceable>...</command></term>
- <term><command>unset-cgroup <replaceable>NAME</replaceable> <replaceable>CGROUP</replaceable>...</command></term>
-
- <listitem><para>Add or remove a unit to/from a specific
- control group hierarchy and/or control group path. Takes a
- unit name, plus a control group specification in the syntax
- <replaceable>CONTROLLER</replaceable>:<replaceable>PATH</replaceable>
- or <replaceable>CONTROLLER</replaceable>. In the latter syntax
- (where the path is omitted) the default unit control group
- path is implied. Examples: <literal>cpu</literal> or
- <literal>cpu:/foo/bar</literal>. If a unit is removed from a
- control group hierarchy all its processes will be moved to the
- root group of the hierarchy and all control group attributes
- will be reset. These operations are immediately reflected in
- the kernel hierarchy, and stored persistently to disk (unless
- <option>--runtime</option> is passed).</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>help <replaceable>NAME</replaceable>...|<replaceable>PID</replaceable>...</command></term>
-
- <listitem>
- <para>Show manual pages for one or more units, if
- available. If a PID is passed the manual pages for the unit
- the process of the PID belongs to is
- shown.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>reset-failed [<replaceable>NAME</replaceable>...]</command></term>
-
- <listitem>
- <para>Reset the <literal>failed</literal> state of the
- specified units, or if no unit name is passed of all
- units. When a unit fails in some way (i.e. process exiting
- with non-zero error code, terminating abnormally or timing
- out) it will automatically enter the
- <literal>failed</literal> state and its exit code and status
- is recorded for introspection by the administrator until the
- service is restarted or reset with this command.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>list-unit-files</command></term>
-
- <listitem>
- <para>List installed unit files.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>enable <replaceable>NAME</replaceable>...</command></term>
-
- <listitem>
- <para>Enable one or more unit files or unit file instances,
- as specified on the command line. This will create a number
- of symlinks as encoded in the <literal>[Install]</literal>
- sections of the unit files. After the symlinks have been
- created the systemd configuration is reloaded (in a way that
- is equivalent to <command>daemon-reload</command>) to ensure
- the changes are taken into account immediately. Note that
- this does not have the effect that any of the units enabled
- are also started at the same time. If this is desired a
- separate <command>start</command> command must be invoked
- for the unit. Also note that in case of instance enablement,
- symlinks named same as instances are created in install
- location, however they all point to the same template unit
- file.</para>
-
- <para>This command will print the actions executed. This
- output may be suppressed by passing <option>--quiet</option>.
- </para>
-
- <para>Note that this operation creates only the suggested
- symlinks for the units. While this command is the
- recommended way to manipulate the unit configuration
- directory, the administrator is free to make additional
- changes manually, by placing or removing symlinks in the
- directory. This is particularly useful to create
- configurations that deviate from the suggested default
- installation. In this case the administrator must make sure
- to invoke <command>daemon-reload</command> manually as
- necessary, to ensure his changes are taken into account.
- </para>
-
- <para>Enabling units should not be confused with starting
- (activating) units, as done by the <command>start</command>
- command. Enabling and starting units is orthogonal: units
- may be enabled without being started and started without
- being enabled. Enabling simply hooks the unit into various
- suggested places (for example, so that the unit is
- automatically started on boot or when a particular kind of
- hardware is plugged in). Starting actually spawns the daemon
- process (in case of service units), or binds the socket (in
- case of socket units), and so on.</para>
-
- <para>Depending on whether <option>--system</option>,
- <option>--user</option> or <option>--global</option> is
- specified this enables the unit for the system, for the
- calling user only or for all future logins of all
- users. Note that in the last case no systemd daemon
- configuration is reloaded.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>disable <replaceable>NAME</replaceable>...</command></term>
-
- <listitem>
- <para>Disables one or more units. This removes all symlinks
- to the specified unit files from the unit configuration
- directory, and hence undoes the changes made by
- <command>enable</command>. Note however that this removes
- all symlinks to the unit files (i.e. including manual
- additions), not just those actually created by
- <command>enable</command>. This call implicitly reloads the
- systemd daemon configuration after completing the disabling
- of the units. Note that this command does not implicitly
- stop the units that are being disabled. If this is desired
- an additional <command>stop</command> command should be
- executed afterwards.</para>
-
- <para>This command will print the actions executed. This
- output may be suppressed by passing <option>--quiet</option>.
- </para>
-
- <para>This command honors <option>--system</option>,
- <option>--user</option>, <option>--global</option> in a
- similar way as <command>enable</command>.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>is-enabled <replaceable>NAME</replaceable>...</command></term>
-
- <listitem>
- <para>Checks whether any of the specified unit files are
- enabled (as with <command>enable</command>). Returns an exit
- code of 0 if at least one is enabled, non-zero
- otherwise. Prints the current enable status. To suppress
- this output use <option>--quiet</option>.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>reenable <replaceable>NAME</replaceable>...</command></term>
-
- <listitem>
- <para>Reenable one or more unit files, as specified on the
- command line. This is a combination of
- <command>disable</command> and <command>enable</command> and
- is useful to reset the symlinks a unit is enabled with to
- the defaults configured in the <literal>[Install]</literal>
- section of the unit file.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>preset <replaceable>NAME</replaceable>...</command></term>
-
- <listitem>
- <para>Reset one or more unit files, as specified on the
- command line, to the defaults configured in the preset
- policy files. This has the same effect as
- <command>disable</command> or <command>enable</command>,
- depending how the unit is listed in the preset files. For
- more information on preset policy format see
- <citerefentry><refentrytitle>systemd.preset</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
- For more information on the concept of presets please
- consult the
- <ulink url="http://freedesktop.org/wiki/Software/systemd/Preset">Preset</ulink>
- document.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>mask <replaceable>NAME</replaceable>...</command></term>
-
- <listitem>
- <para>Mask one or more unit files, as specified on the
- command line. This will link these units to
- <filename>/dev/null</filename>, making it impossible to
- start them. This is a stronger version of
- <command>disable</command>, since it prohibits all kinds of
- activation of the unit, including manual activation. Use
- this option with care.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>unmask <replaceable>NAME</replaceable>...</command></term>
-
- <listitem>
- <para>Unmask one or more unit files, as specified on the
- command line. This will undo the effect of
- <command>mask</command>.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>link <replaceable>FILENAME</replaceable>...</command></term>
-
- <listitem>
- <para>Link a unit file that is not in the unit file search
- paths into the unit file search path. This requires an
- absolute path to a unit file. The effect of this can be
- undone with <command>disable</command>. The effect of this
- command is that a unit file is available for
- <command>start</command> and other commands although it
- isn't installed directly in the unit search path.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>load <replaceable>NAME</replaceable>...</command></term>
-
- <listitem>
- <para>Load one or more units specified on the command
- line. This will simply load their configuration from disk,
- but not start them. To start them you need to use the
- <command>start</command> command which will implicitly load
- a unit that has not been loaded yet. Note that systemd
- garbage collects loaded units that are not active or
- referenced by an active unit. This means that units loaded
- this way will usually not stay loaded for long. Also note
- that this command cannot be used to reload unit
- configuration. Use the <command>daemon-reload</command>
- command for that. All in all, this command is of little use
- except for debugging.</para>
-
- <para>This command should not be confused with the
- <command>daemon-reload</command> or
- <command>reload</command>.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>list-jobs</command></term>
-
- <listitem>
- <para>List jobs that are in progress.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>cancel <replaceable>JOB</replaceable>...</command></term>
-
- <listitem>
- <para>Cancel one or more jobs specified on the command line
- by their numeric job IDs. If no job id is specified, cancel
- all pending jobs.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>dump</command></term>
-
- <listitem>
- <para>Dump server status. This will output a (usually very
- long) human readable manager status dump. Its format is
- subject to change without notice and should not be parsed by
- applications.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>list-dependencies <replaceable>NAME</replaceable></command></term>
-
- <listitem>
- <para>Shows required and wanted units of the specified
- unit. If no unit is specified
- <filename>default.target</filename> is implied. Target units
- are recursively expanded. When <option>--all</option> is
- passed all other units are recursively expanded as
- well.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>snapshot [<replaceable>NAME</replaceable>]</command></term>
-
- <listitem>
- <para>Create a snapshot. If a snapshot name is specified,
- the new snapshot will be named after it. If none is
- specified an automatic snapshot name is generated. In either
- case, the snapshot name used is printed to STDOUT, unless
- <option>--quiet</option> is specified.</para>
-
- <para>A snapshot refers to a saved state of the systemd
- manager. It is implemented itself as a unit that is
- generated dynamically with this command and has dependencies
- on all units active at the time. At a later time the user
- may return to this state by using the
- <command>isolate</command> command on the snapshot unit.
- </para>
-
- <para>Snapshots are only useful for saving and restoring
- which units are running or are stopped, they do not
- save/restore any other state. Snapshots are dynamic and lost
- on reboot.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>delete <replaceable>NAME</replaceable>...</command></term>
-
- <listitem>
- <para>Remove a snapshot previously created with
- <command>snapshot</command>.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>daemon-reload</command></term>
-
- <listitem>
- <para>Reload systemd manager configuration. This will reload
- all unit files and recreate the entire dependency
- tree. While the daemon is reloaded, all sockets systemd
- listens on on behalf of user configuration will stay
- accessible.</para> <para>This command should not be confused
- with the <command>load</command> or
- <command>reload</command> commands.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>daemon-reexec</command></term>
-
- <listitem>
- <para>Reexecute the systemd manager. This will serialize the
- manager state, reexecute the process and deserialize the
- state again. This command is of little use except for
- debugging and package upgrades. Sometimes it might be
- helpful as a heavy-weight <command>daemon-reload</command>.
- While the daemon is reexecuted all sockets systemd listens
- on on behalf of user configuration will stay accessible.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>show-environment</command></term>
-
- <listitem>
- <para>Dump the systemd manager environment block. The
- environment block will be dumped in straight-forward form
- suitable for sourcing into a shell script. This environment
- block will be passed to all processes the manager
- spawns.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>set-environment <replaceable>VARIABLE=VALUE</replaceable>...</command></term>
-
- <listitem>
- <para>Set one or more systemd manager environment variables,
- as specified on the command line.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>unset-environment <replaceable>VARIABLE</replaceable>...</command></term>
-
- <listitem>
- <para>Unset one or more systemd manager environment
- variables. If only a variable name is specified it will be
- removed regardless of its value. If a variable and a value
- are specified the variable is only removed if it has the
- specified value.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>default</command></term>
-
- <listitem>
- <para>Enter default mode. This is mostly equivalent to
- <command>isolate default.target</command>.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>rescue</command></term>
-
- <listitem>
- <para>Enter rescue mode. This is mostly equivalent to
- <command>isolate rescue.target</command> but also prints a
- wall message to all users.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>emergency</command></term>
-
- <listitem>
- <para>Enter emergency mode. This is mostly equivalent to
- <command>isolate emergency.target</command> but also prints
- a wall message to all users.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>halt</command></term>
-
- <listitem>
- <para>Shut down and halt the system. This is mostly equivalent to
- <command>start halt.target --irreversible</command> but also
- prints a wall message to all users. If combined with
- <option>--force</option> shutdown of all running services is
- skipped, however all processes are killed and all file
- systems are unmounted or mounted read-only, immediately
- followed by the system halt. If <option>--force</option> is
- specified twice the operation is immediately executed
- without terminating any processes or unmounting any file
- systems. This may result in data loss.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>poweroff</command></term>
-
- <listitem>
- <para>Shut down and power-off the system. This is mostly
- equivalent to <command>start poweroff.target --irreversible</command>
- but also prints a wall message to all users. If combined with
- <option>--force</option> shutdown of all running services is
- skipped, however all processes are killed and all file
- systems are unmounted or mounted read-only, immediately
- followed by the powering off. If <option>--force</option> is
- specified twice the operation is immediately executed
- without terminating any processes or unmounting any file
- systems. This may result in data loss.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>reboot</command></term>
-
- <listitem>
- <para>Shut down and reboot the system. This is mostly
- equivalent to <command>start reboot.target --irreversible</command>
- but also prints a wall message to all users. If combined with
- <option>--force</option> shutdown of all running services is
- skipped, however all processes are killed and all file
- systems are unmounted or mounted read-only, immediately
- followed by the reboot. If <option>--force</option> is
- specified twice the operation is immediately executed
- without terminating any processes or unmounting any file
- systems. This may result in data loss.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>kexec</command></term>
-
- <listitem>
- <para>Shut down and reboot the system via kexec. This is
- mostly equivalent to <command>start kexec.target --irreversible</command>
- but also prints a wall message to all users. If combined
- with <option>--force</option> shutdown of all running
- services is skipped, however all processes are killed and
- all file systems are unmounted or mounted read-only,
- immediately followed by the reboot.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>exit</command></term>
-
- <listitem>
- <para>Ask the systemd manager to quit. This is only
- supported for user service managers (i.e. in conjunction
- with the <option>--user</option> option) and will fail
- otherwise.</para>
- </listitem>
-
- </varlistentry>
- <varlistentry>
- <term><command>suspend</command></term>
-
- <listitem>
- <para>Suspend the system. This will trigger activation of
- the special <filename>suspend.target</filename> target.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>hibernate</command></term>
-
- <listitem>
- <para>Hibernate the system. This will trigger activation of
- the special <filename>hibernate.target</filename> target.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>hybrid-sleep</command></term>
-
- <listitem>
- <para>Hibernate and suspend the system. This will trigger
- activation of the special
- <filename>hybrid-sleep.target</filename> target.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><command>switch-root <replaceable>ROOT</replaceable> [<replaceable>INIT</replaceable>]</command></term>
-
- <listitem>
- <para>Switches to a different root directory and executes a
- new system manager process below it. This is intended for
- usage in initial RAM disks ("initrd"), and will transition
- from the initrd's system manager process (a.k.a "init"
- process) to the main system manager process. Takes two
- arguments: the directory to make the new root directory, and
- the path to the new system manager binary below it to
- execute as PID 1. If the latter is omitted or the empty
- string, a systemd binary will automatically be searched for
- and used as init. If the system manager path is omitted or
- equal to the empty string the state of the initrd's system
- manager process is passed to the main system manager, which
- allows later introspection of the state of the services
- involved in the initrd boot.</para>
- </listitem>
- </varlistentry>
- </variablelist>
+ </programlisting>
+ Note: because the addresses might contains spaces, this output
+ is not suitable for programmatic consumption.
+ </para>
+
+ <para>See also the options <option>--show-types</option>,
+ <option>--all</option>, and <option>--failed</option>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>start <replaceable>NAME</replaceable>...</command></term>
+
+ <listitem>
+ <para>Start (activate) one or more units specified on the
+ command line.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>stop <replaceable>NAME</replaceable>...</command></term>
+
+ <listitem>
+ <para>Stop (deactivate) one or more units specified on the
+ command line.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>reload <replaceable>NAME</replaceable>...</command></term>
+
+ <listitem>
+ <para>Asks all units listed on the command line to reload
+ their configuration. Note that this will reload the
+ service-specific configuration, not the unit configuration
+ file of systemd. If you want systemd to reload the
+ configuration file of a unit, use the
+ <command>daemon-reload</command> command. In other words:
+ for the example case of Apache, this will reload Apache's
+ <filename>httpd.conf</filename> in the web server, not the
+ <filename>apache.service</filename> systemd unit
+ file.</para>
+
+ <para>This command should not be confused with the
+ <command>daemon-reload</command> or <command>load</command>
+ commands.</para>
+ </listitem>
+
+ </varlistentry>
+ <varlistentry>
+ <term><command>restart <replaceable>NAME</replaceable>...</command></term>
+
+ <listitem>
+ <para>Restart one or more units specified on the command
+ line. If the units are not running yet, they will be
+ started.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>try-restart <replaceable>NAME</replaceable>...</command></term>
+
+ <listitem>
+ <para>Restart one or more units specified on the command
+ line if the units are running. This does nothing if units are not
+ running. Note that, for compatibility with Red Hat init
+ scripts, <command>condrestart</command> is equivalent to this
+ command.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>reload-or-restart <replaceable>NAME</replaceable>...</command></term>
+
+ <listitem>
+ <para>Reload one or more units if they support it. If not,
+ restart them instead. If the units are not running yet, they
+ will be started.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>reload-or-try-restart <replaceable>NAME</replaceable>...</command></term>
+
+ <listitem>
+ <para>Reload one or more units if they support it. If not,
+ restart them instead. This does nothing if the units are not
+ running. Note that, for compatibility with SysV init scripts,
+ <command>force-reload</command> is equivalent to this
+ command.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>isolate <replaceable>NAME</replaceable></command></term>
+
+ <listitem>
+ <para>Start the unit specified on the command line and its
+ dependencies and stop all others.</para>
+
+ <para>This is similar to changing the runlevel in a
+ traditional init system. The <command>isolate</command>
+ command will immediately stop processes that are not enabled
+ in the new unit, possibly including the graphical
+ environment or terminal you are currently using.</para>
+
+ <para>Note that this is allowed only on units where
+ <option>AllowIsolate=</option> is enabled. See
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for details.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>kill <replaceable>NAME</replaceable>...</command></term>
+
+ <listitem>
+ <para>Send a signal to one or more processes of the
+ unit. Use <option>--kill-who=</option> to select which
+ process to kill. Use <option>--kill-mode=</option> to select
+ the kill mode and <option>--signal=</option> to select the
+ signal to send.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>is-active <replaceable>NAME</replaceable>...</command></term>
+
+ <listitem>
+ <para>Check whether any of the specified units are active
+ (i.e. running). Returns an exit code 0 if at least one is
+ active, non-zero otherwise. Unless <option>--quiet</option>
+ is specified, this will also print the current unit state to
+ STDOUT.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>is-failed <replaceable>NAME</replaceable>...</command></term>
+
+ <listitem>
+ <para>Check whether any of the specified units are in a "failed" state.
+ Returns an exit code 0 if at least one has failed, non-zero
+ otherwise. Unless <option>--quiet</option> is specified, this
+ will also print the current unit state to
+ STDOUT.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>status [<replaceable>NAME</replaceable>...|<replaceable>PID</replaceable>...]</command></term>
+
+ <listitem>
+ <para>Show terse runtime status information about one or
+ more units, followed by most recent log data from the
+ journal. If no units are specified, show all units (subject
+ to limitations specified with <option>-t</option>). If a PID
+ is passed, show information about the unit the process
+ belongs to.</para>
+
+ <para>This function is intended to generate human-readable
+ output. If you are looking for computer-parsable output, use
+ <command>show</command> instead.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>show [<replaceable>NAME</replaceable>...|<replaceable>JOB</replaceable>...]</command></term>
+
+ <listitem>
+ <para>Show properties of one or more units, jobs, or the
+ manager itself. If no argument is specified, properties of
+ the manager will be shown. If a unit name is specified,
+ properties of the unit is shown, and if a job id is
+ specified, properties of the job is shown. By default, empty
+ properties are suppressed. Use <option>--all</option> to
+ show those too. To select specific properties to show, use
+ <option>--property=</option>. This command is intended to be
+ used whenever computer-parsable output is required. Use
+ <command>status</command> if you are looking for formatted
+ human-readable output.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>set-property <replaceable>NAME</replaceable> <replaceable>ASSIGNMENT</replaceable>...</command></term>
+
+ <listitem>
+ <para>Set the specified unit properties at runtime where
+ this is supported. This allows changing configuration
+ parameter properties such as resource control settings at
+ runtime. Not all properties may be changed at runtime, but
+ many resource control settings (primarily those in
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>)
+ may. The changes are applied instantly, and stored on disk
+ for future boots, unless <option>--runtime</option> is
+ passed, in which case the settings only apply until the
+ next reboot. The syntax of the property assignment follows
+ closely the syntax of assignments in unit files.</para>
+
+ <para>Example: <command>systemctl set-property foobar.service CPUShares=777</command></para>
+
+ <para>Note that this command allows changing multiple
+ properties at the same time, which is preferable over
+ setting them individually. Like unit file configuration
+ settings, assigning the empty list to list parameters will
+ reset the list.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>help <replaceable>NAME</replaceable>...|<replaceable>PID</replaceable>...</command></term>
+
+ <listitem>
+ <para>Show manual pages for one or more units, if
+ available. If a PID is given, the manual pages for the unit
+ the process belongs to are shown.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>reset-failed [<replaceable>NAME</replaceable>...]</command></term>
+
+ <listitem>
+ <para>Reset the <literal>failed</literal> state of the
+ specified units, or if no unit name is passed, reset the state of all
+ units. When a unit fails in some way (i.e. process exiting
+ with non-zero error code, terminating abnormally or timing
+ out), it will automatically enter the
+ <literal>failed</literal> state and its exit code and status
+ is recorded for introspection by the administrator until the
+ service is restarted or reset with this command.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>list-dependencies <replaceable>NAME</replaceable></command></term>
+
+ <listitem>
+ <para>Shows required and wanted units of the specified
+ unit. If no unit is specified,
+ <filename>default.target</filename> is implied. Target units
+ are recursively expanded. When <option>--all</option> is
+ passed, all other units are recursively expanded as
+ well.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect2>
+
+ <refsect2>
+ <title>Unit File Commands</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><command>list-unit-files</command></term>
+
+ <listitem>
+ <para>List installed unit files.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>enable <replaceable>NAME</replaceable>...</command></term>
+
+ <listitem>
+ <para>Enable one or more unit files or unit file instances,
+ as specified on the command line. This will create a number
+ of symlinks as encoded in the <literal>[Install]</literal>
+ sections of the unit files. After the symlinks have been
+ created, the systemd configuration is reloaded (in a way that
+ is equivalent to <command>daemon-reload</command>) to ensure
+ the changes are taken into account immediately. Note that
+ this does <emphasis>not</emphasis> have the effect of also
+ starting any of the units being enabled. If this
+ is desired, a separate <command>start</command> command must
+ be invoked for the unit. Also note that in case of instance
+ enablement, symlinks named the same as instances are created in
+ the install location, however they all point to the same
+ template unit file.</para>
+
+ <para>This command will print the actions executed. This
+ output may be suppressed by passing <option>--quiet</option>.
+ </para>
+
+ <para>Note that this operation creates only the suggested
+ symlinks for the units. While this command is the
+ recommended way to manipulate the unit configuration
+ directory, the administrator is free to make additional
+ changes manually by placing or removing symlinks in the
+ directory. This is particularly useful to create
+ configurations that deviate from the suggested default
+ installation. In this case, the administrator must make sure
+ to invoke <command>daemon-reload</command> manually as
+ necessary to ensure the changes are taken into account.
+ </para>
+
+ <para>Enabling units should not be confused with starting
+ (activating) units, as done by the <command>start</command>
+ command. Enabling and starting units is orthogonal: units
+ may be enabled without being started and started without
+ being enabled. Enabling simply hooks the unit into various
+ suggested places (for example, so that the unit is
+ automatically started on boot or when a particular kind of
+ hardware is plugged in). Starting actually spawns the daemon
+ process (in case of service units), or binds the socket (in
+ case of socket units), and so on.</para>
+
+ <para>Depending on whether <option>--system</option>,
+ <option>--user</option>, <option>--runtime</option>,
+ or<option>--global</option>, is specified, this enables the unit
+ for the system, for the calling user only, for only this boot of
+ the system, or for all future logins of all users, or only this
+ boot. Note that in the last case, no systemd daemon
+ configuration is reloaded.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>disable <replaceable>NAME</replaceable>...</command></term>
+
+ <listitem>
+ <para>Disables one or more units. This removes all symlinks
+ to the specified unit files from the unit configuration
+ directory, and hence undoes the changes made by
+ <command>enable</command>. Note however that this removes
+ all symlinks to the unit files (i.e. including manual
+ additions), not just those actually created by
+ <command>enable</command>. This call implicitly reloads the
+ systemd daemon configuration after completing the disabling
+ of the units. Note that this command does not implicitly
+ stop the units that are being disabled. If this is desired,
+ an additional <command>stop</command> command should be
+ executed afterwards.</para>
+
+ <para>This command will print the actions executed. This
+ output may be suppressed by passing <option>--quiet</option>.
+ </para>
+
+ <para>This command honors <option>--system</option>,
+ <option>--user</option>, <option>--runtime</option>,
+ <option>--global</option> in a similar way as
+ <command>enable</command>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>is-enabled <replaceable>NAME</replaceable>...</command></term>
+
+ <listitem>
+ <para>Checks whether any of the specified unit files are
+ enabled (as with <command>enable</command>). Returns an exit
+ code of 0 if at least one is enabled, non-zero
+ otherwise. Prints the current enable status. To suppress
+ this output, use <option>--quiet</option>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>reenable <replaceable>NAME</replaceable>...</command></term>
+
+ <listitem>
+ <para>Reenable one or more unit files, as specified on the
+ command line. This is a combination of
+ <command>disable</command> and <command>enable</command> and
+ is useful to reset the symlinks a unit is enabled with to
+ the defaults configured in the <literal>[Install]</literal>
+ section of the unit file.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>preset <replaceable>NAME</replaceable>...</command></term>
+
+ <listitem>
+ <para>Reset one or more unit files, as specified on the
+ command line, to the defaults configured in the preset
+ policy files. This has the same effect as
+ <command>disable</command> or <command>enable</command>,
+ depending how the unit is listed in the preset files. For
+ more information on the preset policy format, see
+ <citerefentry><refentrytitle>systemd.preset</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ For more information on the concept of presets, please
+ consult the
+ <ulink url="http://freedesktop.org/wiki/Software/systemd/Preset">Preset</ulink>
+ document.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>mask <replaceable>NAME</replaceable>...</command></term>
+
+ <listitem>
+ <para>Mask one or more unit files, as specified on the
+ command line. This will link these units to
+ <filename>/dev/null</filename>, making it impossible to
+ start them. This is a stronger version of
+ <command>disable</command>, since it prohibits all kinds of
+ activation of the unit, including manual activation. Use
+ this option with care. This honors the
+ <option>--runtime</option> option, to only mask temporarily
+ until the next reoobt of the system.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>unmask <replaceable>NAME</replaceable>...</command></term>
+
+ <listitem>
+ <para>Unmask one or more unit files, as specified on the
+ command line. This will undo the effect of
+ <command>mask</command>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>link <replaceable>FILENAME</replaceable>...</command></term>
+
+ <listitem>
+ <para>Link a unit file that is not in the unit file search
+ paths into the unit file search path. This requires an
+ absolute path to a unit file. The effect of this can be
+ undone with <command>disable</command>. The effect of this
+ command is that a unit file is available for
+ <command>start</command> and other commands although it
+ is not installed directly in the unit search path.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>get-default</command></term>
+
+ <listitem>
+ <para>Get the default target specified
+ via <filename>default.target</filename> link.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>set-default <replaceable>NAME</replaceable></command></term>
+
+ <listitem>
+ <para>Set the default target to boot into. Command links
+ <filename>default.target</filename> to the given unit.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect2>
+
+ <refsect2>
+ <title>Job Commands</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><command>list-jobs</command></term>
+
+ <listitem>
+ <para>List jobs that are in progress.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>cancel <replaceable>JOB</replaceable>...</command></term>
+
+ <listitem>
+ <para>Cancel one or more jobs specified on the command line
+ by their numeric job IDs. If no job ID is specified, cancel
+ all pending jobs.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect2>
+
+ <refsect2>
+ <title>Snapshot Commands</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><command>snapshot [<replaceable>NAME</replaceable>]</command></term>
+
+ <listitem>
+ <para>Create a snapshot. If a snapshot name is specified,
+ the new snapshot will be named after it. If none is
+ specified, an automatic snapshot name is generated. In either
+ case, the snapshot name used is printed to STDOUT, unless
+ <option>--quiet</option> is specified.</para>
+
+ <para>A snapshot refers to a saved state of the systemd
+ manager. It is implemented itself as a unit that is
+ generated dynamically with this command and has dependencies
+ on all units active at the time. At a later time, the user
+ may return to this state by using the
+ <command>isolate</command> command on the snapshot unit.
+ </para>
+
+ <para>Snapshots are only useful for saving and restoring
+ which units are running or are stopped, they do not
+ save/restore any other state. Snapshots are dynamic and lost
+ on reboot.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>delete <replaceable>NAME</replaceable>...</command></term>
+
+ <listitem>
+ <para>Remove a snapshot previously created with
+ <command>snapshot</command>.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect2>
+
+ <refsect2>
+ <title>Environment Commands</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><command>show-environment</command></term>
+
+ <listitem>
+ <para>Dump the systemd manager environment block. The
+ environment block will be dumped in straight-forward form
+ suitable for sourcing into a shell script. This environment
+ block will be passed to all processes the manager
+ spawns.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>set-environment <replaceable>VARIABLE=VALUE</replaceable>...</command></term>
+
+ <listitem>
+ <para>Set one or more systemd manager environment variables,
+ as specified on the command line.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>unset-environment <replaceable>VARIABLE</replaceable>...</command></term>
+
+ <listitem>
+ <para>Unset one or more systemd manager environment
+ variables. If only a variable name is specified, it will be
+ removed regardless of its value. If a variable and a value
+ are specified, the variable is only removed if it has the
+ specified value.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect2>
+
+ <refsect2>
+ <title>Manager Lifecycle Commands</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><command>daemon-reload</command></term>
+
+ <listitem>
+ <para>Reload systemd manager configuration. This will reload
+ all unit files and recreate the entire dependency
+ tree. While the daemon is being reloaded, all sockets systemd
+ listens on on behalf of user configuration will stay
+ accessible.</para> <para>This command should not be confused
+ with the <command>load</command> or
+ <command>reload</command> commands.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>daemon-reexec</command></term>
+
+ <listitem>
+ <para>Reexecute the systemd manager. This will serialize the
+ manager state, reexecute the process and deserialize the
+ state again. This command is of little use except for
+ debugging and package upgrades. Sometimes, it might be
+ helpful as a heavy-weight <command>daemon-reload</command>.
+ While the daemon is being reexecuted, all sockets systemd listening
+ on behalf of user configuration will stay accessible.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect2>
+
+ <refsect2>
+ <title>System Commands</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><command>default</command></term>
+
+ <listitem>
+ <para>Enter default mode. This is mostly equivalent to
+ <command>isolate default.target</command>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>rescue</command></term>
+
+ <listitem>
+ <para>Enter rescue mode. This is mostly equivalent to
+ <command>isolate rescue.target</command>, but also prints a
+ wall message to all users.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>emergency</command></term>
+
+ <listitem>
+ <para>Enter emergency mode. This is mostly equivalent to
+ <command>isolate emergency.target</command>, but also prints
+ a wall message to all users.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>halt</command></term>
+
+ <listitem>
+ <para>Shut down and halt the system. This is mostly equivalent to
+ <command>start halt.target --irreversible</command>, but also
+ prints a wall message to all users. If combined with
+ <option>--force</option>, shutdown of all running services is
+ skipped, however all processes are killed and all file
+ systems are unmounted or mounted read-only, immediately
+ followed by the system halt. If <option>--force</option> is
+ specified twice, the operation is immediately executed
+ without terminating any processes or unmounting any file
+ systems. This may result in data loss.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>poweroff</command></term>
+
+ <listitem>
+ <para>Shut down and power-off the system. This is mostly
+ equivalent to <command>start poweroff.target --irreversible</command>,
+ but also prints a wall message to all users. If combined with
+ <option>--force</option>, shutdown of all running services is
+ skipped, however all processes are killed and all file
+ systems are unmounted or mounted read-only, immediately
+ followed by the powering off. If <option>--force</option> is
+ specified twice, the operation is immediately executed
+ without terminating any processes or unmounting any file
+ systems. This may result in data loss.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>reboot</command></term>
+
+ <listitem>
+ <para>Shut down and reboot the system. This is mostly
+ equivalent to <command>start reboot.target --irreversible</command>,
+ but also prints a wall message to all users. If combined with
+ <option>--force</option>, shutdown of all running services is
+ skipped, however all processes are killed and all file
+ systems are unmounted or mounted read-only, immediately
+ followed by the reboot. If <option>--force</option> is
+ specified twice, the operation is immediately executed
+ without terminating any processes or unmounting any file
+ systems. This may result in data loss.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>kexec</command></term>
+
+ <listitem>
+ <para>Shut down and reboot the system via kexec. This is
+ mostly equivalent to <command>start kexec.target --irreversible</command>,
+ but also prints a wall message to all users. If combined
+ with <option>--force</option>, shutdown of all running
+ services is skipped, however all processes are killed and
+ all file systems are unmounted or mounted read-only,
+ immediately followed by the reboot.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>exit</command></term>
+
+ <listitem>
+ <para>Ask the systemd manager to quit. This is only
+ supported for user service managers (i.e. in conjunction
+ with the <option>--user</option> option) and will fail
+ otherwise.</para>
+ </listitem>
+
+ </varlistentry>
+ <varlistentry>
+ <term><command>suspend</command></term>
+
+ <listitem>
+ <para>Suspend the system. This will trigger activation of
+ the special <filename>suspend.target</filename> target.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>hibernate</command></term>
+
+ <listitem>
+ <para>Hibernate the system. This will trigger activation of
+ the special <filename>hibernate.target</filename> target.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>hybrid-sleep</command></term>
+
+ <listitem>
+ <para>Hibernate and suspend the system. This will trigger
+ activation of the special
+ <filename>hybrid-sleep.target</filename> target.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>switch-root <replaceable>ROOT</replaceable> [<replaceable>INIT</replaceable>]</command></term>
+
+ <listitem>
+ <para>Switches to a different root directory and executes a
+ new system manager process below it. This is intended for
+ usage in initial RAM disks ("initrd"), and will transition
+ from the initrd's system manager process (a.k.a "init"
+ process) to the main system manager process. This call takes two
+ arguments: the directory that is to become the new root directory, and
+ the path to the new system manager binary below it to
+ execute as PID 1. If the latter is omitted or the empty
+ string, a systemd binary will automatically be searched for
+ and used as init. If the system manager path is omitted or
+ equal to the empty string, the state of the initrd's system
+ manager process is passed to the main system manager, which
+ allows later introspection of the state of the services
+ involved in the initrd boot.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect2>
</refsect1>
<refsect1>
<title>Exit status</title>
- <para>On success 0 is returned, a non-zero failure
+ <para>On success, 0 is returned, a non-zero failure
code otherwise.</para>
</refsect1>
@@ -1328,6 +1290,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>loginctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.resource-management</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>wall</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.preset</refentrytitle><manvolnum>5</manvolnum></citerefentry>
diff --git a/man/systemd-activate.xml b/man/systemd-activate.xml
index b62cf44ec4..d48774d9d6 100644
--- a/man/systemd-activate.xml
+++ b/man/systemd-activate.xml
@@ -123,8 +123,8 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
<listitem><para>Add this variable to the environment of the
launched process. If <replaceable>VAR</replaceable> is
- followed by <literal>=</literal> assume that it is a
- variable–value pair. Otherwise obtain the value from the
+ followed by <literal>=</literal>, assume that it is a
+ variable–value pair. Otherwise, obtain the value from the
environment of <command>systemd-activate</command> itself.
</para></listitem>
</varlistentry>
diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml
index ae45bfcf31..aefbfc8af7 100644
--- a/man/systemd-analyze.xml
+++ b/man/systemd-analyze.xml
@@ -55,19 +55,44 @@
<refsynopsisdiv>
<cmdsynopsis>
- <command>systemd-analyze <arg choice="opt" rep="repeat">OPTIONS</arg> time</command>
+ <command>systemd-analyze</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg>time</arg>
</cmdsynopsis>
<cmdsynopsis>
- <command>systemd-analyze <arg choice="opt" rep="repeat">OPTIONS</arg> blame </command>
+ <command>systemd-analyze</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="plain">blame</arg>
</cmdsynopsis>
<cmdsynopsis>
- <command>systemd-analyze <arg choice="opt" rep="repeat">OPTIONS</arg> critical-chain </command>
+ <command>systemd-analyze</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="plain">critical-chain</arg>
+ <arg choice="opt" rep="repeat"><replaceable>UNIT</replaceable></arg>
</cmdsynopsis>
<cmdsynopsis>
- <command>systemd-analyze <arg choice="opt" rep="repeat">OPTIONS</arg> plot <arg choice="opt">&gt; file.svg</arg></command>
+ <command>systemd-analyze</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="plain">plot</arg>
+ <arg choice="opt">&gt; file.svg</arg>
</cmdsynopsis>
<cmdsynopsis>
- <command>systemd-analyze <arg choice="opt" rep="repeat">OPTIONS</arg> dot <arg choice="opt">pattern...</arg> </command>
+ <command>systemd-analyze</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="plain">dot</arg>
+ <arg choice="opt" rep="repeat"><replaceable>PATTERN</replaceable></arg>
+ <arg choice="opt">&gt; file.dot</arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+ <command>systemd-analyze</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="plain">dump</arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+ <command>systemd-analyze</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="plain">set-log-level</arg>
+ <arg choice="opt"><replaceable>LEVEL</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
@@ -75,14 +100,15 @@
<title>Description</title>
<para><command>systemd-analyze</command> may be used
- to determine system boot-up performance of the current
- boot.</para>
+ to determine system boot-up performance statistics and
+ retrieve other state and tracing information from the
+ system and service manager.</para>
<para><command>systemd-analyze time</command>
prints the time spent in the kernel before
userspace has been reached, the time spent in the
initial RAM disk (initrd) before normal system
- userspace has been reached and the time normal system
+ userspace has been reached, and the time normal system
userspace took to initialize. Note that these
measurements simply measure the time passed up to the
point where all system services have been spawned, but
@@ -97,8 +123,10 @@
be slow simply because it waits for the initialization
of another service to complete.</para>
- <para><command>systemd-analyze critical-chain</command>
- prints a tree of the time critical chain of units.
+ <para><command>systemd-analyze critical-chain [<replaceable>UNIT...</replaceable>]</command>
+ prints a tree of the time-critical chain of units
+ (for each of the specified <replaceable>UNIT</replaceable>s
+ or for the default target otherwise).
The time after the unit is active or started is printed
after the "@" character. The time the unit takes to
start is printed after the "+" character.
@@ -112,7 +140,7 @@
been started at what time, highlighting the time they
spent on initialization.</para>
- <para><command>systemd-analyze dot</command> Generate
+ <para><command>systemd-analyze dot</command> generates
textual dependency graph description in dot format for
further processing with the GraphViz
<citerefentry><refentrytitle>dot</refentrytitle><manvolnum>1</manvolnum></citerefentry>
@@ -120,7 +148,7 @@
dot | dot -Tsvg > systemd.svg</command> to generate a
graphical dependency tree. Unless
<option>--order</option> or <option>--require</option>
- is passed the generated graph will show both ordering
+ is passed, the generated graph will show both ordering
and requirement dependencies. Optional pattern
globbing style specifications
(e.g. <filename>*.target</filename>) may be given at
@@ -128,7 +156,21 @@
any of these patterns match either the origin or
destination node.</para>
- <para>If no command is passed <command>systemd-analyze
+ <para><command>systemd-analyze dump</command> outputs
+ a (usually very long) human-readable serialization of
+ the complete server state. Its format is subject to
+ change without notice and should not be parsed by
+ applications.</para>
+
+ <para><command>systemd-analyze set-log-level
+ <replaceable>LEVEL</replaceable></command> changes the
+ current log level of the <command>systemd</command>
+ daemon to <replaceable>LEVEL</replaceable> (accepts
+ the same values as <option>--log-level=</option>
+ described in
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>).</para>
+
+ <para>If no command is passed, <command>systemd-analyze
time</command> is implied.</para>
</refsect1>
@@ -164,19 +206,19 @@
<command>dot</command> command (see
above), selects which dependencies are
shown in the dependency graph. If
- <option>--order</option> is passed
+ <option>--order</option> is passed,
only dependencies of type
<varname>After=</varname> or
<varname>Before=</varname> are
shown. If <option>--require</option>
- is passed only dependencies of type
+ is passed, only dependencies of type
<varname>Requires=</varname>,
<varname>RequiresOverridable=</varname>,
<varname>Requisite=</varname>,
<varname>RequisiteOverridable=</varname>,
<varname>Wants=</varname> and
<varname>Conflicts=</varname> are
- shown. If neither is passed, shows
+ shown. If neither is passed, this shows
dependencies of all these
types.</para></listitem>
</varlistentry>
@@ -188,16 +230,16 @@
<listitem><para>When used in
conjunction with the
<command>dot</command> command (see
- above), selects which relationships
+ above), this selects which relationships
are shown in the dependency graph.
They both require
<citerefentry><refentrytitle>glob</refentrytitle><manvolnum>7</manvolnum></citerefentry>
patterns as arguments, which are
- matched against lefthand and
- righthand, respectively, nodes of a
+ matched against left-hand and
+ right-hand, respectively, nodes of a
relationship. Each of these can be
- used more than once which means a
- unit name must match one of given
+ used more than once, which means a
+ unit name must match one of the given
values.</para></listitem>
</varlistentry>
@@ -211,7 +253,15 @@
latest unit in the same level. The unit of
<replaceable>timespan</replaceable> is seconds
unless specified with a different unit,
- i.e. "50ms".</para></listitem>
+ e.g. "50ms".</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--no-pager</option></term>
+
+ <listitem>
+ <para>Do not pipe output into a pager.</para>
+ </listitem>
</varlistentry>
</variablelist>
@@ -228,20 +278,38 @@
<title>Examples</title>
<para>This plots all dependencies of any unit whose
- name starts with "<literal>avahi-daemon.</literal>":</para>
+ name starts with <literal>avahi-daemon.</literal>:</para>
<programlisting>$ systemd-analyze dot 'avahi-daemon.*' | dot -Tsvg > avahi.svg
$ eog avahi.svg</programlisting>
<para>This plots the dependencies between all known target units:</para>
- <programlisting>systemd-analyze dot --to-pattern='*.target' --from-patter='*.target' | dot -Tsvg > targets.svg
+ <programlisting>systemd-analyze dot --to-pattern='*.target' --from-pattern='*.target' | dot -Tsvg > targets.svg
$ eog targets.svg</programlisting>
</refsect1>
<refsect1>
+ <title>Environment</title>
+
+ <variablelist class='environment-variables'>
+ <varlistentry>
+ <term><varname>$SYSTEMD_PAGER</varname></term>
+
+ <listitem>
+ <para>Pager to use when <option>--no-pager</option> is not
+ given; overrides <varname>$PAGER</varname>. Setting this to
+ an empty string or the value <literal>cat</literal> is
+ equivalent to passing
+ <option>--no-pager</option>.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
diff --git a/man/systemd-ask-password.xml b/man/systemd-ask-password.xml
index 563f9d5d61..8af328dcfa 100644
--- a/man/systemd-ask-password.xml
+++ b/man/systemd-ask-password.xml
@@ -90,7 +90,7 @@
url="http://www.freedesktop.org/wiki/Software/systemd/PasswordAgents">systemd
Password Agent Specification</ulink>.</para>
- <para>If a password is queried on a TTY the user may
+ <para>If a password is queried on a TTY, the user may
press TAB to hide the asterisks normally shown for
each character typed. Pressing Backspace as first key
achieves the same effect.</para>
@@ -145,7 +145,7 @@
<varlistentry>
<term><option>--accept-cached</option></term>
- <listitem><para>If passed accept
+ <listitem><para>If passed, accept
cached passwords, i.e. passwords
previously typed in.</para></listitem>
</varlistentry>
diff --git a/man/systemd-backlight@.service.xml b/man/systemd-backlight@.service.xml
new file mode 100644
index 0000000000..2b73625e91
--- /dev/null
+++ b/man/systemd-backlight@.service.xml
@@ -0,0 +1,73 @@
+<?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">
+<!--
+ 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/>.
+-->
+<refentry id="systemd-backlight@.service" conditional='ENABLE_BACKLIGHT'>
+
+ <refentryinfo>
+ <title>systemd-backlight@.service</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>systemd-backlight@.service</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>systemd-backlight@.service</refname>
+ <refname>systemd-backlight</refname>
+ <refpurpose>Load and save the display backlight brightness at boot and shutdown</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <para><filename>systemd-backlight@.service</filename></para>
+ <para><filename>/usr/lib/systemd/systemd-backlight</filename></para>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><filename>systemd-backlight@.service</filename>
+ is a service that restores the display backlight
+ brightness at early-boot and saves it at shutdown. On
+ disk, the backlight brightness is stored in
+ <filename>/var/lib/backlight/</filename>. Note that by
+ default, only firmware backlight devices are
+ saved/restored.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/systemd-bootchart.xml b/man/systemd-bootchart.xml
index 8de4c69a2d..ae432b563f 100644
--- a/man/systemd-bootchart.xml
+++ b/man/systemd-bootchart.xml
@@ -203,7 +203,7 @@
<varlistentry>
<term><option>-o</option></term>
<term><option>--output <replaceable>path</replaceable></option></term>
- <listitem><para>Specify the output folder for the
+ <listitem><para>Specify the output directory for the
graphs. By default, bootchart writes the graphs to
<filename>/run/log</filename>.</para></listitem>
</varlistentry>
diff --git a/man/systemd-cat.xml b/man/systemd-cat.xml
index 876ebfa3cc..ffb1dfd50b 100644
--- a/man/systemd-cat.xml
+++ b/man/systemd-cat.xml
@@ -65,11 +65,11 @@
pass the output the previous pipeline element
generates to the journal.</para>
- <para>If no parameter is passed
+ <para>If no parameter is passed,
<command>systemd-cat</command> will write
everything it reads from standard input (STDIN) to the journal.</para>
- <para>If parameters are passed they are executed as
+ <para>If parameters are passed, they are executed as
command line with standard output (STDOUT) and standard
error output (STDERR) connected to the journal, so
that all it writes is stored in the journal.</para>
@@ -102,7 +102,7 @@
<listitem><para>Specify a short string
that is used to identify the logging
- tool. If not specified no identifying
+ tool. If not specified, no identification
string is written to the journal.</para></listitem>
</varlistentry>
@@ -141,7 +141,7 @@
<listitem><para>Controls whether lines
read are parsed for syslog priority
level prefixes. If enabled (the
- default) a line prefixed with a
+ default), a line prefixed with a
priority prefix such as
<literal>&lt;5&gt;</literal> is logged
at priority 5
diff --git a/man/systemd-cgls.xml b/man/systemd-cgls.xml
index 6249d05a8c..432706bcbc 100644
--- a/man/systemd-cgls.xml
+++ b/man/systemd-cgls.xml
@@ -60,19 +60,19 @@
<para><command>systemd-cgls</command> recursively
shows the contents of the selected Linux control group
- hierarchy in a tree. If arguments are specified shows
+ hierarchy in a tree. If arguments are specified, shows
all member processes of the specified control groups
plus all their subgroups and their members. The
control groups may either be specified by their full
file paths or are assumed in the systemd control group
hierarchy. If no argument is specified and the current
working directory is beneath the control group mount
- point <filename>/sys/fs/cgroup</filename> shows the contents
+ point <filename>/sys/fs/cgroup</filename>, shows the contents
of the control group the working directory refers
- to. Otherwise the full systemd control group hierarchy
+ to. Otherwise, the full systemd control group hierarchy
is shown.</para>
- <para>By default empty control groups are not
+ <para>By default, empty control groups are not
shown.</para>
</refsect1>
@@ -107,16 +107,17 @@
<varlistentry>
<term><option>--all</option></term>
- <listitem><para>Don't hide empty
+ <listitem><para>Do not hide empty
control groups in the
output.</para></listitem>
</varlistentry>
<varlistentry>
+ <term><option>-l</option></term>
<term><option>--full</option></term>
- <listitem><para>Do not ellipsize cgroup
- members.</para>
+ <listitem><para>Do not ellipsize
+ process tree members.</para>
</listitem>
</varlistentry>
@@ -131,7 +132,7 @@
<term><option>-m <replaceable>MACHINE</replaceable></option></term>
<term><option>--machine=<replaceable>MACHINE</replaceable></option></term>
- <listitem><para>Limit cgroups shown to
+ <listitem><para>Limit control groups shown to
the part corresponding to the
container <replaceable>MACHINE</replaceable>.
</para></listitem>
diff --git a/man/systemd-cgtop.xml b/man/systemd-cgtop.xml
index e765172234..7faedfbfdb 100644
--- a/man/systemd-cgtop.xml
+++ b/man/systemd-cgtop.xml
@@ -73,30 +73,23 @@
only accounted for control groups in the
<literal>cpuacct</literal> hierarchy, memory usage
only for those in <literal>memory</literal> and disk
- I/O usage for those in
- <literal>blkio</literal>. <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- by default places all services in their own control
- group in the <literal>cpuacct</literal> hierarchy, but
- not in <literal>memory</literal> nor
- <literal>blkio</literal>. If resource monitoring for
- these resources is required it is recommended to add
- <literal>blkio</literal> and <literal>memory</literal>
- to the <varname>DefaultControllers=</varname> setting
- in <filename>/etc/systemd/system.conf</filename> (see
- <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- for details). Alternatively, it is possible to enable
- resource accounting individually for services, by
- making use of the <varname>ControlGroup=</varname>
- option in the unit files (See
- <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ I/O usage for those in <literal>blkio</literal>. If
+ resource monitoring for these resources is required,
+ it is recommended to add the
+ <varname>CPUAccounting=1</varname>,
+ <varname>MemoryAccounting=1</varname> and
+ <varname>BlockIOAccounting=1</varname> settings in the
+ unit files in question (See
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details).</para>
<para>To emphasize this: unless
- <literal>blkio</literal> and <literal>memory</literal>
- are enabled for the services in question with either
- of the options suggested above no resource accounting
- will be available for system services and the data shown
- by <command>systemd-cgtop</command> will be
+ <literal>CPUAccounting=1</literal>,
+ <literal>MemoryAccounting=1</literal> and
+ <literal>BlockIOAccounting=1</literal> are enabled for
+ the services in question no resource accounting will
+ be available for system services and the data shown by
+ <command>systemd-cgtop</command> will be
incomplete.</para>
</refsect1>
@@ -197,8 +190,8 @@
tree traversal depth. Specifies how
deep <command>systemd-cgtop</command>
shall traverse the control group
- hierarchies. If 0 is specified only
- the root group is monitored, for 1
+ hierarchies. If 0 is specified, only
+ the root group is monitored. For 1,
only the first level of control groups
is monitored, and so on. Defaults to
3.</para></listitem>
@@ -281,6 +274,7 @@
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-cgls</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>top</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/systemd-coredumpctl.xml b/man/systemd-coredumpctl.xml
index 02b688606c..9ccb67d12d 100644
--- a/man/systemd-coredumpctl.xml
+++ b/man/systemd-coredumpctl.xml
@@ -202,8 +202,8 @@
<title>Exit status</title>
<para>On success 0 is returned, a non-zero failure
code otherwise. Not finding any matching coredumps is treated
- as failure.
- </para>
+ as failure.
+ </para>
</refsect1>
<refsect1>
diff --git a/man/systemd-cryptsetup-generator.xml b/man/systemd-cryptsetup-generator.xml
index 7950032941..d6b7e49f13 100644
--- a/man/systemd-cryptsetup-generator.xml
+++ b/man/systemd-cryptsetup-generator.xml
@@ -80,7 +80,7 @@
<listitem><para>Takes a boolean
argument. Defaults to
<literal>yes</literal>. If
- <literal>no</literal> disables the
+ <literal>no</literal>, disables the
generator
entirely. <varname>rd.luks=</varname>
is honored only by initial RAM disk
@@ -97,7 +97,7 @@
<listitem><para>Takes a boolean
argument. Defaults to
<literal>yes</literal>. If
- <literal>no</literal> causes the
+ <literal>no</literal>, causes the
generator to ignore any devices
configured in
<filename>/etc/crypttab</filename>
@@ -137,6 +137,29 @@
will be activated in the initrd or the real root.</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><varname>luks.options=</varname></term>
+ <term><varname>rd.luks.options=</varname></term>
+
+ <listitem><para>Takes a LUKS super
+ block UUID followed by an '=' and a string
+ of options separated by commas as argument.
+ This will override the options for the given
+ UUID.</para>
+ <para>If only a list of options, without an
+ UUID, is specified, they apply to any UUIDs not
+ specified elsewhere, and without an entry in
+ /etc/crypttab.</para><para>
+ <varname>rd.luks.options=</varname>
+ is honored only by initial RAM disk
+ (initrd) while
+ <varname>luks.options=</varname> is
+ honored by both the main system and
+ the initrd.</para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>luks.key=</varname></term>
<term><varname>rd.luks.key=</varname></term>
diff --git a/man/systemd-delta.xml b/man/systemd-delta.xml
index 9293c9b462..413ebd8de8 100644
--- a/man/systemd-delta.xml
+++ b/man/systemd-delta.xml
@@ -141,6 +141,13 @@
</varlistentry>
<varlistentry>
+ <term><varname>extended</varname></term>
+
+ <listitem><para>Show *.conf files in drop-in
+ directories for units.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>unchanged</varname></term>
<listitem><para>Show unmodified
@@ -156,7 +163,7 @@
<listitem><para>When showing modified
files, when a file is overridden show a
diff as well. This option takes a
- boolean argument. If omitted it defaults
+ boolean argument. If omitted, it defaults
to <option>true</option>.</para></listitem>
</varlistentry>
diff --git a/man/systemd-detect-virt.xml b/man/systemd-detect-virt.xml
index 762b6ab992..69785ceffa 100644
--- a/man/systemd-detect-virt.xml
+++ b/man/systemd-detect-virt.xml
@@ -70,14 +70,15 @@
<varname>microsoft</varname>,
<varname>oracle</varname>, <varname>xen</varname>,
<varname>bochs</varname>, <varname>chroot</varname>,
+ <varname>uml</varname>,
<varname>openvz</varname>, <varname>lxc</varname>,
<varname>lxc-libvirt</varname>,
<varname>systemd-nspawn</varname>.</para>
- <para>If multiple virtualization solutions are used
+ <para>If multiple virtualization solutions are used,
only the "innermost" is detected and identified. That
means if both VM virtualization and container
- virtualization are used in conjunction only the latter
+ virtualization are used in conjunction, only the latter
will be identified (unless <option>--vm</option> is
passed).</para>
</refsect1>
@@ -137,7 +138,7 @@
<refsect1>
<title>Exit status</title>
- <para>If a virtualization technology is detected 0 is
+ <para>If a virtualization technology is detected, 0 is
returned, a non-zero code otherwise.</para>
</refsect1>
diff --git a/man/systemd-efi-boot-generator.xml b/man/systemd-efi-boot-generator.xml
new file mode 100644
index 0000000000..3a79dfb8df
--- /dev/null
+++ b/man/systemd-efi-boot-generator.xml
@@ -0,0 +1,88 @@
+<?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">
+<!--
+ 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/>.
+-->
+<refentry id="systemd-efi-boot-generator">
+
+ <refentryinfo>
+ <title>systemd-efi-boot-generator</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>systemd-efi-boot-generator</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>systemd-efi-boot-generator</refname>
+ <refpurpose>Generator for automatically mounting the
+ EFI System Partition used by the current boot to
+ <filename>/boot</filename></refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <para><filename>/usr/lib/systemd/system-generators/systemd-efi-boot-generator</filename></para>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><filename>systemd-efi-boot-generator</filename>
+ is a generator that automatically creates mount and
+ automount units for the EFI System Partition (ESP),
+ mounting it to <filename>/boot</filename>. Note that
+ this generator will execute no operation on non-EFI
+ systems, on systems where the boot loader does not
+ communicate the used ESP to the OS, on systems where
+ <filename>/boot</filename> is an explicitly configured
+ mount (for example, listed in <citerefentry><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>) or where the <filename>/boot</filename> mount
+ point is non-empty. Since this generator creates an
+ automount unit, the mount will only be activated
+ on-demand, when accessed.</para>
+
+ <para><filename>systemd-efi-boot-generator</filename>
+ implements the <ulink
+ url="http://www.freedesktop.org/wiki/Software/systemd/Generators">generator
+ specification</ulink>.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.automount</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-gpt-auto-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>gummiboot</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/systemd-fsck@.service.xml b/man/systemd-fsck@.service.xml
index 4d6464c2b8..e934352f19 100644
--- a/man/systemd-fsck@.service.xml
+++ b/man/systemd-fsck@.service.xml
@@ -66,7 +66,7 @@
<para><filename>systemd-fsck</filename> will
forward file system checking progress to the
- console. If a file system check fails emergency mode
+ console. If a file system check fails, emergency mode
is activated, by isolating to
<filename>emergency.target</filename>.</para>
</refsect1>
diff --git a/man/systemd-fstab-generator.xml b/man/systemd-fstab-generator.xml
index 4bd25bfa8f..9ca16c7ea1 100644
--- a/man/systemd-fstab-generator.xml
+++ b/man/systemd-fstab-generator.xml
@@ -90,7 +90,7 @@
<listitem><para>Takes a boolean
argument. Defaults to
<literal>yes</literal>. If
- <literal>no</literal> causes the
+ <literal>no</literal>, causes the
generator to ignore any mounts or swaps
configured in
<filename>/etc/fstab</filename>. <varname>rd.fstab=</varname>
diff --git a/man/systemd-gpt-auto-generator.xml b/man/systemd-gpt-auto-generator.xml
new file mode 100644
index 0000000000..95c0c35046
--- /dev/null
+++ b/man/systemd-gpt-auto-generator.xml
@@ -0,0 +1,104 @@
+<?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">
+<!--
+ 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/>.
+-->
+<refentry id="systemd-gpt-auto-generator">
+
+ <refentryinfo>
+ <title>systemd-gpt-auto-generator</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>systemd-gpt-auto-generator</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>systemd-gpt-auto-generator</refname>
+ <refpurpose>Generator for automatically discovering
+ and mounting <filename>/home</filename> as well as
+ discovering and enabling swap partitions, based on GPT
+ partition type GUIDs.</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <para><filename>/usr/lib/systemd/system-generators/systemd-gpt-auto-generator</filename></para>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><filename>systemd-gpt-auto-generator</filename>
+ is a generator that automatically discovers
+ <filename>/home</filename> and swap partitions and
+ creates mount and swap units for them, based on the
+ the partition type GUIDs of GUID partition tables
+ (GPT). Note that this generator will execute no
+ operation on non-GPT systems, on systems where the
+ units are explicitly configured (for example, listed
+ in
+ <citerefentry><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>)
+ or where the mount point is non-empty.</para>
+
+ <para>This generator will only look for partitions on
+ the same physical disk the root file system is stored
+ on. This generator has no effect on systems where the
+ root file system is distributed on multiple disks, for
+ example via btrfs RAID.</para>
+
+ <para>This generator is useful for centralizing file
+ system configuration in the partition table and making
+ manual configuration in
+ <filename>/etc/fstab</filename> or suchlike
+ unnecessary.</para>
+
+ <para>This generator looks for swap partitions using
+ GPT type 0657fd6d-a4ab-43c4-84e50933c84b4f4f. It looks
+ for <filename>/home</filename> partitions using GPT
+ type 933ac7e1-2eb4-4f13-b8440e14e2aef915.</para>
+
+ <para><filename>systemd-gpt-auto-generator</filename>
+ implements the <ulink
+ url="http://www.freedesktop.org/wiki/Software/systemd/Generators">generator
+ specification</ulink>.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.swap</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-efi-boot-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/systemd-halt.service.xml b/man/systemd-halt.service.xml
index 6a6bfdc7d7..812281e60d 100644
--- a/man/systemd-halt.service.xml
+++ b/man/systemd-halt.service.xml
@@ -89,10 +89,10 @@
executables in
<filename>/usr/lib/systemd/system-shutdown/</filename>
and pass one arguments to them: either
- "<literal>halt</literal>",
- "<literal>poweroff</literal>",
- "<literal>reboot</literal>" or
- "<literal>kexec</literal>", depending on the chosen
+ <literal>halt</literal>,
+ <literal>poweroff</literal>,
+ <literal>reboot</literal> or
+ <literal>kexec</literal>, depending on the chosen
action. All executables in this directory are executed
in parallel, and execution of the action is not
continued before all executables finished.</para>
@@ -101,7 +101,7 @@
<filename>systemd-halt.service</filename> (and the
related units) should never be executed
directly. Instead, trigger system shutdown with a
- command such as "<literal>systemctl halt</literal>" or
+ command such as <literal>systemctl halt</literal> or
suchlike.</para>
</refsect1>
diff --git a/man/systemd-hostnamed.service.xml b/man/systemd-hostnamed.service.xml
index fe64a62fbe..bdd3a51cc9 100644
--- a/man/systemd-hostnamed.service.xml
+++ b/man/systemd-hostnamed.service.xml
@@ -45,7 +45,7 @@
<refnamediv>
<refname>systemd-hostnamed.service</refname>
<refname>systemd-hostnamed</refname>
- <refpurpose>Hostname bus mechanism</refpurpose>
+ <refpurpose>Host name bus mechanism</refpurpose>
</refnamediv>
<refsynopsisdiv>
@@ -57,14 +57,14 @@
<title>Description</title>
<para><filename>systemd-hostnamed</filename> is a system
- service that may be used as mechanism to change the
- system hostname. <filename>systemd-hostnamed</filename> is
+ service that may be used as a mechanism to change the
+ system's hostname. <filename>systemd-hostnamed</filename> is
automatically activated on request and terminates
itself when it is unused.</para>
<para>The tool
<citerefentry><refentrytitle>hostnamectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- is a command line client to this service.</para>
+ is a command-line client to this service.</para>
<para>See the <ulink
url="http://www.freedesktop.org/wiki/Software/systemd/hostnamed">
diff --git a/man/systemd-inhibit.xml b/man/systemd-inhibit.xml
index 6f63c8c73e..de2f264147 100644
--- a/man/systemd-inhibit.xml
+++ b/man/systemd-inhibit.xml
@@ -101,8 +101,8 @@
<varlistentry>
<term><option>--what=</option></term>
- <listitem><para>Takes a colon
- separated list of one or more
+ <listitem><para>Takes a colon-separated
+ list of one or more
operations to inhibit:
<literal>shutdown</literal>,
<literal>sleep</literal>,
@@ -124,9 +124,9 @@
<varlistentry>
<term><option>--who=</option></term>
- <listitem><para>Takes a short human
- readable descriptive string for the
- program taking the lock. If not passed
+ <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>
@@ -134,8 +134,8 @@
<varlistentry>
<term><option>--why=</option></term>
- <listitem><para>Takes a short human
- readable descriptive string for the
+ <listitem><para>Takes a short,
+ human-readable descriptive string for the
reason for taking the lock. Defaults
to "Unknown reason".</para></listitem>
</varlistentry>
@@ -155,7 +155,7 @@
<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
+ time elapses, the lock is ignored and
the operation executed. The time limit
may be specified in
<citerefentry><refentrytitle>systemd-logind.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>. Note
diff --git a/man/systemd-journald.service.xml b/man/systemd-journald.service.xml
index 822f3c28f0..2f877f565c 100644
--- a/man/systemd-journald.service.xml
+++ b/man/systemd-journald.service.xml
@@ -73,24 +73,24 @@
</para>
<para>Log data collected by the journal is primarily
- text based but can also include binary data where
+ text-based but can also include binary data where
necessary. All objects stored in the journal can be up
to 2^64-1 bytes in size.</para>
- <para>By default the journal stores log data in
+ <para>By default, the journal stores log data in
<filename>/run/log/journal/</filename>. Since
- <filename>/run/</filename> is volatile log data is
- lost at reboot. To make the data persistent it
+ <filename>/run/</filename> is volatile, log data is
+ lost at reboot. To make the data persistent, it
is sufficient to create
<filename>/var/log/journal/</filename> where
<filename>systemd-journald</filename> will then store
the data.</para>
<para><filename>systemd-journald</filename> will
- forward all received log messages to the AF_UNIX
- SOCK_DGRAM socket
- <filename>/run/systemd/journal/syslog</filename> (if it exists) which
- may be used by UNIX syslog daemons to process the data
+ forward all received log messages to the <constant>AF_UNIX</constant>
+ <constant>SOCK_DGRAM</constant> socket
+ <filename>/run/systemd/journal/syslog</filename>, if it exists, which
+ may be used by Unix syslog daemons to process the data
further.</para>
<para>See
@@ -161,15 +161,15 @@
<refsect1>
<title>Access Control</title>
- <para>Journal files are by default owned and readable
+ <para>Journal files are, by default, owned and readable
by the <literal>systemd-journal</literal> system group
- (but not writable). Adding a user to this group thus
+ but are not writable. Adding a user to this group thus
enables her/him to read the journal files.</para>
<para>By default, each logged in user will get her/his
own set of journal files in
<filename>/var/log/journal/</filename>. These files
- will not be owned by the user however, in order to
+ will not be owned by the user, however, in order to
avoid that the user can write to them
directly. Instead, file system ACLs are used to ensure
the user gets read access only.</para>
@@ -192,6 +192,52 @@
</refsect1>
<refsect1>
+ <title>Files</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><filename>/etc/systemd/journald.conf</filename></term>
+
+ <listitem><para>Configure
+ <command>systemd-journald</command>
+ behaviour. See
+ <citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><filename>/run/log/journal/<replaceable>machine-id</replaceable>/*.journal</filename></term>
+ <term><filename>/run/log/journal/<replaceable>machine-id</replaceable>/*.journal~</filename></term>
+ <term><filename>/var/log/journal/<replaceable>machine-id</replaceable>/*.journal</filename></term>
+ <term><filename>/var/log/journal/<replaceable>machine-id</replaceable>/*.journal~</filename></term>
+
+ <listitem><para><command>systemd-journald</command>
+ writes entries to files in
+ <filename>/run/log/journal/<replaceable>machine-id</replaceable>/</filename>
+ or
+ <filename>/var/log/journal/<replaceable>machine-id</replaceable>/</filename>
+ with the <literal>.journal</literal>
+ suffix. If the daemon is stopped
+ uncleanly, or if the files are found
+ to be corrupted, they are renamed
+ using the <literal>.journal~</literal>
+ suffix, and
+ <command>systemd-journald</command>
+ starts writing to a new
+ file. <filename>/run</filename> is
+ used when
+ <filename>/var/log/journal</filename>
+ is not available, or when
+ <option>Storage=volatile</option> is
+ set in the
+ <citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ configuration file.
+ </para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
@@ -199,7 +245,8 @@
<citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-journal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>setfacl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>setfacl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <command>pydoc systemd.journal</command>.
</para>
</refsect1>
diff --git a/man/systemd-logind.service.xml b/man/systemd-logind.service.xml
index 09bcfac430..c0c3d1a897 100644
--- a/man/systemd-logind.service.xml
+++ b/man/systemd-logind.service.xml
@@ -56,16 +56,14 @@
<refsect1>
<title>Description</title>
- <para><filename>systemd-logind</filename> is a system
+ <para><command>systemd-logind</command> is a system
service that manages user logins. It is responsible
for:</para>
<itemizedlist>
- <listitem><para>Keeping track of users and sessions, their
- processes and their idle state</para></listitem>
-
- <listitem><para>Creating control groups for
- user processes</para></listitem>
+ <listitem><para>Keeping track of users and
+ sessions, their processes and their idle
+ state</para></listitem>
<listitem><para>Providing PolicyKit-based access
for users to operations such as system
diff --git a/man/systemd-machine-id-setup.xml b/man/systemd-machine-id-setup.xml
index 25fb63af2d..fef76bcfc7 100644
--- a/man/systemd-machine-id-setup.xml
+++ b/man/systemd-machine-id-setup.xml
@@ -69,12 +69,12 @@
initialized.</para>
<para>If a valid D-Bus machine ID is already
- configured for the system the D-Bus machine ID is
+ configured for the system, the D-Bus machine ID is
copied and used to initialize the machine ID in
<filename>/etc/machine-id</filename>.</para>
<para>If run inside a KVM virtual machine and a UUID
- is passed via the <option>-uuid</option> option this
+ is passed via the <option>-uuid</option> option, this
UUID is used to initialize the machine ID instead of a
randomly generated one. The caller must ensure that the
UUID passed is sufficiently unique and is different
diff --git a/man/systemd-machined.service.xml b/man/systemd-machined.service.xml
new file mode 100644
index 0000000000..352b4a025f
--- /dev/null
+++ b/man/systemd-machined.service.xml
@@ -0,0 +1,85 @@
+<?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">
+
+<!--
+ 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/>.
+-->
+
+<refentry id="systemd-machined.service" conditional='ENABLE_MACHINED'>
+
+ <refentryinfo>
+ <title>systemd-machined.service</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>systemd-machined.service</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>systemd-machined.service</refname>
+ <refname>systemd-machined</refname>
+ <refpurpose>Virtual machine and container registration manager</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <para><filename>systemd-machined.service</filename></para>
+ <para><filename>/usr/lib/systemd/systemd-machined</filename></para>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><command>systemd-machined</command> is a
+ system service that keeps track of virtual machines
+ and containers, and processes belonging to
+ them.</para>
+
+ <para>See
+ <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ for some examples on how to start a container the systemd
+ way.</para>
+
+ <para>See the <ulink
+ url="http://www.freedesktop.org/wiki/Software/systemd/machined">
+ machined D-Bus API Documentation</ulink> for information about
+ the APIs <filename>systemd-machined</filename>
+ provides.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>machinectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/systemd-modules-load.service.xml b/man/systemd-modules-load.service.xml
index 1d33b8eec6..28dd8ecb42 100644
--- a/man/systemd-modules-load.service.xml
+++ b/man/systemd-modules-load.service.xml
@@ -77,8 +77,8 @@
<term><varname>modules-load=</varname></term>
<term><varname>rd.modules-load=</varname></term>
- <listitem><para>Takes a comma
- separated list of kernel modules to
+ <listitem><para>Takes a comma-separated
+ list of kernel modules to
statically load during early boot. The
option prefixed with
<literal>rd.</literal> is read by the
@@ -94,7 +94,6 @@
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>modules-load.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>wine</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/systemd-notify.xml b/man/systemd-notify.xml
index b03492c5c1..a76934649a 100644
--- a/man/systemd-notify.xml
+++ b/man/systemd-notify.xml
@@ -119,7 +119,7 @@
<listitem><para>Inform the init system
about the main PID of the
daemon. Takes a PID as argument. If
- the argument is omitted the PID of the
+ the argument is omitted, the PID of the
process that invoked
<command>systemd-notify</command> is
used. This is equivalent to
@@ -148,10 +148,10 @@
<listitem><para>Returns 0 if the
system was booted up with systemd,
non-zero otherwise. If this option is
- passed no message is sent. This option
+ passed, no message is sent. This option
is hence unrelated to the other
options. For details about the
- semantics of this option see
+ semantics of this option, see
<citerefentry><refentrytitle>sd_booted</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
</varlistentry>
diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml
index d9fb899895..7d450f912c 100644
--- a/man/systemd-nspawn.xml
+++ b/man/systemd-nspawn.xml
@@ -97,14 +97,13 @@
involved with boot and systems management.</para>
<para>In contrast to
- <citerefentry><refentrytitle>chroot</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- <command>systemd-nspawn</command> may be used to boot
- full Linux-based operating systems in a
- container.</para>
+ <citerefentry><refentrytitle>chroot</refentrytitle><manvolnum>1</manvolnum></citerefentry> <command>systemd-nspawn</command>
+ may be used to boot full Linux-based operating systems
+ in a container.</para>
<para>Use a tool like
<citerefentry><refentrytitle>yum</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>debootstrap</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>debootstrap</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
or
<citerefentry><refentrytitle>pacman</refentrytitle><manvolnum>8</manvolnum></citerefentry>
to set up an OS directory tree suitable as file system
@@ -136,22 +135,25 @@
<para>As a safety check
<command>systemd-nspawn</command> will verify the
- existance of <filename>/etc/os-release</filename> in
+ existence of <filename>/etc/os-release</filename> in
the container tree before starting the container (see
<citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>). It
might be necessary to add this file to the container
tree manually if the OS of the container is too old to
contain this file out-of-the-box.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Incompatibility with Auditing</title>
<para>Note that the kernel auditing subsystem is
currently broken when used together with
containers. We hence recommend turning it off entirely
- when using <command>systemd-nspawn</command> by
- booting with <literal>audit=0</literal> on the kernel
- command line, or by turning it off at kernel build
- time. If auditing is enabled in the kernel operating
- systems booted in an nspawn container might refuse
- log-in attempts.</para>
+ by booting with <literal>audit=0</literal> on the
+ kernel command line, or by turning it off at kernel
+ build time. If auditing is enabled in the kernel,
+ operating systems booted in an nspawn container might
+ refuse log-in attempts.</para>
</refsect1>
<refsect1>
@@ -190,7 +192,7 @@
<listitem><para>Directory to use as
file system root for the namespace
- container. If omitted the current
+ container. If omitted, the current
directory will be
used.</para></listitem>
</varlistentry>
@@ -231,15 +233,25 @@
host, and is used to initialize the
container's hostname (which the
container can choose to override,
- however). If not specified the last
+ however). If not specified, the last
component of the root directory of the
container is used.</para></listitem>
</varlistentry>
<varlistentry>
+ <term><option>--slice=</option></term>
+
+ <listitem><para>Make the container
+ part of the specified slice, instead
+ of the
+ <filename>machine.slice</filename>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>--uuid=</option></term>
- <listitem><para>Set the specified uuid
+ <listitem><para>Set the specified UUID
for the container. The init system
will initialize
<filename>/etc/machine-id</filename>
@@ -248,16 +260,6 @@
</varlistentry>
<varlistentry>
- <term><option>-C</option></term>
- <term><option>--controllers=</option></term>
-
- <listitem><para>Makes the container appear in
- other hierarchies than the name=systemd:/ one.
- Takes a comma-separated list of controllers.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
<term><option>--private-network</option></term>
<listitem><para>Turn off networking in
@@ -271,7 +273,7 @@
<term><option>--read-only</option></term>
<listitem><para>Mount the root file
- system read only for the
+ system read-only for the
container.</para></listitem>
</varlistentry>
@@ -280,7 +282,7 @@
<listitem><para>List one or more
additional capabilities to grant the
- container. Takes a comma separated
+ container. Takes a comma-separated
list of capability names, see
<citerefentry><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
for more information. Note that the
@@ -306,7 +308,7 @@
<listitem><para>Control whether the
container's journal shall be made
- visible to the host system. If enabled
+ visible to the host system. If enabled,
allows viewing the container's journal
files from the host (but not vice
versa). Takes one of
@@ -332,7 +334,7 @@
<filename>/var/log/journal</filename>
exists, it will be bind mounted
into the container. If the
- subdirectory doesn't exist, no
+ subdirectory does not exist, no
linking is performed. Effectively,
booting a container once with
<literal>guest</literal> or
@@ -440,7 +442,8 @@
<citerefentry><refentrytitle>unshare</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>yum</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>debootstrap</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>pacman</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>pacman</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/systemd-random-seed-load.service.xml b/man/systemd-random-seed.service.xml
index 693c008a2d..8cd14b74cb 100644
--- a/man/systemd-random-seed-load.service.xml
+++ b/man/systemd-random-seed.service.xml
@@ -19,10 +19,10 @@
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="systemd-random-seed-load.service" conditional='ENABLE_RANDOMSEED'>
+<refentry id="systemd-random-seed.service" conditional='ENABLE_RANDOMSEED'>
<refentryinfo>
- <title>systemd-random-seed-load.service</title>
+ <title>systemd-random-seed.service</title>
<productname>systemd</productname>
<authorgroup>
@@ -36,32 +36,27 @@
</refentryinfo>
<refmeta>
- <refentrytitle>systemd-random-seed-load.service</refentrytitle>
+ <refentrytitle>systemd-random-seed.service</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
- <refname>systemd-random-seed-load.service</refname>
- <refname>systemd-random-seed-save.service</refname>
+ <refname>systemd-random-seed.service</refname>
<refname>systemd-random-seed</refname>
<refpurpose>Load and save the system random seed at boot and shutdown</refpurpose>
</refnamediv>
<refsynopsisdiv>
- <para><filename>systemd-random-seed-load.service</filename></para>
- <para><filename>systemd-random-seed-save.service</filename></para>
+ <para><filename>systemd-random-seed.service</filename></para>
<para><filename>/usr/lib/systemd/systemd-random-seed</filename></para>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
- <para><filename>systemd-random-seed-load.service</filename>
- is an early-boot service that restores the random seed
- of the
- system. <filename>systemd-random-seed-save.service</filename>
- is a late-shutdown service that saves the random seed
- of the system. See
+ <para><filename>systemd-random-seed.service</filename>
+ is a service that restores the random seed of the
+ system at early-boot and saves it at shutdown. See
<citerefentry><refentrytitle>random</refentrytitle><manvolnum>4</manvolnum></citerefentry>
for details. Saving/restoring the random seed across
boots increases the amount of available entropy early
diff --git a/man/systemd-readahead-replay.service.xml b/man/systemd-readahead-replay.service.xml
index a00f7e589b..806d46093b 100644
--- a/man/systemd-readahead-replay.service.xml
+++ b/man/systemd-readahead-replay.service.xml
@@ -72,7 +72,7 @@
time. <filename>systemd-readahead-replay.service</filename>
is a service that replays this access data collected
at the subsequent boot. Since disks tend to be
- magnitudes slower than RAM this is intended to improve
+ magnitudes slower than RAM, this is intended to improve
boot speeds by pre-loading early at boot all data on
disk that is known to be read for the complete boot
process.</para>
@@ -80,9 +80,9 @@
<para><filename>systemd-readahead-done.service</filename>
is executed a short while after boot completed and signals
<filename>systemd-readahead-collect.service</filename>
- to end data collection. On this signal this service
+ to end data collection. On this signal, this service
will then sort the collected disk accesses and store
- information about them disk in
+ information about them in
<filename>/.readahead</filename>.</para>
<para>Normally, both
@@ -92,17 +92,17 @@
are activated at boot so that access patterns from the
preceding boot are replayed and new data collected
for the subsequent boot. However, on read-only media
- where the collected data cannot be stored it might
+ where the collected data cannot be stored, it might
be a good idea to disable
<filename>systemd-readahead-collect.service</filename>.</para>
<para>On rotating media, when replaying disk accesses
- at early boot
+ at early boot,
<filename>systemd-readahead-replay.service</filename>
will order read requests by their location on disk. On
non-rotating media, they will be ordered by their
original access timestamp. If the file system supports
- it
+ it,
<filename>systemd-readahead-collect.service</filename>
will also defragment and rearrange files on disk to
optimize subsequent boot times.</para>
@@ -136,7 +136,7 @@
<term><option>--file-size-max=</option></term>
<listitem><para>Maximum size of files
- (in bytes) to read ahead. Only valid
+ in bytes to read ahead. Only valid
for the <command>collect</command>
and <command>replay</command>
commands.</para></listitem>
@@ -145,8 +145,8 @@
<varlistentry>
<term><option>--timeout=</option></term>
- <listitem><para>Maximum time (in usec)
- to to spend collecting data. Only valid
+ <listitem><para>Maximum time in microseconds
+ to spend collecting data. Only valid
for the <command>collect</command>
command.</para></listitem>
</varlistentry>
@@ -164,7 +164,7 @@
[<replaceable>DIRECTORY</replaceable>]</command></term>
<listitem>
<para>Collect read-ahead data on
- early boot. When terminating it will
+ early boot. When terminating, it will
write out a pack file to the indicated
directory containing the read-ahead
data. </para>
@@ -186,9 +186,9 @@
<listitem>
<para>Dumps the content of the
read-ahead pack file to the
- terminal. The output lists
- approximately for each file
- how much will be read-ahead by
+ terminal. For each file, the
+ output lists approximately how
+ much will be read ahead by
the <command>replay</command>
command.</para>
</listitem>
diff --git a/man/systemd-run.xml b/man/systemd-run.xml
new file mode 100644
index 0000000000..e76a402003
--- /dev/null
+++ b/man/systemd-run.xml
@@ -0,0 +1,219 @@
+<?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">
+
+<!--
+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/>.
+-->
+
+<refentry id="systemd-run">
+
+ <refentryinfo>
+ <title>systemd-run</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>systemd-run</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>systemd-run</refname>
+ <refpurpose>Run programs in transient scope or service units</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>systemd-run</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="plain"><replaceable>COMMAND</replaceable>
+ <arg choice="opt" rep="repeat">ARGS</arg>
+ </arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><command>systemd-run</command> may be used create and start
+ a transient <filename>.service</filename> or a
+ <filename>.scope</filename> unit and run the specified
+ <replaceable>COMMAND</replaceable> in it.</para>
+
+ <para>If a command is run as transient service unit, it will be
+ started and managed by the service manager like any other service,
+ and thus show up in the output of <command>systemctl
+ list-units</command> like any other unit. It will run in a clean
+ and detached execution environment. <command>systemd-run</command>
+ will start the service asynchronously in the background and
+ immediately return.</para>
+
+ <para>If a command is run as transient scope unit, it will be
+ started directly by <command>systemd-run</command> and thus
+ inherit the execution environment of the caller. It is however
+ managed by the service manager similar to normal services, and
+ will also show up in the output of <command>systemctl
+ list-units</command>. Execution in this case is synchronous, and
+ execution will return only when the command finishes.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Options</title>
+
+ <para>The following options are understood:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>-h</option></term>
+ <term><option>--help</option></term>
+
+ <listitem><para>Prints a short help
+ text and exits.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--version</option></term>
+
+ <listitem><para>Prints a short version
+ string and exits.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--user</option></term>
+
+ <listitem>
+ <para>Talk to the service manager of the calling user,
+ rather than the service manager of the system.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--scope</option></term>
+
+ <listitem>
+ <para>Create a transient <filename>.scope</filename> unit instead of
+ the default transient <filename>.service</filename> unit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--unit=</option></term>
+
+ <listitem><para>Use this unit name instead of an automatically
+ generated one.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--description=</option></term>
+
+ <listitem><para>Provide description for the unit. If not
+ specified, the command itself will be used as a description.
+ See <varname>Description=</varname> in
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--slice=</option></term>
+
+ <listitem><para>Make the new <filename>.service</filename> or
+ <filename>.scope</filename> unit part of the specified slice,
+ instead of the <filename>system.slice</filename>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--remain-after-exit</option></term>
+
+ <listitem><para>After the service's process has terminated, keep
+ the service around until it is explicitly stopped. This is
+ useful to collect runtime information about the service after
+ it finished running. Also see
+ <varname>RemainAfterExit=</varname> in
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--send-sighup</option></term>
+
+ <listitem><para>When terminating the scope unit, send a SIGHUP
+ immediately after SIGTERM. This is useful to indicate to
+ shells and shell-like processes that the connection has been
+ severed. Also see <varname>SendSIGHUP=</varname> in
+ <citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>All command-line arguments after the first non-option
+ argument become part of the commandline of the launched
+ process. If a command is run as service unit, its first argument
+ needs to be an absolute binary path.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Exit status</title>
+
+ <para>On success, 0 is returned, a non-zero failure
+ code otherwise.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Example</title>
+
+ <para>The following command will log the environment variables
+ provided by systemd to services:</para>
+
+ <programlisting># systemd-run env
+Running as unit run-19945.service.
+# journalctl -u run-19945.service
+Sep 08 07:37:21 bupkis systemd[1]: Starting /usr/bin/env...
+Sep 08 07:37:21 bupkis systemd[1]: Started /usr/bin/env.
+Sep 08 07:37:21 bupkis env[19948]: PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
+Sep 08 07:37:21 bupkis env[19948]: LANG=en_US.UTF-8
+Sep 08 07:37:21 bupkis env[19948]: BOOT_IMAGE=/vmlinuz-3.11.0-0.rc5.git6.2.fc20.x86_64
+ </programlisting>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.scope</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/systemd-suspend.service.xml b/man/systemd-suspend.service.xml
index 4a4ed5cbdb..4abc278191 100644
--- a/man/systemd-suspend.service.xml
+++ b/man/systemd-suspend.service.xml
@@ -80,14 +80,14 @@
executables in
<filename>/usr/lib/systemd/system-sleep/</filename>
and pass two arguments to them. The first argument
- will be "<literal>pre</literal>", the second either
- "<literal>suspend</literal>",
- "<literal>hibernate</literal>", or
- "<literal>hybrid-sleep</literal>" depending on the
+ will be <literal>pre</literal>, the second either
+ <literal>suspend</literal>,
+ <literal>hibernate</literal>, or
+ <literal>hybrid-sleep</literal> depending on the
chosen action. Immediately after leaving system
suspend and/or hibernation the same executables are run,
but the first argument is now
- "<literal>post</literal>". All executables in this
+ <literal>post</literal>. All executables in this
directory are executed in parallel, and execution of
the action is not continued until all executables
have finished.</para>
@@ -96,7 +96,7 @@
<filename>/usr/lib/systemd/system-sleep/</filename>
are intended for local use only and should be
considered hacks. If applications want to be notified
- of system suspend/hibernation and resume there are
+ of system suspend/hibernation and resume, there are
much nicer interfaces available.</para>
<para>Note that
@@ -105,11 +105,11 @@
<filename>systemd-hybrid-sleep.service</filename>
should never be executed directly. Instead, trigger
system sleep states with a command such as
- "<literal>systemctl suspend</literal>" or
+ <literal>systemctl suspend</literal> or
similar.</para>
<para>Internally, this service will echo a string like
- "<literal>mem</literal>" into
+ <literal>mem</literal> into
<filename>/sys/power/state</filename>, to trigger the
actual system suspend. What exactly is written
where can be configured in the <literal>[Sleep]</literal>
diff --git a/man/systemd-sysctl.service.xml b/man/systemd-sysctl.service.xml
index 72a102c128..a9a4765630 100644
--- a/man/systemd-sysctl.service.xml
+++ b/man/systemd-sysctl.service.xml
@@ -71,7 +71,6 @@
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sysctl.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sysctl</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>wine</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml
index d8bfd1279d..e8cf8a9cb2 100644
--- a/man/systemd-system.conf.xml
+++ b/man/systemd-system.conf.xml
@@ -104,42 +104,17 @@
</varlistentry>
<varlistentry>
- <term><varname>DefaultControllers=cpu</varname></term>
-
- <listitem><para>Configures in which
- control group hierarchies to create
- per-service cgroups automatically, in
- addition to the
- <literal>name=systemd</literal> named
- hierarchy. Defaults to
- <literal>cpu</literal>. Takes a space
- separated list of controller
- names. Pass the empty string to ensure
- that systemd does not touch any
- hierarchies but its own.</para>
-
- <para>Note that the default value of
- 'cpu' will make realtime scheduling
- unavailable to system services. See
- <ulink
- url="http://www.freedesktop.org/wiki/Software/systemd/MyServiceCantGetRealtime">My
- Service Can't Get Realtime!</ulink>
- for more
- information.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>JoinControllers=cpu,cpuacct,cpuset net_cls,netprio</varname></term>
+ <term><varname>JoinControllers=cpu,cpuacct net_cls,netprio</varname></term>
<listitem><para>Configures controllers
that shall be mounted in a single
- hierarchy. By default systemd will
+ hierarchy. By default, systemd will
mount all controllers which are
enabled in the kernel in individual
hierarchies, with the exception of
those listed in this setting. Takes a
- space separated list of comma
- separated controller names, in order
+ space-separated list of comma-separated
+ controller names, in order
to allow multiple joined
hierarchies. Defaults to
'cpu,cpuacct'. Pass an empty string to
@@ -150,11 +125,11 @@
<para>Note that this option is only
applied once, at very early boot. If
you use an initial RAM disk (initrd)
- that uses systemd it might hence be
+ that uses systemd, it might hence be
necessary to rebuild the initrd if
this option is changed, and make sure
the new configuration file is included
- in it. Otherwise the initrd might
+ in it. Otherwise, the initrd might
mount the controller hierarchies in a
different configuration than intended,
and the main system cannot remount
@@ -175,7 +150,7 @@
<literal>d</literal>,
<literal>w</literal>). If
<varname>RuntimeWatchdogSec=</varname>
- is set to a non-zero value the
+ is set to a non-zero value, the
watchdog hardware
(<filename>/dev/watchdog</filename>)
will be programmed to automatically
@@ -214,14 +189,13 @@
capability bounding set for PID 1 and
its children. See
<citerefentry><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
- for details. Takes a whitespace
- separated list of capability names as
- read by
+ for details. Takes a whitespace-separated
+ list of capability names as read by
<citerefentry><refentrytitle>cap_from_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
Capabilities listed will be included
in the bounding set, all others are
removed. If the list of capabilities
- is prefixed with ~ all but the listed
+ is prefixed with ~, all but the listed
capabilities will be included, the
effect of the assignment
inverted. Note that this option also
@@ -263,6 +237,28 @@
</varlistentry>
<varlistentry>
+ <term><varname>DefaultEnvironment=</varname></term>
+
+ <listitem><para>Sets manager
+ environment variables passed to all
+ executed processes. Takes a
+ space-separated list of variable
+ assignments. See
+ <citerefentry><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ for details about environment
+ variables.</para>
+
+ <para>Example:
+
+ <programlisting>DefaultEnvironment="VAR1=word1 word2" VAR2=word3 "VAR3=word 5 6"</programlisting>
+
+ Sets three variables
+ <literal>VAR1</literal>,
+ <literal>VAR2</literal>,
+ <literal>VAR3</literal>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>DefaultLimitCPU=</varname></term>
<term><varname>DefaultLimitFSIZE=</varname></term>
<term><varname>DefaultLimitDATA=</varname></term>
@@ -302,7 +298,8 @@
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/systemd-timedated.service.xml b/man/systemd-timedated.service.xml
index c82c0ff439..4f17bccc69 100644
--- a/man/systemd-timedated.service.xml
+++ b/man/systemd-timedated.service.xml
@@ -57,7 +57,7 @@
<title>Description</title>
<para><filename>systemd-timedated</filename> is a
- system service that may be used as mechanism to change
+ system service that may be used as a mechanism to change
the system clock and timezone, as well as to
enable/disable NTP time
synchronization. <filename>systemd-timedated</filename>
@@ -66,7 +66,7 @@
<para>The tool
<citerefentry><refentrytitle>timedatectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- is a command line client to this service.</para>
+ is a command-line client to this service.</para>
<para>See the <ulink
url="http://www.freedesktop.org/wiki/Software/systemd/timedated">
diff --git a/man/systemd-tmpfiles.xml b/man/systemd-tmpfiles.xml
index 0d2d65d593..ba727e1854 100644
--- a/man/systemd-tmpfiles.xml
+++ b/man/systemd-tmpfiles.xml
@@ -76,7 +76,7 @@
<para>If invoked with no arguments, it applies all
directives from all configuration files. If one or
- more file names are passed on the command line, only
+ more filenames are passed on the command line, only
the directives in these files are applied. If only
the basename of a configuration file is specified,
all configuration directories as specified in <citerefentry>
@@ -94,7 +94,7 @@
<varlistentry>
<term><option>--create</option></term>
- <listitem><para>If this option is passed all
+ <listitem><para>If this option is passed, all
files and directories marked with f,
F, d, D in the configuration files are
created. Files and directories marked with z,
@@ -105,7 +105,7 @@
<varlistentry>
<term><option>--clean</option></term>
<listitem><para>If this option is
- passed all files and directories with
+ passed, all files and directories with
an age parameter configured will be
cleaned up.</para></listitem>
</varlistentry>
@@ -113,7 +113,7 @@
<varlistentry>
<term><option>--remove</option></term>
<listitem><para>If this option is
- passed all files and directories marked
+ passed, all files and directories marked
with r, R in the configuration files
are removed.</para></listitem>
</varlistentry>
@@ -121,7 +121,15 @@
<term><option>--prefix=PATH</option></term>
<listitem><para>Only apply rules that
apply to paths with the specified
- prefix.</para></listitem>
+ prefix. This option can be specified
+ multiple times.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--exclude-prefix=PATH</option></term>
+ <listitem><para>Ignore rules that
+ apply to paths with the specified
+ prefix. This option can be specified
+ multiple times.</para></listitem>
</varlistentry>
@@ -157,7 +165,7 @@
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/systemd-udevd.service.xml b/man/systemd-udevd.service.xml
index 77b7374886..7fce3000f5 100644
--- a/man/systemd-udevd.service.xml
+++ b/man/systemd-udevd.service.xml
@@ -162,6 +162,8 @@
</listitem>
</varlistentry>
</variablelist>
+ <!-- when adding entries here, consider also adding them
+ in kernel-command-line.xml -->
</refsect1>
<refsect1><title>Configuration file</title>
diff --git a/man/systemd-update-utmp-runlevel.service.xml b/man/systemd-update-utmp.service.xml
index 867b958d30..846fc959d0 100644
--- a/man/systemd-update-utmp-runlevel.service.xml
+++ b/man/systemd-update-utmp.service.xml
@@ -19,10 +19,10 @@
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="systemd-update-utmp-runlevel.service">
+<refentry id="systemd-update-utmp.service">
<refentryinfo>
- <title>systemd-update-utmp-runlevel.service</title>
+ <title>systemd-update-utmp.service</title>
<productname>systemd</productname>
<authorgroup>
@@ -36,21 +36,21 @@
</refentryinfo>
<refmeta>
- <refentrytitle>systemd-update-utmp-runlevel.service</refentrytitle>
+ <refentrytitle>systemd-update-utmp.service</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
+ <refname>systemd-update-utmp.service</refname>
<refname>systemd-update-utmp-runlevel.service</refname>
- <refname>systemd-update-utmp-shutdown.service</refname>
<refname>systemd-update-utmp</refname>
- <refpurpose>Write audit and utmp updates at runlevel
+ <refpurpose>Write audit and utmp updates at bootup, runlevel
changes and shutdown</refpurpose>
</refnamediv>
<refsynopsisdiv>
+ <para><filename>systemd-update-utmp.service</filename></para>
<para><filename>systemd-update-utmp-runlevel.service</filename></para>
- <para><filename>systemd-update-utmp-shutdown.service</filename></para>
<para><filename>/usr/lib/systemd/systemd-update-utmp</filename></para>
</refsynopsisdiv>
@@ -60,8 +60,8 @@
<para><filename>systemd-update-utmp-runlevel.service</filename>
is a service that writes SysV runlevel changes to utmp
and wtmp, as well as the audit logs, as they
- occur. <filename>systemd-update-utmp-shutdown.service</filename>
- does the same for shut-down requests.</para>
+ occur. <filename>systemd-update-utmp.service</filename>
+ does the same for system reboots and shut-down requests.</para>
</refsect1>
<refsect1>
diff --git a/man/systemd.automount.xml b/man/systemd.automount.xml
index e01cac7bc2..34105126cd 100644
--- a/man/systemd.automount.xml
+++ b/man/systemd.automount.xml
@@ -55,7 +55,7 @@
<title>Description</title>
<para>A unit configuration file whose name ends in
- <filename>.automount</filename> encodes information
+ <literal>.automount</literal> encodes information
about a file system automount point controlled and
supervised by systemd.</para>
@@ -93,7 +93,7 @@
file systems.</para>
<para>If an automount point is beneath another mount
- point in the file system hierarchy a dependency
+ point in the file system hierarchy, a dependency
between both units is created automatically.</para>
</refsect1>
@@ -110,7 +110,7 @@
<citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
<para>If an automount point is configured in both
- <filename>/etc/fstab</filename> and a unit file the
+ <filename>/etc/fstab</filename> and a unit file, the
configuration in the latter takes precedence.</para>
</refsect1>
@@ -129,11 +129,11 @@
<term><varname>Where=</varname></term>
<listitem><para>Takes an absolute path
of a directory of the automount
- point. If the automount point is not
- existing at time that the automount
- point is installed it is created. This
+ point. If the automount point does not
+ exist at time that the automount
+ point is installed, it is created. This
string must be reflected in the unit
- file name. (See above.) This option is
+ filename. (See above.) This option is
mandatory.</para></listitem>
</varlistentry>
diff --git a/man/systemd.device.xml b/man/systemd.device.xml
index 7dffa236cf..96ebe89095 100644
--- a/man/systemd.device.xml
+++ b/man/systemd.device.xml
@@ -55,7 +55,7 @@
<title>Description</title>
<para>A unit configuration file whose name ends in
- <filename>.device</filename> encodes information about
+ <literal>.device</literal> encodes information about
a device unit as exposed in the
sysfs/<citerefentry><refentrytitle>udev</refentrytitle><manvolnum>7</manvolnum></citerefentry>
device tree.</para>
@@ -107,7 +107,7 @@
available. Note that this and the
other tags are not taken into account
unless the device is tagged with the
- "<literal>systemd</literal>" string in
+ <literal>systemd</literal> string in
the udev database, because otherwise
the device is not exposed as systemd
unit.</para></listitem>
@@ -124,11 +124,11 @@
<varlistentry>
<term><varname>SYSTEMD_READY=</varname></term>
- <listitem><para>If set to 0 systemd
+ <listitem><para>If set to 0, systemd
will consider this device unplugged
even if it shows up in the udev
tree. If this property is unset or set
- to 1 the device will be considered
+ to 1, the device will be considered
plugged the moment it shows up in the
udev tree. This property has no
influence on the behavior when a
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
index b3e0287d72..f50161f30c 100644
--- a/man/systemd.exec.xml
+++ b/man/systemd.exec.xml
@@ -1,4 +1,3 @@
-<?xml version='1.0'?> <!--*-nxml-*-->
<?xml-stylesheet type="text/xsl" href="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl"?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
@@ -58,7 +57,7 @@
<title>Description</title>
<para>Unit configuration files for services, sockets,
- mount points and swap devices share a subset of
+ mount points, and swap devices share a subset of
configuration options which define the execution
environment of spawned processes.</para>
@@ -69,7 +68,7 @@
files, and
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd.swap</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>systemd.swap</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
and
<citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for more information on the specific unit
@@ -90,7 +89,7 @@
<listitem><para>Takes an absolute
directory path. Sets the working
directory for executed processes. If
- not set defaults to the root directory
+ not set, defaults to the root directory
when systemd is running as a system
instance and the respective user's
home directory if run as
@@ -105,7 +104,7 @@
directory for executed processes, with
the
<citerefentry><refentrytitle>chroot</refentrytitle><manvolnum>2</manvolnum></citerefentry>
- system call. If this is used it must
+ system call. If this is used, it must
be ensured that the process and all
its auxiliary files are available in
the <function>chroot()</function>
@@ -129,7 +128,7 @@
<listitem><para>Sets the supplementary
Unix groups the processes are executed
- as. This takes a space separated list
+ as. This takes a space-separated list
of group names or IDs. This option may
be specified more than once in which
case all listed groups are set as
@@ -167,7 +166,7 @@
for this process) and 1000 (to make
killing of this process under memory
pressure very likely). See <ulink
- url="http://www.kernel.org/doc/Documentation/filesystems/proc.txt">proc.txt</ulink>
+ url="https://www.kernel.org/doc/Documentation/filesystems/proc.txt">proc.txt</ulink>
for details.</para></listitem>
</varlistentry>
@@ -234,7 +233,7 @@
<term><varname>CPUSchedulingResetOnFork=</varname></term>
<listitem><para>Takes a boolean
- argument. If true elevated CPU
+ argument. If true, elevated CPU
scheduling priorities and policies
will be reset when the executed
processes fork, and can hence not leak
@@ -253,7 +252,7 @@
be specified more than once in which
case the specificed CPU affinity masks
are merged. If the empty string is
- assigned the mask is reset, all
+ assigned, the mask is reset, all
assignments prior to this will have no
effect. See
<citerefentry><refentrytitle>sched_setaffinity</refentrytitle><manvolnum>2</manvolnum></citerefentry>
@@ -281,15 +280,16 @@
option may be specified more than once
in which case all listed variables
will be set. If the same variable is
- set twice the later setting will
+ set twice, the later setting will
override the earlier setting. If the
empty string is assigned to this
- option the list of environment
+ option, the list of environment
variables is reset, all prior
assignments have no effect.
Variable expansion is not performed
- inside the strings, and $ has no special
- meaning.
+ inside the strings, however, specifier
+ expansion is possible. The $ character has
+ no special meaning.
If you need to assign a value containing spaces
to a variable, use double quotes (")
for the assignment.</para>
@@ -311,7 +311,7 @@
<varname>Environment=</varname> but
reads the environment variables from a
text file. The text file should
- contain new-line separated variable
+ contain new-line-separated variable
assignments. Empty lines and lines
starting with ; or # will be ignored,
which may be used for commenting. A line
@@ -323,17 +323,18 @@
double quotes (").</para>
<para>The argument passed should be an
- absolute file name or wildcard
+ absolute filename or wildcard
expression, optionally prefixed with
- "-", which indicates that if the file
- does not exist it won't be read and no
- error or warning message is logged.
- This option may be specified more than
- once in which case all specified files
- are read. If the empty string is
- assigned to this option the list of
- file to read is reset, all prior
- assignments have no effect.</para>
+ <literal>-</literal>, which indicates
+ that if the file does not exist, it
+ will not be read and no error or warning
+ message is logged. This option may be
+ specified more than once in which case
+ all specified files are read. If the
+ empty string is assigned to this
+ option, the list of file to read is
+ reset, all prior assignments have no
+ effect.</para>
<para>The files listed with this
directive will be read shortly before
@@ -342,7 +343,7 @@
with
<varname>Environment=</varname>. If
the same variable is set twice from
- these files the files will be read in
+ these files, the files will be read in
the order they are specified and the
later setting will override the
earlier setting.</para></listitem>
@@ -358,19 +359,19 @@
<option>tty-force</option>,
<option>tty-fail</option> or
<option>socket</option>. If
- <option>null</option> is selected
+ <option>null</option> is selected,
standard input will be connected to
<filename>/dev/null</filename>,
i.e. all read attempts by the process
will result in immediate EOF. If
- <option>tty</option> is selected
+ <option>tty</option> is selected,
standard input is connected to a TTY
(as configured by
<varname>TTYPath=</varname>, see
below) and the executed process
becomes the controlling process of the
terminal. If the terminal is already
- being controlled by another process the
+ being controlled by another process, the
executed process waits until the current
controlling process releases the
terminal.
@@ -392,7 +393,7 @@
file (see
<citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details) specifies a single socket
- only. If this option is set standard
+ only. If this option is set, standard
input will be connected to the socket
the service was activated from, which
is primarily useful for compatibility
@@ -417,19 +418,19 @@
<option>kmsg+console</option>,
<option>journal+console</option> or
<option>socket</option>. If set to
- <option>inherit</option> the file
+ <option>inherit</option>, the file
descriptor of standard input is
duplicated for standard output. If set
- to <option>null</option> standard
+ to <option>null</option>, standard
output will be connected to
<filename>/dev/null</filename>,
i.e. everything written to it will be
- lost. If set to <option>tty</option>
+ lost. If set to <option>tty</option>,
standard output will be connected to a
tty (as configured via
<varname>TTYPath=</varname>, see
below). If the TTY is used for output
- only the executed process will not
+ only, the executed process will not
become the controlling process of the
terminal, and will not fail or wait
for other processes to release the
@@ -516,7 +517,7 @@
<listitem><para>If the terminal
device specified with
<varname>TTYPath=</varname> is a
- virtual console terminal try to
+ virtual console terminal, try to
deallocate the TTY before and after
execution. This ensures that the
screen and scrollback buffer is
@@ -527,7 +528,7 @@
<term><varname>SyslogIdentifier=</varname></term>
<listitem><para>Sets the process name
to prefix log lines sent to syslog or
- the kernel log buffer with. If not set
+ the kernel log buffer with. If not set,
defaults to the process name of the
executed process. This option is only
useful when
@@ -671,13 +672,13 @@
<varlistentry>
<term><varname>PAMName=</varname></term>
<listitem><para>Sets the PAM service
- name to set up a session as. If set
+ name to set up a session as. If set,
the executed process will be
registered as a PAM session under the
specified service name. This is only
useful in conjunction with the
<varname>User=</varname> setting. If
- not set no PAM session will be opened
+ not set, no PAM session will be opened
for the executed processes. See
<citerefentry><refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum></citerefentry>
for details.</para></listitem>
@@ -686,7 +687,7 @@
<varlistentry>
<term><varname>TCPWrapName=</varname></term>
<listitem><para>If this is a
- socket-activated service this sets the
+ socket-activated service, this sets the
tcpwrap service name to check the
permission for the current connection
with. This is only useful in
@@ -696,7 +697,7 @@
socket types (e.g. datagram/UDP) and
on processes unrelated to socket-based
activation. If the tcpwrap
- verification fails daemon start-up
+ verification fails, daemon start-up
will fail and the connection is
terminated. See
<citerefentry><refentrytitle>tcpd</refentrytitle><manvolnum>8</manvolnum></citerefentry>
@@ -716,17 +717,16 @@
capability bounding set for the
executed process. See
<citerefentry><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
- for details. Takes a whitespace
- separated list of capability names as
- read by
+ for details. Takes a whitespace-separated
+ list of capability names as read by
<citerefentry><refentrytitle>cap_from_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- e.g. <literal>CAP_SYS_ADMIN
- CAP_DAC_OVERRIDE
- CAP_SYS_PTRACE</literal>.
+ e.g. <constant>CAP_SYS_ADMIN</constant>,
+ <constant>CAP_DAC_OVERRIDE</constant>,
+ <constant>CAP_SYS_PTRACE</constant>.
Capabilities listed will be included
in the bounding set, all others are
removed. If the list of capabilities
- is prefixed with <literal>~</literal>
+ is prefixed with <literal>~</literal>,
all but the listed capabilities will
be included, the effect of the
assignment inverted. Note that this
@@ -735,7 +735,7 @@
permitted and inheritable capability
sets, on top of what
<varname>Capabilities=</varname>
- does. If this option is not used the
+ does. If this option is not used, the
capability bounding set is not
modified on process execution, hence
no limits on the capabilities of the
@@ -743,11 +743,11 @@
appear more than once in which case
the bounding sets are merged. If the
empty string is assigned to this
- option the bounding set is reset to
+ option, the bounding set is reset to
the empty capability set, and all
prior settings have no effect. If set
to <literal>~</literal> (without any
- further argument) the bounding set is
+ further argument), the bounding set is
reset to the full set of available
capabilities, also undoing any
previous settings.</para></listitem>
@@ -768,7 +768,7 @@
option may appear more than once in
which case the secure bits are
ORed. If the empty string is assigned
- to this option the bits are reset to
+ to this option, the bits are reset to
0.</para></listitem>
</varlistentry>
@@ -791,287 +791,15 @@
</varlistentry>
<varlistentry>
- <term><varname>ControlGroup=</varname></term>
-
- <listitem><para>Controls the control
- groups the executed processes shall be
- made members of. Takes a
- space-separated list of cgroup
- identifiers. A cgroup identifier is
- formatted like
- <filename noindex='true'>cpu:/foo/bar</filename>,
- where "cpu" indicates the kernel
- control group controller used, and
- <filename noindex='true'>/foo/bar</filename> is the
- control group path. The controller
- name and ":" may be omitted in which
- case the named systemd control group
- hierarchy is implied. Alternatively,
- the path and ":" may be omitted, in
- which case the default control group
- path for this unit is implied.</para>
-
- <para>This option may be used to place
- executed processes in arbitrary groups
- in arbitrary hierarchies -- which may
- then be externally configured with
- additional execution limits. By
- default systemd will place all
- executed processes in separate
- per-unit control groups (named after
- the unit) in the systemd named
- hierarchy. This option is primarily
- intended to place executed processes
- in specific paths in specific kernel
- controller hierarchies. It is not
- recommended to manipulate the service
- control group path in the private
- systemd named hierarchy
- (i.e. <literal>name=systemd</literal>),
- and doing this might result in
- undefined behaviour. For details about
- control groups see <ulink
- url="http://www.kernel.org/doc/Documentation/cgroups/cgroups.txt">cgroups.txt</ulink>.</para>
-
- <para>This option may appear more than
- once, in which case the list of
- control group assignments is
- merged. If the same hierarchy gets two
- different paths assigned only the
- later setting will take effect. If the
- empty string is assigned to this
- option the list of control group
- assignments is reset, all previous
- assignments will have no
- effect.</para>
-
- <para>Note that the list of control
- group assignments of a unit is
- extended implicitly based on the
- settings of
- <varname>DefaultControllers=</varname>
- of
- <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
- but a unit's
- <varname>ControlGroup=</varname>
- setting for a specific controller
- takes precedence.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>ControlGroupModify=</varname></term>
- <listitem><para>Takes a boolean
- argument. If true, the control groups
- created for this unit will be owned by
- the user specified with
- <varname>User=</varname> (and the
- appropriate group), and he/she can create
- subgroups as well as add processes to
- the group.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>ControlGroupPersistent=</varname></term>
- <listitem><para>Takes a boolean
- argument. If true, the control groups
- created for this unit will be marked
- to be persistent, i.e. systemd will
- not remove them when stopping the
- unit. The default is false, meaning
- that the control groups will be
- removed when the unit is stopped. For
- details about the semantics of this
- logic see <ulink
- url="http://www.freedesktop.org/wiki/Software/systemd/PaxControlGroups">PaxControlGroups</ulink>.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>ControlGroupAttribute=</varname></term>
-
- <listitem><para>Set a specific control
- group attribute for executed
- processes, and (if needed) add the
- executed processes to a cgroup in the
- hierarchy of the controller the
- attribute belongs to. Takes two
- space-separated arguments: the
- attribute name (syntax is
- <literal>cpu.shares</literal> where
- <literal>cpu</literal> refers to a
- specific controller and
- <literal>shares</literal> to the
- attribute name), and the attribute
- value. Example:
- <literal>ControlGroupAttribute=cpu.shares
- 512</literal>. If this option is used
- for an attribute that belongs to a
- kernel controller hierarchy the unit
- is not already configured to be added
- to (for example via the
- <literal>ControlGroup=</literal>
- option) then the unit will be added to
- the controller and the default unit
- cgroup path is implied. Thus, using
- <varname>ControlGroupAttribute=</varname>
- is in most cases sufficient to make
- use of control group enforcements,
- explicit
- <varname>ControlGroup=</varname> are
- only necessary in case the implied
- default control group path for a
- service is not desirable. For details
- about control group attributes see
- <ulink
- url="http://www.kernel.org/doc/Documentation/cgroups/cgroups.txt">cgroups.txt</ulink>. This
- option may appear more than once, in
- order to set multiple control group
- attributes. If this option is used
- multiple times for the same cgroup
- attribute only the later setting takes
- effect. If the empty string is
- assigned to this option the list of
- attributes is reset, all previous
- cgroup attribute settings have no
- effect, including those done with
- <varname>CPUShares=</varname>,
- <varname>MemoryLimit=</varname>,
- <varname>MemorySoftLimit</varname>,
- <varname>DeviceAllow=</varname>,
- <varname>DeviceDeny=</varname>,
- <varname>BlockIOWeight=</varname>,
- <varname>BlockIOReadBandwidth=</varname>,
- <varname>BlockIOWriteBandwidth=</varname>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>CPUShares=</varname></term>
-
- <listitem><para>Assign the specified
- overall CPU time shares to the
- processes executed. Takes an integer
- value. This controls the
- <literal>cpu.shares</literal> control
- group attribute, which defaults to
- 1024. For details about this control
- group attribute see <ulink
- url="http://www.kernel.org/doc/Documentation/scheduler/sched-design-CFS.txt">sched-design-CFS.txt</ulink>.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>MemoryLimit=</varname></term>
- <term><varname>MemorySoftLimit=</varname></term>
-
- <listitem><para>Limit the overall memory usage
- of the executed processes to a certain
- size. Takes a memory size in bytes. If
- the value is suffixed with K, M, G or
- T the specified memory size is parsed
- as Kilobytes, Megabytes, Gigabytes,
- or Terabytes (to the base
- 1024), respectively. This controls the
- <literal>memory.limit_in_bytes</literal>
- and
- <literal>memory.soft_limit_in_bytes</literal>
- control group attributes. For details
- about these control group attributes
- see <ulink
- url="http://www.kernel.org/doc/Documentation/cgroups/memory.txt">memory.txt</ulink>.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>DeviceAllow=</varname></term>
- <term><varname>DeviceDeny=</varname></term>
-
- <listitem><para>Control access to
- specific device nodes by the executed processes. Takes two
- space separated strings: a device node
- path (such as
- <filename>/dev/null</filename>)
- followed by a combination of r, w, m
- to control reading, writing, or
- creating of the specific device node
- by the unit, respectively. This controls the
- <literal>devices.allow</literal>
- and
- <literal>devices.deny</literal>
- control group attributes. For details
- about these control group attributes
- see <ulink
- url="http://www.kernel.org/doc/Documentation/cgroups/devices.txt">devices.txt</ulink>.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>BlockIOWeight=</varname></term>
-
- <listitem><para>Set the default or
- per-device overall block IO weight
- value for the executed
- processes. Takes either a single
- weight value (between 10 and 1000) to
- set the default block IO weight, or a
- space separated pair of a file path
- and a weight value to specify the
- device specific weight value (Example:
- "/dev/sda 500"). The file path may be
- specified as path to a block device
- node or as any other file in which
- case the backing block device of the
- file system of the file is
- determined. This controls the
- <literal>blkio.weight</literal> and
- <literal>blkio.weight_device</literal>
- control group attributes, which
- default to 1000. Use this option
- multiple times to set weights for
- multiple devices. For details about
- these control group attributes see
- <ulink
- url="http://www.kernel.org/doc/Documentation/cgroups/blkio-controller.txt">blkio-controller.txt</ulink>.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>BlockIOReadBandwidth=</varname></term>
- <term><varname>BlockIOWriteBandwidth=</varname></term>
-
- <listitem><para>Set the per-device
- overall block IO bandwidth limit for
- the executed processes. Takes a space
- separated pair of a file path and a
- bandwidth value (in bytes per second)
- to specify the device specific
- bandwidth. The file path may be
- specified as path to a block device
- node or as any other file in which
- case the backing block device of the
- file system of the file is determined.
- If the bandwidth is suffixed with K, M,
- G, or T the specified bandwidth is
- parsed as Kilobytes, Megabytes,
- Gigabytes, or Terabytes, respectively (Example:
- "/dev/disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0
- 5M"). This controls the
- <literal>blkio.read_bps_device</literal>
- and
- <literal>blkio.write_bps_device</literal>
- control group attributes. Use this
- option multiple times to set bandwidth
- limits for multiple devices. For
- details about these control group
- attributes see <ulink
- url="http://www.kernel.org/doc/Documentation/cgroups/blkio-controller.txt">blkio-controller.txt</ulink>.</para></listitem>
- </varlistentry>
-
- <varlistentry>
<term><varname>ReadWriteDirectories=</varname></term>
<term><varname>ReadOnlyDirectories=</varname></term>
<term><varname>InaccessibleDirectories=</varname></term>
<listitem><para>Sets up a new
- file-system name space for executed
+ file system namespace for executed
processes. These options may be used
to limit access a process might have
- to the main file-system
+ to the main file system
hierarchy. Each setting takes a
space-separated list of absolute
directory paths. Directories listed in
@@ -1097,16 +825,24 @@
directories listed will have limited
access from within the namespace. If
the empty string is assigned to this
- option the specific list is reset, and
+ option, the specific list is reset, and
all prior assignments have no
- effect.</para></listitem>
+ effect.</para>
+ <para>Paths in
+ <varname>ReadOnlyDirectories=</varname>
+ and
+ <varname>InaccessibleDirectories=</varname>
+ may be prefixed with
+ <literal>-</literal>, in which case
+ they will be ignored when they do not
+ exist.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>PrivateTmp=</varname></term>
<listitem><para>Takes a boolean
- argument. If true sets up a new file
+ argument. If true, sets up a new file
system namespace for the executed
processes and mounts private
<filename>/tmp</filename> and
@@ -1129,7 +865,7 @@
<term><varname>PrivateNetwork=</varname></term>
<listitem><para>Takes a boolean
- argument. If true sets up a new
+ argument. If true, sets up a new
network namespace for the executed
processes and configures only the
loopback network device
@@ -1171,7 +907,7 @@
entries must be created and cleared
before and after execution. If the
configured string is longer than four
- characters it is truncated and the
+ characters, it is truncated and the
terminal four characters are
used. This setting interprets %I style
string replacements. This setting is
@@ -1184,10 +920,10 @@
<term><varname>IgnoreSIGPIPE=</varname></term>
<listitem><para>Takes a boolean
- argument. If true causes SIGPIPE to be
+ argument. If true, causes <constant>SIGPIPE</constant> to be
ignored in the executed
- process. Defaults to true, since
- SIGPIPE generally is useful only in
+ process. Defaults to true because
+ <constant>SIGPIPE</constant> generally is useful only in
shell pipelines.</para></listitem>
</varlistentry>
@@ -1195,7 +931,7 @@
<term><varname>NoNewPrivileges=</varname></term>
<listitem><para>Takes a boolean
- argument. If true ensures that the
+ argument. If true, ensures that the
service process and all its children
can never gain new privileges. This
option is more powerful than the respective
@@ -1210,19 +946,20 @@
<varlistentry>
<term><varname>SystemCallFilter=</varname></term>
- <listitem><para>Takes a space
- separated list of system call
- names. If this setting is used all
+ <listitem><para>Takes a space-separated
+ list of system call
+ names. If this setting is used, all
system calls executed by the unit
process except for the listed ones
will result in immediate process
- termination with the SIGSYS signal
+ termination with the
+ <constant>SIGSYS</constant> signal
(whitelisting). If the first character
- of the list is <literal>~</literal>
+ of the list is <literal>~</literal>,
the effect is inverted: only the
listed system calls will result in
immediate process termination
- (blacklisting). If this option is used
+ (blacklisting). If this option is used,
<varname>NoNewPrivileges=yes</varname>
is implied. This feature makes use of
the Secure Computing Mode 2 interfaces
@@ -1234,12 +971,12 @@
<function>sigreturn</function>,
<function>exit_group</function>,
<function>exit</function> system calls
- are implicitly whitelisted and don't
+ are implicitly whitelisted and do not
need to be listed explicitly. This
option may be specified more than once
in which case the filter masks are
merged. If the empty string is
- assigned the filter is reset, all
+ assigned, the filter is reset, all
prior assignments will have no
effect.</para></listitem>
</varlistentry>
@@ -1248,6 +985,118 @@
</refsect1>
<refsect1>
+ <title>Environment variables in spawned processes</title>
+
+ <para>Processes started by the system are executed in
+ a clean environment in which select variables
+ listed below are set. System processes started by systemd
+ do not inherit variables from PID 1, but processes
+ started by user systemd instances inherit all
+ environment variables from the user systemd instance.
+ </para>
+
+ <variablelist class='environment-variables'>
+ <varlistentry>
+ <term><varname>$PATH</varname></term>
+
+ <listitem><para>Colon-separated list
+ of directiories to use when launching
+ executables. Systemd uses a fixed
+ value of
+ <filename>/usr/local/sbin</filename>:<filename>/usr/local/bin</filename>:<filename>/usr/sbin</filename>:<filename>/usr/bin</filename>:<filename>/sbin</filename>:<filename>/bin</filename>.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>$LANG</varname></term>
+
+ <listitem><para>Locale. Can be set in
+ <citerefentry><refentrytitle>locale.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ or on the kernel command line (see
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ and
+ <citerefentry><refentrytitle>kernel-command-line</refentrytitle><manvolnum>7</manvolnum></citerefentry>).
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>$USER</varname></term>
+ <term><varname>$HOME</varname></term>
+
+ <listitem><para>User name and home
+ directory. Set for the units which
+ have <varname>User=</varname> set,
+ which includes user
+ <command>systemd</command> instances.
+ See
+ <citerefentry><refentrytitle>passwd</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>$XDG_RUNTIME_DIR</varname></term>
+
+ <listitem><para>The directory for volatile
+ state. Set for the user <command>systemd</command>
+ instance, and also in user sessions.
+ See
+ <citerefentry><refentrytitle>pam_systemd</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>$XDG_SESSION_ID</varname></term>
+ <term><varname>$XDG_SEAT</varname></term>
+ <term><varname>$XDG_VTNR</varname></term>
+
+ <listitem><para>The identifier of the
+ session, and the seat name, and
+ virtual terminal of the session. Set
+ by
+ <citerefentry><refentrytitle>pam_systemd</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ for login sessions.
+ <varname>$XDG_SEAT</varname> and
+ <varname>$XDG_VTNR</varname> will be
+ only set when attached to a seat and a
+ tty.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>$MANAGERPID</varname></term>
+
+ <listitem><para>The PID of the user
+ <command>systemd</command> instance,
+ set for processes spawned by it.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>$LISTEN_FDS</varname></term>
+ <term><varname>$LISTEN_PID</varname></term>
+
+ <listitem><para>Information about file
+ descriptors passed to a service for
+ socket activation. See
+ <citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+ </para></listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>Additional variables may be configured by the
+ following means: for processes spawned in specific
+ units, use the <varname>Environment=</varname> and
+ <varname>EnvironmentFile=</varname> options above; to
+ specify variables globally, use
+ <varname>DefaultEnvironment=</varname> (see
+ <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>)
+ or the kernel option
+ <varname>systemd.setenv=</varname> (see
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>). Additional
+ variables may also be set through PAM,
+ c.f. <citerefentry><refentrytitle>pam_env</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+ </refsect1>
+
+ <refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
@@ -1259,7 +1108,9 @@
<citerefentry><refentrytitle>systemd.swap</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>exec</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/systemd.journal-fields.xml b/man/systemd.journal-fields.xml
index a0f1bfda13..8a15598e63 100644
--- a/man/systemd.journal-fields.xml
+++ b/man/systemd.journal-fields.xml
@@ -72,7 +72,7 @@
<varlistentry>
<term><varname>MESSAGE=</varname></term>
<listitem>
- <para>The human readable
+ <para>The human-readable
message string for this
entry. This is supposed to be
the primary text shown to the
@@ -87,22 +87,22 @@
<varlistentry>
<term><varname>MESSAGE_ID=</varname></term>
<listitem>
- <para>A 128bit message
+ <para>A 128-bit message
identifier ID for recognizing
certain message types, if this
is desirable. This should
- contain a 128bit id formatted
- as lower-case hexadecimal
+ contain a 128-bit ID formatted
+ as a lower-case hexadecimal
string, without any separating
dashes or suchlike. This is
- recommended to be a UUID
- compatible ID, but this is not
+ recommended to be a
+ UUID-compatible ID, but this is not
enforced, and formatted
differently. Developers can
generate a new ID for this
- purpose with
- <command>journalctl
- --new-id</command>.</para>
+ purpose with <command>journalctl
+ <option>--new-id</option></command>.
+ </para>
</listitem>
</varlistentry>
@@ -113,7 +113,7 @@
0 (<literal>emerg</literal>)
and 7
(<literal>debug</literal>)
- formatted as decimal
+ formatted as a decimal
string. This field is
compatible with syslog's
priority concept.</para>
@@ -128,7 +128,7 @@
<para>The code location
generating this message, if
known. Contains the source
- file name, the line number and
+ filename, the line number and
the function name.</para>
</listitem>
</varlistentry>
@@ -141,7 +141,7 @@
any. Contains the numeric
value of
<citerefentry><refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum></citerefentry>
- formatted as decimal
+ formatted as a decimal
string.</para>
</listitem>
</varlistentry>
@@ -179,7 +179,7 @@
<para>The process, user and
group ID of the process the
journal entry originates from
- formatted as decimal
+ formatted as a decimal
string.</para>
</listitem>
</varlistentry>
@@ -197,6 +197,15 @@
</varlistentry>
<varlistentry>
+ <term><varname>_CAP_EFFECTIVE=</varname></term>
+ <listitem>
+ <para>The effective <citerefentry><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry> of
+ the process the journal entry
+ originates from.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>_AUDIT_SESSION=</varname></term>
<term><varname>_AUDIT_LOGINUID=</varname></term>
<listitem>
@@ -214,17 +223,20 @@
<term><varname>_SYSTEMD_UNIT=</varname></term>
<term><varname>_SYSTEMD_USER_UNIT=</varname></term>
<term><varname>_SYSTEMD_OWNER_UID=</varname></term>
+ <term><varname>_SYSTEMD_SLICE=</varname></term>
<listitem>
- <para>The control group path in
- the systemd hierarchy, the
+ <para>The control group path
+ in the systemd hierarchy, the
systemd session ID (if any),
- the systemd unit name (if any),
- the systemd user session unit name (if any)
- and the owner UID of the
- systemd session (if any) of
- the process the journal entry
- originates from.</para>
+ the systemd unit name (if
+ any), the systemd user session
+ unit name (if any), the owner
+ UID of the systemd session (if
+ any) and the systemd slice
+ unit of the process the
+ journal entry originates
+ from.</para>
</listitem>
</varlistentry>
@@ -246,8 +258,8 @@
any is known that is different
from the reception time of the
journal. This is the time in
- usec since the epoch UTC
- formatted as decimal
+ microseconds since the epoch UTC,
+ formatted as a decimal
string.</para>
</listitem>
</varlistentry>
@@ -258,7 +270,7 @@
<para>The kernel boot ID for
the boot the message was
generated in, formatted as
- 128bit hexadecimal
+ a 128-bit hexadecimal
string.</para>
</listitem>
</varlistentry>
@@ -286,23 +298,75 @@
<listitem>
<para>How the entry was
received by the journal
- service. One of
- <literal>driver</literal>,
- <literal>syslog</literal>,
- <literal>journal</literal>,
- <literal>stdout</literal>,
- <literal>kernel</literal> for
- internally generated messages,
- for those received via the
- local syslog socket with the
- syslog protocol, for those
- received via the native
- journal protocol, for the
- those read from a services'
- standard output or error
- output, or for those read
- from the kernel, respectively.
+ service. Valid transports are:
</para>
+ <variablelist>
+ <varlistentry>
+ <term>
+ <option>driver</option>
+ </term>
+ <listitem>
+ <para>for
+ internally
+ generated
+ messages
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>syslog</option>
+ </term>
+ <listitem>
+ <para>for those
+ received via the
+ local syslog
+ socket with the
+ syslog protocol
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>journal</option>
+ </term>
+ <listitem>
+ <para>for those
+ received via the
+ native journal
+ protocol
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>stdout</option>
+ </term>
+ <listitem>
+ <para>for those
+ read from a
+ service's
+ standard output
+ or error output
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>kernel</option>
+ </term>
+ <listitem>
+ <para>for those
+ read from the
+ kernel
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
</listitem>
</varlistentry>
</variablelist>
@@ -323,15 +387,15 @@
name. If the entry is
associated to a block device,
the major and minor of the
- device node, separated by ':'
- and prefixed by 'b'. Similar
+ device node, separated by <literal>:</literal>
+ and prefixed by <literal>b</literal>. Similar
for character devices, but
- prefixed by 'c'. For network
+ prefixed by <literal>c</literal>. For network
devices the interface index,
- prefixed by 'n'. For all other
- devices '+' followed by the
+ prefixed by <literal>n</literal>. For all other
+ devices <literal>+</literal> followed by the
subsystem name, followed by
- ':', followed by the kernel
+ <literal>:</literal>, followed by the kernel
device name.</para>
</listitem>
</varlistentry>
@@ -372,10 +436,15 @@
</refsect1>
<refsect1>
- <title>Special Journal Fields</title>
+ <title>Fields to log on behalf of a different program</title>
+
+ <para>Fields in this section are used by programs
+ to specify that they are logging on behalf of another
+ program or unit.
+ </para>
<para>Fields used by the <command>systemd-coredump</command>
- coredump kernel helper.
+ coredump kernel helper:
</para>
<variablelist class='journal-directives'>
@@ -392,6 +461,61 @@
</listitem>
</varlistentry>
</variablelist>
+
+ <para>Priviledged programs (currently UID 0) may
+ attach <varname>OBJECT_PID=</varname> to a
+ message. This will instruct
+ <command>systemd-journald</command> to attach
+ additional fields on behalf of the caller:</para>
+
+ <variablelist class='journal-directives'>
+ <varlistentry>
+ <term><varname>OBJECT_PID=<replaceable>PID</replaceable></varname></term>
+ <listitem>
+ <para>PID of the program that this
+ message pertains to.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>OBJECT_UID=</varname></term>
+ <term><varname>OBJECT_GID=</varname></term>
+ <term><varname>OBJECT_COMM=</varname></term>
+ <term><varname>OBJECT_EXE=</varname></term>
+ <term><varname>OBJECT_CMDLINE=</varname></term>
+ <term><varname>OBJECT_AUDIT_SESSION=</varname></term>
+ <term><varname>OBJECT_AUDIT_LOGINUID=</varname></term>
+ <term><varname>OBJECT_SYSTEMD_CGROUP=</varname></term>
+ <term><varname>OBJECT_SYSTEMD_SESSION=</varname></term>
+ <term><varname>OBJECT_SYSTEMD_OWNER_UID=</varname></term>
+ <term><varname>OBJECT_SYSTEMD_UNIT=</varname></term>
+ <term><varname>OBJECT_SYSTEMD_USER_UNIT=</varname></term>
+ <listitem>
+ <para>These are additional fields added automatically
+ by <command>systemd-journald</command>.
+ Their meaning is the same as
+ <varname>_UID=</varname>,
+ <varname>_GID=</varname>,
+ <varname>_COMM=</varname>,
+ <varname>_EXE=</varname>,
+ <varname>_CMDLINE=</varname>,
+ <varname>_AUDIT_SESSION=</varname>,
+ <varname>_AUDIT_LOGINUID=</varname>,
+ <varname>_SYSTEMD_CGROUP=</varname>,
+ <varname>_SYSTEMD_SESSION=</varname>,
+ <varname>_SYSTEMD_UNIT=</varname>,
+ <varname>_SYSTEMD_USER_UNIT=</varname>, and
+ <varname>_SYSTEMD_OWNER_UID=</varname>
+ as described above, except that the
+ process identified by <replaceable>PID</replaceable>
+ is described, instead of the process
+ which logged the message.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+
</refsect1>
<refsect1>
@@ -404,8 +528,8 @@
url="http://www.freedesktop.org/wiki/Software/systemd/json">Journal
JSON Format</ulink>, the addresses of journal entries
are serialized into fields prefixed with double
- underscores. Note that these aren't proper fields when
- stored in the journal, but addressing meta data of
+ underscores. Note that these are not proper fields when
+ stored in the journal but for addressing meta data of
entries. They cannot be written as part of structured
log entries via calls such as
<citerefentry><refentrytitle>sd_journal_send</refentrytitle><manvolnum>3</manvolnum></citerefentry>. They
@@ -422,8 +546,8 @@
describes the position of an
entry in the journal and is
portable across machines,
- platforms and journal
- files.</para>
+ platforms and journal files.
+ </para>
</listitem>
</varlistentry>
@@ -431,16 +555,17 @@
<term><varname>__REALTIME_TIMESTAMP=</varname></term>
<listitem>
<para>The wallclock time
- (CLOCK_REALTIME) at the point
- in time the entry was received
- by the journal, in usec since
- the epoch UTC formatted as
- decimal string. This has
- different properties from
- <literal>_SOURCE_REALTIME_TIMESTAMP=</literal>
+ (<constant>CLOCK_REALTIME</constant>)
+ at the point in time the entry
+ was received by the journal,
+ in microseconds since the epoch
+ UTC, formatted as a decimal
+ string. This has different
+ properties from
+ <literal>_SOURCE_REALTIME_TIMESTAMP=</literal>,
as it is usually a bit later
- but more likely to be
- monotonic.</para>
+ but more likely to be monotonic.
+ </para>
</listitem>
</varlistentry>
@@ -448,15 +573,15 @@
<term><varname>__MONOTONIC_TIMESTAMP=</varname></term>
<listitem>
<para>The monotonic time
- (CLOCK_MONOTONIC) at the point
- in time the entry was received
- by the journal in usec
- formatted as decimal
+ (<constant>CLOCK_MONOTONIC</constant>)
+ at the point in time the entry
+ was received by the journal in
+ microseconds, formatted as a decimal
string. To be useful as an
- address for the entry this
- should be combined with with
- boot ID in
- <literal>_BOOT_ID=</literal>.</para>
+ address for the entry, this
+ should be combined with with the
+ boot ID in <literal>_BOOT_ID=</literal>.
+ </para>
</listitem>
</varlistentry>
</variablelist>
diff --git a/man/systemd.kill.xml b/man/systemd.kill.xml
index b41ce460b5..1b10fba9d5 100644
--- a/man/systemd.kill.xml
+++ b/man/systemd.kill.xml
@@ -94,16 +94,16 @@
<option>none</option>.</para>
<para>If set to
- <option>control-group</option> all
+ <option>control-group</option>, all
remaining processes in the control
group of this unit will be terminated
on unit stop (for services: after the
stop command is executed, as
configured with
<varname>ExecStop=</varname>). If set
- to <option>process</option> only the
+ to <option>process</option>, only the
main process itself is killed. If set
- to <option>none</option> no process is
+ to <option>none</option>, no process is
killed. In this case only the stop
command will be executed on unit
stop, but no process be killed
@@ -115,16 +115,21 @@
<option>control-group</option>.</para>
<para>Processes will first be
- terminated via SIGTERM (unless the
- signal to send is changed via
- <varname>KillSignal=</varname>). If
- then after a delay (configured via the
- <varname>TimeoutSec=</varname> option)
+ terminated via
+ <constant>SIGTERM</constant> (unless
+ the signal to send is changed via
+ <varname>KillSignal=</varname>). Optionally,
+ this is immediately followed by a
+ <constant>SIGHUP</constant> (if
+ enabled with
+ <varname>SendSIGHUP=</varname>). If
+ then, after a delay (configured via the
+ <varname>TimeoutStopSec=</varname> option),
processes still remain, the
termination request is repeated with
- the SIGKILL signal (unless this is
- disabled via the
- <varname>SendSIGKILL=</varname>
+ the <constant>SIGKILL</constant>
+ signal (unless this is disabled via
+ the <varname>SendSIGKILL=</varname>
option). See
<citerefentry><refentrytitle>kill</refentrytitle><manvolnum>2</manvolnum></citerefentry>
for more
@@ -135,20 +140,35 @@
<term><varname>KillSignal=</varname></term>
<listitem><para>Specifies which signal
to use when killing a
- service. Defaults to SIGTERM.
+ service. Defaults to <constant>SIGTERM</constant>.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>SendSIGHUP=</varname></term>
+ <listitem><para>Specifies whether to
+ send <constant>SIGHUP</constant> to
+ remaining processes immediately after
+ sending the signal configured with
+ <varname>KillSignal=</varname>. This
+ is useful to indicate to shells and
+ shell-like programs that their
+ connection has been severed. Takes a
+ boolean value. Defaults to "no".
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>SendSIGKILL=</varname></term>
<listitem><para>Specifies whether to
- send SIGKILL to remaining processes
+ send <constant>SIGKILL</constant> to remaining processes
after a timeout, if the normal
shutdown procedure left processes of
the service around. Takes a boolean
value. Defaults to "yes".
</para></listitem>
</varlistentry>
+
</variablelist>
</refsect1>
diff --git a/man/systemd.mount.xml b/man/systemd.mount.xml
index 21177a2623..48af1caace 100644
--- a/man/systemd.mount.xml
+++ b/man/systemd.mount.xml
@@ -55,7 +55,7 @@
<title>Description</title>
<para>A unit configuration file whose name ends in
- <filename>.mount</filename> encodes information about
+ <literal>.mount</literal> encodes information about
a file system mount point controlled and supervised by
systemd.</para>
@@ -73,14 +73,18 @@
which define the execution environment the
<citerefentry><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry>
binary is executed in, and in
- <citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- which define the way the processes are
- terminated. Note that the User= and Group= options are
- not particularly useful for mount units specifying a
- <literal>Type=</literal> option or using configuration
- not specified in <filename>/etc/fstab</filename>;
+ <citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ which define the way the processes are terminated, and
+ in
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ which configure resource control settings for the
+ processes of the service. Note that the User= and
+ Group= options are not particularly useful for mount
+ units specifying a <literal>Type=</literal> option or
+ using configuration not specified in
+ <filename>/etc/fstab</filename>;
<citerefentry><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- will refuse options that aren't listed in
+ will refuse options that are not listed in
<filename>/etc/fstab</filename> if it is not run as
UID 0.</para>
@@ -147,7 +151,7 @@
<citerefentry><refentrytitle>systemd.automount</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details. If
<option>x-systemd.device-timeout=</option> is
- specified it may be used to configure how long systemd
+ specified, it may be used to configure how long systemd
should wait for a device to show up before giving up
on an entry from
<filename>/etc/fstab</filename>. Specify a time in
@@ -157,9 +161,9 @@
<para>If a mount point is configured in both
<filename>/etc/fstab</filename> and a unit file that
- is stored below <filename>/usr</filename> the former
+ is stored below <filename>/usr</filename>, the former
will take precedence. If the unit file is stored below
- <filename>/etc</filename> it will take
+ <filename>/etc</filename>, it will take
precedence. This means: native unit files take
precedence over traditional configuration files, but
this is superseded by the rule that configuration in
@@ -206,14 +210,14 @@
the mount point does not exist at the
time of mounting, it is created. This
string must be reflected in the unit
- file name. (See above.) This option is
+ filename. (See above.) This option is
mandatory.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>Type=</varname></term>
<listitem><para>Takes a string for the
- filesystem type. See
+ file system type. See
<citerefentry><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry>
for details. This setting is
optional.</para></listitem>
@@ -223,8 +227,8 @@
<term><varname>Options=</varname></term>
<listitem><para>Mount options to use
- when mounting. This takes a comma
- separated list of options. This
+ when mounting. This takes a
+ comma-separated list of options. This
setting is optional.</para></listitem>
</varlistentry>
@@ -245,12 +249,12 @@
<listitem><para>Configures the time to
wait for the mount command to
finish. If a command does not exit
- within the configured time the mount
+ within the configured time, the mount
will be considered failed and be shut
down again. All commands still running
will be terminated forcibly via
- SIGTERM, and after another delay of
- this time with SIGKILL. (See
+ <constant>SIGTERM</constant>, and after another delay of
+ this time with <constant>SIGKILL</constant>. (See
<option>KillMode=</option> in
<citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>.)
Takes a unit-less value in seconds, or
@@ -298,6 +302,7 @@
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.device</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>proc</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
diff --git a/man/systemd.path.xml b/man/systemd.path.xml
index 1975142d2c..8d86fca5d6 100644
--- a/man/systemd.path.xml
+++ b/man/systemd.path.xml
@@ -55,7 +55,7 @@
<title>Description</title>
<para>A unit configuration file whose name ends in
- <filename>.path</filename> encodes information about
+ <literal>.path</literal> encodes information about
a path monitored by systemd, for
path-based activation.</para>
@@ -120,7 +120,7 @@
<varname>PathExists=</varname> may be
used to watch the mere existence of a
file or directory. If the file
- specified exists the configured unit
+ specified exists, the configured unit
is
activated. <varname>PathExistsGlob=</varname>
works similar, but checks for the
@@ -151,7 +151,7 @@
combined, of the same and of different
types, to watch multiple paths. If the
empty string is assigned to any of
- these options the list of paths to
+ these options, the list of paths to
watch is reset, and any prior
assignments of these options will not
have any effect.</para>
@@ -185,7 +185,7 @@
when any of the configured paths
changes. The argument is a unit name,
whose suffix is not
- <filename>.path</filename>. If not
+ <literal>.path</literal>. If not
specified, this value defaults to a
service that has the same name as the
path unit, except for the suffix. (See
@@ -199,7 +199,7 @@
<term><varname>MakeDirectory=</varname></term>
<listitem><para>Takes a boolean
- argument. If true the directories to
+ argument. If true, the directories to
watch are created before
watching. This option is ignored for
<varname>PathExists=</varname>
@@ -211,7 +211,7 @@
<listitem><para>If
<varname>MakeDirectory=</varname> is
- enabled use the mode specified here to
+ enabled, use the mode specified here to
create the directories in
question. Takes an access mode in
octal notation. Defaults to
diff --git a/man/systemd.preset.xml b/man/systemd.preset.xml
index a692053876..16db8cd85b 100644
--- a/man/systemd.preset.xml
+++ b/man/systemd.preset.xml
@@ -86,7 +86,7 @@
<para>If no preset files exist, <command>systemctl
preset</command> will enable all units that are
installed by default. If this is not desired and all
- units shall rather be disabled it is necessary to ship
+ units shall rather be disabled, it is necessary to ship
a preset file with a single, catchall
"<filename>disable *</filename>" line. (See example 1,
below.)</para>
@@ -109,7 +109,7 @@
by default, <literal>disable</literal> to disable
units by default.</para>
- <para>If multiple lines apply to a unit name the
+ <para>If multiple lines apply to a unit name, the
first matching one takes precedence over all
others.</para>
@@ -125,20 +125,19 @@
<filename>/etc/</filename> are reserved for the local
administrator, who may use this logic to override the
preset files installed by vendor packages. All preset
- files are sorted by their filename in alphabetical
+ files are sorted by their filename in lexicographic
order, regardless in which of the directories they
- reside, to guarantee that a specific preset file takes
- precedence over another file with an alphabetically
- earlier name, if both files contain lines that apply
- to the same unit names. It is recommended to prefix
- all file names with two-digit number, to simplify
- ordering.</para>
+ reside. If multiple files specify the same unit name,
+ the entry in the file with the lexicographically earliest
+ name will be applied. 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 preset
- file supplied by the vendor the recommended way is to
+ file supplied by the vendor, the recommended way is to
place a symlink to <filename>/dev/null</filename> in
<filename>/etc/systemd/system-preset/</filename>
- bearing the same file name.</para>
+ bearing the same filename.</para>
</refsect1>
<refsect1>
@@ -150,8 +149,8 @@
<programlisting>disable *</programlisting>
</example>
- <para>This disables all units. Due to the file name
- prefix <literal>99-</literal> it will be read last and
+ <para>This disables all units. Due to the filename
+ prefix <literal>99-</literal>, it will be read last and
hence can easily be overridden by spin or
administrator preset policy or suchlike.</para>
@@ -187,7 +186,7 @@ disable *</programlisting>
<para>This enables three specific services and
disables all others. This is useful for administrators
to specifically select the units to enable, and
- disable all others. Due to the file name prefix
+ disable all others. Due to the filename prefix
<literal>00-</literal> it will be read early and hence
overrides all other preset policy files.</para>
</refsect1>
diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml
new file mode 100644
index 0000000000..868890590d
--- /dev/null
+++ b/man/systemd.resource-control.xml
@@ -0,0 +1,353 @@
+<?xml version='1.0'?> <!--*-nxml-*-->
+<?xml-stylesheet type="text/xsl" href="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+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/>.
+-->
+
+<refentry id="systemd.resource-control">
+ <refentryinfo>
+ <title>systemd.resource-control</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>systemd.resource-control</refentrytitle>
+ <manvolnum>5</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>systemd.resource-control</refname>
+ <refpurpose>Resource control unit settings</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <para>
+ <filename><replaceable>slice</replaceable>.slice</filename>,
+ <filename><replaceable>scope</replaceable>.scope</filename>,
+ <filename><replaceable>service</replaceable>.service</filename>,
+ <filename><replaceable>socket</replaceable>.socket</filename>,
+ <filename><replaceable>mount</replaceable>.mount</filename>,
+ <filename><replaceable>swap</replaceable>.swap</filename>
+ </para>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para>Unit configuration files for services, slices, scopes,
+ sockets, mount points, and swap devices share a subset of
+ configuration options for resource control of spawned
+ processes. Internally, this relies on the the Control Groups
+ kernel concept for organizing processes in a hierarchial tree of
+ named groups for the purpose of resource management.</para>
+
+ <para>This man page lists the configuration options shared by
+ those six unit types. See
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for the common options of all unit configuration files, and
+ <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.scope</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ and
+ <citerefentry><refentrytitle>systemd.swap</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for more information on the specific unit configuration files. The
+ resource control configuration options are configured in the
+ [Slice], [Scope], [Service], [Socket], [Mount], or [Swap]
+ sections, depending on the unit type.</para>
+
+ <para>See the <ulink
+ url="http://www.freedesktop.org/wiki/Software/systemd/ControlGroupInterface/">New
+ Control Group Interfaces</ulink> for an introduction how to make
+ use of resource control APIs from programs.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Options</title>
+
+ <para>Units of the types listed above can have settings
+ for resource control configuration:</para>
+
+ <variablelist class='unit-directives'>
+
+ <varlistentry>
+ <term><varname>CPUAccounting=</varname></term>
+
+ <listitem>
+ <para>Turn on CPU usage accounting for this unit. Takes a
+ boolean argument. Note that turning on CPU accounting for
+ one unit might also implicitly turn it on for all units
+ contained in the same slice and for all its parent slices and
+ the units contained therein.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>CPUShares=<replaceable>weight</replaceable></varname></term>
+
+ <listitem>
+ <para>Assign the specified overall CPU time share weight to
+ the processes executed. Takes an integer value. This
+ controls the <literal>cpu.shares</literal> control group
+ attribute, which defaults to 1024. For details about this
+ control group attribute, see <ulink
+ url="https://www.kernel.org/doc/Documentation/scheduler/sched-design-CFS.txt">sched-design-CFS.txt</ulink>.</para>
+
+ <para>Implies <literal>CPUAccounting=true</literal>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>MemoryAccounting=</varname></term>
+
+ <listitem>
+ <para>Turn on process and kernel memory accounting for this
+ unit. Takes a boolean argument. Note that turning on memory
+ accounting for one unit might also implicitly turn it on for
+ all units contained in the same slice and for all its parent
+ slices and the units contained therein.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>MemoryLimit=<replaceable>bytes</replaceable></varname></term>
+
+ <listitem>
+ <para>Specify the limit on maximum memory usage of the
+ executed processes. The limit specifies how much process and
+ kernel memory can be used by tasks in this unit. Takes a
+ memory size in bytes. If the value is suffixed with K, M, G
+ or T, the specified memory size is parsed as Kilobytes,
+ Megabytes, Gigabytes, or Terabytes (with the base 1024),
+ respectively. This controls the
+ <literal>memory.limit_in_bytes</literal> control group
+ attribute. For details about this control group attribute,
+ see <ulink
+ url="https://www.kernel.org/doc/Documentation/cgroups/memory.txt">memory.txt</ulink>.</para>
+
+ <para>Implies <literal>MemoryAccounting=true</literal>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>BlockIOAccounting=</varname></term>
+
+ <listitem>
+ <para>Turn on Block IO accounting for this unit. Takes a
+ boolean argument. Note that turning on block IO accounting
+ for one unit might also implicitly turn it on for all units
+ contained in the same slice and all for its parent slices and
+ the units contained therein.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>BlockIOWeight=<replaceable>weight</replaceable></varname></term>
+
+ <listitem><para>Set the default
+ overall block IO weight for the
+ executed processes. Takes a single
+ weight value (between 10 and 1000) to
+ set the default block IO weight. This
+ controls the
+ <literal>blkio.weight</literal>
+ control group attribute, which
+ defaults to 1000. For details about
+ this control group attribute, see
+ <ulink
+ url="https://www.kernel.org/doc/Documentation/cgroups/blkio-controller.txt">blkio-controller.txt</ulink>.</para>
+
+ <para>Implies
+ <literal>BlockIOAccounting=true</literal>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>BlockIODeviceWeight=<replaceable>device</replaceable> <replaceable>weight</replaceable></varname></term>
+
+ <listitem>
+ <para>Set the per-device overall block IO weight for the
+ executed processes. Takes a space-separated pair of a file
+ path and a weight value to specify the device specific
+ weight value, between 10 and 1000. (Example: "/dev/sda
+ 500"). The file path may be specified as path to a block
+ device node or as any other file in which case the backing
+ block device of the file system of the file is
+ determined. This controls the
+ <literal>blkio.weight_device</literal> control group
+ attribute, which defaults to 1000. Use this option multiple
+ times to set weights for multiple devices. For details about
+ this control group attribute, see <ulink
+ url="https://www.kernel.org/doc/Documentation/cgroups/blkio-controller.txt">blkio-controller.txt</ulink>.</para>
+
+ <para>Implies
+ <literal>BlockIOAccounting=true</literal>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>BlockIOReadBandwidth=<replaceable>device</replaceable> <replaceable>bytes</replaceable></varname></term>
+ <term><varname>BlockIOWriteBandwidth=<replaceable>device</replaceable> <replaceable>bytes</replaceable></varname></term>
+
+ <listitem>
+ <para>Set the per-device overall block IO bandwidth limit
+ for the executed processes. Takes a space-separated pair of
+ a file path and a bandwidth value (in bytes per second) to
+ specify the device specific bandwidth. The file path may be
+ a path to a block device node, or as any other file in which
+ case the backing block device of the file system of the file
+ is used. If the bandwidth is suffixed with K, M, G, or T,
+ the specified bandwidth is parsed as Kilobytes, Megabytes,
+ Gigabytes, or Terabytes, respectively (Example:
+ "/dev/disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0 5M"). This
+ controls the <literal>blkio.read_bps_device</literal> and
+ <literal>blkio.write_bps_device</literal> control group
+ attributes. Use this option multiple times to set bandwidth
+ limits for multiple devices. For details about these control
+ group attributes, see
+ <ulink url="https://www.kernel.org/doc/Documentation/cgroups/blkio-controller.txt">blkio-controller.txt</ulink>.
+ </para>
+
+ <para>Implies
+ <literal>BlockIOAccounting=true</literal>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>DeviceAllow=</varname></term>
+
+ <listitem>
+ <para>Control access to specific device nodes by the
+ executed processes. Takes two space-separated strings: a
+ device node path (such as <filename>/dev/null</filename>)
+ followed by a combination of <constant>r</constant>,
+ <constant>w</constant>, <constant>m</constant> to control
+ <emphasis>r</emphasis>eading, <emphasis>w</emphasis>riting,
+ or creation of the specific device node by the unit
+ (<emphasis>m</emphasis>knod), respectively. This controls
+ the <literal>devices.allow</literal> and
+ <literal>devices.deny</literal> control group
+ attributes. For details about these control group attributes,
+ see <ulink
+ url="https://www.kernel.org/doc/Documentation/cgroups/devices.txt">devices.txt</ulink>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>DevicePolicy=auto|closed|strict</varname></term>
+
+ <listitem>
+ <para>
+ Control the policy for allowing device access:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term><option>strict</option></term>
+ <listitem>
+ <para>means to only allow types of access that are
+ explicitly specified.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>closed</option></term>
+ <listitem>
+ <para>in addition, allows access to standard pseudo
+ devices including
+ <filename>/dev/null</filename>,
+ <filename>/dev/zero</filename>,
+ <filename>/dev/full</filename>,
+ <filename>/dev/random</filename>, and
+ <filename>/dev/urandom</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>auto</option></term>
+ <listitem>
+ <para>
+ in addition, allows access to all devices if no
+ explicit <varname>DeviceAllow=</varname> is present.
+ This is the default.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>Slice=</varname></term>
+
+ <listitem>
+ <para>The name of the slice unit to place the unit
+ in. Defaults to <filename>system.slice</filename> for all
+ non-instantiated units of all unit types (except for slice
+ units themselves see below). Instance units are by default
+ placed in a subslice of <filename>system.slice</filename>
+ that is named after the template name.</para>
+
+ <para>This option may be used to arrange systemd units in a
+ hierarchy of slices each of which might have resource
+ settings applied.</para>
+
+ <para>For units of type slice, the only accepted value for
+ this setting is the parent slice. Since the name of a slice
+ unit implies the parent slice, it is hence redundant to ever
+ set this parameter directly for slice units.</para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.scope</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.swap</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ The documentation for control groups and specific controllers in the Linux kernel:
+ <ulink url="https://www.kernel.org/doc/Documentation/cgroups/cgroups.txt">cgroups.txt</ulink>,
+ <ulink url="https://www.kernel.org/doc/Documentation/cgroups/cpuacct.txt">cpuacct.txt</ulink>,
+ <ulink url="https://www.kernel.org/doc/Documentation/cgroups/memory.txt">memory.txt</ulink>,
+ <ulink url="https://www.kernel.org/doc/Documentation/cgroups/blkio-controller.txt">blkio-controller.txt</ulink>.
+ </para>
+ </refsect1>
+</refentry>
diff --git a/man/systemd.scope.xml b/man/systemd.scope.xml
new file mode 100644
index 0000000000..392abbf151
--- /dev/null
+++ b/man/systemd.scope.xml
@@ -0,0 +1,100 @@
+<?xml version='1.0'?> <!--*-nxml-*-->
+<?xml-stylesheet type="text/xsl" href="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+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/>.
+-->
+
+<refentry id="systemd.scope">
+ <refentryinfo>
+ <title>systemd.scope</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>systemd.scope</refentrytitle>
+ <manvolnum>5</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>systemd.scope</refname>
+ <refpurpose>Scope unit configuration</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <para><filename><replaceable>scope</replaceable>.scope</filename></para>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para>Scope units are not configured via unit configuration files,
+ but are only created programmatically using the bus interfaces of
+ systemd. They are named similar to filenames. A unit whose name
+ ends in <literal>.scope</literal> refers to a scope unit. Scopes
+ units manage a set of system processes. Unlike service units, scope
+ units manage externally created processes, and do not fork off
+ processes on its own.</para>
+
+ <para>The main purpose of scope units is grouping worker processes
+ of a system service for organization and for managing resources.</para>
+
+ <para><command>systemd-run <option>--scope</option></command> may
+ be used to easily launch a command in a new scope unit from the
+ command line.</para>
+
+ <para>See the <ulink
+ url="http://www.freedesktop.org/wiki/Software/systemd/ControlGroupInterface/">New
+ Control Group Interfaces</ulink> for an introduction how to make
+ use of scope units from programs.</para>
+
+ <para>Unless <varname>DefaultDependencies=false</varname>
+ is used, scope units will implicitly have dependencies of
+ type <varname>Conflicts=</varname> and
+ <varname>Before=</varname> on
+ <filename>shutdown.target</filename>. These ensure
+ that scope units are removed prior to system
+ shutdown. Only scope units involved with early boot or
+ late system shutdown should disable this option.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-run</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/systemd.service.xml b/man/systemd.service.xml
index 0454cf292e..5e1ddf7188 100644
--- a/man/systemd.service.xml
+++ b/man/systemd.service.xml
@@ -73,9 +73,12 @@
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
which define the execution environment the commands
are executed in, and in
- <citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
which define the way the processes of the service are
- terminated.</para>
+ terminated, and in
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ which configure resource control settings for the
+ processes of the service.</para>
<para>Unless <varname>DefaultDependencies=</varname>
is set to <option>false</option>, service units will
@@ -137,13 +140,13 @@
<para>If set to
<option>simple</option> (the default
value if <varname>BusName=</varname>
- is not specified) it is expected that
+ is not specified), it is expected that
the process configured with
<varname>ExecStart=</varname> is the
main process of the service. In this
mode, if the process offers
functionality to other processes on
- the system its communication channels
+ the system, its communication channels
should be installed before the daemon
is started up (e.g. sockets set up by
systemd, via socket activation), as
@@ -151,14 +154,14 @@
starting follow-up units.</para>
<para>If set to
- <option>forking</option> it is
+ <option>forking</option>, it is
expected that the process configured
with <varname>ExecStart=</varname>
will call <function>fork()</function>
as part of its start-up. The parent process is
expected to exit when start-up is
complete and all communication
- channels set up. The child continues
+ channels are set up. The child continues
to run as the main daemon
process. This is the behavior of
traditional UNIX daemons. If this
@@ -207,14 +210,18 @@
starting up. systemd will proceed
starting follow-up units after this
notification message has been sent. If
- this option is used
+ this option is used,
<varname>NotifyAccess=</varname> (see
below) should be set to open access to
the notification socket provided by
systemd. If
<varname>NotifyAccess=</varname> is
not set, it will be implicitly set to
- <option>main</option>.</para>
+ <option>main</option>. Note that
+ currently
+ <varname>Type=</varname><option>notify</option>
+ will not work if used in combination with
+ <varname>PrivateNetwork=</varname><option>yes</option>.</para>
<para>Behavior of
<option>idle</option> is very similar
@@ -255,7 +262,7 @@
guessing algorithm might come to
incorrect conclusions if a daemon
consists of more than one process. If
- the main PID cannot be determined
+ the main PID cannot be determined,
failure detection and automatic
restarting of a service will not work
reliably. Defaults to
@@ -319,8 +326,8 @@
suitable for XDG
<filename>.desktop</filename> files.
Lone semicolons may be escaped as
- '<literal>\;</literal>'. If the empty
- string is assigned to this option the
+ <literal>\;</literal>. If the empty
+ string is assigned to this option, the
list of commands to start is reset,
prior assignments of this option will
have no effect.</para>
@@ -330,7 +337,7 @@
one by one sequentially in the order
they appear in the unit file. If one
of the commands fails (and is not
- prefixed with '<literal>-</literal>'),
+ prefixed with <literal>-</literal>),
other lines are not executed and the
unit is considered failed.</para>
@@ -341,7 +348,7 @@
main process of the daemon.</para>
<para>The command line accepts
- '<literal>%</literal>' specifiers as
+ <literal>%</literal> specifiers as
described in
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>. Note
that the first argument of the command
@@ -362,7 +369,8 @@
case it will be replaced by the value
of the environment variable split up
at whitespace, resulting in zero or
- more arguments. Note that the first
+ more arguments. To pass literal dollar sign
+ use <literal>$$</literal>. Note that the first
argument (i.e. the program to execute)
may not be a variable, since it must
be a literal and absolute path
@@ -370,25 +378,25 @@
<para>Optionally, if the absolute file
name is prefixed with
- '<literal>@</literal>', the second token
+ <literal>@</literal>, the second token
will be passed as
<literal>argv[0]</literal> to the
executed process, followed by the
further arguments specified. If the
- absolute file name is prefixed with
- '<literal>-</literal>' an exit code of
+ absolute filename is prefixed with
+ <literal>-</literal>, an exit code of
the command normally considered a
failure (i.e. non-zero exit status or
abnormal exit due to signal) is ignored
and considered success. If both
- '<literal>-</literal>' and
- '<literal>@</literal>' are used they
+ <literal>-</literal> and
+ <literal>@</literal> are used, they
can appear in either order.</para>
<para>Note that this setting does not
directly support shell command
lines. If shell command lines are to
- be used they need to be passed
+ be used, they need to be passed
explicitly to a shell implementation
of some kind. Example:</para>
<programlisting>ExecStart=/bin/sh -c 'dmesg | tac'
@@ -417,7 +425,7 @@
after the other, serially.</para>
<para>If any of those commands (not
- prefixed with '<literal>-</literal>')
+ prefixed with <literal>-</literal>)
fail, the rest are not executed and
the unit is considered failed.</para>
</listitem>
@@ -464,7 +472,7 @@
<varname>KillMode=</varname> setting
(see
<citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>). If
- this option is not specified the
+ this option is not specified, the
process is terminated right-away when
service stop is requested. Specifier
and environment variable substitution
@@ -480,7 +488,7 @@
was stopped. This includes cases where
the commands configured in
<varname>ExecStop=</varname> were used,
- where the service doesn't have any
+ where the service does not have any
<varname>ExecStop=</varname> defined, or
where the service exited unexpectedly. This
argument takes multiple command lines,
@@ -529,9 +537,9 @@
wait for stop. If a service is asked
to stop but does not terminate in the
specified time, it will be terminated
- forcibly via SIGTERM, and after
+ forcibly via <constant>SIGTERM</constant>, and after
another delay of this time with
- SIGKILL (See
+ <constant>SIGKILL</constant> (See
<varname>KillMode=</varname>
in <citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
Takes a unit-less value in seconds, or a
@@ -560,11 +568,11 @@
regularly with "WATCHDOG=1" (i.e. the
"keep-alive ping"). If the time
between two such calls is larger than
- the configured time then the service
+ the configured time, then the service
is placed in a failure state. By
setting <varname>Restart=</varname> to
<option>on-failure</option> or
- <option>always</option> the service
+ <option>always</option>, the service
will be automatically restarted. The
time configured here will be passed to
the executed service process in the
@@ -573,7 +581,7 @@
daemons to automatically enable the
keep-alive pinging logic if watchdog
support is enabled for the service. If
- this option is used
+ this option is used,
<varname>NotifyAccess=</varname> (see
below) should be set to open access to
the notification socket provided by
@@ -611,19 +619,20 @@
<option>no</option>,
<option>on-success</option>,
<option>on-failure</option>,
+ <option>on-watchdog</option>,
<option>on-abort</option>, or
<option>always</option>. If set to
- <option>no</option> (the default) the
+ <option>no</option> (the default), the
service will not be restarted. If set to
- <option>on-success</option> it will be
+ <option>on-success</option>, it will be
restarted only when the service process
exits cleanly.
In this context, a clean exit means
an exit code of 0, or one of the signals
- SIGHUP, SIGINT, SIGTERM, or SIGPIPE, and
+ <constant>SIGHUP</constant>, <constant>SIGINT</constant>, <constant>SIGTERM</constant>, or <constant>SIGPIPE</constant>, and
additionally, exit statuses and signals
specified in <varname>SuccessExitStatus=</varname>.
- If set to <option>on-failure</option>
+ If set to <option>on-failure</option>,
the service will be restarted when the
process exits with an nonzero exit code,
is terminated by a signal (including on
@@ -631,13 +640,17 @@
service reload) times out, and when the
configured watchdog timeout is triggered.
If set to
- <option>on-abort</option> the service
+ <option>on-abort</option>, the service
will be restarted only if the service
process exits due to an uncaught
signal not specified as a clean exit
status.
If set to
- <option>always</option> the service
+ <option>on-watchdog</option>, the service
+ will be restarted only if the watchdog
+ timeout for the service expires.
+ If set to
+ <option>always</option>, the service
will be restarted regardless whether
it exited cleanly or not, got
terminated abnormally by a signal or
@@ -657,20 +670,20 @@
by the main service process will be
considered successful termination, in
addition to the normal successful exit
- code 0 and the signals SIGHUP, SIGINT,
- SIGTERM and SIGPIPE. Exit status
+ code 0 and the signals <constant>SIGHUP</constant>, <constant>SIGINT</constant>,
+ <constant>SIGTERM</constant> and <constant>SIGPIPE</constant>. Exit status
definitions can either be numeric exit
codes or termination signal names,
separated by spaces. Example:
- "<literal>SuccessExitStatus=1 2 8
- SIGKILL</literal>", ensures that exit
+ <literal>SuccessExitStatus=1 2 8
+ <constant>SIGKILL</constant></literal>, ensures that exit
codes 1, 2, 8 and the termination
- signal SIGKILL are considered clean
+ signal <constant>SIGKILL</constant> are considered clean
service terminations. This option may
appear more than once in which case
the list of successful exit statuses
is merged. If the empty string is
- assigned to this option the list is
+ assigned to this option, the list is
reset, all prior assignments of this
option will have no
effect.</para></listitem>
@@ -692,15 +705,15 @@
that by default no exit status is
excluded from the configured restart
logic. Example:
- "<literal>RestartPreventExitStatus=1 6
- SIGABRT</literal>", ensures that exit
+ <literal>RestartPreventExitStatus=1 6
+ SIGABRT</literal>, ensures that exit
codes 1 and 6 and the termination
signal SIGABRT will not result in
automatic service restarting. This
option may appear more than once in
which case the list of restart preventing
statuses is merged. If the empty
- string is assigned to this option the
+ string is assigned to this option, the
list is reset, all prior assignments
of this option will have no
effect.</para></listitem>
@@ -778,13 +791,13 @@
<option>none</option> (the default),
<option>main</option> or
<option>all</option>. If
- <option>none</option> no daemon status
+ <option>none</option>, no daemon status
updates are accepted from the service
processes, all status update messages
- are ignored. If <option>main</option>
+ are ignored. If <option>main</option>,
only service updates sent from the
main process of the service are
- accepted. If <option>all</option> all
+ accepted. If <option>all</option>, all
services updates from all members of
the service's control group are
accepted. This option should be set to
@@ -793,8 +806,8 @@
<varname>Type=notify</varname> or
<varname>WatchdogSec=</varname> (see
above). If those options are used but
- <varname>NotifyAccess=</varname> not
- configured it will be implicitly set
+ <varname>NotifyAccess=</varname> is not
+ configured, it will be implicitly set
to
<option>main</option>.</para></listitem>
</varlistentry>
@@ -820,7 +833,7 @@
in other words: the
<varname>Service=</varname> setting of
<filename>.socket</filename> units
- doesn't have to match the inverse of
+ does not have to match the inverse of
the <varname>Sockets=</varname>
setting of the
<filename>.service</filename> it
@@ -829,7 +842,7 @@
<para>This option may appear more than
once, in which case the list of socket
units is merged. If the empty string
- is assigned to this option the list of
+ is assigned to this option, the list of
sockets is reset, all prior uses of
this setting will have no
effect.</para></listitem>
@@ -840,12 +853,12 @@
<term><varname>StartLimitBurst=</varname></term>
<listitem><para>Configure service
- start rate limiting. By default
+ start rate limiting. By default,
services which are started more often
than 5 times within 10s are not
permitted to start any more times
until the 10s interval ends. With
- these two options this rate limiting
+ these two options, this rate limiting
may be modified. Use
<varname>StartLimitInterval=</varname>
to configure the checking interval
@@ -994,6 +1007,7 @@
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>
</para>
diff --git a/man/systemd.slice.xml b/man/systemd.slice.xml
new file mode 100644
index 0000000000..4d27ddf890
--- /dev/null
+++ b/man/systemd.slice.xml
@@ -0,0 +1,121 @@
+<?xml version='1.0'?> <!--*-nxml-*-->
+<?xml-stylesheet type="text/xsl" href="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+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/>.
+-->
+
+<refentry id="systemd.slice">
+ <refentryinfo>
+ <title>systemd.slice</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>systemd.slice</refentrytitle>
+ <manvolnum>5</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>systemd.slice</refname>
+ <refpurpose>Slice unit configuration</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <para><filename><replaceable>slice</replaceable>.slice</filename></para>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para>A unit configuration file whose name ends in
+ <literal>.slice</literal> encodes information about a slice which
+ is a concept for hierarchially managing resources of a group of
+ processes. This management is performed by creating a node in the
+ Linux Control Group (cgroup) tree. Units that manage processes
+ (primarilly scope and service units) may be assigned to a specific
+ slice. For each slice, certain resource limits may the be set that
+ apply to all processes of all units contained in that
+ slice. Slices are organized hierarchially in a tree. The name of
+ the slice encodes the location in the tree. The name consists of a
+ dash-separated series of names, which describes the path to the
+ slice from the root slice. The root slice is named,
+ <filename>-.slice</filename>. Example:
+ <filename>foo-bar.slice</filename> is a slice that is located
+ within <filename>foo.slice</filename>, which in turn is located in
+ the root slice <filename>-.slice</filename>.
+ </para>
+
+ <para>By default, service and scope units are placed in
+ <filename>system.slice</filename>, virtual machines and containers
+ registered with
+ <citerefentry><refentrytitle>systemd-machined</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ are found in <filename>machine.slice</filename>, and user sessions
+ handled by
+ <citerefentry><refentrytitle>systemd-logind</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ in <filename>user.slice</filename>. See
+ <citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for more information.</para>
+
+ <para>See
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for the common options of all unit configuration
+ files. The common configuration items are configured
+ in the generic [Unit] and [Install] sections. The
+ slice specific configuration options are configured in
+ the [Slice] section. Currently, only generic resource control settings
+ as described in
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>7</manvolnum></citerefentry> are allowed.
+ </para>
+
+ <para>Unless <varname>DefaultDependencies=false</varname>
+ is used, slice units will implicitly have dependencies of
+ type <varname>Conflicts=</varname> and
+ <varname>Before=</varname> on
+ <filename>shutdown.target</filename>. These ensure
+ that slice units are removed prior to system
+ shutdown. Only slice units involved with early boot or
+ late system shutdown should disable this option.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.scope</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/systemd.snapshot.xml b/man/systemd.snapshot.xml
index 08d14c4e01..1bb074a9b1 100644
--- a/man/systemd.snapshot.xml
+++ b/man/systemd.snapshot.xml
@@ -56,8 +56,8 @@
<para>Snapshot units are not configured via unit
configuration files. Nonetheless they are named
- similar to filenames. A unit name whose name ends in
- <filename>.snapshot</filename> refers to a dynamic
+ similar to filenames. A unit whose name ends in
+ <literal>.snapshot</literal> refers to a dynamic
snapshot of the systemd runtime state.</para>
<para>Snapshots are not configured on disk but created
diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml
index 6dc847df3f..8c88d9f8aa 100644
--- a/man/systemd.socket.xml
+++ b/man/systemd.socket.xml
@@ -55,7 +55,7 @@
<title>Description</title>
<para>A unit configuration file whose name ends in
- <filename>.socket</filename> encodes information about
+ <literal>.socket</literal> encodes information about
an IPC or network socket or a file system FIFO
controlled and supervised by systemd, for socket-based
activation.</para>
@@ -77,9 +77,12 @@
<option>ExecStopPre=</option> and
<option>ExecStopPost=</option> commands are executed
in, and in
- <citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- which define the way the processes are
- terminated.</para>
+ <citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ which define the way the processes are terminated, and
+ in
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ which configure resource control settings for the
+ processes of the socket.</para>
<para>For each socket file a matching service file
(see
@@ -93,7 +96,7 @@
<filename>foo.socket</filename> needs a matching
service <filename>foo.service</filename> if
<option>Accept=false</option> is set. If
- <option>Accept=true</option> is set a service template
+ <option>Accept=true</option> is set, a service template
file <filename>foo@.service</filename> must exist from
which services are instantiated for each incoming
connection.</para>
@@ -150,26 +153,28 @@
<term><varname>ListenSequentialPacket=</varname></term>
<listitem><para>Specifies an address
to listen on for a stream
- (SOCK_STREAM), datagram (SOCK_DGRAM),
+ (<constant>SOCK_STREAM</constant>), datagram (<constant>SOCK_DGRAM</constant>),
or sequential packet
- (SOCK_SEQPACKET) socket, respectively. The address
+ (<constant>SOCK_SEQPACKET</constant>) socket, respectively. The address
can be written in various formats:</para>
<para>If the address starts with a
- slash (/), it is read as file system
- socket in the AF_UNIX socket
+ slash (<literal>/</literal>), it is read as file system
+ socket in the <constant>AF_UNIX</constant> socket
family.</para>
- <para>If the address starts with an
- at symbol (@) it is read as abstract
- namespace socket in the AF_UNIX
- family. The @ is replaced with a NUL
- character before binding. For details
- see
+ <para>If the address starts with an at
+ symbol (<literal>@</literal>), it is read as abstract
+ namespace socket in the
+ <constant>AF_UNIX</constant>
+ family. The <literal>@</literal> is
+ replaced with a
+ <constant>NUL</constant> character
+ before binding. For details, see
<citerefentry><refentrytitle>unix</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
<para>If the address string is a
- single number it is read as port
+ single number, it is read as port
number to listen on via
IPv6. Depending on the value of
<varname>BindIPv6Only=</varname> (see below) this
@@ -179,13 +184,13 @@
</para>
<para>If the address string is a
- string in the format v.w.x.y:z it is
+ string in the format v.w.x.y:z, it is
read as IPv4 specifier for listening
on an address v.w.x.y on a port
z.</para>
<para>If the address string is a
- string in the format [x]:y it is read
+ string in the format [x]:y, it is read
as IPv6 address x on a port y. Note
that this might make the service
available via IPv4, too, depending on
@@ -193,13 +198,13 @@
setting (see below).
</para>
- <para>Note that SOCK_SEQPACKET
+ <para>Note that <constant>SOCK_SEQPACKET</constant>
(i.e. <varname>ListenSequentialPacket=</varname>)
- is only available for AF_UNIX
- sockets. SOCK_STREAM
+ is only available for <constant>AF_UNIX</constant>
+ sockets. <constant>SOCK_STREAM</constant>
(i.e. <varname>ListenStream=</varname>)
when used for IP sockets refers to TCP
- sockets, SOCK_DGRAM
+ sockets, <constant>SOCK_DGRAM</constant>
(i.e. <varname>ListenDatagram=</varname>)
to UDP.</para>
@@ -258,7 +263,7 @@
<listitem><para>Specifies a Netlink
family to create a socket for to
listen on. This expects a short string
- referring to the AF_NETLINK family
+ referring to the <constant>AF_NETLINK</constant> family
name (such as <varname>audit</varname>
or <varname>kobject-uevent</varname>)
as argument, optionally suffixed by a
@@ -298,7 +303,7 @@
<option>ipv6-only</option>, they will
be accessible via IPv6 only. If
<option>default</option> (which is the
- default, surprise!) the system wide
+ default, surprise!), the system wide
default setting is used, as controlled
by
<filename>/proc/sys/net/ipv6/bindv6only</filename>,
@@ -325,7 +330,7 @@
<term><varname>BindToDevice=</varname></term>
<listitem><para>Specifies a network
interface name to bind this socket
- to. If set traffic will only be
+ to. If set, traffic will only be
accepted from the specified network
interfaces. This controls the
SO_BINDTODEVICE socket option (see
@@ -374,17 +379,30 @@
and only one service unit is spawned
for all connections (also see
above). This value is ignored for
- datagram sockets and FIFOs where
- a single service unit unconditionally
+ datagram sockets and FIFOs where a
+ single service unit unconditionally
handles all incoming traffic. Defaults
to <option>false</option>. For
performance reasons, it is recommended
to write new daemons only in a way
that is suitable for
- <option>Accept=false</option>. This
- option is mostly useful to allow
- daemons designed for usage with
- <citerefentry><refentrytitle>inetd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <option>Accept=false</option>. A
+ daemon listening on an <constant>AF_UNIX</constant> socket
+ may, but does not need to, call
+ <citerefentry><refentrytitle>close</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+ on the received socket before
+ exiting. However, it must not unlink
+ the socket from a file system. It
+ should not invoke
+ <citerefentry><refentrytitle>shutdown</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+ on sockets it got with
+ <varname>Accept=false</varname>, but
+ it may do so for sockets it got with
+ <varname>Accept=true</varname> set.
+ Setting <varname>Accept=true</varname>
+ is mostly useful to allow daemons
+ designed for usage with
+ <citerefentry><refentrytitle>inetd</refentrytitle><manvolnum>8</manvolnum></citerefentry>
to work unmodified with systemd socket
activation.</para></listitem>
</varlistentry>
@@ -399,7 +417,7 @@
are coming in, they will be refused
until at least one existing connection
is terminated. This setting has no
- effect for sockets configured with
+ effect on sockets configured with
<option>Accept=false</option> or datagram
sockets. Defaults to
64.</para></listitem>
@@ -490,6 +508,17 @@
</varlistentry>
<varlistentry>
+ <term><varname>ReusePort=</varname></term>
+ <listitem><para>Takes a boolean
+ value. If true, allows multiple <citerefentry><refentrytitle>bind</refentrytitle><manvolnum>2</manvolnum></citerefentry>s
+ to this TCP or UDP port. This
+ controls the SO_REUSEPORT socket
+ option. See
+ <citerefentry><refentrytitle>socket</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ for details.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>SmackLabel=</varname></term>
<term><varname>SmackLabelIPIn=</varname></term>
<term><varname>SmackLabelIPOut=</varname></term>
@@ -503,7 +532,7 @@
respectively, i.e. the security label
of the FIFO, or the security label for
the incoming or outgoing connections
- of the socket, respectively. See
+ of the socket, respectively. See
<ulink
url="https://www.kernel.org/doc/Documentation/security/Smack.txt">Smack.txt</ulink>
for details.</para></listitem>
@@ -514,7 +543,7 @@
<listitem><para>Takes an integer
value. Controls the pipe buffer size
of FIFOs configured in this socket
- unit. See
+ unit. See
<citerefentry><refentrytitle>fcntl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
for details.</para></listitem>
</varlistentry>
@@ -571,7 +600,7 @@
<term><varname>PassCredentials=</varname></term>
<listitem><para>Takes a boolean
value. This controls the SO_PASSCRED
- socket option, which allows AF_UNIX sockets to
+ socket option, which allows <constant>AF_UNIX</constant> sockets to
receive the credentials of the sending
process in an ancillary message.
Defaults to
@@ -582,10 +611,10 @@
<term><varname>PassSecurity=</varname></term>
<listitem><para>Takes a boolean
value. This controls the SO_PASSSEC
- socket option, which allows AF_UNIX
+ socket option, which allows <constant>AF_UNIX</constant>
sockets to receive the security
context of the sending process in an
- ancillary message. Defaults to
+ ancillary message. Defaults to
<option>false</option>.</para></listitem>
</varlistentry>
@@ -609,7 +638,7 @@
before or after the listening
sockets/FIFOs are created and
bound, respectively. The first token of the command
- line must be an absolute file name,
+ line must be an absolute filename,
then followed by arguments for the
process. Multiple command lines may be
specified following the same scheme as
@@ -644,8 +673,8 @@
will be considered failed and be shut
down again. All commands still running,
will be terminated forcibly via
- SIGTERM, and after another delay of
- this time with SIGKILL. (See
+ <constant>SIGTERM</constant>, and after another delay of
+ this time with <constant>SIGKILL</constant>. (See
<option>KillMode=</option> in <citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>.)
Takes a unit-less value in seconds, or
a time span value such as "5min
@@ -683,12 +712,13 @@
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>
</para>
<para>
- For more extensive descriptions see the "Systemd for Developers" series:
+ For more extensive descriptions see the "systemd for Developers" series:
<ulink url="http://0pointer.de/blog/projects/socket-activation.html">Socket Activation</ulink>,
<ulink url="http://0pointer.de/blog/projects/socket-activation2.html">Socket Activation, part II</ulink>,
<ulink url="http://0pointer.de/blog/projects/inetd.html">Converting inetd Services</ulink>,
diff --git a/man/systemd.special.xml b/man/systemd.special.xml
index 7164b1e614..863a029fe3 100644
--- a/man/systemd.special.xml
+++ b/man/systemd.special.xml
@@ -100,7 +100,11 @@
<filename>system-update.target</filename>,
<filename>time-sync.target</filename>,
<filename>timers.target</filename>,
- <filename>umount.target</filename></para>
+ <filename>umount.target</filename>,
+ <filename>-.slice</filename>,
+ <filename>system.slice</filename>,
+ <filename>user.slice</filename>,
+ <filename>machine.slice</filename></para>
</refsynopsisdiv>
<refsect1>
@@ -314,7 +318,7 @@
dependencies of type
<varname>Before=</varname> to
<filename>sysroot-usr.mount</filename>
- and all mount points fround in
+ and all mount points found in
<filename>/etc/fstab</filename>
that have the
<option>auto</option> and
@@ -381,7 +385,7 @@
this unit during
installation. This is best
configured via
- <varname>WantedBy=multi-uer.target</varname>
+ <varname>WantedBy=multi-user.target</varname>
in the unit's
<literal>[Install]</literal>
section.</para>
@@ -444,7 +448,7 @@
after it. Note that networking
daemons that simply provide
functionality to other hosts
- generally don't need to pull
+ generally do not need to pull
this in.</para>
</listitem>
</varlistentry>
@@ -935,7 +939,7 @@
<varname>Wants=</varname> type
dependency. If the unit wants
to be pulled in by the first
- remote mount showing up it
+ remote mount showing up, it
should use
<filename>network-online.target</filename>
(see above).</para>
@@ -1007,8 +1011,8 @@
terminate the user service
manager should start this
unit. If systemd receives
- SIGTERM or SIGINT when running
- as user service daemon it will
+ <constant>SIGTERM</constant> or <constant>SIGINT</constant> when running
+ as user service daemon, it will
start this unit.</para>
<para>Normally, this pulls in
@@ -1023,6 +1027,63 @@
</refsect1>
<refsect1>
+ <title>Special Slice Units</title>
+
+ <para>There are four <literal>.slice</literal> units
+ which form the basis of the hierarchy for assignment
+ of resources for services, users, and virtual machines
+ or containers.</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><filename>-.slice</filename></term>
+ <listitem>
+ <para>The root slice is the
+ root of the hierarchy. It
+ usually does not contain units
+ directly, but may be used to
+ set defaults for the whole
+ tree.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><filename>system.slice</filename></term>
+ <listitem>
+ <para>By default, all services
+ services started by
+ <command>systemd</command> are
+ found in this slice.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><filename>user.slice</filename></term>
+ <listitem>
+ <para>By default, all user
+ processes and services started
+ on behalf of the user,
+ including the per-user systemd
+ instance are found in this
+ slice.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><filename>machine.slice</filename></term>
+ <listitem>
+ <para>By defalt, all virtual
+ machines and containers
+ registered with
+ <command>systemd-machined</command>
+ are found in this slice.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
@@ -1030,6 +1091,7 @@
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.target</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>bootup</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-fstab-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
diff --git a/man/systemd.swap.xml b/man/systemd.swap.xml
index 8268e6164d..813ae6c942 100644
--- a/man/systemd.swap.xml
+++ b/man/systemd.swap.xml
@@ -55,7 +55,7 @@
<title>Description</title>
<para>A unit configuration file whose name ends in
- <filename>.swap</filename> encodes information about a
+ <literal>.swap</literal> encodes information about a
swap device or file for memory paging controlled and
supervised by systemd.</para>
@@ -73,9 +73,12 @@
which define the execution environment the
<citerefentry><refentrytitle>swapon</refentrytitle><manvolnum>8</manvolnum></citerefentry>
binary is executed in, and in
- <citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
which define the way the processes are
- terminated.</para>
+ terminated, and in
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ which configure resource control settings for the
+ processes of the service.</para>
<para>Swap units must be named after the devices
or files they control. Example: the swap device
@@ -111,7 +114,7 @@
for details about the conversion.</para>
<para>If a swap device or file is configured in both
- <filename>/etc/fstab</filename> and a unit file the
+ <filename>/etc/fstab</filename> and a unit file, the
configuration in the latter takes precedence.</para>
<para>Unless the <option>noauto</option> option is set
@@ -172,12 +175,12 @@
<listitem><para>Configures the time to
wait for the swapon command to
finish. If a command does not exit
- within the configured time the swap
+ within the configured time, the swap
will be considered failed and be shut
down again. All commands still running
will be terminated forcibly via
- SIGTERM, and after another delay of
- this time with SIGKILL. (See
+ <constant>SIGTERM</constant>, and after another delay of
+ this time with <constant>SIGKILL</constant>. (See
<option>KillMode=</option> in
<citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>.)
Takes a unit-less value in seconds, or
@@ -203,6 +206,7 @@
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.device</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>swapon</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
diff --git a/man/systemd.target.xml b/man/systemd.target.xml
index fd51cfde3a..15662a548d 100644
--- a/man/systemd.target.xml
+++ b/man/systemd.target.xml
@@ -55,7 +55,7 @@
<title>Description</title>
<para>A unit configuration file whose name ends in
- <filename>.target</filename> encodes information about
+ <literal>.target</literal> encodes information about
a target unit of systemd, which is used for grouping
units and as well-known synchronization points during
start-up.</para>
diff --git a/man/systemd.time.xml b/man/systemd.time.xml
index a9318bb787..f438fa5bb9 100644
--- a/man/systemd.time.xml
+++ b/man/systemd.time.xml
@@ -50,16 +50,16 @@
<refsect1>
<title>Description</title>
- <para>In systemd timestamps, timespans, and calendar
+ <para>In systemd, timestamps, time spans, and calendar
events are displayed and may be specified in closely
related syntaxes.</para>
</refsect1>
<refsect1>
- <title>Displaying Timespans</title>
+ <title>Displaying Time Spans</title>
- <para>Timespans refer to time durations. On display
- systemd will present timespans as a space separated
+ <para>Time spans refer to time durations. On display,
+ systemd will present time spans as a space-separated
series of time values each suffixed by a time
unit.</para>
@@ -70,10 +70,10 @@
</refsect1>
<refsect1>
- <title>Parsing Timespans</title>
+ <title>Parsing Time Spans</title>
- <para>When parsing systemd will accept the same
- timespan syntax. Separating spaces may be omitted. The
+ <para>When parsing, systemd will accept the same
+ time span syntax. Separating spaces may be omitted. The
following time units are understood:</para>
<itemizedlist>
@@ -92,9 +92,9 @@
are assumed, but some exceptions exist and are marked
as such. In a few cases <literal>ns</literal>,
<literal>nsec</literal> is accepted too, where the
- granularity of the timespan allows for this.</para>
+ granularity of the time span allows for this.</para>
- <para>Examples for valid timespan specifications:</para>
+ <para>Examples for valid time span specifications:</para>
<programlisting>2 h
2hours
@@ -108,12 +108,12 @@
<title>Displaying Timestamps</title>
<para>Timestamps refer to specific, unique points in
- time. On display systemd will format these in the
+ time. On display, systemd will format these in the
local timezone as follows:</para>
<programlisting>Fri 2012-11-23 23:02:15 CET</programlisting>
- <para>The week day is printed according to the locale
+ <para>The weekday is printed according to the locale
choice of the user.</para>
</refsect1>
@@ -123,11 +123,11 @@
<para>When parsing systemd will accept a similar
timestamp syntax, but excluding any timezone
specification (this limitation might be removed
- eventually). The week day specification is optional,
- but when the week day is specified it must either be
+ eventually). The weekday specification is optional,
+ but when the weekday is specified it must either be
in the abbreviated (<literal>Wed</literal>) or
- non-abbreviated (<literal>Wednesday</literal>) english
- language form (case doesn't matter), and is not
+ non-abbreviated (<literal>Wednesday</literal>) English
+ language form (case does not matter), and is not
subject to the locale choice of the user. Either the
date, or the time part may be omitted, in which case
the current date or 00:00:00, resp., is assumed. The
@@ -136,11 +136,11 @@
specified in full or may be abbreviated (omitting the
century).</para>
- <para>A timestamp is considered invalid if a week day
+ <para>A timestamp is considered invalid if a weekday
is specified and the date does not actually match the
specified day of the week.</para>
- <para>When parsing systemd will also accept a few
+ <para>When parsing, systemd will also accept a few
special placeholders instead of timestamps:
<literal>now</literal> may be used to refer to the
current time (or of the invocation of the command
@@ -150,14 +150,14 @@
current day, the day before or the next day,
respectively.</para>
- <para>When parsing systemd will also accept relative
- time specifications. A timespan (see above) that is
+ <para>When parsing, systemd will also accept relative
+ time specifications. A time span (see above) that is
prefixed with <literal>+</literal> is evaluated to the
current time plus the specified
- timespan. Correspondingly a timespan that is prefix
+ time span. Correspondingly, a time span that is prefixed
with <literal>-</literal> is evaluated to the current
- time minus the specified timespan. Instead of
- prefixing the timespan with <literal>-</literal> it
+ time minus the specified time span. Instead of
+ prefixing the time span with <literal>-</literal>, it
may also be suffixed with a space and the word
<literal>ago</literal>.</para>
@@ -182,10 +182,10 @@
<para>Note that timestamps printed by systemd will not
be parsed correctly by systemd, as the timezone
specification is not accepted, and printing timestamps
- is subject to locale settings for the week day while
- parsing only accepts english week day names.</para>
+ is subject to locale settings for the weekday while
+ parsing only accepts English weekday names.</para>
- <para>In some cases systemd will display a relative
+ <para>In some cases, systemd will display a relative
timestamp (relative to the current time, or the time
of invocation of the command) instead or in addition
to an absolute timestamp as described above. A
@@ -208,29 +208,30 @@
<para>The above refers to 11:12:13 of the first or
fifth day of any month of the year 2012, given that it
- is a thursday or friday.</para>
+ is a Thursday or Friday.</para>
<para>The weekday specification is optional. If
- specified it should consist of one or more english
- language week day names, either in the abbreviated
+ specified, it should consist of one or more English
+ language weekday names, either in the abbreviated
(Wed) or non-abbreviated (Wednesday) form (case does
- not matter), separated by commas. Specifying two week
- days separated by "-" refers to a range of continuous
- week days. "," and "-" may be combined freely.</para>
-
- <para>In the date and time specifications any
- component may be specified as "*" in which case any
- value will match. Alternatively, each component can be
- specified as list of values separated by
- commas. Values may also be suffixed with "/" and a
- repetition value, which indicates that the value and
- all values plus multiples of the repetition value are
- matched.</para>
+ not matter), separated by commas. Specifying two
+ weekdays separated by <literal>-</literal> refers to a
+ range of continuous weekdays. <literal>,</literal> and
+ <literal>-</literal> may be combined freely.</para>
+
+ <para>In the date and time specifications, any
+ component may be specified as <literal>*</literal> in
+ which case any value will match. Alternatively, each
+ component can be specified as list of values separated
+ by commas. Values may also be suffixed with
+ <literal>/</literal> and a repetition value, which
+ indicates that the value and all values plus multiples
+ of the repetition value are matched.</para>
<para>Either time or date specification may be
omitted, in which case the current day and 00:00:00 is
implied, respectively. If the second component is not
- specified ":00" is assumed.</para>
+ specified, <literal>:00</literal> is assumed.</para>
<para>Timezone names may not be specified.</para>
diff --git a/man/systemd.timer.xml b/man/systemd.timer.xml
index 2b9d91a60f..659bc81ccd 100644
--- a/man/systemd.timer.xml
+++ b/man/systemd.timer.xml
@@ -55,7 +55,7 @@
<title>Description</title>
<para>A unit configuration file whose name ends in
- <filename>.timer</filename> encodes information about
+ <literal>.timer</literal> encodes information about
a timer controlled and supervised by systemd, for
timer-based activation.</para>
@@ -128,7 +128,7 @@
combined of the same and of different
types. For example, by combining
<varname>OnBootSec=</varname> and
- <varname>OnUnitActiveSec=</varname> it is
+ <varname>OnUnitActiveSec=</varname>, it is
possible to define a timer that
elapses in regular intervals and
activates a specific service each
@@ -160,7 +160,7 @@
monotonic clock stops too.</para>
<para>If the empty string is assigned
- to any of these options the list of
+ to any of these options, the list of
timers is reset, and all prior
assignments will have no
effect.</para></listitem>
@@ -187,7 +187,7 @@
<listitem><para>The unit to activate
when this timer elapses. The argument is a
unit name, whose suffix is not
- <filename>.timer</filename>. If not
+ <literal>.timer</literal>. If not
specified, this value defaults to a
service that has the same name as the
timer unit, except for the
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index c56837a6e5..5c8b8e8868 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -60,7 +60,9 @@
<filename><replaceable>target</replaceable>.target</filename>,
<filename><replaceable>path</replaceable>.path</filename>,
<filename><replaceable>timer</replaceable>.timer</filename>,
- <filename><replaceable>snapshot</replaceable>.snapshot</filename></para>
+ <filename><replaceable>snapshot</replaceable>.snapshot</filename>,
+ <filename><replaceable>slice</replaceable>.slice</filename>,
+ <filename><replaceable>scope</replaceable>.scope</filename></para>
<para><literallayout><filename>/etc/systemd/system/*</filename>
<filename>/run/systemd/system/*</filename>
@@ -68,7 +70,8 @@
<filename>...</filename>
</literallayout></para>
- <para><literallayout><filename>/etc/systemd/user/*</filename>
+ <para><literallayout><filename>$HOME/.config/systemd/user/*</filename>
+<filename>/etc/systemd/user/*</filename>
<filename>/run/systemd/user/*</filename>
<filename>/usr/lib/systemd/user/*</filename>
<filename>...</filename>
@@ -81,12 +84,15 @@
<para>A unit configuration file encodes information
about a service, a socket, a device, a mount point, an
automount point, a swap file or partition, a start-up
- target, a file system path, or a timer controlled and
- supervised by
- <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>. The
- syntax is inspired by <ulink
+ target, a watched file system path, a timer controlled
+ and supervised by
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ a temporary system state snapshot, a resource
+ management slice or a group of externally created
+ processes. 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
+ Desktop Entry Specification</ulink>
+ <filename>.desktop</filename> files, which are in turn
inspired by Microsoft Windows
<filename>.ini</filename> files.</para>
@@ -110,6 +116,8 @@
<citerefentry><refentrytitle>systemd.path</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.timer</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.snapshot</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ <citerefentry><refentrytitle>systemd.scope</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</para>
<para>Unit files are loaded from a set of paths
@@ -118,9 +126,9 @@
<para>Unit files may contain additional options on top
of those listed here. If systemd encounters an unknown
- option it will write a warning log message but
+ option, it will write a warning log message but
continue loading the unit. If an option is prefixed
- with <option>X-</option> it is ignored completely by
+ with <option>X-</option>, it is ignored completely by
systemd. Applications may use this to include
additional information in the unit files.</para>
@@ -128,7 +136,7 @@
written in various formats. For positive settings the
strings <option>1</option>, <option>yes</option>,
<option>true</option> and <option>on</option> are
- equivalent. For negative settings the strings
+ equivalent. For negative settings, the strings
<option>0</option>, <option>no</option>,
<option>false</option> and <option>off</option> are
equivalent.</para>
@@ -152,14 +160,14 @@
space character. This may be used to wrap long lines.</para>
<para>Along with a unit file
- <filename>foo.service</filename> the directory
+ <filename>foo.service</filename>, the directory
<filename>foo.service.wants/</filename> may exist. All
unit files symlinked from such a directory are
implicitly added as dependencies of type
<varname>Wanted=</varname> to the unit. This is useful
to hook units into the start-up of other units,
without having to modify their unit files. For details
- about the semantics of <varname>Wanted=</varname> see
+ about the semantics of <varname>Wanted=</varname>, see
below. The preferred way to create symlinks in the
<filename>.wants/</filename> directory of a unit file
is with the <command>enable</command> command of the
@@ -171,9 +179,9 @@
<filename>.requires/</filename> in this case.</para>
<para>Along with a unit file
- <filename>foo.service</filename> a directory
+ <filename>foo.service</filename>, a directory
<filename>foo.service.d/</filename> may exist. All
- files with the suffix <filename>.conf</filename> from
+ files with the suffix <literal>.conf</literal> from
this directory will be parsed after the file itself is
parsed. This is useful to alter or add configuration
settings to a unit, without having to modify their
@@ -182,7 +190,7 @@
directive.</para>
<para>If a line starts with <option>.include</option>
- followed by a file name, the specified file will be
+ followed by a filename, the specified file will be
parsed at this point. Make sure that the file that is
included has the appropriate section headers before
any directives.</para>
@@ -195,12 +203,12 @@
in a both simpler and more flexible system.</para>
<para>Some unit names reflect paths existing in the
- file system name space. Example: a device unit
+ file system namespace. Example: a device unit
<filename>dev-sda.device</filename> refers to a device
with the device node <filename noindex='true'>/dev/sda</filename> in
- the file system namespace. If this applies a special
+ the file system namespace. If this applies, a special
way to escape the path name is used, so that the
- result is usable as part of a file name. Basically,
+ result is usable as part of a filename. Basically,
given a path, "/" is replaced by "-", and all
unprintable characters and the "-" are replaced by
C-style "\x20" escapes. The root directory "/" is
@@ -211,12 +219,12 @@
<para>Optionally, units may be instantiated from a
template file at runtime. This allows creation of
multiple units from a single configuration file. If
- systemd looks for a unit configuration file it will
+ systemd looks for a unit configuration file, it will
first search for the literal unit name in the
filesystem. If that yields no success and the unit
- name contains an @ character, systemd will look for a
+ name contains an <literal>@</literal> character, systemd will look for a
unit template that shares the same name but with the
- instance string (i.e. the part between the @ character
+ instance string (i.e. the part between the <literal>@</literal> character
and the suffix) removed. Example: if a service
<filename>getty@tty3.service</filename> is requested
and no file by that name is found, systemd will look
@@ -230,7 +238,7 @@
configuration options. See below for details.</para>
<para>If a unit file is empty (i.e. has the file size
- 0) or is symlinked to <filename>/dev/null</filename>
+ 0) or is symlinked to <filename>/dev/null</filename>,
its configuration will not be loaded and it appears
with a load state of <literal>masked</literal>, and
cannot be activated. Use this as an effective way to
@@ -249,10 +257,9 @@
<para>Unit files are loaded from a set of paths
determined during compilation, described in the two
- tables below. Unit files found in directories higher
- in the hierarchy override files with the same name
- lower in the hierarchy, thus allowing overrides.
- </para>
+ tables below. Unit files found in directories listed
+ earlier override files with the same name in
+ directories lower in the list.</para>
<para>When systemd is running in user mode
(<option>--user</option>) and the variable
@@ -277,32 +284,16 @@
</thead>
<tbody>
<row>
- <entry><filename>/run/systemd/generator.early</filename></entry>
- <entry>Generated units (early)</entry>
- </row>
- <row>
<entry><filename>/etc/systemd/system</filename></entry>
<entry>Local configuration</entry>
</row>
<row>
- <entry><filename>/run/systemd/systemd</filename></entry>
- <entry>Volatile units</entry>
- </row>
- <row>
- <entry><filename>/run/systemd/generator</filename></entry>
- <entry>Generated units (middle)</entry>
- </row>
- <row>
- <entry><filename>/usr/local/lib/systemd/system</filename></entry>
- <entry>Units for local packages</entry>
+ <entry><filename>/run/systemd/system</filename></entry>
+ <entry>Runtime units</entry>
</row>
<row>
<entry><filename>/usr/lib/systemd/system</filename></entry>
- <entry>Units for installed packages</entry>
- </row>
- <row>
- <entry><filename>/run/systemd/generator.late</filename></entry>
- <entry>Generated units (late)</entry>
+ <entry>Units of installed packages</entry>
</row>
</tbody>
</tgroup>
@@ -310,7 +301,7 @@
<table>
<title>
- Load path when running in session mode (<option>--user</option>).
+ Load path when running in user mode (<option>--user</option>).
</title>
<tgroup cols='2'>
@@ -324,8 +315,8 @@
</thead>
<tbody>
<row>
- <entry><filename>/tmp/systemd-generator.early.<replaceable>XXXXXX</replaceable></filename></entry>
- <entry>Generated units (early)</entry>
+ <entry><filename>$HOME/.config/systemd/user</filename></entry>
+ <entry>User configuration</entry>
</row>
<row>
<entry><filename>/etc/systemd/user</filename></entry>
@@ -333,23 +324,11 @@
</row>
<row>
<entry><filename>/run/systemd/user</filename></entry>
- <entry>Volatile units</entry>
- </row>
- <row>
- <entry><filename>/tmp/systemd-generator.<replaceable>XXXXXX</replaceable></filename></entry>
- <entry>Generated units (middle)</entry>
- </row>
- <row>
- <entry><filename>/usr/local/lib/systemd/user</filename></entry>
- <entry>Units for local packages</entry>
+ <entry>Runtime units</entry>
</row>
<row>
<entry><filename>/usr/lib/systemd/user</filename></entry>
- <entry>Units for installed packages</entry>
- </row>
- <row>
- <entry><filename>/tmp/systemd-generator.late.<replaceable>XXXXXX</replaceable></filename></entry>
- <entry>Generated units (late)</entry>
+ <entry>Units of installed packages</entry>
</row>
</tbody>
</tgroup>
@@ -358,7 +337,10 @@
<para>Additional units might be loaded into systemd
("linked") from directories not on the unit load
path. See the <command>link</command> command for
- <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
+ <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>. Also,
+ some units are dynamically created via generators
+ <ulink
+ url="http://www.freedesktop.org/wiki/Software/systemd/Generators/">Generators</ulink>.
</para>
</refsect1>
@@ -377,12 +359,20 @@
describing the unit. This is intended
for use in UIs to show descriptive
information along with the unit
- name.</para></listitem>
+ name. The description should contain a name
+ that means something to the end user.
+ <literal>Apache2 Web Server</literal> is a good
+ example. Bad examples are
+ <literal>high-performance light-weight HTTP
+ server</literal> (too generic) or
+ <literal>Apache2</literal> (too specific and
+ meaningless for people who do not know
+ Apache).</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>Documentation=</varname></term>
- <listitem><para>A space separated list
+ <listitem><para>A space-separated list
of URIs referencing documentation for
this unit or its
configuration. Accepted are only URIs
@@ -393,7 +383,7 @@
<literal>info:</literal>,
<literal>man:</literal>. For more
information about the syntax of these
- URIs see
+ URIs, see
<citerefentry><refentrytitle>uri</refentrytitle><manvolnum>7</manvolnum></citerefentry>. The
URIs should be listed in order of
relevance, starting with the most
@@ -405,7 +395,7 @@
option may be specified more than once
in which case the specified list of
URIs is merged. If the empty string is
- assigned to this option the list is
+ assigned to this option, the list is
reset and all prior assignments will
have no effect.</para></listitem>
</varlistentry>
@@ -471,7 +461,7 @@
the start-up was pulled in indirectly
by some dependency or automatic
start-up of units that is not
- requested by the user this dependency
+ requested by the user, this dependency
must be fulfilled and otherwise the
transaction fails. Hence, this option
may be used to configure dependencies
@@ -634,7 +624,7 @@
type <varname>After=</varname> or
<varname>Before=</varname>. If two
units have no ordering dependencies
- between them they are shut down
+ between them, they are shut down
or started up simultaneously, and
no ordering takes
place. </para></listitem>
@@ -646,7 +636,7 @@
<listitem><para>Lists one or more
units that are activated when this
unit enters the
- '<literal>failed</literal>'
+ <literal>failed</literal>
state.</para></listitem>
</varlistentry>
@@ -669,8 +659,8 @@
<varlistentry>
<term><varname>RequiresMountsFor=</varname></term>
- <listitem><para>Takes a space
- separated list of absolute paths. Automatically
+ <listitem><para>Takes a space-separated
+ list of absolute paths. Automatically
adds dependencies of type
<varname>Requires=</varname> and
<varname>After=</varname> for all
@@ -682,12 +672,12 @@
<term><varname>OnFailureIsolate=</varname></term>
<listitem><para>Takes a boolean
- argument. If <option>true</option> the
+ argument. If <option>true</option>, the
unit listed in
<varname>OnFailure=</varname> will be
enqueued in isolation mode, i.e. all
units that are not its dependency will
- be stopped. If this is set only a
+ be stopped. If this is set, only a
single unit may be listed in
<varname>OnFailure=</varname>. Defaults
to
@@ -698,7 +688,7 @@
<term><varname>IgnoreOnIsolate=</varname></term>
<listitem><para>Takes a boolean
- argument. If <option>true</option>
+ argument. If <option>true</option>,
this unit will not be stopped when
isolating another unit. Defaults to
<option>false</option>.</para></listitem>
@@ -708,7 +698,7 @@
<term><varname>IgnoreOnSnapshot=</varname></term>
<listitem><para>Takes a boolean
- argument. If <option>true</option>
+ argument. If <option>true</option>,
this unit will not be included in
snapshots. Defaults to
<option>true</option> for device and
@@ -720,7 +710,7 @@
<term><varname>StopWhenUnneeded=</varname></term>
<listitem><para>Takes a boolean
- argument. If <option>true</option>
+ argument. If <option>true</option>,
this unit will be stopped when it is
no longer used. Note that in order to
minimize the work to be executed,
@@ -739,10 +729,10 @@
<term><varname>RefuseManualStop=</varname></term>
<listitem><para>Takes a boolean
- argument. If <option>true</option>
+ argument. If <option>true</option>,
this unit can only be activated
or deactivated indirectly. In
- this case explicit start-up
+ this case, explicit start-up
or termination requested by the
user is denied, however if it is
started or stopped as a
@@ -762,10 +752,10 @@
<term><varname>AllowIsolate=</varname></term>
<listitem><para>Takes a boolean
- argument. If <option>true</option>
+ argument. If <option>true</option>,
this unit may be used with the
<command>systemctl isolate</command>
- command. Otherwise this will be
+ command. Otherwise, this will be
refused. It probably is a good idea to
leave this disabled except for target
units that shall be used similar to
@@ -779,7 +769,7 @@
<term><varname>DefaultDependencies=</varname></term>
<listitem><para>Takes a boolean
- argument. If <option>true</option>
+ argument. If <option>true</option>,
(the default), a few default
dependencies will implicitly be
created for the unit. The actual
@@ -797,7 +787,7 @@
highly recommended to leave this
option enabled for the majority of
common units. If set to
- <option>false</option> this option
+ <option>false</option>, this option
does not disable all implicit
dependencies, just non-essential
ones.</para></listitem>
@@ -809,10 +799,10 @@
<listitem><para>When clients are
waiting for a job of this unit to
complete, time out after the specified
- time. If this time limit is reached
+ time. If this time limit is reached,
the job will be cancelled, the unit
however will not change state or even
- enter the '<literal>failed</literal>'
+ enter the <literal>failed</literal>
mode. This value defaults to 0 (job
timeouts disabled), except for device
units. NB: this timeout is independent
@@ -851,7 +841,7 @@
<listitem><para>Before starting a unit
verify that the specified condition is
- true. If it is not true the starting
+ true. If it is not true, the starting
of the unit will be skipped, however
all ordering dependencies of it are
still respected. A failing condition
@@ -866,12 +856,12 @@
a file existence condition is
checked before a unit is started. If
the specified absolute path name does
- not exist the condition will
+ not exist, the condition will
fail. If the absolute path name passed
to
<varname>ConditionPathExists=</varname>
is prefixed with an exclamation mark
- ('!'), the test is negated, and the unit
+ (<literal>!</literal>), the test is negated, and the unit
is only started if the path does not
exist.</para>
@@ -940,7 +930,7 @@
exclamation mark unset). The argument
must either be a single word, or an
assignment (i.e. two words, separated
- '='). In the former
+ <literal>=</literal>). In the former
case the kernel command line is
searched for the word appearing as is,
or as left hand side of an
@@ -969,13 +959,14 @@
<varname>xen</varname>,
<varname>bochs</varname>,
<varname>chroot</varname>,
+ <varname>uml</varname>,
<varname>openvz</varname>,
<varname>lxc</varname>,
<varname>lxc-libvirt</varname>,
<varname>systemd-nspawn</varname> to
test against a specific
implementation. If multiple
- virtualization technologies are nested
+ virtualization technologies are nested,
only the innermost is considered. The
test may be negated by prepending an
exclamation mark.</para>
@@ -983,9 +974,10 @@
<para><varname>ConditionSecurity=</varname>
may be used to check whether the given
security module is enabled on the
- system. Currently the only recognized
+ system. Currently the recognized values
values are <varname>selinux</varname>,
- <varname>apparmor</varname>, and
+ <varname>apparmor</varname>,
+ <varname>ima</varname> and
<varname>smack</varname>.
The test may be negated by prepending
an exclamation
@@ -1006,11 +998,11 @@
<para><varname>ConditionHost=</varname>
may be used to match against the
- host name or machine ID of the
- host. This either takes a host name
+ hostname or machine ID of the
+ host. This either takes a hostname
string (optionally with shell style
globs) which is tested against the
- locally set host name as returned by
+ locally set hostname as returned by
<citerefentry><refentrytitle>gethostname</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
or a machine ID formatted as string
(see
@@ -1024,12 +1016,12 @@
battery powered at the time of
activation of the unit. This takes a
boolean argument. If set to
- <varname>true</varname> the condition
+ <varname>true</varname>, the condition
will hold only if at least one AC
connector of the system is connected
to a power source, or if no AC
connectors are known. Conversely, if
- set to <varname>false</varname> the
+ set to <varname>false</varname>, the
condition will hold only if there is
at least one AC connector known and
all AC connectors are disconnected
@@ -1040,30 +1032,30 @@
be used to add a constant condition
check value to the unit. It takes a
boolean argument. If set to
- <varname>false</varname> the condition
+ <varname>false</varname>, the condition
will always fail, otherwise
succeed.</para>
<para>If multiple conditions are
- specified the unit will be executed if
+ specified, the unit will be executed if
all of them apply (i.e. a logical AND
is applied). Condition checks can be
prefixed with a pipe symbol (|) in
which case a condition becomes a
triggering condition. If at least one
triggering condition is defined for a
- unit then the unit will be executed if
+ unit, then the unit will be executed if
at least one of the triggering
conditions apply and all of the
non-triggering conditions. If you
prefix an argument with the pipe
- symbol and an exclamation mark the
+ symbol and an exclamation mark, the
pipe symbol must be passed first, the
exclamation second. Except for
<varname>ConditionPathIsSymbolicLink=</varname>,
all path checks follow symlinks. If
any of these options is assigned the
- empty string the list of conditions is
+ empty string, the list of conditions is
reset completely, all previous
condition settings (of any kind) will
have no effect.</para></listitem>
@@ -1107,26 +1099,53 @@
time,
<command>systemctl enable</command>
will create symlinks from these names
- to the unit file name.</para></listitem>
+ to the unit filename.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>WantedBy=</varname></term>
<term><varname>RequiredBy=</varname></term>
- <listitem><para>Installs a symlink in
- the <filename>.wants/</filename>
- or <filename>.requires/</filename>
- subdirectory for a unit, respectively. This has the
- effect that when the listed unit name
- is activated the unit listing it is
- activated
- too. <command>WantedBy=foo.service</command>
+ <listitem><para>A symbolic link is
+ created in the
+ <filename>.wants/</filename> or
+ <filename>.requires/</filename> directory
+ of the listed unit when this unit is
+ activated by <command>systemctl
+ enable</command>. This has the effect
+ that a dependency of type
+ <varname>Wants=</varname> or
+ <varname>Requires=</varname> is added
+ from the listed unit to the current
+ unit. The primary result is that the
+ current unit will be started when the
+ listed unit is started. See the
+ description of
+ <varname>Wants=</varname> and
+ <varname>Requires=</varname> in the
+ [Unit] section for details.</para>
+
+ <para><command>WantedBy=foo.service</command>
in a service
<filename>bar.service</filename> is
mostly equivalent to
<command>Alias=foo.service.wants/bar.service</command>
- in the same file.</para></listitem>
+ in the same file. In case of template
+ units, <command>systemctl enable</command>
+ must be called with an instance name, and
+ this instance will be added to the
+ <filename>.wants/</filename> or
+ <filename>.requires/</filename> list
+ of the listed unit.
+ E.g. <command>WantedBy=getty.target</command>
+ in a service
+ <filename>getty@.service</filename>
+ will result in <command>systemctl
+ enable getty@tty2.service</command>
+ creating a
+ <filename>getty.target.wants/getty@tty2.service</filename>
+ link to <filename>getty@.service</filename>.
+ </para></listitem>
</varlistentry>
<varlistentry>
@@ -1146,7 +1165,7 @@
</variablelist>
<para>The following specifiers are interpreted in the
- Install section: %n, %N, %p, %i, %U, %u, %m, %H, %b.
+ Install section: %n, %N, %p, %i, %U, %u, %m, %H, %b, %v.
For their meaning see the next section.
</para>
</refsect1>
@@ -1197,7 +1216,7 @@
<row>
<entry><literal>%i</literal></entry>
<entry>Instance name</entry>
- <entry>For instantiated units: this is the string between the @ character and the suffix.</entry>
+ <entry>For instantiated units: this is the string between the <literal>@</literal> character and the suffix.</entry>
</row>
<row>
<entry><literal>%I</literal></entry>
@@ -1206,7 +1225,7 @@
</row>
<row>
<entry><literal>%f</literal></entry>
- <entry>Unescaped file name</entry>
+ <entry>Unescaped filename</entry>
<entry>This is either the unescaped instance name (if applicable) with <filename>/</filename> prepended (if applicable), or the prefix name similarly prepended with <filename>/</filename>.</entry>
</row>
<row>
@@ -1222,7 +1241,10 @@
<row>
<entry><literal>%R</literal></entry>
<entry>Parent directory of the control group path where units are placed.</entry>
- <entry>For system instances this usually resolves to <filename>/</filename>, except in containers, where this resolves to the container's root directory. This specifier is particularly useful in the <varname>ControlGroup=</varname> setting (see <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>).</entry>
+ <entry>For system instances this usually
+ resolves to <filename>/</filename>, except in
+ containers, where this resolves to the
+ container's root directory.</entry>
</row>
<row>
<entry><literal>%t</literal></entry>
@@ -1262,7 +1284,12 @@
<row>
<entry><literal>%H</literal></entry>
<entry>Host name</entry>
- <entry>The host name of the running system.</entry>
+ <entry>The hostname of the running system.</entry>
+ </row>
+ <row>
+ <entry><literal>%v</literal></entry>
+ <entry>Kernel release</entry>
+ <entry>Identical to <command>uname -r</command> output.</entry>
</row>
<row>
<entry><literal>%%</literal></entry>
@@ -1290,9 +1317,12 @@
<citerefentry><refentrytitle>systemd.path</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.timer</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.snapshot</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.scope</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>uname</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/systemd.xml b/man/systemd.xml
index d009ed8e1c..fe6e331f25 100644
--- a/man/systemd.xml
+++ b/man/systemd.xml
@@ -136,7 +136,7 @@
<term><option>--unit=</option></term>
<listitem><para>Set default unit to
- activate on startup. If not specified
+ activate on startup. If not specified,
defaults to
<filename>default.target</filename>.</para></listitem>
</varlistentry>
@@ -233,7 +233,7 @@
<listitem><para>Highlight important
log messages. Argument is a boolean
- value. If the argument is omitted it
+ value. If the argument is omitted, it
defaults to
<option>true</option>.</para></listitem>
</varlistentry>
@@ -285,25 +285,27 @@
<title>Concepts</title>
<para>systemd provides a dependency system between
- various entities called "units". 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
+ various entities called "units" of 12 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 or dynamically from system state. 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, or an operation timed out). If this
- state is entered the cause will be logged, for later
+ 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, or an operation timed out). 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
@@ -312,7 +314,7 @@
<para>The following unit types are available:</para>
<orderedlist>
- <listitem><para>Service units, which control
+ <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>
@@ -369,6 +371,18 @@
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
@@ -415,7 +429,7 @@
<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
+ 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>
@@ -425,7 +439,7 @@
individual Linux control groups named after the unit
which they belong to in the private systemd
hierarchy. (see <ulink
- url="http://www.kernel.org/doc/Documentation/cgroups/cgroups.txt">cgroups.txt</ulink>
+ url="https://www.kernel.org/doc/Documentation/cgroups/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
@@ -473,7 +487,7 @@
<para>Systemd contains native implementations of
various tasks that need to be executed as part of the
- boot process. For example, it sets the host name or
+ 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
@@ -611,7 +625,7 @@
<variablelist>
<varlistentry>
- <term>SIGTERM</term>
+ <term><constant>SIGTERM</constant></term>
<listitem><para>Upon receiving this
signal the systemd system manager
@@ -631,7 +645,7 @@
</varlistentry>
<varlistentry>
- <term>SIGINT</term>
+ <term><constant>SIGINT</constant></term>
<listitem><para>Upon receiving this
signal the systemd system manager will
@@ -643,11 +657,11 @@
<para>systemd user managers
treat this signal the same way as
- SIGTERM.</para></listitem>
+ <constant>SIGTERM</constant>.</para></listitem>
</varlistentry>
<varlistentry>
- <term>SIGWINCH</term>
+ <term><constant>SIGWINCH</constant></term>
<listitem><para>When this signal is
received the systemd system manager
@@ -663,7 +677,7 @@
</varlistentry>
<varlistentry>
- <term>SIGPWR</term>
+ <term><constant>SIGPWR</constant></term>
<listitem><para>When this signal is
received the systemd manager
@@ -675,7 +689,7 @@
</varlistentry>
<varlistentry>
- <term>SIGUSR1</term>
+ <term><constant>SIGUSR1</constant></term>
<listitem><para>When this signal is
received the systemd manager will try
@@ -684,7 +698,7 @@
</varlistentry>
<varlistentry>
- <term>SIGUSR2</term>
+ <term><constant>SIGUSR2</constant></term>
<listitem><para>When this signal is
received the systemd manager will log
@@ -695,7 +709,7 @@
</varlistentry>
<varlistentry>
- <term>SIGHUP</term>
+ <term><constant>SIGHUP</constant></term>
<listitem><para>Reloads the complete
daemon configuration. This is mostly
@@ -704,7 +718,7 @@
</varlistentry>
<varlistentry>
- <term>SIGRTMIN+0</term>
+ <term><constant>SIGRTMIN+0</constant></term>
<listitem><para>Enters default mode, starts the
<filename>default.target</filename>
@@ -714,7 +728,7 @@
</varlistentry>
<varlistentry>
- <term>SIGRTMIN+1</term>
+ <term><constant>SIGRTMIN+1</constant></term>
<listitem><para>Enters rescue mode,
starts the
@@ -725,7 +739,7 @@
</varlistentry>
<varlistentry>
- <term>SIGRTMIN+2</term>
+ <term><constant>SIGRTMIN+2</constant></term>
<listitem><para>Enters emergency mode,
starts the
@@ -736,7 +750,7 @@
</varlistentry>
<varlistentry>
- <term>SIGRTMIN+3</term>
+ <term><constant>SIGRTMIN+3</constant></term>
<listitem><para>Halts the machine,
starts the
@@ -747,7 +761,7 @@
</varlistentry>
<varlistentry>
- <term>SIGRTMIN+4</term>
+ <term><constant>SIGRTMIN+4</constant></term>
<listitem><para>Powers off the machine,
starts the
@@ -758,7 +772,7 @@
</varlistentry>
<varlistentry>
- <term>SIGRTMIN+5</term>
+ <term><constant>SIGRTMIN+5</constant></term>
<listitem><para>Reboots the machine,
starts the
@@ -769,7 +783,7 @@
</varlistentry>
<varlistentry>
- <term>SIGRTMIN+6</term>
+ <term><constant>SIGRTMIN+6</constant></term>
<listitem><para>Reboots the machine via kexec,
starts the
@@ -780,31 +794,31 @@
</varlistentry>
<varlistentry>
- <term>SIGRTMIN+13</term>
+ <term><constant>SIGRTMIN+13</constant></term>
<listitem><para>Immediately halts the machine.</para></listitem>
</varlistentry>
<varlistentry>
- <term>SIGRTMIN+14</term>
+ <term><constant>SIGRTMIN+14</constant></term>
<listitem><para>Immediately powers off the machine.</para></listitem>
</varlistentry>
<varlistentry>
- <term>SIGRTMIN+15</term>
+ <term><constant>SIGRTMIN+15</constant></term>
<listitem><para>Immediately reboots the machine.</para></listitem>
</varlistentry>
<varlistentry>
- <term>SIGRTMIN+16</term>
+ <term><constant>SIGRTMIN+16</constant></term>
<listitem><para>Immediately reboots the machine with kexec.</para></listitem>
</varlistentry>
<varlistentry>
- <term>SIGRTMIN+20</term>
+ <term><constant>SIGRTMIN+20</constant></term>
<listitem><para>Enables display of
status messages on the console, as
@@ -815,7 +829,7 @@
</varlistentry>
<varlistentry>
- <term>SIGRTMIN+21</term>
+ <term><constant>SIGRTMIN+21</constant></term>
<listitem><para>Disables display of
status messages on the console, as
@@ -826,23 +840,23 @@
</varlistentry>
<varlistentry>
- <term>SIGRTMIN+22</term>
- <term>SIGRTMIN+23</term>
+ <term><constant>SIGRTMIN+22</constant></term>
+ <term><constant>SIGRTMIN+23</constant></term>
<listitem><para>Sets the log level to
<literal>debug</literal>
(or <literal>info</literal> on
- <literal>SIGRTMIN+23</literal>), as
+ <constant>SIGRTMIN+23</constant>), as
controlled via
<varname>systemd.log_level=debug</varname>
(or <varname>systemd.log_level=info</varname>
- on <literal>SIGRTMIN+23</literal>) on
+ on <constant>SIGRTMIN+23</constant>) on
the kernel command
line.</para></listitem>
</varlistentry>
<varlistentry>
- <term>SIGRTMIN+24</term>
+ <term><constant>SIGRTMIN+24</constant></term>
<listitem><para>Immediately exits the
manager (only available for --user
@@ -850,28 +864,28 @@
</varlistentry>
<varlistentry>
- <term>SIGRTMIN+26</term>
- <term>SIGRTMIN+27</term>
- <term>SIGRTMIN+28</term>
- <term>SIGRTMIN+29</term>
+ <term><constant>SIGRTMIN+26</constant></term>
+ <term><constant>SIGRTMIN+27</constant></term>
+ <term><constant>SIGRTMIN+28</constant></term>
+ <term><constant>SIGRTMIN+29</constant></term>
<listitem><para>Sets the log level to
<literal>journal-or-kmsg</literal>
(or <literal>console</literal> on
- <literal>SIGRTMIN+27</literal>,
+ <constant>SIGRTMIN+27</constant>,
<literal>kmsg</literal> on
- <literal>SIGRTMIN+28</literal>,
+ <constant>SIGRTMIN+28</constant>,
or <literal>syslog-or-kmsg</literal>
- on <literal>SIGRTMIN+29</literal>), as
+ on <constant>SIGRTMIN+29</constant>), as
controlled via
<varname>systemd.log_target=journal-or-kmsg</varname>
(or <varname>systemd.log_target=console</varname>
- on <literal>SIGRTMIN+27</literal>,
+ on <constant>SIGRTMIN+27</constant>,
<varname>systemd.log_target=kmsg</varname>
- on <literal>SIGRTMIN+28</literal>,
+ on <constant>SIGRTMIN+28</constant>,
or
<varname>systemd.log_target=syslog-or-kmsg</varname>
- on <literal>SIGRTMIN+29</literal>) on
+ on <constant>SIGRTMIN+29</constant>) on
the kernel command
line.</para></listitem>
</varlistentry>
@@ -1008,7 +1022,7 @@
option prefixed with
<literal>rd.</literal> is honored
only in the initial RAM disk (initrd),
- while the one that isn't prefixed only
+ while the one that is not prefixed only
in the main system.</para></listitem>
</varlistentry>
@@ -1016,9 +1030,9 @@
<term><varname>systemd.dump_core=</varname></term>
<listitem><para>Takes a boolean
- argument. If <option>true</option>
+ argument. If <option>true</option>,
systemd dumps core when it
- crashes. Otherwise no core dump is
+ crashes. Otherwise, no core dump is
created. Defaults to
<option>true</option>.</para></listitem>
</varlistentry>
@@ -1027,9 +1041,9 @@
<term><varname>systemd.crash_shell=</varname></term>
<listitem><para>Takes a boolean
- argument. If <option>true</option>
+ argument. If <option>true</option>,
systemd spawns a shell when it
- crashes. Otherwise no shell is
+ crashes. Otherwise, no shell is
spawned. Defaults to
<option>false</option>, for security
reasons, as the shell is not protected
@@ -1044,14 +1058,14 @@
argument. If positive systemd
activates the specified virtual
terminal when it crashes. Defaults to
- <literal>-1</literal>.</para></listitem>
+ <constant>-1</constant>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>systemd.confirm_spawn=</varname></term>
<listitem><para>Takes a boolean
- argument. If <option>true</option>
+ argument. If <option>true</option>,
asks for confirmation when spawning
processes. Defaults to
<option>false</option>.</para></listitem>
@@ -1061,7 +1075,7 @@
<term><varname>systemd.show_status=</varname></term>
<listitem><para>Takes a boolean
- argument. If <option>true</option>
+ argument. If <option>true</option>,
shows terse service status updates on
the console during bootup. Defaults to
<option>true</option>, unless
@@ -1099,30 +1113,38 @@
<term><varname>systemd.setenv=</varname></term>
<listitem><para>Takes a string
- argument in the form
- VARIABLE=VALUE. May be used to set
- environment variables for the init
- process and all its children at boot
- time. May be used more than once to
- set multiple variables. If the equal
- sign and variable are missing it unsets
- an environment variable which might be
- passed in from the initial ram
- disk.</para></listitem>
+ 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>quiet</varname></term>
- <listitem><para>If passed turns off
+ <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 to the
- kernel. Passing this option hence
- turns off the usual output from both
- the system manager and the
+ 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>
@@ -1210,7 +1232,7 @@
<listitem><para>Daemon status
notification socket. This is an
- AF_UNIX datagram socket and is used to
+ <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>
@@ -1223,7 +1245,7 @@
<listitem><para>Used internally by the
<citerefentry><refentrytitle>shutdown</refentrytitle><manvolnum>8</manvolnum></citerefentry>
tool to implement delayed
- shutdowns. This is an AF_UNIX datagram
+ shutdowns. This is an <constant>AF_UNIX</constant> datagram
socket.</para></listitem>
</varlistentry>
@@ -1234,7 +1256,7 @@
communication channel between
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
and the systemd process. This is an
- AF_UNIX stream socket. This interface
+ <constant>AF_UNIX</constant> stream socket. This interface
is private to systemd and should not
be used in external
projects.</para></listitem>
@@ -1258,6 +1280,7 @@
<refsect1>
<title>See Also</title>
<para>
+ The <ulink url="http://www.freedesktop.org/wiki/Software/systemd/">systemd Homepage</ulink>,
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>locale.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
diff --git a/man/telinit.xml b/man/telinit.xml
index 4c6064f54a..bb8093914a 100644
--- a/man/telinit.xml
+++ b/man/telinit.xml
@@ -80,7 +80,7 @@
<varlistentry>
<term><option>--no-wall</option></term>
- <listitem><para>Don't send wall
+ <listitem><para>Do not send wall
message before
reboot/halt/power-off.</para></listitem>
</varlistentry>
diff --git a/man/timedatectl.xml b/man/timedatectl.xml
index faccc5086d..be0ad3f012 100644
--- a/man/timedatectl.xml
+++ b/man/timedatectl.xml
@@ -92,18 +92,26 @@
<varlistentry>
<term><option>--no-ask-password</option></term>
- <listitem><para>Don't query the user
+ <listitem><para>Do not query the user
for authentication for privileged
operations.</para></listitem>
</varlistentry>
<varlistentry>
+ <term><option>-P</option></term>
+ <term><option>--privileged</option></term>
+
+ <listitem><para>Acquire privileges via PolicyKit
+ before executing the operation.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>-H</option></term>
<term><option>--host</option></term>
<listitem><para>Execute the operation
remotely. Specify a hostname, or
- username and hostname separated by @,
+ username and hostname separated by <literal>@</literal>,
to connect to. This will use SSH to
talk to a remote
system.</para></listitem>
@@ -114,10 +122,10 @@
<listitem><para>If
<command>set-local-rtc</command> is
- invoked and this option is passed the
+ invoked and this option is passed, the
system clock is synchronized from the
RTC again, taking the new setting into
- account. Otherwise the RTC is
+ account. Otherwise, the RTC is
synchronized from the system
clock.</para></listitem>
</varlistentry>
@@ -150,10 +158,10 @@
<listitem><para>Set the system time
zone to the specified value. Available
- time zones can be listed with
+ timezones can be listed with
<command>list-timezones</command>. If
the RTC is configured to be in the
- local time this will also update the
+ local time, this will also update the
RTC time. This call will alter the
<filename>/etc/localtime</filename>
symlink. See
@@ -168,7 +176,7 @@
<listitem><para>List available time
zones, one per line. Entries from the
list can be set as the system
- time zone with
+ timezone with
<command>set-timezone</command>.</para></listitem>
</varlistentry>
@@ -176,17 +184,17 @@
<term><command>set-local-rtc [BOOL]</command></term>
<listitem><para>Takes a boolean
- argument. If <literal>0</literal> the
+ argument. If <literal>0</literal>, the
system is configured to maintain the
- RTC in universal time, if
- <literal>1</literal> it will maintain
+ RTC in universal time. If
+ <literal>1</literal>, it will maintain
the RTC in local time instead. Note
that maintaining the RTC in the local
- time zone is not fully supported and
+ timezone is not fully supported and
will create various problems with time
zone changes and daylight saving
- adjustments. If at all possible use
- RTC in UTC. Note that invoking this
+ adjustments. If at all possible, keep the
+ RTC in UTC mode. Note that invoking this
will also synchronize the RTC from the
system clock, unless
<option>--adjust-system-clock</option> is
diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml
index 519f9bc618..9fc4b7cd8f 100644
--- a/man/tmpfiles.d.xml
+++ b/man/tmpfiles.d.xml
@@ -67,7 +67,7 @@
<title>Configuration Format</title>
<para>Each configuration file shall be named in the
- style of <filename>&lt;program&gt;.conf</filename>.
+ style of <filename>&lt;package&gt;.conf</filename>.
Files in <filename>/etc/</filename> override files
with the same name in <filename>/usr/lib/</filename>
and <filename>/run/</filename>. Files in
@@ -79,17 +79,18 @@
administrator, who may use this logic to override the
configuration files installed by vendor packages. All
configuration files are sorted by their filename in
- alphabetical order, regardless in which of the
- directories they reside, to guarantee that a specific
- configuration file takes precedence over another file
- with an alphabetically later name.</para>
+ lexicographic order, regardless in which of the
+ directories they reside. If multiple files specify the
+ same path, the entry in the file with the lexicographically
+ earliest name will be applied, all all other conflicting
+ entries logged as errors.</para>
<para>If the administrator wants to disable a
- configuration file supplied by the vendor the
+ configuration file supplied by the vendor, the
recommended way is to place a symlink to
<filename>/dev/null</filename> in
<filename>/etc/tmpfiles.d/</filename> bearing the
- same file name.</para>
+ same filename.</para>
<para>The configuration format is one line per path
containing action, path, mode, ownership, age and argument
@@ -99,12 +100,16 @@
d /run/user 0755 root root 10d -
L /tmp/foobar - - - - /dev/null</programlisting>
+
<refsect2>
<title>Type</title>
+
+ <para>The following line types are understood:</para>
+
<variablelist>
<varlistentry>
<term><varname>f</varname></term>
- <listitem><para>Create a file if it doesn't exist yet (optionally writing a short string into it, if the argument parameter is passed)</para></listitem>
+ <listitem><para>Create a file if it does not exist yet (optionally writing a short string into it, if the argument parameter is passed)</para></listitem>
</varlistentry>
<varlistentry>
@@ -122,7 +127,7 @@ L /tmp/foobar - - - - /dev/null</programlisting>
<varlistentry>
<term><varname>d</varname></term>
- <listitem><para>Create a directory if it doesn't exist yet</para></listitem>
+ <listitem><para>Create a directory if it does not exist yet</para></listitem>
</varlistentry>
<varlistentry>
@@ -132,22 +137,33 @@ L /tmp/foobar - - - - /dev/null</programlisting>
<varlistentry>
<term><varname>p</varname></term>
- <listitem><para>Create a named pipe (FIFO) if it doesn't exist yet</para></listitem>
+ <listitem><para>Create a named pipe (FIFO) if it does not exist yet</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>L</varname></term>
- <listitem><para>Create a symlink if it doesn't exist yet</para></listitem>
+ <listitem><para>Create a symlink if it does not exist yet</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>c</varname></term>
- <listitem><para>Create a character device node if it doesn't exist yet</para></listitem>
+ <listitem><para>Create a character device node if it does not exist yet</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>b</varname></term>
- <listitem><para>Create a block device node if it doesn't exist yet</para></listitem>
+ <listitem><para>Create a block device node if it does not exist yet</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>m</varname></term>
+ <listitem><para>If the
+ specified file path exists
+ adjust its access mode, group
+ and user to the specified
+ values and reset the SELinux
+ label. If it doesn't exist do
+ nothing.</para></listitem>
</varlistentry>
<varlistentry>
@@ -233,14 +249,65 @@ L /tmp/foobar - - - - /dev/null</programlisting>
</refsect2>
<refsect2>
+ <title>Path</title>
+
+ <para>The file system path specification supports simple specifier
+ expansion. The following expansions are
+ understood:</para>
+
+ <table>
+ <title>Specifiers available</title>
+ <tgroup cols='3' align='left' colsep='1' rowsep='1'>
+ <colspec colname="spec" />
+ <colspec colname="mean" />
+ <colspec colname="detail" />
+ <thead>
+ <row>
+ <entry>Specifier</entry>
+ <entry>Meaning</entry>
+ <entry>Details</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>%m</literal></entry>
+ <entry>Machine ID</entry>
+ <entry>The machine ID of the running system, formatted as string. See <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry> for more information.</entry>
+ </row>
+ <row>
+ <entry><literal>%b</literal></entry>
+ <entry>Boot ID</entry>
+ <entry>The boot ID of the running system, formatted as string. See <citerefentry><refentrytitle>random</refentrytitle><manvolnum>4</manvolnum></citerefentry> for more information.</entry>
+ </row>
+ <row>
+ <entry><literal>%H</literal></entry>
+ <entry>Host name</entry>
+ <entry>The hostname of the running system.</entry>
+ </row>
+ <row>
+ <entry><literal>%v</literal></entry>
+ <entry>Kernel release</entry>
+ <entry>Identical to <command>uname -r</command> output.</entry>
+ </row>
+ <row>
+ <entry><literal>%%</literal></entry>
+ <entry>Escaped %</entry>
+ <entry>Single percent sign.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </refsect2>
+
+ <refsect2>
<title>Mode</title>
<para>The file access mode to use when
creating this file or directory. If omitted or
- when set to - the default is used: 0755 for
+ when set to -, the default is used: 0755 for
directories, 0644 for all other file
- objects. For z, Z lines if omitted or when set
- to - the file access mode will not be
+ objects. For z, Z lines, if omitted or when set
+ to -, the file access mode will not be
modified. This parameter is ignored for x, r,
R, L lines.</para>
</refsect2>
@@ -251,8 +318,8 @@ L /tmp/foobar - - - - /dev/null</programlisting>
<para>The user and group to use for this file
or directory. This may either be a numeric
user/group ID or a user or group name. If
- omitted or when set to - the default 0 (root)
- is used. For z, Z lines when omitted or when set to -
+ omitted or when set to -, the default 0 (root)
+ is used. For z, Z lines, when omitted or when set to -,
the file ownership will not be modified.
These parameters are ignored for x, r, R, L lines.</para>
</refsect2>
@@ -262,7 +329,7 @@ L /tmp/foobar - - - - /dev/null</programlisting>
<para>The date field, when set, is used to
decide what files to delete when cleaning. If
a file or directory is older than the current
- time minus the age field it is deleted. The
+ time minus the age field, it is deleted. The
field format is a series of integers each
followed by one of the following
postfixes for the respective time units:</para>
@@ -279,7 +346,7 @@ L /tmp/foobar - - - - /dev/null</programlisting>
<term><varname>us</varname></term></varlistentry>
</variablelist>
- <para>If multiple integers and units are specified the time
+ <para>If multiple integers and units are specified, the time
values are summed up. If an integer is given without a unit,
s is assumed.
</para>
@@ -288,11 +355,11 @@ L /tmp/foobar - - - - /dev/null</programlisting>
unconditionally.</para>
<para>The age field only applies to lines starting with
- d, D and x. If omitted or set to - no automatic clean-up
+ d, D and x. If omitted or set to -, no automatic clean-up
is done.</para>
<para>If the age field starts with a tilde
- character (~) the clean-up is only applied to
+ character (~), the clean-up is only applied to
files and directories one level inside the
directory specified, but not the files and
directories immediately inside it.</para>
@@ -322,6 +389,13 @@ L /tmp/foobar - - - - /dev/null</programlisting>
<programlisting>d /var/run/screens 1777 root root 10d
d /var/run/uscreens 0755 root root 10d12h</programlisting>
</example>
+ <example>
+ <title>/etc/tmpfiles.d/abrt.conf example</title>
+ <para><command>abrt</command> needs a directory created at boot with specific mode and ownership and its content should be preserved.</para>
+
+ <programlisting>d /var/tmp/abrt 0755 abrt abrt
+x /var/tmp/abrt/*</programlisting>
+ </example>
</refsect1>
<refsect1>
diff --git a/man/udev.xml b/man/udev.xml
index e253a0677a..f107482329 100644
--- a/man/udev.xml
+++ b/man/udev.xml
@@ -30,7 +30,7 @@
<refnamediv>
<refname>udev</refname>
- <refpurpose>Linux dynamic device management</refpurpose>
+ <refpurpose>Dynamic device management</refpurpose>
</refnamediv>
<refsect1><title>Description</title>
@@ -54,26 +54,24 @@
sources is provided by the library libudev.</para>
</refsect1>
- <refsect1><title>Rules files</title>
+ <refsect1><title>Rules Files</title>
<para>The udev rules are read from the files located in the
system rules directory <filename>/usr/lib/udev/rules.d</filename>,
the volatile runtime directory <filename>/run/udev/rules.d</filename>
and the local administration directory <filename>/etc/udev/rules.d</filename>.
All rules files are collectively sorted and processed in lexical order,
regardless of the directories in which they live. However, files with
- identical file names replace each other. Files in <filename>/etc</filename>
+ identical filenames replace each other. Files in <filename>/etc</filename>
have the highest priority, files in <filename>/run</filename> take precedence
over files with the same name in <filename>/lib</filename>. This can be
used to override a system-supplied rules file with a local file if needed;
a symlink in <filename>/etc</filename> with the same name as a rules file in
<filename>/lib</filename>, pointing to <filename>/dev/null</filename>,
- disables the rules file entirely.</para>
-
- <para>Rule files must have the extension <filename>.rules</filename>; other
- extensions are ignored.</para>
+ disables the rules file entirely. Rule files must have the extension
+ <filename>.rules</filename>; other extensions are ignored.</para>
<para>Every line in the rules file contains at least one key-value pair.
- Except for empty lines or lines beginning with '#', which are ignored.
+ Except for empty lines or lines beginning with <literal>#</literal>, which are ignored.
There are two kinds of keys: match and assignment.
If all match keys match against their values, the rule gets applied and the
assignment keys get the specified values assigned.</para>
@@ -130,28 +128,28 @@
one and the same parent device.</para>
<variablelist class='udev-directives'>
<varlistentry>
- <term><option>ACTION</option></term>
+ <term><varname>ACTION</varname></term>
<listitem>
<para>Match the name of the event action.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>DEVPATH</option></term>
+ <term><varname>DEVPATH</varname></term>
<listitem>
<para>Match the devpath of the event device.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>KERNEL</option></term>
+ <term><varname>KERNEL</varname></term>
<listitem>
<para>Match the name of the event device.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>NAME</option></term>
+ <term><varname>NAME</varname></term>
<listitem>
<para>Match the name of a network interface. It can be used once the
NAME key has been set in one of the preceding rules.</para>
@@ -159,7 +157,7 @@
</varlistentry>
<varlistentry>
- <term><option>SYMLINK</option></term>
+ <term><varname>SYMLINK</varname></term>
<listitem>
<para>Match the name of a symlink targeting the node. It can
be used once a SYMLINK key has been set in one of the preceding
@@ -169,20 +167,20 @@
</varlistentry>
<varlistentry>
- <term><option>SUBSYSTEM</option></term>
+ <term><varname>SUBSYSTEM</varname></term>
<listitem>
<para>Match the subsystem of the event device.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>DRIVER</option></term>
+ <term><varname>DRIVER</varname></term>
<listitem>
<para>Match the driver name of the event device. Only set this key for devices
which are bound to a driver at the time the event is generated.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>ATTR{<replaceable>filename</replaceable>}</option></term>
+ <term><varname>ATTR{<replaceable>filename</replaceable>}</varname></term>
<listitem>
<para>Match sysfs attribute values of the event device. Trailing
whitespace in the attribute values is ignored unless the specified match
@@ -192,59 +190,59 @@
</varlistentry>
<varlistentry>
- <term><option>KERNELS</option></term>
+ <term><varname>KERNELS</varname></term>
<listitem>
<para>Search the devpath upwards for a matching device name.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>SUBSYSTEMS</option></term>
+ <term><varname>SUBSYSTEMS</varname></term>
<listitem>
<para>Search the devpath upwards for a matching device subsystem name.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>DRIVERS</option></term>
+ <term><varname>DRIVERS</varname></term>
<listitem>
<para>Search the devpath upwards for a matching device driver name.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>ATTRS{<replaceable>filename</replaceable>}</option></term>
+ <term><varname>ATTRS{<replaceable>filename</replaceable>}</varname></term>
<listitem>
<para>Search the devpath upwards for a device with matching sysfs attribute values.
- If multiple <option>ATTRS</option> matches are specified, all of them
+ If multiple <varname>ATTRS</varname> matches are specified, all of them
must match on the same device. Trailing whitespace in the attribute values is ignored
unless the specified match value itself contains trailing whitespace.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>TAGS</option></term>
+ <term><varname>TAGS</varname></term>
<listitem>
<para>Search the devpath upwards for a device with matching tag.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>ENV{<replaceable>key</replaceable>}</option></term>
+ <term><varname>ENV{<replaceable>key</replaceable>}</varname></term>
<listitem>
<para>Match against a device property value.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>TAG</option></term>
+ <term><varname>TAG</varname></term>
<listitem>
<para>Match against a device tag.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>TEST{<replaceable>octal mode mask</replaceable>}</option></term>
+ <term><varname>TEST{<replaceable>octal mode mask</replaceable>}</varname></term>
<listitem>
<para>Test the existence of a file. An octal mode mask can be specified
if needed.</para>
@@ -252,7 +250,7 @@
</varlistentry>
<varlistentry>
- <term><option>PROGRAM</option></term>
+ <term><varname>PROGRAM</varname></term>
<listitem>
<para>Execute a program to determine whether there
is a match; the key is true if the program returns
@@ -260,12 +258,12 @@
executed program in the environment. The program's stdout
is available in the RESULT key.</para>
<para>This can only be used for very short-running foreground tasks. For details
- see <option>RUN</option>.</para>
+ see <varname>RUN</varname>.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>RESULT</option></term>
+ <term><varname>RESULT</varname></term>
<listitem>
<para>Match the returned string of the last PROGRAM call. This key can
be used in the same or in any later rule after a PROGRAM call.</para>
@@ -273,7 +271,7 @@
</varlistentry>
</variablelist>
- <para>Most of the fields support shell-style pattern matching. The following
+ <para>Most of the fields support shell glob pattern matching. The following
pattern characters are supported:</para>
<variablelist>
<varlistentry>
@@ -292,11 +290,12 @@
<term><literal>[]</literal></term>
<listitem>
<para>Matches any single character specified within the brackets. For
- example, the pattern string 'tty[SR]' would match either 'ttyS' or 'ttyR'.
- Ranges are also supported via the '-' character.
+ example, the pattern string <literal>tty[SR]</literal>
+ would match either <literal>ttyS</literal> or <literal>ttyR</literal>.
+ Ranges are also supported via the <literal>-</literal> character.
For example, to match on the range of all digits, the pattern [0-9] could
- be used. If the first character following the '[' is a '!', any characters
- not enclosed are matched.</para>
+ be used. If the first character following the <literal>[</literal> is a
+ <literal>!</literal>, any characters not enclosed are matched.</para>
</listitem>
</varlistentry>
</variablelist>
@@ -304,7 +303,7 @@
<para>The following keys can get values assigned:</para>
<variablelist class='udev-directives'>
<varlistentry>
- <term><option>NAME</option></term>
+ <term><varname>NAME</varname></term>
<listitem>
<para>The name to use for a network interface. The name of a device node
cannot be changed by udev, only additional symlinks can be created.</para>
@@ -312,14 +311,14 @@
</varlistentry>
<varlistentry>
- <term><option>SYMLINK</option></term>
+ <term><varname>SYMLINK</varname></term>
<listitem>
<para>The name of a symlink targeting the node. Every matching rule adds
this value to the list of symlinks to be created.</para>
<para>The set of characters to name a symlink is limited. Allowed
- characters are [0-9A-Za-z#+-.:=@_/], valid utf8 character sequences,
- and "\x00" hex encoding. All other characters are replaced by
- a '_' character.</para>
+ characters are <literal>0-9A-Za-z#+-.:=@_/</literal>, valid UTF-8 character
+ sequences, and <literal>\x00</literal> hex encoding. All other
+ characters are replaced by a <literal>_</literal> character.</para>
<para>Multiple symlinks may be specified by separating the names by the
space character. In case multiple devices claim the same name, the link
always points to the device with the highest link_priority. If the current
@@ -334,7 +333,7 @@
</varlistentry>
<varlistentry>
- <term><option>OWNER</option>, <option>GROUP</option>, <option>MODE</option></term>
+ <term><varname>OWNER</varname>, <varname>GROUP</varname>, <varname>MODE</varname></term>
<listitem>
<para>The permissions for the device node. Every specified value overrides
the compiled-in default value.</para>
@@ -342,7 +341,7 @@
</varlistentry>
<varlistentry>
- <term><option>ATTR{<replaceable>key</replaceable>}</option></term>
+ <term><varname>ATTR{<replaceable>key</replaceable>}</varname></term>
<listitem>
<para>The value that should be written to a sysfs attribute of the
event device.</para>
@@ -350,16 +349,16 @@
</varlistentry>
<varlistentry>
- <term><option>ENV{<replaceable>key</replaceable>}</option></term>
+ <term><varname>ENV{<replaceable>key</replaceable>}</varname></term>
<listitem>
- <para>Set a device property value. Property names with a leading '.'
+ <para>Set a device property value. Property names with a leading <literal>.</literal>
are neither stored in the database nor exported to events or
external tools (run by, say, the PROGRAM match key).</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>TAG</option></term>
+ <term><varname>TAG</varname></term>
<listitem>
<para>Attach a tag to a device. This is used to filter events for users
of libudev's monitor functionality, or to enumerate a group of tagged
@@ -372,7 +371,7 @@
</varlistentry>
<varlistentry>
- <term><option>RUN{<replaceable>type</replaceable>}</option></term>
+ <term><varname>RUN{<replaceable>type</replaceable>}</varname></term>
<listitem>
<para>Add a program to the list of programs to be executed after processing all the
rules for a specific event, depending on <literal>type</literal>:</para>
@@ -390,7 +389,7 @@
<varlistentry>
<term><literal>builtin</literal></term>
<listitem>
- <para>As <option>program</option>, but use one of the built-in programs rather
+ <para>As <varname>program</varname>, but use one of the built-in programs rather
than an external one.</para>
</listitem>
</varlistentry>
@@ -407,21 +406,21 @@
</varlistentry>
<varlistentry>
- <term><option>LABEL</option></term>
+ <term><varname>LABEL</varname></term>
<listitem>
<para>A named label to which a GOTO may jump.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>GOTO</option></term>
+ <term><varname>GOTO</varname></term>
<listitem>
<para>Jumps to the next LABEL with a matching name.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>IMPORT{<replaceable>type</replaceable>}</option></term>
+ <term><varname>IMPORT{<replaceable>type</replaceable>}</varname></term>
<listitem>
<para>Import a set of variables as device properties,
depending on <literal>type</literal>:</para>
@@ -432,14 +431,14 @@
<para>Execute an external program specified as the assigned value and
import its output, which must be in environment key
format. Path specification, command/argument separation,
- and quoting work like in <option>RUN</option>.</para>
+ and quoting work like in <varname>RUN</varname>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>builtin</literal></term>
<listitem>
- <para>As <option>program</option>, but use one of the built-in programs rather
- than an external one.</para>
+ <para>Similar to <literal>program</literal>, but use one of the
+ built-in programs rather than an external one.</para>
</listitem>
</varlistentry>
<varlistentry>
@@ -461,7 +460,7 @@
<term><literal>cmdline</literal></term>
<listitem>
<para>Import a single property from the kernel command line. For simple flags
- the value of the property is set to '1'.</para>
+ the value of the property is set to <literal>1</literal>.</para>
</listitem>
</varlistentry>
<varlistentry>
@@ -470,7 +469,7 @@
<para>Import the stored keys from the parent device by reading
the database entry of the parent device. The value assigned to
<option>IMPORT{parent}</option> is used as a filter of key names
- to import (with the same shell-style pattern matching used for
+ to import (with the same shell glob pattern matching used for
comparisons).</para>
</listitem>
</varlistentry>
@@ -481,7 +480,7 @@
</varlistentry>
<varlistentry>
- <term><option>WAIT_FOR</option></term>
+ <term><varname>WAIT_FOR</varname></term>
<listitem>
<para>Wait for a file to become available or until a timeout of
10 seconds expires. The path is relative to the sysfs device;
@@ -490,7 +489,7 @@
</varlistentry>
<varlistentry>
- <term><option>OPTIONS</option></term>
+ <term><varname>OPTIONS</varname></term>
<listitem>
<para>Rule and device options:</para>
<variablelist class='udev-directives'>
@@ -520,9 +519,13 @@
<term><option>static_node=</option></term>
<listitem>
<para>Apply the permissions specified in this rule to the static device node with
- the specified name. Static device node creation can be requested by kernel modules.
- These nodes might not have a corresponding kernel device at the time systemd-udevd is
- started; they can trigger automatic kernel module loading.</para>
+ the specified name. Also, for every tag specified in this rule, create a symlink
+ in the directory
+ <filename>/run/udev/static_node-tags/<replaceable>tag</replaceable></filename>
+ pointing at the static device node with the specified name. Static device node
+ creation is performed by systemd-tmpfiles before systemd-udevd is started. The
+ static nodes might not have a corresponding kernel device; they are used to
+ trigger automatic kernel module loading when they are accessed.</para>
</listitem>
</varlistentry>
<varlistentry>
@@ -543,9 +546,9 @@
</varlistentry>
</variablelist>
- <para>The <option>NAME</option>, <option>SYMLINK</option>, <option>PROGRAM</option>,
- <option>OWNER</option>, <option>GROUP</option>, <option>MODE</option> and <option>RUN</option>
- fields support simple string substitutions. The <option>RUN</option>
+ <para>The <varname>NAME</varname>, <varname>SYMLINK</varname>, <varname>PROGRAM</varname>,
+ <varname>OWNER</varname>, <varname>GROUP</varname>, <varname>MODE</varname> and <varname>RUN</varname>
+ fields support simple string substitutions. The <varname>RUN</varname>
substitutions are performed after all rules have been processed, right before the program
is executed, allowing for the use of device properties set by earlier matching
rules. For all other fields, substitutions are performed while the individual rule is
@@ -561,8 +564,8 @@
<varlistentry>
<term><option>$number</option>, <option>%n</option></term>
<listitem>
- <para>The kernel number for this device. For example, 'sda3' has
- kernel number of '3'</para>
+ <para>The kernel number for this device. For example,
+ <literal>sda3</literal> has kernel number <literal>3</literal>.</para>
</listitem>
</varlistentry>
@@ -630,9 +633,9 @@
<listitem>
<para>The string returned by the external program requested with PROGRAM.
A single part of the string, separated by a space character, may be selected
- by specifying the part number as an attribute: <option>%c{N}</option>.
- If the number is followed by the '+' character, this part plus all remaining parts
- of the result string are substituted: <option>%c{N+}</option></para>
+ by specifying the part number as an attribute: <literal>%c{N}</literal>.
+ If the number is followed by the <literal>+</literal> character, this part plus all remaining parts
+ of the result string are substituted: <literal>%c{N+}</literal>.</para>
</listitem>
</varlistentry>
@@ -681,21 +684,56 @@
</varlistentry>
<varlistentry>
- <term><literal>%%</literal></term>
+ <term><option>%%</option></term>
<listitem>
- <para>The '%' character itself.</para>
+ <para>The <literal>%</literal> character itself.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><literal>$$</literal></term>
+ <term><option>$$</option></term>
<listitem>
- <para>The '$' character itself.</para>
+ <para>The <literal>$</literal> character itself.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
+ <refsect1><title>Hardware Database Files</title>
+ <para>The hwdb files are read from the files located in the
+ system hwdb directory <filename>/usr/lib/udev/hwdb.d</filename>,
+ the volatile runtime directory <filename>/run/udev/hwdb.d</filename>
+ and the local administration directory <filename>/etc/udev/hwdb.d</filename>.
+ All hwdb files are collectively sorted and processed in lexical order,
+ regardless of the directories in which they live. However, files with
+ identical filenames replace each other. Files in <filename>/etc</filename>
+ have the highest priority, files in <filename>/run</filename> take precedence
+ over files with the same name in <filename>/lib</filename>. This can be
+ used to override a system-supplied hwdb file with a local file if needed;
+ a symlink in <filename>/etc</filename> with the same name as a hwdb file in
+ <filename>/lib</filename>, pointing to <filename>/dev/null</filename>,
+ disables the hwdb file entirely. hwdb files must have the extension
+ <filename>.hwdb</filename>; other extensions are ignored.</para>
+
+ <para>The hwdb file contains data records consisting of matches and
+ associated key-value pairs. Every record in the hwdb starts with one or
+ more match string, specifying a shell glob to compare the database
+ lookup string against. Multiple match lines are specified in additional
+ consecutive lines. Every match line is compared indivdually, they are
+ combined by OR. Every match line must start at the first character of
+ the line.</para>
+
+ <para>The match lines are followed by one or more key-value pair lines, which
+ are recognized by a leading space character. The key name and value are separated
+ by <literal>=</literal>. An empty line signifies the end
+ of a record. Lines beginning with <literal>#</literal> are ignored.</para>
+
+ <para>The content of all hwdb files is read by
+ <citerefentry><refentrytitle>udevadm</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ and compiled to a binary database located at <filename>/etc/udev/hwdb.bin</filename>.
+ During runtime only the binary database is used.</para>
+ </refsect1>
+
<refsect1>
<title>See Also</title>
<para><citerefentry>
diff --git a/po/POTFILES.skip b/po/POTFILES.skip
index 0502c13023..b552029b82 100644
--- a/po/POTFILES.skip
+++ b/po/POTFILES.skip
@@ -5,12 +5,14 @@ src/core/dbus-manager.c
src/core/dbus-mount.c
src/core/dbus-path.c
src/core/dbus-service.c
+src/core/dbus-slice.c
src/core/dbus-snapshot.c
src/core/dbus-socket.c
src/core/dbus-swap.c
src/core/dbus-target.c
src/core/dbus-timer.c
src/core/dbus-unit.c
+src/core/dbus-scope.c
src/hostname/hostnamed.c
src/locale/localed.c
src/core/org.freedesktop.systemd1.policy.in
diff --git a/rules/60-keyboard.rules b/rules/60-keyboard.rules
new file mode 100644
index 0000000000..4e0f3663f6
--- /dev/null
+++ b/rules/60-keyboard.rules
@@ -0,0 +1,22 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION!="add", GOTO="keyboard_end"
+KERNEL!="event*", GOTO="keyboard_end"
+ENV{ID_INPUT_KEY}=="", GOTO="keyboard_end"
+
+# ignore all bluetooth devices
+SUBSYSTEMS=="bluetooth", GOTO="keyboard_end"
+
+# import key mapping for USB device
+SUBSYSTEMS=="usb", IMPORT{builtin}="hwdb --subsystem=usb --lookup-prefix=keyboard:", \
+ RUN{builtin}+="keyboard", GOTO="keyboard_end"
+
+# import key mapping for AT keyboard from DMI data
+DRIVERS=="atkbd", IMPORT{builtin}="hwdb 'keyboard:$attr{[dmi/id]modalias}'", \
+ RUN{builtin}+="keyboard", GOTO="keyboard_end"
+
+# import key mapping for platform input device
+KERNELS=="input*", IMPORT{builtin}="hwdb 'keyboard:name:$attr{name}:$attr{[dmi/id]modalias}'", \
+ RUN{builtin}+="keyboard", GOTO="keyboard_end"
+
+LABEL="keyboard_end"
diff --git a/rules/75-net-description.rules b/rules/75-net-description.rules
index fe9fca14db..7e62f8b26b 100644
--- a/rules/75-net-description.rules
+++ b/rules/75-net-description.rules
@@ -4,11 +4,11 @@ ACTION=="remove", GOTO="net_end"
SUBSYSTEM!="net", GOTO="net_end"
IMPORT{builtin}="net_id"
+
SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb"
SUBSYSTEMS=="usb", GOTO="net_end"
SUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}"
-
-IMPORT{builtin}="hwdb"
+SUBSYSTEMS=="pci", IMPORT{builtin}="hwdb --subsystem=pci"
LABEL="net_end"
diff --git a/rules/75-tty-description.rules b/rules/75-tty-description.rules
index 83083d93ea..11277b7d6f 100644
--- a/rules/75-tty-description.rules
+++ b/rules/75-tty-description.rules
@@ -7,7 +7,6 @@ SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=u
SUBSYSTEMS=="usb", GOTO="tty_end"
SUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}"
-
-IMPORT{builtin}="hwdb"
+SUBSYSTEMS=="pci", IMPORT{builtin}="hwdb --subsystem=pci"
LABEL="tty_end"
diff --git a/rules/80-drivers.rules b/rules/80-drivers.rules
index 50523e4333..0b22d73ce5 100644
--- a/rules/80-drivers.rules
+++ b/rules/80-drivers.rules
@@ -2,7 +2,7 @@
ACTION=="remove", GOTO="drivers_end"
-DRIVER!="?*", ENV{MODALIAS}=="?*", RUN{builtin}="kmod load $env{MODALIAS}"
+ENV{MODALIAS}=="?*", RUN{builtin}="kmod load $env{MODALIAS}"
SUBSYSTEM=="tifm", ENV{TIFM_CARD_TYPE}=="SD", RUN{builtin}="kmod load tifm_sd"
SUBSYSTEM=="tifm", ENV{TIFM_CARD_TYPE}=="MS", RUN{builtin}="kmod load tifm_ms"
SUBSYSTEM=="memstick", RUN{builtin}="kmod load ms_block mspro_block"
diff --git a/rules/80-net-name-slot.rules b/rules/80-net-name-slot.rules
index 15b5bc4107..c5f1b3885b 100644
--- a/rules/80-net-name-slot.rules
+++ b/rules/80-net-name-slot.rules
@@ -1,6 +1,6 @@
# do not edit this file, it will be overwritten on update
-ACTION=="remove", GOTO="net_name_slot_end"
+ACTION!="add", GOTO="net_name_slot_end"
SUBSYSTEM!="net", GOTO="net_name_slot_end"
NAME!="", GOTO="net_name_slot_end"
diff --git a/rules/99-systemd.rules.in b/rules/99-systemd.rules.in
index d17bdd9a0a..bbb7d0c2c3 100644
--- a/rules/99-systemd.rules.in
+++ b/rules/99-systemd.rules.in
@@ -49,7 +49,11 @@ SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{ID_USB_INTERFACES}=="*:0701??:
# Apply sysctl variables to network devices (and only to those) as they appear.
-SUBSYSTEM=="net", KERNEL!="lo", RUN+="@rootlibexecdir@/systemd-sysctl --prefix=/proc/sys/net/ipv4/conf/$name --prefix=/proc/sys/net/ipv4/neigh/$name --prefix=/proc/sys/net/ipv6/conf/$name --prefix=/proc/sys/net/ipv6/neigh/$name"
+ACTION=="add", SUBSYSTEM=="net", KERNEL!="lo", RUN+="@rootlibexecdir@/systemd-sysctl --prefix=/proc/sys/net/ipv4/conf/$name --prefix=/proc/sys/net/ipv4/neigh/$name --prefix=/proc/sys/net/ipv6/conf/$name --prefix=/proc/sys/net/ipv6/neigh/$name"
+
+# Pull in backlight save/restore for all firmware backlight devices
+
+ACTION=="add", SUBSYSTEM=="backlight", ATTR{type}=="firmware", TAG+="systemd", ENV{SYSTEMD_WANTS}+="systemd-backlight@$name.service"
# Asynchronously mount file systems implemented by these modules as
# soon as they are loaded.
diff --git a/rules/Makefile b/rules/Makefile
new file mode 120000
index 0000000000..bd1047548b
--- /dev/null
+++ b/rules/Makefile
@@ -0,0 +1 @@
+../src/Makefile \ No newline at end of file
diff --git a/shell-completion/bash/hostnamectl b/shell-completion/bash/hostnamectl
index a57bffe15f..38ab1344f3 100644
--- a/shell-completion/bash/hostnamectl
+++ b/shell-completion/bash/hostnamectl
@@ -18,9 +18,10 @@
# along with systemd; If not, see <http://www.gnu.org/licenses/>.
__contains_word () {
- local word=$1; shift
- for w in $*; do [[ $w = $word ]] && return 0; done
- return 1
+ local w word=$1; shift
+ for w in "$@"; do
+ [[ $w = "$word" ]] && return
+ done
}
_hostnamectl() {
diff --git a/shell-completion/bash/journalctl b/shell-completion/bash/journalctl
index 19362ae77b..3c40d57a98 100644
--- a/shell-completion/bash/journalctl
+++ b/shell-completion/bash/journalctl
@@ -18,9 +18,10 @@
# along with systemd; If not, see <http://www.gnu.org/licenses/>.
__contains_word () {
- local word=$1; shift
- for w in $*; do [[ $w = $word ]] && return 0; done
- return 1
+ local w word=$1; shift
+ for w in "$@"; do
+ [[ $w = "$word" ]] && return
+ done
}
__journal_fields=(MESSAGE{,_ID} PRIORITY CODE_{FILE,LINE,FUNC}
@@ -37,18 +38,22 @@ __journal_fields=(MESSAGE{,_ID} PRIORITY CODE_{FILE,LINE,FUNC}
_journalctl() {
local field_vals= cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
local -A OPTS=(
- [STANDALONE]='-a --all --full
- -b --this-boot --disk-usage -f --follow --header
+ [STANDALONE]='-a --all --full --system --user
+ --disk-usage -f --follow --header
-h --help -l --local --new-id128 -m --merge --no-pager
--no-tail -q --quiet --setup-keys --this-boot --verify
--version --list-catalog --update-catalog'
- [ARG]='-D --directory -F --field -o --output -u --unit --user-unit'
+ [ARG]='-b --boot --this-boot -D --directory -F --field
+ -o --output -u --unit --user-unit'
[ARGUNKNOWN]='-c --cursor --interval -n --lines -p --priority --since --until
--verify-key'
)
if __contains_word "$prev" ${OPTS[ARG]} ${OPTS[ARGUNKNOWN]}; then
case $prev in
+ --boot|--this-boot|-b)
+ comps=$(journalctl -F '_BOOT_ID' 2>/dev/null)
+ ;;
--directory|-D)
comps=$(compgen -d -- "$cur")
compopt -o filenames
diff --git a/shell-completion/bash/kernel-install b/shell-completion/bash/kernel-install
new file mode 100644
index 0000000000..7cd2494cf7
--- /dev/null
+++ b/shell-completion/bash/kernel-install
@@ -0,0 +1,50 @@
+# kernel-install(8) completion -*- shell-script -*-
+#
+# This file is part of systemd.
+#
+# Copyright 2013 Kay Sievers
+# Copyright 2013 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with systemd; If not, see <http://www.gnu.org/licenses/>.
+
+_kernel_install() {
+ local comps
+ local MACHINE_ID
+ local cur=${COMP_WORDS[COMP_CWORD]}
+
+ case $COMP_CWORD in
+ 1)
+ comps="add remove"
+ ;;
+ 2)
+ comps=$(cd /lib/modules; echo [0-9]*)
+ if [[ ${COMP_WORDS[1]} == "remove" ]] && [[ -f /etc/machine-id ]]; then
+ read MACHINE_ID < /etc/machine-id
+ if [[ $MACHINE_ID ]] && ( [[ -d /boot/$MACHINE_ID ]] || [[ -L /boot/$MACHINE_ID ]] ); then
+ comps=$(cd "/boot/$MACHINE_ID"; echo [0-9]*)
+ fi
+ fi
+ ;;
+ 3)
+ [[ "$cur" ]] || cur=/boot/vmlinuz-${COMP_WORDS[2]}
+ comps=$(compgen -f -- "$cur")
+ compopt -o filenames
+ ;;
+ esac
+
+ COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
+ return 0
+}
+
+complete -F _kernel_install kernel-install
diff --git a/shell-completion/bash/localectl b/shell-completion/bash/localectl
index ef19f01461..bec9e78c64 100644
--- a/shell-completion/bash/localectl
+++ b/shell-completion/bash/localectl
@@ -18,9 +18,10 @@
# along with systemd; If not, see <http://www.gnu.org/licenses/>.
__contains_word () {
- local word=$1; shift
- for w in $*; do [[ $w = $word ]] && return 0; done
- return 1
+ local w word=$1; shift
+ for w in "$@"; do
+ [[ $w = "$word" ]] && return
+ done
}
_localectl() {
diff --git a/shell-completion/bash/loginctl b/shell-completion/bash/loginctl
index 1844085d49..3104b305fa 100644
--- a/shell-completion/bash/loginctl
+++ b/shell-completion/bash/loginctl
@@ -18,9 +18,10 @@
# along with systemd; If not, see <http://www.gnu.org/licenses/>.
__contains_word () {
- local word=$1; shift
- for w in $*; do [[ $w = $word ]] && return 0; done
- return 1
+ local w word=$1; shift
+ for w in "$@"; do
+ [[ $w = "$word" ]] && return
+ done
}
__get_all_sessions () { loginctl list-sessions | { while read -r a b; do printf "%s\n" "$a"; done; } ; }
diff --git a/shell-completion/bash/systemctl b/shell-completion/bash/systemctl
index 191b8d13ec..e335ee871c 100644
--- a/shell-completion/bash/systemctl
+++ b/shell-completion/bash/systemctl
@@ -32,9 +32,10 @@ __systemd_properties() {
}
__contains_word () {
- local word=$1; shift
- for w in $*; do [[ $w = $word ]] && return 0; done
- return 1
+ local w word=$1; shift
+ for w in "$@"; do
+ [[ $w = "$word" ]] && return
+ done
}
__filter_units_by_property () {
@@ -70,10 +71,10 @@ _systemctl () {
local i verb comps mode
local -A OPTS=(
- [STANDALONE]='--all -a --reverse --after --before --defaults --fail --ignore-dependencies --failed --force -f --full --global
+ [STANDALONE]='--all -a --reverse --after --before --defaults --fail --ignore-dependencies --failed --force -f --full -l --global
--help -h --no-ask-password --no-block --no-legend --no-pager --no-reload --no-wall
--quiet -q --privileged -P --system --user --version --runtime'
- [ARG]='--host -H --kill-mode --kill-who --property -p --signal -s --type -t --root'
+ [ARG]='--host -H --kill-mode --kill-who --property -p --signal -s --type -t --state --root'
)
if __contains_word "--user" ${COMP_WORDS[*]}; then
@@ -90,6 +91,11 @@ _systemctl () {
--type|-t)
comps='automount device mount path service snapshot socket swap target timer'
;;
+ --state)
+ comps='loaded not-found stub
+ active inactive
+ dead elapsed exited listening mounted plugged running waiting'
+ ;;
--kill-who)
comps='all control main'
;;
@@ -133,10 +139,11 @@ _systemctl () {
[ENVS]='set-environment unset-environment'
[STANDALONE]='daemon-reexec daemon-reload default dump
emergency exit halt hibernate hybrid-sleep kexec list-jobs
- list-units list-unit-files poweroff reboot rescue
- show-environment suspend'
+ list-sockets list-units list-unit-files poweroff reboot rescue
+ show-environment suspend get-default'
[NAME]='snapshot load'
[FILE]='link'
+ [TARGETS]='set-default'
)
for ((i=0; $i <= $COMP_CWORD; i++)); do
@@ -210,6 +217,9 @@ _systemctl () {
elif __contains_word "$verb" ${VERBS[FILE]}; then
comps=$( compgen -A file -- "$cur" )
compopt -o filenames
+ elif __contains_word "$verb" ${VERBS[TARGETS]}; then
+ comps=$( __systemctl $mode list-unit-files --type target --full --all \
+ | { while read -r a b; do echo " $a"; done; } )
fi
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
diff --git a/shell-completion/bash/systemd-analyze b/shell-completion/bash/systemd-analyze
index 11276ef09c..5bd676866b 100644
--- a/shell-completion/bash/systemd-analyze
+++ b/shell-completion/bash/systemd-analyze
@@ -19,9 +19,10 @@
# along with systemd; If not, see <http://www.gnu.org/licenses/>.
__contains_word () {
- local word=$1; shift
- for w in $*; do [[ $w = $word ]] && return 0; done
- return 1
+ local w word=$1; shift
+ for w in "$@"; do
+ [[ $w = "$word" ]] && return
+ done
}
_systemd_analyze() {
@@ -33,6 +34,7 @@ _systemd_analyze() {
[NO_OPTION]='time blame plot'
[CRITICAL_CHAIN]='critical-chain'
[DOT]='dot'
+ [LOG_LEVEL]='set-log-level'
)
_init_completion || return
@@ -67,6 +69,14 @@ _systemd_analyze() {
if [[ $cur = -* ]]; then
comps='--help --version --system --user --from-pattern --to-pattern --order --require'
fi
+
+ elif __contains_word "$verb" ${VERBS[LOG_LEVEL]}; then
+ if [[ $cur = -* ]]; then
+ comps='--help --version --system --user'
+ else
+ comps='debug info notice warning err crit alert emerg'
+ fi
+
fi
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
diff --git a/shell-completion/bash/systemd-coredumpctl b/shell-completion/bash/systemd-coredumpctl
index 4bbece7347..805e84824e 100644
--- a/shell-completion/bash/systemd-coredumpctl
+++ b/shell-completion/bash/systemd-coredumpctl
@@ -18,9 +18,10 @@
# along with systemd; If not, see <http://www.gnu.org/licenses/>.
__contains_word () {
- local word=$1; shift
- for w in $*; do [[ $w = $word ]] && return 0; done
- return 1
+ local w word=$1; shift
+ for w in "$@"; do
+ [[ $w = "$word" ]] && return
+ done
}
__journal_fields=(MESSAGE{,_ID} PRIORITY CODE_{FILE,LINE,FUNC}
diff --git a/shell-completion/bash/systemd-run b/shell-completion/bash/systemd-run
new file mode 100644
index 0000000000..ab55274233
--- /dev/null
+++ b/shell-completion/bash/systemd-run
@@ -0,0 +1,63 @@
+# systemd-run(1) completion -*- shell-script -*-
+#
+# 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with systemd; If not, see <http://www.gnu.org/licenses/>.
+
+__systemctl() {
+ local mode=$1; shift 1
+ systemctl $mode --full --no-legend "$@"
+}
+
+__get_slice_units () { __systemctl $1 list-units --all -t slice \
+ | { while read -r a b c d; do echo " $a"; done; }; }
+
+_systemd_run() {
+ local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
+ local OPTS='-h --help --version --user --scope --unit --description --slice -r --remain-after-exit --send-sighup'
+
+ local mode=--system
+ local i
+ for (( i=1; i <= COMP_CWORD; i++ )); do
+ if [[ ${COMP_WORDS[i]} != -* ]]; then
+ local root_command=${COMP_WORDS[i]}
+ _command_offset $i
+ return
+ fi
+
+ [[ ${COMP_WORDS[i]} == "--user" ]] && mode=--user
+
+ [[ $i -lt $COMP_CWORD && ${COMP_WORDS[i]} == @(--unit|--description|--slice) ]] && ((i++))
+ done
+
+ case "$prev" in
+ --unit|--description)
+ # argument required but no completions available
+ return
+ ;;
+ --slice)
+ local comps=$(__get_slice_units $mode)
+
+ COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
+ return 0
+ ;;
+ esac
+
+ COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") )
+ return 0
+}
+
+complete -F _systemd_run systemd-run
diff --git a/shell-completion/bash/timedatectl b/shell-completion/bash/timedatectl
index 2842b31069..c6a6545257 100644
--- a/shell-completion/bash/timedatectl
+++ b/shell-completion/bash/timedatectl
@@ -18,9 +18,10 @@
# along with systemd; If not, see <http://www.gnu.org/licenses/>.
__contains_word () {
- local word=$1; shift
- for w in $*; do [[ $w = $word ]] && return 0; done
- return 1
+ local w word=$1; shift
+ for w in "$@"; do
+ [[ $w = "$word" ]] && return
+ done
}
_timedatectl() {
diff --git a/shell-completion/bash/udevadm b/shell-completion/bash/udevadm
index 123fb51633..8ad855060c 100644
--- a/shell-completion/bash/udevadm
+++ b/shell-completion/bash/udevadm
@@ -18,9 +18,10 @@
# along with systemd; If not, see <http://www.gnu.org/licenses/>.
__contains_word () {
- local word=$1; shift
- for w in $*; do [[ $w = $word ]] && return 0; done
- return 1
+ local w word=$1; shift
+ for w in "$@"; do
+ [[ $w = "$word" ]] && return
+ done
}
__get_all_sysdevs() {
@@ -33,68 +34,61 @@ _udevadm() {
local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
local OPTS='-h --help --version --debug'
- local -A VERBS=(
- [INFO]='info'
- [TRIGGER]='trigger'
- [SETTLE]='settle'
- [CONTROL]='control'
- [MONITOR]='monitor'
- [HWDB]='hwdb'
- [TESTBUILTIN]='test-builtin'
- [TEST]='test'
- )
+ local verbs=(info trigger settle control monitor hwdb test-builtin test)
- for ((i=0; $i <= $COMP_CWORD; i++)); do
- if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} &&
+ 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 && $cur = -* ]]; then
- COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") )
+ if [[ -z $verb ]]; then
+ COMPREPLY=( $(compgen -W '${OPTS[*]} ${verbs[*]}' -- "$cur") )
return 0
fi
- if [[ -z $verb ]]; then
- comps=${VERBS[*]}
-
- elif __contains_word "$verb" ${VERBS[INFO]}; then
- if [[ $cur = -* ]]; then
- comps='--help --query= --path= --name= --root --attribute-walk --export-db --cleanup-db'
- else
- comps=$( __get_all_sysdevs )
- fi
-
- elif __contains_word "$verb" ${VERBS[TRIGGER]}; then
- comps='--help --verbose --dry-run --type= --action= --subsystem-match=
- --subsystem-nomatch= --attr-match= --attr-nomatch= --property-match=
- --tag-match= --sysname-match= --parent-match='
-
- elif __contains_word "$verb" ${VERBS[SETTLE]}; then
- comps='--help --timeout= --seq-start= --seq-end= --exit-if-exists= --quiet'
-
- elif __contains_word "$verb" ${VERBS[CONTROL]}; then
- comps='--help --exit --log-priority= --stop-exec-queue --start-exec-queue
- --reload --property= --children-max= --timeout='
-
- elif __contains_word "$verb" ${VERBS[MONITOR]}; then
- comps='--help --kernel --udev --property --subsystem-match= --tag-match='
-
- elif __contains_word "$verb" ${VERBS[HWDB]}; then
- comps='--help --update --test='
-
- elif __contains_word "$verb" ${VERBS[TEST]}; then
- if [[ $cur = -* ]]; then
- comps='--help --action='
- else
- comps=$( __get_all_sysdevs )
- fi
-
- elif __contains_word "$verb" ${VERBS[TESTBUILTIN]}; then
- comps='blkid btrfs hwdb input_id kmod net_id path_id usb_id uaccess'
- fi
+ case $verb in
+ 'info')
+ if [[ $cur = -* ]]; then
+ comps='--help --query= --path= --name= --root --attribute-walk --export-db --cleanup-db'
+ else
+ comps=$( __get_all_sysdevs )
+ fi
+ ;;
+ 'trigger')
+ comps='--help --verbose --dry-run --type= --action= --subsystem-match=
+ --subsystem-nomatch= --attr-match= --attr-nomatch= --property-match=
+ --tag-match= --sysname-match= --parent-match='
+ ;;
+ 'settle')
+ comps='--help --timeout= --seq-start= --seq-end= --exit-if-exists= --quiet'
+ ;;
+ 'control')
+ comps='--help --exit --log-priority= --stop-exec-queue --start-exec-queue
+ --reload --property= --children-max= --timeout='
+ ;;
+ 'monitor')
+ comps='--help --kernel --udev --property --subsystem-match= --tag-match='
+ ;;
+ 'hwdb')
+ comps='--help --update --test='
+ ;;
+ 'test')
+ if [[ $cur = -* ]]; then
+ comps='--help --action='
+ else
+ comps=$( __get_all_sysdevs )
+ fi
+ ;;
+ 'test-builtin')
+ comps='blkid btrfs hwdb input_id keyboard kmod net_id path_id usb_id uaccess'
+ ;;
+ *)
+ comps=${VERBS[*]}
+ ;;
+ esac
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
return 0
diff --git a/shell-completion/systemd-zsh-completion.zsh b/shell-completion/systemd-zsh-completion.zsh
deleted file mode 100644
index 411646ea59..0000000000
--- a/shell-completion/systemd-zsh-completion.zsh
+++ /dev/null
@@ -1,1052 +0,0 @@
-#compdef systemctl loginctl journalctl hostnamectl localectl timedatectl systemd-coredumpctl udevadm systemd-analyze systemd-cat systemd-ask-password systemd-cgls systemd-cgtop systemd-delta systemd-detect-virt systemd-inhibit systemd-machine-id-setup systemd-notify systemd-nspawn systemd-tmpfiles systemd-tty-ask-password-agent
-
-_ctls()
-{
- local curcontext="$curcontext" state lstate line
- case "$service" in
- systemctl)
- # -s for aggregated options like -aP
- _arguments -s \
- {-h,--help}'[Show help]' \
- '--version[Show package version]' \
- {-t,--type=}'[List only units of a particular type]:unit type:(automount device mount path service snapshot socket swap target timer)' \
- \*{-p,--property=}'[Show only properties by specific name]:unit property' \
- {-a,--all}'[Show all units/properties, including dead/empty ones]' \
- '--reverse[Show reverse dependencies]' \
- '--after[Show units ordered after]' \
- '--before[Show units ordered before]' \
- '--failed[Show only failed units]' \
- "--full[Don't ellipsize unit names on output]" \
- '--fail[When queueing a new job, fail if conflicting jobs are pending]' \
- '--ignore-dependencies[When queueing a new job, ignore all its dependencies]' \
- '--kill-who=[Who to send signal to]:killwho:(main control all)' \
- {-s,--signal=}'[Which signal to send]:signal:_signals' \
- {-H,--host=}'[Show information for remote host]:userathost:_hosts_or_user_at_host' \
- {-P,--privileged}'[Acquire privileges before execution]' \
- {-q,--quiet}'[Suppress output]' \
- '--no-block[Do not wait until operation finished]' \
- "--no-wall[Don't send wall message before halt/power-off/reboot]" \
- "--no-reload[When enabling/disabling unit files, don't reload daemon configuration]" \
- '--no-legend[Do not print a legend, i.e. the column headers and the footer with hints]' \
- '--no-pager[Do not pipe output into a pager]' \
- '--no-ask-password[Do not ask for system passwords]' \
- '--system[Connect to system manager]' \
- '--user[Connect to user service manager]' \
- '--global[Enable/disable unit files globally]' \
- {-f,--force}'[When enabling unit files, override existing symlinks. When shutting down, execute action immediately]' \
- '--root=[Enable unit files in the specified root directory]:directory:_directories' \
- '--runtime[Enable unit files only temporarily until next reboot]' \
- {-n,--lines=}'[Journal entries to show]:number of entries' \
- {-o,--output=}'[Change journal output mode]:modes:_outputmodes' \
- '*::systemctl command:_systemctl_command'
- ;;
- loginctl)
- _arguments -s \
- {-h,--help}'[Show help]' \
- '--version[Show package version]' \
- \*{-p,--property=}'[Show only properties by this name]:unit property' \
- {-a,--all}'[Show all properties, including empty ones]' \
- '--kill-who=[Who to send signal to]:killwho:(main control all)' \
- {-s,--signal=}'[Which signal to send]:signal:_signals' \
- '--no-ask-password[Do not ask for system passwords]' \
- {-H,--host=}'[Show information for remote host]:userathost:_hosts_or_user_at_host' \
- {-P,--privileged}'[Acquire privileges before execution]' \
- '--no-pager[Do not pipe output into a pager]' \
- '*::loginctl command:_loginctl_command'
- ;;
-
- hostnamectl)
- _arguments -s \
- {-h,--help}'[Show this help]' \
- '--version[Show package version]' \
- '--transient[Only set transient hostname]' \
- '--static[Only set static hostname]' \
- '--pretty[Only set pretty hostname]' \
- '--no-ask-password[Do not prompt for password]' \
- {-H,--host=}'[Operate on remote host]:userathost:_hosts_or_user_at_host' \
- '*::hostnamectl commands:_hostnamectl_command'
- ;;
- journalctl)
- _arguments -s \
- '--since=[Start showing entries newer or of the specified date]:YYYY-MM-DD HH\:MM\:SS' \
- '--until=[Stop showing entries older or of the specified date]:YYYY-MM-DD HH\:MM\:SS' \
- {-c,--cursor=}'[Start showing entries from specified cursor]:cursors:_journal_fields __CURSORS' \
- {-b,--this-boot}'[Show data only from current boot]' \
- {-u,--unit=}'[Show data only from the specified unit]:units:_journal_fields _SYSTEMD_UNIT' \
- '--user-unit[Show data only from the specified user session unit]:units:_journal_fields _SYSTEMD_USER_UNIT' \
- {-p,--priority=}'[Show only messages within the specified priority range]:priority:_journal_fields PRIORITY' \
- {-f,--follow}'[Follow journal]' \
- {-n,--lines=}'[Number of journal entries to show]:integer' \
- '--no-tail[Show all lines, even in follow mode]' \
- {-o,--output=}'[Change journal output mode]:output modes:_outputmodes' \
- '--full[Show long fields in full]' \
- {-a,--all}'[Show all fields, including long and unprintable]' \
- {-q,--quiet}"[Don't show privilege warning]" \
- '--no-pager[Do not pipe output into a pager]' \
- {-m,--merge}'[Show entries from all available journals]' \
- {-D,--directory=}'[Show journal files from directory]:directories:_directories' \
- '--interval=[Time interval for changing the FSS sealing key]:time interval' \
- '--verify-key=[Specify FSS verification key]:FSS key' \
- {-h,--help}'[Show this help]' \
- '--version[Show package version]' \
- '--new-id128[Generate a new 128 Bit ID]' \
- '--header[Show journal header information]' \
- '--disk-usage[Show total disk usage]' \
- {-F,--field=}'[List all values a certain field takes]:Fields:_list_fields' \
- '--setup-keys[Generate new FSS key pair]' \
- '--verify[Verify journal file consistency]' \
- '--list-catalog[List messages in catalog]' \
- '--update-catalog[Update binary catalog database]' \
- '*::default: _journal_none'
- ;;
- localectl)
- _arguments \
- {-h,--help}'[Show this help]' \
- '--version[Show package version]' \
- "--no-convert[Don't convert keyboard mappings]" \
- '--no-pager[Do not pipe output into a pager]' \
- '--no-ask-password[Do not prompt for password]' \
- {-H,--host=}'[Operate on remote host]:userathost:_hosts_or_user_at_host' \
- '*::localectl commands:_localectl_command'
- ;;
- systemd-coredumpctl)
- _arguments \
- {-o,--output=}'[Write output to FILE]:output file:_files' \
- '--no-pager[Do not pipe output into a pager]' \
- {-h,--help}'[Show this help]' \
- '--version[Show package version]' \
- '*::systemd-coredumpctl commands:_systemd-coredumpctl_command'
-
- ;;
- timedatectl)
- _arguments -s \
- {-h,--help}'[Show this help]' \
- '--version[Show package version]' \
- '--adjust-system-clock[Adjust system clock when changing local RTC mode]' \
- '--no-pager[Do not pipe output into a pager]' \
- '--no-ask-password[Do not prompt for password]' \
- {-H,--host=}'[Operate on remote host]:userathost:_hosts_or_user_at_host' \
- '*::timedatectl commands:_timedatectl_command'
- ;;
- udevadm)
- _arguments \
- '--debug[Print debug messages to stderr]' \
- '--version[Print version number]' \
- '--help[Print help text]' \
- '*::udevadm commands:_udevadm_command'
- ;;
- systemd-analyze)
- _arguments \
- {-h,--help}'[Show help text.]' \
- '--user[Shows performance data of user sessions instead of the system manager.]' \
- '--order[When generating graph for dot, show only order]' \
- '--require[When generating graph for dot, show only requirement]' \
- '*::systemd-analyze commands:_systemd_analyze_command'
- ;;
- systemd-ask-password)
- _arguments \
- {-h,--help}'[Show this help]' \
- '--icon=[Icon name]' \
- '--timeout=[Timeout in sec]' \
- '--no-tty[Ask question via agent even on TTY]' \
- '--accept-cached[Accept cached passwords]' \
- '--multiple[List multiple passwords if available]'
- ;;
- systemd-cat)
- _arguments \
- {-h,--help}'[Show this help]' \
- '--version[Show package version.]' \
- {-t,--identifier=}'[Set syslog identifier.]' \
- {-p,--priority=}'[Set priority value.]:value:({0..7})' \
- '--level-prefix=[Control whether level prefix shall be parsed.]:boolean:(1 0)' \
- ':Message'
- ;;
- systemd-cgls)
- _arguments \
- {-h,--help}'[Show this help]' \
- '--version[Show package version]' \
- '--no-pager[Do not pipe output into a pager]' \
- {-a,--all}'[Show all groups, including empty]' \
- '-k[Include kernel threads in output]' \
- ':cgroups:(cpuset cpu cpuacct memory devices freezer net_cls blkio)'
- ;;
- systemd-cgtop)
- _arguments \
- {-h,--help}'[Show this help]' \
- '--version[Print version and exit]' \
- '(-c -m -i -t)-p[Order by path]' \
- '(-c -p -m -i)-t[Order by number of tasks]' \
- '(-m -p -i -t)-c[Order by CPU load]' \
- '(-c -p -i -t)-m[Order by memory load]' \
- '(-c -m -p -t)-i[Order by IO load]' \
- {-d,--delay=}'[Specify delay]' \
- {-n,--iterations=}'[Run for N iterations before exiting]' \
- {-b,--batch}'[Run in batch mode, accepting no input]' \
- '--depth=[Maximum traversal depth]'
- ;;
- systemd-delta)
- _arguments \
- {-h,--help}'[Show this help]' \
- '--version[Show package version]' \
- '--no-pager[Do not pipe output into a pager]' \
- '--diff=[Show a diff when overridden files differ]:boolean:(1 0)' \
- {-t,--type=}'[Only display a selected set of override types]:types:(masked equivalent redirected overridden unchanged)' \
- ':SUFFIX:(tmpfiles.d sysctl.d systemd/system)'
- ;;
- systemd-detect-virt)
- _arguments \
- {-h,--help}'[Show this help]' \
- '--version[Show package version]' \
- {-c,--container}'[Only detect whether we are run in a container]' \
- {-v,--vm}'[Only detect whether we are run in a VM]' \
- {-q,--quiet}"[Don't output anything, just set return value]"
- ;;
- systemd-inhibit)
- _arguments \
- {-h,--help}'[Show this help]' \
- '--version[Show package version]' \
- '--what=[Operations to inhibit]:options:(shutdown sleep idle handle-power-key handle-suspend-key handle-hibernate-key handle-lid-switch)' \
- '--who=[A descriptive string who is inhibiting]' \
- '--why=[A descriptive string why is being inhibited]' \
- '--mode=[One of block or delay]' \
- '--list[List active inhibitors]' \
- '*:commands:_systemd_inhibit_command'
- ;;
- systemd-machine-id-setup)
- _arguments \
- {-h,--help}'[Show this help]' \
- '--version[Show package version]'
- ;;
- systemd-notify)
- _arguments \
- {-h,--help}'[Show this help]' \
- '--version[Show package version]' \
- '--ready[Inform the init system about service start-up completion.]' \
- '--pid=[Inform the init system about the main PID of the daemon]' \
- '--status=[Send a free-form status string for the daemon to the init systemd]' \
- '--booted[Returns 0 if the system was booted up with systemd]' \
- '--readahead=[Controls disk read-ahead operations]:arguments:(cancel done noreply)'
- ;;
- systemd-nspawn)
- _arguments \
- {-h,--help}'[Show this help]' \
- {--directory=,-D}'[Directory to use as file system root for the namespace container. If omitted the current directory will be used.]:directories:_directories' \
- {--boot,-b}'[Automatically search for an init binary and invoke it instead of a shell or a user supplied program.]' \
- {--user=,-u}'[Run the command under specified user, create home directory and cd into it.]' \
- '--uuid=[Set the specified uuid for the container.]' \
- {--controllers=,-C}'[Makes the container appear in other hierarchies than the name=systemd:/ one. Takes a comma-separated list of controllers.]' \
- '--private-network[Turn off networking in the container. This makes all network interfaces unavailable in the container, with the exception of the loopback device.]' \
- '--read-only[Mount the root file system read only for the container.]' \
- '--capability=[List one or more additional capabilities to grant the container.]:capabilities:_systemd-nspawn' \
- "--link-journal=[Control whether the container's journal shall be made visible to the host system.]:options:(no, host, guest, auto)" \
- '-j[Equivalent to --link-journal=guest.]'
- ;;
- systemd-tmpfiles)
- _arguments \
- '--create[Create, set ownership/permissions based on the config files.]' \
- '--clean[Clean up all files and directories with an age parameter configured.]' \
- '--remove[All files and directories marked with r, R in the configuration files are removed.]' \
- '--prefix=[Only apply rules that apply to paths with the specified prefix.]' \
- '--help[Prints a short help text and exits.]' \
- '*::files:_files'
- ;;
- systemd-tty-ask-password-agent)
- _arguments \
- {-h,--help}'[Prints a short help text and exits.]' \
- '--version[Prints a short version string and exits.]' \
- '--list[Lists all currently pending system password requests.]' \
- '--query[Process all currently pending system password requests by querying the user on the calling TTY.]' \
- '--watch[Continuously process password requests.]' \
- '--wall[Forward password requests to wall(1).]' \
- '--plymouth[Ask question with plymouth(8).]' \
- '--console[Ask question on /dev/console.]'
- ;;
- *) _message 'eh?' ;;
- esac
-}
-
-_systemd-nspawn(){
- local -a _caps
- _caps=( CAP_CHOWN CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH
- CAP_FOWNER CAP_FSETID CAP_IPC_OWNER CAP_KILL CAP_LEASE CAP_LINUX_IMMUTABLE
- CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW CAP_SETGID CAP_SETFCAP CAP_SETPCAP
- CAP_SETUID CAP_SYS_ADMIN CAP_SYS_CHROOT CAP_SYS_NICE CAP_SYS_PTRACE CAP_SYS_TTY_CONFIG
- CAP_SYS_RESOURCE CAP_SYS_BOOT )
- _values -s , 'capabilities' "$_caps[@]"
-}
-
-_systemd_inhibit_command(){
- if (( CURRENT == 1 )); then
- compset -q
- _normal
- else
- local n=${words[(b:2:i)[^-]*]}
- if (( n <= CURRENT )); then
- compset -n $n
- _alternative \
- 'files:file:_files' \
- 'commands:command:_normal' && return 0
- fi
- _default
- fi
-
-}
-
-_systemd_analyze_command(){
- local -a _systemd_analyze_cmds
- # Descriptions taken from systemd-analyze --help.
- _systemd_analyze_cmds=(
- 'time:Print time spent in the kernel before reaching userspace'
- 'blame:Print list of running units ordered by time to init'
- 'critical-chain:Print a tree of the time critical chain of units'
- 'plot:Output SVG graphic showing service initialization'
- 'dot:Dump dependency graph (in dot(1) format)'
- )
-
- if (( CURRENT == 1 )); then
- _describe "options" _systemd_analyze_cmds
- else
- _message "no more options"
- fi
-}
-
-_hosts_or_user_at_host()
-{
- _alternative \
- 'users-hosts:: _user_at_host' \
- 'hosts:: _hosts'
-}
-
-_outputmodes() {
- local -a _output_opts
- _output_opts=(short short-monotonic verbose export json json-pretty json-see cat)
- _describe -t output 'output mode' _output_opts || compadd "$@"
-}
-
-
-(( $+functions[_systemctl_command] )) || _systemctl_command()
-{
- local -a _systemctl_cmds
- _systemctl_cmds=(
- "list-units:List units"
- "start:Start (activate) one or more units"
- "stop:Stop (deactivate) one or more units"
- "reload:Reload one or more units"
- "restart:Start or restart one or more units"
- "condrestart:Restart one or more units if active"
- "try-restart:Restart one or more units if active"
- "reload-or-restart:Reload one or more units if possible, otherwise start or restart"
- "force-reload:Reload one or more units if possible, otherwise restart if active"
- "hibernate:Hibernate the system"
- "hybrid-sleep:Hibernate and suspend the system"
- "reload-or-try-restart:Reload one or more units if possible, otherwise restart if active"
- "isolate:Start one unit and stop all others"
- "kill:Send signal to processes of a unit"
- "is-active:Check whether units are active"
- "is-failed:Check whether units are failed"
- "status:Show runtime status of one or more units"
- "show:Show properties of one or more units/jobs or the manager"
- "reset-failed:Reset failed state for all, one, or more units"
- "load:Load one or more units"
- "list-unit-files:List installed unit files"
- "enable:Enable one or more unit files"
- "disable:Disable one or more unit files"
- "reenable:Reenable one or more unit files"
- "preset:Enable/disable one or more unit files based on preset configuration"
- "help:Show documentation for specified units"
- "list-dependencies:Show unit dependency tree"
- "mask:Mask one or more units"
- "unmask:Unmask one or more units"
- "link:Link one or more units files into the search path"
- "is-enabled:Check whether unit files are enabled"
- "list-jobs:List jobs"
- "cancel:Cancel all, one, or more jobs"
- "dump:Dump server status"
- "snapshot:Create a snapshot"
- "delete:Remove one or more snapshots"
- "show-environment:Dump environment"
- "set-environment:Set one or more environment variables"
- "unset-environment:Unset one or more environment variables"
- "daemon-reload:Reload systemd manager configuration"
- "daemon-reexec:Reexecute systemd manager"
- "default:Enter system default mode"
- "rescue:Enter system rescue mode"
- "emergency:Enter system emergency mode"
- "halt:Shut down and halt the system"
- "suspend:Suspend the system"
- "poweroff:Shut down and power-off the system"
- "reboot:Shut down and reboot the system"
- "kexec:Shut down and reboot the system with kexec"
- "exit:Ask for user instance termination"
- )
-
- if (( CURRENT == 1 )); then
- _describe -t commands 'systemctl command' _systemctl_cmds || compadd "$@"
- else
- local curcontext="$curcontext"
-
- cmd="${${_systemctl_cmds[(r)$words[1]:*]%%:*}}"
- # Deal with any aliases
- case $cmd in
- condrestart) cmd="try-restart";;
- force-reload) cmd="reload-or-try-restart";;
- esac
-
- if (( $#cmd )); then
- curcontext="${curcontext%:*:*}:systemctl-${cmd}:"
-
- local update_policy
- zstyle -s ":completion:${curcontext}:" cache-policy update_policy
- if [[ -z "$update_policy" ]]; then
- zstyle ":completion:${curcontext}:" cache-policy _systemctl_caching_policy
- fi
-
- _call_function ret _systemctl_$cmd || _message 'no more arguments'
- else
- _message "unknown systemctl command: $words[1]"
- fi
- return ret
- fi
-}
-
-__systemctl()
-{
- local -a _modes
- _modes=("--user" "--system")
- systemctl ${words:*_modes} --full --no-legend --no-pager "$@"
-}
-
-
-# Fills the unit list
-_systemctl_all_units()
-{
- if ( [[ ${+_sys_all_units} -eq 0 ]] || _cache_invalid SYS_ALL_UNITS ) &&
- ! _retrieve_cache SYS_ALL_UNITS;
- then
- _sys_all_units=( $(__systemctl list-units --all | { while read a b; do echo " $a"; done; }) )
- _store_cache SYS_ALL_UNITS _sys_all_units
- fi
-}
-
-# Fills the unit list including all file units
-_systemctl_really_all_units()
-{
- local -a all_unit_files;
- local -a really_all_units;
- if ( [[ ${+_sys_really_all_units} -eq 0 ]] || _cache_invalid SYS_REALLY_ALL_UNITS ) &&
- ! _retrieve_cache SYS_REALLY_ALL_UNITS;
- then
- all_unit_files=( $(__systemctl list-unit-files | { while read a b; do echo " $a"; done; }) )
- _systemctl_all_units
- really_all_units=($_sys_all_units $all_unit_files)
- _sys_really_all_units=(${(u)really_all_units})
- _store_cache SYS_REALLY_ALL_UNITS _sys_really_all_units
- fi
-}
-
-_filter_units_by_property() {
- local property=$1 value=$2 ; shift ; shift
- local -a units ; units=($*)
- local prop unit
- for ((i=1; $i <= ${#units[*]}; i++)); do
- # FIXME: "Failed to issue method call: Unknown unit" errors are ignored for
- # now (related to DBUS_ERROR_UNKNOWN_OBJECT). in the future, we need to
- # revert to calling 'systemctl show' once for all units, which is way
- # faster
- unit=${units[i]}
- prop=${(f)"$(_call_program units "$service show --no-pager --property="$property" ${unit} 2>/dev/null")"}
- if [[ "${prop}" = "$property=$value" ]]; then
- echo " ${unit}"
- fi
- done
-}
-
-_systemctl_active_units() {_sys_active_units=( $(__systemctl list-units | { while read a b; do echo " $a"; done; }) )}
-_systemctl_inactive_units(){_sys_inactive_units=($(__systemctl list-units --all | { while read a b c d; do [[ $c == "inactive" || $c == "failed" ]] && echo " $a"; done; }) )}
-_systemctl_failed_units() {_sys_failed_units=( $(__systemctl list-units --failed | { while read a b; do echo " $a"; done; }) )}
-_systemctl_enabled_units() {_sys_enabled_units=( $(__systemctl list-unit-files | { while read a b; do [[ $b == "enabled" ]] && echo " $a"; done; }) )}
-_systemctl_disabled_units(){_sys_disabled_units=($(__systemctl list-unit-files | { while read a b; do [[ $b == "disabled" ]] && echo " $a"; done; }) )}
-_systemctl_masked_units() {_sys_masked_units=( $(__systemctl list-unit-files | { while read a b; do [[ $b == "masked" ]] && echo " $a"; done; }) )}
-
-# Completion functions for ALL_UNITS
-for fun in is-active is-failed is-enabled status show mask preset help list-dependencies ; do
- (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
- {
- _systemctl_really_all_units
- compadd "$@" -a - _sys_really_all_units
- }
-done
-
-# Completion functions for ENABLED_UNITS
-for fun in disable reenable ; do
- (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
- {
- _systemctl_enabled_units
- _systemctl_disabled_units
- compadd "$@" -a - _sys_enabled_units _sys_disabled_units
- }
-done
-
-# Completion functions for DISABLED_UNITS
-(( $+functions[_systemctl_enable] )) || _systemctl_enable()
-{
- _systemctl_disabled_units
- compadd "$@" -a - _sys_disabled_units
-}
-
-# Completion functions for FAILED_UNITS
-(( $+functions[_systemctl_reset-failed] )) || _systemctl_reset-failed()
-{
- _systemctl_failed_units
- compadd "$@" -a - _sys_failed_units || _message "no failed unit found"
-}
-
-# Completion functions for STARTABLE_UNITS
-(( $+functions[_systemctl_start] )) || _systemctl_start()
-{
- _systemctl_inactive_units
- compadd "$@" -a - _sys_inactive_units
-}
-
-# Completion functions for STOPPABLE_UNITS
-for fun in stop kill try-restart condrestart ; do
- (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
- {
- _systemctl_active_units
- compadd "$@" - $( _filter_units_by_property CanStop yes \
- ${_sys_active_units[*]} )
- }
-done
-
-# Completion functions for ISOLATABLE_UNITS
-(( $+functions[_systemctl_isolate] )) || _systemctl_isolate()
-{
- _systemctl_all_units
- compadd "$@" - $( _filter_units_by_property AllowIsolate yes \
- ${_sys_all_units[*]} )
-}
-
-# Completion functions for RELOADABLE_UNITS
-for fun in reload reload-or-try-restart force-reload ; do
- (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
- {
- _systemctl_active_units
- compadd "$@" - $( _filter_units_by_property CanReload yes \
- ${_sys_active_units[*]} )
- }
-done
-
-# Completion functions for RESTARTABLE_UNITS
-for fun in restart reload-or-restart ; do
- (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
- {
- _systemctl_all_units
- compadd "$@" - $( _filter_units_by_property CanStart yes \
- ${_sys_all_units[*]} | while read line; do \
- [[ "$line" =~ \.device$ ]] || echo " $line"; \
- done )
- }
-done
-
-# Completion functions for MASKED_UNITS
-(( $+functions[_systemctl_unmask] )) || _systemctl_unmask()
-{
- _systemctl_masked_units
- compadd "$@" -a - _sys_masked_units || _message "no masked unit found"
-}
-
-# Completion functions for JOBS
-(( $+functions[_systemctl_cancel] )) || _systemctl_cancel()
-{
- compadd "$@" - $(__systemctl list-jobs \
- | cut -d' ' -f1 2>/dev/null ) || _message "no job found"
-}
-
-# Completion functions for SNAPSHOTS
-(( $+functions[_systemctl_delete] )) || _systemctl_delete()
-{
- compadd "$@" - $(__systemctl list-units --type snapshot --all \
- | cut -d' ' -f1 2>/dev/null ) || _message "no snapshot found"
-}
-
-# Completion functions for ENVS
-for fun in set-environment unset-environment ; do
- (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
- {
- local fun=$0 ; fun=${fun##_systemctl_}
- local suf
- if [[ "${fun}" = "set-environment" ]]; then
- suf='-S='
- fi
-
- compadd "$@" ${suf} - $(systemctl show-environment \
- | while read line; do echo " ${line%%\=}";done )
- }
-done
-
-(( $+functions[_systemctl_link] )) || _systemctl_link() { _files }
-
-# no systemctl completion for:
-# [STANDALONE]='daemon-reexec daemon-reload default dump
-# emergency exit halt kexec list-jobs list-units
-# list-unit-files poweroff reboot rescue show-environment'
-# [NAME]='snapshot load'
-
-_systemctl_caching_policy()
-{
- local _sysunits
- local -a oldcache
-
- # rebuild if cache is more than a day old
- oldcache=( "$1"(mh+1) )
- (( $#oldcache )) && return 0
-
- _sysunits=($(__systemctl --all | cut -d' ' -f1))
-
- if (( $#_sysunits )); then
- for unit in $_sysunits; do
- [[ "$unit" -nt "$1" ]] && return 0
- done
- fi
-
- return 1
-}
-
-_list_fields() {
- local -a journal_fields
- journal_fields=(MESSAGE{,_ID} PRIORITY CODE_{FILE,LINE,FUNC}
- ERRNO SYSLOG_{FACILITY,IDENTIFIER,PID}
- _{P,U,G}ID _COMM _EXE _CMDLINE
- _AUDIT_{SESSION,LOGINUID}
- _SYSTEMD_{CGROUP,SESSION,UNIT,OWNER_UID}
- _SYSTEMD_USER_UNIT
- _SELINUX_CONTEXT _SOURCE_REALTIME_TIMESTAMP
- _{BOOT,MACHINE}_ID _HOSTNAME _TRANSPORT
- _KERNEL_{DEVICE,SUBSYSTEM}
- _UDEV_{SYSNAME,DEVNODE,DEVLINK}
- __CURSOR __{REALTIME,MONOTONIC}_TIMESTAMP)
- _describe 'possible fields' journal_fields
-}
-
-_journal_none() {
- local -a _commands _files
- _commands=( ${(f)"$(_call_program commands "$service" -F _EXE 2>/dev/null)"} )
- _alternative : \
- 'files:/dev files:_files -W /dev -P /dev/' \
- "commands:commands:($_commands[@])" \
- 'fields:fields:_list_fields'
-}
-
-_journal_fields() {
- local -a _fields cmd
- cmd=("journalctl" "-F ${@[-1]}" "2>/dev/null" )
- _fields=( ${(f)"$(_call_program fields $cmd[@])"} )
- typeset -U _fields
- _describe 'possible values' _fields
-}
-
-
-_loginctl_all_sessions(){_sys_all_sessions=($(loginctl list-sessions | { while read a b; do echo " $a"; done; }) )}
-_loginctl_all_users() {_sys_all_users=( $(loginctl list-users | { while read a b; do echo " $a"; done; }) )}
-_loginctl_all_seats() {_sys_all_seats=( $(loginctl list-seats | { while read a b; do echo " $a"; done; }) )}
-
-# Completion functions for SESSIONS
-for fun in session-status show-session activate lock-session unlock-session terminate-session kill-session ; do
- (( $+functions[_loginctl_$fun] )) || _loginctl_$fun()
- {
- _loginctl_all_sessions
- compadd "$@" -a - _sys_all_sessions
- }
-done
-
-# Completion functions for USERS
-for fun in user-status show-user enable-linger disable-linger terminate-user kill-user ; do
- (( $+functions[_loginctl_$fun] )) || _loginctl_$fun()
- {
- _loginctl_all_users
- compadd "$@" -a - _sys_all_users
- }
-done
-
-# Completion functions for SEATS
-(( $+functions[_loginctl_seats] )) || _loginctl_seats()
-{
- _loginctl_all_seats
- compadd "$@" -a - _sys_all_seats
-}
-for fun in seat-status show-seat terminate-seat ; do
- (( $+functions[_loginctl_$fun] )) || _loginctl_$fun()
- { _loginctl_seats }
-done
-
-# Completion functions for ATTACH
-(( $+functions[_loginctl_attach] )) || _loginctl_attach()
-{
- _loginctl_all_seats
-
- _arguments -w -C -S -s \
- ':seat:_loginctl_seats' \
- '*:device:_files'
-}
-
-# no loginctl completion for:
-# [STANDALONE]='list-sessions list-users list-seats flush-devices'
-
-(( $+functions[_loginctl_command] )) || _loginctl_command()
-{
- local -a _loginctl_cmds
- _loginctl_cmds=(
- "list-sessions:List sessions"
- "session-status:Show session status"
- "show-session:Show properties of one or more sessions"
- "activate:Activate a session"
- "lock-session:Screen lock one or more sessions"
- "unlock-session:Screen unlock one or more sessions"
- "terminate-session:Terminate one or more sessions"
- "kill-session:Send signal to processes of a session"
- "list-users:List users"
- "user-status:Show user status"
- "show-user:Show properties of one or more users"
- "enable-linger:Enable linger state of one or more users"
- "disable-linger:Disable linger state of one or more users"
- "terminate-user:Terminate all sessions of one or more users"
- "kill-user:Send signal to processes of a user"
- "list-seats:List seats"
- "seat-status:Show seat status"
- "show-seat:Show properties of one or more seats"
- "attach:Attach one or more devices to a seat"
- "flush-devices:Flush all device associations"
- "terminate-seat:Terminate all sessions on one or more seats"
- )
-
- if (( CURRENT == 1 )); then
- _describe -t commands 'loginctl command' _loginctl_cmds || compadd "$@"
- else
- local curcontext="$curcontext"
-
- cmd="${${_loginctl_cmds[(r)$words[1]:*]%%:*}}"
-
- if (( $#cmd )); then
- curcontext="${curcontext%:*:*}:loginctl-${cmd}:"
-
- _call_function ret _loginctl_$cmd || _message 'no more arguments'
- else
- _message "unknown loginctl command: $words[1]"
- fi
- return ret
- fi
-}
-
-_hostnamectl_command() {
- local -a _hostnamectl_cmds
- _hostnamectl_cmds=(
- "status:Show current hostname settings"
- "set-hostname:Set system hostname"
- "set-icon-name:Set icon name for host"
- )
- if (( CURRENT == 1 )); then
- _describe -t commands 'hostnamectl commands' _hostnamectl_cmds || compadd "$@"
- else
- local curcontext="$curcontext"
- cmd="${${_hostnamectl_cmds[(r)$words[1]:*]%%:*}}"
- if (( $#cmd )); then
- [[ $cmd == status ]] && msg="no options" || msg="options for $cmd"
- _message "$msg"
- else
- _message "unknown hostnamectl command: $words[1]"
- fi
- fi
-}
-
-_localectl_set-locale() {
- local -a _confs _locales
- local expl suf
- _locales=( ${(f)"$(_call_program locales "$service" list-locales)"} )
- _confs=( ${${(f)"$(_call_program confs "locale 2>/dev/null")"}%\=*} )
- if [[ -prefix 1 *\= ]]; then
- local conf=${PREFIX%%\=*}
- compset -P1 '*='
- _wanted locales expl "locales configs" \
- _combination localeconfs confs=$conf locales "$@" -
- else
- compadd -S '=' $_confs
- fi
-}
-
-_localectl_set-keymap() {
- local -a _keymaps
- _keymaps=( ${(f)"$(_call_program locales "$service" list-keymaps)"} )
- if (( CURRENT <= 3 )); then
- _describe keymaps _keymaps
- else
- _message "no more options"
- fi
-}
-
-_localectl_set-x11-keymap() {
- if (( $+commands[pkg-config] )); then
- local -a _file _layout _model _variant _options
- local _xorg_lst
- _xorg_lst=${"$($commands[pkg-config] xkeyboard-config --variable=xkb_base)"}
- _file=( ${(ps:\n\!:)"$(<$_xorg_lst/rules/xorg.lst)"} )
- _layout=( ${${${(M)${(f)_file[1]}:# *}# }%% *} )
- _model=( ${${${(M)${(f)_file[2]}:# *}# }%% *} )
- _variant=( ${${${(M)${(f)_file[3]}:# *}# }%% *} )
- _options=( ${${${(M)${(f)_file[4]}:# *}# }%% *} )
- #_layout=( ${(f)"$( echo $_file[1] | awk '/^ / {print $1}' )"} )
- #_model=( ${(f)"$(echo $_file[2] | awk '/^ / {print $1}')"} )
- #_variant=( ${(f)"$(echo $_file[3] | awk '/^ / {print $1}')"} )
- #_options=( ${(f)"$(echo ${_file[4]//:/\\:} | awk '/^ / {print $1}')"} )
-
- case $CURRENT in
- 2) _describe layouts _layout ;;
- 3) _describe models _model;;
- 4) _describe variants _variant;;
- 5) _describe options _options;;
- *) _message "no more options"
- esac
- fi
-}
-
-
-_localectl_command() {
- local -a _localectl_cmds
- _localectl_cmds=(
- 'status:Show current locale settings'
- 'set-locale:Set system locale'
- 'list-locales:Show known locales'
- 'set-keymap:Set virtual console keyboard mapping'
- 'list-keymaps:Show known virtual console keyboard mappings'
- 'set-x11-keymap:Set X11 keyboard mapping'
- )
- if (( CURRENT == 1 )); then
- _describe -t commands 'localectl command' _localectl_cmds
- else
- local curcontext="$curcontext"
- cmd="${${_localectl_cmds[(r)$words[1]:*]%%:*}}"
- if (( $+functions[_localectl_$cmd] )); then
- _localectl_$cmd
- else
- _message "no more options"
- fi
- fi
-}
-
-_timedatectl_set-timezone(){
- local -a _timezones
- _timezones=( ${(f)"$(_call_program timezones "${service}" list-timezones)"} )
- compadd "$_timezones[@]"
-}
-
-_timedatectl_set-time(){
- _message "YYYY-MM-DD HH:MM:SS"
-}
-
-_timedatectl_set-local-rtc(){
- local -a _options
- _options=(
- '0:Maintain RTC in universal time'
- '1:Maintain RTC in local time'
- )
- _describe options _options
-}
-
-_timedatectl_set-ntp(){
- local -a _options
- _options=(
- '0:Disable NTP based network time configuration'
- '1:Enable NTP based network time configuration'
- )
- _describe options _options
-}
-
-_timedatectl_command(){
- local -a _timedatectl_cmds
- _timedatectl_cmds=(
- 'status:Show current time settings'
- 'set-time:Set system time'
- 'set-timezone:Set system timezone'
- 'list-timezones:Show known timezones'
- 'set-local-rtc:Control whether RTC is in local time'
- 'set-ntp:Control whether NTP is enabled'
- )
- if (( CURRENT == 1 )); then
- _describe -t commands 'timedatectl command' _timedatectl_cmds
- else
- local curcontext="$curcontext"
- cmd="${${_timedatectl_cmds[(r)$words[1]:*]%%:*}}"
- if (( $#cmd )); then
- if (( $+functions[_timedatectl_$cmd] )); then
- _timedatectl_$cmd
- else
- _message "no more options"
- fi
- else
- _message "unknown timedatectl command: $words[1]"
- fi
- fi
-}
-_systemd-coredumpctl_command(){
- local -a _systemd_coredumpctl_cmds
- _systemd_coredumpctl_cmds=(
- 'list:List available coredumps'
- 'dump:Print coredump to std'
- )
- if (( CURRENT == 1 )); then
- _describe -t commands 'systemd-coredumpctl command' _systemd_coredumpctl_cmds
- else
- local curcontext="$curcontext"
- local -a _dumps
- cmd="${${_systemd_coredumpctl_cmds[(r)$words[1]:*]%%:*}}"
- if (( $#cmd )); then
- # user can set zstyle ':completion:*:*:systemd-coredumpctl:*' sort no for coredumps to be ordered by date, otherwise they get ordered by pid
- _dumps=( "${(foa)$(systemd-coredumpctl list | awk 'BEGIN{OFS=":"} /^\s/ {sub(/[[ \t]+/, ""); print $5,$0}' 2>/dev/null)}" )
- if [[ -n "$_dumps" ]]; then
- _describe -t pids 'coredumps' _dumps
- else
- _message "no coredumps"
- fi
- else
- _message "no more options"
- fi
-
- fi
-
-}
-
-_udevadm_info(){
- _arguments \
- '--query=[Query the database for specified type of device data. It needs the --path or --name to identify the specified device.]:type:(name symlink path property all)' \
- '--path=[The devpath of the device to query.]:sys files:_files -P /sys/ -W /sys' \
- '--name=[The name of the device node or a symlink to query]:device files:_files -P /dev/ -W /dev' \
- '--root[Print absolute paths in name or symlink query.]' \
- '--attribute-walk[Print all sysfs properties of the specified device that can be used in udev rules to match the specified device]' \
- '--export[Print output as key/value pairs.]' \
- '--export-prefix=[Add a prefix to the key name of exported values.]:prefix' \
- '--device-id-of-file=[Print major/minor numbers of the underlying device, where the file lives on.]:files:_udevadm_mounts' \
- '--export-db[Export the content of the udev database.]' \
- '--cleanup-db[Cleanup the udev database.]'
-}
-
-_udevadm_trigger(){
- _arguments \
- '--verbose[Print the list of devices which will be triggered.]' \
- '--dry-run[Do not actually trigger the event.]' \
- '--type=[Trigger a specific type of devices.]:types:(devices subsystems failed)' \
- '--action=[Type of event to be triggered.]:actions:(add change remove)' \
- '--subsystem-match=[Trigger events for devices which belong to a matching subsystem.]' \
- '--subsystem-nomatch=[Do not trigger events for devices which belong to a matching subsystem.]' \
- '--attr-match=attribute=[Trigger events for devices with a matching sysfs attribute.]' \
- '--attr-nomatch=attribute=[Do not trigger events for devices with a matching sysfs attribute.]' \
- '--property-match=[Trigger events for devices with a matching property value.]' \
- '--tag-match=property[Trigger events for devices with a matching tag.]' \
- '--sysname-match=[Trigger events for devices with a matching sys device name.]' \
- '--parent-match=[Trigger events for all children of a given device.]'
-}
-
-_udevadm_settle(){
- _arguments \
- '--timeout=[Maximum number of seconds to wait for the event queue to become empty.]' \
- '--seq-start=[Wait only for events after the given sequence number.]' \
- '--seq-end=[Wait only for events before the given sequence number.]' \
- '--exit-if-exists=[Stop waiting if file exists.]:files:_files' \
- '--quiet[Do not print any output, like the remaining queue entries when reaching the timeout.]' \
- '--help[Print help text.]'
-}
-
-_udevadm_control(){
- _arguments \
- '--exit[Signal and wait for systemd-udevd to exit.]' \
- '--log-priority=[Set the internal log level of systemd-udevd.]:priorities:(err info debug)' \
- '--stop-exec-queue[Signal systemd-udevd to stop executing new events. Incoming events will be queued.]' \
- '--start-exec-queue[Signal systemd-udevd to enable the execution of events.]' \
- '--reload[Signal systemd-udevd to reload the rules files and other databases like the kernel module index.]' \
- '--property=[Set a global property for all events.]' \
- '--children-max=[Set the maximum number of events.]' \
- '--timeout=[The maximum number of seconds to wait for a reply from systemd-udevd.]' \
- '--help[Print help text.]'
-}
-
-_udevadm_monitor(){
- _arguments \
- '--kernel[Print the kernel uevents.]' \
- '--udev[Print the udev event after the rule processing.]' \
- '--property[Also print the properties of the event.]' \
- '--subsystem-match=[Filter events by subsystem/\[devtype\].]' \
- '--tag-match=[Filter events by property.]' \
- '--help[Print help text.]'
-}
-
-_udevadm_test(){
- _arguments \
- '--action=[The action string.]:actions:(add change remove)' \
- '--subsystem=[The subsystem string.]' \
- '--help[Print help text.]' \
- '*::devpath:_files -P /sys/ -W /sys'
-}
-
-_udevadm_test-builtin(){
- if (( CURRENT == 2 )); then
- _arguments \
- '--help[Print help text]' \
- '*::builtins:(blkid btrfs hwdb input_id kmod path_id usb_id uaccess)'
- elif (( CURRENT == 3 )); then
- _arguments \
- '--help[Print help text]' \
- '*::syspath:_files -P /sys -W /sys'
- else
- _arguments \
- '--help[Print help text]'
- fi
-}
-
-_udevadm_mounts(){
- local dev_tmp dpath_tmp mp_tmp mline
-
- tmp=( "${(@f)$(< /etc/mtab)}" )
- dev_tmp=( "${(@)${(@)tmp%% *}:#none}" )
- mp_tmp=( "${(@)${(@)tmp#* }%% *}" )
-
- local MATCH
- mp_tmp=("${(@q)mp_tmp//(#m)\\[0-7](#c3)/${(#)$(( 8#${MATCH[2,-1]} ))}}")
- dpath_tmp=( "${(@Mq)dev_tmp:#/*}" )
- dev_tmp=( "${(@q)dev_tmp:#/*}" )
-
- _alternative \
- 'device-paths: device path:compadd -a dpath_tmp' \
- 'directories:mount point:compadd -a mp_tmp'
-}
-
-
-_udevadm_command(){
- local -a _udevadm_cmds
- _udevadm_cmds=(
- 'info:query sysfs or the udev database'
- 'trigger:request events from the kernel'
- 'settle:wait for the event queue to finish'
- 'control:control the udev daemon'
- 'monitor:listen to kernel and udev events'
- 'test:test an event run'
- 'test-builtin:test a built-in command'
- )
-
- if ((CURRENT == 1)); then
- _describe -t commands 'udevadm commands' _udevadm_cmds
- else
- local curcontext="$curcontext"
- cmd="${${_udevadm_cmds[(r)$words[1]:*]%%:*}}"
- if (($#cmd)); then
- if (( $+functions[_udevadm_$cmd] )); then
- _udevadm_$cmd
- else
- _message "no options for $cmd"
- fi
- else
- _message "no more options"
- fi
- fi
-}
-
-_ctls "$@"
-
-#vim: set ft=zsh sw=4 ts=4 et
diff --git a/shell-completion/zsh/_hostnamectl b/shell-completion/zsh/_hostnamectl
new file mode 100644
index 0000000000..45b9597897
--- /dev/null
+++ b/shell-completion/zsh/_hostnamectl
@@ -0,0 +1,32 @@
+#compdef hostnamectl
+
+_hostnamectl_command() {
+ local -a _hostnamectl_cmds
+ _hostnamectl_cmds=(
+ "status:Show current hostname settings"
+ "set-hostname:Set system hostname"
+ "set-icon-name:Set icon name for host"
+ )
+ if (( CURRENT == 1 )); then
+ _describe -t commands 'hostnamectl commands' _hostnamectl_cmds || compadd "$@"
+ else
+ local curcontext="$curcontext"
+ cmd="${${_hostnamectl_cmds[(r)$words[1]:*]%%:*}}"
+ if (( $#cmd )); then
+ [[ $cmd == status ]] && msg="no options" || msg="options for $cmd"
+ _message "$msg"
+ else
+ _message "unknown hostnamectl command: $words[1]"
+ fi
+ fi
+}
+
+_arguments -s \
+ {-h,--help}'[Show this help]' \
+ '--version[Show package version]' \
+ '--transient[Only set transient hostname]' \
+ '--static[Only set static hostname]' \
+ '--pretty[Only set pretty hostname]' \
+ '--no-ask-password[Do not prompt for password]' \
+ {-H+,--host=}'[Operate on remote host]:userathost:_sd_hosts_or_user_at_host' \
+ '*::hostnamectl commands:_hostnamectl_command'
diff --git a/shell-completion/zsh/_journalctl b/shell-completion/zsh/_journalctl
new file mode 100644
index 0000000000..73646b57f5
--- /dev/null
+++ b/shell-completion/zsh/_journalctl
@@ -0,0 +1,98 @@
+#compdef journalctl
+
+_outputmodes() {
+ local -a _output_opts
+ _output_opts=(short short-monotonic verbose export json json-pretty json-see cat)
+ _describe -t output 'output mode' _output_opts || compadd "$@"
+}
+
+_list_fields() {
+ local -a journal_fields
+ journal_fields=(MESSAGE{,_ID} PRIORITY CODE_{FILE,LINE,FUNC}
+ ERRNO SYSLOG_{FACILITY,IDENTIFIER,PID}
+ _{P,U,G}ID _COMM _EXE _CMDLINE
+ _AUDIT_{SESSION,LOGINUID}
+ _SYSTEMD_{CGROUP,SESSION,UNIT,OWNER_UID}
+ _SYSTEMD_USER_UNIT USER_UNIT
+ _SELINUX_CONTEXT _SOURCE_REALTIME_TIMESTAMP
+ _{BOOT,MACHINE}_ID _HOSTNAME _TRANSPORT
+ _KERNEL_{DEVICE,SUBSYSTEM}
+ _UDEV_{SYSNAME,DEVNODE,DEVLINK}
+ __CURSOR __{REALTIME,MONOTONIC}_TIMESTAMP)
+ case $_jrnl_none in
+ yes) _values -s '=' 'possible fields' \
+ "${journal_fields[@]}:value:_journal_fields ${words[CURRENT]%%=*}" ;;
+ *) _describe 'possible fields' journal_fields ;;
+ esac
+}
+
+_journal_none() {
+ local -a _commands _files _jrnl_none
+ # Setting use-cache will slow this down considerably
+ _commands=( ${"$(_call_program commands "$service" -F _EXE 2>/dev/null)"} )
+ _jrnl_none='yes'
+ _alternative : \
+ 'files:/dev files:_files -W /dev -P /dev/' \
+ "commands:commands:($_commands[@])" \
+ 'fields:fields:_list_fields'
+}
+
+_journal_fields() {
+ local -a _fields cmd
+ cmd=("journalctl" "-F ${@[-1]}" "2>/dev/null" )
+ _fields=( ${(f)"$(_call_program fields $cmd[@])"} )
+ typeset -U _fields
+ _describe 'possible values' _fields
+}
+
+_journal_boots() {
+ local -a _bootid _previousboots
+ _bootid=( ${(fao)"$(_call_program bootid "$service -F _BOOT_ID")"} )
+ _previousboots=( -{1..${#_bootid}} )
+ _alternative : \
+ "offsets:boot offsets:(${_previousboots[1,-2]})" \
+ "bootid:boot ids:(${_bootid[@]})"
+}
+
+_arguments -s \
+ {-h,--help}'[Show this help]' \
+ '--version[Show package version]' \
+ '--no-pager[Do not pipe output into a pager]' \
+ {-l,--full}'[Show long fields in full]' \
+ {-a,--all}'[Show all fields, including long and unprintable]' \
+ {-f,--follow}'[Follow journal]' \
+ {-e,--pager-end}'[Jump to the end of the journal in the pager]' \
+ {-n+,--lines=}'[Number of journal entries to show]:integer' \
+ '--no-tail[Show all lines, even in follow mode]' \
+ {-r,--reverse}'[Reverse output]' \
+ {-o+,--output=}'[Change journal output mode]:output modes:_outputmodes' \
+ {-x,--catalog}'[Show explanatory texts with each log line]' \
+ {-q,--quiet}"[Don't show privilege warning]" \
+ {-m,--merge}'[Show entries from all available journals]' \
+ {-b+,--boot=}'[Show data only from the specified boot or offset]:boot id or offset:_journal_boots' \
+ {-k,--dmesg}'[Show only kernel messages, Implies -b]' \
+ {-u+,--unit=}'[Show data only from the specified unit]:units:_journal_fields _SYSTEMD_UNIT' \
+ '--user-unit=[Show data only from the specified user session unit]:units:_journal_fields USER_UNIT' \
+ {-p+,--priority=}'[Show only messages within the specified priority range]:priority:_journal_fields PRIORITY' \
+ {-c+,--cursor=}'[Start showing entries from specified cursor]:cursors:_journal_fields __CURSORS' \
+ '--after-cursor=[Start showing entries from the location in the journal after the cursor]:cursors:_journal_fields __CURSORS' \
+ '--since=[Start showing entries newer or of the specified date]:YYYY-MM-DD HH\:MM\:SS' \
+ '--until=[Stop showing entries older or of the specified date]:YYYY-MM-DD HH\:MM\:SS' \
+ {-F,--field=}'[List all values a certain field takes]:Fields:_list_fields' \
+ '--system[Show system and kernel messages]' \
+ '--user[Show messages from user services]' \
+ {-D+,--directory=}'[Show journal files from directory]:directories:_directories' \
+ '--file=[Operate on specified journal files]:file:_files' \
+ '--root=[Operate on catalog hierarchy under specified directory]:directories:_directories' \
+ '--new-id128[Generate a new 128 Bit ID]' \
+ '--header[Show journal header information]' \
+ '--disk-usage[Show total disk usage]' \
+ '--list-catalog[List messages in catalog]' \
+ '--dump-catalog[Dump messages in catalog]' \
+ '--update-catalog[Update binary catalog database]' \
+ '--setup-keys[Generate new FSS key pair]' \
+ '--force[Force recreation of FSS keys]' \
+ '--interval=[Time interval for changing the FSS sealing key]:time interval' \
+ '--verify[Verify journal file consistency]' \
+ '--verify-key=[Specify FSS verification key]:FSS key' \
+ '*::default: _journal_none'
diff --git a/shell-completion/zsh/_kernel-install b/shell-completion/zsh/_kernel-install
new file mode 100644
index 0000000000..065518834c
--- /dev/null
+++ b/shell-completion/zsh/_kernel-install
@@ -0,0 +1,26 @@
+#compdef kernel-install
+
+_images(){
+ if [[ "$words[2]" == "remove" ]]; then
+ _message 'No more options'
+ else
+ _path_files -W /boot/ -P /boot/ -g "vmlinuz-*"
+ fi
+}
+
+_kernels(){
+ read _MACHINE_ID < /etc/machine-id
+ _kernel=( /lib/modules/[0-9]* )
+ if [[ "$cmd" == "remove" && -n "$_MACHINE_ID" ]]; then
+ _kernel=( /lib/modules/[0-9]* "/boot/$_MACHINE_ID"/[0-9]* )
+ fi
+ _kernel=( ${_kernel##*/} )
+ _describe "installed kernels" _kernel
+}
+
+_arguments \
+ '1::add or remove:(add remove)' \
+ '2::kernel versions:_kernels' \
+ '3::kernel images:_images'
+
+#vim: set ft=zsh sw=4 ts=4 et
diff --git a/shell-completion/zsh/_localectl b/shell-completion/zsh/_localectl
new file mode 100644
index 0000000000..3d76bb0c4d
--- /dev/null
+++ b/shell-completion/zsh/_localectl
@@ -0,0 +1,83 @@
+#compdef localectl
+
+_localectl_set-locale() {
+ local -a _confs _locales
+ local expl suf
+ _locales=( ${(f)"$(_call_program locales "$service" list-locales)"} )
+ _confs=( ${${(f)"$(_call_program confs "locale 2>/dev/null")"}%\=*} )
+ if [[ -prefix 1 *\= ]]; then
+ local conf=${PREFIX%%\=*}
+ compset -P1 '*='
+ _wanted locales expl "locales configs" \
+ _combination localeconfs confs=$conf locales "$@" -
+ else
+ compadd -S '=' $_confs
+ fi
+}
+
+_localectl_set-keymap() {
+ local -a _keymaps
+ _keymaps=( ${(f)"$(_call_program locales "$service" list-keymaps)"} )
+ if (( CURRENT <= 3 )); then
+ _describe keymaps _keymaps
+ else
+ _message "no more options"
+ fi
+}
+
+_localectl_set-x11-keymap() {
+ if (( $+commands[pkg-config] )); then
+ local -a _file _layout _model _variant _options
+ local _xorg_lst
+ _xorg_lst=${"$($commands[pkg-config] xkeyboard-config --variable=xkb_base)"}
+ _file=( ${(ps:\n\!:)"$(<$_xorg_lst/rules/xorg.lst)"} )
+ _layout=( ${${${(M)${(f)_file[1]}:# *}# }%% *} )
+ _model=( ${${${(M)${(f)_file[2]}:# *}# }%% *} )
+ _variant=( ${${${(M)${(f)_file[3]}:# *}# }%% *} )
+ _options=( ${${${(M)${(f)_file[4]}:# *}# }%% *} )
+ #_layout=( ${(f)"$( echo $_file[1] | awk '/^ / {print $1}' )"} )
+ #_model=( ${(f)"$(echo $_file[2] | awk '/^ / {print $1}')"} )
+ #_variant=( ${(f)"$(echo $_file[3] | awk '/^ / {print $1}')"} )
+ #_options=( ${(f)"$(echo ${_file[4]//:/\\:} | awk '/^ / {print $1}')"} )
+
+ case $CURRENT in
+ 2) _describe layouts _layout ;;
+ 3) _describe models _model;;
+ 4) _describe variants _variant;;
+ 5) _describe options _options;;
+ *) _message "no more options"
+ esac
+ fi
+}
+
+_localectl_command() {
+ local -a _localectl_cmds
+ _localectl_cmds=(
+ 'status:Show current locale settings'
+ 'set-locale:Set system locale'
+ 'list-locales:Show known locales'
+ 'set-keymap:Set virtual console keyboard mapping'
+ 'list-keymaps:Show known virtual console keyboard mappings'
+ 'set-x11-keymap:Set X11 keyboard mapping'
+ )
+ if (( CURRENT == 1 )); then
+ _describe -t commands 'localectl command' _localectl_cmds
+ else
+ local curcontext="$curcontext"
+ cmd="${${_localectl_cmds[(r)$words[1]:*]%%:*}}"
+ if (( $+functions[_localectl_$cmd] )); then
+ _localectl_$cmd
+ else
+ _message "no more options"
+ fi
+ fi
+}
+
+_arguments \
+ {-h,--help}'[Show this help]' \
+ '--version[Show package version]' \
+ "--no-convert[Don't convert keyboard mappings]" \
+ '--no-pager[Do not pipe output into a pager]' \
+ '--no-ask-password[Do not prompt for password]' \
+ {-H+,--host=}'[Operate on remote host]:userathost:_sd_hosts_or_user_at_host' \
+ '*::localectl commands:_localectl_command'
diff --git a/shell-completion/zsh/_loginctl b/shell-completion/zsh/_loginctl
new file mode 100644
index 0000000000..ebf6b3ae0a
--- /dev/null
+++ b/shell-completion/zsh/_loginctl
@@ -0,0 +1,106 @@
+#compdef loginctl
+
+_loginctl_all_sessions(){_sys_all_sessions=($(loginctl list-sessions | { while read a b; do echo " $a"; done; }) )}
+_loginctl_all_users() {_sys_all_users=( $(loginctl list-users | { while read a b; do echo " $a"; done; }) )}
+_loginctl_all_seats() {_sys_all_seats=( $(loginctl list-seats | { while read a b; do echo " $a"; done; }) )}
+
+# Completion functions for SESSIONS
+for fun in session-status show-session activate lock-session unlock-session terminate-session kill-session ; do
+ (( $+functions[_loginctl_$fun] )) || _loginctl_$fun()
+ {
+ _loginctl_all_sessions
+ compadd "$@" -a - _sys_all_sessions
+ }
+done
+
+# Completion functions for USERS
+for fun in user-status show-user enable-linger disable-linger terminate-user kill-user ; do
+ (( $+functions[_loginctl_$fun] )) || _loginctl_$fun()
+ {
+ _loginctl_all_users
+ compadd "$@" -a - _sys_all_users
+ }
+done
+
+# Completion functions for SEATS
+(( $+functions[_loginctl_seats] )) || _loginctl_seats()
+{
+ _loginctl_all_seats
+ compadd "$@" -a - _sys_all_seats
+}
+for fun in seat-status show-seat terminate-seat ; do
+ (( $+functions[_loginctl_$fun] )) || _loginctl_$fun()
+ { _loginctl_seats }
+done
+
+# Completion functions for ATTACH
+(( $+functions[_loginctl_attach] )) || _loginctl_attach()
+{
+ _loginctl_all_seats
+
+ _arguments -w -C -S -s \
+ ':seat:_loginctl_seats' \
+ '*:device:_files'
+}
+
+# no loginctl completion for:
+# [STANDALONE]='list-sessions list-users list-seats flush-devices'
+
+(( $+functions[_loginctl_command] )) || _loginctl_command()
+{
+ local -a _loginctl_cmds
+ _loginctl_cmds=(
+ "list-sessions:List sessions"
+ "session-status:Show session status"
+ "show-session:Show properties of one or more sessions"
+ "activate:Activate a session"
+ "lock-session:Screen lock one or more sessions"
+ "unlock-session:Screen unlock one or more sessions"
+ "terminate-session:Terminate one or more sessions"
+ "kill-session:Send signal to processes of a session"
+ "list-users:List users"
+ "user-status:Show user status"
+ "show-user:Show properties of one or more users"
+ "enable-linger:Enable linger state of one or more users"
+ "disable-linger:Disable linger state of one or more users"
+ "terminate-user:Terminate all sessions of one or more users"
+ "kill-user:Send signal to processes of a user"
+ "list-seats:List seats"
+ "seat-status:Show seat status"
+ "show-seat:Show properties of one or more seats"
+ "attach:Attach one or more devices to a seat"
+ "flush-devices:Flush all device associations"
+ "terminate-seat:Terminate all sessions on one or more seats"
+ )
+
+ if (( CURRENT == 1 )); then
+ _describe -t commands 'loginctl command' _loginctl_cmds || compadd "$@"
+ else
+ local curcontext="$curcontext"
+
+ cmd="${${_loginctl_cmds[(r)$words[1]:*]%%:*}}"
+
+ if (( $#cmd )); then
+ curcontext="${curcontext%:*:*}:loginctl-${cmd}:"
+
+ _call_function ret _loginctl_$cmd || _message 'no more arguments'
+ else
+ _message "unknown loginctl command: $words[1]"
+ fi
+ return ret
+ fi
+}
+
+
+_arguments -s \
+ {-h,--help}'[Show help]' \
+ '--version[Show package version]' \
+ \*{-p+,--property=}'[Show only properties by this name]:unit property' \
+ {-a,--all}'[Show all properties, including empty ones]' \
+ '--kill-who=[Who to send signal to]:killwho:(main control all)' \
+ {-s+,--signal=}'[Which signal to send]:signal:_signals' \
+ '--no-ask-password[Do not ask for system passwords]' \
+ {-H+,--host=}'[Show information for remote host]:userathost:_sd_hosts_or_user_at_host' \
+ {-P,--privileged}'[Acquire privileges before execution]' \
+ '--no-pager[Do not pipe output into a pager]' \
+ '*::loginctl command:_loginctl_command'
diff --git a/shell-completion/zsh/_machinectl b/shell-completion/zsh/_machinectl
new file mode 100644
index 0000000000..2e5e05cfcc
--- /dev/null
+++ b/shell-completion/zsh/_machinectl
@@ -0,0 +1,47 @@
+#compdef machinectl
+
+(( $+functions[_machinectl_command] )) || _machinectl_command()
+{
+ local -a _machinectl_cmds
+ _machinectl_cmds=(
+ "list:List currently running VMs/containers"
+ "status:Show VM/container status"
+ "show:Show properties of one or more VMs/containers"
+ "terminate:Terminate one or more VMs/containers"
+ "kill:Send signal to process or a VM/container"
+ )
+ if (( CURRENT == 1 )); then
+ _describe -t commands 'machinectl command' _machinectl_cmds || compadd "$@"
+ else
+ local curcontext="$curcontext"
+ cmd="${${_machinectl_cmds[(r)$words[1]:*]%%:*}}"
+ if (( $#cmd )); then
+ case $cmd in
+ list) msg="no options" ;;
+ *)
+ _machines=( "${(foa)$(machinectl list | awk '{print $1}')}" )
+ if [[ -n "$_machines" ]]; then
+ _describe 'machines' _machines
+ else
+ _message 'no machines'
+ fi
+ esac
+ else
+ _message "no more options"
+ fi
+ fi
+}
+
+_arguments \
+ {-h,--help}'[Prints a short help text and exits.]' \
+ '--version[Prints a short version string and exits.]' \
+ \*{-p+,--property=}'[Limit output to specified property.]:property:(Name Id Timestamp TimestampMonotonic Service Scope Leader Class State RootDirectory)' \
+ {-a,--all}'[Show all proerties]' \
+ (-l,--full)'[Do not ellipsize cgroup members]' \
+ '--no-pager[Do not pipe output into a pager]' \
+ '--no-ask-password[Do not ask for system passwords]' \
+ '--kill-who=[Who to send signal to]:killwho:(leader all)' \
+ {-s+,--signal=}'[Which signal to send]:signal:_signals' \
+ {-H+,--host=}'[Show information for remote host]:userathost:_sd_hosts_or_user_at_host' \
+ {-P,--privileged}'[Acquire privileges before execution]' \
+ '*::machinectl command:_machinectl_command'
diff --git a/shell-completion/zsh/_sd_hosts_or_user_at_host b/shell-completion/zsh/_sd_hosts_or_user_at_host
new file mode 100644
index 0000000000..282f7328e4
--- /dev/null
+++ b/shell-completion/zsh/_sd_hosts_or_user_at_host
@@ -0,0 +1,5 @@
+#autoload
+
+_alternative \
+ 'users-hosts:: _user_at_host' \
+ 'hosts:: _hosts'
diff --git a/shell-completion/zsh/_systemctl b/shell-completion/zsh/_systemctl
new file mode 100644
index 0000000000..298e97ed61
--- /dev/null
+++ b/shell-completion/zsh/_systemctl
@@ -0,0 +1,347 @@
+#compdef systemctl
+
+(( $+functions[_systemctl_command] )) || _systemctl_command()
+{
+ local -a _systemctl_cmds
+ _systemctl_cmds=(
+ "list-sockets:List sockets"
+ "list-units:List units"
+ "start:Start (activate) one or more units"
+ "stop:Stop (deactivate) one or more units"
+ "reload:Reload one or more units"
+ "restart:Start or restart one or more units"
+ "condrestart:Restart one or more units if active"
+ "try-restart:Restart one or more units if active"
+ "reload-or-restart:Reload one or more units if possible, otherwise start or restart"
+ "force-reload:Reload one or more units if possible, otherwise restart if active"
+ "hibernate:Hibernate the system"
+ "hybrid-sleep:Hibernate and suspend the system"
+ "reload-or-try-restart:Reload one or more units if possible, otherwise restart if active"
+ "isolate:Start one unit and stop all others"
+ "kill:Send signal to processes of a unit"
+ "is-active:Check whether units are active"
+ "is-failed:Check whether units are failed"
+ "status:Show runtime status of one or more units"
+ "show:Show properties of one or more units/jobs or the manager"
+ "reset-failed:Reset failed state for all, one, or more units"
+ "load:Load one or more units"
+ "list-unit-files:List installed unit files"
+ "enable:Enable one or more unit files"
+ "disable:Disable one or more unit files"
+ "reenable:Reenable one or more unit files"
+ "preset:Enable/disable one or more unit files based on preset configuration"
+ "help:Show documentation for specified units"
+ "list-dependencies:Show unit dependency tree"
+ "mask:Mask one or more units"
+ "unmask:Unmask one or more units"
+ "link:Link one or more units files into the search path"
+ "is-enabled:Check whether unit files are enabled"
+ "list-jobs:List jobs"
+ "cancel:Cancel all, one, or more jobs"
+ "dump:Dump server status"
+ "snapshot:Create a snapshot"
+ "delete:Remove one or more snapshots"
+ "show-environment:Dump environment"
+ "set-environment:Set one or more environment variables"
+ "unset-environment:Unset one or more environment variables"
+ "daemon-reload:Reload systemd manager configuration"
+ "daemon-reexec:Reexecute systemd manager"
+ "default:Enter system default mode"
+ "rescue:Enter system rescue mode"
+ "emergency:Enter system emergency mode"
+ "halt:Shut down and halt the system"
+ "suspend:Suspend the system"
+ "poweroff:Shut down and power-off the system"
+ "reboot:Shut down and reboot the system"
+ "kexec:Shut down and reboot the system with kexec"
+ "exit:Ask for user instance termination"
+ )
+
+ if (( CURRENT == 1 )); then
+ _describe -t commands 'systemctl command' _systemctl_cmds || compadd "$@"
+ else
+ local curcontext="$curcontext"
+
+ cmd="${${_systemctl_cmds[(r)$words[1]:*]%%:*}}"
+ # Deal with any aliases
+ case $cmd in
+ condrestart) cmd="try-restart";;
+ force-reload) cmd="reload-or-try-restart";;
+ esac
+
+ if (( $#cmd )); then
+ curcontext="${curcontext%:*:*}:systemctl-${cmd}:"
+
+ local update_policy
+ zstyle -s ":completion:${curcontext}:" cache-policy update_policy
+ if [[ -z "$update_policy" ]]; then
+ zstyle ":completion:${curcontext}:" cache-policy _systemctl_caching_policy
+ fi
+
+ _call_function ret _systemctl_$cmd || _message 'no more arguments'
+ else
+ _message "unknown systemctl command: $words[1]"
+ fi
+ return ret
+ fi
+}
+
+__systemctl()
+{
+ local -a _modes
+ _modes=("--user" "--system")
+ systemctl ${words:*_modes} --full --no-legend --no-pager "$@"
+}
+
+
+# Fills the unit list
+_systemctl_all_units()
+{
+ if ( [[ ${+_sys_all_units} -eq 0 ]] || _cache_invalid SYS_ALL_UNITS ) &&
+ ! _retrieve_cache SYS_ALL_UNITS;
+ then
+ _sys_all_units=( $(__systemctl list-units --all | { while read a b; do echo " $a"; done; }) )
+ _store_cache SYS_ALL_UNITS _sys_all_units
+ fi
+}
+
+# Fills the unit list including all file units
+_systemctl_really_all_units()
+{
+ local -a all_unit_files;
+ local -a really_all_units;
+ if ( [[ ${+_sys_really_all_units} -eq 0 ]] || _cache_invalid SYS_REALLY_ALL_UNITS ) &&
+ ! _retrieve_cache SYS_REALLY_ALL_UNITS;
+ then
+ all_unit_files=( $(__systemctl list-unit-files | { while read a b; do echo " $a"; done; }) )
+ _systemctl_all_units
+ really_all_units=($_sys_all_units $all_unit_files)
+ _sys_really_all_units=(${(u)really_all_units})
+ _store_cache SYS_REALLY_ALL_UNITS _sys_really_all_units
+ fi
+}
+
+_filter_units_by_property() {
+ local property=$1 value=$2 ; shift ; shift
+ local -a units ; units=($*)
+ local prop unit
+ for ((i=1; $i <= ${#units[*]}; i++)); do
+ # FIXME: "Failed to issue method call: Unknown unit" errors are ignored for
+ # now (related to DBUS_ERROR_UNKNOWN_OBJECT). in the future, we need to
+ # revert to calling 'systemctl show' once for all units, which is way
+ # faster
+ unit=${units[i]}
+ prop=${(f)"$(_call_program units "$service show --no-pager --property="$property" ${unit} 2>/dev/null")"}
+ if [[ "${prop}" = "$property=$value" ]]; then
+ echo " ${unit}"
+ fi
+ done
+}
+
+_systemctl_active_units() {_sys_active_units=( $(__systemctl list-units | { while read a b; do echo " $a"; done; }) )}
+_systemctl_inactive_units(){_sys_inactive_units=($(__systemctl list-units --all | { while read a b c d; do [[ $c == "inactive" || $c == "failed" ]] && echo " $a"; done; }) )}
+_systemctl_failed_units() {_sys_failed_units=( $(__systemctl list-units --failed | { while read a b; do echo " $a"; done; }) )}
+_systemctl_enabled_units() {_sys_enabled_units=( $(__systemctl list-unit-files | { while read a b; do [[ $b == "enabled" ]] && echo " $a"; done; }) )}
+_systemctl_disabled_units(){_sys_disabled_units=($(__systemctl list-unit-files | { while read a b; do [[ $b == "disabled" ]] && echo " $a"; done; }) )}
+_systemctl_masked_units() {_sys_masked_units=( $(__systemctl list-unit-files | { while read a b; do [[ $b == "masked" ]] && echo " $a"; done; }) )}
+
+# Completion functions for ALL_UNITS
+for fun in is-active is-failed is-enabled status show mask preset help list-dependencies ; do
+ (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
+ {
+ _systemctl_really_all_units
+ compadd "$@" -a - _sys_really_all_units
+ }
+done
+
+# Completion functions for ENABLED_UNITS
+for fun in disable reenable ; do
+ (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
+ {
+ _systemctl_enabled_units
+ _systemctl_disabled_units
+ compadd "$@" -a - _sys_enabled_units _sys_disabled_units
+ }
+done
+
+# Completion functions for DISABLED_UNITS
+(( $+functions[_systemctl_enable] )) || _systemctl_enable()
+{
+ _systemctl_disabled_units
+ compadd "$@" -a - _sys_disabled_units
+}
+
+# Completion functions for FAILED_UNITS
+(( $+functions[_systemctl_reset-failed] )) || _systemctl_reset-failed()
+{
+ _systemctl_failed_units
+ compadd "$@" -a - _sys_failed_units || _message "no failed unit found"
+}
+
+# Completion functions for STARTABLE_UNITS
+(( $+functions[_systemctl_start] )) || _systemctl_start()
+{
+ _systemctl_inactive_units
+ compadd "$@" -a - _sys_inactive_units
+}
+
+# Completion functions for STOPPABLE_UNITS
+for fun in stop kill try-restart condrestart ; do
+ (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
+ {
+ _systemctl_active_units
+ compadd "$@" - $( _filter_units_by_property CanStop yes \
+ ${_sys_active_units[*]} )
+ }
+done
+
+# Completion functions for ISOLATABLE_UNITS
+(( $+functions[_systemctl_isolate] )) || _systemctl_isolate()
+{
+ _systemctl_all_units
+ compadd "$@" - $( _filter_units_by_property AllowIsolate yes \
+ ${_sys_all_units[*]} )
+}
+
+# Completion functions for RELOADABLE_UNITS
+for fun in reload reload-or-try-restart force-reload ; do
+ (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
+ {
+ _systemctl_active_units
+ compadd "$@" - $( _filter_units_by_property CanReload yes \
+ ${_sys_active_units[*]} )
+ }
+done
+
+# Completion functions for RESTARTABLE_UNITS
+for fun in restart reload-or-restart ; do
+ (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
+ {
+ _systemctl_all_units
+ compadd "$@" - $( _filter_units_by_property CanStart yes \
+ ${_sys_all_units[*]} | while read line; do \
+ [[ "$line" =~ \.device$ ]] || echo " $line"; \
+ done )
+ }
+done
+
+# Completion functions for MASKED_UNITS
+(( $+functions[_systemctl_unmask] )) || _systemctl_unmask()
+{
+ _systemctl_masked_units
+ compadd "$@" -a - _sys_masked_units || _message "no masked unit found"
+}
+
+# Completion functions for JOBS
+(( $+functions[_systemctl_cancel] )) || _systemctl_cancel()
+{
+ compadd "$@" - $(__systemctl list-jobs \
+ | cut -d' ' -f1 2>/dev/null ) || _message "no job found"
+}
+
+# Completion functions for SNAPSHOTS
+(( $+functions[_systemctl_delete] )) || _systemctl_delete()
+{
+ compadd "$@" - $(__systemctl list-units --type snapshot --all \
+ | cut -d' ' -f1 2>/dev/null ) || _message "no snapshot found"
+}
+
+# Completion functions for ENVS
+for fun in set-environment unset-environment ; do
+ (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
+ {
+ local fun=$0 ; fun=${fun##_systemctl_}
+ local suf
+ if [[ "${fun}" = "set-environment" ]]; then
+ suf='-S='
+ fi
+
+ compadd "$@" ${suf} - $(systemctl show-environment \
+ | while read line; do echo " ${line%%\=}";done )
+ }
+done
+
+(( $+functions[_systemctl_link] )) || _systemctl_link() { _files }
+
+# no systemctl completion for:
+# [STANDALONE]='daemon-reexec daemon-reload default dump
+# emergency exit halt kexec list-jobs list-units
+# list-unit-files poweroff reboot rescue show-environment'
+# [NAME]='snapshot load'
+
+_systemctl_caching_policy()
+{
+ local _sysunits
+ local -a oldcache
+
+ # rebuild if cache is more than a day old
+ oldcache=( "$1"(mh+1) )
+ (( $#oldcache )) && return 0
+
+ _sysunits=($(__systemctl --all | cut -d' ' -f1))
+
+ if (( $#_sysunits )); then
+ for unit in $_sysunits; do
+ [[ "$unit" -nt "$1" ]] && return 0
+ done
+ fi
+
+ return 1
+}
+
+_outputmodes() {
+ local -a _output_opts
+ _output_opts=(short short-monotonic verbose export json json-pretty json-see cat)
+ _describe -t output 'output mode' _output_opts || compadd "$@"
+}
+
+_unit_states() {
+ local -a _states
+ _states=(loaded failed active inactive not-found listening running waiting plugged mounted exited dead masked)
+ _values -s , "${_states[@]}"
+}
+
+_unit_types() {
+ local -a _types
+ _types=(automount device mount path service snapshot socket swap target timer)
+ _values -s , "${_types[@]}"
+}
+
+_arguments -s \
+ {-h,--help}'[Show help]' \
+ '--version[Show package version]' \
+ {-t+,--type=}'[List only units of a particular type]:unit type:_unit_types' \
+ '--state=[Display units in the specifyied state]:unit state:_unit_states' \
+ \*{-p+,--property=}'[Show only properties by specific name]:unit property' \
+ {-a,--all}'[Show all units/properties, including dead/empty ones]' \
+ '--reverse[Show reverse dependencies]' \
+ '--after[Show units ordered after]' \
+ '--before[Show units ordered before]' \
+ '--failed[Show only failed units]' \
+ {-l,--full}"[Don't ellipsize unit names on output]" \
+ '--fail[When queueing a new job, fail if conflicting jobs are pending]' \
+ '--show-types[When showing sockets, show socket type]' \
+ '--irreversible[Mark transactions as irreversible]' \
+ '--ignore-dependencies[When queueing a new job, ignore all its dependencies]' \
+ {-i,--ignore-inhibitors}'[When executing a job, ignore jobs dependencies]' \
+ {-q,--quiet}'[Suppress output]' \
+ '--no-block[Do not wait until operation finished]' \
+ '--no-legend[Do not print a legend, i.e. the column headers and the footer with hints]' \
+ '--no-pager[Do not pipe output into a pager]' \
+ '--system[Connect to system manager]' \
+ '--user[Connect to user service manager]' \
+ "--no-wall[Don't send wall message before halt/power-off/reboot]" \
+ '--global[Enable/disable unit files globally]' \
+ "--no-reload[When enabling/disabling unit files, don't reload daemon configuration]" \
+ '--no-ask-password[Do not ask for system passwords]' \
+ '--kill-who=[Who to send signal to]:killwho:(main control all)' \
+ {-s+,--signal=}'[Which signal to send]:signal:_signals' \
+ {-f,--force}'[When enabling unit files, override existing symlinks. When shutting down, execute action immediately]' \
+ '--root=[Enable unit files in the specified root directory]:directory:_directories' \
+ '--runtime[Enable unit files only temporarily until next reboot]' \
+ {-H+,--host=}'[Show information for remote host]:userathost:_sd_hosts_or_user_at_host' \
+ {-P,--privileged}'[Acquire privileges before execution]' \
+ {-n+,--lines=}'[Journal entries to show]:number of entries' \
+ {-o+,--output=}'[Change journal output mode]:modes:_outputmodes' \
+ '--plain[When used with list-dependencies, print output as a list]' \
+ '*::systemctl command:_systemctl_command'
diff --git a/shell-completion/zsh/_systemd b/shell-completion/zsh/_systemd
new file mode 100644
index 0000000000..06f03bd1e7
--- /dev/null
+++ b/shell-completion/zsh/_systemd
@@ -0,0 +1,83 @@
+#compdef systemd-cat systemd-ask-password systemd-cgls systemd-cgtop systemd-detect-virt systemd-machine-id-setup systemd-notify systemd-tty-ask-password-agent
+
+local curcontext="$curcontext" state lstate line
+case "$service" in
+ systemd-ask-password)
+ _arguments \
+ {-h,--help}'[Show this help]' \
+ '--icon=[Icon name]' \
+ '--timeout=[Timeout in sec]' \
+ '--no-tty[Ask question via agent even on TTY]' \
+ '--accept-cached[Accept cached passwords]' \
+ '--multiple[List multiple passwords if available]'
+ ;;
+ systemd-cat)
+ _arguments \
+ {-h,--help}'[Show this help]' \
+ '--version[Show package version.]' \
+ {-t+,--identifier=}'[Set syslog identifier.]' \
+ {-p+,--priority=}'[Set priority value.]:value:({0..7})' \
+ '--level-prefix=[Control whether level prefix shall be parsed.]:boolean:(1 0)' \
+ ':Message'
+ ;;
+ systemd-cgls)
+ _arguments \
+ {-h,--help}'[Show this help]' \
+ '--version[Show package version]' \
+ '--no-pager[Do not pipe output into a pager]' \
+ {-a,--all}'[Show all groups, including empty]' \
+ '-k[Include kernel threads in output]' \
+ ':cgroups:(cpuset cpu cpuacct memory devices freezer net_cls blkio)'
+ ;;
+ systemd-cgtop)
+ _arguments \
+ {-h,--help}'[Show this help]' \
+ '--version[Print version and exit]' \
+ '(-c -m -i -t)-p[Order by path]' \
+ '(-c -p -m -i)-t[Order by number of tasks]' \
+ '(-m -p -i -t)-c[Order by CPU load]' \
+ '(-c -p -i -t)-m[Order by memory load]' \
+ '(-c -m -p -t)-i[Order by IO load]' \
+ {-d+,--delay=}'[Specify delay]' \
+ {-n+,--iterations=}'[Run for N iterations before exiting]' \
+ {-b,--batch}'[Run in batch mode, accepting no input]' \
+ '--depth=[Maximum traversal depth]'
+ ;;
+ systemd-detect-virt)
+ _arguments \
+ {-h,--help}'[Show this help]' \
+ '--version[Show package version]' \
+ {-c,--container}'[Only detect whether we are run in a container]' \
+ {-v,--vm}'[Only detect whether we are run in a VM]' \
+ {-q,--quiet}"[Don't output anything, just set return value]"
+ ;;
+ systemd-machine-id-setup)
+ _arguments \
+ {-h,--help}'[Show this help]' \
+ '--version[Show package version]'
+ ;;
+ systemd-notify)
+ _arguments \
+ {-h,--help}'[Show this help]' \
+ '--version[Show package version]' \
+ '--ready[Inform the init system about service start-up completion.]' \
+ '--pid=[Inform the init system about the main PID of the daemon]' \
+ '--status=[Send a free-form status string for the daemon to the init systemd]' \
+ '--booted[Returns 0 if the system was booted up with systemd]' \
+ '--readahead=[Controls disk read-ahead operations]:arguments:(cancel done noreply)'
+ ;;
+ systemd-tty-ask-password-agent)
+ _arguments \
+ {-h,--help}'[Prints a short help text and exits.]' \
+ '--version[Prints a short version string and exits.]' \
+ '--list[Lists all currently pending system password requests.]' \
+ '--query[Process all currently pending system password requests by querying the user on the calling TTY.]' \
+ '--watch[Continuously process password requests.]' \
+ '--wall[Forward password requests to wall(1).]' \
+ '--plymouth[Ask question with plymouth(8).]' \
+ '--console[Ask question on /dev/console.]'
+ ;;
+ *) _message 'eh?' ;;
+esac
+
+#vim: set ft=zsh sw=4 ts=4 et
diff --git a/shell-completion/zsh/_systemd-analyze b/shell-completion/zsh/_systemd-analyze
new file mode 100644
index 0000000000..37c60f5b40
--- /dev/null
+++ b/shell-completion/zsh/_systemd-analyze
@@ -0,0 +1,43 @@
+#compdef systemd-analyze
+
+_systemd_analyze_set-log-level() {
+ local -a _levels
+ _levels=(debug info notice warning err crit alert emerg)
+ _describe -t level 'logging level' _levels || compadd "$@"
+}
+
+_systemd_analyze_command(){
+ local -a _systemd_analyze_cmds
+ # Descriptions taken from systemd-analyze --help.
+ _systemd_analyze_cmds=(
+ 'time:Print time spent in the kernel before reaching userspace'
+ 'blame:Print list of running units ordered by time to init'
+ 'critical-chain:Print a tree of the time critical chain of units'
+ 'plot:Output SVG graphic showing service initialization'
+ 'dot:Dump dependency graph (in dot(1) format)'
+ 'set-log-level:Set systemd log threshold'
+ )
+
+ if (( CURRENT == 1 )); then
+ _describe "options" _systemd_analyze_cmds
+ else
+ local curcontext="$curcontext"
+ cmd="${${_systemd_analyze_cmds[(r)$words[1]:*]%%:*}}"
+ if (( $#cmd )); then
+ if (( $+functions[_systemd_analyze_$cmd] )) && (( CURRENT == 2 )); then
+ _systemd_analyze_$cmd
+ else
+ _message "no more options"
+ fi
+ else
+ _message "unknown systemd-analyze command: $words[1]"
+ fi
+ fi
+}
+
+_arguments \
+ {-h,--help}'[Show help text.]' \
+ '--user[Shows performance data of user sessions instead of the system manager.]' \
+ '--order[When generating graph for dot, show only order]' \
+ '--require[When generating graph for dot, show only requirement]' \
+ '*::systemd-analyze commands:_systemd_analyze_command'
diff --git a/shell-completion/zsh/_systemd-coredumpctl b/shell-completion/zsh/_systemd-coredumpctl
new file mode 100644
index 0000000000..159e8ee0e2
--- /dev/null
+++ b/shell-completion/zsh/_systemd-coredumpctl
@@ -0,0 +1,36 @@
+#compdef systemd-coredumpctl
+
+_systemd-coredumpctl_command(){
+ local -a _systemd_coredumpctl_cmds
+ _systemd_coredumpctl_cmds=(
+ 'list:List available coredumps'
+ 'dump:Print coredump to stdout'
+ 'gdb:Start gdb on a coredump'
+ )
+ if (( CURRENT == 1 )); then
+ _describe -t commands 'systemd-coredumpctl command' _systemd_coredumpctl_cmds
+ else
+ local curcontext="$curcontext"
+ local -a _dumps
+ cmd="${${_systemd_coredumpctl_cmds[(r)$words[1]:*]%%:*}}"
+ if (( $#cmd )); then
+ # user can set zstyle ':completion:*:*:systemd-coredumpctl:*' sort no for coredumps to be ordered by date, otherwise they get ordered by pid
+ _dumps=( "${(foa)$(systemd-coredumpctl list | awk 'BEGIN{OFS=":"} /^\s/ {sub(/[[ \t]+/, ""); print $5,$0}' 2>/dev/null)}" )
+ if [[ -n "$_dumps" ]]; then
+ _describe -t pids 'coredumps' _dumps
+ else
+ _message "no coredumps"
+ fi
+ else
+ _message "no more options"
+ fi
+ fi
+}
+
+_arguments \
+ {-o+,--output=}'[Write output to FILE]:output file:_files' \
+ {-F+,--field=}'[Show field in list output]:field' \
+ '--no-pager[Do not pipe output into a pager]' \
+ {-h,--help}'[Show this help]' \
+ '--version[Show package version]' \
+ '*::systemd-coredumpctl commands:_systemd-coredumpctl_command'
diff --git a/shell-completion/zsh/_systemd-delta b/shell-completion/zsh/_systemd-delta
new file mode 100644
index 0000000000..757f1b66fb
--- /dev/null
+++ b/shell-completion/zsh/_systemd-delta
@@ -0,0 +1,15 @@
+#compdef systemd-delta
+
+_delta_type() {
+ local -a _delta_types
+ _delta_types=(masked equivalent redirected overridden unchanged)
+ _values -s , "${_delta_types[@]}"
+}
+
+_arguments \
+ {-h,--help}'[Show this help]' \
+ '--version[Show package version]' \
+ '--no-pager[Do not pipe output into a pager]' \
+ '--diff=[Show a diff when overridden files differ]:boolean:(1 0)' \
+ {-t+,--type=}'[Only display a selected set of override types]:types:_delta_type' \
+ ':SUFFIX:(tmpfiles.d sysctl.d systemd/system)'
diff --git a/shell-completion/zsh/_systemd-inhibit b/shell-completion/zsh/_systemd-inhibit
new file mode 100644
index 0000000000..1ecb6dc7ee
--- /dev/null
+++ b/shell-completion/zsh/_systemd-inhibit
@@ -0,0 +1,33 @@
+#compdef systemd-inhibit
+
+_systemd_inhibit_command(){
+ if (( CURRENT == 1 )); then
+ compset -q
+ _normal
+ else
+ local n=${words[(b:2:i)[^-]*]}
+ if (( n <= CURRENT )); then
+ compset -n $n
+ _alternative \
+ 'files:file:_files' \
+ 'commands:command:_normal' && return 0
+ fi
+ _default
+ fi
+}
+
+_inhibit_what() {
+ local _inhibit
+ _inhibit=(shutdown sleep idle handle-power-key handle-suspend-key handle-hibernate-key handle-lid-switch)
+ _values -s : "${_inhibit[@]}"
+}
+
+_arguments \
+ {-h,--help}'[Show this help]' \
+ '--version[Show package version]' \
+ '--what=[Operations to inhibit]:options:_inhibit_what' \
+ '--who=[A descriptive string who is inhibiting]' \
+ '--why=[A descriptive string why is being inhibited]' \
+ '--mode=[One of block or delay]' \
+ '--list[List active inhibitors]' \
+ '*:commands:_systemd_inhibit_command'
diff --git a/shell-completion/zsh/_systemd-nspawn b/shell-completion/zsh/_systemd-nspawn
new file mode 100644
index 0000000000..a8c2411f2f
--- /dev/null
+++ b/shell-completion/zsh/_systemd-nspawn
@@ -0,0 +1,24 @@
+#compdef systemd-nspawn
+
+_nspawn-caps(){
+ local -a _caps
+ _caps=( CAP_CHOWN CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH
+ CAP_FOWNER CAP_FSETID CAP_IPC_OWNER CAP_KILL CAP_LEASE CAP_LINUX_IMMUTABLE
+ CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW CAP_SETGID CAP_SETFCAP CAP_SETPCAP
+ CAP_SETUID CAP_SYS_ADMIN CAP_SYS_CHROOT CAP_SYS_NICE CAP_SYS_PTRACE CAP_SYS_TTY_CONFIG
+ CAP_SYS_RESOURCE CAP_SYS_BOOT )
+ _values -s , 'capabilities' "$_caps[@]"
+}
+
+_arguments \
+ {-h,--help}'[Show this help]' \
+ {--directory=,-D+}'[Directory to use as file system root for the namespace container. If omitted the current directory will be used.]:directories:_directories' \
+ {--boot,-b+}'[Automatically search for an init binary and invoke it instead of a shell or a user supplied program.]' \
+ {--user=,-u+}'[Run the command under specified user, create home directory and cd into it.]' \
+ '--uuid=[Set the specified uuid for the container.]' \
+ {--controllers=,-C+}'[Makes the container appear in other hierarchies than the name=systemd:/ one. Takes a comma-separated list of controllers.]' \
+ '--private-network[Turn off networking in the container. This makes all network interfaces unavailable in the container, with the exception of the loopback device.]' \
+ '--read-only[Mount the root file system read only for the container.]' \
+ '--capability=[List one or more additional capabilities to grant the container.]:capabilities:_nspawn-caps' \
+ "--link-journal=[Control whether the container's journal shall be made visible to the host system.]:options:(no, host, guest, auto)" \
+ '-j[Equivalent to --link-journal=guest.]'
diff --git a/shell-completion/zsh/_systemd-tmpfiles b/shell-completion/zsh/_systemd-tmpfiles
new file mode 100644
index 0000000000..4913dedd2c
--- /dev/null
+++ b/shell-completion/zsh/_systemd-tmpfiles
@@ -0,0 +1,10 @@
+#compdef systemd-tmpfiles
+
+_arguments \
+ '--create[Create, set ownership/permissions based on the config files.]' \
+ '--clean[Clean up all files and directories with an age parameter configured.]' \
+ '--remove[All files and directories marked with r, R in the configuration files are removed.]' \
+ '--prefix=[Only apply rules that apply to paths with the specified prefix.]' \
+ '--exclude-prefix=[Ignore rules that apply to paths with the specified prefix.]' \
+ '--help[Prints a short help text and exits.]' \
+ '*::files:_files'
diff --git a/shell-completion/zsh/_timedatectl b/shell-completion/zsh/_timedatectl
new file mode 100644
index 0000000000..987c2de88d
--- /dev/null
+++ b/shell-completion/zsh/_timedatectl
@@ -0,0 +1,65 @@
+#compdef timedatectl
+
+_timedatectl_set-timezone(){
+ local -a _timezones
+ _timezones=( ${(f)"$(_call_program timezones "${service}" list-timezones)"} )
+ compadd "$_timezones[@]"
+}
+
+_timedatectl_set-time(){
+ _message "YYYY-MM-DD HH:MM:SS"
+}
+
+_timedatectl_set-local-rtc(){
+ local -a _options
+ _options=(
+ '0:Maintain RTC in universal time'
+ '1:Maintain RTC in local time'
+ )
+ _describe options _options
+}
+
+_timedatectl_set-ntp(){
+ local -a _options
+ _options=(
+ '0:Disable NTP based network time configuration'
+ '1:Enable NTP based network time configuration'
+ )
+ _describe options _options
+}
+
+_timedatectl_command(){
+ local -a _timedatectl_cmds
+ _timedatectl_cmds=(
+ 'status:Show current time settings'
+ 'set-time:Set system time'
+ 'set-timezone:Set system timezone'
+ 'list-timezones:Show known timezones'
+ 'set-local-rtc:Control whether RTC is in local time'
+ 'set-ntp:Control whether NTP is enabled'
+ )
+ if (( CURRENT == 1 )); then
+ _describe -t commands 'timedatectl command' _timedatectl_cmds
+ else
+ local curcontext="$curcontext"
+ cmd="${${_timedatectl_cmds[(r)$words[1]:*]%%:*}}"
+ if (( $#cmd )); then
+ if (( $+functions[_timedatectl_$cmd] )); then
+ _timedatectl_$cmd
+ else
+ _message "no more options"
+ fi
+ else
+ _message "unknown timedatectl command: $words[1]"
+ fi
+ fi
+}
+
+_arguments -s \
+ {-h,--help}'[Show this help]' \
+ '--version[Show package version]' \
+ '--adjust-system-clock[Adjust system clock when changing local RTC mode]' \
+ '--no-pager[Do not pipe output into a pager]' \
+ '--no-ask-password[Do not prompt for password]' \
+ {-H+,--host=}'[Operate on remote host]:userathost:_sd_hosts_or_user_at_host' \
+ '*::timedatectl commands:_timedatectl_command'
diff --git a/shell-completion/zsh/_udevadm b/shell-completion/zsh/_udevadm
new file mode 100644
index 0000000000..04e9f8dd8e
--- /dev/null
+++ b/shell-completion/zsh/_udevadm
@@ -0,0 +1,141 @@
+#compdef udevadm
+
+_udevadm_info(){
+ _arguments \
+ '--query=[Query the database for specified type of device data. It needs the --path or --name to identify the specified device.]:type:(name symlink path property all)' \
+ '--path=[The devpath of the device to query.]:sys files:_files -P /sys/ -W /sys' \
+ '--name=[The name of the device node or a symlink to query]:device files:_files -P /dev/ -W /dev' \
+ '--root[Print absolute paths in name or symlink query.]' \
+ '--attribute-walk[Print all sysfs properties of the specified device that can be used in udev rules to match the specified device]' \
+ '--export[Print output as key/value pairs.]' \
+ '--export-prefix=[Add a prefix to the key name of exported values.]:prefix' \
+ '--device-id-of-file=[Print major/minor numbers of the underlying device, where the file lives on.]:files:_udevadm_mounts' \
+ '--export-db[Export the content of the udev database.]' \
+ '--cleanup-db[Cleanup the udev database.]'
+}
+
+_udevadm_trigger(){
+ _arguments \
+ '--verbose[Print the list of devices which will be triggered.]' \
+ '--dry-run[Do not actually trigger the event.]' \
+ '--type=[Trigger a specific type of devices.]:types:(devices subsystems failed)' \
+ '--action=[Type of event to be triggered.]:actions:(add change remove)' \
+ '--subsystem-match=[Trigger events for devices which belong to a matching subsystem.]' \
+ '--subsystem-nomatch=[Do not trigger events for devices which belong to a matching subsystem.]' \
+ '--attr-match=attribute=[Trigger events for devices with a matching sysfs attribute.]' \
+ '--attr-nomatch=attribute=[Do not trigger events for devices with a matching sysfs attribute.]' \
+ '--property-match=[Trigger events for devices with a matching property value.]' \
+ '--tag-match=property[Trigger events for devices with a matching tag.]' \
+ '--sysname-match=[Trigger events for devices with a matching sys device name.]' \
+ '--parent-match=[Trigger events for all children of a given device.]'
+}
+
+_udevadm_settle(){
+ _arguments \
+ '--timeout=[Maximum number of seconds to wait for the event queue to become empty.]' \
+ '--seq-start=[Wait only for events after the given sequence number.]' \
+ '--seq-end=[Wait only for events before the given sequence number.]' \
+ '--exit-if-exists=[Stop waiting if file exists.]:files:_files' \
+ '--quiet[Do not print any output, like the remaining queue entries when reaching the timeout.]' \
+ '--help[Print help text.]'
+}
+
+_udevadm_control(){
+ _arguments \
+ '--exit[Signal and wait for systemd-udevd to exit.]' \
+ '--log-priority=[Set the internal log level of systemd-udevd.]:priorities:(err info debug)' \
+ '--stop-exec-queue[Signal systemd-udevd to stop executing new events. Incoming events will be queued.]' \
+ '--start-exec-queue[Signal systemd-udevd to enable the execution of events.]' \
+ '--reload[Signal systemd-udevd to reload the rules files and other databases like the kernel module index.]' \
+ '--property=[Set a global property for all events.]' \
+ '--children-max=[Set the maximum number of events.]' \
+ '--timeout=[The maximum number of seconds to wait for a reply from systemd-udevd.]' \
+ '--help[Print help text.]'
+}
+
+_udevadm_monitor(){
+ _arguments \
+ '--kernel[Print the kernel uevents.]' \
+ '--udev[Print the udev event after the rule processing.]' \
+ '--property[Also print the properties of the event.]' \
+ '--subsystem-match=[Filter events by subsystem/\[devtype\].]' \
+ '--tag-match=[Filter events by property.]' \
+ '--help[Print help text.]'
+}
+
+_udevadm_test(){
+ _arguments \
+ '--action=[The action string.]:actions:(add change remove)' \
+ '--subsystem=[The subsystem string.]' \
+ '--help[Print help text.]' \
+ '*::devpath:_files -P /sys/ -W /sys'
+}
+
+_udevadm_test-builtin(){
+ if (( CURRENT == 2 )); then
+ _arguments \
+ '--help[Print help text]' \
+ '*::builtins:(blkid btrfs hwdb input_id kmod path_id usb_id uaccess)'
+ elif (( CURRENT == 3 )); then
+ _arguments \
+ '--help[Print help text]' \
+ '*::syspath:_files -P /sys -W /sys'
+ else
+ _arguments \
+ '--help[Print help text]'
+ fi
+}
+
+_udevadm_mounts(){
+ local dev_tmp dpath_tmp mp_tmp mline
+
+ tmp=( "${(@f)$(< /etc/mtab)}" )
+ dev_tmp=( "${(@)${(@)tmp%% *}:#none}" )
+ mp_tmp=( "${(@)${(@)tmp#* }%% *}" )
+
+ local MATCH
+ mp_tmp=("${(@q)mp_tmp//(#m)\\[0-7](#c3)/${(#)$(( 8#${MATCH[2,-1]} ))}}")
+ dpath_tmp=( "${(@Mq)dev_tmp:#/*}" )
+ dev_tmp=( "${(@q)dev_tmp:#/*}" )
+
+ _alternative \
+ 'device-paths: device path:compadd -a dpath_tmp' \
+ 'directories:mount point:compadd -a mp_tmp'
+}
+
+
+_udevadm_command(){
+ local -a _udevadm_cmds
+ _udevadm_cmds=(
+ 'info:query sysfs or the udev database'
+ 'trigger:request events from the kernel'
+ 'settle:wait for the event queue to finish'
+ 'control:control the udev daemon'
+ 'monitor:listen to kernel and udev events'
+ 'test:test an event run'
+ 'test-builtin:test a built-in command'
+ )
+
+ if ((CURRENT == 1)); then
+ _describe -t commands 'udevadm commands' _udevadm_cmds
+ else
+ local curcontext="$curcontext"
+ cmd="${${_udevadm_cmds[(r)$words[1]:*]%%:*}}"
+ if (($#cmd)); then
+ if (( $+functions[_udevadm_$cmd] )); then
+ _udevadm_$cmd
+ else
+ _message "no options for $cmd"
+ fi
+ else
+ _message "no more options"
+ fi
+ fi
+}
+
+
+_arguments \
+ '--debug[Print debug messages to stderr]' \
+ '--version[Print version number]' \
+ '--help[Print help text]' \
+ '*::udevadm commands:_udevadm_command'
diff --git a/src/.gitignore b/src/.gitignore
index afabb6a5d2..e6ac2d7b8a 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -4,3 +4,5 @@ load-fragment-gperf.gperf
org.freedesktop.systemd1.policy.in
org.freedesktop.systemd1.policy
99-systemd.rules
+*.gcno
+*.gcda
diff --git a/src/activate/activate.c b/src/activate/activate.c
index 87526d47cc..83d25b13af 100644
--- a/src/activate/activate.c
+++ b/src/activate/activate.c
@@ -290,16 +290,15 @@ static int do_accept(const char* name, char **argv, char **envp, int fd) {
}
/* SIGCHLD handler. */
-static void sigchld_hdl(int sig, siginfo_t *t, void *data)
-{
+static void sigchld_hdl(int sig, siginfo_t *t, void *data) {
log_info("Child %d died with code %d", t->si_pid, t->si_status);
- /* Wait for a dead child. */
- waitpid(t->si_pid, NULL, 0);
+ /* Wait for a dead child. */
+ waitpid(t->si_pid, NULL, 0);
}
static int install_chld_handler(void) {
int r;
- struct sigaction act;
+ struct sigaction act;
zero(act);
act.sa_flags = SA_SIGINFO;
act.sa_sigaction = sigchld_hdl;
diff --git a/src/analyze/systemd-analyze.c b/src/analyze/systemd-analyze.c
index bb86ec7da8..27d063c548 100644
--- a/src/analyze/systemd-analyze.c
+++ b/src/analyze/systemd-analyze.c
@@ -38,6 +38,7 @@
#include "unit-name.h"
#include "special.h"
#include "hashmap.h"
+#include "pager.h"
#define SCALE_X (0.1 / 1000.0) /* pixels per us */
#define SCALE_Y 20.0
@@ -67,8 +68,8 @@ static enum dot {
} arg_dot = DEP_ALL;
static char** arg_dot_from_patterns = NULL;
static char** arg_dot_to_patterns = NULL;
-
-usec_t arg_fuzz = 0;
+static usec_t arg_fuzz = 0;
+static bool arg_no_pager = false;
struct boot_times {
usec_t firmware_time;
@@ -78,7 +79,12 @@ struct boot_times {
usec_t initrd_time;
usec_t userspace_time;
usec_t finish_time;
+ usec_t generators_start_time;
+ usec_t generators_finish_time;
+ usec_t unitsload_start_time;
+ usec_t unitsload_finish_time;
};
+
struct unit_times {
char *name;
usec_t ixt;
@@ -88,6 +94,14 @@ struct unit_times {
usec_t time;
};
+static void pager_open_if_enabled(void) {
+
+ if (arg_no_pager)
+ return;
+
+ pager_open(false);
+}
+
static int bus_get_uint64_property(DBusConnection *bus, const char *path, const char *interface, const char *property, uint64_t *val) {
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
DBusMessageIter iter, sub;
@@ -303,7 +317,27 @@ static int acquire_boot_times(DBusConnection *bus, struct boot_times **bt) {
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"FinishTimestampMonotonic",
- &times.finish_time) < 0)
+ &times.finish_time) < 0 ||
+ bus_get_uint64_property(bus,
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "GeneratorsStartTimestampMonotonic",
+ &times.generators_start_time) < 0 ||
+ bus_get_uint64_property(bus,
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "GeneratorsFinishTimestampMonotonic",
+ &times.generators_finish_time) < 0 ||
+ bus_get_uint64_property(bus,
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "UnitsLoadStartTimestampMonotonic",
+ &times.unitsload_start_time) < 0 ||
+ bus_get_uint64_property(bus,
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "UnitsLoadFinishTimestampMonotonic",
+ &times.unitsload_finish_time) < 0)
return -EIO;
if (times.finish_time <= 0) {
@@ -459,7 +493,8 @@ static int analyze_plot(DBusConnection *bus) {
svg("<svg width=\"%.0fpx\" height=\"%.0fpx\" version=\"1.1\" "
"xmlns=\"http://www.w3.org/2000/svg\">\n\n",
- 80.0 + width, 150.0 + (m * SCALE_Y));
+ 80.0 + width, 150.0 + (m * SCALE_Y) +
+ 5 * SCALE_Y /* legend */);
/* write some basic info as a comment, including some help */
svg("<!-- This file is a systemd-analyze SVG file. It is best rendered in a -->\n"
@@ -480,23 +515,23 @@ static int analyze_plot(DBusConnection *bus) {
" rect.firmware { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"
" rect.loader { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"
" rect.userspace { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"
+ " rect.generators { fill: rgb(102,204,255); fill-opacity: 0.7; }\n"
+ " rect.unitsload { fill: rgb( 82,184,255); fill-opacity: 0.7; }\n"
" rect.box { fill: rgb(240,240,240); stroke: rgb(192,192,192); }\n"
" line { stroke: rgb(64,64,64); stroke-width: 1; }\n"
"// line.sec1 { }\n"
" line.sec5 { stroke-width: 2; }\n"
" line.sec01 { stroke: rgb(224,224,224); stroke-width: 1; }\n"
- " text { font-family: Verdana, Helvetica; font-size: 10; }\n"
- " text.left { font-family: Verdana, Helvetica; font-size: 10; text-anchor: start; }\n"
- " text.right { font-family: Verdana, Helvetica; font-size: 10; text-anchor: end; }\n"
- " text.sec { font-size: 8; }\n"
+ " text { font-family: Verdana, Helvetica; font-size: 14px; }\n"
+ " text.left { font-family: Verdana, Helvetica; font-size: 14px; text-anchor: start; }\n"
+ " text.right { font-family: Verdana, Helvetica; font-size: 14px; text-anchor: end; }\n"
+ " text.sec { font-size: 10px; }\n"
" ]]>\n </style>\n</defs>\n\n");
svg("<text x=\"20\" y=\"50\">%s</text>", pretty_times);
svg("<text x=\"20\" y=\"30\">%s %s (%s %s) %s</text>",
isempty(osname) ? "Linux" : osname,
name.nodename, name.release, name.version, name.machine);
- svg("<text x=\"20\" y=\"%.0f\">Legend: Red = Activating; Pink = Active; Dark Pink = Deactivating</text>",
- 120.0 + (m *SCALE_Y));
svg("<g transform=\"translate(%.3f,100)\">\n", 20.0 + (SCALE_X * boot->firmware_time));
svg_graph_box(m, -boot->firmware_time, boot->finish_time);
@@ -521,8 +556,10 @@ static int analyze_plot(DBusConnection *bus) {
svg_text(true, boot->initrd_time, y, "initrd");
y++;
}
- svg_bar("userspace", boot->userspace_time, boot->finish_time, y);
- svg_text("left", boot->userspace_time, y, "userspace");
+ svg_bar("active", boot->userspace_time, boot->finish_time, y);
+ svg_bar("generators", boot->generators_start_time, boot->generators_finish_time, y);
+ svg_bar("unitsload", boot->unitsload_start_time, boot->unitsload_finish_time, y);
+ svg_text("left", boot->userspace_time, y, "systemd");
y++;
for (u = times; u < times + n; u++) {
@@ -544,6 +581,25 @@ static int analyze_plot(DBusConnection *bus) {
svg_text(b, u->ixt, y, "%s", u->name);
y++;
}
+
+ /* Legend */
+ y++;
+ svg_bar("activating", 0, 300000, y);
+ svg_text("right", 400000, y, "Activating");
+ y++;
+ svg_bar("active", 0, 300000, y);
+ svg_text("right", 400000, y, "Active");
+ y++;
+ svg_bar("deactivating", 0, 300000, y);
+ svg_text("right", 400000, y, "Deactivating");
+ y++;
+ svg_bar("generators", 0, 300000, y);
+ svg_text("right", 400000, y, "Generators");
+ y++;
+ svg_bar("unitsload", 0, 300000, y);
+ svg_text("right", 400000, y, "Loading unit files");
+ y++;
+
svg("</g>\n\n");
svg("</svg>");
@@ -553,7 +609,6 @@ static int analyze_plot(DBusConnection *bus) {
return 0;
}
-
static int list_dependencies_print(const char *name, unsigned int level, unsigned int branches,
bool last, struct unit_times *times, struct boot_times *boot) {
unsigned int i;
@@ -779,7 +834,7 @@ static int list_dependencies_one(DBusConnection *bus, const char *name, unsigned
return 0;
}
-static int list_dependencies(DBusConnection *bus) {
+static int list_dependencies(DBusConnection *bus, const char *name) {
_cleanup_strv_free_ char **units = NULL;
char ts[FORMAT_TIMESPAN_MAX];
struct unit_times *times;
@@ -794,7 +849,7 @@ static int list_dependencies(DBusConnection *bus) {
assert(bus);
- path = unit_dbus_path_from_name(SPECIAL_DEFAULT_TARGET);
+ path = unit_dbus_path_from_name(name);
if (path == NULL)
return -EINVAL;
@@ -843,10 +898,10 @@ static int list_dependencies(DBusConnection *bus) {
printf("%s\n", id);
}
- return list_dependencies_one(bus, SPECIAL_DEFAULT_TARGET, 0, &units, 0);
+ return list_dependencies_one(bus, name, 0, &units, 0);
}
-static int analyze_critical_chain(DBusConnection *bus) {
+static int analyze_critical_chain(DBusConnection *bus, char *names[]) {
struct unit_times *times;
int n, r;
unsigned int i;
@@ -867,10 +922,17 @@ static int analyze_critical_chain(DBusConnection *bus) {
}
unit_times_hashmap = h;
+ pager_open_if_enabled();
+
puts("The time after the unit is active or started is printed after the \"@\" character.\n"
"The time the unit takes to start is printed after the \"+\" character.\n");
- list_dependencies(bus);
+ if (!strv_isempty(names)) {
+ char **name;
+ STRV_FOREACH(name, names)
+ list_dependencies(bus, *name);
+ } else
+ list_dependencies(bus, SPECIAL_DEFAULT_TARGET);
hashmap_free(h);
free_unit_times(times, (unsigned) n);
@@ -888,6 +950,8 @@ static int analyze_blame(DBusConnection *bus) {
qsort(times, n, sizeof(struct unit_times), compare_unit_time);
+ pager_open_if_enabled();
+
for (i = 0; i < (unsigned) n; i++) {
char ts[FORMAT_TIMESPAN_MAX];
@@ -1112,8 +1176,97 @@ static int dot(DBusConnection *bus, char* patterns[]) {
return 0;
}
-static void analyze_help(void)
-{
+static int dump(DBusConnection *bus, char **args) {
+ _cleanup_free_ DBusMessage *reply = NULL;
+ DBusError error;
+ int r;
+ const char *text;
+
+ dbus_error_init(&error);
+
+ if (!strv_isempty(args)) {
+ log_error("Too many arguments.");
+ return -E2BIG;
+ }
+
+ pager_open_if_enabled();
+
+ r = bus_method_call_with_reply(
+ bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "Dump",
+ &reply,
+ NULL,
+ DBUS_TYPE_INVALID);
+ if (r < 0)
+ return r;
+
+ if (!dbus_message_get_args(reply, &error,
+ DBUS_TYPE_STRING, &text,
+ DBUS_TYPE_INVALID)) {
+ log_error("Failed to parse reply: %s", bus_error_message(&error));
+ dbus_error_free(&error);
+ return -EIO;
+ }
+
+ fputs(text, stdout);
+ return 0;
+}
+
+static int set_log_level(DBusConnection *bus, char **args) {
+ _cleanup_dbus_error_free_ DBusError error;
+ _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
+ DBusMessageIter iter, sub;
+ const char* property = "LogLevel";
+ const char* interface = "org.freedesktop.systemd1.Manager";
+ const char* value;
+
+ assert(bus);
+ assert(args);
+
+ if (strv_length(args) != 1) {
+ log_error("This command expects one argument only.");
+ return -E2BIG;
+ }
+
+ value = args[0];
+ dbus_error_init(&error);
+
+ m = dbus_message_new_method_call("org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.DBus.Properties",
+ "Set");
+ if (!m)
+ return log_oom();
+
+ dbus_message_iter_init_append(m, &iter);
+
+ if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface) ||
+ !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property) ||
+ !dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, "s", &sub))
+ return log_oom();
+
+ if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &value))
+ return log_oom();
+
+ if (!dbus_message_iter_close_container(&iter, &sub))
+ return log_oom();
+
+ reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
+ if (!reply) {
+ log_error("Failed to issue method call: %s", bus_error_message(&error));
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static void analyze_help(void) {
+
+ pager_open_if_enabled();
+
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
"Process systemd profiling information\n\n"
" -h --help Show this help\n"
@@ -1128,13 +1281,16 @@ static void analyze_help(void)
" --fuzz=TIMESPAN When printing the tree of the critical chain, print also\n"
" services, which finished TIMESPAN earlier, than the\n"
" latest in the branch. The unit of TIMESPAN is seconds\n"
- " unless specified with a different unit, i.e. 50ms\n\n"
+ " unless specified with a different unit, i.e. 50ms\n"
+ " --no-pager Do not pipe output into a pager\n\n"
"Commands:\n"
" time Print time spent in the kernel before reaching userspace\n"
" blame Print list of running units ordered by time to init\n"
" critical-chain Print a tree of the time critical chain of units\n"
" plot Output SVG graphic showing service initialization\n"
- " dot Dump dependency graph (in dot(1) format)\n\n",
+ " dot Output dependency graph in dot(1) format\n"
+ " set-log-level LEVEL Set logging threshold for systemd\n"
+ " dump Output state serialization of service manager\n",
program_invocation_short_name);
/* When updating this list, including descriptions, apply
@@ -1142,8 +1298,7 @@ static void analyze_help(void)
* shell-completion/systemd-zsh-completion.zsh too. */
}
-static int parse_argv(int argc, char *argv[])
-{
+static int parse_argv(int argc, char *argv[]) {
int r;
enum {
@@ -1154,20 +1309,22 @@ static int parse_argv(int argc, char *argv[])
ARG_SYSTEM,
ARG_DOT_FROM_PATTERN,
ARG_DOT_TO_PATTERN,
- ARG_FUZZ
+ ARG_FUZZ,
+ ARG_NO_PAGER
};
static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "order", no_argument, NULL, ARG_ORDER },
- { "require", no_argument, NULL, ARG_REQUIRE },
- { "user", no_argument, NULL, ARG_USER },
- { "system", no_argument, NULL, ARG_SYSTEM },
- { "from-pattern", required_argument, NULL, ARG_DOT_FROM_PATTERN},
- { "to-pattern", required_argument, NULL, ARG_DOT_TO_PATTERN },
- { "fuzz", required_argument, NULL, ARG_FUZZ },
- { NULL, 0, NULL, 0 }
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "order", no_argument, NULL, ARG_ORDER },
+ { "require", no_argument, NULL, ARG_REQUIRE },
+ { "user", no_argument, NULL, ARG_USER },
+ { "system", no_argument, NULL, ARG_SYSTEM },
+ { "from-pattern", required_argument, NULL, ARG_DOT_FROM_PATTERN },
+ { "to-pattern", required_argument, NULL, ARG_DOT_TO_PATTERN },
+ { "fuzz", required_argument, NULL, ARG_FUZZ },
+ { "no-pager", no_argument, NULL, ARG_NO_PAGER },
+ { NULL, 0, NULL, 0 }
};
assert(argc >= 0);
@@ -1218,6 +1375,10 @@ static int parse_argv(int argc, char *argv[])
return r;
break;
+ case ARG_NO_PAGER:
+ arg_no_pager = true;
+ break;
+
case -1:
return 1;
@@ -1240,31 +1401,39 @@ int main(int argc, char *argv[]) {
log_open();
r = parse_argv(argc, argv);
- if (r < 0)
- return EXIT_FAILURE;
- else if (r <= 0)
- return EXIT_SUCCESS;
+ if (r <= 0)
+ goto finish;
bus = dbus_bus_get(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, NULL);
- if (!bus)
- return EXIT_FAILURE;
+ if (!bus) {
+ r = -EIO;
+ goto finish;
+ }
if (!argv[optind] || streq(argv[optind], "time"))
r = analyze_time(bus);
else if (streq(argv[optind], "blame"))
r = analyze_blame(bus);
else if (streq(argv[optind], "critical-chain"))
- r = analyze_critical_chain(bus);
+ r = analyze_critical_chain(bus, argv+optind+1);
else if (streq(argv[optind], "plot"))
r = analyze_plot(bus);
else if (streq(argv[optind], "dot"))
r = dot(bus, argv+optind+1);
+ else if (streq(argv[optind], "dump"))
+ r = dump(bus, argv+optind+1);
+ else if (streq(argv[optind], "set-log-level"))
+ r = set_log_level(bus, argv+optind+1);
else
log_error("Unknown operation '%s'.", argv[optind]);
+ dbus_connection_unref(bus);
+
+finish:
+ pager_close();
+
strv_free(arg_dot_from_patterns);
strv_free(arg_dot_to_patterns);
- dbus_connection_unref(bus);
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/timestamp/Makefile b/src/backlight/Makefile
index d0b0e8e008..d0b0e8e008 120000
--- a/src/timestamp/Makefile
+++ b/src/backlight/Makefile
diff --git a/src/backlight/backlight.c b/src/backlight/backlight.c
new file mode 100644
index 0000000000..9b2eada397
--- /dev/null
+++ b/src/backlight/backlight.c
@@ -0,0 +1,132 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ 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 <libudev.h>
+
+#include "util.h"
+#include "mkdir.h"
+#include "fileio.h"
+
+int main(int argc, char *argv[]) {
+ struct udev *udev = NULL;
+ struct udev_device *device = NULL;
+ _cleanup_free_ char *saved = NULL;
+ int r;
+
+ if (argc != 3) {
+ log_error("This program requires two arguments.");
+ return EXIT_FAILURE;
+ }
+
+ log_set_target(LOG_TARGET_AUTO);
+ log_parse_environment();
+ log_open();
+
+ umask(0022);
+
+ r = mkdir_p("/var/lib/systemd/backlight", 0755);
+ if (r < 0) {
+ log_error("Failed to create backlight directory: %s", strerror(-r));
+ goto finish;
+ }
+
+ udev = udev_new();
+ if (!udev) {
+ r = log_oom();
+ goto finish;
+ }
+
+ errno = 0;
+ device = udev_device_new_from_subsystem_sysname(udev, "backlight", argv[2]);
+ if (!device) {
+ if (errno != 0) {
+ log_error("Failed to get backlight device: %m");
+ r = -errno;
+ } else
+ r = log_oom();
+
+ goto finish;
+ }
+
+ if (!streq_ptr(udev_device_get_subsystem(device), "backlight")) {
+ log_error("Not a backlight device: %s", argv[2]);
+ r = -ENODEV;
+ goto finish;
+ }
+
+ saved = strappend("/var/lib/systemd/backlight/", udev_device_get_sysname(device));
+ if (!saved) {
+ r = log_oom();
+ goto finish;
+ }
+
+ if (streq(argv[1], "load")) {
+ _cleanup_free_ char *value = NULL;
+
+ r = read_one_line_file(saved, &value);
+ if (r < 0) {
+
+ if (r == -ENOENT) {
+ r = 0;
+ goto finish;
+ }
+
+ log_error("Failed to read %s: %s", saved, strerror(-r));
+ goto finish;
+ }
+
+ r = udev_device_set_sysattr_value(device, "brightness", value);
+ if (r < 0) {
+ log_error("Failed to write system attribute: %s", strerror(-r));
+ goto finish;
+ }
+
+ } else if (streq(argv[1], "save")) {
+ const char *value;
+
+ value = udev_device_get_sysattr_value(device, "brightness");
+ if (!value) {
+ log_error("Failed to read system attribute: %s", strerror(-r));
+ goto finish;
+ }
+
+ r = write_string_file(saved, value);
+ if (r < 0) {
+ log_error("Failed to write %s: %s", saved, strerror(-r));
+ goto finish;
+ }
+
+ } else {
+ log_error("Unknown verb %s.", argv[1]);
+ r = -EINVAL;
+ goto finish;
+ }
+
+finish:
+ if (device)
+ udev_device_unref(device);
+
+ if (udev)
+ udev_unref(udev);
+
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+
+}
diff --git a/src/boot/boot-efi.c b/src/boot/boot-efi.c
index 9960c4d742..33840b6864 100644
--- a/src/boot/boot-efi.c
+++ b/src/boot/boot-efi.c
@@ -174,7 +174,7 @@ int boot_info_query(struct boot_info *info) {
efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderFirmwareInfo", &info->fw_info);
efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderImageIdentifier", &info->loader_image_path);
tilt_slashes(info->loader_image_path);
- efi_get_loader_device_part_uuid(&info->loader_part_uuid);
+ efi_loader_get_device_part_uuid(&info->loader_part_uuid);
boot_loader_read_entries(info);
efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntrySelected", &loader_active);
diff --git a/src/bootchart/bootchart.c b/src/bootchart/bootchart.c
index 8be5a27afa..14ccd3efe5 100644
--- a/src/bootchart/bootchart.c
+++ b/src/bootchart/bootchart.c
@@ -3,7 +3,7 @@
/***
This file is part of systemd.
- Copyright (C) 2009-2013 Intel Coproration
+ Copyright (C) 2009-2013 Intel Corporation
Authors:
Auke Kok <auke-jan.h.kok@intel.com>
diff --git a/src/bootchart/bootchart.h b/src/bootchart/bootchart.h
index d0273421de..968c38da26 100644
--- a/src/bootchart/bootchart.h
+++ b/src/bootchart/bootchart.h
@@ -5,7 +5,7 @@
/***
This file is part of systemd.
- Copyright (C) 2009-2013 Intel Coproration
+ Copyright (C) 2009-2013 Intel Corporation
Authors:
Auke Kok <auke-jan.h.kok@intel.com>
diff --git a/src/bootchart/store.c b/src/bootchart/store.c
index b2afb8d13b..f8c97c2324 100755..100644
--- a/src/bootchart/store.c
+++ b/src/bootchart/store.c
@@ -3,7 +3,7 @@
/***
This file is part of systemd.
- Copyright (C) 2009-2013 Intel Coproration
+ Copyright (C) 2009-2013 Intel Corporation
Authors:
Auke Kok <auke-jan.h.kok@intel.com>
diff --git a/src/bootchart/store.h b/src/bootchart/store.h
index 7c8ad284da..f211b6f53b 100644
--- a/src/bootchart/store.h
+++ b/src/bootchart/store.h
@@ -5,7 +5,7 @@
/***
This file is part of systemd.
- Copyright (C) 2009-2013 Intel Coproration
+ Copyright (C) 2009-2013 Intel Corporation
Authors:
Auke Kok <auke-jan.h.kok@intel.com>
diff --git a/src/bootchart/svg.c b/src/bootchart/svg.c
index 859cf81c22..5eee2d1987 100644
--- a/src/bootchart/svg.c
+++ b/src/bootchart/svg.c
@@ -3,7 +3,7 @@
/***
This file is part of systemd.
- Copyright (C) 2009-2013 Intel Coproration
+ Copyright (C) 2009-2013 Intel Corporation
Authors:
Auke Kok <auke-jan.h.kok@intel.com>
diff --git a/src/bootchart/svg.h b/src/bootchart/svg.h
index e7369f5111..df3a7bf8ef 100644
--- a/src/bootchart/svg.h
+++ b/src/bootchart/svg.h
@@ -5,7 +5,7 @@
/***
This file is part of systemd.
- Copyright (C) 2009-2013 Intel Coproration
+ Copyright (C) 2009-2013 Intel Corporation
Authors:
Auke Kok <auke-jan.h.kok@intel.com>
diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c
index ef3e5672ab..c689b5c471 100644
--- a/src/cgls/cgls.c
+++ b/src/cgls/cgls.c
@@ -34,6 +34,7 @@
#include "pager.h"
#include "build.h"
#include "output-mode.h"
+#include "fileio.h"
static bool arg_no_pager = false;
static bool arg_kernel_threads = false;
@@ -49,7 +50,7 @@ static void help(void) {
" --version Show package version\n"
" --no-pager Do not pipe output into a pager\n"
" -a --all Show all groups, including empty\n"
- " --full Do not ellipsize output\n"
+ " -l --full Do not ellipsize output\n"
" -k Include kernel threads in output\n"
" -M --machine Show container\n",
program_invocation_short_name);
@@ -60,7 +61,6 @@ static int parse_argv(int argc, char *argv[]) {
enum {
ARG_NO_PAGER = 0x100,
ARG_VERSION,
- ARG_FULL,
};
static const struct option options[] = {
@@ -68,7 +68,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "version", no_argument, NULL, ARG_VERSION },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
{ "all", no_argument, NULL, 'a' },
- { "full", no_argument, NULL, ARG_FULL },
+ { "full", no_argument, NULL, 'l' },
{ "machine", required_argument, NULL, 'M' },
{ NULL, 0, NULL, 0 }
};
@@ -78,7 +78,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 1);
assert(argv);
- while ((c = getopt_long(argc, argv, "hkaM:", options, NULL)) >= 0) {
+ while ((c = getopt_long(argc, argv, "hkalM:", options, NULL)) >= 0) {
switch (c) {
@@ -99,7 +99,7 @@ static int parse_argv(int argc, char *argv[]) {
arg_all = true;
break;
- case ARG_FULL:
+ case 'l':
arg_full = true;
break;
@@ -156,7 +156,9 @@ int main(int argc, char *argv[]) {
for (i = optind; i < argc; i++) {
int q;
- printf("%s:\n", argv[i]);
+
+ fprintf(stdout, "%s:\n", argv[i]);
+ fflush(stdout);
if (arg_machine)
root = strjoin("machine/", arg_machine, "/", argv[i], NULL);
@@ -185,9 +187,11 @@ int main(int argc, char *argv[]) {
r = show_cgroup_by_path(p, NULL, 0,
arg_kernel_threads, output_flags);
} else {
- if (arg_machine)
- r = cg_get_machine_path(arg_machine, &root);
- else
+ if (arg_machine) {
+ char *m;
+ m = strappenda("/run/systemd/machines/", arg_machine);
+ r = parse_env_file(m, NEWLINE, "CGROUP", &root, NULL);
+ } else
r = cg_get_root_path(&root);
if (r < 0) {
log_error("Failed to get %s path: %s",
diff --git a/src/cgroups-agent/cgroups-agent.c b/src/cgroups-agent/cgroups-agent.c
index 7a6173e2a2..a47949a180 100644
--- a/src/cgroups-agent/cgroups-agent.c
+++ b/src/cgroups-agent/cgroups-agent.c
@@ -48,26 +48,19 @@ int main(int argc, char *argv[]) {
* this to avoid an activation loop when we start dbus when we
* are called when the dbus service is shut down. */
- if (!(bus = dbus_connection_open_private("unix:path=/run/systemd/private", &error))) {
-#ifndef LEGACY
- dbus_error_free(&error);
-
- /* Retry with the pre v21 socket name, to ease upgrades */
- if (!(bus = dbus_connection_open_private("unix:abstract=/org/freedesktop/systemd1/private", &error))) {
-#endif
- log_error("Failed to get D-Bus connection: %s", bus_error_message(&error));
- goto finish;
- }
-#ifndef LEGACY
+ bus = dbus_connection_open_private("unix:path=/run/systemd/private", &error);
+ if (!bus) {
+ log_warning("Failed to get D-Bus connection: %s", bus_error_message(&error));
+ goto finish;
}
-#endif
if (bus_check_peercred(bus) < 0) {
log_error("Bus owner not root.");
goto finish;
}
- if (!(m = dbus_message_new_signal("/org/freedesktop/systemd1/agent", "org.freedesktop.systemd1.Agent", "Released"))) {
+ m = dbus_message_new_signal("/org/freedesktop/systemd1/agent", "org.freedesktop.systemd1.Agent", "Released");
+ if (!m) {
log_error("Could not allocate signal message.");
goto finish;
}
diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c
index 1e21b0074d..cacf705a0a 100644
--- a/src/cgtop/cgtop.c
+++ b/src/cgtop/cgtop.c
@@ -134,7 +134,7 @@ static int process(const char *controller, const char *path, Hashmap *a, Hashmap
/* Regardless which controller, let's find the maximum number
* of processes in any of it */
- r = cg_enumerate_tasks(controller, path, &f);
+ r = cg_enumerate_processes(controller, path, &f);
if (r < 0)
return r;
@@ -824,9 +824,9 @@ int main(int argc, char *argv[]) {
case '?':
case 'h':
fprintf(stdout,
- "\t<" ON "P" OFF "> By path; <" ON "T" OFF "> By tasks; <" ON "C" OFF "> By CPU; <" ON "M" OFF "> By memory; <" ON "I" OFF "> By I/O\n"
+ "\t<" ON "p" OFF "> By path; <" ON "t" OFF "> By tasks; <" ON "c" OFF "> By CPU; <" ON "m" OFF "> By memory; <" ON "i" OFF "> By I/O\n"
"\t<" ON "+" OFF "> Increase delay; <" ON "-" OFF "> Decrease delay; <" ON "%%" OFF "> Toggle time\n"
- "\t<" ON "Q" OFF "> Quit; <" ON "SPACE" OFF "> Refresh");
+ "\t<" ON "q" OFF "> Quit; <" ON "SPACE" OFF "> Refresh");
fflush(stdout);
sleep(3);
break;
diff --git a/src/core/sync.c b/src/core/async.c
index 7e74b63071..af527bea4e 100644
--- a/src/core/sync.c
+++ b/src/core/async.c
@@ -22,14 +22,10 @@
#include <pthread.h>
#include <unistd.h>
-#include "sync.h"
+#include "async.h"
+#include "log.h"
-static void *sync_thread(void *p) {
- sync();
- return NULL;
-}
-
-int asynchronous_sync(void) {
+int asynchronous_job(void* (*func)(void *p), void *arg) {
pthread_attr_t a;
pthread_t t;
int r;
@@ -53,7 +49,7 @@ int asynchronous_sync(void) {
goto finish;
}
- r = pthread_create(&t, &a, sync_thread, NULL);
+ r = pthread_create(&t, &a, func, arg);
if (r != 0) {
r = -r;
goto finish;
@@ -63,3 +59,14 @@ finish:
pthread_attr_destroy(&a);
return r;
}
+
+static void *sync_thread(void *p) {
+ sync();
+ return NULL;
+}
+
+int asynchronous_sync(void) {
+ log_debug("Spawning new thread for sync");
+
+ return asynchronous_job(sync_thread, NULL);
+}
diff --git a/src/core/sync.h b/src/core/async.h
index eb26c88deb..6601b4dc4b 100644
--- a/src/core/sync.h
+++ b/src/core/async.h
@@ -21,4 +21,5 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+int asynchronous_job(void* (*func)(void *p), void *arg);
int asynchronous_sync(void);
diff --git a/src/core/automount.c b/src/core/automount.c
index a20d5340f2..d1379e0913 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -66,7 +66,7 @@ static void automount_init(Unit *u) {
UNIT(a)->ignore_on_isolate = true;
}
-static void repeat_unmout(const char *path) {
+static void repeat_unmount(const char *path) {
assert(path);
for (;;) {
@@ -100,7 +100,7 @@ static void unmount_autofs(Automount *a) {
if (a->where &&
(UNIT(a)->manager->exit_code != MANAGER_RELOAD &&
UNIT(a)->manager->exit_code != MANAGER_REEXECUTE))
- repeat_unmout(a->where);
+ repeat_unmount(a->where);
}
static void automount_done(Unit *u) {
@@ -117,42 +117,17 @@ static void automount_done(Unit *u) {
a->tokens = NULL;
}
-int automount_add_one_mount_link(Automount *a, Mount *m) {
+static int automount_add_mount_links(Automount *a) {
+ _cleanup_free_ char *parent = NULL;
int r;
assert(a);
- assert(m);
-
- if (UNIT(a)->load_state != UNIT_LOADED ||
- UNIT(m)->load_state != UNIT_LOADED)
- return 0;
-
- if (!path_startswith(a->where, m->where))
- return 0;
- if (path_equal(a->where, m->where))
- return 0;
-
- r = unit_add_two_dependencies(UNIT(a), UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true);
+ r = path_get_parent(a->where, &parent);
if (r < 0)
return r;
- return 0;
-}
-
-static int automount_add_mount_links(Automount *a) {
- Unit *other;
- int r;
-
- assert(a);
-
- LIST_FOREACH(units_by_type, other, UNIT(a)->manager->units_by_type[UNIT_MOUNT]) {
- r = automount_add_one_mount_link(a, MOUNT(other));
- if (r < 0)
- return r;
- }
-
- return 0;
+ return unit_require_mounts_for(UNIT(a), parent);
}
static int automount_add_default_dependencies(Automount *a) {
@@ -575,7 +550,7 @@ fail:
close_nointr_nofail(ioctl_fd);
if (mounted)
- repeat_unmout(a->where);
+ repeat_unmount(a->where);
log_error_unit(UNIT(a)->id,
"Failed to initialize automounter: %s", strerror(-r));
diff --git a/src/core/automount.h b/src/core/automount.h
index 0c6b8a72e9..a7a25d34e0 100644
--- a/src/core/automount.h
+++ b/src/core/automount.h
@@ -62,8 +62,6 @@ extern const UnitVTable automount_vtable;
int automount_send_ready(Automount *a, int status);
-int automount_add_one_mount_link(Automount *a, Mount *m);
-
const char* automount_state_to_string(AutomountState i) _const_;
AutomountState automount_state_from_string(const char *s) _pure_;
diff --git a/src/core/bus-errors.h b/src/core/bus-errors.h
index 7a4084ea15..9368d68e80 100644
--- a/src/core/bus-errors.h
+++ b/src/core/bus-errors.h
@@ -40,3 +40,4 @@
#define BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC "org.freedesktop.systemd1.TransactionOrderIsCyclic"
#define BUS_ERROR_SHUTTING_DOWN "org.freedesktop.systemd1.ShuttingDown"
#define BUS_ERROR_NO_SUCH_PROCESS "org.freedesktop.systemd1.NoSuchProcess"
+#define BUS_ERROR_JOB_FAILED "org.freedesktop.systemd1.JobFailed"
diff --git a/src/core/cgroup-attr.c b/src/core/cgroup-attr.c
deleted file mode 100644
index 7e3e08eabb..0000000000
--- a/src/core/cgroup-attr.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "cgroup-attr.h"
-#include "cgroup-util.h"
-#include "list.h"
-#include "fileio.h"
-
-int cgroup_attribute_apply(CGroupAttribute *a, CGroupBonding *b) {
- _cleanup_free_ char *path = NULL, *v = NULL;
- int r;
-
- assert(a);
-
- b = cgroup_bonding_find_list(b, a->controller);
- if (!b)
- return 0;
-
- if (a->semantics && a->semantics->map_write) {
- r = a->semantics->map_write(a->semantics, a->value, &v);
- if (r < 0)
- return r;
- }
-
- r = cg_get_path(a->controller, b->path, a->name, &path);
- if (r < 0)
- return r;
-
- r = write_string_file(path, v ? v : a->value);
- if (r < 0)
- log_warning("Failed to write '%s' to %s: %s", v ? v : a->value, path, strerror(-r));
-
- return r;
-}
-
-int cgroup_attribute_apply_list(CGroupAttribute *first, CGroupBonding *b) {
- CGroupAttribute *a;
- int r = 0;
-
- LIST_FOREACH(by_unit, a, first) {
- int k;
-
- k = cgroup_attribute_apply(a, b);
- if (r == 0)
- r = k;
- }
-
- return r;
-}
-
-bool cgroup_attribute_matches(CGroupAttribute *a, const char *controller, const char *name) {
- assert(a);
-
- if (controller) {
- if (streq(a->controller, controller) && (!name || streq(a->name, name)))
- return true;
-
- } else if (!name)
- return true;
- else if (streq(a->name, name)) {
- size_t x, y;
- x = strlen(a->controller);
- y = strlen(name);
-
- if (y > x &&
- memcmp(a->controller, name, x) == 0 &&
- name[x] == '.')
- return true;
- }
-
- return false;
-}
-
-CGroupAttribute *cgroup_attribute_find_list(
- CGroupAttribute *first,
- const char *controller,
- const char *name) {
- CGroupAttribute *a;
-
- assert(name);
-
- LIST_FOREACH(by_unit, a, first)
- if (cgroup_attribute_matches(a, controller, name))
- return a;
-
- return NULL;
-}
-
-void cgroup_attribute_free(CGroupAttribute *a) {
- assert(a);
-
- if (a->unit)
- LIST_REMOVE(CGroupAttribute, by_unit, a->unit->cgroup_attributes, a);
-
- free(a->controller);
- free(a->name);
- free(a->value);
- free(a);
-}
-
-void cgroup_attribute_free_list(CGroupAttribute *first) {
- CGroupAttribute *a, *n;
-
- LIST_FOREACH_SAFE(by_unit, a, n, first)
- cgroup_attribute_free(a);
-}
-
-void cgroup_attribute_free_some(CGroupAttribute *first, const char *controller, const char *name) {
- CGroupAttribute *a, *n;
-
- LIST_FOREACH_SAFE(by_unit, a, n, first)
- if (cgroup_attribute_matches(a, controller, name))
- cgroup_attribute_free(a);
-}
diff --git a/src/core/cgroup-attr.h b/src/core/cgroup-attr.h
deleted file mode 100644
index 3a13b7c92d..0000000000
--- a/src/core/cgroup-attr.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-typedef struct CGroupAttribute CGroupAttribute;
-
-#include "unit.h"
-#include "cgroup.h"
-#include "cgroup-semantics.h"
-
-struct CGroupAttribute {
- char *controller;
- char *name;
- char *value;
-
- Unit *unit;
-
- const CGroupSemantics *semantics;
-
- LIST_FIELDS(CGroupAttribute, by_unit);
-};
-
-int cgroup_attribute_apply(CGroupAttribute *a, CGroupBonding *b);
-int cgroup_attribute_apply_list(CGroupAttribute *first, CGroupBonding *b);
-
-bool cgroup_attribute_matches(CGroupAttribute *a, const char *controller, const char *name) _pure_;
-CGroupAttribute *cgroup_attribute_find_list(CGroupAttribute *first, const char *controller, const char *name) _pure_;
-
-void cgroup_attribute_free(CGroupAttribute *a);
-void cgroup_attribute_free_list(CGroupAttribute *first);
-void cgroup_attribute_free_some(CGroupAttribute *first, const char *controller, const char *name);
diff --git a/src/core/cgroup-semantics.c b/src/core/cgroup-semantics.c
deleted file mode 100644
index 82b02bbd78..0000000000
--- a/src/core/cgroup-semantics.c
+++ /dev/null
@@ -1,333 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- 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 "strv.h"
-#include "path-util.h"
-#include "cgroup-util.h"
-
-#include "cgroup-semantics.h"
-
-static int parse_cpu_shares(const CGroupSemantics *s, const char *value, char **ret) {
- unsigned long ul;
-
- assert(s);
- assert(value);
- assert(ret);
-
- if (safe_atolu(value, &ul) < 0 || ul < 1)
- return -EINVAL;
-
- if (asprintf(ret, "%lu", ul) < 0)
- return -ENOMEM;
-
- return 1;
-}
-
-static int parse_memory_limit(const CGroupSemantics *s, const char *value, char **ret) {
- off_t sz;
-
- assert(s);
- assert(value);
- assert(ret);
-
- if (parse_bytes(value, &sz) < 0 || sz <= 0)
- return -EINVAL;
-
- if (asprintf(ret, "%llu", (unsigned long long) sz) < 0)
- return -ENOMEM;
-
- return 1;
-}
-
-static int parse_device(const CGroupSemantics *s, const char *value, char **ret) {
- _cleanup_strv_free_ char **l = NULL;
- char *x;
- unsigned k;
-
- assert(s);
- assert(value);
- assert(ret);
-
- l = strv_split_quoted(value);
- if (!l)
- return -ENOMEM;
-
- k = strv_length(l);
- if (k < 1 || k > 2)
- return -EINVAL;
-
- if (!streq(l[0], "*") && !path_startswith(l[0], "/dev"))
- return -EINVAL;
-
- if (!isempty(l[1]) && !in_charset(l[1], "rwm"))
- return -EINVAL;
-
- x = strdup(value);
- if (!x)
- return -ENOMEM;
-
- *ret = x;
- return 1;
-}
-
-static int parse_blkio_weight(const CGroupSemantics *s, const char *value, char **ret) {
- _cleanup_strv_free_ char **l = NULL;
- unsigned long ul;
-
- assert(s);
- assert(value);
- assert(ret);
-
- l = strv_split_quoted(value);
- if (!l)
- return -ENOMEM;
-
- if (strv_length(l) != 1)
- return 0; /* Returning 0 will cause parse_blkio_weight_device() be tried instead */
-
- if (safe_atolu(l[0], &ul) < 0 || ul < 10 || ul > 1000)
- return -EINVAL;
-
- if (asprintf(ret, "%lu", ul) < 0)
- return -ENOMEM;
-
- return 1;
-}
-
-static int parse_blkio_weight_device(const CGroupSemantics *s, const char *value, char **ret) {
- _cleanup_strv_free_ char **l = NULL;
- unsigned long ul;
-
- assert(s);
- assert(value);
- assert(ret);
-
- l = strv_split_quoted(value);
- if (!l)
- return -ENOMEM;
-
- if (strv_length(l) != 2)
- return -EINVAL;
-
- if (!path_startswith(l[0], "/dev"))
- return -EINVAL;
-
- if (safe_atolu(l[1], &ul) < 0 || ul < 10 || ul > 1000)
- return -EINVAL;
-
- if (asprintf(ret, "%s %lu", l[0], ul) < 0)
- return -ENOMEM;
-
- return 1;
-}
-
-static int parse_blkio_bandwidth(const CGroupSemantics *s, const char *value, char **ret) {
- _cleanup_strv_free_ char **l = NULL;
- off_t bytes;
-
- assert(s);
- assert(value);
- assert(ret);
-
- l = strv_split_quoted(value);
- if (!l)
- return -ENOMEM;
-
- if (strv_length(l) != 2)
- return -EINVAL;
-
- if (!path_startswith(l[0], "/dev")) {
- return -EINVAL;
- }
-
- if (parse_bytes(l[1], &bytes) < 0 || bytes <= 0)
- return -EINVAL;
-
- if (asprintf(ret, "%s %llu", l[0], (unsigned long long) bytes) < 0)
- return -ENOMEM;
-
- return 0;
-}
-
-static int map_device(const CGroupSemantics *s, const char *value, char **ret) {
- _cleanup_strv_free_ char **l = NULL;
- unsigned k;
-
- assert(s);
- assert(value);
- assert(ret);
-
- l = strv_split_quoted(value);
- if (!l)
- return -ENOMEM;
-
- k = strv_length(l);
- if (k < 1 || k > 2)
- return -EINVAL;
-
- if (streq(l[0], "*")) {
-
- if (asprintf(ret, "a *:*%s%s",
- isempty(l[1]) ? "" : " ", strempty(l[1])) < 0)
- return -ENOMEM;
- } else {
- struct stat st;
-
- if (stat(l[0], &st) < 0) {
- log_warning("Couldn't stat device %s", l[0]);
- return -errno;
- }
-
- if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
- log_warning("%s is not a device.", l[0]);
- return -ENODEV;
- }
-
- if (asprintf(ret, "%c %u:%u%s%s",
- S_ISCHR(st.st_mode) ? 'c' : 'b',
- major(st.st_rdev), minor(st.st_rdev),
- isempty(l[1]) ? "" : " ", strempty(l[1])) < 0)
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static int map_blkio(const CGroupSemantics *s, const char *value, char **ret) {
- _cleanup_strv_free_ char **l = NULL;
- struct stat st;
- dev_t d;
-
- assert(s);
- assert(value);
- assert(ret);
-
- l = strv_split_quoted(value);
- if (!l)
- return log_oom();
-
- if (strv_length(l) != 2)
- return -EINVAL;
-
- if (stat(l[0], &st) < 0) {
- log_warning("Couldn't stat device %s", l[0]);
- return -errno;
- }
-
- if (S_ISBLK(st.st_mode))
- d = st.st_rdev;
- else if (major(st.st_dev) != 0) {
- /* If this is not a device node then find the block
- * device this file is stored on */
- d = st.st_dev;
-
- /* If this is a partition, try to get the originating
- * block device */
- block_get_whole_disk(d, &d);
- } else {
- log_warning("%s is not a block device and file system block device cannot be determined or is not local.", l[0]);
- return -ENODEV;
- }
-
- if (asprintf(ret, "%u:%u %s", major(d), minor(d), l[1]) < 0)
- return -ENOMEM;
-
- return 0;
-}
-
-static const CGroupSemantics semantics[] = {
- { "cpu", "cpu.shares", "CPUShare", false, parse_cpu_shares, NULL, NULL },
- { "memory", "memory.soft_limit_in_bytes", "MemorySoftLimit", false, parse_memory_limit, NULL, NULL },
- { "memory", "memory.limit_in_bytes", "MemoryLimit", false, parse_memory_limit, NULL, NULL },
- { "devices", "devices.allow", "DeviceAllow", true, parse_device, map_device, NULL },
- { "devices", "devices.deny", "DeviceDeny", true, parse_device, map_device, NULL },
- { "blkio", "blkio.weight", "BlockIOWeight", false, parse_blkio_weight, NULL, NULL },
- { "blkio", "blkio.weight_device", "BlockIOWeight", true, parse_blkio_weight_device, map_blkio, NULL },
- { "blkio", "blkio.read_bps_device", "BlockIOReadBandwidth", true, parse_blkio_bandwidth, map_blkio, NULL },
- { "blkio", "blkio.write_bps_device", "BlockIOWriteBandwidth", true, parse_blkio_bandwidth, map_blkio, NULL }
-};
-
-int cgroup_semantics_find(
- const char *controller,
- const char *name,
- const char *value,
- char **ret,
- const CGroupSemantics **_s) {
-
- _cleanup_free_ char *c = NULL;
- unsigned i;
- int r;
-
- assert(name);
- assert(_s);
- assert(!value == !ret);
-
- if (!controller) {
- r = cg_controller_from_attr(name, &c);
- if (r < 0)
- return r;
-
- controller = c;
- }
-
- for (i = 0; i < ELEMENTSOF(semantics); i++) {
- const CGroupSemantics *s = semantics + i;
- bool matches_name, matches_pretty;
-
- if (controller && s->controller && !streq(s->controller, controller))
- continue;
-
- matches_name = s->name && streq(s->name, name);
- matches_pretty = s->pretty && streq(s->pretty, name);
-
- if (!matches_name && !matches_pretty)
- continue;
-
- if (value) {
- if (matches_pretty && s->map_pretty) {
-
- r = s->map_pretty(s, value, ret);
- if (r < 0)
- return r;
-
- if (r == 0)
- continue;
-
- } else {
- char *x;
-
- x = strdup(value);
- if (!x)
- return -ENOMEM;
-
- *ret = x;
- }
- }
-
- *_s = s;
- return 1;
- }
-
- *ret = NULL;
- *_s = NULL;
- return 0;
-}
diff --git a/src/core/cgroup-semantics.h b/src/core/cgroup-semantics.h
deleted file mode 100644
index 4f848f4bb7..0000000000
--- a/src/core/cgroup-semantics.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-typedef struct CGroupSemantics CGroupSemantics;
-
-struct CGroupSemantics {
- const char *controller;
- const char *name;
- const char *pretty;
-
- bool multiple;
-
- /* This call is used for parsing the pretty value to the actual attribute value */
- int (*map_pretty)(const CGroupSemantics *semantics, const char *value, char **ret);
-
- /* Right before writing this attribute the attribute value is converted to a low-level value */
- int (*map_write)(const CGroupSemantics *semantics, const char *value, char **ret);
-
- /* If this attribute takes a list, this call can be used to reset the list to empty */
- int (*reset)(const CGroupSemantics *semantics, const char *group);
-};
-
-int cgroup_semantics_find(const char *controller, const char *name, const char *value, char **ret, const CGroupSemantics **semantics);
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 83df0f3c9a..8bf4d896de 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -3,7 +3,7 @@
/***
This file is part of systemd.
- Copyright 2010 Lennart Poettering
+ 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
@@ -19,310 +19,578 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <errno.h>
-#include <assert.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <signal.h>
-#include <sys/mount.h>
#include <fcntl.h>
-#include "cgroup.h"
-#include "cgroup-util.h"
-#include "log.h"
-#include "strv.h"
#include "path-util.h"
+#include "special.h"
+#include "cgroup-util.h"
+#include "cgroup.h"
-int cgroup_bonding_realize(CGroupBonding *b) {
- int r;
+void cgroup_context_init(CGroupContext *c) {
+ assert(c);
- assert(b);
- assert(b->path);
- assert(b->controller);
+ /* Initialize everything to the kernel defaults, assuming the
+ * structure is preinitialized to 0 */
- r = cg_create(b->controller, b->path, NULL);
- if (r < 0) {
- log_warning("Failed to create cgroup %s:%s: %s", b->controller, b->path, strerror(-r));
- return r;
- }
+ c->cpu_shares = 1024;
+ c->memory_limit = (uint64_t) -1;
+ c->blockio_weight = 1000;
+}
- b->realized = true;
+void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a) {
+ assert(c);
+ assert(a);
- return 0;
+ LIST_REMOVE(CGroupDeviceAllow, device_allow, c->device_allow, a);
+ free(a->path);
+ free(a);
}
-int cgroup_bonding_realize_list(CGroupBonding *first) {
- CGroupBonding *b;
- int r;
-
- LIST_FOREACH(by_unit, b, first)
- if ((r = cgroup_bonding_realize(b)) < 0 && b->essential)
- return r;
+void cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w) {
+ assert(c);
+ assert(w);
- return 0;
+ LIST_REMOVE(CGroupBlockIODeviceWeight, device_weights, c->blockio_device_weights, w);
+ free(w->path);
+ free(w);
}
-void cgroup_bonding_free(CGroupBonding *b, bool trim) {
+void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockIODeviceBandwidth *b) {
+ assert(c);
assert(b);
- if (b->unit) {
- CGroupBonding *f;
+ LIST_REMOVE(CGroupBlockIODeviceBandwidth, device_bandwidths, c->blockio_device_bandwidths, b);
+ free(b->path);
+ free(b);
+}
- LIST_REMOVE(CGroupBonding, by_unit, b->unit->cgroup_bondings, b);
+void cgroup_context_done(CGroupContext *c) {
+ assert(c);
- if (streq(b->controller, SYSTEMD_CGROUP_CONTROLLER)) {
- assert_se(f = hashmap_get(b->unit->manager->cgroup_bondings, b->path));
- LIST_REMOVE(CGroupBonding, by_path, f, b);
+ while (c->blockio_device_weights)
+ cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
- if (f)
- hashmap_replace(b->unit->manager->cgroup_bondings, b->path, f);
- else
- hashmap_remove(b->unit->manager->cgroup_bondings, b->path);
- }
- }
+ while (c->blockio_device_bandwidths)
+ cgroup_context_free_blockio_device_bandwidth(c, c->blockio_device_bandwidths);
- if (b->realized && b->ours && trim)
- cg_trim(b->controller, b->path, false);
+ while (c->device_allow)
+ cgroup_context_free_device_allow(c, c->device_allow);
+}
- free(b->controller);
- free(b->path);
- free(b);
+void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
+ CGroupBlockIODeviceBandwidth *b;
+ CGroupBlockIODeviceWeight *w;
+ CGroupDeviceAllow *a;
+
+ assert(c);
+ assert(f);
+
+ prefix = strempty(prefix);
+
+ fprintf(f,
+ "%sCPUAccounting=%s\n"
+ "%sBlockIOAccounting=%s\n"
+ "%sMemoryAccounting=%s\n"
+ "%sCPUShares=%lu\n"
+ "%sBlockIOWeight=%lu\n"
+ "%sMemoryLimit=%" PRIu64 "\n"
+ "%sDevicePolicy=%s\n",
+ prefix, yes_no(c->cpu_accounting),
+ prefix, yes_no(c->blockio_accounting),
+ prefix, yes_no(c->memory_accounting),
+ prefix, c->cpu_shares,
+ prefix, c->blockio_weight,
+ prefix, c->memory_limit,
+ prefix, cgroup_device_policy_to_string(c->device_policy));
+
+ LIST_FOREACH(device_allow, a, c->device_allow)
+ fprintf(f,
+ "%sDeviceAllow=%s %s%s%s\n",
+ prefix,
+ a->path,
+ a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
+
+ LIST_FOREACH(device_weights, w, c->blockio_device_weights)
+ fprintf(f,
+ "%sBlockIODeviceWeight=%s %lu",
+ prefix,
+ w->path,
+ w->weight);
+
+ LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
+ char buf[FORMAT_BYTES_MAX];
+
+ fprintf(f,
+ "%s%s=%s %s\n",
+ prefix,
+ b->read ? "BlockIOReadBandwidth" : "BlockIOWriteBandwidth",
+ b->path,
+ format_bytes(buf, sizeof(buf), b->bandwidth));
+ }
}
-void cgroup_bonding_free_list(CGroupBonding *first, bool remove_or_trim) {
- CGroupBonding *b, *n;
+static int lookup_blkio_device(const char *p, dev_t *dev) {
+ struct stat st;
+ int r;
- LIST_FOREACH_SAFE(by_unit, b, n, first)
- cgroup_bonding_free(b, remove_or_trim);
-}
+ assert(p);
+ assert(dev);
-void cgroup_bonding_trim(CGroupBonding *b, bool delete_root) {
- assert(b);
+ r = stat(p, &st);
+ if (r < 0) {
+ log_warning("Couldn't stat device %s: %m", p);
+ return -errno;
+ }
- if (b->realized && b->ours)
- cg_trim(b->controller, b->path, delete_root);
-}
+ 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;
-void cgroup_bonding_trim_list(CGroupBonding *first, bool delete_root) {
- CGroupBonding *b;
+ /* 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;
+ }
- LIST_FOREACH(by_unit, b, first)
- cgroup_bonding_trim(b, delete_root);
+ return 0;
}
-int cgroup_bonding_install(CGroupBonding *b, pid_t pid, const char *cgroup_suffix) {
- _cleanup_free_ char *p = NULL;
- const char *path;
+static int whitelist_device(const char *path, const char *node, const char *acc) {
+ char buf[2+DECIMAL_STR_MAX(dev_t)*2+2+4];
+ struct stat st;
int r;
- assert(b);
- assert(pid >= 0);
+ assert(path);
+ assert(acc);
- if (cgroup_suffix) {
- p = strjoin(b->path, "/", cgroup_suffix, NULL);
- if (!p)
- return -ENOMEM;
+ if (stat(node, &st) < 0) {
+ log_warning("Couldn't stat device %s", node);
+ return -errno;
+ }
- path = p;
- } else
- path = b->path;
+ if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
+ log_warning("%s is not a device.", node);
+ return -ENODEV;
+ }
+
+ sprintf(buf,
+ "%c %u:%u %s",
+ S_ISCHR(st.st_mode) ? 'c' : 'b',
+ major(st.st_rdev), minor(st.st_rdev),
+ acc);
- r = cg_create_and_attach(b->controller, path, pid);
+ r = cg_set_attribute("devices", path, "devices.allow", buf);
if (r < 0)
- return r;
+ log_warning("Failed to set devices.allow on %s: %s", path, strerror(-r));
- b->realized = true;
- return 0;
+ return r;
}
-int cgroup_bonding_install_list(CGroupBonding *first, pid_t pid, const char *cgroup_suffix) {
- CGroupBonding *b;
+void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const char *path) {
int r;
- LIST_FOREACH(by_unit, b, first) {
- r = cgroup_bonding_install(b, pid, cgroup_suffix);
- if (r < 0 && b->essential)
- return r;
+ assert(c);
+ assert(path);
+
+ if (mask == 0)
+ return;
+
+ if (mask & CGROUP_CPU) {
+ char buf[DECIMAL_STR_MAX(unsigned long) + 1];
+
+ sprintf(buf, "%lu\n", c->cpu_shares);
+ r = cg_set_attribute("cpu", path, "cpu.shares", buf);
+ if (r < 0)
+ log_warning("Failed to set cpu.shares on %s: %s", path, strerror(-r));
}
- return 0;
-}
+ if (mask & CGROUP_BLKIO) {
+ char buf[MAX3(DECIMAL_STR_MAX(unsigned long)+1,
+ DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(unsigned long)*1,
+ DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1)];
+ CGroupBlockIODeviceWeight *w;
+ CGroupBlockIODeviceBandwidth *b;
-int cgroup_bonding_migrate(CGroupBonding *b, CGroupBonding *list) {
- CGroupBonding *q;
- int ret = 0;
+ sprintf(buf, "%lu\n", c->blockio_weight);
+ r = cg_set_attribute("blkio", path, "blkio.weight", buf);
+ if (r < 0)
+ log_warning("Failed to set blkio.weight on %s: %s", path, strerror(-r));
- LIST_FOREACH(by_unit, q, list) {
- int r;
+ /* FIXME: no way to reset this list */
+ LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
+ dev_t dev;
- if (q == b)
- continue;
+ r = lookup_blkio_device(w->path, &dev);
+ if (r < 0)
+ continue;
- if (!q->ours)
- continue;
+ sprintf(buf, "%u:%u %lu", major(dev), minor(dev), w->weight);
+ r = cg_set_attribute("blkio", path, "blkio.weight_device", buf);
+ if (r < 0)
+ log_error("Failed to set blkio.weight_device on %s: %s", path, strerror(-r));
+ }
+
+ /* FIXME: no way to reset this list */
+ LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
+ const char *a;
+ dev_t dev;
+
+ r = lookup_blkio_device(b->path, &dev);
+ if (r < 0)
+ continue;
+
+ a = b->read ? "blkio.throttle.read_bps_device" : "blkio.throttle.write_bps_device";
+
+ sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), b->bandwidth);
+ r = cg_set_attribute("blkio", path, a, buf);
+ if (r < 0)
+ log_error("Failed to set %s on %s: %s", a, path, strerror(-r));
+ }
+ }
+
+ if (mask & CGROUP_MEMORY) {
+ if (c->memory_limit != (uint64_t) -1) {
+ char buf[DECIMAL_STR_MAX(uint64_t) + 1];
+
+ sprintf(buf, "%" PRIu64 "\n", c->memory_limit);
+ r = cg_set_attribute("memory", path, "memory.limit_in_bytes", buf);
+ } else
+ r = cg_set_attribute("memory", path, "memory.limit_in_bytes", "-1");
- r = cg_migrate_recursive(q->controller, q->path, b->controller, b->path, true, false);
- if (r < 0 && ret == 0)
- ret = r;
+ if (r < 0)
+ log_error("Failed to set memory.limit_in_bytes on %s: %s", path, strerror(-r));
}
- return ret;
+ if (mask & CGROUP_DEVICE) {
+ CGroupDeviceAllow *a;
+
+ if (c->device_allow || c->device_policy != CGROUP_AUTO)
+ r = cg_set_attribute("devices", path, "devices.deny", "a");
+ else
+ r = cg_set_attribute("devices", path, "devices.allow", "a");
+ if (r < 0)
+ log_error("Failed to reset devices.list on %s: %s", path, strerror(-r));
+
+ if (c->device_policy == CGROUP_CLOSED ||
+ (c->device_policy == CGROUP_AUTO && c->device_allow)) {
+ static const char auto_devices[] =
+ "/dev/null\0" "rw\0"
+ "/dev/zero\0" "rw\0"
+ "/dev/full\0" "rw\0"
+ "/dev/random\0" "rw\0"
+ "/dev/urandom\0" "rw\0";
+
+ const char *x, *y;
+
+ NULSTR_FOREACH_PAIR(x, y, auto_devices)
+ whitelist_device(path, x, y);
+ }
+
+ LIST_FOREACH(device_allow, a, c->device_allow) {
+ char acc[4];
+ unsigned k = 0;
+
+ if (a->r)
+ acc[k++] = 'r';
+ if (a->w)
+ acc[k++] = 'w';
+ if (a->m)
+ acc[k++] = 'm';
+
+ if (k == 0)
+ continue;
+
+ acc[k++] = 0;
+ whitelist_device(path, a->path, acc);
+ }
+ }
}
-int cgroup_bonding_migrate_to(CGroupBonding *b, const char *target, bool rem) {
- assert(b);
- assert(target);
+CGroupControllerMask cgroup_context_get_mask(CGroupContext *c) {
+ CGroupControllerMask mask = 0;
+
+ /* Figure out which controllers we need */
+
+ if (c->cpu_accounting || c->cpu_shares != 1024)
+ mask |= CGROUP_CPUACCT | CGROUP_CPU;
+
+ if (c->blockio_accounting ||
+ c->blockio_weight != 1000 ||
+ c->blockio_device_weights ||
+ c->blockio_device_bandwidths)
+ mask |= CGROUP_BLKIO;
+
+ if (c->memory_accounting ||
+ c->memory_limit != (uint64_t) -1)
+ mask |= CGROUP_MEMORY;
+
+ if (c->device_allow || c->device_policy != CGROUP_AUTO)
+ mask |= CGROUP_DEVICE;
- return cg_migrate_recursive(b->controller, b->path, b->controller, target, true, rem);
+ return mask;
}
-int cgroup_bonding_set_group_access(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid) {
- assert(b);
+static CGroupControllerMask unit_get_cgroup_mask(Unit *u) {
+ CGroupContext *c;
- if (!b->realized)
- return -EINVAL;
+ c = unit_get_cgroup_context(u);
+ if (!c)
+ return 0;
- return cg_set_group_access(b->controller, b->path, mode, uid, gid);
+ return cgroup_context_get_mask(c);
}
-int cgroup_bonding_set_group_access_list(CGroupBonding *first, mode_t mode, uid_t uid, gid_t gid) {
- CGroupBonding *b;
- int r;
+static CGroupControllerMask unit_get_members_mask(Unit *u) {
+ CGroupControllerMask mask = 0;
+ Unit *m;
+ Iterator i;
- LIST_FOREACH(by_unit, b, first) {
- r = cgroup_bonding_set_group_access(b, mode, uid, gid);
- if (r < 0)
- return r;
+ assert(u);
+
+ SET_FOREACH(m, u->dependencies[UNIT_BEFORE], i) {
+
+ if (UNIT_DEREF(m->slice) != u)
+ continue;
+
+ mask |= unit_get_cgroup_mask(m) | unit_get_members_mask(m);
}
- return 0;
+ return mask;
}
-int cgroup_bonding_set_task_access(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid, int sticky) {
- assert(b);
+static CGroupControllerMask unit_get_siblings_mask(Unit *u) {
+ assert(u);
- if (!b->realized)
- return -EINVAL;
+ if (!UNIT_ISSET(u->slice))
+ return 0;
- return cg_set_task_access(b->controller, b->path, mode, uid, gid, sticky);
+ /* Sibling propagation is only relevant for weight-based
+ * controllers, so let's mask out everything else */
+ return unit_get_members_mask(UNIT_DEREF(u->slice)) &
+ (CGROUP_CPU|CGROUP_BLKIO|CGROUP_CPUACCT);
}
-int cgroup_bonding_set_task_access_list(CGroupBonding *first, mode_t mode, uid_t uid, gid_t gid, int sticky) {
- CGroupBonding *b;
+static int unit_create_cgroups(Unit *u, CGroupControllerMask mask) {
+ char *path = NULL;
int r;
+ bool is_in_hash = false;
+
+ assert(u);
+
+ path = unit_default_cgroup_path(u);
+ if (!path)
+ return -ENOMEM;
+
+ r = hashmap_put(u->manager->cgroup_unit, path, u);
+ if (r == 0)
+ is_in_hash = true;
+
+ if (r < 0) {
+ log_error("cgroup %s exists already: %s", path, strerror(-r));
+ free(path);
+ return r;
+ }
+
+ /* First, create our own group */
+ r = cg_create_everywhere(u->manager->cgroup_supported, mask, path);
+ if (r < 0)
+ log_error("Failed to create cgroup %s: %s", path, strerror(-r));
- LIST_FOREACH(by_unit, b, first) {
- r = cgroup_bonding_set_task_access(b, mode, uid, gid, sticky);
+ /* Then, possibly move things over */
+ if (u->cgroup_path) {
+ r = cg_migrate_everywhere(u->manager->cgroup_supported, u->cgroup_path, path);
if (r < 0)
- return r;
+ log_error("Failed to migrate cgroup %s: %s", path, strerror(-r));
}
+ if (!is_in_hash) {
+ /* And remember the new data */
+ free(u->cgroup_path);
+ u->cgroup_path = path;
+ }
+
+ u->cgroup_realized = true;
+ u->cgroup_mask = mask;
+
return 0;
}
-int cgroup_bonding_kill(CGroupBonding *b, int sig, bool sigcont, bool rem, Set *s, const char *cgroup_suffix) {
- char *p = NULL;
- const char *path;
- int r;
+static int unit_realize_cgroup_now(Unit *u) {
+ CGroupControllerMask mask;
- assert(b);
- assert(sig >= 0);
+ assert(u);
+
+ if (u->in_cgroup_queue) {
+ LIST_REMOVE(Unit, cgroup_queue, u->manager->cgroup_queue, u);
+ u->in_cgroup_queue = false;
+ }
+
+ mask = unit_get_cgroup_mask(u) | unit_get_members_mask(u) | unit_get_siblings_mask(u);
+ mask &= u->manager->cgroup_supported;
- /* Don't kill cgroups that aren't ours */
- if (!b->ours)
+ if (u->cgroup_realized &&
+ u->cgroup_mask == mask)
return 0;
- if (cgroup_suffix) {
- p = strjoin(b->path, "/", cgroup_suffix, NULL);
- if (!p)
- return -ENOMEM;
+ /* First, realize parents */
+ if (UNIT_ISSET(u->slice))
+ unit_realize_cgroup_now(UNIT_DEREF(u->slice));
- path = p;
- } else
- path = b->path;
+ /* And then do the real work */
+ return unit_create_cgroups(u, mask);
+}
- r = cg_kill_recursive(b->controller, path, sig, sigcont, true, rem, s);
- free(p);
+static void unit_add_to_cgroup_queue(Unit *u) {
- return r;
+ if (u->in_cgroup_queue)
+ return;
+
+ LIST_PREPEND(Unit, cgroup_queue, u->manager->cgroup_queue, u);
+ u->in_cgroup_queue = true;
}
-int cgroup_bonding_kill_list(CGroupBonding *first, int sig, bool sigcont, bool rem, Set *s, const char *cgroup_suffix) {
- CGroupBonding *b;
- Set *allocated_set = NULL;
- int ret = -EAGAIN, r;
+unsigned manager_dispatch_cgroup_queue(Manager *m) {
+ Unit *i;
+ unsigned n = 0;
- if (!first)
- return 0;
+ while ((i = m->cgroup_queue)) {
+ assert(i->in_cgroup_queue);
+
+ if (unit_realize_cgroup_now(i) >= 0)
+ cgroup_context_apply(unit_get_cgroup_context(i), i->cgroup_mask, i->cgroup_path);
+
+ n++;
+ }
+
+ return n;
+}
+
+static void unit_queue_siblings(Unit *u) {
+ Unit *slice;
+
+ /* This adds the siblings of the specified unit and the
+ * siblings of all parent units to the cgroup queue. (But
+ * neither the specified unit itself nor the parents.) */
- if (!s)
- if (!(s = allocated_set = set_new(trivial_hash_func, trivial_compare_func)))
- return -ENOMEM;
+ while ((slice = UNIT_DEREF(u->slice))) {
+ Iterator i;
+ Unit *m;
- LIST_FOREACH(by_unit, b, first) {
- r = cgroup_bonding_kill(b, sig, sigcont, rem, s, cgroup_suffix);
- if (r < 0) {
- if (r == -EAGAIN || r == -ESRCH)
+ SET_FOREACH(m, slice->dependencies[UNIT_BEFORE], i) {
+ if (m == u)
continue;
- ret = r;
- goto finish;
+ if (UNIT_DEREF(m->slice) != slice)
+ continue;
+
+ unit_add_to_cgroup_queue(m);
}
- if (ret < 0 || r > 0)
- ret = r;
+ u = slice;
}
+}
+
+int unit_realize_cgroup(Unit *u) {
+ CGroupContext *c;
+ int r;
+
+ assert(u);
+
+ c = unit_get_cgroup_context(u);
+ if (!c)
+ return 0;
-finish:
- if (allocated_set)
- set_free(allocated_set);
+ /* So, here's the deal: when realizing the cgroups for this
+ * unit, we need to first create all parents, but there's more
+ * actually: for the weight-based controllers we also need to
+ * make sure that all our siblings (i.e. units that are in the
+ * same slice as we are) have cgroup too. Otherwise things
+ * would become very uneven as each of their processes would
+ * get as much resources as all our group together. This call
+ * will synchronously create the parent cgroups, but will
+ * defer work on the siblings to the next event loop
+ * iteration. */
- return ret;
+ /* Add all sibling slices to the cgroup queue. */
+ unit_queue_siblings(u);
+
+ /* And realize this one now */
+ r = unit_realize_cgroup_now(u);
+
+ /* And apply the values */
+ if (r >= 0)
+ cgroup_context_apply(c, u->cgroup_mask, u->cgroup_path);
+
+ return r;
}
-/* Returns 1 if the group is empty, 0 if it is not, -EAGAIN if we
- * cannot know */
-int cgroup_bonding_is_empty(CGroupBonding *b) {
+void unit_destroy_cgroup(Unit *u) {
int r;
- assert(b);
+ assert(u);
- if ((r = cg_is_empty_recursive(b->controller, b->path, true)) < 0)
- return r;
+ if (!u->cgroup_path)
+ return;
+
+ r = cg_trim_everywhere(u->manager->cgroup_supported, u->cgroup_path, !unit_has_name(u, SPECIAL_ROOT_SLICE));
+ if (r < 0)
+ log_debug("Failed to destroy cgroup %s: %s", u->cgroup_path, strerror(-r));
+
+ hashmap_remove(u->manager->cgroup_unit, u->cgroup_path);
- /* If it is empty it is empty */
- if (r > 0)
- return 1;
+ free(u->cgroup_path);
+ u->cgroup_path = NULL;
+ u->cgroup_realized = false;
+ u->cgroup_mask = 0;
- /* It's not only us using this cgroup, so we just don't know */
- return b->ours ? 0 : -EAGAIN;
}
-int cgroup_bonding_is_empty_list(CGroupBonding *first) {
- CGroupBonding *b;
+pid_t unit_search_main_pid(Unit *u) {
+ _cleanup_fclose_ FILE *f = NULL;
+ pid_t pid = 0, npid, mypid;
- LIST_FOREACH(by_unit, b, first) {
- int r;
+ assert(u);
- if ((r = cgroup_bonding_is_empty(b)) < 0) {
- /* If this returned -EAGAIN, then we don't know if the
- * group is empty, so let's see if another group can
- * tell us */
+ if (!u->cgroup_path)
+ return 0;
- if (r != -EAGAIN)
- return r;
- } else
- return r;
+ if (cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &f) < 0)
+ return 0;
+
+ mypid = getpid();
+ while (cg_read_pid(f, &npid) > 0) {
+ pid_t ppid;
+
+ if (npid == pid)
+ continue;
+
+ /* Ignore processes that aren't our kids */
+ if (get_parent_of_pid(npid, &ppid) >= 0 && ppid != mypid)
+ continue;
+
+ if (pid != 0) {
+ /* Dang, there's more than one daemonized PID
+ in this group, so we don't know what process
+ is the main process. */
+ pid = 0;
+ break;
+ }
+
+ pid = npid;
}
- return -EAGAIN;
+ return pid;
}
int manager_setup_cgroup(Manager *m) {
- _cleanup_free_ char *current = NULL, *path = NULL;
- char suffix_buffer[sizeof("/systemd-") + DECIMAL_STR_MAX(pid_t)];
- const char *suffix;
+ _cleanup_free_ char *path = NULL;
int r;
+ char *e, *a;
assert(m);
@@ -333,37 +601,30 @@ int manager_setup_cgroup(Manager *m) {
}
/* 1. Determine hierarchy */
- r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &current);
+ free(m->cgroup_root);
+ m->cgroup_root = NULL;
+
+ r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &m->cgroup_root);
if (r < 0) {
log_error("Cannot determine cgroup we are running in: %s", strerror(-r));
return r;
}
- if (m->running_as == SYSTEMD_SYSTEM)
- suffix = "/system";
- else {
- sprintf(suffix_buffer, "/systemd-%lu", (unsigned long) getpid());
- suffix = suffix_buffer;
+ /* Already in /system.slice? If so, let's cut this off again */
+ if (m->running_as == SYSTEMD_SYSTEM) {
+ e = endswith(m->cgroup_root, "/" SPECIAL_SYSTEM_SLICE);
+ if (e)
+ *e = 0;
}
- free(m->cgroup_hierarchy);
- if (endswith(current, suffix)) {
- /* We probably got reexecuted and can continue to use our root cgroup */
- m->cgroup_hierarchy = current;
- current = NULL;
- } else {
- /* We need a new root cgroup */
- if (streq(current, "/"))
- m->cgroup_hierarchy = strdup(suffix);
- else
- m->cgroup_hierarchy = strappend(current, suffix);
-
- if (!m->cgroup_hierarchy)
- return log_oom();
- }
+ /* 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. */
+ if (streq(m->cgroup_root, "/"))
+ m->cgroup_root[0] = 0;
/* 2. Show data */
- r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, NULL, &path);
+ r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, NULL, &path);
if (r < 0) {
log_error("Cannot find cgroup mount point: %s", strerror(-r));
return r;
@@ -382,8 +643,12 @@ int manager_setup_cgroup(Manager *m) {
log_debug("Release agent already installed.");
}
- /* 4. Realize the group */
- r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, 0);
+ /* 4. Realize the system slice and put us in there */
+ if (m->running_as == SYSTEMD_SYSTEM) {
+ a = strappenda(m->cgroup_root, "/" SPECIAL_SYSTEM_SLICE);
+ r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, a, 0);
+ } else
+ r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, 0);
if (r < 0) {
log_error("Failed to create root cgroup hierarchy: %s", strerror(-r));
return r;
@@ -399,16 +664,11 @@ int manager_setup_cgroup(Manager *m) {
return -errno;
}
- /* 6. Remove non-existing controllers from the default controllers list */
- cg_shorten_controllers(m->default_controllers);
+ /* 6. Figure out which controllers are supported */
+ m->cgroup_supported = cg_mask_supported();
- /* 7. Let's create the user and machine hierarchies
- * right-away, so that people can inotify on them, if they
- * wish, without this being racy. */
- if (m->running_as == SYSTEMD_SYSTEM) {
- cg_create(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, "../user");
- cg_create(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, "../machine");
- }
+ /* 7. Always enable hierarchial support if it exists... */
+ cg_set_attribute("memory", "/", "memory.use_hierarchy", "1");
return 0;
}
@@ -416,213 +676,88 @@ int manager_setup_cgroup(Manager *m) {
void manager_shutdown_cgroup(Manager *m, bool delete) {
assert(m);
- if (delete && m->cgroup_hierarchy)
- cg_delete(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy);
+ /* We can't really delete the group, since we are in it. But
+ * let's trim it. */
+ if (delete && m->cgroup_root)
+ cg_trim(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, false);
if (m->pin_cgroupfs_fd >= 0) {
close_nointr_nofail(m->pin_cgroupfs_fd);
m->pin_cgroupfs_fd = -1;
}
- free(m->cgroup_hierarchy);
- m->cgroup_hierarchy = NULL;
+ free(m->cgroup_root);
+ m->cgroup_root = NULL;
}
-int cgroup_bonding_get(Manager *m, const char *cgroup, CGroupBonding **bonding) {
- CGroupBonding *b;
+Unit* manager_get_unit_by_cgroup(Manager *m, const char *cgroup) {
char *p;
+ Unit *u;
assert(m);
assert(cgroup);
- assert(bonding);
- b = hashmap_get(m->cgroup_bondings, cgroup);
- if (b) {
- *bonding = b;
- return 1;
- }
+ u = hashmap_get(m->cgroup_unit, cgroup);
+ if (u)
+ return u;
p = strdupa(cgroup);
- if (!p)
- return -ENOMEM;
-
for (;;) {
char *e;
e = strrchr(p, '/');
- if (e == p || !e) {
- *bonding = NULL;
- return 0;
- }
+ if (e == p || !e)
+ return NULL;
*e = 0;
- b = hashmap_get(m->cgroup_bondings, p);
- if (b) {
- *bonding = b;
- return 1;
- }
+ u = hashmap_get(m->cgroup_unit, p);
+ if (u)
+ return u;
}
}
-int cgroup_notify_empty(Manager *m, const char *group) {
- CGroupBonding *l, *b;
+Unit *manager_get_unit_by_pid(Manager *m, pid_t pid) {
+ _cleanup_free_ char *cgroup = NULL;
int r;
assert(m);
- assert(group);
-
- r = cgroup_bonding_get(m, group, &l);
- if (r <= 0)
- return r;
-
- LIST_FOREACH(by_path, b, l) {
- int t;
-
- if (!b->unit)
- continue;
-
- t = cgroup_bonding_is_empty_list(b);
- if (t < 0) {
-
- /* If we don't know, we don't know */
- if (t != -EAGAIN)
- log_warning("Failed to check whether cgroup is empty: %s", strerror(errno));
-
- continue;
- }
-
- if (t > 0) {
- /* If it is empty, let's delete it */
- cgroup_bonding_trim_list(b->unit->cgroup_bondings, true);
-
- if (UNIT_VTABLE(b->unit)->cgroup_notify_empty)
- UNIT_VTABLE(b->unit)->cgroup_notify_empty(b->unit);
- }
- }
-
- return 0;
-}
-
-Unit* cgroup_unit_by_pid(Manager *m, pid_t pid) {
- CGroupBonding *l, *b;
- char *group = NULL;
-
- assert(m);
if (pid <= 1)
return NULL;
- if (cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &group) < 0)
- return NULL;
-
- l = hashmap_get(m->cgroup_bondings, group);
-
- if (!l) {
- char *slash;
-
- while ((slash = strrchr(group, '/'))) {
- if (slash == group)
- break;
-
- *slash = 0;
-
- if ((l = hashmap_get(m->cgroup_bondings, group)))
- break;
- }
- }
-
- free(group);
-
- LIST_FOREACH(by_path, b, l) {
-
- if (!b->unit)
- continue;
-
- if (b->ours)
- return b->unit;
- }
-
- return NULL;
-}
-
-CGroupBonding *cgroup_bonding_find_list(CGroupBonding *first, const char *controller) {
- CGroupBonding *b;
-
- if (!controller)
- controller = SYSTEMD_CGROUP_CONTROLLER;
-
- LIST_FOREACH(by_unit, b, first)
- if (streq(b->controller, controller))
- return b;
-
- return NULL;
-}
-
-char *cgroup_bonding_to_string(CGroupBonding *b) {
- char *r;
-
- assert(b);
-
- if (asprintf(&r, "%s:%s", b->controller, b->path) < 0)
+ r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup);
+ if (r < 0)
return NULL;
- return r;
+ return manager_get_unit_by_cgroup(m, cgroup);
}
-pid_t cgroup_bonding_search_main_pid(CGroupBonding *b) {
- FILE *f;
- pid_t pid = 0, npid, mypid;
-
- assert(b);
-
- if (!b->ours)
- return 0;
-
- if (cg_enumerate_processes(b->controller, b->path, &f) < 0)
- return 0;
-
- mypid = getpid();
-
- while (cg_read_pid(f, &npid) > 0) {
- pid_t ppid;
+int manager_notify_cgroup_empty(Manager *m, const char *cgroup) {
+ Unit *u;
+ int r;
- if (npid == pid)
- continue;
+ assert(m);
+ assert(cgroup);
- /* Ignore processes that aren't our kids */
- if (get_parent_of_pid(npid, &ppid) >= 0 && ppid != mypid)
- continue;
+ u = manager_get_unit_by_cgroup(m, cgroup);
+ if (u) {
+ r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
+ if (r > 0) {
+ if (UNIT_VTABLE(u)->notify_cgroup_empty)
+ UNIT_VTABLE(u)->notify_cgroup_empty(u);
- if (pid != 0) {
- /* Dang, there's more than one daemonized PID
- in this group, so we don't know what process
- is the main process. */
- pid = 0;
- break;
+ unit_add_to_gc_queue(u);
}
-
- pid = npid;
}
- fclose(f);
-
- return pid;
+ return 0;
}
-pid_t cgroup_bonding_search_main_pid_list(CGroupBonding *first) {
- CGroupBonding *b;
- pid_t pid;
-
- /* Try to find a main pid from this cgroup, but checking if
- * there's only one PID in the cgroup and returning it. Later
- * on we might want to add additional, smarter heuristics
- * here. */
+static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] = {
+ [CGROUP_AUTO] = "auto",
+ [CGROUP_CLOSED] = "closed",
+ [CGROUP_STRICT] = "strict",
+};
- LIST_FOREACH(by_unit, b, first)
- if ((pid = cgroup_bonding_search_main_pid(b)) != 0)
- return pid;
-
- return 0;
-
-}
+DEFINE_STRING_TABLE_LOOKUP(cgroup_device_policy, CGroupDevicePolicy);
diff --git a/src/core/cgroup.h b/src/core/cgroup.h
index 6555d89e37..0a079e909d 100644
--- a/src/core/cgroup.h
+++ b/src/core/cgroup.h
@@ -5,7 +5,7 @@
/***
This file is part of systemd.
- Copyright 2010 Lennart Poettering
+ 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
@@ -21,74 +21,95 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-typedef struct CGroupBonding CGroupBonding;
+#include "list.h"
-#include "unit.h"
+typedef struct CGroupContext CGroupContext;
+typedef struct CGroupDeviceAllow CGroupDeviceAllow;
+typedef struct CGroupBlockIODeviceWeight CGroupBlockIODeviceWeight;
+typedef struct CGroupBlockIODeviceBandwidth CGroupBlockIODeviceBandwidth;
-/* Binds a cgroup to a name */
-struct CGroupBonding {
- char *controller;
- char *path;
+typedef enum CGroupDevicePolicy {
- Unit *unit;
+ /* When devices listed, will allow those, plus built-in ones,
+ if none are listed will allow everything. */
+ CGROUP_AUTO,
- /* For the Unit::cgroup_bondings list */
- LIST_FIELDS(CGroupBonding, by_unit);
+ /* Everything forbidden, except built-in ones and listed ones. */
+ CGROUP_CLOSED,
- /* For the Manager::cgroup_bondings hashmap */
- LIST_FIELDS(CGroupBonding, by_path);
+ /* Everythings forbidden, except for the listed devices */
+ CGROUP_STRICT,
- /* When shutting down, remove cgroup? Are our own tasks the
- * only ones in this group?*/
- bool ours:1;
+ _CGROUP_DEVICE_POLICY_MAX,
+ _CGROUP_DEVICE_POLICY_INVALID = -1
+} CGroupDevicePolicy;
- /* If we cannot create this group, or add a process to it, is this fatal? */
- bool essential:1;
+struct CGroupDeviceAllow {
+ LIST_FIELDS(CGroupDeviceAllow, device_allow);
+ char *path;
+ bool r:1;
+ bool w:1;
+ bool m:1;
+};
- /* This cgroup is realized */
- bool realized:1;
+struct CGroupBlockIODeviceWeight {
+ LIST_FIELDS(CGroupBlockIODeviceWeight, device_weights);
+ char *path;
+ unsigned long weight;
};
-int cgroup_bonding_realize(CGroupBonding *b);
-int cgroup_bonding_realize_list(CGroupBonding *first);
+struct CGroupBlockIODeviceBandwidth {
+ LIST_FIELDS(CGroupBlockIODeviceBandwidth, device_bandwidths);
+ char *path;
+ uint64_t bandwidth;
+ bool read;
+};
-void cgroup_bonding_free(CGroupBonding *b, bool trim);
-void cgroup_bonding_free_list(CGroupBonding *first, bool trim);
+struct CGroupContext {
+ bool cpu_accounting;
+ bool blockio_accounting;
+ bool memory_accounting;
-int cgroup_bonding_install(CGroupBonding *b, pid_t pid, const char *suffix);
-int cgroup_bonding_install_list(CGroupBonding *first, pid_t pid, const char *suffix);
+ unsigned long cpu_shares;
-int cgroup_bonding_migrate(CGroupBonding *b, CGroupBonding *list);
-int cgroup_bonding_migrate_to(CGroupBonding *b, const char *target, bool rem);
+ unsigned long blockio_weight;
+ LIST_HEAD(CGroupBlockIODeviceWeight, blockio_device_weights);
+ LIST_HEAD(CGroupBlockIODeviceBandwidth, blockio_device_bandwidths);
-int cgroup_bonding_set_group_access(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid);
-int cgroup_bonding_set_group_access_list(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid);
+ uint64_t memory_limit;
-int cgroup_bonding_set_task_access(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid, int sticky);
-int cgroup_bonding_set_task_access_list(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid, int sticky);
+ CGroupDevicePolicy device_policy;
+ LIST_HEAD(CGroupDeviceAllow, device_allow);
+};
-int cgroup_bonding_kill(CGroupBonding *b, int sig, bool sigcont, bool rem, Set *s, const char *suffix);
-int cgroup_bonding_kill_list(CGroupBonding *first, int sig, bool sigcont, bool rem, Set *s, const char *suffix);
+#include "unit.h"
+#include "manager.h"
+#include "cgroup-util.h"
-void cgroup_bonding_trim(CGroupBonding *first, bool delete_root);
-void cgroup_bonding_trim_list(CGroupBonding *first, bool delete_root);
+void cgroup_context_init(CGroupContext *c);
+void cgroup_context_done(CGroupContext *c);
+void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix);
+void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const char *path);
+CGroupControllerMask cgroup_context_get_mask(CGroupContext *c);
-int cgroup_bonding_is_empty(CGroupBonding *b);
-int cgroup_bonding_is_empty_list(CGroupBonding *first);
+void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a);
+void cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w);
+void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockIODeviceBandwidth *b);
-CGroupBonding *cgroup_bonding_find_list(CGroupBonding *first, const char *controller) _pure_;
+int unit_realize_cgroup(Unit *u);
+void unit_destroy_cgroup(Unit *u);
-char *cgroup_bonding_to_string(CGroupBonding *b);
+int manager_setup_cgroup(Manager *m);
+void manager_shutdown_cgroup(Manager *m, bool delete);
-pid_t cgroup_bonding_search_main_pid(CGroupBonding *b);
-pid_t cgroup_bonding_search_main_pid_list(CGroupBonding *b);
+unsigned manager_dispatch_cgroup_queue(Manager *m);
-#include "manager.h"
+Unit *manager_get_unit_by_cgroup(Manager *m, const char *cgroup);
+Unit* manager_get_unit_by_pid(Manager *m, pid_t pid);
-int manager_setup_cgroup(Manager *m);
-void manager_shutdown_cgroup(Manager *m, bool delete);
+pid_t unit_search_main_pid(Unit *u);
-int cgroup_bonding_get(Manager *m, const char *cgroup, CGroupBonding **bonding);
-int cgroup_notify_empty(Manager *m, const char *group);
+int manager_notify_cgroup_empty(Manager *m, const char *group);
-Unit* cgroup_unit_by_pid(Manager *m, pid_t pid);
+const char* cgroup_device_policy_to_string(CGroupDevicePolicy i) _const_;
+CGroupDevicePolicy cgroup_device_policy_from_string(const char *s) _pure_;
diff --git a/src/core/condition.c b/src/core/condition.c
index 16cae6d23b..6c387450af 100644
--- a/src/core/condition.c
+++ b/src/core/condition.c
@@ -37,6 +37,7 @@
#include "virt.h"
#include "path-util.h"
#include "fileio.h"
+#include "unit.h"
Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate) {
Condition *c;
@@ -157,15 +158,28 @@ static bool test_virtualization(const char *parameter) {
return v > 0 && streq(parameter, id);
}
+static bool test_apparmor_enabled(void) {
+ int r;
+ _cleanup_free_ char *p = NULL;
+
+ r = read_one_line_file("/sys/module/apparmor/parameters/enabled", &p);
+ if (r < 0)
+ return false;
+
+ return parse_boolean(p) > 0;
+}
+
static bool test_security(const char *parameter) {
#ifdef HAVE_SELINUX
if (streq(parameter, "selinux"))
return is_selinux_enabled() > 0;
#endif
- if (streq(parameter, "apparmor"))
- return access("/sys/kernel/security/apparmor/", F_OK) == 0;
- if (streq(parameter, "smack"))
- return access("/sys/fs/smackfs", F_OK) == 0;
+ if (streq(parameter, "apparmor"))
+ return test_apparmor_enabled();
+ if (streq(parameter, "ima"))
+ return access("/sys/kernel/security/ima/", F_OK) == 0;
+ if (streq(parameter, "smack"))
+ return access("/sys/fs/smackfs", F_OK) == 0;
return false;
}
@@ -236,7 +250,7 @@ static bool test_ac_power(const char *parameter) {
return (on_ac_power() != 0) == !!r;
}
-bool condition_test(Condition *c) {
+static bool condition_test(Condition *c) {
assert(c);
switch(c->type) {
@@ -320,7 +334,7 @@ bool condition_test(Condition *c) {
}
}
-bool condition_test_list(Condition *first) {
+bool condition_test_list(const char *unit, Condition *first) {
Condition *c;
int triggered = -1;
@@ -335,6 +349,16 @@ bool condition_test_list(Condition *first) {
bool b;
b = condition_test(c);
+ if (unit)
+ log_debug_unit(unit,
+ "%s=%s%s%s %s for %s.",
+ condition_type_to_string(c->type),
+ c->trigger ? "|" : "",
+ c->negate ? "!" : "",
+ c->parameter,
+ b ? "succeeded" : "failed",
+ unit);
+ c->state = b ? 1 : -1;
if (!c->trigger && !b)
return false;
@@ -354,12 +378,13 @@ void condition_dump(Condition *c, FILE *f, const char *prefix) {
prefix = "";
fprintf(f,
- "%s\t%s: %s%s%s\n",
+ "%s\t%s: %s%s%s %s\n",
prefix,
condition_type_to_string(c->type),
c->trigger ? "|" : "",
c->negate ? "!" : "",
- c->parameter);
+ c->parameter,
+ c->state < 0 ? "failed" : c->state > 0 ? "succeeded" : "untested");
}
void condition_dump_list(Condition *first, FILE *f, const char *prefix) {
@@ -378,9 +403,11 @@ static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
[CONDITION_PATH_IS_READ_WRITE] = "ConditionPathIsReadWrite",
[CONDITION_DIRECTORY_NOT_EMPTY] = "ConditionDirectoryNotEmpty",
[CONDITION_FILE_NOT_EMPTY] = "ConditionFileNotEmpty",
+ [CONDITION_FILE_IS_EXECUTABLE] = "ConditionFileIsExecutable",
[CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine",
[CONDITION_VIRTUALIZATION] = "ConditionVirtualization",
[CONDITION_SECURITY] = "ConditionSecurity",
+ [CONDITION_CAPABILITY] = "ConditionCapability",
[CONDITION_HOST] = "ConditionHost",
[CONDITION_AC_POWER] = "ConditionACPower",
[CONDITION_NULL] = "ConditionNull"
diff --git a/src/core/condition.h b/src/core/condition.h
index 50ed955af9..1813b735a5 100644
--- a/src/core/condition.h
+++ b/src/core/condition.h
@@ -48,11 +48,14 @@ typedef enum ConditionType {
typedef struct Condition {
ConditionType type;
- char *parameter;
bool trigger:1;
bool negate:1;
+ char *parameter;
+
+ int state;
+
LIST_FIELDS(struct Condition, conditions);
} Condition;
@@ -60,8 +63,7 @@ Condition* condition_new(ConditionType type, const char *parameter, bool trigger
void condition_free(Condition *c);
void condition_free_list(Condition *c);
-bool condition_test(Condition *c);
-bool condition_test_list(Condition *c);
+bool condition_test_list(const char *unit, Condition *c);
void condition_dump(Condition *c, FILE *f, const char *prefix);
void condition_dump_list(Condition *c, FILE *f, const char *prefix);
diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c
new file mode 100644
index 0000000000..9ebcad9da6
--- /dev/null
+++ b/src/core/dbus-cgroup.c
@@ -0,0 +1,554 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ 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 <dbus/dbus.h>
+
+#include "path-util.h"
+#include "dbus-cgroup.h"
+
+static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_cgroup_append_device_policy, cgroup_device_policy, CGroupDevicePolicy);
+
+static int bus_cgroup_append_device_weights(DBusMessageIter *i, const char *property, void *data) {
+ DBusMessageIter sub, sub2;
+ CGroupContext *c = data;
+ CGroupBlockIODeviceWeight *w;
+
+ assert(i);
+ assert(property);
+ assert(c);
+
+ if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(st)", &sub))
+ return -ENOMEM;
+
+ LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
+
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &w->path) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &w->weight) ||
+ !dbus_message_iter_close_container(&sub, &sub2))
+ return -ENOMEM;
+ }
+
+ if (!dbus_message_iter_close_container(i, &sub))
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int bus_cgroup_append_device_bandwidths(DBusMessageIter *i, const char *property, void *data) {
+ DBusMessageIter sub, sub2;
+ CGroupContext *c = data;
+ CGroupBlockIODeviceBandwidth *b;
+
+ assert(i);
+ assert(property);
+ assert(c);
+
+ if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(st)", &sub))
+ return -ENOMEM;
+
+ LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
+
+ if (streq(property, "BlockIOReadBandwidth") != b->read)
+ continue;
+
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &b->path) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &b->bandwidth) ||
+ !dbus_message_iter_close_container(&sub, &sub2))
+ return -ENOMEM;
+ }
+
+ if (!dbus_message_iter_close_container(i, &sub))
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int bus_cgroup_append_device_allow(DBusMessageIter *i, const char *property, void *data) {
+ DBusMessageIter sub, sub2;
+ CGroupContext *c = data;
+ CGroupDeviceAllow *a;
+
+ assert(i);
+ assert(property);
+ assert(c);
+
+ if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(ss)", &sub))
+ return -ENOMEM;
+
+ LIST_FOREACH(device_allow, a, c->device_allow) {
+ const char *rwm;
+ char buf[4];
+ unsigned k = 0;
+
+ if (a->r)
+ buf[k++] = 'r';
+ if (a->w)
+ buf[k++] = 'w';
+ if (a->m)
+ buf[k++] = 'm';
+
+ buf[k] = 0;
+ rwm = buf;
+
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &a->path) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &rwm) ||
+ !dbus_message_iter_close_container(&sub, &sub2))
+ return -ENOMEM;
+ }
+
+ if (!dbus_message_iter_close_container(i, &sub))
+ return -ENOMEM;
+
+ return 0;
+}
+
+const BusProperty bus_cgroup_context_properties[] = {
+ { "CPUAccounting", bus_property_append_bool, "b", offsetof(CGroupContext, cpu_accounting) },
+ { "CPUShares", bus_property_append_ul, "t", offsetof(CGroupContext, cpu_shares) },
+ { "BlockIOAccounting", bus_property_append_bool, "b", offsetof(CGroupContext, blockio_accounting) },
+ { "BlockIOWeight", bus_property_append_ul, "t", offsetof(CGroupContext, blockio_weight) },
+ { "BlockIODeviceWeight", bus_cgroup_append_device_weights, "a(st)", 0 },
+ { "BlockIOReadBandwidth", bus_cgroup_append_device_bandwidths, "a(st)", 0 },
+ { "BlockIOWriteBandwidth", bus_cgroup_append_device_bandwidths, "a(st)", 0 },
+ { "MemoryAccounting", bus_property_append_bool, "b", offsetof(CGroupContext, memory_accounting) },
+ { "MemoryLimit", bus_property_append_uint64, "t", offsetof(CGroupContext, memory_limit) },
+ { "DevicePolicy", bus_cgroup_append_device_policy, "s", offsetof(CGroupContext, device_policy) },
+ { "DeviceAllow", bus_cgroup_append_device_allow, "a(ss)", 0 },
+ {}
+};
+
+int bus_cgroup_set_property(
+ Unit *u,
+ CGroupContext *c,
+ const char *name,
+ DBusMessageIter *i,
+ UnitSetPropertiesMode mode,
+ DBusError *error) {
+
+ assert(name);
+ assert(u);
+ assert(c);
+ assert(i);
+
+ if (streq(name, "CPUAccounting")) {
+
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
+ return -EINVAL;
+
+ if (mode != UNIT_CHECK) {
+ dbus_bool_t b;
+ dbus_message_iter_get_basic(i, &b);
+
+ c->cpu_accounting = b;
+ unit_write_drop_in_private(u, mode, name, b ? "CPUAccounting=yes" : "CPUAccounting=no");
+ }
+
+ return 1;
+
+ } else if (streq(name, "CPUShares")) {
+ uint64_t u64;
+ unsigned long ul;
+
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_UINT64)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(i, &u64);
+ ul = (unsigned long) u64;
+
+ if (u64 <= 0 || u64 != (uint64_t) ul)
+ return -EINVAL;
+
+ if (mode != UNIT_CHECK) {
+ c->cpu_shares = ul;
+ unit_write_drop_in_private_format(u, mode, name, "CPUShares=%lu", ul);
+ }
+
+ return 1;
+
+ } else if (streq(name, "BlockIOAccounting")) {
+
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
+ return -EINVAL;
+
+ if (mode != UNIT_CHECK) {
+ dbus_bool_t b;
+ dbus_message_iter_get_basic(i, &b);
+
+ c->blockio_accounting = b;
+ unit_write_drop_in_private(u, mode, name, b ? "BlockIOAccounting=yes" : "BlockIOAccounting=no");
+ }
+
+ return 1;
+
+ } else if (streq(name, "BlockIOWeight")) {
+ uint64_t u64;
+ unsigned long ul;
+
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_UINT64)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(i, &u64);
+ ul = (unsigned long) u64;
+
+ if (u64 < 10 || u64 > 1000)
+ return -EINVAL;
+
+ if (mode != UNIT_CHECK) {
+ c->blockio_weight = ul;
+ unit_write_drop_in_private_format(u, mode, name, "BlockIOWeight=%lu", ul);
+ }
+
+ return 1;
+
+ } else if (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth")) {
+ DBusMessageIter sub;
+ unsigned n = 0;
+ bool read = true;
+
+ if (streq(name, "BlockIOWriteBandwidth"))
+ read = false;
+
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(i) != DBUS_TYPE_STRUCT)
+ return -EINVAL;
+
+ dbus_message_iter_recurse(i, &sub);
+ while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
+ DBusMessageIter sub2;
+ const char *path;
+ uint64_t u64;
+ CGroupBlockIODeviceBandwidth *a;
+
+ dbus_message_iter_recurse(&sub, &sub2);
+ if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &u64, false) < 0)
+ return -EINVAL;
+
+ if (mode != UNIT_CHECK) {
+ CGroupBlockIODeviceBandwidth *b;
+ bool exist = false;
+
+ LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
+ if (path_equal(path, b->path) && read == b->read) {
+ a = b;
+ exist = true;
+ break;
+ }
+ }
+
+ if (!exist) {
+ a = new0(CGroupBlockIODeviceBandwidth, 1);
+ if (!a)
+ return -ENOMEM;
+
+ a->read = read;
+ a->path = strdup(path);
+ if (!a->path) {
+ free(a);
+ return -ENOMEM;
+ }
+ }
+
+ a->bandwidth = u64;
+
+ if (!exist)
+ LIST_PREPEND(CGroupBlockIODeviceBandwidth, device_bandwidths,
+ c->blockio_device_bandwidths, a);
+ }
+
+ n++;
+ dbus_message_iter_next(&sub);
+ }
+
+ if (mode != UNIT_CHECK) {
+ _cleanup_free_ char *buf = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+ CGroupBlockIODeviceBandwidth *a;
+ CGroupBlockIODeviceBandwidth *next;
+ size_t size = 0;
+
+ if (n == 0) {
+ LIST_FOREACH_SAFE(device_bandwidths, a, next, c->blockio_device_bandwidths)
+ if (a->read == read)
+ cgroup_context_free_blockio_device_bandwidth(c, a);
+ }
+
+ f = open_memstream(&buf, &size);
+ if (!f)
+ return -ENOMEM;
+
+ if (read) {
+ fputs("BlockIOReadBandwidth=\n", f);
+ LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
+ if (a->read)
+ fprintf(f, "BlockIOReadBandwidth=%s %" PRIu64 "\n", a->path, a->bandwidth);
+ } else {
+ fputs("BlockIOWriteBandwidth=\n", f);
+ LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
+ if (!a->read)
+ fprintf(f, "BlockIOWriteBandwidth=%s %" PRIu64 "\n", a->path, a->bandwidth);
+ }
+
+ fflush(f);
+ unit_write_drop_in_private(u, mode, name, buf);
+ }
+
+ return 1;
+
+ } else if (streq(name, "BlockIODeviceWeight")) {
+ DBusMessageIter sub;
+ unsigned n = 0;
+
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(i) != DBUS_TYPE_STRUCT)
+ return -EINVAL;
+
+ dbus_message_iter_recurse(i, &sub);
+ while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
+ DBusMessageIter sub2;
+ const char *path;
+ uint64_t u64;
+ unsigned long ul;
+ CGroupBlockIODeviceWeight *a;
+
+ dbus_message_iter_recurse(&sub, &sub2);
+
+ if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &u64, false) < 0)
+ return -EINVAL;
+
+ ul = (unsigned long) u64;
+ if (ul < 10 || ul > 1000)
+ return -EINVAL;
+
+ if (mode != UNIT_CHECK) {
+ CGroupBlockIODeviceWeight *b;
+ bool exist = false;
+
+ LIST_FOREACH(device_weights, b, c->blockio_device_weights) {
+ if (path_equal(b->path, path)) {
+ a = b;
+ exist = true;
+ break;
+ }
+ }
+
+ if (!exist) {
+ a = new0(CGroupBlockIODeviceWeight, 1);
+ if (!a)
+ return -ENOMEM;
+
+ a->path = strdup(path);
+ if (!a->path) {
+ free(a);
+ return -ENOMEM;
+ }
+ }
+
+ a->weight = ul;
+
+ if (!exist)
+ LIST_PREPEND(CGroupBlockIODeviceWeight, device_weights,
+ c->blockio_device_weights, a);
+ }
+
+ n++;
+ dbus_message_iter_next(&sub);
+ }
+
+ if (mode != UNIT_CHECK) {
+ _cleanup_free_ char *buf = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+ CGroupBlockIODeviceWeight *a;
+ size_t size = 0;
+
+ if (n == 0) {
+ while (c->blockio_device_weights)
+ cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
+ }
+
+ f = open_memstream(&buf, &size);
+ if (!f)
+ return -ENOMEM;
+
+ fputs("BlockIODeviceWeight=\n", f);
+ LIST_FOREACH(device_weights, a, c->blockio_device_weights)
+ fprintf(f, "BlockIODeviceWeight=%s %lu\n", a->path, a->weight);
+
+ fflush(f);
+ unit_write_drop_in_private(u, mode, name, buf);
+ }
+
+ return 1;
+
+ } else if (streq(name, "MemoryAccounting")) {
+
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
+ return -EINVAL;
+
+ if (mode != UNIT_CHECK) {
+ dbus_bool_t b;
+ dbus_message_iter_get_basic(i, &b);
+
+ c->memory_accounting = b;
+ unit_write_drop_in_private(u, mode, name, b ? "MemoryAccounting=yes" : "MemoryAccounting=no");
+ }
+
+ return 1;
+
+ } else if (streq(name, "MemoryLimit")) {
+
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_UINT64)
+ return -EINVAL;
+
+ if (mode != UNIT_CHECK) {
+ uint64_t limit;
+ dbus_message_iter_get_basic(i, &limit);
+
+ c->memory_limit = limit;
+ unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64, name, limit);
+ }
+
+ return 1;
+
+ } else if (streq(name, "DevicePolicy")) {
+ const char *policy;
+ CGroupDevicePolicy p;
+
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(i, &policy);
+ p = cgroup_device_policy_from_string(policy);
+ if (p < 0)
+ return -EINVAL;
+
+ if (mode != UNIT_CHECK) {
+ char *buf;
+
+ c->device_policy = p;
+
+ buf = strappenda("DevicePolicy=", policy);
+ unit_write_drop_in_private(u, mode, name, buf);
+ }
+
+ return 1;
+
+ } else if (streq(name, "DeviceAllow")) {
+ DBusMessageIter sub;
+ unsigned n = 0;
+
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(i) != DBUS_TYPE_STRUCT)
+ return -EINVAL;
+
+ dbus_message_iter_recurse(i, &sub);
+ while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
+ DBusMessageIter sub2;
+ const char *path, *rwm;
+ CGroupDeviceAllow *a;
+
+ dbus_message_iter_recurse(&sub, &sub2);
+
+ if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &rwm, false) < 0)
+ return -EINVAL;
+
+ if (!path_startswith(path, "/dev")) {
+ dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "DeviceAllow= requires device node");
+ return -EINVAL;
+ }
+
+ if (isempty(rwm))
+ rwm = "rwm";
+
+ if (!in_charset(rwm, "rwm")) {
+ dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "DeviceAllow= requires combination of rwm flags");
+ return -EINVAL;
+ }
+
+ if (mode != UNIT_CHECK) {
+ CGroupDeviceAllow *b;
+ bool exist = false;
+
+ LIST_FOREACH(device_allow, b, c->device_allow) {
+ if (path_equal(b->path, path)) {
+ a = b;
+ exist = true;
+ break;
+ }
+ }
+
+ if (!exist) {
+ a = new0(CGroupDeviceAllow, 1);
+ if (!a)
+ return -ENOMEM;
+
+ a->path = strdup(path);
+ if (!a->path) {
+ free(a);
+ return -ENOMEM;
+ }
+ }
+
+ a->r = !!strchr(rwm, 'r');
+ a->w = !!strchr(rwm, 'w');
+ a->m = !!strchr(rwm, 'm');
+
+ if (!exist)
+ LIST_PREPEND(CGroupDeviceAllow, device_allow, c->device_allow, a);
+ }
+
+ n++;
+ dbus_message_iter_next(&sub);
+ }
+
+ if (mode != UNIT_CHECK) {
+ _cleanup_free_ char *buf = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+ CGroupDeviceAllow *a;
+ size_t size = 0;
+
+ if (n == 0) {
+ while (c->device_allow)
+ cgroup_context_free_device_allow(c, c->device_allow);
+ }
+
+ f = open_memstream(&buf, &size);
+ if (!f)
+ return -ENOMEM;
+
+ fputs("DeviceAllow=\n", f);
+ LIST_FOREACH(device_allow, a, c->device_allow)
+ fprintf(f, "DeviceAllow=%s %s%s%s\n", a->path, a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
+
+ fflush(f);
+ unit_write_drop_in_private(u, mode, name, buf);
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/src/core/dbus-cgroup.h b/src/core/dbus-cgroup.h
new file mode 100644
index 0000000000..e5ac4c3af7
--- /dev/null
+++ b/src/core/dbus-cgroup.h
@@ -0,0 +1,45 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#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 <dbus/dbus.h>
+
+#include "manager.h"
+#include "dbus-common.h"
+#include "cgroup.h"
+
+#define BUS_CGROUP_CONTEXT_INTERFACE \
+ " <property name=\"CPUAccounting\" type=\"b\" access=\"read\"/>\n" \
+ " <property name=\"CPUShares\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"BlockIOAccounting\" type=\"b\" access=\"read\"/>\n" \
+ " <property name=\"BlockIOWeight\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"BlockIODeviceWeight\" type=\"a(st)\" access=\"read\"/>\n" \
+ " <property name=\"BlockIOReadBandwidth=\" type=\"a(st)\" access=\"read\"/>\n" \
+ " <property name=\"BlockIOWriteBandwidth=\" type=\"a(st)\" access=\"read\"/>\n" \
+ " <property name=\"MemoryAccounting\" type=\"b\" access=\"read\"/>\n" \
+ " <property name=\"MemoryLimit\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"DevicePolicy\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"DeviceAllow\" type=\"a(ss)\" access=\"read\"/>\n"
+
+extern const BusProperty bus_cgroup_context_properties[];
+
+int bus_cgroup_set_property(Unit *u, CGroupContext *c, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index 2a8a0e1ac5..2402e8c34d 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -31,10 +31,10 @@
#include "syscall-list.h"
#include "fileio.h"
-DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_input, exec_input, ExecInput);
-DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_output, exec_output, ExecOutput);
+static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_input, exec_input, ExecInput);
+static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_output, exec_output, ExecOutput);
-int bus_execute_append_env_files(DBusMessageIter *i, const char *property, void *data) {
+static int bus_execute_append_env_files(DBusMessageIter *i, const char *property, void *data) {
char **env_files = data, **j;
DBusMessageIter sub, sub2;
@@ -66,7 +66,7 @@ int bus_execute_append_env_files(DBusMessageIter *i, const char *property, void
return 0;
}
-int bus_execute_append_oom_score_adjust(DBusMessageIter *i, const char *property, void *data) {
+static int bus_execute_append_oom_score_adjust(DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
int32_t n;
@@ -77,12 +77,11 @@ int bus_execute_append_oom_score_adjust(DBusMessageIter *i, const char *property
if (c->oom_score_adjust_set)
n = c->oom_score_adjust;
else {
- char *t;
+ _cleanup_free_ char *t = NULL;
n = 0;
if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0) {
safe_atoi(t, &n);
- free(t);
}
}
@@ -92,7 +91,7 @@ int bus_execute_append_oom_score_adjust(DBusMessageIter *i, const char *property
return 0;
}
-int bus_execute_append_nice(DBusMessageIter *i, const char *property, void *data) {
+static int bus_execute_append_nice(DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
int32_t n;
@@ -111,7 +110,7 @@ int bus_execute_append_nice(DBusMessageIter *i, const char *property, void *data
return 0;
}
-int bus_execute_append_ioprio(DBusMessageIter *i, const char *property, void *data) {
+static int bus_execute_append_ioprio(DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
int32_t n;
@@ -130,7 +129,7 @@ int bus_execute_append_ioprio(DBusMessageIter *i, const char *property, void *da
return 0;
}
-int bus_execute_append_cpu_sched_policy(DBusMessageIter *i, const char *property, void *data) {
+static int bus_execute_append_cpu_sched_policy(DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
int32_t n;
@@ -149,7 +148,7 @@ int bus_execute_append_cpu_sched_policy(DBusMessageIter *i, const char *property
return 0;
}
-int bus_execute_append_cpu_sched_priority(DBusMessageIter *i, const char *property, void *data) {
+static int bus_execute_append_cpu_sched_priority(DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
int32_t n;
@@ -174,7 +173,7 @@ int bus_execute_append_cpu_sched_priority(DBusMessageIter *i, const char *proper
return 0;
}
-int bus_execute_append_affinity(DBusMessageIter *i, const char *property, void *data) {
+static int bus_execute_append_affinity(DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
dbus_bool_t b;
DBusMessageIter sub;
@@ -200,7 +199,7 @@ int bus_execute_append_affinity(DBusMessageIter *i, const char *property, void *
return 0;
}
-int bus_execute_append_timer_slack_nsec(DBusMessageIter *i, const char *property, void *data) {
+static int bus_execute_append_timer_slack_nsec(DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
uint64_t u;
@@ -219,7 +218,7 @@ int bus_execute_append_timer_slack_nsec(DBusMessageIter *i, const char *property
return 0;
}
-int bus_execute_append_capability_bs(DBusMessageIter *i, const char *property, void *data) {
+static int bus_execute_append_capability_bs(DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
uint64_t normal, inverted;
@@ -236,7 +235,7 @@ int bus_execute_append_capability_bs(DBusMessageIter *i, const char *property, v
return bus_property_append_uint64(i, property, &inverted);
}
-int bus_execute_append_capabilities(DBusMessageIter *i, const char *property, void *data) {
+static int bus_execute_append_capabilities(DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
char *t = NULL;
const char *s;
@@ -265,7 +264,7 @@ int bus_execute_append_capabilities(DBusMessageIter *i, const char *property, vo
return 0;
}
-int bus_execute_append_rlimits(DBusMessageIter *i, const char *property, void *data) {
+static int bus_execute_append_rlimits(DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
int r;
uint64_t u;
@@ -347,7 +346,7 @@ int bus_execute_append_command(DBusMessageIter *i, const char *property, void *d
return 0;
}
-int bus_execute_append_syscall_filter(DBusMessageIter *i, const char *property, void *data) {
+static int bus_execute_append_syscall_filter(DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
dbus_bool_t b;
DBusMessageIter sub;
@@ -430,10 +429,8 @@ const BusProperty bus_exec_context_properties[] = {
{ "PrivateNetwork", bus_property_append_bool, "b", offsetof(ExecContext, private_network) },
{ "SameProcessGroup", bus_property_append_bool, "b", offsetof(ExecContext, same_pgrp) },
{ "UtmpIdentifier", bus_property_append_string, "s", offsetof(ExecContext, utmp_id), true },
- { "ControlGroupModify", bus_property_append_bool, "b", offsetof(ExecContext, control_group_modify) },
- { "ControlGroupPersistent", bus_property_append_tristate_false, "b", offsetof(ExecContext, control_group_persistent) },
{ "IgnoreSIGPIPE", bus_property_append_bool, "b", offsetof(ExecContext, ignore_sigpipe) },
{ "NoNewPrivileges", bus_property_append_bool, "b", offsetof(ExecContext, no_new_privileges) },
{ "SystemCallFilter", bus_execute_append_syscall_filter, "au", 0 },
- { NULL, }
+ {}
};
diff --git a/src/core/dbus-execute.h b/src/core/dbus-execute.h
index 91d70e535f..79bf30838a 100644
--- a/src/core/dbus-execute.h
+++ b/src/core/dbus-execute.h
@@ -63,7 +63,7 @@
" <property name=\"CPUSchedulingPolicy\" type=\"i\" access=\"read\"/>\n" \
" <property name=\"CPUSchedulingPriority\" type=\"i\" access=\"read\"/>\n" \
" <property name=\"CPUAffinity\" type=\"ay\" access=\"read\"/>\n" \
- " <property name=\"TimerSlackNS\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"TimerSlackNSec\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"CPUSchedulingResetOnFork\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"NonBlocking\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"StandardInput\" type=\"s\" access=\"read\"/>\n" \
@@ -92,8 +92,6 @@
" <property name=\"PrivateNetwork\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"SameProcessGroup\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"UtmpIdentifier\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"ControlGroupModify\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"ControlGroupPersistent\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"IgnoreSIGPIPE\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"NoNewPrivileges\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"SystemCallFilter\" type=\"au\" access=\"read\"/>\n"
@@ -106,18 +104,4 @@ extern const BusProperty bus_exec_context_properties[];
#define BUS_EXEC_COMMAND_PROPERTY(name, command, indirect) \
{ name, bus_execute_append_command, "a(sasbttttuii)", (command), (indirect), NULL }
-int bus_execute_append_output(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_input(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_oom_score_adjust(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_nice(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_ioprio(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_cpu_sched_policy(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_cpu_sched_priority(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_affinity(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_timer_slack_nsec(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_capabilities(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_capability_bs(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_rlimits(DBusMessageIter *i, const char *property, void *data);
int bus_execute_append_command(DBusMessageIter *u, const char *property, void *data);
-int bus_execute_append_env_files(DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_syscall_filter(DBusMessageIter *i, const char *property, void *data);
diff --git a/src/core/dbus-job.c b/src/core/dbus-job.c
index 98ccfa62ec..4ab88d06c3 100644
--- a/src/core/dbus-job.c
+++ b/src/core/dbus-job.c
@@ -60,7 +60,7 @@ static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_job_append_type, job_type, JobType);
static int bus_job_append_unit(DBusMessageIter *i, const char *property, void *data) {
Job *j = data;
DBusMessageIter sub;
- char *p;
+ _cleanup_free_ char *p = NULL;
assert(i);
assert(property);
@@ -75,12 +75,9 @@ static int bus_job_append_unit(DBusMessageIter *i, const char *property, void *d
if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &j->unit->id) ||
!dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &p)) {
- free(p);
return -ENOMEM;
}
- free(p);
-
if (!dbus_message_iter_close_container(i, &sub))
return -ENOMEM;
@@ -136,7 +133,7 @@ static DBusHandlerResult bus_job_message_handler(DBusConnection *connection, DBu
/* Be nice to gdbus and return introspection data for our mid-level paths */
if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
- char *introspection = NULL;
+ _cleanup_free_ char *introspection = NULL;
FILE *f;
Iterator i;
size_t size;
@@ -169,7 +166,6 @@ static DBusHandlerResult bus_job_message_handler(DBusConnection *connection, DBu
if (ferror(f)) {
fclose(f);
- free(introspection);
goto oom;
}
@@ -179,12 +175,9 @@ static DBusHandlerResult bus_job_message_handler(DBusConnection *connection, DBu
goto oom;
if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
- free(introspection);
goto oom;
}
- free(introspection);
-
if (!bus_maybe_send_reply(connection, message, reply))
goto oom;
@@ -261,55 +254,51 @@ static int job_send_message(Job *j, DBusMessage* (*new_message)(Job *j)) {
}
static DBusMessage* new_change_signal_message(Job *j) {
- DBusMessage *m = NULL;
- char *p = NULL;
+ _cleanup_free_ char *p = NULL;
+ DBusMessage *m;
p = job_dbus_path(j);
if (!p)
- goto oom;
+ return NULL;
if (j->sent_dbus_new_signal) {
/* Send a properties changed signal */
m = bus_properties_changed_new(p, "org.freedesktop.systemd1.Job", INVALIDATING_PROPERTIES);
if (!m)
- goto oom;
+ return NULL;
} else {
/* Send a new signal */
m = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "JobNew");
if (!m)
- goto oom;
+ return NULL;
if (!dbus_message_append_args(m,
DBUS_TYPE_UINT32, &j->id,
DBUS_TYPE_OBJECT_PATH, &p,
DBUS_TYPE_STRING, &j->unit->id,
- DBUS_TYPE_INVALID))
- goto oom;
+ DBUS_TYPE_INVALID)) {
+ dbus_message_unref(m);
+ return NULL;
+ }
}
return m;
-
-oom:
- if (m)
- dbus_message_unref(m);
- free(p);
- return NULL;
}
static DBusMessage* new_removed_signal_message(Job *j) {
- DBusMessage *m = NULL;
- char *p = NULL;
+ _cleanup_free_ char *p = NULL;
+ DBusMessage *m;
const char *r;
p = job_dbus_path(j);
if (!p)
- goto oom;
+ return NULL;
m = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "JobRemoved");
if (!m)
- goto oom;
+ return NULL;
r = job_result_to_string(j->result);
@@ -318,16 +307,12 @@ static DBusMessage* new_removed_signal_message(Job *j) {
DBUS_TYPE_OBJECT_PATH, &p,
DBUS_TYPE_STRING, &j->unit->id,
DBUS_TYPE_STRING, &r,
- DBUS_TYPE_INVALID))
- goto oom;
+ DBUS_TYPE_INVALID)) {
+ dbus_message_unref(m);
+ return NULL;
+ }
return m;
-
-oom:
- if (m)
- dbus_message_unref(m);
- free(p);
- return NULL;
}
void bus_job_send_change_signal(Job *j) {
diff --git a/src/core/dbus-kill.c b/src/core/dbus-kill.c
index 165f63074b..811adb1b5a 100644
--- a/src/core/dbus-kill.c
+++ b/src/core/dbus-kill.c
@@ -25,11 +25,83 @@
#include "dbus-kill.h"
#include "dbus-common.h"
-DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_kill_append_mode, kill_mode, KillMode);
+static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_kill_append_mode, kill_mode, KillMode);
const BusProperty bus_kill_context_properties[] = {
{ "KillMode", bus_kill_append_mode, "s", offsetof(KillContext, kill_mode) },
{ "KillSignal", bus_property_append_int, "i", offsetof(KillContext, kill_signal) },
{ "SendSIGKILL", bus_property_append_bool, "b", offsetof(KillContext, send_sigkill) },
- { NULL, }
+ { "SendSIGHUP", bus_property_append_bool, "b", offsetof(KillContext, send_sighup) },
+ {}
};
+
+int bus_kill_context_set_transient_property(
+ Unit *u,
+ KillContext *c,
+ const char *name,
+ DBusMessageIter *i,
+ UnitSetPropertiesMode mode,
+ DBusError *error) {
+
+ assert(u);
+ assert(c);
+ assert(name);
+ assert(i);
+
+ if (streq(name, "KillMode")) {
+ const char *m;
+ KillMode k;
+
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(i, &m);
+
+ k = kill_mode_from_string(m);
+ if (k < 0)
+ return -EINVAL;
+
+ if (mode != UNIT_CHECK) {
+ c->kill_mode = k;
+
+ unit_write_drop_in_private_format(u, mode, name, "KillMode=%s\n", kill_mode_to_string(k));
+ }
+
+ return 1;
+
+ } else if (streq(name, "SendSIGHUP")) {
+
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
+ return -EINVAL;
+
+ if (mode != UNIT_CHECK) {
+ dbus_bool_t b;
+
+ dbus_message_iter_get_basic(i, &b);
+ c->send_sighup = b;
+
+ unit_write_drop_in_private_format(u, mode, name, "SendSIGHUP=%s\n", yes_no(b));
+ }
+
+ return 1;
+
+ } else if (streq(name, "SendSIGKILL")) {
+
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
+ return -EINVAL;
+
+ if (mode != UNIT_CHECK) {
+ dbus_bool_t b;
+
+ dbus_message_iter_get_basic(i, &b);
+ c->send_sigkill = b;
+
+ unit_write_drop_in_private_format(u, mode, name, "SendSIGKILL=%s\n", yes_no(b));
+ }
+
+ return 1;
+
+ }
+
+ return 0;
+}
diff --git a/src/core/dbus-kill.h b/src/core/dbus-kill.h
index 238fbd36d6..7676d98e91 100644
--- a/src/core/dbus-kill.h
+++ b/src/core/dbus-kill.h
@@ -29,11 +29,9 @@
#define BUS_KILL_CONTEXT_INTERFACE \
" <property name=\"KillMode\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"KillSignal\" type=\"i\" access=\"read\"/>\n" \
- " <property name=\"SendSIGKILL\" type=\"b\" access=\"read\"/>\n"
-
-#define BUS_KILL_COMMAND_INTERFACE(name) \
- " <property name=\"" name "\" type=\"a(sasbttuii)\" access=\"read\"/>\n"
+ " <property name=\"SendSIGKILL\" type=\"b\" access=\"read\"/>\n" \
+ " <property name=\"SendSIGHUP\" type=\"b\" access=\"read\"/>\n"
extern const BusProperty bus_kill_context_properties[];
-int bus_kill_append_mode(DBusMessageIter *i, const char *property, void *data);
+int bus_kill_context_set_transient_property(Unit *u, KillContext *c, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 56b02a1cf5..676a07ffa5 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -103,32 +103,6 @@
" <method name=\"ResetFailedUnit\">\n" \
" <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
" </method>\n" \
- " <method name=\"SetUnitControlGroup\">\n" \
- " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"group\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"UnsetUnitControlGroup\">\n" \
- " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"group\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"\n/>" \
- " </method>\n" \
- " <method name=\"GetUnitControlGroupAttribute\">\n" \
- " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"attribute\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"values\" type=\"as\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"SetUnitControlGroupAttribute\">\n" \
- " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"attribute\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"values\" type=\"as\" direction=\"in\"/>\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"\n/>" \
- " </method>\n" \
- " <method name=\"UnsetUnitControlGroupAttributes\">\n" \
- " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"attribute\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " </method>\n" \
" <method name=\"GetJob\">\n" \
" <arg name=\"id\" type=\"u\" direction=\"in\"/>\n" \
" <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
@@ -178,8 +152,8 @@
" <arg name=\"unset\" type=\"as\" direction=\"in\"/>\n" \
" <arg name=\"set\" type=\"as\" direction=\"in\"/>\n" \
" </method>\n" \
- " <method name=\"ListUnitFiles\">\n" \
- " <arg name=\"files\" type=\"a(ss)\" direction=\"out\"/>\n" \
+ " <method name=\"ListUnitFiles\">\n" \
+ " <arg name=\"files\" type=\"a(ss)\" direction=\"out\"/>\n" \
" </method>\n" \
" <method name=\"GetUnitFileState\">\n" \
" <arg name=\"file\" type=\"s\" direction=\"in\"/>\n" \
@@ -227,6 +201,25 @@
" <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
" <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
" <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ " <method name=\"SetDefaultTarget\">\n" \
+ " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
+ " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ " <method name=\"GetDefaultTarget\">\n" \
+ " <arg name=\"name\" type=\"s\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ " <method name=\"SetUnitProperties\">\n" \
+ " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
+ " <arg name=\"properties\" type=\"a(sv)\" direction=\"in\"/>\n" \
+ " </method>\n" \
+ " <method name=\"StartTransientUnit\">\n" \
+ " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"properties\" type=\"a(sv)\" direction=\"in\"/>\n" \
+ " <arg name=\"aux\" type=\"a(sa(sv))\" direction=\"in\"/>\n" \
+ " <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
" </method>\n"
#define BUS_MANAGER_INTERFACE_SIGNALS \
@@ -257,7 +250,10 @@
" <arg name=\"userspace\" type=\"t\"/>\n" \
" <arg name=\"total\" type=\"t\"/>\n" \
" </signal>" \
- " <signal name=\"UnitFilesChanged\"/>\n"
+ " <signal name=\"UnitFilesChanged\"/>\n" \
+ " <signal name=\"Reloading\">\n" \
+ " <arg name=\"active\" type=\"b\"/>\n" \
+ " </signal>"
#define BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
" <property name=\"Version\" type=\"s\" access=\"read\"/>\n" \
@@ -275,6 +271,14 @@
" <property name=\"UserspaceTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"FinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"GeneratorsStartTimestamp\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"GeneratorsStartTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"GeneratorsFinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"GeneratorsFinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"UnitsLoadStartTimestamp\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"UnitsLoadStartTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"UnitsLoadFinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"UnitsLoadFinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"LogLevel\" type=\"s\" access=\"readwrite\"/>\n" \
" <property name=\"LogTarget\" type=\"s\" access=\"readwrite\"/>\n" \
" <property name=\"NNames\" type=\"u\" access=\"read\"/>\n" \
@@ -286,8 +290,6 @@
" <property name=\"ConfirmSpawn\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"ShowStatus\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"UnitPath\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"DefaultControllers\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"DefaultStandardOutput\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"DefaultStandardError\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"RuntimeWatchdogUSec\" type=\"t\" access=\"readwrite\"/>\n" \
@@ -384,7 +386,7 @@ static int bus_manager_set_log_target(DBusMessageIter *i, const char *property,
}
static int bus_manager_append_log_level(DBusMessageIter *i, const char *property, void *data) {
- char *t;
+ _cleanup_free_ char *t = NULL;
int r;
assert(i);
@@ -397,7 +399,6 @@ static int bus_manager_append_log_level(DBusMessageIter *i, const char *property
if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
r = -ENOMEM;
- free(t);
return r;
}
@@ -580,6 +581,14 @@ static const BusProperty bus_manager_properties[] = {
{ "UserspaceTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, userspace_timestamp.monotonic) },
{ "FinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.realtime) },
{ "FinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, finish_timestamp.monotonic) },
+ { "GeneratorsStartTimestamp", bus_property_append_uint64, "t", offsetof(Manager, generators_start_timestamp.realtime) },
+ { "GeneratorsStartTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, generators_start_timestamp.monotonic) },
+ { "GeneratorsFinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, generators_finish_timestamp.realtime) },
+ { "GeneratorsFinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, generators_finish_timestamp.monotonic) },
+ { "UnitsLoadStartTimestamp", bus_property_append_uint64, "t", offsetof(Manager, unitsload_start_timestamp.realtime) },
+ { "UnitsLoadStartTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, unitsload_start_timestamp.monotonic) },
+ { "UnitsLoadFinishTimestamp", bus_property_append_uint64, "t", offsetof(Manager, unitsload_finish_timestamp.realtime) },
+ { "UnitsLoadFinishTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, unitsload_finish_timestamp.monotonic) },
{ "LogLevel", bus_manager_append_log_level, "s", 0, false, bus_manager_set_log_level },
{ "LogTarget", bus_manager_append_log_target, "s", 0, false, bus_manager_set_log_target },
{ "NNames", bus_manager_append_n_names, "u", 0 },
@@ -591,8 +600,6 @@ static const BusProperty bus_manager_properties[] = {
{ "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) },
{ "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) },
{ "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true },
- { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_hierarchy), true },
- { "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true },
{ "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) },
{ "DefaultStandardError", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_error) },
{ "RuntimeWatchdogUSec", bus_property_append_usec, "t", offsetof(Manager, runtime_watchdog), false, bus_manager_set_runtime_watchdog_usec },
@@ -662,7 +669,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
- u = cgroup_unit_by_pid(m, (pid_t) pid);
+ u = manager_get_unit_by_pid(m, (pid_t) pid);
if (!u) {
dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
return bus_send_error_reply(connection, message, &error, -ENOENT);
@@ -875,151 +882,6 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
if (!reply)
goto oom;
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetUnitControlGroup")) {
- const char *name;
- Unit *u;
- DBusMessageIter iter;
-
- if (!dbus_message_iter_init(message, &iter))
- goto oom;
-
- r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- u = manager_get_unit(m, name);
- if (!u) {
- dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
- return bus_send_error_reply(connection, message, &error, -ENOENT);
- }
-
- SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
-
- r = bus_unit_cgroup_set(u, &iter);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetUnitControlGroup")) {
- const char *name;
- Unit *u;
- DBusMessageIter iter;
-
- if (!dbus_message_iter_init(message, &iter))
- goto oom;
-
- r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- u = manager_get_unit(m, name);
- if (!u) {
- dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
- return bus_send_error_reply(connection, message, &error, -ENOENT);
- }
-
- SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
-
- r = bus_unit_cgroup_unset(u, &iter);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetUnitControlGroupAttribute")) {
- const char *name;
- Unit *u;
- DBusMessageIter iter;
-
- if (!dbus_message_iter_init(message, &iter))
- goto oom;
-
- r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- u = manager_get_unit(m, name);
- if (!u) {
- dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
- return bus_send_error_reply(connection, message, &error, -ENOENT);
- }
-
- SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
-
- r = bus_unit_cgroup_attribute_set(u, &iter);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetUnitControlGroupAttribute")) {
- const char *name;
- Unit *u;
- DBusMessageIter iter;
-
- if (!dbus_message_iter_init(message, &iter))
- goto oom;
-
- r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- u = manager_get_unit(m, name);
- if (!u) {
- dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
- return bus_send_error_reply(connection, message, &error, -ENOENT);
- }
-
- SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
-
- r = bus_unit_cgroup_attribute_unset(u, &iter);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitControlGroupAttribute")) {
- const char *name;
- Unit *u;
- DBusMessageIter iter;
- _cleanup_strv_free_ char **list = NULL;
-
- if (!dbus_message_iter_init(message, &iter))
- goto oom;
-
- r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- u = manager_get_unit(m, name);
- if (!u) {
- dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
- return bus_send_error_reply(connection, message, &error, -ENOENT);
- }
-
- SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
-
- r = bus_unit_cgroup_attribute_get(u, &iter, &list);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- dbus_message_iter_init_append(reply, &iter);
- if (bus_append_strv_iter(&iter, list) < 0)
- goto oom;
-
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
DBusMessageIter iter, sub;
Iterator i;
@@ -1170,17 +1032,9 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
SELINUX_ACCESS_CHECK(connection, message, "status");
- s = BUS_CONNECTION_SUBSCRIBED(m, connection);
- if (!s) {
- s = set_new(string_hash_func, string_compare_func);
- if (!s)
- goto oom;
-
- if (!dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL)) {
- set_free(s);
- goto oom;
- }
- }
+ s = bus_acquire_subscribed(m, connection);
+ if (!s)
+ goto oom;
client = strdup(bus_message_get_sender_with_fallback(message));
if (!client)
@@ -1309,7 +1163,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
- char *introspection = NULL;
+ _cleanup_free_ char *introspection = NULL;
FILE *f;
Iterator i;
Unit *u;
@@ -1335,7 +1189,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
fputs(INTROSPECTION_BEGIN, f);
HASHMAP_FOREACH_KEY(u, k, m->units, i) {
- char *p;
+ _cleanup_free_ char *p = NULL;
if (k != u->id)
continue;
@@ -1343,12 +1197,10 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
p = bus_path_escape(k);
if (!p) {
fclose(f);
- free(introspection);
goto oom;
}
fprintf(f, "<node name=\"unit/%s\"/>", p);
- free(p);
}
HASHMAP_FOREACH(j, m->jobs, i)
@@ -1358,7 +1210,6 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
if (ferror(f)) {
fclose(f);
- free(introspection);
goto oom;
}
@@ -1368,12 +1219,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
goto oom;
if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
- free(introspection);
goto oom;
}
-
- free(introspection);
-
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
SELINUX_ACCESS_CHECK(connection, message, "reload");
@@ -1728,7 +1575,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
- dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles")) {
+ dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles") ||
+ dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetDefaultTarget")) {
char **l = NULL;
DBusMessageIter iter;
@@ -1771,6 +1619,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
carries_install_info = r;
} else if (streq(member, "MaskUnitFiles"))
r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
+ else if (streq(member, "SetDefaultTarget"))
+ r = unit_file_set_default(scope, NULL, l[0], &changes, &n_changes);
else
assert_not_reached("Uh? Wrong method");
@@ -1838,6 +1688,111 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
if (!reply)
goto oom;
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetDefaultTarget")) {
+ UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
+ _cleanup_free_ char *default_target = NULL;
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ r = unit_file_get_default(scope, NULL, &default_target);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &default_target, DBUS_TYPE_INVALID)) {
+ goto oom;
+ }
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetUnitProperties")) {
+ DBusMessageIter iter;
+ dbus_bool_t runtime;
+ const char *name;
+ Unit *u;
+
+ if (!dbus_message_iter_init(message, &iter))
+ goto oom;
+
+ if (bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true) < 0 ||
+ bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0)
+ return bus_send_error_reply(connection, message, NULL, -EINVAL);
+
+ u = manager_get_unit(m, name);
+ if (!u) {
+ dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
+ }
+
+ SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
+
+ r = bus_unit_set_properties(u, &iter, runtime ? UNIT_RUNTIME : UNIT_PERSISTENT, true, &error);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, &error, r);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartTransientUnit")) {
+ const char *name, *smode;
+ DBusMessageIter iter;
+ JobMode mode;
+ UnitType t;
+ Unit *u;
+
+ if (!dbus_message_iter_init(message, &iter))
+ goto oom;
+
+ if (bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true) < 0 ||
+ bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &smode, true) < 0)
+ return bus_send_error_reply(connection, message, NULL, -EINVAL);
+
+ t = unit_name_to_type(name);
+ if (t < 0)
+ return bus_send_error_reply(connection, message, NULL, -EINVAL);
+ if (!unit_vtable[t]->can_transient) {
+ dbus_set_error(&error, DBUS_ERROR_INVALID_ARGS, "Unit type %s does not support transient units.", unit_type_to_string(t));
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+ }
+
+ mode = job_mode_from_string(smode);
+ if (mode < 0) {
+ dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+ }
+
+ r = manager_load_unit(m, name, NULL, NULL, &u);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, &error, r);
+
+ SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
+
+ if (u->load_state != UNIT_NOT_FOUND || set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0) {
+ dbus_set_error(&error, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name);
+ return bus_send_error_reply(connection, message, &error, -EEXIST);
+ }
+
+ /* OK, the unit failed to load and is unreferenced,
+ * now let's fill in the transient data instead */
+ r = unit_make_transient(u);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, &error, r);
+
+ /* Set our properties */
+ r = bus_unit_set_properties(u, &iter, UNIT_RUNTIME, false, &error);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, &error, r);
+
+ /* And load this stub fully */
+ r = unit_load(u);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, &error, r);
+
+ manager_dispatch_load_queue(m);
+
+ /* Finally, start it */
+ return bus_unit_queue_job(connection, message, u, JOB_START, mode, false);
+
} else {
const BusBoundProperties bps[] = {
{ "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
diff --git a/src/core/dbus-mount.c b/src/core/dbus-mount.c
index 0fcceb500d..72e187063c 100644
--- a/src/core/dbus-mount.c
+++ b/src/core/dbus-mount.c
@@ -22,11 +22,12 @@
#include <errno.h>
#include "dbus-unit.h"
-#include "dbus-mount.h"
-#include "dbus-kill.h"
#include "dbus-execute.h"
+#include "dbus-kill.h"
+#include "dbus-cgroup.h"
#include "dbus-common.h"
#include "selinux-access.h"
+#include "dbus-mount.h"
#define BUS_MOUNT_INTERFACE \
" <interface name=\"org.freedesktop.systemd1.Mount\">\n" \
@@ -35,12 +36,13 @@
" <property name=\"Options\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"Type\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"TimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
+ BUS_UNIT_CGROUP_INTERFACE \
BUS_EXEC_COMMAND_INTERFACE("ExecMount") \
BUS_EXEC_COMMAND_INTERFACE("ExecUnmount") \
BUS_EXEC_COMMAND_INTERFACE("ExecRemount") \
BUS_EXEC_CONTEXT_INTERFACE \
BUS_KILL_CONTEXT_INTERFACE \
- BUS_UNIT_CGROUP_INTERFACE \
+ BUS_CGROUP_CONTEXT_INTERFACE \
" <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
" <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
" <property name=\"Result\" type=\"s\" access=\"read\"/>\n" \
@@ -156,11 +158,12 @@ DBusHandlerResult bus_mount_message_handler(Unit *u, DBusConnection *c, DBusMess
Mount *m = MOUNT(u);
const BusBoundProperties bps[] = {
- { "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
- { "org.freedesktop.systemd1.Mount", bus_mount_properties, m },
- { "org.freedesktop.systemd1.Mount", bus_exec_context_properties, &m->exec_context },
- { "org.freedesktop.systemd1.Mount", bus_kill_context_properties, &m->kill_context },
- { "org.freedesktop.systemd1.Mount", bus_unit_cgroup_properties, u },
+ { "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
+ { "org.freedesktop.systemd1.Mount", bus_unit_cgroup_properties, u },
+ { "org.freedesktop.systemd1.Mount", bus_mount_properties, m },
+ { "org.freedesktop.systemd1.Mount", bus_exec_context_properties, &m->exec_context },
+ { "org.freedesktop.systemd1.Mount", bus_kill_context_properties, &m->kill_context },
+ { "org.freedesktop.systemd1.Mount", bus_cgroup_context_properties, &m->cgroup_context },
{ NULL, }
};
@@ -168,3 +171,31 @@ DBusHandlerResult bus_mount_message_handler(Unit *u, DBusConnection *c, DBusMess
return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps );
}
+
+int bus_mount_set_property(
+ Unit *u,
+ const char *name,
+ DBusMessageIter *i,
+ UnitSetPropertiesMode mode,
+ DBusError *error) {
+
+ Mount *m = MOUNT(u);
+ int r;
+
+ assert(name);
+ assert(u);
+ assert(i);
+
+ r = bus_cgroup_set_property(u, &m->cgroup_context, name, i, mode, error);
+ if (r != 0)
+ return r;
+
+ return 0;
+}
+
+int bus_mount_commit_properties(Unit *u) {
+ assert(u);
+
+ unit_realize_cgroup(u);
+ return 0;
+}
diff --git a/src/core/dbus-mount.h b/src/core/dbus-mount.h
index 8597394373..f4ec8b1625 100644
--- a/src/core/dbus-mount.h
+++ b/src/core/dbus-mount.h
@@ -27,5 +27,8 @@
DBusHandlerResult bus_mount_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
+int bus_mount_set_property(Unit *u, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+int bus_mount_commit_properties(Unit *u);
+
extern const char bus_mount_interface[];
extern const char bus_mount_invalidating_properties[];
diff --git a/src/core/dbus-scope.c b/src/core/dbus-scope.c
new file mode 100644
index 0000000000..783a969fb3
--- /dev/null
+++ b/src/core/dbus-scope.c
@@ -0,0 +1,189 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ 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>
+
+#include "dbus-unit.h"
+#include "dbus-common.h"
+#include "dbus-cgroup.h"
+#include "dbus-kill.h"
+#include "selinux-access.h"
+#include "dbus-scope.h"
+
+#define BUS_SCOPE_INTERFACE \
+ " <interface name=\"org.freedesktop.systemd1.Scope\">\n" \
+ BUS_UNIT_CGROUP_INTERFACE \
+ " <property name=\"TimeoutStopUSec\" type=\"t\" access=\"read\"/>\n" \
+ BUS_KILL_CONTEXT_INTERFACE \
+ BUS_CGROUP_CONTEXT_INTERFACE \
+ " <property name=\"Result\" type=\"s\" access=\"read\"/>\n" \
+ " </interface>\n"
+
+#define INTROSPECTION \
+ DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
+ "<node>\n" \
+ BUS_UNIT_INTERFACE \
+ BUS_SCOPE_INTERFACE \
+ BUS_PROPERTIES_INTERFACE \
+ BUS_PEER_INTERFACE \
+ BUS_INTROSPECTABLE_INTERFACE \
+ "</node>\n"
+
+#define INTERFACES_LIST \
+ BUS_UNIT_INTERFACES_LIST \
+ "org.freedesktop.systemd1.Scope\0"
+
+const char bus_scope_interface[] _introspect_("Scope") = BUS_SCOPE_INTERFACE;
+
+static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_scope_append_scope_result, scope_result, ScopeResult);
+
+static const BusProperty bus_scope_properties[] = {
+ { "TimeoutStopUSec", bus_property_append_usec, "t", offsetof(Scope, timeout_stop_usec) },
+ { "Result", bus_scope_append_scope_result, "s", offsetof(Scope, result) },
+ {}
+};
+
+DBusHandlerResult bus_scope_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
+ Scope *s = SCOPE(u);
+
+ const BusBoundProperties bps[] = {
+ { "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
+ { "org.freedesktop.systemd1.Scope", bus_unit_cgroup_properties, u },
+ { "org.freedesktop.systemd1.Scope", bus_scope_properties, s },
+ { "org.freedesktop.systemd1.Scope", bus_cgroup_context_properties, &s->cgroup_context },
+ { "org.freedesktop.systemd1.Scope", bus_kill_context_properties, &s->kill_context },
+ {}
+ };
+
+ SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
+
+ return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
+}
+
+static int bus_scope_set_transient_property(
+ Scope *s,
+ const char *name,
+ DBusMessageIter *i,
+ UnitSetPropertiesMode mode,
+ DBusError *error) {
+
+ int r;
+
+ assert(name);
+ assert(s);
+ assert(i);
+
+ if (streq(name, "PIDs")) {
+ DBusMessageIter sub;
+ unsigned n = 0;
+
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(i) != DBUS_TYPE_UINT32)
+ return -EINVAL;
+
+ r = set_ensure_allocated(&s->pids, trivial_hash_func, trivial_compare_func);
+ if (r < 0)
+ return r;
+
+ dbus_message_iter_recurse(i, &sub);
+ while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32) {
+ uint32_t pid;
+
+ dbus_message_iter_get_basic(&sub, &pid);
+
+ if (pid <= 1)
+ return -EINVAL;
+
+ if (mode != UNIT_CHECK) {
+ r = set_put(s->pids, LONG_TO_PTR(pid));
+ if (r < 0 && r != -EEXIST)
+ return r;
+ }
+
+ dbus_message_iter_next(&sub);
+ n++;
+ }
+
+ if (n <= 0)
+ return -EINVAL;
+
+ return 1;
+
+ } else if (streq(name, "TimeoutStopUSec")) {
+
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_UINT64)
+ return -EINVAL;
+
+ if (mode != UNIT_CHECK) {
+ uint64_t t;
+
+ dbus_message_iter_get_basic(i, &t);
+
+ s->timeout_stop_usec = t;
+
+ unit_write_drop_in_format(UNIT(s), mode, name, "[Scope]\nTimeoutStopSec=%lluus\n", (unsigned long long) t);
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+int bus_scope_set_property(
+ Unit *u,
+ const char *name,
+ DBusMessageIter *i,
+ UnitSetPropertiesMode mode,
+ DBusError *error) {
+
+ Scope *s = SCOPE(u);
+ int r;
+
+ assert(name);
+ assert(u);
+ assert(i);
+
+ r = bus_cgroup_set_property(u, &s->cgroup_context, name, i, mode, error);
+ if (r != 0)
+ return r;
+
+ if (u->load_state == UNIT_STUB) {
+ /* While we are created we still accept PIDs */
+
+ r = bus_scope_set_transient_property(s, name, i, mode, error);
+ if (r != 0)
+ return r;
+
+ r = bus_kill_context_set_transient_property(u, &s->kill_context, name, i, mode, error);
+ if (r != 0)
+ return r;
+ }
+
+ return 0;
+}
+
+int bus_scope_commit_properties(Unit *u) {
+ assert(u);
+
+ unit_realize_cgroup(u);
+ return 0;
+}
diff --git a/src/core/dbus-scope.h b/src/core/dbus-scope.h
new file mode 100644
index 0000000000..e6836f13f0
--- /dev/null
+++ b/src/core/dbus-scope.h
@@ -0,0 +1,33 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#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 <dbus/dbus.h>
+
+#include "unit.h"
+
+DBusHandlerResult bus_scope_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
+
+int bus_scope_set_property(Unit *u, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+int bus_scope_commit_properties(Unit *u);
+
+extern const char bus_scope_interface[];
diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c
index e06a5dce97..696c4462fe 100644
--- a/src/core/dbus-service.c
+++ b/src/core/dbus-service.c
@@ -21,12 +21,15 @@
#include <errno.h>
+#include "strv.h"
+#include "path-util.h"
#include "dbus-unit.h"
#include "dbus-execute.h"
#include "dbus-kill.h"
-#include "dbus-service.h"
+#include "dbus-cgroup.h"
#include "dbus-common.h"
#include "selinux-access.h"
+#include "dbus-service.h"
#define BUS_SERVICE_INTERFACE \
" <interface name=\"org.freedesktop.systemd1.Service\">\n" \
@@ -35,13 +38,15 @@
" <property name=\"PIDFile\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"NotifyAccess\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"RestartUSec\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"TimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"TimeoutStartUSec\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"TimeoutStopUSec\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"WatchdogUSec\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"WatchdogTimestamp\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"WatchdogTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"StartLimitInterval\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"StartLimitBurst\" type=\"u\" access=\"read\"/>\n" \
" <property name=\"StartLimitAction\" type=\"s\" access=\"readwrite\"/>\n" \
+ BUS_UNIT_CGROUP_INTERFACE \
BUS_EXEC_COMMAND_INTERFACE("ExecStartPre") \
BUS_EXEC_COMMAND_INTERFACE("ExecStart") \
BUS_EXEC_COMMAND_INTERFACE("ExecStartPost") \
@@ -50,7 +55,7 @@
BUS_EXEC_COMMAND_INTERFACE("ExecStopPost") \
BUS_EXEC_CONTEXT_INTERFACE \
BUS_KILL_CONTEXT_INTERFACE \
- BUS_UNIT_CGROUP_INTERFACE \
+ BUS_CGROUP_CONTEXT_INTERFACE \
" <property name=\"PermissionsStartOnly\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"RootDirectoryStartOnly\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"RemainAfterExit\" type=\"b\" access=\"read\"/>\n" \
@@ -103,12 +108,12 @@ static DEFINE_BUS_PROPERTY_SET_ENUM(bus_service_set_start_limit_action, start_li
static const BusProperty bus_exec_main_status_properties[] = {
{ "ExecMainStartTimestamp", bus_property_append_usec, "t", offsetof(ExecStatus, start_timestamp.realtime) },
{ "ExecMainStartTimestampMonotonic",bus_property_append_usec, "t", offsetof(ExecStatus, start_timestamp.monotonic) },
- { "ExecMainExitTimestamp", bus_property_append_usec, "t", offsetof(ExecStatus, start_timestamp.realtime) },
- { "ExecMainExitTimestampMonotonic", bus_property_append_usec, "t", offsetof(ExecStatus, start_timestamp.monotonic) },
+ { "ExecMainExitTimestamp", bus_property_append_usec, "t", offsetof(ExecStatus, exit_timestamp.realtime) },
+ { "ExecMainExitTimestampMonotonic", bus_property_append_usec, "t", offsetof(ExecStatus, exit_timestamp.monotonic) },
{ "ExecMainPID", bus_property_append_pid, "u", offsetof(ExecStatus, pid) },
{ "ExecMainCode", bus_property_append_int, "i", offsetof(ExecStatus, code) },
{ "ExecMainStatus", bus_property_append_int, "i", offsetof(ExecStatus, status) },
- { NULL, }
+ {}
};
static const BusProperty bus_service_properties[] = {
@@ -117,7 +122,6 @@ static const BusProperty bus_service_properties[] = {
{ "PIDFile", bus_property_append_string, "s", offsetof(Service, pid_file), true },
{ "NotifyAccess", bus_service_append_notify_access, "s", offsetof(Service, notify_access) },
{ "RestartUSec", bus_property_append_usec, "t", offsetof(Service, restart_usec) },
- { "TimeoutUSec", bus_property_append_usec, "t", offsetof(Service, timeout_start_usec) },
{ "TimeoutStartUSec", bus_property_append_usec, "t", offsetof(Service, timeout_start_usec) },
{ "TimeoutStopUSec", bus_property_append_usec, "t", offsetof(Service, timeout_stop_usec) },
{ "WatchdogUSec", bus_property_append_usec, "t", offsetof(Service, watchdog_usec) },
@@ -141,7 +145,7 @@ static const BusProperty bus_service_properties[] = {
{ "BusName", bus_property_append_string, "s", offsetof(Service, bus_name), true },
{ "StatusText", bus_property_append_string, "s", offsetof(Service, status_text), true },
{ "Result", bus_service_append_service_result,"s", offsetof(Service, result) },
- { NULL, }
+ {}
};
DBusHandlerResult bus_service_message_handler(Unit *u, DBusConnection *connection, DBusMessage *message) {
@@ -149,15 +153,184 @@ DBusHandlerResult bus_service_message_handler(Unit *u, DBusConnection *connectio
const BusBoundProperties bps[] = {
{ "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
+ { "org.freedesktop.systemd1.Service", bus_unit_cgroup_properties, u },
{ "org.freedesktop.systemd1.Service", bus_service_properties, s },
{ "org.freedesktop.systemd1.Service", bus_exec_context_properties, &s->exec_context },
{ "org.freedesktop.systemd1.Service", bus_kill_context_properties, &s->kill_context },
+ { "org.freedesktop.systemd1.Service", bus_cgroup_context_properties, &s->cgroup_context },
{ "org.freedesktop.systemd1.Service", bus_exec_main_status_properties, &s->main_exec_status },
- { "org.freedesktop.systemd1.Service", bus_unit_cgroup_properties, u },
- { NULL, }
+ {}
};
SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps);
}
+
+static int bus_service_set_transient_property(
+ Service *s,
+ const char *name,
+ DBusMessageIter *i,
+ UnitSetPropertiesMode mode,
+ DBusError *error) {
+
+ int r;
+
+ assert(name);
+ assert(s);
+ assert(i);
+
+ if (streq(name, "RemainAfterExit")) {
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
+ return -EINVAL;
+
+ if (mode != UNIT_CHECK) {
+ dbus_bool_t b;
+
+ dbus_message_iter_get_basic(i, &b);
+
+ s->remain_after_exit = b;
+ unit_write_drop_in_private_format(UNIT(s), mode, name, "RemainAfterExit=%s\n", yes_no(b));
+ }
+
+ return 1;
+
+ } else if (streq(name, "ExecStart")) {
+ DBusMessageIter sub;
+ unsigned n = 0;
+
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(i) != DBUS_TYPE_STRUCT)
+ return -EINVAL;
+
+ dbus_message_iter_recurse(i, &sub);
+ while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
+ _cleanup_strv_free_ char **argv = NULL;
+ DBusMessageIter sub2;
+ dbus_bool_t ignore;
+ const char *path;
+
+ dbus_message_iter_recurse(&sub, &sub2);
+
+ if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
+ return -EINVAL;
+
+ if (!path_is_absolute(path)) {
+ dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
+ return -EINVAL;
+ }
+
+ r = bus_parse_strv_iter(&sub2, &argv);
+ if (r < 0)
+ return r;
+
+ dbus_message_iter_next(&sub2);
+
+ if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) < 0)
+ return -EINVAL;
+
+ if (mode != UNIT_CHECK) {
+ ExecCommand *c;
+
+ c = new0(ExecCommand, 1);
+ if (!c)
+ return -ENOMEM;
+
+ c->path = strdup(path);
+ if (!c->path) {
+ free(c);
+ return -ENOMEM;
+ }
+
+ c->argv = argv;
+ argv = NULL;
+
+ c->ignore = ignore;
+
+ path_kill_slashes(c->path);
+ exec_command_append_list(&s->exec_command[SERVICE_EXEC_START], c);
+ }
+
+ n++;
+ dbus_message_iter_next(&sub);
+ }
+
+ if (mode != UNIT_CHECK) {
+ _cleanup_free_ char *buf = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+ ExecCommand *c;
+ size_t size = 0;
+
+ if (n == 0) {
+ exec_command_free_list(s->exec_command[SERVICE_EXEC_START]);
+ s->exec_command[SERVICE_EXEC_START] = NULL;
+ }
+
+ f = open_memstream(&buf, &size);
+ if (!f)
+ return -ENOMEM;
+
+ fputs("ExecStart=\n", f);
+
+ LIST_FOREACH(command, c, s->exec_command[SERVICE_EXEC_START]) {
+ _cleanup_free_ char *a;
+
+ a = strv_join_quoted(c->argv);
+ if (!a)
+ return -ENOMEM;
+
+ fprintf(f, "ExecStart=%s@%s %s\n",
+ c->ignore ? "-" : "",
+ c->path,
+ a);
+ }
+
+ fflush(f);
+ unit_write_drop_in_private(UNIT(s), mode, name, buf);
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+int bus_service_set_property(
+ Unit *u,
+ const char *name,
+ DBusMessageIter *i,
+ UnitSetPropertiesMode mode,
+ DBusError *error) {
+
+ Service *s = SERVICE(u);
+ int r;
+
+ assert(name);
+ assert(u);
+ assert(i);
+
+ r = bus_cgroup_set_property(u, &s->cgroup_context, name, i, mode, error);
+ if (r != 0)
+ return r;
+
+ if (u->transient && u->load_state == UNIT_STUB) {
+ /* This is a transient unit, let's load a little more */
+
+ r = bus_service_set_transient_property(s, name, i, mode, error);
+ if (r != 0)
+ return r;
+
+ r = bus_kill_context_set_transient_property(u, &s->kill_context, name, i, mode, error);
+ if (r != 0)
+ return r;
+ }
+
+ return 0;
+}
+
+int bus_service_commit_properties(Unit *u) {
+ assert(u);
+
+ unit_realize_cgroup(u);
+ return 0;
+}
diff --git a/src/core/dbus-service.h b/src/core/dbus-service.h
index 143aed7ae5..9b9f13701c 100644
--- a/src/core/dbus-service.h
+++ b/src/core/dbus-service.h
@@ -27,5 +27,8 @@
DBusHandlerResult bus_service_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
+int bus_service_set_property(Unit *u, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+int bus_service_commit_properties(Unit *u);
+
extern const char bus_service_interface[];
extern const char bus_service_invalidating_properties[];
diff --git a/src/core/dbus-slice.c b/src/core/dbus-slice.c
new file mode 100644
index 0000000000..dac9fbdf5f
--- /dev/null
+++ b/src/core/dbus-slice.c
@@ -0,0 +1,93 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ 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>
+
+#include "dbus-unit.h"
+#include "dbus-common.h"
+#include "dbus-cgroup.h"
+#include "selinux-access.h"
+#include "dbus-slice.h"
+
+#define BUS_SLICE_INTERFACE \
+ " <interface name=\"org.freedesktop.systemd1.Slice\">\n" \
+ BUS_UNIT_CGROUP_INTERFACE \
+ BUS_CGROUP_CONTEXT_INTERFACE \
+ " </interface>\n"
+
+#define INTROSPECTION \
+ DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
+ "<node>\n" \
+ BUS_UNIT_INTERFACE \
+ BUS_SLICE_INTERFACE \
+ BUS_PROPERTIES_INTERFACE \
+ BUS_PEER_INTERFACE \
+ BUS_INTROSPECTABLE_INTERFACE \
+ "</node>\n"
+
+#define INTERFACES_LIST \
+ BUS_UNIT_INTERFACES_LIST \
+ "org.freedesktop.systemd1.Slice\0"
+
+const char bus_slice_interface[] _introspect_("Slice") = BUS_SLICE_INTERFACE;
+
+DBusHandlerResult bus_slice_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
+ Slice *s = SLICE(u);
+
+ const BusBoundProperties bps[] = {
+ { "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
+ { "org.freedesktop.systemd1.Slice", bus_unit_cgroup_properties, u },
+ { "org.freedesktop.systemd1.Slice", bus_cgroup_context_properties, &s->cgroup_context },
+ {}
+ };
+
+ SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
+
+ return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
+}
+
+int bus_slice_set_property(
+ Unit *u,
+ const char *name,
+ DBusMessageIter *i,
+ UnitSetPropertiesMode mode,
+ DBusError *error) {
+
+ Slice *s = SLICE(u);
+ int r;
+
+ assert(name);
+ assert(u);
+ assert(i);
+
+ r = bus_cgroup_set_property(u, &s->cgroup_context, name, i, mode, error);
+ if (r != 0)
+ return r;
+
+ return 0;
+}
+
+int bus_slice_commit_properties(Unit *u) {
+ assert(u);
+
+ unit_realize_cgroup(u);
+ return 0;
+}
diff --git a/src/core/dbus-slice.h b/src/core/dbus-slice.h
new file mode 100644
index 0000000000..c5ac473763
--- /dev/null
+++ b/src/core/dbus-slice.h
@@ -0,0 +1,33 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#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 <dbus/dbus.h>
+
+#include "unit.h"
+
+DBusHandlerResult bus_slice_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
+
+int bus_slice_set_property(Unit *u, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+int bus_slice_commit_properties(Unit *u);
+
+extern const char bus_slice_interface[];
diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c
index 77d98ea0fd..30c4b6302c 100644
--- a/src/core/dbus-socket.c
+++ b/src/core/dbus-socket.c
@@ -22,24 +22,26 @@
#include <errno.h>
#include "dbus-unit.h"
-#include "dbus-socket.h"
#include "dbus-execute.h"
#include "dbus-kill.h"
+#include "dbus-cgroup.h"
#include "dbus-common.h"
#include "selinux-access.h"
+#include "dbus-socket.h"
#define BUS_SOCKET_INTERFACE \
" <interface name=\"org.freedesktop.systemd1.Socket\">\n" \
" <property name=\"BindIPv6Only\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"Backlog\" type=\"u\" access=\"read\"/>\n" \
" <property name=\"TimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
+ BUS_UNIT_CGROUP_INTERFACE \
BUS_EXEC_COMMAND_INTERFACE("ExecStartPre") \
BUS_EXEC_COMMAND_INTERFACE("ExecStartPost") \
BUS_EXEC_COMMAND_INTERFACE("ExecStopPre") \
BUS_EXEC_COMMAND_INTERFACE("ExecStopPost") \
BUS_EXEC_CONTEXT_INTERFACE \
BUS_KILL_CONTEXT_INTERFACE \
- BUS_UNIT_CGROUP_INTERFACE \
+ BUS_CGROUP_CONTEXT_INTERFACE \
" <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
" <property name=\"BindToDevice\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
@@ -65,6 +67,7 @@
" <property name=\"MessageQueueMessageSize\" type=\"x\" access=\"read\"/>\n" \
" <property name=\"Listen\" type=\"a(ss)\" access=\"read\"/>\n" \
" <property name=\"Result\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"ReusePort\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"SmackLabel\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"SmackLabelIPIn\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"SmackLabelIPOut\" type=\"s\" access=\"read\"/>\n" \
@@ -192,24 +195,54 @@ static const BusProperty bus_socket_properties[] = {
{ "MessageQueueMaxMessages", bus_property_append_long, "x", offsetof(Socket, mq_maxmsg) },
{ "MessageQueueMessageSize", bus_property_append_long, "x", offsetof(Socket, mq_msgsize) },
{ "Result", bus_socket_append_socket_result, "s", offsetof(Socket, result) },
+ { "ReusePort", bus_property_append_bool, "b", offsetof(Socket, reuseport) },
{ "SmackLabel", bus_property_append_string, "s", offsetof(Socket, smack), true },
{ "SmackLabelIPIn", bus_property_append_string, "s", offsetof(Socket, smack_ip_in), true },
{ "SmackLabelIPOut",bus_property_append_string, "s", offsetof(Socket, smack_ip_out), true },
- { NULL, }
+ {}
};
DBusHandlerResult bus_socket_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
Socket *s = SOCKET(u);
const BusBoundProperties bps[] = {
- { "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
- { "org.freedesktop.systemd1.Socket", bus_socket_properties, s },
- { "org.freedesktop.systemd1.Socket", bus_exec_context_properties, &s->exec_context },
- { "org.freedesktop.systemd1.Socket", bus_kill_context_properties, &s->kill_context },
- { "org.freedesktop.systemd1.Socket", bus_unit_properties, u },
- { NULL, }
+ { "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
+ { "org.freedesktop.systemd1.Socket", bus_unit_cgroup_properties, u },
+ { "org.freedesktop.systemd1.Socket", bus_socket_properties, s },
+ { "org.freedesktop.systemd1.Socket", bus_exec_context_properties, &s->exec_context },
+ { "org.freedesktop.systemd1.Socket", bus_kill_context_properties, &s->kill_context },
+ { "org.freedesktop.systemd1.Socket", bus_cgroup_context_properties, &s->cgroup_context },
+ {}
};
SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
}
+
+int bus_socket_set_property(
+ Unit *u,
+ const char *name,
+ DBusMessageIter *i,
+ UnitSetPropertiesMode mode,
+ DBusError *error) {
+
+ Socket *s = SOCKET(u);
+ int r;
+
+ assert(name);
+ assert(u);
+ assert(i);
+
+ r = bus_cgroup_set_property(u, &s->cgroup_context, name, i, mode, error);
+ if (r != 0)
+ return r;
+
+ return 0;
+}
+
+int bus_socket_commit_properties(Unit *u) {
+ assert(u);
+
+ unit_realize_cgroup(u);
+ return 0;
+}
diff --git a/src/core/dbus-socket.h b/src/core/dbus-socket.h
index 5369b22e5e..eb035c1a94 100644
--- a/src/core/dbus-socket.h
+++ b/src/core/dbus-socket.h
@@ -27,5 +27,8 @@
DBusHandlerResult bus_socket_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
+int bus_socket_set_property(Unit *u, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+int bus_socket_commit_properties(Unit *u);
+
extern const char bus_socket_interface[];
extern const char bus_socket_invalidating_properties[];
diff --git a/src/core/dbus-swap.c b/src/core/dbus-swap.c
index 2e99fba7db..06edfdcde4 100644
--- a/src/core/dbus-swap.c
+++ b/src/core/dbus-swap.c
@@ -23,22 +23,24 @@
#include <errno.h>
#include "dbus-unit.h"
-#include "dbus-swap.h"
#include "dbus-execute.h"
#include "dbus-kill.h"
+#include "dbus-cgroup.h"
#include "dbus-common.h"
#include "selinux-access.h"
+#include "dbus-swap.h"
#define BUS_SWAP_INTERFACE \
" <interface name=\"org.freedesktop.systemd1.Swap\">\n" \
" <property name=\"What\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"Priority\" type=\"i\" access=\"read\"/>\n" \
" <property name=\"TimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
+ BUS_UNIT_CGROUP_INTERFACE \
BUS_EXEC_COMMAND_INTERFACE("ExecActivate") \
BUS_EXEC_COMMAND_INTERFACE("ExecDeactivate") \
BUS_EXEC_CONTEXT_INTERFACE \
BUS_KILL_CONTEXT_INTERFACE \
- BUS_UNIT_CGROUP_INTERFACE \
+ BUS_CGROUP_CONTEXT_INTERFACE \
" <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
" <property name=\"Result\" type=\"s\" access=\"read\"/>\n" \
" </interface>\n"
@@ -93,6 +95,7 @@ static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_swap_append_swap_result, swap_result,
static const BusProperty bus_swap_properties[] = {
{ "What", bus_property_append_string, "s", offsetof(Swap, what), true },
{ "Priority", bus_swap_append_priority, "i", 0 },
+ { "TimeoutUSec",bus_property_append_usec, "t", offsetof(Swap, timeout_usec)},
BUS_EXEC_COMMAND_PROPERTY("ExecActivate", offsetof(Swap, exec_command[SWAP_EXEC_ACTIVATE]), false),
BUS_EXEC_COMMAND_PROPERTY("ExecDeactivate", offsetof(Swap, exec_command[SWAP_EXEC_DEACTIVATE]), false),
{ "ControlPID", bus_property_append_pid, "u", offsetof(Swap, control_pid) },
@@ -103,11 +106,12 @@ static const BusProperty bus_swap_properties[] = {
DBusHandlerResult bus_swap_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
Swap *s = SWAP(u);
const BusBoundProperties bps[] = {
- { "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
- { "org.freedesktop.systemd1.Swap", bus_swap_properties, s },
- { "org.freedesktop.systemd1.Swap", bus_exec_context_properties, &s->exec_context },
- { "org.freedesktop.systemd1.Swap", bus_kill_context_properties, &s->kill_context },
- { "org.freedesktop.systemd1.Swap", bus_unit_cgroup_properties, u },
+ { "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
+ { "org.freedesktop.systemd1.Swap", bus_unit_cgroup_properties, u },
+ { "org.freedesktop.systemd1.Swap", bus_swap_properties, s },
+ { "org.freedesktop.systemd1.Swap", bus_exec_context_properties, &s->exec_context },
+ { "org.freedesktop.systemd1.Swap", bus_kill_context_properties, &s->kill_context },
+ { "org.freedesktop.systemd1.Swap", bus_cgroup_context_properties, &s->cgroup_context },
{ NULL, }
};
@@ -115,3 +119,31 @@ DBusHandlerResult bus_swap_message_handler(Unit *u, DBusConnection *c, DBusMessa
return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
}
+
+int bus_swap_set_property(
+ Unit *u,
+ const char *name,
+ DBusMessageIter *i,
+ UnitSetPropertiesMode mode,
+ DBusError *error) {
+
+ Swap *s = SWAP(u);
+ int r;
+
+ assert(name);
+ assert(u);
+ assert(i);
+
+ r = bus_cgroup_set_property(u, &s->cgroup_context, name, i, mode, error);
+ if (r != 0)
+ return r;
+
+ return 0;
+}
+
+int bus_swap_commit_properties(Unit *u) {
+ assert(u);
+
+ unit_realize_cgroup(u);
+ return 0;
+}
diff --git a/src/core/dbus-swap.h b/src/core/dbus-swap.h
index 41fe4447ff..9b586a1ad2 100644
--- a/src/core/dbus-swap.h
+++ b/src/core/dbus-swap.h
@@ -28,5 +28,8 @@
DBusHandlerResult bus_swap_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
+int bus_swap_set_property(Unit *u, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+int bus_swap_commit_properties(Unit *u);
+
extern const char bus_swap_interface[];
extern const char bus_swap_invalidating_properties[];
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index 575f8eb36a..2ea59b2913 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -81,6 +81,22 @@ static int bus_unit_append_following(DBusMessageIter *i, const char *property, v
return 0;
}
+static int bus_unit_append_slice(DBusMessageIter *i, const char *property, void *data) {
+ Unit *u = data;
+ const char *d;
+
+ assert(i);
+ assert(property);
+ assert(u);
+
+ d = strempty(unit_slice_name(u));
+
+ if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &d))
+ return -ENOMEM;
+
+ return 0;
+}
+
static int bus_unit_append_dependencies(DBusMessageIter *i, const char *property, void *data) {
Unit *u;
Iterator j;
@@ -279,101 +295,69 @@ static int bus_unit_append_job(DBusMessageIter *i, const char *property, void *d
return 0;
}
-static int bus_unit_append_default_cgroup(DBusMessageIter *i, const char *property, void *data) {
+static int bus_unit_append_need_daemon_reload(DBusMessageIter *i, const char *property, void *data) {
Unit *u = data;
- char *t;
- CGroupBonding *cgb;
- bool success;
+ dbus_bool_t b;
assert(i);
assert(property);
assert(u);
- cgb = unit_get_default_cgroup(u);
- if (cgb) {
- t = cgroup_bonding_to_string(cgb);
- if (!t)
- return -ENOMEM;
- } else
- t = (char*) "";
-
- success = dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t);
-
- if (cgb)
- free(t);
-
- return success ? 0 : -ENOMEM;
-}
-
-static int bus_unit_append_cgroups(DBusMessageIter *i, const char *property, void *data) {
- Unit *u = data;
- CGroupBonding *cgb;
- DBusMessageIter sub;
-
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "s", &sub))
- return -ENOMEM;
-
- LIST_FOREACH(by_unit, cgb, u->cgroup_bondings) {
- _cleanup_free_ char *t = NULL;
- bool success;
-
- t = cgroup_bonding_to_string(cgb);
- if (!t)
- return -ENOMEM;
-
- success = dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &t);
- if (!success)
- return -ENOMEM;
- }
+ b = unit_need_daemon_reload(u);
- if (!dbus_message_iter_close_container(i, &sub))
+ if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
return -ENOMEM;
return 0;
}
-static int bus_unit_append_cgroup_attrs(DBusMessageIter *i, const char *property, void *data) {
- Unit *u = data;
- CGroupAttribute *a;
- DBusMessageIter sub, sub2;
-
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sss)", &sub))
- return -ENOMEM;
+static int bus_property_append_condition(DBusMessageIter *i, const char *property, void *data) {
+ Condition **cp = data;
+ Condition *c;
+ const char *name, *param;
+ dbus_bool_t trigger, negate;
+ dbus_int32_t state;
+ DBusMessageIter sub;
- LIST_FOREACH(by_unit, a, u->cgroup_attributes) {
- _cleanup_free_ char *v = NULL;
- bool success;
+ assert(i);
+ assert(property);
+ assert(cp);
- if (a->semantics && a->semantics->map_write)
- a->semantics->map_write(a->semantics, a->value, &v);
+ c = *cp;
+ assert(c);
- success =
- dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) &&
- dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &a->controller) &&
- dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &a->name) &&
- dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, v ? &v : &a->value) &&
- dbus_message_iter_close_container(&sub, &sub2);
- if (!success)
- return -ENOMEM;
- }
+ name = condition_type_to_string(c->type);
+ param = c->parameter;
+ trigger = c->trigger;
+ negate = c->negate;
+ state = c->state;
- if (!dbus_message_iter_close_container(i, &sub))
+ if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub) ||
+ !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &name) ||
+ !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &trigger) ||
+ !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &negate) ||
+ !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &param) ||
+ !dbus_message_iter_append_basic(&sub, DBUS_TYPE_INT32, &state) ||
+ !dbus_message_iter_close_container(i, &sub))
return -ENOMEM;
return 0;
}
-static int bus_unit_append_need_daemon_reload(DBusMessageIter *i, const char *property, void *data) {
- Unit *u = data;
- dbus_bool_t b;
+static int bus_property_append_condition_list(DBusMessageIter *i, const char *property, void *data) {
+ Condition **first = data, *c;
+ DBusMessageIter sub;
assert(i);
- assert(property);
- assert(u);
+ assert(data);
- b = unit_need_daemon_reload(u);
+ if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sbbsi)", &sub))
+ return -ENOMEM;
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
+ LIST_FOREACH(conditions, c, *first)
+ bus_property_append_condition(&sub, property, &c);
+
+ if (!dbus_message_iter_close_container(i, &sub))
return -ENOMEM;
return 0;
@@ -471,86 +455,21 @@ static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *conn
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
-
- } else if (streq_ptr(dbus_message_get_member(message), "SetControlGroup")) {
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "SetProperties")) {
DBusMessageIter iter;
-
- SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
+ dbus_bool_t runtime;
if (!dbus_message_iter_init(message, &iter))
goto oom;
- r = bus_unit_cgroup_set(u, &iter);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (streq_ptr(dbus_message_get_member(message), "UnsetControlGroup")) {
- DBusMessageIter iter;
-
- SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
-
- if (!dbus_message_iter_init(message, &iter))
- goto oom;
-
- r = bus_unit_cgroup_unset(u, &iter);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
- } else if (streq_ptr(dbus_message_get_member(message), "GetControlGroupAttribute")) {
- DBusMessageIter iter;
- _cleanup_strv_free_ char **list = NULL;
-
- SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
-
- if (!dbus_message_iter_init(message, &iter))
- goto oom;
-
- r = bus_unit_cgroup_attribute_get(u, &iter, &list);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- dbus_message_iter_init_append(reply, &iter);
- if (bus_append_strv_iter(&iter, list) < 0)
- goto oom;
-
- } else if (streq_ptr(dbus_message_get_member(message), "SetControlGroupAttribute")) {
- DBusMessageIter iter;
+ if (bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0)
+ return bus_send_error_reply(connection, message, NULL, -EINVAL);
SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
- if (!dbus_message_iter_init(message, &iter))
- goto oom;
-
- r = bus_unit_cgroup_attribute_set(u, &iter);
+ r = bus_unit_set_properties(u, &iter, runtime ? UNIT_RUNTIME : UNIT_PERSISTENT, true, &error);
if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
-
- reply = dbus_message_new_method_return(message);
- if (!reply)
- goto oom;
-
- } else if (streq_ptr(dbus_message_get_member(message), "UnsetControlGroupAttribute")) {
- DBusMessageIter iter;
-
- SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
-
- if (!dbus_message_iter_init(message, &iter))
- goto oom;
-
- r = bus_unit_cgroup_attribute_unset(u, &iter);
- if (r < 0)
- return bus_send_error_reply(connection, message, NULL, r);
+ return bus_send_error_reply(connection, message, &error, r);
reply = dbus_message_new_method_return(message);
if (!reply)
@@ -701,8 +620,9 @@ const DBusObjectPathVTable bus_unit_vtable = {
};
void bus_unit_send_change_signal(Unit *u) {
- _cleanup_free_ char *p = NULL;
_cleanup_dbus_message_unref_ DBusMessage *m = NULL;
+ _cleanup_free_ char *p = NULL;
+ int r;
assert(u);
@@ -720,8 +640,10 @@ void bus_unit_send_change_signal(Unit *u) {
}
p = unit_dbus_path(u);
- if (!p)
- goto oom;
+ if (!p) {
+ log_oom();
+ return;
+ }
if (u->sent_dbus_new_signal) {
/* Send a properties changed signal. First for the
@@ -734,19 +656,26 @@ void bus_unit_send_change_signal(Unit *u) {
m = bus_properties_changed_new(p,
UNIT_VTABLE(u)->bus_interface,
UNIT_VTABLE(u)->bus_invalidating_properties);
- if (!m)
- goto oom;
+ if (!m) {
+ log_oom();
+ return;
+ }
- if (bus_broadcast(u->manager, m) < 0)
- goto oom;
+ r = bus_broadcast(u->manager, m);
+ if (r < 0) {
+ log_error("Failed to broadcast change message: %s", strerror(-r));
+ return;
+ }
dbus_message_unref(m);
}
m = bus_properties_changed_new(p, "org.freedesktop.systemd1.Unit",
INVALIDATING_PROPERTIES);
- if (!m)
- goto oom;
+ if (!m) {
+ log_oom();
+ return;
+ }
} else {
/* Send a new signal */
@@ -754,25 +683,27 @@ void bus_unit_send_change_signal(Unit *u) {
m = dbus_message_new_signal("/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"UnitNew");
- if (!m)
- goto oom;
+ if (!m) {
+ log_oom();
+ return;
+ }
if (!dbus_message_append_args(m,
DBUS_TYPE_STRING, &u->id,
DBUS_TYPE_OBJECT_PATH, &p,
- DBUS_TYPE_INVALID))
- goto oom;
+ DBUS_TYPE_INVALID)) {
+ log_oom();
+ return;
+ }
}
- if (bus_broadcast(u->manager, m) < 0)
- goto oom;
+ r = bus_broadcast(u->manager, m);
+ if (r < 0) {
+ log_error("Failed to broadcast UnitNew/PropertiesChanged message.");
+ return;
+ }
u->sent_dbus_new_signal = true;
-
- return;
-
-oom:
- log_oom();
}
void bus_unit_send_removed_signal(Unit *u) {
@@ -849,7 +780,7 @@ DBusHandlerResult bus_unit_queue_job(
(type == JOB_START || type == JOB_RESTART || type == JOB_TRY_RESTART) ? "start" :
type == JOB_STOP ? "stop" : "reload");
- if (type == JOB_STOP && u->load_state == UNIT_ERROR && unit_active_state(u) == UNIT_INACTIVE) {
+ if (type == JOB_STOP && (u->load_state == UNIT_NOT_FOUND || u->load_state == UNIT_ERROR) && unit_active_state(u) == UNIT_INACTIVE) {
dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
return bus_send_error_reply(connection, message, &error, -EPERM);
}
@@ -897,428 +828,273 @@ oom:
return DBUS_HANDLER_RESULT_NEED_MEMORY;
}
-static int parse_mode(DBusMessageIter *iter, bool *runtime, bool next) {
- const char *mode;
- int r;
-
- assert(iter);
- assert(runtime);
-
- r = bus_iter_get_basic_and_next(iter, DBUS_TYPE_STRING, &mode, next);
- if (r < 0)
- return r;
-
- if (streq(mode, "runtime"))
- *runtime = true;
- else if (streq(mode, "persistent"))
- *runtime = false;
- else
- return -EINVAL;
-
- return 0;
-}
+static int bus_unit_set_transient_property(
+ Unit *u,
+ const char *name,
+ DBusMessageIter *i,
+ UnitSetPropertiesMode mode,
+ DBusError *error) {
-int bus_unit_cgroup_set(Unit *u, DBusMessageIter *iter) {
- _cleanup_free_ char *controller = NULL, *old_path = NULL, *new_path = NULL, *contents = NULL;
- const char *name;
- CGroupBonding *b;
- bool runtime;
int r;
assert(u);
- assert(iter);
+ assert(name);
+ assert(i);
- if (!unit_get_exec_context(u))
- return -EINVAL;
+ if (streq(name, "Description")) {
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING)
+ return -EINVAL;
- r = bus_iter_get_basic_and_next(iter, DBUS_TYPE_STRING, &name, true);
- if (r < 0)
- return r;
+ if (mode != UNIT_CHECK) {
+ const char *description;
- r = parse_mode(iter, &runtime, false);
- if (r < 0)
- return r;
+ dbus_message_iter_get_basic(i, &description);
- r = cg_split_spec(name, &controller, &new_path);
- if (r < 0)
- return r;
+ r = unit_set_description(u, description);
+ if (r < 0)
+ return r;
- if (!new_path) {
- new_path = unit_default_cgroup_path(u);
- if (!new_path)
- return -ENOMEM;
- }
+ unit_write_drop_in_format(u, mode, name, "[Unit]\nDescription=%s\n", description);
+ }
- if (!controller || streq(controller, SYSTEMD_CGROUP_CONTROLLER))
- return -EINVAL;
+ return 1;
- b = cgroup_bonding_find_list(u->cgroup_bondings, controller);
- if (b) {
- if (streq(b->path, new_path))
- return 0;
+ } else if (streq(name, "Slice") && unit_get_cgroup_context(u)) {
+ const char *s;
- if (b->essential)
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING)
return -EINVAL;
- old_path = strdup(b->path);
- if (!old_path)
- return -ENOMEM;
- }
-
- r = unit_add_cgroup_from_text(u, name, true, &b);
- if (r < 0)
- return r;
- if (r > 0) {
- CGroupAttribute *a;
-
- /* Try to move things to the new place, and clean up the old place */
- cgroup_bonding_realize(b);
- cgroup_bonding_migrate(b, u->cgroup_bondings);
-
- if (old_path)
- cg_trim(controller, old_path, true);
-
- /* Apply the attributes to the new group */
- LIST_FOREACH(by_unit, a, u->cgroup_attributes)
- if (streq(a->controller, controller))
- cgroup_attribute_apply(a, b);
- }
-
- contents = strjoin("[", UNIT_VTABLE(u)->exec_section, "]\n"
- "ControlGroup=", name, "\n", NULL);
- if (!contents)
- return -ENOMEM;
-
- return unit_write_drop_in(u, runtime, controller, contents);
-}
+ dbus_message_iter_get_basic(i, &s);
-int bus_unit_cgroup_unset(Unit *u, DBusMessageIter *iter) {
- _cleanup_free_ char *controller = NULL, *path = NULL, *target = NULL;
- const char *name;
- CGroupAttribute *a, *n;
- CGroupBonding *b;
- bool runtime;
- int r;
+ if (isempty(s)) {
+ if (mode != UNIT_CHECK) {
+ unit_ref_unset(&u->slice);
+ unit_remove_drop_in(u, mode, name);
+ }
+ } else {
+ Unit *slice;
- assert(u);
- assert(iter);
+ r = manager_load_unit(u->manager, s, NULL, error, &slice);
+ if (r < 0)
+ return r;
- if (!unit_get_exec_context(u))
- return -EINVAL;
+ if (slice->type != UNIT_SLICE)
+ return -EINVAL;
- r = bus_iter_get_basic_and_next(iter, DBUS_TYPE_STRING, &name, true);
- if (r < 0)
- return r;
+ if (mode != UNIT_CHECK) {
+ unit_ref_set(&u->slice, slice);
+ unit_write_drop_in_private_format(u, mode, name, "Slice=%s\n", s);
+ }
+ }
- r = parse_mode(iter, &runtime, false);
- if (r < 0)
- return r;
+ return 1;
+
+ } else if (streq(name, "Requires") ||
+ streq(name, "RequiresOverridable") ||
+ streq(name, "Requisite") ||
+ streq(name, "RequisiteOverridable") ||
+ streq(name, "Wants") ||
+ streq(name, "BindsTo") ||
+ streq(name, "Conflicts") ||
+ streq(name, "Before") ||
+ streq(name, "After") ||
+ streq(name, "OnFailure") ||
+ streq(name, "PropagatesReloadTo") ||
+ streq(name, "ReloadPropagatedFrom") ||
+ streq(name, "PartOf")) {
+
+ UnitDependency d;
+ DBusMessageIter sub;
+
+ d = unit_dependency_from_string(name);
+ if (d < 0)
+ return -EINVAL;
- r = cg_split_spec(name, &controller, &path);
- if (r < 0)
- return r;
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(i) != DBUS_TYPE_STRING)
+ return -EINVAL;
- if (!controller || streq(controller, SYSTEMD_CGROUP_CONTROLLER))
- return -EINVAL;
+ dbus_message_iter_recurse(i, &sub);
+ while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
+ const char *other;
- b = cgroup_bonding_find_list(u->cgroup_bondings, controller);
- if (!b)
- return -ENOENT;
+ dbus_message_iter_get_basic(&sub, &other);
- if (path && !path_equal(path, b->path))
- return -ENOENT;
+ if (!unit_name_is_valid(other, false))
+ return -EINVAL;
- if (b->essential)
- return -EINVAL;
+ if (mode != UNIT_CHECK) {
+ _cleanup_free_ char *label = NULL;
- unit_remove_drop_in(u, runtime, controller);
+ r = unit_add_dependency_by_name(u, d, other, NULL, true);
+ if (r < 0)
+ return r;
- /* Try to migrate the old group away */
- if (cg_pid_get_path(controller, 0, &target) >= 0)
- cgroup_bonding_migrate_to(u->cgroup_bondings, target, false);
+ label = strjoin(name, "-", other, NULL);
+ if (!label)
+ return -ENOMEM;
- cgroup_bonding_free(b, true);
+ unit_write_drop_in_format(u, mode, label, "[Unit]\n%s=%s\n", name, other);
+ }
- /* Drop all attributes of this controller */
- LIST_FOREACH_SAFE(by_unit, a, n, u->cgroup_attributes) {
- if (!streq(a->controller, controller))
- continue;
+ dbus_message_iter_next(&sub);
+ }
- unit_remove_drop_in(u, runtime, a->name);
- cgroup_attribute_free(a);
+ return 1;
}
return 0;
}
-int bus_unit_cgroup_attribute_get(Unit *u, DBusMessageIter *iter, char ***_result) {
- _cleanup_free_ char *controller = NULL;
- CGroupAttribute *a;
- CGroupBonding *b;
- const char *name;
- char **l = NULL;
+int bus_unit_set_properties(
+ Unit *u,
+ DBusMessageIter *iter,
+ UnitSetPropertiesMode mode,
+ bool commit,
+ DBusError *error) {
+
+ bool for_real = false;
+ DBusMessageIter sub;
+ unsigned n = 0;
int r;
assert(u);
assert(iter);
- assert(_result);
- if (!unit_get_exec_context(u))
- return -EINVAL;
+ if (u->transient)
+ mode &= UNIT_RUNTIME;
- r = bus_iter_get_basic_and_next(iter, DBUS_TYPE_STRING, &name, false);
- if (r < 0)
- return r;
+ /* We iterate through the array twice. First run we just check
+ * if all passed data is valid, second run actually applies
+ * it. This is to implement transaction-like behaviour without
+ * actually providing full transactions. */
- r = cg_controller_from_attr(name, &controller);
- if (r < 0)
- return r;
-
- /* First attempt, read the value from the kernel */
- b = cgroup_bonding_find_list(u->cgroup_bondings, controller);
- if (b) {
- _cleanup_free_ char *p = NULL, *v = NULL;
-
- r = cg_get_path(b->controller, b->path, name, &p);
- if (r < 0)
- return r;
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(iter) != DBUS_TYPE_STRUCT)
+ return -EINVAL;
- r = read_full_file(p, &v, NULL);
- if (r >= 0) {
- /* Split on new lines */
- l = strv_split_newlines(v);
- if (!l)
- return -ENOMEM;
+ dbus_message_iter_recurse(iter, &sub);
+ for (;;) {
+ DBusMessageIter sub2, sub3;
+ const char *name;
- *_result = l;
- return 0;
+ if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_INVALID) {
- }
- }
+ if (for_real || mode == UNIT_CHECK)
+ break;
- /* If that didn't work, read our cached value */
- LIST_FOREACH(by_unit, a, u->cgroup_attributes) {
-
- if (!cgroup_attribute_matches(a, controller, name))
+ /* Reached EOF. Let's try again, and this time for realz... */
+ dbus_message_iter_recurse(iter, &sub);
+ for_real = true;
continue;
-
- r = strv_extend(&l, a->value);
- if (r < 0) {
- strv_free(l);
- return r;
}
- }
-
- if (!l)
- return -ENOENT;
-
- *_result = l;
- return 0;
-}
-
-static int update_attribute_drop_in(Unit *u, bool runtime, const char *name) {
- _cleanup_free_ char *buf = NULL;
- CGroupAttribute *a;
- assert(u);
- assert(name);
-
- LIST_FOREACH(by_unit, a, u->cgroup_attributes) {
- if (!cgroup_attribute_matches(a, NULL, name))
- continue;
-
- if (!buf) {
- buf = strjoin("[", UNIT_VTABLE(u)->exec_section, "]\n"
- "ControlGroupAttribute=", a->name, " ", a->value, "\n", NULL);
-
- if (!buf)
- return -ENOMEM;
- } else {
- char *b;
+ if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT)
+ return -EINVAL;
- b = strjoin(buf,
- "ControlGroupAttribute=", a->name, " ", a->value, "\n", NULL);
+ dbus_message_iter_recurse(&sub, &sub2);
- if (!b)
- return -ENOMEM;
+ if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
+ dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT)
+ return -EINVAL;
- free(buf);
- buf = b;
+ if (!UNIT_VTABLE(u)->bus_set_property) {
+ dbus_set_error(error, DBUS_ERROR_PROPERTY_READ_ONLY, "Objects of this type do not support setting properties.");
+ return -ENOENT;
}
- }
-
- if (buf)
- return unit_write_drop_in(u, runtime, name, buf);
- else
- return unit_remove_drop_in(u, runtime, name);
-}
-
-int bus_unit_cgroup_attribute_set(Unit *u, DBusMessageIter *iter) {
- _cleanup_strv_free_ char **l = NULL;
- int r;
- bool runtime = false;
- char **value;
- const char *name;
-
- assert(u);
- assert(iter);
-
- if (!unit_get_exec_context(u))
- return -EINVAL;
-
- r = bus_iter_get_basic_and_next(iter, DBUS_TYPE_STRING, &name, true);
- if (r < 0)
- return r;
-
- r = bus_parse_strv_iter(iter, &l);
- if (r < 0)
- return r;
-
- if (!dbus_message_iter_next(iter))
- return -EINVAL;
- r = parse_mode(iter, &runtime, false);
- if (r < 0)
- return r;
-
- STRV_FOREACH(value, l) {
- _cleanup_free_ char *v = NULL;
- CGroupAttribute *a;
- const CGroupSemantics *s;
-
- r = cgroup_semantics_find(NULL, name, *value, &v, &s);
+ dbus_message_iter_recurse(&sub2, &sub3);
+ r = UNIT_VTABLE(u)->bus_set_property(u, name, &sub3, for_real ? mode : UNIT_CHECK, error);
+ if (r == 0 && u->transient && u->load_state == UNIT_STUB)
+ r = bus_unit_set_transient_property(u, name, &sub3, for_real ? mode : UNIT_CHECK, error);
if (r < 0)
return r;
-
- if (s && !s->multiple && l[1])
- return -EINVAL;
-
- r = unit_add_cgroup_attribute(u, s, NULL, name, v ? v : *value, &a);
- if (r < 0)
- return r;
-
- if (r > 0) {
- CGroupBonding *b;
-
- b = cgroup_bonding_find_list(u->cgroup_bondings, a->controller);
- if (!b) {
- /* Doesn't exist yet? Then let's add it */
- r = unit_add_cgroup_from_text(u, a->controller, false, &b);
- if (r < 0)
- return r;
-
- if (r > 0) {
- cgroup_bonding_realize(b);
- cgroup_bonding_migrate(b, u->cgroup_bondings);
- }
- }
-
- /* Make it count */
- cgroup_attribute_apply(a, u->cgroup_bondings);
+ if (r == 0) {
+ dbus_set_error(error, DBUS_ERROR_PROPERTY_READ_ONLY, "Cannot set property %s, or unknown property.", name);
+ return -ENOENT;
}
- }
-
- r = update_attribute_drop_in(u, runtime, name);
- if (r < 0)
- return r;
-
- return 0;
-}
+ dbus_message_iter_next(&sub);
-int bus_unit_cgroup_attribute_unset(Unit *u, DBusMessageIter *iter) {
- const char *name;
- bool runtime;
- int r;
-
- assert(u);
- assert(iter);
-
- if (!unit_get_exec_context(u))
- return -EINVAL;
-
- r = bus_iter_get_basic_and_next(iter, DBUS_TYPE_STRING, &name, true);
- if (r < 0)
- return r;
-
- r = parse_mode(iter, &runtime, false);
- if (r < 0)
- return r;
+ n += for_real;
+ }
- cgroup_attribute_free_some(u->cgroup_attributes, NULL, name);
- update_attribute_drop_in(u, runtime, name);
+ if (commit && n > 0 && UNIT_VTABLE(u)->bus_commit_properties)
+ UNIT_VTABLE(u)->bus_commit_properties(u);
- return 0;
+ return n;
}
const BusProperty bus_unit_properties[] = {
- { "Id", bus_property_append_string, "s", offsetof(Unit, id), true },
- { "Names", bus_unit_append_names, "as", 0 },
- { "Following", bus_unit_append_following, "s", 0 },
- { "Requires", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRES]), true },
- { "RequiresOverridable", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRES_OVERRIDABLE]), true },
- { "Requisite", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUISITE]), true },
- { "RequisiteOverridable", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUISITE_OVERRIDABLE]), true },
- { "Wants", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_WANTS]), true },
- { "BindsTo", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BINDS_TO]), true },
- { "PartOf", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PART_OF]), true },
- { "RequiredBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRED_BY]), true },
- { "RequiredByOverridable",bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRED_BY_OVERRIDABLE]), true },
- { "WantedBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_WANTED_BY]), true },
- { "BoundBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BOUND_BY]), true },
- { "ConsistsOf", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_CONSISTS_OF]), true },
- { "Conflicts", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_CONFLICTS]), true },
- { "ConflictedBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_CONFLICTED_BY]), true },
- { "Before", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BEFORE]), true },
- { "After", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_AFTER]), true },
- { "OnFailure", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_ON_FAILURE]), true },
- { "Triggers", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_TRIGGERS]), true },
- { "TriggeredBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]), true },
- { "PropagatesReloadTo", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]), true },
- { "ReloadPropagatedFrom", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]), true },
- { "RequiresMountsFor", bus_property_append_strv, "as", offsetof(Unit, requires_mounts_for), true },
- { "Documentation", bus_property_append_strv, "as", offsetof(Unit, documentation), true },
- { "Description", bus_unit_append_description, "s", 0 },
- { "LoadState", bus_unit_append_load_state, "s", offsetof(Unit, load_state) },
- { "ActiveState", bus_unit_append_active_state, "s", 0 },
- { "SubState", bus_unit_append_sub_state, "s", 0 },
- { "FragmentPath", bus_property_append_string, "s", offsetof(Unit, fragment_path), true },
- { "SourcePath", bus_property_append_string, "s", offsetof(Unit, source_path), true },
- { "DropInPaths", bus_property_append_strv, "as", offsetof(Unit, dropin_paths), true },
- { "UnitFileState", bus_unit_append_file_state, "s", 0 },
- { "InactiveExitTimestamp",bus_property_append_usec, "t", offsetof(Unit, inactive_exit_timestamp.realtime) },
- { "InactiveExitTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, inactive_exit_timestamp.monotonic) },
- { "ActiveEnterTimestamp", bus_property_append_usec, "t", offsetof(Unit, active_enter_timestamp.realtime) },
- { "ActiveEnterTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, active_enter_timestamp.monotonic) },
- { "ActiveExitTimestamp", bus_property_append_usec, "t", offsetof(Unit, active_exit_timestamp.realtime) },
- { "ActiveExitTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, active_exit_timestamp.monotonic) },
- { "InactiveEnterTimestamp", bus_property_append_usec, "t", offsetof(Unit, inactive_enter_timestamp.realtime) },
- { "InactiveEnterTimestampMonotonic",bus_property_append_usec, "t", offsetof(Unit, inactive_enter_timestamp.monotonic) },
- { "CanStart", bus_unit_append_can_start, "b", 0 },
- { "CanStop", bus_unit_append_can_stop, "b", 0 },
- { "CanReload", bus_unit_append_can_reload, "b", 0 },
- { "CanIsolate", bus_unit_append_can_isolate, "b", 0 },
- { "Job", bus_unit_append_job, "(uo)", 0 },
- { "StopWhenUnneeded", bus_property_append_bool, "b", offsetof(Unit, stop_when_unneeded) },
- { "RefuseManualStart", bus_property_append_bool, "b", offsetof(Unit, refuse_manual_start) },
- { "RefuseManualStop", bus_property_append_bool, "b", offsetof(Unit, refuse_manual_stop) },
- { "AllowIsolate", bus_property_append_bool, "b", offsetof(Unit, allow_isolate) },
- { "DefaultDependencies", bus_property_append_bool, "b", offsetof(Unit, default_dependencies) },
- { "OnFailureIsolate", bus_property_append_bool, "b", offsetof(Unit, on_failure_isolate) },
- { "IgnoreOnIsolate", bus_property_append_bool, "b", offsetof(Unit, ignore_on_isolate) },
- { "IgnoreOnSnapshot", bus_property_append_bool, "b", offsetof(Unit, ignore_on_snapshot) },
- { "NeedDaemonReload", bus_unit_append_need_daemon_reload, "b", 0 },
- { "JobTimeoutUSec", bus_property_append_usec, "t", offsetof(Unit, job_timeout) },
- { "ConditionTimestamp", bus_property_append_usec, "t", offsetof(Unit, condition_timestamp.realtime) },
- { "ConditionTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, condition_timestamp.monotonic) },
- { "ConditionResult", bus_property_append_bool, "b", offsetof(Unit, condition_result) },
- { "LoadError", bus_unit_append_load_error, "(ss)", 0 },
- { NULL, }
+ { "Id", bus_property_append_string, "s", offsetof(Unit, id), true },
+ { "Names", bus_unit_append_names, "as", 0 },
+ { "Following", bus_unit_append_following, "s", 0 },
+ { "Requires", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRES]), true },
+ { "RequiresOverridable", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRES_OVERRIDABLE]), true },
+ { "Requisite", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUISITE]), true },
+ { "RequisiteOverridable", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUISITE_OVERRIDABLE]), true },
+ { "Wants", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_WANTS]), true },
+ { "BindsTo", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BINDS_TO]), true },
+ { "PartOf", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PART_OF]), true },
+ { "RequiredBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRED_BY]), true },
+ { "RequiredByOverridable", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRED_BY_OVERRIDABLE]), true },
+ { "WantedBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_WANTED_BY]), true },
+ { "BoundBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BOUND_BY]), true },
+ { "ConsistsOf", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_CONSISTS_OF]), true },
+ { "Conflicts", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_CONFLICTS]), true },
+ { "ConflictedBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_CONFLICTED_BY]), true },
+ { "Before", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BEFORE]), true },
+ { "After", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_AFTER]), true },
+ { "OnFailure", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_ON_FAILURE]), true },
+ { "Triggers", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_TRIGGERS]), true },
+ { "TriggeredBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]), true },
+ { "PropagatesReloadTo", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]), true },
+ { "ReloadPropagatedFrom", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]), true },
+ { "RequiresMountsFor", bus_property_append_strv, "as", offsetof(Unit, requires_mounts_for), true },
+ { "Documentation", bus_property_append_strv, "as", offsetof(Unit, documentation), true },
+ { "Description", bus_unit_append_description, "s", 0 },
+ { "LoadState", bus_unit_append_load_state, "s", offsetof(Unit, load_state) },
+ { "ActiveState", bus_unit_append_active_state, "s", 0 },
+ { "SubState", bus_unit_append_sub_state, "s", 0 },
+ { "FragmentPath", bus_property_append_string, "s", offsetof(Unit, fragment_path), true },
+ { "SourcePath", bus_property_append_string, "s", offsetof(Unit, source_path), true },
+ { "DropInPaths", bus_property_append_strv, "as", offsetof(Unit, dropin_paths), true },
+ { "UnitFileState", bus_unit_append_file_state, "s", 0 },
+ { "InactiveExitTimestamp", bus_property_append_usec, "t", offsetof(Unit, inactive_exit_timestamp.realtime) },
+ { "InactiveExitTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, inactive_exit_timestamp.monotonic) },
+ { "ActiveEnterTimestamp", bus_property_append_usec, "t", offsetof(Unit, active_enter_timestamp.realtime) },
+ { "ActiveEnterTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, active_enter_timestamp.monotonic) },
+ { "ActiveExitTimestamp", bus_property_append_usec, "t", offsetof(Unit, active_exit_timestamp.realtime) },
+ { "ActiveExitTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, active_exit_timestamp.monotonic) },
+ { "InactiveEnterTimestamp", bus_property_append_usec, "t", offsetof(Unit, inactive_enter_timestamp.realtime) },
+ { "InactiveEnterTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, inactive_enter_timestamp.monotonic) },
+ { "CanStart", bus_unit_append_can_start, "b", 0 },
+ { "CanStop", bus_unit_append_can_stop, "b", 0 },
+ { "CanReload", bus_unit_append_can_reload, "b", 0 },
+ { "CanIsolate", bus_unit_append_can_isolate, "b", 0 },
+ { "Job", bus_unit_append_job, "(uo)", 0 },
+ { "StopWhenUnneeded", bus_property_append_bool, "b", offsetof(Unit, stop_when_unneeded) },
+ { "RefuseManualStart", bus_property_append_bool, "b", offsetof(Unit, refuse_manual_start) },
+ { "RefuseManualStop", bus_property_append_bool, "b", offsetof(Unit, refuse_manual_stop) },
+ { "AllowIsolate", bus_property_append_bool, "b", offsetof(Unit, allow_isolate) },
+ { "DefaultDependencies", bus_property_append_bool, "b", offsetof(Unit, default_dependencies) },
+ { "OnFailureIsolate", bus_property_append_bool, "b", offsetof(Unit, on_failure_isolate) },
+ { "IgnoreOnIsolate", bus_property_append_bool, "b", offsetof(Unit, ignore_on_isolate) },
+ { "IgnoreOnSnapshot", bus_property_append_bool, "b", offsetof(Unit, ignore_on_snapshot) },
+ { "NeedDaemonReload", bus_unit_append_need_daemon_reload, "b", 0 },
+ { "JobTimeoutUSec", bus_property_append_usec, "t", offsetof(Unit, job_timeout) },
+ { "ConditionTimestamp", bus_property_append_usec, "t", offsetof(Unit, condition_timestamp.realtime) },
+ { "ConditionTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, condition_timestamp.monotonic) },
+ { "ConditionResult", bus_property_append_bool, "b", offsetof(Unit, condition_result) },
+ { "Conditions", bus_property_append_condition_list, "a(sbbsi)", offsetof(Unit, conditions) },
+ { "LoadError", bus_unit_append_load_error, "(ss)", 0 },
+ { "Transient", bus_property_append_bool, "b", offsetof(Unit, transient) },
+ {}
};
const BusProperty bus_unit_cgroup_properties[] = {
- { "DefaultControlGroup", bus_unit_append_default_cgroup, "s", 0 },
- { "ControlGroups", bus_unit_append_cgroups, "as", 0 },
- { "ControlGroupAttributes", bus_unit_append_cgroup_attrs, "a(sss)", 0 },
- { NULL, }
+ { "Slice", bus_unit_append_slice, "s", 0 },
+ { "ControlGroup", bus_property_append_string, "s", offsetof(Unit, cgroup_path), true },
+ {}
};
diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h
index acd1ddbe78..3064cd552a 100644
--- a/src/core/dbus-unit.h
+++ b/src/core/dbus-unit.h
@@ -61,6 +61,10 @@
" <arg name=\"signal\" type=\"i\" direction=\"in\"/>\n" \
" </method>\n" \
" <method name=\"ResetFailed\"/>\n" \
+ " <method name=\"SetProperties\">\n" \
+ " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
+ " <arg name=\"properties\" type=\"a(sv)\" direction=\"in\"/>\n" \
+ " </method>\n" \
" <property name=\"Id\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"Names\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"Following\" type=\"s\" access=\"read\"/>\n" \
@@ -121,34 +125,14 @@
" <property name=\"ConditionTimestamp\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"ConditionTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"ConditionResult\" type=\"b\" access=\"read\"/>\n" \
+ " <property name=\"Conditions\" type=\"a(sbbsi)\" access=\"read\"/>\n" \
" <property name=\"LoadError\" type=\"(ss)\" access=\"read\"/>\n" \
+ " <property name=\"Transient\" type=\"b\" access=\"read\"/>\n" \
" </interface>\n"
#define BUS_UNIT_CGROUP_INTERFACE \
- " <property name=\"DefaultControlGroup\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"ControlGroups\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"ControlGroupAttributes\" type=\"a(sss)\" access=\"read\"/>\n" \
- " <method name=\"SetControlGroup\">\n" \
- " <arg name=\"group\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"UnsetControlGroup\">\n" \
- " <arg name=\"group\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"GetControlGroupAttribute\">\n" \
- " <arg name=\"attribute\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"values\" type=\"as\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"SetControlGroupAttribute\">\n" \
- " <arg name=\"attribute\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"values\" type=\"as\" direction=\"in\"/>\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"UnsetControlGroupAttribute\">\n" \
- " <arg name=\"attribute\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " </method>\n"
+ " <property name=\"Slice\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"ControlGroup\" type=\"s\" access=\"read\"/>\n"
#define BUS_UNIT_INTERFACES_LIST \
BUS_GENERIC_INTERFACES_LIST \
@@ -160,19 +144,9 @@ extern const BusProperty bus_unit_cgroup_properties[];
void bus_unit_send_change_signal(Unit *u);
void bus_unit_send_removed_signal(Unit *u);
-DBusHandlerResult bus_unit_queue_job(
- DBusConnection *connection,
- DBusMessage *message,
- Unit *u,
- JobType type,
- JobMode mode,
- bool reload_if_possible);
-
-int bus_unit_cgroup_set(Unit *u, DBusMessageIter *iter);
-int bus_unit_cgroup_unset(Unit *u, DBusMessageIter *iter);
-int bus_unit_cgroup_attribute_get(Unit *u, DBusMessageIter *iter, char ***_result);
-int bus_unit_cgroup_attribute_set(Unit *u, DBusMessageIter *iter);
-int bus_unit_cgroup_attribute_unset(Unit *u, DBusMessageIter *iter);
+DBusHandlerResult bus_unit_queue_job(DBusConnection *connection, DBusMessage *message, Unit *u, JobType type, JobMode mode, bool reload_if_possible);
+
+int bus_unit_set_properties(Unit *u, DBusMessageIter *i, UnitSetPropertiesMode mode, bool commit, DBusError *error);
extern const DBusObjectPathVTable bus_unit_vtable;
diff --git a/src/core/dbus.c b/src/core/dbus.c
index 1272c938cf..aa3d93bf06 100644
--- a/src/core/dbus.c
+++ b/src/core/dbus.c
@@ -28,7 +28,6 @@
#include "dbus.h"
#include "log.h"
#include "strv.h"
-#include "cgroup.h"
#include "mkdir.h"
#include "missing.h"
#include "dbus-unit.h"
@@ -453,7 +452,7 @@ static DBusHandlerResult system_bus_message_filter(DBusConnection *connection, D
DBUS_TYPE_INVALID))
log_error("Failed to parse Released message: %s", bus_error_message(&error));
else
- cgroup_notify_empty(m, cgroup);
+ manager_notify_cgroup_empty(m, cgroup);
}
dbus_error_free(&error);
@@ -489,7 +488,7 @@ static DBusHandlerResult private_bus_message_filter(DBusConnection *connection,
DBUS_TYPE_INVALID))
log_error("Failed to parse Released message: %s", bus_error_message(&error));
else
- cgroup_notify_empty(m, cgroup);
+ manager_notify_cgroup_empty(m, cgroup);
/* Forward the message to the system bus, so that user
* instances are notified as well */
@@ -1136,19 +1135,19 @@ int bus_init(Manager *m, bool try_bus_connect) {
if (set_ensure_allocated(&m->bus_connections, trivial_hash_func, trivial_compare_func) < 0 ||
set_ensure_allocated(&m->bus_connections_for_dispatch, trivial_hash_func, trivial_compare_func) < 0)
- goto oom;
+ return log_oom();
if (m->name_data_slot < 0)
if (!dbus_pending_call_allocate_data_slot(&m->name_data_slot))
- goto oom;
+ return log_oom();
if (m->conn_data_slot < 0)
if (!dbus_pending_call_allocate_data_slot(&m->conn_data_slot))
- goto oom;
+ return log_oom();
if (m->subscribed_data_slot < 0)
if (!dbus_connection_allocate_data_slot(&m->subscribed_data_slot))
- goto oom;
+ return log_oom();
if (try_bus_connect) {
if ((r = bus_init_system(m)) < 0 ||
@@ -1156,16 +1155,14 @@ int bus_init(Manager *m, bool try_bus_connect) {
return r;
}
- if ((r = bus_init_private(m)) < 0)
+ r = bus_init_private(m);
+ if (r < 0)
return r;
return 0;
-oom:
- return log_oom();
}
static void shutdown_connection(Manager *m, DBusConnection *c) {
- Set *s;
Job *j;
Iterator i;
@@ -1181,15 +1178,7 @@ static void shutdown_connection(Manager *m, DBusConnection *c) {
set_remove(m->bus_connections, c);
set_remove(m->bus_connections_for_dispatch, c);
-
- if ((s = BUS_CONNECTION_SUBSCRIBED(m, c))) {
- char *t;
-
- while ((t = set_steal_first(s)))
- free(t);
-
- set_free(s);
- }
+ set_free_free(BUS_CONNECTION_SUBSCRIBED(m, c));
if (m->queued_message_connection == c) {
m->queued_message_connection = NULL;
@@ -1260,10 +1249,10 @@ void bus_done(Manager *m) {
set_free(m->bus_connections_for_dispatch);
if (m->name_data_slot >= 0)
- dbus_pending_call_free_data_slot(&m->name_data_slot);
+ dbus_pending_call_free_data_slot(&m->name_data_slot);
if (m->conn_data_slot >= 0)
- dbus_pending_call_free_data_slot(&m->conn_data_slot);
+ dbus_pending_call_free_data_slot(&m->conn_data_slot);
if (m->subscribed_data_slot >= 0)
dbus_connection_free_data_slot(&m->subscribed_data_slot);
@@ -1390,6 +1379,12 @@ bool bus_has_subscriber(Manager *m) {
assert(m);
+ /* If we are reloading then we might not have deserialized the
+ subscribers yet, hence let's assume that there are some */
+
+ if (m->n_reloading > 0)
+ return true;
+
SET_FOREACH(c, m->bus_connections_for_dispatch, i)
if (bus_connection_has_subscriber(m, c))
return true;
@@ -1456,7 +1451,7 @@ void bus_broadcast_finished(
usec_t userspace_usec,
usec_t total_usec) {
- DBusMessage *message;
+ _cleanup_dbus_message_unref_ DBusMessage *message = NULL;
assert(m);
@@ -1476,16 +1471,106 @@ void bus_broadcast_finished(
DBUS_TYPE_UINT64, &total_usec,
DBUS_TYPE_INVALID)) {
log_oom();
- goto finish;
+ return;
}
if (bus_broadcast(m, message) < 0) {
log_oom();
- goto finish;
+ return;
}
+}
-finish:
- if (message)
- dbus_message_unref(message);
+void bus_broadcast_reloading(Manager *m, bool active) {
+
+ _cleanup_dbus_message_unref_ DBusMessage *message = NULL;
+ dbus_bool_t b = active;
+
+ assert(m);
+
+ message = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading");
+ if (!message) {
+ log_oom();
+ return;
+ }
+
+ assert_cc(sizeof(usec_t) == sizeof(uint64_t));
+ if (!dbus_message_append_args(message,
+ DBUS_TYPE_BOOLEAN, &b,
+ DBUS_TYPE_INVALID)) {
+ log_oom();
+ return;
+ }
+
+
+ if (bus_broadcast(m, message) < 0) {
+ log_oom();
+ return;
+ }
+}
+
+Set *bus_acquire_subscribed(Manager *m, DBusConnection *c) {
+ Set *s;
+
+ assert(m);
+ assert(c);
+
+ s = BUS_CONNECTION_SUBSCRIBED(m, c);
+ if (s)
+ return s;
+
+ s = set_new(string_hash_func, string_compare_func);
+ if (!s)
+ return NULL;
+
+ if (!dbus_connection_set_data(c, m->subscribed_data_slot, s, NULL)) {
+ set_free(s);
+ return NULL;
+ }
+
+ return s;
+}
+
+void bus_serialize(Manager *m, FILE *f) {
+ char *client;
+ Iterator i;
+ Set *s;
+
+ assert(m);
+ assert(f);
+
+ if (!m->api_bus)
+ return;
+
+ s = BUS_CONNECTION_SUBSCRIBED(m, m->api_bus);
+ SET_FOREACH(client, s, i)
+ fprintf(f, "subscribed=%s\n", client);
+}
+
+int bus_deserialize_item(Manager *m, const char *line) {
+ const char *e;
+ char *b;
+ Set *s;
+
+ assert(m);
+ assert(line);
+
+ if (!m->api_bus)
+ return 0;
+
+ e = startswith(line, "subscribed=");
+ if (!e)
+ return 0;
+
+ s = bus_acquire_subscribed(m, m->api_bus);
+ if (!s)
+ return -ENOMEM;
+
+ b = strdup(e);
+ if (!b)
+ return -ENOMEM;
+
+ set_consume(s, b);
+
+ return 1;
}
diff --git a/src/core/dbus.h b/src/core/dbus.h
index c7a058e198..6500cd7455 100644
--- a/src/core/dbus.h
+++ b/src/core/dbus.h
@@ -43,6 +43,12 @@ bool bus_connection_has_subscriber(Manager *m, DBusConnection *c);
int bus_fdset_add_all(Manager *m, FDSet *fds);
void bus_broadcast_finished(Manager *m, usec_t firmware_usec, usec_t loader_usec, usec_t kernel_usec, usec_t initrd_usec, usec_t userspace_usec, usec_t total_usec);
+void bus_broadcast_reloading(Manager *m, bool active);
+
+Set *bus_acquire_subscribed(Manager *m, DBusConnection *c);
+
+void bus_serialize(Manager *m, FILE *f);
+int bus_deserialize_item(Manager *m, const char *line);
#define BUS_CONNECTION_SUBSCRIBED(m, c) dbus_connection_get_data((c), (m)->subscribed_data_slot)
#define BUS_PENDING_CALL_NAME(m, p) dbus_pending_call_get_data((p), (m)->name_data_slot)
diff --git a/src/core/execute.c b/src/core/execute.c
index 3959ef9623..a53ef48ef8 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -55,7 +55,6 @@
#include "sd-messages.h"
#include "ioprio.h"
#include "securebits.h"
-#include "cgroup.h"
#include "namespace.h"
#include "tcpwrap.h"
#include "exit-status.h"
@@ -67,8 +66,11 @@
#include "syscall-list.h"
#include "env-util.h"
#include "fileio.h"
+#include "unit.h"
+#include "async.h"
#define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC)
+#define IDLE_TIMEOUT2_USEC (1*USEC_PER_SEC)
/* This assumes there is a 'tty' group */
#define TTY_MODE 0620
@@ -758,24 +760,30 @@ static int setup_pam(
* daemon. We do things this way to ensure that the main PID
* of the daemon is the one we initially fork()ed. */
- if ((pam_code = pam_start(name, user, &conv, &handle)) != PAM_SUCCESS) {
+ pam_code = pam_start(name, user, &conv, &handle);
+ if (pam_code != PAM_SUCCESS) {
handle = NULL;
goto fail;
}
- if (tty)
- if ((pam_code = pam_set_item(handle, PAM_TTY, tty)) != PAM_SUCCESS)
+ if (tty) {
+ pam_code = pam_set_item(handle, PAM_TTY, tty);
+ if (pam_code != PAM_SUCCESS)
goto fail;
+ }
- if ((pam_code = pam_acct_mgmt(handle, PAM_SILENT)) != PAM_SUCCESS)
+ pam_code = pam_acct_mgmt(handle, PAM_SILENT);
+ if (pam_code != PAM_SUCCESS)
goto fail;
- if ((pam_code = pam_open_session(handle, PAM_SILENT)) != PAM_SUCCESS)
+ pam_code = pam_open_session(handle, PAM_SILENT);
+ if (pam_code != PAM_SUCCESS)
goto fail;
close_session = true;
- if ((!(e = pam_getenvlist(handle)))) {
+ e = pam_getenvlist(handle);
+ if (!e) {
pam_code = PAM_BUF_ERR;
goto fail;
}
@@ -789,7 +797,8 @@ static int setup_pam(
parent_pid = getpid();
- if ((pam_pid = fork()) < 0)
+ pam_pid = fork();
+ if (pam_pid < 0)
goto fail;
if (pam_pid == 0) {
@@ -840,9 +849,11 @@ static int setup_pam(
}
/* If our parent died we'll end the session */
- if (getppid() != parent_pid)
- if ((pam_code = pam_close_session(handle, PAM_DATA_SILENT)) != PAM_SUCCESS)
+ if (getppid() != parent_pid) {
+ pam_code = pam_close_session(handle, PAM_DATA_SILENT);
+ if (pam_code != PAM_SUCCESS)
goto child_finish;
+ }
r = 0;
@@ -977,6 +988,35 @@ static int apply_seccomp(uint32_t *syscall_filter) {
return 0;
}
+static void do_idle_pipe_dance(int idle_pipe[4]) {
+ assert(idle_pipe);
+
+ if (idle_pipe[1] >= 0)
+ close_nointr_nofail(idle_pipe[1]);
+ if (idle_pipe[2] >= 0)
+ close_nointr_nofail(idle_pipe[2]);
+
+ if (idle_pipe[0] >= 0) {
+ int r;
+
+ r = fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT_USEC);
+
+ if (idle_pipe[3] >= 0 && r == 0 /* timeout */) {
+ /* Signal systemd that we are bored and want to continue. */
+ write(idle_pipe[3], "x", 1);
+
+ /* Wait for systemd to react to the signal above. */
+ fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT2_USEC);
+ }
+
+ close_nointr_nofail(idle_pipe[0]);
+
+ }
+
+ if (idle_pipe[3] >= 0)
+ close_nointr_nofail(idle_pipe[3]);
+}
+
int exec_spawn(ExecCommand *command,
char **argv,
ExecContext *context,
@@ -986,18 +1026,17 @@ int exec_spawn(ExecCommand *command,
bool apply_chroot,
bool apply_tty_stdin,
bool confirm_spawn,
- CGroupBonding *cgroup_bondings,
- CGroupAttribute *cgroup_attributes,
- const char *cgroup_suffix,
+ CGroupControllerMask cgroup_supported,
+ const char *cgroup_path,
const char *unit_id,
- int idle_pipe[2],
+ int idle_pipe[4],
pid_t *ret) {
+ _cleanup_strv_free_ char **files_env = NULL;
+ int socket_fd;
+ char *line;
pid_t pid;
int r;
- char *line;
- int socket_fd;
- _cleanup_strv_free_ char **files_env = NULL;
assert(command);
assert(context);
@@ -1042,17 +1081,6 @@ int exec_spawn(ExecCommand *command,
NULL);
free(line);
- r = cgroup_bonding_realize_list(cgroup_bondings);
- if (r < 0)
- return r;
-
- /* We must initialize the attributes in the parent, before we
- fork, because we really need them initialized before making
- the process a member of the group (which we do in both the
- child and the parent), and we cannot really apply them twice
- (due to 'append' style attributes) */
- cgroup_attribute_apply_list(cgroup_attributes, cgroup_bondings);
-
if (context->private_tmp && !context->tmp_dir && !context->var_tmp_dir) {
r = setup_tmpdirs(&context->tmp_dir, &context->var_tmp_dir);
if (r < 0)
@@ -1072,7 +1100,6 @@ int exec_spawn(ExecCommand *command,
_cleanup_strv_free_ char **our_env = NULL, **pam_env = NULL,
**final_env = NULL, **final_argv = NULL;
unsigned n_env = 0;
- bool set_access = false;
/* child */
@@ -1096,14 +1123,8 @@ int exec_spawn(ExecCommand *command,
goto fail_child;
}
- if (idle_pipe) {
- if (idle_pipe[1] >= 0)
- close_nointr_nofail(idle_pipe[1]);
- if (idle_pipe[0] >= 0) {
- fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT_USEC);
- close_nointr_nofail(idle_pipe[0]);
- }
- }
+ if (idle_pipe)
+ do_idle_pipe_dance(idle_pipe);
/* Close sockets very early to make sure we don't
* block init reexecution because it cannot bind its
@@ -1185,8 +1206,8 @@ int exec_spawn(ExecCommand *command,
goto fail_child;
}
- if (cgroup_bondings) {
- err = cgroup_bonding_install_list(cgroup_bondings, 0, cgroup_suffix);
+ if (cgroup_path) {
+ err = cg_attach_everywhere(cgroup_supported, cgroup_path, 0);
if (err < 0) {
r = EXIT_CGROUP;
goto fail_child;
@@ -1269,37 +1290,24 @@ int exec_spawn(ExecCommand *command,
goto fail_child;
}
}
+ }
- if (cgroup_bondings && context->control_group_modify) {
- err = cgroup_bonding_set_group_access_list(cgroup_bondings, 0755, uid, gid);
- if (err >= 0)
- err = cgroup_bonding_set_task_access_list(
- cgroup_bondings,
- 0644,
- uid,
- gid,
- context->control_group_persistent);
- if (err < 0) {
- r = EXIT_CGROUP;
- goto fail_child;
- }
-
- set_access = true;
+#ifdef HAVE_PAM
+ if (cgroup_path && context->user && context->pam_name) {
+ err = cg_set_task_access(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, 0644, uid, gid);
+ if (err < 0) {
+ r = EXIT_CGROUP;
+ goto fail_child;
}
- }
- if (cgroup_bondings && !set_access && context->control_group_persistent >= 0) {
- err = cgroup_bonding_set_task_access_list(
- cgroup_bondings,
- (mode_t) -1,
- (uid_t) -1,
- (uid_t) -1,
- context->control_group_persistent);
+
+ err = cg_set_group_access(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, 0755, uid, gid);
if (err < 0) {
r = EXIT_CGROUP;
goto fail_child;
}
}
+#endif
if (apply_permissions) {
err = enforce_groups(context, username, gid);
@@ -1562,7 +1570,8 @@ int exec_spawn(ExecCommand *command,
* outside of the cgroup) and in the parent (so that we can be
* sure that when we kill the cgroup the process will be
* killed too). */
- cgroup_bonding_install_list(cgroup_bondings, pid, cgroup_suffix);
+ if (cgroup_path)
+ cg_attach(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, pid);
exec_status_start(&command->exec_status, pid);
@@ -1578,11 +1587,32 @@ void exec_context_init(ExecContext *c) {
c->cpu_sched_policy = SCHED_OTHER;
c->syslog_priority = LOG_DAEMON|LOG_INFO;
c->syslog_level_prefix = true;
- c->control_group_persistent = -1;
c->ignore_sigpipe = true;
c->timer_slack_nsec = (nsec_t) -1;
}
+static void *remove_tmpdir_thread(void *p) {
+ int r;
+ _cleanup_free_ char *dirp = p;
+ char *dir;
+
+ assert(dirp);
+
+ r = rm_rf_dangerous(dirp, false, true, false);
+ dir = dirname(dirp);
+ if (r < 0)
+ log_warning("Failed to remove content of temporary directory %s: %s",
+ dir, strerror(-r));
+ else {
+ r = rmdir(dir);
+ if (r < 0)
+ log_warning("Failed to remove temporary directory %s: %s",
+ dir, strerror(-r));
+ }
+
+ return NULL;
+}
+
void exec_context_tmp_dirs_done(ExecContext *c) {
char* dirs[] = {c->tmp_dir ? c->tmp_dir : c->var_tmp_dir,
c->tmp_dir ? c->var_tmp_dir : NULL,
@@ -1590,22 +1620,8 @@ void exec_context_tmp_dirs_done(ExecContext *c) {
char **dirp;
for(dirp = dirs; *dirp; dirp++) {
- char *dir;
- int r;
-
- r = rm_rf_dangerous(*dirp, false, true, false);
- dir = dirname(*dirp);
- if (r < 0)
- log_warning("Failed to remove content of temporary directory %s: %s",
- dir, strerror(-r));
- else {
- r = rmdir(dir);
- if (r < 0)
- log_warning("Failed to remove temporary directory %s: %s",
- dir, strerror(-r));
- }
-
- free(*dirp);
+ log_debug("Spawning thread to nuke %s", *dirp);
+ asynchronous_job(remove_tmpdir_thread, *dirp);
}
c->tmp_dir = c->var_tmp_dir = NULL;
@@ -1770,10 +1786,10 @@ int exec_context_load_environment(const ExecContext *c, char ***l) {
strv_free(r);
return k;
- }
+ }
/* Log invalid environment variables with filename */
- if (p)
- p = strv_env_clean_log(p, pglob.gl_pathv[n]);
+ if (p)
+ p = strv_env_clean_log(p, pglob.gl_pathv[n]);
if (r == NULL)
r = p;
@@ -1837,14 +1853,13 @@ static void strv_fprintf(FILE *f, char **l) {
}
void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
- char ** e;
+ char **e;
unsigned i;
assert(c);
assert(f);
- if (!prefix)
- prefix = "";
+ prefix = strempty(prefix);
fprintf(f,
"%sUMask: %04o\n"
@@ -1852,8 +1867,6 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
"%sRootDirectory: %s\n"
"%sNonBlocking: %s\n"
"%sPrivateTmp: %s\n"
- "%sControlGroupModify: %s\n"
- "%sControlGroupPersistent: %s\n"
"%sPrivateNetwork: %s\n"
"%sIgnoreSIGPIPE: %s\n",
prefix, c->umask,
@@ -1861,8 +1874,6 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
prefix, c->root_directory ? c->root_directory : "/",
prefix, yes_no(c->non_blocking),
prefix, yes_no(c->private_tmp),
- prefix, yes_no(c->control_group_modify),
- prefix, yes_no(c->control_group_persistent),
prefix, yes_no(c->private_network),
prefix, yes_no(c->ignore_sigpipe));
diff --git a/src/core/execute.h b/src/core/execute.h
index 15574dc97e..c1e9717dc8 100644
--- a/src/core/execute.h
+++ b/src/core/execute.h
@@ -33,14 +33,11 @@ typedef struct ExecContext ExecContext;
#include <stdio.h>
#include <sched.h>
-struct CGroupBonding;
-struct CGroupAttribute;
-
-typedef struct Unit Unit;
-
#include "list.h"
#include "util.h"
+typedef struct Unit Unit;
+
typedef enum ExecInput {
EXEC_INPUT_NULL,
EXEC_INPUT_TTY,
@@ -148,9 +145,6 @@ struct ExecContext {
bool no_new_privileges;
- bool control_group_modify;
- int control_group_persistent;
-
/* This is not exposed to the user but available
* internally. We need it to make sure that whenever we spawn
* /bin/mount it is run in the same process group as us so
@@ -166,6 +160,8 @@ struct ExecContext {
bool cpu_sched_set:1;
};
+#include "cgroup.h"
+
int exec_spawn(ExecCommand *command,
char **argv,
ExecContext *context,
@@ -175,9 +171,8 @@ int exec_spawn(ExecCommand *command,
bool apply_chroot,
bool apply_tty_stdin,
bool confirm_spawn,
- struct CGroupBonding *cgroup_bondings,
- struct CGroupAttribute *cgroup_attributes,
- const char *cgroup_suffix,
+ CGroupControllerMask cgroup_mask,
+ const char *cgroup_path,
const char *unit_id,
int pipe_fd[2],
pid_t *ret);
diff --git a/src/core/job.c b/src/core/job.c
index d304a16d06..bf1d956908 100644
--- a/src/core/job.c
+++ b/src/core/job.c
@@ -35,7 +35,7 @@
#include "log.h"
#include "dbus-job.h"
#include "special.h"
-#include "sync.h"
+#include "async.h"
#include "virt.h"
JobBusClient* job_bus_client_new(DBusConnection *connection, const char *name) {
@@ -1088,10 +1088,13 @@ void job_shutdown_magic(Job *j) {
* asynchronous sync() would cause their exit to be
* delayed. */
- if (!unit_has_name(j->unit, SPECIAL_SHUTDOWN_TARGET))
+ if (j->type != JOB_START)
return;
- if (j->type != JOB_START)
+ if (j->unit->manager->running_as != SYSTEMD_SYSTEM)
+ return;
+
+ if (!unit_has_name(j->unit, SPECIAL_SHUTDOWN_TARGET))
return;
if (detect_container(NULL) > 0)
diff --git a/src/core/kill.c b/src/core/kill.c
index 0775653f73..ea947c23ae 100644
--- a/src/core/kill.c
+++ b/src/core/kill.c
@@ -29,6 +29,7 @@ void kill_context_init(KillContext *c) {
c->kill_signal = SIGTERM;
c->send_sigkill = true;
+ c->send_sighup = false;
}
void kill_context_dump(KillContext *c, FILE *f, const char *prefix) {
@@ -40,10 +41,12 @@ void kill_context_dump(KillContext *c, FILE *f, const char *prefix) {
fprintf(f,
"%sKillMode: %s\n"
"%sKillSignal: SIG%s\n"
- "%sSendSIGKILL: %s\n",
+ "%sSendSIGKILL: %s\n"
+ "%sSendSIGHUP: %s\n",
prefix, kill_mode_to_string(c->kill_mode),
prefix, signal_to_string(c->kill_signal),
- prefix, yes_no(c->send_sigkill));
+ prefix, yes_no(c->send_sigkill),
+ prefix, yes_no(c->send_sighup));
}
static const char* const kill_mode_table[_KILL_MODE_MAX] = {
diff --git a/src/core/kill.h b/src/core/kill.h
index 71a0513e84..41773f07ae 100644
--- a/src/core/kill.h
+++ b/src/core/kill.h
@@ -41,6 +41,7 @@ struct KillContext {
KillMode kill_mode;
int kill_signal;
bool send_sigkill;
+ bool send_sighup;
};
typedef enum KillWho {
diff --git a/src/core/killall.c b/src/core/killall.c
index a0f57455fb..e395050107 100644
--- a/src/core/killall.c
+++ b/src/core/killall.c
@@ -33,7 +33,7 @@
static bool ignore_proc(pid_t pid) {
_cleanup_fclose_ FILE *f = NULL;
- char c;
+ char c, *p;
size_t count;
uid_t uid;
int r;
@@ -50,7 +50,8 @@ static bool ignore_proc(pid_t pid) {
if (uid != 0)
return false;
- f = fopen(procfs_file_alloca(pid, "cmdline"), "re");
+ p = procfs_file_alloca(pid, "cmdline");
+ f = fopen(p, "re");
if (!f)
return true; /* not really, but has the desired effect */
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index 4e1454ee6c..31fb7bcd3f 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -66,16 +66,6 @@ $1.LimitMSGQUEUE, config_parse_limit, RLIMIT_MSGQ
$1.LimitNICE, config_parse_limit, RLIMIT_NICE, offsetof($1, exec_context.rlimit)
$1.LimitRTPRIO, config_parse_limit, RLIMIT_RTPRIO, offsetof($1, exec_context.rlimit)
$1.LimitRTTIME, config_parse_limit, RLIMIT_RTTIME, offsetof($1, exec_context.rlimit)
-$1.ControlGroup, config_parse_unit_cgroup, 0, 0
-$1.ControlGroupAttribute, config_parse_unit_cgroup_attr, 0, 0
-$1.CPUShares, config_parse_unit_cgroup_attr_pretty, 0, 0
-$1.MemoryLimit, config_parse_unit_cgroup_attr_pretty, 0, 0
-$1.MemorySoftLimit, config_parse_unit_cgroup_attr_pretty, 0, 0
-$1.DeviceAllow, config_parse_unit_cgroup_attr_pretty, 0, 0
-$1.DeviceDeny, config_parse_unit_cgroup_attr_pretty, 0, 0
-$1.BlockIOWeight, config_parse_unit_cgroup_attr_pretty, 0, 0
-$1.BlockIOReadBandwidth, config_parse_unit_cgroup_attr_pretty, 0, 0
-$1.BlockIOWriteBandwidth, config_parse_unit_cgroup_attr_pretty, 0, 0
$1.ReadWriteDirectories, config_parse_path_strv, 0, offsetof($1, exec_context.read_write_dirs)
$1.ReadOnlyDirectories, config_parse_path_strv, 0, offsetof($1, exec_context.read_only_dirs)
$1.InaccessibleDirectories, config_parse_path_strv, 0, offsetof($1, exec_context.inaccessible_dirs)
@@ -85,15 +75,28 @@ $1.MountFlags, config_parse_exec_mount_flags, 0,
$1.TCPWrapName, config_parse_unit_string_printf, 0, offsetof($1, exec_context.tcpwrap_name)
$1.PAMName, config_parse_unit_string_printf, 0, offsetof($1, exec_context.pam_name)
$1.IgnoreSIGPIPE, config_parse_bool, 0, offsetof($1, exec_context.ignore_sigpipe)
-$1.UtmpIdentifier, config_parse_unit_string_printf, 0, offsetof($1, exec_context.utmp_id)
-$1.ControlGroupModify, config_parse_bool, 0, offsetof($1, exec_context.control_group_modify)
-$1.ControlGroupPersistent, config_parse_tristate, 0, offsetof($1, exec_context.control_group_persistent)'
+$1.UtmpIdentifier, config_parse_unit_string_printf, 0, offsetof($1, exec_context.utmp_id)'
)m4_dnl
m4_define(`KILL_CONTEXT_CONFIG_ITEMS',
`$1.SendSIGKILL, config_parse_bool, 0, offsetof($1, kill_context.send_sigkill)
+$1.SendSIGHUP, config_parse_bool, 0, offsetof($1, kill_context.send_sighup)
$1.KillMode, config_parse_kill_mode, 0, offsetof($1, kill_context.kill_mode)
$1.KillSignal, config_parse_kill_signal, 0, offsetof($1, kill_context.kill_signal)'
)m4_dnl
+m4_define(`CGROUP_CONTEXT_CONFIG_ITEMS',
+`$1.Slice, config_parse_unit_slice, 0, 0
+$1.CPUAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.cpu_accounting)
+$1.CPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context)
+$1.MemoryAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.memory_accounting)
+$1.MemoryLimit, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
+$1.DeviceAllow, config_parse_device_allow, 0, offsetof($1, cgroup_context)
+$1.DevicePolicy, config_parse_device_policy, 0, offsetof($1, cgroup_context.device_policy)
+$1.BlockIOAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.blockio_accounting)
+$1.BlockIOWeight, config_parse_blockio_weight, 0, offsetof($1, cgroup_context)
+$1.BlockIODeviceWeight, config_parse_blockio_device_weight, 0, offsetof($1, cgroup_context)
+$1.BlockIOReadBandwidth, config_parse_blockio_bandwidth, 0, offsetof($1, cgroup_context)
+$1.BlockIOWriteBandwidth, config_parse_blockio_bandwidth, 0, offsetof($1, cgroup_context)'
+)m4_dnl
Unit.Description, config_parse_unit_string_printf, 0, offsetof(Unit, description)
Unit.Documentation, config_parse_documentation, 0, offsetof(Unit, documentation)
Unit.SourcePath, config_parse_path, 0, offsetof(Unit, source_path)
@@ -113,7 +116,7 @@ Unit.PropagateReloadTo, config_parse_unit_deps, UNIT_PROPAG
Unit.ReloadPropagatedFrom, config_parse_unit_deps, UNIT_RELOAD_PROPAGATED_FROM, 0
Unit.PropagateReloadFrom, config_parse_unit_deps, UNIT_RELOAD_PROPAGATED_FROM, 0
Unit.PartOf, config_parse_unit_deps, UNIT_PART_OF, 0
-Unit.RequiresMountsFor, config_parse_unit_requires_mounts_for, 0, offsetof(Unit, requires_mounts_for)
+Unit.RequiresMountsFor, config_parse_unit_requires_mounts_for, 0, 0
Unit.StopWhenUnneeded, config_parse_bool, 0, offsetof(Unit, stop_when_unneeded)
Unit.RefuseManualStart, config_parse_bool, 0, offsetof(Unit, refuse_manual_start)
Unit.RefuseManualStop, config_parse_bool, 0, offsetof(Unit, refuse_manual_stop)
@@ -172,6 +175,7 @@ Service.NotifyAccess, config_parse_notify_access, 0,
Service.Sockets, config_parse_service_sockets, 0, 0
Service.FsckPassNo, config_parse_fsck_passno, 0, offsetof(Service, fsck_passno)
EXEC_CONTEXT_CONFIG_ITEMS(Service)m4_dnl
+CGROUP_CONTEXT_CONFIG_ITEMS(Service)m4_dnl
KILL_CONTEXT_CONFIG_ITEMS(Service)m4_dnl
m4_dnl
Socket.ListenStream, config_parse_socket_listen, SOCKET_SOCKET, 0
@@ -214,6 +218,7 @@ Socket.SmackLabel, config_parse_string, 0,
Socket.SmackLabelIPIn, config_parse_string, 0, offsetof(Socket, smack_ip_in)
Socket.SmackLabelIPOut, config_parse_string, 0, offsetof(Socket, smack_ip_out)
EXEC_CONTEXT_CONFIG_ITEMS(Socket)m4_dnl
+CGROUP_CONTEXT_CONFIG_ITEMS(Socket)m4_dnl
KILL_CONTEXT_CONFIG_ITEMS(Socket)m4_dnl
m4_dnl
Mount.What, config_parse_string, 0, offsetof(Mount, parameters_fragment.what)
@@ -224,6 +229,7 @@ Mount.FsckPassNo, config_parse_fsck_passno, 0,
Mount.TimeoutSec, config_parse_sec, 0, offsetof(Mount, timeout_usec)
Mount.DirectoryMode, config_parse_mode, 0, offsetof(Mount, directory_mode)
EXEC_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl
+CGROUP_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl
KILL_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl
m4_dnl
Automount.Where, config_parse_path, 0, offsetof(Automount, where)
@@ -233,6 +239,7 @@ Swap.What, config_parse_path, 0,
Swap.Priority, config_parse_int, 0, offsetof(Swap, parameters_fragment.priority)
Swap.TimeoutSec, config_parse_sec, 0, offsetof(Swap, timeout_usec)
EXEC_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl
+CGROUP_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl
KILL_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl
m4_dnl
Timer.OnCalendar, config_parse_timer, 0, 0
@@ -251,6 +258,12 @@ Path.DirectoryNotEmpty, config_parse_path_spec, 0,
Path.Unit, config_parse_trigger_unit, 0, 0
Path.MakeDirectory, config_parse_bool, 0, offsetof(Path, make_directory)
Path.DirectoryMode, config_parse_mode, 0, offsetof(Path, directory_mode)
+m4_dnl
+CGROUP_CONTEXT_CONFIG_ITEMS(Slice)m4_dnl
+m4_dnl
+CGROUP_CONTEXT_CONFIG_ITEMS(Scope)m4_dnl
+KILL_CONTEXT_CONFIG_ITEMS(Scope)m4_dnl
+Scope.TimeoutStopSec, config_parse_sec, 0, offsetof(Scope, timeout_stop_usec)
m4_dnl The [Install] section is ignored here.
Install.Alias, NULL, 0, 0
Install.WantedBy, NULL, 0, 0
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index e2015ed58f..44920d6449 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -51,6 +51,7 @@
#include "path-util.h"
#include "syscall-list.h"
#include "env-util.h"
+#include "cgroup.h"
#ifndef HAVE_SYSV_COMPAT
int config_parse_warn_compat(const char *unit,
@@ -98,9 +99,12 @@ int config_parse_unit_deps(const char* unit,
if (!t)
return log_oom();
- k = unit_name_printf(u, t);
- if (!k)
- return log_oom();
+ r = unit_name_printf(u, t, &k);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, -r,
+ "Failed to resolve specifiers, ignoring: %s", strerror(-r));
+ continue;
+ }
r = unit_add_dependency_by_name(u, d, k, NULL, true);
if (r < 0)
@@ -123,16 +127,17 @@ int config_parse_unit_string_printf(const char *unit,
Unit *u = userdata;
_cleanup_free_ char *k = NULL;
+ int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(u);
- k = unit_full_printf(u, rvalue);
- if (!k)
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
+ r = unit_full_printf(u, rvalue, &k);
+ if (r < 0)
+ log_syntax(unit, LOG_ERR, filename, line, -r,
+ "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
return config_parse_string(unit, filename, line, section, lvalue, ltype,
k ? k : rvalue, data, userdata);
@@ -150,16 +155,17 @@ int config_parse_unit_strv_printf(const char *unit,
Unit *u = userdata;
_cleanup_free_ char *k = NULL;
+ int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(u);
- k = unit_full_printf(u, rvalue);
- if (!k)
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
+ r = unit_full_printf(u, rvalue, &k);
+ if (r < 0)
+ log_syntax(unit, LOG_ERR, filename, line, -r,
+ "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
return config_parse_strv(unit, filename, line, section, lvalue, ltype,
k ? k : rvalue, data, userdata);
@@ -177,16 +183,17 @@ int config_parse_unit_path_printf(const char *unit,
Unit *u = userdata;
_cleanup_free_ char *k = NULL;
+ int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(u);
- k = unit_full_printf(u, rvalue);
- if (!k)
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
+ r = unit_full_printf(u, rvalue, &k);
+ if (r < 0)
+ log_syntax(unit, LOG_ERR, filename, line, -r,
+ "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
return config_parse_path(unit, filename, line, section, lvalue, ltype,
k ? k : rvalue, data, userdata);
@@ -204,6 +211,7 @@ int config_parse_socket_listen(const char *unit,
SocketPort *p, *tail;
Socket *s;
+ int r;
assert(filename);
assert(lvalue);
@@ -225,32 +233,31 @@ int config_parse_socket_listen(const char *unit,
if (ltype != SOCKET_SOCKET) {
p->type = ltype;
- p->path = unit_full_printf(UNIT(s), rvalue);
- if (!p->path) {
+ r = unit_full_printf(UNIT(s), rvalue, &p->path);
+ if (r < 0) {
p->path = strdup(rvalue);
if (!p->path) {
free(p);
return log_oom();
} else
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, -r,
+ "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
}
path_kill_slashes(p->path);
} else if (streq(lvalue, "ListenNetlink")) {
_cleanup_free_ char *k = NULL;
- int r;
p->type = SOCKET_SOCKET;
- k = unit_full_printf(UNIT(s), rvalue);
- if (!k)
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
+ r = unit_full_printf(UNIT(s), rvalue, &k);
+ if (r < 0)
+ log_syntax(unit, LOG_ERR, filename, line, -r,
+ "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
r = socket_address_parse_netlink(&p->address, k ? k : rvalue);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ log_syntax(unit, LOG_ERR, filename, line, -r,
"Failed to parse address value, ignoring: %s", rvalue);
free(p);
return 0;
@@ -258,17 +265,16 @@ int config_parse_socket_listen(const char *unit,
} else {
_cleanup_free_ char *k = NULL;
- int r;
p->type = SOCKET_SOCKET;
- k = unit_full_printf(UNIT(s), rvalue);
- if (!k)
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
+ r = unit_full_printf(UNIT(s), rvalue, &k);
+ if (r < 0)
+ log_syntax(unit, LOG_ERR, filename, line, -r,
+ "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
r = socket_address_parse(&p->address, k ? k : rvalue);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ log_syntax(unit, LOG_ERR, filename, line, -r,
"Failed to parse address value, ignoring: %s", rvalue);
free(p);
return 0;
@@ -996,58 +1002,6 @@ int config_parse_limit(const char *unit,
return 0;
}
-int config_parse_unit_cgroup(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Unit *u = userdata;
- char *w;
- size_t l;
- char *state;
-
- if (isempty(rvalue)) {
- /* An empty assignment resets the list */
- cgroup_bonding_free_list(u->cgroup_bondings, false);
- u->cgroup_bondings = NULL;
- return 0;
- }
-
- FOREACH_WORD_QUOTED(w, l, rvalue, state) {
- _cleanup_free_ char *t = NULL, *k = NULL, *ku = NULL;
- int r;
-
- t = strndup(w, l);
- if (!t)
- return log_oom();
-
- k = unit_full_printf(u, t);
- if (!k)
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Failed to resolve unit specifiers on %s. Ignoring.",
- t);
-
- ku = cunescape(k ? k : t);
- if (!ku)
- return log_oom();
-
- r = unit_add_cgroup_from_text(u, ku, true, NULL);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to parse cgroup value %s, ignoring: %s",
- k, rvalue);
- return 0;
- }
- }
-
- return 0;
-}
-
#ifdef HAVE_SYSV_COMPAT
int config_parse_sysv_priority(const char *unit,
const char *filename,
@@ -1281,11 +1235,12 @@ int config_parse_trigger_unit(
return 0;
}
- p = unit_name_printf(u, rvalue);
- if (!p)
- return log_oom();
+ r = unit_name_printf(u, rvalue, &p);
+ if (r < 0)
+ log_syntax(unit, LOG_ERR, filename, line, -r,
+ "Failed to resolve specifiers, ignoring: %s", strerror(-r));
- type = unit_name_to_type(p);
+ type = unit_name_to_type(p ?: rvalue);
if (type < 0) {
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Unit type not valid, ignoring: %s", rvalue);
@@ -1298,10 +1253,10 @@ int config_parse_trigger_unit(
return 0;
}
- r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_TRIGGERS, p, NULL, true);
+ r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_TRIGGERS, p ?: rvalue, NULL, true);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to add trigger on %s, ignoring: %s", p, strerror(-r));
+ "Failed to add trigger on %s, ignoring: %s", p ?: rvalue, strerror(-r));
return 0;
}
@@ -1322,6 +1277,7 @@ int config_parse_path_spec(const char *unit,
PathSpec *s;
PathType b;
_cleanup_free_ char *k = NULL;
+ int r;
assert(filename);
assert(lvalue);
@@ -1341,13 +1297,13 @@ int config_parse_path_spec(const char *unit,
return 0;
}
- k = unit_full_printf(UNIT(p), rvalue);
- if (!k) {
+ r = unit_full_printf(UNIT(p), rvalue, &k);
+ if (r < 0) {
k = strdup(rvalue);
if (!k)
return log_oom();
else
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ log_syntax(unit, LOG_ERR, filename, line, -r,
"Failed to resolve unit specifiers on %s. Ignoring.",
rvalue);
}
@@ -1395,19 +1351,20 @@ int config_parse_socket_service(const char *unit,
dbus_error_init(&error);
- p = unit_name_printf(UNIT(s), rvalue);
- if (!p)
- return log_oom();
+ r = unit_name_printf(UNIT(s), rvalue, &p);
+ if (r < 0)
+ log_syntax(unit, LOG_ERR, filename, line, -r,
+ "Failed to resolve specifiers, ignoring: %s", rvalue);
- if (!endswith(p, ".service")) {
+ if (!endswith(p ?: rvalue, ".service")) {
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Unit must be of type service, ignoring: %s", rvalue);
return 0;
}
- r = manager_load_unit(UNIT(s)->manager, p, NULL, &error, &x);
+ r = manager_load_unit(UNIT(s)->manager, p ?: rvalue, NULL, &error, &x);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to load unit %s, ignoring: %s",
rvalue, bus_error(&error, r));
dbus_error_free(&error);
@@ -1446,23 +1403,24 @@ int config_parse_service_sockets(const char *unit,
if (!t)
return log_oom();
- k = unit_name_printf(UNIT(s), t);
- if (!k)
- return log_oom();
+ r = unit_name_printf(UNIT(s), t, &k);
+ if (r < 0)
+ log_syntax(unit, LOG_ERR, filename, line, -r,
+ "Failed to resolve specifiers, ignoring: %s", strerror(-r));
- if (!endswith(k, ".socket")) {
+ if (!endswith(k ?: t, ".socket")) {
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Unit must be of type socket, ignoring: %s", k);
+ "Unit must be of type socket, ignoring: %s", k ?: t);
continue;
}
- r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k, NULL, true);
+ r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k ?: t, NULL, true);
if (r < 0)
log_syntax(unit, LOG_ERR, filename, line, -r,
"Failed to add dependency on %s, ignoring: %s",
- k, strerror(-r));
+ k ?: t, strerror(-r));
- r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k, NULL, true);
+ r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k ?: t, NULL, true);
if (r < 0)
return r;
}
@@ -1514,7 +1472,8 @@ int config_parse_unit_env_file(const char *unit,
char ***env = data;
Unit *u = userdata;
- _cleanup_free_ char *s = NULL;
+ _cleanup_free_ char *n = NULL;
+ const char *s;
int r;
assert(filename);
@@ -1529,10 +1488,12 @@ int config_parse_unit_env_file(const char *unit,
return 0;
}
- s = unit_full_printf(u, rvalue);
- if (!s)
- return log_oom();
+ r = unit_full_printf(u, rvalue, &n);
+ if (r < 0)
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to resolve specifiers, ignoring: %s", rvalue);
+ s = n ?: rvalue;
if (!path_is_absolute(s[0] == '-' ? s + 1 : s)) {
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Path '%s' is not absolute, ignoring.", s);
@@ -1560,11 +1521,12 @@ int config_parse_environ(const char *unit,
char*** env = data, *w, *state;
size_t l;
_cleanup_free_ char *k = NULL;
+ int r;
assert(filename);
assert(lvalue);
assert(rvalue);
- assert(u);
+ assert(data);
if (isempty(rvalue)) {
/* Empty assignment resets the list */
@@ -1573,7 +1535,15 @@ int config_parse_environ(const char *unit,
return 0;
}
- k = unit_full_printf(u, rvalue);
+ if (u) {
+ r = unit_full_printf(u, rvalue, &k);
+ if (r < 0)
+ log_syntax(unit, LOG_ERR, filename, line, -r,
+ "Failed to resolve specifiers, ignoring: %s", rvalue);
+ }
+
+ if (!k)
+ k = strdup(rvalue);
if (!k)
return log_oom();
@@ -1645,6 +1615,7 @@ int config_parse_unit_condition_path(const char *unit,
bool trigger, negate;
Condition *c;
_cleanup_free_ char *p = NULL;
+ int r;
assert(filename);
assert(lvalue);
@@ -1666,9 +1637,15 @@ int config_parse_unit_condition_path(const char *unit,
if (negate)
rvalue++;
- p = unit_full_printf(u, rvalue);
- if (!p)
- return log_oom();
+ r = unit_full_printf(u, rvalue, &p);
+ if (r < 0)
+ log_syntax(unit, LOG_ERR, filename, line, -r,
+ "Failed to resolve specifiers, ignoring: %s", rvalue);
+ if (!p) {
+ p = strdup(rvalue);
+ if (!p)
+ return log_oom();
+ }
if (!path_is_absolute(p)) {
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
@@ -1699,6 +1676,7 @@ int config_parse_unit_condition_string(const char *unit,
bool trigger, negate;
Condition *c;
_cleanup_free_ char *s = NULL;
+ int r;
assert(filename);
assert(lvalue);
@@ -1720,9 +1698,15 @@ int config_parse_unit_condition_string(const char *unit,
if (negate)
rvalue++;
- s = unit_full_printf(u, rvalue);
- if (!s)
- return log_oom();
+ r = unit_full_printf(u, rvalue, &s);
+ if (r < 0)
+ log_syntax(unit, LOG_ERR, filename, line, -r,
+ "Failed to resolve specifiers, ignoring: %s", rvalue);
+ if (!s) {
+ s = strdup(rvalue);
+ if (!s)
+ return log_oom();
+ }
c = condition_new(cond, s, trigger, negate);
if (!c)
@@ -1789,139 +1773,52 @@ int config_parse_unit_condition_null(const char *unit,
DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
DEFINE_CONFIG_PARSE_ENUM(config_parse_start_limit_action, start_limit_action, StartLimitAction, "Failed to parse start limit action specifier");
-int config_parse_unit_cgroup_attr(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_unit_requires_mounts_for(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
- Unit *u = data;
- size_t a, b;
- _cleanup_free_ char *n = NULL, *v = NULL;
- const CGroupSemantics *s;
- int r;
+ Unit *u = userdata;
+ char *state;
+ size_t l;
+ char *w;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
- if (isempty(rvalue)) {
- /* Empty assignment clears the list */
- cgroup_attribute_free_list(u->cgroup_attributes);
- u->cgroup_attributes = NULL;
- return 0;
- }
-
- a = strcspn(rvalue, WHITESPACE);
- b = strspn(rvalue + a, WHITESPACE);
- if (a <= 0 || b <= 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Failed to parse cgroup attribute value, ignoring: %s",
- rvalue);
- return 0;
- }
-
- n = strndup(rvalue, a);
- if (!n)
- return log_oom();
-
- r = cgroup_semantics_find(NULL, n, rvalue + a + b, &v, &s);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to parse cgroup attribute value, ignoring: %s",
- rvalue);
- return 0;
- }
-
- r = unit_add_cgroup_attribute(u, s, NULL, n, v ? v : rvalue + a + b, NULL);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to add cgroup attribute value, ignoring: %s", rvalue);
- return 0;
- }
-
- return 0;
-}
-
-int config_parse_unit_cgroup_attr_pretty(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Unit *u = data;
- _cleanup_free_ char *v = NULL;
- const CGroupSemantics *s;
- int r;
+ FOREACH_WORD_QUOTED(w, l, rvalue, state) {
+ int r;
+ _cleanup_free_ char *n;
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
+ n = strndup(w, l);
+ if (!n)
+ return log_oom();
- r = cgroup_semantics_find(NULL, lvalue, rvalue, &v, &s);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to parse cgroup attribute value, ignoring: %s",
- rvalue);
- return 0;
- } else if (r == 0) {
- log_syntax(unit, LOG_ERR, filename, line, ENOTSUP,
- "Unknown or unsupported cgroup attribute %s, ignoring: %s",
- lvalue, rvalue);
- return 0;
- }
+ if (!utf8_is_valid(n)) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ "Path is not UTF-8 clean, ignoring assignment: %s", rvalue);
+ continue;
+ }
- r = unit_add_cgroup_attribute(u, s, NULL, NULL, v, NULL);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to add cgroup attribute value, ignoring: %s", rvalue);
- return 0;
+ r = unit_require_mounts_for(u, n);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to add required mount for, ignoring: %s", rvalue);
+ continue;
+ }
}
return 0;
}
-int config_parse_unit_requires_mounts_for(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Unit *u = userdata;
- int r;
- bool empty_before;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- empty_before = !u->requires_mounts_for;
-
- r = config_parse_path_strv(unit, filename, line, section, lvalue, ltype,
- rvalue, data, userdata);
-
- /* Make it easy to find units with requires_mounts set */
- if (empty_before && u->requires_mounts_for)
- LIST_PREPEND(Unit, has_requires_mounts_for, u->manager->has_requires_mounts_for, u);
-
- return r;
-}
-
int config_parse_documentation(const char *unit,
const char *filename,
unsigned line,
@@ -2058,6 +1955,365 @@ int config_parse_syscall_filter(const char *unit,
return 0;
}
+int config_parse_unit_slice(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ _cleanup_free_ char *k = NULL;
+ Unit *u = userdata, *slice;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(u);
+
+ r = unit_name_printf(u, rvalue, &k);
+ if (r < 0)
+ log_syntax(unit, LOG_ERR, filename, line, -r,
+ "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
+ if (!k) {
+ k = strdup(rvalue);
+ if (!k)
+ return log_oom();
+ }
+
+ r = manager_load_unit(u->manager, k, NULL, NULL, &slice);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, -r,
+ "Failed to load slice unit %s. Ignoring.", k);
+ return 0;
+ }
+
+ if (slice->type != UNIT_SLICE) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ "Slice unit %s is not a slice. Ignoring.", k);
+ return 0;
+ }
+
+ unit_ref_set(&u->slice, slice);
+ return 0;
+}
+
+DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGroupDevicePolicy, "Failed to parse device policy");
+
+int config_parse_cpu_shares(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ CGroupContext *c = data;
+ unsigned long lu;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ if (isempty(rvalue)) {
+ c->cpu_shares = 1024;
+ return 0;
+ }
+
+ r = safe_atolu(rvalue, &lu);
+ if (r < 0 || lu <= 0) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ "CPU shares '%s' invalid. Ignoring.", rvalue);
+ return 0;
+ }
+
+ c->cpu_shares = lu;
+ return 0;
+}
+
+int config_parse_memory_limit(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ CGroupContext *c = data;
+ off_t bytes;
+ int r;
+
+ if (isempty(rvalue)) {
+ c->memory_limit = (uint64_t) -1;
+ return 0;
+ }
+
+ assert_cc(sizeof(uint64_t) == sizeof(off_t));
+
+ r = parse_bytes(rvalue, &bytes);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ "Memory limit '%s' invalid. Ignoring.", rvalue);
+ return 0;
+ }
+
+ c->memory_limit = (uint64_t) bytes;
+ return 0;
+}
+
+int config_parse_device_allow(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ _cleanup_free_ char *path = NULL;
+ CGroupContext *c = data;
+ CGroupDeviceAllow *a;
+ const char *m;
+ size_t n;
+
+ if (isempty(rvalue)) {
+ while (c->device_allow)
+ cgroup_context_free_device_allow(c, c->device_allow);
+
+ return 0;
+ }
+
+ n = strcspn(rvalue, WHITESPACE);
+ path = strndup(rvalue, n);
+ if (!path)
+ return log_oom();
+
+ if (!path_startswith(path, "/dev")) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ "Invalid device node path '%s'. Ignoring.", path);
+ return 0;
+ }
+
+ m = rvalue + n + strspn(rvalue + n, WHITESPACE);
+ if (isempty(m))
+ m = "rwm";
+
+ if (!in_charset(m, "rwm")) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ "Invalid device rights '%s'. Ignoring.", m);
+ return 0;
+ }
+
+ a = new0(CGroupDeviceAllow, 1);
+ if (!a)
+ return log_oom();
+
+ a->path = path;
+ path = NULL;
+ a->r = !!strchr(m, 'r');
+ a->w = !!strchr(m, 'w');
+ a->m = !!strchr(m, 'm');
+
+ LIST_PREPEND(CGroupDeviceAllow, device_allow, c->device_allow, a);
+ return 0;
+}
+
+int config_parse_blockio_weight(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ CGroupContext *c = data;
+ unsigned long lu;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ if (isempty(rvalue)) {
+ c->blockio_weight = 1000;
+ return 0;
+ }
+
+ r = safe_atolu(rvalue, &lu);
+ if (r < 0 || lu < 10 || lu > 1000) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ "Block IO weight '%s' invalid. Ignoring.", rvalue);
+ return 0;
+ }
+
+ c->blockio_weight = lu;
+
+ return 0;
+}
+
+int config_parse_blockio_device_weight(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ _cleanup_free_ char *path = NULL;
+ CGroupBlockIODeviceWeight *w;
+ CGroupContext *c = data;
+ unsigned long lu;
+ const char *weight;
+ size_t n;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ if (isempty(rvalue)) {
+ while (c->blockio_device_weights)
+ cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
+
+ return 0;
+ }
+
+ n = strcspn(rvalue, WHITESPACE);
+ weight = rvalue + n;
+ if (!*weight) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ "Expected block device and device weight. Ignoring.");
+ return 0;
+ }
+
+ path = strndup(rvalue, n);
+ if (!path)
+ return log_oom();
+
+ if (!path_startswith(path, "/dev")) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ "Invalid device node path '%s'. Ignoring.", path);
+ return 0;
+ }
+
+ weight += strspn(weight, WHITESPACE);
+ r = safe_atolu(weight, &lu);
+ if (r < 0 || lu < 10 || lu > 1000) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ "Block IO weight '%s' invalid. Ignoring.", rvalue);
+ return 0;
+ }
+
+
+ w = new0(CGroupBlockIODeviceWeight, 1);
+ if (!w)
+ return log_oom();
+
+ w->path = path;
+ path = NULL;
+
+ w->weight = lu;
+
+ LIST_PREPEND(CGroupBlockIODeviceWeight, device_weights, c->blockio_device_weights, w);
+ return 0;
+}
+
+int config_parse_blockio_bandwidth(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ _cleanup_free_ char *path = NULL;
+ CGroupBlockIODeviceBandwidth *b;
+ CGroupContext *c = data;
+ const char *bandwidth;
+ off_t bytes;
+ bool read;
+ size_t n;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ read = streq("BlockIOReadBandwidth", lvalue);
+
+ if (isempty(rvalue)) {
+ CGroupBlockIODeviceBandwidth *next;
+
+ LIST_FOREACH_SAFE (device_bandwidths, b, next, c->blockio_device_bandwidths)
+ if (b->read == read)
+ cgroup_context_free_blockio_device_bandwidth(c, b);
+
+ return 0;
+ }
+
+ n = strcspn(rvalue, WHITESPACE);
+ bandwidth = rvalue + n;
+ bandwidth += strspn(bandwidth, WHITESPACE);
+
+ if (!*bandwidth) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ "Expected space separated pair of device node and bandwidth. Ignoring.");
+ return 0;
+ }
+
+ path = strndup(rvalue, n);
+ if (!path)
+ return log_oom();
+
+ if (!path_startswith(path, "/dev")) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ "Invalid device node path '%s'. Ignoring.", path);
+ return 0;
+ }
+
+ r = parse_bytes(bandwidth, &bytes);
+ if (r < 0 || bytes <= 0) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ "Block IO Bandwidth '%s' invalid. Ignoring.", rvalue);
+ return 0;
+ }
+
+ b = new0(CGroupBlockIODeviceBandwidth, 1);
+ if (!b)
+ return log_oom();
+
+ b->path = path;
+ path = NULL;
+ b->bandwidth = (uint64_t) bytes;
+ b->read = read;
+
+ LIST_PREPEND(CGroupBlockIODeviceBandwidth, device_bandwidths, c->blockio_device_bandwidths, b);
+
+ return 0;
+}
+
#define FOLLOW_MAX 8
static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
@@ -2267,14 +2523,14 @@ static int load_from_path(Unit *u, const char *path) {
if (null_or_empty(&st))
u->load_state = UNIT_MASKED;
else {
+ u->load_state = UNIT_LOADED;
+
/* Now, parse the file contents */
r = config_parse(u->id, filename, f, UNIT_VTABLE(u)->sections,
config_item_perf_lookup,
(void*) load_fragment_gperf_lookup, false, true, u);
if (r < 0)
goto finish;
-
- u->load_state = UNIT_LOADED;
}
free(u->fragment_path);
@@ -2417,7 +2673,6 @@ void unit_dump_config_items(FILE *f) {
{ config_parse_exec_secure_bits, "SECUREBITS" },
{ config_parse_bounding_set, "BOUNDINGSET" },
{ config_parse_limit, "LIMIT" },
- { config_parse_unit_cgroup, "CGROUP [...]" },
{ config_parse_unit_deps, "UNIT [...]" },
{ config_parse_exec, "PATH [ARGUMENT [...]]" },
{ config_parse_service_type, "SERVICETYPE" },
@@ -2446,6 +2701,24 @@ void unit_dump_config_items(FILE *f) {
{ config_parse_unit_condition_path, "CONDITION" },
{ config_parse_unit_condition_string, "CONDITION" },
{ config_parse_unit_condition_null, "CONDITION" },
+ { config_parse_unit_slice, "SLICE" },
+ { config_parse_documentation, "URL" },
+ { config_parse_service_timeout, "SECONDS" },
+ { config_parse_start_limit_action, "ACTION" },
+ { config_parse_set_status, "STATUS" },
+ { config_parse_service_sockets, "SOCKETS" },
+ { config_parse_fsck_passno, "PASSNO" },
+ { config_parse_environ, "ENVIRON" },
+ { config_parse_syscall_filter, "SYSCALL" },
+ { config_parse_cpu_shares, "SHARES" },
+ { config_parse_memory_limit, "LIMIT" },
+ { config_parse_device_allow, "DEVICE" },
+ { config_parse_device_policy, "POLICY" },
+ { config_parse_blockio_bandwidth, "BANDWIDTH" },
+ { config_parse_blockio_weight, "WEIGHT" },
+ { config_parse_blockio_device_weight, "DEVICEWEIGHT" },
+ { config_parse_long, "LONG" },
+ { config_parse_socket_service, "SERVICE" },
};
const char *prev = NULL;
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
index ff7f22a6f0..90e5e3a5c9 100644
--- a/src/core/load-fragment.h
+++ b/src/core/load-fragment.h
@@ -55,7 +55,6 @@ int config_parse_exec_capabilities(const char *unit, const char *filename, unsig
int config_parse_exec_secure_bits(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_bounding_set(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_limit(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_cgroup(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_sysv_priority(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_fsck_passno(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_kill_signal(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
@@ -73,11 +72,17 @@ int config_parse_unit_condition_null(const char *unit, const char *filename, uns
int config_parse_kill_mode(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_notify_access(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_start_limit_action(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_cgroup_attr(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_cgroup_attr_pretty(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_unit_requires_mounts_for(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_syscall_filter(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_environ(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_unit_slice(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_cpu_shares(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_memory_limit(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_device_policy(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_device_allow(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_blockio_weight(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_blockio_device_weight(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_blockio_bandwidth(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
/* gperf prototypes */
const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, unsigned length);
diff --git a/src/core/locale-setup.c b/src/core/locale-setup.c
index d7113b9795..276deb9dc1 100644
--- a/src/core/locale-setup.c
+++ b/src/core/locale-setup.c
@@ -28,6 +28,8 @@
#include "macro.h"
#include "virt.h"
#include "fileio.h"
+#include "strv.h"
+#include "env-util.h"
enum {
/* We don't list LC_ALL here on purpose. People should be
@@ -67,7 +69,8 @@ static const char * const variable_names[_VARIABLE_MAX] = {
[VARIABLE_LC_IDENTIFICATION] = "LC_IDENTIFICATION"
};
-int locale_setup(void) {
+int locale_setup(char ***environment) {
+ char **add;
char *variables[_VARIABLE_MAX] = {};
int r = 0, i;
@@ -117,27 +120,44 @@ int locale_setup(void) {
log_warning("Failed to read /etc/locale.conf: %s", strerror(-r));
}
- if (!variables[VARIABLE_LANG]) {
- variables[VARIABLE_LANG] = strdup("C");
- if (!variables[VARIABLE_LANG]) {
+ add = NULL;
+ for (i = 0; i < _VARIABLE_MAX; i++) {
+ char *s;
+
+ if (!variables[i])
+ continue;
+
+ s = strjoin(variable_names[i], "=", variables[i], NULL);
+ if (!s) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ if (strv_push(&add, s) < 0) {
+ free(s);
r = -ENOMEM;
goto finish;
}
}
- for (i = 0; i < _VARIABLE_MAX; i++) {
- if (variables[i]) {
- if (setenv(variable_names[i], variables[i], 1) < 0) {
- r = -errno;
- goto finish;
- }
- } else
- unsetenv(variable_names[i]);
+ if (!strv_isempty(add)) {
+ char **e;
+
+ e = strv_env_merge(2, *environment, add);
+ if (!e) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ strv_free(*environment);
+ *environment = e;
}
r = 0;
finish:
+ strv_free(add);
+
for (i = 0; i < _VARIABLE_MAX; i++)
free(variables[i]);
diff --git a/src/core/locale-setup.h b/src/core/locale-setup.h
index 5a0f2f7888..62c654c37c 100644
--- a/src/core/locale-setup.h
+++ b/src/core/locale-setup.h
@@ -21,4 +21,4 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-int locale_setup(void);
+int locale_setup(char ***environment);
diff --git a/src/core/macros.systemd.in b/src/core/macros.systemd.in
index f77082c2db..89b48259ad 100644
--- a/src/core/macros.systemd.in
+++ b/src/core/macros.systemd.in
@@ -20,6 +20,7 @@
# RPM macros for packages installing systemd unit files
%_unitdir @systemunitdir@
+%_userunitdir @userunitdir@
%_presetdir @systempresetdir@
%_udevhwdbdir @udevhwdbdir@
%_udevrulesdir @udevrulesdir@
@@ -71,3 +72,7 @@ fi \
%journal_catalog_update() \
@rootbindir@/journalctl --update-catalog >/dev/null 2>&1 || : \
%{nil}
+
+%tmpfiles_create() \
+@rootbindir@/systemd-tmpfiles --create %{?*} >/dev/null 2>&1 || : \
+%{nil}
diff --git a/src/core/main.c b/src/core/main.c
index 7fc06bea05..fe291f8410 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -64,12 +64,10 @@
#endif
#include "hostname-setup.h"
#include "machine-id-setup.h"
-#include "locale-setup.h"
#include "selinux-setup.h"
#include "ima-setup.h"
#include "fileio.h"
#include "smack-setup.h"
-#include "efivars.h"
static enum {
ACTION_RUN,
@@ -89,12 +87,12 @@ static int arg_crash_chvt = -1;
static bool arg_confirm_spawn = false;
static bool arg_show_status = true;
static bool arg_switched_root = false;
-static char **arg_default_controllers = NULL;
static char ***arg_join_controllers = NULL;
static ExecOutput arg_default_std_output = EXEC_OUTPUT_JOURNAL;
static ExecOutput arg_default_std_error = EXEC_OUTPUT_INHERIT;
static usec_t arg_runtime_watchdog = 0;
static usec_t arg_shutdown_watchdog = 10 * USEC_PER_MINUTE;
+static char **arg_default_environment = NULL;
static struct rlimit *arg_default_rlimit[RLIMIT_NLIMITS] = {};
static uint64_t arg_capability_bounding_set_drop = 0;
static nsec_t arg_timer_slack_nsec = (nsec_t) -1;
@@ -106,7 +104,10 @@ static void nop_handler(int sig) {
_noreturn_ static void crash(int sig) {
- if (!arg_dump_core)
+ if (getpid() != 1)
+ /* Pass this on immediately, if this is not PID 1 */
+ raise(sig);
+ else if (!arg_dump_core)
log_error("Caught <%s>, not dumping core.", signal_to_string(sig));
else {
struct sigaction sa = {
@@ -116,7 +117,7 @@ _noreturn_ static void crash(int sig) {
pid_t pid;
/* We want to wait for the core process, hence let's enable SIGCHLD */
- assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
+ sigaction(SIGCHLD, &sa, NULL);
pid = fork();
if (pid < 0)
@@ -128,7 +129,7 @@ _noreturn_ static void crash(int sig) {
/* Enable default signal handler for core dump */
zero(sa);
sa.sa_handler = SIG_DFL;
- assert_se(sigaction(sig, &sa, NULL) == 0);
+ sigaction(sig, &sa, NULL);
/* Don't limit the core dump size */
rl.rlim_cur = RLIM_INFINITY;
@@ -136,7 +137,7 @@ _noreturn_ static void crash(int sig) {
setrlimit(RLIMIT_CORE, &rl);
/* Just to be sure... */
- assert_se(chdir("/") == 0);
+ chdir("/");
/* Raise the signal again */
raise(sig);
@@ -347,32 +348,21 @@ static int parse_proc_cmdline_word(const char *word) {
arg_default_std_error = r;
} else if (startswith(word, "systemd.setenv=")) {
_cleanup_free_ char *cenv = NULL;
- char *eq;
- int r;
cenv = strdup(word + 15);
if (!cenv)
return -ENOMEM;
- eq = strchr(cenv, '=');
- if (!eq) {
- if (!env_name_is_valid(cenv))
- log_warning("Environment variable name '%s' is not valid. Ignoring.", cenv);
- else {
- r = unsetenv(cenv);
- if (r < 0)
- log_warning("Unsetting environment variable '%s' failed, ignoring: %m", cenv);
- }
- } else {
- if (!env_assignment_is_valid(cenv))
- log_warning("Environment variable assignment '%s' is not valid. Ignoring.", cenv);
- else {
- *eq = 0;
- r = setenv(cenv, eq + 1, 1);
- if (r < 0)
- log_warning("Setting environment variable '%s=%s' failed, ignoring: %m", cenv, eq + 1);
- }
- }
+ if (env_assignment_is_valid(cenv)) {
+ char **env;
+
+ env = strv_env_set(arg_default_environment, cenv);
+ if (env)
+ arg_default_environment = env;
+ else
+ log_warning("Setting environment variable '%s' failed, ignoring: %m", cenv);
+ } else
+ log_warning("Environment variable name '%s' is not valid. Ignoring.", cenv);
} else if (startswith(word, "systemd.") ||
(in_initrd() && startswith(word, "rd.systemd."))) {
@@ -411,7 +401,14 @@ static int parse_proc_cmdline_word(const char *word) {
} else if (streq(word, "quiet"))
arg_show_status = false;
- else if (!in_initrd()) {
+ else if (streq(word, "debug")) {
+ /* Log to kmsg, the journal socket will fill up before the
+ * journal is started and tools running during that time
+ * will block with every log message for for 60 seconds,
+ * before they give up. */
+ log_set_max_level(LOG_DEBUG);
+ log_set_target(LOG_TARGET_KMSG);
+ } else if (!in_initrd()) {
unsigned i;
/* SysV compatibility */
@@ -637,7 +634,6 @@ static int parse_config_file(void) {
{ "Manager", "ShowStatus", config_parse_bool, 0, &arg_show_status },
{ "Manager", "CrashChVT", config_parse_int, 0, &arg_crash_chvt },
{ "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, NULL },
- { "Manager", "DefaultControllers", config_parse_strv, 0, &arg_default_controllers },
{ "Manager", "DefaultStandardOutput", config_parse_output, 0, &arg_default_std_output },
{ "Manager", "DefaultStandardError", config_parse_output, 0, &arg_default_std_error },
{ "Manager", "JoinControllers", config_parse_join_controllers, 0, &arg_join_controllers },
@@ -645,6 +641,7 @@ static int parse_config_file(void) {
{ "Manager", "ShutdownWatchdogSec", config_parse_sec, 0, &arg_shutdown_watchdog },
{ "Manager", "CapabilityBoundingSet", config_parse_bounding_set, 0, &arg_capability_bounding_set_drop },
{ "Manager", "TimerSlackNSec", config_parse_nsec, 0, &arg_timer_slack_nsec },
+ { "Manager", "DefaultEnvironment", config_parse_environ, 0, &arg_default_environment },
{ "Manager", "DefaultLimitCPU", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_CPU]},
{ "Manager", "DefaultLimitFSIZE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_FSIZE]},
{ "Manager", "DefaultLimitDATA", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_DATA]},
@@ -1051,15 +1048,16 @@ static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching
assert(_f);
assert(_fds);
- /* Make sure nothing is really destructed when we shut down */
- m->n_reloading ++;
-
r = manager_open_serialization(m, &f);
if (r < 0) {
log_error("Failed to create serialization file: %s", strerror(-r));
goto fail;
}
+ /* Make sure nothing is really destructed when we shut down */
+ m->n_reloading ++;
+ bus_broadcast_reloading(m, true);
+
fds = fdset_new();
if (!fds) {
r = -ENOMEM;
@@ -1140,25 +1138,6 @@ static int bump_rlimit_nofile(struct rlimit *saved_rlimit) {
return 0;
}
-static struct dual_timestamp* parse_initrd_timestamp(struct dual_timestamp *t) {
- const char *e;
- unsigned long long a, b;
-
- assert(t);
-
- e = getenv("RD_TIMESTAMP");
- if (!e)
- return NULL;
-
- if (sscanf(e, "%llu %llu", &a, &b) != 2)
- return NULL;
-
- t->realtime = (usec_t) a;
- t->monotonic = (usec_t) b;
-
- return t;
-}
-
static void test_mtab(void) {
char *p;
@@ -1239,8 +1218,6 @@ int main(int argc, char *argv[]) {
dual_timestamp initrd_timestamp = { 0ULL, 0ULL };
dual_timestamp userspace_timestamp = { 0ULL, 0ULL };
dual_timestamp kernel_timestamp = { 0ULL, 0ULL };
- dual_timestamp firmware_timestamp = { 0ULL, 0ULL };
- dual_timestamp loader_timestamp = { 0ULL, 0ULL };
static char systemd[] = "systemd";
bool skip_setup = false;
int j;
@@ -1288,28 +1265,20 @@ int main(int argc, char *argv[]) {
log_show_color(isatty(STDERR_FILENO) > 0);
+ /* Disable the umask logic */
+ if (getpid() == 1)
+ umask(0);
+
if (getpid() == 1 && detect_container(NULL) <= 0) {
-#ifdef ENABLE_EFI
- efi_get_boot_timestamps(&userspace_timestamp, &firmware_timestamp, &loader_timestamp);
-#endif
+
/* Running outside of a container as PID 1 */
arg_running_as = SYSTEMD_SYSTEM;
make_null_stdio();
log_set_target(LOG_TARGET_KMSG);
log_open();
- if (in_initrd()) {
- char *rd_timestamp = NULL;
-
+ if (in_initrd())
initrd_timestamp = userspace_timestamp;
- asprintf(&rd_timestamp, "%llu %llu",
- (unsigned long long) initrd_timestamp.realtime,
- (unsigned long long) initrd_timestamp.monotonic);
- if (rd_timestamp) {
- setenv("RD_TIMESTAMP", rd_timestamp, 1);
- free(rd_timestamp);
- }
- }
if (!skip_setup) {
mount_setup_early();
@@ -1345,10 +1314,10 @@ int main(int argc, char *argv[]) {
*/
hwclock_reset_timezone();
- /* Tell the kernel our time zone */
+ /* Tell the kernel our timezone */
r = hwclock_set_timezone(NULL);
if (r < 0)
- log_error("Failed to set the kernel's time zone, ignoring: %s", strerror(-r));
+ log_error("Failed to set the kernel's timezone, ignoring: %s", strerror(-r));
}
}
@@ -1408,7 +1377,6 @@ int main(int argc, char *argv[]) {
/* Reset all signal handlers. */
assert_se(reset_all_signal_handlers() == 0);
- /* If we are init, we can block sigkill. Yay. */
ignore_signals(SIGNALS_IGNORE, -1);
if (parse_config_file() < 0)
@@ -1474,59 +1442,12 @@ int main(int argc, char *argv[]) {
if (serialization)
assert_se(fdset_remove(fds, fileno(serialization)) >= 0);
- /* Set up PATH unless it is already set */
- setenv("PATH",
-#ifdef HAVE_SPLIT_USR
- "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
-#else
- "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin",
-#endif
- arg_running_as == SYSTEMD_SYSTEM);
-
- if (arg_running_as == SYSTEMD_SYSTEM) {
- /* Parse the data passed to us. We leave this
- * variables set, but the manager later on will not
- * pass them on to our children. */
- if (!in_initrd())
- parse_initrd_timestamp(&initrd_timestamp);
-
- /* Unset some environment variables passed in from the
- * kernel that don't really make sense for us. */
- unsetenv("HOME");
- unsetenv("TERM");
-
- /* When we are invoked by a shell, these might be set,
- * but make little sense to pass on */
- unsetenv("PWD");
- unsetenv("SHLVL");
- unsetenv("_");
-
- /* When we are invoked by a chroot-like tool such as
- * nspawn, these might be set, but make little sense
- * to pass on */
- unsetenv("USER");
- unsetenv("LOGNAME");
-
- /* We suppress the socket activation env vars, as
- * we'll try to match *any* open fd to units if
- * possible. */
- unsetenv("LISTEN_FDS");
- unsetenv("LISTEN_PID");
-
- /* All other variables are left as is, so that clients
- * can still read them via /proc/1/environ */
- }
-
- /* Move out of the way, so that we won't block unmounts */
- assert_se(chdir("/") == 0);
-
- if (arg_running_as == SYSTEMD_SYSTEM) {
+ if (arg_running_as == SYSTEMD_SYSTEM)
/* Become a session leader if we aren't one yet. */
setsid();
- /* Disable the umask logic */
- umask(0);
- }
+ /* Move out of the way, so that we won't block unmounts */
+ assert_se(chdir("/") == 0);
/* Make sure D-Bus doesn't fiddle with the SIGPIPE handlers */
dbus_connection_set_change_sigpipe(FALSE);
@@ -1565,8 +1486,6 @@ int main(int argc, char *argv[]) {
log_debug(PACKAGE_STRING " running in user mode. (" SYSTEMD_FEATURES ")");
if (arg_running_as == SYSTEMD_SYSTEM && !skip_setup) {
- locale_setup();
-
if (arg_show_status || plymouth_running())
status_welcome();
@@ -1590,14 +1509,14 @@ int main(int argc, char *argv[]) {
log_error("Failed to adjust timer slack: %m");
if (arg_capability_bounding_set_drop) {
- r = capability_bounding_set_drop(arg_capability_bounding_set_drop, true);
+ r = capability_bounding_set_drop_usermode(arg_capability_bounding_set_drop);
if (r < 0) {
- log_error("Failed to drop capability bounding set: %s", strerror(-r));
+ log_error("Failed to drop capability bounding set of usermode helpers: %s", strerror(-r));
goto finish;
}
- r = capability_bounding_set_drop_usermode(arg_capability_bounding_set_drop);
+ r = capability_bounding_set_drop(arg_capability_bounding_set_drop, true);
if (r < 0) {
- log_error("Failed to drop capability bounding set of usermode helpers: %s", strerror(-r));
+ log_error("Failed to drop capability bounding set: %s", strerror(-r));
goto finish;
}
}
@@ -1614,7 +1533,7 @@ int main(int argc, char *argv[]) {
if (arg_running_as == SYSTEMD_SYSTEM)
bump_rlimit_nofile(&saved_rlimit_nofile);
- r = manager_new(arg_running_as, &m);
+ r = manager_new(arg_running_as, !!serialization, &m);
if (r < 0) {
log_error("Failed to allocate manager object: %s", strerror(-r));
goto finish;
@@ -1627,14 +1546,12 @@ int main(int argc, char *argv[]) {
m->shutdown_watchdog = arg_shutdown_watchdog;
m->userspace_timestamp = userspace_timestamp;
m->kernel_timestamp = kernel_timestamp;
- m->firmware_timestamp = firmware_timestamp;
- m->loader_timestamp = loader_timestamp;
m->initrd_timestamp = initrd_timestamp;
manager_set_default_rlimits(m, arg_default_rlimit);
- if (arg_default_controllers)
- manager_set_default_controllers(m, arg_default_controllers);
+ if (arg_default_environment)
+ manager_environment_add(m, arg_default_environment);
manager_set_show_status(m, arg_show_status);
@@ -1650,6 +1567,7 @@ int main(int argc, char *argv[]) {
/* This will close all file descriptors that were opened, but
* not claimed by any unit. */
fdset_free(fds);
+ fds = NULL;
if (serialization) {
fclose(serialization);
@@ -1669,7 +1587,7 @@ int main(int argc, char *argv[]) {
if (r < 0) {
log_error("Failed to load default target: %s", bus_error(&error, r));
dbus_error_free(&error);
- } else if (target->load_state == UNIT_ERROR)
+ } else if (target->load_state == UNIT_ERROR || target->load_state == UNIT_NOT_FOUND)
log_error("Failed to load default target: %s", strerror(-target->load_error));
else if (target->load_state == UNIT_MASKED)
log_error("Default target masked.");
@@ -1682,7 +1600,7 @@ int main(int argc, char *argv[]) {
log_error("Failed to load rescue target: %s", bus_error(&error, r));
dbus_error_free(&error);
goto finish;
- } else if (target->load_state == UNIT_ERROR) {
+ } else if (target->load_state == UNIT_ERROR || target->load_state == UNIT_NOT_FOUND) {
log_error("Failed to load rescue target: %s", strerror(-target->load_error));
goto finish;
} else if (target->load_state == UNIT_MASKED) {
@@ -1805,7 +1723,6 @@ finish:
free(arg_default_rlimit[j]);
free(arg_default_unit);
- strv_free(arg_default_controllers);
free_join_controllers();
dbus_shutdown();
@@ -1865,6 +1782,10 @@ finish:
args[i++] = sfd;
args[i++] = NULL;
+ /* do not pass along the environment we inherit from the kernel or initrd */
+ if (switch_root_dir)
+ clearenv();
+
assert(i <= args_size);
execv(args[0], (char* const*) args);
}
@@ -1946,6 +1867,12 @@ finish:
watchdog_close(true);
}
+ /* Avoid the creation of new processes forked by the
+ * kernel; at this point, we will not listen to the
+ * signals anyway */
+ if (detect_container(NULL) <= 0)
+ cg_uninstall_release_agent(SYSTEMD_CGROUP_CONTROLLER);
+
execve(SYSTEMD_SHUTDOWN_BINARY_PATH, (char **) command_line, env_block);
free(env_block);
log_error("Failed to execute shutdown binary, freezing: %m");
diff --git a/src/core/manager.c b/src/core/manager.c
index c7f8f20a70..58dacdc8b5 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -55,7 +55,7 @@
#include "util.h"
#include "mkdir.h"
#include "ratelimit.h"
-#include "cgroup.h"
+#include "locale-setup.h"
#include "mount-setup.h"
#include "unit-name.h"
#include "dbus-unit.h"
@@ -70,11 +70,9 @@
#include "cgroup-util.h"
#include "path-util.h"
#include "audit-fd.h"
+#include "boot-timestamps.h"
#include "env-util.h"
-/* As soon as 16 units are in our GC queue, make sure to run a gc sweep */
-#define GC_QUEUE_ENTRIES_MAX 16
-
/* As soon as 5s passed since a unit was added to our GC queue, make sure to run a gc sweep */
#define GC_QUEUE_USEC_MAX (10*USEC_PER_SEC)
@@ -276,6 +274,54 @@ static void manager_print_jobs_in_progress(Manager *m) {
m->jobs_in_progress_iteration++;
}
+static int manager_watch_idle_pipe(Manager *m) {
+ struct epoll_event ev = {
+ .events = EPOLLIN,
+ .data.ptr = &m->idle_pipe_watch,
+ };
+ int r;
+
+ if (m->idle_pipe_watch.type != WATCH_INVALID)
+ return 0;
+
+ if (m->idle_pipe[2] < 0)
+ return 0;
+
+ m->idle_pipe_watch.type = WATCH_IDLE_PIPE;
+ m->idle_pipe_watch.fd = m->idle_pipe[2];
+ if (m->idle_pipe_watch.fd < 0) {
+ log_error("Failed to create timerfd: %m");
+ r = -errno;
+ goto err;
+ }
+
+ if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->idle_pipe_watch.fd, &ev) < 0) {
+ log_error("Failed to add idle_pipe fd to epoll: %m");
+ r = -errno;
+ goto err;
+ }
+
+ log_debug("Set up idle_pipe watch.");
+
+ return 0;
+
+err:
+ if (m->idle_pipe_watch.fd >= 0)
+ close_nointr_nofail(m->idle_pipe_watch.fd);
+ watch_init(&m->idle_pipe_watch);
+ return r;
+}
+
+static void manager_unwatch_idle_pipe(Manager *m) {
+ if (m->idle_pipe_watch.type != WATCH_IDLE_PIPE)
+ return;
+
+ assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, m->idle_pipe_watch.fd, NULL) >= 0);
+ watch_init(&m->idle_pipe_watch);
+
+ log_debug("Closed idle_pipe watch.");
+}
+
static int manager_setup_time_change(Manager *m) {
struct epoll_event ev = {
.events = EPOLLIN,
@@ -409,25 +455,34 @@ static int manager_setup_signals(Manager *m) {
return 0;
}
-static void manager_strip_environment(Manager *m) {
+static int manager_default_environment(Manager *m) {
assert(m);
- /* Remove variables from the inherited set that are part of
- * the container interface:
- * http://www.freedesktop.org/wiki/Software/systemd/ContainerInterface */
- strv_remove_prefix(m->environment, "container=");
- strv_remove_prefix(m->environment, "container_");
+ if (m->running_as == SYSTEMD_SYSTEM) {
+ /* The system manager always starts with a clean
+ * environment for its children. It does not import
+ * the kernel or the parents exported variables.
+ *
+ * The initial passed environ is untouched to keep
+ * /proc/self/environ valid; it is used for tagging
+ * the init process inside containers. */
+ m->environment = strv_new("PATH=" DEFAULT_PATH,
+ NULL);
+
+ /* Import locale variables LC_*= from configuration */
+ locale_setup(&m->environment);
+ } else
+ /* The user manager passes its own environment
+ * along to its children. */
+ m->environment = strv_copy(environ);
- /* Remove variables from the inherited set that are part of
- * the initrd interface:
- * http://www.freedesktop.org/wiki/Software/systemd/InitrdInterface */
- strv_remove_prefix(m->environment, "RD_");
+ if (!m->environment)
+ return -ENOMEM;
- /* Drop invalid entries */
- strv_env_clean(m->environment);
+ return 0;
}
-int manager_new(SystemdRunningAs running_as, Manager **_m) {
+int manager_new(SystemdRunningAs running_as, bool reexecuting, Manager **_m) {
Manager *m;
int r = -ENOMEM;
@@ -439,11 +494,16 @@ int manager_new(SystemdRunningAs running_as, Manager **_m) {
if (!m)
return -ENOMEM;
+#ifdef ENABLE_EFI
+ if (detect_container(NULL) <= 0)
+ boot_timestamps(&m->userspace_timestamp, &m->firmware_timestamp, &m->loader_timestamp);
+#endif
+
m->running_as = running_as;
m->name_data_slot = m->conn_data_slot = m->subscribed_data_slot = -1;
m->exit_code = _MANAGER_EXIT_CODE_INVALID;
m->pin_cgroupfs_fd = -1;
- m->idle_pipe[0] = m->idle_pipe[1] = -1;
+ m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] = m->idle_pipe[3] = -1;
watch_init(&m->signal_watch);
watch_init(&m->mount_watch);
@@ -455,18 +515,10 @@ int manager_new(SystemdRunningAs running_as, Manager **_m) {
m->epoll_fd = m->dev_autofs_fd = -1;
m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */
- m->environment = strv_copy(environ);
- if (!m->environment)
+ r = manager_default_environment(m);
+ if (r < 0)
goto fail;
- manager_strip_environment(m);
-
- if (running_as == SYSTEMD_SYSTEM) {
- m->default_controllers = strv_new("cpu", NULL);
- if (!m->default_controllers)
- goto fail;
- }
-
if (!(m->units = hashmap_new(string_hash_func, string_compare_func)))
goto fail;
@@ -476,10 +528,12 @@ int manager_new(SystemdRunningAs running_as, Manager **_m) {
if (!(m->watch_pids = hashmap_new(trivial_hash_func, trivial_compare_func)))
goto fail;
- if (!(m->cgroup_bondings = hashmap_new(string_hash_func, string_compare_func)))
+ m->cgroup_unit = hashmap_new(string_hash_func, string_compare_func);
+ if (!m->cgroup_unit)
goto fail;
- if (!(m->watch_bus = hashmap_new(string_hash_func, string_compare_func)))
+ m->watch_bus = hashmap_new(string_hash_func, string_compare_func);
+ if (!m->watch_bus)
goto fail;
m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
@@ -503,9 +557,13 @@ int manager_new(SystemdRunningAs running_as, Manager **_m) {
goto fail;
/* Try to connect to the busses, if possible. */
- r = bus_init(m, running_as != SYSTEMD_SYSTEM);
- if (r < 0)
- goto fail;
+ if ((running_as == SYSTEMD_USER && getenv("DBUS_SESSION_BUS_ADDRESS")) ||
+ running_as == SYSTEMD_SYSTEM) {
+ r = bus_init(m, reexecuting || running_as != SYSTEMD_SYSTEM);
+ if (r < 0)
+ goto fail;
+ } else
+ log_debug("Skipping DBus session bus connection attempt - no DBUS_SESSION_BUS_ADDRESS set...");
m->taint_usr = dir_is_empty("/usr") > 0;
@@ -600,12 +658,7 @@ static unsigned manager_dispatch_gc_queue(Manager *m) {
assert(m);
- if ((m->n_in_gc_queue < GC_QUEUE_ENTRIES_MAX) &&
- (m->gc_queue_timestamp <= 0 ||
- (m->gc_queue_timestamp + GC_QUEUE_USEC_MAX) > now(CLOCK_MONOTONIC)))
- return 0;
-
- log_debug("Running GC...");
+ /* log_debug("Running GC..."); */
m->gc_marker += _GC_OFFSET_MAX;
if (m->gc_marker + _GC_OFFSET_MAX <= _GC_OFFSET_MAX)
@@ -632,7 +685,6 @@ static unsigned manager_dispatch_gc_queue(Manager *m) {
}
m->n_in_gc_queue = 0;
- m->gc_queue_timestamp = 0;
return n;
}
@@ -661,6 +713,11 @@ static void manager_clear_jobs_and_units(Manager *m) {
m->n_running_jobs = 0;
}
+static void close_idle_pipe(Manager *m) {
+ close_pipe(m->idle_pipe);
+ close_pipe(m->idle_pipe + 2);
+}
+
void manager_free(Manager *m) {
UnitType c;
int i;
@@ -702,12 +759,10 @@ void manager_free(Manager *m) {
lookup_paths_free(&m->lookup_paths);
strv_free(m->environment);
- strv_free(m->default_controllers);
-
- hashmap_free(m->cgroup_bondings);
+ hashmap_free(m->cgroup_unit);
set_free_free(m->unit_path_cache);
- close_pipe(m->idle_pipe);
+ close_idle_pipe(m);
free(m->switch_root);
free(m->switch_root_init);
@@ -715,6 +770,9 @@ void manager_free(Manager *m) {
for (i = 0; i < RLIMIT_NLIMITS; i++)
free(m->rlimit[i]);
+ assert(hashmap_isempty(m->units_requiring_mounts_for));
+ hashmap_free(m->units_requiring_mounts_for);
+
free(m);
}
@@ -727,9 +785,11 @@ int manager_enumerate(Manager *m) {
/* Let's ask every type to load all units from disk/kernel
* that it might know */
for (c = 0; c < _UNIT_TYPE_MAX; c++)
- if (unit_vtable[c]->enumerate)
- if ((q = unit_vtable[c]->enumerate(m)) < 0)
+ if (unit_vtable[c]->enumerate) {
+ q = unit_vtable[c]->enumerate(m);
+ if (q < 0)
r = q;
+ }
manager_dispatch_load_queue(m);
return r;
@@ -820,7 +880,9 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
assert(m);
+ dual_timestamp_get(&m->generators_start_timestamp);
manager_run_generators(m);
+ dual_timestamp_get(&m->generators_finish_timestamp);
r = lookup_paths_init(
&m->lookup_paths, m->running_as, true,
@@ -839,7 +901,9 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
m->n_reloading ++;
/* First, enumerate what we can from all config files */
+ dual_timestamp_get(&m->unitsload_start_timestamp);
r = manager_enumerate(m);
+ dual_timestamp_get(&m->unitsload_finish_timestamp);
/* Second, deserialize if there is something to deserialize */
if (serialization) {
@@ -866,6 +930,11 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
if (serialization) {
assert(m->n_reloading > 0);
m->n_reloading --;
+
+ /* Let's wait for the UnitNew/JobNew messages being
+ * sent, before we notify that the reload is
+ * finished */
+ m->send_reloading_done = true;
}
return r;
@@ -987,7 +1056,13 @@ unsigned manager_dispatch_load_queue(Manager *m) {
return n;
}
-int manager_load_unit_prepare(Manager *m, const char *name, const char *path, DBusError *e, Unit **_ret) {
+int manager_load_unit_prepare(
+ Manager *m,
+ const char *name,
+ const char *path,
+ DBusError *e,
+ Unit **_ret) {
+
Unit *ret;
UnitType t;
int r;
@@ -1031,7 +1106,8 @@ int manager_load_unit_prepare(Manager *m, const char *name, const char *path, DB
}
}
- if ((r = unit_add_name(ret, name)) < 0) {
+ r = unit_add_name(ret, name);
+ if (r < 0) {
unit_free(ret);
return r;
}
@@ -1046,7 +1122,13 @@ int manager_load_unit_prepare(Manager *m, const char *name, const char *path, DB
return 0;
}
-int manager_load_unit(Manager *m, const char *name, const char *path, DBusError *e, Unit **_ret) {
+int manager_load_unit(
+ Manager *m,
+ const char *name,
+ const char *path,
+ DBusError *e,
+ Unit **_ret) {
+
int r;
assert(m);
@@ -1122,6 +1204,9 @@ unsigned manager_dispatch_run_queue(Manager *m) {
if (m->n_running_jobs > 0)
manager_watch_jobs_in_progress(m);
+ if (m->n_on_console > 0)
+ manager_watch_idle_pipe(m);
+
return n;
}
@@ -1152,6 +1237,13 @@ unsigned manager_dispatch_dbus_queue(Manager *m) {
}
m->dispatching_dbus_queue = false;
+
+ if (m->send_reloading_done) {
+ m->send_reloading_done = false;
+
+ bus_broadcast_reloading(m, false);
+ }
+
return n;
}
@@ -1205,7 +1297,7 @@ static int manager_process_notify_fd(Manager *m) {
u = hashmap_get(m->watch_pids, LONG_TO_PTR(ucred->pid));
if (!u) {
- u = cgroup_unit_by_pid(m, ucred->pid);
+ u = manager_get_unit_by_pid(m, ucred->pid);
if (!u) {
log_warning("Cannot find unit for notify message of PID %lu.", (unsigned long) ucred->pid);
continue;
@@ -1270,7 +1362,7 @@ static int manager_dispatch_sigchld(Manager *m) {
/* And now figure out the unit this belongs to */
u = hashmap_get(m->watch_pids, LONG_TO_PTR(si.si_pid));
if (!u)
- u = cgroup_unit_by_pid(m, si.si_pid);
+ u = manager_get_unit_by_pid(m, si.si_pid);
/* And now, we actually reap the zombie. */
if (waitid(P_PID, si.si_pid, &si, WEXITED) < 0) {
@@ -1372,7 +1464,7 @@ static int manager_process_signal_fd(Manager *m) {
case SIGINT:
if (m->running_as == SYSTEMD_SYSTEM) {
- manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE);
+ manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY);
break;
}
@@ -1668,6 +1760,14 @@ static int process_event(Manager *m, struct epoll_event *ev) {
break;
}
+ case WATCH_IDLE_PIPE: {
+ m->no_console_output = true;
+
+ manager_unwatch_idle_pipe(m);
+ close_idle_pipe(m);
+ break;
+ }
+
default:
log_error("event type=%i", w->type);
assert_not_reached("Unknown epoll event type.");
@@ -1714,16 +1814,19 @@ int manager_loop(Manager *m) {
if (manager_dispatch_load_queue(m) > 0)
continue;
- if (manager_dispatch_run_queue(m) > 0)
+ if (manager_dispatch_gc_queue(m) > 0)
continue;
- if (bus_dispatch(m) > 0)
+ if (manager_dispatch_cleanup_queue(m) > 0)
continue;
- if (manager_dispatch_cleanup_queue(m) > 0)
+ if (manager_dispatch_cgroup_queue(m) > 0)
continue;
- if (manager_dispatch_gc_queue(m) > 0)
+ if (manager_dispatch_run_queue(m) > 0)
+ continue;
+
+ if (bus_dispatch(m) > 0)
continue;
if (manager_dispatch_dbus_queue(m) > 0)
@@ -1761,7 +1864,7 @@ int manager_loop(Manager *m) {
}
int manager_load_unit_from_dbus_path(Manager *m, const char *s, DBusError *e, Unit **_u) {
- char *n;
+ _cleanup_free_ char *n = NULL;
Unit *u;
int r;
@@ -1769,16 +1872,11 @@ int manager_load_unit_from_dbus_path(Manager *m, const char *s, DBusError *e, Un
assert(s);
assert(_u);
- if (!startswith(s, "/org/freedesktop/systemd1/unit/"))
- return -EINVAL;
-
- n = bus_path_unescape(s+31);
- if (!n)
- return -ENOMEM;
+ r = unit_name_from_dbus_path(s, &n);
+ if (r < 0)
+ return r;
r = manager_load_unit(m, n, NULL, e, &u);
- free(n);
-
if (r < 0)
return r;
@@ -2033,6 +2131,8 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
}
}
+ bus_serialize(m, f);
+
fputc('\n', f);
HASHMAP_FOREACH_KEY(u, t, m->units, i) {
@@ -2046,7 +2146,8 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
fputs(u->id, f);
fputc('\n', f);
- if ((r = unit_serialize(u, f, fds, !switching_root)) < 0) {
+ r = unit_serialize(u, f, fds, !switching_root);
+ if (r < 0) {
m->n_reloading --;
return r;
}
@@ -2151,7 +2252,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
strv_free(m->environment);
m->environment = e;
- } else
+ } else if (bus_deserialize_item(m, l) == 0)
log_debug("Unknown serialization item '%s'", l);
}
@@ -2226,6 +2327,7 @@ int manager_reload(Manager *m) {
return r;
m->n_reloading ++;
+ bus_broadcast_reloading(m, true);
fds = fdset_new();
if (!fds) {
@@ -2285,6 +2387,8 @@ int manager_reload(Manager *m) {
assert(m->n_reloading > 0);
m->n_reloading--;
+ m->send_reloading_done = true;
+
finish:
if (f)
fclose(f);
@@ -2357,7 +2461,8 @@ void manager_check_finished(Manager *m) {
}
/* Notify Type=idle units that we are done now */
- close_pipe(m->idle_pipe);
+ manager_unwatch_idle_pipe(m);
+ close_idle_pipe(m);
/* Turn off confirm spawn now */
m->confirm_spawn = false;
@@ -2559,19 +2664,16 @@ void manager_undo_generators(Manager *m) {
remove_generator_dir(m, &m->generator_unit_path_late);
}
-int manager_set_default_controllers(Manager *m, char **controllers) {
- char **l;
-
+int manager_environment_add(Manager *m, char **environment) {
+ char **e = NULL;
assert(m);
- l = strv_copy(controllers);
- if (!l)
+ e = strv_env_merge(2, m->environment, environment);
+ if (!e)
return -ENOMEM;
- strv_free(m->default_controllers);
- m->default_controllers = l;
-
- cg_shorten_controllers(m->default_controllers);
+ strv_free(m->environment);
+ m->environment = e;
return 0;
}
@@ -2638,6 +2740,9 @@ static bool manager_get_show_status(Manager *m) {
if (m->running_as != SYSTEMD_SYSTEM)
return false;
+ if (m->no_console_output)
+ return false;
+
if (m->show_status)
return true;
@@ -2666,6 +2771,41 @@ void manager_status_printf(Manager *m, bool ephemeral, const char *status, const
va_end(ap);
}
+int manager_get_unit_by_path(Manager *m, const char *path, const char *suffix, Unit **_found) {
+ _cleanup_free_ char *p = NULL;
+ Unit *found;
+
+ assert(m);
+ assert(path);
+ assert(suffix);
+ assert(_found);
+
+ p = unit_name_from_path(path, suffix);
+ if (!p)
+ return -ENOMEM;
+
+ found = manager_get_unit(m, p);
+ if (!found) {
+ *_found = NULL;
+ return 0;
+ }
+
+ *_found = found;
+ return 1;
+}
+
+Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path) {
+ char p[strlen(path)+1];
+
+ assert(m);
+ assert(path);
+
+ strcpy(p, path);
+ path_kill_slashes(p);
+
+ return hashmap_get(m->units_requiring_mounts_for, streq(p, "/") ? "" : p);
+}
+
void watch_init(Watch *w) {
assert(w);
diff --git a/src/core/manager.h b/src/core/manager.h
index bf833540ae..a3049b5e5b 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -27,6 +27,7 @@
#include <dbus/dbus.h>
#include "fdset.h"
+#include "cgroup-util.h"
/* Enforce upper limit how many names we allow */
#define MANAGER_MAX_NAMES 131072 /* 128K */
@@ -62,7 +63,8 @@ enum WatchType {
WATCH_DBUS_WATCH,
WATCH_DBUS_TIMEOUT,
WATCH_TIME_CHANGE,
- WATCH_JOBS_IN_PROGRESS
+ WATCH_JOBS_IN_PROGRESS,
+ WATCH_IDLE_PIPE,
};
struct Watch {
@@ -86,6 +88,7 @@ struct Watch {
#include "dbus.h"
#include "path-lookup.h"
#include "execute.h"
+#include "unit-name.h"
struct Manager {
/* Note that the set of units we know of is allowed to be
@@ -100,9 +103,6 @@ struct Manager {
* type we maintain a per type linked list */
LIST_HEAD(Unit, units_by_type[_UNIT_TYPE_MAX]);
- /* To optimize iteration of units that have requires_mounts_for set */
- LIST_HEAD(Unit, has_requires_mounts_for);
-
/* Units that need to be loaded */
LIST_HEAD(Unit, load_queue); /* this is actually more a stack than a queue, but uh. */
@@ -122,6 +122,9 @@ struct Manager {
/* Units to check when doing GC */
LIST_HEAD(Unit, gc_queue);
+ /* Units that should be realized */
+ LIST_HEAD(Unit, cgroup_queue);
+
Hashmap *watch_pids; /* pid => Unit object n:1 */
char *notify_socket;
@@ -130,6 +133,7 @@ struct Manager {
Watch signal_watch;
Watch time_change_watch;
Watch jobs_in_progress_watch;
+ Watch idle_pipe_watch;
int epoll_fd;
@@ -139,7 +143,6 @@ struct Manager {
Set *unit_path_cache;
char **environment;
- char **default_controllers;
usec_t runtime_watchdog;
usec_t shutdown_watchdog;
@@ -150,6 +153,10 @@ struct Manager {
dual_timestamp initrd_timestamp;
dual_timestamp userspace_timestamp;
dual_timestamp finish_timestamp;
+ dual_timestamp generators_start_timestamp;
+ dual_timestamp generators_finish_timestamp;
+ dual_timestamp unitsload_start_timestamp;
+ dual_timestamp unitsload_finish_timestamp;
char *generator_unit_path;
char *generator_unit_path_early;
@@ -187,6 +194,8 @@ struct Manager {
int32_t conn_data_slot;
int32_t subscribed_data_slot;
+ bool send_reloading_done;
+
uint32_t current_job_id;
uint32_t default_unit_job_id;
@@ -194,10 +203,10 @@ struct Manager {
int dev_autofs_fd;
/* Data specific to the cgroup subsystem */
- Hashmap *cgroup_bondings; /* path string => CGroupBonding object 1:n */
- char *cgroup_hierarchy;
+ Hashmap *cgroup_unit;
+ CGroupControllerMask cgroup_supported;
+ char *cgroup_root;
- usec_t gc_queue_timestamp;
int gc_marker;
unsigned n_in_gc_queue;
@@ -217,6 +226,7 @@ struct Manager {
bool show_status;
bool confirm_spawn;
+ bool no_console_output;
ExecOutput default_std_output, default_std_error;
@@ -234,13 +244,18 @@ struct Manager {
unsigned jobs_in_progress_iteration;
/* Type=idle pipes */
- int idle_pipe[2];
+ int idle_pipe[4];
char *switch_root;
char *switch_root_init;
+
+ /* This maps all possible path prefixes to the units needing
+ * them. It's a hashmap with a path string as key and a Set as
+ * value where Unit objects are contained. */
+ Hashmap *units_requiring_mounts_for;
};
-int manager_new(SystemdRunningAs running_as, Manager **m);
+int manager_new(SystemdRunningAs running_as, bool reexecuting, Manager **m);
void manager_free(Manager *m);
int manager_enumerate(Manager *m);
@@ -250,6 +265,8 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds);
Job *manager_get_job(Manager *m, uint32_t id);
Unit *manager_get_unit(Manager *m, const char *name);
+int manager_get_unit_by_path(Manager *m, const char *path, const char *suffix, Unit **_found);
+
int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j);
int manager_load_unit_prepare(Manager *m, const char *name, const char *path, DBusError *e, Unit **_ret);
@@ -268,7 +285,7 @@ unsigned manager_dispatch_load_queue(Manager *m);
unsigned manager_dispatch_run_queue(Manager *m);
unsigned manager_dispatch_dbus_queue(Manager *m);
-int manager_set_default_controllers(Manager *m, char **controllers);
+int manager_environment_add(Manager *m, char **environment);
int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit);
int manager_loop(Manager *m);
@@ -303,4 +320,6 @@ void manager_recheck_journal(Manager *m);
void manager_set_show_status(Manager *m, bool b);
void manager_status_printf(Manager *m, bool ephemeral, const char *status, const char *format, ...) _printf_attr_(4,5);
+Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path);
+
void watch_init(Watch *w);
diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c
index 4629808a7a..4359f59908 100644
--- a/src/core/mount-setup.c
+++ b/src/core/mount-setup.c
@@ -350,14 +350,8 @@ static int nftw_cb(
};
int mount_setup(bool loaded_policy) {
-
- static const char relabel[] =
- "/run/initramfs/root-fsck\0"
- "/run/initramfs/shutdown\0";
-
int r;
unsigned i;
- const char *j;
for (i = 0; i < ELEMENTSOF(mount_table); i ++) {
r = mount_one(mount_table + i, true);
@@ -379,10 +373,6 @@ int mount_setup(bool loaded_policy) {
nftw("/dev", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
nftw("/run", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
- /* Explicitly relabel these */
- NULSTR_FOREACH(j, relabel)
- label_fix(j, true, false);
-
after_relabel = now(CLOCK_MONOTONIC);
log_info("Relabelled /dev and /run in %s.",
diff --git a/src/core/mount.c b/src/core/mount.c
index 10073b50be..3d46557fb1 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -82,6 +82,7 @@ static void mount_init(Unit *u) {
}
kill_context_init(&m->kill_context);
+ cgroup_context_init(&m->cgroup_context);
/* We need to make sure that /bin/mount is always called in
* the same process group as us, so that the autofs kernel
@@ -127,6 +128,7 @@ static void mount_done(Unit *u) {
mount_parameters_done(&m->parameters_proc_self_mountinfo);
mount_parameters_done(&m->parameters_fragment);
+ cgroup_context_done(&m->cgroup_context);
exec_context_done(&m->exec_context, manager_is_reloading_or_reexecuting(u->manager));
exec_command_done_array(m->exec_command, _MOUNT_EXEC_COMMAND_MAX);
m->control_command = NULL;
@@ -155,138 +157,58 @@ _pure_ static MountParameters* get_mount_parameters(Mount *m) {
}
static int mount_add_mount_links(Mount *m) {
- Unit *other;
- int r;
+ _cleanup_free_ char *parent = NULL;
MountParameters *pm;
-
- assert(m);
-
- pm = get_mount_parameters_fragment(m);
-
- /* Adds in links to other mount points that might lie below or
- * above us in the hierarchy */
-
- LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_MOUNT]) {
- Mount *n = MOUNT(other);
- MountParameters *pn;
-
- if (n == m)
- continue;
-
- if (UNIT(n)->load_state != UNIT_LOADED)
- continue;
-
- pn = get_mount_parameters_fragment(n);
-
- if (path_startswith(m->where, n->where)) {
-
- if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, UNIT(n), true)) < 0)
- return r;
-
- if (pn)
- if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, UNIT(n), true)) < 0)
- return r;
-
- } else if (path_startswith(n->where, m->where)) {
-
- if ((r = unit_add_dependency(UNIT(n), UNIT_AFTER, UNIT(m), true)) < 0)
- return r;
-
- if (pm)
- if ((r = unit_add_dependency(UNIT(n), UNIT_REQUIRES, UNIT(m), true)) < 0)
- return r;
-
- } else if (pm && pm->what && path_startswith(pm->what, n->where)) {
-
- if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, UNIT(n), true)) < 0)
- return r;
-
- if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, UNIT(n), true)) < 0)
- return r;
-
- } else if (pn && pn->what && path_startswith(pn->what, m->where)) {
-
- if ((r = unit_add_dependency(UNIT(n), UNIT_AFTER, UNIT(m), true)) < 0)
- return r;
-
- if ((r = unit_add_dependency(UNIT(n), UNIT_REQUIRES, UNIT(m), true)) < 0)
- return r;
- }
- }
-
- return 0;
-}
-
-static int mount_add_swap_links(Mount *m) {
Unit *other;
+ Iterator i;
+ Set *s;
int r;
assert(m);
- LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_SWAP]) {
- r = swap_add_one_mount_link(SWAP(other), m);
+ if (!path_equal(m->where, "/")) {
+ /* Adds in links to other mount points that might lie further
+ * up in the hierarchy */
+ r = path_get_parent(m->where, &parent);
if (r < 0)
return r;
- }
- return 0;
-}
-
-static int mount_add_path_links(Mount *m) {
- Unit *other;
- int r;
-
- assert(m);
-
- LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_PATH]) {
- r = path_add_one_mount_link(PATH(other), m);
+ r = unit_require_mounts_for(UNIT(m), parent);
if (r < 0)
return r;
}
- return 0;
-}
-
-static int mount_add_automount_links(Mount *m) {
- Unit *other;
- int r;
-
- assert(m);
-
- LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_AUTOMOUNT]) {
- r = automount_add_one_mount_link(AUTOMOUNT(other), m);
+ /* Adds in links to other mount points that might be needed
+ * for the source path (if this is a bind mount) to be
+ * available. */
+ pm = get_mount_parameters_fragment(m);
+ if (pm && path_is_absolute(pm->what)) {
+ r = unit_require_mounts_for(UNIT(m), pm->what);
if (r < 0)
return r;
}
- return 0;
-}
+ /* Adds in links to other units that use this path or paths
+ * further down in the hierarchy */
+ s = manager_get_units_requiring_mounts_for(UNIT(m)->manager, m->where);
+ SET_FOREACH(other, s, i) {
-static int mount_add_socket_links(Mount *m) {
- Unit *other;
- int r;
+ if (other->load_state != UNIT_LOADED)
+ continue;
- assert(m);
+ if (other == UNIT(m))
+ continue;
- LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_SOCKET]) {
- r = socket_add_one_mount_link(SOCKET(other), m);
+ r = unit_add_dependency(other, UNIT_AFTER, UNIT(m), true);
if (r < 0)
return r;
- }
-
- return 0;
-}
-static int mount_add_requires_mounts_links(Mount *m) {
- Unit *other;
- int r;
-
- assert(m);
-
- LIST_FOREACH(has_requires_mounts_for, other, UNIT(m)->manager->has_requires_mounts_for) {
- r = unit_add_one_mount_link(other, m);
- if (r < 0)
- return r;
+ if (UNIT(m)->fragment_path) {
+ /* If we have fragment configuration, then make this dependency required */
+ r = unit_add_dependency(other, UNIT_REQUIRES, UNIT(m), true);
+ if (r < 0)
+ return r;
+ }
}
return 0;
@@ -336,6 +258,12 @@ static bool mount_is_bind(MountParameters *p) {
return false;
}
+static bool mount_is_auto(MountParameters *p) {
+ assert(p);
+
+ return !mount_test_option(p->options, "noauto");
+}
+
static bool needs_quota(MountParameters *p) {
assert(p);
@@ -354,6 +282,7 @@ static bool needs_quota(MountParameters *p) {
static int mount_add_device_links(Mount *m) {
MountParameters *p;
+ bool device_wants_mount = false;
int r;
assert(m);
@@ -374,7 +303,10 @@ static int mount_add_device_links(Mount *m) {
if (path_equal(m->where, "/"))
return 0;
- r = unit_add_node_link(UNIT(m), p->what, false);
+ if (mount_is_auto(p) && UNIT(m)->manager->running_as == SYSTEMD_SYSTEM)
+ device_wants_mount = true;
+
+ r = unit_add_node_link(UNIT(m), p->what, device_wants_mount);
if (r < 0)
return r;
@@ -435,6 +367,21 @@ static int mount_add_quota_links(Mount *m) {
return 0;
}
+static bool should_umount(Mount *m) {
+ MountParameters *p;
+
+ if (path_equal(m->where, "/") ||
+ path_equal(m->where, "/usr"))
+ return false;
+
+ p = get_mount_parameters(m);
+ if (p && mount_test_option(p->options, "x-initrd.mount") &&
+ !in_initrd())
+ return false;
+
+ return true;
+}
+
static int mount_add_default_dependencies(Mount *m) {
const char *after, *after2, *online;
MountParameters *p;
@@ -479,9 +426,11 @@ static int mount_add_default_dependencies(Mount *m) {
return r;
}
- r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
- if (r < 0)
- return r;
+ if (should_umount(m)) {
+ r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
+ if (r < 0)
+ return r;
+ }
return 0;
}
@@ -538,8 +487,9 @@ static int mount_fix_timeouts(Mount *m) {
}
static int mount_verify(Mount *m) {
+ _cleanup_free_ char *e = NULL;
bool b;
- char *e;
+
assert(m);
if (UNIT(m)->load_state != UNIT_LOADED)
@@ -548,12 +498,11 @@ static int mount_verify(Mount *m) {
if (!m->from_fragment && !m->from_proc_self_mountinfo)
return -ENOENT;
- if (!(e = unit_name_from_path(m->where, ".mount")))
+ e = unit_name_from_path(m->where, ".mount");
+ if (!e)
return -ENOMEM;
b = unit_has_name(UNIT(m), e);
- free(e);
-
if (!b) {
log_error_unit(UNIT(m)->id,
"%s's Where setting doesn't match unit name. Refusing.",
@@ -617,26 +566,6 @@ static int mount_add_extras(Mount *m) {
if (r < 0)
return r;
- r = mount_add_socket_links(m);
- if (r < 0)
- return r;
-
- r = mount_add_swap_links(m);
- if (r < 0)
- return r;
-
- r = mount_add_path_links(m);
- if (r < 0)
- return r;
-
- r = mount_add_requires_mounts_links(m);
- if (r < 0)
- return r;
-
- r = mount_add_automount_links(m);
- if (r < 0)
- return r;
-
r = mount_add_quota_links(m);
if (r < 0)
return r;
@@ -647,7 +576,7 @@ static int mount_add_extras(Mount *m) {
return r;
}
- r = unit_add_default_cgroups(u);
+ r = unit_add_default_slice(u);
if (r < 0)
return r;
@@ -820,9 +749,9 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
prefix, mount_state_to_string(m->state),
prefix, mount_result_to_string(m->result),
prefix, m->where,
- prefix, strna(p->what),
- prefix, strna(p->fstype),
- prefix, strna(p->options),
+ prefix, p ? strna(p->what) : "n/a",
+ prefix, p ? strna(p->fstype) : "n/a",
+ prefix, p ? strna(p->options) : "n/a",
prefix, yes_no(m->from_proc_self_mountinfo),
prefix, yes_no(m->from_fragment),
prefix, m->directory_mode);
@@ -844,28 +773,31 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
assert(c);
assert(_pid);
+ unit_realize_cgroup(UNIT(m));
+
r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
if (r < 0)
goto fail;
- if ((r = exec_spawn(c,
- NULL,
- &m->exec_context,
- NULL, 0,
- UNIT(m)->manager->environment,
- true,
- true,
- true,
- UNIT(m)->manager->confirm_spawn,
- UNIT(m)->cgroup_bondings,
- UNIT(m)->cgroup_attributes,
- NULL,
- UNIT(m)->id,
- NULL,
- &pid)) < 0)
+ r = exec_spawn(c,
+ NULL,
+ &m->exec_context,
+ NULL, 0,
+ UNIT(m)->manager->environment,
+ true,
+ true,
+ true,
+ UNIT(m)->manager->confirm_spawn,
+ UNIT(m)->manager->cgroup_supported,
+ UNIT(m)->cgroup_path,
+ UNIT(m)->id,
+ NULL,
+ &pid);
+ if (r < 0)
goto fail;
- if ((r = unit_watch_pid(UNIT(m), pid)) < 0)
+ r = unit_watch_pid(UNIT(m), pid);
+ if (r < 0)
/* FIXME: we need to do something here */
goto fail;
@@ -1538,9 +1470,11 @@ static int mount_add_one(
if (r < 0)
goto fail;
- r = unit_add_dependency_by_name(u, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
- if (r < 0)
- goto fail;
+ if (should_umount(MOUNT(u))) {
+ r = unit_add_dependency_by_name(u, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
+ if (r < 0)
+ goto fail;
+ }
unit_add_to_load_queue(u);
} else {
@@ -1555,7 +1489,7 @@ static int mount_add_one(
}
}
- if (u->load_state == UNIT_ERROR) {
+ if (u->load_state == UNIT_NOT_FOUND) {
u->load_state = UNIT_LOADED;
u->load_error = 0;
@@ -1616,79 +1550,56 @@ fail:
static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
int r = 0;
unsigned i;
- char *device, *path, *options, *options2, *fstype, *d, *p, *o;
assert(m);
rewind(m->proc_self_mountinfo);
for (i = 1;; i++) {
+ _cleanup_free_ char *device = NULL, *path = NULL, *options = NULL, *options2 = NULL, *fstype = NULL, *d = NULL, *p = NULL, *o = NULL;
int k;
- device = path = options = options2 = fstype = d = p = o = NULL;
-
- if ((k = fscanf(m->proc_self_mountinfo,
- "%*s " /* (1) mount id */
- "%*s " /* (2) parent id */
- "%*s " /* (3) major:minor */
- "%*s " /* (4) root */
- "%ms " /* (5) mount point */
- "%ms" /* (6) mount options */
- "%*[^-]" /* (7) optional fields */
- "- " /* (8) separator */
- "%ms " /* (9) file system type */
- "%ms" /* (10) mount source */
- "%ms" /* (11) mount options 2 */
- "%*[^\n]", /* some rubbish at the end */
- &path,
- &options,
- &fstype,
- &device,
- &options2)) != 5) {
-
- if (k == EOF)
- break;
-
+ k = fscanf(m->proc_self_mountinfo,
+ "%*s " /* (1) mount id */
+ "%*s " /* (2) parent id */
+ "%*s " /* (3) major:minor */
+ "%*s " /* (4) root */
+ "%ms " /* (5) mount point */
+ "%ms" /* (6) mount options */
+ "%*[^-]" /* (7) optional fields */
+ "- " /* (8) separator */
+ "%ms " /* (9) file system type */
+ "%ms" /* (10) mount source */
+ "%ms" /* (11) mount options 2 */
+ "%*[^\n]", /* some rubbish at the end */
+ &path,
+ &options,
+ &fstype,
+ &device,
+ &options2);
+
+ if (k == EOF)
+ break;
+
+ if (k != 5) {
log_warning("Failed to parse /proc/self/mountinfo:%u.", i);
- goto clean_up;
+ continue;
}
o = strjoin(options, ",", options2, NULL);
- if (!o) {
- r = -ENOMEM;
- goto finish;
- }
+ if (!o)
+ return log_oom();
- if (!(d = cunescape(device)) ||
- !(p = cunescape(path))) {
- r = -ENOMEM;
- goto finish;
- }
+ d = cunescape(device);
+ p = cunescape(path);
+ if (!d || !p)
+ return log_oom();
- if ((k = mount_add_one(m, d, p, o, fstype, 0, set_flags)) < 0)
+ k = mount_add_one(m, d, p, o, fstype, 0, set_flags);
+ if (k < 0)
r = k;
-
-clean_up:
- free(device);
- free(path);
- free(options);
- free(options2);
- free(fstype);
- free(d);
- free(p);
- free(o);
}
-finish:
- free(device);
- free(path);
- free(options);
- free(options2);
- free(fstype);
- free(d);
- free(p);
- free(o);
-
return r;
}
@@ -1872,8 +1783,9 @@ const UnitVTable mount_vtable = {
"Mount\0"
"Install\0",
+ .private_section = "Mount",
.exec_context_offset = offsetof(Mount, exec_context),
- .exec_section = "Mount",
+ .cgroup_context_offset = offsetof(Mount, cgroup_context),
.no_alias = true,
.no_instances = true,
@@ -1908,6 +1820,8 @@ const UnitVTable mount_vtable = {
.bus_interface = "org.freedesktop.systemd1.Mount",
.bus_message_handler = bus_mount_message_handler,
.bus_invalidating_properties = bus_mount_invalidating_properties,
+ .bus_set_property = bus_mount_set_property,
+ .bus_commit_properties = bus_mount_commit_properties,
.enumerate = mount_enumerate,
.shutdown = mount_shutdown,
diff --git a/src/core/mount.h b/src/core/mount.h
index bcc10ee0d4..7cd4320d94 100644
--- a/src/core/mount.h
+++ b/src/core/mount.h
@@ -25,6 +25,8 @@ typedef struct Mount Mount;
#include "unit.h"
#include "kill.h"
+#include "execute.h"
+#include "cgroup.h"
typedef enum MountState {
MOUNT_DEAD,
@@ -95,8 +97,10 @@ struct Mount {
usec_t timeout_usec;
ExecCommand exec_command[_MOUNT_EXEC_COMMAND_MAX];
+
ExecContext exec_context;
KillContext kill_context;
+ CGroupContext cgroup_context;
MountState state, deserialized_state;
diff --git a/src/core/namespace.c b/src/core/namespace.c
index 7e33d84156..16b132ba56 100644
--- a/src/core/namespace.c
+++ b/src/core/namespace.c
@@ -51,6 +51,7 @@ typedef struct BindMount {
const char *path;
MountMode mode;
bool done;
+ bool ignore;
} BindMount;
static int append_mounts(BindMount **p, char **strv, MountMode mode) {
@@ -58,6 +59,13 @@ static int append_mounts(BindMount **p, char **strv, MountMode mode) {
STRV_FOREACH(i, strv) {
+ (*p)->ignore = false;
+
+ if ((mode == INACCESSIBLE || mode == READONLY) && (*i)[0] == '-') {
+ (*p)->ignore = true;
+ (*i)++;
+ }
+
if (!path_is_absolute(*i))
return -EINVAL;
@@ -155,6 +163,8 @@ static int apply_mount(
r = mount(what, m->path, NULL, MS_BIND|MS_REC, NULL);
if (r >= 0)
log_debug("Successfully mounted %s to %s", what, m->path);
+ else if (m->ignore && errno == ENOENT)
+ r = 0;
return r;
}
@@ -168,7 +178,7 @@ static int make_read_only(BindMount *m) {
return 0;
r = mount(NULL, m->path, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_REC, NULL);
- if (r < 0)
+ if (r < 0 && !(m->ignore && errno == ENOENT))
return -errno;
return 0;
diff --git a/src/core/org.freedesktop.systemd1.conf b/src/core/org.freedesktop.systemd1.conf
index a07a8e1ce3..a375dce0b0 100644
--- a/src/core/org.freedesktop.systemd1.conf
+++ b/src/core/org.freedesktop.systemd1.conf
@@ -86,6 +86,10 @@
send_interface="org.freedesktop.systemd1.Manager"
send_member="Dump"/>
+ <allow send_destination="org.freedesktop.systemd1"
+ send_interface="org.freedesktop.systemd1.Manager"
+ send_member="GetDefaultTarget"/>
+
<allow receive_sender="org.freedesktop.systemd1"/>
</policy>
diff --git a/src/core/path.c b/src/core/path.c
index 8a09deb4ff..99e2fedf29 100644
--- a/src/core/path.c
+++ b/src/core/path.c
@@ -241,10 +241,6 @@ static bool path_spec_check_good(PathSpec *s, bool initial) {
return good;
}
-static bool path_spec_startswith(PathSpec *s, const char *what) {
- return path_startswith(s->path, what);
-}
-
static void path_spec_mkdir(PathSpec *s, mode_t mode) {
int r;
@@ -301,38 +297,14 @@ static void path_done(Unit *u) {
path_free_specs(p);
}
-int path_add_one_mount_link(Path *p, Mount *m) {
+static int path_add_mount_links(Path *p) {
PathSpec *s;
int r;
assert(p);
- assert(m);
-
- if (UNIT(p)->load_state != UNIT_LOADED ||
- UNIT(m)->load_state != UNIT_LOADED)
- return 0;
LIST_FOREACH(spec, s, p->specs) {
- if (!path_spec_startswith(s, m->where))
- continue;
-
- r = unit_add_two_dependencies(UNIT(p), UNIT_AFTER, UNIT_REQUIRES,
- UNIT(m), true);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-static int path_add_mount_links(Path *p) {
- Unit *other;
- int r;
-
- assert(p);
-
- LIST_FOREACH(units_by_type, other, UNIT(p)->manager->units_by_type[UNIT_MOUNT]) {
- r = path_add_one_mount_link(p, MOUNT(other));
+ r = unit_require_mounts_for(UNIT(p), s->path);
if (r < 0)
return r;
}
diff --git a/src/core/path.h b/src/core/path.h
index 6adab5897d..dec3df7035 100644
--- a/src/core/path.h
+++ b/src/core/path.h
@@ -90,10 +90,6 @@ struct Path {
PathResult result;
};
-/* Called from the mount code figure out if a mount is a dependency of
- * any of the paths of this path object */
-int path_add_one_mount_link(Path *p, Mount *m);
-
void path_free_specs(Path *p);
extern const UnitVTable path_vtable;
diff --git a/src/core/scope.c b/src/core/scope.c
new file mode 100644
index 0000000000..50e5dbacb4
--- /dev/null
+++ b/src/core/scope.c
@@ -0,0 +1,482 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ 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>
+#include <signal.h>
+#include <unistd.h>
+
+#include "unit.h"
+#include "scope.h"
+#include "load-fragment.h"
+#include "log.h"
+#include "dbus-scope.h"
+#include "special.h"
+#include "unit-name.h"
+#include "load-dropin.h"
+
+static const UnitActiveState state_translation_table[_SCOPE_STATE_MAX] = {
+ [SCOPE_DEAD] = UNIT_INACTIVE,
+ [SCOPE_RUNNING] = UNIT_ACTIVE,
+ [SCOPE_STOP_SIGTERM] = UNIT_DEACTIVATING,
+ [SCOPE_STOP_SIGKILL] = UNIT_DEACTIVATING,
+ [SCOPE_FAILED] = UNIT_FAILED
+};
+
+static void scope_init(Unit *u) {
+ Scope *s = SCOPE(u);
+
+ assert(u);
+ assert(u->load_state == UNIT_STUB);
+
+ s->timeout_stop_usec = DEFAULT_TIMEOUT_USEC;
+
+ watch_init(&s->timer_watch);
+
+ cgroup_context_init(&s->cgroup_context);
+ kill_context_init(&s->kill_context);
+
+ UNIT(s)->ignore_on_isolate = true;
+ UNIT(s)->ignore_on_snapshot = true;
+}
+
+static void scope_done(Unit *u) {
+ Scope *s = SCOPE(u);
+
+ assert(u);
+
+ cgroup_context_done(&s->cgroup_context);
+
+ set_free(s->pids);
+ s->pids = NULL;
+
+ unit_unwatch_timer(u, &s->timer_watch);
+}
+
+static void scope_set_state(Scope *s, ScopeState state) {
+ ScopeState old_state;
+ assert(s);
+
+ old_state = s->state;
+ s->state = state;
+
+ if (state != SCOPE_STOP_SIGTERM &&
+ state != SCOPE_STOP_SIGKILL)
+ unit_unwatch_timer(UNIT(s), &s->timer_watch);
+
+ if (state != old_state)
+ log_debug("%s changed %s -> %s",
+ UNIT(s)->id,
+ scope_state_to_string(old_state),
+ scope_state_to_string(state));
+
+ unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true);
+}
+
+static int scope_add_default_dependencies(Scope *s) {
+ int r;
+
+ assert(s);
+
+ /* Make sure scopes are unloaded on shutdown */
+ r = unit_add_two_dependencies_by_name(
+ UNIT(s),
+ UNIT_BEFORE, UNIT_CONFLICTS,
+ SPECIAL_SHUTDOWN_TARGET, NULL, true);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int scope_verify(Scope *s) {
+ assert(s);
+
+ if (UNIT(s)->load_state != UNIT_LOADED)
+ return 0;
+
+ if (set_size(s->pids) <= 0 && UNIT(s)->manager->n_reloading <= 0) {
+ log_error_unit(UNIT(s)->id, "Scope %s has no PIDs. Refusing.", UNIT(s)->id);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int scope_load(Unit *u) {
+ Scope *s = SCOPE(u);
+ int r;
+
+ assert(s);
+ assert(u->load_state == UNIT_STUB);
+
+ if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
+ return -ENOENT;
+
+ u->load_state = UNIT_LOADED;
+
+ r = unit_load_dropin(u);
+ if (r < 0)
+ return r;
+
+ r = unit_add_default_slice(u);
+ if (r < 0)
+ return r;
+
+ if (u->default_dependencies) {
+ r = scope_add_default_dependencies(s);
+ if (r < 0)
+ return r;
+ }
+
+ return scope_verify(s);
+}
+
+static int scope_coldplug(Unit *u) {
+ Scope *s = SCOPE(u);
+ int r;
+
+ assert(s);
+ assert(s->state == SCOPE_DEAD);
+
+ if (s->deserialized_state != s->state) {
+
+ if ((s->deserialized_state == SCOPE_STOP_SIGKILL || s->deserialized_state == SCOPE_STOP_SIGTERM)
+ && s->timeout_stop_usec > 0) {
+ r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_stop_usec, &s->timer_watch);
+ if (r < 0)
+
+ return r;
+ }
+
+ scope_set_state(s, s->deserialized_state);
+ }
+
+ return 0;
+}
+
+static void scope_dump(Unit *u, FILE *f, const char *prefix) {
+ Scope *s = SCOPE(u);
+
+ assert(s);
+ assert(f);
+
+ fprintf(f,
+ "%sScope State: %s\n"
+ "%sResult: %s\n",
+ prefix, scope_state_to_string(s->state),
+ prefix, scope_result_to_string(s->result));
+
+ cgroup_context_dump(&s->cgroup_context, f, prefix);
+ kill_context_dump(&s->kill_context, f, prefix);
+}
+
+static void scope_enter_dead(Scope *s, ScopeResult f) {
+ assert(s);
+
+ if (f != SCOPE_SUCCESS)
+ s->result = f;
+
+ scope_set_state(s, s->result != SCOPE_SUCCESS ? SCOPE_FAILED : SCOPE_DEAD);
+}
+
+static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
+ int r;
+
+ assert(s);
+
+ if (f != SCOPE_SUCCESS)
+ s->result = f;
+
+ r = unit_kill_context(
+ UNIT(s),
+ &s->kill_context,
+ state != SCOPE_STOP_SIGTERM,
+ -1, -1, false);
+ if (r < 0)
+ goto fail;
+
+ if (r > 0) {
+ if (s->timeout_stop_usec > 0) {
+ r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_stop_usec, &s->timer_watch);
+ if (r < 0)
+ goto fail;
+ }
+
+ scope_set_state(s, state);
+ } else
+ scope_enter_dead(s, SCOPE_SUCCESS);
+
+ return;
+
+fail:
+ log_warning_unit(UNIT(s)->id,
+ "%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));
+
+ scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
+}
+
+static int scope_start(Unit *u) {
+ Scope *s = SCOPE(u);
+ int r;
+
+ assert(s);
+
+ if (s->state == SCOPE_FAILED)
+ return -EPERM;
+
+ if (s->state == SCOPE_STOP_SIGTERM ||
+ s->state == SCOPE_STOP_SIGKILL)
+ return -EAGAIN;
+
+ assert(s->state == SCOPE_DEAD);
+
+ if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
+ return -ENOENT;
+
+ r = unit_realize_cgroup(u);
+ if (r < 0) {
+ log_error("Failed to realize cgroup: %s", strerror(-r));
+ return r;
+ }
+
+ r = cg_attach_many_everywhere(u->manager->cgroup_supported, u->cgroup_path, s->pids);
+ if (r < 0)
+ return r;
+
+ set_free(s->pids);
+ s->pids = NULL;
+
+ s->result = SCOPE_SUCCESS;
+
+ scope_set_state(s, SCOPE_RUNNING);
+ return 0;
+}
+
+static int scope_stop(Unit *u) {
+ Scope *s = SCOPE(u);
+
+ assert(s);
+ assert(s->state == SCOPE_RUNNING);
+
+ if (s->state == SCOPE_STOP_SIGTERM ||
+ s->state == SCOPE_STOP_SIGKILL)
+ return 0;
+
+ assert(s->state == SCOPE_RUNNING);
+
+ scope_enter_signal(s, SCOPE_STOP_SIGTERM, SCOPE_SUCCESS);
+ return 0;
+}
+
+static void scope_reset_failed(Unit *u) {
+ Scope *s = SCOPE(u);
+
+ assert(s);
+
+ if (s->state == SCOPE_FAILED)
+ scope_set_state(s, SCOPE_DEAD);
+
+ s->result = SCOPE_SUCCESS;
+}
+
+static int scope_kill(Unit *u, KillWho who, int signo, DBusError *error) {
+ return unit_kill_common(u, who, signo, -1, -1, error);
+}
+
+static int scope_serialize(Unit *u, FILE *f, FDSet *fds) {
+ Scope *s = SCOPE(u);
+
+ assert(s);
+ assert(f);
+ assert(fds);
+
+ unit_serialize_item(u, f, "state", scope_state_to_string(s->state));
+ return 0;
+}
+
+static int scope_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
+ Scope *s = SCOPE(u);
+
+ assert(u);
+ assert(key);
+ assert(value);
+ assert(fds);
+
+ if (streq(key, "state")) {
+ ScopeState state;
+
+ state = scope_state_from_string(value);
+ if (state < 0)
+ log_debug("Failed to parse state value %s", value);
+ else
+ s->deserialized_state = state;
+
+ } else
+ log_debug("Unknown serialization key '%s'", key);
+
+ return 0;
+}
+
+static bool scope_check_gc(Unit *u) {
+ Scope *s = SCOPE(u);
+ int r;
+
+ assert(s);
+
+ /* Never clean up scopes that still have a process around,
+ * even if the scope is formally dead. */
+
+ if (UNIT(s)->cgroup_path) {
+ r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, UNIT(s)->cgroup_path, true);
+ if (r <= 0)
+ return true;
+ }
+
+ return false;
+}
+
+static void scope_timer_event(Unit *u, uint64_t elapsed, Watch*w) {
+ Scope *s = SCOPE(u);
+
+ assert(s);
+ assert(elapsed == 1);
+ assert(w == &s->timer_watch);
+
+ switch (s->state) {
+
+ case SCOPE_STOP_SIGTERM:
+ if (s->kill_context.send_sigkill) {
+ log_warning_unit(u->id, "%s stopping timed out. Killing.", u->id);
+ scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_FAILURE_TIMEOUT);
+ } else {
+ log_warning_unit(u->id, "%s stopping timed out. Skipping SIGKILL.", u->id);
+ scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
+ }
+
+ break;
+
+ case SCOPE_STOP_SIGKILL:
+ log_warning_unit(u->id, "%s still around after SIGKILL. Ignoring.", u->id);
+ scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
+ break;
+
+ default:
+ assert_not_reached("Timeout at wrong time.");
+ }
+}
+
+static void scope_notify_cgroup_empty_event(Unit *u) {
+ Scope *s = SCOPE(u);
+ assert(u);
+
+ log_debug_unit(u->id, "%s: cgroup is empty", u->id);
+
+ switch (s->state) {
+
+ case SCOPE_RUNNING:
+ case SCOPE_STOP_SIGTERM:
+ case SCOPE_STOP_SIGKILL:
+ scope_enter_dead(s, SCOPE_SUCCESS);
+
+ break;
+
+ default:
+ ;
+ }
+}
+
+_pure_ static UnitActiveState scope_active_state(Unit *u) {
+ assert(u);
+
+ return state_translation_table[SCOPE(u)->state];
+}
+
+_pure_ static const char *scope_sub_state_to_string(Unit *u) {
+ assert(u);
+
+ return scope_state_to_string(SCOPE(u)->state);
+}
+
+static const char* const scope_state_table[_SCOPE_STATE_MAX] = {
+ [SCOPE_DEAD] = "dead",
+ [SCOPE_RUNNING] = "running",
+ [SCOPE_STOP_SIGTERM] = "stop-sigterm",
+ [SCOPE_STOP_SIGKILL] = "stop-sigkill",
+ [SCOPE_FAILED] = "failed",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(scope_state, ScopeState);
+
+static const char* const scope_result_table[_SCOPE_RESULT_MAX] = {
+ [SCOPE_SUCCESS] = "success",
+ [SCOPE_FAILURE_RESOURCES] = "resources",
+ [SCOPE_FAILURE_TIMEOUT] = "timeout",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(scope_result, ScopeResult);
+
+const UnitVTable scope_vtable = {
+ .object_size = sizeof(Scope),
+ .sections =
+ "Unit\0"
+ "Scope\0"
+ "Install\0",
+
+ .private_section = "Scope",
+ .cgroup_context_offset = offsetof(Scope, cgroup_context),
+
+ .no_alias = true,
+ .no_instances = true,
+
+ .init = scope_init,
+ .load = scope_load,
+ .done = scope_done,
+
+ .coldplug = scope_coldplug,
+
+ .dump = scope_dump,
+
+ .start = scope_start,
+ .stop = scope_stop,
+
+ .kill = scope_kill,
+
+ .serialize = scope_serialize,
+ .deserialize_item = scope_deserialize_item,
+
+ .active_state = scope_active_state,
+ .sub_state_to_string = scope_sub_state_to_string,
+
+ .check_gc = scope_check_gc,
+
+ .timer_event = scope_timer_event,
+
+ .reset_failed = scope_reset_failed,
+
+ .notify_cgroup_empty = scope_notify_cgroup_empty_event,
+
+ .bus_interface = "org.freedesktop.systemd1.Scope",
+ .bus_message_handler = bus_scope_message_handler,
+ .bus_set_property = bus_scope_set_property,
+ .bus_commit_properties = bus_scope_commit_properties,
+
+ .can_transient = true
+};
diff --git a/src/core/scope.h b/src/core/scope.h
new file mode 100644
index 0000000000..2a3dcb73d7
--- /dev/null
+++ b/src/core/scope.h
@@ -0,0 +1,69 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#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/>.
+***/
+
+typedef struct Scope Scope;
+
+#include "unit.h"
+#include "kill.h"
+
+typedef enum ScopeState {
+ SCOPE_DEAD,
+ SCOPE_RUNNING,
+ SCOPE_STOP_SIGTERM,
+ SCOPE_STOP_SIGKILL,
+ SCOPE_FAILED,
+ _SCOPE_STATE_MAX,
+ _SCOPE_STATE_INVALID = -1
+} ScopeState;
+
+typedef enum ScopeResult {
+ SCOPE_SUCCESS,
+ SCOPE_FAILURE_RESOURCES,
+ SCOPE_FAILURE_TIMEOUT,
+ _SCOPE_RESULT_MAX,
+ _SCOPE_RESULT_INVALID = -1
+} ScopeResult;
+
+struct Scope {
+ Unit meta;
+
+ CGroupContext cgroup_context;
+ KillContext kill_context;
+
+ ScopeState state, deserialized_state;
+ ScopeResult result;
+
+ usec_t timeout_stop_usec;
+
+ Set *pids;
+
+ Watch timer_watch;
+};
+
+extern const UnitVTable scope_vtable;
+
+const char* scope_state_to_string(ScopeState i) _const_;
+ScopeState scope_state_from_string(const char *s) _pure_;
+
+const char* scope_result_to_string(ScopeResult i) _const_;
+ScopeResult scope_result_from_string(const char *s) _pure_;
diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c
index 426aed07d2..0a3ee18bb9 100644
--- a/src/core/selinux-access.c
+++ b/src/core/selinux-access.c
@@ -6,16 +6,16 @@
Copyright 2012 Dan Walsh
systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that 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.
+ Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
diff --git a/src/core/selinux-access.h b/src/core/selinux-access.h
index 9183cbc9a6..2d7ac64c8f 100644
--- a/src/core/selinux-access.h
+++ b/src/core/selinux-access.h
@@ -8,16 +8,16 @@
Copyright 2012 Dan Walsh
systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that 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.
+ Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
diff --git a/src/core/service.c b/src/core/service.c
index 3617c24711..67920248d3 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -141,6 +141,7 @@ static void service_init(Unit *u) {
exec_context_init(&s->exec_context);
kill_context_init(&s->kill_context);
+ cgroup_context_init(&s->cgroup_context);
RATELIMIT_INIT(s->start_limit, 10*USEC_PER_SEC, 5);
@@ -190,6 +191,14 @@ static int service_set_main_pid(Service *s, pid_t pid) {
if (pid == getpid())
return -EINVAL;
+ if (s->main_pid == pid && s->main_pid_known)
+ return 0;
+
+ if (s->main_pid != pid) {
+ service_unwatch_main_pid(s);
+ exec_status_start(&s->main_exec_status, pid);
+ }
+
s->main_pid = pid;
s->main_pid_known = true;
@@ -202,8 +211,6 @@ static int service_set_main_pid(Service *s, pid_t pid) {
} else
s->main_pid_alien = false;
- exec_status_start(&s->main_exec_status, pid);
-
return 0;
}
@@ -220,7 +227,7 @@ static void service_close_socket_fd(Service *s) {
static void service_connection_unref(Service *s) {
assert(s);
- if (!UNIT_DEREF(s->accept_socket))
+ if (!UNIT_ISSET(s->accept_socket))
return;
socket_connection_unref(SOCKET(UNIT_DEREF(s->accept_socket)));
@@ -235,7 +242,7 @@ static void service_stop_watchdog(Service *s) {
s->watchdog_timestamp.monotonic = 0;
}
-static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart);
+static void service_enter_signal(Service *s, ServiceState state, ServiceResult f);
static void service_handle_watchdog(Service *s) {
usec_t offset;
@@ -249,7 +256,7 @@ static void service_handle_watchdog(Service *s) {
offset = now(CLOCK_MONOTONIC) - s->watchdog_timestamp.monotonic;
if (offset >= s->watchdog_usec) {
log_error_unit(UNIT(s)->id, "%s watchdog timeout!", UNIT(s)->id);
- service_enter_dead(s, SERVICE_FAILURE_WATCHDOG, true);
+ service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_FAILURE_WATCHDOG);
return;
}
@@ -283,6 +290,7 @@ static void service_done(Unit *u) {
free(s->status_text);
s->status_text = NULL;
+ cgroup_context_done(&s->cgroup_context);
exec_context_done(&s->exec_context, manager_is_reloading_or_reexecuting(u->manager));
exec_command_free_array(s->exec_command, _SERVICE_EXEC_COMMAND_MAX);
s->control_command = NULL;
@@ -981,7 +989,7 @@ static int service_load_sysv_name(Service *s, const char *name) {
assert(s);
assert(name);
- /* For SysV services we strip the *.sh suffixes. */
+ /* For SysV services we strip the *.sh suffixes. */
if (endswith(name, ".sh.service"))
return -ENOENT;
@@ -1109,6 +1117,12 @@ static int service_verify(Service *s) {
return -EINVAL;
}
+ if (s->type == SERVICE_ONESHOT && s->restart != SERVICE_RESTART_NO) {
+ log_error_unit(UNIT(s)->id,
+ "%s has Restart setting other than no, which isn't allowed for Type=oneshot services. Refusing.", UNIT(s)->id);
+ return -EINVAL;
+ }
+
if (s->type == SERVICE_DBUS && !s->bus_name) {
log_error_unit(UNIT(s)->id,
"%s is of type D-Bus but no D-Bus service name has been specified. Refusing.", UNIT(s)->id);
@@ -1191,27 +1205,32 @@ static int service_load(Unit *u) {
assert(s);
/* Load a .service file */
- if ((r = unit_load_fragment(u)) < 0)
+ r = unit_load_fragment(u);
+ if (r < 0)
return r;
#ifdef HAVE_SYSV_COMPAT
/* Load a classic init script as a fallback, if we couldn't find anything */
- if (u->load_state == UNIT_STUB)
- if ((r = service_load_sysv(s)) < 0)
+ if (u->load_state == UNIT_STUB) {
+ r = service_load_sysv(s);
+ if (r < 0)
return r;
+ }
#endif
/* Still nothing found? Then let's give up */
if (u->load_state == UNIT_STUB)
return -ENOENT;
- /* We were able to load something, then let's add in the
- * dropin directories. */
- if ((r = unit_load_dropin(unit_follow_merge(u))) < 0)
- return r;
-
/* This is a new unit? Then let's add in some extras */
if (u->load_state == UNIT_LOADED) {
+
+ /* We were able to load something, then let's add in
+ * the dropin directories. */
+ r = unit_load_dropin(u);
+ if (r < 0)
+ return r;
+
if (s->type == _SERVICE_TYPE_INVALID)
s->type = s->bus_name ? SERVICE_DBUS : SERVICE_SIMPLE;
@@ -1225,7 +1244,7 @@ static int service_load(Unit *u) {
if (r < 0)
return r;
- r = unit_add_default_cgroups(u);
+ r = unit_add_default_slice(u);
if (r < 0)
return r;
@@ -1453,7 +1472,7 @@ static int service_search_main_pid(Service *s) {
assert(s->main_pid <= 0);
- pid = cgroup_bonding_search_main_pid_list(UNIT(s)->cgroup_bondings);
+ pid = unit_search_main_pid(UNIT(s));
if (pid <= 0)
return -ENOENT;
@@ -1474,24 +1493,6 @@ static int service_search_main_pid(Service *s) {
return 0;
}
-static void service_notify_sockets_dead(Service *s, bool failed_permanent) {
- Iterator i;
- Unit *u;
-
- assert(s);
-
- /* Notifies all our sockets when we die */
-
- if (s->socket_fd >= 0)
- return;
-
- SET_FOREACH(u, UNIT(s)->dependencies[UNIT_TRIGGERED_BY], i)
- if (u->type == UNIT_SOCKET)
- socket_notify_service_dead(SOCKET(u), failed_permanent);
-
- return;
-}
-
static void service_set_state(Service *s, ServiceState state) {
ServiceState old_state;
const UnitActiveState *table;
@@ -1543,19 +1544,6 @@ static void service_set_state(Service *s, ServiceState state) {
s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID;
}
- if (state == SERVICE_FAILED)
- service_notify_sockets_dead(s, s->result == SERVICE_FAILURE_START_LIMIT);
-
- if (state == SERVICE_DEAD ||
- state == SERVICE_STOP ||
- state == SERVICE_STOP_SIGTERM ||
- state == SERVICE_STOP_SIGKILL ||
- state == SERVICE_STOP_POST ||
- state == SERVICE_FINAL_SIGTERM ||
- state == SERVICE_FINAL_SIGKILL ||
- state == SERVICE_AUTO_RESTART)
- service_notify_sockets_dead(s, false);
-
if (state != SERVICE_START_PRE &&
state != SERVICE_START &&
state != SERVICE_START_POST &&
@@ -1578,7 +1566,7 @@ static void service_set_state(Service *s, ServiceState state) {
/* For the inactive states unit_notify() will trim the cgroup,
* but for exit we have to do that ourselves... */
if (state == SERVICE_EXITED && UNIT(s)->manager->n_reloading <= 0)
- cgroup_bonding_trim_list(UNIT(s)->cgroup_bondings, true);
+ unit_destroy_cgroup(UNIT(s));
if (old_state != state)
log_debug_unit(UNIT(s)->id,
@@ -1610,6 +1598,7 @@ static int service_coldplug(Unit *u) {
s->deserialized_state == SERVICE_FINAL_SIGTERM ||
s->deserialized_state == SERVICE_FINAL_SIGKILL ||
s->deserialized_state == SERVICE_AUTO_RESTART) {
+
if (s->deserialized_state == SERVICE_AUTO_RESTART || s->timeout_start_usec > 0) {
usec_t k;
@@ -1747,11 +1736,14 @@ static int service_spawn(
unsigned n_fds = 0, n_env = 0;
_cleanup_strv_free_ char
**argv = NULL, **final_env = NULL, **our_env = NULL;
+ const char *path;
assert(s);
assert(c);
assert(_pid);
+ unit_realize_cgroup(UNIT(s));
+
if (pass_fds ||
s->exec_context.std_input == EXEC_INPUT_SOCKET ||
s->exec_context.std_output == EXEC_OUTPUT_SOCKET ||
@@ -1777,11 +1769,9 @@ static int service_spawn(
} else
unit_unwatch_timer(UNIT(s), &s->timer_watch);
- argv = unit_full_printf_strv(UNIT(s), c->argv);
- if (!argv) {
- r = -ENOMEM;
+ r = unit_full_printf_strv(UNIT(s), c->argv, &argv);
+ if (r < 0)
goto fail;
- }
our_env = new0(char*, 5);
if (!our_env) {
@@ -1807,7 +1797,7 @@ static int service_spawn(
goto fail;
}
- if (s->meta.manager->running_as != SYSTEMD_SYSTEM)
+ if (UNIT(s)->manager->running_as != SYSTEMD_SYSTEM)
if (asprintf(our_env + n_env++, "MANAGERPID=%lu", (unsigned long) getpid()) < 0) {
r = -ENOMEM;
goto fail;
@@ -1819,6 +1809,12 @@ static int service_spawn(
goto fail;
}
+ if (is_control && UNIT(s)->cgroup_path) {
+ path = strappenda(UNIT(s)->cgroup_path, "/control");
+ cg_create(SYSTEMD_CGROUP_CONTROLLER, path);
+ } else
+ path = UNIT(s)->cgroup_path;
+
r = exec_spawn(c,
argv,
&s->exec_context,
@@ -1828,9 +1824,8 @@ static int service_spawn(
apply_chroot,
apply_tty_stdin,
UNIT(s)->manager->confirm_spawn,
- UNIT(s)->cgroup_bondings,
- UNIT(s)->cgroup_attributes,
- is_control ? "control" : NULL,
+ UNIT(s)->manager->cgroup_supported,
+ path,
UNIT(s)->id,
s->type == SERVICE_IDLE ? UNIT(s)->manager->idle_pipe : NULL,
&pid);
@@ -1865,7 +1860,7 @@ static int main_pid_good(Service *s) {
/* If it's an alien child let's check if it is still
* alive ... */
- if (s->main_pid_alien)
+ if (s->main_pid_alien && s->main_pid > 0)
return kill(s->main_pid, 0) >= 0 || errno != ESRCH;
/* .. otherwise assume we'll get a SIGCHLD for it,
@@ -1889,7 +1884,10 @@ static int cgroup_good(Service *s) {
assert(s);
- r = cgroup_bonding_is_empty_list(UNIT(s)->cgroup_bondings);
+ if (!UNIT(s)->cgroup_path)
+ return 0;
+
+ r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, UNIT(s)->cgroup_path, true);
if (r < 0)
return r;
@@ -1910,6 +1908,7 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
(s->restart == SERVICE_RESTART_ALWAYS ||
(s->restart == SERVICE_RESTART_ON_SUCCESS && s->result == SERVICE_SUCCESS) ||
(s->restart == SERVICE_RESTART_ON_FAILURE && s->result != SERVICE_SUCCESS) ||
+ (s->restart == SERVICE_RESTART_ON_WATCHDOG && s->result == SERVICE_FAILURE_WATCHDOG) ||
(s->restart == SERVICE_RESTART_ON_ABORT && (s->result == SERVICE_FAILURE_SIGNAL ||
s->result == SERVICE_FAILURE_CORE_DUMP))) &&
(s->result != SERVICE_FAILURE_EXIT_CODE ||
@@ -1930,6 +1929,12 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
/* we want fresh tmpdirs in case service is started again immediately */
exec_context_tmp_dirs_done(&s->exec_context);
+ /* Try to delete the pid file. At this point it will be
+ * out-of-date, and some software might be confused by it, so
+ * let's remove it. */
+ if (s->pid_file)
+ unlink_noerrno(s->pid_file);
+
return;
fail:
@@ -1939,8 +1944,6 @@ fail:
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, false);
}
-static void service_enter_signal(Service *s, ServiceState state, ServiceResult f);
-
static void service_enter_stop_post(Service *s, ServiceResult f) {
int r;
assert(s);
@@ -1970,7 +1973,7 @@ static void service_enter_stop_post(Service *s, ServiceResult f) {
service_set_state(s, SERVICE_STOP_POST);
} else
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_SUCCESS);
+ service_enter_dead(s, SERVICE_SUCCESS, true);
return;
@@ -2121,25 +2124,33 @@ fail:
service_enter_stop(s, SERVICE_FAILURE_RESOURCES);
}
+static void service_kill_control_processes(Service *s) {
+ char *p;
+
+ if (!UNIT(s)->cgroup_path)
+ return;
+
+ p = strappenda(UNIT(s)->cgroup_path, "/control");
+ cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, p, SIGKILL, true, true, true, NULL);
+}
+
static void service_enter_start(Service *s) {
+ ExecCommand *c;
pid_t pid;
int r;
- ExecCommand *c;
assert(s);
assert(s->exec_command[SERVICE_EXEC_START]);
assert(!s->exec_command[SERVICE_EXEC_START]->command_next || s->type == SERVICE_ONESHOT);
- if (s->type == SERVICE_FORKING)
- service_unwatch_control_pid(s);
- else
- service_unwatch_main_pid(s);
+ service_unwatch_control_pid(s);
+ service_unwatch_main_pid(s);
/* We want to ensure that nobody leaks processes from
* START_PRE here, so let's go on a killing spree, People
* should not spawn long running processes from START_PRE. */
- cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, SIGKILL, true, true, NULL, "control");
+ service_kill_control_processes(s);
if (s->type == SERVICE_FORKING) {
s->control_command_id = SERVICE_EXEC_START;
@@ -2215,11 +2226,9 @@ static void service_enter_start_pre(Service *s) {
s->control_command = s->exec_command[SERVICE_EXEC_START_PRE];
if (s->control_command) {
-
/* Before we start anything, let's clear up what might
* be left from previous runs. */
- cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, SIGKILL,
- true,true, NULL, "control");
+ service_kill_control_processes(s);
s->control_command_id = SERVICE_EXEC_START_PRE;
@@ -2691,8 +2700,10 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
if (parse_pid(value, &pid) < 0)
log_debug_unit(u->id, "Failed to parse main-pid value %s", value);
- else
- service_set_main_pid(s, (pid_t) pid);
+ else {
+ service_set_main_pid(s, pid);
+ unit_watch_pid(UNIT(s), pid);
+ }
} else if (streq(key, "main-pid-known")) {
int b;
@@ -3043,7 +3054,6 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
}
} else if (s->control_pid == pid) {
-
s->control_pid = 0;
if (s->control_command) {
@@ -3064,8 +3074,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
/* Immediately get rid of the cgroup, so that the
* kernel doesn't delay the cgroup empty messages for
* the service cgroup any longer than necessary */
- cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, SIGKILL,
- true, true, NULL, "control");
+ service_kill_control_processes(s);
if (s->control_command &&
s->control_command->command_next &&
@@ -3294,13 +3303,12 @@ static void service_timer_event(Unit *u, uint64_t elapsed, Watch* w) {
}
}
-static void service_cgroup_notify_event(Unit *u) {
+static void service_notify_cgroup_empty_event(Unit *u) {
Service *s = SERVICE(u);
assert(u);
- log_debug_unit(u->id,
- "%s: cgroup is empty", u->id);
+ log_debug_unit(u->id, "%s: cgroup is empty", u->id);
switch (s->state) {
@@ -3387,6 +3395,7 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags) {
log_debug_unit(u->id,
"%s: got %s", u->id, e);
service_set_main_pid(s, pid);
+ unit_watch_pid(UNIT(s), pid);
}
}
@@ -3683,8 +3692,10 @@ static void service_bus_query_pid_done(
(s->state == SERVICE_START ||
s->state == SERVICE_START_POST ||
s->state == SERVICE_RUNNING ||
- s->state == SERVICE_RELOAD))
+ s->state == SERVICE_RELOAD)){
service_set_main_pid(s, pid);
+ unit_watch_pid(UNIT(s), pid);
+ }
}
int service_set_socket_fd(Service *s, int fd, Socket *sock) {
@@ -3729,6 +3740,7 @@ static void service_reset_failed(Unit *u) {
static int service_kill(Unit *u, KillWho who, int signo, DBusError *error) {
Service *s = SERVICE(u);
+
return unit_kill_common(u, who, signo, s->main_pid, s->control_pid, error);
}
@@ -3756,6 +3768,7 @@ static const char* const service_restart_table[_SERVICE_RESTART_MAX] = {
[SERVICE_RESTART_NO] = "no",
[SERVICE_RESTART_ON_SUCCESS] = "on-success",
[SERVICE_RESTART_ON_FAILURE] = "on-failure",
+ [SERVICE_RESTART_ON_WATCHDOG] = "on-watchdog",
[SERVICE_RESTART_ON_ABORT] = "on-abort",
[SERVICE_RESTART_ALWAYS] = "always"
};
@@ -3821,8 +3834,9 @@ const UnitVTable service_vtable = {
"Service\0"
"Install\0",
+ .private_section = "Service",
.exec_context_offset = offsetof(Service, exec_context),
- .exec_section = "Service",
+ .cgroup_context_offset = offsetof(Service, cgroup_context),
.init = service_init,
.done = service_done,
@@ -3855,7 +3869,7 @@ const UnitVTable service_vtable = {
.reset_failed = service_reset_failed,
- .cgroup_notify_empty = service_cgroup_notify_event,
+ .notify_cgroup_empty = service_notify_cgroup_empty_event,
.notify_message = service_notify_message,
.bus_name_owner_change = service_bus_name_owner_change,
@@ -3864,6 +3878,10 @@ const UnitVTable service_vtable = {
.bus_interface = "org.freedesktop.systemd1.Service",
.bus_message_handler = bus_service_message_handler,
.bus_invalidating_properties = bus_service_invalidating_properties,
+ .bus_set_property = bus_service_set_property,
+ .bus_commit_properties = bus_service_commit_properties,
+
+ .can_transient = true,
#ifdef HAVE_SYSV_COMPAT
.enumerate = service_enumerate,
diff --git a/src/core/service.h b/src/core/service.h
index 703d3faa45..ce5b5e04ab 100644
--- a/src/core/service.h
+++ b/src/core/service.h
@@ -54,6 +54,7 @@ typedef enum ServiceRestart {
SERVICE_RESTART_NO,
SERVICE_RESTART_ON_SUCCESS,
SERVICE_RESTART_ON_FAILURE,
+ SERVICE_RESTART_ON_WATCHDOG,
SERVICE_RESTART_ON_ABORT,
SERVICE_RESTART_ALWAYS,
_SERVICE_RESTART_MAX,
@@ -135,6 +136,7 @@ struct Service {
ExecContext exec_context;
KillContext kill_context;
+ CGroupContext cgroup_context;
ServiceState state, deserialized_state;
diff --git a/src/core/shutdown.c b/src/core/shutdown.c
index 2db761de36..4709746de4 100644
--- a/src/core/shutdown.c
+++ b/src/core/shutdown.c
@@ -39,6 +39,7 @@
#include "missing.h"
#include "log.h"
+#include "fileio.h"
#include "umount.h"
#include "util.h"
#include "mkdir.h"
@@ -130,12 +131,27 @@ static int pivot_to_new_root(void) {
}
int main(int argc, char *argv[]) {
+ _cleanup_free_ char *line = NULL;
int cmd, r;
unsigned retries;
bool need_umount = true, need_swapoff = true, need_loop_detach = true, need_dm_detach = true;
bool in_container, use_watchdog = false;
char *arguments[3];
+ /* suppress shutdown status output if 'quiet' is used */
+ r = read_one_line_file("/proc/cmdline", &line);
+ if (r >= 0) {
+ char *w, *state;
+ size_t l;
+
+ FOREACH_WORD_QUOTED(w, l, line, state) {
+ if (l == 5 && memcmp(w, "quiet", 5) == 0) {
+ log_set_max_level(LOG_WARNING);
+ break;
+ }
+ }
+ }
+
log_parse_environment();
log_set_target(LOG_TARGET_CONSOLE); /* syslog will die if not gone yet */
log_open();
@@ -302,7 +318,7 @@ int main(int argc, char *argv[]) {
log_warning("kexec failed. Falling back to normal reboot.");
} else {
/* Child */
- const char *args[3] = { "/sbin/kexec", "-e", NULL };
+ const char *args[3] = { KEXEC, "-e", NULL };
execv(args[0], (char * const *) args);
return EXIT_FAILURE;
}
diff --git a/src/core/slice.c b/src/core/slice.c
new file mode 100644
index 0000000000..40d416e35e
--- /dev/null
+++ b/src/core/slice.c
@@ -0,0 +1,322 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ 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>
+#include <signal.h>
+#include <unistd.h>
+
+#include "unit.h"
+#include "slice.h"
+#include "load-fragment.h"
+#include "log.h"
+#include "dbus-slice.h"
+#include "special.h"
+#include "unit-name.h"
+
+static const UnitActiveState state_translation_table[_SLICE_STATE_MAX] = {
+ [SLICE_DEAD] = UNIT_INACTIVE,
+ [SLICE_ACTIVE] = UNIT_ACTIVE
+};
+
+static void slice_init(Unit *u) {
+ Slice *s = SLICE(u);
+
+ assert(u);
+ assert(u->load_state == UNIT_STUB);
+
+ cgroup_context_init(&s->cgroup_context);
+}
+
+static void slice_done(Unit *u) {
+ Slice *s = SLICE(u);
+
+ assert(u);
+
+ cgroup_context_done(&s->cgroup_context);
+}
+
+static void slice_set_state(Slice *t, SliceState state) {
+ SliceState old_state;
+ assert(t);
+
+ old_state = t->state;
+ t->state = state;
+
+ if (state != old_state)
+ log_debug("%s changed %s -> %s",
+ UNIT(t)->id,
+ slice_state_to_string(old_state),
+ slice_state_to_string(state));
+
+ unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], true);
+}
+
+static int slice_add_parent_slice(Slice *s) {
+ char *a, *dash;
+ Unit *parent;
+ int r;
+
+ assert(s);
+
+ if (UNIT_ISSET(UNIT(s)->slice))
+ return 0;
+
+ if (unit_has_name(UNIT(s), SPECIAL_ROOT_SLICE))
+ return 0;
+
+ a = strdupa(UNIT(s)->id);
+ dash = strrchr(a, '-');
+ if (dash)
+ strcpy(dash, ".slice");
+ else
+ a = (char*) SPECIAL_ROOT_SLICE;
+
+ r = manager_load_unit(UNIT(s)->manager, a, NULL, NULL, &parent);
+ if (r < 0)
+ return r;
+
+ unit_ref_set(&UNIT(s)->slice, parent);
+ return 0;
+}
+
+static int slice_add_default_dependencies(Slice *s) {
+ int r;
+
+ assert(s);
+
+ /* Make sure slices are unloaded on shutdown */
+ r = unit_add_two_dependencies_by_name(
+ UNIT(s),
+ UNIT_BEFORE, UNIT_CONFLICTS,
+ SPECIAL_SHUTDOWN_TARGET, NULL, true);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int slice_verify(Slice *s) {
+ assert(s);
+
+ if (UNIT(s)->load_state != UNIT_LOADED)
+ return 0;
+
+ if (UNIT_DEREF(UNIT(s)->slice)) {
+ char *a, *dash;
+
+ a = strdupa(UNIT(s)->id);
+ dash = strrchr(a, '-');
+ if (dash)
+ strcpy(dash, ".slice");
+ else
+ a = (char*) SPECIAL_ROOT_SLICE;
+
+ if (!unit_has_name(UNIT_DEREF(UNIT(s)->slice), a)) {
+ log_error_unit(UNIT(s)->id,
+ "%s located outside its parent slice. Refusing.", UNIT(s)->id);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static int slice_load(Unit *u) {
+ Slice *s = SLICE(u);
+ int r;
+
+ assert(s);
+
+ r = unit_load_fragment_and_dropin_optional(u);
+ if (r < 0)
+ return r;
+
+ /* This is a new unit? Then let's add in some extras */
+ if (u->load_state == UNIT_LOADED) {
+
+ r = slice_add_parent_slice(s);
+ if (r < 0)
+ return r;
+
+ if (u->default_dependencies) {
+ r = slice_add_default_dependencies(s);
+ if (r < 0)
+ return r;
+ }
+ }
+
+ return slice_verify(s);
+}
+
+static int slice_coldplug(Unit *u) {
+ Slice *t = SLICE(u);
+
+ assert(t);
+ assert(t->state == SLICE_DEAD);
+
+ if (t->deserialized_state != t->state)
+ slice_set_state(t, t->deserialized_state);
+
+ return 0;
+}
+
+static void slice_dump(Unit *u, FILE *f, const char *prefix) {
+ Slice *t = SLICE(u);
+
+ assert(t);
+ assert(f);
+
+ fprintf(f,
+ "%sSlice State: %s\n",
+ prefix, slice_state_to_string(t->state));
+
+ cgroup_context_dump(&t->cgroup_context, f, prefix);
+}
+
+static int slice_start(Unit *u) {
+ Slice *t = SLICE(u);
+
+ assert(t);
+ assert(t->state == SLICE_DEAD);
+
+ unit_realize_cgroup(u);
+
+ slice_set_state(t, SLICE_ACTIVE);
+ return 0;
+}
+
+static int slice_stop(Unit *u) {
+ Slice *t = SLICE(u);
+
+ assert(t);
+ assert(t->state == SLICE_ACTIVE);
+
+ /* We do not need to destroy the cgroup explicitly,
+ * unit_notify() will do that for us anyway. */
+
+ slice_set_state(t, SLICE_DEAD);
+ return 0;
+}
+
+static int slice_kill(Unit *u, KillWho who, int signo, DBusError *error) {
+ return unit_kill_common(u, who, signo, -1, -1, error);
+}
+
+static int slice_serialize(Unit *u, FILE *f, FDSet *fds) {
+ Slice *s = SLICE(u);
+
+ assert(s);
+ assert(f);
+ assert(fds);
+
+ unit_serialize_item(u, f, "state", slice_state_to_string(s->state));
+ return 0;
+}
+
+static int slice_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
+ Slice *s = SLICE(u);
+
+ assert(u);
+ assert(key);
+ assert(value);
+ assert(fds);
+
+ if (streq(key, "state")) {
+ SliceState state;
+
+ state = slice_state_from_string(value);
+ if (state < 0)
+ log_debug("Failed to parse state value %s", value);
+ else
+ s->deserialized_state = state;
+
+ } else
+ log_debug("Unknown serialization key '%s'", key);
+
+ return 0;
+}
+
+_pure_ static UnitActiveState slice_active_state(Unit *u) {
+ assert(u);
+
+ return state_translation_table[SLICE(u)->state];
+}
+
+_pure_ static const char *slice_sub_state_to_string(Unit *u) {
+ assert(u);
+
+ return slice_state_to_string(SLICE(u)->state);
+}
+
+static const char* const slice_state_table[_SLICE_STATE_MAX] = {
+ [SLICE_DEAD] = "dead",
+ [SLICE_ACTIVE] = "active"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(slice_state, SliceState);
+
+const UnitVTable slice_vtable = {
+ .object_size = sizeof(Slice),
+ .sections =
+ "Unit\0"
+ "Slice\0"
+ "Install\0",
+
+ .private_section = "Slice",
+ .cgroup_context_offset = offsetof(Slice, cgroup_context),
+
+ .no_alias = true,
+ .no_instances = true,
+
+ .init = slice_init,
+ .load = slice_load,
+ .done = slice_done,
+
+ .coldplug = slice_coldplug,
+
+ .dump = slice_dump,
+
+ .start = slice_start,
+ .stop = slice_stop,
+
+ .kill = slice_kill,
+
+ .serialize = slice_serialize,
+ .deserialize_item = slice_deserialize_item,
+
+ .active_state = slice_active_state,
+ .sub_state_to_string = slice_sub_state_to_string,
+
+ .bus_interface = "org.freedesktop.systemd1.Slice",
+ .bus_message_handler = bus_slice_message_handler,
+ .bus_set_property = bus_slice_set_property,
+ .bus_commit_properties = bus_slice_commit_properties,
+
+ .status_message_formats = {
+ .finished_start_job = {
+ [JOB_DONE] = "Created slice %s.",
+ [JOB_DEPENDENCY] = "Dependency failed for %s.",
+ },
+ .finished_stop_job = {
+ [JOB_DONE] = "Removed slice %s.",
+ },
+ },
+};
diff --git a/src/core/slice.h b/src/core/slice.h
new file mode 100644
index 0000000000..ad0c63902b
--- /dev/null
+++ b/src/core/slice.h
@@ -0,0 +1,46 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#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/>.
+***/
+
+typedef struct Slice Slice;
+
+#include "unit.h"
+
+typedef enum SliceState {
+ SLICE_DEAD,
+ SLICE_ACTIVE,
+ _SLICE_STATE_MAX,
+ _SLICE_STATE_INVALID = -1
+} SliceState;
+
+struct Slice {
+ Unit meta;
+
+ SliceState state, deserialized_state;
+
+ CGroupContext cgroup_context;
+};
+
+extern const UnitVTable slice_vtable;
+
+const char* slice_state_to_string(SliceState i) _const_;
+SliceState slice_state_from_string(const char *s) _pure_;
diff --git a/src/core/smack-setup.c b/src/core/smack-setup.c
index 73eeb04190..1434dea7c1 100644
--- a/src/core/smack-setup.c
+++ b/src/core/smack-setup.c
@@ -40,7 +40,9 @@
#include "label.h"
#define SMACK_CONFIG "/etc/smack/accesses.d/"
-#define CIPSO_CONFIG "/etc/smack/cipso/"
+#define CIPSO_CONFIG "/etc/smack/cipso.d/"
+
+#ifdef HAVE_SMACK
static int write_rules(const char* dstpath, const char* srcdir) {
_cleanup_fclose_ FILE *dst = NULL;
@@ -111,8 +113,12 @@ static int write_rules(const char* dstpath, const char* srcdir) {
return r;
}
+#endif
int smack_setup(void) {
+
+#ifdef HAVE_SMACK
+
int r;
r = write_rules("/sys/fs/smackfs/load2", SMACK_CONFIG);
@@ -148,4 +154,8 @@ int smack_setup(void) {
strerror(abs(r)));
return 0;
}
+
+#endif
+
+ return 0;
}
diff --git a/src/core/snapshot.c b/src/core/snapshot.c
index a63eccd8de..d11239dff3 100644
--- a/src/core/snapshot.c
+++ b/src/core/snapshot.c
@@ -40,6 +40,7 @@ static void snapshot_init(Unit *u) {
UNIT(s)->ignore_on_isolate = true;
UNIT(s)->ignore_on_snapshot = true;
+ UNIT(s)->allow_isolate = true;
}
static void snapshot_set_state(Snapshot *s, SnapshotState state) {
@@ -66,7 +67,7 @@ static int snapshot_load(Unit *u) {
/* Make sure that only snapshots created via snapshot_create()
* can be loaded */
- if (!s->by_snapshot_create && UNIT(s)->manager->n_reloading <= 0)
+ if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
return -ENOENT;
u->load_state = UNIT_LOADED;
@@ -151,21 +152,24 @@ static int snapshot_deserialize_item(Unit *u, const char *key, const char *value
if (streq(key, "state")) {
SnapshotState state;
- if ((state = snapshot_state_from_string(value)) < 0)
+ state = snapshot_state_from_string(value);
+ if (state < 0)
log_debug("Failed to parse state value %s", value);
else
s->deserialized_state = state;
} else if (streq(key, "cleanup")) {
- if ((r = parse_boolean(value)) < 0)
+ r = parse_boolean(value);
+ if (r < 0)
log_debug("Failed to parse cleanup value %s", value);
else
s->cleanup = r;
} else if (streq(key, "wants")) {
- if ((r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_WANTS, value, NULL, true)) < 0)
+ r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_WANTS, value, NULL, true);
+ if (r < 0)
return r;
} else
log_debug("Unknown serialization key '%s'", key);
@@ -186,9 +190,9 @@ _pure_ static const char *snapshot_sub_state_to_string(Unit *u) {
}
int snapshot_create(Manager *m, const char *name, bool cleanup, DBusError *e, Snapshot **_s) {
- Iterator i;
+ _cleanup_free_ char *n = NULL;
Unit *other, *u = NULL;
- char *n = NULL;
+ Iterator i;
int r;
const char *k;
@@ -217,28 +221,28 @@ int snapshot_create(Manager *m, const char *name, bool cleanup, DBusError *e, Sn
if (asprintf(&n, "snapshot-%u.snapshot", ++ m->n_snapshots) < 0)
return -ENOMEM;
- if (!manager_get_unit(m, n))
+ if (!manager_get_unit(m, n)) {
+ name = n;
break;
+ }
free(n);
+ n = NULL;
}
-
- name = n;
}
r = manager_load_unit_prepare(m, name, NULL, e, &u);
- free(n);
-
if (r < 0)
goto fail;
- SNAPSHOT(u)->by_snapshot_create = true;
+ u->transient = true;
manager_dispatch_load_queue(m);
assert(u->load_state == UNIT_LOADED);
HASHMAP_FOREACH_KEY(other, k, m->units, i) {
- if (other->ignore_on_snapshot)
+ if (other->ignore_on_snapshot ||
+ other->transient)
continue;
if (k != other->id)
@@ -251,12 +255,12 @@ int snapshot_create(Manager *m, const char *name, bool cleanup, DBusError *e, Sn
if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
continue;
- if ((r = unit_add_two_dependencies(u, UNIT_AFTER, UNIT_WANTS, other, true)) < 0)
+ r = unit_add_two_dependencies(u, UNIT_AFTER, UNIT_WANTS, other, true);
+ if (r < 0)
goto fail;
}
SNAPSHOT(u)->cleanup = cleanup;
- u->allow_isolate = true;
*_s = SNAPSHOT(u);
return 0;
diff --git a/src/core/snapshot.h b/src/core/snapshot.h
index 56f87cff4d..2675b1b242 100644
--- a/src/core/snapshot.h
+++ b/src/core/snapshot.h
@@ -38,7 +38,6 @@ struct Snapshot {
SnapshotState state, deserialized_state;
bool cleanup;
- bool by_snapshot_create:1;
};
extern const UnitVTable snapshot_vtable;
diff --git a/src/core/socket.c b/src/core/socket.c
index 1b08f0a5fd..6c0ac1a898 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -88,6 +88,7 @@ static void socket_init(Unit *u) {
s->exec_context.std_output = u->manager->default_std_output;
s->exec_context.std_error = u->manager->default_std_error;
kill_context_init(&s->kill_context);
+ cgroup_context_init(&s->cgroup_context);
s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID;
}
@@ -128,6 +129,8 @@ static void socket_done(Unit *u) {
socket_free_ports(s);
exec_context_done(&s->exec_context, manager_is_reloading_or_reexecuting(u->manager));
+ cgroup_context_init(&s->cgroup_context);
+
exec_command_free_array(s->exec_command, _SOCKET_EXEC_COMMAND_MAX);
s->control_command = NULL;
@@ -255,53 +258,24 @@ static int socket_verify(Socket *s) {
return 0;
}
-static bool socket_needs_mount(Socket *s, const char *prefix) {
+static int socket_add_mount_links(Socket *s) {
SocketPort *p;
-
- assert(s);
-
- LIST_FOREACH(port, p, s->ports) {
-
- if (p->type == SOCKET_SOCKET) {
- if (socket_address_needs_mount(&p->address, prefix))
- return true;
- } else if (p->type == SOCKET_FIFO || p->type == SOCKET_SPECIAL) {
- if (path_startswith(p->path, prefix))
- return true;
- }
- }
-
- return false;
-}
-
-int socket_add_one_mount_link(Socket *s, Mount *m) {
int r;
assert(s);
- assert(m);
- if (UNIT(s)->load_state != UNIT_LOADED ||
- UNIT(m)->load_state != UNIT_LOADED)
- return 0;
-
- if (!socket_needs_mount(s, m->where))
- return 0;
-
- r = unit_add_two_dependencies(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true);
- if (r < 0)
- return r;
-
- return 0;
-}
+ LIST_FOREACH(port, p, s->ports) {
+ const char *path = NULL;
-static int socket_add_mount_links(Socket *s) {
- Unit *other;
- int r;
+ if (p->type == SOCKET_SOCKET)
+ path = socket_address_get_path(&p->address);
+ else if (p->type == SOCKET_FIFO || p->type == SOCKET_SPECIAL)
+ path = p->path;
- assert(s);
+ if (!path)
+ continue;
- LIST_FOREACH(units_by_type, other, UNIT(s)->manager->units_by_type[UNIT_MOUNT]) {
- r = socket_add_one_mount_link(s, MOUNT(other));
+ r = unit_require_mounts_for(UNIT(s), path);
if (r < 0)
return r;
}
@@ -395,7 +369,8 @@ static int socket_load(Unit *u) {
if ((r = unit_add_exec_dependencies(u, &s->exec_context)) < 0)
return r;
- if ((r = unit_add_default_cgroups(u)) < 0)
+ r = unit_add_default_slice(u);
+ if (r < 0)
return r;
if (UNIT(s)->default_dependencies)
@@ -532,6 +507,11 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
"%sMessageQueueMessageSize: %li\n",
prefix, s->mq_msgsize);
+ if (s->reuseport)
+ fprintf(f,
+ "%sReusePort: %s\n",
+ prefix, yes_no(s->reuseport));
+
if (s->smack)
fprintf(f,
"%sSmackLabel: %s\n",
@@ -788,7 +768,13 @@ static void socket_apply_socket_options(Socket *s, int fd) {
if (setsockopt(fd, SOL_TCP, TCP_CONGESTION, s->tcp_congestion, strlen(s->tcp_congestion)+1) < 0)
log_warning_unit(UNIT(s)->id, "TCP_CONGESTION failed: %m");
-#ifdef HAVE_XATTR
+ if (s->reuseport) {
+ int b = s->reuseport;
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &b, sizeof(b)))
+ log_warning_unit(UNIT(s)->id, "SO_REUSEPORT failed: %m");
+ }
+
+#ifdef HAVE_SMACK
if (s->smack_ip_in)
if (fsetxattr(fd, "security.SMACK64IPIN", s->smack_ip_in, strlen(s->smack_ip_in), 0) < 0)
log_error_unit(UNIT(s)->id,
@@ -810,7 +796,7 @@ static void socket_apply_fifo_options(Socket *s, int fd) {
log_warning_unit(UNIT(s)->id,
"F_SETPIPE_SZ: %m");
-#ifdef HAVE_XATTR
+#ifdef HAVE_SMACK
if (s->smack)
if (fsetxattr(fd, "security.SMACK64", s->smack, strlen(s->smack), 0) < 0)
log_error_unit(UNIT(s)->id,
@@ -1000,7 +986,7 @@ static int socket_open_fds(Socket *s) {
if ((r = socket_instantiate_service(s)) < 0)
return r;
- if (UNIT_DEREF(s->service) &&
+ if (UNIT_ISSET(s->service) &&
SERVICE(UNIT_DEREF(s->service))->exec_command[SERVICE_EXEC_START]) {
r = label_get_create_label_from_exe(SERVICE(UNIT_DEREF(s->service))->exec_command[SERVICE_EXEC_START]->path, &label);
@@ -1205,15 +1191,15 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
assert(c);
assert(_pid);
+ unit_realize_cgroup(UNIT(s));
+
r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
if (r < 0)
goto fail;
- argv = unit_full_printf_strv(UNIT(s), c->argv);
- if (!argv) {
- r = -ENOMEM;
+ r = unit_full_printf_strv(UNIT(s), c->argv, &argv);
+ if (r < 0)
goto fail;
- }
r = exec_spawn(c,
argv,
@@ -1224,9 +1210,8 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
true,
true,
UNIT(s)->manager->confirm_spawn,
- UNIT(s)->cgroup_bondings,
- UNIT(s)->cgroup_attributes,
- NULL,
+ UNIT(s)->manager->cgroup_supported,
+ UNIT(s)->cgroup_path,
UNIT(s)->id,
NULL,
&pid);
@@ -1628,7 +1613,7 @@ static int socket_start(Unit *u) {
return 0;
/* Cannot run this without the service being around */
- if (UNIT_DEREF(s->service)) {
+ if (UNIT_ISSET(s->service)) {
Service *service;
service = SERVICE(UNIT_DEREF(s->service));
@@ -2261,7 +2246,7 @@ int socket_collect_fds(Socket *s, int **fds, unsigned *n_fds) {
return 0;
}
-void socket_notify_service_dead(Socket *s, bool failed_permanent) {
+static void socket_notify_service_dead(Socket *s, bool failed_permanent) {
assert(s);
/* The service is dead. Dang!
@@ -2306,6 +2291,41 @@ static void socket_reset_failed(Unit *u) {
s->result = SOCKET_SUCCESS;
}
+static void socket_trigger_notify(Unit *u, Unit *other) {
+ Socket *s = SOCKET(u);
+ Service *se = SERVICE(other);
+
+ assert(u);
+ assert(other);
+
+ /* Don't propagate state changes from the service if we are
+ already down or accepting connections */
+ if ((s->state != SOCKET_RUNNING &&
+ s->state != SOCKET_LISTENING) ||
+ s->accept)
+ return;
+
+ if (other->load_state != UNIT_LOADED ||
+ other->type != UNIT_SERVICE)
+ return;
+
+ if (se->state == SERVICE_FAILED)
+ socket_notify_service_dead(s, se->result == SERVICE_FAILURE_START_LIMIT);
+
+ if (se->state == SERVICE_DEAD ||
+ se->state == SERVICE_STOP ||
+ se->state == SERVICE_STOP_SIGTERM ||
+ se->state == SERVICE_STOP_SIGKILL ||
+ se->state == SERVICE_STOP_POST ||
+ se->state == SERVICE_FINAL_SIGTERM ||
+ se->state == SERVICE_FINAL_SIGKILL ||
+ se->state == SERVICE_AUTO_RESTART)
+ socket_notify_service_dead(s, false);
+
+ if (se->state == SERVICE_RUNNING)
+ socket_set_state(s, SOCKET_RUNNING);
+}
+
static int socket_kill(Unit *u, KillWho who, int signo, DBusError *error) {
return unit_kill_common(u, who, signo, -1, SOCKET(u)->control_pid, error);
}
@@ -2356,8 +2376,9 @@ const UnitVTable socket_vtable = {
"Socket\0"
"Install\0",
+ .private_section = "Socket",
.exec_context_offset = offsetof(Socket, exec_context),
- .exec_section = "Socket",
+ .cgroup_context_offset = offsetof(Socket, cgroup_context),
.init = socket_init,
.done = socket_done,
@@ -2385,11 +2406,15 @@ const UnitVTable socket_vtable = {
.sigchld_event = socket_sigchld_event,
.timer_event = socket_timer_event,
+ .trigger_notify = socket_trigger_notify,
+
.reset_failed = socket_reset_failed,
.bus_interface = "org.freedesktop.systemd1.Socket",
.bus_message_handler = bus_socket_message_handler,
.bus_invalidating_properties = bus_socket_invalidating_properties,
+ .bus_set_property = bus_socket_set_property,
+ .bus_commit_properties = bus_socket_commit_properties,
.status_message_formats = {
/*.starting_stopping = {
diff --git a/src/core/socket.h b/src/core/socket.h
index 9d48cde0a6..3d7eadc9fe 100644
--- a/src/core/socket.h
+++ b/src/core/socket.h
@@ -102,6 +102,7 @@ struct Socket {
ExecCommand* exec_command[_SOCKET_EXEC_COMMAND_MAX];
ExecContext exec_context;
KillContext kill_context;
+ CGroupContext cgroup_context;
/* For Accept=no sockets refers to the one service we'll
activate. For Accept=yes sockets is either NULL, or filled
@@ -143,6 +144,7 @@ struct Socket {
size_t pipe_size;
char *bind_to_device;
char *tcp_congestion;
+ bool reuseport;
long mq_maxmsg;
long mq_msgsize;
@@ -154,13 +156,6 @@ struct Socket {
/* Called from the service code when collecting fds */
int socket_collect_fds(Socket *s, int **fds, unsigned *n_fds);
-/* Called from the service when it shut down */
-void socket_notify_service_dead(Socket *s, bool failed_permanent);
-
-/* Called from the mount code figure out if a mount is a dependency of
- * any of the sockets of this socket */
-int socket_add_one_mount_link(Socket *s, Mount *m);
-
/* Called from the service code when a per-connection service ended */
void socket_connection_unref(Socket *s);
diff --git a/src/core/special.h b/src/core/special.h
index a9b50bce05..6d252e7baa 100644
--- a/src/core/special.h
+++ b/src/core/special.h
@@ -113,3 +113,9 @@
#define SPECIAL_RUNLEVEL3_TARGET "runlevel3.target"
#define SPECIAL_RUNLEVEL4_TARGET "runlevel4.target"
#define SPECIAL_RUNLEVEL5_TARGET "runlevel5.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"
diff --git a/src/core/swap.c b/src/core/swap.c
index d503fe20df..a68ab7cdf8 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -92,6 +92,7 @@ static void swap_init(Unit *u) {
s->exec_context.std_output = u->manager->default_std_output;
s->exec_context.std_error = u->manager->default_std_error;
kill_context_init(&s->kill_context);
+ cgroup_context_init(&s->cgroup_context);
s->parameters_proc_swaps.priority = s->parameters_fragment.priority = -1;
@@ -129,47 +130,13 @@ static void swap_done(Unit *u) {
exec_command_done_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX);
s->control_command = NULL;
+ cgroup_context_done(&s->cgroup_context);
+
swap_unwatch_control_pid(s);
unit_unwatch_timer(u, &s->timer_watch);
}
-int swap_add_one_mount_link(Swap *s, Mount *m) {
- int r;
-
- assert(s);
- assert(m);
-
- if (UNIT(s)->load_state != UNIT_LOADED ||
- UNIT(m)->load_state != UNIT_LOADED)
- return 0;
-
- if (is_device_path(s->what))
- return 0;
-
- if (!path_startswith(s->what, m->where))
- return 0;
-
- r = unit_add_two_dependencies(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static int swap_add_mount_links(Swap *s) {
- Unit *other;
- int r;
-
- assert(s);
-
- LIST_FOREACH(units_by_type, other, UNIT(s)->manager->units_by_type[UNIT_MOUNT])
- if ((r = swap_add_one_mount_link(s, MOUNT(other))) < 0)
- return r;
-
- return 0;
-}
-
static int swap_add_device_links(Swap *s) {
SwapParameters *p;
@@ -184,8 +151,7 @@ static int swap_add_device_links(Swap *s) {
return 0;
if (is_device_path(s->what))
- return unit_add_node_link(UNIT(s), s->what,
- !p->noauto && p->nofail &&
+ return unit_add_node_link(UNIT(s), s->what, !p->noauto &&
UNIT(s)->manager->running_as == SYSTEMD_SYSTEM);
else
/* File based swap devices need to be ordered after
@@ -195,6 +161,7 @@ static int swap_add_device_links(Swap *s) {
}
static int swap_add_default_dependencies(Swap *s) {
+ bool nofail = false, noauto = false;
int r;
assert(s);
@@ -209,6 +176,24 @@ static int swap_add_default_dependencies(Swap *s) {
if (r < 0)
return r;
+ if (s->from_fragment) {
+ SwapParameters *p = &s->parameters_fragment;
+
+ nofail = p->nofail;
+ noauto = p->noauto;
+ }
+
+ if (!noauto) {
+ if (nofail)
+ r = unit_add_dependency_by_name_inverse(UNIT(s),
+ UNIT_WANTS, SPECIAL_SWAP_TARGET, NULL, true);
+ else
+ r = unit_add_two_dependencies_by_name_inverse(UNIT(s),
+ UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SWAP_TARGET, NULL, true);
+ if (r < 0)
+ return r;
+ }
+
return 0;
}
@@ -279,15 +264,15 @@ static int swap_load(Unit *u) {
if ((r = unit_set_description(u, s->what)) < 0)
return r;
- r = swap_add_device_links(s);
+ r = unit_require_mounts_for(UNIT(s), s->what);
if (r < 0)
return r;
- r = swap_add_mount_links(s);
+ r = swap_add_device_links(s);
if (r < 0)
return r;
- r = unit_add_default_cgroups(u);
+ r = unit_add_default_slice(u);
if (r < 0)
return r;
@@ -589,6 +574,8 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
assert(c);
assert(_pid);
+ unit_realize_cgroup(UNIT(s));
+
r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
if (r < 0)
goto fail;
@@ -602,9 +589,8 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
true,
true,
UNIT(s)->manager->confirm_spawn,
- UNIT(s)->cgroup_bondings,
- UNIT(s)->cgroup_attributes,
- NULL,
+ UNIT(s)->manager->cgroup_supported,
+ UNIT(s)->cgroup_path,
UNIT(s)->id,
NULL,
&pid);
@@ -1052,7 +1038,7 @@ static int swap_load_proc_swaps(Manager *m, bool set_flags) {
(void) fscanf(m->proc_swaps, "%*s %*s %*s %*s %*s\n");
for (i = 1;; i++) {
- char *dev = NULL, *d;
+ _cleanup_free_ char *dev = NULL, *d = NULL;
int prio = 0, k;
k = fscanf(m->proc_swaps,
@@ -1067,19 +1053,14 @@ static int swap_load_proc_swaps(Manager *m, bool set_flags) {
break;
log_warning("Failed to parse /proc/swaps:%u", i);
- free(dev);
continue;
}
d = cunescape(dev);
- free(dev);
-
if (!d)
return -ENOMEM;
k = swap_process_new_swap(m, d, prio, set_flags);
- free(d);
-
if (k < 0)
r = k;
}
@@ -1323,8 +1304,9 @@ const UnitVTable swap_vtable = {
"Swap\0"
"Install\0",
+ .private_section = "Swap",
.exec_context_offset = offsetof(Swap, exec_context),
- .exec_section = "Swap",
+ .cgroup_context_offset = offsetof(Swap, cgroup_context),
.no_alias = true,
.no_instances = true,
@@ -1358,6 +1340,8 @@ const UnitVTable swap_vtable = {
.bus_interface = "org.freedesktop.systemd1.Swap",
.bus_message_handler = bus_swap_message_handler,
.bus_invalidating_properties = bus_swap_invalidating_properties,
+ .bus_set_property = bus_swap_set_property,
+ .bus_commit_properties = bus_swap_commit_properties,
.following = swap_following,
.following_set = swap_following_set,
diff --git a/src/core/swap.h b/src/core/swap.h
index 121889d1d5..dd89535895 100644
--- a/src/core/swap.h
+++ b/src/core/swap.h
@@ -88,6 +88,7 @@ struct Swap {
ExecCommand exec_command[_SWAP_EXEC_COMMAND_MAX];
ExecContext exec_context;
KillContext kill_context;
+ CGroupContext cgroup_context;
SwapState state, deserialized_state;
@@ -106,8 +107,6 @@ struct Swap {
extern const UnitVTable swap_vtable;
-int swap_add_one_mount_link(Swap *s, Mount *m);
-
int swap_dispatch_reload(Manager *m);
int swap_fd_event(Manager *m, int events);
diff --git a/src/core/system.conf b/src/core/system.conf
index 508e0f5fa4..7b03c8782b 100644
--- a/src/core/system.conf
+++ b/src/core/system.conf
@@ -17,14 +17,14 @@
#ShowStatus=yes
#CrashChVT=1
#CPUAffinity=1 2
-#DefaultControllers=cpu
#DefaultStandardOutput=journal
#DefaultStandardError=inherit
-#JoinControllers=cpu,cpuacct,cpuset net_cls,net_prio
+#JoinControllers=cpu,cpuacct net_cls,net_prio
#RuntimeWatchdogSec=0
#ShutdownWatchdogSec=10min
#CapabilityBoundingSet=
#TimerSlackNSec=
+#DefaultEnvironment=
#DefaultLimitCPU=
#DefaultLimitFSIZE=
#DefaultLimitDATA=
diff --git a/src/core/systemd.pc.in b/src/core/systemd.pc.in
index 2f49d5df52..de0f6494e9 100644
--- a/src/core/systemd.pc.in
+++ b/src/core/systemd.pc.in
@@ -16,6 +16,9 @@ systemdsystemconfdir=@pkgsysconfdir@/system
systemduserconfdir=@pkgsysconfdir@/user
systemdsystemunitpath=${systemdsystemconfdir}:/etc/systemd/system:/run/systemd/system:/usr/local/lib/systemd/system:${systemdsystemunitdir}:/usr/lib/systemd/system:/lib/systemd/system
systemduserunitpath=${systemduserconfdir}:/etc/systemd/user:/run/systemd/user:/usr/local/lib/systemd/user:/usr/local/share/systemd/user:${systemduserunitdir}:/usr/lib/systemd/user:/usr/share/systemd/user
+systemdsystemgeneratordir=@systemgeneratordir@
+systemdusergeneratordir=@usergeneratordir@
+catalogdir=@catalogdir@
Name: systemd
Description: systemd System and Service Manager
diff --git a/src/core/transaction.c b/src/core/transaction.c
index fa97b69755..203070fa26 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -344,7 +344,7 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
assert(!j->transaction_prev);
/* Does a recursive sweep through the ordering graph, looking
- * for a cycle. If we find cycle we try to break it. */
+ * for a cycle. If we find a cycle we try to break it. */
/* Have we seen this before? */
if (j->generation == generation) {
@@ -371,7 +371,7 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
/* logging for j not k here here to provide consistent narrative */
log_info_unit(j->unit->id,
- "Walked on cycle path to %s/%s",
+ "Found dependency on %s/%s",
k->unit->id, job_type_to_string(k->type));
if (!delete &&
@@ -733,8 +733,11 @@ int transaction_activate(Transaction *tr, Manager *m, JobMode mode, DBusError *e
* feature for cosmetics, not actually useful for
* anything beyond that. */
- if (m->idle_pipe[0] < 0 && m->idle_pipe[1] < 0)
+ if (m->idle_pipe[0] < 0 && m->idle_pipe[1] < 0 &&
+ m->idle_pipe[2] < 0 && m->idle_pipe[3] < 0) {
pipe2(m->idle_pipe, O_NONBLOCK|O_CLOEXEC);
+ pipe2(m->idle_pipe + 2, O_NONBLOCK|O_CLOEXEC);
+ }
}
return 0;
@@ -851,6 +854,7 @@ int transaction_add_job_and_dependencies(
if (unit->load_state != UNIT_LOADED &&
unit->load_state != UNIT_ERROR &&
+ unit->load_state != UNIT_NOT_FOUND &&
unit->load_state != UNIT_MASKED) {
dbus_set_error(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id);
return -EINVAL;
@@ -866,6 +870,14 @@ int transaction_add_job_and_dependencies(
return -EINVAL;
}
+ if (type != JOB_STOP && unit->load_state == UNIT_NOT_FOUND) {
+ dbus_set_error(e, BUS_ERROR_LOAD_FAILED,
+ "Unit %s failed to load: %s.",
+ unit->id,
+ strerror(-unit->load_error));
+ return -EINVAL;
+ }
+
if (type != JOB_STOP && unit->load_state == UNIT_MASKED) {
dbus_set_error(e, BUS_ERROR_MASKED, "Unit %s is masked.", unit->id);
return -EADDRNOTAVAIL;
diff --git a/src/core/unit-printf.c b/src/core/unit-printf.c
index 85a05b872a..1a29a986e9 100644
--- a/src/core/unit-printf.c
+++ b/src/core/unit-printf.c
@@ -27,99 +27,161 @@
#include "unit-name.h"
#include "unit-printf.h"
#include "macro.h"
+#include "cgroup-util.h"
+#include "special.h"
-static char *specifier_prefix_and_instance(char specifier, void *data, void *userdata) {
+static int specifier_prefix_and_instance(char specifier, void *data, void *userdata, char **ret) {
Unit *u = userdata;
+ char *n;
+
assert(u);
- return unit_name_to_prefix_and_instance(u->id);
+ n = unit_name_to_prefix_and_instance(u->id);
+ if (!n)
+ return -ENOMEM;
+
+ *ret = n;
+ return 0;
}
-static char *specifier_prefix(char specifier, void *data, void *userdata) {
+static int specifier_prefix(char specifier, void *data, void *userdata, char **ret) {
Unit *u = userdata;
+ char *n;
+
assert(u);
- return unit_name_to_prefix(u->id);
+ n = unit_name_to_prefix(u->id);
+ if (!n)
+ return -ENOMEM;
+
+ *ret = n;
+ return 0;
}
-static char *specifier_prefix_unescaped(char specifier, void *data, void *userdata) {
+static int specifier_prefix_unescaped(char specifier, void *data, void *userdata, char **ret) {
Unit *u = userdata;
- char *p, *r;
+ _cleanup_free_ char *p = NULL;
+ char *n;
assert(u);
p = unit_name_to_prefix(u->id);
if (!p)
- return NULL;
+ return -ENOMEM;
- r = unit_name_unescape(p);
- free(p);
+ n = unit_name_unescape(p);
+ if (!n)
+ return -ENOMEM;
- return r;
+ *ret = n;
+ return 0;
}
-static char *specifier_instance_unescaped(char specifier, void *data, void *userdata) {
+static int specifier_instance_unescaped(char specifier, void *data, void *userdata, char **ret) {
Unit *u = userdata;
+ char *n;
+
assert(u);
if (u->instance)
- return unit_name_unescape(u->instance);
+ n = unit_name_unescape(u->instance);
+ else
+ n = strdup("");
+
+ if (!n)
+ return -ENOMEM;
- return strdup("");
+ *ret = n;
+ return 0;
}
-static char *specifier_filename(char specifier, void *data, void *userdata) {
+static int specifier_filename(char specifier, void *data, void *userdata, char **ret) {
Unit *u = userdata;
+ char *n;
+
assert(u);
if (u->instance)
- return unit_name_path_unescape(u->instance);
+ n = unit_name_path_unescape(u->instance);
+ else
+ n = unit_name_to_path(u->id);
- return unit_name_to_path(u->id);
+ if (!n)
+ return -ENOMEM;
+
+ *ret = n;
+ return 0;
}
-static char *specifier_cgroup(char specifier, void *data, void *userdata) {
+static int specifier_cgroup(char specifier, void *data, void *userdata, char **ret) {
Unit *u = userdata;
+ char *n;
+
assert(u);
- return unit_default_cgroup_path(u);
+ n = unit_default_cgroup_path(u);
+ if (!n)
+ return -ENOMEM;
+
+ *ret = n;
+ return 0;
}
-static char *specifier_cgroup_root(char specifier, void *data, void *userdata) {
+static int specifier_cgroup_root(char specifier, void *data, void *userdata, char **ret) {
Unit *u = userdata;
- char *p;
+ const char *slice;
+ char *n;
+ int r;
+
assert(u);
- if (specifier == 'r')
- return strdup(u->manager->cgroup_hierarchy);
+ slice = unit_slice_name(u);
+ if (specifier == 'R' || !slice)
+ n = strdup(u->manager->cgroup_root);
+ else {
+ _cleanup_free_ char *p = NULL;
- if (path_get_parent(u->manager->cgroup_hierarchy, &p) < 0)
- return strdup("");
+ r = cg_slice_to_path(slice, &p);
+ if (r < 0)
+ return r;
- if (streq(p, "/")) {
- free(p);
- return strdup("");
+ n = strjoin(u->manager->cgroup_root, "/", p, NULL);
+ if (!n)
+ return -ENOMEM;
}
- return p;
+ *ret = n;
+ return 0;
}
-static char *specifier_runtime(char specifier, void *data, void *userdata) {
+static int specifier_runtime(char specifier, void *data, void *userdata, char **ret) {
Unit *u = userdata;
+ char *n = NULL;
+
assert(u);
if (u->manager->running_as == SYSTEMD_USER) {
const char *e;
e = getenv("XDG_RUNTIME_DIR");
- if (e)
- return strdup(e);
+ if (e) {
+ n = strdup(e);
+ if (!n)
+ return -ENOMEM;
+ }
+ }
+
+ if (!n) {
+ n = strdup("/run");
+ if (!n)
+ return -ENOMEM;
}
- return strdup("/run");
+ *ret = n;
+ return 0;
}
-static char *specifier_user_name(char specifier, void *data, void *userdata) {
+static int specifier_user_name(char specifier, void *data, void *userdata, char **ret) {
Unit *u = userdata;
ExecContext *c;
int r;
@@ -141,26 +203,31 @@ static char *specifier_user_name(char specifier, void *data, void *userdata) {
/* fish username from passwd */
r = get_user_creds(&username, &uid, NULL, NULL, NULL);
if (r < 0)
- return NULL;
+ return r;
switch (specifier) {
case 'U':
if (asprintf(&printed, "%d", uid) < 0)
- return NULL;
+ return -ENOMEM;
break;
case 'u':
printed = strdup(username);
break;
}
- return printed;
+ if (!printed)
+ return -ENOMEM;
+
+ *ret = printed;
+ return 0;
}
-static char *specifier_user_home(char specifier, void *data, void *userdata) {
+static int specifier_user_home(char specifier, void *data, void *userdata, char **ret) {
Unit *u = userdata;
ExecContext *c;
int r;
const char *username, *home;
+ char *n;
assert(u);
@@ -172,25 +239,31 @@ static char *specifier_user_home(char specifier, void *data, void *userdata) {
r = get_home_dir(&h);
if (r < 0)
- return NULL;
+ return r;
- return h;
+ *ret = h;
+ return 0;
}
username = c->user;
r = get_user_creds(&username, NULL, NULL, &home, NULL);
if (r < 0)
- return NULL;
+ return r;
+
+ n = strdup(home);
+ if (!n)
+ return -ENOMEM;
- return strdup(home);
+ *ret = n;
+ return 0;
}
-static char *specifier_user_shell(char specifier, void *data, void *userdata) {
+static int specifier_user_shell(char specifier, void *data, void *userdata, char **ret) {
Unit *u = userdata;
ExecContext *c;
int r;
const char *username, *shell;
- char *ret;
+ char *n;
assert(u);
@@ -203,27 +276,18 @@ static char *specifier_user_shell(char specifier, void *data, void *userdata) {
/* return /bin/sh for root, otherwise the value from passwd */
r = get_user_creds(&username, NULL, NULL, NULL, &shell);
- if (r < 0) {
- log_warning_unit(u->id,
- "Failed to determine shell: %s",
- strerror(-r));
- return NULL;
- }
-
- if (!path_is_absolute(shell)) {
- log_warning_unit(u->id,
- "Shell %s is not absolute, ignoring.",
- shell);
- }
+ if (r < 0)
+ return r;
- ret = strdup(shell);
- if (!ret)
- log_oom();
+ n = strdup(shell);
+ if (!n)
+ return -ENOMEM;
- return ret;
+ *ret = n;
+ return 0;
}
-char *unit_name_printf(Unit *u, const char* format) {
+int unit_name_printf(Unit *u, const char* format, char **ret) {
/*
* This will use the passed string as format string and
@@ -245,19 +309,20 @@ char *unit_name_printf(Unit *u, const char* format) {
assert(u);
assert(format);
+ assert(ret);
- return specifier_printf(format, table, u);
+ return specifier_printf(format, table, u, ret);
}
-char *unit_full_printf(Unit *u, const char *format) {
+int unit_full_printf(Unit *u, const char *format, char **ret) {
/* This is similar to unit_name_printf() but also supports
* unescaping. Also, adds a couple of additional codes:
*
* %f the the instance if set, otherwise the id
* %c cgroup path of unit
- * %r root cgroup path of this systemd instance (e.g. "/user/lennart/shared/systemd-4711")
- * %R parent of root cgroup path (e.g. "/usr/lennart/shared")
+ * %r where units in this slice are place in the cgroup tree
+ * %R the root of this systemd's instance tree
* %t the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR)
* %U the UID of the configured user or running user
* %u the username of the configured user or running user
@@ -266,6 +331,7 @@ char *unit_full_printf(Unit *u, const char *format) {
* %m the machine ID of the running system
* %H the host name of the running system
* %b the boot ID of the running system
+ * %v `uname -r` of the running system
*/
const Specifier table[] = {
@@ -289,17 +355,21 @@ char *unit_full_printf(Unit *u, const char *format) {
{ 'm', specifier_machine_id, NULL },
{ 'H', specifier_host_name, NULL },
{ 'b', specifier_boot_id, NULL },
- { 0, NULL, NULL }
+ { 'v', specifier_kernel_release, NULL },
+ {}
};
+ assert(u);
assert(format);
+ assert(ret);
- return specifier_printf(format, table, u);
+ return specifier_printf(format, table, u, ret);
}
-char **unit_full_printf_strv(Unit *u, char **l) {
+int unit_full_printf_strv(Unit *u, char **l, char ***ret) {
size_t n;
char **r, **i, **j;
+ int q;
/* Applies unit_full_printf to every entry in l */
@@ -308,22 +378,22 @@ char **unit_full_printf_strv(Unit *u, char **l) {
n = strv_length(l);
r = new(char*, n+1);
if (!r)
- return NULL;
+ return -ENOMEM;
for (i = l, j = r; *i; i++, j++) {
- *j = unit_full_printf(u, *i);
- if (!*j)
+ q = unit_full_printf(u, *i, j);
+ if (q < 0)
goto fail;
}
*j = NULL;
- return r;
+ *ret = r;
+ return 0;
fail:
for (j--; j >= r; j--)
free(*j);
free(r);
-
- return NULL;
+ return q;
}
diff --git a/src/core/unit-printf.h b/src/core/unit-printf.h
index d2f4ccd178..51acad63e9 100644
--- a/src/core/unit-printf.h
+++ b/src/core/unit-printf.h
@@ -23,6 +23,6 @@
#include "unit.h"
-char *unit_name_printf(Unit *u, const char* text);
-char *unit_full_printf(Unit *u, const char *text);
-char **unit_full_printf_strv(Unit *u, char **l);
+int unit_name_printf(Unit *u, const char* text, char **ret);
+int unit_full_printf(Unit *u, const char *text, char **ret);
+int unit_full_printf_strv(Unit *u, char **l, char ***ret);
diff --git a/src/core/unit.c b/src/core/unit.c
index 9b36b225fa..4b9771076a 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -44,7 +44,6 @@
#include "special.h"
#include "cgroup-util.h"
#include "missing.h"
-#include "cgroup-attr.h"
#include "mkdir.h"
#include "label.h"
#include "fileio-label.h"
@@ -60,7 +59,9 @@ const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
[UNIT_AUTOMOUNT] = &automount_vtable,
[UNIT_SNAPSHOT] = &snapshot_vtable,
[UNIT_SWAP] = &swap_vtable,
- [UNIT_PATH] = &path_vtable
+ [UNIT_PATH] = &path_vtable,
+ [UNIT_SLICE] = &slice_vtable,
+ [UNIT_SCOPE] = &scope_vtable
};
Unit *unit_new(Manager *m, size_t size) {
@@ -188,7 +189,8 @@ fail:
}
int unit_choose_id(Unit *u, const char *name) {
- char *s, *t = NULL, *i;
+ char *s, *i;
+ _cleanup_free_ char *t = NULL;
int r;
assert(u);
@@ -207,7 +209,6 @@ int unit_choose_id(Unit *u, const char *name) {
/* Selects one of the names of this unit as the id */
s = set_get(u->names, (char*) name);
- free(t);
if (!s)
return -ENOENT;
@@ -230,8 +231,13 @@ int unit_set_description(Unit *u, const char *description) {
assert(u);
- if (!(s = strdup(description)))
- return -ENOMEM;
+ if (isempty(description))
+ s = NULL;
+ else {
+ s = strdup(description);
+ if (!s)
+ return -ENOMEM;
+ }
free(u->description);
u->description = s;
@@ -305,9 +311,6 @@ void unit_add_to_gc_queue(Unit *u) {
u->in_gc_queue = true;
u->manager->n_in_gc_queue ++;
-
- if (u->manager->gc_queue_timestamp <= 0)
- u->manager->gc_queue_timestamp = now(CLOCK_MONOTONIC);
}
void unit_add_to_dbus_queue(Unit *u) {
@@ -348,6 +351,57 @@ static void bidi_set_free(Unit *u, Set *s) {
set_free(s);
}
+static void unit_remove_transient(Unit *u) {
+ char **i;
+
+ assert(u);
+
+ if (!u->transient)
+ return;
+
+ if (u->fragment_path)
+ unlink(u->fragment_path);
+
+ STRV_FOREACH(i, u->dropin_paths) {
+ _cleanup_free_ char *p = NULL;
+ int r;
+
+ unlink(*i);
+
+ r = path_get_parent(*i, &p);
+ if (r >= 0)
+ rmdir(p);
+ }
+}
+
+static void unit_free_requires_mounts_for(Unit *u) {
+ char **j;
+
+ STRV_FOREACH(j, u->requires_mounts_for) {
+ char s[strlen(*j) + 1];
+
+ PATH_FOREACH_PREFIX_MORE(s, *j) {
+ char *y;
+ Set *x;
+
+ x = hashmap_get2(u->manager->units_requiring_mounts_for, s, (void**) &y);
+ if (!x)
+ continue;
+
+ set_remove(x, u);
+
+ if (set_isempty(x)) {
+ hashmap_remove(u->manager->units_requiring_mounts_for, y);
+ free(y);
+ set_free(x);
+ }
+ }
+ }
+
+ strv_free(u->requires_mounts_for);
+ u->requires_mounts_for = NULL;
+}
+
void unit_free(Unit *u) {
UnitDependency d;
Iterator i;
@@ -355,12 +409,17 @@ void unit_free(Unit *u) {
assert(u);
+ if (u->manager->n_reloading <= 0)
+ unit_remove_transient(u);
+
bus_unit_send_removed_signal(u);
if (u->load_state != UNIT_STUB)
if (UNIT_VTABLE(u)->done)
UNIT_VTABLE(u)->done(u);
+ unit_free_requires_mounts_for(u);
+
SET_FOREACH(t, u->names, i)
hashmap_remove_value(u->manager->units, t, u);
@@ -379,11 +438,6 @@ void unit_free(Unit *u) {
for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
bidi_set_free(u, u->dependencies[d]);
- if (u->requires_mounts_for) {
- LIST_REMOVE(Unit, has_requires_mounts_for, u->manager->has_requires_mounts_for, u);
- strv_free(u->requires_mounts_for);
- }
-
if (u->type != _UNIT_TYPE_INVALID)
LIST_REMOVE(Unit, units_by_type, u->manager->units_by_type[u->type], u);
@@ -401,8 +455,13 @@ void unit_free(Unit *u) {
u->manager->n_in_gc_queue--;
}
- cgroup_bonding_free_list(u->cgroup_bondings, u->manager->n_reloading <= 0);
- cgroup_attribute_free_list(u->cgroup_attributes);
+ if (u->in_cgroup_queue)
+ LIST_REMOVE(Unit, cgroup_queue, u->manager->cgroup_queue, u);
+
+ if (u->cgroup_path) {
+ hashmap_remove(u->manager->cgroup_unit, u->cgroup_path);
+ free(u->cgroup_path);
+ }
free(u->description);
strv_free(u->documentation);
@@ -415,6 +474,8 @@ void unit_free(Unit *u) {
condition_free_list(u->conditions);
+ unit_ref_unset(&u->slice);
+
while (u->refs)
unit_ref_unset(u->refs);
@@ -521,7 +582,7 @@ int unit_merge(Unit *u, Unit *other) {
return -EINVAL;
if (other->load_state != UNIT_STUB &&
- other->load_state != UNIT_ERROR)
+ other->load_state != UNIT_NOT_FOUND)
return -EEXIST;
if (other->job)
@@ -562,7 +623,7 @@ int unit_merge(Unit *u, Unit *other) {
int unit_merge_by_name(Unit *u, const char *name) {
Unit *other;
int r;
- char *s = NULL;
+ _cleanup_free_ char *s = NULL;
assert(u);
assert(name);
@@ -577,12 +638,12 @@ int unit_merge_by_name(Unit *u, const char *name) {
name = s;
}
- if (!(other = manager_get_unit(u->manager, name)))
+ other = manager_get_unit(u->manager, name);
+ if (!other)
r = unit_add_name(u, name);
else
r = unit_merge(u, other);
- free(s);
return r;
}
@@ -640,7 +701,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
char *t, **j;
UnitDependency d;
Iterator i;
- char *p2;
+ _cleanup_free_ char *p2 = NULL;
const char *prefix2;
char
timestamp1[FORMAT_TIMESTAMP_MAX],
@@ -669,7 +730,12 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
"%s\tActive Exit Timestamp: %s\n"
"%s\tInactive Enter Timestamp: %s\n"
"%s\tGC Check Good: %s\n"
- "%s\tNeed Daemon Reload: %s\n",
+ "%s\tNeed Daemon Reload: %s\n"
+ "%s\tTransient: %s\n"
+ "%s\tSlice: %s\n"
+ "%s\tCGroup: %s\n"
+ "%s\tCGroup realized: %s\n"
+ "%s\tCGroup mask: 0x%x\n",
prefix, u->id,
prefix, unit_description(u),
prefix, strna(u->instance),
@@ -680,7 +746,12 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
prefix, strna(format_timestamp(timestamp3, sizeof(timestamp3), u->active_exit_timestamp.realtime)),
prefix, strna(format_timestamp(timestamp4, sizeof(timestamp4), u->inactive_enter_timestamp.realtime)),
prefix, yes_no(unit_check_gc(u)),
- prefix, yes_no(unit_need_daemon_reload(u)));
+ prefix, yes_no(unit_need_daemon_reload(u)),
+ prefix, yes_no(u->transient),
+ prefix, strna(unit_slice_name(u)),
+ prefix, strna(u->cgroup_path),
+ prefix, yes_no(u->cgroup_realized),
+ prefix, u->cgroup_mask);
SET_FOREACH(t, u->names, i)
fprintf(f, "%s\tName: %s\n", prefix, t);
@@ -730,8 +801,6 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
}
if (u->load_state == UNIT_LOADED) {
- CGroupBonding *b;
- CGroupAttribute *a;
fprintf(f,
"%s\tStopWhenUnneeded: %s\n"
@@ -749,20 +818,6 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
prefix, yes_no(u->ignore_on_isolate),
prefix, yes_no(u->ignore_on_snapshot));
- LIST_FOREACH(by_unit, b, u->cgroup_bondings)
- fprintf(f, "%s\tControlGroup: %s:%s\n",
- prefix, b->controller, b->path);
-
- LIST_FOREACH(by_unit, a, u->cgroup_attributes) {
- _cleanup_free_ char *v = NULL;
-
- if (a->semantics && a->semantics->map_write)
- a->semantics->map_write(a->semantics, a->value, &v);
-
- fprintf(f, "%s\tControlGroupAttribute: %s %s \"%s\"\n",
- prefix, a->controller, a->name, v ? v : a->value);
- }
-
if (UNIT_VTABLE(u)->dump)
UNIT_VTABLE(u)->dump(u, f, prefix2);
@@ -780,7 +835,6 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
if (u->nop_job)
job_dump(u->nop_job, f, prefix2);
- free(p2);
}
/* Common implementation for multiple backends */
@@ -790,14 +844,16 @@ int unit_load_fragment_and_dropin(Unit *u) {
assert(u);
/* Load a .service file */
- if ((r = unit_load_fragment(u)) < 0)
+ r = unit_load_fragment(u);
+ if (r < 0)
return r;
if (u->load_state == UNIT_STUB)
return -ENOENT;
/* Load drop-in directory data */
- if ((r = unit_load_dropin(unit_follow_merge(u))) < 0)
+ r = unit_load_dropin(unit_follow_merge(u));
+ if (r < 0)
return r;
return 0;
@@ -813,14 +869,16 @@ int unit_load_fragment_and_dropin_optional(Unit *u) {
* something can be loaded or not doesn't matter. */
/* Load a .service file */
- if ((r = unit_load_fragment(u)) < 0)
+ r = unit_load_fragment(u);
+ if (r < 0)
return r;
if (u->load_state == UNIT_STUB)
u->load_state = UNIT_LOADED;
/* Load drop-in directory data */
- if ((r = unit_load_dropin(unit_follow_merge(u))) < 0)
+ r = unit_load_dropin(unit_follow_merge(u));
+ if (r < 0)
return r;
return 0;
@@ -853,6 +911,7 @@ int unit_add_default_target_dependency(Unit *u, Unit *target) {
}
static int unit_add_default_dependencies(Unit *u) {
+
static const UnitDependency deps[] = {
UNIT_REQUIRED_BY,
UNIT_REQUIRED_BY_OVERRIDABLE,
@@ -868,9 +927,21 @@ static int unit_add_default_dependencies(Unit *u) {
assert(u);
for (k = 0; k < ELEMENTSOF(deps); k++)
- SET_FOREACH(target, u->dependencies[deps[k]], i)
- if ((r = unit_add_default_target_dependency(u, target)) < 0)
+ SET_FOREACH(target, u->dependencies[deps[k]], i) {
+ r = unit_add_default_target_dependency(u, target);
+ if (r < 0)
return r;
+ }
+
+ if (u->default_dependencies && unit_get_cgroup_context(u)) {
+ if (UNIT_ISSET(u->slice))
+ r = unit_add_two_dependencies(u, UNIT_AFTER, UNIT_WANTS, UNIT_DEREF(u->slice), true);
+ else
+ r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_WANTS, SPECIAL_ROOT_SLICE, NULL, true);
+
+ if (r < 0)
+ return r;
+ }
return 0;
}
@@ -891,34 +962,38 @@ int unit_load(Unit *u) {
if (u->load_state != UNIT_STUB)
return 0;
- if (UNIT_VTABLE(u)->load)
- if ((r = UNIT_VTABLE(u)->load(u)) < 0)
+ if (UNIT_VTABLE(u)->load) {
+ r = UNIT_VTABLE(u)->load(u);
+ if (r < 0)
goto fail;
+ }
if (u->load_state == UNIT_STUB) {
r = -ENOENT;
goto fail;
}
- if (u->load_state == UNIT_LOADED &&
- u->default_dependencies)
- if ((r = unit_add_default_dependencies(u)) < 0)
- goto fail;
-
if (u->load_state == UNIT_LOADED) {
+
+ if (u->default_dependencies) {
+ r = unit_add_default_dependencies(u);
+ if (r < 0)
+ goto fail;
+ }
+
r = unit_add_mount_links(u);
if (r < 0)
- return r;
- }
+ goto fail;
- if (u->on_failure_isolate &&
- set_size(u->dependencies[UNIT_ON_FAILURE]) > 1) {
+ if (u->on_failure_isolate &&
+ set_size(u->dependencies[UNIT_ON_FAILURE]) > 1) {
- log_error_unit(u->id,
- "More than one OnFailure= dependencies specified for %s but OnFailureIsolate= enabled. Refusing.", u->id);
+ log_error_unit(u->id,
+ "More than one OnFailure= dependencies specified for %s but OnFailureIsolate= enabled. Refusing.", u->id);
- r = -EINVAL;
- goto fail;
+ r = -EINVAL;
+ goto fail;
+ }
}
assert((u->load_state != UNIT_MERGED) == !u->merged_into);
@@ -929,7 +1004,7 @@ int unit_load(Unit *u) {
return 0;
fail:
- u->load_state = UNIT_ERROR;
+ u->load_state = u->load_state == UNIT_STUB ? UNIT_NOT_FOUND : UNIT_ERROR;
u->load_error = r;
unit_add_to_dbus_queue(u);
unit_add_to_gc_queue(u);
@@ -944,7 +1019,7 @@ bool unit_condition_test(Unit *u) {
assert(u);
dual_timestamp_get(&u->condition_timestamp);
- u->condition_result = condition_test_list(u->conditions);
+ u->condition_result = condition_test_list(u->id, u->conditions);
return u->condition_result;
}
@@ -1073,7 +1148,8 @@ int unit_start(Unit *u) {
}
/* Forward to the main object, if we aren't it. */
- if ((following = unit_following(u))) {
+ following = unit_following(u);
+ if (following) {
log_debug_unit(u->id, "Redirecting start request from %s to %s.",
u->id, following->id);
return unit_start(following);
@@ -1368,15 +1444,19 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
}
if (UNIT_IS_INACTIVE_OR_FAILED(ns))
- cgroup_bonding_trim_list(u->cgroup_bondings, true);
+ unit_destroy_cgroup(u);
if (UNIT_IS_INACTIVE_OR_FAILED(os) != UNIT_IS_INACTIVE_OR_FAILED(ns)) {
ExecContext *ec = unit_get_exec_context(u);
if (ec && exec_context_may_touch_console(ec)) {
- if (UNIT_IS_INACTIVE_OR_FAILED(ns))
- m->n_on_console--;
- else
- m->n_on_console++;
+ if (UNIT_IS_INACTIVE_OR_FAILED(ns)) {
+ m->n_on_console --;
+
+ if (m->n_on_console == 0)
+ /* unset no_console_output flag, since the console is free */
+ m->no_console_output = 0;
+ } else
+ m->n_on_console ++;
}
}
@@ -1857,7 +1937,7 @@ int unit_add_dependency_by_name(Unit *u, UnitDependency d, const char *name, con
int unit_add_two_dependencies_by_name(Unit *u, UnitDependency d, UnitDependency e, const char *name, const char *path, bool add_reference) {
Unit *other;
int r;
- char *s;
+ _cleanup_free_ char *s = NULL;
assert(u);
assert(name || path);
@@ -1866,19 +1946,17 @@ int unit_add_two_dependencies_by_name(Unit *u, UnitDependency d, UnitDependency
return -ENOMEM;
if ((r = manager_load_unit(u->manager, name, path, NULL, &other)) < 0)
- goto finish;
+ return r;
r = unit_add_two_dependencies(u, d, e, other, add_reference);
-finish:
- free(s);
return r;
}
int unit_add_dependency_by_name_inverse(Unit *u, UnitDependency d, const char *name, const char *path, bool add_reference) {
Unit *other;
int r;
- char *s;
+ _cleanup_free_ char *s = NULL;
assert(u);
assert(name || path);
@@ -1887,19 +1965,17 @@ int unit_add_dependency_by_name_inverse(Unit *u, UnitDependency d, const char *n
return -ENOMEM;
if ((r = manager_load_unit(u->manager, name, path, NULL, &other)) < 0)
- goto finish;
+ return r;
r = unit_add_dependency(other, d, u, add_reference);
-finish:
- free(s);
return r;
}
int unit_add_two_dependencies_by_name_inverse(Unit *u, UnitDependency d, UnitDependency e, const char *name, const char *path, bool add_reference) {
Unit *other;
int r;
- char *s;
+ _cleanup_free_ char *s = NULL;
assert(u);
assert(name || path);
@@ -1908,13 +1984,11 @@ int unit_add_two_dependencies_by_name_inverse(Unit *u, UnitDependency d, UnitDep
return -ENOMEM;
if ((r = manager_load_unit(u->manager, name, path, NULL, &other)) < 0)
- goto finish;
+ return r;
if ((r = unit_add_two_dependencies(other, d, e, u, add_reference)) < 0)
- goto finish;
+ return r;
-finish:
- free(s);
return r;
}
@@ -1938,351 +2012,91 @@ char *unit_dbus_path(Unit *u) {
return unit_dbus_path_from_name(u->id);
}
-static int unit_add_cgroup(Unit *u, CGroupBonding *b) {
+char *unit_default_cgroup_path(Unit *u) {
+ _cleanup_free_ char *escaped = NULL, *slice = NULL;
int r;
assert(u);
- assert(b);
-
- assert(b->path);
- if (!b->controller) {
- b->controller = strdup(SYSTEMD_CGROUP_CONTROLLER);
- if (!b->controller)
- return log_oom();
-
- b->ours = true;
- }
+ if (unit_has_name(u, SPECIAL_ROOT_SLICE))
+ return strdup(u->manager->cgroup_root);
- /* Ensure this hasn't been added yet */
- assert(!b->unit);
-
- if (streq(b->controller, SYSTEMD_CGROUP_CONTROLLER)) {
- CGroupBonding *l;
-
- l = hashmap_get(u->manager->cgroup_bondings, b->path);
- LIST_PREPEND(CGroupBonding, by_path, l, b);
-
- r = hashmap_replace(u->manager->cgroup_bondings, b->path, l);
- if (r < 0) {
- LIST_REMOVE(CGroupBonding, by_path, l, b);
- return r;
- }
+ if (UNIT_ISSET(u->slice) && !unit_has_name(UNIT_DEREF(u->slice), SPECIAL_ROOT_SLICE)) {
+ r = cg_slice_to_path(UNIT_DEREF(u->slice)->id, &slice);
+ if (r < 0)
+ return NULL;
}
- LIST_PREPEND(CGroupBonding, by_unit, u->cgroup_bondings, b);
- b->unit = u;
-
- return 0;
-}
-
-char *unit_default_cgroup_path(Unit *u) {
- _cleanup_free_ char *escaped_instance = NULL;
-
- assert(u);
-
- escaped_instance = cg_escape(u->id);
- if (!escaped_instance)
+ escaped = cg_escape(u->id);
+ if (!escaped)
return NULL;
- if (u->instance) {
- _cleanup_free_ char *t = NULL, *escaped_template = NULL;
-
- t = unit_name_template(u->id);
- if (!t)
- return NULL;
-
- escaped_template = cg_escape(t);
- if (!escaped_template)
- return NULL;
-
- return strjoin(u->manager->cgroup_hierarchy, "/", escaped_template, "/", escaped_instance, NULL);
- } else
- return strjoin(u->manager->cgroup_hierarchy, "/", escaped_instance, NULL);
+ if (slice)
+ return strjoin(u->manager->cgroup_root, "/", slice, "/", escaped, NULL);
+ else
+ return strjoin(u->manager->cgroup_root, "/", escaped, NULL);
}
-int unit_add_cgroup_from_text(Unit *u, const char *name, bool overwrite, CGroupBonding **ret) {
- char *controller = NULL, *path = NULL;
- CGroupBonding *b = NULL;
- bool ours = false;
+int unit_add_default_slice(Unit *u) {
+ _cleanup_free_ char *b = NULL;
+ const char *slice_name;
+ Unit *slice;
int r;
assert(u);
- assert(name);
-
- r = cg_split_spec(name, &controller, &path);
- if (r < 0)
- return r;
-
- if (!path) {
- path = unit_default_cgroup_path(u);
- ours = true;
- }
-
- if (!controller) {
- controller = strdup("systemd");
- ours = true;
- }
-
- if (!path || !controller) {
- free(path);
- free(controller);
- return log_oom();
- }
- if (streq(controller, "systemd")) {
- /* Within the systemd unit hierarchy we do not allow changes. */
- if (path_startswith(path, "/system")) {
- log_warning_unit(u->id, "Manipulating the systemd:/system cgroup hierarchy is not permitted.");
- free(path);
- free(controller);
- return -EPERM;
- }
- }
-
- b = cgroup_bonding_find_list(u->cgroup_bondings, controller);
- if (b) {
- if (streq(path, b->path)) {
- free(path);
- free(controller);
-
- if (ret)
- *ret = b;
- return 0;
- }
-
- if (overwrite && !b->essential) {
- free(controller);
-
- free(b->path);
- b->path = path;
-
- b->ours = ours;
- b->realized = false;
-
- if (ret)
- *ret = b;
-
- return 1;
- }
-
- r = -EEXIST;
- b = NULL;
- goto fail;
- }
-
- b = new0(CGroupBonding, 1);
- if (!b) {
- r = -ENOMEM;
- goto fail;
- }
-
- b->controller = controller;
- b->path = path;
- b->ours = ours;
- b->essential = streq(controller, SYSTEMD_CGROUP_CONTROLLER);
-
- r = unit_add_cgroup(u, b);
- if (r < 0)
- goto fail;
-
- if (ret)
- *ret = b;
-
- return 1;
-
-fail:
- free(path);
- free(controller);
- free(b);
-
- return r;
-}
-
-static int unit_add_one_default_cgroup(Unit *u, const char *controller) {
- CGroupBonding *b = NULL;
- int r = -ENOMEM;
-
- assert(u);
-
- if (controller && !cg_controller_is_valid(controller, true))
- return -EINVAL;
-
- if (!controller)
- controller = SYSTEMD_CGROUP_CONTROLLER;
-
- if (cgroup_bonding_find_list(u->cgroup_bondings, controller))
+ if (UNIT_ISSET(u->slice))
return 0;
- b = new0(CGroupBonding, 1);
- if (!b)
- return -ENOMEM;
-
- b->controller = strdup(controller);
- if (!b->controller)
- goto fail;
-
- b->path = unit_default_cgroup_path(u);
- if (!b->path)
- goto fail;
-
- b->ours = true;
- b->essential = streq(controller, SYSTEMD_CGROUP_CONTROLLER);
-
- r = unit_add_cgroup(u, b);
- if (r < 0)
- goto fail;
+ if (!unit_get_cgroup_context(u))
+ return 0;
- return 1;
+ if (u->instance) {
+ _cleanup_free_ char *prefix = NULL, *escaped = NULL;
-fail:
- free(b->path);
- free(b->controller);
- free(b);
+ /* Implicitly place all instantiated units in their
+ * own per-template slice */
- return r;
-}
-
-int unit_add_default_cgroups(Unit *u) {
- CGroupAttribute *a;
- char **c;
- int r;
+ prefix = unit_name_to_prefix(u->id);
+ if (!prefix)
+ return -ENOMEM;
- assert(u);
+ /* The prefix is already escaped, but it might include
+ * "-" which has a special meaning for slice units,
+ * hence escape it here extra. */
+ escaped = strreplace(prefix, "-", "\\x2d");
+ if (!escaped)
+ return -ENOMEM;
- /* Adds in the default cgroups, if they weren't specified
- * otherwise. */
+ if (u->manager->running_as == SYSTEMD_SYSTEM)
+ b = strjoin("system-", escaped, ".slice", NULL);
+ else
+ b = strappend(escaped, ".slice");
+ if (!b)
+ return -ENOMEM;
- if (!u->manager->cgroup_hierarchy)
- return 0;
+ slice_name = b;
+ } else
+ slice_name =
+ u->manager->running_as == SYSTEMD_SYSTEM
+ ? SPECIAL_SYSTEM_SLICE
+ : SPECIAL_ROOT_SLICE;
- r = unit_add_one_default_cgroup(u, NULL);
+ r = manager_load_unit(u->manager, slice_name, NULL, NULL, &slice);
if (r < 0)
return r;
- STRV_FOREACH(c, u->manager->default_controllers)
- unit_add_one_default_cgroup(u, *c);
-
- LIST_FOREACH(by_unit, a, u->cgroup_attributes)
- unit_add_one_default_cgroup(u, a->controller);
-
+ unit_ref_set(&u->slice, slice);
return 0;
}
-CGroupBonding* unit_get_default_cgroup(Unit *u) {
- assert(u);
-
- return cgroup_bonding_find_list(u->cgroup_bondings, NULL);
-}
-
-int unit_add_cgroup_attribute(
- Unit *u,
- const CGroupSemantics *semantics,
- const char *controller,
- const char *name,
- const char *value,
- CGroupAttribute **ret) {
-
- _cleanup_free_ char *c = NULL;
- CGroupAttribute *a;
- int r;
-
+const char *unit_slice_name(Unit *u) {
assert(u);
- assert(value);
-
- if (semantics) {
- /* Semantics always take precedence */
- if (semantics->name)
- name = semantics->name;
-
- if (semantics->controller)
- controller = semantics->controller;
- }
-
- if (!name)
- return -EINVAL;
-
- if (!controller) {
- r = cg_controller_from_attr(name, &c);
- if (r < 0)
- return -EINVAL;
-
- controller = c;
- }
-
- if (!controller ||
- streq(controller, SYSTEMD_CGROUP_CONTROLLER) ||
- streq(controller, "systemd"))
- return -EINVAL;
-
- if (!filename_is_safe(name))
- return -EINVAL;
-
- if (!cg_controller_is_valid(controller, false))
- return -EINVAL;
-
- /* Check if this attribute already exists. Note that we will
- * explicitly check for the value here too, as there are
- * attributes which accept multiple values. */
- a = cgroup_attribute_find_list(u->cgroup_attributes, controller, name);
- if (a) {
- if (streq(value, a->value)) {
- /* Exactly the same value is always OK, let's ignore this */
- if (ret)
- *ret = a;
-
- return 0;
- }
-
- if (semantics && !semantics->multiple) {
- char *v;
-
- /* If this is a single-item entry, we can
- * simply patch the existing attribute */
-
- v = strdup(value);
- if (!v)
- return -ENOMEM;
-
- free(a->value);
- a->value = v;
-
- if (ret)
- *ret = a;
- return 1;
- }
- }
- a = new0(CGroupAttribute, 1);
- if (!a)
- return -ENOMEM;
-
- if (c) {
- a->controller = c;
- c = NULL;
- } else
- a->controller = strdup(controller);
-
- a->name = strdup(name);
- a->value = strdup(value);
-
- if (!a->controller || !a->name || !a->value) {
- free(a->controller);
- free(a->name);
- free(a->value);
- free(a);
- return -ENOMEM;
- }
-
- a->semantics = semantics;
- a->unit = u;
-
- LIST_PREPEND(CGroupAttribute, by_unit, u->cgroup_attributes, a);
-
- if (ret)
- *ret = a;
+ if (!UNIT_ISSET(u->slice))
+ return NULL;
- return 1;
+ return UNIT_DEREF(u->slice)->id;
}
int unit_load_related_unit(Unit *u, const char *type, Unit **_found) {
@@ -2359,7 +2173,8 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
if (!unit_can_serialize(u))
return 0;
- if ((r = UNIT_VTABLE(u)->serialize(u, f, fds)) < 0)
+ r = UNIT_VTABLE(u)->serialize(u, f, fds);
+ if (r < 0)
return r;
@@ -2384,6 +2199,11 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
if (dual_timestamp_is_set(&u->condition_timestamp))
unit_serialize_item(u, f, "condition-result", yes_no(u->condition_result));
+ unit_serialize_item(u, f, "transient", yes_no(u->transient));
+
+ if (u->cgroup_path)
+ unit_serialize_item(u, f, "cgroup", u->cgroup_path);
+
/* End marker */
fputc('\n', f);
return 0;
@@ -2506,22 +2326,47 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
} else if (streq(l, "condition-result")) {
int b;
- if ((b = parse_boolean(v)) < 0)
+ b = parse_boolean(v);
+ if (b < 0)
log_debug("Failed to parse condition result value %s", v);
else
u->condition_result = b;
continue;
+
+ } else if (streq(l, "transient")) {
+ int b;
+
+ b = parse_boolean(v);
+ if (b < 0)
+ log_debug("Failed to parse transient bool %s", v);
+ else
+ u->transient = b;
+
+ continue;
+ } else if (streq(l, "cgroup")) {
+ char *s;
+
+ s = strdup(v);
+ if (!s)
+ return -ENOMEM;
+
+ free(u->cgroup_path);
+ u->cgroup_path = s;
+
+ assert(hashmap_put(u->manager->cgroup_unit, s, u) == 1);
+ continue;
}
- if ((r = UNIT_VTABLE(u)->deserialize_item(u, l, v, fds)) < 0)
+ r = UNIT_VTABLE(u)->deserialize_item(u, l, v, fds);
+ if (r < 0)
return r;
}
}
int unit_add_node_link(Unit *u, const char *what, bool wants) {
Unit *device;
- char *e;
+ _cleanup_free_ char *e = NULL;
int r;
assert(u);
@@ -2539,7 +2384,7 @@ int unit_add_node_link(Unit *u, const char *what, bool wants) {
return -ENOMEM;
r = manager_load_unit(u->manager, e, NULL, NULL, &device);
- free(e);
+
if (r < 0)
return r;
@@ -2714,6 +2559,34 @@ int unit_kill(Unit *u, KillWho w, int signo, DBusError *error) {
return UNIT_VTABLE(u)->kill(u, w, signo, error);
}
+static Set *unit_pid_set(pid_t main_pid, pid_t control_pid) {
+ Set *pid_set;
+ int r;
+
+ pid_set = set_new(trivial_hash_func, trivial_compare_func);
+ if (!pid_set)
+ return NULL;
+
+ /* Exclude the main/control pids from being killed via the cgroup */
+ if (main_pid > 0) {
+ r = set_put(pid_set, LONG_TO_PTR(main_pid));
+ if (r < 0)
+ goto fail;
+ }
+
+ if (control_pid > 0) {
+ r = set_put(pid_set, LONG_TO_PTR(control_pid));
+ if (r < 0)
+ goto fail;
+ }
+
+ return pid_set;
+
+fail:
+ set_free(pid_set);
+ return NULL;
+}
+
int unit_kill_common(
Unit *u,
KillWho who,
@@ -2750,28 +2623,16 @@ int unit_kill_common(
if (kill(main_pid, signo) < 0)
r = -errno;
- if (who == KILL_ALL) {
+ if (who == KILL_ALL && u->cgroup_path) {
_cleanup_set_free_ Set *pid_set = NULL;
int q;
- pid_set = set_new(trivial_hash_func, trivial_compare_func);
+ /* Exclude the main/control pids from being killed via the cgroup */
+ pid_set = unit_pid_set(main_pid, control_pid);
if (!pid_set)
return -ENOMEM;
- /* Exclude the control/main pid from being killed via the cgroup */
- if (control_pid > 0) {
- q = set_put(pid_set, LONG_TO_PTR(control_pid));
- if (q < 0)
- return q;
- }
-
- if (main_pid > 0) {
- q = set_put(pid_set, LONG_TO_PTR(main_pid));
- if (q < 0)
- return q;
- }
-
- q = cgroup_bonding_kill_list(u->cgroup_bondings, signo, false, false, pid_set, NULL);
+ q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, false, true, false, pid_set);
if (q < 0 && q != -EAGAIN && q != -ESRCH && q != -ENOENT)
r = q;
}
@@ -2823,40 +2684,39 @@ void unit_ref_unset(UnitRef *ref) {
ref->unit = NULL;
}
-int unit_add_one_mount_link(Unit *u, Mount *m) {
+int unit_add_mount_links(Unit *u) {
char **i;
+ int r;
assert(u);
- assert(m);
-
- if (u->load_state != UNIT_LOADED ||
- UNIT(m)->load_state != UNIT_LOADED)
- return 0;
STRV_FOREACH(i, u->requires_mounts_for) {
+ char prefix[strlen(*i) + 1];
- if (UNIT(m) == u)
- continue;
+ PATH_FOREACH_PREFIX_MORE(prefix, *i) {
+ Unit *m;
- if (!path_startswith(*i, m->where))
- continue;
-
- return unit_add_two_dependencies(u, UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true);
- }
+ r = manager_get_unit_by_path(u->manager, prefix, ".mount", &m);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ continue;
+ if (m == u)
+ continue;
- return 0;
-}
+ if (m->load_state != UNIT_LOADED)
+ continue;
-int unit_add_mount_links(Unit *u) {
- Unit *other;
- int r;
-
- assert(u);
+ r = unit_add_dependency(u, UNIT_AFTER, m, true);
+ if (r < 0)
+ return r;
- LIST_FOREACH(units_by_type, other, u->manager->units_by_type[UNIT_MOUNT]) {
- r = unit_add_one_mount_link(u, MOUNT(other));
- if (r < 0)
- return r;
+ if (m->fragment_path) {
+ r = unit_add_dependency(u, UNIT_REQUIRES, m, true);
+ if (r < 0)
+ return r;
+ }
+ }
}
return 0;
@@ -2870,7 +2730,6 @@ int unit_exec_context_defaults(Unit *u, ExecContext *c) {
assert(c);
/* This only copies in the ones that need memory */
-
for (i = 0; i < RLIMIT_NLIMITS; i++)
if (u->manager->rlimit[i] && !c->rlimit[i]) {
c->rlimit[i] = newdup(struct rlimit, u->manager->rlimit[i], 1);
@@ -2900,7 +2759,18 @@ ExecContext *unit_get_exec_context(Unit *u) {
return (ExecContext*) ((uint8_t*) u + offset);
}
-static int drop_in_file(Unit *u, bool runtime, const char *name, char **_p, char **_q) {
+CGroupContext *unit_get_cgroup_context(Unit *u) {
+ size_t offset;
+
+ offset = UNIT_VTABLE(u)->cgroup_context_offset;
+ if (offset <= 0)
+ return NULL;
+
+ return (CGroupContext*) ((uint8_t*) u + offset);
+}
+
+static int drop_in_file(Unit *u, UnitSetPropertiesMode mode, const char *name, char **_p, char **_q) {
+ _cleanup_free_ char *b = NULL;
char *p, *q;
int r;
@@ -2908,11 +2778,13 @@ static int drop_in_file(Unit *u, bool runtime, const char *name, char **_p, char
assert(name);
assert(_p);
assert(_q);
+ assert(mode & (UNIT_PERSISTENT|UNIT_RUNTIME));
- if (u->manager->running_as == SYSTEMD_USER && runtime)
- return -ENOTSUP;
+ b = xescape(name, "/.");
+ if (!b)
+ return -ENOMEM;
- if (!filename_is_safe(name))
+ if (!filename_is_safe(b))
return -EINVAL;
if (u->manager->running_as == SYSTEMD_USER) {
@@ -2925,14 +2797,14 @@ static int drop_in_file(Unit *u, bool runtime, const char *name, char **_p, char
return -ENOENT;
p = strjoin(c, "/", u->id, ".d", NULL);
- } else if (runtime)
- p = strjoin("/run/systemd/system/", u->id, ".d", NULL);
- else
+ } else if (mode & UNIT_PERSISTENT)
p = strjoin("/etc/systemd/system/", u->id, ".d", NULL);
+ else
+ p = strjoin("/run/systemd/system/", u->id, ".d", NULL);
if (!p)
return -ENOMEM;
- q = strjoin(p, "/50-", name, ".conf", NULL);
+ q = strjoin(p, "/90-", b, ".conf", NULL);
if (!q) {
free(p);
return -ENOMEM;
@@ -2943,13 +2815,18 @@ static int drop_in_file(Unit *u, bool runtime, const char *name, char **_p, char
return 0;
}
-int unit_write_drop_in(Unit *u, bool runtime, const char *name, const char *data) {
+int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) {
_cleanup_free_ char *p = NULL, *q = NULL;
int r;
assert(u);
+ assert(name);
+ assert(data);
+
+ if (!(mode & (UNIT_PERSISTENT|UNIT_RUNTIME)))
+ return 0;
- r = drop_in_file(u, runtime, name, &p, &q);
+ r = drop_in_file(u, mode, name, &p, &q);
if (r < 0)
return r;
@@ -2957,22 +2834,126 @@ int unit_write_drop_in(Unit *u, bool runtime, const char *name, const char *data
return write_string_file_atomic_label(q, data);
}
-int unit_remove_drop_in(Unit *u, bool runtime, const char *name) {
+int unit_write_drop_in_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) {
+ _cleanup_free_ char *p = NULL;
+ va_list ap;
+ int r;
+
+ assert(u);
+ assert(name);
+ assert(format);
+
+ if (!(mode & (UNIT_PERSISTENT|UNIT_RUNTIME)))
+ return 0;
+
+ va_start(ap, format);
+ r = vasprintf(&p, format, ap);
+ va_end(ap);
+
+ if (r < 0)
+ return -ENOMEM;
+
+ return unit_write_drop_in(u, mode, name, p);
+}
+
+int unit_write_drop_in_private(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) {
+ _cleanup_free_ char *ndata = NULL;
+
+ assert(u);
+ assert(name);
+ assert(data);
+
+ if (!UNIT_VTABLE(u)->private_section)
+ return -EINVAL;
+
+ if (!(mode & (UNIT_PERSISTENT|UNIT_RUNTIME)))
+ return 0;
+
+ ndata = strjoin("[", UNIT_VTABLE(u)->private_section, "]\n", data, NULL);
+ if (!ndata)
+ return -ENOMEM;
+
+ return unit_write_drop_in(u, mode, name, ndata);
+}
+
+int unit_write_drop_in_private_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) {
+ _cleanup_free_ char *p = NULL;
+ va_list ap;
+ int r;
+
+ assert(u);
+ assert(name);
+ assert(format);
+
+ if (!(mode & (UNIT_PERSISTENT|UNIT_RUNTIME)))
+ return 0;
+
+ va_start(ap, format);
+ r = vasprintf(&p, format, ap);
+ va_end(ap);
+
+ if (r < 0)
+ return -ENOMEM;
+
+ return unit_write_drop_in_private(u, mode, name, p);
+}
+
+int unit_remove_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name) {
_cleanup_free_ char *p = NULL, *q = NULL;
int r;
assert(u);
- r = drop_in_file(u, runtime, name, &p, &q);
+ if (!(mode & (UNIT_PERSISTENT|UNIT_RUNTIME)))
+ return 0;
+
+ r = drop_in_file(u, mode, name, &p, &q);
if (unlink(q) < 0)
- r = -errno;
+ r = errno == ENOENT ? 0 : -errno;
else
- r = 0;
+ r = 1;
rmdir(p);
return r;
}
+int unit_make_transient(Unit *u) {
+ int r;
+
+ assert(u);
+
+ u->load_state = UNIT_STUB;
+ u->load_error = 0;
+ u->transient = true;
+
+ free(u->fragment_path);
+ u->fragment_path = NULL;
+
+ if (u->manager->running_as == SYSTEMD_USER) {
+ _cleanup_free_ char *c = NULL;
+
+ r = user_config_home(&c);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -ENOENT;
+
+ u->fragment_path = strjoin(c, "/", u->id, NULL);
+ if (!u->fragment_path)
+ return -ENOMEM;
+
+ mkdir_p(c, 0755);
+ } else {
+ u->fragment_path = strappend("/run/systemd/system/", u->id);
+ if (!u->fragment_path)
+ return -ENOMEM;
+
+ mkdir_p("/run/systemd/system", 0755);
+ }
+
+ return write_string_file_atomic_label(u->fragment_path, "# Transient stub");
+}
+
int unit_kill_context(
Unit *u,
KillContext *c,
@@ -3000,8 +2981,12 @@ int unit_kill_context(
log_warning_unit(u->id, "Failed to kill main process %li (%s): %s",
(long) main_pid, strna(comm), strerror(-r));
- } else
+ } else {
wait_for_exit = !main_pid_alien;
+
+ if (c->send_sighup)
+ kill(main_pid, SIGHUP);
+ }
}
if (control_pid > 0) {
@@ -3014,41 +2999,123 @@ int unit_kill_context(
log_warning_unit(u->id,
"Failed to kill control process %li (%s): %s",
(long) control_pid, strna(comm), strerror(-r));
- } else
+ } else {
wait_for_exit = true;
+
+ if (c->send_sighup)
+ kill(control_pid, SIGHUP);
+ }
}
- if (c->kill_mode == KILL_CONTROL_GROUP) {
+ if (c->kill_mode == KILL_CONTROL_GROUP && u->cgroup_path) {
_cleanup_set_free_ Set *pid_set = NULL;
- pid_set = set_new(trivial_hash_func, trivial_compare_func);
+ /* Exclude the main/control pids from being killed via the cgroup */
+ pid_set = unit_pid_set(main_pid, control_pid);
if (!pid_set)
return -ENOMEM;
- /* Exclude the main/control pids from being killed via the cgroup */
- if (main_pid > 0) {
- r = set_put(pid_set, LONG_TO_PTR(main_pid));
- if (r < 0)
- return r;
- }
-
- if (control_pid > 0) {
- r = set_put(pid_set, LONG_TO_PTR(control_pid));
- if (r < 0)
- return r;
- }
-
- r = cgroup_bonding_kill_list(u->cgroup_bondings, sig, true, false, pid_set, NULL);
+ r = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, sig, true, true, false, pid_set);
if (r < 0) {
if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
log_warning_unit(u->id, "Failed to kill control group: %s", strerror(-r));
- } else if (r > 0)
+ } else if (r > 0) {
wait_for_exit = true;
+ if (c->send_sighup) {
+ set_free(pid_set);
+
+ pid_set = unit_pid_set(main_pid, control_pid);
+ if (!pid_set)
+ return -ENOMEM;
+
+ cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, SIGHUP, true, true, false, pid_set);
+ }
+ }
}
return wait_for_exit;
}
+int unit_require_mounts_for(Unit *u, const char *path) {
+ char prefix[strlen(path) + 1], *p;
+ int r;
+
+ assert(u);
+ assert(path);
+
+ /* Registers a unit for requiring a certain path and all its
+ * prefixes. We keep a simple array of these paths in the
+ * unit, since its usually short. However, we build a prefix
+ * table for all possible prefixes so that new appearing mount
+ * units can easily determine which units to make themselves a
+ * dependency of. */
+
+ p = strdup(path);
+ if (!p)
+ return -ENOMEM;
+
+ path_kill_slashes(p);
+
+ if (!path_is_absolute(p)) {
+ free(p);
+ return -EINVAL;
+ }
+
+ if (!path_is_safe(p)) {
+ free(p);
+ return -EPERM;
+ }
+
+ if (strv_contains(u->requires_mounts_for, p)) {
+ free(p);
+ return 0;
+ }
+
+ r = strv_push(&u->requires_mounts_for, p);
+ if (r < 0) {
+ free(p);
+ return r;
+ }
+
+ PATH_FOREACH_PREFIX_MORE(prefix, p) {
+ Set *x;
+
+ x = hashmap_get(u->manager->units_requiring_mounts_for, prefix);
+ if (!x) {
+ char *q;
+
+ if (!u->manager->units_requiring_mounts_for) {
+ u->manager->units_requiring_mounts_for = hashmap_new(string_hash_func, string_compare_func);
+ if (!u->manager->units_requiring_mounts_for)
+ return -ENOMEM;
+ }
+
+ q = strdup(prefix);
+ if (!q)
+ return -ENOMEM;
+
+ x = set_new(NULL, NULL);
+ if (!x) {
+ free(q);
+ return -ENOMEM;
+ }
+
+ r = hashmap_put(u->manager->units_requiring_mounts_for, q, x);
+ if (r < 0) {
+ free(q);
+ set_free(x);
+ return r;
+ }
+ }
+
+ r = set_put(x, u);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
[UNIT_ACTIVE] = "active",
[UNIT_RELOADING] = "reloading",
diff --git a/src/core/unit.h b/src/core/unit.h
index b04475e4fb..6dd750f8c2 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -37,10 +37,10 @@ typedef struct UnitStatusMessageFormats UnitStatusMessageFormats;
#include "list.h"
#include "socket-util.h"
#include "execute.h"
+#include "cgroup.h"
#include "condition.h"
#include "install.h"
#include "unit-name.h"
-#include "cgroup-semantics.h"
enum UnitActiveState {
UNIT_ACTIVE,
@@ -115,8 +115,15 @@ enum UnitDependency {
#include "manager.h"
#include "job.h"
-#include "cgroup.h"
-#include "cgroup-attr.h"
+
+struct UnitRef {
+ /* Keeps tracks of references to a unit. This is useful so
+ * that we can merge two units if necessary and correct all
+ * references to them */
+
+ Unit* unit;
+ LIST_FIELDS(UnitRef, refs);
+};
struct Unit {
Manager *manager;
@@ -165,8 +172,10 @@ struct Unit {
dual_timestamp inactive_enter_timestamp;
/* Counterparts in the cgroup filesystem */
- CGroupBonding *cgroup_bondings;
- CGroupAttribute *cgroup_attributes;
+ char *cgroup_path;
+ CGroupControllerMask cgroup_mask;
+
+ UnitRef slice;
/* Per type list */
LIST_FIELDS(Unit, units_by_type);
@@ -186,6 +195,9 @@ struct Unit {
/* GC queue */
LIST_FIELDS(Unit, gc_queue);
+ /* CGroup realize members queue */
+ LIST_FIELDS(Unit, cgroup_queue);
+
/* Used during GC sweeps */
unsigned gc_marker;
@@ -228,25 +240,22 @@ struct Unit {
/* Did the last condition check succeed? */
bool condition_result;
+ /* Is this a transient unit? */
+ bool transient;
+
bool in_load_queue:1;
bool in_dbus_queue:1;
bool in_cleanup_queue:1;
bool in_gc_queue:1;
+ bool in_cgroup_queue:1;
bool sent_dbus_new_signal:1;
bool no_gc:1;
bool in_audit:1;
-};
-struct UnitRef {
- /* Keeps tracks of references to a unit. This is useful so
- * that we can merge two units if necessary and correct all
- * references to them */
-
- Unit* unit;
- LIST_FIELDS(UnitRef, refs);
+ bool cgroup_realized:1;
};
struct UnitStatusMessageFormats {
@@ -255,6 +264,12 @@ struct UnitStatusMessageFormats {
const char *finished_stop_job[_JOB_RESULT_MAX];
};
+typedef enum UnitSetPropertiesMode {
+ UNIT_CHECK = 0,
+ UNIT_RUNTIME = 1,
+ UNIT_PERSISTENT = 2,
+} UnitSetPropertiesMode;
+
#include "service.h"
#include "timer.h"
#include "socket.h"
@@ -265,6 +280,8 @@ struct UnitStatusMessageFormats {
#include "snapshot.h"
#include "swap.h"
#include "path.h"
+#include "slice.h"
+#include "scope.h"
struct UnitVTable {
/* How much memory does an object of this unit type need */
@@ -274,8 +291,12 @@ struct UnitVTable {
* ExecContext is found, if the unit type has that */
size_t exec_context_offset;
- /* The name of the section with the exec settings of ExecContext */
- const char *exec_section;
+ /* If greater than 0, the offset into the object where
+ * CGroupContext is found, if the unit type has that */
+ size_t cgroup_context_offset;
+
+ /* The name of the configuration file section with the private settings of this unit*/
+ const char *private_section;
/* Config file sections this unit type understands, separated
* by NUL chars */
@@ -347,7 +368,7 @@ struct UnitVTable {
/* Called whenever any of the cgroups this unit watches for
* ran empty */
- void (*cgroup_notify_empty)(Unit *u);
+ void (*notify_cgroup_empty)(Unit *u);
/* Called whenever a process of this unit sends us a message */
void (*notify_message)(Unit *u, pid_t pid, char **tags);
@@ -362,6 +383,12 @@ struct UnitVTable {
/* Called for each message received on the bus */
DBusHandlerResult (*bus_message_handler)(Unit *u, DBusConnection *c, DBusMessage *message);
+ /* Called for each property that is being set */
+ int (*bus_set_property)(Unit *u, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+
+ /* Called after at least one property got changed to apply the necessary change */
+ int (*bus_commit_properties)(Unit *u);
+
/* Return the unit this unit is following */
Unit *(*following)(Unit *u);
@@ -403,6 +430,9 @@ struct UnitVTable {
/* Exclude from automatic gc */
bool no_gc:1;
+
+ /* True if transient units of this type are OK */
+ bool can_transient:1;
};
extern const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX];
@@ -433,6 +463,8 @@ DEFINE_CAST(AUTOMOUNT, Automount);
DEFINE_CAST(SNAPSHOT, Snapshot);
DEFINE_CAST(SWAP, Swap);
DEFINE_CAST(PATH, Path);
+DEFINE_CAST(SLICE, Slice);
+DEFINE_CAST(SCOPE, Scope);
Unit *unit_new(Manager *m, size_t size);
void unit_free(Unit *u);
@@ -450,11 +482,6 @@ int unit_add_two_dependencies_by_name_inverse(Unit *u, UnitDependency d, UnitDep
int unit_add_exec_dependencies(Unit *u, ExecContext *c);
-int unit_add_cgroup_from_text(Unit *u, const char *name, bool overwrite, CGroupBonding **ret);
-int unit_add_default_cgroups(Unit *u);
-CGroupBonding* unit_get_default_cgroup(Unit *u);
-int unit_add_cgroup_attribute(Unit *u, const CGroupSemantics *semantics, const char *controller, const char *name, const char *value, CGroupAttribute **ret);
-
int unit_choose_id(Unit *u, const char *name);
int unit_set_description(Unit *u, const char *description);
@@ -474,6 +501,8 @@ int unit_load_fragment_and_dropin(Unit *u);
int unit_load_fragment_and_dropin_optional(Unit *u);
int unit_load(Unit *unit);
+int unit_add_default_slice(Unit *u);
+
const char *unit_description(Unit *u) _pure_;
bool unit_has_name(Unit *u, const char *name);
@@ -536,6 +565,8 @@ void unit_reset_failed(Unit *u);
Unit *unit_following(Unit *u);
+const char *unit_slice_name(Unit *u);
+
bool unit_stop_pending(Unit *u) _pure_;
bool unit_inactive_or_pending(Unit *u) _pure_;
bool unit_active_or_pending(Unit *u);
@@ -557,19 +588,29 @@ Unit* unit_ref_set(UnitRef *ref, Unit *u);
void unit_ref_unset(UnitRef *ref);
#define UNIT_DEREF(ref) ((ref).unit)
+#define UNIT_ISSET(ref) (!!(ref).unit)
-int unit_add_one_mount_link(Unit *u, Mount *m);
int unit_add_mount_links(Unit *u);
int unit_exec_context_defaults(Unit *u, ExecContext *c);
ExecContext *unit_get_exec_context(Unit *u) _pure_;
+CGroupContext *unit_get_cgroup_context(Unit *u) _pure_;
-int unit_write_drop_in(Unit *u, bool runtime, const char *name, const char *data);
-int unit_remove_drop_in(Unit *u, bool runtime, const char *name);
+int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data);
+int unit_write_drop_in_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) _printf_attr_(4,5);
+
+int unit_write_drop_in_private(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data);
+int unit_write_drop_in_private_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) _printf_attr_(4,5);
+
+int unit_remove_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name);
int unit_kill_context(Unit *u, KillContext *c, bool sigkill, pid_t main_pid, pid_t control_pid, bool main_pid_alien);
+int unit_make_transient(Unit *u);
+
+int unit_require_mounts_for(Unit *u, const char *path);
+
const char *unit_active_state_to_string(UnitActiveState i) _const_;
UnitActiveState unit_active_state_from_string(const char *s) _pure_;
diff --git a/src/core/user.conf b/src/core/user.conf
index 4252451eb7..4a0129a984 100644
--- a/src/core/user.conf
+++ b/src/core/user.conf
@@ -12,6 +12,5 @@
#LogTarget=console
#LogColor=yes
#LogLocation=no
-#DefaultControllers=cpu
#DefaultStandardOutput=inherit
#DefaultStandardError=inherit
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
index 81b770890a..e1798a3e82 100644
--- a/src/cryptsetup/cryptsetup-generator.c
+++ b/src/cryptsetup/cryptsetup-generator.c
@@ -72,13 +72,20 @@ static int create_disk(
_cleanup_free_ char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *from = NULL, *to = NULL, *e = NULL;
_cleanup_fclose_ FILE *f = NULL;
- bool noauto, nofail;
+ bool noauto, nofail, tmp, swap;
assert(name);
assert(device);
noauto = has_option(options, "noauto");
nofail = has_option(options, "nofail");
+ tmp = has_option(options, "tmp");
+ swap = has_option(options, "swap");
+
+ if (tmp && swap) {
+ log_error("Device '%s' cannot be both 'tmp' and 'swap'. Ignoring.", name);
+ return -EINVAL;
+ }
n = unit_name_from_path_instance("systemd-cryptsetup", name, ".service");
if (!n)
@@ -111,6 +118,7 @@ static int create_disk(
"Conflicts=umount.target\n"
"DefaultDependencies=no\n"
"BindsTo=dev-mapper-%i.device\n"
+ "IgnoreOnIsolate=true\n"
"After=systemd-readahead-collect.service systemd-readahead-replay.service\n",
f);
@@ -122,7 +130,7 @@ static int create_disk(
if (streq(password, "/dev/urandom") ||
streq(password, "/dev/random") ||
streq(password, "/dev/hw_random"))
- fputs("After=systemd-random-seed-load.service\n", f);
+ fputs("After=systemd-random-seed.service\n", f);
else if (!streq(password, "-") &&
!streq(password, "none"))
fprintf(f,
@@ -151,12 +159,12 @@ static int create_disk(
name, u, strempty(password), strempty(options),
name);
- if (has_option(options, "tmp"))
+ if (tmp)
fprintf(f,
"ExecStartPost=/sbin/mke2fs '/dev/mapper/%s'\n",
name);
- if (has_option(options, "swap"))
+ if (swap)
fprintf(f,
"ExecStartPost=/sbin/mkswap '/dev/mapper/%s'\n",
name);
@@ -233,7 +241,7 @@ static int create_disk(
return 0;
}
-static int parse_proc_cmdline(char ***arg_proc_cmdline_disks, char **arg_proc_cmdline_keyfile) {
+static int parse_proc_cmdline(char ***arg_proc_cmdline_disks, char ***arg_proc_cmdline_options, char **arg_proc_cmdline_keyfile) {
_cleanup_free_ char *line = NULL;
char *w = NULL, *state = NULL;
int r;
@@ -300,7 +308,20 @@ static int parse_proc_cmdline(char ***arg_proc_cmdline_disks, char **arg_proc_cm
return log_oom();
}
+ } else if (startswith(word, "luks.options=")) {
+ if (strv_extend(arg_proc_cmdline_options, word + 13) < 0)
+ return log_oom();
+
+ } else if (startswith(word, "rd.luks.options=")) {
+
+ if (in_initrd()) {
+ if (strv_extend(arg_proc_cmdline_options, word + 16) < 0)
+ return log_oom();
+ }
+
} else if (startswith(word, "luks.key=")) {
+ if (*arg_proc_cmdline_keyfile)
+ free(*arg_proc_cmdline_keyfile);
*arg_proc_cmdline_keyfile = strdup(word + 9);
if (!*arg_proc_cmdline_keyfile)
return log_oom();
@@ -330,6 +351,7 @@ static int parse_proc_cmdline(char ***arg_proc_cmdline_disks, char **arg_proc_cm
int main(int argc, char *argv[]) {
_cleanup_strv_free_ char **arg_proc_cmdline_disks_done = NULL;
_cleanup_strv_free_ char **arg_proc_cmdline_disks = NULL;
+ _cleanup_strv_free_ char **arg_proc_cmdline_options = NULL;
_cleanup_free_ char *arg_proc_cmdline_keyfile = NULL;
_cleanup_fclose_ FILE *f = NULL;
unsigned n = 0;
@@ -350,7 +372,7 @@ int main(int argc, char *argv[]) {
umask(0022);
- if (parse_proc_cmdline(&arg_proc_cmdline_disks, &arg_proc_cmdline_keyfile) < 0)
+ if (parse_proc_cmdline(&arg_proc_cmdline_disks, &arg_proc_cmdline_options, &arg_proc_cmdline_keyfile) < 0)
return EXIT_FAILURE;
if (!arg_enabled)
@@ -405,6 +427,26 @@ int main(int argc, char *argv[]) {
continue;
}
+ if (arg_proc_cmdline_options) {
+ /*
+ If options are specified on the kernel commandline, let them override
+ the ones from crypttab.
+ */
+ STRV_FOREACH(i, arg_proc_cmdline_options) {
+ _cleanup_free_ char *proc_uuid = NULL, *proc_options = NULL;
+ const char *p = *i;
+
+ k = sscanf(p, "%m[0-9a-fA-F-]=%ms", &proc_uuid, &proc_options);
+ if (k == 2 && streq(proc_uuid, device + 5)) {
+ if (options)
+ free(options);
+ options = strdup(p);
+ if (!proc_options)
+ return log_oom();
+ }
+ }
+ }
+
if (arg_proc_cmdline_disks) {
/*
If luks UUIDs are specified on the kernel command line, use them as a filter
@@ -445,7 +487,7 @@ next:
on the kernel command line and not yet written.
*/
- _cleanup_free_ char *name = NULL, *device = NULL;
+ _cleanup_free_ char *name = NULL, *device = NULL, *options = NULL;
const char *p = *i;
if (startswith(p, "luks-"))
@@ -460,7 +502,44 @@ next:
if (!name || !device)
return log_oom();
- if (create_disk(name, device, arg_proc_cmdline_keyfile, "timeout=0") < 0)
+ if (arg_proc_cmdline_options) {
+ /*
+ If options are specified on the kernel commandline, use them.
+ */
+ char **j;
+
+ STRV_FOREACH(j, arg_proc_cmdline_options) {
+ _cleanup_free_ char *proc_uuid = NULL, *proc_options = NULL;
+ const char *s = *j;
+ int k;
+
+ k = sscanf(s, "%m[0-9a-fA-F-]=%ms", &proc_uuid, &proc_options);
+ if (k == 2) {
+ if (streq(proc_uuid, device + 5)) {
+ if (options)
+ free(options);
+ options = strdup(proc_options);
+ if (!options)
+ return log_oom();
+ }
+ } else if (!options) {
+ /*
+ Fall back to options without a specified UUID
+ */
+ options = strdup(s);
+ if (!options)
+ return log_oom();
+ }
+ }
+ }
+
+ if (!options) {
+ options = strdup("timeout=0");
+ if (!options)
+ return log_oom();
+ }
+
+ if (create_disk(name, device, arg_proc_cmdline_keyfile, options) < 0)
r = EXIT_FAILURE;
}
diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
index 347394db8e..22b5eead72 100644
--- a/src/cryptsetup/cryptsetup.c
+++ b/src/cryptsetup/cryptsetup.c
@@ -27,6 +27,7 @@
#include <libcryptsetup.h>
#include <libudev.h>
+#include "fileio.h"
#include "log.h"
#include "util.h"
#include "path-util.h"
@@ -34,16 +35,19 @@
#include "ask-password-api.h"
#include "def.h"
-static const char *opt_type = NULL; /* LUKS1 or PLAIN */
+static const char *opt_type = NULL; /* CRYPT_LUKS1, CRYPT_TCRYPT or CRYPT_PLAIN */
static char *opt_cipher = NULL;
static unsigned opt_key_size = 0;
static unsigned opt_keyfile_size = 0;
static unsigned opt_keyfile_offset = 0;
static char *opt_hash = NULL;
-static unsigned opt_tries = 0;
+static unsigned opt_tries = 3;
static bool opt_readonly = false;
static bool opt_verify = false;
static bool opt_discards = false;
+static bool opt_tcrypt_hidden = false;
+static bool opt_tcrypt_system = false;
+static char **opt_tcrypt_keyfiles = NULL;
static usec_t opt_timeout = 0;
/* Options Debian's crypttab knows we don't:
@@ -82,6 +86,14 @@ static int parse_one_option(const char *option) {
return 0;
}
+ } else if (startswith(option, "tcrypt-keyfile=")) {
+
+ opt_type = CRYPT_TCRYPT;
+ if (path_is_absolute(option+15))
+ opt_tcrypt_keyfiles = strv_append(opt_tcrypt_keyfiles, strdup(option+15));
+ else
+ log_error("Key file path '%s' is not absolute. Ignoring.", option+15);
+
} else if (startswith(option, "keyfile-size=")) {
if (safe_atou(option+13, &opt_keyfile_size) < 0) {
@@ -117,11 +129,19 @@ static int parse_one_option(const char *option) {
opt_readonly = true;
else if (streq(option, "verify"))
opt_verify = true;
- else if (streq(option, "allow-discards"))
+ else if (streq(option, "allow-discards") || streq(option, "discard"))
opt_discards = true;
else if (streq(option, "luks"))
opt_type = CRYPT_LUKS1;
- else if (streq(option, "plain") ||
+ else if (streq(option, "tcrypt"))
+ opt_type = CRYPT_TCRYPT;
+ else if (streq(option, "tcrypt-hidden")) {
+ opt_type = CRYPT_TCRYPT;
+ opt_tcrypt_hidden = true;
+ } else if (streq(option, "tcrypt-system")) {
+ opt_type = CRYPT_TCRYPT;
+ opt_tcrypt_system = true;
+ } else if (streq(option, "plain") ||
streq(option, "swap") ||
streq(option, "tmp"))
opt_type = CRYPT_PLAIN;
@@ -215,7 +235,8 @@ finish:
}
static char *disk_mount_point(const char *label) {
- char *mp = NULL, *device = NULL;
+ char *mp = NULL;
+ _cleanup_free_ char *device = NULL;
FILE *f = NULL;
struct mntent *m;
@@ -238,11 +259,211 @@ finish:
if (f)
endmntent(f);
- free(device);
-
return mp;
}
+static int get_password(const char *name, usec_t until, bool accept_cached, char ***passwords) {
+ int r;
+ char **p;
+ _cleanup_free_ char *text = NULL;
+
+ assert(name);
+ assert(passwords);
+
+ if (asprintf(&text, "Please enter passphrase for disk %s!", name) < 0)
+ return log_oom();
+
+ r = ask_password_auto(text, "drive-harddisk", until, accept_cached, passwords);
+ if (r < 0) {
+ log_error("Failed to query password: %s", strerror(-r));
+ return r;
+ }
+
+ if (opt_verify) {
+ _cleanup_strv_free_ char **passwords2 = NULL;
+
+ assert(strv_length(*passwords) == 1);
+
+ if (asprintf(&text, "Please enter passphrase for disk %s! (verification)", name) < 0)
+ return log_oom();
+
+ r = ask_password_auto(text, "drive-harddisk", until, false, &passwords2);
+ if (r < 0) {
+ log_error("Failed to query verification password: %s", strerror(-r));
+ return r;
+ }
+
+ assert(strv_length(passwords2) == 1);
+
+ if (!streq(*passwords[0], passwords2[0])) {
+ log_warning("Passwords did not match, retrying.");
+ return -EAGAIN;
+ }
+ }
+
+ strv_uniq(*passwords);
+
+ STRV_FOREACH(p, *passwords) {
+ char *c;
+
+ if (strlen(*p)+1 >= opt_key_size)
+ continue;
+
+ /* Pad password if necessary */
+ if (!(c = new(char, opt_key_size)))
+ return log_oom();
+
+ strncpy(c, *p, opt_key_size);
+ free(*p);
+ *p = c;
+ }
+
+ return 0;
+}
+
+static int attach_tcrypt(struct crypt_device *cd,
+ const char *name,
+ const char *key_file,
+ char **passwords,
+ uint32_t flags) {
+ int r = 0;
+ _cleanup_free_ char *passphrase = NULL;
+ struct crypt_params_tcrypt params = {
+ .flags = CRYPT_TCRYPT_LEGACY_MODES,
+ .keyfiles = (const char **)opt_tcrypt_keyfiles,
+ .keyfiles_count = strv_length(opt_tcrypt_keyfiles)
+ };
+
+ assert(cd);
+ assert(name);
+ assert(key_file || passwords);
+
+ if (opt_tcrypt_hidden)
+ params.flags |= CRYPT_TCRYPT_HIDDEN_HEADER;
+
+ if (opt_tcrypt_system)
+ params.flags |= CRYPT_TCRYPT_SYSTEM_HEADER;
+
+ if (key_file) {
+ r = read_one_line_file(key_file, &passphrase);
+ if (r < 0) {
+ log_error("Failed to read password file '%s': %s", key_file, strerror(-r));
+ return -EAGAIN;
+ }
+
+ params.passphrase = passphrase;
+ } else
+ params.passphrase = passwords[0];
+ params.passphrase_size = strlen(params.passphrase);
+
+ r = crypt_load(cd, CRYPT_TCRYPT, &params);
+ if (r < 0) {
+ if (key_file && r == -EPERM) {
+ log_error("Failed to activate using password file '%s'.", key_file);
+ return -EAGAIN;
+ }
+ return r;
+ }
+
+ return crypt_activate_by_volume_key(cd, name, NULL, 0, flags);;
+}
+
+static int attach_luks_or_plain(struct crypt_device *cd,
+ const char *name,
+ const char *key_file,
+ char **passwords,
+ uint32_t flags) {
+ int r = 0;
+ bool pass_volume_key = false;
+
+ assert(cd);
+ assert(name);
+ assert(key_file || passwords);
+
+ if (!opt_type || streq(opt_type, CRYPT_LUKS1))
+ r = crypt_load(cd, CRYPT_LUKS1, NULL);
+
+ if ((!opt_type && r < 0) || streq_ptr(opt_type, CRYPT_PLAIN)) {
+ struct crypt_params_plain params = {};
+ const char *cipher, *cipher_mode;
+ _cleanup_free_ char *truncated_cipher = NULL;
+
+ if (opt_hash) {
+ /* plain isn't a real hash type. it just means "use no hash" */
+ if (!streq(opt_hash, "plain"))
+ params.hash = opt_hash;
+ } else
+ params.hash = "ripemd160";
+
+ if (opt_cipher) {
+ size_t l;
+
+ l = strcspn(opt_cipher, "-");
+ truncated_cipher = strndup(opt_cipher, l);
+ if (!truncated_cipher)
+ return log_oom();
+
+ cipher = truncated_cipher;
+ cipher_mode = opt_cipher[l] ? opt_cipher+l+1 : "plain";
+ } else {
+ cipher = "aes";
+ cipher_mode = "cbc-essiv:sha256";
+ }
+
+ /* for CRYPT_PLAIN limit reads
+ * from keyfile to key length, and
+ * ignore keyfile-size */
+ opt_keyfile_size = opt_key_size / 8;
+
+ /* In contrast to what the name
+ * crypt_setup() might suggest this
+ * doesn't actually format anything,
+ * it just configures encryption
+ * parameters when used for plain
+ * mode. */
+ r = crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode,
+ NULL, NULL, opt_keyfile_size, &params);
+
+ /* hash == NULL implies the user passed "plain" */
+ pass_volume_key = (params.hash == NULL);
+ }
+
+ if (r < 0) {
+ log_error("Loading of cryptographic parameters failed: %s", strerror(-r));
+ return r;
+ }
+
+ log_info("Set cipher %s, mode %s, key size %i bits for device %s.",
+ crypt_get_cipher(cd),
+ crypt_get_cipher_mode(cd),
+ crypt_get_volume_key_size(cd)*8,
+ crypt_get_device_name(cd));
+
+ if (key_file) {
+ r = crypt_activate_by_keyfile_offset(cd, name, CRYPT_ANY_SLOT,
+ key_file, opt_keyfile_size,
+ opt_keyfile_offset, flags);
+ if (r < 0) {
+ log_error("Failed to activate with key file '%s': %s", key_file, strerror(-r));
+ return -EAGAIN;
+ }
+ } else {
+ char **p;
+
+ STRV_FOREACH(p, passwords) {
+ if (pass_volume_key)
+ r = crypt_activate_by_volume_key(cd, name, *p, opt_key_size, flags);
+ else
+ r = crypt_activate_by_passphrase(cd, name, CRYPT_ANY_SLOT, *p, strlen(*p), flags);
+
+ if (r >= 0)
+ break;
+ }
+ }
+
+ return r;
+}
+
static int help(void) {
printf("%s attach VOLUME SOURCEDEVICE [PASSWORD] [OPTIONS]\n"
@@ -257,9 +478,6 @@ static int help(void) {
int main(int argc, char *argv[]) {
int r = EXIT_FAILURE;
struct crypt_device *cd = NULL;
- char **passwords = NULL, *truncated_cipher = NULL;
- const char *cipher = NULL, *cipher_mode = NULL, *hash = NULL, *name = NULL;
- char *description = NULL, *name_buffer = NULL, *mount_point = NULL;
if (argc <= 1) {
help();
@@ -280,10 +498,11 @@ int main(int argc, char *argv[]) {
if (streq(argv[1], "attach")) {
uint32_t flags = 0;
int k;
- unsigned try;
- const char *key_file = NULL;
+ unsigned tries;
usec_t until;
crypt_status_info status;
+ const char *key_file = NULL, *name = NULL;
+ _cleanup_free_ char *description = NULL, *name_buffer = NULL, *mount_point = NULL;
/* Arguments: systemd-cryptsetup attach VOLUME SOURCE-DEVICE [PASSWORD] [OPTIONS] */
@@ -298,7 +517,7 @@ int main(int argc, char *argv[]) {
!streq(argv[4], "none")) {
if (!path_is_absolute(argv[4]))
- log_error("Password file path %s is not absolute. Ignoring.", argv[4]);
+ log_error("Password file path '%s' is not absolute. Ignoring.", argv[4]);
else
key_file = argv[4];
}
@@ -357,183 +576,38 @@ int main(int argc, char *argv[]) {
else
until = 0;
- opt_tries = opt_tries > 0 ? opt_tries : 3;
opt_key_size = (opt_key_size > 0 ? opt_key_size : 256);
- if (opt_hash) {
- /* plain isn't a real hash type. it just means "use no hash" */
- if (!streq(opt_hash, "plain"))
- hash = opt_hash;
- } else
- hash = "ripemd160";
-
- if (opt_cipher) {
- size_t l;
- l = strcspn(opt_cipher, "-");
- truncated_cipher = strndup(opt_cipher, l);
-
- if (!truncated_cipher) {
- log_oom();
- goto finish;
- }
+ if (key_file) {
+ struct stat st;
- cipher = truncated_cipher;
- cipher_mode = opt_cipher[l] ? opt_cipher+l+1 : "plain";
- } else {
- cipher = "aes";
- cipher_mode = "cbc-essiv:sha256";
+ /* Ideally we'd do this on the open fd, but since this is just a
+ * warning it's OK to do this in two steps. */
+ if (stat(key_file, &st) >= 0 && (st.st_mode & 0005))
+ log_warning("Key file %s is world-readable. This is not a good idea!", key_file);
}
- for (try = 0; try < opt_tries; try++) {
- bool pass_volume_key = false;
-
- strv_free(passwords);
- passwords = NULL;
+ for (tries = 0; opt_tries == 0 || tries < opt_tries; tries++) {
+ _cleanup_strv_free_ char **passwords = NULL;
if (!key_file) {
- char *text, **p;
-
- if (asprintf(&text, "Please enter passphrase for disk %s!", name) < 0) {
- log_oom();
- goto finish;
- }
-
- k = ask_password_auto(text, "drive-harddisk", until, try == 0 && !opt_verify, &passwords);
- free(text);
-
- if (k < 0) {
- log_error("Failed to query password: %s", strerror(-k));
- goto finish;
- }
-
- if (opt_verify) {
- char **passwords2 = NULL;
-
- assert(strv_length(passwords) == 1);
-
- if (asprintf(&text, "Please enter passphrase for disk %s! (verification)", name) < 0) {
- log_oom();
- goto finish;
- }
-
- k = ask_password_auto(text, "drive-harddisk", until, false, &passwords2);
- free(text);
-
- if (k < 0) {
- log_error("Failed to query verification password: %s", strerror(-k));
- goto finish;
- }
-
- assert(strv_length(passwords2) == 1);
-
- if (!streq(passwords[0], passwords2[0])) {
- log_warning("Passwords did not match, retrying.");
- strv_free(passwords2);
- continue;
- }
-
- strv_free(passwords2);
- }
-
- strv_uniq(passwords);
-
- STRV_FOREACH(p, passwords) {
- char *c;
-
- if (strlen(*p)+1 >= opt_key_size)
- continue;
-
- /* Pad password if necessary */
- if (!(c = new(char, opt_key_size))) {
- log_oom();
- goto finish;
- }
-
- strncpy(c, *p, opt_key_size);
- free(*p);
- *p = c;
- }
- }
-
- k = 0;
-
- if (!opt_type || streq(opt_type, CRYPT_LUKS1))
- k = crypt_load(cd, CRYPT_LUKS1, NULL);
-
- if ((!opt_type && k < 0) || streq_ptr(opt_type, CRYPT_PLAIN)) {
- struct crypt_params_plain params = { .hash = hash };
-
- /* for CRYPT_PLAIN limit reads
- * from keyfile to key length, and
- * ignore keyfile-size */
- opt_keyfile_size = opt_key_size / 8;
-
- /* In contrast to what the name
- * crypt_setup() might suggest this
- * doesn't actually format anything,
- * it just configures encryption
- * parameters when used for plain
- * mode. */
- k = crypt_format(cd, CRYPT_PLAIN,
- cipher,
- cipher_mode,
- NULL,
- NULL,
- opt_keyfile_size,
- &params);
-
- /* hash == NULL implies the user passed "plain" */
- pass_volume_key = (hash == NULL);
- }
-
- if (k < 0) {
- log_error("Loading of cryptographic parameters failed: %s", strerror(-k));
- goto finish;
- }
-
- log_info("Set cipher %s, mode %s, key size %i bits for device %s.",
- crypt_get_cipher(cd),
- crypt_get_cipher_mode(cd),
- crypt_get_volume_key_size(cd)*8,
- argv[3]);
-
- if (key_file) {
- struct stat st;
-
- /* Ideally we'd do this on the open
- * fd, but since this is just a
- * warning it's OK to do this in two
- * steps */
- if (stat(key_file, &st) >= 0 && (st.st_mode & 0005))
- log_warning("Key file %s is world-readable. That's certainly not a good idea.", key_file);
-
- k = crypt_activate_by_keyfile_offset(
- cd, argv[2], CRYPT_ANY_SLOT, key_file, opt_keyfile_size,
- opt_keyfile_offset, flags);
- if (k < 0) {
- log_error("Failed to activate with key file '%s': %s", key_file, strerror(-k));
- key_file = NULL;
+ k = get_password(name, until, tries == 0 && !opt_verify, &passwords);
+ if (k == -EAGAIN)
continue;
- }
- } else {
- char **p;
-
- STRV_FOREACH(p, passwords) {
-
- if (pass_volume_key)
- k = crypt_activate_by_volume_key(cd, argv[2], *p, opt_key_size, flags);
- else
- k = crypt_activate_by_passphrase(cd, argv[2], CRYPT_ANY_SLOT, *p, strlen(*p), flags);
-
- if (k >= 0)
- break;
- }
+ else if (k < 0)
+ goto finish;
}
+ if (streq_ptr(opt_type, CRYPT_TCRYPT))
+ k = attach_tcrypt(cd, argv[2], key_file, passwords, flags);
+ else
+ k = attach_luks_or_plain(cd, argv[2], key_file, passwords, flags);
if (k >= 0)
break;
-
- if (k != -EPERM) {
+ else if (k == -EAGAIN) {
+ key_file = NULL;
+ continue;
+ } else if (k != -EPERM) {
log_error("Failed to activate: %s", strerror(-k));
goto finish;
}
@@ -541,8 +615,8 @@ int main(int argc, char *argv[]) {
log_warning("Invalid passphrase.");
}
- if (try >= opt_tries) {
- log_error("Too many attempts.");
+ if (opt_tries != 0 && tries >= opt_tries) {
+ log_error("Too many attempts; giving up.");
r = EXIT_FAILURE;
goto finish;
}
@@ -578,14 +652,7 @@ finish:
free(opt_cipher);
free(opt_hash);
-
- free(truncated_cipher);
-
- strv_free(passwords);
-
- free(description);
- free(mount_point);
- free(name_buffer);
+ strv_free(opt_tcrypt_keyfiles);
return r;
}
diff --git a/src/delta/delta.c b/src/delta/delta.c
index aec3dc8995..b3272d916e 100644
--- a/src/delta/delta.c
+++ b/src/delta/delta.c
@@ -31,6 +31,7 @@
#include "log.h"
#include "pager.h"
#include "build.h"
+#include "strv.h"
static bool arg_no_pager = false;
static int arg_diff = -1;
@@ -41,9 +42,10 @@ static enum {
SHOW_REDIRECTED = 1 << 2,
SHOW_OVERRIDDEN = 1 << 3,
SHOW_UNCHANGED = 1 << 4,
+ SHOW_EXTENDED = 1 << 5,
SHOW_DEFAULTS =
- (SHOW_MASKED | SHOW_EQUIVALENT | SHOW_REDIRECTED | SHOW_OVERRIDDEN)
+ (SHOW_MASKED | SHOW_EQUIVALENT | SHOW_REDIRECTED | SHOW_OVERRIDDEN | SHOW_EXTENDED)
} arg_flags = 0;
static int equivalent(const char *a, const char *b) {
@@ -64,7 +66,8 @@ static int notify_override_masked(const char *top, const char *bottom) {
if (!(arg_flags & SHOW_MASKED))
return 0;
- printf(ANSI_HIGHLIGHT_RED_ON "[MASKED]" ANSI_HIGHLIGHT_OFF " %s → %s\n", top, bottom);
+ printf("%s%s%s %s → %s\n",
+ ansi_highlight_red(), "[MASKED]", ansi_highlight_off(), top, bottom);
return 1;
}
@@ -72,7 +75,8 @@ static int notify_override_equivalent(const char *top, const char *bottom) {
if (!(arg_flags & SHOW_EQUIVALENT))
return 0;
- printf(ANSI_HIGHLIGHT_GREEN_ON "[EQUIVALENT]" ANSI_HIGHLIGHT_OFF " %s → %s\n", top, bottom);
+ printf("%s%s%s %s → %s\n",
+ ansi_highlight_green(), "[EQUIVALENT]", ansi_highlight(), top, bottom);
return 1;
}
@@ -80,7 +84,8 @@ static int notify_override_redirected(const char *top, const char *bottom) {
if (!(arg_flags & SHOW_REDIRECTED))
return 0;
- printf(ANSI_HIGHLIGHT_ON "[REDIRECTED]" ANSI_HIGHLIGHT_OFF " %s → %s\n", top, bottom);
+ printf("%s%s%s %s → %s\n",
+ ansi_highlight(), "[REDIRECTED]", ansi_highlight_off(), top, bottom);
return 1;
}
@@ -88,7 +93,17 @@ static int notify_override_overridden(const char *top, const char *bottom) {
if (!(arg_flags & SHOW_OVERRIDDEN))
return 0;
- printf(ANSI_HIGHLIGHT_ON "[OVERRIDDEN]" ANSI_HIGHLIGHT_OFF " %s → %s\n", top, bottom);
+ printf("%s%s%s %s → %s\n",
+ ansi_highlight(), "[OVERRIDDEN]", ansi_highlight_off(), top, bottom);
+ return 1;
+}
+
+static int notify_override_extended(const char *top, const char *bottom) {
+ if (!(arg_flags & SHOW_EXTENDED))
+ return 0;
+
+ printf("%s%s%s %s → %s\n",
+ ansi_highlight(), "[EXTENDED]", ansi_highlight_off(), top, bottom);
return 1;
}
@@ -108,24 +123,20 @@ static int found_override(const char *top, const char *bottom) {
assert(top);
assert(bottom);
- if (null_or_empty_path(top) > 0) {
- notify_override_masked(top, bottom);
- return 0;
- }
+ if (null_or_empty_path(top) > 0)
+ return notify_override_masked(top, bottom);
k = readlink_malloc(top, &dest);
if (k >= 0) {
if (equivalent(dest, bottom) > 0)
- notify_override_equivalent(top, bottom);
+ return notify_override_equivalent(top, bottom);
else
- notify_override_redirected(top, bottom);
-
- return 0;
+ return notify_override_redirected(top, bottom);
}
- notify_override_overridden(top, bottom);
+ k = notify_override_overridden(top, bottom);
if (!arg_diff)
- return 0;
+ return k;
putchar('\n');
@@ -145,14 +156,117 @@ static int found_override(const char *top, const char *bottom) {
putchar('\n');
+ return k;
+}
+
+static int enumerate_dir_d(Hashmap *top, Hashmap *bottom, Hashmap *drops, const char *toppath, const char *drop) {
+ _cleanup_free_ char *conf = NULL;
+ _cleanup_free_ char *path = NULL;
+ _cleanup_strv_free_ char **list = NULL;
+ char **file;
+ char *c;
+ int r;
+
+ path = strjoin(toppath, "/", drop, NULL);
+ if (!path)
+ return -ENOMEM;
+
+ path_kill_slashes(path);
+
+ conf = strdup(drop);
+ if (!conf)
+ return -ENOMEM;
+
+ c = strrchr(conf, '.');
+ if (!c)
+ return -EINVAL;
+ *c = 0;
+
+ r = get_files_in_directory(path, &list);
+ if (r < 0){
+ log_error("Failed to enumerate %s: %s", path, strerror(-r));
+ return r;
+ }
+
+ STRV_FOREACH(file, list) {
+ Hashmap *h;
+ int k;
+ char *p;
+ char *d;
+
+ if (!endswith(*file, ".conf"))
+ continue;
+
+ p = strjoin(path, "/", *file, NULL);
+ if (!p)
+ return -ENOMEM;
+
+ path_kill_slashes(p);
+
+ d = strrchr(p, '/');
+ if (!d || d == p) {
+ free(p);
+ return -EINVAL;
+ }
+ d--;
+ d = strrchr(p, '/');
+
+ if (!d || d == p) {
+ free(p);
+ return -EINVAL;
+ }
+
+ k = hashmap_put(top, d, p);
+ if (k >= 0) {
+ p = strdup(p);
+ if (!p)
+ return -ENOMEM;
+ d = strrchr(p, '/');
+ d--;
+ d = strrchr(p, '/');
+ } else if (k != -EEXIST) {
+ free(p);
+ return k;
+ }
+
+ free(hashmap_remove(bottom, d));
+ k = hashmap_put(bottom, d, p);
+ if (k < 0) {
+ free(p);
+ return k;
+ }
+
+ h = hashmap_get(drops, conf);
+ if (!h) {
+ h = hashmap_new(string_hash_func, string_compare_func);
+ if (!h)
+ return -ENOMEM;
+ hashmap_put(drops, conf, h);
+ conf = strdup(conf);
+ if (!conf)
+ return -ENOMEM;
+ }
+
+ p = strdup(p);
+ if (!p)
+ return -ENOMEM;
+
+ k = hashmap_put(h, path_get_file_name(p), p);
+ if (k < 0) {
+ free(p);
+ if (k != -EEXIST)
+ return k;
+ }
+ }
return 0;
}
-static int enumerate_dir(Hashmap *top, Hashmap *bottom, const char *path) {
+static int enumerate_dir(Hashmap *top, Hashmap *bottom, Hashmap *drops, const char *path, bool dropins) {
_cleanup_closedir_ DIR *d;
assert(top);
assert(bottom);
+ assert(drops);
assert(path);
d = opendir(path);
@@ -177,6 +291,9 @@ static int enumerate_dir(Hashmap *top, Hashmap *bottom, const char *path) {
if (!de)
break;
+ if (dropins && de->d_type == DT_DIR && endswith(de->d_name, ".d"))
+ enumerate_dir_d(top, bottom, drops, path, de->d_name);
+
if (!dirent_is_file(de))
continue;
@@ -207,12 +324,14 @@ static int enumerate_dir(Hashmap *top, Hashmap *bottom, const char *path) {
return 0;
}
-static int process_suffix(const char *prefixes, const char *suffix) {
+static int process_suffix(const char *prefixes, const char *suffix, bool dropins) {
const char *p;
char *f;
- Hashmap *top, *bottom=NULL;
+ Hashmap *top, *bottom=NULL, *drops=NULL;
+ Hashmap *h;
+ char *key;
int r = 0, k;
- Iterator i;
+ Iterator i, j;
int n_found = 0;
assert(prefixes);
@@ -230,6 +349,12 @@ static int process_suffix(const char *prefixes, const char *suffix) {
goto finish;
}
+ drops = hashmap_new(string_hash_func, string_compare_func);
+ if (!drops) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
NULSTR_FOREACH(p, prefixes) {
_cleanup_free_ char *t = NULL;
@@ -239,29 +364,33 @@ static int process_suffix(const char *prefixes, const char *suffix) {
goto finish;
}
- k = enumerate_dir(top, bottom, t);
+ k = enumerate_dir(top, bottom, drops, t, dropins);
if (k < 0)
r = k;
log_debug("Looking at %s", t);
}
- HASHMAP_FOREACH(f, top, i) {
+ HASHMAP_FOREACH_KEY(f, key, top, i) {
char *o;
- o = hashmap_get(bottom, path_get_file_name(f));
+ o = hashmap_get(bottom, key);
assert(o);
- if (path_equal(o, f)) {
+ if (path_equal(o, f))
notify_override_unchanged(f);
- continue;
+ else {
+ k = found_override(f, o);
+ if (k < 0)
+ r = k;
+ else
+ n_found += k;
}
- k = found_override(f, o);
- if (k < 0)
- r = k;
-
- n_found ++;
+ h = hashmap_get(drops, key);
+ if (h)
+ HASHMAP_FOREACH(o, h, j)
+ n_found += notify_override_extended(f, o);
}
finish:
@@ -269,25 +398,32 @@ finish:
hashmap_free_free(top);
if (bottom)
hashmap_free_free(bottom);
-
+ if (drops) {
+ HASHMAP_FOREACH_KEY(h, key, drops, i){
+ hashmap_free_free(hashmap_remove(drops, key));
+ hashmap_remove(drops, key);
+ free(key);
+ }
+ hashmap_free(drops);
+ }
return r < 0 ? r : n_found;
}
-static int process_suffix_chop(const char *prefixes, const char *suffix) {
+static int process_suffix_chop(const char *prefixes, const char *suffix, const char *have_dropins) {
const char *p;
assert(prefixes);
assert(suffix);
if (!path_is_absolute(suffix))
- return process_suffix(prefixes, suffix);
+ return process_suffix(prefixes, suffix, nulstr_contains(have_dropins, suffix));
/* Strip prefix from the suffix */
NULSTR_FOREACH(p, prefixes) {
if (startswith(suffix, p)) {
suffix += strlen(p);
suffix += strspn(suffix, "/");
- return process_suffix(prefixes, suffix);
+ return process_suffix(prefixes, suffix, nulstr_contains(have_dropins, suffix));
}
}
@@ -322,6 +458,8 @@ static int parse_flags(const char *flag_str, int flags) {
flags |= SHOW_OVERRIDDEN;
else if (strneq("unchanged", w, l))
flags |= SHOW_UNCHANGED;
+ else if (strneq("extended", w, l))
+ flags |= SHOW_EXTENDED;
else if (strneq("default", w, l))
flags |= SHOW_DEFAULTS;
else
@@ -435,6 +573,10 @@ int main(int argc, char *argv[]) {
"udev/rules.d\0"
"modprobe.d\0";
+ const char have_dropins[] =
+ "systemd/system\0"
+ "systemd/user\0";
+
int r = 0, k;
int n_found = 0;
@@ -460,7 +602,7 @@ int main(int argc, char *argv[]) {
int i;
for (i = optind; i < argc; i++) {
- k = process_suffix_chop(prefixes, argv[i]);
+ k = process_suffix_chop(prefixes, argv[i], have_dropins);
if (k < 0)
r = k;
else
@@ -471,7 +613,7 @@ int main(int argc, char *argv[]) {
const char *n;
NULSTR_FOREACH(n, suffixes) {
- k = process_suffix(prefixes, n);
+ k = process_suffix(prefixes, n, nulstr_contains(have_dropins, n));
if (k < 0)
r = k;
else
@@ -480,7 +622,8 @@ int main(int argc, char *argv[]) {
}
if (r >= 0)
- printf("\n%i overridden configuration files found.\n", n_found);
+ printf("%s%i overridden configuration files found.\n",
+ n_found ? "\n" : "", n_found);
finish:
pager_close();
diff --git a/src/efi-boot-generator/efi-boot-generator.c b/src/efi-boot-generator/efi-boot-generator.c
index 4367c536b0..05b95ed455 100644
--- a/src/efi-boot-generator/efi-boot-generator.c
+++ b/src/efi-boot-generator/efi-boot-generator.c
@@ -55,7 +55,7 @@ int main(int argc, char *argv[]) {
if (dir_is_empty("/boot") <= 0)
return EXIT_SUCCESS;
- r = efi_get_loader_device_part_uuid(&id);
+ r = efi_loader_get_device_part_uuid(&id);
if (r == -ENOENT)
return EXIT_SUCCESS;
if (r < 0) {
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index c17299f267..9efccb983d 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -38,22 +38,6 @@
static const char *arg_dest = "/tmp";
static bool arg_enabled = true;
-static int device_name(const char *path, char **unit) {
- char *p;
-
- assert(path);
-
- if (!is_device_path(path))
- return 0;
-
- p = unit_name_from_path(path, ".device");
- if (!p)
- return log_oom();
-
- *unit = p;
- return 1;
-}
-
static int mount_find_pri(struct mntent *me, int *ret) {
char *end, *pri;
unsigned long r;
@@ -80,9 +64,9 @@ static int mount_find_pri(struct mntent *me, int *ret) {
}
static int add_swap(const char *what, struct mntent *me) {
- _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL, *device = NULL;
+ _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL;
_cleanup_fclose_ FILE *f = NULL;
- bool noauto, nofail;
+ bool noauto;
int r, pri = -1;
assert(what);
@@ -95,7 +79,6 @@ static int add_swap(const char *what, struct mntent *me) {
}
noauto = !!hasmntopt(me, "noauto");
- nofail = !!hasmntopt(me, "nofail");
name = unit_name_from_path(what, ".swap");
if (!name)
@@ -114,18 +97,10 @@ static int add_swap(const char *what, struct mntent *me) {
return -errno;
}
- fputs("# Automatically generated by systemd-fstab-generator\n\n"
- "[Unit]\n"
- "SourcePath=/etc/fstab\n"
- "DefaultDependencies=no\n"
- "Conflicts=" SPECIAL_UMOUNT_TARGET "\n"
- "Before=" SPECIAL_UMOUNT_TARGET "\n", f);
-
- if (!noauto && !nofail)
- fputs("Before=" SPECIAL_SWAP_TARGET "\n", f);
-
fprintf(f,
- "\n"
+ "# Automatically generated by systemd-fstab-generator\n\n"
+ "[Unit]\n"
+ "SourcePath=/etc/fstab\n\n"
"[Swap]\n"
"What=%s\n",
what);
@@ -151,38 +126,11 @@ static int add_swap(const char *what, struct mntent *me) {
log_error("Failed to create symlink %s: %m", lnk);
return -errno;
}
-
- r = device_name(what, &device);
- if (r < 0)
- return r;
-
- if (r > 0) {
- free(lnk);
- lnk = strjoin(arg_dest, "/", device, ".wants/", name, NULL);
- if (!lnk)
- return log_oom();
-
- mkdir_parents_label(lnk, 0755);
- if (symlink(unit, lnk) < 0) {
- log_error("Failed to create symlink %s: %m", lnk);
- return -errno;
- }
- }
}
return 0;
}
-static bool mount_is_bind(struct mntent *me) {
- assert(me);
-
- return
- hasmntopt(me, "bind") ||
- streq(me->mnt_type, "bind") ||
- hasmntopt(me, "rbind") ||
- streq(me->mnt_type, "rbind");
-}
-
static bool mount_is_network(struct mntent *me) {
assert(me);
@@ -208,17 +156,12 @@ static int add_mount(
bool noauto,
bool nofail,
bool automount,
- bool isbind,
- const char *pre,
- const char *pre2,
- const char *online,
const char *post,
const char *source) {
_cleanup_free_ char
- *name = NULL, *unit = NULL, *lnk = NULL, *device = NULL,
+ *name = NULL, *unit = NULL, *lnk = NULL,
*automount_name = NULL, *automount_unit = NULL;
_cleanup_fclose_ FILE *f = NULL;
- int r;
assert(what);
assert(where);
@@ -258,33 +201,9 @@ static int add_mount(
fprintf(f,
"# Automatically generated by systemd-fstab-generator\n\n"
"[Unit]\n"
- "SourcePath=%s\n"
- "DefaultDependencies=no\n",
+ "SourcePath=%s\n",
source);
- if (!path_equal(where, "/")) {
- if (pre)
- fprintf(f,
- "After=%s\n",
- pre);
-
- if (pre2)
- fprintf(f,
- "After=%s\n",
- pre2);
-
- if (online)
- fprintf(f,
- "After=%s\n"
- "Wants=%s\n",
- online,
- online);
-
- fprintf(f,
- "Conflicts=" SPECIAL_UMOUNT_TARGET "\n"
- "Before=" SPECIAL_UMOUNT_TARGET "\n");
- }
-
if (post && !noauto && !nofail && !automount)
fprintf(f,
"Before=%s\n",
@@ -326,32 +245,11 @@ static int add_mount(
return -errno;
}
}
-
- if (!isbind &&
- !path_equal(where, "/")) {
-
- r = device_name(what, &device);
- if (r < 0)
- return r;
-
- if (r > 0) {
- free(lnk);
- lnk = strjoin(arg_dest, "/", device, ".wants/", name, NULL);
- if (!lnk)
- return log_oom();
-
- mkdir_parents_label(lnk, 0755);
- if (symlink(unit, lnk) < 0) {
- log_error("Failed to create symlink %s: %m", lnk);
- return -errno;
- }
- }
- }
}
if (automount && !path_equal(where, "/")) {
automount_name = unit_name_from_path(where, ".automount");
- if (!name)
+ if (!automount_name)
return log_oom();
automount_unit = strjoin(arg_dest, "/", automount_name, NULL);
@@ -368,10 +266,7 @@ static int add_mount(
fprintf(f,
"# Automatically generated by systemd-fstab-generator\n\n"
"[Unit]\n"
- "SourcePath=%s\n"
- "DefaultDependencies=no\n"
- "Conflicts=" SPECIAL_UMOUNT_TARGET "\n"
- "Before=" SPECIAL_UMOUNT_TARGET "\n",
+ "SourcePath=%s\n",
source);
if (post)
@@ -446,36 +341,28 @@ static int parse_fstab(const char *prefix, bool initrd) {
if (streq(me->mnt_type, "swap"))
k = add_swap(what, me);
else {
- bool noauto, nofail, automount, isbind;
- const char *pre, *pre2, *post, *online;
+ bool noauto, nofail, automount;
+ const char *post;
noauto = !!hasmntopt(me, "noauto");
nofail = !!hasmntopt(me, "nofail");
automount =
hasmntopt(me, "comment=systemd.automount") ||
hasmntopt(me, "x-systemd.automount");
- isbind = mount_is_bind(me);
if (initrd) {
- pre = pre2 = online = NULL;
post = SPECIAL_INITRD_FS_TARGET;
} else if (mount_in_initrd(me)) {
- pre = pre2 = online = NULL;
post = SPECIAL_INITRD_ROOT_FS_TARGET;
} else if (mount_is_network(me)) {
- pre = SPECIAL_REMOTE_FS_PRE_TARGET;
- pre2 = SPECIAL_NETWORK_TARGET;
- online = SPECIAL_NETWORK_ONLINE_TARGET;
post = SPECIAL_REMOTE_FS_TARGET;
} else {
- pre = SPECIAL_LOCAL_FS_PRE_TARGET;
- pre2 = online = NULL;
post = SPECIAL_LOCAL_FS_TARGET;
}
k = add_mount(what, where, me->mnt_type, me->mnt_opts,
me->mnt_passno, noauto, nofail, automount,
- isbind, pre, pre2, online, post, fstab_path);
+ post, fstab_path);
}
if (k < 0)
@@ -492,6 +379,7 @@ static int parse_new_root_from_proc_cmdline(void) {
char *w, *state;
int r;
size_t l;
+ bool noauto, nofail;
r = read_one_line_file("/proc/cmdline", &line);
if (r < 0) {
@@ -547,6 +435,9 @@ static int parse_new_root_from_proc_cmdline(void) {
}
}
+ noauto = !!strstr(opts, "noauto");
+ nofail = !!strstr(opts, "nofail");
+
if (!what) {
log_debug("Could not find a root= entry on the kernel commandline.");
return 0;
@@ -558,8 +449,8 @@ static int parse_new_root_from_proc_cmdline(void) {
}
log_debug("Found entry what=%s where=/sysroot type=%s", what, type);
- r = add_mount(what, "/sysroot", type, opts, 0, false, false, false,
- false, NULL, NULL, NULL, SPECIAL_INITRD_ROOT_FS_TARGET, "/proc/cmdline");
+ r = add_mount(what, "/sysroot", type, opts, 0, noauto, nofail, false,
+ SPECIAL_INITRD_ROOT_FS_TARGET, "/proc/cmdline");
return (r < 0) ? r : 0;
}
@@ -596,9 +487,9 @@ static int parse_proc_cmdline(void) {
} else if (startswith(word, "rd.fstab=")) {
if (in_initrd()) {
- r = parse_boolean(word + 6);
+ r = parse_boolean(word + 9);
if (r < 0)
- log_warning("Failed to parse fstab switch %s. Ignoring.", word + 6);
+ log_warning("Failed to parse fstab switch %s. Ignoring.", word + 9);
else
arg_enabled = r;
}
diff --git a/src/getty-generator/getty-generator.c b/src/getty-generator/getty-generator.c
index 4b7a60a4ec..6c938062de 100644
--- a/src/getty-generator/getty-generator.c
+++ b/src/getty-generator/getty-generator.c
@@ -122,33 +122,42 @@ int main(int argc, char *argv[]) {
}
if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
- const char *tty;
-
- tty = strrchr(active, ' ');
- if (tty)
- tty ++;
- else
- tty = active;
-
- /* Automatically add in a serial getty on the kernel
- * console */
- if (isempty(tty) || tty_is_vc(tty))
- free(active);
- else {
+ char *w, *state;
+ size_t l;
+
+ /* Automatically add in a serial getty on all active
+ * kernel consoles */
+ FOREACH_WORD(w, l, active, state) {
+ char *tty;
int k;
+ tty = strndup(w, l);
+ if (!tty) {
+ log_oom();
+ free(active);
+ r = EXIT_FAILURE;
+ goto finish;
+ }
+
+ if (isempty(tty) || tty_is_vc(tty)) {
+ free(tty);
+ continue;
+ }
+
/* We assume that gettys on virtual terminals are
* started via manual configuration and do this magic
* only for non-VC terminals. */
k = add_serial_getty(tty);
- free(active);
if (k < 0) {
+ free(tty);
+ free(active);
r = EXIT_FAILURE;
goto finish;
}
}
+ free(active);
}
/* Automatically add in a serial getty on the first
diff --git a/src/gpt-auto-generator/Makefile b/src/gpt-auto-generator/Makefile
new file mode 120000
index 0000000000..d0b0e8e008
--- /dev/null
+++ b/src/gpt-auto-generator/Makefile
@@ -0,0 +1 @@
+../Makefile \ No newline at end of file
diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
new file mode 100644
index 0000000000..ca54925da4
--- /dev/null
+++ b/src/gpt-auto-generator/gpt-auto-generator.c
@@ -0,0 +1,527 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ 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 <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/statfs.h>
+#include <blkid.h>
+
+#ifdef HAVE_LINUX_BTRFS_H
+#include <linux/btrfs.h>
+#endif
+
+#include "path-util.h"
+#include "util.h"
+#include "mkdir.h"
+#include "missing.h"
+#include "sd-id128.h"
+#include "libudev.h"
+#include "special.h"
+#include "unit-name.h"
+
+/* TODO:
+ *
+ * - Properly handle cryptsetup partitions
+ * - Define new partition type for encrypted swap
+ * - Make /home automount rather than mount
+ *
+ */
+
+static const char *arg_dest = "/tmp";
+
+static inline void blkid_free_probep(blkid_probe *b) {
+ if (*b)
+ blkid_free_probe(*b);
+}
+#define _cleanup_blkid_freep_probe_ _cleanup_(blkid_free_probep)
+
+static int verify_gpt_partition(const char *node, sd_id128_t *type, unsigned *nr, char **fstype) {
+ _cleanup_blkid_freep_probe_ blkid_probe b = NULL;
+ const char *v;
+ int r;
+
+ errno = 0;
+ b = blkid_new_probe_from_filename(node);
+ if (!b)
+ return errno != 0 ? -errno : -ENOMEM;
+
+ blkid_probe_enable_superblocks(b, 1);
+ blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
+ blkid_probe_enable_partitions(b, 1);
+ blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
+
+ errno = 0;
+ r = blkid_do_safeprobe(b);
+ if (r == -2)
+ return -ENODEV;
+ else if (r == 1)
+ return -ENODEV;
+ else if (r != 0)
+ return errno ? -errno : -EIO;
+
+ errno = 0;
+ r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &v, NULL);
+ if (r != 0)
+ /* return 0 if we're not on GPT */
+ return errno ? -errno : 0;
+
+ if (strcmp(v, "gpt") != 0)
+ return 0;
+
+ if (type) {
+ errno = 0;
+ r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL);
+ if (r != 0)
+ return errno ? -errno : -EIO;
+
+ r = sd_id128_from_string(v, type);
+ if (r < 0)
+ return r;
+ }
+
+ if (nr) {
+ errno = 0;
+ r = blkid_probe_lookup_value(b, "PART_ENTRY_NUMBER", &v, NULL);
+ if (r != 0)
+ return errno ? -errno : -EIO;
+
+ r = safe_atou(v, nr);
+ if (r < 0)
+ return r;
+ }
+
+
+ if (fstype) {
+ char *fst;
+
+ errno = 0;
+ r = blkid_probe_lookup_value(b, "TYPE", &v, NULL);
+ if (r != 0)
+ *fstype = NULL;
+ else {
+ fst = strdup(v);
+ if (!fst)
+ return -ENOMEM;
+
+ *fstype = fst;
+ }
+ }
+
+ return 1;
+}
+
+static int add_swap(const char *path, const char *fstype) {
+ _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+
+ log_debug("Adding swap: %s %s", path, fstype);
+
+ name = unit_name_from_path(path, ".swap");
+ if (!name)
+ return log_oom();
+
+ unit = strjoin(arg_dest, "/", name, NULL);
+ if (!unit)
+ return log_oom();
+
+ f = fopen(unit, "wxe");
+ if (!f) {
+ log_error("Failed to create unit file %s: %m", unit);
+ return -errno;
+ }
+
+ fprintf(f,
+ "# Automatically generated by systemd-gpt-auto-generator\n\n"
+ "[Unit]\n"
+ "DefaultDependencies=no\n"
+ "Conflicts=" SPECIAL_UMOUNT_TARGET "\n"
+ "Before=" SPECIAL_UMOUNT_TARGET " " SPECIAL_SWAP_TARGET "\n\n"
+ "[Swap]\n"
+ "What=%s\n",
+ path);
+
+ fflush(f);
+ if (ferror(f)) {
+ log_error("Failed to write unit file %s: %m", unit);
+ return -errno;
+ }
+
+ lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL);
+ if (!lnk)
+ return log_oom();
+
+ mkdir_parents_label(lnk, 0755);
+ if (symlink(unit, lnk) < 0) {
+ log_error("Failed to create symlink %s: %m", lnk);
+ return -errno;
+ }
+
+ return 0;
+}
+
+static int add_home(const char *path, const char *fstype) {
+ _cleanup_free_ char *unit = NULL, *lnk = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+
+ if (dir_is_empty("/home") <= 0)
+ return 0;
+
+ log_debug("Adding home: %s %s", path, fstype);
+
+ unit = strappend(arg_dest, "/home.mount");
+ if (!unit)
+ return log_oom();
+
+ f = fopen(unit, "wxe");
+ if (!f) {
+ log_error("Failed to create unit file %s: %m", unit);
+ return -errno;
+ }
+
+ fprintf(f,
+ "# Automatically generated by systemd-gpt-auto-generator\n\n"
+ "[Unit]\n"
+ "DefaultDependencies=no\n"
+ "After=" SPECIAL_LOCAL_FS_PRE_TARGET "\n"
+ "Conflicts=" SPECIAL_UMOUNT_TARGET "\n"
+ "Before=" SPECIAL_UMOUNT_TARGET " " SPECIAL_LOCAL_FS_TARGET "\n\n"
+ "[Mount]\n"
+ "What=%s\n"
+ "Where=/home\n"
+ "Type=%s\n"
+ "FsckPassNo=2\n",
+ path, fstype);
+
+ fflush(f);
+ if (ferror(f)) {
+ log_error("Failed to write unit file %s: %m", unit);
+ return -errno;
+ }
+
+ lnk = strjoin(arg_dest, "/" SPECIAL_LOCAL_FS_TARGET ".requires/home.mount", NULL);
+ if (!lnk)
+ return log_oom();
+
+
+ mkdir_parents_label(lnk, 0755);
+ if (symlink(unit, lnk) < 0) {
+ log_error("Failed to create symlink %s: %m", lnk);
+ return -errno;
+ }
+
+ return 0;
+}
+
+static int enumerate_partitions(struct udev *udev, dev_t dev) {
+ struct udev_enumerate *e = NULL;
+ struct udev_device *parent = NULL, *d = NULL;
+ struct udev_list_entry *first, *item;
+ unsigned home_nr = (unsigned) -1;
+ _cleanup_free_ char *home = NULL, *home_fstype = NULL;
+ int r;
+
+ e = udev_enumerate_new(udev);
+ if (!e) {
+ r = log_oom();
+ goto finish;
+ }
+
+ d = udev_device_new_from_devnum(udev, 'b', dev);
+ if (!d) {
+ r = log_oom();
+ goto finish;
+ }
+
+ parent = udev_device_get_parent(d);
+ if (!parent) {
+ r = log_oom();
+ goto finish;
+ }
+
+ r = udev_enumerate_add_match_parent(e, parent);
+ if (r < 0) {
+ r = log_oom();
+ goto finish;
+ }
+
+ r = udev_enumerate_add_match_subsystem(e, "block");
+ if (r < 0) {
+ r = log_oom();
+ goto finish;
+ }
+
+ r = udev_enumerate_scan_devices(e);
+ if (r < 0) {
+ log_error("Failed to enumerate partitions on /dev/block/%u:%u: %s",
+ major(dev), minor(dev), strerror(-r));
+ goto finish;
+ }
+
+ first = udev_enumerate_get_list_entry(e);
+ udev_list_entry_foreach(item, first) {
+ _cleanup_free_ char *fstype = NULL;
+ const char *node = NULL;
+ struct udev_device *q;
+ sd_id128_t type_id;
+ unsigned nr;
+
+ q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
+ if (!q) {
+ r = log_oom();
+ goto finish;
+ }
+
+ if (udev_device_get_devnum(q) == udev_device_get_devnum(d))
+ goto skip;
+
+ if (udev_device_get_devnum(q) == udev_device_get_devnum(parent))
+ goto skip;
+
+ node = udev_device_get_devnode(q);
+ if (!node) {
+ r = log_oom();
+ goto finish;
+ }
+
+ r = verify_gpt_partition(node, &type_id, &nr, &fstype);
+ if (r < 0) {
+ log_error("Failed to verify GPT partition %s: %s",
+ node, strerror(-r));
+ udev_device_unref(q);
+ goto finish;
+ }
+ if (r == 0)
+ goto skip;
+
+ if (sd_id128_equal(type_id, SD_ID128_MAKE(06,57,fd,6d,a4,ab,43,c4,84,e5,09,33,c8,4b,4f,4f)))
+ add_swap(node, fstype);
+ else if (sd_id128_equal(type_id, SD_ID128_MAKE(93,3a,c7,e1,2e,b4,4f,13,b8,44,0e,14,e2,ae,f9,15))) {
+
+ if (!home || nr < home_nr) {
+ free(home);
+ home = strdup(node);
+ if (!home) {
+ r = log_oom();
+ goto finish;
+ }
+
+ home_nr = nr;
+
+ free(home_fstype);
+ home_fstype = fstype;
+ fstype = NULL;
+ }
+ }
+
+ skip:
+ udev_device_unref(q);
+ }
+
+ if (home && home_fstype)
+ add_home(home, home_fstype);
+
+finish:
+ if (d)
+ udev_device_unref(d);
+
+ if (e)
+ udev_enumerate_unref(e);
+
+
+ return r;
+}
+
+static int get_btrfs_block_device(const char *path, dev_t *dev) {
+ struct btrfs_ioctl_fs_info_args fsi;
+ _cleanup_close_ int fd = -1;
+ uint64_t id;
+
+ assert(path);
+ assert(dev);
+
+ fd = open(path, O_DIRECTORY|O_CLOEXEC);
+ if (fd < 0)
+ return -errno;
+
+ zero(fsi);
+ if (ioctl(fd, BTRFS_IOC_FS_INFO, &fsi) < 0)
+ return -errno;
+
+ /* We won't do this for btrfs RAID */
+ if (fsi.num_devices != 1)
+ return 0;
+
+ for (id = 1; id <= fsi.max_id; id++) {
+ struct btrfs_ioctl_dev_info_args di;
+ struct stat st;
+
+ zero(di);
+ di.devid = id;
+
+ if (ioctl(fd, BTRFS_IOC_DEV_INFO, &di) < 0) {
+ if (errno == ENODEV)
+ continue;
+
+ return -errno;
+ }
+
+ if (stat((char*) di.path, &st) < 0)
+ return -errno;
+
+ if (!S_ISBLK(st.st_mode))
+ return -ENODEV;
+
+ if (major(st.st_rdev) == 0)
+ return -ENODEV;
+
+ *dev = st.st_rdev;
+ return 1;
+ }
+
+ return -ENODEV;
+}
+
+static int get_block_device(const char *path, dev_t *dev) {
+ struct stat st;
+ struct statfs sfs;
+
+ assert(path);
+ assert(dev);
+
+ if (lstat("/", &st))
+ return -errno;
+
+ if (major(st.st_dev) != 0) {
+ *dev = st.st_dev;
+ return 1;
+ }
+
+ if (statfs("/", &sfs) < 0)
+ return -errno;
+
+ if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
+ return get_btrfs_block_device(path, dev);
+
+ return 0;
+}
+
+static int devno_to_devnode(struct udev *udev, dev_t devno, char **ret) {
+ struct udev_device *d = NULL;
+ const char *t;
+ char *n;
+ int r;
+
+ d = udev_device_new_from_devnum(udev, 'b', devno);
+ if (!d) {
+ r = log_oom();
+ goto finish;
+ }
+
+ t = udev_device_get_devnode(d);
+ if (!t) {
+ r = -ENODEV;
+ goto finish;
+ }
+
+ n = strdup(t);
+ if (!n) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ *ret = n;
+ r = 0;
+
+finish:
+ if (d)
+ udev_device_unref(d);
+
+ return r;
+}
+
+int main(int argc, char *argv[]) {
+ _cleanup_free_ char *node = NULL;
+ struct udev *udev = NULL;
+ dev_t devno;
+ int r;
+
+ if (argc > 1 && argc != 4) {
+ log_error("This program takes three or no arguments.");
+ r = -EINVAL;
+ goto finish;
+ }
+
+ if (argc > 1)
+ arg_dest = argv[3];
+
+ log_set_target(LOG_TARGET_SAFE);
+ log_parse_environment();
+ log_open();
+
+ umask(0022);
+
+ if (in_initrd()) {
+ r = 0;
+ goto finish;
+ }
+
+ r = get_block_device("/", &devno);
+ if (r < 0) {
+ log_error("Failed to determine block device of root file system: %s", strerror(-r));
+ goto finish;
+ }
+ if (r == 0) {
+ log_debug("Root file system not on a (single) block device.");
+ goto finish;
+ }
+
+ udev = udev_new();
+ if (!udev) {
+ r = log_oom();
+ goto finish;
+ }
+
+ r = devno_to_devnode(udev, devno, &node);
+ if (r < 0) {
+ log_error("Failed to determine block device node from major/minor: %s", strerror(-r));
+ goto finish;
+ }
+
+ log_debug("Root device %s.", node);
+
+ r = verify_gpt_partition(node, NULL, NULL, NULL);
+ if (r < 0) {
+ log_error("Failed to verify GPT partition %s: %s", node, strerror(-r));
+ goto finish;
+ }
+ if (r == 0)
+ goto finish;
+
+ r = enumerate_partitions(udev, devno);
+
+finish:
+ if (udev)
+ udev_unref(udev);
+
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c
index 064581a31c..66015c2f4c 100644
--- a/src/hostname/hostnamectl.c
+++ b/src/hostname/hostnamectl.c
@@ -44,10 +44,11 @@ static enum transport {
TRANSPORT_POLKIT
} arg_transport = TRANSPORT_NORMAL;
static bool arg_ask_password = true;
-static const char *arg_host = NULL;
-static bool arg_set_transient = false;
-static bool arg_set_pretty = false;
-static bool arg_set_static = false;
+static char *arg_host = NULL;
+static char *arg_user = NULL;
+static bool arg_transient = false;
+static bool arg_pretty = false;
+static bool arg_static = false;
static void polkit_agent_open_if_enabled(void) {
@@ -151,15 +152,52 @@ static int status_property(const char *name, DBusMessageIter *iter, StatusInfo *
return 0;
}
-static int show_status(DBusConnection *bus, char **args, unsigned n) {
+static int show_one_name(DBusConnection *bus, const char* attr) {
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ const char *interface = "org.freedesktop.hostname1", *s;
+ DBusMessageIter iter, sub;
+ int r;
+
+ r = bus_method_call_with_reply(
+ bus,
+ "org.freedesktop.hostname1",
+ "/org/freedesktop/hostname1",
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ &reply,
+ NULL,
+ DBUS_TYPE_STRING, &interface,
+ DBUS_TYPE_STRING, &attr,
+ DBUS_TYPE_INVALID);
+ if (r < 0)
+ return r;
+
+ if (!dbus_message_iter_init(reply, &iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
+ log_error("Failed to parse reply.");
+ return -EIO;
+ }
+
+ dbus_message_iter_recurse(&iter, &sub);
+
+ if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
+ log_error("Failed to parse reply.");
+ return -EIO;
+ }
+
+ dbus_message_iter_get_basic(&sub, &s);
+ printf("%s\n", s);
+
+ return 0;
+}
+
+static int show_all_names(DBusConnection *bus) {
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
const char *interface = "";
int r;
DBusMessageIter iter, sub, sub2, sub3;
StatusInfo info = {};
- assert(args);
-
r = bus_method_call_with_reply(
bus,
"org.freedesktop.hostname1",
@@ -217,9 +255,28 @@ static int show_status(DBusConnection *bus, char **args, unsigned n) {
return 0;
}
+static int show_status(DBusConnection *bus, char **args, unsigned n) {
+ assert(args);
+
+ if (arg_pretty || arg_static || arg_transient) {
+ const char *attr;
+
+ if (!!arg_static + !!arg_pretty + !!arg_transient > 1) {
+ log_error("Cannot query more than one name type at a time");
+ return -EINVAL;
+ }
+
+ attr = arg_pretty ? "PrettyHostname" :
+ arg_static ? "StaticHostname" : "Hostname";
+
+ return show_one_name(bus, attr);
+ } else
+ return show_all_names(bus);
+}
+
static int set_hostname(DBusConnection *bus, char **args, unsigned n) {
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- dbus_bool_t interactive = true;
+ dbus_bool_t interactive = arg_ask_password;
_cleanup_free_ char *h = NULL;
const char *hostname = args[1];
int r;
@@ -229,7 +286,10 @@ static int set_hostname(DBusConnection *bus, char **args, unsigned n) {
polkit_agent_open_if_enabled();
- if (arg_set_pretty) {
+ if (!arg_pretty && !arg_static && !arg_transient)
+ arg_pretty = arg_static = arg_transient = true;
+
+ if (arg_pretty) {
const char *p;
/* If the passed hostname is already valid, then
@@ -244,7 +304,7 @@ static int set_hostname(DBusConnection *bus, char **args, unsigned n) {
hostname_cleanup(h, true);
- if (arg_set_static && streq(h, hostname))
+ if (arg_static && streq(h, hostname))
p = "";
else {
p = hostname;
@@ -269,7 +329,7 @@ static int set_hostname(DBusConnection *bus, char **args, unsigned n) {
reply = NULL;
}
- if (arg_set_static) {
+ if (arg_static) {
r = bus_method_call_with_reply(
bus,
"org.freedesktop.hostname1",
@@ -289,7 +349,7 @@ static int set_hostname(DBusConnection *bus, char **args, unsigned n) {
reply = NULL;
}
- if (arg_set_transient) {
+ if (arg_transient) {
r = bus_method_call_with_reply(
bus,
"org.freedesktop.hostname1",
@@ -311,7 +371,7 @@ static int set_hostname(DBusConnection *bus, char **args, unsigned n) {
static int set_icon_name(DBusConnection *bus, char **args, unsigned n) {
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- dbus_bool_t interactive = true;
+ dbus_bool_t interactive = arg_ask_password;
assert(args);
assert(n == 2);
@@ -333,7 +393,7 @@ static int set_icon_name(DBusConnection *bus, char **args, unsigned n) {
static int set_chassis(DBusConnection *bus, char **args, unsigned n) {
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- dbus_bool_t interactive = true;
+ dbus_bool_t interactive = arg_ask_password;
assert(args);
assert(n == 2);
@@ -362,6 +422,7 @@ static int help(void) {
" --transient Only set transient hostname\n"
" --static Only set static hostname\n"
" --pretty Only set pretty hostname\n"
+ " -P --privileged Acquire privileges before execution\n"
" --no-ask-password Do not prompt for password\n"
" -H --host=[USER@]HOST Operate on remote host\n\n"
"Commands:\n"
@@ -379,17 +440,17 @@ static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
ARG_NO_ASK_PASSWORD,
- ARG_SET_TRANSIENT,
- ARG_SET_STATIC,
- ARG_SET_PRETTY
+ ARG_TRANSIENT,
+ ARG_STATIC,
+ ARG_PRETTY
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
- { "transient", no_argument, NULL, ARG_SET_TRANSIENT },
- { "static", no_argument, NULL, ARG_SET_STATIC },
- { "pretty", no_argument, NULL, ARG_SET_PRETTY },
+ { "transient", no_argument, NULL, ARG_TRANSIENT },
+ { "static", no_argument, NULL, ARG_STATIC },
+ { "pretty", no_argument, NULL, ARG_PRETTY },
{ "host", required_argument, NULL, 'H' },
{ "privileged", no_argument, NULL, 'P' },
{ "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
@@ -420,19 +481,19 @@ static int parse_argv(int argc, char *argv[]) {
case 'H':
arg_transport = TRANSPORT_SSH;
- arg_host = optarg;
+ parse_user_at_host(optarg, &arg_user, &arg_host);
break;
- case ARG_SET_TRANSIENT:
- arg_set_transient = true;
+ case ARG_TRANSIENT:
+ arg_transient = true;
break;
- case ARG_SET_PRETTY:
- arg_set_pretty = true;
+ case ARG_PRETTY:
+ arg_pretty = true;
break;
- case ARG_SET_STATIC:
- arg_set_static = true;
+ case ARG_STATIC:
+ arg_static = true;
break;
case ARG_NO_ASK_PASSWORD:
@@ -448,9 +509,6 @@ static int parse_argv(int argc, char *argv[]) {
}
}
- if (!arg_set_transient && !arg_set_pretty && !arg_set_static)
- arg_set_transient = arg_set_pretty = arg_set_static = true;
-
return 1;
}
diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
index 0437e33a66..6a43aeb840 100644
--- a/src/hostname/hostnamed.c
+++ b/src/hostname/hostnamed.c
@@ -553,7 +553,8 @@ static DBusHandlerResult hostname_message_handler(
* safe than sorry */
if (k == PROP_ICON_NAME && !filename_is_safe(name))
return bus_send_error_reply(connection, message, NULL, -EINVAL);
- if (k == PROP_PRETTY_HOSTNAME && string_has_cc(name))
+ if (k == PROP_PRETTY_HOSTNAME &&
+ (string_has_cc(name) || chars_intersect(name, "\t")))
return bus_send_error_reply(connection, message, NULL, -EINVAL);
if (k == PROP_CHASSIS && !valid_chassis(name))
return bus_send_error_reply(connection, message, NULL, -EINVAL);
diff --git a/src/initctl/initctl.c b/src/initctl/initctl.c
index 735f1e1450..ec33040509 100644
--- a/src/initctl/initctl.c
+++ b/src/initctl/initctl.c
@@ -122,7 +122,7 @@ static void change_runlevel(Server *s, int runlevel) {
if (isolate)
mode = "isolate";
else
- mode = "replace";
+ mode = "replace-irreversibly";
log_debug("Running request %s/start/%s", target, mode);
@@ -223,8 +223,10 @@ static int fifo_process(Fifo *f) {
assert(f);
errno = EIO;
- if ((l = read(f->fd, ((uint8_t*) &f->buffer) + f->bytes_read, sizeof(f->buffer) - f->bytes_read)) <= 0) {
-
+ l = read(f->fd,
+ ((uint8_t*) &f->buffer) + f->bytes_read,
+ sizeof(f->buffer) - f->bytes_read);
+ if (l <= 0) {
if (errno == EAGAIN)
return 0;
@@ -372,8 +374,8 @@ static int process_event(Server *s, struct epoll_event *ev) {
}
f = (Fifo*) ev->data.ptr;
-
- if ((r = fifo_process(f)) < 0) {
+ r = fifo_process(f);
+ if (r < 0) {
log_info("Got error on fifo: %s", strerror(-r));
fifo_free(f);
return r;
diff --git a/src/journal/coredump.c b/src/journal/coredump.c
index fd03e389bb..68c353fe83 100644
--- a/src/journal/coredump.c
+++ b/src/journal/coredump.c
@@ -41,7 +41,7 @@
#define COREDUMP_MIN_START (3*1024*1024)
/* Make sure to not make this larger than the maximum journal entry
* size. See ENTRY_SIZE_MAX in journald-native.c. */
-#define COREDUMP_MAX (768*1024*1024)
+#define COREDUMP_MAX (767*1024*1024)
enum {
ARG_PID = 1,
@@ -241,7 +241,7 @@ int main(int argc, char* argv[]) {
coredump_data = malloc(coredump_bufsize);
if (!coredump_data) {
r = log_oom();
- goto finish;
+ goto finalize;
}
memcpy(coredump_data, "COREDUMP=", 9);
@@ -258,9 +258,15 @@ int main(int argc, char* argv[]) {
break;
coredump_size += n;
+
+ if(coredump_size > COREDUMP_MAX) {
+ log_error("Coredump too large, ignoring");
+ goto finalize;
+ }
+
if (!GREEDY_REALLOC(coredump_data, coredump_bufsize, coredump_size + 1)) {
r = log_oom();
- goto finish;
+ goto finalize;
}
}
@@ -268,6 +274,7 @@ int main(int argc, char* argv[]) {
iovec[j].iov_len = coredump_size;
j++;
+finalize:
r = sd_journal_sendv(iovec, j);
if (r < 0)
log_error("Failed to send coredump: %s", strerror(-r));
diff --git a/src/journal/coredumpctl.c b/src/journal/coredumpctl.c
index 5652c2f91a..75c96cc081 100644
--- a/src/journal/coredumpctl.c
+++ b/src/journal/coredumpctl.c
@@ -84,6 +84,7 @@ static int help(void) {
"Flags:\n"
" -o --output=FILE Write output to FILE\n"
" --no-pager Do not pipe output into a pager\n"
+ " --no-legend Do not print the column headers.\n\n"
"Commands:\n"
" -h --help Show this help\n"
@@ -341,7 +342,7 @@ static int dump_list(sd_journal *j) {
assert(j);
/* The coredumps are likely to compressed, and for just
- * listing them we don#t need to decompress them, so let's
+ * listing them we don't need to decompress them, so let's
* pick a fairly low data threshold here */
sd_journal_set_data_threshold(j, 4096);
@@ -556,6 +557,13 @@ int main(int argc, char *argv[]) {
}
}
+ if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
+ _cleanup_free_ char *filter;
+
+ filter = journal_make_match_string(j);
+ log_debug("Journal filter: %s", filter);
+ }
+
switch(arg_action) {
case ACTION_LIST:
diff --git a/src/journal/fsprg.c b/src/journal/fsprg.c
index 6817a629c8..dd9a242561 100644
--- a/src/journal/fsprg.c
+++ b/src/journal/fsprg.c
@@ -19,7 +19,13 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
+ */
+
+/*
+ * See "Practical Secure Logging: Seekable Sequential Key Generators"
+ * by G. A. Marson, B. Poettering for details:
*
+ * http://eprint.iacr.org/2013/397
*/
#include <gcrypt.h>
diff --git a/src/journal/journal-authenticate.c b/src/journal/journal-authenticate.c
index 64bf96874e..bd7100a8d5 100644
--- a/src/journal/journal-authenticate.c
+++ b/src/journal/journal-authenticate.c
@@ -60,9 +60,9 @@ int journal_file_append_tag(JournalFile *f) {
o->tag.seqnum = htole64(journal_file_tag_seqnum(f));
o->tag.epoch = htole64(FSPRG_GetEpoch(f->fsprg_state));
- log_debug("Writing tag %llu for epoch %llu\n",
- (unsigned long long) le64toh(o->tag.seqnum),
- (unsigned long long) FSPRG_GetEpoch(f->fsprg_state));
+ log_debug("Writing tag %"PRIu64" for epoch %"PRIu64"\n",
+ le64toh(o->tag.seqnum),
+ FSPRG_GetEpoch(f->fsprg_state));
/* Add the tag object itself, so that we can protect its
* header. This will exclude the actual hash value in it */
@@ -152,7 +152,7 @@ int journal_file_fsprg_evolve(JournalFile *f, uint64_t realtime) {
epoch = FSPRG_GetEpoch(f->fsprg_state);
if (epoch < goal)
- log_debug("Evolving FSPRG key from epoch %llu to %llu.", (unsigned long long) epoch, (unsigned long long) goal);
+ log_debug("Evolving FSPRG key from epoch %"PRIu64" to %"PRIu64".", epoch, goal);
for (;;) {
if (epoch > goal)
@@ -195,7 +195,7 @@ int journal_file_fsprg_seek(JournalFile *f, uint64_t goal) {
return -ENOMEM;
}
- log_debug("Seeking FSPRG key to %llu.", (unsigned long long) goal);
+ log_debug("Seeking FSPRG key to %"PRIu64".", goal);
msk = alloca(FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR));
FSPRG_GenMK(msk, NULL, f->fsprg_seed, f->fsprg_seed_size, FSPRG_RECOMMENDED_SECPAR);
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
index 38499a6881..12364030d9 100644
--- a/src/journal/journal-file.c
+++ b/src/journal/journal-file.c
@@ -549,7 +549,7 @@ static int journal_file_setup_data_hash_table(JournalFile *f) {
if (s < DEFAULT_DATA_HASH_TABLE_SIZE)
s = DEFAULT_DATA_HASH_TABLE_SIZE;
- log_debug("Reserving %llu entries in hash table.", (unsigned long long) (s / sizeof(HashItem)));
+ log_debug("Reserving %"PRIu64" entries in hash table.", s / sizeof(HashItem));
r = journal_file_append_object(f,
OBJECT_DATA_HASH_TABLE,
@@ -985,7 +985,7 @@ static int journal_file_append_data(
o->object.size = htole64(offsetof(Object, data.payload) + rsize);
o->object.flags |= OBJECT_COMPRESSED;
- log_debug("Compressed data object %lu -> %lu", (unsigned long) size, (unsigned long) rsize);
+ log_debug("Compressed data object %"PRIu64" -> %"PRIu64, size, rsize);
}
}
#endif
@@ -1206,7 +1206,7 @@ static int journal_file_link_entry(JournalFile *f, Object *o, uint64_t offset) {
if (r < 0)
return r;
- /* log_debug("=> %s seqnr=%lu n_entries=%lu", f->path, (unsigned long) o->entry.seqnum, (unsigned long) f->header->n_entries); */
+ /* log_debug("=> %s seqnr=%"PRIu64" n_entries=%"PRIu64, f->path, o->entry.seqnum, f->header->n_entries); */
if (f->header->head_entry_realtime == 0)
f->header->head_entry_realtime = o->entry.realtime;
@@ -2227,10 +2227,10 @@ void journal_file_dump(JournalFile *f) {
break;
case OBJECT_ENTRY:
- printf("Type: OBJECT_ENTRY seqnum=%llu monotonic=%llu realtime=%llu\n",
- (unsigned long long) le64toh(o->entry.seqnum),
- (unsigned long long) le64toh(o->entry.monotonic),
- (unsigned long long) le64toh(o->entry.realtime));
+ printf("Type: OBJECT_ENTRY seqnum=%"PRIu64" monotonic=%"PRIu64" realtime=%"PRIu64"\n",
+ le64toh(o->entry.seqnum),
+ le64toh(o->entry.monotonic),
+ le64toh(o->entry.realtime));
break;
case OBJECT_FIELD_HASH_TABLE:
@@ -2246,9 +2246,9 @@ void journal_file_dump(JournalFile *f) {
break;
case OBJECT_TAG:
- printf("Type: OBJECT_TAG seqnum=%llu epoch=%llu\n",
- (unsigned long long) le64toh(o->tag.seqnum),
- (unsigned long long) le64toh(o->tag.epoch));
+ printf("Type: OBJECT_TAG seqnum=%"PRIu64" epoch=%"PRIu64"\n",
+ le64toh(o->tag.seqnum),
+ le64toh(o->tag.epoch));
break;
default:
@@ -2270,9 +2270,18 @@ fail:
log_error("File corrupt");
}
+static const char* format_timestamp_safe(char *buf, size_t l, usec_t t) {
+ const char *x;
+
+ x = format_timestamp(buf, l, t);
+ if (x)
+ return x;
+ return " --- ";
+}
+
void journal_file_print_header(JournalFile *f) {
- char a[33], b[33], c[33];
- char x[FORMAT_TIMESTAMP_MAX], y[FORMAT_TIMESTAMP_MAX];
+ char a[33], b[33], c[33], d[33];
+ char x[FORMAT_TIMESTAMP_MAX], y[FORMAT_TIMESTAMP_MAX], z[FORMAT_TIMESTAMP_MAX];
struct stat st;
char bytes[FORMAT_BYTES_MAX];
@@ -2286,22 +2295,23 @@ void journal_file_print_header(JournalFile *f) {
"State: %s\n"
"Compatible Flags:%s%s\n"
"Incompatible Flags:%s%s\n"
- "Header size: %llu\n"
- "Arena size: %llu\n"
- "Data Hash Table Size: %llu\n"
- "Field Hash Table Size: %llu\n"
+ "Header size: %"PRIu64"\n"
+ "Arena size: %"PRIu64"\n"
+ "Data Hash Table Size: %"PRIu64"\n"
+ "Field Hash Table Size: %"PRIu64"\n"
"Rotate Suggested: %s\n"
- "Head Sequential Number: %llu\n"
- "Tail Sequential Number: %llu\n"
+ "Head Sequential Number: %"PRIu64"\n"
+ "Tail Sequential Number: %"PRIu64"\n"
"Head Realtime Timestamp: %s\n"
"Tail Realtime Timestamp: %s\n"
- "Objects: %llu\n"
- "Entry Objects: %llu\n",
+ "Tail Monotonic Timestamp: %s\n"
+ "Objects: %"PRIu64"\n"
+ "Entry Objects: %"PRIu64"\n",
f->path,
sd_id128_to_string(f->header->file_id, a),
sd_id128_to_string(f->header->machine_id, b),
sd_id128_to_string(f->header->boot_id, c),
- sd_id128_to_string(f->header->seqnum_id, c),
+ sd_id128_to_string(f->header->seqnum_id, d),
f->header->state == STATE_OFFLINE ? "OFFLINE" :
f->header->state == STATE_ONLINE ? "ONLINE" :
f->header->state == STATE_ARCHIVED ? "ARCHIVED" : "UNKNOWN",
@@ -2309,36 +2319,37 @@ void journal_file_print_header(JournalFile *f) {
(le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_SEALED) ? " ???" : "",
JOURNAL_HEADER_COMPRESSED(f->header) ? " COMPRESSED" : "",
(le32toh(f->header->incompatible_flags) & ~HEADER_INCOMPATIBLE_COMPRESSED) ? " ???" : "",
- (unsigned long long) le64toh(f->header->header_size),
- (unsigned long long) le64toh(f->header->arena_size),
- (unsigned long long) le64toh(f->header->data_hash_table_size) / sizeof(HashItem),
- (unsigned long long) le64toh(f->header->field_hash_table_size) / sizeof(HashItem),
+ le64toh(f->header->header_size),
+ le64toh(f->header->arena_size),
+ le64toh(f->header->data_hash_table_size) / sizeof(HashItem),
+ le64toh(f->header->field_hash_table_size) / sizeof(HashItem),
yes_no(journal_file_rotate_suggested(f, 0)),
- (unsigned long long) le64toh(f->header->head_entry_seqnum),
- (unsigned long long) le64toh(f->header->tail_entry_seqnum),
- format_timestamp(x, sizeof(x), le64toh(f->header->head_entry_realtime)),
- format_timestamp(y, sizeof(y), le64toh(f->header->tail_entry_realtime)),
- (unsigned long long) le64toh(f->header->n_objects),
- (unsigned long long) le64toh(f->header->n_entries));
+ le64toh(f->header->head_entry_seqnum),
+ le64toh(f->header->tail_entry_seqnum),
+ format_timestamp_safe(x, sizeof(x), le64toh(f->header->head_entry_realtime)),
+ format_timestamp_safe(y, sizeof(y), le64toh(f->header->tail_entry_realtime)),
+ format_timespan(z, sizeof(z), le64toh(f->header->tail_entry_monotonic), USEC_PER_MSEC),
+ le64toh(f->header->n_objects),
+ le64toh(f->header->n_entries));
if (JOURNAL_HEADER_CONTAINS(f->header, n_data))
- printf("Data Objects: %llu\n"
+ printf("Data Objects: %"PRIu64"\n"
"Data Hash Table Fill: %.1f%%\n",
- (unsigned long long) le64toh(f->header->n_data),
+ le64toh(f->header->n_data),
100.0 * (double) le64toh(f->header->n_data) / ((double) (le64toh(f->header->data_hash_table_size) / sizeof(HashItem))));
if (JOURNAL_HEADER_CONTAINS(f->header, n_fields))
- printf("Field Objects: %llu\n"
+ printf("Field Objects: %"PRIu64"\n"
"Field Hash Table Fill: %.1f%%\n",
- (unsigned long long) le64toh(f->header->n_fields),
+ le64toh(f->header->n_fields),
100.0 * (double) le64toh(f->header->n_fields) / ((double) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem))));
if (JOURNAL_HEADER_CONTAINS(f->header, n_tags))
- printf("Tag Objects: %llu\n",
- (unsigned long long) le64toh(f->header->n_tags));
+ printf("Tag Objects: %"PRIu64"\n",
+ le64toh(f->header->n_tags));
if (JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays))
- printf("Entry Array Objects: %llu\n",
- (unsigned long long) le64toh(f->header->n_entry_arrays));
+ printf("Entry Array Objects: %"PRIu64"\n",
+ le64toh(f->header->n_entry_arrays));
if (fstat(f->fd, &st) >= 0)
printf("Disk usage: %s\n", format_bytes(bytes, sizeof(bytes), (off_t) st.st_blocks * 512ULL));
@@ -2564,9 +2575,9 @@ int journal_file_rotate(JournalFile **f, bool compress, bool seal) {
p[l-8] = '@';
sd_id128_to_string(old_file->header->seqnum_id, p + l - 8 + 1);
snprintf(p + l - 8 + 1 + 32, 1 + 16 + 1 + 16 + 8 + 1,
- "-%016llx-%016llx.journal",
- (unsigned long long) le64toh((*f)->header->head_entry_seqnum),
- (unsigned long long) le64toh((*f)->header->head_entry_realtime));
+ "-%016"PRIx64"-%016"PRIx64".journal",
+ le64toh((*f)->header->head_entry_seqnum),
+ le64toh((*f)->header->head_entry_realtime));
r = rename(old_file->path, p);
free(p);
@@ -2596,7 +2607,7 @@ int journal_file_open_reliably(
int r;
size_t l;
- char *p;
+ _cleanup_free_ char *p = NULL;
r = journal_file_open(fname, flags, mode, compress, seal,
metrics, mmap_cache, template, ret);
@@ -2627,7 +2638,6 @@ int journal_file_open_reliably(
return -ENOMEM;
r = rename(fname, p);
- free(p);
if (r < 0)
return -errno;
@@ -2873,23 +2883,23 @@ bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec) {
if (JOURNAL_HEADER_CONTAINS(f->header, n_data))
if (le64toh(f->header->n_data) * 4ULL > (le64toh(f->header->data_hash_table_size) / sizeof(HashItem)) * 3ULL) {
- log_debug("Data hash table of %s has a fill level at %.1f (%llu of %llu items, %llu file size, %llu bytes per hash table item), suggesting rotation.",
+ log_debug("Data hash table of %s has a fill level at %.1f (%"PRIu64" of %"PRIu64" items, %llu file size, %"PRIu64" bytes per hash table item), suggesting rotation.",
f->path,
100.0 * (double) le64toh(f->header->n_data) / ((double) (le64toh(f->header->data_hash_table_size) / sizeof(HashItem))),
- (unsigned long long) le64toh(f->header->n_data),
- (unsigned long long) (le64toh(f->header->data_hash_table_size) / sizeof(HashItem)),
- (unsigned long long) (f->last_stat.st_size),
- (unsigned long long) (f->last_stat.st_size / le64toh(f->header->n_data)));
+ le64toh(f->header->n_data),
+ le64toh(f->header->data_hash_table_size) / sizeof(HashItem),
+ (unsigned long long) f->last_stat.st_size,
+ f->last_stat.st_size / le64toh(f->header->n_data));
return true;
}
if (JOURNAL_HEADER_CONTAINS(f->header, n_fields))
if (le64toh(f->header->n_fields) * 4ULL > (le64toh(f->header->field_hash_table_size) / sizeof(HashItem)) * 3ULL) {
- log_debug("Field hash table of %s has a fill level at %.1f (%llu of %llu items), suggesting rotation.",
+ log_debug("Field hash table of %s has a fill level at %.1f (%"PRIu64" of %"PRIu64" items), suggesting rotation.",
f->path,
100.0 * (double) le64toh(f->header->n_fields) / ((double) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem))),
- (unsigned long long) le64toh(f->header->n_fields),
- (unsigned long long) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem)));
+ le64toh(f->header->n_fields),
+ le64toh(f->header->field_hash_table_size) / sizeof(HashItem));
return true;
}
diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h
index 7b1cd42854..5cc2c2d28d 100644
--- a/src/journal/journal-file.h
+++ b/src/journal/journal-file.h
@@ -42,10 +42,14 @@ typedef struct JournalMetrics {
uint64_t keep_free;
} JournalMetrics;
+typedef enum direction {
+ DIRECTION_UP,
+ DIRECTION_DOWN
+} direction_t;
+
typedef struct JournalFile {
int fd;
- char *path;
- struct stat last_stat;
+
mode_t mode;
int flags;
@@ -56,6 +60,11 @@ typedef struct JournalFile {
bool tail_entry_monotonic_valid;
+ direction_t last_direction;
+
+ char *path;
+ struct stat last_stat;
+
Header *header;
HashItem *data_hash_table;
HashItem *field_hash_table;
@@ -90,11 +99,6 @@ typedef struct JournalFile {
#endif
} JournalFile;
-typedef enum direction {
- DIRECTION_UP,
- DIRECTION_DOWN
-} direction_t;
-
int journal_file_open(
const char *fname,
int flags,
diff --git a/src/journal/journal-gatewayd.c b/src/journal/journal-gatewayd.c
index 745f45f932..06a236df6b 100644
--- a/src/journal/journal-gatewayd.c
+++ b/src/journal/journal-gatewayd.c
@@ -109,7 +109,7 @@ static int open_journal(RequestMeta *m) {
if (m->journal)
return 0;
- return sd_journal_open(&m->journal, SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM_ONLY);
+ return sd_journal_open(&m->journal, SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM);
}
static int respond_oom_internal(struct MHD_Connection *connection) {
@@ -248,7 +248,7 @@ static ssize_t request_reader_entries(
}
}
- r = output_journal(m->tmp, m->journal, m->mode, 0, OUTPUT_FULL_WIDTH);
+ r = output_journal(m->tmp, m->journal, m->mode, 0, OUTPUT_FULL_WIDTH, NULL);
if (r < 0) {
log_error("Failed to serialize item: %s", strerror(-r));
return MHD_CONTENT_READER_END_WITH_ERROR;
@@ -834,17 +834,17 @@ static int request_handler_machine(
"\"hostname\" : \"%s\","
"\"os_pretty_name\" : \"%s\","
"\"virtualization\" : \"%s\","
- "\"usage\" : \"%llu\","
- "\"cutoff_from_realtime\" : \"%llu\","
- "\"cutoff_to_realtime\" : \"%llu\" }\n",
+ "\"usage\" : \"%"PRIu64"\","
+ "\"cutoff_from_realtime\" : \"%"PRIu64"\","
+ "\"cutoff_to_realtime\" : \"%"PRIu64"\" }\n",
SD_ID128_FORMAT_VAL(mid),
SD_ID128_FORMAT_VAL(bid),
hostname_cleanup(hostname, false),
os_name ? os_name : "Linux",
v ? v : "bare",
- (unsigned long long) usage,
- (unsigned long long) cutoff_from,
- (unsigned long long) cutoff_to);
+ usage,
+ cutoff_from,
+ cutoff_to);
if (r < 0)
return respond_oom(connection);
diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h
index c7e585d810..5bc653537c 100644
--- a/src/journal/journal-internal.h
+++ b/src/journal/journal-internal.h
@@ -97,8 +97,6 @@ struct Directory {
};
struct sd_journal {
- int flags;
-
char *path;
Hashmap *files;
@@ -109,26 +107,29 @@ struct sd_journal {
JournalFile *current_file;
uint64_t current_field;
- Hashmap *directories_by_path;
- Hashmap *directories_by_wd;
-
- int inotify_fd;
-
Match *level0, *level1, *level2;
+ pid_t original_pid;
+
+ int inotify_fd;
unsigned current_invalidate_counter, last_invalidate_counter;
+ usec_t last_process_usec;
char *unique_field;
JournalFile *unique_file;
uint64_t unique_offset;
+ int flags;
+
bool on_network;
+ bool no_new_files;
size_t data_threshold;
- Set *errors;
+ Hashmap *directories_by_path;
+ Hashmap *directories_by_wd;
- usec_t last_process_usec;
+ Set *errors;
};
char *journal_make_match_string(sd_journal *j);
@@ -139,3 +140,6 @@ static inline void journal_closep(sd_journal **j) {
}
#define _cleanup_journal_close_ _cleanup_(journal_closep)
+
+#define JOURNAL_FOREACH_DATA_RETVAL(j, data, l, retval) \
+ for (sd_journal_restart_data(j); ((retval) = sd_journal_enumerate_data((j), &(data), &(l))) > 0; )
diff --git a/src/journal/journal-qrcode.c b/src/journal/journal-qrcode.c
index 10a14e4def..1db66e89c6 100644
--- a/src/journal/journal-qrcode.c
+++ b/src/journal/journal-qrcode.c
@@ -76,9 +76,9 @@ int print_qr_code(
fprintf(f, "%02x", ((uint8_t*) seed)[i]);
}
- fprintf(f, "/%llx-%llx?machine=" SD_ID128_FORMAT_STR,
- (unsigned long long) start,
- (unsigned long long) interval,
+ fprintf(f, "/%"PRIx64"-%"PRIx64"?machine=" SD_ID128_FORMAT_STR,
+ start,
+ interval,
SD_ID128_FORMAT_VAL(machine));
if (hn)
diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c
index 14c437da78..d00e26f1eb 100644
--- a/src/journal/journal-send.c
+++ b/src/journal/journal-send.c
@@ -204,8 +204,14 @@ _public_ int sd_journal_sendv(const struct iovec *iov, int n) {
struct iovec *w;
uint64_t *l;
int i, j = 0;
- struct msghdr mh;
- struct sockaddr_un sa;
+ struct sockaddr_un sa = {
+ .sun_family = AF_UNIX,
+ .sun_path = "/run/systemd/journal/socket",
+ };
+ struct msghdr mh = {
+ .msg_name = &sa,
+ .msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path),
+ };
ssize_t k;
union {
struct cmsghdr cmsghdr;
@@ -239,7 +245,7 @@ _public_ int sd_journal_sendv(const struct iovec *iov, int n) {
have_syslog_identifier = have_syslog_identifier ||
(c == (char *) iov[i].iov_base + 17 &&
- memcmp(iov[i].iov_base, "SYSLOG_IDENTIFIER", 17) == 0);
+ startswith(iov[i].iov_base, "SYSLOG_IDENTIFIER"));
nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len);
if (nl) {
@@ -292,13 +298,6 @@ _public_ int sd_journal_sendv(const struct iovec *iov, int n) {
if (_unlikely_(fd < 0))
return fd;
- zero(sa);
- sa.sun_family = AF_UNIX;
- strncpy(sa.sun_path, "/run/systemd/journal/socket", sizeof(sa.sun_path));
-
- zero(mh);
- mh.msg_name = &sa;
- mh.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path);
mh.msg_iov = w;
mh.msg_iovlen = j;
@@ -402,7 +401,10 @@ _public_ int sd_journal_perror(const char *message) {
}
_public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) {
- union sockaddr_union sa;
+ union sockaddr_union sa = {
+ .un.sun_family = AF_UNIX,
+ .un.sun_path = "/run/systemd/journal/stdout",
+ };
int fd;
char *header;
size_t l;
@@ -415,10 +417,6 @@ _public_ int sd_journal_stream_fd(const char *identifier, int priority, int leve
if (fd < 0)
return -errno;
- zero(sa);
- sa.un.sun_family = AF_UNIX;
- strncpy(sa.un.sun_path, "/run/systemd/journal/stdout", sizeof(sa.un.sun_path));
-
r = connect(fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
if (r < 0) {
close_nointr_nofail(fd);
diff --git a/src/journal/journal-vacuum.c b/src/journal/journal-vacuum.c
index 4a3a5a9e63..c73ad8f393 100644
--- a/src/journal/journal-vacuum.c
+++ b/src/journal/journal-vacuum.c
@@ -128,6 +128,25 @@ static void patch_realtime(
#endif
}
+static int journal_file_empty(int dir_fd, const char *name) {
+ int r;
+ le64_t n_entries;
+ _cleanup_close_ int fd;
+
+ fd = openat(dir_fd, name, O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NONBLOCK);
+ if (fd < 0)
+ return -errno;
+
+ if (lseek(fd, offsetof(Header, n_entries), SEEK_SET) < 0)
+ return -errno;
+
+ r = read(fd, &n_entries, sizeof(n_entries));
+ if (r != sizeof(n_entries))
+ return r == 0 ? -EINVAL : -errno;
+
+ return le64toh(n_entries) == 0;
+}
+
int journal_directory_vacuum(
const char *directory,
uint64_t max_use,
@@ -135,11 +154,12 @@ int journal_directory_vacuum(
usec_t max_retention_usec,
usec_t *oldest_usec) {
- DIR *d;
+ _cleanup_closedir_ DIR *d = NULL;
int r = 0;
struct vacuum_info *list = NULL;
- unsigned n_list = 0, n_allocated = 0, i;
- uint64_t sum = 0;
+ unsigned n_list = 0, i;
+ size_t n_allocated = 0;
+ uint64_t sum = 0, freed = 0;
usec_t retention_limit = 0;
assert(directory);
@@ -246,22 +266,25 @@ int journal_directory_vacuum(
/* We do not vacuum active files or unknown files! */
continue;
- patch_realtime(directory, de->d_name, &st, &realtime);
+ if (journal_file_empty(dirfd(d), p)) {
+ /* Always vacuum empty non-online files. */
- if (n_list >= n_allocated) {
- struct vacuum_info *j;
+ uint64_t size = 512UL * (uint64_t) st.st_blocks;
- n_allocated = MAX(n_allocated * 2U, 8U);
- j = realloc(list, n_allocated * sizeof(struct vacuum_info));
- if (!j) {
- free(p);
- r = -ENOMEM;
- goto finish;
- }
+ if (unlinkat(dirfd(d), p, 0) >= 0) {
+ log_info("Deleted empty journal %s/%s (%"PRIu64" bytes).",
+ directory, p, size);
+ freed += size;
+ } else if (errno != ENOENT)
+ log_warning("Failed to delete %s/%s: %m", directory, p);
- list = j;
+ continue;
}
+ patch_realtime(directory, p, &st, &realtime);
+
+ GREEDY_REALLOC(list, n_allocated, n_list + 1);
+
list[n_list].filename = p;
list[n_list].usage = 512UL * (uint64_t) st.st_blocks;
list[n_list].seqnum = seqnum;
@@ -291,7 +314,9 @@ int journal_directory_vacuum(
break;
if (unlinkat(dirfd(d), list[i].filename, 0) >= 0) {
- log_debug("Deleted archived journal %s/%s.", directory, list[i].filename);
+ log_debug("Deleted archived journal %s/%s (%"PRIu64" bytes).",
+ directory, list[i].filename, list[i].usage);
+ freed += list[i].usage;
if (list[i].usage < sum)
sum -= list[i].usage;
@@ -308,11 +333,9 @@ int journal_directory_vacuum(
finish:
for (i = 0; i < n_list; i++)
free(list[i].filename);
-
free(list);
- if (d)
- closedir(d);
+ log_info("Vacuuming done, freed %"PRIu64" bytes", freed);
return r;
}
diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
index ed28b45737..3405811534 100644
--- a/src/journal/journal-verify.c
+++ b/src/journal/journal-verify.c
@@ -34,10 +34,15 @@
#include "compress.h"
#include "fsprg.h"
-static int journal_file_object_verify(JournalFile *f, Object *o) {
+/* Use six characters to cover the offsets common in smallish journal
+ * files without adding to many zeros. */
+#define OFSfmt "%06"PRIx64
+
+static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o) {
uint64_t i;
assert(f);
+ assert(offset);
assert(o);
/* This does various superficial tests about the length an
@@ -53,12 +58,21 @@ static int journal_file_object_verify(JournalFile *f, Object *o) {
case OBJECT_DATA: {
uint64_t h1, h2;
- if (le64toh(o->data.entry_offset) <= 0 ||
- le64toh(o->data.n_entries) <= 0)
+ if (le64toh(o->data.entry_offset) == 0)
+ log_warning(OFSfmt": unused data (entry_offset==0)", offset);
+
+ if ((le64toh(o->data.entry_offset) == 0) ^ (le64toh(o->data.n_entries) == 0)) {
+ log_error(OFSfmt": bad n_entries: %"PRIu64, offset, o->data.n_entries);
return -EBADMSG;
+ }
- if (le64toh(o->object.size) - offsetof(DataObject, payload) <= 0)
+ if (le64toh(o->object.size) - offsetof(DataObject, payload) <= 0) {
+ log_error(OFSfmt": bad object size (<= %zu): %"PRIu64,
+ offset,
+ offsetof(DataObject, payload),
+ le64toh(o->object.size));
return -EBADMSG;
+ }
h1 = le64toh(o->data.hash);
@@ -69,104 +83,197 @@ static int journal_file_object_verify(JournalFile *f, Object *o) {
if (!uncompress_blob(o->data.payload,
le64toh(o->object.size) - offsetof(Object, data.payload),
- &b, &alloc, &b_size, 0))
+ &b, &alloc, &b_size, 0)) {
+ log_error(OFSfmt": uncompression failed", offset);
return -EBADMSG;
+ }
h2 = hash64(b, b_size);
free(b);
#else
+ log_error("Compression is not supported");
return -EPROTONOSUPPORT;
#endif
} else
h2 = hash64(o->data.payload, le64toh(o->object.size) - offsetof(Object, data.payload));
- if (h1 != h2)
+ if (h1 != h2) {
+ log_error(OFSfmt": invalid hash (%08"PRIx64" vs. %08"PRIx64, offset, h1, h2);
return -EBADMSG;
+ }
if (!VALID64(o->data.next_hash_offset) ||
!VALID64(o->data.next_field_offset) ||
!VALID64(o->data.entry_offset) ||
- !VALID64(o->data.entry_array_offset))
+ !VALID64(o->data.entry_array_offset)) {
+ log_error(OFSfmt": invalid offset (next_hash_offset="OFSfmt", next_field_offset="OFSfmt", entry_offset="OFSfmt", entry_array_offset="OFSfmt,
+ offset,
+ o->data.next_hash_offset,
+ o->data.next_field_offset,
+ o->data.entry_offset,
+ o->data.entry_array_offset);
return -EBADMSG;
+ }
break;
}
case OBJECT_FIELD:
- if (le64toh(o->object.size) - offsetof(FieldObject, payload) <= 0)
+ if (le64toh(o->object.size) - offsetof(FieldObject, payload) <= 0) {
+ log_error(OFSfmt": bad field size (<= %zu): %"PRIu64,
+ offset,
+ offsetof(FieldObject, payload),
+ le64toh(o->object.size));
return -EBADMSG;
+ }
if (!VALID64(o->field.next_hash_offset) ||
- !VALID64(o->field.head_data_offset))
+ !VALID64(o->field.head_data_offset)) {
+ log_error(OFSfmt": invalid offset (next_hash_offset="OFSfmt", head_data_offset="OFSfmt,
+ offset,
+ o->field.next_hash_offset,
+ o->field.head_data_offset);
return -EBADMSG;
+ }
break;
case OBJECT_ENTRY:
- if ((le64toh(o->object.size) - offsetof(EntryObject, items)) % sizeof(EntryItem) != 0)
+ if ((le64toh(o->object.size) - offsetof(EntryObject, items)) % sizeof(EntryItem) != 0) {
+ log_error(OFSfmt": bad entry size (<= %zu): %"PRIu64,
+ offset,
+ offsetof(EntryObject, items),
+ le64toh(o->object.size));
return -EBADMSG;
+ }
- if ((le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem) <= 0)
+ if ((le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem) <= 0) {
+ log_error(OFSfmt": invalid number items in entry: %"PRIu64,
+ offset,
+ (le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem));
return -EBADMSG;
+ }
+
+ if (le64toh(o->entry.seqnum) <= 0) {
+ log_error(OFSfmt": invalid entry seqnum: %"PRIx64,
+ offset,
+ le64toh(o->entry.seqnum));
+ return -EBADMSG;
+ }
- if (le64toh(o->entry.seqnum) <= 0 ||
- !VALID_REALTIME(le64toh(o->entry.realtime)) ||
- !VALID_MONOTONIC(le64toh(o->entry.monotonic)))
+ if (!VALID_REALTIME(le64toh(o->entry.realtime))) {
+ log_error(OFSfmt": invalid entry realtime timestamp: %"PRIu64,
+ offset,
+ le64toh(o->entry.realtime));
return -EBADMSG;
+ }
+
+ if (!VALID_MONOTONIC(le64toh(o->entry.monotonic))) {
+ log_error(OFSfmt": invalid entry monotonic timestamp: %"PRIu64,
+ offset,
+ le64toh(o->entry.monotonic));
+ return -EBADMSG;
+ }
for (i = 0; i < journal_file_entry_n_items(o); i++) {
if (o->entry.items[i].object_offset == 0 ||
- !VALID64(o->entry.items[i].object_offset))
+ !VALID64(o->entry.items[i].object_offset)) {
+ log_error(OFSfmt": invalid entry item (%"PRIu64"/%"PRIu64" offset: "OFSfmt,
+ offset,
+ i, journal_file_entry_n_items(o),
+ o->entry.items[i].object_offset);
return -EBADMSG;
+ }
}
break;
case OBJECT_DATA_HASH_TABLE:
case OBJECT_FIELD_HASH_TABLE:
- if ((le64toh(o->object.size) - offsetof(HashTableObject, items)) % sizeof(HashItem) != 0)
- return -EBADMSG;
-
- if ((le64toh(o->object.size) - offsetof(HashTableObject, items)) / sizeof(HashItem) <= 0)
+ if ((le64toh(o->object.size) - offsetof(HashTableObject, items)) % sizeof(HashItem) != 0 ||
+ (le64toh(o->object.size) - offsetof(HashTableObject, items)) / sizeof(HashItem) <= 0) {
+ log_error(OFSfmt": invalid %s hash table size: %"PRIu64,
+ offset,
+ o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field",
+ le64toh(o->object.size));
return -EBADMSG;
+ }
for (i = 0; i < journal_file_hash_table_n_items(o); i++) {
if (o->hash_table.items[i].head_hash_offset != 0 &&
- !VALID64(le64toh(o->hash_table.items[i].head_hash_offset)))
+ !VALID64(le64toh(o->hash_table.items[i].head_hash_offset))) {
+ log_error(OFSfmt": invalid %s hash table item (%"PRIu64"/%"PRIu64") head_hash_offset: "OFSfmt,
+ offset,
+ o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field",
+ i, journal_file_hash_table_n_items(o),
+ le64toh(o->hash_table.items[i].head_hash_offset));
return -EBADMSG;
+ }
if (o->hash_table.items[i].tail_hash_offset != 0 &&
- !VALID64(le64toh(o->hash_table.items[i].tail_hash_offset)))
+ !VALID64(le64toh(o->hash_table.items[i].tail_hash_offset))) {
+ log_error(OFSfmt": invalid %s hash table item (%"PRIu64"/%"PRIu64") tail_hash_offset: "OFSfmt,
+ offset,
+ o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field",
+ i, journal_file_hash_table_n_items(o),
+ le64toh(o->hash_table.items[i].tail_hash_offset));
return -EBADMSG;
+ }
if ((o->hash_table.items[i].head_hash_offset != 0) !=
- (o->hash_table.items[i].tail_hash_offset != 0))
+ (o->hash_table.items[i].tail_hash_offset != 0)) {
+ log_error(OFSfmt": invalid %s hash table item (%"PRIu64"/%"PRIu64"): head_hash_offset="OFSfmt" tail_hash_offset="OFSfmt,
+ offset,
+ o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field",
+ i, journal_file_hash_table_n_items(o),
+ le64toh(o->hash_table.items[i].head_hash_offset),
+ le64toh(o->hash_table.items[i].tail_hash_offset));
return -EBADMSG;
+ }
}
break;
case OBJECT_ENTRY_ARRAY:
- if ((le64toh(o->object.size) - offsetof(EntryArrayObject, items)) % sizeof(le64_t) != 0)
- return -EBADMSG;
-
- if ((le64toh(o->object.size) - offsetof(EntryArrayObject, items)) / sizeof(le64_t) <= 0)
+ if ((le64toh(o->object.size) - offsetof(EntryArrayObject, items)) % sizeof(le64_t) != 0 ||
+ (le64toh(o->object.size) - offsetof(EntryArrayObject, items)) / sizeof(le64_t) <= 0) {
+ log_error(OFSfmt": invalid object entry array size: %"PRIu64,
+ offset,
+ le64toh(o->object.size));
return -EBADMSG;
+ }
- if (!VALID64(o->entry_array.next_entry_array_offset))
+ if (!VALID64(o->entry_array.next_entry_array_offset)) {
+ log_error(OFSfmt": invalid object entry array next_entry_array_offset: "OFSfmt,
+ offset,
+ o->entry_array.next_entry_array_offset);
return -EBADMSG;
+ }
for (i = 0; i < journal_file_entry_array_n_items(o); i++)
if (o->entry_array.items[i] != 0 &&
- !VALID64(o->entry_array.items[i]))
+ !VALID64(o->entry_array.items[i])) {
+ log_error(OFSfmt": invalid object entry array item (%"PRIu64"/%"PRIu64"): "OFSfmt,
+ offset,
+ i, journal_file_entry_array_n_items(o),
+ o->entry_array.items[i]);
return -EBADMSG;
+ }
break;
case OBJECT_TAG:
- if (le64toh(o->object.size) != sizeof(TagObject))
+ if (le64toh(o->object.size) != sizeof(TagObject)) {
+ log_error(OFSfmt": invalid object tag size: %"PRIu64,
+ offset,
+ le64toh(o->object.size));
return -EBADMSG;
+ }
- if (!VALID_EPOCH(o->tag.epoch))
+ if (!VALID_EPOCH(o->tag.epoch)) {
+ log_error(OFSfmt": invalid object tag epoch: %"PRIu64,
+ offset,
+ o->tag.epoch);
return -EBADMSG;
+ }
break;
}
@@ -203,7 +310,7 @@ static void draw_progress(uint64_t p, usec_t *last_usec) {
for (i = 0; i < k; i++)
fputs("\xe2\x96\x91", stdout);
- printf(" %3lu%%", 100LU * (unsigned long) p / 65535LU);
+ printf(" %3"PRIu64"%%", 100U * p / 65535U);
fputs("\r\x1B[?25h", stdout);
fflush(stdout);
@@ -288,7 +395,7 @@ static int entry_points_to_data(
assert(entry_fd >= 0);
if (!contains_uint64(f->mmap, entry_fd, n_entries, entry_p)) {
- log_error("Data object references invalid entry at %llu", (unsigned long long) data_p);
+ log_error("Data object references invalid entry at %"PRIu64, data_p);
return -EBADMSG;
}
@@ -304,7 +411,7 @@ static int entry_points_to_data(
}
if (!found) {
- log_error("Data object not referenced by linked entry at %llu", (unsigned long long) data_p);
+ log_error("Data object not referenced by linked entry at %"PRIu64, data_p);
return -EBADMSG;
}
@@ -347,7 +454,7 @@ static int entry_points_to_data(
x = z;
}
- log_error("Entry object doesn't exist in main entry array at %llu", (unsigned long long) entry_p);
+ log_error("Entry object doesn't exist in main entry array at %"PRIu64, entry_p);
return -EBADMSG;
}
@@ -375,8 +482,18 @@ static int verify_data(
n = le64toh(o->data.n_entries);
a = le64toh(o->data.entry_array_offset);
- /* We already checked this earlier */
- assert(n > 0);
+ /* Entry array means at least two objects */
+ if (a && n < 2) {
+ log_error("Entry array present (entry_array_offset=%"PRIu64", but n_entries=%"PRIu64,
+ a, n);
+ return -EBADMSG;
+ }
+
+ if (n == 0)
+ return 0;
+
+ /* We already checked that earlier */
+ assert(o->data.entry_offset);
last = q = le64toh(o->data.entry_offset);
r = entry_points_to_data(f, entry_fd, n_entries, q, p);
@@ -388,12 +505,12 @@ static int verify_data(
uint64_t next, m, j;
if (a == 0) {
- log_error("Array chain too short at %llu", (unsigned long long) p);
+ log_error("Array chain too short at %"PRIu64, p);
return -EBADMSG;
}
if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) {
- log_error("Invalid array at %llu", (unsigned long long) p);
+ log_error("Invalid array at %"PRIu64, p);
return -EBADMSG;
}
@@ -403,7 +520,7 @@ static int verify_data(
next = le64toh(o->entry_array.next_entry_array_offset);
if (next != 0 && next <= a) {
- log_error("Array chain has cycle at %llu", (unsigned long long) p);
+ log_error("Array chain has cycle at %"PRIu64, p);
return -EBADMSG;
}
@@ -412,7 +529,7 @@ static int verify_data(
q = le64toh(o->entry_array.items[j]);
if (q <= last) {
- log_error("Data object's entry array not sorted at %llu", (unsigned long long) p);
+ log_error("Data object's entry array not sorted at %"PRIu64, p);
return -EBADMSG;
}
last = q;
@@ -463,8 +580,8 @@ static int verify_hash_table(
uint64_t next;
if (!contains_uint64(f->mmap, data_fd, n_data, p)) {
- log_error("Invalid data object at hash entry %llu of %llu",
- (unsigned long long) i, (unsigned long long) n);
+ log_error("Invalid data object at hash entry %"PRIu64" of %"PRIu64,
+ i, n);
return -EBADMSG;
}
@@ -474,14 +591,14 @@ static int verify_hash_table(
next = le64toh(o->data.next_hash_offset);
if (next != 0 && next <= p) {
- log_error("Hash chain has a cycle in hash entry %llu of %llu",
- (unsigned long long) i, (unsigned long long) n);
+ log_error("Hash chain has a cycle in hash entry %"PRIu64" of %"PRIu64,
+ i, n);
return -EBADMSG;
}
if (le64toh(o->data.hash) % n != i) {
- log_error("Hash value mismatch in hash entry %llu of %llu",
- (unsigned long long) i, (unsigned long long) n);
+ log_error("Hash value mismatch in hash entry %"PRIu64" of %"PRIu64,
+ i, n);
return -EBADMSG;
}
@@ -548,8 +665,7 @@ static int verify_entry(
h = le64toh(o->entry.items[i].hash);
if (!contains_uint64(f->mmap, data_fd, n_data, q)) {
- log_error("Invalid data object at entry %llu",
- (unsigned long long) p);
+ log_error("Invalid data object at entry %"PRIu64, p);
return -EBADMSG;
}
@@ -558,8 +674,7 @@ static int verify_entry(
return r;
if (le64toh(u->data.hash) != h) {
- log_error("Hash mismatch for data object at entry %llu",
- (unsigned long long) p);
+ log_error("Hash mismatch for data object at entry %"PRIu64, p);
return -EBADMSG;
}
@@ -567,8 +682,7 @@ static int verify_entry(
if (r < 0)
return r;
if (r == 0) {
- log_error("Data object missing from hash at entry %llu",
- (unsigned long long) p);
+ log_error("Data object missing from hash at entry %"PRIu64, p);
return -EBADMSG;
}
}
@@ -603,14 +717,12 @@ static int verify_entry_array(
draw_progress(0x8000 + (0x3FFF * i / n), last_usec);
if (a == 0) {
- log_error("Array chain too short at %llu of %llu",
- (unsigned long long) i, (unsigned long long) n);
+ log_error("Array chain too short at %"PRIu64" of %"PRIu64, i, n);
return -EBADMSG;
}
if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) {
- log_error("Invalid array at %llu of %llu",
- (unsigned long long) i, (unsigned long long) n);
+ log_error("Invalid array at %"PRIu64" of %"PRIu64, i, n);
return -EBADMSG;
}
@@ -620,8 +732,7 @@ static int verify_entry_array(
next = le64toh(o->entry_array.next_entry_array_offset);
if (next != 0 && next <= a) {
- log_error("Array chain has cycle at %llu of %llu",
- (unsigned long long) i, (unsigned long long) n);
+ log_error("Array chain has cycle at %"PRIu64" of %"PRIu64, i, n);
return -EBADMSG;
}
@@ -631,15 +742,15 @@ static int verify_entry_array(
p = le64toh(o->entry_array.items[j]);
if (p <= last) {
- log_error("Entry array not sorted at %llu of %llu",
- (unsigned long long) i, (unsigned long long) n);
+ log_error("Entry array not sorted at %"PRIu64" of %"PRIu64,
+ i, n);
return -EBADMSG;
}
last = p;
if (!contains_uint64(f->mmap, entry_fd, n_entries, p)) {
- log_error("Invalid array entry at %llu of %llu",
- (unsigned long long) i, (unsigned long long) n);
+ log_error("Invalid array entry at %"PRIu64" of %"PRIu64,
+ i, n);
return -EBADMSG;
}
@@ -753,7 +864,7 @@ int journal_file_verify(
r = journal_file_move_to_object(f, -1, p, &o);
if (r < 0) {
- log_error("Invalid object at %llu", (unsigned long long) p);
+ log_error("Invalid object at "OFSfmt, p);
goto fail;
}
@@ -768,14 +879,14 @@ int journal_file_verify(
n_objects ++;
- r = journal_file_object_verify(f, o);
+ r = journal_file_object_verify(f, p, o);
if (r < 0) {
- log_error("Invalid object contents at %llu", (unsigned long long) p);
+ log_error("Invalid object contents at "OFSfmt": %s", p, strerror(-r));
goto fail;
}
if ((o->object.flags & OBJECT_COMPRESSED) && !JOURNAL_HEADER_COMPRESSED(f->header)) {
- log_error("Compressed object in file without compression at %llu", (unsigned long long) p);
+ log_error("Compressed object in file without compression at "OFSfmt, p);
r = -EBADMSG;
goto fail;
}
@@ -796,7 +907,7 @@ int journal_file_verify(
case OBJECT_ENTRY:
if (JOURNAL_HEADER_SEALED(f->header) && n_tags <= 0) {
- log_error("First entry before first tag at %llu", (unsigned long long) p);
+ log_error("First entry before first tag at "OFSfmt, p);
r = -EBADMSG;
goto fail;
}
@@ -806,21 +917,21 @@ int journal_file_verify(
goto fail;
if (le64toh(o->entry.realtime) < last_tag_realtime) {
- log_error("Older entry after newer tag at %llu", (unsigned long long) p);
+ log_error("Older entry after newer tag at "OFSfmt, p);
r = -EBADMSG;
goto fail;
}
if (!entry_seqnum_set &&
le64toh(o->entry.seqnum) != le64toh(f->header->head_entry_seqnum)) {
- log_error("Head entry sequence number incorrect at %llu", (unsigned long long) p);
+ log_error("Head entry sequence number incorrect at "OFSfmt, p);
r = -EBADMSG;
goto fail;
}
if (entry_seqnum_set &&
entry_seqnum >= le64toh(o->entry.seqnum)) {
- log_error("Entry sequence number out of synchronization at %llu", (unsigned long long) p);
+ log_error("Entry sequence number out of synchronization at "OFSfmt, p);
r = -EBADMSG;
goto fail;
}
@@ -831,7 +942,7 @@ int journal_file_verify(
if (entry_monotonic_set &&
sd_id128_equal(entry_boot_id, o->entry.boot_id) &&
entry_monotonic > le64toh(o->entry.monotonic)) {
- log_error("Entry timestamp out of synchronization at %llu", (unsigned long long) p);
+ log_error("Entry timestamp out of synchronization at "OFSfmt, p);
r = -EBADMSG;
goto fail;
}
@@ -855,7 +966,7 @@ int journal_file_verify(
case OBJECT_DATA_HASH_TABLE:
if (n_data_hash_tables > 1) {
- log_error("More than one data hash table at %llu", (unsigned long long) p);
+ log_error("More than one data hash table at "OFSfmt, p);
r = -EBADMSG;
goto fail;
}
@@ -872,7 +983,7 @@ int journal_file_verify(
case OBJECT_FIELD_HASH_TABLE:
if (n_field_hash_tables > 1) {
- log_error("More than one field hash table at %llu", (unsigned long long) p);
+ log_error("More than one field hash table at "OFSfmt, p);
r = -EBADMSG;
goto fail;
}
@@ -894,7 +1005,7 @@ int journal_file_verify(
if (p == le64toh(f->header->entry_array_offset)) {
if (found_main_entry_array) {
- log_error("More than one main entry array at %llu", (unsigned long long) p);
+ log_error("More than one main entry array at "OFSfmt, p);
r = -EBADMSG;
goto fail;
}
@@ -907,19 +1018,19 @@ int journal_file_verify(
case OBJECT_TAG:
if (!JOURNAL_HEADER_SEALED(f->header)) {
- log_error("Tag object in file without sealing at %llu", (unsigned long long) p);
+ log_error("Tag object in file without sealing at "OFSfmt, p);
r = -EBADMSG;
goto fail;
}
if (le64toh(o->tag.seqnum) != n_tags + 1) {
- log_error("Tag sequence number out of synchronization at %llu", (unsigned long long) p);
+ log_error("Tag sequence number out of synchronization at "OFSfmt, p);
r = -EBADMSG;
goto fail;
}
if (le64toh(o->tag.epoch) < last_epoch) {
- log_error("Epoch sequence out of synchronization at %llu", (unsigned long long) p);
+ log_error("Epoch sequence out of synchronization at "OFSfmt, p);
r = -EBADMSG;
goto fail;
}
@@ -928,11 +1039,11 @@ int journal_file_verify(
if (f->seal) {
uint64_t q, rt;
- log_debug("Checking tag %llu..", (unsigned long long) le64toh(o->tag.seqnum));
+ log_debug("Checking tag %"PRIu64"...", le64toh(o->tag.seqnum));
rt = f->fss_start_usec + o->tag.epoch * f->fss_interval_usec;
if (entry_realtime_set && entry_realtime >= rt + f->fss_interval_usec) {
- log_error("Tag/entry realtime timestamp out of synchronization at %llu", (unsigned long long) p);
+ log_error("Tag/entry realtime timestamp out of synchronization at "OFSfmt, p);
r = -EBADMSG;
goto fail;
}
@@ -975,7 +1086,7 @@ int journal_file_verify(
goto fail;
if (memcmp(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH) != 0) {
- log_error("Tag failed verification at %llu", (unsigned long long) p);
+ log_error("Tag failed verification at "OFSfmt, p);
r = -EBADMSG;
goto fail;
}
@@ -1138,11 +1249,11 @@ fail:
if (show_progress)
flush_progress();
- log_error("File corruption detected at %s:%llu (of %llu, %llu%%).",
+ log_error("File corruption detected at %s:"OFSfmt" (of %llu bytes, %"PRIu64"%%).",
f->path,
- (unsigned long long) p,
+ p,
(unsigned long long) f->last_stat.st_size,
- (unsigned long long) (100 * p / f->last_stat.st_size));
+ 100 * p / f->last_stat.st_size);
if (data_fd >= 0) {
mmap_cache_close_fd(f->mmap, data_fd);
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index 409f082276..9a2d255361 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -45,6 +45,7 @@
#include "logs-show.h"
#include "util.h"
#include "path-util.h"
+#include "fileio.h"
#include "build.h"
#include "pager.h"
#include "logs-show.h"
@@ -70,13 +71,19 @@ static int arg_lines = -1;
static bool arg_no_tail = false;
static bool arg_quiet = false;
static bool arg_merge = false;
-static bool arg_this_boot = false;
+static bool arg_boot = false;
+static char *arg_boot_descriptor = NULL;
+static bool arg_dmesg = false;
static const char *arg_cursor = NULL;
+static const char *arg_after_cursor = NULL;
+static bool arg_show_cursor = false;
static const char *arg_directory = NULL;
+static char **arg_file = NULL;
static int arg_priorities = 0xFF;
static const char *arg_verify_key = NULL;
#ifdef HAVE_GCRYPT
static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
+static bool arg_force = false;
#endif
static usec_t arg_since, arg_until;
static bool arg_since_set = false, arg_until_set = false;
@@ -85,6 +92,7 @@ static char **arg_user_units = NULL;
static const char *arg_field = NULL;
static bool arg_catalog = false;
static bool arg_reverse = false;
+static int arg_journal_type = 0;
static const char *arg_root = NULL;
static enum {
@@ -99,50 +107,63 @@ static enum {
ACTION_UPDATE_CATALOG
} arg_action = ACTION_SHOW;
+typedef struct boot_id_t {
+ sd_id128_t id;
+ uint64_t timestamp;
+} boot_id_t;
+
static int help(void) {
printf("%s [OPTIONS...] [MATCHES...]\n\n"
"Query the journal.\n\n"
"Flags:\n"
- " --since=DATE Start showing entries newer or of the specified date\n"
- " --until=DATE Stop showing entries older or of the specified date\n"
- " -c --cursor=CURSOR Start showing entries from specified cursor\n"
- " -b --this-boot Show data only from current boot\n"
- " -u --unit=UNIT Show data only from the specified unit\n"
- " --user-unit=UNIT Show data only from the specified user session unit\n"
- " -p --priority=RANGE Show only messages within the specified priority range\n"
- " -e --pager-end Immediately jump to end of the journal in the pager\n"
- " -f --follow Follow journal\n"
- " -n --lines[=INTEGER] Number of journal entries to show\n"
- " --no-tail Show all lines, even in follow mode\n"
- " -r --reverse Show the newest entries first\n"
- " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
- " verbose, export, json, json-pretty, json-sse, cat)\n"
- " -x --catalog Add message explanations where available\n"
- " --full Do not ellipsize fields\n"
- " -a --all Show all fields, including long and unprintable\n"
- " -q --quiet Don't show privilege warning\n"
- " --no-pager Do not pipe output into a pager\n"
- " -m --merge Show entries from all available journals\n"
- " -D --directory=PATH Show journal files from directory\n"
- " --root=ROOT Operate on catalog files underneath the root ROOT\n"
+ " --system Show only the system journal\n"
+ " --user Show only the user journal for current user\n"
+ " --since=DATE Start showing entries newer or of the specified date\n"
+ " --until=DATE Stop showing entries older or of the specified date\n"
+ " -c --cursor=CURSOR Start showing entries from specified cursor\n"
+ " --after-cursor=CURSOR Start showing entries from specified cursor\n"
+ " --show-cursor Print the cursor after all the entries\n"
+ " -b --boot[=ID] Show data only from ID or current boot if unspecified\n"
+ " -k --dmesg Show kernel message log from current boot\n"
+ " -u --unit=UNIT Show data only from the specified unit\n"
+ " --user-unit=UNIT Show data only from the specified user session unit\n"
+ " -p --priority=RANGE Show only messages within the specified priority range\n"
+ " -e --pager-end Immediately jump to end of the journal in the pager\n"
+ " -f --follow Follow journal\n"
+ " -n --lines[=INTEGER] Number of journal entries to show\n"
+ " --no-tail Show all lines, even in follow mode\n"
+ " -r --reverse Show the newest entries first\n"
+ " -o --output=STRING Change journal output mode (short, short-iso,\n"
+ " short-precise, short-monotonic, verbose,\n"
+ " export, json, json-pretty, json-sse, cat)\n"
+ " -x --catalog Add message explanations where available\n"
+ " -l --full Do not ellipsize fields\n"
+ " -a --all Show all fields, including long and unprintable\n"
+ " -q --quiet Don't show privilege warning\n"
+ " --no-pager Do not pipe output into a pager\n"
+ " -m --merge Show entries from all available journals\n"
+ " -D --directory=PATH Show journal files from directory\n"
+ " --file=PATH Show journal file\n"
+ " --root=ROOT Operate on catalog files underneath the root ROOT\n"
#ifdef HAVE_GCRYPT
- " --interval=TIME Time interval for changing the FSS sealing key\n"
- " --verify-key=KEY Specify FSS verification key\n"
+ " --interval=TIME Time interval for changing the FSS sealing key\n"
+ " --verify-key=KEY Specify FSS verification key\n"
+ " --force Force overriding new FSS key pair with --setup-keys\n"
#endif
"\nCommands:\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --new-id128 Generate a new 128 Bit ID\n"
- " --header Show journal header information\n"
- " --disk-usage Show total disk usage\n"
- " -F --field=FIELD List all values a certain field takes\n"
- " --list-catalog Show message IDs of all entries in the message catalog\n"
- " --dump-catalog Show entries in the message catalog\n"
- " --update-catalog Update the message catalog database\n"
+ " -h --help Show this help\n"
+ " --version Show package version\n"
+ " --new-id128 Generate a new 128 Bit ID\n"
+ " --header Show journal header information\n"
+ " --disk-usage Show total disk usage\n"
+ " -F --field=FIELD List all values a certain field takes\n"
+ " --list-catalog Show message IDs of all entries in the message catalog\n"
+ " --dump-catalog Show entries in the message catalog\n"
+ " --update-catalog Update the message catalog database\n"
#ifdef HAVE_GCRYPT
- " --setup-keys Generate new FSS key pair\n"
- " --verify Verify journal file consistency\n"
+ " --setup-keys Generate new FSS key pair\n"
+ " --verify Verify journal file consistency\n"
#endif
, program_invocation_short_name);
@@ -156,58 +177,71 @@ static int parse_argv(int argc, char *argv[]) {
ARG_NO_PAGER,
ARG_NO_TAIL,
ARG_NEW_ID128,
+ ARG_USER,
+ ARG_SYSTEM,
ARG_ROOT,
ARG_HEADER,
- ARG_FULL,
ARG_SETUP_KEYS,
+ ARG_FILE,
ARG_INTERVAL,
ARG_VERIFY,
ARG_VERIFY_KEY,
ARG_DISK_USAGE,
ARG_SINCE,
ARG_UNTIL,
+ ARG_AFTER_CURSOR,
+ ARG_SHOW_CURSOR,
ARG_USER_UNIT,
ARG_LIST_CATALOG,
ARG_DUMP_CATALOG,
- ARG_UPDATE_CATALOG
+ ARG_UPDATE_CATALOG,
+ ARG_FORCE,
};
static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version" , no_argument, NULL, ARG_VERSION },
- { "no-pager", no_argument, NULL, ARG_NO_PAGER },
- { "pager-end", no_argument, NULL, 'e' },
- { "follow", no_argument, NULL, 'f' },
- { "output", required_argument, NULL, 'o' },
- { "all", no_argument, NULL, 'a' },
- { "full", no_argument, NULL, ARG_FULL },
- { "lines", optional_argument, NULL, 'n' },
- { "no-tail", no_argument, NULL, ARG_NO_TAIL },
- { "new-id128", no_argument, NULL, ARG_NEW_ID128 },
- { "quiet", no_argument, NULL, 'q' },
- { "merge", no_argument, NULL, 'm' },
- { "this-boot", no_argument, NULL, 'b' },
- { "directory", required_argument, NULL, 'D' },
- { "root", required_argument, NULL, ARG_ROOT },
- { "header", no_argument, NULL, ARG_HEADER },
- { "priority", required_argument, NULL, 'p' },
- { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS },
- { "interval", required_argument, NULL, ARG_INTERVAL },
- { "verify", no_argument, NULL, ARG_VERIFY },
- { "verify-key", required_argument, NULL, ARG_VERIFY_KEY },
- { "disk-usage", no_argument, NULL, ARG_DISK_USAGE },
- { "cursor", required_argument, NULL, 'c' },
- { "since", required_argument, NULL, ARG_SINCE },
- { "until", required_argument, NULL, ARG_UNTIL },
- { "unit", required_argument, NULL, 'u' },
- { "user-unit", required_argument, NULL, ARG_USER_UNIT },
- { "field", required_argument, NULL, 'F' },
- { "catalog", no_argument, NULL, 'x' },
- { "list-catalog", no_argument, NULL, ARG_LIST_CATALOG },
- { "dump-catalog", no_argument, NULL, ARG_DUMP_CATALOG },
- { "update-catalog",no_argument, NULL, ARG_UPDATE_CATALOG },
- { "reverse", no_argument, NULL, 'r' },
- { NULL, 0, NULL, 0 }
+ { "help", no_argument, NULL, 'h' },
+ { "version" , no_argument, NULL, ARG_VERSION },
+ { "no-pager", no_argument, NULL, ARG_NO_PAGER },
+ { "pager-end", no_argument, NULL, 'e' },
+ { "follow", no_argument, NULL, 'f' },
+ { "force", no_argument, NULL, ARG_FORCE },
+ { "output", required_argument, NULL, 'o' },
+ { "all", no_argument, NULL, 'a' },
+ { "full", no_argument, NULL, 'l' },
+ { "lines", optional_argument, NULL, 'n' },
+ { "no-tail", no_argument, NULL, ARG_NO_TAIL },
+ { "new-id128", no_argument, NULL, ARG_NEW_ID128 },
+ { "quiet", no_argument, NULL, 'q' },
+ { "merge", no_argument, NULL, 'm' },
+ { "boot", optional_argument, NULL, 'b' },
+ { "this-boot", optional_argument, NULL, 'b' }, /* deprecated */
+ { "dmesg", no_argument, NULL, 'k' },
+ { "system", no_argument, NULL, ARG_SYSTEM },
+ { "user", no_argument, NULL, ARG_USER },
+ { "directory", required_argument, NULL, 'D' },
+ { "file", required_argument, NULL, ARG_FILE },
+ { "root", required_argument, NULL, ARG_ROOT },
+ { "header", no_argument, NULL, ARG_HEADER },
+ { "priority", required_argument, NULL, 'p' },
+ { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS },
+ { "interval", required_argument, NULL, ARG_INTERVAL },
+ { "verify", no_argument, NULL, ARG_VERIFY },
+ { "verify-key", required_argument, NULL, ARG_VERIFY_KEY },
+ { "disk-usage", no_argument, NULL, ARG_DISK_USAGE },
+ { "cursor", required_argument, NULL, 'c' },
+ { "after-cursor", required_argument, NULL, ARG_AFTER_CURSOR },
+ { "show-cursor", no_argument, NULL, ARG_SHOW_CURSOR },
+ { "since", required_argument, NULL, ARG_SINCE },
+ { "until", required_argument, NULL, ARG_UNTIL },
+ { "unit", required_argument, NULL, 'u' },
+ { "user-unit", required_argument, NULL, ARG_USER_UNIT },
+ { "field", required_argument, NULL, 'F' },
+ { "catalog", no_argument, NULL, 'x' },
+ { "list-catalog", no_argument, NULL, ARG_LIST_CATALOG },
+ { "dump-catalog", no_argument, NULL, ARG_DUMP_CATALOG },
+ { "update-catalog", no_argument, NULL, ARG_UPDATE_CATALOG },
+ { "reverse", no_argument, NULL, 'r' },
+ { NULL, 0, NULL, 0 }
};
int c, r;
@@ -215,7 +249,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "hefo:an::qmbD:p:c:u:F:xr", options, NULL)) >= 0) {
+ while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:c:u:F:xr", options, NULL)) >= 0) {
switch (c) {
@@ -260,7 +294,7 @@ static int parse_argv(int argc, char *argv[]) {
break;
- case ARG_FULL:
+ case 'l':
arg_full = true;
break;
@@ -314,13 +348,46 @@ static int parse_argv(int argc, char *argv[]) {
break;
case 'b':
- arg_this_boot = true;
+ arg_boot = true;
+
+ if (optarg)
+ arg_boot_descriptor = optarg;
+ else if (optind < argc) {
+ int boot;
+
+ if (argv[optind][0] != '-' ||
+ safe_atoi(argv[optind], &boot) >= 0) {
+ arg_boot_descriptor = argv[optind];
+ optind++;
+ }
+ }
+
+ break;
+
+ case 'k':
+ arg_boot = arg_dmesg = true;
+ break;
+
+ case ARG_SYSTEM:
+ arg_journal_type |= SD_JOURNAL_SYSTEM;
+ break;
+
+ case ARG_USER:
+ arg_journal_type |= SD_JOURNAL_CURRENT_USER;
break;
case 'D':
arg_directory = optarg;
break;
+ case ARG_FILE:
+ r = glob_extend(&arg_file, optarg);
+ if (r < 0) {
+ log_error("Failed to add paths: %s", strerror(-r));
+ return r;
+ };
+ break;
+
case ARG_ROOT:
arg_root = optarg;
break;
@@ -329,6 +396,14 @@ static int parse_argv(int argc, char *argv[]) {
arg_cursor = optarg;
break;
+ case ARG_AFTER_CURSOR:
+ arg_after_cursor = optarg;
+ break;
+
+ case ARG_SHOW_CURSOR:
+ arg_show_cursor = true;
+ break;
+
case ARG_HEADER:
arg_action = ACTION_PRINT_HEADER;
break;
@@ -342,6 +417,10 @@ static int parse_argv(int argc, char *argv[]) {
break;
#ifdef HAVE_GCRYPT
+ case ARG_FORCE:
+ arg_force = true;
+ break;
+
case ARG_SETUP_KEYS:
arg_action = ACTION_SETUP_KEYS;
break;
@@ -364,6 +443,7 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_SETUP_KEYS:
case ARG_VERIFY_KEY:
case ARG_INTERVAL:
+ case ARG_FORCE:
log_error("Forward-secure sealing not available.");
return -ENOTSUP;
#endif
@@ -484,13 +564,18 @@ static int parse_argv(int argc, char *argv[]) {
if (arg_follow && !arg_no_tail && arg_lines < 0)
arg_lines = 10;
+ if (arg_directory && arg_file) {
+ log_error("Please specify either -D/--directory= or --file=, not both.");
+ return -EINVAL;
+ }
+
if (arg_since_set && arg_until_set && arg_since > arg_until) {
log_error("--since= must be before --until=.");
return -EINVAL;
}
- if (arg_cursor && arg_since_set) {
- log_error("Please specify either --since= or --cursor=, not both.");
+ if (!!arg_cursor + !!arg_after_cursor + !!arg_since_set > 1) {
+ log_error("Please specify only one of --since=, --cursor=, and --after-cursor.");
return -EINVAL;
}
@@ -544,8 +629,9 @@ static int add_matches(sd_journal *j, char **args) {
if (streq(*i, "+"))
r = sd_journal_add_disjunction(j);
else if (path_is_absolute(*i)) {
- _cleanup_free_ char *p, *t = NULL;
+ _cleanup_free_ char *p, *t = NULL, *t2 = NULL;
const char *path;
+ _cleanup_free_ char *interpreter = NULL;
struct stat st;
p = canonicalize_file_name(*i);
@@ -556,9 +642,27 @@ static int add_matches(sd_journal *j, char **args) {
return -errno;
}
- if (S_ISREG(st.st_mode) && (0111 & st.st_mode))
- t = strappend("_EXE=", path);
- else if (S_ISCHR(st.st_mode))
+ if (S_ISREG(st.st_mode) && (0111 & st.st_mode)) {
+ if (executable_is_script(path, &interpreter) > 0) {
+ _cleanup_free_ char *comm;
+
+ comm = strndup(path_get_file_name(path), 15);
+ if (!comm)
+ return log_oom();
+
+ t = strappend("_COMM=", comm);
+
+ /* Append _EXE only if the interpreter is not a link.
+ Otherwise it might be outdated often. */
+ if (lstat(interpreter, &st) == 0 &&
+ !S_ISLNK(st.st_mode)) {
+ t2 = strappend("_EXE=", interpreter);
+ if (!t2)
+ return log_oom();
+ }
+ } else
+ t = strappend("_EXE=", path);
+ } else if (S_ISCHR(st.st_mode))
asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
else if (S_ISBLK(st.st_mode))
asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
@@ -571,6 +675,8 @@ static int add_matches(sd_journal *j, char **args) {
return log_oom();
r = sd_journal_add_match(j, t, 0);
+ if (t2)
+ r = sd_journal_add_match(j, t2, 0);
} else
r = sd_journal_add_match(j, *i, 0);
@@ -583,24 +689,169 @@ static int add_matches(sd_journal *j, char **args) {
return 0;
}
-static int add_this_boot(sd_journal *j) {
- char match[9+32+1] = "_BOOT_ID=";
- sd_id128_t boot_id;
+static int boot_id_cmp(const void *a, const void *b) {
+ uint64_t _a, _b;
+
+ _a = ((const boot_id_t *)a)->timestamp;
+ _b = ((const boot_id_t *)b)->timestamp;
+
+ return _a < _b ? -1 : (_a > _b ? 1 : 0);
+}
+
+static int get_relative_boot_id(sd_journal *j, sd_id128_t *boot_id, int relative) {
int r;
+ const void *data;
+ unsigned int count = 0;
+ size_t length, allocated = 0;
+ boot_id_t ref_boot_id = {SD_ID128_NULL}, *id;
+ _cleanup_free_ boot_id_t *all_ids = NULL;
+
+ assert(j);
+ assert(boot_id);
+
+ if (relative == 0 && !sd_id128_equal(*boot_id, SD_ID128_NULL))
+ return 0;
+
+ r = sd_journal_query_unique(j, "_BOOT_ID");
+ if (r < 0)
+ return r;
+
+ SD_JOURNAL_FOREACH_UNIQUE(j, data, length) {
+ if (length < strlen("_BOOT_ID="))
+ continue;
+
+ if (!GREEDY_REALLOC(all_ids, allocated, count + 1))
+ return log_oom();
+
+ id = &all_ids[count];
+
+ r = sd_id128_from_string(((const char *)data) + strlen("_BOOT_ID="), &id->id);
+ if (r < 0)
+ continue;
+
+ r = sd_journal_add_match(j, data, length);
+ if (r < 0)
+ return r;
+
+ r = sd_journal_seek_head(j);
+ if (r < 0)
+ return r;
+
+ r = sd_journal_next(j);
+ if (r < 0)
+ return r;
+ else if (r == 0)
+ goto flush;
+
+ r = sd_journal_get_realtime_usec(j, &id->timestamp);
+ if (r < 0)
+ return r;
+
+ if (sd_id128_equal(id->id, *boot_id))
+ ref_boot_id = *id;
+
+ count++;
+ flush:
+ sd_journal_flush_matches(j);
+ }
+
+ qsort(all_ids, count, sizeof(boot_id_t), boot_id_cmp);
+
+ if (sd_id128_equal(*boot_id, SD_ID128_NULL)) {
+ if (relative > (int) count || relative <= -(int)count)
+ return -EADDRNOTAVAIL;
+
+ *boot_id = all_ids[(relative <= 0)*count + relative - 1].id;
+ } else {
+ id = bsearch(&ref_boot_id, all_ids, count, sizeof(boot_id_t), boot_id_cmp);
+
+ if (!id ||
+ relative <= 0 ? (id - all_ids) + relative < 0 :
+ (id - all_ids) + relative >= (int) count)
+ return -EADDRNOTAVAIL;
+
+ *boot_id = (id + relative)->id;
+ }
+
+ return 0;
+}
+
+static int add_boot(sd_journal *j) {
+ char match[9+32+1] = "_BOOT_ID=";
+ char *offset;
+ sd_id128_t boot_id = SD_ID128_NULL;
+ int r, relative = 0;
assert(j);
- if (!arg_this_boot)
+ if (!arg_boot)
return 0;
- r = sd_id128_get_boot(&boot_id);
+ if (!arg_boot_descriptor)
+ return add_match_this_boot(j);
+
+ if (strlen(arg_boot_descriptor) >= 32) {
+ char tmp = arg_boot_descriptor[32];
+ arg_boot_descriptor[32] = '\0';
+ r = sd_id128_from_string(arg_boot_descriptor, &boot_id);
+ arg_boot_descriptor[32] = tmp;
+
+ if (r < 0) {
+ log_error("Failed to parse boot ID '%.32s': %s",
+ arg_boot_descriptor, strerror(-r));
+ return r;
+ }
+
+ offset = arg_boot_descriptor + 32;
+
+ if (*offset && *offset != '-' && *offset != '+') {
+ log_error("Relative boot ID offset must start with a '+' or a '-', found '%s' ", offset);
+ return -EINVAL;
+ }
+ } else
+ offset = arg_boot_descriptor;
+
+ if (*offset) {
+ r = safe_atoi(offset, &relative);
+ if (r < 0) {
+ log_error("Failed to parse relative boot ID number '%s'", offset);
+ return -EINVAL;
+ }
+ }
+
+ r = get_relative_boot_id(j, &boot_id, relative);
if (r < 0) {
- log_error("Failed to get boot id: %s", strerror(-r));
+ if (sd_id128_equal(boot_id, SD_ID128_NULL))
+ log_error("Failed to look up boot %+d: %s", relative, strerror(-r));
+ else
+ log_error("Failed to look up boot ID "SD_ID128_FORMAT_STR"%+d: %s",
+ SD_ID128_FORMAT_VAL(boot_id), relative, strerror(-r));
return r;
}
sd_id128_to_string(boot_id, match + 9);
- r = sd_journal_add_match(j, match, strlen(match));
+
+ r = sd_journal_add_match(j, match, sizeof(match) - 1);
+ if (r < 0) {
+ log_error("Failed to add match: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_journal_add_conjunction(j);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int add_dmesg(sd_journal *j) {
+ int r;
+ assert(j);
+
+ if (!arg_dmesg)
+ return 0;
+
+ r = sd_journal_add_match(j, "_TRANSPORT=kernel", strlen("_TRANSPORT=kernel"));
if (r < 0) {
log_error("Failed to add match: %s", strerror(-r));
return r;
@@ -690,6 +941,19 @@ static int setup_keys(void) {
char *p = NULL, *k = NULL;
struct FSSHeader h;
uint64_t n;
+ struct stat st;
+
+ r = stat("/var/log/journal", &st);
+ if (r < 0 && errno != ENOENT && errno != ENOTDIR) {
+ log_error("stat(\"%s\") failed: %m", "/var/log/journal");
+ return -errno;
+ }
+
+ if (r < 0 || !S_ISDIR(st.st_mode)) {
+ log_error("%s is not a directory, must be using persistent logging for FSS.",
+ "/var/log/journal");
+ return r < 0 ? -errno : -ENOTDIR;
+ }
r = sd_id128_get_machine(&machine);
if (r < 0) {
@@ -708,9 +972,18 @@ static int setup_keys(void) {
return log_oom();
if (access(p, F_OK) >= 0) {
- log_error("Sealing key file %s exists already.", p);
- r = -EEXIST;
- goto finish;
+ if (arg_force) {
+ r = unlink(p);
+ if (r < 0) {
+ log_error("unlink(\"%s\") failed: %m", p);
+ r = -errno;
+ goto finish;
+ }
+ } else {
+ log_error("Sealing key file %s exists already. (--force to recreate)", p);
+ r = -EEXIST;
+ goto finish;
+ }
}
if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
@@ -1028,11 +1301,12 @@ static int access_check(sd_journal *j) {
int main(int argc, char *argv[]) {
int r;
- _cleanup_journal_close_ sd_journal*j = NULL;
+ _cleanup_journal_close_ sd_journal *j = NULL;
bool need_seek = false;
sd_id128_t previous_boot_id;
bool previous_boot_id_valid = false, first_line = true;
int n_shown = 0;
+ bool ellipsized = false;
setlocale(LC_ALL, "");
log_parse_environment();
@@ -1090,11 +1364,15 @@ int main(int argc, char *argv[]) {
}
if (arg_directory)
- r = sd_journal_open_directory(&j, arg_directory, 0);
+ r = sd_journal_open_directory(&j, arg_directory, arg_journal_type);
+ else if (arg_file)
+ r = sd_journal_open_files(&j, (const char**) arg_file, 0);
else
- r = sd_journal_open(&j, arg_merge ? 0 : SD_JOURNAL_LOCAL_ONLY);
+ r = sd_journal_open(&j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type);
if (r < 0) {
- log_error("Failed to open journal: %s", strerror(-r));
+ log_error("Failed to open %s: %s",
+ arg_directory ? arg_directory : arg_file ? "files" : "journal",
+ strerror(-r));
return EXIT_FAILURE;
}
@@ -1125,7 +1403,13 @@ int main(int argc, char *argv[]) {
return EXIT_SUCCESS;
}
- r = add_this_boot(j);
+ /* add_boot() must be called first!
+ * It may need to seek the journal to find parent boot IDs. */
+ r = add_boot(j);
+ if (r < 0)
+ return EXIT_FAILURE;
+
+ r = add_dmesg(j);
if (r < 0)
return EXIT_FAILURE;
@@ -1144,10 +1428,12 @@ int main(int argc, char *argv[]) {
if (r < 0)
return EXIT_FAILURE;
- /* Opening the fd now means the first sd_journal_wait() will actually wait */
- r = sd_journal_get_fd(j);
- if (r < 0)
- return EXIT_FAILURE;
+ if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
+ _cleanup_free_ char *filter;
+
+ filter = journal_make_match_string(j);
+ log_debug("Journal filter: %s", filter);
+ }
if (arg_field) {
const void *data;
@@ -1183,16 +1469,27 @@ int main(int argc, char *argv[]) {
return EXIT_SUCCESS;
}
- if (arg_cursor) {
- r = sd_journal_seek_cursor(j, arg_cursor);
+ /* Opening the fd now means the first sd_journal_wait() will actually wait */
+ if (arg_follow) {
+ r = sd_journal_get_fd(j);
+ if (r < 0)
+ return EXIT_FAILURE;
+ }
+
+ if (arg_cursor || arg_after_cursor) {
+ r = sd_journal_seek_cursor(j, arg_cursor ? arg_cursor : arg_after_cursor);
if (r < 0) {
log_error("Failed to seek to cursor: %s", strerror(-r));
return EXIT_FAILURE;
}
if (!arg_reverse)
- r = sd_journal_next(j);
+ r = sd_journal_next_skip(j, 1 + !!arg_after_cursor);
else
- r = sd_journal_previous(j);
+ r = sd_journal_previous_skip(j, 1 + !!arg_after_cursor);
+
+ if (arg_after_cursor && r < 2 && !arg_follow)
+ /* We couldn't find the next entry after the cursor. */
+ arg_lines = 0;
} else if (arg_since_set && !arg_reverse) {
r = sd_journal_seek_realtime_usec(j, arg_since);
@@ -1280,11 +1577,10 @@ int main(int argc, char *argv[]) {
log_error("Failed to iterate through journal: %s", strerror(-r));
goto finish;
}
+ if (r == 0)
+ break;
}
- if (r == 0)
- break;
-
if (arg_until_set && !arg_reverse) {
usec_t usec;
@@ -1316,7 +1612,8 @@ int main(int argc, char *argv[]) {
if (r >= 0) {
if (previous_boot_id_valid &&
!sd_id128_equal(boot_id, previous_boot_id))
- printf(ANSI_HIGHLIGHT_ON "-- Reboot --" ANSI_HIGHLIGHT_OFF "\n");
+ printf("%s-- Reboot --%s\n",
+ ansi_highlight(), ansi_highlight_off());
previous_boot_id = boot_id;
previous_boot_id_valid = true;
@@ -1329,16 +1626,29 @@ int main(int argc, char *argv[]) {
on_tty() * OUTPUT_COLOR |
arg_catalog * OUTPUT_CATALOG;
- r = output_journal(stdout, j, arg_output, 0, flags);
- if (r < 0 || ferror(stdout))
+ r = output_journal(stdout, j, arg_output, 0, flags, &ellipsized);
+ need_seek = true;
+ if (r == -EADDRNOTAVAIL)
+ break;
+ else if (r < 0 || ferror(stdout))
goto finish;
- need_seek = true;
n_shown++;
}
- if (!arg_follow)
+ if (!arg_follow) {
+ if (arg_show_cursor) {
+ _cleanup_free_ char *cursor = NULL;
+
+ r = sd_journal_get_cursor(j, &cursor);
+ if (r < 0 && r != -EADDRNOTAVAIL)
+ log_error("Failed to get cursor: %s", strerror(-r));
+ else if (r >= 0)
+ printf("-- cursor: %s\n", cursor);
+ }
+
break;
+ }
r = sd_journal_wait(j, (uint64_t) -1);
if (r < 0) {
diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c
index 2f536320f8..21649d06ce 100644
--- a/src/journal/journald-kmsg.c
+++ b/src/journal/journald-kmsg.c
@@ -151,7 +151,8 @@ static void dev_kmsg_record(Server *s, char *p, size_t l) {
/* Did we lose any? */
if (serial > *s->kernel_seqnum)
- server_driver_message(s, SD_MESSAGE_JOURNAL_MISSED, "Missed %llu kernel messages", (unsigned long long) serial - *s->kernel_seqnum - 1);
+ server_driver_message(s, SD_MESSAGE_JOURNAL_MISSED, "Missed %"PRIu64" kernel messages",
+ serial - *s->kernel_seqnum - 1);
/* Make sure we never read this one again. Note that
* we always store the next message serial we expect
@@ -303,7 +304,7 @@ static void dev_kmsg_record(Server *s, char *p, size_t l) {
if (message)
IOVEC_SET_STRING(iovec[n++], message);
- server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), NULL, NULL, NULL, 0, NULL, priority);
+ server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), NULL, NULL, NULL, 0, NULL, priority, 0);
finish:
for (j = 0; j < z; j++)
diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c
index f878dfc911..c50cf64f5c 100644
--- a/src/journal/journald-native.c
+++ b/src/journal/journald-native.c
@@ -71,6 +71,10 @@ static bool valid_user_field(const char *p, size_t l) {
return true;
}
+static bool allow_object_pid(struct ucred *ucred) {
+ return ucred && ucred->uid == 0;
+}
+
void server_process_native_message(
Server *s,
const void *buffer, size_t buffer_size,
@@ -79,11 +83,12 @@ void server_process_native_message(
const char *label, size_t label_len) {
struct iovec *iovec = NULL;
- unsigned n = 0, m = 0, j, tn = (unsigned) -1;
+ unsigned n = 0, j, tn = (unsigned) -1;
const char *p;
- size_t remaining;
+ size_t remaining, m = 0;
int priority = LOG_INFO;
char *identifier = NULL, *message = NULL;
+ pid_t object_pid = 0;
assert(s);
assert(buffer || buffer_size == 0);
@@ -104,7 +109,7 @@ void server_process_native_message(
if (e == p) {
/* Entry separator */
- server_dispatch_message(s, iovec, n, m, ucred, tv, label, label_len, NULL, priority);
+ server_dispatch_message(s, iovec, n, m, ucred, tv, label, label_len, NULL, priority, object_pid);
n = 0;
priority = LOG_INFO;
@@ -124,19 +129,10 @@ void server_process_native_message(
/* A property follows */
/* n received properties, +1 for _TRANSPORT */
- if (n + 1 + N_IOVEC_META_FIELDS >= m) {
- struct iovec *c;
- unsigned u;
-
- u = MAX((n + 1 + N_IOVEC_META_FIELDS) * 2U, 4U);
- c = realloc(iovec, u * sizeof(struct iovec));
- if (!c) {
- log_oom();
- break;
- }
-
- iovec = c;
- m = u;
+ if (!GREEDY_REALLOC(iovec, m, n + 1 + N_IOVEC_META_FIELDS +
+ !!object_pid * N_IOVEC_OBJECT_FIELDS)) {
+ log_oom();
+ break;
}
q = memchr(p, '=', e - p);
@@ -158,23 +154,23 @@ void server_process_native_message(
* of this entry for the rate limiting
* logic */
if (l == 10 &&
- memcmp(p, "PRIORITY=", 9) == 0 &&
+ startswith(p, "PRIORITY=") &&
p[9] >= '0' && p[9] <= '9')
priority = (priority & LOG_FACMASK) | (p[9] - '0');
else if (l == 17 &&
- memcmp(p, "SYSLOG_FACILITY=", 16) == 0 &&
+ startswith(p, "SYSLOG_FACILITY=") &&
p[16] >= '0' && p[16] <= '9')
priority = (priority & LOG_PRIMASK) | ((p[16] - '0') << 3);
else if (l == 18 &&
- memcmp(p, "SYSLOG_FACILITY=", 16) == 0 &&
+ startswith(p, "SYSLOG_FACILITY=") &&
p[16] >= '0' && p[16] <= '9' &&
p[17] >= '0' && p[17] <= '9')
priority = (priority & LOG_PRIMASK) | (((p[16] - '0')*10 + (p[17] - '0')) << 3);
else if (l >= 19 &&
- memcmp(p, "SYSLOG_IDENTIFIER=", 18) == 0) {
+ startswith(p, "SYSLOG_IDENTIFIER=")) {
char *t;
t = strndup(p + 18, l - 18);
@@ -183,7 +179,7 @@ void server_process_native_message(
identifier = t;
}
} else if (l >= 8 &&
- memcmp(p, "MESSAGE=", 8) == 0) {
+ startswith(p, "MESSAGE=")) {
char *t;
t = strndup(p + 8, l - 8);
@@ -191,6 +187,16 @@ void server_process_native_message(
free(message);
message = t;
}
+ } else if (l > strlen("OBJECT_PID=") &&
+ l < strlen("OBJECT_PID=") + DECIMAL_STR_MAX(pid_t) &&
+ startswith(p, "OBJECT_PID=") &&
+ allow_object_pid(ucred)) {
+ char buf[DECIMAL_STR_MAX(pid_t)];
+ memcpy(buf, p + strlen("OBJECT_PID="), l - strlen("OBJECT_PID="));
+ char_array_0(buf);
+
+ /* ignore error */
+ parse_pid(buf, &object_pid);
}
}
@@ -260,7 +266,7 @@ void server_process_native_message(
server_forward_console(s, priority, identifier, message, ucred);
}
- server_dispatch_message(s, iovec, n, m, ucred, tv, label, label_len, NULL, priority);
+ server_dispatch_message(s, iovec, n, m, ucred, tv, label, label_len, NULL, priority, object_pid);
finish:
for (j = 0; j < n; j++) {
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index cc52b8a5c9..4f47eb1c11 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -65,8 +65,8 @@
#define USER_JOURNALS_MAX 1024
#define DEFAULT_SYNC_INTERVAL_USEC (5*USEC_PER_MINUTE)
-#define DEFAULT_RATE_LIMIT_INTERVAL (10*USEC_PER_SEC)
-#define DEFAULT_RATE_LIMIT_BURST 200
+#define DEFAULT_RATE_LIMIT_INTERVAL (30*USEC_PER_SEC)
+#define DEFAULT_RATE_LIMIT_BURST 1000
#define RECHECK_AVAILABLE_SPACE_USEC (30*USEC_PER_SEC)
@@ -89,21 +89,22 @@ static const char* const split_mode_table[] = {
DEFINE_STRING_TABLE_LOOKUP(split_mode, SplitMode);
DEFINE_CONFIG_PARSE_ENUM(config_parse_split_mode, split_mode, SplitMode, "Failed to parse split mode setting");
-static uint64_t available_space(Server *s) {
+static uint64_t available_space(Server *s, bool verbose) {
char ids[33];
_cleanup_free_ char *p = NULL;
- const char *f;
sd_id128_t machine;
struct statvfs ss;
- uint64_t sum = 0, avail = 0, ss_avail = 0;
+ uint64_t sum = 0, ss_avail = 0, avail = 0;
int r;
_cleanup_closedir_ DIR *d = NULL;
usec_t ts;
+ const char *f;
JournalMetrics *m;
ts = now(CLOCK_MONOTONIC);
- if (s->cached_available_space_timestamp + RECHECK_AVAILABLE_SPACE_USEC > ts)
+ if (s->cached_available_space_timestamp + RECHECK_AVAILABLE_SPACE_USEC > ts
+ && !verbose)
return s->cached_available_space;
r = sd_id128_get_machine(&machine);
@@ -156,38 +157,27 @@ static uint64_t available_space(Server *s) {
sum += (uint64_t) st.st_blocks * 512UL;
}
- avail = sum >= m->max_use ? 0 : m->max_use - sum;
-
ss_avail = ss.f_bsize * ss.f_bavail;
+ avail = ss_avail > m->keep_free ? ss_avail - m->keep_free : 0;
- ss_avail = ss_avail < m->keep_free ? 0 : ss_avail - m->keep_free;
-
- if (ss_avail < avail)
- avail = ss_avail;
-
- s->cached_available_space = avail;
+ s->cached_available_space = MIN(m->max_use, avail) > sum ? MIN(m->max_use, avail) - sum : 0;
s->cached_available_space_timestamp = ts;
- return avail;
-}
-
-static void server_read_file_gid(Server *s) {
- const char *g = "systemd-journal";
- int r;
-
- assert(s);
-
- if (s->file_gid_valid)
- return;
-
- r = get_group_creds(&g, &s->file_gid);
- if (r < 0)
- log_warning("Failed to resolve '%s' group: %s", g, strerror(-r));
+ if (verbose) {
+ char fb1[FORMAT_BYTES_MAX], fb2[FORMAT_BYTES_MAX], fb3[FORMAT_BYTES_MAX],
+ fb4[FORMAT_BYTES_MAX], fb5[FORMAT_BYTES_MAX];
+
+ server_driver_message(s, SD_MESSAGE_JOURNAL_USAGE,
+ "%s journal is using %s (max %s, leaving %s of free %s, current limit %s).",
+ s->system_journal ? "Permanent" : "Runtime",
+ format_bytes(fb1, sizeof(fb1), sum),
+ format_bytes(fb2, sizeof(fb2), m->max_use),
+ format_bytes(fb3, sizeof(fb3), m->keep_free),
+ format_bytes(fb4, sizeof(fb4), ss_avail),
+ format_bytes(fb5, sizeof(fb5), MIN(m->max_use, avail)));
+ }
- /* if we couldn't read the gid, then it will be 0, but that's
- * fine and we shouldn't try to resolve the group again, so
- * let's just pretend it worked right-away. */
- s->file_gid_valid = true;
+ return s->cached_available_space;
}
void server_fix_perms(Server *s, JournalFile *f, uid_t uid) {
@@ -200,11 +190,9 @@ void server_fix_perms(Server *s, JournalFile *f, uid_t uid) {
assert(f);
- server_read_file_gid(s);
-
- r = fchmod_and_fchown(f->fd, 0640, 0, s->file_gid);
+ r = fchmod(f->fd, 0640);
if (r < 0)
- log_warning("Failed to fix access mode/rights on %s, ignoring: %s", f->path, strerror(-r));
+ log_warning("Failed to fix access mode on %s, ignoring: %s", f->path, strerror(-r));
#ifdef HAVE_ACL
if (uid <= 0)
@@ -227,9 +215,11 @@ void server_fix_perms(Server *s, JournalFile *f, uid_t uid) {
}
}
- /* We do not recalculate the mask here, so that the fchmod() mask above stays intact. */
+ /* We do not recalculate the mask unconditionally here,
+ * so that the fchmod() mask above stays intact. */
if (acl_get_permset(entry, &permset) < 0 ||
- acl_add_perm(permset, ACL_READ) < 0) {
+ acl_add_perm(permset, ACL_READ) < 0 ||
+ calc_acl_mask_if_needed(&acl) < 0) {
log_warning("Failed to patch ACL on %s, ignoring: %m", f->path);
goto finish;
}
@@ -243,7 +233,7 @@ finish:
}
static JournalFile* find_journal(Server *s, uid_t uid) {
- char *p;
+ _cleanup_free_ char *p = NULL;
int r;
JournalFile *f;
sd_id128_t machine;
@@ -280,9 +270,7 @@ static JournalFile* find_journal(Server *s, uid_t uid) {
journal_file_close(f);
}
- r = journal_file_open_reliably(p, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, s->system_journal, &f);
- free(p);
-
+ r = journal_file_open_reliably(p, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &f);
if (r < 0)
return s->system_journal;
@@ -343,13 +331,12 @@ void server_rotate(Server *s) {
}
void server_sync(Server *s) {
+ static const struct itimerspec sync_timer_disable = {};
JournalFile *f;
void *k;
Iterator i;
int r;
- static const struct itimerspec sync_timer_disable = {};
-
if (s->system_journal) {
r = journal_file_set_offline(s->system_journal);
if (r < 0)
@@ -370,7 +357,6 @@ void server_sync(Server *s) {
}
void server_vacuum(Server *s) {
- char *p;
char ids[33];
sd_id128_t machine;
int r;
@@ -388,29 +374,19 @@ void server_vacuum(Server *s) {
sd_id128_to_string(machine, ids);
if (s->system_journal) {
- p = strappend("/var/log/journal/", ids);
- if (!p) {
- log_oom();
- return;
- }
+ char *p = strappenda("/var/log/journal/", ids);
r = journal_directory_vacuum(p, s->system_metrics.max_use, s->system_metrics.keep_free, s->max_retention_usec, &s->oldest_file_usec);
if (r < 0 && r != -ENOENT)
log_error("Failed to vacuum %s: %s", p, strerror(-r));
- free(p);
}
if (s->runtime_journal) {
- p = strappend("/run/log/journal/", ids);
- if (!p) {
- log_oom();
- return;
- }
+ char *p = strappenda("/run/log/journal/", ids);
r = journal_directory_vacuum(p, s->runtime_metrics.max_use, s->runtime_metrics.keep_free, s->max_retention_usec, &s->oldest_file_usec);
if (r < 0 && r != -ENOENT)
log_error("Failed to vacuum %s: %s", p, strerror(-r));
- free(p);
}
s->cached_available_space_timestamp = 0;
@@ -445,7 +421,7 @@ bool shall_try_append_again(JournalFile *f, int r) {
return true;
}
-static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned n) {
+static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned n, int priority) {
JournalFile *f;
bool vacuumed = false;
int r;
@@ -471,12 +447,17 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned
r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
if (r >= 0) {
- server_schedule_sync(s);
+ server_schedule_sync(s, priority);
return;
}
if (vacuumed || !shall_try_append_again(f, r)) {
- log_error("Failed to write entry, ignoring: %s", strerror(-r));
+ size_t size = 0;
+ unsigned i;
+ for (i = 0; i < n; i++)
+ size += iovec[i].iov_len;
+
+ log_error("Failed to write entry (%d items, %zu bytes), ignoring: %s", n, size, strerror(-r));
return;
}
@@ -489,8 +470,15 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned
log_debug("Retrying write.");
r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
- if (r < 0)
- log_error("Failed to write entry, ignoring: %s", strerror(-r));
+ if (r < 0) {
+ size_t size = 0;
+ unsigned i;
+ for (i = 0; i < n; i++)
+ size += iovec[i].iov_len;
+
+ log_error("Failed to write entry (%d items, %zu bytes) despite vacuuming, ignoring: %s", n, size, strerror(-r));
+ } else
+ server_schedule_sync(s, priority);
}
static void dispatch_message_real(
@@ -499,24 +487,33 @@ static void dispatch_message_real(
struct ucred *ucred,
struct timeval *tv,
const char *label, size_t label_len,
- const char *unit_id) {
+ const char *unit_id,
+ int priority,
+ pid_t object_pid) {
- char pid[sizeof("_PID=") + DECIMAL_STR_MAX(pid_t)],
+ char pid[sizeof("_PID=") + DECIMAL_STR_MAX(pid_t)],
uid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)],
gid[sizeof("_GID=") + DECIMAL_STR_MAX(gid_t)],
owner_uid[sizeof("_SYSTEMD_OWNER_UID=") + DECIMAL_STR_MAX(uid_t)],
source_time[sizeof("_SOURCE_REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t)],
boot_id[sizeof("_BOOT_ID=") + 32] = "_BOOT_ID=",
- machine_id[sizeof("_MACHINE_ID=") + 32] = "_MACHINE_ID=";
- char *comm, *exe, *cmdline, *cgroup, *session, *unit, *hostname;
+ machine_id[sizeof("_MACHINE_ID=") + 32] = "_MACHINE_ID=",
+ o_uid[sizeof("OBJECT_UID=") + DECIMAL_STR_MAX(uid_t)],
+ o_gid[sizeof("OBJECT_GID=") + DECIMAL_STR_MAX(gid_t)],
+ o_owner_uid[sizeof("OBJECT_SYSTEMD_OWNER_UID=") + DECIMAL_STR_MAX(uid_t)];
+ uid_t object_uid;
+ gid_t object_gid;
+ char *x;
sd_id128_t id;
int r;
char *t, *c;
uid_t realuid = 0, owner = 0, journal_uid;
bool owner_valid = false;
#ifdef HAVE_AUDIT
- char audit_session[sizeof("_AUDIT_SESSION=") + DECIMAL_STR_MAX(uint32_t)],
- audit_loginuid[sizeof("_AUDIT_LOGINUID=") + DECIMAL_STR_MAX(uid_t)];
+ char audit_session[sizeof("_AUDIT_SESSION=") + DECIMAL_STR_MAX(uint32_t)],
+ audit_loginuid[sizeof("_AUDIT_LOGINUID=") + DECIMAL_STR_MAX(uid_t)],
+ o_audit_session[sizeof("OBJECT_AUDIT_SESSION=") + DECIMAL_STR_MAX(uint32_t)],
+ o_audit_loginuid[sizeof("OBJECT_AUDIT_LOGINUID=") + DECIMAL_STR_MAX(uid_t)];
uint32_t audit;
uid_t loginuid;
@@ -525,7 +522,7 @@ static void dispatch_message_real(
assert(s);
assert(iovec);
assert(n > 0);
- assert(n + N_IOVEC_META_FIELDS <= m);
+ assert(n + N_IOVEC_META_FIELDS + (object_pid ? N_IOVEC_OBJECT_FIELDS : 0) <= m);
if (ucred) {
realuid = ucred->uid;
@@ -541,23 +538,30 @@ static void dispatch_message_real(
r = get_process_comm(ucred->pid, &t);
if (r >= 0) {
- comm = strappenda("_COMM=", t);
+ x = strappenda("_COMM=", t);
free(t);
- IOVEC_SET_STRING(iovec[n++], comm);
+ IOVEC_SET_STRING(iovec[n++], x);
}
r = get_process_exe(ucred->pid, &t);
if (r >= 0) {
- exe = strappenda("_EXE=", t);
+ x = strappenda("_EXE=", t);
free(t);
- IOVEC_SET_STRING(iovec[n++], exe);
+ IOVEC_SET_STRING(iovec[n++], x);
}
r = get_process_cmdline(ucred->pid, 0, false, &t);
if (r >= 0) {
- cmdline = strappenda("_CMDLINE=", t);
+ x = strappenda("_CMDLINE=", t);
free(t);
- IOVEC_SET_STRING(iovec[n++], cmdline);
+ IOVEC_SET_STRING(iovec[n++], x);
+ }
+
+ r = get_process_capeff(ucred->pid, &t);
+ if (r >= 0) {
+ x = strappenda("_CAP_EFFECTIVE=", t);
+ free(t);
+ IOVEC_SET_STRING(iovec[n++], x);
}
#ifdef HAVE_AUDIT
@@ -576,8 +580,10 @@ static void dispatch_message_real(
r = cg_pid_get_path_shifted(ucred->pid, NULL, &c);
if (r >= 0) {
- cgroup = strappenda("_SYSTEMD_CGROUP=", c);
- IOVEC_SET_STRING(iovec[n++], cgroup);
+ char *session = NULL;
+
+ x = strappenda("_SYSTEMD_CGROUP=", c);
+ IOVEC_SET_STRING(iovec[n++], x);
r = cg_path_get_session(c, &t);
if (r >= 0) {
@@ -594,43 +600,133 @@ static void dispatch_message_real(
}
if (cg_path_get_unit(c, &t) >= 0) {
- unit = strappenda("_SYSTEMD_UNIT=", t);
+ x = strappenda("_SYSTEMD_UNIT=", t);
free(t);
- } else if (cg_path_get_user_unit(c, &t) >= 0) {
- unit = strappenda("_SYSTEMD_USER_UNIT=", t);
+ IOVEC_SET_STRING(iovec[n++], x);
+ } else if (unit_id && !session) {
+ x = strappenda("_SYSTEMD_UNIT=", unit_id);
+ IOVEC_SET_STRING(iovec[n++], x);
+ }
+
+ if (cg_path_get_user_unit(c, &t) >= 0) {
+ x = strappenda("_SYSTEMD_USER_UNIT=", t);
free(t);
- } else if (unit_id) {
- if (session)
- unit = strappenda("_SYSTEMD_USER_UNIT=", unit_id);
- else
- unit = strappenda("_SYSTEMD_UNIT=", unit_id);
- } else
- unit = NULL;
+ IOVEC_SET_STRING(iovec[n++], x);
+ } else if (unit_id && session) {
+ x = strappenda("_SYSTEMD_USER_UNIT=", unit_id);
+ IOVEC_SET_STRING(iovec[n++], x);
+ }
- if (unit)
- IOVEC_SET_STRING(iovec[n++], unit);
+ if (cg_path_get_slice(c, &t) >= 0) {
+ x = strappenda("_SYSTEMD_SLICE=", t);
+ free(t);
+ IOVEC_SET_STRING(iovec[n++], x);
+ }
free(c);
}
#ifdef HAVE_SELINUX
if (label) {
- char *selinux_context = alloca(sizeof("_SELINUX_CONTEXT=") + label_len);
+ x = alloca(sizeof("_SELINUX_CONTEXT=") + label_len);
- *((char*) mempcpy(stpcpy(selinux_context, "_SELINUX_CONTEXT="), label, label_len)) = 0;
- IOVEC_SET_STRING(iovec[n++], selinux_context);
+ *((char*) mempcpy(stpcpy(x, "_SELINUX_CONTEXT="), label, label_len)) = 0;
+ IOVEC_SET_STRING(iovec[n++], x);
} else {
security_context_t con;
if (getpidcon(ucred->pid, &con) >= 0) {
- char *selinux_context = strappenda("_SELINUX_CONTEXT=", con);
+ x = strappenda("_SELINUX_CONTEXT=", con);
freecon(con);
- IOVEC_SET_STRING(iovec[n++], selinux_context);
+ IOVEC_SET_STRING(iovec[n++], x);
}
}
#endif
}
+ assert(n <= m);
+
+ if (object_pid) {
+ r = get_process_uid(object_pid, &object_uid);
+ if (r >= 0) {
+ sprintf(o_uid, "OBJECT_UID=%lu", (unsigned long) object_uid);
+ IOVEC_SET_STRING(iovec[n++], o_uid);
+ }
+
+ r = get_process_gid(object_pid, &object_gid);
+ if (r >= 0) {
+ sprintf(o_gid, "OBJECT_GID=%lu", (unsigned long) object_gid);
+ IOVEC_SET_STRING(iovec[n++], o_gid);
+ }
+
+ r = get_process_comm(object_pid, &t);
+ if (r >= 0) {
+ x = strappenda("OBJECT_COMM=", t);
+ free(t);
+ IOVEC_SET_STRING(iovec[n++], x);
+ }
+
+ r = get_process_exe(object_pid, &t);
+ if (r >= 0) {
+ x = strappenda("OBJECT_EXE=", t);
+ free(t);
+ IOVEC_SET_STRING(iovec[n++], x);
+ }
+
+ r = get_process_cmdline(object_pid, 0, false, &t);
+ if (r >= 0) {
+ x = strappenda("OBJECT_CMDLINE=", t);
+ free(t);
+ IOVEC_SET_STRING(iovec[n++], x);
+ }
+
+#ifdef HAVE_AUDIT
+ r = audit_session_from_pid(object_pid, &audit);
+ if (r >= 0) {
+ sprintf(o_audit_session, "OBJECT_AUDIT_SESSION=%lu", (unsigned long) audit);
+ IOVEC_SET_STRING(iovec[n++], o_audit_session);
+ }
+
+ r = audit_loginuid_from_pid(object_pid, &loginuid);
+ if (r >= 0) {
+ sprintf(o_audit_loginuid, "OBJECT_AUDIT_LOGINUID=%lu", (unsigned long) loginuid);
+ IOVEC_SET_STRING(iovec[n++], o_audit_loginuid);
+ }
+#endif
+
+ r = cg_pid_get_path_shifted(object_pid, NULL, &c);
+ if (r >= 0) {
+ x = strappenda("OBJECT_SYSTEMD_CGROUP=", c);
+ IOVEC_SET_STRING(iovec[n++], x);
+
+ r = cg_path_get_session(c, &t);
+ if (r >= 0) {
+ x = strappenda("OBJECT_SYSTEMD_SESSION=", t);
+ free(t);
+ IOVEC_SET_STRING(iovec[n++], x);
+ }
+
+ if (cg_path_get_owner_uid(c, &owner) >= 0) {
+ sprintf(o_owner_uid, "OBJECT_SYSTEMD_OWNER_UID=%lu", (unsigned long) owner);
+ IOVEC_SET_STRING(iovec[n++], o_owner_uid);
+ }
+
+ if (cg_path_get_unit(c, &t) >= 0) {
+ x = strappenda("OBJECT_SYSTEMD_UNIT=", t);
+ free(t);
+ IOVEC_SET_STRING(iovec[n++], x);
+ }
+
+ if (cg_path_get_user_unit(c, &t) >= 0) {
+ x = strappenda("OBJECT_SYSTEMD_USER_UNIT=", t);
+ free(t);
+ IOVEC_SET_STRING(iovec[n++], x);
+ }
+
+ free(c);
+ }
+ }
+ assert(n <= m);
if (tv) {
sprintf(source_time, "_SOURCE_REALTIME_TIMESTAMP=%llu", (unsigned long long) timeval_load(tv));
@@ -642,21 +738,21 @@ static void dispatch_message_real(
* anyway. However, we need this indexed, too. */
r = sd_id128_get_boot(&id);
if (r >= 0) {
- sd_id128_to_string(id, boot_id + sizeof("_BOOT_ID=") - 1);
+ sd_id128_to_string(id, boot_id + strlen("_BOOT_ID="));
IOVEC_SET_STRING(iovec[n++], boot_id);
}
r = sd_id128_get_machine(&id);
if (r >= 0) {
- sd_id128_to_string(id, machine_id + sizeof("_MACHINE_ID=") - 1);
+ sd_id128_to_string(id, machine_id + strlen("_MACHINE_ID="));
IOVEC_SET_STRING(iovec[n++], machine_id);
}
t = gethostname_malloc();
if (t) {
- hostname = strappenda("_HOSTNAME=", t);
+ x = strappenda("_HOSTNAME=", t);
free(t);
- IOVEC_SET_STRING(iovec[n++], hostname);
+ IOVEC_SET_STRING(iovec[n++], x);
}
assert(n <= m);
@@ -675,7 +771,7 @@ static void dispatch_message_real(
else
journal_uid = 0;
- write_to_journal(s, journal_uid, iovec, n);
+ write_to_journal(s, journal_uid, iovec, n, priority);
}
void server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) {
@@ -709,7 +805,7 @@ void server_driver_message(Server *s, sd_id128_t message_id, const char *format,
ucred.uid = getuid();
ucred.gid = getgid();
- dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL);
+ dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL, LOG_INFO, 0);
}
void server_dispatch_message(
@@ -719,7 +815,8 @@ void server_dispatch_message(
struct timeval *tv,
const char *label, size_t label_len,
const char *unit_id,
- int priority) {
+ int priority,
+ pid_t object_pid) {
int rl, r;
_cleanup_free_ char *path = NULL;
@@ -734,6 +831,11 @@ void server_dispatch_message(
if (LOG_PRI(priority) > s->max_level_store)
return;
+ /* Stop early in case the information will not be stored
+ * in a journal. */
+ if (s->storage == STORAGE_NONE)
+ return;
+
if (!ucred)
goto finish;
@@ -758,7 +860,7 @@ void server_dispatch_message(
}
rl = journal_rate_limit_test(s->rate_limit, path,
- priority & LOG_PRIMASK, available_space(s));
+ priority & LOG_PRIMASK, available_space(s, false));
if (rl == 0)
return;
@@ -769,7 +871,7 @@ void server_dispatch_message(
"Suppressed %u messages from %s", rl - 1, path);
finish:
- dispatch_message_real(s, iovec, n, m, ucred, tv, label, label_len, unit_id);
+ dispatch_message_real(s, iovec, n, m, ucred, tv, label, label_len, unit_id, priority, object_pid);
}
@@ -780,8 +882,10 @@ static int system_journal_open(Server *s) {
char ids[33];
r = sd_id128_get_machine(&machine);
- if (r < 0)
+ if (r < 0) {
+ log_error("Failed to get machine id: %s", strerror(-r));
return r;
+ }
sd_id128_to_string(machine, ids);
@@ -798,29 +902,15 @@ static int system_journal_open(Server *s) {
if (s->storage == STORAGE_PERSISTENT)
(void) mkdir("/var/log/journal/", 0755);
- fn = strappend("/var/log/journal/", ids);
- if (!fn)
- return -ENOMEM;
-
+ fn = strappenda("/var/log/journal/", ids);
(void) mkdir(fn, 0755);
- free(fn);
-
- fn = strjoin("/var/log/journal/", ids, "/system.journal", NULL);
- if (!fn)
- return -ENOMEM;
+ fn = strappenda(fn, "/system.journal");
r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &s->system_journal);
- free(fn);
-
- if (r >= 0) {
- char fb[FORMAT_BYTES_MAX];
+ if (r >= 0)
server_fix_perms(s, s->system_journal, 0);
- server_driver_message(s, SD_ID128_NULL, "Allowing system journal files to grow to %s.",
- format_bytes(fb, sizeof(fb), s->system_metrics.max_use));
-
- } else if (r < 0) {
-
+ else if (r < 0) {
if (r != -ENOENT && r != -EROFS)
log_warning("Failed to open system journal: %s", strerror(-r));
@@ -866,15 +956,12 @@ static int system_journal_open(Server *s) {
}
}
- if (s->runtime_journal) {
- char fb[FORMAT_BYTES_MAX];
-
+ if (s->runtime_journal)
server_fix_perms(s, s->runtime_journal, 0);
- server_driver_message(s, SD_ID128_NULL, "Allowing runtime journal files to grow to %s.",
- format_bytes(fb, sizeof(fb), s->runtime_metrics.max_use));
- }
}
+ available_space(s, true);
+
return r;
}
@@ -900,10 +987,8 @@ int server_flush_to_var(Server *s) {
log_debug("Flushing to /var...");
r = sd_id128_get_machine(&machine);
- if (r < 0) {
- log_error("Failed to get machine id: %s", strerror(-r));
+ if (r < 0)
return r;
- }
r = sd_journal_open(&j, SD_JOURNAL_RUNTIME_ONLY);
if (r < 0) {
@@ -975,7 +1060,8 @@ int process_event(Server *s, struct epoll_event *ev) {
ssize_t n;
if (ev->events != EPOLLIN) {
- log_error("Got invalid event from epoll.");
+ log_error("Got invalid event from epoll for %s: %"PRIx32,
+ "signal fd", ev->events);
return -EIO;
}
@@ -992,6 +1078,8 @@ int process_event(Server *s, struct epoll_event *ev) {
}
if (sfsi.ssi_signo == SIGUSR1) {
+ log_info("Received request to flush runtime journal from PID %"PRIu32,
+ sfsi.ssi_pid);
touch("/run/systemd/journal/flushed");
server_flush_to_var(s);
server_sync(s);
@@ -999,6 +1087,8 @@ int process_event(Server *s, struct epoll_event *ev) {
}
if (sfsi.ssi_signo == SIGUSR2) {
+ log_info("Received request to rotate journal from PID %"PRIu32,
+ sfsi.ssi_pid);
server_rotate(s);
server_vacuum(s);
return 1;
@@ -1024,8 +1114,12 @@ int process_event(Server *s, struct epoll_event *ev) {
} else if (ev->data.fd == s->dev_kmsg_fd) {
int r;
- if (ev->events != EPOLLIN) {
- log_error("Got invalid event from epoll.");
+ if (ev->events & EPOLLERR)
+ log_warning("/dev/kmsg buffer overrun, some messages lost.");
+
+ if (!(ev->events & EPOLLIN)) {
+ log_error("Got invalid event from epoll for %s: %"PRIx32,
+ "/dev/kmsg", ev->events);
return -EIO;
}
@@ -1039,7 +1133,9 @@ int process_event(Server *s, struct epoll_event *ev) {
ev->data.fd == s->syslog_fd) {
if (ev->events != EPOLLIN) {
- log_error("Got invalid event from epoll.");
+ log_error("Got invalid event from epoll for %s: %"PRIx32,
+ ev->data.fd == s->native_fd ? "native fd" : "syslog fd",
+ ev->events);
return -EIO;
}
@@ -1126,8 +1222,8 @@ int process_event(Server *s, struct epoll_event *ev) {
label = (char*) CMSG_DATA(cmsg);
label_len = cmsg->cmsg_len - CMSG_LEN(0);
} else if (cmsg->cmsg_level == SOL_SOCKET &&
- cmsg->cmsg_type == SO_TIMESTAMP &&
- cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
+ cmsg->cmsg_type == SO_TIMESTAMP &&
+ cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
tv = (struct timeval*) CMSG_DATA(cmsg);
else if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_RIGHTS) {
@@ -1137,15 +1233,8 @@ int process_event(Server *s, struct epoll_event *ev) {
}
if (ev->data.fd == s->syslog_fd) {
- char *e;
-
if (n > 0 && n_fds == 0) {
- e = memchr(s->buffer, '\n', n);
- if (e)
- *e = 0;
- else
- s->buffer[n] = 0;
-
+ s->buffer[n] = 0;
server_process_syslog_message(s, strstrip(s->buffer), ucred, tv, label, label_len);
} else if (n_fds > 0)
log_warning("Got file descriptors via syslog socket. Ignoring.");
@@ -1167,7 +1256,8 @@ int process_event(Server *s, struct epoll_event *ev) {
} else if (ev->data.fd == s->stdout_fd) {
if (ev->events != EPOLLIN) {
- log_error("Got invalid event from epoll.");
+ log_error("Got invalid event from epoll for %s: %"PRIx32,
+ "stdout fd", ev->events);
return -EIO;
}
@@ -1178,7 +1268,8 @@ int process_event(Server *s, struct epoll_event *ev) {
StdoutStream *stream;
if ((ev->events|EPOLLIN|EPOLLHUP) != (EPOLLIN|EPOLLHUP)) {
- log_error("Got invalid event from epoll.");
+ log_error("Got invalid event from epoll for %s: %"PRIx32,
+ "stdout stream", ev->events);
return -EIO;
}
@@ -1323,19 +1414,24 @@ static int server_open_sync_timer(Server *s) {
return 0;
}
-int server_schedule_sync(Server *s) {
+int server_schedule_sync(Server *s, int priority) {
int r;
assert(s);
+ if (priority <= LOG_CRIT) {
+ /* Immediately sync to disk when this is of priority CRIT, ALERT, EMERG */
+ server_sync(s);
+ return 0;
+ }
+
if (s->sync_scheduled)
return 0;
if (s->sync_interval_usec) {
- struct itimerspec sync_timer_enable = {
- .it_value.tv_sec = s->sync_interval_usec / USEC_PER_SEC,
- .it_value.tv_nsec = s->sync_interval_usec % MSEC_PER_SEC,
- };
+ struct itimerspec sync_timer_enable = {};
+
+ timespec_store(&sync_timer_enable.it_value, s->sync_interval_usec);
r = timerfd_settime(s->sync_timer_fd, 0, &sync_timer_enable, NULL);
if (r < 0)
@@ -1354,7 +1450,7 @@ int server_init(Server *s) {
zero(*s);
s->sync_timer_fd = s->syslog_fd = s->native_fd = s->stdout_fd =
- s->signal_fd = s->epoll_fd = s->dev_kmsg_fd = -1;
+ s->signal_fd = s->epoll_fd = s->dev_kmsg_fd = -1;
s->compress = true;
s->seal = true;
diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h
index 129f7e8ab4..10e9958be0 100644
--- a/src/journal/journald-server.h
+++ b/src/journal/journald-server.h
@@ -97,9 +97,6 @@ typedef struct Server {
usec_t max_file_usec;
usec_t oldest_file_usec;
- gid_t file_gid;
- bool file_gid_valid;
-
LIST_HEAD(StdoutStream, stdout_streams);
unsigned n_stdout_streams;
@@ -125,11 +122,12 @@ typedef struct Server {
bool sync_scheduled;
} Server;
-#define N_IOVEC_META_FIELDS 17
+#define N_IOVEC_META_FIELDS 20
#define N_IOVEC_KERNEL_FIELDS 64
#define N_IOVEC_UDEV_FIELDS 32
+#define N_IOVEC_OBJECT_FIELDS 11
-void server_dispatch_message(Server *s, struct iovec *iovec, unsigned n, unsigned m, struct ucred *ucred, struct timeval *tv, const char *label, size_t label_len, const char *unit_id, int priority);
+void server_dispatch_message(Server *s, struct iovec *iovec, unsigned n, unsigned m, struct ucred *ucred, struct timeval *tv, const char *label, size_t label_len, const char *unit_id, int priority, pid_t object_pid);
void server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) _printf_attr_(3,4);
/* gperf lookup function */
@@ -152,7 +150,7 @@ void server_done(Server *s);
void server_sync(Server *s);
void server_vacuum(Server *s);
void server_rotate(Server *s);
-int server_schedule_sync(Server *s);
+int server_schedule_sync(Server *s, int priority);
int server_flush_to_var(Server *s);
int process_event(Server *s, struct epoll_event *ev);
void server_maybe_append_tags(Server *s);
diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c
index 6d51c29083..9c4efec9bc 100644
--- a/src/journal/journald-stream.c
+++ b/src/journal/journald-stream.c
@@ -90,7 +90,7 @@ static int stdout_stream_log(StdoutStream *s, const char *p) {
priority = s->priority;
if (s->level_prefix)
- syslog_parse_priority((char**) &p, &priority);
+ syslog_parse_priority((char**) &p, &priority, false);
if (s->forward_to_syslog || s->server->forward_to_syslog)
server_forward_syslog(s->server, syslog_fixup_facility(priority), s->identifier, p, &s->ucred, NULL);
@@ -127,7 +127,7 @@ static int stdout_stream_log(StdoutStream *s, const char *p) {
}
#endif
- server_dispatch_message(s->server, iovec, n, ELEMENTSOF(iovec), &s->ucred, NULL, label, label_len, s->unit_id, priority);
+ server_dispatch_message(s->server, iovec, n, ELEMENTSOF(iovec), &s->ucred, NULL, label, label_len, s->unit_id, priority, 0);
free(message);
free(syslog_priority);
@@ -440,7 +440,7 @@ int server_open_stdout_socket(Server *s) {
chmod(sa.un.sun_path, 0666);
if (listen(s->stdout_fd, SOMAXCONN) < 0) {
- log_error("liste() failed: %m");
+ log_error("listen() failed: %m");
return -errno;
}
} else
diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c
index 000f5acc10..c2770a53d0 100644
--- a/src/journal/journald-syslog.c
+++ b/src/journal/journald-syslog.c
@@ -236,7 +236,7 @@ size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid)
return e;
}
-void syslog_parse_priority(char **p, int *priority) {
+void syslog_parse_priority(char **p, int *priority, bool with_facility) {
int a = 0, b = 0, c = 0;
int k;
@@ -265,10 +265,14 @@ void syslog_parse_priority(char **p, int *priority) {
} else
return;
- if (a < 0 || b < 0 || c < 0)
+ if (a < 0 || b < 0 || c < 0 ||
+ (!with_facility && (a || b || c > 7)))
return;
- *priority = a*100+b*10+c;
+ if (with_facility)
+ *priority = a*100 + b*10 + c;
+ else
+ *priority = (*priority & LOG_FACMASK) | c;
*p += k;
}
@@ -361,7 +365,7 @@ void server_process_syslog_message(
assert(buf);
orig = buf;
- syslog_parse_priority((char**) &buf, &priority);
+ syslog_parse_priority((char**) &buf, &priority, true);
if (s->forward_to_syslog)
forward_syslog_raw(s, priority, orig, ucred, tv);
@@ -400,7 +404,7 @@ void server_process_syslog_message(
if (message)
IOVEC_SET_STRING(iovec[n++], message);
- server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), ucred, tv, label, label_len, NULL, priority);
+ server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), ucred, tv, label, label_len, NULL, priority, 0);
free(message);
free(identifier);
diff --git a/src/journal/journald-syslog.h b/src/journal/journald-syslog.h
index 324b70eef0..8ccdb77a09 100644
--- a/src/journal/journald-syslog.h
+++ b/src/journal/journald-syslog.h
@@ -25,7 +25,7 @@
int syslog_fixup_facility(int priority) _const_;
-void syslog_parse_priority(char **p, int *priority);
+void syslog_parse_priority(char **p, int *priority, bool with_facility);
size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid);
void server_forward_syslog(Server *s, int priority, const char *identifier, const char *message, struct ucred *ucred, struct timeval *tv);
diff --git a/src/journal/journald.conf b/src/journal/journald.conf
index 5410477201..54f6833a17 100644
--- a/src/journal/journald.conf
+++ b/src/journal/journald.conf
@@ -13,8 +13,8 @@
#Seal=yes
#SplitMode=login
#SyncIntervalSec=5m
-#RateLimitInterval=10s
-#RateLimitBurst=200
+#RateLimitInterval=30s
+#RateLimitBurst=1000
#SystemMaxUse=
#SystemKeepFree=
#SystemMaxFileSize=
diff --git a/src/journal/libsystemd-journal.sym b/src/journal/libsystemd-journal.sym
index 449f37c4da..4eb15910d2 100644
--- a/src/journal/libsystemd-journal.sym
+++ b/src/journal/libsystemd-journal.sym
@@ -104,3 +104,8 @@ LIBSYSTEMD_JOURNAL_202 {
global:
sd_journal_add_conjunction;
} LIBSYSTEMD_JOURNAL_201;
+
+LIBSYSTEMD_JOURNAL_205 {
+global:
+ sd_journal_open_files;
+} LIBSYSTEMD_JOURNAL_202;
diff --git a/src/journal/mmap-cache.c b/src/journal/mmap-cache.c
index 767f555526..03b57beb04 100644
--- a/src/journal/mmap-cache.c
+++ b/src/journal/mmap-cache.c
@@ -307,9 +307,13 @@ static void mmap_cache_free(MMapCache *m) {
while ((c = hashmap_first(m->contexts)))
context_free(c);
+ hashmap_free(m->contexts);
+
while ((f = hashmap_first(m->fds)))
fd_free(f);
+ hashmap_free(m->fds);
+
while (m->unused)
window_free(m->unused);
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
index c21712b7c4..7700d6cb12 100644
--- a/src/journal/sd-journal.c
+++ b/src/journal/sd-journal.c
@@ -33,6 +33,7 @@
#include "journal-file.h"
#include "hashmap.h"
#include "list.h"
+#include "strv.h"
#include "path-util.h"
#include "lookup3.h"
#include "compress.h"
@@ -49,6 +50,15 @@
#define DEFAULT_DATA_THRESHOLD (64*1024)
+static bool journal_pid_changed(sd_journal *j) {
+ assert(j);
+
+ /* We don't support people creating a journal object and
+ * keeping it around over a fork(). Let's complain. */
+
+ return j->original_pid != getpid();
+}
+
/* We return an error here only if we didn't manage to
memorize the real error. */
static int set_put_error(sd_journal *j, int r) {
@@ -101,7 +111,8 @@ static void init_location(Location *l, LocationType type, JournalFile *f, Object
l->seqnum_set = l->realtime_set = l->monotonic_set = l->xor_hash_set = true;
}
-static void set_location(sd_journal *j, LocationType type, JournalFile *f, Object *o, uint64_t offset) {
+static void set_location(sd_journal *j, LocationType type, JournalFile *f, Object *o,
+ direction_t direction, uint64_t offset) {
assert(j);
assert(type == LOCATION_DISCRETE || type == LOCATION_SEEK);
assert(f);
@@ -109,12 +120,10 @@ static void set_location(sd_journal *j, LocationType type, JournalFile *f, Objec
init_location(&j->current_location, type, f, o);
- if (j->current_file)
- j->current_file->current_offset = 0;
-
j->current_file = f;
j->current_field = 0;
+ f->last_direction = direction;
f->current_offset = offset;
}
@@ -163,7 +172,7 @@ static bool same_field(const void *_a, size_t s, const void *_b, size_t t) {
return true;
}
- return true;
+ assert_not_reached("\"=\" not found");
}
static Match *match_new(Match *p, MatchType t) {
@@ -197,9 +206,7 @@ static void match_free(Match *m) {
}
static void match_free_if_empty(Match *m) {
- assert(m);
-
- if (m->matches)
+ if (!m || m->matches)
return;
match_free(m);
@@ -211,6 +218,8 @@ _public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size)
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
if (!data)
return -EINVAL;
@@ -296,23 +305,19 @@ _public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size)
return 0;
fail:
- if (add_here)
- match_free_if_empty(add_here);
-
- if (j->level2)
- match_free_if_empty(j->level2);
-
- if (j->level1)
- match_free_if_empty(j->level1);
-
- if (j->level0)
- match_free_if_empty(j->level0);
+ match_free_if_empty(add_here);
+ match_free_if_empty(j->level2);
+ match_free_if_empty(j->level1);
+ match_free_if_empty(j->level0);
return -ENOMEM;
}
_public_ int sd_journal_add_conjunction(sd_journal *j) {
- assert(j);
+ if (!j)
+ return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
if (!j->level0)
return 0;
@@ -330,7 +335,10 @@ _public_ int sd_journal_add_conjunction(sd_journal *j) {
}
_public_ int sd_journal_add_disjunction(sd_journal *j) {
- assert(j);
+ if (!j)
+ return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
if (!j->level0)
return 0;
@@ -354,7 +362,7 @@ static char *match_make_string(Match *m) {
bool enclose = false;
if (!m)
- return strdup("");
+ return strdup("none");
if (m->type == MATCH_DISCRETE)
return strndup(m->data, m->size);
@@ -380,10 +388,8 @@ static char *match_make_string(Match *m) {
p = k;
enclose = true;
- } else {
- free(p);
+ } else
p = t;
- }
}
if (enclose) {
@@ -402,7 +408,6 @@ char *journal_make_match_string(sd_journal *j) {
}
_public_ void sd_journal_flush_matches(sd_journal *j) {
-
if (!j)
return;
@@ -596,52 +601,47 @@ static int next_for_match(
if (r < 0)
return r;
else if (r > 0) {
- if (np == 0 || (direction == DIRECTION_DOWN ? np > cp : np < cp))
+ if (np == 0 || (direction == DIRECTION_DOWN ? cp < np : cp > np))
np = cp;
}
}
+ if (np == 0)
+ return 0;
+
} else if (m->type == MATCH_AND_TERM) {
- Match *i;
- bool continue_looking;
+ Match *i, *last_moved;
/* Always jump to the next matching entry and repeat
- * this until we fine and offset that matches for all
+ * this until we find an offset that matches for all
* matches. */
if (!m->matches)
return 0;
- np = 0;
- do {
- continue_looking = false;
+ r = next_for_match(j, m->matches, f, after_offset, direction, NULL, &np);
+ if (r <= 0)
+ return r;
- LIST_FOREACH(matches, i, m->matches) {
- uint64_t cp, limit;
+ assert(direction == DIRECTION_DOWN ? np >= after_offset : np <= after_offset);
+ last_moved = m->matches;
- if (np == 0)
- limit = after_offset;
- else if (direction == DIRECTION_DOWN)
- limit = MAX(np, after_offset);
- else
- limit = MIN(np, after_offset);
+ LIST_LOOP_BUT_ONE(matches, i, m->matches, last_moved) {
+ uint64_t cp;
- r = next_for_match(j, i, f, limit, direction, NULL, &cp);
- if (r <= 0)
- return r;
+ r = next_for_match(j, i, f, np, direction, NULL, &cp);
+ if (r <= 0)
+ return r;
- if ((direction == DIRECTION_DOWN ? cp >= after_offset : cp <= after_offset) &&
- (np == 0 || (direction == DIRECTION_DOWN ? cp > np : cp < np))) {
- np = cp;
- continue_looking = true;
- }
+ assert(direction == DIRECTION_DOWN ? cp >= np : cp <= np);
+ if (direction == DIRECTION_DOWN ? cp > np : cp < np) {
+ np = cp;
+ last_moved = i;
}
-
- } while (continue_looking);
+ }
}
- if (np == 0)
- return 0;
+ assert(np > 0);
r = journal_file_move_to_object(f, OBJECT_ENTRY, np, &n);
if (r < 0)
@@ -746,7 +746,7 @@ static int find_location_for_match(
if (r <= 0)
return r;
- if (np == 0 || (direction == DIRECTION_DOWN ? np < cp : np > cp))
+ if (np == 0 || (direction == DIRECTION_DOWN ? cp > np : cp < np))
np = cp;
}
@@ -826,7 +826,7 @@ static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direc
assert(j);
assert(f);
- if (f->current_offset > 0) {
+ if (f->last_direction == direction && f->current_offset > 0) {
cp = f->current_offset;
r = journal_file_move_to_object(f, OBJECT_ENTRY, cp, &c);
@@ -842,7 +842,7 @@ static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direc
return r;
}
- /* OK, we found the spot, now let's advance until to an entry
+ /* OK, we found the spot, now let's advance until an entry
* that is actually different from what we were previously
* looking at. This is necessary to handle entries which exist
* in two (or more) journal files, and which shall all be
@@ -886,6 +886,8 @@ static int real_journal_next(sd_journal *j, direction_t direction) {
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
HASHMAP_FOREACH(f, j->files, i) {
bool found;
@@ -904,10 +906,7 @@ static int real_journal_next(sd_journal *j, direction_t direction) {
k = compare_entry_order(f, o, new_file, new_offset);
- if (direction == DIRECTION_DOWN)
- found = k < 0;
- else
- found = k > 0;
+ found = direction == DIRECTION_DOWN ? k < 0 : k > 0;
}
if (found) {
@@ -923,7 +922,7 @@ static int real_journal_next(sd_journal *j, direction_t direction) {
if (r < 0)
return r;
- set_location(j, LOCATION_DISCRETE, new_file, o, new_offset);
+ set_location(j, LOCATION_DISCRETE, new_file, o, direction, new_offset);
return 1;
}
@@ -941,6 +940,8 @@ static int real_journal_next_skip(sd_journal *j, direction_t direction, uint64_t
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
if (skip == 0) {
/* If this is not a discrete skip, then at least
@@ -981,6 +982,8 @@ _public_ int sd_journal_get_cursor(sd_journal *j, char **cursor) {
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
if (!cursor)
return -EINVAL;
@@ -995,11 +998,11 @@ _public_ int sd_journal_get_cursor(sd_journal *j, char **cursor) {
sd_id128_to_string(o->entry.boot_id, bid);
if (asprintf(cursor,
- "s=%s;i=%llx;b=%s;m=%llx;t=%llx;x=%llx",
- sid, (unsigned long long) le64toh(o->entry.seqnum),
- bid, (unsigned long long) le64toh(o->entry.monotonic),
- (unsigned long long) le64toh(o->entry.realtime),
- (unsigned long long) le64toh(o->entry.xor_hash)) < 0)
+ "s=%s;i=%"PRIx64";b=%s;m=%"PRIx64";t=%"PRIx64";x=%"PRIx64,
+ sid, le64toh(o->entry.seqnum),
+ bid, le64toh(o->entry.monotonic),
+ le64toh(o->entry.realtime),
+ le64toh(o->entry.xor_hash)) < 0)
return -ENOMEM;
return 0;
@@ -1020,6 +1023,8 @@ _public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) {
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
if (isempty(cursor))
return -EINVAL;
@@ -1119,6 +1124,8 @@ _public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) {
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
if (isempty(cursor))
return -EINVAL;
@@ -1197,6 +1204,8 @@ _public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) {
_public_ int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t usec) {
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
reset_location(j);
j->current_location.type = LOCATION_SEEK;
@@ -1210,6 +1219,8 @@ _public_ int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, u
_public_ int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec) {
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
reset_location(j);
j->current_location.type = LOCATION_SEEK;
@@ -1222,6 +1233,8 @@ _public_ int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec) {
_public_ int sd_journal_seek_head(sd_journal *j) {
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
reset_location(j);
j->current_location.type = LOCATION_HEAD;
@@ -1232,6 +1245,8 @@ _public_ int sd_journal_seek_head(sd_journal *j) {
_public_ int sd_journal_seek_tail(sd_journal *j) {
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
reset_location(j);
j->current_location.type = LOCATION_TAIL;
@@ -1251,48 +1266,67 @@ static void check_network(sd_journal *j, int fd) {
return;
j->on_network =
- F_TYPE_CMP(sfs.f_type, CIFS_MAGIC_NUMBER) ||
- F_TYPE_CMP(sfs.f_type, CODA_SUPER_MAGIC) ||
- F_TYPE_CMP(sfs.f_type, NCP_SUPER_MAGIC) ||
- F_TYPE_CMP(sfs.f_type, NFS_SUPER_MAGIC) ||
- F_TYPE_CMP(sfs.f_type, SMB_SUPER_MAGIC);
+ F_TYPE_EQUAL(sfs.f_type, CIFS_MAGIC_NUMBER) ||
+ F_TYPE_EQUAL(sfs.f_type, CODA_SUPER_MAGIC) ||
+ F_TYPE_EQUAL(sfs.f_type, NCP_SUPER_MAGIC) ||
+ F_TYPE_EQUAL(sfs.f_type, NFS_SUPER_MAGIC) ||
+ F_TYPE_EQUAL(sfs.f_type, SMB_SUPER_MAGIC);
}
-static int add_file(sd_journal *j, const char *prefix, const char *filename) {
- _cleanup_free_ char *path = NULL;
- int r;
- JournalFile *f;
+static bool file_has_type_prefix(const char *prefix, const char *filename) {
+ const char *full, *tilded, *atted;
- assert(j);
- assert(prefix);
- assert(filename);
+ full = strappend(prefix, ".journal");
+ tilded = strappenda(full, "~");
+ atted = strappenda(prefix, "@");
- if ((j->flags & SD_JOURNAL_SYSTEM_ONLY) &&
- !(streq(filename, "system.journal") ||
- streq(filename, "system.journal~") ||
- (startswith(filename, "system@") &&
- (endswith(filename, ".journal") || endswith(filename, ".journal~")))))
- return 0;
+ return streq(filename, full) ||
+ streq(filename, tilded) ||
+ startswith(filename, atted);
+}
- path = strjoin(prefix, "/", filename, NULL);
- if (!path)
- return -ENOMEM;
+static bool file_type_wanted(int flags, const char *filename) {
+ if (!endswith(filename, ".journal") && !endswith(filename, ".journal~"))
+ return false;
+
+ /* no flags set → every type is OK */
+ if (!(flags & (SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER)))
+ return true;
+
+ if (flags & SD_JOURNAL_SYSTEM && file_has_type_prefix("system", filename))
+ return true;
+
+ if (flags & SD_JOURNAL_CURRENT_USER) {
+ char prefix[5 + DECIMAL_STR_MAX(uid_t) + 1];
+
+ assert_se(snprintf(prefix, sizeof(prefix), "user-%lu", (unsigned long) getuid())
+ < (int) sizeof(prefix));
+
+ if (file_has_type_prefix(prefix, filename))
+ return true;
+ }
+
+ return false;
+}
+
+static int add_any_file(sd_journal *j, const char *path) {
+ JournalFile *f;
+ int r;
+
+ assert(j);
+ assert(path);
if (hashmap_get(j->files, path))
return 0;
if (hashmap_size(j->files) >= JOURNAL_FILES_MAX) {
- log_debug("Too many open journal files, not adding %s, ignoring.", path);
+ log_warning("Too many open journal files, not adding %s.", path);
return set_put_error(j, -ETOOMANYREFS);
}
r = journal_file_open(path, O_RDONLY, 0, false, false, NULL, j->mmap, NULL, &f);
- if (r < 0) {
- if (errno == ENOENT)
- return 0;
-
+ if (r < 0)
return r;
- }
/* journal_file_dump(f); */
@@ -1302,7 +1336,7 @@ static int add_file(sd_journal *j, const char *prefix, const char *filename) {
return r;
}
- log_debug("File %s got added.", f->path);
+ log_debug("File %s added.", f->path);
check_network(j, f->fd);
@@ -1311,6 +1345,28 @@ static int add_file(sd_journal *j, const char *prefix, const char *filename) {
return 0;
}
+static int add_file(sd_journal *j, const char *prefix, const char *filename) {
+ _cleanup_free_ char *path = NULL;
+ int r;
+
+ assert(j);
+ assert(prefix);
+ assert(filename);
+
+ if (j->no_new_files ||
+ !file_type_wanted(j->flags, filename))
+ return 0;
+
+ path = strjoin(prefix, "/", filename, NULL);
+ if (!path)
+ return -ENOMEM;
+
+ r = add_any_file(j, path);
+ if (r == -ENOENT)
+ return 0;
+ return 0;
+}
+
static int remove_file(sd_journal *j, const char *prefix, const char *filename) {
char *path;
JournalFile *f;
@@ -1330,7 +1386,7 @@ static int remove_file(sd_journal *j, const char *prefix, const char *filename)
hashmap_remove(j->files, f->path);
- log_debug("File %s got removed.", f->path);
+ log_debug("File %s removed.", f->path);
if (j->current_file == f) {
j->current_file = NULL;
@@ -1397,7 +1453,7 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname)
path = NULL; /* avoid freeing in cleanup */
j->current_invalidate_counter ++;
- log_debug("Directory %s got added.", m->path);
+ log_debug("Directory %s added.", m->path);
} else if (m->is_root)
return 0;
@@ -1476,7 +1532,7 @@ static int add_root_directory(sd_journal *j, const char *p) {
j->current_invalidate_counter ++;
- log_debug("Root directory %s got added.", m->path);
+ log_debug("Root directory %s added.", m->path);
} else if (!m->is_root)
return 0;
@@ -1491,6 +1547,9 @@ static int add_root_directory(sd_journal *j, const char *p) {
inotify_rm_watch(j->inotify_fd, m->wd);
}
+ if (j->no_new_files)
+ return 0;
+
for (;;) {
struct dirent *de;
union dirent_storage buf;
@@ -1537,9 +1596,9 @@ static int remove_directory(sd_journal *j, Directory *d) {
hashmap_remove(j->directories_by_path, d->path);
if (d->is_root)
- log_debug("Root directory %s got removed.", d->path);
+ log_debug("Root directory %s removed.", d->path);
else
- log_debug("Directory %s got removed.", d->path);
+ log_debug("Directory %s removed.", d->path);
free(d->path);
free(d);
@@ -1571,6 +1630,36 @@ static int add_search_paths(sd_journal *j) {
return 0;
}
+static int add_current_paths(sd_journal *j) {
+ Iterator i;
+ JournalFile *f;
+
+ assert(j);
+ assert(j->no_new_files);
+
+ /* Simply adds all directories for files we have open as
+ * "root" directories. We don't expect errors here, so we
+ * treat them as fatal. */
+
+ HASHMAP_FOREACH(f, j->files, i) {
+ int r;
+ _cleanup_free_ char *dir;
+
+ dir = dirname_malloc(f->path);
+ if (!dir)
+ return -ENOMEM;
+
+ r = add_root_directory(j, dir);
+ if (r < 0) {
+ set_put_error(j, r);
+ return r;
+ }
+ }
+
+ return 0;
+}
+
+
static int allocate_inotify(sd_journal *j) {
assert(j);
@@ -1596,6 +1685,7 @@ static sd_journal *journal_new(int flags, const char *path) {
if (!j)
return NULL;
+ j->original_pid = getpid();
j->inotify_fd = -1;
j->flags = flags;
j->data_threshold = DEFAULT_DATA_THRESHOLD;
@@ -1628,7 +1718,8 @@ _public_ int sd_journal_open(sd_journal **ret, int flags) {
if (flags & ~(SD_JOURNAL_LOCAL_ONLY|
SD_JOURNAL_RUNTIME_ONLY|
- SD_JOURNAL_SYSTEM_ONLY))
+ SD_JOURNAL_SYSTEM|
+ SD_JOURNAL_CURRENT_USER))
return -EINVAL;
j = journal_new(flags, NULL);
@@ -1680,6 +1771,40 @@ fail:
return r;
}
+_public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int flags) {
+ sd_journal *j;
+ const char **path;
+ int r;
+
+ if (!ret)
+ return -EINVAL;
+
+ if (flags != 0)
+ return -EINVAL;
+
+ j = journal_new(flags, NULL);
+ if (!j)
+ return -ENOMEM;
+
+ STRV_FOREACH(path, paths) {
+ r = add_any_file(j, *path);
+ if (r < 0) {
+ log_error("Failed to open %s: %s", *path, strerror(-r));
+ goto fail;
+ }
+ }
+
+ j->no_new_files = true;
+
+ *ret = j;
+ return 0;
+
+fail:
+ sd_journal_close(j);
+
+ return r;
+}
+
_public_ void sd_journal_close(sd_journal *j) {
Directory *d;
JournalFile *f;
@@ -1722,6 +1847,8 @@ _public_ int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret) {
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
if (!ret)
return -EINVAL;
@@ -1748,6 +1875,8 @@ _public_ int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id12
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
f = j->current_file;
if (!f)
@@ -1814,6 +1943,8 @@ _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void **
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
if (!field)
return -EINVAL;
if (!data)
@@ -1940,6 +2071,8 @@ _public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
if (!data)
return -EINVAL;
if (!size)
@@ -1990,6 +2123,8 @@ _public_ int sd_journal_get_fd(sd_journal *j) {
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
if (j->inotify_fd >= 0)
return j->inotify_fd;
@@ -2000,7 +2135,9 @@ _public_ int sd_journal_get_fd(sd_journal *j) {
/* Iterate through all dirs again, to add them to the
* inotify */
- if (j->path)
+ if (j->no_new_files)
+ r = add_current_paths(j);
+ else if (j->path)
r = add_root_directory(j, j->path);
else
r = add_search_paths(j);
@@ -2015,6 +2152,8 @@ _public_ int sd_journal_get_events(sd_journal *j) {
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
fd = sd_journal_get_fd(j);
if (fd < 0)
@@ -2028,6 +2167,8 @@ _public_ int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec) {
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
if (!timeout_usec)
return -EINVAL;
@@ -2128,6 +2269,8 @@ _public_ int sd_journal_process(sd_journal *j) {
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
j->last_process_usec = now(CLOCK_MONOTONIC);
@@ -2166,7 +2309,10 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) {
int r;
uint64_t t;
- assert(j);
+ if (!j)
+ return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
if (j->inotify_fd < 0) {
@@ -2215,8 +2361,12 @@ _public_ int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from,
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
if (!from && !to)
return -EINVAL;
+ if (from == to)
+ return -EINVAL;
HASHMAP_FOREACH(f, j->files, i) {
usec_t fr, t;
@@ -2254,8 +2404,12 @@ _public_ int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, sd_id128_t boot
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
if (!from && !to)
return -EINVAL;
+ if (from == to)
+ return -EINVAL;
HASHMAP_FOREACH(f, j->files, i) {
usec_t fr, t;
@@ -2309,6 +2463,8 @@ _public_ int sd_journal_get_usage(sd_journal *j, uint64_t *bytes) {
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
if (!bytes)
return -EINVAL;
@@ -2330,6 +2486,8 @@ _public_ int sd_journal_query_unique(sd_journal *j, const char *field) {
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
if (isempty(field))
return -EINVAL;
if (!field_is_valid(field))
@@ -2354,6 +2512,8 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
if (!data)
return -EINVAL;
if (!l)
@@ -2466,6 +2626,8 @@ _public_ void sd_journal_restart_unique(sd_journal *j) {
_public_ int sd_journal_reliable_fd(sd_journal *j) {
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
return !j->on_network;
}
@@ -2499,6 +2661,8 @@ _public_ int sd_journal_get_catalog(sd_journal *j, char **ret) {
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
if (!ret)
return -EINVAL;
@@ -2536,6 +2700,8 @@ _public_ int sd_journal_get_catalog_for_message_id(sd_id128_t id, char **ret) {
_public_ int sd_journal_set_data_threshold(sd_journal *j, size_t sz) {
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
j->data_threshold = sz;
return 0;
@@ -2544,6 +2710,8 @@ _public_ int sd_journal_set_data_threshold(sd_journal *j, size_t sz) {
_public_ int sd_journal_get_data_threshold(sd_journal *j, size_t *sz) {
if (!j)
return -EINVAL;
+ if (journal_pid_changed(j))
+ return -ECHILD;
if (!sz)
return -EINVAL;
diff --git a/src/journal/test-catalog.c b/src/journal/test-catalog.c
index 987867f0c8..5db5bed8de 100644
--- a/src/journal/test-catalog.c
+++ b/src/journal/test-catalog.c
@@ -31,6 +31,16 @@
#include "sd-messages.h"
#include "catalog.h"
+static const char *catalog_dirs[] = {
+ CATALOG_DIR,
+ NULL,
+};
+
+static const char *no_catalog_dirs[] = {
+ "/bin/hopefully/with/no/catalog",
+ NULL
+};
+
static void test_import(Hashmap *h, struct strbuf *sb,
const char* contents, ssize_t size, int code) {
int r;
@@ -100,9 +110,13 @@ static void test_catalog_update(void) {
r = catalog_update(database, NULL, NULL);
assert(r >= 0);
- /* Note: this might actually not find anything, if systemd was
- * not installed before. That should be fine too. */
- r = catalog_update(database, NULL, catalog_file_dirs);
+ /* Test what happens if there are no files in the directory. */
+ r = catalog_update(database, NULL, no_catalog_dirs);
+ assert(r >= 0);
+
+ /* Make sure that we at least have some files loaded or the
+ catalog_list below will fail. */
+ r = catalog_update(database, NULL, catalog_dirs);
assert(r >= 0);
}
diff --git a/src/journal/test-journal-init.c b/src/journal/test-journal-init.c
new file mode 100644
index 0000000000..58f260d6c2
--- /dev/null
+++ b/src/journal/test-journal-init.c
@@ -0,0 +1,60 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ 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 <systemd/sd-journal.h>
+
+#include "log.h"
+#include "util.h"
+
+int main(int argc, char *argv[]) {
+ sd_journal *j;
+ int r, i, I = 100;
+ char t[] = "/tmp/journal-stream-XXXXXX";
+
+ log_set_max_level(LOG_DEBUG);
+
+ if (argc >= 2)
+ safe_atoi(argv[1], &I);
+ log_info("Running %d loops", I);
+
+ assert_se(mkdtemp(t));
+
+ for (i = 0; i < I; i++) {
+ r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
+ assert_se(r == 0);
+
+ sd_journal_close(j);
+
+ r = sd_journal_open_directory(&j, t, 0);
+ assert_se(r == 0);
+
+ sd_journal_close(j);
+
+ j = NULL;
+ r = sd_journal_open_directory(&j, t, SD_JOURNAL_LOCAL_ONLY);
+ assert_se(r == -EINVAL);
+ assert_se(j == NULL);
+ }
+
+ assert_se(rm_rf_dangerous(t, false, true, false) >= 0);
+
+ return 0;
+}
diff --git a/src/journal/test-journal-interleaving.c b/src/journal/test-journal-interleaving.c
new file mode 100644
index 0000000000..1a058eaedd
--- /dev/null
+++ b/src/journal/test-journal-interleaving.c
@@ -0,0 +1,303 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2013 Marius Vollmer
+ 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 <unistd.h>
+#include <fcntl.h>
+
+#include <systemd/sd-journal.h>
+
+#include "journal-file.h"
+#include "journal-internal.h"
+#include "journal-vacuum.h"
+#include "util.h"
+#include "log.h"
+
+/* This program tests skipping around in a multi-file journal.
+ */
+
+static bool arg_keep = false;
+
+_noreturn_ static void log_assert_errno(const char *text, int eno, const char *file, int line, const char *func) {
+ log_meta(LOG_CRIT, file, line, func,
+ "'%s' failed at %s:%u (%s): %s.",
+ text, file, line, func, strerror(eno));
+ abort();
+}
+
+#define assert_ret(expr) \
+ do { \
+ int _r_ = (expr); \
+ if (_unlikely_(_r_ < 0)) \
+ log_assert_errno(#expr, -_r_, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
+ } while (false)
+
+static JournalFile *test_open (const char *name)
+{
+ JournalFile *f;
+ assert_ret(journal_file_open(name, O_RDWR|O_CREAT, 0644, true, false, NULL, NULL, NULL, &f));
+ return f;
+}
+
+static void test_close (JournalFile *f)
+{
+ journal_file_close (f);
+}
+
+static void append_number(JournalFile *f, int n, uint64_t *seqnum)
+{
+ char *p;
+ dual_timestamp ts;
+ struct iovec iovec[1];
+
+ dual_timestamp_get(&ts);
+
+ assert_se(asprintf(&p, "NUMBER=%d", n) >= 0);
+ iovec[0].iov_base = p;
+ iovec[0].iov_len = strlen(p);
+ assert_ret(journal_file_append_entry(f, &ts, iovec, 1, seqnum, NULL, NULL));
+ free (p);
+}
+
+static void test_check_number (sd_journal *j, int n)
+{
+ const void *d;
+ char *k;
+ size_t l;
+ int x;
+
+ assert_ret(sd_journal_get_data(j, "NUMBER", &d, &l));
+ assert_se(k = strndup(d, l));
+ printf("%s\n", k);
+
+ assert_se(safe_atoi(k + 7, &x) >= 0);
+ assert_se(n == x);
+}
+
+static void test_check_numbers_down (sd_journal *j, int count)
+{
+ for (int i = 1; i <= count; i++) {
+ int r;
+ test_check_number(j, i);
+ assert_ret(r = sd_journal_next(j));
+ if (i == count)
+ assert_se(r == 0);
+ else
+ assert_se(r == 1);
+ }
+
+}
+
+static void test_check_numbers_up (sd_journal *j, int count)
+{
+ for (int i = count; i >= 1; i--) {
+ int r;
+ test_check_number(j, i);
+ assert_ret(r = sd_journal_previous(j));
+ if (i == 1)
+ assert_se(r == 0);
+ else
+ assert_se(r == 1);
+ }
+
+}
+
+static void setup_sequential(void) {
+ JournalFile *one, *two;
+ one = test_open("one.journal");
+ two = test_open("two.journal");
+ append_number(one, 1, NULL);
+ append_number(one, 2, NULL);
+ append_number(two, 3, NULL);
+ append_number(two, 4, NULL);
+ test_close(one);
+ test_close(two);
+}
+
+static void setup_interleaved(void) {
+ JournalFile *one, *two;
+ one = test_open("one.journal");
+ two = test_open("two.journal");
+ append_number(one, 1, NULL);
+ append_number(two, 2, NULL);
+ append_number(one, 3, NULL);
+ append_number(two, 4, NULL);
+ test_close(one);
+ test_close(two);
+}
+
+static void test_skip(void (*setup)(void))
+{
+ char t[] = "/tmp/journal-skip-XXXXXX";
+ sd_journal *j;
+ int r;
+
+ assert_se(mkdtemp(t));
+ assert_se(chdir(t) >= 0);
+
+ setup();
+
+ /* Seek to head, iterate down.
+ */
+ assert_ret(sd_journal_open_directory(&j, t, 0));
+ assert_ret(sd_journal_seek_head(j));
+ assert_ret(sd_journal_next(j));
+ test_check_numbers_down(j, 4);
+ sd_journal_close(j);
+
+ /* Seek to tail, iterate up.
+ */
+ assert_ret(sd_journal_open_directory(&j, t, 0));
+ assert_ret(sd_journal_seek_tail(j));
+ assert_ret(sd_journal_previous(j));
+ test_check_numbers_up(j, 4);
+ sd_journal_close(j);
+
+ /* Seek to tail, skip to head, iterate down.
+ */
+ assert_ret(sd_journal_open_directory(&j, t, 0));
+ assert_ret(sd_journal_seek_tail(j));
+ assert_ret(r = sd_journal_previous_skip(j, 4));
+ assert_se(r == 4);
+ test_check_numbers_down(j, 4);
+ sd_journal_close(j);
+
+ /* Seek to head, skip to tail, iterate up.
+ */
+ assert_ret(sd_journal_open_directory(&j, t, 0));
+ assert_ret(sd_journal_seek_head(j));
+ assert_ret(r = sd_journal_next_skip(j, 4));
+ assert_se(r == 4);
+ test_check_numbers_up(j, 4);
+ sd_journal_close(j);
+
+ log_info("Done...");
+
+ if (arg_keep)
+ log_info("Not removing %s", t);
+ else {
+ journal_directory_vacuum(".", 3000000, 0, 0, NULL);
+
+ assert_se(rm_rf_dangerous(t, false, true, false) >= 0);
+ }
+
+ puts("------------------------------------------------------------");
+}
+
+static void test_sequence_numbers(void) {
+
+ char t[] = "/tmp/journal-seq-XXXXXX";
+ JournalFile *one, *two;
+ uint64_t seqnum = 0;
+ sd_id128_t seqnum_id;
+
+ assert_se(mkdtemp(t));
+ assert_se(chdir(t) >= 0);
+
+ assert_se(journal_file_open("one.journal", O_RDWR|O_CREAT, 0644,
+ true, false, NULL, NULL, NULL, &one) == 0);
+
+ append_number(one, 1, &seqnum);
+ printf("seqnum=%"PRIu64"\n", seqnum);
+ assert(seqnum == 1);
+ append_number(one, 2, &seqnum);
+ printf("seqnum=%"PRIu64"\n", seqnum);
+ assert(seqnum == 2);
+
+ assert(one->header->state == STATE_ONLINE);
+ assert(!sd_id128_equal(one->header->file_id, one->header->machine_id));
+ assert(!sd_id128_equal(one->header->file_id, one->header->boot_id));
+ assert(sd_id128_equal(one->header->file_id, one->header->seqnum_id));
+
+ memcpy(&seqnum_id, &one->header->seqnum_id, sizeof(sd_id128_t));
+
+ assert_se(journal_file_open("two.journal", O_RDWR|O_CREAT, 0644,
+ true, false, NULL, NULL, one, &two) == 0);
+
+ assert(two->header->state == STATE_ONLINE);
+ assert(!sd_id128_equal(two->header->file_id, one->header->file_id));
+ assert(sd_id128_equal(one->header->machine_id, one->header->machine_id));
+ assert(sd_id128_equal(one->header->boot_id, one->header->boot_id));
+ assert(sd_id128_equal(one->header->seqnum_id, one->header->seqnum_id));
+
+ append_number(two, 3, &seqnum);
+ printf("seqnum=%"PRIu64"\n", seqnum);
+ assert(seqnum == 3);
+ append_number(two, 4, &seqnum);
+ printf("seqnum=%"PRIu64"\n", seqnum);
+ assert(seqnum == 4);
+
+ test_close(two);
+
+ append_number(one, 5, &seqnum);
+ printf("seqnum=%"PRIu64"\n", seqnum);
+ assert(seqnum == 5);
+
+ append_number(one, 6, &seqnum);
+ printf("seqnum=%"PRIu64"\n", seqnum);
+ assert(seqnum == 6);
+
+ test_close(one);
+
+ /* restart server */
+ seqnum = 0;
+
+ assert_se(journal_file_open("two.journal", O_RDWR, 0,
+ true, false, NULL, NULL, NULL, &two) == 0);
+
+ assert(sd_id128_equal(two->header->seqnum_id, seqnum_id));
+
+ append_number(two, 7, &seqnum);
+ printf("seqnum=%"PRIu64"\n", seqnum);
+ assert(seqnum == 5);
+
+ /* So..., here we have the same seqnum in two files with the
+ * same seqnum_id. */
+
+ test_close(two);
+
+ log_info("Done...");
+
+ if (arg_keep)
+ log_info("Not removing %s", t);
+ else {
+ journal_directory_vacuum(".", 3000000, 0, 0, NULL);
+
+ assert_se(rm_rf_dangerous(t, false, true, false) >= 0);
+ }
+}
+
+int main(int argc, char *argv[]) {
+ log_set_max_level(LOG_DEBUG);
+
+ /* journal_file_open requires a valid machine id */
+ if (access("/etc/machine-id", F_OK) != 0)
+ return EXIT_TEST_SKIP;
+
+ arg_keep = argc > 1;
+
+ test_skip(setup_sequential);
+ test_skip(setup_interleaved);
+
+ test_sequence_numbers();
+
+ return 0;
+}
diff --git a/src/journal/test-journal-stream.c b/src/journal/test-journal-stream.c
index 4aba7febc7..8e1d08d596 100644
--- a/src/journal/test-journal-stream.c
+++ b/src/journal/test-journal-stream.c
@@ -75,11 +75,15 @@ int main(int argc, char *argv[]) {
JournalFile *one, *two, *three;
char t[] = "/tmp/journal-stream-XXXXXX";
unsigned i;
- _cleanup_journal_close_ sd_journal*j = NULL;
+ _cleanup_journal_close_ sd_journal *j = NULL;
char *z;
const void *data;
size_t l;
+ /* journal_file_open requires a valid machine id */
+ if (access("/etc/machine-id", F_OK) != 0)
+ return EXIT_TEST_SKIP;
+
log_set_max_level(LOG_DEBUG);
assert_se(mkdtemp(t));
diff --git a/src/journal/test-journal-verify.c b/src/journal/test-journal-verify.c
index ad2e2d4c3b..0540074207 100644
--- a/src/journal/test-journal-verify.c
+++ b/src/journal/test-journal-verify.c
@@ -77,6 +77,10 @@ int main(int argc, char *argv[]) {
struct stat st;
uint64_t p;
+ /* journal_file_open requires a valid machine id */
+ if (access("/etc/machine-id", F_OK) != 0)
+ return EXIT_TEST_SKIP;
+
log_set_max_level(LOG_DEBUG);
assert_se(mkdtemp(t));
@@ -130,10 +134,10 @@ int main(int argc, char *argv[]) {
for (p = 38448*8+0; p < ((uint64_t) st.st_size * 8); p ++) {
bit_toggle("test.journal", p);
- log_info("[ %llu+%llu]", (unsigned long long) p / 8, (unsigned long long) p % 8);
+ log_info("[ %"PRIu64"+%"PRIu64"]", p / 8, p % 8);
if (raw_verify("test.journal", verification_key) >= 0)
- log_notice(ANSI_HIGHLIGHT_RED_ON ">>>> %llu (bit %llu) can be toggled without detection." ANSI_HIGHLIGHT_OFF, (unsigned long long) p / 8, (unsigned long long) p % 8);
+ log_notice(ANSI_HIGHLIGHT_RED_ON ">>>> %"PRIu64" (bit %"PRIu64") can be toggled without detection." ANSI_HIGHLIGHT_OFF, p / 8, p % 8);
bit_toggle("test.journal", p);
}
diff --git a/src/journal/test-journal.c b/src/journal/test-journal.c
index f4dc52cd81..190c426eba 100644
--- a/src/journal/test-journal.c
+++ b/src/journal/test-journal.c
@@ -29,7 +29,9 @@
#include "journal-authenticate.h"
#include "journal-vacuum.h"
-int main(int argc, char *argv[]) {
+static bool arg_keep = false;
+
+static void test_non_empty(void) {
dual_timestamp ts;
JournalFile *f;
struct iovec iovec;
@@ -119,11 +121,65 @@ int main(int argc, char *argv[]) {
journal_file_close(f);
- journal_directory_vacuum(".", 3000000, 0, 0, NULL);
+ log_info("Done...");
+
+ if (arg_keep)
+ log_info("Not removing %s", t);
+ else {
+ journal_directory_vacuum(".", 3000000, 0, 0, NULL);
+
+ assert_se(rm_rf_dangerous(t, false, true, false) >= 0);
+ }
+
+ puts("------------------------------------------------------------");
+}
+
+static void test_empty(void) {
+ JournalFile *f1, *f2, *f3, *f4;
+ char t[] = "/tmp/journal-XXXXXX";
+
+ log_set_max_level(LOG_DEBUG);
+
+ assert_se(mkdtemp(t));
+ assert_se(chdir(t) >= 0);
+
+ assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, false, false, NULL, NULL, NULL, &f1) == 0);
+
+ assert_se(journal_file_open("test-compress.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, &f2) == 0);
+
+ assert_se(journal_file_open("test-seal.journal", O_RDWR|O_CREAT, 0666, false, true, NULL, NULL, NULL, &f3) == 0);
+
+ assert_se(journal_file_open("test-seal-compress.journal", O_RDWR|O_CREAT, 0666, true, true, NULL, NULL, NULL, &f4) == 0);
+
+ journal_file_print_header(f1);
+ puts("");
+ journal_file_print_header(f2);
+ puts("");
+ journal_file_print_header(f3);
+ puts("");
+ journal_file_print_header(f4);
+ puts("");
+
+ log_info("Done...");
+
+ if (arg_keep)
+ log_info("Not removing %s", t);
+ else {
+ journal_directory_vacuum(".", 3000000, 0, 0, NULL);
+
+ assert_se(rm_rf_dangerous(t, false, true, false) >= 0);
+ }
+}
+
+int main(int argc, char *argv[]) {
+ arg_keep = argc > 1;
- log_error("Exiting...");
+ /* journal_file_open requires a valid machine id */
+ if (access("/etc/machine-id", F_OK) != 0)
+ return EXIT_TEST_SKIP;
- assert_se(rm_rf_dangerous(t, false, true, false) >= 0);
+ test_non_empty();
+ test_empty();
return 0;
}
diff --git a/src/kernel-install/90-loaderentry.install b/src/kernel-install/90-loaderentry.install
index 55b4d24672..a6a8abc2bd 100644
--- a/src/kernel-install/90-loaderentry.install
+++ b/src/kernel-install/90-loaderentry.install
@@ -38,21 +38,30 @@ if ! [[ $PRETTY_NAME ]]; then
PRETTY_NAME="Linux $KERNEL_VERSION"
fi
+declare -a BOOT_OPTIONS
+
if [[ -f /etc/kernel/cmdline ]]; then
readarray -t BOOT_OPTIONS < /etc/kernel/cmdline
fi
if ! [[ ${BOOT_OPTIONS[*]} ]]; then
- readarray -t BOOT_OPTIONS < /proc/cmdline
+ readarray -t line < /proc/cmdline
+ for i in ${line[*]}; do
+ if [[ "${i#initrd=*}" == "$i" ]]; then
+ BOOT_OPTIONS[${#BOOT_OPTIONS[@]}]="$i"
+ fi
+ done
fi
-if ! [[ $BOOT_OPTIONS ]]; then
+if ! [[ ${BOOT_OPTIONS[*]} ]]; then
echo "Could not determine the kernel command line parameters." >&2
echo "Please specify the kernel command line in /etc/kernel/cmdline!" >&2
exit 1
fi
-cp --preserve "$KERNEL_IMAGE" "$BOOT_DIR_ABS/linux" || {
+cp "$KERNEL_IMAGE" "$BOOT_DIR_ABS/linux" &&
+ chown root:root "$BOOT_DIR_ABS/linux" &&
+ chmod 0644 "$BOOT_DIR_ABS/linux" || {
echo "Could not copy '$KERNEL_IMAGE to '$BOOT_DIR_ABS/linux'." >&2
exit 1
}
@@ -70,6 +79,7 @@ mkdir -p "${LOADER_ENTRY%/*}" || {
echo "linux $BOOT_DIR/linux"
[[ -f $BOOT_DIR_ABS/initrd ]] && \
echo "initrd $BOOT_DIR/initrd"
+ :
} > "$LOADER_ENTRY" || {
echo "Could not create loader entry '$LOADER_ENTRY'." >&2
exit 1
diff --git a/src/kernel-install/kernel-install b/src/kernel-install/kernel-install
index fb2ee57b5b..9d3e75db08 100644
--- a/src/kernel-install/kernel-install
+++ b/src/kernel-install/kernel-install
@@ -54,9 +54,15 @@ dropindirs_sort()
export LC_COLLATE=C
-COMMAND="$1"
-KERNEL_VERSION="$2"
-KERNEL_IMAGE="$3"
+if [[ "${0##*/}" == 'installkernel' ]]; then
+ COMMAND='add'
+else
+ COMMAND="$1"
+ shift
+fi
+
+KERNEL_VERSION="$1"
+KERNEL_IMAGE="$2"
if [[ -f /etc/machine-id ]]; then
read MACHINE_ID < /etc/machine-id
diff --git a/src/libsystemd-bus/bus-bloom.c b/src/libsystemd-bus/bus-bloom.c
index cb65e47b4c..04bee8581e 100644
--- a/src/libsystemd-bus/bus-bloom.c
+++ b/src/libsystemd-bus/bus-bloom.c
@@ -49,6 +49,8 @@ void bloom_add_data(uint64_t filter[BLOOM_SIZE/8], const void *data, size_t n) {
for (k = 0; k < ELEMENTSOF(hash); k++)
set_bit(filter, hash[k] & 511);
+
+ /* log_debug("bloom: adding <%.*s>", (int) n, (char*) data); */
}
void bloom_add_pair(uint64_t filter[BLOOM_SIZE/8], const char *a, const char *b) {
diff --git a/src/libsystemd-bus/bus-control.c b/src/libsystemd-bus/bus-control.c
index a4dc9bf511..0ba8585805 100644
--- a/src/libsystemd-bus/bus-control.c
+++ b/src/libsystemd-bus/bus-control.c
@@ -32,6 +32,7 @@
#include "bus-internal.h"
#include "bus-message.h"
#include "bus-control.h"
+#include "bus-bloom.h"
int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
int r;
@@ -40,6 +41,8 @@ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
return -EINVAL;
if (!unique)
return -EINVAL;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
r = bus_ensure_running(bus);
if (r < 0)
@@ -60,6 +63,10 @@ int sd_bus_request_name(sd_bus *bus, const char *name, int flags) {
return -EINVAL;
if (!bus->bus_client)
return -EINVAL;
+ if (!BUS_IS_OPEN(bus->state))
+ return -ENOTCONN;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
if (bus->is_kernel) {
struct kdbus_cmd_name *n;
@@ -68,7 +75,7 @@ int sd_bus_request_name(sd_bus *bus, const char *name, int flags) {
l = strlen(name);
n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
- n->name_flags = flags;
+ n->flags = flags;
memcpy(n->name, name, l+1);
#ifdef HAVE_VALGRIND_MEMCHECK_H
@@ -79,7 +86,7 @@ int sd_bus_request_name(sd_bus *bus, const char *name, int flags) {
if (r < 0)
return -errno;
- return n->name_flags;
+ return n->flags;
} else {
r = sd_bus_call_method(
bus,
@@ -114,6 +121,10 @@ int sd_bus_release_name(sd_bus *bus, const char *name) {
return -EINVAL;
if (!bus->bus_client)
return -EINVAL;
+ if (!BUS_IS_OPEN(bus->state))
+ return -ENOTCONN;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
if (bus->is_kernel) {
struct kdbus_cmd_name *n;
@@ -131,7 +142,7 @@ int sd_bus_release_name(sd_bus *bus, const char *name) {
if (r < 0)
return -errno;
- return n->name_flags;
+ return n->flags;
} else {
r = sd_bus_call_method(
bus,
@@ -163,6 +174,10 @@ int sd_bus_list_names(sd_bus *bus, char ***l) {
return -EINVAL;
if (!l)
return -EINVAL;
+ if (!BUS_IS_OPEN(bus->state))
+ return -ENOTCONN;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
r = sd_bus_call_method(
bus,
@@ -213,6 +228,10 @@ int sd_bus_get_owner(sd_bus *bus, const char *name, char **owner) {
return -EINVAL;
if (!name)
return -EINVAL;
+ if (!BUS_IS_OPEN(bus->state))
+ return -ENOTCONN;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
r = sd_bus_call_method(
bus,
@@ -255,6 +274,10 @@ int sd_bus_get_owner_uid(sd_bus *bus, const char *name, uid_t *uid) {
return -EINVAL;
if (!uid)
return -EINVAL;
+ if (!BUS_IS_OPEN(bus->state))
+ return -ENOTCONN;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
r = sd_bus_call_method(
bus,
@@ -288,6 +311,10 @@ int sd_bus_get_owner_pid(sd_bus *bus, const char *name, pid_t *pid) {
return -EINVAL;
if (!pid)
return -EINVAL;
+ if (!BUS_IS_OPEN(bus->state))
+ return -ENOTCONN;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
r = sd_bus_call_method(
bus,
@@ -313,36 +340,201 @@ int sd_bus_get_owner_pid(sd_bus *bus, const char *name, pid_t *pid) {
return 0;
}
-int bus_add_match_internal(sd_bus *bus, const char *match) {
+int bus_add_match_internal(
+ sd_bus *bus,
+ const char *match,
+ struct bus_match_component *components,
+ unsigned n_components,
+ uint64_t cookie) {
+
+ int r;
+
assert(bus);
assert(match);
- return sd_bus_call_method(
- bus,
- "org.freedesktop.DBus",
- "/",
- "org.freedesktop.DBus",
- "AddMatch",
- NULL,
- NULL,
- "s",
- match);
+ if (bus->is_kernel) {
+ struct kdbus_cmd_match *m;
+ struct kdbus_item *item;
+ uint64_t bloom[BLOOM_SIZE/8];
+ size_t sz;
+ const char *sender = NULL;
+ size_t sender_length = 0;
+ uint64_t src_id = KDBUS_MATCH_SRC_ID_ANY;
+ bool using_bloom = false;
+ unsigned i;
+
+ zero(bloom);
+
+ sz = 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:
+ r = bus_kernel_parse_unique_name(c->value_str, &src_id);
+ if (r < 0)
+ return r;
+
+ if (r > 0) {
+ sender = c->value_str;
+ sender_length = strlen(sender);
+ sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
+ }
+
+ break;
+
+ case BUS_MATCH_MESSAGE_TYPE:
+ bloom_add_pair(bloom, "message-type", bus_message_type_to_string(c->value_u8));
+ using_bloom = true;
+ break;
+
+ case BUS_MATCH_INTERFACE:
+ bloom_add_pair(bloom, "interface", c->value_str);
+ using_bloom = true;
+ break;
+
+ case BUS_MATCH_MEMBER:
+ bloom_add_pair(bloom, "member", c->value_str);
+ using_bloom = true;
+ break;
+
+ case BUS_MATCH_PATH:
+ bloom_add_pair(bloom, "path", c->value_str);
+ using_bloom = true;
+ break;
+
+ case BUS_MATCH_PATH_NAMESPACE:
+ if (!streq(c->value_str, "/")) {
+ bloom_add_pair(bloom, "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];
+
+ snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
+ bloom_add_pair(bloom, buf, c->value_str);
+ using_bloom = true;
+ break;
+ }
+
+ case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
+ char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
+
+ snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
+ bloom_add_pair(bloom, buf, c->value_str);
+ using_bloom = true;
+ break;
+ }
+
+ case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
+ char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
+
+ snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
+ bloom_add_pair(bloom, buf, c->value_str);
+ using_bloom = true;
+ break;
+ }
+
+ case BUS_MATCH_DESTINATION:
+ /* The bloom filter does not include
+ the destination, since it is only
+ available for broadcast messages
+ which do not carry a destination
+ since they are undirected. */
+ 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) + BLOOM_SIZE);
+
+ m = alloca0(sz);
+ m->size = sz;
+ m->cookie = cookie;
+ m->src_id = src_id;
+
+ item = m->items;
+
+ if (using_bloom) {
+ item->size = offsetof(struct kdbus_item, data64) + BLOOM_SIZE;
+ item->type = KDBUS_MATCH_BLOOM;
+ memcpy(item->data64, bloom, BLOOM_SIZE);
+
+ item = KDBUS_ITEM_NEXT(item);
+ }
+
+ if (sender) {
+ item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
+ item->type = KDBUS_MATCH_SRC_NAME;
+ memcpy(item->str, sender, sender_length + 1);
+ }
+
+ r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
+ if (r < 0)
+ return -errno;
+
+ } else {
+ return sd_bus_call_method(
+ bus,
+ "org.freedesktop.DBus",
+ "/",
+ "org.freedesktop.DBus",
+ "AddMatch",
+ NULL,
+ NULL,
+ "s",
+ match);
+ }
+
+ return 0;
}
-int bus_remove_match_internal(sd_bus *bus, const char *match) {
+int bus_remove_match_internal(
+ sd_bus *bus,
+ const char *match,
+ uint64_t cookie) {
+
+ int r;
+
assert(bus);
assert(match);
- return sd_bus_call_method(
- bus,
- "org.freedesktop.DBus",
- "/",
- "org.freedesktop.DBus",
- "RemoveMatch",
- NULL,
- NULL,
- "s",
- match);
+ if (bus->is_kernel) {
+ struct kdbus_cmd_match m;
+
+ zero(m);
+ m.size = offsetof(struct kdbus_cmd_match, items);
+ m.cookie = cookie;
+
+ r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
+ if (r < 0)
+ return -errno;
+
+ } else {
+ return sd_bus_call_method(
+ bus,
+ "org.freedesktop.DBus",
+ "/",
+ "org.freedesktop.DBus",
+ "RemoveMatch",
+ NULL,
+ NULL,
+ "s",
+ match);
+ }
+
+ return 0;
}
int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
@@ -354,6 +546,10 @@ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machi
return -EINVAL;
if (!name)
return -EINVAL;
+ if (!BUS_IS_OPEN(bus->state))
+ return -ENOTCONN;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
if (streq_ptr(name, bus->unique_name))
return sd_id128_get_machine(machine);
diff --git a/src/libsystemd-bus/bus-control.h b/src/libsystemd-bus/bus-control.h
index 34ecb260c3..2cac5d83ae 100644
--- a/src/libsystemd-bus/bus-control.h
+++ b/src/libsystemd-bus/bus-control.h
@@ -23,5 +23,5 @@
#include "sd-bus.h"
-int bus_add_match_internal(sd_bus *bus, const char *match);
-int bus_remove_match_internal(sd_bus *bus, const char *match);
+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);
diff --git a/src/libsystemd-bus/bus-error.c b/src/libsystemd-bus/bus-error.c
index 5faa17384e..4696a88f76 100644
--- a/src/libsystemd-bus/bus-error.c
+++ b/src/libsystemd-bus/bus-error.c
@@ -142,6 +142,9 @@ int bus_error_to_errno(const sd_bus_error* e) {
/* Better replce this with a gperf table */
+ if (!e)
+ return -EIO;
+
if (!e->name)
return -EIO;
@@ -152,6 +155,30 @@ int bus_error_to_errno(const sd_bus_error* e) {
streq(e->name, "org.freedesktop.DBus.Error.AccessDenied"))
return -EPERM;
+ if (streq(e->name, "org.freedesktop.DBus.Error.InvalidArgs"))
+ return -EINVAL;
+
+ if (streq(e->name, "org.freedesktop.DBus.Error.UnixProcessIdUnknown"))
+ return -ESRCH;
+
+ if (streq(e->name, "org.freedesktop.DBus.Error.FileNotFound"))
+ return -ENOENT;
+
+ if (streq(e->name, "org.freedesktop.DBus.Error.FileExists"))
+ return -EEXIST;
+
+ if (streq(e->name, "org.freedesktop.DBus.Error.Timeout"))
+ return -ETIMEDOUT;
+
+ if (streq(e->name, "org.freedesktop.DBus.Error.IOError"))
+ return -EIO;
+
+ if (streq(e->name, "org.freedesktop.DBus.Error.Disconnected"))
+ return -ECONNRESET;
+
+ if (streq(e->name, "org.freedesktop.DBus.Error.NotSupported"))
+ return -ENOTSUP;
+
return -EIO;
}
@@ -159,13 +186,54 @@ int bus_error_from_errno(sd_bus_error *e, int error) {
if (!e)
return error;
- if (error == -ENOMEM)
- sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.NoMemory", strerror(-error));
- else if (error == -EPERM || error == -EACCES)
- sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.AccessDenied", strerror(-error));
- else
- sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.Failed", "Operation failed");
+ switch (error) {
+
+ case -ENOMEM:
+ sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.NoMemory", "Out of memory");
+ break;
+
+ case -EPERM:
+ case -EACCES:
+ sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.AccessDenied", "Access denied");
+ break;
+
+ case -EINVAL:
+ sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid argument");
+ break;
+
+ case -ESRCH:
+ sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.UnixProcessIdUnknown", "No such process");
+ break;
+
+ case -ENOENT:
+ sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.FileNotFound", "File not found");
+ break;
+
+ case -EEXIST:
+ sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.FileExists", "File exists");
+ break;
+
+ case -ETIMEDOUT:
+ case -ETIME:
+ sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.Timeout", "Timed out");
+ break;
+
+ case -EIO:
+ sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.IOError", "Input/output error");
+ break;
+
+ case -ENETRESET:
+ case -ECONNABORTED:
+ case -ECONNRESET:
+ sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.Disconnected", "Disconnected");
+ break;
+
+ case -ENOTSUP:
+ sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.NotSupported", "Not supported");
+ break;
+ }
+ sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.Failed", "Operation failed");
return error;
}
diff --git a/src/libsystemd-bus/bus-internal.h b/src/libsystemd-bus/bus-internal.h
index 4babfac86d..30b8d519a0 100644
--- a/src/libsystemd-bus/bus-internal.h
+++ b/src/libsystemd-bus/bus-internal.h
@@ -24,15 +24,18 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
+#include <pthread.h>
#include "hashmap.h"
#include "prioq.h"
#include "list.h"
#include "util.h"
+#include "refcnt.h"
#include "sd-bus.h"
#include "bus-error.h"
#include "bus-match.h"
+#include "bus-kernel.h"
struct reply_callback {
sd_bus_message_handler_t callback;
@@ -66,9 +69,14 @@ enum bus_state {
BUS_OPENING,
BUS_AUTHENTICATING,
BUS_HELLO,
- BUS_RUNNING
+ BUS_RUNNING,
+ BUS_CLOSED
};
+static inline bool BUS_IS_OPEN(enum bus_state state) {
+ return state > BUS_UNSET && state < BUS_CLOSED;
+}
+
enum bus_auth {
_BUS_AUTH_INVALID,
BUS_AUTH_EXTERNAL,
@@ -76,13 +84,21 @@ enum bus_auth {
};
struct sd_bus {
- unsigned n_ref;
+ /* We use atomic ref counting here since sd_bus_message
+ objects retain references to their originating sd_bus but
+ we want to allow them to be processed in a different
+ thread. We won't provide full thread safety, but only the
+ bare minimum that makes it possible to use sd_bus and
+ sd_bus_message objects independently and on different
+ threads as long as each object is used only once at the
+ same time. */
+ RefCount n_ref;
+
enum bus_state state;
int input_fd, output_fd;
int message_version;
bool is_kernel:1;
- bool negotiate_fds:1;
bool can_fds:1;
bool bus_client:1;
bool ucred_valid:1;
@@ -95,6 +111,8 @@ struct sd_bus {
bool filter_callbacks_modified:1;
bool object_callbacks_modified:1;
+ int use_memfd;
+
void *rbuffer;
size_t rbuffer_size;
@@ -150,6 +168,24 @@ struct sd_bus {
uint64_t hello_serial;
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
+ * adding something to the memfd cache might happen when a
+ * message is released, we hence need to protect this bit with
+ * a mutex. */
+ pthread_mutex_t memfd_cache_mutex;
+ struct memfd_cache memfd_cache[MEMFD_CACHE_MAX];
+ unsigned n_memfd_cache;
+
+ pid_t original_pid;
+
+ uint64_t hello_flags;
+
+ uint64_t match_cookie;
};
static inline void bus_unrefp(sd_bus **b) {
@@ -196,3 +232,5 @@ const char *bus_message_type_to_string(uint8_t u);
int bus_ensure_running(sd_bus *bus);
int bus_start_running(sd_bus *bus);
int bus_next_address(sd_bus *bus);
+
+bool bus_pid_changed(sd_bus *bus);
diff --git a/src/libsystemd-bus/bus-kernel.c b/src/libsystemd-bus/bus-kernel.c
index 0762b7836f..bf8de04ab6 100644
--- a/src/libsystemd-bus/bus-kernel.c
+++ b/src/libsystemd-bus/bus-kernel.c
@@ -25,6 +25,7 @@
#include <fcntl.h>
#include <malloc.h>
+#include <sys/mman.h>
#include "util.h"
@@ -33,18 +34,7 @@
#include "bus-kernel.h"
#include "bus-bloom.h"
-#define KDBUS_ITEM_NEXT(item) \
- (typeof(item))(((uint8_t *)item) + ALIGN8((item)->size))
-
-#define KDBUS_ITEM_FOREACH(item, head) \
- for (item = (head)->items; \
- (uint8_t *)(item) < (uint8_t *)(head) + (head)->size; \
- item = KDBUS_ITEM_NEXT(item))
-
-#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data)
-#define KDBUS_ITEM_SIZE(s) ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE)
-
-static int parse_unique_name(const char *s, uint64_t *id) {
+int bus_kernel_parse_unique_name(const char *s, uint64_t *id) {
int r;
assert(s);
@@ -62,19 +52,36 @@ static int parse_unique_name(const char *s, uint64_t *id) {
static void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) {
assert(d);
- assert(p);
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_MSG_PAYLOAD_VEC;
- (*d)->vec.address = (intptr_t) p;
+ (*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 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_MSG_PAYLOAD_MEMFD;
+ (*d)->memfd.fd = memfd;
+ (*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);
@@ -111,7 +118,7 @@ static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) {
*d = ALIGN8_PTR(*d);
(*d)->size = offsetof(struct kdbus_item, fds) + sizeof(int) * n_fds;
- (*d)->type = KDBUS_MSG_UNIX_FDS;
+ (*d)->type = KDBUS_MSG_FDS;
memcpy((*d)->fds, fds, sizeof(int) * n_fds);
*d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
@@ -134,6 +141,7 @@ static int bus_message_setup_bloom(sd_bus_message *m, void *bloom) {
bloom_add_pair(bloom, "member", m->member);
if (m->path) {
bloom_add_pair(bloom, "path", m->path);
+ bloom_add_pair(bloom, "path-slash-prefix", m->path);
bloom_add_prefixes(bloom, "path-slash-prefix", m->path, '/');
}
@@ -181,10 +189,12 @@ static int bus_message_setup_bloom(sd_bus_message *m, void *bloom) {
}
static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
+ struct bus_body_part *part;
struct kdbus_item *d;
bool well_known;
uint64_t unique;
size_t sz, dl;
+ unsigned i;
int r;
assert(b);
@@ -195,7 +205,7 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
return 0;
if (m->destination) {
- r = parse_unique_name(m->destination, &unique);
+ r = bus_kernel_parse_unique_name(m->destination, &unique);
if (r < 0)
return r;
@@ -205,8 +215,12 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
sz = offsetof(struct kdbus_msg, items);
+ assert_cc(ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec)) ==
+ ALIGN8(offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd)));
+
/* Add in fixed header, fields header and payload */
- sz += 3 * ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec));
+ sz += (1 + m->n_body_parts) *
+ ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec));
/* Add space for bloom filter */
sz += ALIGN8(offsetof(struct kdbus_item, data) + BLOOM_SIZE);
@@ -222,9 +236,12 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
m->kdbus = memalign(8, sz);
- if (!m->kdbus)
- return -ENOMEM;
+ if (!m->kdbus) {
+ r = -ENOMEM;
+ goto fail;
+ }
+ m->free_kdbus = true;
memset(m->kdbus, 0, sz);
m->kdbus->flags =
@@ -243,24 +260,43 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
if (well_known)
append_destination(&d, m->destination, dl);
- append_payload_vec(&d, m->header, sizeof(*m->header));
+ append_payload_vec(&d, m->header, BUS_MESSAGE_BODY_BEGIN(m));
- if (m->fields)
- append_payload_vec(&d, m->fields, ALIGN8(m->header->fields_size));
+ 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 */
- if (m->body)
- append_payload_vec(&d, m->body, m->header->body_size);
+ append_payload_vec(&d, NULL, part->size);
+ continue;
+ }
+
+ if (part->memfd >= 0 && part->sealed && m->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->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->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) {
void *p;
p = append_bloom(&d, BLOOM_SIZE);
r = bus_message_setup_bloom(m, p);
- if (r < 0) {
- free(m->kdbus);
- m->kdbus = NULL;
- return -r;
- }
+ if (r < 0)
+ goto fail;
}
if (m->n_fds > 0)
@@ -269,23 +305,15 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
assert(m->kdbus->size <= sz);
- m->free_kdbus = true;
-
return 0;
+
+fail:
+ m->poisoned = true;
+ return r;
}
int bus_kernel_take_fd(sd_bus *b) {
- struct kdbus_cmd_hello hello = {
- .conn_flags =
- KDBUS_HELLO_ACCEPT_FD|
- KDBUS_HELLO_ATTACH_COMM|
- KDBUS_HELLO_ATTACH_EXE|
- KDBUS_HELLO_ATTACH_CMDLINE|
- KDBUS_HELLO_ATTACH_CGROUP|
- KDBUS_HELLO_ATTACH_CAPS|
- KDBUS_HELLO_ATTACH_SECLABEL|
- KDBUS_HELLO_ATTACH_AUDIT
- };
+ struct kdbus_cmd_hello hello;
int r;
assert(b);
@@ -293,10 +321,25 @@ int bus_kernel_take_fd(sd_bus *b) {
if (b->is_server)
return -EINVAL;
+ b->use_memfd = 1;
+
+ zero(hello);
+ hello.size = sizeof(hello);
+ hello.conn_flags = b->hello_flags;
+ hello.pool_size = KDBUS_POOL_SIZE;
+
r = ioctl(b->input_fd, KDBUS_CMD_HELLO, &hello);
if (r < 0)
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;
+ return -errno;
+ }
+ }
+
/* The higher 32bit of both flags fields are considered
* 'incompatible flags'. Refuse them all for now. */
if (hello.bus_flags > 0xFFFFFFFFULL ||
@@ -311,7 +354,7 @@ int bus_kernel_take_fd(sd_bus *b) {
b->is_kernel = true;
b->bus_client = true;
- b->can_fds = true;
+ b->can_fds = !!(hello.conn_flags & KDBUS_HELLO_ACCEPT_FD);
r = bus_start_running(b);
if (r < 0)
@@ -356,22 +399,29 @@ int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
return 1;
}
-static void close_kdbus_msg(struct kdbus_msg *k) {
+static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
+ uint64_t off;
struct kdbus_item *d;
- KDBUS_ITEM_FOREACH(d, k) {
+ assert(bus);
+ assert(k);
- if (d->type != KDBUS_MSG_UNIX_FDS)
- continue;
+ off = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer;
+ ioctl(bus->input_fd, KDBUS_CMD_MSG_RELEASE, &off);
- close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
+ KDBUS_ITEM_FOREACH(d, k) {
+
+ if (d->type == KDBUS_MSG_FDS)
+ close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
+ else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD)
+ close_nointr_nofail(d->memfd.fd);
}
}
static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) {
sd_bus_message *m = NULL;
struct kdbus_item *d;
- unsigned n_payload = 0, n_fds = 0;
+ unsigned n_fds = 0;
_cleanup_free_ int *fds = NULL;
struct bus_header *h = NULL;
size_t total, n_bytes = 0, idx = 0;
@@ -390,19 +440,25 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess
l = d->size - offsetof(struct kdbus_item, data);
- if (d->type == KDBUS_MSG_PAYLOAD) {
+ if (d->type == KDBUS_MSG_PAYLOAD_OFF) {
if (!h) {
- if (l < sizeof(struct bus_header))
- return -EBADMSG;
+ h = (struct bus_header *)((uint8_t *)bus->kdbus_buffer + d->vec.offset);
- h = (struct bus_header*) d->data;
+ if (!bus_header_is_complete(h, d->vec.size))
+ return -EBADMSG;
}
- n_payload++;
- n_bytes += l;
+ n_bytes += d->vec.size;
+
+ } else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD) {
- } else if (d->type == KDBUS_MSG_UNIX_FDS) {
+ if (!h)
+ return -EBADMSG;
+
+ n_bytes += d->memfd.size;
+
+ } else if (d->type == KDBUS_MSG_FDS) {
int *f;
unsigned j;
@@ -415,16 +471,14 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess
memcpy(fds + n_fds, d->fds, sizeof(int) * j);
n_fds += j;
- } else if (d->type == KDBUS_MSG_DST_NAME)
- destination = d->str;
- else if (d->type == KDBUS_MSG_SRC_SECLABEL)
+ } else if (d->type == KDBUS_MSG_SRC_SECLABEL)
seclabel = d->str;
}
if (!h)
return -EBADMSG;
- r = bus_header_size(h, &total);
+ r = bus_header_message_size(h, &total);
if (r < 0)
return r;
@@ -440,20 +494,59 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess
l = d->size - offsetof(struct kdbus_item, data);
- if (d->type == KDBUS_MSG_PAYLOAD) {
+ if (d->type == KDBUS_MSG_PAYLOAD_OFF) {
+ size_t begin_body;
- if (idx == sizeof(struct bus_header) &&
- l == ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m)))
- m->fields = d->data;
- else if (idx == sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m)) &&
- l == BUS_MESSAGE_BODY_SIZE(m))
- m->body = d->data;
- else if (!(idx == 0 && l == sizeof(struct bus_header))) {
- sd_bus_message_unref(m);
- return -EBADMSG;
+ 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 *)bus->kdbus_buffer + d->vec.offset;
+ part->size = d->vec.size;
+ } else {
+ if (!part->is_zero)
+ part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset + (begin_body - idx);
+ part->size = d->vec.size - (begin_body - idx);
+ }
+
+ part->sealed = true;
}
- idx += l;
+ idx += d->vec.size;
+ } else if (d->type == KDBUS_MSG_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->size = d->memfd.size;
+ part->sealed = true;
+
+ idx += d->memfd.size;
+
} else if (d->type == KDBUS_MSG_SRC_CREDS) {
m->pid_starttime = d->creds.starttime / NSEC_PER_USEC;
m->uid = d->creds.uid;
@@ -480,15 +573,16 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess
else if (d->type == KDBUS_MSG_SRC_CAPS) {
m->capability = d->data;
m->capability_size = l;
- } else
+ } else if (d->type == KDBUS_MSG_DST_NAME)
+ destination = d->str;
+ else if (d->type != KDBUS_MSG_FDS &&
+ d->type != KDBUS_MSG_SRC_SECLABEL)
log_debug("Got unknown field from kernel %llu", d->type);
}
r = bus_message_parse_fields(m);
- if (r < 0) {
- sd_bus_message_unref(m);
- return r;
- }
+ if (r < 0)
+ goto fail;
if (k->src_id == KDBUS_SRC_ID_KERNEL)
m->sender = "org.freedesktop.DBus";
@@ -509,66 +603,58 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess
/* We take possession of the kmsg struct now */
m->kdbus = k;
- m->free_kdbus = true;
+ m->bus = sd_bus_ref(bus);
+ m->release_kdbus = true;
m->free_fds = true;
fds = NULL;
*ret = m;
return 1;
+
+fail:
+ if (m) {
+ struct bus_body_part *part;
+ unsigned i;
+
+ /* Make sure the memfds are not freed twice */
+ MESSAGE_FOREACH_PART(part, i, m)
+ if (part->memfd >= 0)
+ part->memfd = -1;
+
+ sd_bus_message_unref(m);
+ }
+
+ return r;
}
int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) {
+ uint64_t off;
struct kdbus_msg *k;
- size_t sz = 1024;
int r;
assert(bus);
assert(m);
- for (;;) {
- void *q;
-
- q = memalign(8, sz);
- if (!q)
- return -errno;
-
- free(bus->rbuffer);
- k = bus->rbuffer = q;
- k->size = sz;
-
- /* Let's tell valgrind that there's really no need to
- * initialize this fully. This should be removed again
- * when valgrind learned the kdbus ioctls natively. */
-#ifdef HAVE_VALGRIND_MEMCHECK_H
- VALGRIND_MAKE_MEM_DEFINED(k, sz);
-#endif
-
- r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, bus->rbuffer);
- if (r >= 0)
- break;
-
+ r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &off);
+ if (r < 0) {
if (errno == EAGAIN)
return 0;
- if (errno != ENOBUFS)
- return -errno;
-
- sz *= 2;
+ return -errno;
}
+ k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + off);
r = bus_kernel_make_message(bus, k, m);
- if (r > 0)
- bus->rbuffer = NULL;
- else
- close_kdbus_msg(k);
+ if (r <= 0)
+ close_kdbus_msg(bus, k);
return r < 0 ? r : 1;
}
int bus_kernel_create(const char *name, char **s) {
struct kdbus_cmd_bus_make *make;
- struct kdbus_item *n, *cg;
+ struct kdbus_item *n;
size_t l;
int fd;
char *p;
@@ -585,18 +671,13 @@ int bus_kernel_create(const char *name, char **s) {
KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t) +
KDBUS_ITEM_HEADER_SIZE + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
- cg = make->items;
- cg->type = KDBUS_MAKE_CGROUP;
- cg->data64[0] = 1;
- cg->size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t);
-
- n = KDBUS_ITEM_NEXT(cg);
+ n = make->items;
n->type = KDBUS_MAKE_NAME;
sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
n->size = KDBUS_ITEM_HEADER_SIZE + strlen(n->str) + 1;
- make->size = offsetof(struct kdbus_cmd_bus_make, items) + cg->size + n->size;
- make->flags = KDBUS_MAKE_ACCESS_WORLD | KDBUS_MAKE_POLICY_OPEN;
+ make->size = offsetof(struct kdbus_cmd_bus_make, items) + n->size;
+ make->flags = KDBUS_MAKE_POLICY_OPEN;
make->bus_flags = 0;
make->bloom_size = BLOOM_SIZE;
assert_cc(BLOOM_SIZE % 8 == 0);
@@ -616,3 +697,95 @@ int bus_kernel_create(const char *name, char **s) {
return fd;
}
+
+int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size) {
+ struct memfd_cache *c;
+ int fd;
+
+ assert(address);
+ assert(size);
+
+ if (!bus || !bus->is_kernel)
+ return -ENOTSUP;
+
+ 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 = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, &fd);
+ if (r < 0)
+ return -errno;
+
+ *address = NULL;
+ *size = 0;
+ return fd;
+ }
+
+ c = &bus->memfd_cache[--bus->n_memfd_cache];
+
+ assert(c->fd >= 0);
+ assert(c->size == 0 || c->address);
+
+ *address = c->address;
+ *size = c->size;
+ 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) {
+ if (size > 0)
+ assert_se(munmap(address, PAGE_ALIGN(size)) >= 0);
+
+ close_nointr_nofail(fd);
+}
+
+void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size) {
+ struct memfd_cache *c;
+ uint64_t max_sz = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX);
+
+ assert(fd >= 0);
+ assert(size == 0 || address);
+
+ if (!bus || !bus->is_kernel) {
+ close_and_munmap(fd, address, size);
+ 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, size);
+ 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 (size > max_sz) {
+ assert_se(ioctl(fd, KDBUS_CMD_MEMFD_SIZE_SET, &max_sz) >= 0);
+ assert_se(munmap((uint8_t*) address + max_sz, PAGE_ALIGN(size - max_sz)) >= 0);
+ c->size = max_sz;
+ } else
+ c->size = size;
+
+ assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
+}
+
+void bus_kernel_flush_memfd(sd_bus *b) {
+ unsigned i;
+
+ assert(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].size);
+}
diff --git a/src/libsystemd-bus/bus-kernel.h b/src/libsystemd-bus/bus-kernel.h
index ac746afe03..c4573c9222 100644
--- a/src/libsystemd-bus/bus-kernel.h
+++ b/src/libsystemd-bus/bus-kernel.h
@@ -23,6 +23,37 @@
#include "sd-bus.h"
+#define KDBUS_ITEM_NEXT(item) \
+ (typeof(item))(((uint8_t *)item) + ALIGN8((item)->size))
+
+#define KDBUS_ITEM_FOREACH(item, head) \
+ for (item = (head)->items; \
+ (uint8_t *)(item) < (uint8_t *)(head) + (head)->size; \
+ item = KDBUS_ITEM_NEXT(item))
+
+#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
+ * longer than this in order not to keep too much data around. */
+#define MEMFD_CACHE_ITEM_SIZE_MAX (128*1024)
+
+/* This determines at which minimum size we prefer sending memfds over
+ * sending vectors */
+#define MEMFD_MIN_SIZE (128*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;
+ size_t size;
+};
+
int bus_kernel_connect(sd_bus *b);
int bus_kernel_take_fd(sd_bus *b);
@@ -30,3 +61,10 @@ int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m);
int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m);
int bus_kernel_create(const char *name, char **s);
+
+int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size);
+void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size);
+
+void bus_kernel_flush_memfd(sd_bus *bus);
+
+int bus_kernel_parse_unique_name(const char *s, uint64_t *id);
diff --git a/src/libsystemd-bus/bus-match.c b/src/libsystemd-bus/bus-match.c
index 501a38df70..1411167a7f 100644
--- a/src/libsystemd-bus/bus-match.c
+++ b/src/libsystemd-bus/bus-match.c
@@ -199,7 +199,6 @@ static bool value_node_same(
int bus_match_run(
sd_bus *bus,
struct bus_match_node *node,
- int ret,
sd_bus_message *m) {
@@ -230,7 +229,7 @@ int bus_match_run(
* we won't call any. The children of the root node
* are compares or leaves, they will automatically
* call their siblings. */
- return bus_match_run(bus, node->child, ret, m);
+ return bus_match_run(bus, node->child, m);
case BUS_MATCH_VALUE:
@@ -240,7 +239,7 @@ int bus_match_run(
* automatically call their siblings */
assert(node->child);
- return bus_match_run(bus, node->child, ret, m);
+ return bus_match_run(bus, node->child, m);
case BUS_MATCH_LEAF:
@@ -256,12 +255,13 @@ int bus_match_run(
return r;
/* Run the callback. And then invoke siblings. */
- assert(node->leaf.callback);
- r = node->leaf.callback(bus, ret, m, node->leaf.userdata);
- if (r != 0)
- return r;
+ if (node->leaf.callback) {
+ r = node->leaf.callback(bus, m, node->leaf.userdata);
+ if (r != 0)
+ return r;
+ }
- return bus_match_run(bus, node->next, ret, m);
+ return bus_match_run(bus, node->next, m);
case BUS_MATCH_MESSAGE_TYPE:
test_u8 = m->header->type;
@@ -318,7 +318,7 @@ int bus_match_run(
found = NULL;
if (found) {
- r = bus_match_run(bus, found, ret, m);
+ r = bus_match_run(bus, found, m);
if (r != 0)
return r;
}
@@ -331,7 +331,7 @@ int bus_match_run(
if (!value_node_test(c, node->type, test_u8, test_str))
continue;
- r = bus_match_run(bus, c, ret, m);
+ r = bus_match_run(bus, c, m);
if (r != 0)
return r;
}
@@ -341,7 +341,7 @@ int bus_match_run(
return 0;
/* And now, let's invoke our siblings */
- return bus_match_run(bus, node->next, ret, m);
+ return bus_match_run(bus, node->next, m);
}
static int bus_match_add_compare_value(
@@ -500,6 +500,7 @@ static int bus_match_add_leaf(
struct bus_match_node *where,
sd_bus_message_handler_t callback,
void *userdata,
+ uint64_t cookie,
struct bus_match_node **ret) {
struct bus_match_node *n;
@@ -519,6 +520,7 @@ static int bus_match_add_leaf(
n->next->prev = n;
n->leaf.callback = callback;
n->leaf.userdata = userdata;
+ n->leaf.cookie = cookie;
where->child = n;
@@ -553,22 +555,22 @@ static int bus_match_find_leaf(
enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n) {
assert(k);
- if (n == 4 && memcmp(k, "type", 4) == 0)
+ if (n == 4 && startswith(k, "type"))
return BUS_MATCH_MESSAGE_TYPE;
- if (n == 6 && memcmp(k, "sender", 6) == 0)
+ if (n == 6 && startswith(k, "sender"))
return BUS_MATCH_SENDER;
- if (n == 11 && memcmp(k, "destination", 11) == 0)
+ if (n == 11 && startswith(k, "destination"))
return BUS_MATCH_DESTINATION;
- if (n == 9 && memcmp(k, "interface", 9) == 0)
+ if (n == 9 && startswith(k, "interface"))
return BUS_MATCH_INTERFACE;
- if (n == 6 && memcmp(k, "member", 6) == 0)
+ if (n == 6 && startswith(k, "member"))
return BUS_MATCH_MEMBER;
- if (n == 4 && memcmp(k, "path", 4) == 0)
+ if (n == 4 && startswith(k, "path"))
return BUS_MATCH_PATH;
- if (n == 14 && memcmp(k, "path_namespace", 14) == 0)
+ if (n == 14 && startswith(k, "path_namespace"))
return BUS_MATCH_PATH_NAMESPACE;
- if (n == 4 && memcmp(k, "arg", 3) == 0) {
+ if (n == 4 && startswith(k, "arg")) {
int j;
j = undecchar(k[3]);
@@ -578,7 +580,7 @@ enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n
return BUS_MATCH_ARG + j;
}
- if (n == 5 && memcmp(k, "arg", 3) == 0) {
+ if (n == 5 && startswith(k, "arg")) {
int a, b;
enum bus_match_node_type t;
@@ -594,7 +596,7 @@ enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n
return t;
}
- if (n == 8 && memcmp(k, "arg", 3) == 0 && memcmp(k + 4, "path", 4) == 0) {
+ if (n == 8 && startswith(k, "arg") && startswith(k + 4, "path")) {
int j;
j = undecchar(k[3]);
@@ -604,7 +606,7 @@ enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n
return BUS_MATCH_ARG_PATH + j;
}
- if (n == 9 && memcmp(k, "arg", 3) == 0 && memcmp(k + 5, "path", 4) == 0) {
+ if (n == 9 && startswith(k, "arg") && startswith(k + 5, "path")) {
enum bus_match_node_type t;
int a, b;
@@ -620,7 +622,7 @@ enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n
return t;
}
- if (n == 13 && memcmp(k, "arg", 3) == 0 && memcmp(k + 4, "namespace", 9) == 0) {
+ if (n == 13 && startswith(k, "arg") && startswith(k + 4, "namespace")) {
int j;
j = undecchar(k[3]);
@@ -630,7 +632,7 @@ enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n
return BUS_MATCH_ARG_NAMESPACE + j;
}
- if (n == 14 && memcmp(k, "arg", 3) == 0 && memcmp(k + 5, "namespace", 9) == 0) {
+ if (n == 14 && startswith(k, "arg") && startswith(k + 5, "namespace")) {
enum bus_match_node_type t;
int a, b;
@@ -649,14 +651,8 @@ enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n
return -EINVAL;
}
-struct match_component {
- enum bus_match_node_type type;
- uint8_t value_u8;
- char *value_str;
-};
-
static int match_component_compare(const void *a, const void *b) {
- const struct match_component *x = a, *y = b;
+ const struct bus_match_component *x = a, *y = b;
if (x->type < y->type)
return -1;
@@ -666,7 +662,7 @@ static int match_component_compare(const void *a, const void *b) {
return 0;
}
-static void free_components(struct match_component *components, unsigned n_components) {
+void bus_match_parse_free(struct bus_match_component *components, unsigned n_components) {
unsigned i;
for (i = 0; i < n_components; i++)
@@ -675,13 +671,13 @@ static void free_components(struct match_component *components, unsigned n_compo
free(components);
}
-static int parse_match(
+int bus_match_parse(
const char *match,
- struct match_component **_components,
+ struct bus_match_component **_components,
unsigned *_n_components) {
const char *p = match;
- struct match_component *components = NULL;
+ struct bus_match_component *components = NULL;
size_t components_allocated = 0;
unsigned n_components = 0, i;
_cleanup_free_ char *value = NULL;
@@ -772,7 +768,7 @@ static int parse_match(
}
/* Order the whole thing, so that we always generate the same tree */
- qsort(components, n_components, sizeof(struct match_component), match_component_compare);
+ qsort(components, n_components, sizeof(struct bus_match_component), match_component_compare);
/* Check for duplicates */
for (i = 0; i+1 < n_components; i++)
@@ -787,29 +783,24 @@ static int parse_match(
return 0;
fail:
- free_components(components, n_components);
+ bus_match_parse_free(components, n_components);
return r;
}
int bus_match_add(
struct bus_match_node *root,
- const char *match,
+ struct bus_match_component *components,
+ unsigned n_components,
sd_bus_message_handler_t callback,
void *userdata,
+ uint64_t cookie,
struct bus_match_node **ret) {
- struct match_component *components = NULL;
- unsigned n_components = 0, i;
+ unsigned i;
struct bus_match_node *n;
int r;
assert(root);
- assert(match);
- assert(callback);
-
- r = parse_match(match, &components, &n_components);
- if (r < 0)
- return r;
n = root;
for (i = 0; i < n_components; i++) {
@@ -817,38 +808,32 @@ int bus_match_add(
n, components[i].type,
components[i].value_u8, components[i].value_str, &n);
if (r < 0)
- goto finish;
+ return r;
}
- r = bus_match_add_leaf(n, callback, userdata, &n);
+ r = bus_match_add_leaf(n, callback, userdata, cookie, &n);
if (r < 0)
- goto finish;
+ return r;
if (ret)
*ret = n;
-finish:
- free_components(components, n_components);
- return r;
+ return 0;
}
int bus_match_remove(
struct bus_match_node *root,
- const char *match,
+ struct bus_match_component *components,
+ unsigned n_components,
sd_bus_message_handler_t callback,
- void *userdata) {
+ void *userdata,
+ uint64_t *cookie) {
- struct match_component *components = NULL;
- unsigned n_components = 0, i;
+ unsigned i;
struct bus_match_node *n, **gc;
int r;
assert(root);
- assert(match);
-
- r = parse_match(match, &components, &n_components);
- if (r < 0)
- return r;
gc = newa(struct bus_match_node*, n_components);
@@ -859,14 +844,17 @@ int bus_match_remove(
components[i].value_u8, components[i].value_str,
&n);
if (r <= 0)
- goto finish;
+ return r;
gc[i] = n;
}
r = bus_match_find_leaf(n, callback, userdata, &n);
if (r <= 0)
- goto finish;
+ return r;
+
+ if (cookie)
+ *cookie = n->leaf.cookie;
/* Free the leaf */
bus_match_node_free(n);
@@ -882,8 +870,6 @@ int bus_match_remove(
break;
}
-finish:
- free_components(components, n_components);
return r;
}
diff --git a/src/libsystemd-bus/bus-match.h b/src/libsystemd-bus/bus-match.h
index 075f1a9e3a..d24aeec43d 100644
--- a/src/libsystemd-bus/bus-match.h
+++ b/src/libsystemd-bus/bus-match.h
@@ -61,6 +61,7 @@ struct bus_match_node {
sd_bus_message_handler_t callback;
void *userdata;
unsigned last_iteration;
+ uint64_t cookie;
} leaf;
struct {
/* If this is set, then the child is NULL */
@@ -69,10 +70,16 @@ struct bus_match_node {
};
};
-int bus_match_run(sd_bus *bus, struct bus_match_node *root, int ret, sd_bus_message *m);
+struct bus_match_component {
+ enum bus_match_node_type type;
+ uint8_t value_u8;
+ char *value_str;
+};
-int bus_match_add(struct bus_match_node *root, const char *match, sd_bus_message_handler_t callback, void *userdata, struct bus_match_node **ret);
-int bus_match_remove(struct bus_match_node *root, const char *match, sd_bus_message_handler_t callback, void *userdata);
+int bus_match_run(sd_bus *bus, struct bus_match_node *root, sd_bus_message *m);
+
+int bus_match_add(struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, sd_bus_message_handler_t callback, void *userdata, uint64_t cookie, struct bus_match_node **ret);
+int bus_match_remove(struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, sd_bus_message_handler_t callback, void *userdata, uint64_t *cookie);
void bus_match_free(struct bus_match_node *node);
@@ -80,3 +87,6 @@ void bus_match_dump(struct bus_match_node *node, unsigned level);
const char* bus_match_node_type_to_string(enum bus_match_node_type t, char buf[], size_t l);
enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n);
+
+int bus_match_parse(const char *match, struct bus_match_component **_components, unsigned *_n_components);
+void bus_match_parse_free(struct bus_match_component *components, unsigned n_components);
diff --git a/src/libsystemd-bus/bus-message.c b/src/libsystemd-bus/bus-message.c
index 835a9f9a44..760a148fad 100644
--- a/src/libsystemd-bus/bus-message.c
+++ b/src/libsystemd-bus/bus-message.c
@@ -21,6 +21,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <sys/mman.h>
#include "util.h"
#include "utf8.h"
@@ -36,7 +37,69 @@
static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
-static void reset_containers(sd_bus_message *m) {
+static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
+
+ if (p == NULL)
+ return NULL;
+
+ if (old_base == new_base)
+ return (void*) p;
+
+ if ((uint8_t*) p < (uint8_t*) old_base)
+ return (void*) p;
+
+ if ((uint8_t*) p >= (uint8_t*) old_base + sz)
+ return (void*) p;
+
+ return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
+}
+
+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)
+ bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped);
+ else {
+ if (part->mapped > 0)
+ assert_se(munmap(part->data, part->mapped) == 0);
+
+ close_nointr_nofail(part->memfd);
+ }
+
+ } else if (part->munmap_this)
+ munmap(part->data, part->mapped);
+ else if (part->free_this)
+ free(part->data);
+
+ if (part != &m->body)
+ free(part);
+}
+
+static void message_reset_parts(sd_bus_message *m) {
+ struct bus_body_part *part;
+
+ assert(m);
+
+ part = &m->body;
+ while (m->n_body_parts > 0) {
+ struct bus_body_part *next = part->next;
+ message_free_part(m, part);
+ part = next;
+ m->n_body_parts--;
+ }
+
+ m->body_end = NULL;
+
+ m->cached_rindex_part = NULL;
+ m->cached_rindex_part_begin = 0;
+}
+
+static void message_reset_containers(sd_bus_message *m) {
unsigned i;
assert(m);
@@ -57,23 +120,32 @@ static void message_free(sd_bus_message *m) {
if (m->free_header)
free(m->header);
- if (m->free_fields)
- free(m->fields);
-
- if (m->free_body)
- free(m->body);
+ message_reset_parts(m);
if (m->free_kdbus)
free(m->kdbus);
+ if (m->release_kdbus) {
+ uint64_t off;
+
+ off = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer;
+ ioctl(m->bus->input_fd, KDBUS_CMD_MSG_RELEASE, &off);
+ }
+
+ if (m->bus)
+ sd_bus_unref(m->bus);
+
if (m->free_fds) {
close_many(m->fds, m->n_fds);
free(m->fds);
}
+ if (m->iovec != m->iovec_fixed)
+ free(m->iovec);
+
free(m->cmdline_array);
- reset_containers(m);
+ message_reset_containers(m);
free(m->root_container.signature);
free(m->peeked_signature);
@@ -84,67 +156,64 @@ static void message_free(sd_bus_message *m) {
free(m);
}
-static void* buffer_extend(void **p, uint32_t *sz, size_t align, size_t extend) {
- size_t start, n;
- void *k;
-
- assert(p);
- assert(sz);
- assert(align > 0);
-
- start = ALIGN_TO((size_t) *sz, align);
- n = start + extend;
+static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz) {
+ void *op, *np;
+ size_t old_size, new_size, start;
- if (n == *sz)
- return (uint8_t*) *p + start;
+ assert(m);
- if (n > (size_t) ((uint32_t) -1))
+ if (m->poisoned)
return NULL;
- k = realloc(*p, n);
- if (!k)
- return NULL;
+ old_size = sizeof(struct bus_header) + m->header->fields_size;
+ start = ALIGN_TO(old_size, align);
+ new_size = start + sz;
- /* Zero out padding */
- if (start > *sz)
- memset((uint8_t*) k + *sz, 0, start - *sz);
+ if (old_size == new_size)
+ return (uint8_t*) m->header + old_size;
- *p = k;
- *sz = n;
+ if (new_size > (size_t) ((uint32_t) -1))
+ goto poison;
- return (uint8_t*) k + start;
-}
+ if (m->free_header) {
+ np = realloc(m->header, ALIGN8(new_size));
+ if (!np)
+ goto poison;
+ } else {
+ /* Initially, the header is allocated as part of of
+ * the sd_bus_message itself, let's replace it by
+ * dynamic data */
-static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz) {
- void *p, *o;
+ np = malloc(ALIGN8(new_size));
+ if (!np)
+ goto poison;
- assert(m);
+ memcpy(np, m->header, sizeof(struct bus_header));
+ }
- o = m->fields;
- p = buffer_extend(&m->fields, &m->header->fields_size, align, sz);
- if (!p)
- return NULL;
+ /* Zero out padding */
+ if (start > old_size)
+ memset((uint8_t*) np + old_size, 0, start - old_size);
- if (o != m->fields) {
- /* Adjust quick access pointers */
+ op = m->header;
+ m->header = np;
+ m->header->fields_size = new_size - sizeof(struct bus_header);
- if (m->path)
- m->path = (const char*) m->fields + (m->path - (const char*) o);
- if (m->interface)
- m->interface = (const char*) m->fields + (m->interface - (const char*) o);
- if (m->member)
- m->member = (const char*) m->fields + (m->member - (const char*) o);
- if (m->destination)
- m->destination = (const char*) m->fields + (m->destination - (const char*) o);
- if (m->sender)
- m->sender = (const char*) m->fields + (m->sender - (const char*) o);
- if (m->error.name)
- m->error.name = (const char*) m->fields + (m->error.name - (const char*) o);
- }
+ /* Adjust quick access pointers */
+ m->path = adjust_pointer(m->path, op, old_size, m->header);
+ m->interface = adjust_pointer(m->interface, op, old_size, m->header);
+ m->member = adjust_pointer(m->member, op, old_size, m->header);
+ m->destination = adjust_pointer(m->destination, op, old_size, m->header);
+ m->sender = adjust_pointer(m->sender, op, old_size, m->header);
+ m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
+
+ m->free_header = true;
- m->free_fields = true;
+ return (uint8_t*) np + start;
- return p;
+poison:
+ m->poisoned = true;
+ return NULL;
}
static int message_append_field_string(
@@ -177,7 +246,7 @@ static int message_append_field_string(
memcpy(p + 8, s, l + 1);
if (ret)
- *ret = (const char*) p + 8;
+ *ret = (char*) p + 8;
return 0;
}
@@ -324,10 +393,14 @@ int bus_message_from_malloc(
goto fail;
}
- m->fields = (uint8_t*) buffer + sizeof(struct bus_header);
- m->body = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
+ m->n_body_parts = 1;
+ m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
+ m->body.size = length - sizeof(struct bus_header) - ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
+ m->body.sealed = true;
+ m->body.memfd = -1;
m->n_iovec = 1;
+ m->iovec = m->iovec_fixed;
m->iovec[0].iov_base = buffer;
m->iovec[0].iov_len = length;
@@ -361,6 +434,9 @@ static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
m->header->version = bus ? bus->message_version : 1;
m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
+ if (bus)
+ m->bus = sd_bus_ref(bus);
+
return m;
}
@@ -492,7 +568,7 @@ static int message_new_reply(
goto fail;
if (call->sender) {
- r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->sender);
+ r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
if (r < 0)
goto fail;
}
@@ -551,6 +627,43 @@ fail:
return r;
}
+int bus_message_new_synthetic_error(
+ sd_bus *bus,
+ uint64_t serial,
+ const sd_bus_error *e,
+ sd_bus_message **m) {
+
+ sd_bus_message *t;
+ int r;
+
+ assert(sd_bus_error_is_set(e));
+ assert(m);
+
+ t = message_new(bus, SD_BUS_MESSAGE_TYPE_METHOD_ERROR);
+ if (!t)
+ return -ENOMEM;
+
+ t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
+ t->reply_serial = serial;
+
+ r = message_append_field_uint32(t, SD_BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
+ if (r < 0)
+ goto fail;
+
+ if (bus && bus->unique_name) {
+ r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
+ if (r < 0)
+ goto fail;
+ }
+
+ *m = t;
+ return 0;
+
+fail:
+ message_free(t);
+ return r;
+}
+
sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
if (!m)
return NULL;
@@ -1016,35 +1129,205 @@ static struct bus_container *message_get_container(sd_bus_message *m) {
return m->containers + m->n_containers - 1;
}
-static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz) {
- void *p, *o;
- size_t added;
+struct bus_body_part *message_append_part(sd_bus_message *m) {
+ struct bus_body_part *part;
+
+ assert(m);
+
+ if (m->poisoned)
+ return NULL;
+
+ if (m->n_body_parts <= 0) {
+ part = &m->body;
+ zero(*part);
+ } else {
+ assert(m->body_end);
+
+ part = new0(struct bus_body_part, 1);
+ if (!part) {
+ m->poisoned = true;
+ return NULL;
+ }
+
+ m->body_end->next = part;
+ }
+
+ part->memfd = -1;
+ m->body_end = part;
+ m->n_body_parts ++;
+
+ return part;
+}
+
+static void part_zero(struct bus_body_part *part, size_t sz) {
+ assert(part);
+ assert(sz > 0);
+ assert(sz < 8);
+
+ /* All other fields can be left in their defaults */
+ assert(!part->data);
+ assert(part->memfd < 0);
+
+ part->size = sz;
+ part->is_zero = true;
+ part->sealed = true;
+}
+
+static int part_make_space(
+ struct sd_bus_message *m,
+ struct bus_body_part *part,
+ size_t sz,
+ void **q) {
+
+ void *n;
+ int r;
+
+ assert(m);
+ assert(part);
+ assert(!part->sealed);
+
+ if (m->poisoned)
+ return -ENOMEM;
+
+ if (!part->data && part->memfd < 0)
+ part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped);
+
+ if (part->memfd >= 0) {
+ uint64_t u = sz;
+
+ r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &u);
+ if (r < 0) {
+ m->poisoned = true;
+ return -errno;
+ }
+
+ if (!part->data || sz > part->mapped) {
+ size_t 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->data, part->mapped, psz, MREMAP_MAYMOVE);
+
+ if (n == MAP_FAILED) {
+ m->poisoned = true;
+ return -errno;
+ }
+
+ part->mapped = psz;
+ part->data = n;
+ }
+
+ part->munmap_this = true;
+ } else {
+ n = realloc(part->data, sz);
+ if (!n) {
+ m->poisoned = true;
+ return -ENOMEM;
+ }
+
+ part->data = n;
+ part->free_this = true;
+ }
+
+ if (q)
+ *q = part->data ? (uint8_t*) part->data + part->size : NULL;
+
+ part->size = sz;
+ return 0;
+}
+
+static void message_extend_containers(sd_bus_message *m, size_t expand) {
struct bus_container *c;
assert(m);
+
+ if (expand <= 0)
+ return;
+
+ /* Update counters */
+ for (c = m->containers; c < m->containers + m->n_containers; c++)
+ if (c->array_size)
+ *c->array_size += expand;
+}
+
+static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz) {
+ struct bus_body_part *part = NULL;
+ size_t start_body, end_body, padding, start_part, end_part, added;
+ bool add_new_part;
+ void *p;
+ int r;
+
+ assert(m);
assert(align > 0);
+ assert(!m->sealed);
+
+ if (m->poisoned)
+ return NULL;
- o = m->body;
- added = m->header->body_size;
+ start_body = ALIGN_TO((size_t) m->header->body_size, align);
+ end_body = start_body + sz;
- p = buffer_extend(&m->body, &m->header->body_size, align, sz);
- if (!p)
+ padding = start_body - m->header->body_size;
+ added = padding + sz;
+
+ /* Check for 32bit overflows */
+ if (end_body > (size_t) ((uint32_t) -1)) {
+ m->poisoned = true;
return NULL;
+ }
- added = m->header->body_size - added;
+ add_new_part =
+ m->n_body_parts <= 0 ||
+ m->body_end->sealed ||
+ padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
- for (c = m->containers; c < m->containers + m->n_containers; c++)
- if (c->array_size) {
- c->array_size = (uint32_t*) ((uint8_t*) m->body + ((uint8_t*) c->array_size - (uint8_t*) o));
- *c->array_size += added;
+ if (add_new_part) {
+ if (padding > 0) {
+ part = message_append_part(m);
+ if (!part)
+ return NULL;
+
+ part_zero(part, padding);
+ }
+
+ part = message_append_part(m);
+ if (!part)
+ return NULL;
+
+ r = part_make_space(m, part, sz, &p);
+ if (r < 0)
+ return NULL;
+ } else {
+ struct bus_container *c;
+ void *op;
+ size_t os;
+
+ part = m->body_end;
+ op = part->data;
+ os = part->size;
+
+ start_part = ALIGN_TO(part->size, align);
+ end_part = start_part + sz;
+
+ r = part_make_space(m, part, end_part, &p);
+ if (r < 0)
+ return NULL;
+
+ if (padding > 0) {
+ memset(p, 0, padding);
+ p = (uint8_t*) p + padding;
}
- if (o != m->body) {
- if (m->error.message)
- m->error.message = (const char*) m->body + (m->error.message - (const char*) o);
+ /* Readjust pointers */
+ for (c = m->containers; c < m->containers + m->n_containers; c++)
+ c->array_size = adjust_pointer(c->array_size, op, os, part->data);
+
+ m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
}
- m->free_body = true;
+ m->header->body_size = end_body;
+ message_extend_containers(m, added);
return p;
}
@@ -1054,7 +1337,6 @@ int message_append_basic(sd_bus_message *m, char type, const void *p, const void
ssize_t align, sz;
uint32_t k;
void *a;
- char *e = NULL;
int fd = -1;
uint32_t fdi = 0;
int r;
@@ -1067,6 +1349,8 @@ int message_append_basic(sd_bus_message *m, char type, const void *p, const void
return -EPERM;
if (!bus_type_is_basic(type))
return -EINVAL;
+ if (m->poisoned)
+ return -ESTALE;
c = message_get_container(m);
@@ -1076,13 +1360,17 @@ int message_append_basic(sd_bus_message *m, char type, const void *p, const void
if (c->signature[c->index] != type)
return -ENXIO;
} else {
+ char *e;
+
/* Maybe we can append to the signature? But only if this is the top-level container*/
if (c->enclosing != 0)
return -ENXIO;
e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
- if (!e)
+ if (!e) {
+ m->poisoned = true;
return -ENOMEM;
+ }
}
switch (type) {
@@ -1133,6 +1421,7 @@ int message_append_basic(sd_bus_message *m, char type, const void *p, const void
f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
if (!f) {
+ m->poisoned = true;
r = -ENOMEM;
goto fail;
}
@@ -1193,10 +1482,6 @@ int message_append_basic(sd_bus_message *m, char type, const void *p, const void
return 0;
fail:
- /* Truncate extended signature again */
- if (e)
- c->signature[c->index] = 0;
-
if (fd >= 0)
close_nointr_nofail(fd);
@@ -1207,6 +1492,55 @@ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
return message_append_basic(m, type, p, NULL);
}
+int sd_bus_message_append_string_space(sd_bus_message *m, size_t size, char **s) {
+ struct bus_container *c;
+ void *a;
+
+ if (!m)
+ return -EINVAL;
+ if (!s)
+ return -EINVAL;
+ if (m->sealed)
+ return -EPERM;
+ if (m->poisoned)
+ return -ESTALE;
+
+ c = message_get_container(m);
+
+ if (c->signature && c->signature[c->index]) {
+ /* Container signature is already set */
+
+ if (c->signature[c->index] != SD_BUS_TYPE_STRING)
+ return -ENXIO;
+ } else {
+ char *e;
+
+ /* Maybe we can append to the signature? But only if this is the top-level container*/
+ if (c->enclosing != 0)
+ return -ENXIO;
+
+ e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
+ if (!e) {
+ m->poisoned = true;
+ return -ENOMEM;
+ }
+ }
+
+ a = message_extend_body(m, 4, 4 + size + 1);
+ if (!a)
+ return -ENOMEM;
+
+ *(uint32_t*) a = size;
+ *s = (char*) a + 4;
+
+ (*s)[size] = 0;
+
+ if (c->enclosing != SD_BUS_TYPE_ARRAY)
+ c->index++;
+
+ return 0;
+}
+
static int bus_message_open_array(
sd_bus_message *m,
struct bus_container *c,
@@ -1214,10 +1548,10 @@ static int bus_message_open_array(
uint32_t **array_size) {
unsigned nindex;
- char *e = NULL;
- void *a, *b;
+ void *a, *op;
int alignment;
- size_t saved;
+ size_t os;
+ struct bus_body_part *o;
assert(m);
assert(c);
@@ -1243,45 +1577,42 @@ static int bus_message_open_array(
nindex = c->index + 1 + strlen(contents);
} else {
+ char *e;
+
if (c->enclosing != 0)
return -ENXIO;
/* Extend the existing signature */
e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
- if (!e)
+ if (!e) {
+ m->poisoned = true;
return -ENOMEM;
+ }
nindex = e - c->signature;
}
- saved = m->header->body_size;
a = message_extend_body(m, 4, 4);
- if (!a) {
- /* Truncate extended signature again */
- if (e)
- c->signature[c->index] = 0;
-
+ if (!a)
return -ENOMEM;
- }
- b = m->body;
- if (!message_extend_body(m, alignment, 0)) {
- /* Add alignment between size and first element */
- if (e)
- c->signature[c->index] = 0;
+ o = m->body_end;
+ op = m->body_end->data;
+ os = m->body_end->size;
- m->header->body_size = saved;
+ /* Add alignment between size and first element */
+ if (!message_extend_body(m, alignment, 0))
return -ENOMEM;
- }
if (c->enclosing != SD_BUS_TYPE_ARRAY)
c->index = nindex;
- /* m->body might have changed so let's readjust a */
- a = (uint8_t*) m->body + ((uint8_t*) a - (uint8_t*) b);
- *(uint32_t*) a = 0;
+ /* location of array size might have changed so let's readjust a */
+ if (o == m->body_end)
+ a = adjust_pointer(a, op, os, m->body_end->data);
+ *(uint32_t*) a = 0;
*array_size = a;
return 0;
}
@@ -1291,7 +1622,6 @@ static int bus_message_open_variant(
struct bus_container *c,
const char *contents) {
- char *e = NULL;
size_t l;
void *a;
@@ -1311,23 +1641,22 @@ static int bus_message_open_variant(
return -ENXIO;
} else {
+ char *e;
+
if (c->enclosing != 0)
return -ENXIO;
e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
- if (!e)
+ if (!e) {
+ m->poisoned = true;
return -ENOMEM;
+ }
}
l = strlen(contents);
a = message_extend_body(m, 1, 1 + l + 1);
- if (!a) {
- /* Truncate extended signature again */
- if (e)
- c->signature[c->index] = 0;
-
+ if (!a)
return -ENOMEM;
- }
*(uint8_t*) a = l;
memcpy((uint8_t*) a + 1, contents, l + 1);
@@ -1344,7 +1673,6 @@ static int bus_message_open_struct(
const char *contents) {
size_t nindex;
- char *e = NULL;
assert(m);
assert(c);
@@ -1365,23 +1693,23 @@ static int bus_message_open_struct(
nindex = c->index + 1 + l + 1;
} else {
+ char *e;
+
if (c->enclosing != 0)
return -ENXIO;
e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
- if (!e)
+ if (!e) {
+ m->poisoned = true;
return -ENOMEM;
+ }
nindex = e - c->signature;
}
/* Align contents to 8 byte boundary */
- if (!message_extend_body(m, 8, 0)) {
- if (e)
- c->signature[c->index] = 0;
-
+ if (!message_extend_body(m, 8, 0))
return -ENOMEM;
- }
if (c->enclosing != SD_BUS_TYPE_ARRAY)
c->index = nindex;
@@ -1438,6 +1766,7 @@ int sd_bus_message_open_container(
struct bus_container *c, *w;
uint32_t *array_size = NULL;
char *signature;
+ size_t before;
int r;
if (!m)
@@ -1446,18 +1775,30 @@ int sd_bus_message_open_container(
return -EPERM;
if (!contents)
return -EINVAL;
+ if (m->poisoned)
+ return -ESTALE;
/* Make sure we have space for one more container */
w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
- if (!w)
+ if (!w) {
+ m->poisoned = true;
return -ENOMEM;
+ }
+
m->containers = w;
c = message_get_container(m);
signature = strdup(contents);
- if (!signature)
+ if (!signature) {
+ m->poisoned = true;
return -ENOMEM;
+ }
+
+ /* Save old index in the parent container, in case we have to
+ * abort this container */
+ c->saved_index = c->index;
+ before = m->header->body_size;
if (type == SD_BUS_TYPE_ARRAY)
r = bus_message_open_array(m, c, contents, &array_size);
@@ -1481,7 +1822,8 @@ int sd_bus_message_open_container(
w->signature = signature;
w->index = 0;
w->array_size = array_size;
- w->begin = 0;
+ w->before = before;
+ w->begin = m->rindex;
return 0;
}
@@ -1495,6 +1837,8 @@ int sd_bus_message_close_container(sd_bus_message *m) {
return -EPERM;
if (m->n_containers <= 0)
return -EINVAL;
+ if (m->poisoned)
+ return -ESTALE;
c = message_get_container(m);
if (c->enclosing != SD_BUS_TYPE_ARRAY)
@@ -1507,7 +1851,6 @@ int sd_bus_message_close_container(sd_bus_message *m) {
return 0;
}
-
typedef struct {
const char *types;
unsigned n_struct;
@@ -1752,6 +2095,8 @@ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
return -EINVAL;
if (m->sealed)
return -EPERM;
+ if (m->poisoned)
+ return -ESTALE;
if (!types)
return 0;
@@ -1762,16 +2107,280 @@ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
return r;
}
+int sd_bus_message_append_array_space(sd_bus_message *m, char type, size_t size, void **ptr) {
+ ssize_t align, sz;
+ void *a;
+ int r;
+
+ if (!m)
+ return -EINVAL;
+ if (m->sealed)
+ return -EPERM;
+ if (!bus_type_is_trivial(type))
+ return -EINVAL;
+ if (!ptr && size > 0)
+ return -EINVAL;
+ if (m->poisoned)
+ return -ESTALE;
+
+ align = bus_type_get_alignment(type);
+ sz = bus_type_get_size(type);
+
+ assert_se(align > 0);
+ assert_se(sz > 0);
+
+ if (size % sz != 0)
+ return -EINVAL;
+
+ r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
+ if (r < 0)
+ return r;
+
+ a = message_extend_body(m, align, size);
+ if (!a)
+ return -ENOMEM;
+
+ r = sd_bus_message_close_container(m);
+ if (r < 0)
+ return r;
+
+ *ptr = a;
+ return 0;
+}
+
+int sd_bus_message_append_array(sd_bus_message *m, char type, const void *ptr, size_t size) {
+ int r;
+ void *p;
+
+ if (!ptr && size > 0)
+ return -EINVAL;
+
+ r = sd_bus_message_append_array_space(m, type, size, &p);
+ if (r < 0)
+ return r;
+
+ if (size > 0)
+ memcpy(p, ptr, size);
+
+ return 0;
+}
+
+int sd_bus_message_append_array_memfd(sd_bus_message *m, char type, sd_memfd *memfd) {
+ _cleanup_close_ int copy_fd = -1;
+ struct bus_body_part *part;
+ ssize_t align, sz;
+ uint64_t size;
+ void *a;
+ int r;
+
+ if (!m)
+ return -EINVAL;
+ if (!memfd)
+ return -EINVAL;
+ if (m->sealed)
+ return -EPERM;
+ if (!bus_type_is_trivial(type))
+ return -EINVAL;
+ if (m->poisoned)
+ return -ESTALE;
+
+ r = sd_memfd_set_sealed(memfd, true);
+ if (r < 0)
+ return r;
+
+ copy_fd = sd_memfd_dup_fd(memfd);
+ if (copy_fd < 0)
+ return copy_fd;
+
+ r = sd_memfd_get_size(memfd, &size);
+ if (r < 0)
+ return r;
+
+ align = bus_type_get_alignment(type);
+ sz = bus_type_get_size(type);
+
+ assert_se(align > 0);
+ assert_se(sz > 0);
+
+ if (size % sz != 0)
+ return -EINVAL;
+
+ if (size > (uint64_t) (uint32_t) -1)
+ return -EINVAL;
+
+ r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
+ if (r < 0)
+ return r;
+
+ a = message_extend_body(m, align, 0);
+ if (!a)
+ return -ENOMEM;
+
+ part = message_append_part(m);
+ if (!part)
+ return -ENOMEM;
+
+ part->memfd = copy_fd;
+ part->sealed = true;
+ part->size = size;
+ copy_fd = -1;
+
+ message_extend_containers(m, size);
+ m->header->body_size += size;
+
+ return sd_bus_message_close_container(m);
+}
+
+int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *memfd) {
+ _cleanup_close_ int copy_fd = -1;
+ struct bus_body_part *part;
+ struct bus_container *c;
+ uint64_t size;
+ void *a;
+ int r;
+
+ if (!m)
+ return -EINVAL;
+ if (!memfd)
+ return -EINVAL;
+ if (m->sealed)
+ return -EPERM;
+ if (m->poisoned)
+ return -ESTALE;
+
+ r = sd_memfd_set_sealed(memfd, true);
+ if (r < 0)
+ return r;
+
+ copy_fd = sd_memfd_dup_fd(memfd);
+ if (copy_fd < 0)
+ return copy_fd;
+
+ r = sd_memfd_get_size(memfd, &size);
+ if (r < 0)
+ return r;
+
+ /* We require this to be NUL terminated */
+ if (size == 0)
+ return -EINVAL;
+
+ if (size > (uint64_t) (uint32_t) -1)
+ return -EINVAL;
+
+ c = message_get_container(m);
+ if (c->signature && c->signature[c->index]) {
+ /* Container signature is already set */
+
+ if (c->signature[c->index] != SD_BUS_TYPE_STRING)
+ return -ENXIO;
+ } else {
+ char *e;
+
+ /* Maybe we can append to the signature? But only if this is the top-level container*/
+ if (c->enclosing != 0)
+ return -ENXIO;
+
+ e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
+ if (!e) {
+ m->poisoned = true;
+ return -ENOMEM;
+ }
+ }
+
+ a = message_extend_body(m, 4, 4);
+ if (!a)
+ return -ENOMEM;
+
+ *(uint32_t*) a = size - 1;
+
+ part = message_append_part(m);
+ if (!part)
+ return -ENOMEM;
+
+ part->memfd = copy_fd;
+ part->sealed = true;
+ part->size = size;
+ copy_fd = -1;
+
+ message_extend_containers(m, size);
+ m->header->body_size += size;
+
+ if (c->enclosing != SD_BUS_TYPE_ARRAY)
+ c->index++;
+
+ return 0;
+}
+
+int bus_body_part_map(struct bus_body_part *part) {
+ void *p;
+ size_t psz;
+
+ assert_se(part);
+
+ if (part->data)
+ return 0;
+
+ if (part->size <= 0)
+ return 0;
+
+ /* For smaller zero parts (as used for padding) we don't need to map anything... */
+ if (part->memfd < 0 && part->is_zero && part->size < 8) {
+ static const uint8_t zeroes[7] = { };
+ part->data = (void*) zeroes;
+ return 0;
+ }
+
+ psz = PAGE_ALIGN(part->size);
+
+ if (part->memfd >= 0)
+ p = mmap(NULL, psz, PROT_READ, MAP_SHARED, part->memfd, 0);
+ else if (part->is_zero)
+ p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ else
+ return -EINVAL;
+
+ if (p == MAP_FAILED)
+ return -errno;
+
+ part->mapped = psz;
+ part->data = p;
+ part->munmap_this = true;
+
+ return 0;
+}
+
+void bus_body_part_unmap(struct bus_body_part *part) {
+
+ assert_se(part);
+
+ if (part->memfd < 0)
+ return;
+
+ if (!part->data)
+ return;
+
+ if (!part->munmap_this)
+ return;
+
+ assert_se(munmap(part->data, part->mapped) == 0);
+
+ part->data = NULL;
+ part->mapped = 0;
+ part->munmap_this = false;
+
+ return;
+}
+
static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
- size_t k, start, n;
+ size_t k, start, end;
assert(rindex);
assert(align > 0);
start = ALIGN_TO((size_t) *rindex, align);
- n = start + nbytes;
+ end = start + nbytes;
- if (n > sz)
+ if (end > sz)
return -EBADMSG;
/* Verify that padding is 0 */
@@ -1782,7 +2391,7 @@ static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align,
if (r)
*r = (uint8_t*) p + start;
- *rindex = n;
+ *rindex = end;
return 1;
}
@@ -1799,7 +2408,58 @@ static bool message_end_of_array(sd_bus_message *m, size_t index) {
return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
}
-static int message_peek_body(sd_bus_message *m, size_t *rindex, size_t align, size_t nbytes, void **ret) {
+static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
+ struct bus_body_part *part;
+ size_t begin;
+ int r;
+
+ assert(m);
+
+ if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
+ part = m->cached_rindex_part;
+ begin = m->cached_rindex_part_begin;
+ } else {
+ part = &m->body;
+ begin = 0;
+ }
+
+ while (part) {
+ if (index < begin)
+ return NULL;
+
+ if (index + sz <= begin + part->size) {
+
+ r = bus_body_part_map(part);
+ if (r < 0)
+ return NULL;
+
+ if (p)
+ *p = (uint8_t*) part->data + index - begin;
+
+ m->cached_rindex_part = part;
+ m->cached_rindex_part_begin = begin;
+
+ return part;
+ }
+
+ begin += part->size;
+ part = part->next;
+ }
+
+ return NULL;
+}
+
+static int message_peek_body(
+ sd_bus_message *m,
+ size_t *rindex,
+ size_t align,
+ size_t nbytes,
+ void **ret) {
+
+ size_t k, start, end, padding;
+ struct bus_body_part *part;
+ uint8_t *q;
+
assert(m);
assert(rindex);
assert(align > 0);
@@ -1807,7 +2467,34 @@ static int message_peek_body(sd_bus_message *m, size_t *rindex, size_t align, si
if (message_end_of_array(m, *rindex))
return 0;
- return buffer_peek(m->body, BUS_MESSAGE_BODY_SIZE(m), rindex, align, nbytes, ret);
+ start = ALIGN_TO((size_t) *rindex, align);
+ padding = start - *rindex;
+ end = start + nbytes;
+
+ if (end > BUS_MESSAGE_BODY_SIZE(m))
+ return -EBADMSG;
+
+ part = find_part(m, *rindex, padding, (void**) &q);
+ if (!part)
+ return -EBADMSG;
+
+ if (q) {
+ /* Verify padding */
+ for (k = 0; k < padding; k++)
+ if (q[k] != 0)
+ return -EBADMSG;
+ }
+
+ part = find_part(m, start, nbytes, (void**) &q);
+ if (!part || !q)
+ return -EBADMSG;
+
+ *rindex = end;
+
+ if (ret)
+ *ret = q;
+
+ return 1;
}
static bool validate_nul(const char *s, size_t l) {
@@ -1990,7 +2677,7 @@ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
assert_not_reached("Unknown basic type...");
}
- m->rindex = rindex;
+ m->rindex = rindex;
break;
}
@@ -2186,6 +2873,7 @@ int sd_bus_message_enter_container(sd_bus_message *m, char type, const char *con
struct bus_container *c, *w;
uint32_t *array_size = NULL;
char *signature;
+ size_t before;
int r;
if (!m)
@@ -2228,6 +2916,9 @@ int sd_bus_message_enter_container(sd_bus_message *m, char type, const char *con
if (!signature)
return -ENOMEM;
+ c->saved_index = c->index;
+ before = m->rindex;
+
if (type == SD_BUS_TYPE_ARRAY)
r = bus_message_enter_array(m, c, contents, &array_size);
else if (type == SD_BUS_TYPE_VARIANT)
@@ -2250,6 +2941,7 @@ int sd_bus_message_enter_container(sd_bus_message *m, char type, const char *con
w->signature = signature;
w->index = 0;
w->array_size = array_size;
+ w->before = before;
w->begin = m->rindex;
return 1;
@@ -2284,6 +2976,28 @@ int sd_bus_message_exit_container(sd_bus_message *m) {
return 1;
}
+static void message_quit_container(sd_bus_message *m) {
+ struct bus_container *c;
+
+ assert(m);
+ assert(m->sealed);
+ assert(m->n_containers > 0);
+
+ c = message_get_container(m);
+
+ /* Undo seeks */
+ assert(m->rindex >= c->before);
+ m->rindex = c->before;
+
+ /* Free container */
+ free(c->signature);
+ m->n_containers--;
+
+ /* Correct index of new top-level container */
+ c = message_get_container(m);
+ c->index = c->saved_index;
+}
+
int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
struct bus_container *c;
int r;
@@ -2415,7 +3129,7 @@ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
return -EPERM;
if (complete) {
- reset_containers(m);
+ message_reset_containers(m);
m->rindex = 0;
m->root_container.index = 0;
@@ -2627,6 +3341,59 @@ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
return r;
}
+int sd_bus_message_read_array(sd_bus_message *m, char type, const void **ptr, size_t *size) {
+ struct bus_container *c;
+ void *p;
+ size_t sz;
+ ssize_t align;
+ int r;
+
+ if (!m)
+ return -EINVAL;
+ if (!m->sealed)
+ return -EPERM;
+ if (!bus_type_is_trivial(type))
+ return -EINVAL;
+ if (!ptr)
+ return -EINVAL;
+ if (!size)
+ return -EINVAL;
+ if (BUS_MESSAGE_NEED_BSWAP(m))
+ return -ENOTSUP;
+
+ align = bus_type_get_alignment(type);
+ if (align < 0)
+ return align;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
+ if (r <= 0)
+ return r;
+
+ c = message_get_container(m);
+ sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
+
+ r = message_peek_body(m, &m->rindex, align, sz, &p);
+ if (r < 0)
+ goto fail;
+ if (r == 0) {
+ r = -EBADMSG;
+ goto fail;
+ }
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ goto fail;
+
+ *ptr = (const void*) p;
+ *size = sz;
+
+ return 1;
+
+fail:
+ message_quit_container(m);
+ return r;
+}
+
static int message_peek_fields(
sd_bus_message *m,
size_t *rindex,
@@ -2638,7 +3405,7 @@ static int message_peek_fields(
assert(rindex);
assert(align > 0);
- return buffer_peek(m->fields, BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
+ return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
}
static int message_peek_field_uint32(
@@ -3061,8 +3828,10 @@ int bus_message_parse_fields(sd_bus_message *m) {
}
int bus_message_seal(sd_bus_message *m, uint64_t serial) {
- int r;
+ struct bus_body_part *part;
size_t l, a;
+ unsigned i;
+ int r;
assert(m);
@@ -3072,6 +3841,9 @@ int bus_message_seal(sd_bus_message *m, uint64_t serial) {
if (m->n_containers > 0)
return -EBADMSG;
+ if (m->poisoned)
+ return -ESTALE;
+
/* If there's a non-trivial signature set, then add it in here */
if (!isempty(m->root_container.signature)) {
r = message_append_field_signature(m, SD_BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
@@ -3085,20 +3857,26 @@ int bus_message_seal(sd_bus_message *m, uint64_t serial) {
return r;
}
+ /* Add padding at the end of the fields part, since we know
+ * the body needs to start at an 8 byte alignment. We made
+ * sure we allocated enough space for this, so all we need to
+ * do here is to zero it out. */
l = BUS_MESSAGE_FIELDS_SIZE(m);
a = ALIGN8(l) - l;
-
- if (a > 0) {
- /* Add padding at the end, since we know the body
- * needs to start at an 8 byte alignment. */
- void *p;
-
- p = message_extend_fields(m, 1, a);
- if (!p)
- return -ENOMEM;
-
- memset(p, 0, a);
- m->header->fields_size -= a;
+ if (a > 0)
+ memset((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, 0, a);
+
+ /* If this is something we can send as memfd, then let's seal
+ the memfd now. Note that we can send memfds as payload only
+ for directed messages, and not for broadcasts. */
+ if (m->destination && m->bus && m->bus->use_memfd) {
+ MESSAGE_FOREACH_PART(part, i, m)
+ if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
+ bus_body_part_unmap(part);
+
+ if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0)
+ part->sealed = true;
+ }
}
m->header->serial = serial;
@@ -3148,7 +3926,8 @@ int bus_message_dump(sd_bus_message *m) {
"\treply_serial=%u\n"
"\terror.name=%s\n"
"\terror.message=%s\n"
- "\tsealed=%s\n",
+ "\tsealed=%s\n"
+ "\tn_body_parts=%u\n",
m,
m->n_ref,
m->header->endian,
@@ -3167,7 +3946,8 @@ int bus_message_dump(sd_bus_message *m) {
m->reply_serial,
strna(m->error.name),
strna(m->error.message),
- yes_no(m->sealed));
+ yes_no(m->sealed),
+ m->n_body_parts);
if (m->pid != 0)
printf("\tpid=%lu\n", (unsigned long) m->pid);
@@ -3381,6 +4161,8 @@ int bus_message_dump(sd_bus_message *m) {
int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
size_t total;
void *p, *e;
+ unsigned i;
+ struct bus_body_part *part;
assert(m);
assert(buffer);
@@ -3392,17 +4174,9 @@ int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
if (!p)
return -ENOMEM;
- e = mempcpy(p, m->header, sizeof(*m->header));
-
- if (m->fields) {
- e = mempcpy(e, m->fields, m->header->fields_size);
-
- if (m->header->fields_size % 8 != 0)
- e = mempset(e, 0, 8 - (m->header->fields_size % 8));
- }
-
- if (m->body)
- e = mempcpy(e, m->body, m->header->body_size);
+ e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
+ MESSAGE_FOREACH_PART(part, i, m)
+ e = mempcpy(e, part->data, part->size);
assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
@@ -3474,7 +4248,22 @@ const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
return t;
}
-int bus_header_size(struct bus_header *h, size_t *sum) {
+bool bus_header_is_complete(struct bus_header *h, size_t size) {
+ size_t full;
+
+ assert(h);
+ assert(size);
+
+ if (size < sizeof(struct bus_header))
+ return false;
+
+ full = sizeof(struct bus_header) +
+ (h->endian == SD_BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
+
+ return size >= full;
+}
+
+int bus_header_message_size(struct bus_header *h, size_t *sum) {
size_t fs, bs;
assert(h);
@@ -3492,3 +4281,12 @@ int bus_header_size(struct bus_header *h, size_t *sum) {
*sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
return 0;
}
+
+int bus_message_to_errno(sd_bus_message *m) {
+ assert(m);
+
+ if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
+ return 0;
+
+ return bus_error_to_errno(&m->error);
+}
diff --git a/src/libsystemd-bus/bus-message.h b/src/libsystemd-bus/bus-message.h
index 9c0829c7fa..2fb11ea3b1 100644
--- a/src/libsystemd-bus/bus-message.h
+++ b/src/libsystemd-bus/bus-message.h
@@ -33,11 +33,12 @@
struct bus_container {
char enclosing;
+ unsigned index, saved_index;
+
char *signature;
- unsigned index;
uint32_t *array_size;
- size_t begin;
+ size_t before, begin;
};
struct bus_header {
@@ -50,9 +51,23 @@ struct bus_header {
uint32_t fields_size;
} _packed_;
+struct bus_body_part {
+ struct bus_body_part *next;
+ void *data;
+ size_t size;
+ size_t mapped;
+ int memfd;
+ bool free_this:1;
+ bool munmap_this:1;
+ bool sealed:1;
+ bool is_zero:1;
+};
+
struct sd_bus_message {
unsigned n_ref;
+ sd_bus *bus;
+
uint32_t reply_serial;
const char *path;
@@ -77,19 +92,21 @@ struct sd_bus_message {
bool uid_valid:1;
bool gid_valid:1;
bool free_header:1;
- bool free_fields:1;
- bool free_body:1;
bool free_kdbus:1;
bool free_fds:1;
+ bool release_kdbus:1;
+ bool poisoned:1;
struct bus_header *header;
- void *fields;
- void *body;
- struct kdbus_msg *kdbus;
+ struct bus_body_part body;
+ struct bus_body_part *body_end;
+ unsigned n_body_parts;
char *label;
size_t rindex;
+ struct bus_body_part *cached_rindex_part;
+ size_t cached_rindex_part_begin;
uint32_t n_fds;
int *fds;
@@ -97,9 +114,12 @@ struct sd_bus_message {
struct bus_container root_container, *containers;
unsigned n_containers;
- struct iovec iovec[3];
+ struct iovec *iovec;
+ struct iovec iovec_fixed[2];
unsigned n_iovec;
+ struct kdbus_msg *kdbus;
+
char *peeked_signature;
usec_t timeout;
@@ -159,6 +179,16 @@ static inline uint32_t BUS_MESSAGE_SIZE(sd_bus_message *m) {
BUS_MESSAGE_BODY_SIZE(m);
}
+static inline uint32_t BUS_MESSAGE_BODY_BEGIN(sd_bus_message *m) {
+ return
+ sizeof(struct bus_header) +
+ ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
+}
+
+static inline void* BUS_MESSAGE_FIELDS(sd_bus_message *m) {
+ return (uint8_t*) m->header + sizeof(struct bus_header);
+}
+
static inline void bus_message_unrefp(sd_bus_message **m) {
sd_bus_message_unref(*m);
}
@@ -195,4 +225,17 @@ int bus_message_append_ap(sd_bus_message *m, const char *types, va_list ap);
int bus_message_parse_fields(sd_bus_message *m);
-int bus_header_size(struct bus_header *h, size_t *sum);
+bool bus_header_is_complete(struct bus_header *h, size_t size);
+int bus_header_message_size(struct bus_header *h, size_t *sum);
+
+struct bus_body_part *message_append_part(sd_bus_message *m);
+
+#define MESSAGE_FOREACH_PART(part, i, m) \
+ for ((i) = 0, (part) = &(m)->body; (i) < (m)->n_body_parts; (i)++, (part) = (part)->next)
+
+int bus_body_part_map(struct bus_body_part *part);
+void bus_body_part_unmap(struct bus_body_part *part);
+
+int bus_message_to_errno(sd_bus_message *m);
+
+int bus_message_new_synthetic_error(sd_bus *bus, uint64_t serial, const sd_bus_error *e, sd_bus_message **m);
diff --git a/src/libsystemd-bus/bus-socket.c b/src/libsystemd-bus/bus-socket.c
index 8a86b02c68..b60facb20f 100644
--- a/src/libsystemd-bus/bus-socket.c
+++ b/src/libsystemd-bus/bus-socket.c
@@ -58,7 +58,7 @@ static void iovec_advance(struct iovec iov[], unsigned *idx, size_t size) {
}
}
-static void append_iovec(sd_bus_message *m, const void *p, size_t sz) {
+static int append_iovec(sd_bus_message *m, const void *p, size_t sz) {
assert(m);
assert(p);
assert(sz > 0);
@@ -66,22 +66,55 @@ static void append_iovec(sd_bus_message *m, const void *p, size_t sz) {
m->iovec[m->n_iovec].iov_base = (void*) p;
m->iovec[m->n_iovec].iov_len = sz;
m->n_iovec++;
+
+ return 0;
}
-static void bus_message_setup_iovec(sd_bus_message *m) {
+static int bus_message_setup_iovec(sd_bus_message *m) {
+ struct bus_body_part *part;
+ unsigned n, i;
+ int r;
+
assert(m);
assert(m->sealed);
if (m->n_iovec > 0)
- return;
+ return 0;
+
+ assert(!m->iovec);
+
+ n = 1 + m->n_body_parts;
+ if (n < ELEMENTSOF(m->iovec_fixed))
+ m->iovec = m->iovec_fixed;
+ else {
+ m->iovec = new(struct iovec, n);
+ if (!m->iovec) {
+ r = -ENOMEM;
+ goto fail;
+ }
+ }
+
+ r = append_iovec(m, m->header, BUS_MESSAGE_BODY_BEGIN(m));
+ if (r < 0)
+ goto fail;
+
+ MESSAGE_FOREACH_PART(part, i, m) {
+ r = bus_body_part_map(part);
+ if (r < 0)
+ goto fail;
- append_iovec(m, m->header, sizeof(*m->header));
+ r = append_iovec(m, part->data, part->size);
+ if (r < 0)
+ goto fail;
+ }
- if (m->fields)
- append_iovec(m, m->fields, ALIGN8(m->header->fields_size));
+ assert(n == m->n_iovec);
- if (m->body)
- append_iovec(m, m->body, m->header->body_size);
+ return 0;
+
+fail:
+ m->poisoned = true;
+ return r;
}
bool bus_socket_auth_needs_write(sd_bus *b) {
@@ -148,7 +181,7 @@ static int bus_socket_auth_verify_client(sd_bus *b) {
if (!e)
return 0;
- if (b->negotiate_fds) {
+ if (b->hello_flags & KDBUS_HELLO_ACCEPT_FD) {
f = memmem(e + 2, b->rbuffer_size - (e - (char*) b->rbuffer) - 2, "\r\n", 2);
if (!f)
return 0;
@@ -431,7 +464,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->negotiate_fds)
+ if (b->auth == _BUS_AUTH_INVALID || !(b->hello_flags & KDBUS_HELLO_ACCEPT_FD))
r = bus_socket_auth_write(b, "ERROR\r\n");
else {
b->can_fds = true;
@@ -577,6 +610,8 @@ static int bus_socket_setup(sd_bus *b) {
* socket, just in case. */
enable = !b->bus_client;
setsockopt(b->input_fd, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable));
+
+ enable = !b->bus_client && (b->hello_flags & KDBUS_HELLO_ATTACH_SECLABEL);
setsockopt(b->input_fd, SOL_SOCKET, SO_PASSSEC, &enable, sizeof(enable));
/* Increase the buffers to a MB */
@@ -618,7 +653,7 @@ static int bus_socket_start_auth_client(sd_bus *b) {
if (!b->auth_buffer)
return -ENOMEM;
- if (b->negotiate_fds)
+ if (b->hello_flags & KDBUS_HELLO_ACCEPT_FD)
auth_suffix = "\r\nNEGOTIATE_UNIX_FD\r\nBEGIN\r\n";
else
auth_suffix = "\r\nBEGIN\r\n";
@@ -640,11 +675,11 @@ static int bus_socket_start_auth(sd_bus *b) {
b->auth_timeout = now(CLOCK_MONOTONIC) + BUS_DEFAULT_TIMEOUT;
if (sd_is_socket(b->input_fd, AF_UNIX, 0, 0) <= 0)
- b->negotiate_fds = false;
+ b->hello_flags &= ~KDBUS_HELLO_ACCEPT_FD;
if (b->output_fd != b->input_fd)
if (sd_is_socket(b->output_fd, AF_UNIX, 0, 0) <= 0)
- b->negotiate_fds = false;
+ b->hello_flags &= ~KDBUS_HELLO_ACCEPT_FD;
if (b->is_server)
return bus_socket_read_auth(b);
@@ -749,6 +784,7 @@ int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
ssize_t k;
size_t n;
unsigned j;
+ int r;
assert(bus);
assert(m);
@@ -758,7 +794,9 @@ int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
if (*idx >= BUS_MESSAGE_SIZE(m))
return 0;
- bus_message_setup_iovec(m);
+ r = bus_message_setup_iovec(m);
+ if (r < 0)
+ return r;
n = m->n_iovec * sizeof(struct iovec);
iov = alloca(n);
diff --git a/src/libsystemd-bus/bus-type.c b/src/libsystemd-bus/bus-type.c
index 0557328085..6354c84f2c 100644
--- a/src/libsystemd-bus/bus-type.c
+++ b/src/libsystemd-bus/bus-type.c
@@ -92,6 +92,23 @@ bool bus_type_is_basic(char c) {
return !!memchr(valid, c, sizeof(valid));
}
+bool bus_type_is_trivial(char c) {
+ static const char valid[] = {
+ SD_BUS_TYPE_BYTE,
+ SD_BUS_TYPE_BOOLEAN,
+ SD_BUS_TYPE_INT16,
+ SD_BUS_TYPE_UINT16,
+ SD_BUS_TYPE_INT32,
+ SD_BUS_TYPE_UINT32,
+ SD_BUS_TYPE_INT64,
+ SD_BUS_TYPE_UINT64,
+ SD_BUS_TYPE_DOUBLE
+ };
+
+ return !!memchr(valid, c, sizeof(valid));
+}
+
+
bool bus_type_is_container(char c) {
static const char valid[] = {
SD_BUS_TYPE_ARRAY,
diff --git a/src/libsystemd-bus/bus-type.h b/src/libsystemd-bus/bus-type.h
index e261136084..122628c66b 100644
--- a/src/libsystemd-bus/bus-type.h
+++ b/src/libsystemd-bus/bus-type.h
@@ -29,6 +29,7 @@
bool bus_type_is_valid(char c);
bool bus_type_is_valid_in_signature(char c);
bool bus_type_is_basic(char c);
+bool bus_type_is_trivial(char c);
bool bus_type_is_container(char c);
int bus_type_get_alignment(char c);
int bus_type_get_size(char c);
diff --git a/src/libsystemd-bus/kdbus.h b/src/libsystemd-bus/kdbus.h
index db5e243c17..06c2c245f3 100644
--- a/src/libsystemd-bus/kdbus.h
+++ b/src/libsystemd-bus/kdbus.h
@@ -21,6 +21,18 @@
#endif
#define KDBUS_IOC_MAGIC 0x95
+#define KDBUS_SRC_ID_KERNEL (0)
+#define KDBUS_DST_ID_WELL_KNOWN_NAME (0)
+#define KDBUS_MATCH_SRC_ID_ANY (~0ULL)
+#define KDBUS_DST_ID_BROADCAST (~0ULL)
+
+/* Common first elements in a structure which are used to iterate over
+ * a list of elements. */
+#define KDBUS_PART_HEADER \
+ struct { \
+ __u64 size; \
+ __u64 type; \
+ }
/* Message sent from kernel to userspace, when the owner or starter of
* a well-known name changes */
@@ -60,24 +72,35 @@ struct kdbus_timestamp {
__u64 realtime_ns;
};
-#define KDBUS_SRC_ID_KERNEL (0)
-#define KDBUS_DST_ID_WELL_KNOWN_NAME (0)
-#define KDBUS_MATCH_SRC_ID_ANY (~0ULL)
-#define KDBUS_DST_ID_BROADCAST (~0ULL)
+struct kdbus_vec {
+ __u64 size;
+ union {
+ __u64 address;
+ __u64 offset;
+ };
+};
+
+struct kdbus_memfd {
+ __u64 size;
+ int fd;
+ __u32 __pad;
+};
/* Message Item Types */
enum {
- KDBUS_MSG_NULL,
+ _KDBUS_MSG_NULL,
/* Filled in by userspace */
- KDBUS_MSG_PAYLOAD, /* .data, inline memory */
KDBUS_MSG_PAYLOAD_VEC, /* .data_vec, reference to memory area */
- KDBUS_MSG_UNIX_FDS, /* .data_fds of file descriptors */
+ KDBUS_MSG_PAYLOAD_OFF, /* .data_vec, reference to memory area */
+ KDBUS_MSG_PAYLOAD_MEMFD, /* file descriptor of a special data file */
+ KDBUS_MSG_FDS, /* .data_fds of file descriptors */
KDBUS_MSG_BLOOM, /* for broadcasts, carries bloom filter blob in .data */
KDBUS_MSG_DST_NAME, /* destination's well-known name, in .str */
+ KDBUS_MSG_PRIORITY, /* queue priority for message */
/* Filled in by kernelspace */
- KDBUS_MSG_SRC_NAMES = 0x200,/* NUL separated string list with well-known names of source */
+ KDBUS_MSG_SRC_NAMES = 0x400,/* NUL separated string list with well-known names of source */
KDBUS_MSG_TIMESTAMP, /* .timestamp */
KDBUS_MSG_SRC_CREDS, /* .creds */
KDBUS_MSG_SRC_PID_COMM, /* optional, in .str */
@@ -90,7 +113,7 @@ enum {
KDBUS_MSG_SRC_AUDIT, /* .audit */
/* Special messages from kernel, consisting of one and only one of these data blocks */
- KDBUS_MSG_NAME_ADD = 0x400,/* .name_change */
+ KDBUS_MSG_NAME_ADD = 0x800,/* .name_change */
KDBUS_MSG_NAME_REMOVE, /* .name_change */
KDBUS_MSG_NAME_CHANGE, /* .name_change */
KDBUS_MSG_ID_ADD, /* .id_change */
@@ -99,16 +122,6 @@ enum {
KDBUS_MSG_REPLY_DEAD, /* dito */
};
-enum {
- KDBUS_VEC_ALIGNED = 1 << 0,
-};
-
-struct kdbus_vec {
- __u64 address;
- __u64 size;
- __u64 flags;
-};
-
/**
* struct kdbus_item - chain of data blocks
*
@@ -116,8 +129,7 @@ struct kdbus_vec {
* type: kdbus_item type of data
*/
struct kdbus_item {
- __u64 size;
- __u64 type;
+ KDBUS_PART_HEADER;
union {
/* inline data */
__u8 data[0];
@@ -137,6 +149,7 @@ struct kdbus_item {
struct kdbus_timestamp timestamp;
/* specific fields */
+ struct kdbus_memfd memfd;
int fds[0];
struct kdbus_manager_msg_name_change name_change;
struct kdbus_manager_msg_id_change id_change;
@@ -149,7 +162,7 @@ enum {
};
enum {
- KDBUS_PAYLOAD_NULL,
+ KDBUS_PAYLOAD_KERNEL,
KDBUS_PAYLOAD_DBUS1 = 0x4442757356657231ULL, /* 'DBusVer1' */
KDBUS_PAYLOAD_GVARIANT = 0x4756617269616e74ULL, /* 'GVariant' */
};
@@ -180,13 +193,13 @@ struct kdbus_msg {
};
enum {
- KDBUS_POLICY_NULL,
+ _KDBUS_POLICY_NULL,
KDBUS_POLICY_NAME,
KDBUS_POLICY_ACCESS,
};
enum {
- KDBUS_POLICY_ACCESS_NULL,
+ _KDBUS_POLICY_ACCESS_NULL,
KDBUS_POLICY_ACCESS_USER,
KDBUS_POLICY_ACCESS_GROUP,
KDBUS_POLICY_ACCESS_WORLD,
@@ -198,23 +211,25 @@ enum {
KDBUS_POLICY_OWN = 1 << 0,
};
+struct kdbus_policy_access {
+ __u64 type; /* USER, GROUP, WORLD */
+ __u64 bits; /* RECV, SEND, OWN */
+ __u64 id; /* uid, gid, 0 */
+};
+
+//FIXME: convert access to access[]
struct kdbus_policy {
- __u64 size;
- __u64 type; /* NAME or ACCESS */
+ KDBUS_PART_HEADER;
union {
char name[0];
- struct {
- __u32 type; /* USER, GROUP, WORLD */
- __u32 bits; /* RECV, SEND, OWN */
- __u64 id; /* uid, gid, 0 */
- } access;
+ struct kdbus_policy_access access;
};
};
+/* A series of KDBUS_POLICY_NAME, plus one or more KDBUS_POLICY_ACCESS */
struct kdbus_cmd_policy {
__u64 size;
- __u8 buffer[0]; /* a series of KDBUS_POLICY_NAME plus one or
- * more KDBUS_POLICY_ACCESS each. */
+ struct kdbus_policy policies[0];
};
/* Flags for struct kdbus_cmd_hello */
@@ -233,11 +248,6 @@ enum {
KDBUS_HELLO_ATTACH_AUDIT = 1 << 16,
};
-/* Items to append to struct kdbus_cmd_hello */
-enum {
- KDBUS_HELLO_NULL,
-};
-
struct kdbus_cmd_hello {
__u64 size;
@@ -258,6 +268,7 @@ struct kdbus_cmd_hello {
__u64 id; /* id assigned to this connection */
__u64 bloom_size; /* The bloom filter size chosen by the
* bus owner */
+ __u64 pool_size; /* maximum size of pool buffer */
struct kdbus_item items[0];
};
@@ -270,13 +281,11 @@ enum {
/* Items to append to kdbus_cmd_{bus,ep,ns}_make */
enum {
- KDBUS_MAKE_NULL,
+ _KDBUS_MAKE_NULL,
KDBUS_MAKE_NAME,
- KDBUS_MAKE_CGROUP, /* the cgroup hierarchy ID for which to attach
- * cgroup membership paths * to messages. */
KDBUS_MAKE_CRED, /* allow translator services which connect
* to the bus on behalf of somebody else,
- * allow specifying the credentials of the
+ * allow specifiying the credentials of the
* client to connect on behalf on. Needs
* privileges */
};
@@ -293,7 +302,6 @@ struct kdbus_cmd_bus_make {
* KDBUS_CMD_HELLO, later */
__u64 bloom_size; /* size of the bloom filter for this bus */
struct kdbus_item items[0];
-
};
struct kdbus_cmd_ep_make {
@@ -328,10 +336,11 @@ enum {
KDBUS_NAME_IN_QUEUE = 1 << 16,
};
+/* We allow (de)regestration of names of other peers */
struct kdbus_cmd_name {
__u64 size;
- __u64 name_flags;
- __u64 id; /* We allow registration/deregestration of names of other peers */
+ __u64 flags;
+ __u64 id;
__u64 conn_flags;
char name[0];
};
@@ -342,7 +351,7 @@ struct kdbus_cmd_names {
};
enum {
- KDBUS_NAME_INFO_ITEM_NULL,
+ _KDBUS_NAME_INFO_ITEM_NULL,
KDBUS_NAME_INFO_ITEM_NAME, /* userspace → kernel */
KDBUS_NAME_INFO_ITEM_SECLABEL, /* kernel → userspace */
KDBUS_NAME_INFO_ITEM_AUDIT, /* kernel → userspace */
@@ -357,7 +366,7 @@ struct kdbus_cmd_name_info {
};
enum {
- KDBUS_MATCH_NULL,
+ _KDBUS_MATCH_NULL,
KDBUS_MATCH_BLOOM, /* Matches a mask blob against KDBUS_MSG_BLOOM */
KDBUS_MATCH_SRC_NAME, /* Matches a name string against KDBUS_MSG_SRC_NAMES */
KDBUS_MATCH_NAME_ADD, /* Matches a name string against KDBUS_MSG_NAME_ADD */
@@ -377,7 +386,8 @@ struct kdbus_cmd_match {
struct kdbus_cmd_monitor {
__u64 id; /* We allow setting the monitor flag of other peers */
- unsigned int enabled; /* A boolean to enable/disable monitoring */
+ unsigned int enable; /* A boolean to enable/disable monitoring */
+ __u32 __pad;
};
/* FD states:
@@ -390,29 +400,37 @@ struct kdbus_cmd_monitor {
* starter (via KDBUS_CMD_HELLO with KDBUS_CMD_HELLO_STARTER)
* ep owner (via KDBUS_CMD_EP_MAKE)
*/
-enum kdbus_cmd {
+enum {
/* kdbus control node commands: require unset state */
- KDBUS_CMD_BUS_MAKE = _IOWR(KDBUS_IOC_MAGIC, 0x00, struct kdbus_cmd_bus_make),
- KDBUS_CMD_NS_MAKE = _IOWR(KDBUS_IOC_MAGIC, 0x10, struct kdbus_cmd_ns_make),
+ KDBUS_CMD_BUS_MAKE = _IOW(KDBUS_IOC_MAGIC, 0x00, struct kdbus_cmd_bus_make),
+ KDBUS_CMD_NS_MAKE = _IOR(KDBUS_IOC_MAGIC, 0x10, struct kdbus_cmd_ns_make),
/* kdbus ep node commands: require unset state */
- KDBUS_CMD_EP_MAKE = _IOWR(KDBUS_IOC_MAGIC, 0x20, struct kdbus_cmd_ep_make),
+ KDBUS_CMD_EP_MAKE = _IOW(KDBUS_IOC_MAGIC, 0x20, struct kdbus_cmd_ep_make),
KDBUS_CMD_HELLO = _IOWR(KDBUS_IOC_MAGIC, 0x30, struct kdbus_cmd_hello),
/* kdbus ep node commands: require connected state */
- KDBUS_CMD_MSG_SEND = _IOWR(KDBUS_IOC_MAGIC, 0x40, struct kdbus_msg),
- KDBUS_CMD_MSG_RECV = _IOWR(KDBUS_IOC_MAGIC, 0x41, struct kdbus_msg),
+ KDBUS_CMD_MSG_SEND = _IOW(KDBUS_IOC_MAGIC, 0x40, struct kdbus_msg),
+ KDBUS_CMD_MSG_RECV = _IOR(KDBUS_IOC_MAGIC, 0x41, __u64 *),
+ KDBUS_CMD_MSG_RELEASE = _IOW(KDBUS_IOC_MAGIC, 0x42, __u64 *),
KDBUS_CMD_NAME_ACQUIRE = _IOWR(KDBUS_IOC_MAGIC, 0x50, struct kdbus_cmd_name),
- KDBUS_CMD_NAME_RELEASE = _IOWR(KDBUS_IOC_MAGIC, 0x51, struct kdbus_cmd_name),
+ KDBUS_CMD_NAME_RELEASE = _IOW(KDBUS_IOC_MAGIC, 0x51, struct kdbus_cmd_name),
KDBUS_CMD_NAME_LIST = _IOWR(KDBUS_IOC_MAGIC, 0x52, struct kdbus_cmd_names),
KDBUS_CMD_NAME_QUERY = _IOWR(KDBUS_IOC_MAGIC, 0x53, struct kdbus_cmd_name_info),
- KDBUS_CMD_MATCH_ADD = _IOWR(KDBUS_IOC_MAGIC, 0x60, struct kdbus_cmd_match),
- KDBUS_CMD_MATCH_REMOVE = _IOWR(KDBUS_IOC_MAGIC, 0x61, struct kdbus_cmd_match),
- KDBUS_CMD_MONITOR = _IOWR(KDBUS_IOC_MAGIC, 0x62, struct kdbus_cmd_monitor),
+ KDBUS_CMD_MATCH_ADD = _IOW(KDBUS_IOC_MAGIC, 0x60, struct kdbus_cmd_match),
+ KDBUS_CMD_MATCH_REMOVE = _IOW(KDBUS_IOC_MAGIC, 0x61, struct kdbus_cmd_match),
+ KDBUS_CMD_MONITOR = _IOW(KDBUS_IOC_MAGIC, 0x62, struct kdbus_cmd_monitor),
/* kdbus ep node commands: require ep owner state */
- KDBUS_CMD_EP_POLICY_SET = _IOWR(KDBUS_IOC_MAGIC, 0x70, struct kdbus_cmd_policy),
+ KDBUS_CMD_EP_POLICY_SET = _IOW(KDBUS_IOC_MAGIC, 0x70, struct kdbus_cmd_policy),
+
+ /* kdbus memfd commands: */
+ KDBUS_CMD_MEMFD_NEW = _IOR(KDBUS_IOC_MAGIC, 0x80, int *),
+ KDBUS_CMD_MEMFD_SIZE_GET = _IOR(KDBUS_IOC_MAGIC, 0x81, __u64 *),
+ KDBUS_CMD_MEMFD_SIZE_SET = _IOW(KDBUS_IOC_MAGIC, 0x82, __u64 *),
+ KDBUS_CMD_MEMFD_SEAL_GET = _IOR(KDBUS_IOC_MAGIC, 0x83, int *),
+ KDBUS_CMD_MEMFD_SEAL_SET = _IO(KDBUS_IOC_MAGIC, 0x84),
};
#endif
diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c
index 7d6d848ec5..3f766fb519 100644
--- a/src/libsystemd-bus/sd-bus.c
+++ b/src/libsystemd-bus/sd-bus.c
@@ -26,6 +26,8 @@
#include <netdb.h>
#include <sys/poll.h>
#include <byteswap.h>
+#include <sys/mman.h>
+#include <pthread.h>
#include "util.h"
#include "macro.h"
@@ -43,6 +45,18 @@
static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec);
+static void bus_close_fds(sd_bus *b) {
+ assert(b);
+
+ if (b->input_fd >= 0)
+ close_nointr_nofail(b->input_fd);
+
+ if (b->output_fd >= 0 && b->output_fd != b->input_fd)
+ close_nointr_nofail(b->output_fd);
+
+ b->input_fd = b->output_fd = -1;
+}
+
static void bus_free(sd_bus *b) {
struct filter_callback *f;
struct object_callback *c;
@@ -50,7 +64,10 @@ static void bus_free(sd_bus *b) {
assert(b);
- sd_bus_close(b);
+ bus_close_fds(b);
+
+ if (b->kdbus_buffer)
+ munmap(b->kdbus_buffer, KDBUS_POOL_SIZE);
free(b->rbuffer);
free(b->unique_name);
@@ -86,9 +103,12 @@ static void bus_free(sd_bus *b) {
}
hashmap_free(b->object_callbacks);
-
bus_match_free(&b->match_callbacks);
+ bus_kernel_flush_memfd(b);
+
+ assert_se(pthread_mutex_destroy(&b->memfd_cache_mutex) == 0);
+
free(b);
}
@@ -102,10 +122,13 @@ int sd_bus_new(sd_bus **ret) {
if (!r)
return -ENOMEM;
- r->n_ref = 1;
+ r->n_ref = REFCNT_INIT;
r->input_fd = r->output_fd = -1;
r->message_version = 1;
- r->negotiate_fds = true;
+ r->hello_flags |= KDBUS_HELLO_ACCEPT_FD;
+ r->original_pid = getpid();
+
+ assert_se(pthread_mutex_init(&r->memfd_cache_mutex, NULL) == 0);
/* We guarantee that wqueue always has space for at least one
* entry */
@@ -128,6 +151,8 @@ int sd_bus_set_address(sd_bus *bus, const char *address) {
return -EPERM;
if (!address)
return -EINVAL;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
a = strdup(address);
if (!a)
@@ -148,6 +173,8 @@ int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd) {
return -EINVAL;
if (output_fd < 0)
return -EINVAL;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
bus->input_fd = input_fd;
bus->output_fd = output_fd;
@@ -165,6 +192,8 @@ int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[]) {
return -EINVAL;
if (strv_isempty(argv))
return -EINVAL;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
p = strdup(path);
if (!p)
@@ -190,18 +219,106 @@ int sd_bus_set_bus_client(sd_bus *bus, int b) {
return -EINVAL;
if (bus->state != BUS_UNSET)
return -EPERM;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
bus->bus_client = !!b;
return 0;
}
-int sd_bus_set_negotiate_fds(sd_bus *bus, int b) {
+int sd_bus_negotiate_fds(sd_bus *bus, int b) {
+ if (!bus)
+ return -EINVAL;
+ if (bus->state != BUS_UNSET)
+ return -EPERM;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
+
+ SET_FLAG(bus->hello_flags, KDBUS_HELLO_ACCEPT_FD, b);
+ return 0;
+}
+
+int sd_bus_negotiate_attach_comm(sd_bus *bus, int b) {
+ if (!bus)
+ return -EINVAL;
+ if (bus->state != BUS_UNSET)
+ return -EPERM;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
+
+ SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_COMM, b);
+ return 0;
+}
+
+int sd_bus_negotiate_attach_exe(sd_bus *bus, int b) {
+ if (!bus)
+ return -EINVAL;
+ if (bus->state != BUS_UNSET)
+ return -EPERM;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
+
+ SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_EXE, b);
+ return 0;
+}
+
+int sd_bus_negotiate_attach_cmdline(sd_bus *bus, int b) {
if (!bus)
return -EINVAL;
if (bus->state != BUS_UNSET)
return -EPERM;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
- bus->negotiate_fds = !!b;
+ SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CMDLINE, b);
+ return 0;
+}
+
+int sd_bus_negotiate_attach_cgroup(sd_bus *bus, int b) {
+ if (!bus)
+ return -EINVAL;
+ if (bus->state != BUS_UNSET)
+ return -EPERM;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
+
+ SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CGROUP, b);
+ return 0;
+}
+
+int sd_bus_negotiate_attach_caps(sd_bus *bus, int b) {
+ if (!bus)
+ return -EINVAL;
+ if (bus->state != BUS_UNSET)
+ return -EPERM;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
+
+ SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CAPS, b);
+ return 0;
+}
+
+int sd_bus_negotiate_attach_selinux_context(sd_bus *bus, int b) {
+ if (!bus)
+ return -EINVAL;
+ if (bus->state != BUS_UNSET)
+ return -EPERM;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
+
+ SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_SECLABEL, b);
+ return 0;
+}
+
+int sd_bus_negotiate_attach_audit(sd_bus *bus, int b) {
+ if (!bus)
+ return -EINVAL;
+ if (bus->state != BUS_UNSET)
+ return -EPERM;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
+
+ SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_AUDIT, b);
return 0;
}
@@ -212,6 +329,8 @@ int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id) {
return -EINVAL;
if (bus->state != BUS_UNSET)
return -EPERM;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
bus->is_server = !!b;
bus->server_id = server_id;
@@ -223,23 +342,25 @@ int sd_bus_set_anonymous(sd_bus *bus, int b) {
return -EINVAL;
if (bus->state != BUS_UNSET)
return -EPERM;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
bus->anonymous_auth = !!b;
return 0;
}
-static int hello_callback(sd_bus *bus, int error, sd_bus_message *reply, void *userdata) {
+static int hello_callback(sd_bus *bus, sd_bus_message *reply, void *userdata) {
const char *s;
int r;
assert(bus);
assert(bus->state == BUS_HELLO);
-
- if (error != 0)
- return -error;
-
assert(reply);
+ r = bus_message_to_errno(reply);
+ if (r < 0)
+ return r;
+
r = sd_bus_message_read(reply, "s", &s);
if (r < 0)
return r;
@@ -811,6 +932,8 @@ int sd_bus_start(sd_bus *bus) {
return -EINVAL;
if (bus->state != BUS_UNSET)
return -EPERM;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
bus->state = BUS_OPENING;
@@ -920,22 +1043,29 @@ fail:
void sd_bus_close(sd_bus *bus) {
if (!bus)
return;
+ if (bus->state == BUS_CLOSED)
+ return;
+ if (bus_pid_changed(bus))
+ return;
- if (bus->input_fd >= 0)
- close_nointr_nofail(bus->input_fd);
- if (bus->output_fd >= 0 && bus->output_fd != bus->input_fd)
- close_nointr_nofail(bus->output_fd);
+ bus->state = BUS_CLOSED;
- bus->input_fd = bus->output_fd = -1;
+ 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_MSG_RELEASE ioctl on the fd when they are
+ * freed. */
}
sd_bus *sd_bus_ref(sd_bus *bus) {
if (!bus)
return NULL;
- assert(bus->n_ref > 0);
+ assert_se(REFCNT_INC(bus->n_ref) >= 2);
- bus->n_ref++;
return bus;
}
@@ -943,10 +1073,7 @@ sd_bus *sd_bus_unref(sd_bus *bus) {
if (!bus)
return NULL;
- assert(bus->n_ref > 0);
- bus->n_ref--;
-
- if (bus->n_ref <= 0)
+ if (REFCNT_DEC(bus->n_ref) <= 0)
bus_free(bus);
return NULL;
@@ -955,8 +1082,10 @@ sd_bus *sd_bus_unref(sd_bus *bus) {
int sd_bus_is_open(sd_bus *bus) {
if (!bus)
return -EINVAL;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
- return bus->state != BUS_UNSET && bus->input_fd >= 0;
+ return BUS_IS_OPEN(bus->state);
}
int sd_bus_can_send(sd_bus *bus, char type) {
@@ -964,11 +1093,13 @@ int sd_bus_can_send(sd_bus *bus, char type) {
if (!bus)
return -EINVAL;
- if (bus->output_fd < 0)
+ if (bus->state == BUS_UNSET)
return -ENOTCONN;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
if (type == SD_BUS_TYPE_UNIX_FD) {
- if (!bus->negotiate_fds)
+ if (!(bus->hello_flags & KDBUS_HELLO_ACCEPT_FD))
return 0;
r = bus_ensure_running(bus);
@@ -988,6 +1119,8 @@ int sd_bus_get_server_id(sd_bus *bus, sd_id128_t *server_id) {
return -EINVAL;
if (!server_id)
return -EINVAL;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
r = bus_ensure_running(bus);
if (r < 0)
@@ -1015,9 +1148,6 @@ static int dispatch_wqueue(sd_bus *bus) {
assert(bus);
assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
- if (bus->output_fd < 0)
- return -ENOTCONN;
-
while (bus->wqueue_size > 0) {
if (bus->is_kernel)
@@ -1062,9 +1192,6 @@ static int dispatch_rqueue(sd_bus *bus, sd_bus_message **m) {
assert(m);
assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
- if (bus->input_fd < 0)
- return -ENOTCONN;
-
if (bus->rqueue_size > 0) {
/* Dispatch a queued message */
@@ -1100,12 +1227,12 @@ int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) {
if (!bus)
return -EINVAL;
- if (bus->state == BUS_UNSET)
- return -ENOTCONN;
- if (bus->output_fd < 0)
+ if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
if (!m)
return -EINVAL;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
if (m->n_fds > 0) {
r = sd_bus_can_send(bus, SD_BUS_TYPE_UNIX_FD);
@@ -1213,9 +1340,7 @@ int sd_bus_send_with_reply(
if (!bus)
return -EINVAL;
- if (bus->state == BUS_UNSET)
- return -ENOTCONN;
- if (bus->output_fd < 0)
+ if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
if (!m)
return -EINVAL;
@@ -1225,6 +1350,8 @@ int sd_bus_send_with_reply(
return -EINVAL;
if (m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
return -EINVAL;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
r = hashmap_ensure_allocated(&bus->reply_callbacks, uint64_hash_func, uint64_compare_func);
if (r < 0)
@@ -1280,6 +1407,8 @@ int sd_bus_send_with_reply_cancel(sd_bus *bus, uint64_t serial) {
return -EINVAL;
if (serial == 0)
return -EINVAL;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
c = hashmap_remove(bus->reply_callbacks, &serial);
if (!c)
@@ -1297,11 +1426,8 @@ int bus_ensure_running(sd_bus *bus) {
assert(bus);
- if (bus->input_fd < 0)
- return -ENOTCONN;
- if (bus->state == BUS_UNSET)
+ if (bus->state == BUS_UNSET || bus->state == BUS_CLOSED)
return -ENOTCONN;
-
if (bus->state == BUS_RUNNING)
return 1;
@@ -1334,9 +1460,7 @@ int sd_bus_send_with_reply_and_block(
if (!bus)
return -EINVAL;
- if (bus->output_fd < 0)
- return -ENOTCONN;
- if (bus->state == BUS_UNSET)
+ if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
if (!m)
return -EINVAL;
@@ -1346,6 +1470,8 @@ int sd_bus_send_with_reply_and_block(
return -EINVAL;
if (bus_error_is_dirty(error))
return -EINVAL;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
r = bus_ensure_running(bus);
if (r < 0)
@@ -1452,10 +1578,12 @@ int sd_bus_send_with_reply_and_block(
int sd_bus_get_fd(sd_bus *bus) {
if (!bus)
return -EINVAL;
- if (bus->input_fd < 0)
+ if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
if (bus->input_fd != bus->output_fd)
return -EPERM;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
return bus->input_fd;
}
@@ -1465,10 +1593,10 @@ int sd_bus_get_events(sd_bus *bus) {
if (!bus)
return -EINVAL;
- if (bus->state == BUS_UNSET)
- return -ENOTCONN;
- if (bus->input_fd < 0)
+ if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
if (bus->state == BUS_OPENING)
flags |= POLLOUT;
@@ -1496,10 +1624,10 @@ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
return -EINVAL;
if (!timeout_usec)
return -EINVAL;
- if (bus->state == BUS_UNSET)
- return -ENOTCONN;
- if (bus->input_fd < 0)
+ if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
if (bus->state == BUS_AUTHENTICATING) {
*timeout_usec = bus->auth_timeout;
@@ -1522,6 +1650,7 @@ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
}
static int process_timeout(sd_bus *bus) {
+ _cleanup_bus_message_unref_ sd_bus_message* m = NULL;
struct reply_callback *c;
usec_t n;
int r;
@@ -1536,10 +1665,18 @@ static int process_timeout(sd_bus *bus) {
if (c->timeout > n)
return 0;
+ r = bus_message_new_synthetic_error(
+ bus,
+ c->serial,
+ &SD_BUS_ERROR_MAKE("org.freedesktop.DBus.Error.Timeout", "Timed out"),
+ &m);
+ if (r < 0)
+ return r;
+
assert_se(prioq_pop(bus->reply_callbacks_prioq) == c);
hashmap_remove(bus->reply_callbacks, &c->serial);
- r = c->callback(bus, ETIMEDOUT, NULL, c->userdata);
+ r = c->callback(bus, m, c->userdata);
free(c);
return r < 0 ? r : 1;
@@ -1589,7 +1726,7 @@ static int process_reply(sd_bus *bus, sd_bus_message *m) {
if (r < 0)
return r;
- r = c->callback(bus, 0, m, c->userdata);
+ r = c->callback(bus, m, c->userdata);
free(c);
return r;
@@ -1620,7 +1757,7 @@ static int process_filter(sd_bus *bus, sd_bus_message *m) {
if (r < 0)
return r;
- r = l->callback(bus, 0, m, l->userdata);
+ r = l->callback(bus, m, l->userdata);
if (r != 0)
return r;
@@ -1640,7 +1777,7 @@ static int process_match(sd_bus *bus, sd_bus_message *m) {
do {
bus->match_callbacks_modified = false;
- r = bus_match_run(bus, &bus->match_callbacks, 0, m);
+ r = bus_match_run(bus, &bus->match_callbacks, m);
if (r != 0)
return r;
@@ -1733,7 +1870,7 @@ static int process_object(sd_bus *bus, sd_bus_message *m) {
if (r < 0)
return r;
- r = c->callback(bus, 0, m, c->userdata);
+ r = c->callback(bus, m, c->userdata);
if (r != 0)
return r;
@@ -1763,7 +1900,7 @@ static int process_object(sd_bus *bus, sd_bus_message *m) {
if (r < 0)
return r;
- r = c->callback(bus, 0, m, c->userdata);
+ r = c->callback(bus, m, c->userdata);
if (r != 0)
return r;
@@ -1986,8 +2123,8 @@ int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
if (!bus)
return -EINVAL;
- if (bus->input_fd < 0)
- return -ENOTCONN;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
/* We don't allow recursively invoking sd_bus_process(). */
if (bus->processing)
@@ -1996,6 +2133,7 @@ int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
switch (bus->state) {
case BUS_UNSET:
+ case BUS_CLOSED:
return -ENOTCONN;
case BUS_OPENING:
@@ -2036,7 +2174,7 @@ static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
assert(bus);
- if (bus->input_fd < 0)
+ if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
e = sd_bus_get_events(bus);
@@ -2082,10 +2220,11 @@ int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec) {
if (!bus)
return -EINVAL;
- if (bus->state == BUS_UNSET)
- return -ENOTCONN;
- if (bus->input_fd < 0)
+ if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
+
if (bus->rqueue_size > 0)
return 0;
@@ -2097,10 +2236,10 @@ int sd_bus_flush(sd_bus *bus) {
if (!bus)
return -EINVAL;
- if (bus->state == BUS_UNSET)
- return -ENOTCONN;
- if (bus->output_fd < 0)
+ if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
r = bus_ensure_running(bus);
if (r < 0)
@@ -2130,6 +2269,8 @@ int sd_bus_add_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *user
return -EINVAL;
if (!callback)
return -EINVAL;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
f = new0(struct filter_callback, 1);
if (!f)
@@ -2149,6 +2290,8 @@ int sd_bus_remove_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *u
return -EINVAL;
if (!callback)
return -EINVAL;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
LIST_FOREACH(callbacks, f, bus->filter_callbacks) {
if (f->callback == callback && f->userdata == userdata) {
@@ -2178,6 +2321,8 @@ static int bus_add_object(
return -EINVAL;
if (!callback)
return -EINVAL;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
r = hashmap_ensure_allocated(&bus->object_callbacks, string_hash_func, string_compare_func);
if (r < 0)
@@ -2223,6 +2368,8 @@ static int bus_remove_object(
return -EINVAL;
if (!callback)
return -EINVAL;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
c = hashmap_get(bus->object_callbacks, path);
if (!c)
@@ -2257,51 +2404,68 @@ int sd_bus_remove_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handl
}
int sd_bus_add_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata) {
+ struct bus_match_component *components = NULL;
+ unsigned n_components = 0;
+ uint64_t cookie = 0;
int r = 0;
if (!bus)
return -EINVAL;
if (!match)
return -EINVAL;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
+
+ r = bus_match_parse(match, &components, &n_components);
+ if (r < 0)
+ goto finish;
if (bus->bus_client) {
- r = bus_add_match_internal(bus, match);
+ cookie = ++bus->match_cookie;
+
+ r = bus_add_match_internal(bus, match, components, n_components, cookie);
if (r < 0)
- return r;
+ goto finish;
}
- if (callback) {
- bus->match_callbacks_modified = true;
- r = bus_match_add(&bus->match_callbacks, match, callback, userdata, NULL);
- if (r < 0) {
-
- if (bus->bus_client)
- bus_remove_match_internal(bus, match);
- }
+ bus->match_callbacks_modified = true;
+ r = bus_match_add(&bus->match_callbacks, components, n_components, callback, userdata, cookie, NULL);
+ if (r < 0) {
+ if (bus->bus_client)
+ bus_remove_match_internal(bus, match, cookie);
}
+finish:
+ bus_match_parse_free(components, n_components);
return r;
}
int sd_bus_remove_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata) {
+ struct bus_match_component *components = NULL;
+ unsigned n_components = 0;
int r = 0, q = 0;
+ uint64_t cookie = 0;
if (!bus)
return -EINVAL;
if (!match)
return -EINVAL;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
+
+ r = bus_match_parse(match, &components, &n_components);
+ if (r < 0)
+ return r;
+
+ bus->match_callbacks_modified = true;
+ r = bus_match_remove(&bus->match_callbacks, components, n_components, callback, userdata, &cookie);
if (bus->bus_client)
- r = bus_remove_match_internal(bus, match);
+ q = bus_remove_match_internal(bus, match, cookie);
- if (callback) {
- bus->match_callbacks_modified = true;
- q = bus_match_remove(&bus->match_callbacks, match, callback, userdata);
- }
+ bus_match_parse_free(components, n_components);
- if (r < 0)
- return r;
- return q;
+ return r < 0 ? r : q;
}
int sd_bus_emit_signal(
@@ -2317,6 +2481,10 @@ int sd_bus_emit_signal(
if (!bus)
return -EINVAL;
+ if (!BUS_IS_OPEN(bus->state))
+ return -ENOTCONN;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
r = sd_bus_message_new_signal(bus, path, interface, member, &m);
if (r < 0)
@@ -2346,7 +2514,12 @@ int sd_bus_call_method(
int r;
if (!bus)
+
return -EINVAL;
+ if (!BUS_IS_OPEN(bus->state))
+ return -ENOTCONN;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
r = sd_bus_message_new_method_call(bus, destination, path, interface, member, &m);
if (r < 0)
@@ -2378,6 +2551,10 @@ int sd_bus_reply_method_return(
return -EPERM;
if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
return -EINVAL;
+ if (!BUS_IS_OPEN(bus->state))
+ return -ENOTCONN;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
return 0;
@@ -2413,6 +2590,10 @@ int sd_bus_reply_method_error(
return -EINVAL;
if (!sd_bus_error_is_set(e))
return -EINVAL;
+ if (!BUS_IS_OPEN(bus->state))
+ return -ENOTCONN;
+ if (bus_pid_changed(bus))
+ return -ECHILD;
if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
return 0;
@@ -2423,3 +2604,12 @@ int sd_bus_reply_method_error(
return sd_bus_send(bus, m, NULL);
}
+
+bool bus_pid_changed(sd_bus *bus) {
+ assert(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();
+}
diff --git a/src/libsystemd-bus/sd-memfd.c b/src/libsystemd-bus/sd-memfd.c
new file mode 100644
index 0000000000..bd14da3a70
--- /dev/null
+++ b/src/libsystemd-bus/sd-memfd.c
@@ -0,0 +1,231 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ 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>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include "util.h"
+#include "kdbus.h"
+
+#include "sd-memfd.h"
+
+struct sd_memfd {
+ int fd;
+ FILE *f;
+};
+
+int sd_memfd_new(sd_memfd **m) {
+ _cleanup_close_ int kdbus = -1;
+ sd_memfd *n;
+ int fd;
+
+ if (!m)
+ return -EINVAL;
+
+ kdbus = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
+ if (kdbus < 0)
+ return -errno;
+
+ if (ioctl(kdbus, KDBUS_CMD_MEMFD_NEW, &fd) < 0)
+ return -errno;
+
+ n = new0(struct sd_memfd, 1);
+ if (!n)
+ return -ENOMEM;
+
+ n->fd = fd;
+ *m = n;
+ return 0;
+}
+
+int sd_memfd_make(int fd, sd_memfd **m) {
+ sd_memfd *n;
+ uint64_t sz;
+
+ if (!m)
+ return -EINVAL;
+ if (fd < 0)
+ return -EINVAL;
+
+ /* Check if this is a valid memfd */
+ if (ioctl(fd, KDBUS_CMD_MEMFD_SIZE_GET, &sz) < 0)
+ return -ENOTTY;
+
+ n = new0(struct sd_memfd, 1);
+ if (!n)
+ return -ENOMEM;
+
+ n->fd = fd;
+ *m = n;
+
+ return 0;
+}
+
+void sd_memfd_free(sd_memfd *m) {
+ if (!m)
+ return;
+
+ if (m->f)
+ fclose(m->f);
+ else
+ close_nointr_nofail(m->fd);
+
+ free(m);
+}
+
+int sd_memfd_get_fd(sd_memfd *m) {
+ if (!m)
+ return -EINVAL;
+
+ return m->fd;
+}
+
+int sd_memfd_get_file(sd_memfd *m, FILE **f) {
+ if (!m)
+ return -EINVAL;
+ if (!f)
+ return -EINVAL;
+
+ if (!m->f) {
+ m->f = fdopen(m->fd, "r+");
+ if (!m->f)
+ return -errno;
+ }
+
+ *f = m->f;
+ return 0;
+}
+
+int sd_memfd_dup_fd(sd_memfd *m) {
+ int fd;
+
+ if (!m)
+ return -EINVAL;
+
+ fd = fcntl(m->fd, F_DUPFD_CLOEXEC, 3);
+ if (fd < 0)
+ return -errno;
+
+ return fd;
+}
+
+int sd_memfd_map(sd_memfd *m, uint64_t offset, size_t size, void **p) {
+ void *q;
+ int sealed;
+
+ if (!m)
+ return -EINVAL;
+ if (size <= 0)
+ return -EINVAL;
+ if (!p)
+ return -EINVAL;
+
+ sealed = sd_memfd_get_sealed(m);
+ if (sealed < 0)
+ return sealed;
+
+ q = mmap(NULL, size, sealed ? PROT_READ : PROT_READ|PROT_WRITE, MAP_SHARED, m->fd, offset);
+ if (q == MAP_FAILED)
+ return -errno;
+
+ *p = q;
+ return 0;
+}
+
+int sd_memfd_set_sealed(sd_memfd *m, int b) {
+ int r;
+
+ if (!m)
+ return -EINVAL;
+
+ r = ioctl(m->fd, KDBUS_CMD_MEMFD_SEAL_SET, b);
+ if (r < 0)
+ return -errno;
+
+ return 0;
+}
+
+int sd_memfd_get_sealed(sd_memfd *m) {
+ int r, b;
+
+ if (!m)
+ return -EINVAL;
+
+ r = ioctl(m->fd, KDBUS_CMD_MEMFD_SEAL_GET, &b);
+ if (r < 0)
+ return -errno;
+
+ return !!b;
+}
+
+int sd_memfd_get_size(sd_memfd *m, uint64_t *sz) {
+ int r;
+
+ if (!m)
+ return -EINVAL;
+ if (!sz)
+ return -EINVAL;
+
+ r = ioctl(m->fd, KDBUS_CMD_MEMFD_SIZE_GET, sz);
+ if (r < 0)
+ return -errno;
+
+ return r;
+}
+
+int sd_memfd_set_size(sd_memfd *m, uint64_t sz) {
+ int r;
+
+ if (!m)
+ return -EINVAL;
+
+ r = ioctl(m->fd, KDBUS_CMD_MEMFD_SIZE_SET, &sz);
+ if (r < 0)
+ return -errno;
+
+ return r;
+}
+
+int sd_memfd_new_and_map(sd_memfd **m, size_t sz, void **p) {
+ sd_memfd *n;
+ int r;
+
+ r = sd_memfd_new(&n);
+ if (r < 0)
+ return r;
+
+ r = sd_memfd_set_size(n, sz);
+ if (r < 0) {
+ sd_memfd_free(n);
+ return r;
+ }
+
+ r = sd_memfd_map(n, 0, sz, p);
+ if (r < 0) {
+ sd_memfd_free(n);
+ return r;
+ }
+
+ *m = n;
+ return 0;
+}
diff --git a/src/libsystemd-bus/test-bus-chat.c b/src/libsystemd-bus/test-bus-chat.c
index f457c8f88a..f308eddbb0 100644
--- a/src/libsystemd-bus/test-bus-chat.c
+++ b/src/libsystemd-bus/test-bus-chat.c
@@ -35,17 +35,17 @@
#include "bus-match.h"
#include "bus-internal.h"
-static int match_callback(sd_bus *bus, int error, sd_bus_message *m, void *userdata) {
+static int match_callback(sd_bus *bus, sd_bus_message *m, void *userdata) {
log_info("Match triggered! interface=%s member=%s", strna(sd_bus_message_get_interface(m)), strna(sd_bus_message_get_member(m)));
return 0;
}
-static int object_callback(sd_bus *bus, int error, sd_bus_message *m, void *userdata) {
+static int object_callback(sd_bus *bus, sd_bus_message *m, void *userdata) {
int r;
assert(bus);
- if (error != 0)
+ if (sd_bus_message_is_method_error(m, NULL))
return 0;
if (sd_bus_message_is_method_call(m, "org.object.test", "Foobar")) {
@@ -356,10 +356,10 @@ finish:
return INT_TO_PTR(r);
}
-static int quit_callback(sd_bus *b, int ret, sd_bus_message *m, void *userdata) {
+static int quit_callback(sd_bus *b, sd_bus_message *m, void *userdata) {
bool *x = userdata;
- log_error("Quit callback: %s", strerror(ret));
+ log_error("Quit callback: %s", strerror(bus_message_to_errno(m)));
*x = 1;
return 1;
diff --git a/src/libsystemd-bus/test-bus-kernel-benchmark.c b/src/libsystemd-bus/test-bus-kernel-benchmark.c
new file mode 100644
index 0000000000..2e84cd9244
--- /dev/null
+++ b/src/libsystemd-bus/test-bus-kernel-benchmark.c
@@ -0,0 +1,302 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ 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 <ctype.h>
+#include <sys/wait.h>
+
+#include "util.h"
+#include "log.h"
+#include "time-util.h"
+
+#include "sd-bus.h"
+#include "bus-message.h"
+#include "bus-error.h"
+#include "bus-kernel.h"
+#include "bus-internal.h"
+
+#define MAX_SIZE (4*1024*1024)
+
+static usec_t arg_loop_usec = 100 * USEC_PER_MSEC;
+
+static void server(sd_bus *b, size_t *result) {
+ int r;
+
+ for (;;) {
+ _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+
+ r = sd_bus_process(b, &m);
+ assert_se(r >= 0);
+
+ if (r == 0)
+ assert_se(sd_bus_wait(b, (usec_t) -1) >= 0);
+ if (!m)
+ continue;
+
+ if (sd_bus_message_is_method_call(m, "benchmark.server", "Ping"))
+ assert_se(sd_bus_reply_method_return(b, m, NULL) >= 0);
+ else if (sd_bus_message_is_method_call(m, "benchmark.server", "Work")) {
+ const void *p;
+ size_t sz;
+
+ /* Make sure the mmap is mapped */
+ assert_se(sd_bus_message_read_array(m, 'y', &p, &sz) > 0);
+
+ assert_se(sd_bus_reply_method_return(b, m, NULL) >= 0);
+ } else if (sd_bus_message_is_method_call(m, "benchmark.server", "Exit")) {
+ uint64_t res;
+ assert_se(sd_bus_message_read(m, "t", &res) > 0);
+
+ *result = res;
+ return;
+
+ } else
+ assert_not_reached("Unknown method");
+ }
+}
+
+static void transaction(sd_bus *b, size_t sz) {
+ _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+ uint8_t *p;
+
+ assert_se(sd_bus_message_new_method_call(b, ":1.1", "/", "benchmark.server", "Work", &m) >= 0);
+ assert_se(sd_bus_message_append_array_space(m, 'y', sz, (void**) &p) >= 0);
+
+ memset(p, 0x80, sz);
+
+ assert_se(sd_bus_send_with_reply_and_block(b, m, 0, NULL, &reply) >= 0);
+}
+
+static void client_bisect(const char *address) {
+ _cleanup_bus_message_unref_ sd_bus_message *x = NULL;
+ size_t lsize, rsize, csize;
+ sd_bus *b;
+ int r;
+
+ r = sd_bus_new(&b);
+ assert_se(r >= 0);
+
+ r = sd_bus_set_address(b, address);
+ assert_se(r >= 0);
+
+ r = sd_bus_start(b);
+ assert_se(r >= 0);
+
+ assert_se(sd_bus_call_method(b, ":1.1", "/", "benchmark.server", "Ping", NULL, NULL, NULL) >= 0);
+
+ lsize = 1;
+ rsize = MAX_SIZE;
+
+ printf("SIZE\tCOPY\tMEMFD\n");
+
+ for (;;) {
+ usec_t t;
+ unsigned n_copying, n_memfd;
+
+ csize = (lsize + rsize) / 2;
+
+ if (csize <= lsize)
+ break;
+
+ if (csize <= 0)
+ break;
+
+ printf("%zu\t", csize);
+
+ b->use_memfd = 0;
+
+ t = now(CLOCK_MONOTONIC);
+ for (n_copying = 0;; n_copying++) {
+ transaction(b, csize);
+ if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
+ break;
+ }
+ printf("%u\t", (unsigned) ((n_copying * USEC_PER_SEC) / arg_loop_usec));
+
+ b->use_memfd = -1;
+
+ t = now(CLOCK_MONOTONIC);
+ for (n_memfd = 0;; n_memfd++) {
+ transaction(b, csize);
+ if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
+ break;
+ }
+ printf("%u\n", (unsigned) ((n_memfd * USEC_PER_SEC) / arg_loop_usec));
+
+ if (n_copying == n_memfd)
+ break;
+
+ if (n_copying > n_memfd)
+ lsize = csize;
+ else
+ rsize = csize;
+ }
+
+ b->use_memfd = 1;
+ assert_se(sd_bus_message_new_method_call(b, ":1.1", "/", "benchmark.server", "Exit", &x) >= 0);
+ assert_se(sd_bus_message_append(x, "t", csize) >= 0);
+ assert_se(sd_bus_send(b, x, NULL) >= 0);
+
+ sd_bus_unref(b);
+}
+
+static void client_chart(const char *address) {
+ _cleanup_bus_message_unref_ sd_bus_message *x = NULL;
+ size_t csize;
+ sd_bus *b;
+ int r;
+
+ r = sd_bus_new(&b);
+ assert_se(r >= 0);
+
+ r = sd_bus_set_address(b, address);
+ assert_se(r >= 0);
+
+ r = sd_bus_start(b);
+ assert_se(r >= 0);
+
+ assert_se(sd_bus_call_method(b, ":1.1", "/", "benchmark.server", "Ping", NULL, NULL, NULL) >= 0);
+
+ printf("SIZE\tCOPY\tMEMFD\n");
+
+ for (csize = 1; csize <= MAX_SIZE; csize *= 2) {
+ usec_t t;
+ unsigned n_copying, n_memfd;
+
+ printf("%zu\t", csize);
+
+ b->use_memfd = 0;
+
+ t = now(CLOCK_MONOTONIC);
+ for (n_copying = 0;; n_copying++) {
+ transaction(b, csize);
+ if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
+ break;
+ }
+
+ printf("%u\t", (unsigned) ((n_copying * USEC_PER_SEC) / arg_loop_usec));
+
+ b->use_memfd = -1;
+
+ t = now(CLOCK_MONOTONIC);
+ for (n_memfd = 0;; n_memfd++) {
+ transaction(b, csize);
+ if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
+ break;
+ }
+
+ printf("%u\n", (unsigned) ((n_memfd * USEC_PER_SEC) / arg_loop_usec));
+ }
+
+ b->use_memfd = 1;
+ assert_se(sd_bus_message_new_method_call(b, ":1.1", "/", "benchmark.server", "Exit", &x) >= 0);
+ assert_se(sd_bus_message_append(x, "t", csize) >= 0);
+ assert_se(sd_bus_send(b, x, NULL) >= 0);
+
+ sd_bus_unref(b);
+}
+
+int main(int argc, char *argv[]) {
+ enum {
+ MODE_BISECT,
+ MODE_CHART,
+ } mode = MODE_BISECT;
+ int i;
+ _cleanup_free_ char *bus_name = NULL, *address = NULL;
+ _cleanup_close_ int bus_ref = -1;
+ cpu_set_t cpuset;
+ size_t result;
+ sd_bus *b;
+ pid_t pid;
+ int r;
+
+ log_set_max_level(LOG_DEBUG);
+
+ for (i = 1; i < argc; i++) {
+ if (streq(argv[i], "chart")) {
+ mode = MODE_CHART;
+ continue;
+ }
+
+ assert_se(parse_sec(argv[i], &arg_loop_usec) >= 0);
+ }
+
+ assert_se(arg_loop_usec > 0);
+
+ bus_ref = bus_kernel_create("deine-mutter", &bus_name);
+ if (bus_ref == -ENOENT)
+ exit(EXIT_TEST_SKIP);
+
+ assert_se(bus_ref >= 0);
+
+ address = strappend("kernel:path=", bus_name);
+ assert_se(address);
+
+ r = sd_bus_new(&b);
+ assert_se(r >= 0);
+
+ r = sd_bus_set_address(b, address);
+ assert_se(r >= 0);
+
+ r = sd_bus_start(b);
+ assert_se(r >= 0);
+
+ sync();
+ setpriority(PRIO_PROCESS, 0, -19);
+
+ pid = fork();
+ assert_se(pid >= 0);
+
+ if (pid == 0) {
+ CPU_ZERO(&cpuset);
+ CPU_SET(0, &cpuset);
+ pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
+
+ close_nointr_nofail(bus_ref);
+ sd_bus_unref(b);
+
+ switch (mode) {
+ case MODE_BISECT:
+ client_bisect(address);
+ break;
+
+ case MODE_CHART:
+ client_chart(address);
+ break;
+ }
+
+ _exit(0);
+ }
+
+ CPU_ZERO(&cpuset);
+ CPU_SET(1, &cpuset);
+ pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
+
+ server(b, &result);
+
+ if (mode == MODE_BISECT)
+ printf("Copying/memfd are equally fast at %zu bytes\n", result);
+
+ assert_se(waitpid(pid, NULL, 0) == pid);
+
+ sd_bus_unref(b);
+
+ return 0;
+}
diff --git a/src/libsystemd-bus/test-bus-kernel-bloom.c b/src/libsystemd-bus/test-bus-kernel-bloom.c
new file mode 100644
index 0000000000..5445d3488f
--- /dev/null
+++ b/src/libsystemd-bus/test-bus-kernel-bloom.c
@@ -0,0 +1,112 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ 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 "log.h"
+
+#include "sd-bus.h"
+#include "bus-message.h"
+#include "bus-error.h"
+#include "bus-kernel.h"
+
+static void test_one(
+ const char *path,
+ const char *interface,
+ const char *member,
+ const char *arg0,
+ const char *match,
+ bool good) {
+
+ _cleanup_close_ int bus_ref = -1;
+ _cleanup_free_ char *bus_name = NULL, *address = NULL;
+ _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ sd_bus *a, *b;
+ int r;
+
+ bus_ref = bus_kernel_create("deine-mutter", &bus_name);
+ if (bus_ref == -ENOENT)
+ exit(EXIT_TEST_SKIP);
+
+ assert_se(bus_ref >= 0);
+
+ address = strappend("kernel:path=", bus_name);
+ assert_se(address);
+
+ r = sd_bus_new(&a);
+ assert_se(r >= 0);
+
+ r = sd_bus_new(&b);
+ assert_se(r >= 0);
+
+ r = sd_bus_set_address(a, address);
+ assert_se(r >= 0);
+
+ r = sd_bus_set_address(b, address);
+ assert_se(r >= 0);
+
+ r = sd_bus_start(a);
+ assert_se(r >= 0);
+
+ r = sd_bus_start(b);
+ assert_se(r >= 0);
+
+ log_debug("match");
+ r = sd_bus_add_match(b, match, NULL, NULL);
+ assert_se(r >= 0);
+
+ log_debug("signal");
+ r = sd_bus_emit_signal(a, path, interface, member, "s", arg0);
+ assert_se(r >= 0);
+
+ r = sd_bus_process(b, &m);
+ assert_se(r >= 0 && (good == !!m));
+
+ sd_bus_unref(a);
+ sd_bus_unref(b);
+}
+
+int main(int argc, char *argv[]) {
+ log_set_max_level(LOG_DEBUG);
+
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "", true);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path='/foo/bar/waldo'", true);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path='/foo/bar/waldo/tuut'", false);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "interface='waldo.com'", true);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "member='Piep'", true);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "member='Pi_ep'", false);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "arg0='foobar'", true);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "arg0='foo_bar'", false);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path='/foo/bar/waldo',interface='waldo.com',member='Piep',arg0='foobar'", true);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path='/foo/bar/waldo',interface='waldo.com',member='Piep',arg0='foobar2'", false);
+
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path='/foo/bar/waldo'", true);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path='/foo/bar'", false);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path='/foo'", false);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path='/'", false);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path='/foo/bar/waldo/quux'", false);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path_namespace='/foo/bar/waldo'", true);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path_namespace='/foo/bar'", true);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path_namespace='/foo'", true);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path_namespace='/'", true);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path_namespace='/quux'", false);
+
+ return 0;
+}
diff --git a/src/libsystemd-bus/test-bus-kernel.c b/src/libsystemd-bus/test-bus-kernel.c
index 1095e57e42..680dcde5b4 100644
--- a/src/libsystemd-bus/test-bus-kernel.c
+++ b/src/libsystemd-bus/test-bus-kernel.c
@@ -22,6 +22,7 @@
#include <fcntl.h>
#include "util.h"
+#include "log.h"
#include "sd-bus.h"
#include "bus-message.h"
@@ -36,6 +37,8 @@ int main(int argc, char *argv[]) {
sd_bus *a, *b;
int r, pipe_fds[2];
+ log_set_max_level(LOG_DEBUG);
+
bus_ref = bus_kernel_create("deine-mutter", &bus_name);
if (bus_ref == -ENOENT)
return EXIT_TEST_SKIP;
@@ -57,6 +60,22 @@ int main(int argc, char *argv[]) {
r = sd_bus_set_address(b, address);
assert_se(r >= 0);
+ assert_se(sd_bus_negotiate_attach_comm(a, 1) >= 0);
+ assert_se(sd_bus_negotiate_attach_exe(a, 1) >= 0);
+ assert_se(sd_bus_negotiate_attach_cmdline(a, 1) >= 0);
+ assert_se(sd_bus_negotiate_attach_cgroup(a, 1) >= 0);
+ assert_se(sd_bus_negotiate_attach_caps(a, 1) >= 0);
+ assert_se(sd_bus_negotiate_attach_selinux_context(a, 1) >= 0);
+ assert_se(sd_bus_negotiate_attach_audit(a, 1) >= 0);
+
+ assert_se(sd_bus_negotiate_attach_comm(b, 1) >= 0);
+ assert_se(sd_bus_negotiate_attach_exe(b, 1) >= 0);
+ assert_se(sd_bus_negotiate_attach_cmdline(b, 1) >= 0);
+ assert_se(sd_bus_negotiate_attach_cgroup(b, 1) >= 0);
+ assert_se(sd_bus_negotiate_attach_caps(b, 1) >= 0);
+ assert_se(sd_bus_negotiate_attach_selinux_context(b, 1) >= 0);
+ assert_se(sd_bus_negotiate_attach_audit(b, 1) >= 0);
+
r = sd_bus_start(a);
assert_se(r >= 0);
@@ -73,19 +92,8 @@ int main(int argc, char *argv[]) {
printf("unique b: %s\n", ub);
- {
- //FIXME:
- struct kdbus_cmd_match cmd_match;
-
- cmd_match.size = sizeof(cmd_match);
- cmd_match.src_id = KDBUS_MATCH_SRC_ID_ANY;
-
- r = ioctl(sd_bus_get_fd(a), KDBUS_CMD_MATCH_ADD, &cmd_match);
- assert_se(r >= 0);
-
- r = ioctl(sd_bus_get_fd(b), KDBUS_CMD_MATCH_ADD, &cmd_match);
- assert_se(r >= 0);
- }
+ r = sd_bus_add_match(b, "interface='waldo.com',member='Piep'", NULL, NULL);
+ assert_se(r >= 0);
r = sd_bus_emit_signal(a, "/foo/bar/waldo", "waldo.com", "Piep", "sss", "I am a string", "/this/is/a/path", "and.this.a.domain.name");
assert_se(r >= 0);
diff --git a/src/libsystemd-bus/test-bus-marshal.c b/src/libsystemd-bus/test-bus-marshal.c
index 20ae723fbe..ef1a77f5fc 100644
--- a/src/libsystemd-bus/test-bus-marshal.c
+++ b/src/libsystemd-bus/test-bus-marshal.c
@@ -43,6 +43,8 @@ int main(int argc, char *argv[]) {
void *buffer = NULL;
size_t sz;
char *h;
+ const int32_t integer_array[] = { -1, -2, 0, 1, 2 }, *return_array;
+ char *s;
r = sd_bus_message_new_method_call(NULL, "foobar.waldo", "/", "foobar.waldo", "Piep", &m);
assert_se(r >= 0);
@@ -77,6 +79,13 @@ int main(int argc, char *argv[]) {
r = sd_bus_message_close_container(m);
assert_se(r >= 0);
+ r = sd_bus_message_append_string_space(m, 5, &s);
+ assert_se(r >= 0);
+ strcpy(s, "hallo");
+
+ r = sd_bus_message_append_array(m, 'i', integer_array, sizeof(integer_array));
+ assert_se(r >= 0);
+
r = bus_message_seal(m, 4711);
assert_se(r >= 0);
@@ -168,6 +177,15 @@ int main(int argc, char *argv[]) {
assert_se(streq(x, "foobar"));
assert_se(streq(y, "waldo"));
+ r = sd_bus_message_read_basic(m, 's', &s);
+ assert_se(r > 0);
+ assert_se(streq(s, "hallo"));
+
+ r = sd_bus_message_read_array(m, 'i', (const void**) &return_array, &sz);
+ assert_se(r > 0);
+ assert_se(sz == sizeof(integer_array));
+ assert_se(memcmp(integer_array, return_array, sz) == 0);
+
r = sd_bus_message_peek_type(m, NULL, NULL);
assert_se(r == 0);
diff --git a/src/libsystemd-bus/test-bus-match.c b/src/libsystemd-bus/test-bus-match.c
index 9cf994009d..db977f726e 100644
--- a/src/libsystemd-bus/test-bus-match.c
+++ b/src/libsystemd-bus/test-bus-match.c
@@ -30,7 +30,7 @@
static bool mask[32];
-static int filter(sd_bus *b, int ret, sd_bus_message *m, void *userdata) {
+static int filter(sd_bus *b, sd_bus_message *m, void *userdata) {
log_info("Ran %i", PTR_TO_INT(userdata));
mask[PTR_TO_INT(userdata)] = true;
return 0;
@@ -55,6 +55,36 @@ static bool mask_contains(unsigned a[], unsigned n) {
return true;
}
+static int match_add(struct bus_match_node *root, const char *match, int value) {
+ struct bus_match_component *components = NULL;
+ unsigned n_components = 0;
+ int r;
+
+ r = bus_match_parse(match, &components, &n_components);
+ if (r < 0)
+ return r;
+
+ r = bus_match_add(root, components, n_components, filter, INT_TO_PTR(value), 0, NULL);
+ bus_match_parse_free(components, n_components);
+
+ return r;
+}
+
+static int match_remove(struct bus_match_node *root, const char *match, int value) {
+ struct bus_match_component *components = NULL;
+ unsigned n_components = 0;
+ int r;
+
+ r = bus_match_parse(match, &components, &n_components);
+ if (r < 0)
+ return r;
+
+ r = bus_match_remove(root, components, n_components, filter, INT_TO_PTR(value), 0);
+ bus_match_parse_free(components, n_components);
+
+ return r;
+}
+
int main(int argc, char *argv[]) {
struct bus_match_node root;
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
@@ -63,20 +93,20 @@ int main(int argc, char *argv[]) {
zero(root);
root.type = BUS_MATCH_ROOT;
- assert_se(bus_match_add(&root, "arg2='wal\\'do',sender='foo',type='signal',interface='bar',", filter, INT_TO_PTR(1), NULL) >= 0);
- assert_se(bus_match_add(&root, "arg2='wal\\'do2',sender='foo',type='signal',interface='bar',", filter, INT_TO_PTR(2), NULL) >= 0);
- assert_se(bus_match_add(&root, "arg3='test',sender='foo',type='signal',interface='bar',", filter, INT_TO_PTR(3), NULL) >= 0);
- assert_se(bus_match_add(&root, "arg3='test',sender='foo',type='method_call',interface='bar',", filter, INT_TO_PTR(4), NULL) >= 0);
- assert_se(bus_match_add(&root, "", filter, INT_TO_PTR(5), NULL) >= 0);
- assert_se(bus_match_add(&root, "interface='quux'", filter, INT_TO_PTR(6), NULL) >= 0);
- assert_se(bus_match_add(&root, "interface='bar'", filter, INT_TO_PTR(7), NULL) >= 0);
- assert_se(bus_match_add(&root, "member='waldo',path='/foo/bar'", filter, INT_TO_PTR(8), NULL) >= 0);
- assert_se(bus_match_add(&root, "path='/foo/bar'", filter, INT_TO_PTR(9), NULL) >= 0);
- assert_se(bus_match_add(&root, "path_namespace='/foo'", filter, INT_TO_PTR(10), NULL) >= 0);
- assert_se(bus_match_add(&root, "path_namespace='/foo/quux'", filter, INT_TO_PTR(11), NULL) >= 0);
- assert_se(bus_match_add(&root, "arg1='two'", filter, INT_TO_PTR(12), NULL) >= 0);
- assert_se(bus_match_add(&root, "member='waldo',arg2path='/prefix/'", filter, INT_TO_PTR(13), NULL) >= 0);
- assert_se(bus_match_add(&root, "member='waldo',path='/foo/bar',arg3namespace='prefix'", filter, INT_TO_PTR(14), NULL) >= 0);
+ assert_se(match_add(&root, "arg2='wal\\'do',sender='foo',type='signal',interface='bar',", 1) >= 0);
+ assert_se(match_add(&root, "arg2='wal\\'do2',sender='foo',type='signal',interface='bar',", 2) >= 0);
+ assert_se(match_add(&root, "arg3='test',sender='foo',type='signal',interface='bar',", 3) >= 0);
+ assert_se(match_add(&root, "arg3='test',sender='foo',type='method_call',interface='bar',", 4) >= 0);
+ assert_se(match_add(&root, "", 5) >= 0);
+ assert_se(match_add(&root, "interface='quux'", 6) >= 0);
+ assert_se(match_add(&root, "interface='bar'", 7) >= 0);
+ assert_se(match_add(&root, "member='waldo',path='/foo/bar'", 8) >= 0);
+ assert_se(match_add(&root, "path='/foo/bar'", 9) >= 0);
+ assert_se(match_add(&root, "path_namespace='/foo'", 10) >= 0);
+ assert_se(match_add(&root, "path_namespace='/foo/quux'", 11) >= 0);
+ assert_se(match_add(&root, "arg1='two'", 12) >= 0);
+ assert_se(match_add(&root, "member='waldo',arg2path='/prefix/'", 13) >= 0);
+ assert_se(match_add(&root, "member='waldo',path='/foo/bar',arg3namespace='prefix'", 14) >= 0);
bus_match_dump(&root, 0);
@@ -85,17 +115,17 @@ int main(int argc, char *argv[]) {
assert_se(bus_message_seal(m, 1) >= 0);
zero(mask);
- assert_se(bus_match_run(NULL, &root, 0, m) == 0);
+ assert_se(bus_match_run(NULL, &root, m) == 0);
assert_se(mask_contains((unsigned[]) { 9, 8, 7, 5, 10, 12, 13, 14 }, 8));
- assert_se(bus_match_remove(&root, "member='waldo',path='/foo/bar'", filter, INT_TO_PTR(8)) > 0);
- assert_se(bus_match_remove(&root, "arg2path='/prefix/',member='waldo'", filter, INT_TO_PTR(13)) > 0);
- assert_se(bus_match_remove(&root, "interface='barxx'", filter, INT_TO_PTR(7)) == 0);
+ assert_se(match_remove(&root, "member='waldo',path='/foo/bar'", 8) > 0);
+ assert_se(match_remove(&root, "arg2path='/prefix/',member='waldo'", 13) > 0);
+ assert_se(match_remove(&root, "interface='barxx'", 7) == 0);
bus_match_dump(&root, 0);
zero(mask);
- assert_se(bus_match_run(NULL, &root, 0, m) == 0);
+ assert_se(bus_match_run(NULL, &root, m) == 0);
assert_se(mask_contains((unsigned[]) { 9, 5, 10, 12, 14, 7 }, 6));
for (i = 0; i < _BUS_MATCH_NODE_TYPE_MAX; i++) {
diff --git a/src/libsystemd-bus/test-bus-memfd.c b/src/libsystemd-bus/test-bus-memfd.c
new file mode 100644
index 0000000000..05ef555f0d
--- /dev/null
+++ b/src/libsystemd-bus/test-bus-memfd.c
@@ -0,0 +1,174 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ 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/mman.h>
+#include <sys/uio.h>
+
+#include "log.h"
+#include "macro.h"
+#include "util.h"
+
+#include "sd-memfd.h"
+
+int main(int argc, char *argv[]) {
+ sd_memfd *m;
+ char *s;
+ uint64_t sz;
+ int r, fd;
+ FILE *f;
+ char buf[3] = {};
+ struct iovec iov[3] = {};
+ char bufv[3][3] = {};
+
+ log_set_max_level(LOG_DEBUG);
+
+ r = sd_memfd_new(&m);
+ if (r == -ENOENT)
+ return EXIT_TEST_SKIP;
+
+ r = sd_memfd_map(m, 0, 12, (void**) &s);
+ assert_se(r >= 0);
+
+ strcpy(s, "----- world");
+
+ r = sd_memfd_set_sealed(m, 1);
+ assert_se(r == -ETXTBSY);
+
+ assert_se(write(sd_memfd_get_fd(m), "he", 2) == 2);
+ assert_se(write(sd_memfd_get_fd(m), "XXX", 3) == 3);
+ assert_se(streq(s, "heXXX world"));
+
+ /* fix "hello" */
+ assert_se(lseek(sd_memfd_get_fd(m), 2, SEEK_SET) == 2);
+ assert_se(write(sd_memfd_get_fd(m), "ll", 2) == 2);
+
+ assert_se(sd_memfd_get_file(m, &f) >= 0);
+ fputc('o', f);
+ fflush(f);
+
+ /* check content */
+ assert_se(streq(s, "hello world"));
+
+ assert_se(munmap(s, 12) == 0);
+
+ r = sd_memfd_get_sealed(m);
+ assert_se(r == 0);
+
+ r = sd_memfd_get_size(m, &sz);
+ assert_se(r >= 0);
+ assert_se(sz = page_size());
+
+ /* truncate it */
+ r = sd_memfd_set_size(m, 6);
+ assert_se(r >= 0);
+
+ /* get back new value */
+ r = sd_memfd_get_size(m, &sz);
+ assert_se(r >= 0);
+ assert_se(sz == 6);
+
+ r = sd_memfd_set_sealed(m, 1);
+ assert_se(r >= 0);
+
+ r = sd_memfd_get_sealed(m);
+ assert_se(r == 1);
+
+ fd = sd_memfd_dup_fd(m);
+ assert_se(fd >= 0);
+
+ sd_memfd_free(m);
+
+ /* new sd_memfd, same underlying memfd */
+ r = sd_memfd_make(fd, &m);
+ assert_se(r >= 0);
+
+ /* we did truncate it to 6 */
+ r = sd_memfd_get_size(m, &sz);
+ assert_se(sz == 6);
+
+ /* map it, check content */
+ r = sd_memfd_map(m, 0, 12, (void **)&s);
+ assert_se(r >= 0);
+
+ /* we only see the truncated size */
+ assert_se(streq(s, "hello "));
+
+ /* it was already sealed */
+ r = sd_memfd_set_sealed(m, 1);
+ assert_se(r == -EALREADY);
+
+ /* we cannot break the seal, it is mapped */
+ r = sd_memfd_set_sealed(m, 0);
+ assert_se(r == -ETXTBSY);
+
+ /* unmap it; become the single owner */
+ assert_se(munmap(s, 12) == 0);
+
+ /* now we can do flip the sealing */
+ r = sd_memfd_set_sealed(m, 0);
+ assert_se(r == 0);
+ r = sd_memfd_get_sealed(m);
+ assert_se(r == 0);
+
+ r = sd_memfd_set_sealed(m, 1);
+ assert_se(r == 0);
+ r = sd_memfd_get_sealed(m);
+ assert_se(r == 1);
+
+ r = sd_memfd_set_sealed(m, 0);
+ assert_se(r == 0);
+ r = sd_memfd_get_sealed(m);
+ assert_se(r == 0);
+
+ /* seek at 2, read() 2 bytes */
+ assert_se(lseek(fd, 2, SEEK_SET) == 2);
+ assert_se(read(fd, buf, 2) == 2);
+
+ /* check content */
+ assert_se(memcmp(buf, "ll", 2) == 0);
+
+ /* writev it out*/
+ iov[0].iov_base = (char *)"ABC";
+ iov[0].iov_len = 3;
+ iov[1].iov_base = (char *)"DEF";
+ iov[1].iov_len = 3;
+ iov[2].iov_base = (char *)"GHI";
+ iov[2].iov_len = 3;
+ assert_se(pwritev(fd, iov, 3, 0) == 9);
+
+ /* readv it back */
+ iov[0].iov_base = bufv[0];
+ iov[0].iov_len = 3;
+ iov[1].iov_base = bufv[1];
+ iov[1].iov_len = 3;
+ iov[2].iov_base = bufv[2];
+ iov[2].iov_len = 3;
+ assert_se(preadv(fd, iov, 3, 0) == 9);
+
+ /* check content */
+ assert_se(memcmp(bufv[0], "ABC", 3) == 0);
+ assert_se(memcmp(bufv[1], "DEF", 3) == 0);
+ assert_se(memcmp(bufv[2], "GHI", 3) == 0);
+
+ sd_memfd_free(m);
+
+ return 0;
+}
diff --git a/src/libsystemd-bus/test-bus-server.c b/src/libsystemd-bus/test-bus-server.c
index a9772624f2..ef26a65d87 100644
--- a/src/libsystemd-bus/test-bus-server.c
+++ b/src/libsystemd-bus/test-bus-server.c
@@ -55,8 +55,8 @@ static void *server(void *p) {
assert_se(sd_bus_new(&bus) >= 0);
assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0);
assert_se(sd_bus_set_server(bus, 1, id) >= 0);
- assert_se(sd_bus_set_negotiate_fds(bus, c->server_negotiate_unix_fds) >= 0);
assert_se(sd_bus_set_anonymous(bus, c->server_anonymous_auth) >= 0);
+ assert_se(sd_bus_negotiate_fds(bus, c->server_negotiate_unix_fds) >= 0);
assert_se(sd_bus_start(bus) >= 0);
while (!quit) {
@@ -134,7 +134,7 @@ static int client(struct context *c) {
assert_se(sd_bus_new(&bus) >= 0);
assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0);
- assert_se(sd_bus_set_negotiate_fds(bus, c->client_negotiate_unix_fds) >= 0);
+ assert_se(sd_bus_negotiate_fds(bus, c->client_negotiate_unix_fds) >= 0);
assert_se(sd_bus_set_anonymous(bus, c->client_anonymous_auth) >= 0);
assert_se(sd_bus_start(bus) >= 0);
diff --git a/src/libsystemd-bus/test-bus-zero-copy.c b/src/libsystemd-bus/test-bus-zero-copy.c
new file mode 100644
index 0000000000..db3906e274
--- /dev/null
+++ b/src/libsystemd-bus/test-bus-zero-copy.c
@@ -0,0 +1,183 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ 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>
+#include <sys/mman.h>
+
+#include "util.h"
+#include "log.h"
+
+#include "sd-bus.h"
+#include "sd-memfd.h"
+#include "bus-message.h"
+#include "bus-error.h"
+#include "bus-kernel.h"
+
+#define FIRST_ARRAY 17
+#define SECOND_ARRAY 33
+
+#define STRING_SIZE 123
+
+int main(int argc, char *argv[]) {
+ _cleanup_free_ char *bus_name = NULL, *address = NULL;
+ uint8_t *p;
+ sd_bus *a, *b;
+ int r, bus_ref;
+ sd_bus_message *m;
+ sd_memfd *f;
+ uint64_t sz;
+ uint32_t u32;
+ size_t i, l;
+ char *s;
+
+ log_set_max_level(LOG_DEBUG);
+
+ bus_ref = bus_kernel_create("deine-mutter", &bus_name);
+ if (bus_ref == -ENOENT)
+ return EXIT_TEST_SKIP;
+
+ assert_se(bus_ref >= 0);
+
+ address = strappend("kernel:path=", bus_name);
+ assert_se(address);
+
+ r = sd_bus_new(&a);
+ assert_se(r >= 0);
+
+ r = sd_bus_new(&b);
+ assert_se(r >= 0);
+
+ r = sd_bus_set_address(a, address);
+ assert_se(r >= 0);
+
+ r = sd_bus_set_address(b, address);
+ assert_se(r >= 0);
+
+ r = sd_bus_start(a);
+ assert_se(r >= 0);
+
+ r = sd_bus_start(b);
+ assert_se(r >= 0);
+
+ r = sd_bus_message_new_method_call(b, ":1.1", "/a/path", "an.inter.face", "AMethod", &m);
+ assert_se(r >= 0);
+
+ r = sd_bus_message_open_container(m, 'r', "aysay");
+ assert_se(r >= 0);
+
+ r = sd_bus_message_append_array_space(m, 'y', FIRST_ARRAY, (void**) &p);
+ assert_se(r >= 0);
+
+ memset(p, 'L', FIRST_ARRAY);
+
+ r = sd_memfd_new_and_map(&f, STRING_SIZE, (void**) &s);
+ assert_se(r >= 0);
+
+ for (i = 0; i < STRING_SIZE-1; i++)
+ s[i] = '0' + (i % 10);
+
+ s[STRING_SIZE-1] = 0;
+ munmap(s, STRING_SIZE);
+
+ r = sd_memfd_get_size(f, &sz);
+ assert_se(r >= 0);
+ assert_se(sz == STRING_SIZE);
+
+ r = sd_bus_message_append_string_memfd(m, f);
+ assert_se(r >= 0);
+
+ sd_memfd_free(f);
+
+ r = sd_memfd_new_and_map(&f, SECOND_ARRAY, (void**) &p);
+ assert_se(r >= 0);
+
+ memset(p, 'P', SECOND_ARRAY);
+ munmap(p, SECOND_ARRAY);
+
+ r = sd_memfd_get_size(f, &sz);
+ assert_se(r >= 0);
+ assert_se(sz == SECOND_ARRAY);
+
+ r = sd_bus_message_append_array_memfd(m, 'y', f);
+ assert_se(r >= 0);
+
+ sd_memfd_free(f);
+
+ r = sd_bus_message_close_container(m);
+ assert_se(r >= 0);
+
+ r = sd_bus_message_append(m, "u", 4711);
+ assert_se(r >= 0);
+
+ r = bus_message_seal(m, 55);
+ assert_se(r >= 0);
+
+ bus_message_dump(m);
+
+ r = sd_bus_send(b, m, NULL);
+ assert_se(r >= 0);
+
+ sd_bus_message_unref(m);
+
+ r = sd_bus_process(a, &m);
+ assert_se(r > 0);
+
+ bus_message_dump(m);
+ sd_bus_message_rewind(m, true);
+
+ r = sd_bus_message_enter_container(m, 'r', "aysay");
+ assert_se(r > 0);
+
+ r = sd_bus_message_read_array(m, 'y', (const void**) &p, &l);
+ assert_se(r > 0);
+ assert_se(l == FIRST_ARRAY);
+
+ for (i = 0; i < l; i++)
+ assert_se(p[i] == 'L');
+
+ r = sd_bus_message_read(m, "s", &s);
+ assert_se(r > 0);
+
+ for (i = 0; i < STRING_SIZE-1; i++)
+ assert_se(s[i] == (char) ('0' + (i % 10)));
+ assert_se(s[STRING_SIZE-1] == 0);
+
+ r = sd_bus_message_read_array(m, 'y', (const void**) &p, &l);
+ assert_se(r > 0);
+ assert_se(l == SECOND_ARRAY);
+
+ for (i = 0; i < l; i++)
+ assert_se(p[i] == 'P');
+
+ r = sd_bus_message_exit_container(m);
+ assert_se(r > 0);
+
+ r = sd_bus_message_read(m, "u", &u32);
+ assert_se(r > 0);
+ assert_se(u32 == 4711);
+
+ sd_bus_message_unref(m);
+
+ sd_bus_unref(a);
+ sd_bus_unref(b);
+
+ return 0;
+}
diff --git a/src/libudev/libudev-device.c b/src/libudev/libudev-device.c
index 6bb2e41510..a644904757 100644
--- a/src/libudev/libudev-device.c
+++ b/src/libudev/libudev-device.c
@@ -42,7 +42,7 @@
*
* Representation of kernel sys devices. Devices are uniquely identified
* by their syspath, every device has exactly one path in the kernel sys
- * filesystem. Devices usually belong to a kernel subsystem, and and have
+ * filesystem. Devices usually belong to a kernel subsystem, and have
* a unique name inside that subsystem.
*/
@@ -780,7 +780,7 @@ _public_ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char
*
* Returns: a new udev device, or #NULL, if it does not exist
**/
-_public_ struct udev_device *udev_device_new_from_device_id(struct udev *udev, char *id)
+_public_ struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id)
{
char type;
int maj, min;
diff --git a/src/libudev/libudev-enumerate.c b/src/libudev/libudev-enumerate.c
index 5ccaabdc6c..8146f27e4f 100644
--- a/src/libudev/libudev-enumerate.c
+++ b/src/libudev/libudev-enumerate.c
@@ -270,8 +270,9 @@ _public_ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enume
return NULL;
if (!udev_enumerate->devices_uptodate) {
unsigned int i;
+ int move_later = -1;
unsigned int max;
- struct syspath *prev = NULL, *move_later = NULL;
+ struct syspath *prev = NULL;
size_t move_later_prefix = 0;
udev_list_cleanup(&udev_enumerate->devices_list);
@@ -299,27 +300,29 @@ _public_ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enume
/* skip to be delayed devices, and move the to
* the point where the prefix changes. We can
* only move one item at a time. */
- if (!move_later) {
+ if (move_later == -1) {
move_later_prefix = devices_delay_later(udev_enumerate->udev, entry->syspath);
if (move_later_prefix > 0) {
- move_later = entry;
+ move_later = i;
continue;
}
}
- if (move_later &&
- !strneq(entry->syspath, move_later->syspath, move_later_prefix)) {
+ if ((move_later >= 0) &&
+ !strneq(entry->syspath, udev_enumerate->devices[move_later].syspath, move_later_prefix)) {
- udev_list_entry_add(&udev_enumerate->devices_list, move_later->syspath, NULL);
- move_later = NULL;
+ udev_list_entry_add(&udev_enumerate->devices_list,
+ udev_enumerate->devices[move_later].syspath, NULL);
+ move_later = -1;
}
udev_list_entry_add(&udev_enumerate->devices_list, entry->syspath, NULL);
}
- if (move_later)
- udev_list_entry_add(&udev_enumerate->devices_list, move_later->syspath, NULL);
+ if (move_later >= 0)
+ udev_list_entry_add(&udev_enumerate->devices_list,
+ udev_enumerate->devices[move_later].syspath, NULL);
/* add and cleanup delayed devices from end of list */
for (i = max; i < udev_enumerate->devices_cur; i++) {
@@ -718,10 +721,14 @@ static bool match_subsystem(struct udev_enumerate *udev_enumerate, const char *s
{
struct udev_list_entry *list_entry;
+ if (!subsystem)
+ return false;
+
udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->subsystem_nomatch_list)) {
if (fnmatch(udev_list_entry_get_name(list_entry), subsystem, 0) == 0)
return false;
}
+
if (udev_list_get_entry(&udev_enumerate->subsystem_match_list) != NULL) {
udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->subsystem_match_list)) {
if (fnmatch(udev_list_entry_get_name(list_entry), subsystem, 0) == 0)
@@ -729,6 +736,7 @@ static bool match_subsystem(struct udev_enumerate *udev_enumerate, const char *s
}
return false;
}
+
return true;
}
@@ -826,23 +834,27 @@ nomatch:
static int parent_add_child(struct udev_enumerate *enumerate, const char *path)
{
struct udev_device *dev;
+ int r = 0;
dev = udev_device_new_from_syspath(enumerate->udev, path);
if (dev == NULL)
return -ENODEV;
if (!match_subsystem(enumerate, udev_device_get_subsystem(dev)))
- return 0;
+ goto nomatch;
if (!match_sysname(enumerate, udev_device_get_sysname(dev)))
- return 0;
+ goto nomatch;
if (!match_property(enumerate, dev))
- return 0;
+ goto nomatch;
if (!match_sysattr(enumerate, dev))
- return 0;
+ goto nomatch;
syspath_add(enumerate, udev_device_get_syspath(dev));
+ r = 1;
+
+nomatch:
udev_device_unref(dev);
- return 1;
+ return r;
}
static int parent_crawl_children(struct udev_enumerate *enumerate, const char *path, int maxdepth)
diff --git a/src/libudev/libudev-hwdb.c b/src/libudev/libudev-hwdb.c
index 42ab6d9a6b..de1cb83188 100644
--- a/src/libudev/libudev-hwdb.c
+++ b/src/libudev/libudev-hwdb.c
@@ -140,9 +140,13 @@ static const struct trie_node_f *node_lookup_f(struct udev_hwdb *hwdb, const str
}
static int hwdb_add_property(struct udev_hwdb *hwdb, const char *key, const char *value) {
- /* TODO: add sub-matches (+) against DMI data */
+ /*
+ * Silently ignore all properties which do not start with a
+ * space; future extensions might use additional prefixes.
+ */
if (key[0] != ' ')
return 0;
+
if (udev_list_entry_add(&hwdb->properties_list, key+1, value) == NULL)
return -ENOMEM;
return 0;
@@ -300,11 +304,11 @@ _public_ struct udev_hwdb *udev_hwdb_new(struct udev *udev) {
}
log_debug("=== trie on-disk ===\n");
- log_debug("tool version: %llu", (unsigned long long)le64toh(hwdb->head->tool_version));
- log_debug("file size: %8llu bytes\n", (unsigned long long)hwdb->st.st_size);
- log_debug("header size %8llu bytes\n", (unsigned long long)le64toh(hwdb->head->header_size));
- log_debug("strings %8llu bytes\n", (unsigned long long)le64toh(hwdb->head->strings_len));
- log_debug("nodes %8llu bytes\n", (unsigned long long)le64toh(hwdb->head->nodes_len));
+ log_debug("tool version: %"PRIu64, le64toh(hwdb->head->tool_version));
+ log_debug("file size: %8llu bytes\n", (unsigned long long) hwdb->st.st_size);
+ log_debug("header size %8"PRIu64" bytes\n", le64toh(hwdb->head->header_size));
+ log_debug("strings %8"PRIu64" bytes\n", le64toh(hwdb->head->strings_len));
+ log_debug("nodes %8"PRIu64" bytes\n", le64toh(hwdb->head->nodes_len));
return hwdb;
}
@@ -354,7 +358,7 @@ bool udev_hwdb_validate(struct udev_hwdb *hwdb) {
return false;
if (!hwdb->f)
return false;
- if (fstat(fileno(hwdb->f), &st) < 0)
+ if (stat("/etc/udev/hwdb.bin", &st) < 0)
return true;
if (timespec_load(&hwdb->st.st_mtim) != timespec_load(&st.st_mtim))
return true;
diff --git a/src/libudev/libudev-util.c b/src/libudev/libudev-util.c
index 714dc50ae9..b5b9db67fc 100644
--- a/src/libudev/libudev-util.c
+++ b/src/libudev/libudev-util.c
@@ -32,8 +32,10 @@
#include <sys/stat.h>
#include <sys/param.h>
+#include "device-nodes.h"
#include "libudev.h"
#include "libudev-private.h"
+#include "utf8.h"
/**
* SECTION:libudev-util
@@ -306,129 +308,6 @@ void util_remove_trailing_chars(char *path, char c)
path[--len] = '\0';
}
-/* count of characters used to encode one unicode char */
-static int utf8_encoded_expected_len(const char *str)
-{
- unsigned char c = (unsigned char)str[0];
-
- if (c < 0x80)
- return 1;
- if ((c & 0xe0) == 0xc0)
- return 2;
- if ((c & 0xf0) == 0xe0)
- return 3;
- if ((c & 0xf8) == 0xf0)
- return 4;
- if ((c & 0xfc) == 0xf8)
- return 5;
- if ((c & 0xfe) == 0xfc)
- return 6;
- return 0;
-}
-
-/* decode one unicode char */
-static int utf8_encoded_to_unichar(const char *str)
-{
- int unichar;
- int len;
- int i;
-
- len = utf8_encoded_expected_len(str);
- switch (len) {
- case 1:
- return (int)str[0];
- case 2:
- unichar = str[0] & 0x1f;
- break;
- case 3:
- unichar = (int)str[0] & 0x0f;
- break;
- case 4:
- unichar = (int)str[0] & 0x07;
- break;
- case 5:
- unichar = (int)str[0] & 0x03;
- break;
- case 6:
- unichar = (int)str[0] & 0x01;
- break;
- default:
- return -1;
- }
-
- for (i = 1; i < len; i++) {
- if (((int)str[i] & 0xc0) != 0x80)
- return -1;
- unichar <<= 6;
- unichar |= (int)str[i] & 0x3f;
- }
-
- return unichar;
-}
-
-/* expected size used to encode one unicode char */
-static int utf8_unichar_to_encoded_len(int unichar)
-{
- if (unichar < 0x80)
- return 1;
- if (unichar < 0x800)
- return 2;
- if (unichar < 0x10000)
- return 3;
- if (unichar < 0x200000)
- return 4;
- if (unichar < 0x4000000)
- return 5;
- return 6;
-}
-
-/* check if unicode char has a valid numeric range */
-static int utf8_unichar_valid_range(int unichar)
-{
- if (unichar > 0x10ffff)
- return 0;
- if ((unichar & 0xfffff800) == 0xd800)
- return 0;
- if ((unichar > 0xfdcf) && (unichar < 0xfdf0))
- return 0;
- if ((unichar & 0xffff) == 0xffff)
- return 0;
- return 1;
-}
-
-/* validate one encoded unicode char and return its length */
-static int utf8_encoded_valid_unichar(const char *str)
-{
- int len;
- int unichar;
- int i;
-
- len = utf8_encoded_expected_len(str);
- if (len == 0)
- return -1;
-
- /* ascii is valid */
- if (len == 1)
- return 1;
-
- /* check if expected encoded chars are available */
- for (i = 0; i < len; i++)
- if ((str[i] & 0x80) != 0x80)
- return -1;
-
- unichar = utf8_encoded_to_unichar(str);
-
- /* check if encoded length matches encoded value */
- if (utf8_unichar_to_encoded_len(unichar) != len)
- return -1;
-
- /* check if value has valid range */
- if (!utf8_unichar_valid_range(unichar))
- return -1;
-
- return len;
-}
-
int util_replace_whitespace(const char *str, char *to, size_t len)
{
size_t i, j;
@@ -457,17 +336,6 @@ int util_replace_whitespace(const char *str, char *to, size_t len)
return 0;
}
-static int is_whitelisted(char c, const char *white)
-{
- if ((c >= '0' && c <= '9') ||
- (c >= 'A' && c <= 'Z') ||
- (c >= 'a' && c <= 'z') ||
- strchr("#+-.:=@_", c) != NULL ||
- (white != NULL && strchr(white, c) != NULL))
- return 1;
- return 0;
-}
-
/* allow chars in whitelist, plain ascii, hex-escaping and valid utf8 */
int util_replace_chars(char *str, const char *white)
{
@@ -477,7 +345,7 @@ int util_replace_chars(char *str, const char *white)
while (str[i] != '\0') {
int len;
- if (is_whitelisted(str[i], white)) {
+ if (whitelisted_char_for_devnode(str[i], white)) {
i++;
continue;
}
@@ -525,39 +393,7 @@ int util_replace_chars(char *str, const char *white)
**/
_public_ int udev_util_encode_string(const char *str, char *str_enc, size_t len)
{
- size_t i, j;
-
- if (str == NULL || str_enc == NULL)
- return -1;
-
- for (i = 0, j = 0; str[i] != '\0'; i++) {
- int seqlen;
-
- seqlen = utf8_encoded_valid_unichar(&str[i]);
- if (seqlen > 1) {
- if (len-j < (size_t)seqlen)
- goto err;
- memcpy(&str_enc[j], &str[i], seqlen);
- j += seqlen;
- i += (seqlen-1);
- } else if (str[i] == '\\' || !is_whitelisted(str[i], NULL)) {
- if (len-j < 4)
- goto err;
- sprintf(&str_enc[j], "\\x%02x", (unsigned char) str[i]);
- j += 4;
- } else {
- if (len-j < 1)
- goto err;
- str_enc[j] = str[i];
- j++;
- }
- }
- if (len-j < 1)
- goto err;
- str_enc[j] = '\0';
- return 0;
-err:
- return -1;
+ return encode_devnode_name(str, str_enc, len);
}
/*
diff --git a/src/libudev/libudev.h b/src/libudev/libudev.h
index 61567b1d67..b9b8f13e44 100644
--- a/src/libudev/libudev.h
+++ b/src/libudev/libudev.h
@@ -81,7 +81,7 @@ struct udev *udev_device_get_udev(struct udev_device *udev_device);
struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath);
struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum);
struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname);
-struct udev_device *udev_device_new_from_device_id(struct udev *udev, char *id);
+struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id);
struct udev_device *udev_device_new_from_environment(struct udev *udev);
/* udev_device_get_parent_*() does not take a reference on the returned device, it is automatically unref'd with the parent */
struct udev_device *udev_device_get_parent(struct udev_device *udev_device);
diff --git a/src/libudev/libudev.sym b/src/libudev/libudev.sym
index 8e09430aec..1e6f885141 100644
--- a/src/libudev/libudev.sym
+++ b/src/libudev/libudev.sym
@@ -109,5 +109,6 @@ global:
} LIBUDEV_189;
LIBUDEV_199 {
+global:
udev_device_set_sysattr_value;
} LIBUDEV_196;
diff --git a/src/locale/localectl.c b/src/locale/localectl.c
index 50250c4b47..8259c0af5f 100644
--- a/src/locale/localectl.c
+++ b/src/locale/localectl.c
@@ -46,7 +46,8 @@ static enum transport {
TRANSPORT_POLKIT
} arg_transport = TRANSPORT_NORMAL;
static bool arg_ask_password = true;
-static const char *arg_host = NULL;
+static char *arg_host = NULL;
+static char *arg_user = NULL;
static bool arg_convert = true;
static void pager_open_if_enabled(void) {
@@ -223,7 +224,7 @@ static int show_status(DBusConnection *bus, char **args, unsigned n) {
static int set_locale(DBusConnection *bus, char **args, unsigned n) {
_cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
- dbus_bool_t interactive = true;
+ dbus_bool_t interactive = arg_ask_password;
DBusError error;
DBusMessageIter iter;
int r;
@@ -459,7 +460,7 @@ static int list_locales(DBusConnection *bus, char **args, unsigned n) {
static int set_vconsole_keymap(DBusConnection *bus, char **args, unsigned n) {
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- dbus_bool_t interactive = true, b;
+ dbus_bool_t interactive = arg_ask_password, b;
const char *map, *toggle_map;
assert(bus);
@@ -537,6 +538,7 @@ static int list_vconsole_keymaps(DBusConnection *bus, char **args, unsigned n) {
if (!keymaps)
return log_oom();
+ nftw("/usr/share/keymaps/", nftw_cb, 20, FTW_MOUNT|FTW_PHYS);
nftw("/usr/share/kbd/keymaps/", nftw_cb, 20, FTW_MOUNT|FTW_PHYS);
nftw("/usr/lib/kbd/keymaps/", nftw_cb, 20, FTW_MOUNT|FTW_PHYS);
nftw("/lib/kbd/keymaps/", nftw_cb, 20, FTW_MOUNT|FTW_PHYS);
@@ -565,7 +567,7 @@ static int list_vconsole_keymaps(DBusConnection *bus, char **args, unsigned n) {
static int set_x11_keymap(DBusConnection *bus, char **args, unsigned n) {
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- dbus_bool_t interactive = true, b;
+ dbus_bool_t interactive = arg_ask_password, b;
const char *layout, *model, *variant, *options;
assert(bus);
@@ -712,6 +714,7 @@ static int help(void) {
" --version Show package version\n"
" --no-convert Don't convert keyboard mappings\n"
" --no-pager Do not pipe output into a pager\n"
+ " -P --privileged Acquire privileges before execution\n"
" --no-ask-password Do not prompt for password\n"
" -H --host=[USER@]HOST Operate on remote host\n\n"
"Commands:\n"
@@ -757,7 +760,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "has:H:P", options, NULL)) >= 0) {
+ while ((c = getopt_long(argc, argv, "hH:P", options, NULL)) >= 0) {
switch (c) {
@@ -776,7 +779,7 @@ static int parse_argv(int argc, char *argv[]) {
case 'H':
arg_transport = TRANSPORT_SSH;
- arg_host = optarg;
+ parse_user_at_host(optarg, &arg_user, &arg_host);
break;
case ARG_NO_CONVERT:
@@ -787,6 +790,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_no_pager = true;
break;
+ case ARG_NO_ASK_PASSWORD:
+ arg_ask_password = false;
+ break;
+
case '?':
return -EINVAL;
diff --git a/src/login/70-uaccess.rules b/src/login/70-uaccess.rules
index a118f8e887..01484c95f1 100644
--- a/src/login/70-uaccess.rules
+++ b/src/login/70-uaccess.rules
@@ -25,7 +25,8 @@ 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
SUBSYSTEM=="firewire", ENV{ID_FFADO}=="1", TAG+="uaccess"
diff --git a/src/login/libsystemd-login.sym b/src/login/libsystemd-login.sym
index 925fb91095..54aa91c609 100644
--- a/src/login/libsystemd-login.sym
+++ b/src/login/libsystemd-login.sym
@@ -75,3 +75,13 @@ LIBSYSTEMD_LOGIN_203 {
global:
sd_get_machine_names;
} LIBSYSTEMD_LOGIN_202;
+
+LIBSYSTEMD_LOGIN_205 {
+global:
+ sd_pid_get_slice;
+} LIBSYSTEMD_LOGIN_203;
+
+LIBSYSTEMD_LOGIN_207 {
+global:
+ sd_session_get_vt;
+} LIBSYSTEMD_LOGIN_205;
diff --git a/src/login/login-shared.c b/src/login/login-shared.c
new file mode 100644
index 0000000000..054c77503b
--- /dev/null
+++ b/src/login/login-shared.c
@@ -0,0 +1,29 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ 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 "login-shared.h"
+#include "def.h"
+
+bool session_id_valid(const char *id) {
+ assert(id);
+
+ return id[0] && id[strspn(id, LETTERS DIGITS)] == '\0';
+}
diff --git a/src/login/login-shared.h b/src/login/login-shared.h
new file mode 100644
index 0000000000..b2787c9c62
--- /dev/null
+++ b/src/login/login-shared.h
@@ -0,0 +1,24 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ 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>
+
+bool session_id_valid(const char *id);
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index caaea8dfaa..736db6a11b 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -34,8 +34,10 @@
#include "dbus-common.h"
#include "build.h"
#include "strv.h"
-#include "cgroup-show.h"
+#include "unit-name.h"
#include "sysfs-show.h"
+#include "cgroup-show.h"
+#include "cgroup-util.h"
#include "spawn-polkit-agent.h"
static char **arg_property = NULL;
@@ -50,7 +52,8 @@ static enum transport {
TRANSPORT_POLKIT
} arg_transport = TRANSPORT_NORMAL;
static bool arg_ask_password = true;
-static const char *arg_host = NULL;
+static char *arg_host = NULL;
+static char *arg_user = NULL;
static void pager_open_if_enabled(void) {
@@ -260,12 +263,82 @@ static int list_seats(DBusConnection *bus, char **args, unsigned n) {
return 0;
}
+static int show_unit_cgroup(DBusConnection *bus, const char *interface, const char *unit, pid_t leader) {
+ const char *property = "ControlGroup";
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ _cleanup_free_ char *path = NULL;
+ DBusMessageIter iter, sub;
+ const char *cgroup;
+ DBusError error;
+ int r, output_flags;
+ unsigned c;
+
+ assert(bus);
+ assert(unit);
+
+ if (arg_transport == TRANSPORT_SSH)
+ return 0;
+
+ path = unit_dbus_path_from_name(unit);
+ if (!path)
+ return log_oom();
+
+ r = bus_method_call_with_reply(
+ bus,
+ "org.freedesktop.systemd1",
+ path,
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ &reply,
+ &error,
+ DBUS_TYPE_STRING, &interface,
+ DBUS_TYPE_STRING, &property,
+ DBUS_TYPE_INVALID);
+ if (r < 0) {
+ log_error("Failed to query ControlGroup: %s", bus_error(&error, r));
+ dbus_error_free(&error);
+ return r;
+ }
+
+ if (!dbus_message_iter_init(reply, &iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
+ log_error("Failed to parse reply.");
+ return -EINVAL;
+ }
+
+ dbus_message_iter_recurse(&iter, &sub);
+ if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
+ log_error("Failed to parse reply.");
+ return -EINVAL;
+ }
+
+ dbus_message_iter_get_basic(&sub, &cgroup);
+
+ if (isempty(cgroup))
+ return 0;
+
+ if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
+ return 0;
+
+ output_flags =
+ arg_all * OUTPUT_SHOW_ALL |
+ arg_full * OUTPUT_FULL_WIDTH;
+
+ c = columns();
+ if (c > 18)
+ c -= 18;
+ else
+ c = 0;
+
+ show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, output_flags);
+ return 0;
+}
+
typedef struct SessionStatusInfo {
const char *id;
uid_t uid;
const char *name;
usec_t timestamp;
- const char *default_control_group;
int vtnr;
const char *seat;
const char *tty;
@@ -278,16 +351,17 @@ typedef struct SessionStatusInfo {
const char *type;
const char *class;
const char *state;
+ const char *scope;
} SessionStatusInfo;
typedef struct UserStatusInfo {
uid_t uid;
const char *name;
usec_t timestamp;
- const char *default_control_group;
const char *state;
char **sessions;
const char *display;
+ const char *slice;
} UserStatusInfo;
typedef struct SeatStatusInfo {
@@ -296,7 +370,7 @@ typedef struct SeatStatusInfo {
char **sessions;
} SeatStatusInfo;
-static void print_session_status_info(SessionStatusInfo *i) {
+static void print_session_status_info(DBusConnection *bus, SessionStatusInfo *i) {
char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
char since2[FORMAT_TIMESTAMP_MAX], *s2;
assert(i);
@@ -317,15 +391,13 @@ static void print_session_status_info(SessionStatusInfo *i) {
printf("\t Since: %s\n", s2);
if (i->leader > 0) {
- char *t = NULL;
+ _cleanup_free_ char *t = NULL;
printf("\t Leader: %u", (unsigned) i->leader);
get_process_comm(i->leader, &t);
- if (t) {
+ if (t)
printf(" (%s)", t);
- free(t);
- }
printf("\n");
}
@@ -374,30 +446,13 @@ static void print_session_status_info(SessionStatusInfo *i) {
if (i->state)
printf("\t State: %s\n", i->state);
- if (i->default_control_group) {
- unsigned c;
- int output_flags =
- arg_all * OUTPUT_SHOW_ALL |
- arg_full * OUTPUT_FULL_WIDTH;
-
- printf("\t CGroup: %s\n", i->default_control_group);
-
- if (arg_transport != TRANSPORT_SSH) {
- c = columns();
- if (c > 18)
- c -= 18;
- else
- c = 0;
-
- show_cgroup_and_extra_by_spec(i->default_control_group,
- "\t\t ", c, false, &i->leader,
- i->leader > 0 ? 1 : 0,
- output_flags);
- }
+ if (i->scope) {
+ printf("\t Unit: %s\n", i->scope);
+ show_unit_cgroup(bus, "org.freedesktop.systemd1.Scope", i->scope, i->leader);
}
}
-static void print_user_status_info(UserStatusInfo *i) {
+static void print_user_status_info(DBusConnection *bus, UserStatusInfo *i) {
char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
char since2[FORMAT_TIMESTAMP_MAX], *s2;
assert(i);
@@ -418,6 +473,7 @@ static void print_user_status_info(UserStatusInfo *i) {
if (!isempty(i->state))
printf("\t State: %s\n", i->state);
+
if (!strv_isempty(i->sessions)) {
char **l;
printf("\tSessions:");
@@ -432,24 +488,9 @@ static void print_user_status_info(UserStatusInfo *i) {
printf("\n");
}
- if (i->default_control_group) {
- unsigned c;
- int output_flags =
- arg_all * OUTPUT_SHOW_ALL |
- arg_full * OUTPUT_FULL_WIDTH;
-
- printf("\t CGroup: %s\n", i->default_control_group);
-
- if (arg_transport != TRANSPORT_SSH) {
- c = columns();
- if (c > 18)
- c -= 18;
- else
- c = 0;
-
- show_cgroup_by_path(i->default_control_group, "\t\t ",
- c, false, output_flags);
- }
+ if (i->slice) {
+ printf("\t Unit: %s\n", i->slice);
+ show_unit_cgroup(bus, "org.freedesktop.systemd1.Slice", i->slice, 0);
}
}
@@ -504,8 +545,6 @@ static int status_property_session(const char *name, DBusMessageIter *iter, Sess
i->id = s;
else if (streq(name, "Name"))
i->name = s;
- else if (streq(name, "DefaultControlGroup"))
- i->default_control_group = s;
else if (streq(name, "TTY"))
i->tty = s;
else if (streq(name, "Display"))
@@ -520,6 +559,8 @@ static int status_property_session(const char *name, DBusMessageIter *iter, Sess
i->type = s;
else if (streq(name, "Class"))
i->class = s;
+ else if (streq(name, "Scope"))
+ i->scope = s;
else if (streq(name, "State"))
i->state = s;
}
@@ -603,8 +644,8 @@ static int status_property_user(const char *name, DBusMessageIter *iter, UserSta
if (!isempty(s)) {
if (streq(name, "Name"))
i->name = s;
- else if (streq(name, "DefaultControlGroup"))
- i->default_control_group = s;
+ else if (streq(name, "Slice"))
+ i->slice = s;
else if (streq(name, "State"))
i->state = s;
}
@@ -913,9 +954,9 @@ static int show_one(const char *verb, DBusConnection *bus, const char *path, boo
if (!show_properties) {
if (strstr(verb, "session"))
- print_session_status_info(&session_info);
+ print_session_status_info(bus, &session_info);
else if (strstr(verb, "user"))
- print_user_status_info(&user_info);
+ print_user_status_info(bus, &user_info);
else
print_seat_status_info(&seat_info);
}
@@ -980,7 +1021,7 @@ static int show(DBusConnection *bus, char **args, unsigned n) {
}
u = (uint32_t) uid;
- ret = bus_method_call_with_reply (
+ ret = bus_method_call_with_reply(
bus,
"org.freedesktop.login1",
"/org/freedesktop/login1",
@@ -990,9 +1031,10 @@ static int show(DBusConnection *bus, char **args, unsigned n) {
NULL,
DBUS_TYPE_UINT32, &u,
DBUS_TYPE_INVALID);
+
} else {
- ret = bus_method_call_with_reply (
+ ret = bus_method_call_with_reply(
bus,
"org.freedesktop.login1",
"/org/freedesktop/login1",
@@ -1002,8 +1044,10 @@ static int show(DBusConnection *bus, char **args, unsigned n) {
NULL,
DBUS_TYPE_STRING, &args[i],
DBUS_TYPE_INVALID);
+
}
- if (ret)
+
+ if (ret < 0)
goto finish;
if (!dbus_message_get_args(reply, &error,
@@ -1296,7 +1340,7 @@ static int help(void) {
" -p --property=NAME Show only properties by this name\n"
" -a --all Show all properties, including empty ones\n"
" --kill-who=WHO Who to send signal to\n"
- " --full Do not ellipsize output\n"
+ " -l --full Do not ellipsize output\n"
" -s --signal=SIGNAL Which signal to send\n"
" --no-ask-password Don't prompt for password\n"
" -H --host=[USER@]HOST Show information for remote host\n"
@@ -1338,7 +1382,6 @@ static int parse_argv(int argc, char *argv[]) {
ARG_NO_PAGER,
ARG_KILL_WHO,
ARG_NO_ASK_PASSWORD,
- ARG_FULL,
};
static const struct option options[] = {
@@ -1346,13 +1389,13 @@ static int parse_argv(int argc, char *argv[]) {
{ "version", no_argument, NULL, ARG_VERSION },
{ "property", required_argument, NULL, 'p' },
{ "all", no_argument, NULL, 'a' },
+ { "full", no_argument, NULL, 'l' },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
{ "kill-who", required_argument, NULL, ARG_KILL_WHO },
{ "signal", required_argument, NULL, 's' },
{ "host", required_argument, NULL, 'H' },
{ "privileged", no_argument, NULL, 'P' },
{ "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
- { "full", no_argument, NULL, ARG_FULL },
{ NULL, 0, NULL, 0 }
};
@@ -1361,7 +1404,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "hp:as:H:P", options, NULL)) >= 0) {
+ while ((c = getopt_long(argc, argv, "hp:als:H:P", options, NULL)) >= 0) {
switch (c) {
@@ -1395,6 +1438,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_all = true;
break;
+ case 'l':
+ arg_full = true;
+ break;
+
case ARG_NO_PAGER:
arg_no_pager = true;
break;
@@ -1421,11 +1468,7 @@ static int parse_argv(int argc, char *argv[]) {
case 'H':
arg_transport = TRANSPORT_SSH;
- arg_host = optarg;
- break;
-
- case ARG_FULL:
- arg_full = true;
+ parse_user_at_host(optarg, &arg_user, &arg_host);
break;
case '?':
@@ -1452,29 +1495,29 @@ static int loginctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
const int argc;
int (* const dispatch)(DBusConnection *bus, char **args, unsigned n);
} verbs[] = {
- { "list-sessions", LESS, 1, list_sessions },
- { "session-status", MORE, 2, show },
- { "show-session", MORE, 1, show },
- { "activate", EQUAL, 2, activate },
- { "lock-session", MORE, 2, activate },
- { "unlock-session", MORE, 2, activate },
- { "lock-sessions", EQUAL, 1, lock_sessions },
- { "unlock-sessions", EQUAL, 1, lock_sessions },
- { "terminate-session", MORE, 2, activate },
- { "kill-session", MORE, 2, kill_session },
- { "list-users", EQUAL, 1, list_users },
- { "user-status", MORE, 2, show },
- { "show-user", MORE, 1, show },
- { "enable-linger", MORE, 2, enable_linger },
- { "disable-linger", MORE, 2, enable_linger },
- { "terminate-user", MORE, 2, terminate_user },
- { "kill-user", MORE, 2, kill_user },
- { "list-seats", EQUAL, 1, list_seats },
- { "seat-status", MORE, 2, show },
- { "show-seat", MORE, 1, show },
- { "attach", MORE, 3, attach },
- { "flush-devices", EQUAL, 1, flush_devices },
- { "terminate-seat", MORE, 2, terminate_seat },
+ { "list-sessions", LESS, 1, list_sessions },
+ { "session-status", MORE, 2, show },
+ { "show-session", MORE, 1, show },
+ { "activate", EQUAL, 2, activate },
+ { "lock-session", MORE, 2, activate },
+ { "unlock-session", MORE, 2, activate },
+ { "lock-sessions", EQUAL, 1, lock_sessions },
+ { "unlock-sessions", EQUAL, 1, lock_sessions },
+ { "terminate-session", MORE, 2, activate },
+ { "kill-session", MORE, 2, kill_session },
+ { "list-users", EQUAL, 1, list_users },
+ { "user-status", MORE, 2, show },
+ { "show-user", MORE, 1, show },
+ { "enable-linger", MORE, 2, enable_linger },
+ { "disable-linger", MORE, 2, enable_linger },
+ { "terminate-user", MORE, 2, terminate_user },
+ { "kill-user", MORE, 2, kill_user },
+ { "list-seats", EQUAL, 1, list_seats },
+ { "seat-status", MORE, 2, show },
+ { "show-seat", MORE, 1, show },
+ { "attach", MORE, 3, attach },
+ { "flush-devices", EQUAL, 1, flush_devices },
+ { "terminate-seat", MORE, 2, terminate_seat },
};
int left;
diff --git a/src/login/logind-acl.c b/src/login/logind-acl.c
index cb045a9928..25abcbcf80 100644
--- a/src/login/logind-acl.c
+++ b/src/login/logind-acl.c
@@ -28,6 +28,7 @@
#include "logind-acl.h"
#include "util.h"
#include "acl-util.h"
+#include "set.h"
static int flush_acl(acl_t acl) {
acl_entry_t i;
@@ -179,23 +180,34 @@ int devnode_acl_all(struct udev *udev,
struct udev_list_entry *item = NULL, *first = NULL;
struct udev_enumerate *e;
+ Set *nodes;
+ Iterator i;
+ char *n;
+ _cleanup_closedir_ DIR *dir = NULL;
+ struct dirent *dent;
int r;
assert(udev);
- if (isempty(seat))
- seat = "seat0";
+ nodes = set_new(string_hash_func, string_compare_func);
+ if (!nodes) {
+ return -ENOMEM;
+ }
e = udev_enumerate_new(udev);
- if (!e)
- return -ENOMEM;
+ if (!e) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ if (isempty(seat))
+ seat = "seat0";
/* We can only match by one tag in libudev. We choose
* "uaccess" for that. If we could match for two tags here we
* could add the seat name as second match tag, but this would
* be hardly optimizable in libudev, and hence checking the
* second tag manually in our loop is a good solution. */
-
r = udev_enumerate_add_match_tag(e, "uaccess");
if (r < 0)
goto finish;
@@ -231,18 +243,52 @@ int devnode_acl_all(struct udev *udev,
continue;
}
- log_debug("Fixing up %s for seat %s...", node, sn);
-
- r = devnode_acl(node, flush, del, old_uid, add, new_uid);
+ n = strdup(node);
udev_device_unref(d);
+ if (!n)
+ goto finish;
+ log_debug("Found udev node %s for seat %s", n, seat);
+ r = set_put(nodes, n);
if (r < 0)
goto finish;
}
-finish:
- if (e)
- udev_enumerate_unref(e);
+ /* udev exports "dead" device nodes to allow module on-demand loading,
+ * these devices are not known to the kernel at this moment */
+ dir = opendir("/run/udev/static_node-tags/uaccess");
+ if (dir) {
+ FOREACH_DIRENT(dent, dir, r = -errno; goto finish) {
+ _cleanup_free_ char *unescaped_devname = NULL;
+ unescaped_devname = cunescape(dent->d_name);
+ if (unescaped_devname == NULL) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ n = strappend("/dev/", unescaped_devname);
+ if (!n) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ log_debug("Found static node %s for seat %s", n, seat);
+ r = set_put(nodes, n);
+ if (r < 0 && r != -EEXIST)
+ goto finish;
+ else
+ r = 0;
+ }
+ }
+
+ SET_FOREACH(n, nodes, i) {
+ log_debug("Fixing up ACLs at %s for seat %s", n, seat);
+ r = devnode_acl(n, flush, del, old_uid, add, new_uid);
+ }
+
+finish:
+ udev_enumerate_unref(e);
+ set_free_free(nodes);
return r;
}
diff --git a/src/login/logind-action.c b/src/login/logind-action.c
index c930591023..74114ee0a1 100644
--- a/src/login/logind-action.c
+++ b/src/login/logind-action.c
@@ -81,7 +81,7 @@ int manager_handle_action(
else if (handle == HANDLE_HYBRID_SLEEP)
supported = can_sleep("hybrid-sleep") > 0;
else if (handle == HANDLE_KEXEC)
- supported = access("/sbin/kexec", X_OK) >= 0;
+ supported = access(KEXEC, X_OK) >= 0;
else
supported = true;
diff --git a/src/login/logind-core.c b/src/login/logind-core.c
new file mode 100644
index 0000000000..36999ace40
--- /dev/null
+++ b/src/login/logind-core.c
@@ -0,0 +1,514 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2011 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <linux/vt.h>
+
+#include "logind.h"
+#include "dbus-common.h"
+#include "strv.h"
+
+int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device) {
+ Device *d;
+
+ assert(m);
+ assert(sysfs);
+
+ d = hashmap_get(m->devices, sysfs);
+ if (d) {
+ if (_device)
+ *_device = d;
+
+ /* we support adding master-flags, but not removing them */
+ d->master = d->master || master;
+
+ return 0;
+ }
+
+ d = device_new(m, sysfs, master);
+ if (!d)
+ return -ENOMEM;
+
+ if (_device)
+ *_device = d;
+
+ return 0;
+}
+
+int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
+ Seat *s;
+
+ assert(m);
+ assert(id);
+
+ s = hashmap_get(m->seats, id);
+ if (s) {
+ if (_seat)
+ *_seat = s;
+
+ return 0;
+ }
+
+ s = seat_new(m, id);
+ if (!s)
+ return -ENOMEM;
+
+ if (_seat)
+ *_seat = s;
+
+ return 0;
+}
+
+int manager_add_session(Manager *m, const char *id, Session **_session) {
+ Session *s;
+
+ assert(m);
+ assert(id);
+
+ s = hashmap_get(m->sessions, id);
+ if (s) {
+ if (_session)
+ *_session = s;
+
+ return 0;
+ }
+
+ s = session_new(m, id);
+ if (!s)
+ return -ENOMEM;
+
+ if (_session)
+ *_session = s;
+
+ return 0;
+}
+
+int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
+ User *u;
+
+ assert(m);
+ assert(name);
+
+ u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
+ if (u) {
+ if (_user)
+ *_user = u;
+
+ return 0;
+ }
+
+ u = user_new(m, uid, gid, name);
+ if (!u)
+ return -ENOMEM;
+
+ if (_user)
+ *_user = u;
+
+ return 0;
+}
+
+int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
+ uid_t uid;
+ gid_t gid;
+ int r;
+
+ assert(m);
+ assert(name);
+
+ r = get_user_creds(&name, &uid, &gid, NULL, NULL);
+ if (r < 0)
+ return r;
+
+ return manager_add_user(m, uid, gid, name, _user);
+}
+
+int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
+ struct passwd *p;
+
+ assert(m);
+
+ errno = 0;
+ p = getpwuid(uid);
+ if (!p)
+ return errno ? -errno : -ENOENT;
+
+ return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
+}
+
+int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
+ Inhibitor *i;
+
+ assert(m);
+ assert(id);
+
+ i = hashmap_get(m->inhibitors, id);
+ if (i) {
+ if (_inhibitor)
+ *_inhibitor = i;
+
+ return 0;
+ }
+
+ i = inhibitor_new(m, id);
+ if (!i)
+ return -ENOMEM;
+
+ if (_inhibitor)
+ *_inhibitor = i;
+
+ return 0;
+}
+
+int manager_add_button(Manager *m, const char *name, Button **_button) {
+ Button *b;
+
+ assert(m);
+ assert(name);
+
+ b = hashmap_get(m->buttons, name);
+ if (b) {
+ if (_button)
+ *_button = b;
+
+ return 0;
+ }
+
+ b = button_new(m, name);
+ if (!b)
+ return -ENOMEM;
+
+ if (_button)
+ *_button = b;
+
+ return 0;
+}
+
+int manager_watch_busname(Manager *m, const char *name) {
+ char *n;
+ int r;
+
+ assert(m);
+ assert(name);
+
+ if (hashmap_get(m->busnames, name))
+ return 0;
+
+ n = strdup(name);
+ if (!n)
+ return -ENOMEM;
+
+ r = hashmap_put(m->busnames, n, n);
+ if (r < 0) {
+ free(n);
+ return r;
+ }
+
+ return 0;
+}
+
+void manager_drop_busname(Manager *m, const char *name) {
+ Session *session;
+ Iterator i;
+ char *key;
+
+ assert(m);
+ assert(name);
+
+ if (!hashmap_get(m->busnames, name))
+ return;
+
+ /* keep it if the name still owns a controller */
+ HASHMAP_FOREACH(session, m->sessions, i)
+ if (session_is_controller(session, name))
+ return;
+
+ key = hashmap_remove(m->busnames, name);
+ if (key)
+ free(key);
+}
+
+int manager_process_seat_device(Manager *m, struct udev_device *d) {
+ Device *device;
+ int r;
+
+ assert(m);
+
+ if (streq_ptr(udev_device_get_action(d), "remove")) {
+
+ device = hashmap_get(m->devices, udev_device_get_syspath(d));
+ if (!device)
+ return 0;
+
+ seat_add_to_gc_queue(device->seat);
+ device_free(device);
+
+ } else {
+ const char *sn;
+ Seat *seat = NULL;
+ bool master;
+
+ sn = udev_device_get_property_value(d, "ID_SEAT");
+ if (isempty(sn))
+ sn = "seat0";
+
+ if (!seat_name_is_valid(sn)) {
+ log_warning("Device with invalid seat name %s found, ignoring.", sn);
+ return 0;
+ }
+
+ /* ignore non-master devices for unknown seats */
+ master = udev_device_has_tag(d, "master-of-seat");
+ if (!master && !(seat = hashmap_get(m->seats, sn)))
+ return 0;
+
+ r = manager_add_device(m, udev_device_get_syspath(d), master, &device);
+ if (r < 0)
+ return r;
+
+ if (!seat) {
+ r = manager_add_seat(m, sn, &seat);
+ if (r < 0) {
+ if (!device->seat)
+ device_free(device);
+
+ return r;
+ }
+ }
+
+ device_attach(device, seat);
+ seat_start(seat);
+ }
+
+ return 0;
+}
+
+int manager_process_button_device(Manager *m, struct udev_device *d) {
+ Button *b;
+
+ int r;
+
+ assert(m);
+
+ if (streq_ptr(udev_device_get_action(d), "remove")) {
+
+ b = hashmap_get(m->buttons, udev_device_get_sysname(d));
+ if (!b)
+ return 0;
+
+ button_free(b);
+
+ } else {
+ const char *sn;
+
+ r = manager_add_button(m, udev_device_get_sysname(d), &b);
+ if (r < 0)
+ return r;
+
+ sn = udev_device_get_property_value(d, "ID_SEAT");
+ if (isempty(sn))
+ sn = "seat0";
+
+ button_set_seat(b, sn);
+ button_open(b);
+ }
+
+ return 0;
+}
+
+int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
+ _cleanup_free_ char *unit = NULL;
+ Session *s;
+ int r;
+
+ assert(m);
+ assert(session);
+
+ if (pid < 1)
+ return -EINVAL;
+
+ r = cg_pid_get_unit(pid, &unit);
+ if (r < 0)
+ return r;
+
+ s = hashmap_get(m->session_units, unit);
+ if (!s)
+ return 0;
+
+ *session = s;
+ return 1;
+}
+
+int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
+ _cleanup_free_ char *unit = NULL;
+ User *u;
+ int r;
+
+ assert(m);
+ assert(user);
+
+ if (pid < 1)
+ return -EINVAL;
+
+ r = cg_pid_get_slice(pid, &unit);
+ if (r < 0)
+ return r;
+
+ u = hashmap_get(m->user_units, unit);
+ if (!u)
+ return 0;
+
+ *user = u;
+ return 1;
+}
+
+int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
+ Session *s;
+ bool idle_hint;
+ dual_timestamp ts = { 0, 0 };
+ Iterator i;
+
+ assert(m);
+
+ idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0);
+
+ HASHMAP_FOREACH(s, m->sessions, i) {
+ dual_timestamp k;
+ int ih;
+
+ ih = session_get_idle_hint(s, &k);
+ if (ih < 0)
+ return ih;
+
+ if (!ih) {
+ if (!idle_hint) {
+ if (k.monotonic < ts.monotonic)
+ ts = k;
+ } else {
+ idle_hint = false;
+ ts = k;
+ }
+ } else if (idle_hint) {
+
+ if (k.monotonic > ts.monotonic)
+ ts = k;
+ }
+ }
+
+ if (t)
+ *t = ts;
+
+ return idle_hint;
+}
+
+bool manager_shall_kill(Manager *m, const char *user) {
+ assert(m);
+ assert(user);
+
+ if (!m->kill_user_processes)
+ return false;
+
+ if (strv_contains(m->kill_exclude_users, user))
+ return false;
+
+ if (strv_isempty(m->kill_only_users))
+ return true;
+
+ return strv_contains(m->kill_only_users, user);
+}
+
+static int vt_is_busy(int vtnr) {
+ struct vt_stat vt_stat;
+ int r = 0, fd;
+
+ assert(vtnr >= 1);
+
+ /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
+ * we'd open the latter we'd open the foreground tty which
+ * hence would be unconditionally busy. By opening /dev/tty1
+ * we avoid this. Since tty1 is special and needs to be an
+ * explicitly loaded getty or DM this is safe. */
+
+ fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
+ if (fd < 0)
+ return -errno;
+
+ if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
+ r = -errno;
+ else
+ r = !!(vt_stat.v_state & (1 << vtnr));
+
+ close_nointr_nofail(fd);
+
+ return r;
+}
+
+int manager_spawn_autovt(Manager *m, int vtnr) {
+ int r;
+ char *name = NULL;
+ const char *mode = "fail";
+
+ assert(m);
+ assert(vtnr >= 1);
+
+ if ((unsigned) vtnr > m->n_autovts &&
+ (unsigned) vtnr != m->reserve_vt)
+ return 0;
+
+ if ((unsigned) vtnr != m->reserve_vt) {
+ /* If this is the reserved TTY, we'll start the getty
+ * on it in any case, but otherwise only if it is not
+ * busy. */
+
+ r = vt_is_busy(vtnr);
+ if (r < 0)
+ return r;
+ else if (r > 0)
+ return -EBUSY;
+ }
+
+ if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
+ log_error("Could not allocate service name.");
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ r = bus_method_call_with_reply (
+ m->bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "StartUnit",
+ NULL,
+ NULL,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_STRING, &mode,
+ DBUS_TYPE_INVALID);
+
+finish:
+ free(name);
+
+ return r;
+}
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 4a84b860f1..bb85c7d4af 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -36,6 +36,10 @@
#include "systemd/sd-messages.h"
#include "fileio-label.h"
#include "label.h"
+#include "utf8.h"
+#include "unit-name.h"
+#include "bus-errors.h"
+#include "virt.h"
#define BUS_MANAGER_INTERFACE \
" <interface name=\"org.freedesktop.login1.Manager\">\n" \
@@ -51,6 +55,10 @@
" <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \
" <arg name=\"user\" type=\"o\" direction=\"out\"/>\n" \
" </method>\n" \
+ " <method name=\"GetUserByPID\">\n" \
+ " <arg name=\"pid\" type=\"u\" direction=\"in\"/>\n" \
+ " <arg name=\"user\" type=\"o\" direction=\"out\"/>\n" \
+ " </method>\n" \
" <method name=\"GetSeat\">\n" \
" <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
" <arg name=\"seat\" type=\"o\" direction=\"out\"/>\n" \
@@ -77,9 +85,7 @@
" <arg name=\"remote\" type=\"b\" direction=\"in\"/>\n" \
" <arg name=\"remote_user\" type=\"s\" direction=\"in\"/>\n" \
" <arg name=\"remote_host\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"controllers\" type=\"as\" direction=\"in\"/>\n" \
- " <arg name=\"reset_controllers\" type=\"as\" direction=\"in\"/>\n" \
- " <arg name=\"kill_processes\" type=\"b\" direction=\"in\"/>\n" \
+ " <arg name=\"scope_properties\" type=\"a(sv)\" direction=\"in\"/>\n" \
" <arg name=\"id\" type=\"s\" direction=\"out\"/>\n" \
" <arg name=\"path\" type=\"o\" direction=\"out\"/>\n" \
" <arg name=\"runtime_path\" type=\"o\" direction=\"out\"/>\n" \
@@ -207,9 +213,6 @@
" <signal name=\"PrepareForSleep\">\n" \
" <arg name=\"active\" type=\"b\"/>\n" \
" </signal>\n" \
- " <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Controllers\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"ResetControllers\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"NAutoVTs\" type=\"u\" access=\"read\"/>\n" \
" <property name=\"KillOnlyUsers\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"KillExcludeUsers\" type=\"as\" access=\"read\"/>\n" \
@@ -308,27 +311,24 @@ static int bus_manager_append_preparing(DBusMessageIter *i, const char *property
return 0;
}
-static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMessage **_reply) {
+static int bus_manager_create_session(Manager *m, DBusMessage *message) {
+
const char *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *service;
uint32_t uid, leader, audit_id = 0;
- dbus_bool_t remote, kill_processes, exists;
- _cleanup_strv_free_ char **controllers = NULL, **reset_controllers = NULL;
- _cleanup_free_ char *cgroup = NULL, *id = NULL, *p = NULL;
- SessionType t;
- SessionClass c;
- DBusMessageIter iter;
- int r;
- uint32_t vtnr = 0;
- _cleanup_close_ int fifo_fd = -1;
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ _cleanup_free_ char *id = NULL;
Session *session = NULL;
User *user = NULL;
Seat *seat = NULL;
+ DBusMessageIter iter;
+ dbus_bool_t remote;
+ uint32_t vtnr = 0;
+ SessionType t;
+ SessionClass c;
bool b;
+ int r;
assert(m);
assert(message);
- assert(_reply);
if (!dbus_message_iter_init(message, &iter) ||
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
@@ -342,8 +342,7 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess
dbus_message_iter_get_basic(&iter, &leader);
- if (leader <= 0 ||
- !dbus_message_iter_next(&iter) ||
+ if (!dbus_message_iter_next(&iter) ||
dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
return -EINVAL;
@@ -405,8 +404,8 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess
int v;
if (!seat)
- seat = m->vtconsole;
- else if (seat != m->vtconsole)
+ seat = m->seat0;
+ else if (seat != m->seat0)
return -EINVAL;
v = vtnr_from_tty(tty);
@@ -421,8 +420,8 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess
} else if (tty_is_console(tty)) {
if (!seat)
- seat = m->vtconsole;
- else if (seat != m->vtconsole)
+ seat = m->seat0;
+ else if (seat != m->seat0)
return -EINVAL;
if (vtnr != 0)
@@ -430,7 +429,7 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess
}
if (seat) {
- if (seat_can_multi_session(seat)) {
+ if (seat_has_vts(seat)) {
if (vtnr > 63)
return -EINVAL;
} else {
@@ -479,61 +478,37 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess
dbus_message_iter_get_basic(&iter, &remote_host);
- if (!dbus_message_iter_next(&iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRING)
- return -EINVAL;
-
- r = bus_parse_strv_iter(&iter, &controllers);
- if (r < 0)
- return -EINVAL;
-
- if (!dbus_message_iter_next(&iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRING) {
- r = -EINVAL;
- goto fail;
- }
-
- r = bus_parse_strv_iter(&iter, &reset_controllers);
- if (r < 0)
- goto fail;
-
- if (!dbus_message_iter_next(&iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN) {
- r = -EINVAL;
- goto fail;
+ if (leader <= 0) {
+ leader = bus_get_unix_process_id(m->bus, dbus_message_get_sender(message), NULL);
+ if (leader == 0)
+ return -EINVAL;
}
- dbus_message_iter_get_basic(&iter, &kill_processes);
-
- r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, leader, &cgroup);
- if (r < 0)
- goto fail;
+ r = manager_get_session_by_pid(m, leader, &session);
+ if (session) {
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ _cleanup_free_ char *path = NULL;
+ _cleanup_close_ int fifo_fd = -1;
+ dbus_bool_t exists;
- r = manager_get_session_by_cgroup(m, cgroup, &session);
- if (r < 0)
- goto fail;
+ /* Session already exists, client is probably
+ * something like "su" which changes uid but is still
+ * the same session */
- if (session) {
fifo_fd = session_create_fifo(session);
if (fifo_fd < 0) {
r = fifo_fd;
goto fail;
}
- /* Session already exists, client is probably
- * something like "su" which changes uid but
- * is still the same audit session */
-
- reply = dbus_message_new_method_return(message);
- if (!reply) {
+ path = session_bus_path(session);
+ if (!path) {
r = -ENOMEM;
goto fail;
}
- p = session_bus_path(session);
- if (!p) {
+ reply = dbus_message_new_method_return(message);
+ if (!reply) {
r = -ENOMEM;
goto fail;
}
@@ -545,7 +520,7 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess
b = dbus_message_append_args(
reply,
DBUS_TYPE_STRING, &session->id,
- DBUS_TYPE_OBJECT_PATH, &p,
+ DBUS_TYPE_OBJECT_PATH, &path,
DBUS_TYPE_STRING, &session->user->runtime_path,
DBUS_TYPE_UNIX_FD, &fifo_fd,
DBUS_TYPE_STRING, &cseat,
@@ -557,8 +532,10 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess
goto fail;
}
- *_reply = reply;
- reply = NULL;
+ if (!dbus_connection_send(m->bus, reply, NULL)) {
+ r = -ENOMEM;
+ goto fail;
+ }
return 0;
}
@@ -577,6 +554,7 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess
* 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;
free(id);
@@ -601,22 +579,19 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess
if (r < 0)
goto fail;
- r = manager_add_session(m, user, id, &session);
+ r = manager_add_session(m, id, &session);
if (r < 0)
goto fail;
+ session_set_user(session, user);
+
session->leader = leader;
session->audit_id = audit_id;
session->type = t;
session->class = c;
session->remote = remote;
- session->kill_processes = kill_processes;
session->vtnr = vtnr;
- session->controllers = cg_shorten_controllers(controllers);
- session->reset_controllers = cg_shorten_controllers(reset_controllers);
- controllers = reset_controllers = NULL;
-
if (!isempty(tty)) {
session->tty = strdup(tty);
if (!session->tty) {
@@ -657,12 +632,6 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess
}
}
- fifo_fd = session_create_fifo(session);
- if (fifo_fd < 0) {
- r = fifo_fd;
- goto fail;
- }
-
if (seat) {
r = seat_attach_session(seat, session);
if (r < 0)
@@ -673,38 +642,11 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess
if (r < 0)
goto fail;
- reply = dbus_message_new_method_return(message);
- if (!reply) {
- r = -ENOMEM;
- goto fail;
- }
-
- p = session_bus_path(session);
- if (!p) {
- r = -ENOMEM;
- goto fail;
- }
-
- cseat = seat ? seat->id : "";
- exists = false;
- b = dbus_message_append_args(
- reply,
- DBUS_TYPE_STRING, &session->id,
- DBUS_TYPE_OBJECT_PATH, &p,
- DBUS_TYPE_STRING, &session->user->runtime_path,
- DBUS_TYPE_UNIX_FD, &fifo_fd,
- DBUS_TYPE_STRING, &cseat,
- DBUS_TYPE_UINT32, &vtnr,
- DBUS_TYPE_BOOLEAN, &exists,
- DBUS_TYPE_INVALID);
-
- if (!b) {
- r = -ENOMEM;
- goto fail;
- }
+ session->create_message = dbus_message_ref(message);
- *_reply = reply;
- reply = NULL;
+ /* Now, let's wait until the slice unit and stuff got
+ * created. We send the reply back from
+ * session_send_create_reply().*/
return 0;
@@ -1015,6 +957,7 @@ static int have_multiple_sessions(
* count, and non-login sessions do not count either. */
HASHMAP_FOREACH(session, m->sessions, i)
if (session->class == SESSION_USER &&
+ !session->closing &&
session->user->uid != uid)
return true;
@@ -1387,9 +1330,6 @@ static int bus_manager_do_shutdown_or_sleep(
static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_handle_action, handle_action, HandleAction);
static const BusProperty bus_login_manager_properties[] = {
- { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_path), true },
- { "Controllers", bus_property_append_strv, "as", offsetof(Manager, controllers), true },
- { "ResetControllers", bus_property_append_strv, "as", offsetof(Manager, reset_controllers), true },
{ "NAutoVTs", bus_property_append_unsigned, "u", offsetof(Manager, n_autovts) },
{ "KillOnlyUsers", bus_property_append_strv, "as", offsetof(Manager, kill_only_users), true },
{ "KillExcludeUsers", bus_property_append_strv, "as", offsetof(Manager, kill_exclude_users), true },
@@ -1530,6 +1470,40 @@ static DBusHandlerResult manager_message_handler(
if (!b)
goto oom;
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "GetUserByPID")) {
+ uint32_t pid;
+ char *p;
+ User *user;
+ bool b;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_UINT32, &pid,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ r = manager_get_user_by_pid(m, pid, &user);
+ if (r <= 0)
+ return bus_send_error_reply(connection, message, NULL, r < 0 ? r : -ENOENT);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ p = user_bus_path(user);
+ if (!p)
+ goto oom;
+
+ b = dbus_message_append_args(
+ reply,
+ DBUS_TYPE_OBJECT_PATH, &p,
+ DBUS_TYPE_INVALID);
+ free(p);
+
+ if (!b)
+ goto oom;
+
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "GetSeat")) {
const char *name;
char *p;
@@ -1612,7 +1586,6 @@ static DBusHandlerResult manager_message_handler(
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ListUsers")) {
- char *p;
User *user;
Iterator i;
DBusMessageIter iter, sub;
@@ -1627,6 +1600,7 @@ static DBusHandlerResult manager_message_handler(
goto oom;
HASHMAP_FOREACH(user, m->users, i) {
+ _cleanup_free_ char *p = NULL;
DBusMessageIter sub2;
uint32_t uid;
@@ -1646,8 +1620,6 @@ static DBusHandlerResult manager_message_handler(
goto oom;
}
- free(p);
-
if (!dbus_message_iter_close_container(&sub, &sub2))
goto oom;
}
@@ -1656,7 +1628,6 @@ static DBusHandlerResult manager_message_handler(
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ListSeats")) {
- char *p;
Seat *seat;
Iterator i;
DBusMessageIter iter, sub;
@@ -1671,6 +1642,7 @@ static DBusHandlerResult manager_message_handler(
goto oom;
HASHMAP_FOREACH(seat, m->seats, i) {
+ _cleanup_free_ char *p = NULL;
DBusMessageIter sub2;
if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
@@ -1686,8 +1658,6 @@ static DBusHandlerResult manager_message_handler(
goto oom;
}
- free(p);
-
if (!dbus_message_iter_close_container(&sub, &sub2))
goto oom;
}
@@ -1739,6 +1709,7 @@ static DBusHandlerResult manager_message_handler(
if (!dbus_message_iter_close_container(&iter, &sub))
goto oom;
+
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "Inhibit")) {
r = bus_manager_inhibit(m, connection, message, &error, &reply);
@@ -1749,7 +1720,7 @@ static DBusHandlerResult manager_message_handler(
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CreateSession")) {
- r = bus_manager_create_session(m, message, &reply);
+ r = bus_manager_create_session(m, message);
/* Don't delay the work on OOM here, since it might be
* triggered by a low RLIMIT_NOFILE here (since we
@@ -2286,7 +2257,7 @@ static DBusHandlerResult manager_message_handler(
}
HASHMAP_FOREACH(user, m->users, i)
- fprintf(f, "<node name=\"user/%llu\"/>", (unsigned long long) user->uid);
+ fprintf(f, "<node name=\"user/_%llu\"/>", (unsigned long long) user->uid);
HASHMAP_FOREACH(session, m->sessions, i) {
p = bus_path_escape(session->id);
@@ -2326,7 +2297,7 @@ static DBusHandlerResult manager_message_handler(
if (reply) {
if (!bus_maybe_send_reply(connection, message, reply))
- goto oom;
+ goto oom;
}
return DBUS_HANDLER_RESULT_HANDLED;
@@ -2355,29 +2326,23 @@ DBusHandlerResult bus_message_filter(
dbus_error_init(&error);
- if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
- const char *cgroup;
-
- if (!dbus_message_get_args(message, &error,
- DBUS_TYPE_STRING, &cgroup,
- DBUS_TYPE_INVALID))
- log_error("Failed to parse Released message: %s", bus_error_message(&error));
- else
- manager_cgroup_notify_empty(m, cgroup);
+ log_debug("Got message: %s %s %s", strna(dbus_message_get_sender(message)), strna(dbus_message_get_interface(message)), strna(dbus_message_get_member(message)));
- } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
- uint32_t id;
+ if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
const char *path, *result, *unit;
+ uint32_t id;
if (!dbus_message_get_args(message, &error,
DBUS_TYPE_UINT32, &id,
DBUS_TYPE_OBJECT_PATH, &path,
DBUS_TYPE_STRING, &unit,
DBUS_TYPE_STRING, &result,
- DBUS_TYPE_INVALID))
+ DBUS_TYPE_INVALID)) {
log_error("Failed to parse JobRemoved message: %s", bus_error_message(&error));
+ goto finish;
+ }
- else if (m->action_job && streq(m->action_job, path)) {
+ if (m->action_job && streq(m->action_job, path)) {
log_info("Operation finished.");
/* Tell people that they now may take a lock again */
@@ -2387,9 +2352,141 @@ DBusHandlerResult bus_message_filter(
m->action_job = NULL;
m->action_unit = NULL;
m->action_what = 0;
+
+ } else {
+ Session *s;
+ User *u;
+
+ s = hashmap_get(m->session_units, unit);
+ if (s) {
+ if (streq_ptr(path, s->scope_job)) {
+ free(s->scope_job);
+ s->scope_job = NULL;
+
+ if (s->started) {
+ if (streq(result, "done"))
+ session_send_create_reply(s, NULL);
+ else {
+ dbus_set_error(&error, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
+ session_send_create_reply(s, &error);
+ }
+ } else
+ session_save(s);
+ }
+
+ session_add_to_gc_queue(s);
+ }
+
+ u = hashmap_get(m->user_units, unit);
+ if (u) {
+ if (streq_ptr(path, u->service_job)) {
+ free(u->service_job);
+ u->service_job = NULL;
+ }
+
+ if (streq_ptr(path, u->slice_job)) {
+ free(u->slice_job);
+ u->slice_job = NULL;
+ }
+
+ user_save(u);
+ user_add_to_gc_queue(u);
+ }
+ }
+
+ } else if (dbus_message_is_signal(message, "org.freedesktop.DBus.Properties", "PropertiesChanged")) {
+
+ _cleanup_free_ char *unit = NULL;
+ const char *path;
+
+ path = dbus_message_get_path(message);
+ if (!path)
+ goto finish;
+
+ unit_name_from_dbus_path(path, &unit);
+ if (unit) {
+ Session *s;
+ User *u;
+
+ s = hashmap_get(m->session_units, unit);
+ if (s)
+ session_add_to_gc_queue(s);
+
+ u = hashmap_get(m->user_units, unit);
+ if (u)
+ user_add_to_gc_queue(u);
+ }
+
+ } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "UnitRemoved")) {
+
+ const char *path, *unit;
+ Session *session;
+ User *user;
+
+ if (!dbus_message_get_args(message, &error,
+ DBUS_TYPE_STRING, &unit,
+ DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID)) {
+ log_error("Failed to parse UnitRemoved message: %s", bus_error_message(&error));
+ goto finish;
+ }
+
+ session = hashmap_get(m->session_units, unit);
+ if (session)
+ session_add_to_gc_queue(session);
+
+ user = hashmap_get(m->user_units, unit);
+ if (user)
+ user_add_to_gc_queue(user);
+
+ } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "Reloading")) {
+ dbus_bool_t b;
+
+ if (!dbus_message_get_args(message, &error,
+ DBUS_TYPE_BOOLEAN, &b,
+ DBUS_TYPE_INVALID)) {
+ log_error("Failed to parse Reloading message: %s", bus_error_message(&error));
+ goto finish;
+ }
+
+ /* systemd finished reloading, let's recheck all our sessions */
+ if (!b) {
+ Session *session;
+ Iterator i;
+
+ log_debug("System manager has been reloaded, rechecking sessions...");
+
+ HASHMAP_FOREACH(session, m->sessions, i)
+ session_add_to_gc_queue(session);
+ }
+
+ } else if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
+ const char *name, *old, *new;
+ char *key;
+
+ if (!dbus_message_get_args(message, &error,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_STRING, &old,
+ DBUS_TYPE_STRING, &new,
+ DBUS_TYPE_INVALID)) {
+ log_error("Failed to parse NameOwnerChanged message: %s", bus_error_message(&error));
+ goto finish;
+ }
+
+ /* drop all controllers owned by this name */
+ if (*old && !*new && (key = hashmap_remove(m->busnames, old))) {
+ Session *session;
+ Iterator i;
+
+ free(key);
+
+ HASHMAP_FOREACH(session, m->sessions, i)
+ if (session_is_controller(session, old))
+ session_drop_controller(session);
}
}
+finish:
dbus_error_free(&error);
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
@@ -2444,3 +2541,356 @@ int manager_dispatch_delayed(Manager *manager) {
return 1;
}
+
+int manager_start_scope(
+ Manager *manager,
+ const char *scope,
+ pid_t pid,
+ const char *slice,
+ const char *description,
+ const char *after,
+ const char *kill_mode,
+ DBusError *error,
+ char **job) {
+
+ const char *timeout_stop_property = "TimeoutStopUSec", *send_sighup_property = "SendSIGHUP", *pids_property = "PIDs";
+ _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
+ DBusMessageIter iter, sub, sub2, sub3, sub4;
+ uint64_t timeout = 500 * USEC_PER_MSEC;
+ dbus_bool_t send_sighup = true;
+ const char *fail = "fail";
+ uint32_t u;
+
+ assert(manager);
+ assert(scope);
+ assert(pid > 1);
+
+ if (!slice)
+ slice = "";
+
+ m = dbus_message_new_method_call(
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "StartTransientUnit");
+ if (!m)
+ return log_oom();
+
+ dbus_message_iter_init_append(m, &iter);
+
+ if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &scope) ||
+ !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &fail) ||
+ !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sv)", &sub))
+ return log_oom();
+
+ if (!isempty(slice)) {
+ const char *slice_property = "Slice";
+
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &slice_property) ||
+ !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, "s", &sub3) ||
+ !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &slice) ||
+ !dbus_message_iter_close_container(&sub2, &sub3) ||
+ !dbus_message_iter_close_container(&sub, &sub2))
+ return log_oom();
+ }
+
+ if (!isempty(description)) {
+ const char *description_property = "Description";
+
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description_property) ||
+ !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, "s", &sub3) ||
+ !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &description) ||
+ !dbus_message_iter_close_container(&sub2, &sub3) ||
+ !dbus_message_iter_close_container(&sub, &sub2))
+ return log_oom();
+ }
+
+ if (!isempty(after)) {
+ const char *after_property = "After";
+
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &after_property) ||
+ !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, "as", &sub3) ||
+ !dbus_message_iter_open_container(&sub3, DBUS_TYPE_ARRAY, "s", &sub4) ||
+ !dbus_message_iter_append_basic(&sub4, DBUS_TYPE_STRING, &after) ||
+ !dbus_message_iter_close_container(&sub3, &sub4) ||
+ !dbus_message_iter_close_container(&sub2, &sub3) ||
+ !dbus_message_iter_close_container(&sub, &sub2))
+ return log_oom();
+ }
+
+ if (!isempty(kill_mode)) {
+ const char *kill_mode_property = "KillMode";
+
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &kill_mode_property) ||
+ !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, "s", &sub3) ||
+ !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &kill_mode) ||
+ !dbus_message_iter_close_container(&sub2, &sub3) ||
+ !dbus_message_iter_close_container(&sub, &sub2))
+ return log_oom();
+ }
+
+ /* 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. */
+
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &timeout_stop_property) ||
+ !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, "t", &sub3) ||
+ !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_UINT64, &timeout) ||
+ !dbus_message_iter_close_container(&sub2, &sub3) ||
+ !dbus_message_iter_close_container(&sub, &sub2))
+ return log_oom();
+
+ /* Make sure that the session shells are terminated with
+ * SIGHUP since bash and friends tend to ignore SIGTERM */
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &send_sighup_property) ||
+ !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, "b", &sub3) ||
+ !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_BOOLEAN, &send_sighup) ||
+ !dbus_message_iter_close_container(&sub2, &sub3) ||
+ !dbus_message_iter_close_container(&sub, &sub2))
+ return log_oom();
+
+ u = pid;
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &pids_property) ||
+ !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, "au", &sub3) ||
+ !dbus_message_iter_open_container(&sub3, DBUS_TYPE_ARRAY, "u", &sub4) ||
+ !dbus_message_iter_append_basic(&sub4, DBUS_TYPE_UINT32, &u) ||
+ !dbus_message_iter_close_container(&sub3, &sub4) ||
+ !dbus_message_iter_close_container(&sub2, &sub3) ||
+ !dbus_message_iter_close_container(&sub, &sub2))
+ return log_oom();
+
+ if (!dbus_message_iter_close_container(&iter, &sub))
+ return log_oom();
+
+ reply = dbus_connection_send_with_reply_and_block(manager->bus, m, -1, error);
+ if (!reply)
+ return -EIO;
+
+ if (job) {
+ const char *j;
+ char *copy;
+
+ if (!dbus_message_get_args(reply, error, DBUS_TYPE_OBJECT_PATH, &j, DBUS_TYPE_INVALID))
+ return -EIO;
+
+ copy = strdup(j);
+ if (!copy)
+ return -ENOMEM;
+
+ *job = copy;
+ }
+
+ return 0;
+}
+
+int manager_start_unit(Manager *manager, const char *unit, DBusError *error, char **job) {
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ const char *fail = "fail";
+ int r;
+
+ assert(manager);
+ assert(unit);
+
+ r = bus_method_call_with_reply(
+ manager->bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "StartUnit",
+ &reply,
+ error,
+ DBUS_TYPE_STRING, &unit,
+ DBUS_TYPE_STRING, &fail,
+ DBUS_TYPE_INVALID);
+ if (r < 0) {
+ log_error("Failed to start unit %s: %s", unit, bus_error(error, r));
+ return r;
+ }
+
+ if (job) {
+ const char *j;
+ char *copy;
+
+ if (!dbus_message_get_args(reply, error,
+ DBUS_TYPE_OBJECT_PATH, &j,
+ DBUS_TYPE_INVALID)) {
+ log_error("Failed to parse reply.");
+ return -EIO;
+ }
+
+ copy = strdup(j);
+ if (!copy)
+ return -ENOMEM;
+
+ *job = copy;
+ }
+
+ return 0;
+}
+
+int manager_stop_unit(Manager *manager, const char *unit, DBusError *error, char **job) {
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ const char *fail = "fail";
+ int r;
+
+ assert(manager);
+ assert(unit);
+
+ r = bus_method_call_with_reply(
+ manager->bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "StopUnit",
+ &reply,
+ error,
+ DBUS_TYPE_STRING, &unit,
+ DBUS_TYPE_STRING, &fail,
+ DBUS_TYPE_INVALID);
+ if (r < 0) {
+ if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
+ dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
+
+ if (job)
+ *job = NULL;
+
+ dbus_error_free(error);
+ return 0;
+ }
+
+ log_error("Failed to stop unit %s: %s", unit, bus_error(error, r));
+ return r;
+ }
+
+ if (job) {
+ const char *j;
+ char *copy;
+
+ if (!dbus_message_get_args(reply, error,
+ DBUS_TYPE_OBJECT_PATH, &j,
+ DBUS_TYPE_INVALID)) {
+ log_error("Failed to parse reply.");
+ return -EIO;
+ }
+
+ copy = strdup(j);
+ if (!copy)
+ return -ENOMEM;
+
+ *job = copy;
+ }
+
+ return 1;
+}
+
+int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, DBusError *error) {
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ const char *w;
+ int r;
+
+ assert(manager);
+ assert(unit);
+
+ w = who == KILL_LEADER ? "process" : "cgroup";
+ assert_cc(sizeof(signo) == sizeof(int32_t));
+
+ r = bus_method_call_with_reply(
+ manager->bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "KillUnit",
+ &reply,
+ error,
+ DBUS_TYPE_STRING, &unit,
+ DBUS_TYPE_STRING, &w,
+ DBUS_TYPE_INT32, &signo,
+ DBUS_TYPE_INVALID);
+ if (r < 0) {
+ log_error("Failed to stop unit %s: %s", unit, bus_error(error, r));
+ return r;
+ }
+
+ return 0;
+}
+
+int manager_unit_is_active(Manager *manager, const char *unit) {
+
+ const char *interface = "org.freedesktop.systemd1.Unit";
+ const char *property = "ActiveState";
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ _cleanup_free_ char *path = NULL;
+ DBusMessageIter iter, sub;
+ const char *state;
+ DBusError error;
+ int r;
+
+ assert(manager);
+ assert(unit);
+
+ dbus_error_init(&error);
+
+ path = unit_dbus_path_from_name(unit);
+ if (!path)
+ return -ENOMEM;
+
+ r = bus_method_call_with_reply(
+ manager->bus,
+ "org.freedesktop.systemd1",
+ path,
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ &reply,
+ &error,
+ DBUS_TYPE_STRING, &interface,
+ DBUS_TYPE_STRING, &property,
+ DBUS_TYPE_INVALID);
+ if (r < 0) {
+ if (dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY) ||
+ dbus_error_has_name(&error, DBUS_ERROR_DISCONNECTED)) {
+ /* systemd might have droppped off
+ * momentarily, let's not make this an
+ * error */
+
+ dbus_error_free(&error);
+ return true;
+ }
+
+ if (dbus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
+ dbus_error_has_name(&error, BUS_ERROR_LOAD_FAILED)) {
+ /* If the unit is already unloaded then it's
+ * not active */
+
+ dbus_error_free(&error);
+ return false;
+ }
+
+ log_error("Failed to query ActiveState: %s", bus_error(&error, r));
+ dbus_error_free(&error);
+ return r;
+ }
+
+ if (!dbus_message_iter_init(reply, &iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
+ log_error("Failed to parse reply.");
+ return -EINVAL;
+ }
+
+ dbus_message_iter_recurse(&iter, &sub);
+ if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
+ log_error("Failed to parse reply.");
+ return -EINVAL;
+ }
+
+ dbus_message_iter_get_basic(&sub, &state);
+
+ return !streq(state, "inactive") && !streq(state, "failed");
+}
diff --git a/src/login/logind-device.c b/src/login/logind-device.c
index 51b15358ba..95c2307baf 100644
--- a/src/login/logind-device.c
+++ b/src/login/logind-device.c
@@ -25,7 +25,7 @@
#include "logind-device.h"
#include "util.h"
-Device* device_new(Manager *m, const char *sysfs) {
+Device* device_new(Manager *m, const char *sysfs, bool master) {
Device *d;
assert(m);
@@ -48,6 +48,7 @@ Device* device_new(Manager *m, const char *sysfs) {
}
d->manager = m;
+ d->master = master;
dual_timestamp_get(&d->timestamp);
return d;
@@ -66,20 +67,29 @@ void device_free(Device *d) {
void device_detach(Device *d) {
Seat *s;
+ SessionDevice *sd;
assert(d);
if (!d->seat)
return;
+ while ((sd = d->session_devices))
+ session_device_free(sd);
+
s = d->seat;
LIST_REMOVE(Device, devices, d->seat->devices, d);
d->seat = NULL;
- seat_add_to_gc_queue(s);
- seat_send_changed(s, "CanGraphical\0");
+ if (!seat_has_master_device(s)) {
+ seat_add_to_gc_queue(s);
+ seat_send_changed(s, "CanGraphical\0");
+ }
}
void device_attach(Device *d, Seat *s) {
+ Device *i;
+ bool had_master;
+
assert(d);
assert(s);
@@ -90,7 +100,26 @@ void device_attach(Device *d, Seat *s) {
device_detach(d);
d->seat = s;
- LIST_PREPEND(Device, devices, s->devices, d);
+ had_master = seat_has_master_device(s);
+
+ /* We keep the device list sorted by the "master" flag. That is, master
+ * devices are at the front, other devices at the tail. As there is no
+ * way to easily add devices at the list-tail, we need to iterate the
+ * list to find the first non-master device when adding non-master
+ * devices. We assume there is only a few (normally 1) master devices
+ * per seat, so we iterate only a few times. */
+
+ if (d->master || !s->devices)
+ LIST_PREPEND(Device, devices, s->devices, d);
+ else {
+ LIST_FOREACH(devices, i, s->devices) {
+ if (!i->devices_next || !i->master) {
+ LIST_INSERT_AFTER(Device, devices, s->devices, i, d);
+ break;
+ }
+ }
+ }
- seat_send_changed(s, "CanGraphical\0");
+ if (!had_master && d->master)
+ seat_send_changed(s, "CanGraphical\0");
}
diff --git a/src/login/logind-device.h b/src/login/logind-device.h
index 3b153568cb..fa6eda7e55 100644
--- a/src/login/logind-device.h
+++ b/src/login/logind-device.h
@@ -27,19 +27,22 @@ typedef struct Device Device;
#include "util.h"
#include "logind.h"
#include "logind-seat.h"
+#include "logind-session-device.h"
struct Device {
Manager *manager;
char *sysfs;
Seat *seat;
+ bool master;
dual_timestamp timestamp;
LIST_FIELDS(struct Device, devices);
+ LIST_HEAD(SessionDevice, session_devices);
};
-Device* device_new(Manager *m, const char *sysfs);
+Device* device_new(Manager *m, const char *sysfs, bool master);
void device_free(Device *d);
void device_attach(Device *d, Seat *s);
void device_detach(Device *d);
diff --git a/src/login/logind-gperf.gperf b/src/login/logind-gperf.gperf
index 735d2dbc9c..845302a54d 100644
--- a/src/login/logind-gperf.gperf
+++ b/src/login/logind-gperf.gperf
@@ -19,8 +19,6 @@ Login.ReserveVT, config_parse_unsigned, 0, offsetof(Manag
Login.KillUserProcesses, config_parse_bool, 0, offsetof(Manager, kill_user_processes)
Login.KillOnlyUsers, config_parse_strv, 0, offsetof(Manager, kill_only_users)
Login.KillExcludeUsers, config_parse_strv, 0, offsetof(Manager, kill_exclude_users)
-Login.Controllers, config_parse_strv, 0, offsetof(Manager, controllers)
-Login.ResetControllers, config_parse_strv, 0, offsetof(Manager, reset_controllers)
Login.InhibitDelayMaxSec, config_parse_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)
diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c
index 5c535ba0ec..230f7f082a 100644
--- a/src/login/logind-seat-dbus.c
+++ b/src/login/logind-seat-dbus.c
@@ -209,8 +209,8 @@ static int bus_seat_append_idle_hint_since(DBusMessageIter *i, const char *prope
}
static int get_seat_for_path(Manager *m, const char *path, Seat **_s) {
+ _cleanup_free_ char *id = NULL;
Seat *s;
- char *id;
assert(m);
assert(path);
@@ -224,8 +224,6 @@ static int get_seat_for_path(Manager *m, const char *path, Seat **_s) {
return -ENOMEM;
s = hashmap_get(m->seats, id);
- free(id);
-
if (!s)
return -ENOENT;
@@ -348,7 +346,7 @@ const DBusObjectPathVTable bus_seat_vtable = {
};
char *seat_bus_path(Seat *s) {
- _cleanup_free_ char *t;
+ _cleanup_free_ char *t = NULL;
assert(s);
diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c
index 470d08bc05..feebcf4558 100644
--- a/src/login/logind-seat.c
+++ b/src/login/logind-seat.c
@@ -105,11 +105,11 @@ int seat_save(Seat *s) {
fprintf(f,
"# This is private data. Do not parse.\n"
- "IS_VTCONSOLE=%i\n"
+ "IS_SEAT0=%i\n"
"CAN_MULTI_SESSION=%i\n"
"CAN_TTY=%i\n"
"CAN_GRAPHICAL=%i\n",
- seat_is_vtconsole(s),
+ seat_is_seat0(s),
seat_can_multi_session(s),
seat_can_tty(s),
seat_can_graphical(s));
@@ -201,7 +201,7 @@ int seat_preallocate_vts(Seat *s) {
if (s->manager->n_autovts <= 0)
return 0;
- if (!seat_can_multi_session(s))
+ if (!seat_has_vts(s))
return 0;
for (i = 1; i <= s->manager->n_autovts; i++) {
@@ -246,10 +246,17 @@ int seat_set_active(Seat *s, Session *session) {
old_active = s->active;
s->active = session;
+ if (old_active) {
+ session_device_pause_all(old_active);
+ session_send_changed(old_active, "Active\0");
+ }
+
seat_apply_acls(s, old_active);
- if (session && session->started)
+ if (session && session->started) {
session_send_changed(session, "Active\0");
+ session_device_resume_all(session);
+ }
if (!session || session->started)
seat_send_changed(s, "ActiveSession\0");
@@ -277,7 +284,7 @@ int seat_active_vt_changed(Seat *s, int vtnr) {
assert(s);
assert(vtnr >= 1);
- if (!seat_can_multi_session(s))
+ if (!seat_has_vts(s))
return -EINVAL;
log_debug("VT changed to %i", vtnr);
@@ -301,7 +308,7 @@ int seat_read_active_vt(Seat *s) {
assert(s);
- if (!seat_can_multi_session(s))
+ if (!seat_has_vts(s))
return 0;
lseek(s->manager->console_active_fd, SEEK_SET, 0);
@@ -412,46 +419,64 @@ int seat_attach_session(Seat *s, Session *session) {
seat_send_changed(s, "Sessions\0");
- /* Note that even if a seat is not multi-session capable it
- * still might have multiple sessions on it since old, dead
- * sessions might continue to be tracked until all their
- * processes are gone. The most recently added session
- * (i.e. the first in s->sessions) is the one that matters. */
-
- if (!seat_can_multi_session(s))
+ /* On seats with VTs, the VT logic defines which session is active. On
+ * seats without VTs, we automatically activate the first session. */
+ if (!seat_has_vts(s) && !s->active)
seat_set_active(s, session);
return 0;
}
-bool seat_is_vtconsole(Seat *s) {
+void seat_complete_switch(Seat *s) {
+ Session *session;
+
assert(s);
- return s->manager->vtconsole == s;
+ /* if no session-switch is pending or if it got canceled, do nothing */
+ if (!s->pending_switch)
+ return;
+
+ session = s->pending_switch;
+ s->pending_switch = NULL;
+
+ seat_set_active(s, session);
}
-bool seat_can_multi_session(Seat *s) {
+bool seat_has_vts(Seat *s) {
assert(s);
- if (!seat_is_vtconsole(s))
- return false;
+ return seat_is_seat0(s) && s->manager->console_active_fd >= 0;
+}
- /* If we can't watch which VT is in the foreground, we don't
- * support VT switching */
+bool seat_is_seat0(Seat *s) {
+ assert(s);
- return s->manager->console_active_fd >= 0;
+ return s->manager->seat0 == s;
+}
+
+bool seat_can_multi_session(Seat *s) {
+ assert(s);
+
+ return seat_has_vts(s);
}
bool seat_can_tty(Seat *s) {
assert(s);
- return seat_is_vtconsole(s);
+ return seat_has_vts(s);
+}
+
+bool seat_has_master_device(Seat *s) {
+ assert(s);
+
+ /* device list is ordered by "master" flag */
+ return !!s->devices && s->devices->master;
}
bool seat_can_graphical(Seat *s) {
assert(s);
- return !!s->devices;
+ return seat_has_master_device(s);
}
int seat_get_idle_hint(Seat *s, dual_timestamp *t) {
@@ -496,10 +521,10 @@ int seat_check_gc(Seat *s, bool drop_not_started) {
if (drop_not_started && !s->started)
return 0;
- if (seat_is_vtconsole(s))
+ if (seat_is_seat0(s))
return 1;
- return !!s->devices;
+ return seat_has_master_device(s);
}
void seat_add_to_gc_queue(Seat *s) {
diff --git a/src/login/logind-seat.h b/src/login/logind-seat.h
index c8ab17f7cf..be6db6eed1 100644
--- a/src/login/logind-seat.h
+++ b/src/login/logind-seat.h
@@ -38,6 +38,7 @@ struct Seat {
LIST_HEAD(Device, devices);
Session *active;
+ Session *pending_switch;
LIST_HEAD(Session, sessions);
bool in_gc_queue:1;
@@ -59,10 +60,13 @@ int seat_read_active_vt(Seat *s);
int seat_preallocate_vts(Seat *s);
int seat_attach_session(Seat *s, Session *session);
+void seat_complete_switch(Seat *s);
-bool seat_is_vtconsole(Seat *s);
+bool seat_has_vts(Seat *s);
+bool seat_is_seat0(Seat *s);
bool seat_can_multi_session(Seat *s);
bool seat_can_tty(Seat *s);
+bool seat_has_master_device(Seat *s);
bool seat_can_graphical(Seat *s);
int seat_get_idle_hint(Seat *s, dual_timestamp *t);
diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c
index ec823af547..5f6bafbc6a 100644
--- a/src/login/logind-session-dbus.c
+++ b/src/login/logind-session-dbus.c
@@ -24,6 +24,7 @@
#include "logind.h"
#include "logind-session.h"
+#include "logind-session-device.h"
#include "dbus-common.h"
#include "util.h"
@@ -40,6 +41,34 @@
" <arg name=\"who\" type=\"s\"/>\n" \
" <arg name=\"signal\" type=\"s\"/>\n" \
" </method>\n" \
+ " <method name=\"TakeControl\"/>\n" \
+ " <arg name=\"force\" type=\"b\"/>\n" \
+ " </method>\n" \
+ " <method name=\"ReleaseControl\"/>\n" \
+ " <method name=\"TakeDevice\">\n" \
+ " <arg name=\"major\" type=\"u\" direction=\"in\"/>\n" \
+ " <arg name=\"minor\" type=\"u\" direction=\"in\"/>\n" \
+ " <arg name=\"fd\" type=\"h\" direction=\"out\"/>\n" \
+ " <arg name=\"paused\" type=\"b\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ " <method name=\"ReleaseDevice\">\n" \
+ " <arg name=\"major\" type=\"u\"/>\n" \
+ " <arg name=\"minor\" type=\"u\"/>\n" \
+ " </method>\n" \
+ " <method name=\"PauseDeviceComplete\">\n" \
+ " <arg name=\"major\" type=\"u\"/>\n" \
+ " <arg name=\"minor\" type=\"u\"/>\n" \
+ " </method>\n" \
+ " <signal name=\"PauseDevice\">\n" \
+ " <arg name=\"major\" type=\"u\"/>\n" \
+ " <arg name=\"minor\" type=\"u\"/>\n" \
+ " <arg name=\"type\" type=\"s\"/>\n" \
+ " </signal>\n" \
+ " <signal name=\"ResumeDevice\">\n" \
+ " <arg name=\"major\" type=\"u\"/>\n" \
+ " <arg name=\"minor\" type=\"u\"/>\n" \
+ " <arg name=\"fd\" type=\"h\"/>\n" \
+ " </signal>\n" \
" <signal name=\"Lock\"/>\n" \
" <signal name=\"Unlock\"/>\n" \
" <property name=\"Id\" type=\"s\" access=\"read\"/>\n" \
@@ -47,7 +76,6 @@
" <property name=\"Name\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"Timestamp\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"TimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"DefaultControlGroup\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"VTNr\" type=\"u\" access=\"read\"/>\n" \
" <property name=\"Seat\" type=\"(so)\" access=\"read\"/>\n" \
" <property name=\"TTY\" type=\"s\" access=\"read\"/>\n" \
@@ -56,15 +84,13 @@
" <property name=\"RemoteHost\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"RemoteUser\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"Service\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"Scope\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"Leader\" type=\"u\" access=\"read\"/>\n" \
" <property name=\"Audit\" type=\"u\" access=\"read\"/>\n" \
" <property name=\"Type\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"Class\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"Active\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"State\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"Controllers\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"ResetControllers\" type=\"as\" access=\"read\"/>\n" \
- " <property name=\"KillProcesses\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"IdleHint\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"IdleSinceHint\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"IdleSinceHintMonotonic\" type=\"t\" access=\"read\"/>\n" \
@@ -195,24 +221,6 @@ static int bus_session_append_idle_hint_since(DBusMessageIter *i, const char *pr
return 0;
}
-static int bus_session_append_default_cgroup(DBusMessageIter *i, const char *property, void *data) {
- Session *s = data;
- _cleanup_free_ char *t = NULL;
- int r;
- bool success;
-
- assert(i);
- assert(property);
- assert(s);
-
- r = cg_join_spec(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, &t);
- if (r < 0)
- return r;
-
- success = dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t);
- return success ? 0 : -ENOMEM;
-}
-
static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_session_append_type, session_type, SessionType);
static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_session_append_class, session_class, SessionClass);
@@ -233,8 +241,8 @@ static int bus_session_append_state(DBusMessageIter *i, const char *property, vo
}
static int get_session_for_path(Manager *m, const char *path, Session **_s) {
+ _cleanup_free_ char *id = NULL;
Session *s;
- char *id;
assert(m);
assert(path);
@@ -248,8 +256,6 @@ static int get_session_for_path(Manager *m, const char *path, Session **_s) {
return -ENOMEM;
s = hashmap_get(m->sessions, id);
- free(id);
-
if (!s)
return -ENOENT;
@@ -261,7 +267,6 @@ static const BusProperty bus_login_session_properties[] = {
{ "Id", bus_property_append_string, "s", offsetof(Session, id), true },
{ "Timestamp", bus_property_append_usec, "t", offsetof(Session, timestamp.realtime) },
{ "TimestampMonotonic", bus_property_append_usec, "t", offsetof(Session, timestamp.monotonic) },
- { "DefaultControlGroup", bus_session_append_default_cgroup, "s", 0, },
{ "VTNr", bus_property_append_uint32, "u", offsetof(Session, vtnr) },
{ "Seat", bus_session_append_seat, "(so)", 0 },
{ "TTY", bus_property_append_string, "s", offsetof(Session, tty), true },
@@ -270,15 +275,13 @@ static const BusProperty bus_login_session_properties[] = {
{ "RemoteUser", bus_property_append_string, "s", offsetof(Session, remote_user), true },
{ "RemoteHost", bus_property_append_string, "s", offsetof(Session, remote_host), true },
{ "Service", bus_property_append_string, "s", offsetof(Session, service), true },
+ { "Scope", bus_property_append_string, "s", offsetof(Session, scope), true },
{ "Leader", bus_property_append_pid, "u", offsetof(Session, leader) },
{ "Audit", bus_property_append_uint32, "u", offsetof(Session, audit_id) },
{ "Type", bus_session_append_type, "s", offsetof(Session, type) },
{ "Class", bus_session_append_class, "s", offsetof(Session, class) },
{ "Active", bus_session_append_active, "b", 0 },
{ "State", bus_session_append_state, "s", 0 },
- { "Controllers", bus_property_append_strv, "as", offsetof(Session, controllers), true },
- { "ResetControllers", bus_property_append_strv, "as", offsetof(Session, reset_controllers), true },
- { "KillProcesses", bus_property_append_bool, "b", offsetof(Session, kill_processes) },
{ "IdleHint", bus_session_append_idle_hint, "b", 0 },
{ "IdleSinceHint", bus_session_append_idle_hint_since, "t", 0 },
{ "IdleSinceHintMonotonic", bus_session_append_idle_hint_since, "t", 0 },
@@ -392,6 +395,147 @@ static DBusHandlerResult session_message_dispatch(
if (!reply)
goto oom;
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Session", "TakeControl")) {
+ dbus_bool_t force;
+ unsigned long ul;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_BOOLEAN, &force,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), &error);
+ if (ul == (unsigned long) -1)
+ return bus_send_error_reply(connection, message, &error, -EIO);
+
+ if (ul != 0 && (force || ul != s->user->uid))
+ return bus_send_error_reply(connection, message, NULL, -EPERM);
+
+ r = session_set_controller(s, bus_message_get_sender_with_fallback(message), force);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Session", "ReleaseControl")) {
+ const char *sender = bus_message_get_sender_with_fallback(message);
+
+ if (!session_is_controller(s, sender))
+ return bus_send_error_reply(connection, message, NULL, -EPERM);
+
+ session_drop_controller(s);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Session", "TakeDevice")) {
+ SessionDevice *sd;
+ bool b;
+ dbus_bool_t paused;
+ uint32_t major, minor;
+ dev_t dev;
+
+ if (!session_is_controller(s, bus_message_get_sender_with_fallback(message)))
+ return bus_send_error_reply(connection, message, NULL, -EPERM);
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_UINT32, &major,
+ DBUS_TYPE_UINT32, &minor,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ dev = makedev(major, minor);
+ sd = hashmap_get(s->devices, &dev);
+ if (sd) {
+ /* We don't allow retrieving a device multiple times.
+ * The related ReleaseDevice call is not ref-counted.
+ * The caller should use dup() if it requires more than
+ * one fd (it would be functionally equivalent). */
+ return bus_send_error_reply(connection, message, &error, -EBUSY);
+ }
+
+ r = session_device_new(s, dev, &sd);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply) {
+ session_device_free(sd);
+ goto oom;
+ }
+
+ paused = !sd->active;
+ b = dbus_message_append_args(
+ reply,
+ DBUS_TYPE_UNIX_FD, &sd->fd,
+ DBUS_TYPE_BOOLEAN, &paused,
+ DBUS_TYPE_INVALID);
+ if (!b) {
+ session_device_free(sd);
+ return bus_send_error_reply(connection, message, NULL, -ENOMEM);
+ }
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Session", "ReleaseDevice")) {
+ SessionDevice *sd;
+ uint32_t major, minor;
+ dev_t dev;
+
+ if (!session_is_controller(s, bus_message_get_sender_with_fallback(message)))
+ return bus_send_error_reply(connection, message, NULL, -EPERM);
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_UINT32, &major,
+ DBUS_TYPE_UINT32, &minor,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ dev = makedev(major, minor);
+ sd = hashmap_get(s->devices, &dev);
+ if (!sd)
+ return bus_send_error_reply(connection, message, NULL, -ENODEV);
+
+ session_device_free(sd);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Session", "PauseDeviceComplete")) {
+ SessionDevice *sd;
+ uint32_t major, minor;
+ dev_t dev;
+
+ if (!session_is_controller(s, bus_message_get_sender_with_fallback(message)))
+ return bus_send_error_reply(connection, message, NULL, -EPERM);
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_UINT32, &major,
+ DBUS_TYPE_UINT32, &minor,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ dev = makedev(major, minor);
+ sd = hashmap_get(s->devices, &dev);
+ if (!sd)
+ return bus_send_error_reply(connection, message, NULL, -ENODEV);
+
+ session_device_complete_pause(sd);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
} else {
const BusBoundProperties bps[] = {
{ "org.freedesktop.login1.Session", bus_login_session_properties, s },
@@ -448,7 +592,7 @@ const DBusObjectPathVTable bus_session_vtable = {
};
char *session_bus_path(Session *s) {
- _cleanup_free_ char *t;
+ _cleanup_free_ char *t = NULL;
assert(s);
@@ -552,3 +696,81 @@ int session_send_lock_all(Manager *m, bool lock) {
return r;
}
+
+int session_send_create_reply(Session *s, DBusError *error) {
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+
+ assert(s);
+
+ if (!s->create_message)
+ return 0;
+
+ /* This is called after the session scope was successfully
+ * created, and finishes where bus_manager_create_session()
+ * left off. */
+
+ if (error) {
+ DBusError buffer;
+
+ dbus_error_init(&buffer);
+
+ if (!dbus_error_is_set(error)) {
+ dbus_set_error_const(&buffer, DBUS_ERROR_INVALID_ARGS, "Invalid Arguments");
+ error = &buffer;
+ }
+
+ reply = dbus_message_new_error(s->create_message, error->name, error->message);
+ dbus_error_free(&buffer);
+
+ if (!reply)
+ return log_oom();
+ } else {
+ _cleanup_close_ int fifo_fd = -1;
+ _cleanup_free_ char *path = NULL;
+ const char *cseat;
+ uint32_t vtnr;
+ dbus_bool_t exists;
+
+ fifo_fd = session_create_fifo(s);
+ if (fifo_fd < 0) {
+ log_error("Failed to create fifo: %s", strerror(-fifo_fd));
+ return fifo_fd;
+ }
+
+ path = session_bus_path(s);
+ if (!path)
+ return log_oom();
+
+ reply = dbus_message_new_method_return(s->create_message);
+ if (!reply)
+ return log_oom();
+
+ cseat = s->seat ? s->seat->id : "";
+ vtnr = s->vtnr;
+ exists = false;
+
+ if (!dbus_message_append_args(
+ reply,
+ DBUS_TYPE_STRING, &s->id,
+ DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_STRING, &s->user->runtime_path,
+ DBUS_TYPE_UNIX_FD, &fifo_fd,
+ DBUS_TYPE_STRING, &cseat,
+ DBUS_TYPE_UINT32, &vtnr,
+ DBUS_TYPE_BOOLEAN, &exists,
+ DBUS_TYPE_INVALID))
+ return log_oom();
+ }
+
+ /* Update the state file before we notify the client about the
+ * result */
+ session_save(s);
+
+ if (!dbus_connection_send(s->manager->bus, reply, NULL))
+ return log_oom();
+
+ dbus_message_unref(s->create_message);
+ s->create_message = NULL;
+
+ return 0;
+}
diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c
new file mode 100644
index 0000000000..6605935f3c
--- /dev/null
+++ b/src/login/logind-session-device.c
@@ -0,0 +1,483 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ 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/>.
+***/
+
+#include <assert.h>
+#include <fcntl.h>
+#include <libudev.h>
+#include <linux/input.h>
+#include <linux/ioctl.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "dbus-common.h"
+#include "logind-session-device.h"
+#include "util.h"
+#include "missing.h"
+
+enum SessionDeviceNotifications {
+ SESSION_DEVICE_RESUME,
+ SESSION_DEVICE_TRY_PAUSE,
+ SESSION_DEVICE_PAUSE,
+ SESSION_DEVICE_RELEASE,
+};
+
+static void session_device_notify(SessionDevice *sd, enum SessionDeviceNotifications type) {
+ _cleanup_dbus_message_unref_ DBusMessage *m = NULL;
+ _cleanup_free_ char *path = NULL;
+ const char *t = NULL;
+ uint32_t major, minor;
+
+ assert(sd);
+
+ major = major(sd->dev);
+ minor = minor(sd->dev);
+
+ if (!sd->session->controller)
+ return;
+
+ path = session_bus_path(sd->session);
+ if (!path)
+ return;
+
+ m = dbus_message_new_signal(path,
+ "org.freedesktop.login1.Session",
+ (type == SESSION_DEVICE_RESUME) ? "ResumeDevice" : "PauseDevice");
+ if (!m)
+ return;
+
+ if (!dbus_message_set_destination(m, sd->session->controller))
+ return;
+
+ switch (type) {
+ case SESSION_DEVICE_RESUME:
+ if (!dbus_message_append_args(m,
+ DBUS_TYPE_UINT32, &major,
+ DBUS_TYPE_UINT32, &minor,
+ DBUS_TYPE_UNIX_FD, &sd->fd,
+ DBUS_TYPE_INVALID))
+ return;
+ 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;
+ }
+
+ if (t && !dbus_message_append_args(m,
+ DBUS_TYPE_UINT32, &major,
+ DBUS_TYPE_UINT32, &minor,
+ DBUS_TYPE_STRING, &t,
+ DBUS_TYPE_INVALID))
+ return;
+
+ dbus_connection_send(sd->session->manager->bus, m, NULL);
+}
+
+static int sd_eviocrevoke(int fd) {
+ static bool warned;
+ int r;
+
+ assert(fd >= 0);
+
+ r = ioctl(fd, EVIOCREVOKE, 1);
+ if (r < 0) {
+ r = -errno;
+ if (r == -EINVAL && !warned) {
+ 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)
+ 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)
+ return -errno;
+
+ return 0;
+}
+
+static int session_device_open(SessionDevice *sd, bool active) {
+ int fd, r;
+
+ assert(sd->type != DEVICE_TYPE_UNKNOWN);
+
+ /* open device and try to get an udev_device from it */
+ fd = open(sd->node, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
+ if (fd < 0)
+ 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. */
+ r = sd_drmsetmaster(fd);
+ if (r < 0) {
+ close(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);
+ }
+ break;
+ case DEVICE_TYPE_EVDEV:
+ if (!active)
+ sd_eviocrevoke(fd);
+ break;
+ case DEVICE_TYPE_UNKNOWN:
+ default:
+ /* fallback for devices wihout synchronizations */
+ break;
+ }
+
+ return fd;
+}
+
+static int session_device_start(SessionDevice *sd) {
+ int r;
+
+ assert(sd);
+ assert(session_is_active(sd->session));
+
+ if (sd->active)
+ 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(). */
+ 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. */
+ r = session_device_open(sd, true);
+ if (r < 0)
+ return r;
+ close_nointr_nofail(sd->fd);
+ sd->fd = r;
+ break;
+ case DEVICE_TYPE_UNKNOWN:
+ default:
+ /* fallback for devices wihout synchronizations */
+ break;
+ }
+
+ sd->active = true;
+ return 0;
+}
+
+static void session_device_stop(SessionDevice *sd) {
+ assert(sd);
+
+ if (!sd->active)
+ return;
+
+ switch (sd->type) {
+ case DEVICE_TYPE_DRM:
+ /* 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
+ * cannot be undone. Good side is: it needs no CAP_SYS_ADMIN
+ * protection this way. */
+ sd_eviocrevoke(sd->fd);
+ break;
+ case DEVICE_TYPE_UNKNOWN:
+ default:
+ /* fallback for devices without synchronization */
+ break;
+ }
+
+ sd->active = false;
+}
+
+static DeviceType detect_device_type(struct udev_device *dev) {
+ const char *sysname, *subsystem;
+ DeviceType type;
+
+ sysname = udev_device_get_sysname(dev);
+ subsystem = udev_device_get_subsystem(dev);
+ type = DEVICE_TYPE_UNKNOWN;
+
+ if (streq_ptr(subsystem, "drm")) {
+ if (startswith(sysname, "card"))
+ type = DEVICE_TYPE_DRM;
+ } else if (streq_ptr(subsystem, "input")) {
+ if (startswith(sysname, "event"))
+ type = DEVICE_TYPE_EVDEV;
+ }
+
+ return type;
+}
+
+static int session_device_verify(SessionDevice *sd) {
+ struct udev_device *dev, *p = NULL;
+ const char *sp, *node;
+ int r;
+
+ dev = udev_device_new_from_devnum(sd->session->manager->udev, 'c', sd->dev);
+ if (!dev)
+ return -ENODEV;
+
+ sp = udev_device_get_syspath(dev);
+ node = udev_device_get_devnode(dev);
+ if (!node) {
+ r = -EINVAL;
+ goto err_dev;
+ }
+
+ /* detect device type so we can find the correct sysfs parent */
+ sd->type = detect_device_type(dev);
+ if (sd->type == DEVICE_TYPE_UNKNOWN) {
+ r = -ENODEV;
+ goto err_dev;
+ } else if (sd->type == DEVICE_TYPE_EVDEV) {
+ /* for evdev devices we need the parent node as device */
+ p = dev;
+ dev = udev_device_get_parent_with_subsystem_devtype(p, "input", NULL);
+ if (!dev) {
+ r = -ENODEV;
+ goto err_dev;
+ }
+ sp = udev_device_get_syspath(dev);
+ } else if (sd->type != DEVICE_TYPE_DRM) {
+ /* Prevent opening unsupported devices. Especially devices of
+ * subsystem "input" must be opened via the evdev node as
+ * we require EVIOCREVOKE. */
+ r = -ENODEV;
+ goto err_dev;
+ }
+
+ /* search for an existing seat device and return it if available */
+ sd->device = hashmap_get(sd->session->manager->devices, sp);
+ if (!sd->device) {
+ /* The caller might have gotten the udev event before we were
+ * able to process it. Hence, fake the "add" event and let the
+ * logind-manager handle the new device. */
+ r = manager_process_seat_device(sd->session->manager, dev);
+ if (r < 0)
+ goto err_dev;
+
+ /* if it's still not available, then the device is invalid */
+ sd->device = hashmap_get(sd->session->manager->devices, sp);
+ if (!sd->device) {
+ r = -ENODEV;
+ goto err_dev;
+ }
+ }
+
+ if (sd->device->seat != sd->session->seat) {
+ r = -EPERM;
+ goto err_dev;
+ }
+
+ sd->node = strdup(node);
+ if (!sd->node) {
+ r = -ENOMEM;
+ goto err_dev;
+ }
+
+ r = 0;
+err_dev:
+ udev_device_unref(p ? : dev);
+ return r;
+}
+
+int session_device_new(Session *s, dev_t dev, SessionDevice **out) {
+ SessionDevice *sd;
+ int r;
+
+ assert(s);
+ assert(out);
+
+ if (!s->seat)
+ return -EPERM;
+
+ sd = new0(SessionDevice, 1);
+ if (!sd)
+ return -ENOMEM;
+
+ sd->session = s;
+ sd->dev = dev;
+ sd->fd = -1;
+ sd->type = DEVICE_TYPE_UNKNOWN;
+
+ r = session_device_verify(sd);
+ if (r < 0)
+ goto error;
+
+ r = hashmap_put(s->devices, &sd->dev, sd);
+ if (r < 0) {
+ r = -ENOMEM;
+ goto error;
+ }
+
+ /* Open the device for the first time. We need a valid fd to pass back
+ * to the caller. If the session is not active, this _might_ immediately
+ * revoke access and thus invalidate the fd. But this is still needed
+ * to pass a valid fd back. */
+ sd->active = session_is_active(s);
+ r = session_device_open(sd, sd->active);
+ if (r < 0) {
+ /* EINVAL _may_ mean a master is active; retry inactive */
+ if (sd->active && r == -EINVAL) {
+ sd->active = false;
+ r = session_device_open(sd, false);
+ }
+ if (r < 0)
+ goto error;
+ }
+ sd->fd = r;
+
+ LIST_PREPEND(SessionDevice, sd_by_device, sd->device->session_devices, sd);
+
+ *out = sd;
+ return 0;
+
+error:
+ hashmap_remove(s->devices, &sd->dev);
+ free(sd->node);
+ free(sd);
+ return r;
+}
+
+void session_device_free(SessionDevice *sd) {
+ assert(sd);
+
+ session_device_stop(sd);
+ session_device_notify(sd, SESSION_DEVICE_RELEASE);
+ close_nointr_nofail(sd->fd);
+
+ LIST_REMOVE(SessionDevice, sd_by_device, sd->device->session_devices, sd);
+
+ hashmap_remove(sd->session->devices, &sd->dev);
+
+ free(sd->node);
+ free(sd);
+}
+
+void session_device_complete_pause(SessionDevice *sd) {
+ SessionDevice *iter;
+ Iterator i;
+
+ if (!sd->active)
+ return;
+
+ session_device_stop(sd);
+
+ /* if not all devices are paused, wait for further completion events */
+ HASHMAP_FOREACH(iter, sd->session->devices, i)
+ if (iter->active)
+ return;
+
+ /* complete any pending session switch */
+ seat_complete_switch(sd->session->seat);
+}
+
+void session_device_resume_all(Session *s) {
+ SessionDevice *sd;
+ Iterator i;
+ int r;
+
+ assert(s);
+
+ HASHMAP_FOREACH(sd, s->devices, i) {
+ if (!sd->active) {
+ r = session_device_start(sd);
+ if (!r)
+ session_device_notify(sd, SESSION_DEVICE_RESUME);
+ }
+ }
+}
+
+void session_device_pause_all(Session *s) {
+ SessionDevice *sd;
+ Iterator i;
+
+ assert(s);
+
+ HASHMAP_FOREACH(sd, s->devices, i) {
+ if (sd->active) {
+ session_device_stop(sd);
+ session_device_notify(sd, SESSION_DEVICE_PAUSE);
+ }
+ }
+}
+
+unsigned int session_device_try_pause_all(Session *s) {
+ 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;
+ }
+ }
+
+ return num_pending;
+}
diff --git a/src/login/logind-session-device.h b/src/login/logind-session-device.h
new file mode 100644
index 0000000000..61a843d09d
--- /dev/null
+++ b/src/login/logind-session-device.h
@@ -0,0 +1,59 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#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;
+
+#include "list.h"
+#include "util.h"
+#include "logind.h"
+#include "logind-device.h"
+#include "logind-seat.h"
+#include "logind-session.h"
+
+enum DeviceType {
+ DEVICE_TYPE_UNKNOWN,
+ DEVICE_TYPE_DRM,
+ DEVICE_TYPE_EVDEV,
+};
+
+struct SessionDevice {
+ Session *session;
+ Device *device;
+
+ dev_t dev;
+ char *node;
+ int fd;
+ bool active;
+ DeviceType type;
+
+ LIST_FIELDS(struct SessionDevice, sd_by_device);
+};
+
+int session_device_new(Session *s, dev_t dev, SessionDevice **out);
+void session_device_free(SessionDevice *sd);
+void session_device_complete_pause(SessionDevice *sd);
+
+void session_device_resume_all(Session *s);
+void session_device_pause_all(Session *s);
+unsigned int session_device_try_pause_all(Session *s);
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index 662273b07f..27aa335142 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -25,21 +25,38 @@
#include <sys/epoll.h>
#include <fcntl.h>
-#include "systemd/sd-id128.h"
-#include "systemd/sd-messages.h"
+#include <systemd/sd-id128.h>
+#include <systemd/sd-messages.h>
+
#include "strv.h"
#include "util.h"
#include "mkdir.h"
#include "path-util.h"
-#include "cgroup-util.h"
-#include "logind-session.h"
#include "fileio.h"
+#include "dbus-common.h"
+#include "logind-session.h"
+
+static unsigned devt_hash_func(const void *p) {
+ uint64_t u = *(const dev_t*)p;
+
+ return uint64_hash_func(&u);
+}
+
+static int devt_compare_func(const void *_a, const void *_b) {
+ dev_t a, b;
-Session* session_new(Manager *m, User *u, const char *id) {
+ a = *(const dev_t*) _a;
+ b = *(const dev_t*) _b;
+
+ return a < b ? -1 : (a > b ? 1 : 0);
+}
+
+Session* session_new(Manager *m, const char *id) {
Session *s;
assert(m);
assert(id);
+ assert(session_id_valid(id));
s = new0(Session, 1);
if (!s)
@@ -51,9 +68,17 @@ Session* session_new(Manager *m, User *u, const char *id) {
return NULL;
}
+ s->devices = hashmap_new(devt_hash_func, devt_compare_func);
+ if (!s->devices) {
+ free(s->state_file);
+ free(s);
+ return NULL;
+ }
+
s->id = path_get_file_name(s->state_file);
if (hashmap_put(m->sessions, s->id, s) < 0) {
+ hashmap_free(s->devices);
free(s->state_file);
free(s);
return NULL;
@@ -61,19 +86,25 @@ Session* session_new(Manager *m, User *u, const char *id) {
s->manager = m;
s->fifo_fd = -1;
- s->user = u;
-
- LIST_PREPEND(Session, sessions_by_user, u->sessions, s);
return s;
}
void session_free(Session *s) {
+ SessionDevice *sd;
+
assert(s);
if (s->in_gc_queue)
LIST_REMOVE(Session, gc_queue, s->manager->session_gc_queue, s);
+ session_drop_controller(s);
+
+ while ((sd = hashmap_first(s->devices)))
+ session_device_free(sd);
+
+ hashmap_free(s->devices);
+
if (s->user) {
LIST_REMOVE(Session, sessions_by_user, s->user->sessions, s);
@@ -84,15 +115,21 @@ void session_free(Session *s) {
if (s->seat) {
if (s->seat->active == s)
s->seat->active = NULL;
+ if (s->seat->pending_switch == s)
+ s->seat->pending_switch = NULL;
LIST_REMOVE(Session, sessions_by_seat, s->seat->sessions, s);
}
- if (s->cgroup_path)
- hashmap_remove(s->manager->session_cgroups, s->cgroup_path);
+ if (s->scope) {
+ hashmap_remove(s->manager->session_units, s->scope);
+ free(s->scope);
+ }
+
+ free(s->scope_job);
- free(s->cgroup_path);
- strv_free(s->controllers);
+ if (s->create_message)
+ dbus_message_unref(s->create_message);
free(s->tty);
free(s->display);
@@ -107,13 +144,24 @@ void session_free(Session *s) {
free(s);
}
+void session_set_user(Session *s, User *u) {
+ assert(s);
+ assert(!s->user);
+
+ s->user = u;
+ LIST_PREPEND(Session, sessions_by_user, u->sessions, s);
+}
+
int session_save(Session *s) {
- FILE *f;
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *temp_path = NULL;
int r = 0;
- char *temp_path;
assert(s);
+ if (!s->user)
+ return -ESTALE;
+
if (!s->started)
return 0;
@@ -135,79 +183,61 @@ int session_save(Session *s) {
"USER=%s\n"
"ACTIVE=%i\n"
"STATE=%s\n"
- "REMOTE=%i\n"
- "KILL_PROCESSES=%i\n",
+ "REMOTE=%i\n",
(unsigned long) s->user->uid,
s->user->name,
session_is_active(s),
session_state_to_string(session_get_state(s)),
- s->remote,
- s->kill_processes);
+ s->remote);
if (s->type >= 0)
- fprintf(f,
- "TYPE=%s\n",
- session_type_to_string(s->type));
+ fprintf(f, "TYPE=%s\n", session_type_to_string(s->type));
if (s->class >= 0)
- fprintf(f,
- "CLASS=%s\n",
- session_class_to_string(s->class));
+ fprintf(f, "CLASS=%s\n", session_class_to_string(s->class));
- if (s->cgroup_path)
- fprintf(f,
- "CGROUP=%s\n",
- s->cgroup_path);
+ if (s->scope)
+ fprintf(f, "SCOPE=%s\n", s->scope);
+
+ if (s->scope_job)
+ fprintf(f, "SCOPE_JOB=%s\n", s->scope_job);
if (s->fifo_path)
- fprintf(f,
- "FIFO=%s\n",
- s->fifo_path);
+ fprintf(f, "FIFO=%s\n", s->fifo_path);
if (s->seat)
- fprintf(f,
- "SEAT=%s\n",
- s->seat->id);
+ fprintf(f, "SEAT=%s\n", s->seat->id);
if (s->tty)
- fprintf(f,
- "TTY=%s\n",
- s->tty);
+ fprintf(f, "TTY=%s\n", s->tty);
if (s->display)
- fprintf(f,
- "DISPLAY=%s\n",
- s->display);
+ fprintf(f, "DISPLAY=%s\n", s->display);
if (s->remote_host)
- fprintf(f,
- "REMOTE_HOST=%s\n",
- s->remote_host);
+ fprintf(f, "REMOTE_HOST=%s\n", s->remote_host);
if (s->remote_user)
- fprintf(f,
- "REMOTE_USER=%s\n",
- s->remote_user);
+ fprintf(f, "REMOTE_USER=%s\n", s->remote_user);
if (s->service)
- fprintf(f,
- "SERVICE=%s\n",
- s->service);
+ fprintf(f, "SERVICE=%s\n", s->service);
- if (s->seat && seat_can_multi_session(s->seat))
- fprintf(f,
- "VTNR=%i\n",
- s->vtnr);
+ if (s->seat && seat_has_vts(s->seat))
+ fprintf(f, "VTNR=%i\n", s->vtnr);
if (s->leader > 0)
- fprintf(f,
- "LEADER=%lu\n",
- (unsigned long) s->leader);
+ fprintf(f, "LEADER=%lu\n", (unsigned long) s->leader);
if (s->audit_id > 0)
+ fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id);
+
+ if (dual_timestamp_is_set(&s->timestamp))
fprintf(f,
- "AUDIT=%llu\n",
- (unsigned long long) s->audit_id);
+ "REALTIME=%llu\n"
+ "MONOTONIC=%llu\n",
+ (unsigned long long) s->timestamp.realtime,
+ (unsigned long long) s->timestamp.monotonic);
fflush(f);
@@ -217,9 +247,6 @@ int session_save(Session *s) {
unlink(temp_path);
}
- fclose(f);
- free(temp_path);
-
finish:
if (r < 0)
log_error("Failed to save session data for %s: %s", s->id, strerror(-r));
@@ -228,14 +255,15 @@ finish:
}
int session_load(Session *s) {
- char *remote = NULL,
- *kill_processes = NULL,
+ _cleanup_free_ char *remote = NULL,
*seat = NULL,
*vtnr = NULL,
*leader = NULL,
- *audit_id = NULL,
*type = NULL,
- *class = NULL;
+ *class = NULL,
+ *uid = NULL,
+ *realtime = NULL,
+ *monotonic = NULL;
int k, r;
@@ -243,8 +271,8 @@ int session_load(Session *s) {
r = parse_env_file(s->state_file, NEWLINE,
"REMOTE", &remote,
- "KILL_PROCESSES", &kill_processes,
- "CGROUP", &s->cgroup_path,
+ "SCOPE", &s->scope,
+ "SCOPE_JOB", &s->scope_job,
"FIFO", &s->fifo_path,
"SEAT", &seat,
"TTY", &s->tty,
@@ -256,10 +284,39 @@ int session_load(Session *s) {
"LEADER", &leader,
"TYPE", &type,
"CLASS", &class,
+ "UID", &uid,
+ "REALTIME", &realtime,
+ "MONOTONIC", &monotonic,
NULL);
- if (r < 0)
- goto finish;
+ if (r < 0) {
+ log_error("Failed to read %s: %s", s->state_file, strerror(-r));
+ return r;
+ }
+
+ if (!s->user) {
+ uid_t u;
+ User *user;
+
+ if (!uid) {
+ log_error("UID not specified for session %s", s->id);
+ return -ENOENT;
+ }
+
+ r = parse_uid(uid, &u);
+ if (r < 0) {
+ log_error("Failed to parse UID value %s for session %s.", uid, s->id);
+ return r;
+ }
+
+ user = hashmap_get(s->manager->users, ULONG_TO_PTR((unsigned long) u));
+ if (!user) {
+ log_error("User of session %s not known.", s->id);
+ return -ENOENT;
+ }
+
+ session_set_user(s, user);
+ }
if (remote) {
k = parse_boolean(remote);
@@ -267,12 +324,6 @@ int session_load(Session *s) {
s->remote = k;
}
- if (kill_processes) {
- k = parse_boolean(kill_processes);
- if (k >= 0)
- s->kill_processes = k;
- }
-
if (seat && !s->seat) {
Seat *o;
@@ -281,7 +332,7 @@ int session_load(Session *s) {
seat_attach_session(o, s);
}
- if (vtnr && s->seat && seat_can_multi_session(s->seat)) {
+ if (vtnr && s->seat && seat_has_vts(s->seat)) {
int v;
k = safe_atoi(vtnr, &v);
@@ -324,25 +375,26 @@ int session_load(Session *s) {
close_nointr_nofail(fd);
}
-finish:
- free(remote);
- free(kill_processes);
- free(seat);
- free(vtnr);
- free(leader);
- free(audit_id);
- free(class);
+ if (realtime) {
+ unsigned long long l;
+ if (sscanf(realtime, "%llu", &l) > 0)
+ s->timestamp.realtime = l;
+ }
+
+ if (monotonic) {
+ unsigned long long l;
+ if (sscanf(monotonic, "%llu", &l) > 0)
+ s->timestamp.monotonic = l;
+ }
return r;
}
int session_activate(Session *s) {
- int r;
+ unsigned int num_pending;
assert(s);
-
- if (s->vtnr < 0)
- return -ENOTSUP;
+ assert(s->user);
if (!s->seat)
return -ENOTSUP;
@@ -350,17 +402,34 @@ int session_activate(Session *s) {
if (s->seat->active == s)
return 0;
- assert(seat_is_vtconsole(s->seat));
+ /* on seats with VTs, we let VTs manage session-switching */
+ if (seat_has_vts(s->seat)) {
+ if (s->vtnr <= 0)
+ return -ENOTSUP;
- r = chvt(s->vtnr);
- if (r < 0)
- return r;
+ return chvt(s->vtnr);
+ }
+
+ /* On seats without VTs, we implement session-switching in logind. We
+ * try to pause all session-devices and wait until the session
+ * controller acknowledged them. Once all devices are asleep, we simply
+ * switch the active session and be done.
+ * We save the session we want to switch to in seat->pending_switch and
+ * seat_complete_switch() will perform the final switch. */
- return seat_set_active(s->seat, s);
+ s->seat->pending_switch = s;
+
+ /* if no devices are running, immediately perform the session switch */
+ num_pending = session_device_try_pause_all(s);
+ if (!num_pending)
+ seat_complete_switch(s->seat);
+
+ return 0;
}
static int session_link_x11_socket(Session *s) {
- char *t, *f, *c;
+ _cleanup_free_ char *t = NULL, *f = NULL;
+ char *c;
size_t k;
assert(s);
@@ -384,7 +453,6 @@ static int session_link_x11_socket(Session *s) {
if (access(f, F_OK) < 0) {
log_warning("Session %s has display %s with non-existing socket %s.", s->id, s->display, f);
- free(f);
return -ENOENT;
}
@@ -393,10 +461,8 @@ static int session_link_x11_socket(Session *s) {
* path is owned by the user */
t = strappend(s->user->runtime_path, "/X11-display");
- if (!t) {
- free(f);
+ if (!t)
return log_oom();
- }
if (link(f, t) < 0) {
if (errno == EEXIST) {
@@ -416,128 +482,60 @@ static int session_link_x11_socket(Session *s) {
}
log_error("Failed to link %s to %s: %m", f, t);
- free(f);
- free(t);
return -errno;
}
}
done:
log_info("Linked %s to %s.", f, t);
- free(f);
- free(t);
-
s->user->display = s;
return 0;
}
-static int session_create_one_group(Session *s, const char *controller, const char *path) {
- int r;
-
- assert(s);
- assert(path);
-
- if (s->leader > 0) {
- r = cg_create_and_attach(controller, path, s->leader);
- if (r < 0)
- r = cg_create(controller, path, NULL);
- } else
- r = cg_create(controller, path, NULL);
-
- if (r < 0)
- return r;
-
- r = cg_set_task_access(controller, path, 0644, s->user->uid, s->user->gid, -1);
- if (r >= 0)
- r = cg_set_group_access(controller, path, 0755, s->user->uid, s->user->gid);
-
- return r;
-}
-
-static int session_create_cgroup(Session *s) {
- char **k;
- char *p;
+static int session_start_scope(Session *s) {
+ DBusError error;
int r;
assert(s);
assert(s->user);
- assert(s->user->cgroup_path);
+ assert(s->user->slice);
- if (!s->cgroup_path) {
- _cleanup_free_ char *name = NULL, *escaped = NULL;
+ dbus_error_init(&error);
- name = strappend(s->id, ".session");
- if (!name)
- return log_oom();
+ if (!s->scope) {
+ _cleanup_free_ char *description = NULL;
+ const char *kill_mode;
+ char *scope, *job;
- escaped = cg_escape(name);
- if (!escaped)
+ description = strjoin("Session ", s->id, " of user ", s->user->name, NULL);
+ if (!description)
return log_oom();
- p = strjoin(s->user->cgroup_path, "/", escaped, NULL);
- if (!p)
+ scope = strjoin("session-", s->id, ".scope", NULL);
+ if (!scope)
return log_oom();
- } else
- p = s->cgroup_path;
-
- r = session_create_one_group(s, SYSTEMD_CGROUP_CONTROLLER, p);
- if (r < 0) {
- log_error("Failed to create "SYSTEMD_CGROUP_CONTROLLER":%s: %s", p, strerror(-r));
- free(p);
- s->cgroup_path = NULL;
- return r;
- }
-
- s->cgroup_path = p;
- STRV_FOREACH(k, s->controllers) {
+ kill_mode = manager_shall_kill(s->manager, s->user->name) ? "control-group" : "none";
- if (strv_contains(s->reset_controllers, *k))
- continue;
+ r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "systemd-user-sessions.service", kill_mode, &error, &job);
+ if (r < 0) {
+ log_error("Failed to start session scope %s: %s %s",
+ scope, bus_error(&error, r), error.name);
+ dbus_error_free(&error);
- r = session_create_one_group(s, *k, p);
- if (r < 0)
- log_warning("Failed to create %s:%s: %s", *k, p, strerror(-r));
- }
-
- STRV_FOREACH(k, s->manager->controllers) {
-
- if (strv_contains(s->reset_controllers, *k) ||
- strv_contains(s->manager->reset_controllers, *k) ||
- strv_contains(s->controllers, *k))
- continue;
-
- r = session_create_one_group(s, *k, p);
- if (r < 0)
- log_warning("Failed to create %s:%s: %s", *k, p, strerror(-r));
- }
-
- if (s->leader > 0) {
-
- STRV_FOREACH(k, s->reset_controllers) {
- r = cg_attach(*k, "/", s->leader);
- if (r < 0)
- log_warning("Failed to reset controller %s: %s", *k, strerror(-r));
-
- }
-
- STRV_FOREACH(k, s->manager->reset_controllers) {
-
- if (strv_contains(s->reset_controllers, *k) ||
- strv_contains(s->controllers, *k))
- continue;
-
- r = cg_attach(*k, "/", s->leader);
- if (r < 0)
- log_warning("Failed to reset controller %s: %s", *k, strerror(-r));
+ free(scope);
+ return r;
+ } else {
+ s->scope = scope;
+ free(s->scope_job);
+ s->scope_job = job;
}
}
- r = hashmap_put(s->manager->session_cgroups, s->cgroup_path, s);
- if (r < 0)
- log_warning("Failed to create mapping between cgroup and session");
+ if (s->scope)
+ hashmap_put(s->manager->session_units, s->scope, s);
return 0;
}
@@ -546,7 +544,9 @@ int session_start(Session *s) {
int r;
assert(s);
- assert(s->user);
+
+ if (!s->user)
+ return -ESTALE;
if (s->started)
return 0;
@@ -555,6 +555,11 @@ int session_start(Session *s) {
if (r < 0)
return r;
+ /* Create cgroup */
+ r = session_start_scope(s);
+ if (r < 0)
+ return r;
+
log_struct(s->type == SESSION_TTY || s->type == SESSION_X11 ? LOG_INFO : LOG_DEBUG,
MESSAGE_ID(SD_MESSAGE_SESSION_START),
"SESSION_ID=%s", s->id,
@@ -563,15 +568,11 @@ int session_start(Session *s) {
"MESSAGE=New session %s of user %s.", s->id, s->user->name,
NULL);
- /* Create cgroup */
- r = session_create_cgroup(s);
- if (r < 0)
- return r;
-
/* Create X11 symlink */
session_link_x11_socket(s);
- dual_timestamp_get(&s->timestamp);
+ if (!dual_timestamp_is_set(&s->timestamp))
+ dual_timestamp_get(&s->timestamp);
if (s->seat)
seat_read_active_vt(s->seat);
@@ -598,79 +599,33 @@ int session_start(Session *s) {
return 0;
}
-static bool session_shall_kill(Session *s) {
- assert(s);
-
- if (!s->kill_processes)
- return false;
-
- if (strv_contains(s->manager->kill_exclude_users, s->user->name))
- return false;
-
- if (strv_isempty(s->manager->kill_only_users))
- return true;
-
- return strv_contains(s->manager->kill_only_users, s->user->name);
-}
-
-static int session_terminate_cgroup(Session *s) {
+static int session_stop_scope(Session *s) {
+ DBusError error;
+ char *job;
int r;
- char **k;
assert(s);
- if (!s->cgroup_path)
- return 0;
-
- cg_trim(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, false);
+ dbus_error_init(&error);
- if (session_shall_kill(s)) {
-
- r = cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, true);
- if (r < 0)
- log_error("Failed to kill session cgroup: %s", strerror(-r));
-
- } else {
- if (s->leader > 0) {
- Session *t;
-
- /* We still send a HUP to the leader process,
- * even if we are not supposed to kill the
- * whole cgroup. But let's first check the
- * leader still exists and belongs to our
- * session... */
-
- r = manager_get_session_by_pid(s->manager, s->leader, &t);
- if (r > 0 && t == s) {
- kill(s->leader, SIGTERM); /* for normal processes */
- kill(s->leader, SIGHUP); /* for shells */
- kill(s->leader, SIGCONT); /* in case they are stopped */
- }
- }
+ if (!s->scope)
+ return 0;
- r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, true);
- if (r < 0)
- log_error("Failed to check session cgroup: %s", strerror(-r));
- else if (r > 0) {
- r = cg_delete(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path);
- if (r < 0)
- log_error("Failed to delete session cgroup: %s", strerror(-r));
- }
+ r = manager_stop_unit(s->manager, s->scope, &error, &job);
+ if (r < 0) {
+ log_error("Failed to stop session scope: %s", bus_error(&error, r));
+ dbus_error_free(&error);
+ return r;
}
- STRV_FOREACH(k, s->user->manager->controllers)
- cg_trim(*k, s->cgroup_path, true);
-
- hashmap_remove(s->manager->session_cgroups, s->cgroup_path);
-
- free(s->cgroup_path);
- s->cgroup_path = NULL;
+ free(s->scope_job);
+ s->scope_job = job;
return 0;
}
static int session_unlink_x11_socket(Session *s) {
- char *t;
+ _cleanup_free_ char *t = NULL;
int r;
assert(s);
@@ -686,16 +641,34 @@ static int session_unlink_x11_socket(Session *s) {
return log_oom();
r = unlink(t);
- free(t);
-
return r < 0 ? -errno : 0;
}
int session_stop(Session *s) {
- int r = 0, k;
+ int r;
+
+ assert(s);
+
+ if (!s->user)
+ return -ESTALE;
+
+ /* Kill cgroup */
+ r = session_stop_scope(s);
+
+ session_save(s);
+
+ return r;
+}
+
+int session_finalize(Session *s) {
+ int r = 0;
+ SessionDevice *sd;
assert(s);
+ if (!s->user)
+ return -ESTALE;
+
if (s->started)
log_struct(s->type == SESSION_TTY || s->type == SESSION_X11 ? LOG_INFO : LOG_DEBUG,
MESSAGE_ID(SD_MESSAGE_SESSION_STOP),
@@ -705,10 +678,9 @@ int session_stop(Session *s) {
"MESSAGE=Removed session %s.", s->id,
NULL);
- /* Kill cgroup */
- k = session_terminate_cgroup(s);
- if (k < 0)
- r = k;
+ /* Kill session devices */
+ while ((sd = hashmap_first(s->devices)))
+ session_device_free(sd);
/* Remove X11 symlink */
session_unlink_x11_socket(s);
@@ -717,10 +689,10 @@ int session_stop(Session *s) {
session_add_to_gc_queue(s);
user_add_to_gc_queue(s->user);
- if (s->started)
+ if (s->started) {
session_send_signal(s, false);
-
- s->started = false;
+ s->started = false;
+ }
if (s->seat) {
if (s->seat->active == s)
@@ -817,28 +789,6 @@ int session_get_idle_hint(Session *s, dual_timestamp *t) {
goto found_atime;
}
- /* For other TTY sessions, let's find the most recent atime of
- * the ttys of any of the processes of the session */
- if (s->cgroup_path) {
- _cleanup_fclose_ FILE *f = NULL;
-
- if (cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, &f) >= 0) {
- pid_t pid;
-
- atime = 0;
- while (cg_read_pid(f, &pid) > 0) {
- usec_t a;
-
- if (get_process_ctty_atime(pid, &a) >= 0)
- if (atime == 0 || atime < a)
- atime = a;
- }
-
- if (atime != 0)
- goto found_atime;
- }
- }
-
dont_know:
if (t)
*t = s->idle_hint_timestamp;
@@ -961,8 +911,10 @@ int session_check_gc(Session *s, bool drop_not_started) {
if (drop_not_started && !s->started)
return 0;
- if (s->fifo_fd >= 0) {
+ if (!s->user)
+ return 0;
+ if (s->fifo_fd >= 0) {
r = pipe_eof(s->fifo_fd);
if (r < 0)
return r;
@@ -971,15 +923,11 @@ int session_check_gc(Session *s, bool drop_not_started) {
return 1;
}
- if (s->cgroup_path) {
+ if (s->scope_job)
+ return 1;
- r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, false);
- if (r < 0)
- return r;
-
- if (r <= 0)
- return 1;
- }
+ if (s->scope)
+ return manager_unit_is_active(s->manager, s->scope) != 0;
return 0;
}
@@ -997,6 +945,12 @@ void session_add_to_gc_queue(Session *s) {
SessionState session_get_state(Session *s) {
assert(s);
+ if (s->closing)
+ return SESSION_CLOSING;
+
+ if (s->scope_job)
+ return SESSION_OPENING;
+
if (s->fifo_fd < 0)
return SESSION_CLOSING;
@@ -1007,47 +961,69 @@ SessionState session_get_state(Session *s) {
}
int session_kill(Session *s, KillWho who, int signo) {
- int r = 0;
- Set *pid_set = NULL;
-
assert(s);
- if (!s->cgroup_path)
+ if (!s->scope)
return -ESRCH;
- if (s->leader <= 0 && who == KILL_LEADER)
- return -ESRCH;
+ return manager_kill_unit(s->manager, s->scope, who, signo, NULL);
+}
- if (s->leader > 0)
- if (kill(s->leader, signo) < 0)
- r = -errno;
+bool session_is_controller(Session *s, const char *sender)
+{
+ assert(s);
+
+ return streq_ptr(s->controller, sender);
+}
- if (who == KILL_ALL) {
- int q;
+int session_set_controller(Session *s, const char *sender, bool force) {
+ char *t;
+ int r;
- pid_set = set_new(trivial_hash_func, trivial_compare_func);
- if (!pid_set)
- return -ENOMEM;
+ assert(s);
+ assert(sender);
- if (s->leader > 0) {
- q = set_put(pid_set, LONG_TO_PTR(s->leader));
- if (q < 0)
- r = q;
- }
+ if (session_is_controller(s, sender))
+ return 0;
+ if (s->controller && !force)
+ return -EBUSY;
- q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, signo, false, true, false, pid_set);
- if (q < 0)
- if (q != -EAGAIN && q != -ESRCH && q != -ENOENT)
- r = q;
+ t = strdup(sender);
+ if (!t)
+ return -ENOMEM;
+
+ r = manager_watch_busname(s->manager, sender);
+ if (r) {
+ free(t);
+ return r;
}
- if (pid_set)
- set_free(pid_set);
+ session_drop_controller(s);
- return r;
+ s->controller = t;
+ return 0;
+}
+
+void session_drop_controller(Session *s) {
+ SessionDevice *sd;
+
+ assert(s);
+
+ if (!s->controller)
+ return;
+
+ manager_drop_busname(s->manager, s->controller);
+ free(s->controller);
+ s->controller = NULL;
+
+ /* Drop all devices as they're now unused. Do that after the controller
+ * is released to avoid sending out useles dbus signals. */
+ while ((sd = hashmap_first(s->devices)))
+ session_device_free(sd);
}
-static const char* const session_state_table[_SESSION_TYPE_MAX] = {
+static const char* const session_state_table[_SESSION_STATE_MAX] = {
+ [SESSION_OPENING] = "opening",
[SESSION_ONLINE] = "online",
[SESSION_ACTIVE] = "active",
[SESSION_CLOSING] = "closing"
diff --git a/src/login/logind-session.h b/src/login/logind-session.h
index a73df3a3bc..f175a8995e 100644
--- a/src/login/logind-session.h
+++ b/src/login/logind-session.h
@@ -22,17 +22,21 @@
***/
typedef struct Session Session;
+typedef enum KillWho KillWho;
#include "list.h"
#include "util.h"
#include "logind.h"
#include "logind-seat.h"
+#include "logind-session-device.h"
#include "logind-user.h"
+#include "login-shared.h"
typedef enum SessionState {
+ SESSION_OPENING, /* Session scope is being created */
SESSION_ONLINE, /* Logged in */
SESSION_ACTIVE, /* Logged in and in the fg */
- SESSION_CLOSING, /* Logged out, but processes still remain */
+ SESSION_CLOSING, /* Logged out, but scope is still there */
_SESSION_STATE_MAX,
_SESSION_STATE_INVALID = -1
} SessionState;
@@ -54,12 +58,12 @@ typedef enum SessionType {
_SESSION_TYPE_INVALID = -1
} SessionType;
-typedef enum KillWho {
+enum KillWho {
KILL_LEADER,
KILL_ALL,
_KILL_WHO_MAX,
_KILL_WHO_INVALID = -1
-} KillWho;
+};
struct Session {
Manager *manager;
@@ -80,9 +84,11 @@ struct Session {
bool remote;
char *remote_user;
char *remote_host;
-
char *service;
+ char *scope;
+ char *scope_job;
+
int vtnr;
Seat *seat;
@@ -92,15 +98,17 @@ struct Session {
int fifo_fd;
char *fifo_path;
- char *cgroup_path;
- char **controllers, **reset_controllers;
-
bool idle_hint;
dual_timestamp idle_hint_timestamp;
- bool kill_processes;
bool in_gc_queue:1;
bool started:1;
+ bool closing:1;
+
+ DBusMessage *create_message;
+
+ char *controller;
+ Hashmap *devices;
LIST_FIELDS(Session, sessions_by_user);
LIST_FIELDS(Session, sessions_by_seat);
@@ -108,8 +116,9 @@ struct Session {
LIST_FIELDS(Session, gc_queue);
};
-Session *session_new(Manager *m, User *u, const char *id);
+Session *session_new(Manager *m, const char *id);
void session_free(Session *s);
+void session_set_user(Session *s, User *u);
int session_check_gc(Session *s, bool drop_not_started);
void session_add_to_gc_queue(Session *s);
int session_activate(Session *s);
@@ -120,6 +129,7 @@ int session_create_fifo(Session *s);
void session_remove_fifo(Session *s);
int session_start(Session *s);
int session_stop(Session *s);
+int session_finalize(Session *s);
int session_save(Session *s);
int session_load(Session *s);
int session_kill(Session *s, KillWho who, int signo);
@@ -135,6 +145,8 @@ int session_send_changed(Session *s, const char *properties);
int session_send_lock(Session *s, bool lock);
int session_send_lock_all(Manager *m, bool lock);
+int session_send_create_reply(Session *s, DBusError *error);
+
const char* session_state_to_string(SessionState t) _const_;
SessionState session_state_from_string(const char *s) _pure_;
@@ -146,3 +158,7 @@ SessionClass session_class_from_string(const char *s) _pure_;
const char *kill_who_to_string(KillWho k) _const_;
KillWho kill_who_from_string(const char *s) _pure_;
+
+bool session_is_controller(Session *s, const char *sender);
+int session_set_controller(Session *s, const char *sender, bool force);
+void session_drop_controller(Session *s);
diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c
index 3ec3ff8e61..fa2ecba53c 100644
--- a/src/login/logind-user-dbus.c
+++ b/src/login/logind-user-dbus.c
@@ -38,15 +38,15 @@
" <property name=\"Timestamp\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"TimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"RuntimePath\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"DefaultControlGroup\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"Service\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"Slice\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"Display\" type=\"(so)\" access=\"read\"/>\n" \
" <property name=\"State\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"Sessions\" type=\"a(so)\" access=\"read\"/>\n" \
" <property name=\"IdleHint\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"IdleSinceHint\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"IdleSinceHintMonotonic\" type=\"t\" access=\"read\"/>\n" \
- " </interface>\n" \
+ " </interface>\n"
#define INTROSPECTION \
DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
@@ -185,24 +185,6 @@ static int bus_user_append_idle_hint_since(DBusMessageIter *i, const char *prope
return 0;
}
-static int bus_user_append_default_cgroup(DBusMessageIter *i, const char *property, void *data) {
- User *u = data;
- _cleanup_free_ char *t = NULL;
- int r;
- bool success;
-
- assert(i);
- assert(property);
- assert(u);
-
- r = cg_join_spec(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &t);
- if (r < 0)
- return r;
-
- success = dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t);
- return success ? 0 : -ENOMEM;
-}
-
static int get_user_for_path(Manager *m, const char *path, User **_u) {
User *u;
unsigned long lu;
@@ -212,10 +194,10 @@ static int get_user_for_path(Manager *m, const char *path, User **_u) {
assert(path);
assert(_u);
- if (!startswith(path, "/org/freedesktop/login1/user/"))
+ if (!startswith(path, "/org/freedesktop/login1/user/_"))
return -EINVAL;
- r = safe_atolu(path + 29, &lu);
+ r = safe_atolu(path + 30, &lu);
if (r < 0)
return r;
@@ -234,8 +216,8 @@ static const BusProperty bus_login_user_properties[] = {
{ "Timestamp", bus_property_append_usec, "t", offsetof(User, timestamp.realtime) },
{ "TimestampMonotonic", bus_property_append_usec, "t", offsetof(User, timestamp.monotonic) },
{ "RuntimePath", bus_property_append_string, "s", offsetof(User, runtime_path), true },
- { "DefaultControlGroup", bus_user_append_default_cgroup, "s", 0 },
{ "Service", bus_property_append_string, "s", offsetof(User, service), true },
+ { "Slice", bus_property_append_string, "s", offsetof(User, slice), true },
{ "Display", bus_user_append_display, "(so)", 0 },
{ "State", bus_user_append_state, "s", 0 },
{ "Sessions", bus_user_append_sessions, "a(so)", 0 },
@@ -348,7 +330,7 @@ char *user_bus_path(User *u) {
assert(u);
- if (asprintf(&s, "/org/freedesktop/login1/user/%llu", (unsigned long long) u->uid) < 0)
+ if (asprintf(&s, "/org/freedesktop/login1/user/_%llu", (unsigned long long) u->uid) < 0)
return NULL;
return s;
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index 9e2cbf646b..adbe638d46 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -23,13 +23,16 @@
#include <unistd.h>
#include <errno.h>
-#include "logind-user.h"
#include "util.h"
#include "mkdir.h"
#include "cgroup-util.h"
#include "hashmap.h"
#include "strv.h"
#include "fileio.h"
+#include "special.h"
+#include "unit-name.h"
+#include "dbus-common.h"
+#include "logind-user.h"
User* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) {
User *u;
@@ -42,29 +45,27 @@ User* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) {
return NULL;
u->name = strdup(name);
- if (!u->name) {
- free(u);
- return NULL;
- }
+ if (!u->name)
+ goto fail;
- if (asprintf(&u->state_file, "/run/systemd/users/%lu", (unsigned long) uid) < 0) {
- free(u->name);
- free(u);
- return NULL;
- }
+ if (asprintf(&u->state_file, "/run/systemd/users/%lu", (unsigned long) uid) < 0)
+ goto fail;
- if (hashmap_put(m->users, ULONG_TO_PTR((unsigned long) uid), u) < 0) {
- free(u->state_file);
- free(u->name);
- free(u);
- return NULL;
- }
+ if (hashmap_put(m->users, ULONG_TO_PTR((unsigned long) uid), u) < 0)
+ goto fail;
u->manager = m;
u->uid = uid;
u->gid = gid;
return u;
+
+fail:
+ free(u->state_file);
+ free(u->name);
+ free(u);
+
+ return NULL;
}
void user_free(User *u) {
@@ -76,11 +77,19 @@ void user_free(User *u) {
while (u->sessions)
session_free(u->sessions);
- if (u->cgroup_path)
- hashmap_remove(u->manager->user_cgroups, u->cgroup_path);
- free(u->cgroup_path);
+ if (u->slice) {
+ hashmap_remove(u->manager->user_units, u->slice);
+ free(u->slice);
+ }
+
+ if (u->service) {
+ hashmap_remove(u->manager->user_units, u->service);
+ free(u->service);
+ }
+
+ free(u->slice_job);
+ free(u->service_job);
- free(u->service);
free(u->runtime_path);
hashmap_remove(u->manager->users, ULONG_TO_PTR((unsigned long) u->uid));
@@ -91,9 +100,9 @@ void user_free(User *u) {
}
int user_save(User *u) {
- FILE *f;
+ _cleanup_free_ char *temp_path = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
int r;
- char *temp_path;
assert(u);
assert(u->state_file);
@@ -118,25 +127,28 @@ int user_save(User *u) {
u->name,
user_state_to_string(user_get_state(u)));
- if (u->cgroup_path)
- fprintf(f,
- "CGROUP=%s\n",
- u->cgroup_path);
-
if (u->runtime_path)
- fprintf(f,
- "RUNTIME=%s\n",
- u->runtime_path);
+ fprintf(f, "RUNTIME=%s\n", u->runtime_path);
if (u->service)
- fprintf(f,
- "SERVICE=%s\n",
- u->service);
+ fprintf(f, "SERVICE=%s\n", u->service);
+ if (u->service_job)
+ fprintf(f, "SERVICE_JOB=%s\n", u->service_job);
+
+ if (u->slice)
+ fprintf(f, "SLICE=%s\n", u->slice);
+ if (u->slice_job)
+ fprintf(f, "SLICE_JOB=%s\n", u->slice_job);
if (u->display)
+ fprintf(f, "DISPLAY=%s\n", u->display->id);
+
+ if (dual_timestamp_is_set(&u->timestamp))
fprintf(f,
- "DISPLAY=%s\n",
- u->display->id);
+ "REALTIME=%llu\n"
+ "MONOTONIC=%llu\n",
+ (unsigned long long) u->timestamp.realtime,
+ (unsigned long long) u->timestamp.monotonic);
if (u->sessions) {
Session *i;
@@ -233,9 +245,6 @@ int user_save(User *u) {
unlink(temp_path);
}
- fclose(f);
- free(temp_path);
-
finish:
if (r < 0)
log_error("Failed to save user data for %s: %s", u->name, strerror(-r));
@@ -244,21 +253,23 @@ finish:
}
int user_load(User *u) {
- int r;
- char *display = NULL;
+ _cleanup_free_ char *display = NULL, *realtime = NULL, *monotonic = NULL;
Session *s = NULL;
+ int r;
assert(u);
r = parse_env_file(u->state_file, NEWLINE,
- "CGROUP", &u->cgroup_path,
- "RUNTIME", &u->runtime_path,
- "SERVICE", &u->service,
- "DISPLAY", &display,
+ "RUNTIME", &u->runtime_path,
+ "SERVICE", &u->service,
+ "SERVICE_JOB", &u->service_job,
+ "SLICE", &u->slice,
+ "SLICE_JOB", &u->slice_job,
+ "DISPLAY", &display,
+ "REALTIME", &realtime,
+ "MONOTONIC", &monotonic,
NULL);
if (r < 0) {
- free(display);
-
if (r == -ENOENT)
return 0;
@@ -266,14 +277,24 @@ int user_load(User *u) {
return r;
}
- if (display) {
+ if (display)
s = hashmap_get(u->manager->sessions, display);
- free(display);
- }
if (s && s->display && display_is_local(s->display))
u->display = s;
+ if (realtime) {
+ unsigned long long l;
+ if (sscanf(realtime, "%llu", &l) > 0)
+ u->timestamp.realtime = l;
+ }
+
+ if (monotonic) {
+ unsigned long long l;
+ if (sscanf(monotonic, "%llu", &l) > 0)
+ u->timestamp.monotonic = l;
+ }
+
return r;
}
@@ -307,60 +328,76 @@ static int user_mkdir_runtime_path(User *u) {
return 0;
}
-static int user_create_cgroup(User *u) {
- char **k;
- char *p;
+static int user_start_slice(User *u) {
+ DBusError error;
+ char *job;
int r;
assert(u);
- if (!u->cgroup_path) {
- _cleanup_free_ char *name = NULL, *escaped = NULL;
-
- if (asprintf(&name, "%lu.user", (unsigned long) u->uid) < 0)
- return log_oom();
-
- escaped = cg_escape(name);
- if (!escaped)
- return log_oom();
-
- p = strjoin(u->manager->cgroup_path, "/", escaped, NULL);
- if (!p)
- return log_oom();
- } else
- p = u->cgroup_path;
+ dbus_error_init(&error);
- r = cg_create(SYSTEMD_CGROUP_CONTROLLER, p, NULL);
- if (r < 0) {
- log_error("Failed to create cgroup "SYSTEMD_CGROUP_CONTROLLER":%s: %s", p, strerror(-r));
- free(p);
- u->cgroup_path = NULL;
- return r;
- }
+ if (!u->slice) {
+ char lu[DECIMAL_STR_MAX(unsigned long) + 1], *slice;
+ sprintf(lu, "%lu", (unsigned long) u->uid);
- u->cgroup_path = p;
+ r = build_subslice(SPECIAL_USER_SLICE, lu, &slice);
+ if (r < 0)
+ return r;
- STRV_FOREACH(k, u->manager->controllers) {
+ r = manager_start_unit(u->manager, slice, &error, &job);
+ if (r < 0) {
+ log_error("Failed to start user slice: %s", bus_error(&error, r));
+ dbus_error_free(&error);
- if (strv_contains(u->manager->reset_controllers, *k))
- continue;
+ free(slice);
+ } else {
+ u->slice = slice;
- r = cg_create(*k, p, NULL);
- if (r < 0)
- log_warning("Failed to create cgroup %s:%s: %s", *k, p, strerror(-r));
+ free(u->slice_job);
+ u->slice_job = job;
+ }
}
- r = hashmap_put(u->manager->user_cgroups, u->cgroup_path, u);
- if (r < 0)
- log_warning("Failed to create mapping between cgroup and user");
+ if (u->slice)
+ hashmap_put(u->manager->user_units, u->slice, u);
return 0;
}
static int user_start_service(User *u) {
+ DBusError error;
+ char *job;
+ int r;
+
assert(u);
- /* FIXME: Fill me in later ... */
+ dbus_error_init(&error);
+
+ if (!u->service) {
+ char lu[DECIMAL_STR_MAX(unsigned long) + 1], *service;
+ sprintf(lu, "%lu", (unsigned long) u->uid);
+
+ service = unit_name_build("user", lu, ".service");
+ if (!service)
+ return log_oom();
+
+ r = manager_start_unit(u->manager, service, &error, &job);
+ if (r < 0) {
+ log_error("Failed to start user service: %s", bus_error(&error, r));
+ dbus_error_free(&error);
+
+ free(service);
+ } else {
+ u->service = service;
+
+ free(u->service_job);
+ u->service_job = job;
+ }
+ }
+
+ if (u->service)
+ hashmap_put(u->manager->user_units, u->service, u);
return 0;
}
@@ -381,7 +418,7 @@ int user_start(User *u) {
return r;
/* Create cgroup */
- r = user_create_cgroup(u);
+ r = user_start_slice(u);
if (r < 0)
return r;
@@ -390,7 +427,8 @@ int user_start(User *u) {
if (r < 0)
return r;
- dual_timestamp_get(&u->timestamp);
+ if (!dual_timestamp_is_set(&u->timestamp))
+ dual_timestamp_get(&u->timestamp);
u->started = true;
@@ -402,66 +440,52 @@ int user_start(User *u) {
return 0;
}
-static int user_stop_service(User *u) {
- assert(u);
-
- if (!u->service)
- return 0;
-
- return 0;
-}
+static int user_stop_slice(User *u) {
+ DBusError error;
+ char *job;
+ int r;
-static int user_shall_kill(User *u) {
assert(u);
- if (!u->manager->kill_user_processes)
- return false;
+ dbus_error_init(&error);
+
+ if (!u->slice)
+ return 0;
- if (strv_contains(u->manager->kill_exclude_users, u->name))
- return false;
+ r = manager_stop_unit(u->manager, u->slice, &error, &job);
+ if (r < 0) {
+ log_error("Failed to stop user slice: %s", bus_error(&error, r));
+ dbus_error_free(&error);
+ return r;
+ }
- if (strv_isempty(u->manager->kill_only_users))
- return true;
+ free(u->slice_job);
+ u->slice_job = job;
- return strv_contains(u->manager->kill_only_users, u->name);
+ return r;
}
-static int user_terminate_cgroup(User *u) {
+static int user_stop_service(User *u) {
+ DBusError error;
+ char *job;
int r;
- char **k;
assert(u);
- if (!u->cgroup_path)
- return 0;
-
- cg_trim(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, false);
-
- if (user_shall_kill(u)) {
+ dbus_error_init(&error);
- r = cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
- if (r < 0)
- log_error("Failed to kill user cgroup: %s", strerror(-r));
- } else {
+ if (!u->service)
+ return 0;
- r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
- if (r < 0)
- log_error("Failed to check user cgroup: %s", strerror(-r));
- else if (r > 0) {
- r = cg_delete(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path);
- if (r < 0)
- log_error("Failed to delete user cgroup: %s", strerror(-r));
- } else
- r = -EBUSY;
+ r = manager_stop_unit(u->manager, u->service, &error, &job);
+ if (r < 0) {
+ log_error("Failed to stop user service: %s", bus_error(&error, r));
+ dbus_error_free(&error);
+ return r;
}
- STRV_FOREACH(k, u->manager->controllers)
- cg_trim(*k, u->cgroup_path, true);
-
- hashmap_remove(u->manager->user_cgroups, u->cgroup_path);
-
- free(u->cgroup_path);
- u->cgroup_path = NULL;
+ free(u->service_job);
+ u->service_job = job;
return r;
}
@@ -489,9 +513,6 @@ int user_stop(User *u) {
int r = 0, k;
assert(u);
- if (u->started)
- log_debug("User %s logged out.", u->name);
-
LIST_FOREACH(sessions_by_user, s, u->sessions) {
k = session_stop(s);
if (k < 0)
@@ -504,10 +525,30 @@ int user_stop(User *u) {
r = k;
/* Kill cgroup */
- k = user_terminate_cgroup(u);
+ k = user_stop_slice(u);
if (k < 0)
r = k;
+ user_save(u);
+
+ return r;
+}
+
+int user_finalize(User *u) {
+ Session *s;
+ int r = 0, k;
+
+ assert(u);
+
+ if (u->started)
+ log_debug("User %s logged out.", u->name);
+
+ LIST_FOREACH(sessions_by_user, s, u->sessions) {
+ k = session_finalize(s);
+ if (k < 0)
+ r = k;
+ }
+
/* Kill XDG_RUNTIME_DIR */
k = user_remove_runtime_path(u);
if (k < 0)
@@ -516,10 +557,10 @@ int user_stop(User *u) {
unlink(u->state_file);
user_add_to_gc_queue(u);
- if (u->started)
+ if (u->started) {
user_send_signal(u, false);
-
- u->started = false;
+ u->started = false;
+ }
return r;
}
@@ -574,8 +615,6 @@ static int user_check_linger_file(User *u) {
}
int user_check_gc(User *u, bool drop_not_started) {
- int r;
-
assert(u);
if (drop_not_started && !u->started)
@@ -587,14 +626,14 @@ int user_check_gc(User *u, bool drop_not_started) {
if (user_check_linger_file(u) > 0)
return 1;
- if (u->cgroup_path) {
- r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, false);
- if (r < 0)
- return r;
+ if (u->slice_job || u->service_job)
+ return 1;
- if (r <= 0)
- return 1;
- }
+ if (u->slice && manager_unit_is_active(u->manager, u->slice) != 0)
+ return 1;
+
+ if (u->service && manager_unit_is_active(u->manager, u->service) != 0)
+ return 1;
return 0;
}
@@ -615,6 +654,11 @@ UserState user_get_state(User *u) {
assert(u);
+ if (u->closing)
+ return USER_CLOSING;
+
+ if (u->slice_job || u->service_job)
+ return USER_OPENING;
LIST_FOREACH(sessions_by_user, i, u->sessions) {
if (session_is_active(i))
@@ -633,31 +677,17 @@ UserState user_get_state(User *u) {
}
int user_kill(User *u, int signo) {
- int r = 0, q;
- Set *pid_set = NULL;
-
assert(u);
- if (!u->cgroup_path)
+ if (!u->slice)
return -ESRCH;
- pid_set = set_new(trivial_hash_func, trivial_compare_func);
- if (!pid_set)
- return -ENOMEM;
-
- q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, false, true, false, pid_set);
- if (q < 0)
- if (q != -EAGAIN && q != -ESRCH && q != -ENOENT)
- r = q;
-
- if (pid_set)
- set_free(pid_set);
-
- return r;
+ return manager_kill_unit(u->manager, u->slice, KILL_ALL, signo, NULL);
}
static const char* const user_state_table[_USER_STATE_MAX] = {
[USER_OFFLINE] = "offline",
+ [USER_OPENING] = "opening",
[USER_LINGERING] = "lingering",
[USER_ONLINE] = "online",
[USER_ACTIVE] = "active",
diff --git a/src/login/logind-user.h b/src/login/logind-user.h
index 080354da74..b9171d345d 100644
--- a/src/login/logind-user.h
+++ b/src/login/logind-user.h
@@ -30,6 +30,7 @@ typedef struct User User;
typedef enum UserState {
USER_OFFLINE, /* Not logged in at all */
+ USER_OPENING, /* Is logging in */
USER_LINGERING, /* Lingering has been enabled by the admin for this user */
USER_ONLINE, /* User logged in */
USER_ACTIVE, /* User logged in and has a session in the fg */
@@ -47,8 +48,12 @@ struct User {
char *state_file;
char *runtime_path;
+
char *service;
- char *cgroup_path;
+ char *slice;
+
+ char *service_job;
+ char *slice_job;
Session *display;
@@ -56,6 +61,7 @@ struct User {
bool in_gc_queue:1;
bool started:1;
+ bool closing:1;
LIST_HEAD(Session, sessions);
LIST_FIELDS(User, gc_queue);
@@ -67,6 +73,7 @@ int user_check_gc(User *u, bool drop_not_started);
void user_add_to_gc_queue(User *u);
int user_start(User *u);
int user_stop(User *u);
+int user_finalize(User *u);
UserState user_get_state(User *u);
int user_get_idle_hint(User *u, dual_timestamp *t);
int user_save(User *u);
diff --git a/src/login/logind.c b/src/login/logind.c
index 5a394401dc..0628032ae5 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -20,13 +20,11 @@
***/
#include <errno.h>
-#include <pwd.h>
#include <libudev.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/epoll.h>
-#include <sys/ioctl.h>
#include <linux/vt.h>
#include <sys/timerfd.h>
@@ -74,24 +72,24 @@ Manager *manager_new(void) {
m->users = hashmap_new(trivial_hash_func, trivial_compare_func);
m->inhibitors = hashmap_new(string_hash_func, string_compare_func);
m->buttons = hashmap_new(string_hash_func, string_compare_func);
+ m->busnames = hashmap_new(string_hash_func, string_compare_func);
- m->user_cgroups = hashmap_new(string_hash_func, string_compare_func);
- m->session_cgroups = hashmap_new(string_hash_func, string_compare_func);
+ m->user_units = hashmap_new(string_hash_func, string_compare_func);
+ m->session_units = hashmap_new(string_hash_func, string_compare_func);
m->session_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
m->inhibitor_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
m->button_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
- if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons ||
- !m->user_cgroups || !m->session_cgroups ||
+ if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->busnames ||
+ !m->user_units || !m->session_units ||
!m->session_fds || !m->inhibitor_fds || !m->button_fds) {
manager_free(m);
return NULL;
}
- m->reset_controllers = strv_new("cpu", NULL);
m->kill_exclude_users = strv_new("root", NULL);
- if (!m->reset_controllers || !m->kill_exclude_users) {
+ if (!m->kill_exclude_users) {
manager_free(m);
return NULL;
}
@@ -102,11 +100,6 @@ Manager *manager_new(void) {
return NULL;
}
- if (cg_get_user_path(&m->cgroup_path) < 0) {
- manager_free(m);
- return NULL;
- }
-
return m;
}
@@ -117,6 +110,7 @@ void manager_free(Manager *m) {
Seat *s;
Inhibitor *i;
Button *b;
+ char *n;
assert(m);
@@ -138,15 +132,19 @@ void manager_free(Manager *m) {
while ((b = hashmap_first(m->buttons)))
button_free(b);
+ while ((n = hashmap_first(m->busnames)))
+ free(hashmap_remove(m->busnames, n));
+
hashmap_free(m->devices);
hashmap_free(m->seats);
hashmap_free(m->sessions);
hashmap_free(m->users);
hashmap_free(m->inhibitors);
hashmap_free(m->buttons);
+ hashmap_free(m->busnames);
- hashmap_free(m->user_cgroups);
- hashmap_free(m->session_cgroups);
+ hashmap_free(m->user_units);
+ hashmap_free(m->session_units);
hashmap_free(m->session_fds);
hashmap_free(m->inhibitor_fds);
@@ -157,6 +155,8 @@ void manager_free(Manager *m) {
if (m->udev_seat_monitor)
udev_monitor_unref(m->udev_seat_monitor);
+ if (m->udev_device_monitor)
+ udev_monitor_unref(m->udev_device_monitor);
if (m->udev_vcsa_monitor)
udev_monitor_unref(m->udev_vcsa_monitor);
if (m->udev_button_monitor)
@@ -183,269 +183,13 @@ void manager_free(Manager *m) {
if (m->idle_action_fd >= 0)
close_nointr_nofail(m->idle_action_fd);
- strv_free(m->controllers);
- strv_free(m->reset_controllers);
strv_free(m->kill_only_users);
strv_free(m->kill_exclude_users);
free(m->action_job);
-
- free(m->cgroup_path);
free(m);
}
-int manager_add_device(Manager *m, const char *sysfs, Device **_device) {
- Device *d;
-
- assert(m);
- assert(sysfs);
-
- d = hashmap_get(m->devices, sysfs);
- if (d) {
- if (_device)
- *_device = d;
-
- return 0;
- }
-
- d = device_new(m, sysfs);
- if (!d)
- return -ENOMEM;
-
- if (_device)
- *_device = d;
-
- return 0;
-}
-
-int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
- Seat *s;
-
- assert(m);
- assert(id);
-
- s = hashmap_get(m->seats, id);
- if (s) {
- if (_seat)
- *_seat = s;
-
- return 0;
- }
-
- s = seat_new(m, id);
- if (!s)
- return -ENOMEM;
-
- if (_seat)
- *_seat = s;
-
- return 0;
-}
-
-int manager_add_session(Manager *m, User *u, const char *id, Session **_session) {
- Session *s;
-
- assert(m);
- assert(id);
-
- s = hashmap_get(m->sessions, id);
- if (s) {
- if (_session)
- *_session = s;
-
- return 0;
- }
-
- s = session_new(m, u, id);
- if (!s)
- return -ENOMEM;
-
- if (_session)
- *_session = s;
-
- return 0;
-}
-
-int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
- User *u;
-
- assert(m);
- assert(name);
-
- u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
- if (u) {
- if (_user)
- *_user = u;
-
- return 0;
- }
-
- u = user_new(m, uid, gid, name);
- if (!u)
- return -ENOMEM;
-
- if (_user)
- *_user = u;
-
- return 0;
-}
-
-int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
- uid_t uid;
- gid_t gid;
- int r;
-
- assert(m);
- assert(name);
-
- r = get_user_creds(&name, &uid, &gid, NULL, NULL);
- if (r < 0)
- return r;
-
- return manager_add_user(m, uid, gid, name, _user);
-}
-
-int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
- struct passwd *p;
-
- assert(m);
-
- errno = 0;
- p = getpwuid(uid);
- if (!p)
- return errno ? -errno : -ENOENT;
-
- return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
-}
-
-int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
- Inhibitor *i;
-
- assert(m);
- assert(id);
-
- i = hashmap_get(m->inhibitors, id);
- if (i) {
- if (_inhibitor)
- *_inhibitor = i;
-
- return 0;
- }
-
- i = inhibitor_new(m, id);
- if (!i)
- return -ENOMEM;
-
- if (_inhibitor)
- *_inhibitor = i;
-
- return 0;
-}
-
-int manager_add_button(Manager *m, const char *name, Button **_button) {
- Button *b;
-
- assert(m);
- assert(name);
-
- b = hashmap_get(m->buttons, name);
- if (b) {
- if (_button)
- *_button = b;
-
- return 0;
- }
-
- b = button_new(m, name);
- if (!b)
- return -ENOMEM;
-
- if (_button)
- *_button = b;
-
- return 0;
-}
-
-int manager_process_seat_device(Manager *m, struct udev_device *d) {
- Device *device;
- int r;
-
- assert(m);
-
- if (streq_ptr(udev_device_get_action(d), "remove")) {
-
- device = hashmap_get(m->devices, udev_device_get_syspath(d));
- if (!device)
- return 0;
-
- seat_add_to_gc_queue(device->seat);
- device_free(device);
-
- } else {
- const char *sn;
- Seat *seat;
-
- sn = udev_device_get_property_value(d, "ID_SEAT");
- if (isempty(sn))
- sn = "seat0";
-
- if (!seat_name_is_valid(sn)) {
- log_warning("Device with invalid seat name %s found, ignoring.", sn);
- return 0;
- }
-
- r = manager_add_device(m, udev_device_get_syspath(d), &device);
- if (r < 0)
- return r;
-
- r = manager_add_seat(m, sn, &seat);
- if (r < 0) {
- if (!device->seat)
- device_free(device);
-
- return r;
- }
-
- device_attach(device, seat);
- seat_start(seat);
- }
-
- return 0;
-}
-
-int manager_process_button_device(Manager *m, struct udev_device *d) {
- Button *b;
-
- int r;
-
- assert(m);
-
- if (streq_ptr(udev_device_get_action(d), "remove")) {
-
- b = hashmap_get(m->buttons, udev_device_get_sysname(d));
- if (!b)
- return 0;
-
- button_free(b);
-
- } else {
- const char *sn;
-
- r = manager_add_button(m, udev_device_get_sysname(d), &b);
- if (r < 0)
- return r;
-
- sn = udev_device_get_property_value(d, "ID_SEAT");
- if (isempty(sn))
- sn = "seat0";
-
- button_set_seat(b, sn);
- button_open(b);
- }
-
- return 0;
-}
-
int manager_enumerate_devices(Manager *m) {
struct udev_list_entry *item = NULL, *first = NULL;
struct udev_enumerate *e;
@@ -554,7 +298,7 @@ finish:
}
int manager_enumerate_seats(Manager *m) {
- DIR *d;
+ _cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
int r = 0;
@@ -573,7 +317,7 @@ int manager_enumerate_seats(Manager *m) {
return -errno;
}
- while ((de = readdir(d))) {
+ FOREACH_DIRENT(de, d, return -errno) {
Seat *s;
int k;
@@ -591,66 +335,16 @@ int manager_enumerate_seats(Manager *m) {
r = k;
}
- closedir(d);
-
- return r;
-}
-
-static int manager_enumerate_users_from_cgroup(Manager *m) {
- _cleanup_closedir_ DIR *d = NULL;
- int r = 0, k;
- char *name;
-
- r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_path, &d);
- if (r < 0) {
- if (r == -ENOENT)
- return 0;
-
- log_error("Failed to open %s: %s", m->cgroup_path, strerror(-r));
- return r;
- }
-
- while ((k = cg_read_subgroup(d, &name)) > 0) {
- User *user;
- char *e;
-
- e = endswith(name, ".user");
- if (e) {
- *e = 0;
-
- k = manager_add_user_by_name(m, name, &user);
- if (k < 0) {
- free(name);
- r = k;
- continue;
- }
-
- user_add_to_gc_queue(user);
-
- if (!user->cgroup_path) {
- user->cgroup_path = strjoin(m->cgroup_path, "/", name, NULL);
- if (!user->cgroup_path) {
- k = log_oom();
- free(name);
- break;
- }
- }
- }
-
- free(name);
- }
-
- if (k < 0)
- r = k;
-
return r;
}
static int manager_enumerate_linger_users(Manager *m) {
- DIR *d;
+ _cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
int r = 0;
+ assert(m);
+
d = opendir("/var/lib/systemd/linger");
if (!d) {
if (errno == ENOENT)
@@ -660,7 +354,7 @@ static int manager_enumerate_linger_users(Manager *m) {
return -errno;
}
- while ((de = readdir(d))) {
+ FOREACH_DIRENT(de, d, return -errno) {
int k;
if (!dirent_is_file(de))
@@ -673,27 +367,20 @@ static int manager_enumerate_linger_users(Manager *m) {
}
}
- closedir(d);
-
return r;
}
int manager_enumerate_users(Manager *m) {
- DIR *d;
+ _cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
int r, k;
assert(m);
- /* First, enumerate user cgroups */
- r = manager_enumerate_users_from_cgroup(m);
+ /* Add lingering users */
+ r = manager_enumerate_linger_users(m);
- /* Second, add lingering users on top */
- k = manager_enumerate_linger_users(m);
- if (k < 0)
- r = k;
-
- /* Third, read in user data stored on disk */
+ /* Read in user data stored on disk */
d = opendir("/run/systemd/users");
if (!d) {
if (errno == ENOENT)
@@ -703,88 +390,23 @@ int manager_enumerate_users(Manager *m) {
return -errno;
}
- while ((de = readdir(d))) {
- uid_t uid;
+ FOREACH_DIRENT(de, d, return -errno) {
User *u;
if (!dirent_is_file(de))
continue;
- k = parse_uid(de->d_name, &uid);
+ k = manager_add_user_by_name(m, de->d_name, &u);
if (k < 0) {
- log_error("Failed to parse file name %s: %s", de->d_name, strerror(-k));
- continue;
- }
-
- u = hashmap_get(m->users, ULONG_TO_PTR(uid));
- if (!u) {
- unlinkat(dirfd(d), de->d_name, 0);
- continue;
- }
+ log_error("Failed to add user by file name %s: %s", de->d_name, strerror(-k));
- k = user_load(u);
- if (k < 0)
- r = k;
- }
-
- closedir(d);
-
- return r;
-}
-
-static int manager_enumerate_sessions_from_cgroup(Manager *m) {
- User *u;
- Iterator i;
- int r = 0;
-
- HASHMAP_FOREACH(u, m->users, i) {
- _cleanup_closedir_ DIR *d = NULL;
- char *name;
- int k;
-
- if (!u->cgroup_path)
- continue;
-
- k = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &d);
- if (k < 0) {
- if (k == -ENOENT)
- continue;
-
- log_error("Failed to open %s: %s", u->cgroup_path, strerror(-k));
r = k;
continue;
}
- while ((k = cg_read_subgroup(d, &name)) > 0) {
- Session *session;
- char *e;
-
- e = endswith(name, ".session");
- if (e) {
- *e = 0;
-
- k = manager_add_session(m, u, name, &session);
- if (k < 0) {
- free(name);
- r = k;
- continue;
- }
-
- session_add_to_gc_queue(session);
-
- if (!session->cgroup_path) {
- session->cgroup_path = strjoin(m->cgroup_path, "/", name, NULL);
- if (!session->cgroup_path) {
- k = log_oom();
- free(name);
- break;
- }
- }
- }
-
- free(name);
- }
+ user_add_to_gc_queue(u);
+ k = user_load(u);
if (k < 0)
r = k;
}
@@ -793,16 +415,13 @@ static int manager_enumerate_sessions_from_cgroup(Manager *m) {
}
int manager_enumerate_sessions(Manager *m) {
- DIR *d;
+ _cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
int r = 0;
assert(m);
- /* First enumerate session cgroups */
- r = manager_enumerate_sessions_from_cgroup(m);
-
- /* Second, read in session data stored on disk */
+ /* Read in session data stored on disk */
d = opendir("/run/systemd/sessions");
if (!d) {
if (errno == ENOENT)
@@ -812,31 +431,39 @@ int manager_enumerate_sessions(Manager *m) {
return -errno;
}
- while ((de = readdir(d))) {
+ FOREACH_DIRENT(de, d, return -errno) {
struct Session *s;
int k;
if (!dirent_is_file(de))
continue;
- s = hashmap_get(m->sessions, de->d_name);
- if (!s) {
- unlinkat(dirfd(d), de->d_name, 0);
+ if (!session_id_valid(de->d_name)) {
+ log_warning("Invalid session file name '%s', ignoring.", de->d_name);
+ r = -EINVAL;
+ continue;
+ }
+
+ k = manager_add_session(m, de->d_name, &s);
+ if (k < 0) {
+ log_error("Failed to add session by file name %s: %s", de->d_name, strerror(-k));
+
+ r = k;
continue;
}
+ session_add_to_gc_queue(s);
+
k = session_load(s);
if (k < 0)
r = k;
}
- closedir(d);
-
return r;
}
int manager_enumerate_inhibitors(Manager *m) {
- DIR *d;
+ _cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
int r = 0;
@@ -851,7 +478,7 @@ int manager_enumerate_inhibitors(Manager *m) {
return -errno;
}
- while ((de = readdir(d))) {
+ FOREACH_DIRENT(de, d, return -errno) {
int k;
Inhibitor *i;
@@ -870,8 +497,6 @@ int manager_enumerate_inhibitors(Manager *m) {
r = k;
}
- closedir(d);
-
return r;
}
@@ -891,6 +516,22 @@ int manager_dispatch_seat_udev(Manager *m) {
return r;
}
+static int manager_dispatch_device_udev(Manager *m) {
+ struct udev_device *d;
+ int r;
+
+ assert(m);
+
+ d = udev_monitor_receive_device(m->udev_device_monitor);
+ if (!d)
+ return -ENOMEM;
+
+ r = manager_process_seat_device(m, d);
+ udev_device_unref(d);
+
+ return r;
+}
+
int manager_dispatch_vcsa_udev(Manager *m) {
struct udev_device *d;
int r = 0;
@@ -908,7 +549,7 @@ int manager_dispatch_vcsa_udev(Manager *m) {
* VTs, to make sure our auto VTs never go away. */
if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
- r = seat_preallocate_vts(m->vtconsole);
+ r = seat_preallocate_vts(m->seat0);
udev_device_unref(d);
@@ -933,87 +574,13 @@ int manager_dispatch_button_udev(Manager *m) {
int manager_dispatch_console(Manager *m) {
assert(m);
+ assert(m->seat0);
- if (m->vtconsole)
- seat_read_active_vt(m->vtconsole);
+ seat_read_active_vt(m->seat0);
return 0;
}
-static int vt_is_busy(int vtnr) {
- struct vt_stat vt_stat;
- int r = 0, fd;
-
- assert(vtnr >= 1);
-
- /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
- * we'd open the latter we'd open the foreground tty which
- * hence would be unconditionally busy. By opening /dev/tty1
- * we avoid this. Since tty1 is special and needs to be an
- * explicitly loaded getty or DM this is safe. */
-
- fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return -errno;
-
- if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
- r = -errno;
- else
- r = !!(vt_stat.v_state & (1 << vtnr));
-
- close_nointr_nofail(fd);
-
- return r;
-}
-
-int manager_spawn_autovt(Manager *m, int vtnr) {
- int r;
- char *name = NULL;
- const char *mode = "fail";
-
- assert(m);
- assert(vtnr >= 1);
-
- if ((unsigned) vtnr > m->n_autovts &&
- (unsigned) vtnr != m->reserve_vt)
- return 0;
-
- if ((unsigned) vtnr != m->reserve_vt) {
- /* If this is the reserved TTY, we'll start the getty
- * on it in any case, but otherwise only if it is not
- * busy. */
-
- r = vt_is_busy(vtnr);
- if (r < 0)
- return r;
- else if (r > 0)
- return -EBUSY;
- }
-
- if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
- log_error("Could not allocate service name.");
- r = -ENOMEM;
- goto finish;
- }
-
- r = bus_method_call_with_reply (
- m->bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "StartUnit",
- NULL,
- NULL,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_STRING, &mode,
- DBUS_TYPE_INVALID);
-
-finish:
- free(name);
-
- return r;
-}
-
static int manager_reserve_vt(Manager *m) {
_cleanup_free_ char *p = NULL;
@@ -1037,107 +604,6 @@ static int manager_reserve_vt(Manager *m) {
return 0;
}
-int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) {
- Session *s;
- char *p;
-
- assert(m);
- assert(cgroup);
- assert(session);
-
- s = hashmap_get(m->session_cgroups, cgroup);
- if (s) {
- *session = s;
- return 1;
- }
-
- p = strdupa(cgroup);
-
- for (;;) {
- char *e;
-
- e = strrchr(p, '/');
- if (!e || e == p) {
- *session = NULL;
- return 0;
- }
-
- *e = 0;
-
- s = hashmap_get(m->session_cgroups, p);
- if (s) {
- *session = s;
- return 1;
- }
- }
-}
-
-int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) {
- User *u;
- char *p;
-
- assert(m);
- assert(cgroup);
- assert(user);
-
- u = hashmap_get(m->user_cgroups, cgroup);
- if (u) {
- *user = u;
- return 1;
- }
-
- p = strdupa(cgroup);
- if (!p)
- return log_oom();
-
- for (;;) {
- char *e;
-
- e = strrchr(p, '/');
- if (!e || e == p) {
- *user = NULL;
- return 0;
- }
-
- *e = 0;
-
- u = hashmap_get(m->user_cgroups, p);
- if (u) {
- *user = u;
- return 1;
- }
- }
-}
-
-int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
- _cleanup_free_ char *p = NULL;
- int r;
-
- assert(m);
- assert(pid >= 1);
- assert(session);
-
- r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
- if (r < 0)
- return r;
-
- return manager_get_session_by_cgroup(m, p, session);
-}
-
-void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
- Session *s;
- User *u;
- int r;
-
- r = manager_get_session_by_cgroup(m, cgroup, &s);
- if (r > 0)
- session_add_to_gc_queue(s);
-
- r = manager_get_user_by_cgroup(m, cgroup, &u);
- if (r > 0)
- user_add_to_gc_queue(u);
-}
-
static void manager_dispatch_other(Manager *m, int fd) {
Session *s;
Inhibitor *i;
@@ -1204,15 +670,75 @@ static int manager_connect_bus(Manager *m) {
dbus_bus_add_match(m->bus,
"type='signal',"
- "interface='org.freedesktop.systemd1.Agent',"
- "member='Released',"
- "path='/org/freedesktop/systemd1/agent'",
+ "sender='"DBUS_SERVICE_DBUS"',"
+ "interface='"DBUS_INTERFACE_DBUS"',"
+ "member='NameOwnerChanged',"
+ "path='"DBUS_PATH_DBUS"'",
+ &error);
+ if (dbus_error_is_set(&error)) {
+ log_error("Failed to add match for NameOwnerChanged: %s", bus_error_message(&error));
+ dbus_error_free(&error);
+ }
+
+ dbus_bus_add_match(m->bus,
+ "type='signal',"
+ "sender='org.freedesktop.systemd1',"
+ "interface='org.freedesktop.systemd1.Manager',"
+ "member='JobRemoved',"
+ "path='/org/freedesktop/systemd1'",
&error);
+ if (dbus_error_is_set(&error)) {
+ log_error("Failed to add match for JobRemoved: %s", bus_error_message(&error));
+ dbus_error_free(&error);
+ }
+ dbus_bus_add_match(m->bus,
+ "type='signal',"
+ "sender='org.freedesktop.systemd1',"
+ "interface='org.freedesktop.systemd1.Manager',"
+ "member='UnitRemoved',"
+ "path='/org/freedesktop/systemd1'",
+ &error);
if (dbus_error_is_set(&error)) {
- log_error("Failed to register match: %s", bus_error_message(&error));
- r = -EIO;
- goto fail;
+ log_error("Failed to add match for UnitRemoved: %s", bus_error_message(&error));
+ dbus_error_free(&error);
+ }
+
+ dbus_bus_add_match(m->bus,
+ "type='signal',"
+ "sender='org.freedesktop.systemd1',"
+ "interface='org.freedesktop.DBus.Properties',"
+ "member='PropertiesChanged'",
+ &error);
+ if (dbus_error_is_set(&error)) {
+ log_error("Failed to add match for PropertiesChanged: %s", bus_error_message(&error));
+ dbus_error_free(&error);
+ }
+
+ dbus_bus_add_match(m->bus,
+ "type='signal',"
+ "sender='org.freedesktop.systemd1',"
+ "interface='org.freedesktop.systemd1.Manager',"
+ "member='Reloading',"
+ "path='/org/freedesktop/systemd1'",
+ &error);
+ if (dbus_error_is_set(&error)) {
+ log_error("Failed to add match for Reloading: %s", bus_error_message(&error));
+ dbus_error_free(&error);
+ }
+
+ r = bus_method_call_with_reply(
+ m->bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "Subscribe",
+ NULL,
+ &error,
+ DBUS_TYPE_INVALID);
+ if (r < 0) {
+ log_error("Failed to enable subscription: %s", bus_error(&error, r));
+ dbus_error_free(&error);
}
r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
@@ -1289,6 +815,7 @@ static int manager_connect_udev(Manager *m) {
assert(m);
assert(!m->udev_seat_monitor);
+ assert(!m->udev_device_monitor);
assert(!m->udev_vcsa_monitor);
assert(!m->udev_button_monitor);
@@ -1309,6 +836,33 @@ static int manager_connect_udev(Manager *m) {
if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
return -errno;
+ m->udev_device_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
+ if (!m->udev_device_monitor)
+ return -ENOMEM;
+
+ r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "input", NULL);
+ if (r < 0)
+ return r;
+
+ r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "graphics", NULL);
+ if (r < 0)
+ return r;
+
+ r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "drm", NULL);
+ if (r < 0)
+ return r;
+
+ r = udev_monitor_enable_receiving(m->udev_device_monitor);
+ if (r < 0)
+ return r;
+
+ m->udev_device_fd = udev_monitor_get_fd(m->udev_device_monitor);
+ zero(ev);
+ ev.events = EPOLLIN;
+ ev.data.u32 = FD_DEVICE_UDEV;
+ if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_device_fd, &ev) < 0)
+ return -errno;
+
/* Don't watch keys if nobody cares */
if (m->handle_power_key != HANDLE_IGNORE ||
m->handle_suspend_key != HANDLE_IGNORE ||
@@ -1390,6 +944,7 @@ void manager_gc(Manager *m, bool drop_not_started) {
if (session_check_gc(session, drop_not_started) == 0) {
session_stop(session);
+ session_finalize(session);
session_free(session);
}
}
@@ -1400,50 +955,12 @@ void manager_gc(Manager *m, bool drop_not_started) {
if (user_check_gc(user, drop_not_started) == 0) {
user_stop(user);
+ user_finalize(user);
user_free(user);
}
}
}
-int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
- Session *s;
- bool idle_hint;
- dual_timestamp ts = { 0, 0 };
- Iterator i;
-
- assert(m);
-
- idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0);
-
- HASHMAP_FOREACH(s, m->sessions, i) {
- dual_timestamp k;
- int ih;
-
- ih = session_get_idle_hint(s, &k);
- if (ih < 0)
- return ih;
-
- if (!ih) {
- if (!idle_hint) {
- if (k.monotonic < ts.monotonic)
- ts = k;
- } else {
- idle_hint = false;
- ts = k;
- }
- } else if (idle_hint) {
-
- if (k.monotonic > ts.monotonic)
- ts = k;
- }
- }
-
- if (t)
- *t = ts;
-
- return idle_hint;
-}
-
int manager_dispatch_idle_action(Manager *m) {
struct dual_timestamp since;
struct itimerspec its = {};
@@ -1526,9 +1043,6 @@ int manager_startup(Manager *m) {
assert(m);
assert(m->epoll_fd <= 0);
- cg_shorten_controllers(m->reset_controllers);
- cg_shorten_controllers(m->controllers);
-
m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
if (m->epoll_fd < 0)
return -errno;
@@ -1549,17 +1063,34 @@ int manager_startup(Manager *m) {
return r;
/* Instantiate magic seat 0 */
- r = manager_add_seat(m, "seat0", &m->vtconsole);
+ r = manager_add_seat(m, "seat0", &m->seat0);
if (r < 0)
return r;
/* Deserialize state */
- manager_enumerate_devices(m);
- manager_enumerate_seats(m);
- manager_enumerate_users(m);
- manager_enumerate_sessions(m);
- manager_enumerate_inhibitors(m);
- manager_enumerate_buttons(m);
+ r = manager_enumerate_devices(m);
+ if (r < 0)
+ log_warning("Device enumeration failed: %s", strerror(-r));
+
+ r = manager_enumerate_seats(m);
+ if (r < 0)
+ log_warning("Seat enumeration failed: %s", strerror(-r));
+
+ r = manager_enumerate_users(m);
+ if (r < 0)
+ log_warning("User enumeration failed: %s", strerror(-r));
+
+ r = manager_enumerate_sessions(m);
+ if (r < 0)
+ log_warning("Session enumeration failed: %s", strerror(-r));
+
+ r = manager_enumerate_inhibitors(m);
+ if (r < 0)
+ log_warning("Inhibitor enumeration failed: %s", strerror(-r));
+
+ r = manager_enumerate_buttons(m);
+ if (r < 0)
+ log_warning("Button enumeration failed: %s", strerror(-r));
/* Remove stale objects before we start them */
manager_gc(m, false);
@@ -1653,6 +1184,10 @@ int manager_run(Manager *m) {
manager_dispatch_seat_udev(m);
break;
+ case FD_DEVICE_UDEV:
+ manager_dispatch_device_udev(m);
+ break;
+
case FD_VCSA_UDEV:
manager_dispatch_vcsa_udev(m);
break;
diff --git a/src/login/logind.conf b/src/login/logind.conf
index 0861d73e0b..c0abf01b0c 100644
--- a/src/login/logind.conf
+++ b/src/login/logind.conf
@@ -13,8 +13,6 @@
#KillUserProcesses=no
#KillOnlyUsers=
#KillExcludeUsers=root
-#Controllers=
-#ResetControllers=cpu
#InhibitDelayMaxSec=5
#HandlePowerKey=poweroff
#HandleSuspendKey=suspend
diff --git a/src/login/logind.h b/src/login/logind.h
index 904dc20467..9e6296cb7e 100644
--- a/src/login/logind.h
+++ b/src/login/logind.h
@@ -51,15 +51,17 @@ struct Manager {
Hashmap *users;
Hashmap *inhibitors;
Hashmap *buttons;
+ Hashmap *busnames;
LIST_HEAD(Seat, seat_gc_queue);
LIST_HEAD(Session, session_gc_queue);
LIST_HEAD(User, user_gc_queue);
struct udev *udev;
- struct udev_monitor *udev_seat_monitor, *udev_vcsa_monitor, *udev_button_monitor;
+ struct udev_monitor *udev_seat_monitor, *udev_device_monitor, *udev_vcsa_monitor, *udev_button_monitor;
int udev_seat_fd;
+ int udev_device_fd;
int udev_vcsa_fd;
int udev_button_fd;
@@ -72,20 +74,16 @@ struct Manager {
unsigned reserve_vt;
int reserve_vt_fd;
- Seat *vtconsole;
-
- char *cgroup_path;
- char **controllers, **reset_controllers;
+ Seat *seat0;
char **kill_only_users, **kill_exclude_users;
-
bool kill_user_processes;
unsigned long session_counter;
unsigned long inhibit_counter;
- Hashmap *session_cgroups;
- Hashmap *user_cgroups;
+ Hashmap *session_units;
+ Hashmap *user_units;
Hashmap *session_fds;
Hashmap *inhibitor_fds;
@@ -125,6 +123,7 @@ struct Manager {
enum {
FD_SEAT_UDEV,
+ FD_DEVICE_UDEV,
FD_VCSA_UDEV,
FD_BUTTON_UDEV,
FD_CONSOLE,
@@ -136,10 +135,10 @@ enum {
Manager *manager_new(void);
void manager_free(Manager *m);
-int manager_add_device(Manager *m, const char *sysfs, Device **_device);
+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);
-int manager_add_session(Manager *m, User *u, const char *id, Session **_session);
+int manager_add_session(Manager *m, const char *id, Session **_session);
int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user);
int manager_add_user_by_name(Manager *m, const char *name, User **_user);
int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user);
@@ -165,14 +164,13 @@ int manager_startup(Manager *m);
int manager_run(Manager *m);
int manager_spawn_autovt(Manager *m, int vtnr);
-void manager_cgroup_notify_empty(Manager *m, const char *cgroup);
-
void manager_gc(Manager *m, bool drop_not_started);
+bool manager_shall_kill(Manager *m, const char *user);
+
int manager_get_idle_hint(Manager *m, dual_timestamp *t);
-int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user);
-int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session);
+int manager_get_user_by_pid(Manager *m, pid_t pid, User **user);
int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session);
extern const DBusObjectPathVTable bus_manager_vtable;
@@ -185,5 +183,14 @@ int manager_send_changed(Manager *manager, const char *properties);
int manager_dispatch_delayed(Manager *manager);
+int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *kill_mode, DBusError *error, char **job);
+int manager_start_unit(Manager *manager, const char *unit, DBusError *error, char **job);
+int manager_stop_unit(Manager *manager, const char *unit, DBusError *error, char **job);
+int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, DBusError *error);
+int manager_unit_is_active(Manager *manager, const char *unit);
+
/* gperf lookup function */
const struct ConfigPerfItem* logind_gperf_lookup(const char *key, unsigned length);
+
+int manager_watch_busname(Manager *manager, const char *name);
+void manager_drop_busname(Manager *manager, const char *name);
diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf
index 6c1f2f57e5..0407609c19 100644
--- a/src/login/org.freedesktop.login1.conf
+++ b/src/login/org.freedesktop.login1.conf
@@ -62,6 +62,10 @@
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
+ send_member="ListMachines"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
send_member="ListSeats"/>
<allow send_destination="org.freedesktop.login1"
diff --git a/src/login/org.freedesktop.login1.policy.in b/src/login/org.freedesktop.login1.policy.in
index 0c551d4f9b..b96d32d526 100644
--- a/src/login/org.freedesktop.login1.policy.in
+++ b/src/login/org.freedesktop.login1.policy.in
@@ -190,7 +190,7 @@
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
- <allow_active>auth_admin_keep</allow_active>
+ <allow_active>yes</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.reboot</annotate>
</action>
diff --git a/src/login/pam-module.c b/src/login/pam-module.c
index 13290fd8ea..49296b5d63 100644
--- a/src/login/pam-module.c
+++ b/src/login/pam-module.c
@@ -43,11 +43,6 @@
static int parse_argv(pam_handle_t *handle,
int argc, const char **argv,
- char ***controllers,
- char ***reset_controllers,
- bool *kill_processes,
- char ***kill_only_users,
- char ***kill_exclude_users,
const char **class,
bool *debug) {
@@ -59,89 +54,15 @@ static int parse_argv(pam_handle_t *handle,
for (i = 0; i < (unsigned) argc; i++) {
int k;
- if (startswith(argv[i], "kill-session-processes=")) {
- if ((k = parse_boolean(argv[i] + 23)) < 0) {
- pam_syslog(handle, LOG_ERR, "Failed to parse kill-session-processes= argument.");
- return k;
- }
-
- if (kill_processes)
- *kill_processes = k;
-
- } else if (startswith(argv[i], "kill-session=")) {
- /* As compatibility for old versions */
-
- if ((k = parse_boolean(argv[i] + 13)) < 0) {
- pam_syslog(handle, LOG_ERR, "Failed to parse kill-session= argument.");
- return k;
- }
-
- if (kill_processes)
- *kill_processes = k;
-
- } else if (startswith(argv[i], "controllers=")) {
-
- if (controllers) {
- char **l;
-
- if (!(l = strv_split(argv[i] + 12, ","))) {
- pam_syslog(handle, LOG_ERR, "Out of memory.");
- return -ENOMEM;
- }
-
- strv_free(*controllers);
- *controllers = l;
- }
-
- } else if (startswith(argv[i], "reset-controllers=")) {
-
- if (reset_controllers) {
- char **l;
-
- if (!(l = strv_split(argv[i] + 18, ","))) {
- pam_syslog(handle, LOG_ERR, "Out of memory.");
- return -ENOMEM;
- }
-
- strv_free(*reset_controllers);
- *reset_controllers = l;
- }
-
- } else if (startswith(argv[i], "kill-only-users=")) {
-
- if (kill_only_users) {
- char **l;
-
- if (!(l = strv_split(argv[i] + 16, ","))) {
- pam_syslog(handle, LOG_ERR, "Out of memory.");
- return -ENOMEM;
- }
-
- strv_free(*kill_only_users);
- *kill_only_users = l;
- }
-
- } else if (startswith(argv[i], "kill-exclude-users=")) {
-
- if (kill_exclude_users) {
- char **l;
-
- if (!(l = strv_split(argv[i] + 19, ","))) {
- pam_syslog(handle, LOG_ERR, "Out of memory.");
- return -ENOMEM;
- }
-
- strv_free(*kill_exclude_users);
- *kill_exclude_users = l;
- }
-
- } else if (startswith(argv[i], "class=")) {
+ if (startswith(argv[i], "class=")) {
if (class)
*class = argv[i] + 6;
} else if (startswith(argv[i], "debug=")) {
- if ((k = parse_boolean(argv[i] + 6)) < 0) {
+ k = parse_boolean(argv[i] + 6);
+
+ if (k < 0) {
pam_syslog(handle, LOG_ERR, "Failed to parse debug= argument.");
return k;
}
@@ -149,14 +70,9 @@ static int parse_argv(pam_handle_t *handle,
if (debug)
*debug = k;
- } else if (startswith(argv[i], "create-session=") ||
- startswith(argv[i], "kill-user=")) {
-
- pam_syslog(handle, LOG_WARNING, "Option %s not supported anymore, ignoring.", argv[i]);
-
} else {
- pam_syslog(handle, LOG_ERR, "Unknown parameter '%s'.", argv[i]);
- return -EINVAL;
+ pam_syslog(handle, LOG_WARNING, "Unknown parameter '%s', ignoring", argv[i]);
+ return 0;
}
}
@@ -206,55 +122,6 @@ static int get_user_data(
return PAM_SUCCESS;
}
-static bool check_user_lists(
- pam_handle_t *handle,
- uid_t uid,
- char **kill_only_users,
- char **kill_exclude_users) {
-
- const char *name = NULL;
- char **l;
-
- assert(handle);
-
- if (uid == 0)
- name = "root"; /* Avoid obvious NSS requests, to suppress network traffic */
- else {
- struct passwd *pw;
-
- pw = pam_modutil_getpwuid(handle, uid);
- if (pw)
- name = pw->pw_name;
- }
-
- STRV_FOREACH(l, kill_exclude_users) {
- uid_t u;
-
- if (parse_uid(*l, &u) >= 0)
- if (u == uid)
- return false;
-
- if (name && streq(name, *l))
- return false;
- }
-
- if (strv_isempty(kill_only_users))
- return true;
-
- STRV_FOREACH(l, kill_only_users) {
- uid_t u;
-
- if (parse_uid(*l, &u) >= 0)
- if (u == uid)
- return true;
-
- if (name && streq(name, *l))
- return true;
- }
-
- return false;
-}
-
static int get_seat_from_display(const char *display, const char **seat, uint32_t *vtnr) {
_cleanup_free_ char *p = NULL;
int r;
@@ -316,13 +183,11 @@ _public_ PAM_EXTERN int pam_sm_open_session(
int argc, const char **argv) {
struct passwd *pw;
- bool kill_processes = false, debug = false;
+ bool debug = false;
const char *username, *id, *object_path, *runtime_path, *service = NULL, *tty = NULL, *display = NULL, *remote_user = NULL, *remote_host = NULL, *seat = NULL, *type = NULL, *class = NULL, *class_pam = NULL, *cvtnr = NULL;
- char **controllers = NULL, **reset_controllers = NULL, **kill_only_users = NULL, **kill_exclude_users = NULL;
DBusError error;
uint32_t uid, pid;
DBusMessageIter iter;
- dbus_bool_t kp;
int session_fd = -1;
DBusConnection *bus = NULL;
DBusMessage *m = NULL, *reply = NULL;
@@ -342,9 +207,8 @@ _public_ PAM_EXTERN int pam_sm_open_session(
if (parse_argv(handle,
argc, argv,
- &controllers, &reset_controllers,
- &kill_processes, &kill_only_users, &kill_exclude_users,
- &class_pam, &debug) < 0) {
+ &class_pam,
+ &debug) < 0) {
r = PAM_SESSION_ERR;
goto finish;
}
@@ -356,11 +220,11 @@ _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
* background to finish start-up. If the service is
- * "systemd-shared" we simply set XDG_RUNTIME_DIR and
+ * "systemd-user" we simply set XDG_RUNTIME_DIR and
* leave. */
pam_get_item(handle, PAM_SERVICE, (const void**) &service);
- if (streq_ptr(service, "systemd-shared")) {
+ if (streq_ptr(service, "systemd-user")) {
char *p, *rt = NULL;
if (asprintf(&p, "/run/systemd/users/%lu", (unsigned long) pw->pw_uid) < 0) {
@@ -393,9 +257,6 @@ _public_ PAM_EXTERN int pam_sm_open_session(
goto finish;
}
- if (kill_processes)
- kill_processes = check_user_lists(handle, pw->pw_uid, kill_only_users, kill_exclude_users);
-
dbus_connection_set_change_sigpipe(FALSE);
bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
@@ -510,27 +371,6 @@ _public_ PAM_EXTERN int pam_sm_open_session(
dbus_message_iter_init_append(m, &iter);
- r = bus_append_strv_iter(&iter, controllers);
- if (r < 0) {
- pam_syslog(handle, LOG_ERR, "Could not attach parameter to message.");
- r = PAM_BUF_ERR;
- goto finish;
- }
-
- r = bus_append_strv_iter(&iter, reset_controllers);
- if (r < 0) {
- pam_syslog(handle, LOG_ERR, "Could not attach parameter to message.");
- r = PAM_BUF_ERR;
- goto finish;
- }
-
- kp = kill_processes;
- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &kp)) {
- pam_syslog(handle, LOG_ERR, "Could not attach parameter to message.");
- r = PAM_BUF_ERR;
- goto finish;
- }
-
if (debug)
pam_syslog(handle, LOG_DEBUG, "Asking logind to create session: "
"uid=%u pid=%u service=%s type=%s class=%s seat=%s vtnr=%u tty=%s display=%s remote=%s remote_user=%s remote_host=%s",
@@ -613,11 +453,6 @@ _public_ PAM_EXTERN int pam_sm_open_session(
r = PAM_SUCCESS;
finish:
- strv_free(controllers);
- strv_free(reset_controllers);
- strv_free(kill_only_users);
- strv_free(kill_exclude_users);
-
dbus_error_free(&error);
if (bus) {
diff --git a/src/login/sd-login.c b/src/login/sd-login.c
index d0dc42f685..71d8c2942e 100644
--- a/src/login/sd-login.c
+++ b/src/login/sd-login.c
@@ -31,6 +31,7 @@
#include "sd-login.h"
#include "strv.h"
#include "fileio.h"
+#include "login-shared.h"
_public_ int sd_pid_get_session(pid_t pid, char **session) {
if (pid < 0)
@@ -72,6 +73,16 @@ _public_ int sd_pid_get_machine_name(pid_t pid, char **name) {
return cg_pid_get_machine_name(pid, name);
}
+_public_ int sd_pid_get_slice(pid_t pid, char **slice) {
+
+ if (pid < 0)
+ return -EINVAL;
+ if (!slice)
+ return -EINVAL;
+
+ return cg_pid_get_slice(pid, slice);
+}
+
_public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) {
if (pid < 0)
@@ -216,17 +227,19 @@ static int file_of_session(const char *session, char **_p) {
assert(_p);
- if (session)
+ if (session) {
+ if (!session_id_valid(session))
+ return -EINVAL;
+
p = strappend("/run/systemd/sessions/", session);
- else {
- char *buf;
+ } else {
+ _cleanup_free_ char *buf = NULL;
r = sd_pid_get_session(0, &buf);
if (r < 0)
return r;
p = strappend("/run/systemd/sessions/", buf);
- free(buf);
}
if (!p)
@@ -245,7 +258,6 @@ _public_ int sd_session_is_active(const char *session) {
return r;
r = parse_env_file(p, NEWLINE, "ACTIVE", &s, NULL);
-
if (r < 0)
return r;
@@ -337,6 +349,23 @@ _public_ int sd_session_get_tty(const char *session, char **tty) {
return session_get_string(session, "TTY", tty);
}
+_public_ int sd_session_get_vt(const char *session, unsigned *vtnr) {
+ _cleanup_free_ char *vtnr_string;
+ unsigned u;
+ int r;
+
+ r = session_get_string(session, "VTNr", &vtnr_string);
+ if (r < 0)
+ return r;
+
+ r = safe_atou(vtnr_string, &u);
+ if (r < 0)
+ return r;
+
+ *vtnr = u;
+ return 0;
+}
+
_public_ int sd_session_get_service(const char *session, char **service) {
return session_get_string(session, "SERVICE", service);
}
@@ -592,40 +621,7 @@ _public_ int sd_get_uids(uid_t **users) {
}
_public_ int sd_get_machine_names(char ***machines) {
- _cleanup_closedir_ DIR *d = NULL;
- _cleanup_strv_free_ char **l = NULL;
- _cleanup_free_ char *md = NULL;
- char *n;
- int c = 0, r;
-
- r = cg_get_machine_path(NULL, &md);
- if (r < 0)
- return r;
-
- r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, md, &d);
- if (r < 0)
- return r;
-
- while ((r = cg_read_subgroup(d, &n)) > 0) {
-
- r = strv_push(&l, n);
- if (r < 0) {
- free(n);
- return -ENOMEM;
- }
-
- c++;
- }
-
- if (r < 0)
- return r;
-
- if (machines) {
- *machines = l;
- l = NULL;
- }
-
- return c;
+ return get_files_in_directory("/run/systemd/machines/", machines);
}
static inline int MONITOR_TO_FD(sd_login_monitor *m) {
@@ -678,18 +674,7 @@ _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) {
}
if (!category || streq(category, "machine")) {
- _cleanup_free_ char *md = NULL, *p = NULL;
- int r;
-
- r = cg_get_machine_path(NULL, &md);
- if (r < 0)
- return r;
-
- r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, md, NULL, &p);
- if (r < 0)
- return r;
-
- k = inotify_add_watch(fd, p, IN_MOVED_TO|IN_CREATE|IN_DELETE);
+ k = inotify_add_watch(fd, "/run/systemd/machines/", IN_MOVED_TO|IN_DELETE);
if (k < 0) {
close_nointr_nofail(fd);
return -errno;
diff --git a/src/login/systemd-user b/src/login/systemd-user
new file mode 100644
index 0000000000..7b57dbf784
--- /dev/null
+++ b/src/login/systemd-user
@@ -0,0 +1,8 @@
+#%PAM-1.0
+
+# Used by systemd when launching systemd user instances.
+
+account include system-auth
+session include system-auth
+auth required pam_deny.so
+password required pam_deny.so
diff --git a/src/timestamp/timestamp.c b/src/login/test-login-shared.c
index 1152f1b52e..d29d7e7921 100644
--- a/src/timestamp/timestamp.c
+++ b/src/login/test-login-shared.c
@@ -3,7 +3,7 @@
/***
This file is part of systemd.
- Copyright 2010 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
@@ -19,21 +19,23 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
+#include "macro.h"
+#include "login-shared.h"
-#include "util.h"
+static void test_session_id_valid(void) {
+ assert_se(session_id_valid("c1"));
+ assert_se(session_id_valid("1234"));
-int main(int argc, char *argv[]) {
- struct dual_timestamp t;
+ assert_se(!session_id_valid("1-2"));
+ assert_se(!session_id_valid(""));
+ assert_se(!session_id_valid("\tid"));
+}
- /* This is mostly useful for stuff like init ram disk scripts
- * which want to take a proper timestamp to do minimal bootup
- * profiling. */
+int main(int argc, char* argv[]) {
+ log_parse_environment();
+ log_open();
- dual_timestamp_get(&t);
- printf("%llu %llu\n",
- (unsigned long long) t.realtime,
- (unsigned long long) t.monotonic);
+ test_session_id_valid();
return 0;
}
diff --git a/src/login/test-login-tables.c b/src/login/test-login-tables.c
new file mode 100644
index 0000000000..a4196bf14b
--- /dev/null
+++ b/src/login/test-login-tables.c
@@ -0,0 +1,35 @@
+/***
+ 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 "logind-action.h"
+#include "logind-session.h"
+
+#include "test-tables.h"
+
+int main(int argc, char **argv) {
+ test_table(handle_action, HANDLE_ACTION);
+ test_table(inhibit_mode, INHIBIT_MODE);
+ test_table(kill_who, KILL_WHO);
+ test_table(session_class, SESSION_CLASS);
+ test_table(session_state, SESSION_STATE);
+ test_table(session_type, SESSION_TYPE);
+ test_table(user_state, USER_STATE);
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/login/test-login.c b/src/login/test-login.c
index 945cb38be9..228ddb2933 100644
--- a/src/login/test-login.c
+++ b/src/login/test-login.c
@@ -27,7 +27,7 @@
#include "util.h"
#include "strv.h"
-int main(int argc, char* argv[]) {
+static void test_login(void) {
int r, k;
uid_t u, u2;
char *seat, *type, *class, *display;
@@ -215,6 +215,13 @@ int main(int argc, char* argv[]) {
}
sd_login_monitor_unref(m);
+}
+
+int main(int argc, char* argv[]) {
+ log_parse_environment();
+ log_open();
+
+ test_login();
return 0;
}
diff --git a/src/login/user-sessions.c b/src/login/user-sessions.c
index 41d32044e9..45fb427671 100644
--- a/src/login/user-sessions.c
+++ b/src/login/user-sessions.c
@@ -25,7 +25,6 @@
#include "log.h"
#include "util.h"
-#include "cgroup-util.h"
#include "fileio.h"
int main(int argc, char*argv[]) {
@@ -67,29 +66,12 @@ int main(int argc, char*argv[]) {
goto finish;
} else if (streq(argv[1], "stop")) {
- int r, q;
- char *cgroup_user_tree = NULL;
+ int r;
r = write_string_file_atomic("/run/nologin", "System is going down.");
if (r < 0)
log_error("Failed to create /run/nologin: %s", strerror(-r));
- q = cg_get_user_path(&cgroup_user_tree);
- if (q < 0) {
- log_error("Failed to determine use path: %s", strerror(-q));
- goto finish;
- }
-
- q = cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, cgroup_user_tree, true);
- free(cgroup_user_tree);
- if (q < 0) {
- log_error("Failed to kill sessions: %s", strerror(-q));
- goto finish;
- }
-
- if (r < 0)
- goto finish;
-
} else {
log_error("Unknown verb %s.", argv[1]);
goto finish;
diff --git a/src/machine/Makefile b/src/machine/Makefile
new file mode 120000
index 0000000000..d0b0e8e008
--- /dev/null
+++ b/src/machine/Makefile
@@ -0,0 +1 @@
+../Makefile \ No newline at end of file
diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
new file mode 100644
index 0000000000..ceab96e078
--- /dev/null
+++ b/src/machine/machine-dbus.c
@@ -0,0 +1,364 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2011 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <errno.h>
+#include <string.h>
+
+#include "machined.h"
+#include "machine.h"
+#include "dbus-common.h"
+
+#define BUS_MACHINE_INTERFACE \
+ " <interface name=\"org.freedesktop.machine1.Machine\">\n" \
+ " <method name=\"Terminate\"/>\n" \
+ " <method name=\"Kill\">\n" \
+ " <arg name=\"who\" type=\"s\"/>\n" \
+ " <arg name=\"signal\" type=\"s\"/>\n" \
+ " </method>\n" \
+ " <property name=\"Name\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"Id\" type=\"ay\" access=\"read\"/>\n" \
+ " <property name=\"Timestamp\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"TimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"Service\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"Scope\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"Leader\" type=\"u\" access=\"read\"/>\n" \
+ " <property name=\"Class\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"State\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"RootDirectory\" type=\"s\" access=\"read\"/>\n" \
+ " </interface>\n"
+
+#define INTROSPECTION \
+ DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
+ "<node>\n" \
+ BUS_MACHINE_INTERFACE \
+ BUS_PROPERTIES_INTERFACE \
+ BUS_PEER_INTERFACE \
+ BUS_INTROSPECTABLE_INTERFACE \
+ "</node>\n"
+
+#define INTERFACES_LIST \
+ BUS_GENERIC_INTERFACES_LIST \
+ "org.freedesktop.machine1.Machine\0"
+
+static int bus_machine_append_id(DBusMessageIter *i, const char *property, void *data) {
+ DBusMessageIter sub;
+ Machine *m = data;
+ dbus_bool_t b;
+ void *p;
+
+ assert(i);
+ assert(property);
+ assert(m);
+
+ if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "y", &sub))
+ return -ENOMEM;
+
+ p = &m->id;
+ b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &p, 16);
+ if (!b)
+ return -ENOMEM;
+
+ if (!dbus_message_iter_close_container(i, &sub))
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int bus_machine_append_state(DBusMessageIter *i, const char *property, void *data) {
+ Machine *m = data;
+ const char *state;
+
+ assert(i);
+ assert(property);
+ assert(m);
+
+ state = machine_state_to_string(machine_get_state(m));
+
+ if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &state))
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int get_machine_for_path(Manager *m, const char *path, Machine **_machine) {
+ _cleanup_free_ char *e = NULL;
+ Machine *machine;
+
+ assert(m);
+ assert(path);
+ assert(_machine);
+
+ if (!startswith(path, "/org/freedesktop/machine1/machine/"))
+ return -EINVAL;
+
+ e = bus_path_unescape(path + 34);
+ if (!e)
+ return -ENOMEM;
+
+ machine = hashmap_get(m->machines, e);
+ if (!machine)
+ return -ENOENT;
+
+ *_machine = machine;
+ return 0;
+}
+
+static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_machine_append_class, machine_class, MachineClass);
+
+static const BusProperty bus_machine_machine_properties[] = {
+ { "Name", bus_property_append_string, "s", offsetof(Machine, name), true },
+ { "Id", bus_machine_append_id, "ay", 0 },
+ { "Timestamp", bus_property_append_usec, "t", offsetof(Machine, timestamp.realtime) },
+ { "TimestampMonotonic", bus_property_append_usec, "t", offsetof(Machine, timestamp.monotonic) },
+ { "Service", bus_property_append_string, "s", offsetof(Machine, service), true },
+ { "Scope", bus_property_append_string, "s", offsetof(Machine, scope), true },
+ { "Leader", bus_property_append_pid, "u", offsetof(Machine, leader) },
+ { "Class", bus_machine_append_class, "s", offsetof(Machine, class) },
+ { "State", bus_machine_append_state, "s", 0 },
+ { "RootDirectory", bus_property_append_string, "s", offsetof(Machine, root_directory), true },
+ { NULL, }
+};
+
+static DBusHandlerResult machine_message_dispatch(
+ Machine *m,
+ DBusConnection *connection,
+ DBusMessage *message) {
+
+ DBusError error;
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ int r;
+
+ assert(m);
+ assert(connection);
+ assert(message);
+
+ if (dbus_message_is_method_call(message, "org.freedesktop.machine1.Machine", "Terminate")) {
+
+ r = machine_stop(m);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.machine1.Machine", "Kill")) {
+ const char *swho;
+ int32_t signo;
+ KillWho who;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_STRING, &swho,
+ DBUS_TYPE_INT32, &signo,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ if (isempty(swho))
+ who = KILL_ALL;
+ else {
+ who = kill_who_from_string(swho);
+ if (who < 0)
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+ }
+
+ if (signo <= 0 || signo >= _NSIG)
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ r = machine_kill(m, who, signo);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ } else {
+ const BusBoundProperties bps[] = {
+ { "org.freedesktop.machine1.Machine", bus_machine_machine_properties, m },
+ { NULL, }
+ };
+
+ return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps);
+ }
+
+ if (reply) {
+ if (!bus_maybe_send_reply(connection, message, reply))
+ goto oom;
+ }
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+
+oom:
+ dbus_error_free(&error);
+
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+}
+
+static DBusHandlerResult machine_message_handler(
+ DBusConnection *connection,
+ DBusMessage *message,
+ void *userdata) {
+
+ Manager *manager = userdata;
+ Machine *m;
+ int r;
+
+ r = get_machine_for_path(manager, dbus_message_get_path(message), &m);
+ if (r < 0) {
+
+ if (r == -ENOMEM)
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+ if (r == -ENOENT) {
+ DBusError e;
+
+ dbus_error_init(&e);
+ dbus_set_error_const(&e, DBUS_ERROR_UNKNOWN_OBJECT, "Unknown machine");
+ return bus_send_error_reply(connection, message, &e, r);
+ }
+
+ return bus_send_error_reply(connection, message, NULL, r);
+ }
+
+ return machine_message_dispatch(m, connection, message);
+}
+
+const DBusObjectPathVTable bus_machine_vtable = {
+ .message_function = machine_message_handler
+};
+
+char *machine_bus_path(Machine *m) {
+ _cleanup_free_ char *e = NULL;
+
+ assert(m);
+
+ e = bus_path_escape(m->name);
+ if (!e)
+ return NULL;
+
+ return strappend("/org/freedesktop/machine1/machine/", e);
+}
+
+int machine_send_signal(Machine *m, bool new_machine) {
+ _cleanup_dbus_message_unref_ DBusMessage *msg = NULL;
+ _cleanup_free_ char *p = NULL;
+
+ assert(m);
+
+ msg = dbus_message_new_signal("/org/freedesktop/machine1",
+ "org.freedesktop.machine1.Manager",
+ new_machine ? "MachineNew" : "MachineRemoved");
+
+ if (!m)
+ return -ENOMEM;
+
+ p = machine_bus_path(m);
+ if (!p)
+ return -ENOMEM;
+
+ if (!dbus_message_append_args(
+ msg,
+ DBUS_TYPE_STRING, &m->name,
+ DBUS_TYPE_OBJECT_PATH, &p,
+ DBUS_TYPE_INVALID))
+ return -ENOMEM;
+
+ if (!dbus_connection_send(m->manager->bus, msg, NULL))
+ return -ENOMEM;
+
+ return 0;
+}
+
+int machine_send_changed(Machine *m, const char *properties) {
+ _cleanup_dbus_message_unref_ DBusMessage *msg = NULL;
+ _cleanup_free_ char *p = NULL;
+
+ assert(m);
+
+ if (!m->started)
+ return 0;
+
+ p = machine_bus_path(m);
+ if (!p)
+ return -ENOMEM;
+
+ msg = bus_properties_changed_new(p, "org.freedesktop.machine1.Machine", properties);
+ if (!msg)
+ return -ENOMEM;
+
+ if (!dbus_connection_send(m->manager->bus, msg, NULL))
+ return -ENOMEM;
+
+ return 0;
+}
+
+int machine_send_create_reply(Machine *m, DBusError *error) {
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+
+ assert(m);
+
+ if (!m->create_message)
+ return 0;
+
+ if (error) {
+ DBusError buffer;
+
+ dbus_error_init(&buffer);
+
+ if (!error || !dbus_error_is_set(error)) {
+ dbus_set_error_const(&buffer, DBUS_ERROR_INVALID_ARGS, "Invalid Arguments");
+ error = &buffer;
+ }
+
+ reply = dbus_message_new_error(m->create_message, error->name, error->message);
+ dbus_error_free(&buffer);
+
+ if (!reply)
+ return log_oom();
+ } else {
+ _cleanup_free_ char *p = NULL;
+
+ p = machine_bus_path(m);
+ if (!p)
+ return log_oom();
+
+ reply = dbus_message_new_method_return(m->create_message);
+ if (!reply)
+ return log_oom();
+
+ if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &p, DBUS_TYPE_INVALID))
+ return log_oom();
+ }
+
+ /* Update the machine state file before we notify the client
+ * about the result. */
+ machine_save(m);
+
+ if (!dbus_connection_send(m->manager->bus, reply, NULL))
+ return log_oom();
+
+ dbus_message_unref(m->create_message);
+ m->create_message = NULL;
+
+ return 0;
+}
diff --git a/src/machine/machine.c b/src/machine/machine.c
new file mode 100644
index 0000000000..602aa18be6
--- /dev/null
+++ b/src/machine/machine.c
@@ -0,0 +1,414 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2011 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <systemd/sd-messages.h>
+
+#include "util.h"
+#include "mkdir.h"
+#include "hashmap.h"
+#include "strv.h"
+#include "fileio.h"
+#include "special.h"
+#include "unit-name.h"
+#include "dbus-common.h"
+#include "machine.h"
+
+Machine* machine_new(Manager *manager, const char *name) {
+ Machine *m;
+
+ assert(manager);
+ assert(name);
+
+ m = new0(Machine, 1);
+ if (!m)
+ return NULL;
+
+ m->name = strdup(name);
+ if (!m->name)
+ goto fail;
+
+ m->state_file = strappend("/run/systemd/machines/", m->name);
+ if (!m->state_file)
+ goto fail;
+
+ if (hashmap_put(manager->machines, m->name, m) < 0)
+ goto fail;
+
+ m->class = _MACHINE_CLASS_INVALID;
+ m->manager = manager;
+
+ return m;
+
+fail:
+ free(m->state_file);
+ free(m->name);
+ free(m);
+
+ return NULL;
+}
+
+void machine_free(Machine *m) {
+ assert(m);
+
+ if (m->in_gc_queue)
+ LIST_REMOVE(Machine, gc_queue, m->manager->machine_gc_queue, m);
+
+ if (m->scope) {
+ hashmap_remove(m->manager->machine_units, m->scope);
+ free(m->scope);
+ }
+
+ free(m->scope_job);
+
+ hashmap_remove(m->manager->machines, m->name);
+
+ if (m->create_message)
+ dbus_message_unref(m->create_message);
+
+ free(m->name);
+ free(m->state_file);
+ free(m->service);
+ free(m->root_directory);
+ free(m);
+}
+
+int machine_save(Machine *m) {
+ _cleanup_free_ char *temp_path = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+ int r;
+
+ assert(m);
+ assert(m->state_file);
+
+ if (!m->started)
+ return 0;
+
+ r = mkdir_safe_label("/run/systemd/machines", 0755, 0, 0);
+ if (r < 0)
+ goto finish;
+
+ r = fopen_temporary(m->state_file, &f, &temp_path);
+ if (r < 0)
+ goto finish;
+
+ fchmod(fileno(f), 0644);
+
+ fprintf(f,
+ "# This is private data. Do not parse.\n"
+ "NAME=%s\n",
+ m->name);
+
+ if (m->scope)
+ fprintf(f, "SCOPE=%s\n", m->scope);
+
+ if (m->scope_job)
+ fprintf(f, "SCOPE_JOB=%s\n", m->scope_job);
+
+ if (m->service)
+ fprintf(f, "SERVICE=%s\n", m->service);
+
+ if (m->root_directory)
+ fprintf(f, "ROOT=%s\n", m->root_directory);
+
+ if (!sd_id128_equal(m->id, SD_ID128_NULL))
+ fprintf(f, "ID=" SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(m->id));
+
+ if (m->leader != 0)
+ fprintf(f, "LEADER=%lu\n", (unsigned long) m->leader);
+
+ if (m->class != _MACHINE_CLASS_INVALID)
+ fprintf(f, "CLASS=%s\n", machine_class_to_string(m->class));
+
+ if (dual_timestamp_is_set(&m->timestamp))
+ fprintf(f,
+ "REALTIME=%llu\n"
+ "MONOTONIC=%llu\n",
+ (unsigned long long) m->timestamp.realtime,
+ (unsigned long long) m->timestamp.monotonic);
+
+ fflush(f);
+
+ if (ferror(f) || rename(temp_path, m->state_file) < 0) {
+ r = -errno;
+ unlink(m->state_file);
+ unlink(temp_path);
+ }
+
+finish:
+ if (r < 0)
+ log_error("Failed to save machine data for %s: %s", m->name, strerror(-r));
+
+ return r;
+}
+
+int machine_load(Machine *m) {
+ _cleanup_free_ char *realtime = NULL, *monotonic = NULL, *id = NULL, *leader = NULL, *class = NULL;
+ int r;
+
+ assert(m);
+
+ r = parse_env_file(m->state_file, NEWLINE,
+ "SCOPE", &m->scope,
+ "SCOPE_JOB", &m->scope_job,
+ "SERVICE", &m->service,
+ "ROOT", &m->root_directory,
+ "ID", &id,
+ "LEADER", &leader,
+ "CLASS", &class,
+ "REALTIME", &realtime,
+ "MONOTONIC", &monotonic,
+ NULL);
+ if (r < 0) {
+ if (r == -ENOENT)
+ return 0;
+
+ log_error("Failed to read %s: %s", m->state_file, strerror(-r));
+ return r;
+ }
+
+ if (id)
+ sd_id128_from_string(id, &m->id);
+
+ if (leader)
+ parse_pid(leader, &m->leader);
+
+ if (class) {
+ MachineClass c;
+
+ c = machine_class_from_string(class);
+ if (c >= 0)
+ m->class = c;
+ }
+
+ if (realtime) {
+ unsigned long long l;
+ if (sscanf(realtime, "%llu", &l) > 0)
+ m->timestamp.realtime = l;
+ }
+
+ if (monotonic) {
+ unsigned long long l;
+ if (sscanf(monotonic, "%llu", &l) > 0)
+ m->timestamp.monotonic = l;
+ }
+
+ return r;
+}
+
+static int machine_start_scope(Machine *m, DBusMessageIter *iter) {
+ _cleanup_free_ char *description = NULL;
+ DBusError error;
+ char *job;
+ int r = 0;
+
+ assert(m);
+
+ dbus_error_init(&error);
+
+ if (!m->scope) {
+ _cleanup_free_ char *escaped = NULL;
+ char *scope;
+
+ escaped = unit_name_escape(m->name);
+ if (!escaped)
+ return log_oom();
+
+ scope = strjoin("machine-", escaped, ".scope", NULL);
+ if (!scope)
+ return log_oom();
+
+ description = strappend(m->class == MACHINE_VM ? "Virtual Machine " : "Container ", m->name);
+
+ r = manager_start_scope(m->manager, scope, m->leader, SPECIAL_MACHINE_SLICE, description, iter, &error, &job);
+ if (r < 0) {
+ log_error("Failed to start machine scope: %s", bus_error(&error, r));
+ dbus_error_free(&error);
+
+ free(scope);
+ return r;
+ } else {
+ m->scope = scope;
+
+ free(m->scope_job);
+ m->scope_job = job;
+ }
+ }
+
+ if (m->scope)
+ hashmap_put(m->manager->machine_units, m->scope, m);
+
+ return r;
+}
+
+int machine_start(Machine *m, DBusMessageIter *iter) {
+ int r;
+
+ assert(m);
+
+ if (m->started)
+ return 0;
+
+ /* Create cgroup */
+ r = machine_start_scope(m, iter);
+ if (r < 0)
+ return r;
+
+ log_struct(LOG_INFO,
+ MESSAGE_ID(SD_MESSAGE_MACHINE_START),
+ "NAME=%s", m->name,
+ "LEADER=%lu", (unsigned long) m->leader,
+ "MESSAGE=New machine %s.", m->name,
+ NULL);
+
+ if (!dual_timestamp_is_set(&m->timestamp))
+ dual_timestamp_get(&m->timestamp);
+
+ m->started = true;
+
+ /* Save new machine data */
+ machine_save(m);
+
+ machine_send_signal(m, true);
+
+ return 0;
+}
+
+static int machine_stop_scope(Machine *m) {
+ DBusError error;
+ char *job;
+ int r;
+
+ assert(m);
+
+ dbus_error_init(&error);
+
+ if (!m->scope)
+ return 0;
+
+ r = manager_stop_unit(m->manager, m->scope, &error, &job);
+ if (r < 0) {
+ log_error("Failed to stop machine scope: %s", bus_error(&error, r));
+ dbus_error_free(&error);
+ return r;
+ }
+
+ free(m->scope_job);
+ m->scope_job = job;
+
+ return r;
+}
+
+int machine_stop(Machine *m) {
+ int r = 0, k;
+ assert(m);
+
+ if (m->started)
+ log_struct(LOG_INFO,
+ MESSAGE_ID(SD_MESSAGE_MACHINE_STOP),
+ "NAME=%s", m->name,
+ "LEADER=%lu", (unsigned long) m->leader,
+ "MESSAGE=Machine %s terminated.", m->name,
+ NULL);
+
+ /* Kill cgroup */
+ k = machine_stop_scope(m);
+ if (k < 0)
+ r = k;
+
+ unlink(m->state_file);
+ machine_add_to_gc_queue(m);
+
+ if (m->started)
+ machine_send_signal(m, false);
+
+ m->started = false;
+
+ return r;
+}
+
+int machine_check_gc(Machine *m, bool drop_not_started) {
+ assert(m);
+
+ if (drop_not_started && !m->started)
+ return 0;
+
+ if (m->scope_job)
+ return 1;
+
+ if (m->scope)
+ return manager_unit_is_active(m->manager, m->scope) != 0;
+
+ return 0;
+}
+
+void machine_add_to_gc_queue(Machine *m) {
+ assert(m);
+
+ if (m->in_gc_queue)
+ return;
+
+ LIST_PREPEND(Machine, gc_queue, m->manager->machine_gc_queue, m);
+ m->in_gc_queue = true;
+}
+
+MachineState machine_get_state(Machine *s) {
+ assert(s);
+
+ if (s->scope_job)
+ return s->started ? MACHINE_OPENING : MACHINE_CLOSING;
+
+ return MACHINE_RUNNING;
+}
+
+int machine_kill(Machine *m, KillWho who, int signo) {
+ assert(m);
+
+ if (!m->scope)
+ return -ESRCH;
+
+ return manager_kill_unit(m->manager, m->scope, who, signo, NULL);
+}
+
+static const char* const machine_class_table[_MACHINE_CLASS_MAX] = {
+ [MACHINE_CONTAINER] = "container",
+ [MACHINE_VM] = "vm"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(machine_class, MachineClass);
+
+static const char* const machine_state_table[_MACHINE_STATE_MAX] = {
+ [MACHINE_OPENING] = "opening",
+ [MACHINE_RUNNING] = "running",
+ [MACHINE_CLOSING] = "closing"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(machine_state, MachineState);
+
+static const char* const kill_who_table[_KILL_WHO_MAX] = {
+ [KILL_LEADER] = "leader",
+ [KILL_ALL] = "all"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);
diff --git a/src/machine/machine.h b/src/machine/machine.h
new file mode 100644
index 0000000000..c5d52a968b
--- /dev/null
+++ b/src/machine/machine.h
@@ -0,0 +1,109 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#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/>.
+***/
+
+typedef struct Machine Machine;
+typedef enum KillWho KillWho;
+
+#include "list.h"
+#include "util.h"
+#include "machined.h"
+
+typedef enum MachineState {
+ MACHINE_OPENING, /* Machine is being registered */
+ MACHINE_RUNNING, /* Machine is running */
+ MACHINE_CLOSING, /* Machine is terminating */
+ _MACHINE_STATE_MAX,
+ _MACHINE_STATE_INVALID = -1
+} MachineState;
+
+typedef enum MachineClass {
+ MACHINE_CONTAINER,
+ MACHINE_VM,
+ _MACHINE_CLASS_MAX,
+ _MACHINE_CLASS_INVALID = -1
+} MachineClass;
+
+enum KillWho {
+ KILL_LEADER,
+ KILL_ALL,
+ _KILL_WHO_MAX,
+ _KILL_WHO_INVALID = -1
+};
+
+struct Machine {
+ Manager *manager;
+
+ char *name;
+ sd_id128_t id;
+
+ MachineState state;
+ MachineClass class;
+
+ char *state_file;
+ char *service;
+ char *root_directory;
+
+ char *scope;
+ char *scope_job;
+
+ pid_t leader;
+
+ dual_timestamp timestamp;
+
+ bool in_gc_queue:1;
+ bool started:1;
+
+ DBusMessage *create_message;
+
+ LIST_FIELDS(Machine, gc_queue);
+};
+
+Machine* machine_new(Manager *manager, const char *name);
+void machine_free(Machine *m);
+int machine_check_gc(Machine *m, bool drop_not_started);
+void machine_add_to_gc_queue(Machine *m);
+int machine_start(Machine *m, DBusMessageIter *iter);
+int machine_stop(Machine *m);
+int machine_save(Machine *m);
+int machine_load(Machine *m);
+int machine_kill(Machine *m, KillWho who, int signo);
+
+char *machine_bus_path(Machine *s);
+
+MachineState machine_get_state(Machine *u);
+
+extern const DBusObjectPathVTable bus_machine_vtable;
+
+int machine_send_signal(Machine *m, bool new_machine);
+int machine_send_changed(Machine *m, const char *properties);
+
+int machine_send_create_reply(Machine *m, DBusError *error);
+
+const char* machine_class_to_string(MachineClass t) _const_;
+MachineClass machine_class_from_string(const char *s) _pure_;
+
+const char* machine_state_to_string(MachineState t) _const_;
+MachineState machine_state_from_string(const char *s) _pure_;
+
+const char *kill_who_to_string(KillWho k) _const_;
+KillWho kill_who_from_string(const char *s) _pure_;
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
new file mode 100644
index 0000000000..97c2193551
--- /dev/null
+++ b/src/machine/machinectl.c
@@ -0,0 +1,816 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ 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 <dbus/dbus.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <getopt.h>
+#include <pwd.h>
+#include <locale.h>
+
+#include "log.h"
+#include "util.h"
+#include "macro.h"
+#include "pager.h"
+#include "dbus-common.h"
+#include "build.h"
+#include "strv.h"
+#include "unit-name.h"
+#include "cgroup-show.h"
+#include "cgroup-util.h"
+#include "spawn-polkit-agent.h"
+
+static char **arg_property = NULL;
+static bool arg_all = false;
+static bool arg_full = false;
+static bool arg_no_pager = false;
+static const char *arg_kill_who = NULL;
+static int arg_signal = SIGTERM;
+static enum transport {
+ TRANSPORT_NORMAL,
+ TRANSPORT_SSH,
+ TRANSPORT_POLKIT
+} arg_transport = TRANSPORT_NORMAL;
+static bool arg_ask_password = true;
+static char *arg_host = NULL;
+static char *arg_user = NULL;
+
+static void pager_open_if_enabled(void) {
+
+ /* Cache result before we open the pager */
+ if (arg_no_pager)
+ return;
+
+ pager_open(false);
+}
+
+static int list_machines(DBusConnection *bus, char **args, unsigned n) {
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ DBusMessageIter iter, sub, sub2;
+ unsigned k = 0;
+ int r;
+
+ pager_open_if_enabled();
+
+ r = bus_method_call_with_reply (
+ bus,
+ "org.freedesktop.machine1",
+ "/org/freedesktop/machine1",
+ "org.freedesktop.machine1.Manager",
+ "ListMachines",
+ &reply,
+ NULL,
+ DBUS_TYPE_INVALID);
+ if (r)
+ return r;
+
+ if (!dbus_message_iter_init(reply, &iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
+ log_error("Failed to parse reply.");
+ return -EIO;
+ }
+
+ dbus_message_iter_recurse(&iter, &sub);
+
+ if (on_tty())
+ printf("%-32s %-9s %-16s\n", "MACHINE", "CONTAINER", "SERVICE");
+
+ while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
+ const char *name, *class, *service, *object;
+
+ if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
+ log_error("Failed to parse reply.");
+ return -EIO;
+ }
+
+ dbus_message_iter_recurse(&sub, &sub2);
+
+ if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &class, true) < 0 ||
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &service, true) < 0 ||
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &object, false) < 0) {
+ log_error("Failed to parse reply.");
+ return -EIO;
+ }
+
+ printf("%-32s %-9s %-16s\n", name, class, service);
+
+ k++;
+
+ dbus_message_iter_next(&sub);
+ }
+
+ if (on_tty())
+ printf("\n%u machines listed.\n", k);
+
+ return 0;
+}
+
+static int show_scope_cgroup(DBusConnection *bus, const char *unit, pid_t leader) {
+ const char *interface = "org.freedesktop.systemd1.Scope";
+ const char *property = "ControlGroup";
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ _cleanup_free_ char *path = NULL;
+ DBusMessageIter iter, sub;
+ const char *cgroup;
+ DBusError error;
+ int r, output_flags;
+ unsigned c;
+
+ assert(bus);
+ assert(unit);
+
+ if (arg_transport == TRANSPORT_SSH)
+ return 0;
+
+ path = unit_dbus_path_from_name(unit);
+ if (!path)
+ return log_oom();
+
+ r = bus_method_call_with_reply(
+ bus,
+ "org.freedesktop.systemd1",
+ path,
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ &reply,
+ &error,
+ DBUS_TYPE_STRING, &interface,
+ DBUS_TYPE_STRING, &property,
+ DBUS_TYPE_INVALID);
+ if (r < 0) {
+ log_error("Failed to query ControlGroup: %s", bus_error(&error, r));
+ dbus_error_free(&error);
+ return r;
+ }
+
+ if (!dbus_message_iter_init(reply, &iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
+ log_error("Failed to parse reply.");
+ return -EINVAL;
+ }
+
+ dbus_message_iter_recurse(&iter, &sub);
+ if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
+ log_error("Failed to parse reply.");
+ return -EINVAL;
+ }
+
+ dbus_message_iter_get_basic(&sub, &cgroup);
+
+ if (isempty(cgroup))
+ return 0;
+
+ if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
+ return 0;
+
+ output_flags =
+ arg_all * OUTPUT_SHOW_ALL |
+ arg_full * OUTPUT_FULL_WIDTH;
+
+ c = columns();
+ if (c > 18)
+ c -= 18;
+ else
+ c = 0;
+
+ show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, output_flags);
+ return 0;
+}
+
+typedef struct MachineStatusInfo {
+ const char *name;
+ sd_id128_t id;
+ const char *class;
+ const char *service;
+ const char *scope;
+ const char *root_directory;
+ pid_t leader;
+ usec_t timestamp;
+} MachineStatusInfo;
+
+static void print_machine_status_info(DBusConnection *bus, MachineStatusInfo *i) {
+ char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
+ char since2[FORMAT_TIMESTAMP_MAX], *s2;
+ assert(i);
+
+ fputs(strna(i->name), stdout);
+
+ if (!sd_id128_equal(i->id, SD_ID128_NULL))
+ printf("(" SD_ID128_FORMAT_STR ")\n", SD_ID128_FORMAT_VAL(i->id));
+ else
+ putchar('\n');
+
+ s1 = format_timestamp_relative(since1, sizeof(since1), i->timestamp);
+ s2 = format_timestamp(since2, sizeof(since2), i->timestamp);
+
+ if (s1)
+ printf("\t Since: %s; %s\n", s2, s1);
+ else if (s2)
+ printf("\t Since: %s\n", s2);
+
+ if (i->leader > 0) {
+ _cleanup_free_ char *t = NULL;
+
+ printf("\t Leader: %u", (unsigned) i->leader);
+
+ get_process_comm(i->leader, &t);
+ if (t)
+ printf(" (%s)", t);
+
+ putchar('\n');
+ }
+
+ if (i->service) {
+ printf("\t Service: %s", i->service);
+
+ if (i->class)
+ printf("; class %s", i->class);
+
+ putchar('\n');
+ } else if (i->class)
+ printf("\t Class: %s\n", i->class);
+
+ if (i->root_directory)
+ printf("\t Root: %s\n", i->root_directory);
+
+ if (i->scope) {
+ printf("\t Unit: %s\n", i->scope);
+ show_scope_cgroup(bus, i->scope, i->leader);
+ }
+}
+
+static int status_property_machine(const char *name, DBusMessageIter *iter, MachineStatusInfo *i) {
+ assert(name);
+ assert(iter);
+ assert(i);
+
+ switch (dbus_message_iter_get_arg_type(iter)) {
+
+ case DBUS_TYPE_STRING: {
+ const char *s;
+
+ dbus_message_iter_get_basic(iter, &s);
+
+ if (!isempty(s)) {
+ if (streq(name, "Name"))
+ i->name = s;
+ else if (streq(name, "Class"))
+ i->class = s;
+ else if (streq(name, "Service"))
+ i->service = s;
+ else if (streq(name, "Scope"))
+ i->scope = s;
+ else if (streq(name, "RootDirectory"))
+ i->root_directory = s;
+ }
+ break;
+ }
+
+ case DBUS_TYPE_UINT32: {
+ uint32_t u;
+
+ dbus_message_iter_get_basic(iter, &u);
+
+ if (streq(name, "Leader"))
+ i->leader = (pid_t) u;
+
+ break;
+ }
+
+ case DBUS_TYPE_UINT64: {
+ uint64_t u;
+
+ dbus_message_iter_get_basic(iter, &u);
+
+ if (streq(name, "Timestamp"))
+ i->timestamp = (usec_t) u;
+
+ break;
+ }
+
+ case DBUS_TYPE_ARRAY: {
+ DBusMessageIter sub;
+
+ dbus_message_iter_recurse(iter, &sub);
+
+ if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_BYTE && streq(name, "Id")) {
+ void *v;
+ int n;
+
+ dbus_message_iter_get_fixed_array(&sub, &v, &n);
+ if (n == 0)
+ i->id = SD_ID128_NULL;
+ else if (n == 16)
+ memcpy(&i->id, v, n);
+ }
+
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int print_property(const char *name, DBusMessageIter *iter) {
+ assert(name);
+ assert(iter);
+
+ if (arg_property && !strv_find(arg_property, name))
+ return 0;
+
+ if (generic_print_property(name, iter, arg_all) > 0)
+ return 0;
+
+ if (arg_all)
+ printf("%s=[unprintable]\n", name);
+
+ return 0;
+}
+
+static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ const char *interface = "";
+ int r;
+ DBusMessageIter iter, sub, sub2, sub3;
+ MachineStatusInfo machine_info = {};
+
+ assert(path);
+ assert(new_line);
+
+ r = bus_method_call_with_reply(
+ bus,
+ "org.freedesktop.machine1",
+ path,
+ "org.freedesktop.DBus.Properties",
+ "GetAll",
+ &reply,
+ NULL,
+ DBUS_TYPE_STRING, &interface,
+ DBUS_TYPE_INVALID);
+ if (r < 0)
+ goto finish;
+
+ if (!dbus_message_iter_init(reply, &iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
+ log_error("Failed to parse reply.");
+ r = -EIO;
+ goto finish;
+ }
+
+ dbus_message_iter_recurse(&iter, &sub);
+
+ if (*new_line)
+ printf("\n");
+
+ *new_line = true;
+
+ while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
+ const char *name;
+
+ if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
+ log_error("Failed to parse reply.");
+ r = -EIO;
+ goto finish;
+ }
+
+ dbus_message_iter_recurse(&sub, &sub2);
+
+ if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
+ log_error("Failed to parse reply.");
+ r = -EIO;
+ goto finish;
+ }
+
+ if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
+ log_error("Failed to parse reply.");
+ r = -EIO;
+ goto finish;
+ }
+
+ dbus_message_iter_recurse(&sub2, &sub3);
+
+ if (show_properties)
+ r = print_property(name, &sub3);
+ else
+ r = status_property_machine(name, &sub3, &machine_info);
+
+ if (r < 0) {
+ log_error("Failed to parse reply.");
+ goto finish;
+ }
+
+ dbus_message_iter_next(&sub);
+ }
+
+ if (!show_properties)
+ print_machine_status_info(bus, &machine_info);
+
+ r = 0;
+
+finish:
+
+ return r;
+}
+
+static int show(DBusConnection *bus, char **args, unsigned n) {
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ int r, ret = 0;
+ DBusError error;
+ unsigned i;
+ bool show_properties, new_line = false;
+
+ assert(bus);
+ assert(args);
+
+ dbus_error_init(&error);
+
+ show_properties = !strstr(args[0], "status");
+
+ pager_open_if_enabled();
+
+ if (show_properties && n <= 1) {
+ /* If not argument is specified inspect the manager
+ * itself */
+
+ ret = show_one(args[0], bus, "/org/freedesktop/machine1", show_properties, &new_line);
+ goto finish;
+ }
+
+ for (i = 1; i < n; i++) {
+ const char *path = NULL;
+
+ ret = bus_method_call_with_reply(
+ bus,
+ "org.freedesktop.machine1",
+ "/org/freedesktop/machine1",
+ "org.freedesktop.machine1.Manager",
+ "GetMachine",
+ &reply,
+ NULL,
+ DBUS_TYPE_STRING, &args[i],
+ DBUS_TYPE_INVALID);
+ if (ret < 0)
+ goto finish;
+
+ if (!dbus_message_get_args(reply, &error,
+ DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID)) {
+ log_error("Failed to parse reply: %s", bus_error_message(&error));
+ ret = -EIO;
+ goto finish;
+ }
+
+ r = show_one(args[0], bus, path, show_properties, &new_line);
+ if (r != 0)
+ ret = r;
+ }
+
+finish:
+ dbus_error_free(&error);
+
+ return ret;
+}
+
+static int kill_machine(DBusConnection *bus, char **args, unsigned n) {
+ unsigned i;
+
+ assert(args);
+
+ if (!arg_kill_who)
+ arg_kill_who = "all";
+
+ for (i = 1; i < n; i++) {
+ int r;
+
+ r = bus_method_call_with_reply (
+ bus,
+ "org.freedesktop.machine1",
+ "/org/freedesktop/machine1",
+ "org.freedesktop.machine1.Manager",
+ "KillMachine",
+ NULL,
+ NULL,
+ DBUS_TYPE_STRING, &args[i],
+ DBUS_TYPE_STRING, &arg_kill_who,
+ DBUS_TYPE_INT32, &arg_signal,
+ DBUS_TYPE_INVALID);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
+static int terminate_machine(DBusConnection *bus, char **args, unsigned n) {
+ unsigned i;
+
+ assert(args);
+
+ for (i = 1; i < n; i++) {
+ int r;
+
+ r = bus_method_call_with_reply (
+ bus,
+ "org.freedesktop.machine1",
+ "/org/freedesktop/machine1",
+ "org.freedesktop.machine1.Manager",
+ "TerminateMachine",
+ NULL,
+ NULL,
+ DBUS_TYPE_STRING, &args[i],
+ DBUS_TYPE_INVALID);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
+static int help(void) {
+
+ printf("%s [OPTIONS...] {COMMAND} ...\n\n"
+ "Send control commands to or query the virtual machine and container registration manager.\n\n"
+ " -h --help Show this help\n"
+ " --version Show package version\n"
+ " -p --property=NAME Show only properties by this name\n"
+ " -a --all Show all properties, including empty ones\n"
+ " --kill-who=WHO Who to send signal to\n"
+ " -l --full Do not ellipsize output\n"
+ " -s --signal=SIGNAL Which signal to send\n"
+ " --no-ask-password Don't prompt for password\n"
+ " -H --host=[USER@]HOST Show information for remote host\n"
+ " -P --privileged Acquire privileges before execution\n"
+ " --no-pager Do not pipe output into a pager\n\n"
+ "Commands:\n"
+ " list List running VMs and containers\n"
+ " status [NAME...] Show VM/container status\n"
+ " show [NAME...] Show properties of one or more VMs/containers\n"
+ " terminate [NAME...] Terminate one or more VMs/containers\n"
+ " kill [NAME...] Send signal to processes of a VM/container\n",
+ program_invocation_short_name);
+
+ return 0;
+}
+
+static int parse_argv(int argc, char *argv[]) {
+
+ enum {
+ ARG_VERSION = 0x100,
+ ARG_NO_PAGER,
+ ARG_KILL_WHO,
+ ARG_NO_ASK_PASSWORD,
+ };
+
+ static const struct option options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "property", required_argument, NULL, 'p' },
+ { "all", no_argument, NULL, 'a' },
+ { "full", no_argument, NULL, 'l' },
+ { "no-pager", no_argument, NULL, ARG_NO_PAGER },
+ { "kill-who", required_argument, NULL, ARG_KILL_WHO },
+ { "signal", required_argument, NULL, 's' },
+ { "host", required_argument, NULL, 'H' },
+ { "privileged", no_argument, NULL, 'P' },
+ { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
+ { NULL, 0, NULL, 0 }
+ };
+
+ int c;
+
+ assert(argc >= 0);
+ assert(argv);
+
+ while ((c = getopt_long(argc, argv, "hp:als:H:P", options, NULL)) >= 0) {
+
+ switch (c) {
+
+ case 'h':
+ help();
+ return 0;
+
+ case ARG_VERSION:
+ puts(PACKAGE_STRING);
+ puts(SYSTEMD_FEATURES);
+ return 0;
+
+ case 'p': {
+ char **l;
+
+ l = strv_append(arg_property, optarg);
+ if (!l)
+ return -ENOMEM;
+
+ strv_free(arg_property);
+ arg_property = l;
+
+ /* If the user asked for a particular
+ * property, show it to him, even if it is
+ * empty. */
+ arg_all = true;
+ break;
+ }
+
+ case 'a':
+ arg_all = true;
+ break;
+
+ case 'l':
+ arg_full = true;
+ break;
+
+ case ARG_NO_PAGER:
+ arg_no_pager = true;
+ break;
+
+ case ARG_NO_ASK_PASSWORD:
+ arg_ask_password = false;
+ break;
+
+ case ARG_KILL_WHO:
+ arg_kill_who = optarg;
+ break;
+
+ case 's':
+ arg_signal = signal_from_string_try_harder(optarg);
+ if (arg_signal < 0) {
+ log_error("Failed to parse signal string %s.", optarg);
+ return -EINVAL;
+ }
+ break;
+
+ case 'P':
+ arg_transport = TRANSPORT_POLKIT;
+ break;
+
+ case 'H':
+ arg_transport = TRANSPORT_SSH;
+ parse_user_at_host(optarg, &arg_user, &arg_host);
+ break;
+
+ case '?':
+ return -EINVAL;
+
+ default:
+ log_error("Unknown option code %c", c);
+ return -EINVAL;
+ }
+ }
+
+ return 1;
+}
+
+static int machinectl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
+
+ static const struct {
+ const char* verb;
+ const enum {
+ MORE,
+ LESS,
+ EQUAL
+ } argc_cmp;
+ const int argc;
+ int (* const dispatch)(DBusConnection *bus, char **args, unsigned n);
+ } verbs[] = {
+ { "list", LESS, 1, list_machines },
+ { "status", MORE, 2, show },
+ { "show", MORE, 1, show },
+ { "terminate", MORE, 2, terminate_machine },
+ { "kill", MORE, 2, kill_machine },
+ };
+
+ int left;
+ unsigned i;
+
+ assert(argc >= 0);
+ assert(argv);
+ assert(error);
+
+ left = argc - optind;
+
+ if (left <= 0)
+ /* Special rule: no arguments means "list-sessions" */
+ i = 0;
+ else {
+ if (streq(argv[optind], "help")) {
+ help();
+ return 0;
+ }
+
+ for (i = 0; i < ELEMENTSOF(verbs); i++)
+ if (streq(argv[optind], verbs[i].verb))
+ break;
+
+ if (i >= ELEMENTSOF(verbs)) {
+ log_error("Unknown operation %s", argv[optind]);
+ return -EINVAL;
+ }
+ }
+
+ switch (verbs[i].argc_cmp) {
+
+ case EQUAL:
+ if (left != verbs[i].argc) {
+ log_error("Invalid number of arguments.");
+ return -EINVAL;
+ }
+
+ break;
+
+ case MORE:
+ if (left < verbs[i].argc) {
+ log_error("Too few arguments.");
+ return -EINVAL;
+ }
+
+ break;
+
+ case LESS:
+ if (left > verbs[i].argc) {
+ log_error("Too many arguments.");
+ return -EINVAL;
+ }
+
+ break;
+
+ default:
+ assert_not_reached("Unknown comparison operator.");
+ }
+
+ if (!bus) {
+ log_error("Failed to get D-Bus connection: %s", error->message);
+ return -EIO;
+ }
+
+ return verbs[i].dispatch(bus, argv + optind, left);
+}
+
+int main(int argc, char*argv[]) {
+ int r, retval = EXIT_FAILURE;
+ DBusConnection *bus = NULL;
+ DBusError error;
+
+ dbus_error_init(&error);
+
+ setlocale(LC_ALL, "");
+ log_parse_environment();
+ log_open();
+
+ r = parse_argv(argc, argv);
+ if (r < 0)
+ goto finish;
+ else if (r == 0) {
+ retval = EXIT_SUCCESS;
+ goto finish;
+ }
+
+ if (arg_transport == TRANSPORT_NORMAL)
+ bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
+ else if (arg_transport == TRANSPORT_POLKIT)
+ bus_connect_system_polkit(&bus, &error);
+ else if (arg_transport == TRANSPORT_SSH)
+ bus_connect_system_ssh(NULL, arg_host, &bus, &error);
+ else
+ assert_not_reached("Uh, invalid transport...");
+
+ r = machinectl_main(bus, argc, argv, &error);
+ retval = r < 0 ? EXIT_FAILURE : r;
+
+finish:
+ if (bus) {
+ dbus_connection_flush(bus);
+ dbus_connection_close(bus);
+ dbus_connection_unref(bus);
+ }
+
+ dbus_error_free(&error);
+ dbus_shutdown();
+
+ strv_free(arg_property);
+
+ pager_close();
+
+ return retval;
+}
diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c
new file mode 100644
index 0000000000..22caadfceb
--- /dev/null
+++ b/src/machine/machined-dbus.c
@@ -0,0 +1,1042 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2011 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+
+#include <systemd/sd-id128.h>
+#include <systemd/sd-messages.h>
+
+#include "machined.h"
+#include "dbus-common.h"
+#include "strv.h"
+#include "mkdir.h"
+#include "path-util.h"
+#include "special.h"
+#include "sleep-config.h"
+#include "fileio-label.h"
+#include "label.h"
+#include "utf8.h"
+#include "unit-name.h"
+#include "bus-errors.h"
+#include "virt.h"
+#include "cgroup-util.h"
+
+#define BUS_MANAGER_INTERFACE \
+ " <interface name=\"org.freedesktop.machine1.Manager\">\n" \
+ " <method name=\"GetMachine\">\n" \
+ " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"machine\" type=\"o\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ " <method name=\"GetMachineByPID\">\n" \
+ " <arg name=\"pid\" type=\"u\" direction=\"in\"/>\n" \
+ " <arg name=\"machine\" type=\"o\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ " <method name=\"ListMachines\">\n" \
+ " <arg name=\"machines\" type=\"a(ssso)\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ " <method name=\"CreateMachine\">\n" \
+ " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"id\" type=\"ay\" direction=\"in\"/>\n" \
+ " <arg name=\"service\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"class\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"leader\" type=\"u\" direction=\"in\"/>\n" \
+ " <arg name=\"root_directory\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"scope_properties\" type=\"a(sv)\" direction=\"in\"/>\n" \
+ " <arg name=\"path\" type=\"o\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ " <method name=\"KillMachine\">\n" \
+ " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"who\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"signal\" type=\"s\" direction=\"in\"/>\n" \
+ " </method>\n" \
+ " <method name=\"TerminateMachine\">\n" \
+ " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
+ " </method>\n" \
+ " <signal name=\"MachineNew\">\n" \
+ " <arg name=\"machine\" type=\"s\"/>\n" \
+ " <arg name=\"path\" type=\"o\"/>\n" \
+ " </signal>\n" \
+ " <signal name=\"MachineRemoved\">\n" \
+ " <arg name=\"machine\" type=\"s\"/>\n" \
+ " <arg name=\"path\" type=\"o\"/>\n" \
+ " </signal>\n" \
+ " </interface>\n"
+
+#define INTROSPECTION_BEGIN \
+ DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
+ "<node>\n" \
+ BUS_MANAGER_INTERFACE \
+ BUS_PROPERTIES_INTERFACE \
+ BUS_PEER_INTERFACE \
+ BUS_INTROSPECTABLE_INTERFACE
+
+#define INTROSPECTION_END \
+ "</node>\n"
+
+#define INTERFACES_LIST \
+ BUS_GENERIC_INTERFACES_LIST \
+ "org.freedesktop.machine1.Manager\0"
+
+static bool valid_machine_name(const char *p) {
+ size_t l;
+
+ if (!filename_is_safe(p))
+ return false;
+
+ if (!ascii_is_valid(p))
+ return false;
+
+ l = strlen(p);
+
+ if (l < 1 || l> 64)
+ return false;
+
+ return true;
+}
+
+static int bus_manager_create_machine(Manager *manager, DBusMessage *message) {
+
+ const char *name, *service, *class, *root_directory;
+ DBusMessageIter iter, sub;
+ MachineClass c;
+ uint32_t leader;
+ sd_id128_t id;
+ Machine *m;
+ int n, r;
+ void *v;
+
+ assert(manager);
+ assert(message);
+
+ if (!dbus_message_iter_init(message, &iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&iter, &name);
+
+ if (!valid_machine_name(name) ||
+ !dbus_message_iter_next(&iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE)
+ return -EINVAL;
+
+ dbus_message_iter_recurse(&iter, &sub);
+ dbus_message_iter_get_fixed_array(&sub, &v, &n);
+
+ if (n == 0)
+ id = SD_ID128_NULL;
+ else if (n == 16)
+ memcpy(&id, v, n);
+ else
+ return -EINVAL;
+
+ if (!dbus_message_iter_next(&iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&iter, &service);
+
+ if (!dbus_message_iter_next(&iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&iter, &class);
+
+ if (isempty(class))
+ c = _MACHINE_CLASS_INVALID;
+ else {
+ c = machine_class_from_string(class);
+ if (c < 0)
+ return -EINVAL;
+ }
+
+ if (!dbus_message_iter_next(&iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&iter, &leader);
+ if (!dbus_message_iter_next(&iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&iter, &root_directory);
+
+ if (!(isempty(root_directory) || path_is_absolute(root_directory)))
+ return -EINVAL;
+
+ if (!dbus_message_iter_next(&iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT)
+ return -EINVAL;
+
+ dbus_message_iter_recurse(&iter, &sub);
+
+ if (hashmap_get(manager->machines, name))
+ return -EEXIST;
+
+ if (leader <= 0) {
+ leader = bus_get_unix_process_id(manager->bus, dbus_message_get_sender(message), NULL);
+ if (leader == 0)
+ return -EINVAL;
+ }
+
+ r = manager_add_machine(manager, name, &m);
+ if (r < 0)
+ goto fail;
+
+ m->leader = leader;
+ m->class = c;
+ m->id = id;
+
+ if (!isempty(service)) {
+ m->service = strdup(service);
+ if (!m->service) {
+ r = -ENOMEM;
+ goto fail;
+ }
+ }
+
+ if (!isempty(root_directory)) {
+ m->root_directory = strdup(root_directory);
+ if (!m->root_directory) {
+ r = -ENOMEM;
+ goto fail;
+ }
+ }
+
+ r = machine_start(m, &sub);
+ if (r < 0)
+ goto fail;
+
+ m->create_message = dbus_message_ref(message);
+
+ return 0;
+
+fail:
+ if (m)
+ machine_add_to_gc_queue(m);
+
+ return r;
+}
+
+static DBusHandlerResult manager_message_handler(
+ DBusConnection *connection,
+ DBusMessage *message,
+ void *userdata) {
+
+ Manager *m = userdata;
+
+ DBusError error;
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ int r;
+
+ assert(connection);
+ assert(message);
+ assert(m);
+
+ dbus_error_init(&error);
+
+ if (dbus_message_is_method_call(message, "org.freedesktop.machine1.Manager", "GetMachine")) {
+ Machine *machine;
+ const char *name;
+ char *p;
+ bool b;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ machine = hashmap_get(m->machines, name);
+ if (!machine)
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ p = machine_bus_path(machine);
+ if (!p)
+ goto oom;
+
+ b = dbus_message_append_args(
+ reply,
+ DBUS_TYPE_OBJECT_PATH, &p,
+ DBUS_TYPE_INVALID);
+ free(p);
+
+ if (!b)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.machine1.Manager", "GetMachineByPID")) {
+ uint32_t pid;
+ char *p;
+ Machine *machine;
+ bool b;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_UINT32, &pid,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ r = manager_get_machine_by_pid(m, pid, &machine);
+ if (r <= 0)
+ return bus_send_error_reply(connection, message, NULL, r < 0 ? r : -ENOENT);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ p = machine_bus_path(machine);
+ if (!p)
+ goto oom;
+
+ b = dbus_message_append_args(
+ reply,
+ DBUS_TYPE_OBJECT_PATH, &p,
+ DBUS_TYPE_INVALID);
+ free(p);
+
+ if (!b)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.machine1.Manager", "ListMachines")) {
+ Machine *machine;
+ Iterator i;
+ DBusMessageIter iter, sub;
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssso)", &sub))
+ goto oom;
+
+ HASHMAP_FOREACH(machine, m->machines, i) {
+ _cleanup_free_ char *p = NULL;
+ DBusMessageIter sub2;
+ const char *class;
+
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
+ goto oom;
+
+ p = machine_bus_path(machine);
+ if (!p)
+ goto oom;
+
+ class = strempty(machine_class_to_string(machine->class));
+
+ if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &machine->name) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &class) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &machine->service) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &p)) {
+ free(p);
+ goto oom;
+ }
+
+ if (!dbus_message_iter_close_container(&sub, &sub2))
+ goto oom;
+ }
+
+ if (!dbus_message_iter_close_container(&iter, &sub))
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.machine1.Manager", "CreateMachine")) {
+
+ r = bus_manager_create_machine(m, message);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.machine1.Manager", "KillMachine")) {
+ const char *swho;
+ int32_t signo;
+ KillWho who;
+ const char *name;
+ Machine *machine;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_STRING, &swho,
+ DBUS_TYPE_INT32, &signo,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ if (isempty(swho))
+ who = KILL_ALL;
+ else {
+ who = kill_who_from_string(swho);
+ if (who < 0)
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+ }
+
+ if (signo <= 0 || signo >= _NSIG)
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ machine = hashmap_get(m->machines, name);
+ if (!machine)
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
+
+ r = machine_kill(machine, who, signo);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.machine1.Manager", "TerminateMachine")) {
+ const char *name;
+ Machine *machine;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ machine = hashmap_get(m->machines, name);
+ if (!machine)
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
+
+ r = machine_stop(machine);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
+ char *introspection = NULL;
+ FILE *f;
+ Iterator i;
+ Machine *machine;
+ size_t size;
+ char *p;
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ /* We roll our own introspection code here, instead of
+ * relying on bus_default_message_handler() because we
+ * need to generate our introspection string
+ * dynamically. */
+
+ f = open_memstream(&introspection, &size);
+ if (!f)
+ goto oom;
+
+ fputs(INTROSPECTION_BEGIN, f);
+
+ HASHMAP_FOREACH(machine, m->machines, i) {
+ p = bus_path_escape(machine->name);
+
+ if (p) {
+ fprintf(f, "<node name=\"machine/%s\"/>", p);
+ free(p);
+ }
+ }
+
+ fputs(INTROSPECTION_END, f);
+
+ if (ferror(f)) {
+ fclose(f);
+ free(introspection);
+ goto oom;
+ }
+
+ fclose(f);
+
+ if (!introspection)
+ goto oom;
+
+ if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
+ free(introspection);
+ goto oom;
+ }
+
+ free(introspection);
+ } else
+ return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, NULL);
+
+ if (reply) {
+ if (!bus_maybe_send_reply(connection, message, reply))
+ goto oom;
+ }
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+
+oom:
+ dbus_error_free(&error);
+
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+}
+
+const DBusObjectPathVTable bus_manager_vtable = {
+ .message_function = manager_message_handler
+};
+
+DBusHandlerResult bus_message_filter(
+ DBusConnection *connection,
+ DBusMessage *message,
+ void *userdata) {
+
+ Manager *m = userdata;
+ DBusError error;
+
+ assert(m);
+ assert(connection);
+ assert(message);
+
+ dbus_error_init(&error);
+
+ log_debug("Got message: %s %s %s", strna(dbus_message_get_sender(message)), strna(dbus_message_get_interface(message)), strna(dbus_message_get_member(message)));
+
+ if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
+ const char *path, *result, *unit;
+ Machine *mm;
+ uint32_t id;
+
+ if (!dbus_message_get_args(message, &error,
+ DBUS_TYPE_UINT32, &id,
+ DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_STRING, &unit,
+ DBUS_TYPE_STRING, &result,
+ DBUS_TYPE_INVALID)) {
+ log_error("Failed to parse JobRemoved message: %s", bus_error_message(&error));
+ goto finish;
+ }
+
+ mm = hashmap_get(m->machine_units, unit);
+ if (mm) {
+ if (streq_ptr(path, mm->scope_job)) {
+ free(mm->scope_job);
+ mm->scope_job = NULL;
+
+ if (mm->started) {
+ if (streq(result, "done"))
+ machine_send_create_reply(mm, NULL);
+ else {
+ dbus_set_error(&error, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
+ machine_send_create_reply(mm, &error);
+ }
+ } else
+ machine_save(mm);
+ }
+
+ machine_add_to_gc_queue(mm);
+ }
+
+ } else if (dbus_message_is_signal(message, "org.freedesktop.DBus.Properties", "PropertiesChanged")) {
+
+ _cleanup_free_ char *unit = NULL;
+ const char *path;
+
+ path = dbus_message_get_path(message);
+ if (!path)
+ goto finish;
+
+ unit_name_from_dbus_path(path, &unit);
+ if (unit) {
+ Machine *mm;
+
+ mm = hashmap_get(m->machine_units, unit);
+ if (mm)
+ machine_add_to_gc_queue(mm);
+ }
+
+ } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "UnitRemoved")) {
+ const char *path, *unit;
+ Machine *mm;
+
+ if (!dbus_message_get_args(message, &error,
+ DBUS_TYPE_STRING, &unit,
+ DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID)) {
+ log_error("Failed to parse UnitRemoved message: %s", bus_error_message(&error));
+ goto finish;
+ }
+
+ mm = hashmap_get(m->machine_units, unit);
+ if (mm)
+ machine_add_to_gc_queue(mm);
+
+ } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "Reloading")) {
+ dbus_bool_t b;
+
+ if (!dbus_message_get_args(message, &error,
+ DBUS_TYPE_BOOLEAN, &b,
+ DBUS_TYPE_INVALID)) {
+ log_error("Failed to parse Reloading message: %s", bus_error_message(&error));
+ goto finish;
+ }
+
+ /* systemd finished reloading, let's recheck all our machines */
+ if (!b) {
+ Machine *mm;
+ Iterator i;
+
+ log_debug("System manager has been reloaded, rechecking machines...");
+
+ HASHMAP_FOREACH(mm, m->machines, i)
+ machine_add_to_gc_queue(mm);
+ }
+ }
+
+finish:
+ dbus_error_free(&error);
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static int copy_many_fields(DBusMessageIter *dest, DBusMessageIter *src);
+
+static int copy_one_field(DBusMessageIter *dest, DBusMessageIter *src) {
+ int type, r;
+
+ type = dbus_message_iter_get_arg_type(src);
+
+ switch (type) {
+
+ case DBUS_TYPE_STRUCT: {
+ DBusMessageIter dest_sub, src_sub;
+
+ dbus_message_iter_recurse(src, &src_sub);
+
+ if (!dbus_message_iter_open_container(dest, DBUS_TYPE_STRUCT, NULL, &dest_sub))
+ return log_oom();
+
+ r = copy_many_fields(&dest_sub, &src_sub);
+ if (r < 0)
+ return r;
+
+ if (!dbus_message_iter_close_container(dest, &dest_sub))
+ return log_oom();
+
+ return 0;
+ }
+
+ case DBUS_TYPE_ARRAY: {
+ DBusMessageIter dest_sub, src_sub;
+
+ dbus_message_iter_recurse(src, &src_sub);
+
+ if (!dbus_message_iter_open_container(dest, DBUS_TYPE_ARRAY, dbus_message_iter_get_signature(&src_sub), &dest_sub))
+ return log_oom();
+
+ r = copy_many_fields(&dest_sub, &src_sub);
+ if (r < 0)
+ return r;
+
+ if (!dbus_message_iter_close_container(dest, &dest_sub))
+ return log_oom();
+
+ return 0;
+ }
+
+ case DBUS_TYPE_VARIANT: {
+ DBusMessageIter dest_sub, src_sub;
+
+ dbus_message_iter_recurse(src, &src_sub);
+
+ if (!dbus_message_iter_open_container(dest, DBUS_TYPE_VARIANT, dbus_message_iter_get_signature(&src_sub), &dest_sub))
+ return log_oom();
+
+ r = copy_one_field(&dest_sub, &src_sub);
+ if (r < 0)
+ return r;
+
+ if (!dbus_message_iter_close_container(dest, &dest_sub))
+ return log_oom();
+
+ return 0;
+ }
+
+ case DBUS_TYPE_STRING:
+ case DBUS_TYPE_OBJECT_PATH:
+ case DBUS_TYPE_BYTE:
+ case DBUS_TYPE_BOOLEAN:
+ case DBUS_TYPE_UINT16:
+ case DBUS_TYPE_INT16:
+ case DBUS_TYPE_UINT32:
+ case DBUS_TYPE_INT32:
+ case DBUS_TYPE_UINT64:
+ case DBUS_TYPE_INT64:
+ case DBUS_TYPE_DOUBLE:
+ case DBUS_TYPE_SIGNATURE: {
+ const void *p;
+
+ dbus_message_iter_get_basic(src, &p);
+ dbus_message_iter_append_basic(dest, type, &p);
+ return 0;
+ }
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int copy_many_fields(DBusMessageIter *dest, DBusMessageIter *src) {
+ int r;
+
+ assert(dest);
+ assert(src);
+
+ while (dbus_message_iter_get_arg_type(src) != DBUS_TYPE_INVALID) {
+
+ r = copy_one_field(dest, src);
+ if (r < 0)
+ return r;
+
+ dbus_message_iter_next(src);
+ }
+
+ return 0;
+}
+
+int manager_start_scope(
+ Manager *manager,
+ const char *scope,
+ pid_t pid,
+ const char *slice,
+ const char *description,
+ DBusMessageIter *more_properties,
+ DBusError *error,
+ char **job) {
+
+ _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
+ DBusMessageIter iter, sub, sub2, sub3, sub4;
+ const char *timeout_stop_property = "TimeoutStopUSec";
+ const char *pids_property = "PIDs";
+ uint64_t timeout = 500 * USEC_PER_MSEC;
+ const char *fail = "fail";
+ uint32_t u;
+ int r;
+
+ assert(manager);
+ assert(scope);
+ assert(pid > 1);
+
+ if (!slice)
+ slice = "";
+
+ m = dbus_message_new_method_call(
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "StartTransientUnit");
+ if (!m)
+ return log_oom();
+
+ dbus_message_iter_init_append(m, &iter);
+
+ if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &scope) ||
+ !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &fail) ||
+ !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sv)", &sub))
+ return log_oom();
+
+ if (!isempty(slice)) {
+ const char *slice_property = "Slice";
+
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &slice_property) ||
+ !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, "s", &sub3) ||
+ !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &slice) ||
+ !dbus_message_iter_close_container(&sub2, &sub3) ||
+ !dbus_message_iter_close_container(&sub, &sub2))
+ return log_oom();
+ }
+
+ if (!isempty(description)) {
+ const char *description_property = "Description";
+
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description_property) ||
+ !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, "s", &sub3) ||
+ !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &description) ||
+ !dbus_message_iter_close_container(&sub2, &sub3) ||
+ !dbus_message_iter_close_container(&sub, &sub2))
+ return log_oom();
+ }
+
+ /* 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. */
+
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &timeout_stop_property) ||
+ !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, "t", &sub3) ||
+ !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_UINT64, &timeout) ||
+ !dbus_message_iter_close_container(&sub2, &sub3) ||
+ !dbus_message_iter_close_container(&sub, &sub2))
+ return log_oom();
+
+ u = pid;
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &pids_property) ||
+ !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, "au", &sub3) ||
+ !dbus_message_iter_open_container(&sub3, DBUS_TYPE_ARRAY, "u", &sub4) ||
+ !dbus_message_iter_append_basic(&sub4, DBUS_TYPE_UINT32, &u) ||
+ !dbus_message_iter_close_container(&sub3, &sub4) ||
+ !dbus_message_iter_close_container(&sub2, &sub3) ||
+ !dbus_message_iter_close_container(&sub, &sub2))
+ return log_oom();
+
+ if (more_properties) {
+ r = copy_many_fields(&sub, more_properties);
+ if (r < 0)
+ return r;
+ }
+
+ if (!dbus_message_iter_close_container(&iter, &sub))
+ return log_oom();
+
+ reply = dbus_connection_send_with_reply_and_block(manager->bus, m, -1, error);
+ if (!reply)
+ return -EIO;
+
+ if (job) {
+ const char *j;
+ char *copy;
+
+ if (!dbus_message_get_args(reply, error, DBUS_TYPE_OBJECT_PATH, &j, DBUS_TYPE_INVALID))
+ return -EIO;
+
+ copy = strdup(j);
+ if (!copy)
+ return -ENOMEM;
+
+ *job = copy;
+ }
+
+ return 0;
+}
+
+int manager_stop_unit(Manager *manager, const char *unit, DBusError *error, char **job) {
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ const char *fail = "fail";
+ int r;
+
+ assert(manager);
+ assert(unit);
+
+ r = bus_method_call_with_reply(
+ manager->bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "StopUnit",
+ &reply,
+ error,
+ DBUS_TYPE_STRING, &unit,
+ DBUS_TYPE_STRING, &fail,
+ DBUS_TYPE_INVALID);
+ if (r < 0) {
+ if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
+ dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
+
+ if (job)
+ *job = NULL;
+
+ dbus_error_free(error);
+ return 0;
+ }
+
+ log_error("Failed to stop unit %s: %s", unit, bus_error(error, r));
+ return r;
+ }
+
+ if (job) {
+ const char *j;
+ char *copy;
+
+ if (!dbus_message_get_args(reply, error,
+ DBUS_TYPE_OBJECT_PATH, &j,
+ DBUS_TYPE_INVALID)) {
+ log_error("Failed to parse reply.");
+ return -EIO;
+ }
+
+ copy = strdup(j);
+ if (!copy)
+ return -ENOMEM;
+
+ *job = copy;
+ }
+
+ return 1;
+}
+
+int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, DBusError *error) {
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ const char *w;
+ int r;
+
+ assert(manager);
+ assert(unit);
+
+ w = who == KILL_LEADER ? "process" : "cgroup";
+ assert_cc(sizeof(signo) == sizeof(int32_t));
+
+ r = bus_method_call_with_reply(
+ manager->bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "KillUnit",
+ &reply,
+ error,
+ DBUS_TYPE_STRING, &unit,
+ DBUS_TYPE_STRING, &w,
+ DBUS_TYPE_INT32, &signo,
+ DBUS_TYPE_INVALID);
+ if (r < 0) {
+ log_error("Failed to stop unit %s: %s", unit, bus_error(error, r));
+ return r;
+ }
+
+ return 0;
+}
+
+int manager_unit_is_active(Manager *manager, const char *unit) {
+
+ const char *interface = "org.freedesktop.systemd1.Unit";
+ const char *property = "ActiveState";
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ _cleanup_free_ char *path = NULL;
+ DBusMessageIter iter, sub;
+ const char *state;
+ DBusError error;
+ int r;
+
+ assert(manager);
+ assert(unit);
+
+ dbus_error_init(&error);
+
+ path = unit_dbus_path_from_name(unit);
+ if (!path)
+ return -ENOMEM;
+
+ r = bus_method_call_with_reply(
+ manager->bus,
+ "org.freedesktop.systemd1",
+ path,
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ &reply,
+ &error,
+ DBUS_TYPE_STRING, &interface,
+ DBUS_TYPE_STRING, &property,
+ DBUS_TYPE_INVALID);
+ if (r < 0) {
+ if (dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY) ||
+ dbus_error_has_name(&error, DBUS_ERROR_DISCONNECTED)) {
+ dbus_error_free(&error);
+ return true;
+ }
+
+ if (dbus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
+ dbus_error_has_name(&error, BUS_ERROR_LOAD_FAILED)) {
+ dbus_error_free(&error);
+ return false;
+ }
+
+ log_error("Failed to query ActiveState: %s", bus_error(&error, r));
+ dbus_error_free(&error);
+ return r;
+ }
+
+ if (!dbus_message_iter_init(reply, &iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
+ log_error("Failed to parse reply.");
+ return -EINVAL;
+ }
+
+ dbus_message_iter_recurse(&iter, &sub);
+ if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
+ log_error("Failed to parse reply.");
+ return -EINVAL;
+ }
+
+ dbus_message_iter_get_basic(&sub, &state);
+
+ return !streq(state, "inactive") && !streq(state, "failed");
+}
+
+int manager_add_machine(Manager *m, const char *name, Machine **_machine) {
+ Machine *machine;
+
+ assert(m);
+ assert(name);
+
+ machine = hashmap_get(m->machines, name);
+ if (machine) {
+ if (_machine)
+ *_machine = machine;
+
+ return 0;
+ }
+
+ machine = machine_new(m, name);
+ if (!machine)
+ return -ENOMEM;
+
+ if (_machine)
+ *_machine = machine;
+
+ return 0;
+}
+
+int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
+ _cleanup_free_ char *unit = NULL;
+ Machine *mm;
+ int r;
+
+ assert(m);
+ assert(pid >= 1);
+ assert(machine);
+
+ r = cg_pid_get_unit(pid, &unit);
+ if (r < 0)
+ return r;
+
+ mm = hashmap_get(m->machine_units, unit);
+ if (!mm)
+ return 0;
+
+ *machine = mm;
+ return 1;
+}
diff --git a/src/machine/machined.c b/src/machine/machined.c
new file mode 100644
index 0000000000..ad804a1e14
--- /dev/null
+++ b/src/machine/machined.c
@@ -0,0 +1,386 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ 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>
+#include <pwd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/epoll.h>
+
+#include <systemd/sd-daemon.h>
+
+#include "machined.h"
+#include "dbus-common.h"
+#include "dbus-loop.h"
+#include "strv.h"
+#include "conf-parser.h"
+#include "mkdir.h"
+
+Manager *manager_new(void) {
+ Manager *m;
+
+ m = new0(Manager, 1);
+ if (!m)
+ return NULL;
+
+ m->bus_fd = -1;
+ m->epoll_fd = -1;
+
+ m->machines = hashmap_new(string_hash_func, string_compare_func);
+ m->machine_units = hashmap_new(string_hash_func, string_compare_func);
+
+ if (!m->machines || !m->machine_units) {
+ manager_free(m);
+ return NULL;
+ }
+
+ return m;
+}
+
+void manager_free(Manager *m) {
+ Machine *machine;
+
+ assert(m);
+
+ while ((machine = hashmap_first(m->machines)))
+ machine_free(machine);
+
+ hashmap_free(m->machines);
+ hashmap_free(m->machine_units);
+
+ if (m->bus) {
+ dbus_connection_flush(m->bus);
+ dbus_connection_close(m->bus);
+ dbus_connection_unref(m->bus);
+ }
+
+ if (m->bus_fd >= 0)
+ close_nointr_nofail(m->bus_fd);
+
+ if (m->epoll_fd >= 0)
+ close_nointr_nofail(m->epoll_fd);
+
+ free(m);
+}
+
+int manager_enumerate_machines(Manager *m) {
+ _cleanup_closedir_ DIR *d = NULL;
+ struct dirent *de;
+ int r = 0;
+
+ assert(m);
+
+ /* Read in machine data stored on disk */
+ d = opendir("/run/systemd/machines");
+ if (!d) {
+ if (errno == ENOENT)
+ return 0;
+
+ log_error("Failed to open /run/systemd/machines: %m");
+ return -errno;
+ }
+
+ FOREACH_DIRENT(de, d, return -errno) {
+ struct Machine *machine;
+ int k;
+
+ if (!dirent_is_file(de))
+ continue;
+
+ k = manager_add_machine(m, de->d_name, &machine);
+ if (k < 0) {
+ log_error("Failed to add machine by file name %s: %s", de->d_name, strerror(-k));
+
+ r = k;
+ continue;
+ }
+
+ machine_add_to_gc_queue(machine);
+
+ k = machine_load(machine);
+ if (k < 0)
+ r = k;
+ }
+
+ return r;
+}
+
+static int manager_connect_bus(Manager *m) {
+ DBusError error;
+ int r;
+ struct epoll_event ev = {
+ .events = EPOLLIN,
+ .data.u32 = FD_BUS,
+ };
+
+ assert(m);
+ assert(!m->bus);
+ assert(m->bus_fd < 0);
+
+ dbus_error_init(&error);
+
+ m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
+ if (!m->bus) {
+ log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
+ r = -ECONNREFUSED;
+ goto fail;
+ }
+
+ if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/machine1", &bus_manager_vtable, m) ||
+ !dbus_connection_register_fallback(m->bus, "/org/freedesktop/machine1/machine", &bus_machine_vtable, m) ||
+ !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
+ r = log_oom();
+ goto fail;
+ }
+
+ dbus_bus_add_match(m->bus,
+ "type='signal',"
+ "sender='org.freedesktop.systemd1',"
+ "interface='org.freedesktop.systemd1.Manager',"
+ "member='JobRemoved',"
+ "path='/org/freedesktop/systemd1'",
+ &error);
+ if (dbus_error_is_set(&error)) {
+ log_error("Failed to add match for JobRemoved: %s", bus_error_message(&error));
+ dbus_error_free(&error);
+ }
+
+ dbus_bus_add_match(m->bus,
+ "type='signal',"
+ "sender='org.freedesktop.systemd1',"
+ "interface='org.freedesktop.systemd1.Manager',"
+ "member='UnitRemoved',"
+ "path='/org/freedesktop/systemd1'",
+ &error);
+ if (dbus_error_is_set(&error)) {
+ log_error("Failed to add match for UnitRemoved: %s", bus_error_message(&error));
+ dbus_error_free(&error);
+ }
+
+ dbus_bus_add_match(m->bus,
+ "type='signal',"
+ "sender='org.freedesktop.systemd1',"
+ "interface='org.freedesktop.DBus.Properties',"
+ "member='PropertiesChanged'",
+ &error);
+ if (dbus_error_is_set(&error)) {
+ log_error("Failed to add match for PropertiesChanged: %s", bus_error_message(&error));
+ dbus_error_free(&error);
+ }
+
+ dbus_bus_add_match(m->bus,
+ "type='signal',"
+ "sender='org.freedesktop.systemd1',"
+ "interface='org.freedesktop.systemd1.Manager',"
+ "member='Reloading',"
+ "path='/org/freedesktop/systemd1'",
+ &error);
+ if (dbus_error_is_set(&error)) {
+ log_error("Failed to add match for Reloading: %s", bus_error_message(&error));
+ dbus_error_free(&error);
+ }
+
+ r = bus_method_call_with_reply(
+ m->bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "Subscribe",
+ NULL,
+ &error,
+ DBUS_TYPE_INVALID);
+ if (r < 0) {
+ log_error("Failed to enable subscription: %s", bus_error(&error, r));
+ dbus_error_free(&error);
+ }
+
+ r = dbus_bus_request_name(m->bus, "org.freedesktop.machine1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
+ if (dbus_error_is_set(&error)) {
+ log_error("Failed to register name on bus: %s", bus_error_message(&error));
+ r = -EIO;
+ goto fail;
+ }
+
+ if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+ log_error("Failed to acquire name.");
+ r = -EEXIST;
+ goto fail;
+ }
+
+ m->bus_fd = bus_loop_open(m->bus);
+ if (m->bus_fd < 0) {
+ r = m->bus_fd;
+ goto fail;
+ }
+
+ if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
+ goto fail;
+
+ return 0;
+
+fail:
+ dbus_error_free(&error);
+
+ return r;
+}
+
+void manager_gc(Manager *m, bool drop_not_started) {
+ Machine *machine;
+
+ assert(m);
+
+ while ((machine = m->machine_gc_queue)) {
+ LIST_REMOVE(Machine, gc_queue, m->machine_gc_queue, machine);
+ machine->in_gc_queue = false;
+
+ if (machine_check_gc(machine, drop_not_started) == 0) {
+ machine_stop(machine);
+ machine_free(machine);
+ }
+ }
+}
+
+int manager_startup(Manager *m) {
+ int r;
+ Machine *machine;
+ Iterator i;
+
+ assert(m);
+ assert(m->epoll_fd <= 0);
+
+ m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
+ if (m->epoll_fd < 0)
+ return -errno;
+
+ /* Connect to the bus */
+ r = manager_connect_bus(m);
+ if (r < 0)
+ return r;
+
+ /* Deserialize state */
+ manager_enumerate_machines(m);
+
+ /* Remove stale objects before we start them */
+ manager_gc(m, false);
+
+ /* And start everything */
+ HASHMAP_FOREACH(machine, m->machines, i)
+ machine_start(machine, NULL);
+
+ return 0;
+}
+
+int manager_run(Manager *m) {
+ assert(m);
+
+ for (;;) {
+ struct epoll_event event;
+ int n;
+
+ manager_gc(m, true);
+
+ if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
+ continue;
+
+ manager_gc(m, true);
+
+ n = epoll_wait(m->epoll_fd, &event, 1, -1);
+ if (n < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+
+ log_error("epoll() failed: %m");
+ return -errno;
+ }
+
+ if (n == 0)
+ continue;
+
+ switch (event.data.u32) {
+
+ case FD_BUS:
+ bus_loop_dispatch(m->bus_fd);
+ break;
+
+ default:
+ assert_not_reached("Unknown fd");
+ }
+ }
+
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ Manager *m = NULL;
+ int r;
+
+ log_set_target(LOG_TARGET_AUTO);
+ log_set_facility(LOG_AUTH);
+ log_parse_environment();
+ log_open();
+
+ umask(0022);
+
+ if (argc != 1) {
+ log_error("This program takes no arguments.");
+ r = -EINVAL;
+ goto finish;
+ }
+
+ /* 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
+ * machined is available, so please always make sure this check
+ * stays in. */
+ mkdir_label("/run/systemd/machines", 0755);
+
+ m = manager_new();
+ if (!m) {
+ r = log_oom();
+ goto finish;
+ }
+
+ r = manager_startup(m);
+ if (r < 0) {
+ log_error("Failed to fully start up daemon: %s", strerror(-r));
+ goto finish;
+ }
+
+ log_debug("systemd-machined running as pid %lu", (unsigned long) getpid());
+
+ sd_notify(false,
+ "READY=1\n"
+ "STATUS=Processing requests...");
+
+ r = manager_run(m);
+
+ log_debug("systemd-machined stopped as pid %lu", (unsigned long) getpid());
+
+finish:
+ sd_notify(false,
+ "STATUS=Shutting down...");
+
+ if (m)
+ manager_free(m);
+
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/src/machine/machined.h b/src/machine/machined.h
new file mode 100644
index 0000000000..780f51678c
--- /dev/null
+++ b/src/machine/machined.h
@@ -0,0 +1,73 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#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 <inttypes.h>
+#include <dbus/dbus.h>
+
+#include "util.h"
+#include "list.h"
+#include "hashmap.h"
+
+typedef struct Manager Manager;
+
+#include "machine.h"
+
+struct Manager {
+ DBusConnection *bus;
+
+ int bus_fd;
+ int epoll_fd;
+
+ Hashmap *machines;
+ Hashmap *machine_units;
+
+ LIST_HEAD(Machine, machine_gc_queue);
+};
+
+enum {
+ FD_BUS
+};
+
+Manager *manager_new(void);
+void manager_free(Manager *m);
+
+int manager_add_machine(Manager *m, const char *name, Machine **_machine);
+
+int manager_enumerate_machines(Manager *m);
+
+int manager_startup(Manager *m);
+int manager_run(Manager *m);
+
+void manager_gc(Manager *m, bool drop_not_started);
+
+int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine);
+
+extern const DBusObjectPathVTable bus_manager_vtable;
+
+DBusHandlerResult bus_message_filter(DBusConnection *c, DBusMessage *message, void *userdata);
+
+int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, DBusMessageIter *more_properties, DBusError *error, char **job);
+int manager_stop_unit(Manager *manager, const char *unit, DBusError *error, char **job);
+int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, DBusError *error);
+int manager_unit_is_active(Manager *manager, const char *unit);
diff --git a/src/machine/org.freedesktop.machine1.conf b/src/machine/org.freedesktop.machine1.conf
new file mode 100644
index 0000000000..b2d6df3121
--- /dev/null
+++ b/src/machine/org.freedesktop.machine1.conf
@@ -0,0 +1,50 @@
+<?xml version="1.0"?> <!--*-nxml-*-->
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+
+<!--
+ This file is part of systemd.
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+-->
+
+<busconfig>
+
+ <policy user="root">
+ <allow own="org.freedesktop.machine1"/>
+ <allow send_destination="org.freedesktop.machine1"/>
+ <allow receive_sender="org.freedesktop.machine1"/>
+ </policy>
+
+ <policy context="default">
+ <deny send_destination="org.freedesktop.machine1"/>
+
+ <allow send_destination="org.freedesktop.machine1"
+ send_interface="org.freedesktop.DBus.Introspectable"/>
+
+ <allow send_destination="org.freedesktop.machine1"
+ send_interface="org.freedesktop.DBus.Peer"/>
+
+ <allow send_destination="org.freedesktop.machine1"
+ send_interface="org.freedesktop.DBus.Properties"
+ send_member="Get"/>
+
+ <allow send_destination="org.freedesktop.machine1"
+ send_interface="org.freedesktop.DBus.Properties"
+ send_member="GetAll"/>
+
+ <allow send_destination="org.freedesktop.machine1"
+ send_interface="org.freedesktop.machine1.Manager"
+ send_member="ListMachines"/>
+
+ <allow send_destination="org.freedesktop.machine1"
+ send_interface="org.freedesktop.machine1.Manager"
+ send_member="GetMachine"/>
+
+ <allow receive_sender="org.freedesktop.machine1"/>
+ </policy>
+
+</busconfig>
diff --git a/src/machine/org.freedesktop.machine1.service b/src/machine/org.freedesktop.machine1.service
new file mode 100644
index 0000000000..d3dc99852b
--- /dev/null
+++ b/src/machine/org.freedesktop.machine1.service
@@ -0,0 +1,12 @@
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[D-BUS Service]
+Name=org.freedesktop.machine1
+Exec=/bin/false
+User=root
+SystemdService=dbus-org.freedesktop.machine1.service
diff --git a/src/machine/test-machine-tables.c b/src/machine/test-machine-tables.c
new file mode 100644
index 0000000000..4aae426050
--- /dev/null
+++ b/src/machine/test-machine-tables.c
@@ -0,0 +1,30 @@
+/***
+ 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 "machine.h"
+
+#include "test-tables.h"
+
+int main(int argc, char **argv) {
+ test_table(machine_class, MACHINE_CLASS);
+ test_table(machine_state, MACHINE_STATE);
+ test_table(kill_who, KILL_WHO);
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/notify/notify.c b/src/notify/notify.c
index 1e9766f862..a688a9f879 100644
--- a/src/notify/notify.c
+++ b/src/notify/notify.c
@@ -157,7 +157,8 @@ int main(int argc, char* argv[]) {
log_parse_environment();
log_open();
- if ((r = parse_argv(argc, argv)) <= 0) {
+ r = parse_argv(argc, argv);
+ if (r <= 0) {
retval = r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
goto finish;
}
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 09153c87ce..eb9605c356 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -41,12 +41,10 @@
#include <linux/fs.h>
#include <sys/un.h>
#include <sys/socket.h>
-
-#ifdef HAVE_XATTR
-#include <attr/xattr.h>
-#endif
+#include <linux/netlink.h>
#include <systemd/sd-daemon.h>
+#include <systemd/sd-bus.h>
#include "log.h"
#include "util.h"
@@ -63,6 +61,8 @@
#include "fdset.h"
#include "build.h"
#include "fileio.h"
+#include "bus-internal.h"
+#include "bus-message.h"
#ifndef TTY_GID
#define TTY_GID 5
@@ -77,9 +77,9 @@ typedef enum LinkJournal {
static char *arg_directory = NULL;
static char *arg_user = NULL;
-static char **arg_controllers = NULL;
-static char *arg_uuid = NULL;
+static sd_id128_t arg_uuid = {};
static char *arg_machine = NULL;
+static const char *arg_slice = NULL;
static bool arg_private_network = false;
static bool arg_read_only = false;
static bool arg_boot = false;
@@ -122,10 +122,9 @@ static int help(void) {
" -D --directory=NAME Root directory for the container\n"
" -b --boot Boot up full system (i.e. invoke init)\n"
" -u --user=USER Run the command under specified user or uid\n"
- " -C --controllers=LIST Put the container in specified comma-separated\n"
- " cgroup hierarchies\n"
" --uuid=UUID Set a specific machine UUID for the container\n"
" -M --machine=NAME Set the machine name for the container\n"
+ " -S --slice=SLICE Place the container in the specified slice\n"
" --private-network Disable network in container\n"
" --read-only Mount the root directory read-only\n"
" --capability=CAP In addition to the default, retain specified\n"
@@ -158,7 +157,6 @@ static int parse_argv(int argc, char *argv[]) {
{ "version", no_argument, NULL, ARG_VERSION },
{ "directory", required_argument, NULL, 'D' },
{ "user", required_argument, NULL, 'u' },
- { "controllers", required_argument, NULL, 'C' },
{ "private-network", no_argument, NULL, ARG_PRIVATE_NETWORK },
{ "boot", no_argument, NULL, 'b' },
{ "uuid", required_argument, NULL, ARG_UUID },
@@ -168,15 +166,16 @@ static int parse_argv(int argc, char *argv[]) {
{ "bind", required_argument, NULL, ARG_BIND },
{ "bind-ro", required_argument, NULL, ARG_BIND_RO },
{ "machine", required_argument, NULL, 'M' },
+ { "slice", required_argument, NULL, 'S' },
{ NULL, 0, NULL, 0 }
};
- int c;
+ int c, r;
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "+hD:u:C:bM:j", options, NULL)) >= 0) {
+ while ((c = getopt_long(argc, argv, "+hD:u:bM:jS:", options, NULL)) >= 0) {
switch (c) {
@@ -207,15 +206,6 @@ static int parse_argv(int argc, char *argv[]) {
break;
- case 'C':
- strv_free(arg_controllers);
- arg_controllers = strv_split(optarg, ",");
- if (!arg_controllers)
- return log_oom();
-
- cg_shorten_controllers(arg_controllers);
- break;
-
case ARG_PRIVATE_NETWORK:
arg_private_network = true;
break;
@@ -225,12 +215,15 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_UUID:
- if (!id128_is_valid(optarg)) {
+ r = sd_id128_from_string(optarg, &arg_uuid);
+ if (r < 0) {
log_error("Invalid UUID: %s", optarg);
- return -EINVAL;
+ return r;
}
+ break;
- arg_uuid = optarg;
+ case 'S':
+ arg_slice = strdup(optarg);
break;
case 'M':
@@ -300,7 +293,6 @@ static int parse_argv(int argc, char *argv[]) {
_cleanup_free_ char *a = NULL, *b = NULL;
char *e;
char ***x;
- int r;
x = c == ARG_BIND ? &arg_bind : &arg_bind_ro;
@@ -419,12 +411,39 @@ static int mount_binds(const char *dest, char **l, unsigned long flags) {
STRV_FOREACH_PAIR(x, y, l) {
_cleanup_free_ char *where = NULL;
+ struct stat source_st, dest_st;
+
+ if (stat(*x, &source_st) < 0) {
+ log_error("failed to stat %s: %m", *x);
+ return -errno;
+ }
where = strjoin(dest, "/", *y, NULL);
if (!where)
return log_oom();
- mkdir_p_label(where, 0755);
+ if (stat(where, &dest_st) == 0) {
+ if ((source_st.st_mode & S_IFMT) != (dest_st.st_mode & S_IFMT)) {
+ log_error("The file types of %s and %s do not match. Refusing bind mount",
+ *x, where);
+ return -EINVAL;
+ }
+ } else {
+ /* Create the mount point, but be conservative -- refuse to create block
+ * and char devices. */
+ if (S_ISDIR(source_st.st_mode))
+ mkdir_p_label(where, 0755);
+ else if (S_ISFIFO(source_st.st_mode))
+ mkfifo(where, 0644);
+ else if (S_ISSOCK(source_st.st_mode))
+ mknod(where, 0644 | S_IFSOCK, 0);
+ else if (S_ISREG(source_st.st_mode))
+ touch(where);
+ else {
+ log_error("Refusing to create mountpoint for file: %s", *x);
+ return -ENOTSUP;
+ }
+ }
if (mount(*x, where, "bind", MS_BIND, NULL) < 0) {
log_error("mount(%s) failed: %m", where);
@@ -911,68 +930,6 @@ static int setup_journal(const char *directory) {
return 0;
}
-static int setup_cgroup(const char *path) {
- char **c;
- int r;
-
- r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, path, 1);
- if (r < 0) {
- log_error("Failed to create cgroup: %s", strerror(-r));
- return r;
- }
-
- STRV_FOREACH(c, arg_controllers) {
- r = cg_create_and_attach(*c, path, 1);
- if (r < 0)
- log_warning("Failed to create cgroup in controller %s: %s", *c, strerror(-r));
- }
-
- return 0;
-}
-
-static int save_attributes(const char *cgroup, pid_t pid, const char *uuid, const char *directory) {
-#ifdef HAVE_XATTR
- _cleanup_free_ char *path = NULL;
- char buf[DECIMAL_STR_MAX(pid_t)];
- int r = 0, k;
-
- assert(cgroup);
- assert(pid >= 0);
- assert(arg_directory);
-
- assert_se(snprintf(buf, sizeof(buf), "%lu", (unsigned long) pid) < (int) sizeof(buf));
-
- r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, cgroup, NULL, &path);
- if (r < 0) {
- log_error("Failed to get path: %s", strerror(-r));
- return r;
- }
-
- r = setxattr(path, "trusted.init_pid", buf, strlen(buf), XATTR_CREATE);
- if (r < 0)
- log_warning("Failed to set %s attribute on %s: %m", "trusted.init_pid", path);
-
- if (uuid) {
- k = setxattr(path, "trusted.machine_id", uuid, strlen(uuid), XATTR_CREATE);
- if (k < 0) {
- log_warning("Failed to set %s attribute on %s: %m", "trusted.machine_id", path);
- if (r == 0)
- r = k;
- }
- }
-
- k = setxattr(path, "trusted.root_directory", directory, strlen(directory), XATTR_CREATE);
- if (k < 0) {
- log_warning("Failed to set %s attribute on %s: %m", "trusted.root_directory", path);
- if (r == 0)
- r = k;
- }
- return r;
-#else
- return 0;
-#endif
-}
-
static int drop_capabilities(void) {
return capability_bounding_set_drop(~arg_retain, false);
}
@@ -1219,10 +1176,55 @@ finish:
return r;
}
+static int register_machine(void) {
+ _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_bus_unref_ sd_bus *bus = NULL;
+ int r;
+
+ r = sd_bus_open_system(&bus);
+ if (r < 0) {
+ log_error("Failed to open system bus: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.machine1",
+ "/org/freedesktop/machine1",
+ "org.freedesktop.machine1.Manager",
+ "CreateMachine",
+ &error,
+ NULL,
+ "sayssusa(sv)",
+ arg_machine,
+ SD_BUS_APPEND_ID128(arg_uuid),
+ "nspawn",
+ "container",
+ (uint32_t) 0,
+ strempty(arg_directory),
+ 1, "Slice", "s", strempty(arg_slice));
+ if (r < 0) {
+ log_error("Failed to register machine: %s", error.message ? error.message : strerror(-r));
+ return r;
+ }
+
+ return 0;
+}
+
+static bool audit_enabled(void) {
+ int fd;
+
+ fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_AUDIT);
+ if (fd >= 0) {
+ close_nointr_nofail(fd);
+ return true;
+ }
+ return false;
+}
+
int main(int argc, char *argv[]) {
pid_t pid = 0;
int r = EXIT_FAILURE, k;
- _cleanup_free_ char *newcg = NULL;
_cleanup_close_ int master = -1;
int n_fd_passed;
const char *console = NULL;
@@ -1284,6 +1286,13 @@ int main(int argc, char *argv[]) {
goto finish;
}
+ if (arg_boot && audit_enabled()) {
+ log_warning("The kernel auditing subsystem is known to be incompatible with containers.\n"
+ "Please make sure to turn off auditing with 'audit=0' on the kernel command\n"
+ "line before using systemd-nspawn. Sleeping for 5s...\n");
+ sleep(5);
+ }
+
if (path_equal(arg_directory, "/")) {
log_error("Spawning container on root directory not supported.");
goto finish;
@@ -1306,22 +1315,6 @@ int main(int argc, char *argv[]) {
fdset_close_others(fds);
log_open();
- k = cg_get_machine_path(arg_machine, &newcg);
- if (k < 0) {
- log_error("Failed to determine machine cgroup path: %s", strerror(-k));
- goto finish;
- }
-
- k = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, newcg, true);
- if (k <= 0 && k != -ENOENT) {
- log_error("Container already running.");
-
- free(newcg);
- newcg = NULL;
-
- goto finish;
- }
-
master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY);
if (master < 0) {
log_error("Failed to acquire pseudo tty: %m");
@@ -1465,11 +1458,12 @@ int main(int argc, char *argv[]) {
goto child_fail;
}
- if (setup_cgroup(newcg) < 0)
- goto child_fail;
-
close_pipe(pipefd2);
+ r = register_machine();
+ if (r < 0)
+ goto finish;
+
/* Mark everything as slave, so that we still
* receive mounts from the real root, but don't
* propagate mounts to the real root. */
@@ -1620,8 +1614,8 @@ int main(int argc, char *argv[]) {
goto child_fail;
}
- if (arg_uuid) {
- if (asprintf((char**)(envp + n_env++), "container_uuid=%s", arg_uuid) < 0) {
+ if (!sd_id128_equal(arg_uuid, SD_ID128_NULL)) {
+ if (asprintf((char**)(envp + n_env++), "container_uuid=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(arg_uuid)) < 0) {
log_oom();
goto child_fail;
}
@@ -1635,7 +1629,7 @@ int main(int argc, char *argv[]) {
}
if ((asprintf((char **)(envp + n_env++), "LISTEN_FDS=%u", n_fd_passed) < 0) ||
- (asprintf((char **)(envp + n_env++), "LISTEN_PID=%lu", (unsigned long) 1) < 0)) {
+ (asprintf((char **)(envp + n_env++), "LISTEN_PID=1") < 0)) {
log_oom();
goto child_fail;
}
@@ -1683,8 +1677,6 @@ int main(int argc, char *argv[]) {
fd_wait_for_event(pipefd2[0], POLLHUP, -1);
close_nointr_nofail(pipefd2[0]);
- save_attributes(newcg, pid, arg_uuid, arg_directory);
-
fdset_free(fds);
fds = NULL;
@@ -1737,12 +1729,11 @@ finish:
close_pipe(kmsg_socket_pair);
- if (newcg)
- cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, newcg, true);
+ if (pid > 0)
+ kill(pid, SIGKILL);
free(arg_directory);
free(arg_machine);
- strv_free(arg_controllers);
fdset_free(fds);
diff --git a/src/python-systemd/_daemon.c b/src/python-systemd/_daemon.c
index d3b4807368..6b84fb81c7 100644
--- a/src/python-systemd/_daemon.c
+++ b/src/python-systemd/_daemon.c
@@ -40,43 +40,6 @@ PyDoc_STRVAR(module__doc__,
"running under systemd."
);
-static PyObject* set_error(int r, const char* invalid_message) {
- assert (r < 0);
-
- if (r == -EINVAL && invalid_message)
- PyErr_SetString(PyExc_ValueError, invalid_message);
- else if (r == -ENOMEM)
- PyErr_SetString(PyExc_MemoryError, "Not enough memory");
- else {
- errno = -r;
- PyErr_SetFromErrno(PyExc_OSError);
- }
-
- return NULL;
-}
-
-
-#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
-static int Unicode_FSConverter(PyObject* obj, void *_result) {
- PyObject **result = _result;
-
- assert(result);
-
- if (!obj)
- /* cleanup: we don't return Py_CLEANUP_SUPPORTED, so
- * we can assume that it was PyUnicode_FSConverter. */
- return PyUnicode_FSConverter(obj, result);
-
- if (obj == Py_None) {
- *result = NULL;
- return 1;
- }
-
- return PyUnicode_FSConverter(obj, result);
-}
-#endif
-
-
PyDoc_STRVAR(booted__doc__,
"booted() -> bool\n\n"
"Return True iff this system is running under systemd.\n"
@@ -88,8 +51,45 @@ static PyObject* booted(PyObject *self, PyObject *args) {
assert(args == NULL);
r = sd_booted();
- if (r < 0)
- return set_error(r, NULL);
+ if (set_error(r, NULL, NULL))
+ return NULL;
+
+ return PyBool_FromLong(r);
+}
+
+PyDoc_STRVAR(notify__doc__,
+ "notify(status, unset_environment=False) -> bool\n\n"
+ "Send a message to the init system about a status change.\n"
+ "Wraps sd_notify(3).");
+
+static PyObject* notify(PyObject *self, PyObject *args, PyObject *keywds) {
+ int r;
+ const char* msg;
+ int unset = false;
+
+ static const char* const kwlist[] = {
+ "status",
+ "unset_environment",
+ NULL,
+ };
+#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 3
+ if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|p:notify",
+ (char**) kwlist, &msg, &unset))
+ return NULL;
+#else
+ PyObject *obj = NULL;
+ if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|O:notify",
+ (char**) kwlist, &msg, &obj))
+ return NULL;
+ if (obj != NULL)
+ unset = PyObject_IsTrue(obj);
+ if (unset < 0)
+ return NULL;
+#endif
+
+ r = sd_notify(unset, msg);
+ if (set_error(r, NULL, NULL))
+ return NULL;
return PyBool_FromLong(r);
}
@@ -102,16 +102,19 @@ PyDoc_STRVAR(listen_fds__doc__,
"Wraps sd_listen_fds(3)."
);
-static PyObject* listen_fds(PyObject *self, PyObject *args) {
+static PyObject* listen_fds(PyObject *self, PyObject *args, PyObject *keywds) {
int r;
int unset = true;
+ static const char* const kwlist[] = {"unset_environment", NULL};
#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 3
- if (!PyArg_ParseTuple(args, "|p:_listen_fds", &unset))
+ if (!PyArg_ParseTupleAndKeywords(args, keywds, "|p:_listen_fds",
+ (char**) kwlist, &unset))
return NULL;
#else
PyObject *obj = NULL;
- if (!PyArg_ParseTuple(args, "|O:_listen_fds", &obj))
+ if (!PyArg_ParseTupleAndKeywords(args, keywds, "|O:_listen_fds",
+ (char**) kwlist, &unset, &obj))
return NULL;
if (obj != NULL)
unset = PyObject_IsTrue(obj);
@@ -120,8 +123,8 @@ static PyObject* listen_fds(PyObject *self, PyObject *args) {
#endif
r = sd_listen_fds(unset);
- if (r < 0)
- return set_error(r, NULL);
+ if (set_error(r, NULL, NULL))
+ return NULL;
return long_FromLong(r);
}
@@ -148,8 +151,8 @@ static PyObject* is_fifo(PyObject *self, PyObject *args) {
#endif
r = sd_is_fifo(fd, path);
- if (r < 0)
- return set_error(r, NULL);
+ if (set_error(r, path, NULL))
+ return NULL;
return PyBool_FromLong(r);
}
@@ -176,8 +179,8 @@ static PyObject* is_mq(PyObject *self, PyObject *args) {
#endif
r = sd_is_mq(fd, path);
- if (r < 0)
- return set_error(r, NULL);
+ if (set_error(r, path, NULL))
+ return NULL;
return PyBool_FromLong(r);
}
@@ -200,8 +203,8 @@ static PyObject* is_socket(PyObject *self, PyObject *args) {
return NULL;
r = sd_is_socket(fd, family, type, listening);
- if (r < 0)
- return set_error(r, NULL);
+ if (set_error(r, NULL, NULL))
+ return NULL;
return PyBool_FromLong(r);
}
@@ -221,12 +224,14 @@ static PyObject* is_socket_inet(PyObject *self, PyObject *args) {
&fd, &family, &type, &listening, &port))
return NULL;
- if (port < 0 || port > INT16_MAX)
- return set_error(-EINVAL, "port must fit into uint16_t");
+ if (port < 0 || port > INT16_MAX) {
+ set_error(-EINVAL, NULL, "port must fit into uint16_t");
+ return NULL;
+ }
r = sd_is_socket_inet(fd, family, type, listening, (uint16_t) port);
- if (r < 0)
- return set_error(r, NULL);
+ if (set_error(r, NULL, NULL))
+ return NULL;
return PyBool_FromLong(r);
}
@@ -260,8 +265,8 @@ static PyObject* is_socket_unix(PyObject *self, PyObject *args) {
#endif
r = sd_is_socket_unix(fd, type, listening, path, length);
- if (r < 0)
- return set_error(r, NULL);
+ if (set_error(r, path, NULL))
+ return NULL;
return PyBool_FromLong(r);
}
@@ -269,7 +274,8 @@ static PyObject* is_socket_unix(PyObject *self, PyObject *args) {
static PyMethodDef methods[] = {
{ "booted", booted, METH_NOARGS, booted__doc__},
- { "_listen_fds", listen_fds, METH_VARARGS, listen_fds__doc__},
+ { "notify", (PyCFunction) notify, METH_VARARGS | METH_KEYWORDS, notify__doc__},
+ { "_listen_fds", (PyCFunction) listen_fds, METH_VARARGS | METH_KEYWORDS, listen_fds__doc__},
{ "_is_fifo", is_fifo, METH_VARARGS, is_fifo__doc__},
{ "_is_mq", is_mq, METH_VARARGS, is_mq__doc__},
{ "_is_socket", is_socket, METH_VARARGS, is_socket__doc__},
diff --git a/src/python-systemd/_reader.c b/src/python-systemd/_reader.c
index d20c58d2a8..bc5db19049 100644
--- a/src/python-systemd/_reader.c
+++ b/src/python-systemd/_reader.c
@@ -30,6 +30,7 @@
#include "pyutil.h"
#include "macro.h"
#include "util.h"
+#include "strv.h"
#include "build.h"
typedef struct {
@@ -38,20 +39,6 @@ typedef struct {
} Reader;
static PyTypeObject ReaderType;
-static int set_error(int r, const char* path, const char* invalid_message) {
- if (r >= 0)
- return r;
- if (r == -EINVAL && invalid_message)
- PyErr_SetString(PyExc_ValueError, invalid_message);
- else if (r == -ENOMEM)
- PyErr_SetString(PyExc_MemoryError, "Not enough memory");
- else {
- errno = -r;
- PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
- }
- return -1;
-}
-
PyDoc_STRVAR(module__doc__,
"Class to reads the systemd journal similar to journalctl.");
@@ -77,6 +64,70 @@ static PyStructSequence_Desc Monotonic_desc = {
};
#endif
+/**
+ * Convert a Python sequence object into a strv (char**), and
+ * None into a NULL pointer.
+ */
+static int strv_converter(PyObject* obj, void *_result) {
+ char ***result = _result;
+ Py_ssize_t i, len;
+
+ assert(result);
+
+ if (!obj)
+ return 0;
+
+ if (obj == Py_None) {
+ *result = NULL;
+ return 1;
+ }
+
+ if (!PySequence_Check(obj))
+ return 0;
+
+ len = PySequence_Length(obj);
+ *result = new0(char*, len + 1);
+ if (!*result) {
+ set_error(-ENOMEM, NULL, NULL);
+ return 0;
+ }
+
+ for (i = 0; i < len; i++) {
+ PyObject *item;
+#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
+ int r;
+ PyObject *bytes;
+#endif
+ char *s, *s2;
+
+ item = PySequence_ITEM(obj, i);
+#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
+ r = PyUnicode_FSConverter(item, &bytes);
+ if (r == 0)
+ goto cleanup;
+
+ s = PyBytes_AsString(bytes);
+#else
+ s = PyString_AsString(item);
+#endif
+ if (!s)
+ goto cleanup;
+
+ s2 = strdup(s);
+ if (!s2)
+ log_oom();
+
+ (*result)[i] = s2;
+ }
+
+ return 1;
+
+cleanup:
+ strv_free(*result);
+ *result = NULL;
+
+ return 0;
+}
static void Reader_dealloc(Reader* self)
{
@@ -85,40 +136,45 @@ static void Reader_dealloc(Reader* self)
}
PyDoc_STRVAR(Reader__doc__,
- "_Reader([flags | path]) -> ...\n\n"
+ "_Reader([flags | path | files]) -> ...\n\n"
"_Reader allows filtering and retrieval of Journal entries.\n"
"Note: this is a low-level interface, and probably not what you\n"
"want, use systemd.journal.Reader instead.\n\n"
"Argument `flags` sets open flags of the journal, which can be one\n"
"of, or ORed combination of constants: LOCAL_ONLY (default) opens\n"
"journal on local machine only; RUNTIME_ONLY opens only\n"
- "volatile journal files; and SYSTEM_ONLY opens only\n"
- "journal files of system services and the kernel.\n\n"
- "Argument `path` is the directory of journal files. Note that\n"
- "`flags` and `path` are exclusive.\n\n"
+ "volatile journal files; and SYSTEM opens journal files of\n"
+ "system services and the kernel, and CURRENT_USER opens files\n"
+ "of the current user.\n\n"
+ "Argument `path` is the directory of journal files.\n"
+ "Argument `files` is a list of files. Note that\n"
+ "`flags`, `path`, and `files` are exclusive.\n\n"
"_Reader implements the context manager protocol: the journal\n"
"will be closed when exiting the block.");
static int Reader_init(Reader *self, PyObject *args, PyObject *keywds)
{
int flags = 0, r;
char *path = NULL;
+ char **files = NULL;
+
+ static const char* const kwlist[] = {"flags", "path", "files", NULL};
+ if (!PyArg_ParseTupleAndKeywords(args, keywds, "|izO&:__init__", (char**) kwlist,
+ &flags, &path, strv_converter, &files))
+ return -1;
- static const char* const kwlist[] = {"flags", "path", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, keywds, "|iz", (char**) kwlist,
- &flags, &path))
+ if (!!flags + !!path + !!files > 1) {
+ PyErr_SetString(PyExc_ValueError, "cannot use more than one of flags, path, and files");
return -1;
+ }
if (!flags)
flags = SD_JOURNAL_LOCAL_ONLY;
- else
- if (path) {
- PyErr_SetString(PyExc_ValueError, "cannot use both flags and path");
- return -1;
- }
Py_BEGIN_ALLOW_THREADS
if (path)
r = sd_journal_open_directory(&self->j, path, 0);
+ else if (files)
+ r = sd_journal_open_files(&self->j, (const char**) files, 0);
else
r = sd_journal_open(&self->j, flags);
Py_END_ALLOW_THREADS
@@ -177,7 +233,7 @@ PyDoc_STRVAR(Reader_get_timeout__doc__,
"Returns a timeout value for usage in poll(), the time since the\n"
"epoch of clock_gettime(2) in microseconds, or None if no timeout\n"
"is necessary.\n\n"
- "The return value must be converted to a relative timeout in \n"
+ "The return value must be converted to a relative timeout in\n"
"milliseconds if it is to be used as an argument for poll().\n"
"See man:sd_journal_get_timeout(3) for further discussion.");
static PyObject* Reader_get_timeout(Reader *self, PyObject *args)
@@ -275,11 +331,7 @@ PyDoc_STRVAR(Reader___exit____doc__,
"Closes the journal.\n");
static PyObject* Reader___exit__(Reader *self, PyObject *args)
{
- assert(self);
-
- sd_journal_close(self->j);
- self->j = NULL;
- Py_RETURN_NONE;
+ return Reader_close(self, args);
}
@@ -869,9 +921,9 @@ static PyObject* Reader_get_catalog(Reader *self, PyObject *args)
r = sd_journal_get_data(self->j, "MESSAGE_ID", &mid, &mid_len);
if (r == 0) {
- const int l = sizeof("MESSAGE_ID");
+ const size_t l = sizeof("MESSAGE_ID");
assert(mid_len > l);
- PyErr_Format(PyExc_KeyError, "%.*s", (int) mid_len - l,
+ PyErr_Format(PyExc_KeyError, "%.*s", (int) (mid_len - l),
(const char*) mid + l);
} else if (r == -ENOENT)
PyErr_SetString(PyExc_IndexError, "no MESSAGE_ID field");
@@ -1007,48 +1059,20 @@ static PyMethodDef Reader_methods[] = {
static PyTypeObject ReaderType = {
PyVarObject_HEAD_INIT(NULL, 0)
- "_reader._Reader", /*tp_name*/
- sizeof(Reader), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)Reader_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
- Reader__doc__, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- Reader_methods, /* tp_methods */
- 0, /* tp_members */
- Reader_getsetters, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc) Reader_init, /* tp_init */
- 0, /* tp_alloc */
- PyType_GenericNew, /* tp_new */
+ .tp_name = "_reader._Reader",
+ .tp_basicsize = sizeof(Reader),
+ .tp_dealloc = (destructor) Reader_dealloc,
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ .tp_doc = Reader__doc__,
+ .tp_methods = Reader_methods,
+ .tp_getset = Reader_getsetters,
+ .tp_init = (initproc) Reader_init,
+ .tp_new = PyType_GenericNew,
};
static PyMethodDef methods[] = {
{ "_get_catalog", get_catalog, METH_VARARGS, get_catalog__doc__},
- { NULL, NULL, 0, NULL } /* Sentinel */
+ {} /* Sentinel */
};
#if PY_MAJOR_VERSION >= 3
@@ -1058,7 +1082,6 @@ static PyModuleDef module = {
module__doc__,
-1,
methods,
- NULL, NULL, NULL, NULL
};
#endif
@@ -1115,7 +1138,9 @@ init_reader(void)
PyModule_AddIntConstant(m, "INVALIDATE", SD_JOURNAL_INVALIDATE) ||
PyModule_AddIntConstant(m, "LOCAL_ONLY", SD_JOURNAL_LOCAL_ONLY) ||
PyModule_AddIntConstant(m, "RUNTIME_ONLY", SD_JOURNAL_RUNTIME_ONLY) ||
+ PyModule_AddIntConstant(m, "SYSTEM", SD_JOURNAL_SYSTEM) ||
PyModule_AddIntConstant(m, "SYSTEM_ONLY", SD_JOURNAL_SYSTEM_ONLY) ||
+ PyModule_AddIntConstant(m, "CURRENT_USER", SD_JOURNAL_CURRENT_USER) ||
PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION)) {
#if PY_MAJOR_VERSION >= 3
Py_DECREF(m);
diff --git a/src/python-systemd/daemon.py b/src/python-systemd/daemon.py
index e2829d1671..1c386bb6fc 100644
--- a/src/python-systemd/daemon.py
+++ b/src/python-systemd/daemon.py
@@ -1,5 +1,6 @@
from ._daemon import (__version__,
booted,
+ notify,
_listen_fds,
_is_fifo,
_is_socket,
diff --git a/src/python-systemd/docs/journal.rst b/src/python-systemd/docs/journal.rst
index 08756b99be..ea74cf85c4 100644
--- a/src/python-systemd/docs/journal.rst
+++ b/src/python-systemd/docs/journal.rst
@@ -42,7 +42,7 @@ event loop:
>>> j = journal.Reader()
>>> j.seek_tail()
>>> p = select.poll()
- >>> p.register(j, select.POLLIN)
+ >>> p.register(j, j.get_events())
>>> p.poll()
[(3, 1)]
>>> j.get_next()
@@ -53,7 +53,8 @@ Journal access types
.. autoattribute:: systemd.journal.LOCAL_ONLY
.. autoattribute:: systemd.journal.RUNTIME_ONLY
-.. autoattribute:: systemd.journal.SYSTEM_ONLY
+.. autoattribute:: systemd.journal.SYSTEM
+.. autoattribute:: systemd.journal.CURRENT_USER
Journal event types
~~~~~~~~~~~~~~~~~~~
diff --git a/src/python-systemd/docs/login.rst b/src/python-systemd/docs/login.rst
index 2cd9d8cbee..6b4de64c55 100644
--- a/src/python-systemd/docs/login.rst
+++ b/src/python-systemd/docs/login.rst
@@ -3,3 +3,26 @@
.. automodule:: systemd.login
:members:
+
+.. autoclass:: Monitor
+ :undoc-members:
+ :inherited-members:
+
+Example: polling for events
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This example shows that session/uid/seat/machine events can be waited
+for (using e.g. `poll`). This makes it easy to integrate Monitor in an
+external event loop:
+
+ >>> import select
+ >>> from systemd import login
+ >>> m = login.Monitor("machine")
+ >>> p = select.poll()
+ >>> p.register(m, m.get_events())
+ >>> login.machine_names()
+ []
+ >>> p.poll()
+ [(3, 1)]
+ >>> login.machine_names()
+ ['fedora-19.nspawn']
diff --git a/src/python-systemd/journal.py b/src/python-systemd/journal.py
index 9ef1ede229..d0bcd24d15 100644
--- a/src/python-systemd/journal.py
+++ b/src/python-systemd/journal.py
@@ -33,7 +33,8 @@ from syslog import (LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR,
LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG)
from ._journal import __version__, sendv, stream_fd
from ._reader import (_Reader, NOP, APPEND, INVALIDATE,
- LOCAL_ONLY, RUNTIME_ONLY, SYSTEM_ONLY,
+ LOCAL_ONLY, RUNTIME_ONLY,
+ SYSTEM, SYSTEM_ONLY, CURRENT_USER,
_get_catalog)
from . import id128 as _id128
@@ -55,6 +56,9 @@ def _convert_realtime(t):
def _convert_timestamp(s):
return _datetime.datetime.fromtimestamp(int(s) / 1000000)
+def _convert_trivial(x):
+ return x
+
if _sys.version_info >= (3,):
def _convert_uuid(s):
return _uuid.UUID(s.decode())
@@ -87,6 +91,7 @@ DEFAULT_CONVERTERS = {
'__REALTIME_TIMESTAMP': _convert_realtime,
'_SOURCE_MONOTONIC_TIMESTAMP': _convert_source_monotonic,
'__MONOTONIC_TIMESTAMP': _convert_monotonic,
+ '__CURSOR': _convert_trivial,
'COREDUMP': bytes,
'COREDUMP_PID': int,
'COREDUMP_UID': int,
@@ -119,7 +124,7 @@ class Reader(_Reader):
See systemd.journal-fields(7) for more info on typical fields
found in the journal.
"""
- def __init__(self, flags=0, path=None, converters=None):
+ def __init__(self, flags=0, path=None, files=None, converters=None):
"""Create an instance of Reader, which allows filtering and
return of journal entries.
@@ -145,7 +150,7 @@ class Reader(_Reader):
Reader implements the context manager protocol: the journal
will be closed when exiting the block.
"""
- super(Reader, self).__init__(flags, path)
+ super(Reader, self).__init__(flags, path, files)
if _sys.version_info >= (3,3):
self.converters = _ChainMap()
if converters is not None:
@@ -187,18 +192,18 @@ class Reader(_Reader):
"""
return self
- if _sys.version_info >= (3,):
- def __next__(self):
- """Part of iterator protocol.
- Returns self.get_next().
- """
- return self.get_next()
- else:
- def next(self):
- """Part of iterator protocol.
- Returns self.get_next().
- """
- return self.get_next()
+ def __next__(self):
+ """Part of iterator protocol.
+ Returns self.get_next() or raises StopIteration.
+ """
+ ans = self.get_next()
+ if ans:
+ return ans
+ else:
+ raise StopIteration()
+
+ if _sys.version_info < (3,):
+ next = __next__
def add_match(self, *args, **kwargs):
"""Add one or more matches to the filter journal log entries.
diff --git a/src/python-systemd/login.c b/src/python-systemd/login.c
index 1dbe5ac5bf..dd2edbca00 100644
--- a/src/python-systemd/login.c
+++ b/src/python-systemd/login.c
@@ -133,6 +133,200 @@ static PyMethodDef methods[] = {
{} /* Sentinel */
};
+
+typedef struct {
+ PyObject_HEAD
+ sd_login_monitor *monitor;
+} Monitor;
+static PyTypeObject MonitorType;
+
+static void Monitor_dealloc(Monitor* self)
+{
+ sd_login_monitor_unref(self->monitor);
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+PyDoc_STRVAR(Monitor__doc__,
+ "Monitor([category]) -> ...\n\n"
+ "Monitor may be used to monitor login sessions, users, seats,\n"
+ "and virtual machines/containers. Monitor provides a file\n"
+ "descriptor which can be integrated in an external event loop.\n"
+ "See man:sd_login_monitor_new(3) for the details about what\n"
+ "can be monitored.");
+static int Monitor_init(Monitor *self, PyObject *args, PyObject *keywds)
+{
+ const char *category = NULL;
+ int r;
+
+ static const char* const kwlist[] = {"category", NULL};
+ if (!PyArg_ParseTupleAndKeywords(args, keywds, "|z:__init__", (char**) kwlist,
+ &category))
+ return -1;
+
+ Py_BEGIN_ALLOW_THREADS
+ r = sd_login_monitor_new(category, &self->monitor);
+ Py_END_ALLOW_THREADS
+
+ return set_error(r, NULL, "Invalid category");
+}
+
+
+PyDoc_STRVAR(Monitor_fileno__doc__,
+ "fileno() -> int\n\n"
+ "Get a file descriptor to poll for events.\n"
+ "This method wraps sd_login_monitor_get_fd(3).");
+static PyObject* Monitor_fileno(Monitor *self, PyObject *args)
+{
+ int fd = sd_login_monitor_get_fd(self->monitor);
+ set_error(fd, NULL, NULL);
+ if (fd < 0)
+ return NULL;
+ return long_FromLong(fd);
+}
+
+
+PyDoc_STRVAR(Monitor_get_events__doc__,
+ "get_events() -> int\n\n"
+ "Returns a mask of poll() events to wait for on the file\n"
+ "descriptor returned by .fileno().\n\n"
+ "See man:sd_login_monitor_get_events(3) for further discussion.");
+static PyObject* Monitor_get_events(Monitor *self, PyObject *args)
+{
+ int r = sd_login_monitor_get_events(self->monitor);
+ set_error(r, NULL, NULL);
+ if (r < 0)
+ return NULL;
+ return long_FromLong(r);
+}
+
+
+PyDoc_STRVAR(Monitor_get_timeout__doc__,
+ "get_timeout() -> int or None\n\n"
+ "Returns a timeout value for usage in poll(), the time since the\n"
+ "epoch of clock_gettime(2) in microseconds, or None if no timeout\n"
+ "is necessary.\n\n"
+ "The return value must be converted to a relative timeout in\n"
+ "milliseconds if it is to be used as an argument for poll().\n"
+ "See man:sd_login_monitor_get_timeout(3) for further discussion.");
+static PyObject* Monitor_get_timeout(Monitor *self, PyObject *args)
+{
+ int r;
+ uint64_t t;
+
+ r = sd_login_monitor_get_timeout(self->monitor, &t);
+ set_error(r, NULL, NULL);
+ if (r < 0)
+ return NULL;
+
+ if (t == (uint64_t) -1)
+ Py_RETURN_NONE;
+
+ assert_cc(sizeof(unsigned long long) == sizeof(t));
+ return PyLong_FromUnsignedLongLong(t);
+}
+
+
+PyDoc_STRVAR(Monitor_get_timeout_ms__doc__,
+ "get_timeout_ms() -> int\n\n"
+ "Returns a timeout value suitable for usage in poll(), the value\n"
+ "returned by .get_timeout() converted to relative ms, or -1 if\n"
+ "no timeout is necessary.");
+static PyObject* Monitor_get_timeout_ms(Monitor *self, PyObject *args)
+{
+ int r;
+ uint64_t t;
+
+ r = sd_login_monitor_get_timeout(self->monitor, &t);
+ set_error(r, NULL, NULL);
+ if (r < 0)
+ return NULL;
+
+ return absolute_timeout(t);
+}
+
+
+PyDoc_STRVAR(Monitor_close__doc__,
+ "close() -> None\n\n"
+ "Free resources allocated by this Monitor object.\n"
+ "This method invokes sd_login_monitor_unref().\n"
+ "See man:sd_login_monitor_unref(3).");
+static PyObject* Monitor_close(Monitor *self, PyObject *args)
+{
+ assert(self);
+ assert(!args);
+
+ sd_login_monitor_unref(self->monitor);
+ self->monitor = NULL;
+ Py_RETURN_NONE;
+}
+
+
+PyDoc_STRVAR(Monitor_flush__doc__,
+ "flush() -> None\n\n"
+ "Reset the wakeup state of the monitor object.\n"
+ "This method invokes sd_login_monitor_flush().\n"
+ "See man:sd_login_monitor_flush(3).");
+static PyObject* Monitor_flush(Monitor *self, PyObject *args)
+{
+ assert(self);
+ assert(!args);
+
+ Py_BEGIN_ALLOW_THREADS
+ sd_login_monitor_flush(self->monitor);
+ Py_END_ALLOW_THREADS
+ Py_RETURN_NONE;
+}
+
+
+PyDoc_STRVAR(Monitor___enter____doc__,
+ "__enter__() -> self\n\n"
+ "Part of the context manager protocol.\n"
+ "Returns self.\n");
+static PyObject* Monitor___enter__(PyObject *self, PyObject *args)
+{
+ assert(self);
+ assert(!args);
+
+ Py_INCREF(self);
+ return self;
+}
+
+
+PyDoc_STRVAR(Monitor___exit____doc__,
+ "__exit__(type, value, traceback) -> None\n\n"
+ "Part of the context manager protocol.\n"
+ "Closes the monitor..\n");
+static PyObject* Monitor___exit__(Monitor *self, PyObject *args)
+{
+ return Monitor_close(self, args);
+}
+
+
+static PyMethodDef Monitor_methods[] = {
+ {"fileno", (PyCFunction) Monitor_fileno, METH_NOARGS, Monitor_fileno__doc__},
+ {"get_events", (PyCFunction) Monitor_get_events, METH_NOARGS, Monitor_get_events__doc__},
+ {"get_timeout", (PyCFunction) Monitor_get_timeout, METH_NOARGS, Monitor_get_timeout__doc__},
+ {"get_timeout_ms", (PyCFunction) Monitor_get_timeout_ms, METH_NOARGS, Monitor_get_timeout_ms__doc__},
+ {"close", (PyCFunction) Monitor_close, METH_NOARGS, Monitor_close__doc__},
+ {"flush", (PyCFunction) Monitor_flush, METH_NOARGS, Monitor_flush__doc__},
+ {"__enter__", (PyCFunction) Monitor___enter__, METH_NOARGS, Monitor___enter____doc__},
+ {"__exit__", (PyCFunction) Monitor___exit__, METH_VARARGS, Monitor___exit____doc__},
+ {} /* Sentinel */
+};
+
+static PyTypeObject MonitorType = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "login.Monitor",
+ .tp_basicsize = sizeof(Monitor),
+ .tp_dealloc = (destructor) Monitor_dealloc,
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ .tp_doc = Monitor__doc__,
+ .tp_methods = Monitor_methods,
+ .tp_init = (initproc) Monitor_init,
+ .tp_new = PyType_GenericNew,
+};
+
+
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-prototypes"
@@ -141,10 +335,17 @@ static PyMethodDef methods[] = {
PyMODINIT_FUNC initlogin(void) {
PyObject *m;
+ if (PyType_Ready(&MonitorType) < 0)
+ return;
+
m = Py_InitModule3("login", methods, module__doc__);
if (m == NULL)
return;
+
PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
+
+ Py_INCREF(&MonitorType);
+ PyModule_AddObject(m, "Monitor", (PyObject *) &MonitorType);
}
#else
@@ -159,6 +360,9 @@ static struct PyModuleDef module = {
PyMODINIT_FUNC PyInit_login(void) {
PyObject *m;
+ if (PyType_Ready(&MonitorType) < 0)
+ return NULL;
+
m = PyModule_Create(&module);
if (m == NULL)
return NULL;
@@ -168,6 +372,13 @@ PyMODINIT_FUNC PyInit_login(void) {
return NULL;
}
+ Py_INCREF(&MonitorType);
+ if (PyModule_AddObject(m, "Monitor", (PyObject *) &MonitorType)) {
+ Py_DECREF(&MonitorType);
+ Py_DECREF(m);
+ return NULL;
+ }
+
return m;
}
diff --git a/src/python-systemd/pyutil.c b/src/python-systemd/pyutil.c
index 9510acdddb..722c4f5b5f 100644
--- a/src/python-systemd/pyutil.c
+++ b/src/python-systemd/pyutil.c
@@ -30,17 +30,51 @@ void cleanup_Py_DECREFp(PyObject **p) {
}
PyObject* absolute_timeout(uint64_t t) {
- if (t == (uint64_t) -1)
- return PyLong_FromLong(-1);
- else {
- struct timespec ts;
- uint64_t n;
- int msec;
-
- clock_gettime(CLOCK_MONOTONIC, &ts);
- n = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
- msec = t > n ? (int) ((t - n + 999) / 1000) : 0;
-
- return PyLong_FromLong(msec);
- }
+ if (t == (uint64_t) -1)
+ return PyLong_FromLong(-1);
+ else {
+ struct timespec ts;
+ uint64_t n;
+ int msec;
+
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ n = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
+ msec = t > n ? (int) ((t - n + 999) / 1000) : 0;
+
+ return PyLong_FromLong(msec);
+ }
+}
+
+int set_error(int r, const char* path, const char* invalid_message) {
+ if (r >= 0)
+ return r;
+ if (r == -EINVAL && invalid_message)
+ PyErr_SetString(PyExc_ValueError, invalid_message);
+ else if (r == -ENOMEM)
+ PyErr_SetString(PyExc_MemoryError, "Not enough memory");
+ else {
+ errno = -r;
+ PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
+ }
+ return -1;
+}
+
+#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
+int Unicode_FSConverter(PyObject* obj, void *_result) {
+ PyObject **result = _result;
+
+ assert(result);
+
+ if (!obj)
+ /* cleanup: we don't return Py_CLEANUP_SUPPORTED, so
+ * we can assume that it was PyUnicode_FSConverter. */
+ return PyUnicode_FSConverter(obj, result);
+
+ if (obj == Py_None) {
+ *result = NULL;
+ return 1;
+ }
+
+ return PyUnicode_FSConverter(obj, result);
}
+#endif
diff --git a/src/python-systemd/pyutil.h b/src/python-systemd/pyutil.h
index 5c7ea37cdb..1477e7bf9c 100644
--- a/src/python-systemd/pyutil.h
+++ b/src/python-systemd/pyutil.h
@@ -28,6 +28,11 @@
void cleanup_Py_DECREFp(PyObject **p);
PyObject* absolute_timeout(uint64_t t);
+int set_error(int r, const char* path, const char* invalid_message);
+
+#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
+int Unicode_FSConverter(PyObject* obj, void *_result);
+#endif
#define _cleanup_Py_DECREF_ __attribute__((cleanup(cleanup_Py_DECREFp)))
diff --git a/src/random-seed/random-seed.c b/src/random-seed/random-seed.c
index fdcaa1e154..afbd5002dd 100644
--- a/src/random-seed/random-seed.c
+++ b/src/random-seed/random-seed.c
@@ -32,11 +32,11 @@
#define POOL_SIZE_MIN 512
int main(int argc, char *argv[]) {
- int seed_fd = -1, random_fd = -1;
- int ret = EXIT_FAILURE;
- void* buf;
+ _cleanup_close_ int seed_fd = -1, random_fd = -1;
+ _cleanup_free_ void* buf = NULL;
size_t buf_size = 0;
- ssize_t r;
+ ssize_t k;
+ int r;
FILE *f;
if (argc != 2) {
@@ -51,7 +51,8 @@ int main(int argc, char *argv[]) {
umask(0022);
/* Read pool size, if possible */
- if ((f = fopen("/proc/sys/kernel/random/poolsize", "re"))) {
+ f = fopen("/proc/sys/kernel/random/poolsize", "re");
+ if (f) {
if (fscanf(f, "%zu", &buf_size) > 0) {
/* poolsize is in bits on 2.6, but we want bytes */
buf_size /= 8;
@@ -63,13 +64,15 @@ int main(int argc, char *argv[]) {
if (buf_size <= POOL_SIZE_MIN)
buf_size = POOL_SIZE_MIN;
- if (!(buf = malloc(buf_size))) {
- log_error("Failed to allocate buffer.");
+ buf = malloc(buf_size);
+ if (!buf) {
+ r = log_oom();
goto finish;
}
- if (mkdir_parents_label(RANDOM_SEED, 0755) < 0) {
- log_error("Failed to create directories parents of %s: %m", RANDOM_SEED);
+ r = mkdir_parents_label(RANDOM_SEED, 0755);
+ if (r < 0) {
+ log_error("Failed to create parent directory of " RANDOM_SEED ": %s", strerror(-r));
goto finish;
}
@@ -79,45 +82,64 @@ int main(int argc, char *argv[]) {
if (streq(argv[1], "load")) {
- if ((seed_fd = open(RANDOM_SEED, O_RDWR|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600)) < 0) {
- if ((seed_fd = open(RANDOM_SEED, O_RDONLY|O_CLOEXEC|O_NOCTTY)) < 0) {
+ seed_fd = open(RANDOM_SEED, O_RDWR|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600);
+ if (seed_fd < 0) {
+ seed_fd = open(RANDOM_SEED, O_RDONLY|O_CLOEXEC|O_NOCTTY);
+ if (seed_fd < 0) {
log_error("Failed to open random seed: %m");
+ r = -errno;
goto finish;
}
}
- if ((random_fd = open("/dev/urandom", O_RDWR|O_CLOEXEC|O_NOCTTY, 0600)) < 0) {
- if ((random_fd = open("/dev/urandom", O_WRONLY|O_CLOEXEC|O_NOCTTY, 0600)) < 0) {
+ random_fd = open("/dev/urandom", O_RDWR|O_CLOEXEC|O_NOCTTY, 0600);
+ if (random_fd < 0) {
+ random_fd = open("/dev/urandom", O_WRONLY|O_CLOEXEC|O_NOCTTY, 0600);
+ if (random_fd < 0) {
log_error("Failed to open /dev/urandom: %m");
+ r = -errno;
goto finish;
}
}
- if ((r = loop_read(seed_fd, buf, buf_size, false)) <= 0) {
+ k = loop_read(seed_fd, buf, buf_size, false);
+ if (k <= 0) {
if (r != 0)
log_error("Failed to read seed file: %m");
+
+ r = k == 0 ? -EIO : (int) k;
+
} else {
lseek(seed_fd, 0, SEEK_SET);
- if ((r = loop_write(random_fd, buf, (size_t) r, false)) <= 0)
- log_error("Failed to write seed to /dev/urandom: %s",
- r < 0 ? strerror(errno) : "short write");
+ k = loop_write(random_fd, buf, (size_t) k, false);
+ if (k <= 0) {
+ log_error("Failed to write seed to /dev/urandom: %s", r < 0 ? strerror(-r) : "short write");
+
+ r = k == 0 ? -EIO : (int) k;
+ }
}
} else if (streq(argv[1], "save")) {
- if ((seed_fd = open(RANDOM_SEED, O_WRONLY|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600)) < 0) {
+ seed_fd = open(RANDOM_SEED, O_WRONLY|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600);
+ if (seed_fd < 0) {
log_error("Failed to open random seed: %m");
+ r = -errno;
goto finish;
}
- if ((random_fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY)) < 0) {
+ random_fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
+ if (random_fd < 0) {
log_error("Failed to open /dev/urandom: %m");
+ r = -errno;
goto finish;
}
+
} else {
log_error("Unknown verb %s.", argv[1]);
+ r = -EINVAL;
goto finish;
}
@@ -127,23 +149,18 @@ int main(int argc, char *argv[]) {
fchmod(seed_fd, 0600);
fchown(seed_fd, 0, 0);
- if ((r = loop_read(random_fd, buf, buf_size, false)) <= 0)
- log_error("Failed to read new seed from /dev/urandom: %s", r < 0 ? strerror(errno) : "EOF");
- else {
- if ((r = loop_write(seed_fd, buf, (size_t) r, false)) <= 0)
- log_error("Failed to write new random seed file: %s", r < 0 ? strerror(errno) : "short write");
+ k = loop_read(random_fd, buf, buf_size, false);
+ if (k <= 0) {
+ log_error("Failed to read new seed from /dev/urandom: %s", r < 0 ? strerror(-r) : "EOF");
+ r = k == 0 ? -EIO : (int) k;
+ } else {
+ r = loop_write(seed_fd, buf, (size_t) k, false);
+ if (r <= 0) {
+ log_error("Failed to write new random seed file: %s", r < 0 ? strerror(-r) : "short write");
+ r = r == 0 ? -EIO : r;
+ }
}
- ret = EXIT_SUCCESS;
-
finish:
- if (random_fd >= 0)
- close_nointr_nofail(random_fd);
-
- if (seed_fd >= 0)
- close_nointr_nofail(seed_fd);
-
- free(buf);
-
- return ret;
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/readahead/readahead-collect.c b/src/readahead/readahead-collect.c
index ccd8408c1b..32888add01 100644
--- a/src/readahead/readahead-collect.c
+++ b/src/readahead/readahead-collect.c
@@ -44,6 +44,10 @@
#include <sys/inotify.h>
#include <math.h>
+#ifdef HAVE_LINUX_BTRFS_H
+#include <linux/btrfs.h>
+#endif
+
#ifdef HAVE_FANOTIFY_INIT
#include <sys/fanotify.h>
#endif
@@ -506,7 +510,7 @@ done:
on_ssd = fs_on_ssd(root) > 0;
log_debug("On SSD: %s", yes_no(on_ssd));
- on_btrfs = statfs(root, &sfs) >= 0 && F_TYPE_CMP(sfs.f_type, BTRFS_SUPER_MAGIC);
+ on_btrfs = statfs(root, &sfs) >= 0 && F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC);
log_debug("On btrfs: %s", yes_no(on_btrfs));
if (asprintf(&pack_fn_new, "%s/.readahead.new", root) < 0) {
diff --git a/src/run/Makefile b/src/run/Makefile
new file mode 120000
index 0000000000..d0b0e8e008
--- /dev/null
+++ b/src/run/Makefile
@@ -0,0 +1 @@
+../Makefile \ No newline at end of file
diff --git a/src/run/run.c b/src/run/run.c
new file mode 100644
index 0000000000..18a4920f03
--- /dev/null
+++ b/src/run/run.c
@@ -0,0 +1,376 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ 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>
+#include <getopt.h>
+
+#include "sd-bus.h"
+#include "bus-internal.h"
+#include "bus-message.h"
+#include "strv.h"
+#include "build.h"
+#include "unit-name.h"
+#include "path-util.h"
+
+static bool arg_scope = false;
+static bool arg_user = false;
+static bool arg_remain_after_exit = false;
+static const char *arg_unit = NULL;
+static const char *arg_description = NULL;
+static const char *arg_slice = NULL;
+static bool arg_send_sighup = false;
+
+static int help(void) {
+
+ printf("%s [OPTIONS...] COMMAND [ARGS...]\n\n"
+ "Run the specified command in a transient scope or service unit.\n\n"
+ " -h --help Show this help\n"
+ " --version Show package version\n"
+ " --user Run as user unit\n"
+ " --scope Run this as scope rather than service\n"
+ " --unit=UNIT Run under the specified unit name\n"
+ " --description=TEXT Description for unit\n"
+ " --slice=SLICE Run in the specified slice\n"
+ " -r --remain-after-exit Leave service around until explicitly stopped\n"
+ " --send-sighup Send SIGHUP when terminating\n",
+ program_invocation_short_name);
+
+ return 0;
+}
+
+static int parse_argv(int argc, char *argv[]) {
+
+ enum {
+ ARG_VERSION = 0x100,
+ ARG_USER,
+ ARG_SCOPE,
+ ARG_UNIT,
+ ARG_DESCRIPTION,
+ ARG_SLICE,
+ ARG_SEND_SIGHUP,
+ };
+
+ static const struct option options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "user", no_argument, NULL, ARG_USER },
+ { "scope", no_argument, NULL, ARG_SCOPE },
+ { "unit", required_argument, NULL, ARG_UNIT },
+ { "description", required_argument, NULL, ARG_DESCRIPTION },
+ { "slice", required_argument, NULL, ARG_SLICE },
+ { "remain-after-exit", no_argument, NULL, 'r' },
+ { "send-sighup", no_argument, NULL, ARG_SEND_SIGHUP },
+ { NULL, 0, NULL, 0 },
+ };
+
+ int c;
+
+ assert(argc >= 0);
+ assert(argv);
+
+ while ((c = getopt_long(argc, argv, "+hr", options, NULL)) >= 0) {
+
+ switch (c) {
+
+ case 'h':
+ help();
+ return 0;
+
+ case ARG_VERSION:
+ puts(PACKAGE_STRING);
+ puts(SYSTEMD_FEATURES);
+ return 0;
+
+ case ARG_USER:
+ arg_user = true;
+ break;
+
+ case ARG_SCOPE:
+ arg_scope = true;
+ break;
+
+ case ARG_UNIT:
+ arg_unit = optarg;
+ break;
+
+ case ARG_DESCRIPTION:
+ arg_description = optarg;
+ break;
+
+ case ARG_SLICE:
+ arg_slice = optarg;
+ break;
+
+ case ARG_SEND_SIGHUP:
+ arg_send_sighup = true;
+ break;
+
+ case 'r':
+ arg_remain_after_exit = true;
+ break;
+
+ case '?':
+ return -EINVAL;
+
+ default:
+ log_error("Unknown option code %c", c);
+ return -EINVAL;
+ }
+ }
+
+ if (optind >= argc) {
+ log_error("Command line to execute required.");
+ return -EINVAL;
+ }
+
+ return 1;
+}
+
+static int message_start_transient_unit_new(sd_bus *bus, const char *name, sd_bus_message **ret) {
+ _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ int r;
+
+ log_info("Running as unit %s.", name);
+
+ r = sd_bus_message_new_method_call(
+ bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "StartTransientUnit", &m);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append(m, "ss", name, "fail");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_open_container(m, 'a', "(sv)");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append(m, "(sv)", "Description", "s", arg_description);
+ if (r < 0)
+ return r;
+
+ if (!isempty(arg_slice)) {
+ _cleanup_free_ char *slice;
+
+ slice = unit_name_mangle_with_suffix(arg_slice, ".slice");
+ if (!slice)
+ return -ENOMEM;
+
+ r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", arg_send_sighup);
+ if (r < 0)
+ return r;
+
+ *ret = m;
+ m = NULL;
+
+ return 0;
+}
+
+static int message_start_transient_unit_send(sd_bus *bus, sd_bus_message *m, sd_bus_error *error, sd_bus_message **reply) {
+ int r;
+
+ r = sd_bus_message_close_container(m);
+ if (r < 0)
+ return r;
+
+ return sd_bus_send_with_reply_and_block(bus, m, 0, error, reply);
+}
+
+static int start_transient_service(
+ sd_bus *bus,
+ char **argv,
+ sd_bus_error *error) {
+
+ _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+ _cleanup_free_ char *name = NULL;
+ char **i;
+ int r;
+
+ if (arg_unit)
+ name = unit_name_mangle_with_suffix(arg_unit, ".service");
+ else
+ asprintf(&name, "run-%lu.service", (unsigned long) getpid());
+ if (!name)
+ return -ENOMEM;
+
+ r = message_start_transient_unit_new(bus, name, &m);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append(m, "(sv)", "RemainAfterExit", "b", arg_remain_after_exit);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_open_container(m, 'r', "sv");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append(m, "s", "ExecStart");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_open_container(m, 'v', "a(sasb)");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_open_container(m, 'a', "(sasb)");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_open_container(m, 'r', "sasb");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append(m, "s", argv[0]);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_open_container(m, 'a', "s");
+ if (r < 0)
+ return r;
+
+ STRV_FOREACH(i, argv) {
+ r = sd_bus_message_append(m, "s", *i);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_bus_message_close_container(m);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append(m, "b", false);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_close_container(m);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_close_container(m);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_close_container(m);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_close_container(m);
+ if (r < 0)
+ return r;
+
+ return message_start_transient_unit_send(bus, m, error, &reply);
+}
+
+static int start_transient_scope(
+ sd_bus *bus,
+ char **argv,
+ sd_bus_error *error) {
+
+ _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+ _cleanup_free_ char *name = NULL;
+ int r;
+
+ if (arg_unit)
+ name = unit_name_mangle_with_suffix(arg_unit, ".scope");
+ else
+ asprintf(&name, "run-%lu.scope", (unsigned long) getpid());
+ if (!name)
+ return -ENOMEM;
+
+ r = message_start_transient_unit_new(bus, name, &m);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, (uint32_t) getpid());
+ if (r < 0)
+ return r;
+
+ r = message_start_transient_unit_send(bus, m, error, &reply);
+ if (r < 0)
+ return r;
+
+ execvp(argv[0], argv);
+ log_error("Failed to execute: %m");
+ return -errno;
+}
+
+int main(int argc, char* argv[]) {
+ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_bus_unref_ sd_bus *bus = NULL;
+ _cleanup_free_ char *description = NULL, *command = NULL;
+ int r;
+
+ log_parse_environment();
+ log_open();
+
+ r = parse_argv(argc, argv);
+ if (r <= 0)
+ goto fail;
+
+ r = find_binary(argv[optind], &command);
+ if (r < 0) {
+ log_error("Failed to find executable %s: %s", argv[optind], strerror(-r));
+ goto fail;
+ }
+ argv[optind] = command;
+
+ if (!arg_description) {
+ description = strv_join(argv + optind, " ");
+ if (!description) {
+ r = log_oom();
+ goto fail;
+ }
+
+ arg_description = description;
+ }
+
+ if (arg_user)
+ r = sd_bus_open_user(&bus);
+ else
+ r = sd_bus_open_system(&bus);
+ if (r < 0) {
+ log_error("Failed to create new bus connection: %s", strerror(-r));
+ goto fail;
+ }
+
+ if (arg_scope)
+ r = start_transient_scope(bus, argv + optind, &error);
+ else
+ r = start_transient_service(bus, argv + optind, &error);
+ if (r < 0) {
+ log_error("Failed start transient unit: %s", error.message ? error.message : strerror(-r));
+ sd_bus_error_free(&error);
+ goto fail;
+ }
+
+fail:
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c
index 48bb12f46b..fb04e49dc4 100644
--- a/src/shared/acl-util.c
+++ b/src/shared/acl-util.c
@@ -69,6 +69,34 @@ int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry) {
return 0;
}
+int calc_acl_mask_if_needed(acl_t *acl_p) {
+ acl_entry_t i;
+ int found;
+
+ assert(acl_p);
+
+ for (found = acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i);
+ found > 0;
+ found = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) {
+
+ acl_tag_t tag;
+
+ if (acl_get_tag_type(i, &tag) < 0)
+ return -errno;
+
+ if (tag == ACL_MASK)
+ return 0;
+ }
+
+ if (found < 0)
+ return -errno;
+
+ if (acl_calc_mask(acl_p) < 0)
+ return -errno;
+
+ return 0;
+}
+
int search_acl_groups(char*** dst, const char* path, bool* belong) {
acl_t acl;
diff --git a/src/shared/acl-util.h b/src/shared/acl-util.h
index 23090d9984..36ef490d7e 100644
--- a/src/shared/acl-util.h
+++ b/src/shared/acl-util.h
@@ -24,4 +24,5 @@
#include <stdbool.h>
int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry);
+int calc_acl_mask_if_needed(acl_t *acl_p);
int search_acl_groups(char*** dst, const char* path, bool* belong);
diff --git a/src/shared/acpi-fpdt.c b/src/shared/acpi-fpdt.c
new file mode 100644
index 0000000000..b094f34a5f
--- /dev/null
+++ b/src/shared/acpi-fpdt.c
@@ -0,0 +1,155 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ 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 <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+
+#include <util.h>
+#include <fileio.h>
+#include <time-util.h>
+#include <acpi-fpdt.h>
+
+struct acpi_table_header {
+ char signature[4];
+ uint32_t length;
+ uint8_t revision;
+ uint8_t checksum;
+ char oem_id[6];
+ char oem_table_id[8];
+ uint32_t oem_revision;
+ char asl_compiler_id[4];
+ uint32_t asl_compiler_revision;
+};
+
+enum {
+ ACPI_FPDT_TYPE_BOOT = 0,
+ ACPI_FPDT_TYPE_S3PERF = 1,
+};
+
+struct acpi_fpdt_header {
+ uint16_t type;
+ uint8_t length;
+ uint8_t revision;
+ uint8_t reserved[4];
+ uint64_t ptr;
+};
+
+struct acpi_fpdt_boot_header {
+ char signature[4];
+ uint32_t length;
+};
+
+enum {
+ ACPI_FPDT_S3PERF_RESUME_REC = 0,
+ ACPI_FPDT_S3PERF_SUSPEND_REC = 1,
+ ACPI_FPDT_BOOT_REC = 2,
+};
+
+struct acpi_fpdt_boot {
+ uint16_t type;
+ uint8_t length;
+ uint8_t revision;
+ uint8_t reserved[4];
+ uint64_t reset_end;
+ uint64_t load_start;
+ uint64_t startup_start;
+ uint64_t exit_services_entry;
+ uint64_t exit_services_exit;
+};
+
+int acpi_get_boot_usec(usec_t *loader_start, usec_t *loader_exit) {
+ char *buf;
+ struct acpi_table_header *tbl;
+ size_t l;
+ struct acpi_fpdt_header *rec;
+ int r;
+ uint64_t ptr = 0;
+ _cleanup_close_ int fd = -1;
+ struct acpi_fpdt_boot_header hbrec;
+ struct acpi_fpdt_boot brec;
+
+ r = read_full_file("/sys/firmware/acpi/tables/FPDT", &buf, &l);
+ if (r < 0)
+ return r;
+
+ if (l < sizeof(struct acpi_table_header) + sizeof(struct acpi_fpdt_header))
+ return -EINVAL;
+
+ tbl = (struct acpi_table_header *)buf;
+ if (l != tbl->length)
+ return -EINVAL;
+
+ if (memcmp(tbl->signature, "FPDT", 4) != 0)
+ return -EINVAL;
+
+ /* find Firmware Basic Boot Performance Pointer Record */
+ for (rec = (struct acpi_fpdt_header *)(buf + sizeof(struct acpi_table_header));
+ (char *)rec < buf + l;
+ rec = (struct acpi_fpdt_header *)((char *)rec + rec->length)) {
+ if (rec->type != ACPI_FPDT_TYPE_BOOT)
+ continue;
+ if (rec->length != sizeof(struct acpi_fpdt_header))
+ continue;
+
+ ptr = rec->ptr;
+ break;
+ }
+
+ if (ptr == 0)
+ return -EINVAL;
+
+ /* read Firmware Basic Boot Performance Data Record */
+ fd = open("/dev/mem", O_CLOEXEC|O_RDONLY);
+ if (fd < 0)
+ return -errno;
+
+ l = pread(fd, &hbrec, sizeof(struct acpi_fpdt_boot_header), ptr);
+ if (l != sizeof(struct acpi_fpdt_boot_header))
+ return -EINVAL;
+
+ if (memcmp(hbrec.signature, "FBPT", 4) != 0)
+ return -EINVAL;
+
+ if (hbrec.length < sizeof(struct acpi_fpdt_boot_header) + sizeof(struct acpi_fpdt_boot))
+ return -EINVAL;
+
+ l = pread(fd, &brec, sizeof(struct acpi_fpdt_boot), ptr + sizeof(struct acpi_fpdt_boot_header));
+ if (l != sizeof(struct acpi_fpdt_boot))
+ return -EINVAL;
+
+ if (brec.length != sizeof(struct acpi_fpdt_boot))
+ return -EINVAL;
+
+ if (brec.type != ACPI_FPDT_BOOT_REC)
+ return -EINVAL;
+
+ if (loader_start)
+ *loader_start = brec.startup_start / 1000;
+ if (loader_exit)
+ *loader_exit = brec.exit_services_exit / 1000;
+
+ return 0;
+}
diff --git a/src/shared/acpi-fpdt.h b/src/shared/acpi-fpdt.h
new file mode 100644
index 0000000000..fc4fe6f10f
--- /dev/null
+++ b/src/shared/acpi-fpdt.h
@@ -0,0 +1,26 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ 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 <time-util.h>
+
+int acpi_get_boot_usec(usec_t *loader_start, usec_t *loader_exit);
diff --git a/src/shared/boot-timestamps.c b/src/shared/boot-timestamps.c
new file mode 100644
index 0000000000..944996582e
--- /dev/null
+++ b/src/shared/boot-timestamps.c
@@ -0,0 +1,65 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2012 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 <unistd.h>
+
+#include "boot-timestamps.h"
+#include "acpi-fpdt.h"
+#include "efivars.h"
+
+int boot_timestamps(const dual_timestamp *n, dual_timestamp *firmware, dual_timestamp *loader) {
+ usec_t x, y, a;
+ int r;
+ dual_timestamp _n;
+
+ assert(firmware);
+ assert(loader);
+
+ if (!n) {
+ dual_timestamp_get(&_n);
+ n = &_n;
+ }
+
+ r = acpi_get_boot_usec(&x, &y);
+ if (r < 0) {
+ r = efi_loader_get_boot_usec(&x, &y);
+ if (r < 0)
+ return r;
+ }
+
+ /* Let's convert this to timestamps where the firmware
+ * began/loader began working. To make this more confusing:
+ * since usec_t is unsigned and the kernel's monotonic clock
+ * begins at kernel initialization we'll actually initialize
+ * the monotonic timestamps here as negative of the actual
+ * value. */
+
+ firmware->monotonic = y;
+ loader->monotonic = y - x;
+
+ a = n->monotonic + firmware->monotonic;
+ firmware->realtime = n->realtime > a ? n->realtime - a : 0;
+
+ a = n->monotonic + loader->monotonic;
+ loader->realtime = n->realtime > a ? n->realtime - a : 0;
+
+ return 0;
+}
diff --git a/src/shared/boot-timestamps.h b/src/shared/boot-timestamps.h
new file mode 100644
index 0000000000..a3d2405b56
--- /dev/null
+++ b/src/shared/boot-timestamps.h
@@ -0,0 +1,27 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2012 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 <time-util.h>
+
+int boot_timestamps(const dual_timestamp *n, dual_timestamp *firmware, dual_timestamp *loader);
diff --git a/src/shared/cgroup-label.c b/src/shared/cgroup-label.c
deleted file mode 100644
index 5b5163c250..0000000000
--- a/src/shared/cgroup-label.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <unistd.h>
-#include <signal.h>
-#include <string.h>
-#include <stdlib.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <ftw.h>
-
-#include "cgroup-util.h"
-#include "log.h"
-#include "set.h"
-#include "macro.h"
-#include "util.h"
-#include "mkdir.h"
-
-int cg_create(const char *controller, const char *path, const char *suffix) {
- _cleanup_free_ char *fs = NULL;
- int r;
-
- r = cg_get_path_and_check(controller, path, suffix, &fs);
- if (r < 0)
- return r;
-
- r = mkdir_parents_label(fs, 0755);
- if (r < 0)
- return r;
-
- if (mkdir(fs, 0755) < 0) {
-
- if (errno == EEXIST)
- return 0;
-
- return -errno;
- }
-
- return 1;
-}
-
-int cg_create_and_attach(const char *controller, const char *path, pid_t pid) {
- int r, q;
-
- assert(pid >= 0);
-
- r = cg_create(controller, path, NULL);
- if (r < 0)
- return r;
-
- q = cg_attach(controller, path, pid);
- if (q < 0)
- return q;
-
- /* This does not remove the cgroup on failure */
- return r;
-}
diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c
index 83cc0731b8..e971f36190 100644
--- a/src/shared/cgroup-show.c
+++ b/src/shared/cgroup-show.c
@@ -241,7 +241,6 @@ static int show_extra_pids(const char *controller, const char *path, const char
unsigned i, j;
int r;
- assert(controller);
assert(path);
if (n_pids <= 0)
diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c
index 43c415d760..8a4eddab7a 100644
--- a/src/shared/cgroup-util.c
+++ b/src/shared/cgroup-util.c
@@ -38,6 +38,8 @@
#include "strv.h"
#include "unit-name.h"
#include "fileio.h"
+#include "special.h"
+#include "mkdir.h"
int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
_cleanup_free_ char *fs = NULL;
@@ -58,25 +60,6 @@ int cg_enumerate_processes(const char *controller, const char *path, FILE **_f)
return 0;
}
-int cg_enumerate_tasks(const char *controller, const char *path, FILE **_f) {
- _cleanup_free_ char *fs = NULL;
- FILE *f;
- int r;
-
- assert(_f);
-
- r = cg_get_path(controller, path, "tasks", &fs);
- if (r < 0)
- return r;
-
- f = fopen(fs, "re");
- if (!f)
- return -errno;
-
- *_f = f;
- return 0;
-}
-
int cg_read_pid(FILE *f, pid_t *_pid) {
unsigned long ul;
@@ -150,7 +133,7 @@ int cg_read_subgroup(DIR *d, char **fn) {
return 0;
}
-int cg_rmdir(const char *controller, const char *path, bool honour_sticky) {
+int cg_rmdir(const char *controller, const char *path) {
_cleanup_free_ char *p = NULL;
int r;
@@ -158,22 +141,6 @@ int cg_rmdir(const char *controller, const char *path, bool honour_sticky) {
if (r < 0)
return r;
- if (honour_sticky) {
- char *tasks;
-
- /* If the sticky bit is set don't remove the directory */
-
- tasks = strappend(p, "/tasks");
- if (!tasks)
- return -ENOMEM;
-
- r = file_is_priv_sticky(tasks);
- free(tasks);
-
- if (r > 0)
- return 0;
- }
-
r = rmdir(p);
if (r < 0 && errno != ENOENT)
return -errno;
@@ -304,7 +271,7 @@ int cg_kill_recursive(const char *controller, const char *path, int sig, bool si
ret = r;
if (rem) {
- r = cg_rmdir(controller, path, true);
+ r = cg_rmdir(controller, path);
if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY)
return r;
}
@@ -365,7 +332,7 @@ int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char
pid_t pid = 0;
done = true;
- r = cg_enumerate_tasks(cfrom, pfrom, &f);
+ r = cg_enumerate_processes(cfrom, pfrom, &f);
if (r < 0) {
if (ret >= 0 && r != -ENOENT)
return r;
@@ -413,7 +380,14 @@ int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char
return ret;
}
-int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool rem) {
+int cg_migrate_recursive(
+ const char *cfrom,
+ const char *pfrom,
+ const char *cto,
+ const char *pto,
+ bool ignore_self,
+ bool rem) {
+
_cleanup_closedir_ DIR *d = NULL;
int r, ret = 0;
char *fn;
@@ -454,7 +428,7 @@ int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto,
ret = r;
if (rem) {
- r = cg_rmdir(cfrom, pfrom, true);
+ r = cg_rmdir(cfrom, pfrom);
if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY)
return r;
}
@@ -462,6 +436,37 @@ int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto,
return ret;
}
+int cg_migrate_recursive_fallback(
+ const char *cfrom,
+ const char *pfrom,
+ const char *cto,
+ const char *pto,
+ bool ignore_self,
+ bool rem) {
+
+ int r;
+
+ assert(cfrom);
+ assert(pfrom);
+ assert(cto);
+ assert(pto);
+
+ r = cg_migrate_recursive(cfrom, pfrom, cto, pto, ignore_self, rem);
+ if (r < 0) {
+ char prefix[strlen(pto) + 1];
+
+ /* This didn't work? Then let's try all prefixes of the destination */
+
+ PATH_FOREACH_PREFIX(prefix, pto) {
+ r = cg_migrate_recursive(cfrom, pfrom, cto, prefix, ignore_self, rem);
+ if (r >= 0)
+ break;
+ }
+ }
+
+ return 0;
+}
+
static const char *normalize_controller(const char *controller) {
assert(controller);
@@ -477,19 +482,19 @@ static const char *normalize_controller(const char *controller) {
static int join_path(const char *controller, const char *path, const char *suffix, char **fs) {
char *t = NULL;
- if (controller) {
- if (path && suffix)
+ if (!isempty(controller)) {
+ if (!isempty(path) && !isempty(suffix))
t = strjoin("/sys/fs/cgroup/", controller, "/", path, "/", suffix, NULL);
- else if (path)
+ else if (!isempty(path))
t = strjoin("/sys/fs/cgroup/", controller, "/", path, NULL);
- else if (suffix)
+ else if (!isempty(suffix))
t = strjoin("/sys/fs/cgroup/", controller, "/", suffix, NULL);
else
t = strappend("/sys/fs/cgroup/", controller);
} else {
- if (path && suffix)
+ if (!isempty(path) && !isempty(suffix))
t = strjoin(path, "/", suffix, NULL);
- else if (path)
+ else if (!isempty(path))
t = strdup(path);
else
return -EINVAL;
@@ -564,8 +569,9 @@ int cg_get_path_and_check(const char *controller, const char *path, const char *
}
static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
- char *p;
- bool is_sticky;
+ assert(path);
+ assert(sb);
+ assert(ftwbuf);
if (typeflag != FTW_DP)
return 0;
@@ -573,18 +579,6 @@ static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct
if (ftwbuf->level < 1)
return 0;
- p = strappend(path, "/tasks");
- if (!p) {
- errno = ENOMEM;
- return 1;
- }
-
- is_sticky = file_is_priv_sticky(p) > 0;
- free(p);
-
- if (is_sticky)
- return 0;
-
rmdir(path);
return 0;
}
@@ -604,19 +598,8 @@ int cg_trim(const char *controller, const char *path, bool delete_root) {
r = errno ? -errno : -EIO;
if (delete_root) {
- bool is_sticky;
- char *p;
-
- p = strappend(fs, "/tasks");
- if (!p)
- return -ENOMEM;
-
- is_sticky = file_is_priv_sticky(p) > 0;
- free(p);
-
- if (!is_sticky)
- if (rmdir(fs) < 0 && errno != ENOENT && r == 0)
- return -errno;
+ if (rmdir(fs) < 0 && errno != ENOENT)
+ return -errno;
}
return r;
@@ -636,6 +619,46 @@ int cg_delete(const char *controller, const char *path) {
return r == -ENOENT ? 0 : r;
}
+int cg_create(const char *controller, const char *path) {
+ _cleanup_free_ char *fs = NULL;
+ int r;
+
+ r = cg_get_path_and_check(controller, path, NULL, &fs);
+ if (r < 0)
+ return r;
+
+ r = mkdir_parents(fs, 0755);
+ if (r < 0)
+ return r;
+
+ if (mkdir(fs, 0755) < 0) {
+
+ if (errno == EEXIST)
+ return 0;
+
+ return -errno;
+ }
+
+ return 1;
+}
+
+int cg_create_and_attach(const char *controller, const char *path, pid_t pid) {
+ int r, q;
+
+ assert(pid >= 0);
+
+ r = cg_create(controller, path);
+ if (r < 0)
+ return r;
+
+ q = cg_attach(controller, path, pid);
+ if (q < 0)
+ return q;
+
+ /* This does not remove the cgroup on failure */
+ return r;
+}
+
int cg_attach(const char *controller, const char *path, pid_t pid) {
_cleanup_free_ char *fs = NULL;
char c[DECIMAL_STR_MAX(pid_t) + 2];
@@ -644,7 +667,7 @@ int cg_attach(const char *controller, const char *path, pid_t pid) {
assert(path);
assert(pid >= 0);
- r = cg_get_path_and_check(controller, path, "tasks", &fs);
+ r = cg_get_path_and_check(controller, path, "cgroup.procs", &fs);
if (r < 0)
return r;
@@ -656,6 +679,30 @@ int cg_attach(const char *controller, const char *path, pid_t pid) {
return write_string_file(fs, c);
}
+int cg_attach_fallback(const char *controller, const char *path, pid_t pid) {
+ int r;
+
+ assert(controller);
+ assert(path);
+ assert(pid >= 0);
+
+ r = cg_attach(controller, path, pid);
+ if (r < 0) {
+ char prefix[strlen(path) + 1];
+
+ /* This didn't work? Then let's try all prefixes of
+ * the destination */
+
+ PATH_FOREACH_PREFIX(prefix, path) {
+ r = cg_attach(controller, prefix, pid);
+ if (r >= 0)
+ break;
+ }
+ }
+
+ return 0;
+}
+
int cg_set_group_access(
const char *controller,
const char *path,
@@ -683,52 +730,30 @@ int cg_set_task_access(
const char *path,
mode_t mode,
uid_t uid,
- gid_t gid,
- int sticky) {
+ gid_t gid) {
_cleanup_free_ char *fs = NULL, *procs = NULL;
int r;
assert(path);
- if (mode == (mode_t) -1 && uid == (uid_t) -1 && gid == (gid_t) -1 && sticky < 0)
+ if (mode == (mode_t) -1 && uid == (uid_t) -1 && gid == (gid_t) -1)
return 0;
if (mode != (mode_t) -1)
mode &= 0666;
- r = cg_get_path(controller, path, "tasks", &fs);
+ r = cg_get_path(controller, path, "cgroup.procs", &fs);
if (r < 0)
return r;
- if (sticky >= 0 && mode != (mode_t) -1)
- /* Both mode and sticky param are passed */
- mode |= (sticky ? S_ISVTX : 0);
- else if ((sticky >= 0 && mode == (mode_t) -1) ||
- (mode != (mode_t) -1 && sticky < 0)) {
- struct stat st;
-
- /* Only one param is passed, hence read the current
- * mode from the file itself */
-
- r = lstat(fs, &st);
- if (r < 0)
- return -errno;
-
- if (mode == (mode_t) -1)
- /* No mode set, we just shall set the sticky bit */
- mode = (st.st_mode & ~S_ISVTX) | (sticky ? S_ISVTX : 0);
- else
- /* Only mode set, leave sticky bit untouched */
- mode = (st.st_mode & ~0777) | mode;
- }
-
r = chmod_and_chown(fs, mode, uid, gid);
if (r < 0)
return r;
- /* Always keep values for "cgroup.procs" in sync with "tasks" */
- r = cg_get_path(controller, path, "cgroup.procs", &procs);
+ /* Compatibility, Always keep values for "tasks" in sync with
+ * "cgroup.procs" */
+ r = cg_get_path(controller, path, "tasks", &procs);
if (r < 0)
return r;
@@ -861,6 +886,32 @@ int cg_install_release_agent(const char *controller, const char *agent) {
return 0;
}
+int cg_uninstall_release_agent(const char *controller) {
+ _cleanup_free_ char *fs = NULL;
+ int r;
+
+ r = cg_get_path(controller, NULL, "notify_on_release", &fs);
+ if (r < 0)
+ return r;
+
+ r = write_string_file(fs, "0");
+ if (r < 0)
+ return r;
+
+ free(fs);
+ fs = NULL;
+
+ r = cg_get_path(controller, NULL, "release_agent", &fs);
+ if (r < 0)
+ return r;
+
+ r = write_string_file(fs, "");
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
_cleanup_fclose_ FILE *f = NULL;
pid_t pid = 0, self_pid;
@@ -869,7 +920,7 @@ int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
assert(path);
- r = cg_enumerate_tasks(controller, path, &f);
+ r = cg_enumerate_processes(controller, path, &f);
if (r < 0)
return r == -ENOENT ? 1 : r;
@@ -993,19 +1044,28 @@ int cg_split_spec(const char *spec, char **controller, char **path) {
return -EINVAL;
}
- u = strdup(e+1);
- if (!u) {
- free(t);
- return -ENOMEM;
- }
- if (!path_is_safe(u) ||
- !path_is_absolute(u)) {
- free(t);
- free(u);
- return -EINVAL;
- }
+ if (streq(e+1, "")) {
+ u = strdup("/");
+ if (!u) {
+ free(t);
+ return -ENOMEM;
+ }
+ } else {
+ u = strdup(e+1);
+ if (!u) {
+ free(t);
+ return -ENOMEM;
+ }
+
+ if (!path_is_safe(u) ||
+ !path_is_absolute(u)) {
+ free(t);
+ free(u);
+ return -EINVAL;
+ }
- path_kill_slashes(u);
+ path_kill_slashes(u);
+ }
if (controller)
*controller = t;
@@ -1075,96 +1135,20 @@ int cg_mangle_path(const char *path, char **result) {
return cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
}
-int cg_get_system_path(char **path) {
- char *p;
- int r;
-
- assert(path);
-
- r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &p);
- if (r < 0) {
- p = strdup("/system");
- if (!p)
- return -ENOMEM;
- }
-
- if (endswith(p, "/system"))
- *path = p;
- else {
- char *q;
-
- q = strappend(p, "/system");
- free(p);
- if (!q)
- return -ENOMEM;
-
- *path = q;
- }
-
- return 0;
-}
-
int cg_get_root_path(char **path) {
- char *root, *e;
+ char *p, *e;
int r;
assert(path);
- r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &root);
+ r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &p);
if (r < 0)
return r;
- e = endswith(root, "/system");
- if (e == root)
- e[1] = 0;
- else if (e)
+ e = endswith(p, "/" SPECIAL_SYSTEM_SLICE);
+ if (e)
*e = 0;
- *path = root;
- return 0;
-}
-
-int cg_get_user_path(char **path) {
- _cleanup_free_ char *root = NULL;
- char *p;
-
- assert(path);
-
- /* Figure out the place to put user cgroups below. We use the
- * same as PID 1 has but with the "/system" suffix replaced by
- * "/user" */
-
- if (cg_get_root_path(&root) < 0 || streq(root, "/"))
- p = strdup("/user");
- else
- p = strappend(root, "/user");
-
- if (!p)
- return -ENOMEM;
-
- *path = p;
- return 0;
-}
-
-int cg_get_machine_path(const char *machine, char **path) {
- _cleanup_free_ char *root = NULL, *escaped = NULL;
- char *p;
-
- assert(path);
-
- if (machine) {
- const char *name = strappenda(machine, ".nspawn");
-
- escaped = cg_escape(name);
- if (!escaped)
- return -ENOMEM;
- }
-
- p = strjoin(cg_get_root_path(&root) >= 0 && !streq(root, "/") ? root : "",
- "/machine", machine ? "/" : "", machine ? escaped : "", NULL);
- if (!p)
- return -ENOMEM;
-
*path = p;
return 0;
}
@@ -1247,7 +1231,7 @@ int cg_pid_get_path_shifted(pid_t pid, char **root, char **cgroup) {
}
int cg_path_decode_unit(const char *cgroup, char **unit){
- char *p, *e, *c, *s, *k;
+ char *e, *c, *s;
assert(cgroup);
assert(unit);
@@ -1256,33 +1240,31 @@ int cg_path_decode_unit(const char *cgroup, char **unit){
c = strndupa(cgroup, e - cgroup);
c = cg_unescape(c);
- /* Could this be a valid unit name? */
- if (!unit_name_is_valid(c, true))
+ if (!unit_name_is_valid(c, false))
return -EINVAL;
- if (!unit_name_is_template(c))
- s = strdup(c);
- else {
- if (*e != '/')
- return -EINVAL;
+ s = strdup(c);
+ if (!s)
+ return -ENOMEM;
- e += strspn(e, "/");
+ *unit = s;
+ return 0;
+}
- p = strchrnul(e, '/');
- k = strndupa(e, p - e);
- k = cg_unescape(k);
+static const char *skip_slices(const char *p) {
+ /* Skips over all slice assignments */
- if (!unit_name_is_valid(k, false))
- return -EINVAL;
+ for (;;) {
+ size_t n;
- s = strdup(k);
- }
+ p += strspn(p, "/");
- if (!s)
- return -ENOMEM;
+ n = strcspn(p, "/");
+ if (n <= 6 || memcmp(p + n - 6, ".slice", 6) != 0)
+ return p;
- *unit = s;
- return 0;
+ p += n;
+ }
}
int cg_path_get_unit(const char *path, char **unit) {
@@ -1291,9 +1273,7 @@ int cg_path_get_unit(const char *path, char **unit) {
assert(path);
assert(unit);
- e = path_startswith(path, "/system/");
- if (!e)
- return -ENOENT;
+ e = skip_slices(path);
return cg_path_decode_unit(e, unit);
}
@@ -1311,15 +1291,21 @@ int cg_pid_get_unit(pid_t pid, char **unit) {
return cg_path_get_unit(cgroup, unit);
}
-_pure_ static const char *skip_label(const char *e) {
- assert(e);
+static const char *skip_session(const char *p) {
+ size_t n;
- e = strchr(e, '/');
- if (!e)
+ assert(p);
+
+ p += strspn(p, "/");
+
+ n = strcspn(p, "/");
+ if (n <= 12 || memcmp(p, "session-", 8) != 0 || memcmp(p + n - 6, ".scope", 6) != 0)
return NULL;
- e += strspn(e, "/");
- return e;
+ p += n;
+ p += strspn(p, "/");
+
+ return p;
}
int cg_path_get_user_unit(const char *path, char **unit) {
@@ -1332,24 +1318,16 @@ int cg_path_get_user_unit(const char *path, char **unit) {
* cgroups might have arbitrary child cgroups and we shouldn't get
* confused by those */
- e = path_startswith(path, "/user/");
- if (!e)
- return -ENOENT;
-
- /* Skip the user name */
- e = skip_label(e);
- if (!e)
- return -ENOENT;
+ /* Skip slices, if there are any */
+ e = skip_slices(path);
- /* Skip the session ID */
- e = skip_label(e);
+ /* Skip the session scope, require that there is one */
+ e = skip_session(e);
if (!e)
return -ENOENT;
- /* Skip the systemd cgroup */
- e = skip_label(e);
- if (!e)
- return -ENOENT;
+ /* And skip more slices */
+ e = skip_slices(e);
return cg_path_decode_unit(e, unit);
}
@@ -1368,23 +1346,34 @@ int cg_pid_get_user_unit(pid_t pid, char **unit) {
}
int cg_path_get_machine_name(const char *path, char **machine) {
- const char *e, *n;
+ const char *e, *n, *x;
char *s, *r;
+ size_t l;
assert(path);
assert(machine);
- e = path_startswith(path, "/machine/");
- if (!e)
- return -ENOENT;
+ /* Skip slices, if there are any */
+ e = skip_slices(path);
n = strchrnul(e, '/');
if (e == n)
return -ENOENT;
s = strndupa(e, n - e);
+ s = cg_unescape(s);
+
+ x = startswith(s, "machine-");
+ if (!x)
+ return -ENOENT;
+ if (!endswith(x, ".scope"))
+ return -ENOENT;
+
+ l = strlen(x);
+ if (l <= 6)
+ return -ENOENT;
- r = strdup(cg_unescape(s));
+ r = strndup(x, l - 6);
if (!r)
return -ENOMEM;
@@ -1406,32 +1395,38 @@ int cg_pid_get_machine_name(pid_t pid, char **machine) {
}
int cg_path_get_session(const char *path, char **session) {
- const char *e, *n;
- char *s;
+ const char *e, *n, *x;
+ char *s, *r;
+ size_t l;
assert(path);
assert(session);
- e = path_startswith(path, "/user/");
- if (!e)
- return -ENOENT;
+ /* Skip slices, if there are any */
+ e = skip_slices(path);
- /* Skip the user name */
- e = skip_label(e);
- if (!e)
+ n = strchrnul(e, '/');
+ if (e == n)
return -ENOENT;
- n = strchrnul(e, '/');
- if (n - e < 8)
+ s = strndupa(e, n - e);
+ s = cg_unescape(s);
+
+ x = startswith(s, "session-");
+ if (!x)
return -ENOENT;
- if (memcmp(n - 8, ".session", 8) != 0)
+ if (!endswith(x, ".scope"))
return -ENOENT;
- s = strndup(e, n - e - 8);
- if (!s)
+ l = strlen(x);
+ if (l <= 6)
+ return -ENOENT;
+
+ r = strndup(x, l - 6);
+ if (!r)
return -ENOMEM;
- *session = s;
+ *session = r;
return 0;
}
@@ -1449,23 +1444,25 @@ int cg_pid_get_session(pid_t pid, char **session) {
}
int cg_path_get_owner_uid(const char *path, uid_t *uid) {
- const char *e, *n;
+ _cleanup_free_ char *slice = NULL;
+ const char *e;
char *s;
+ int r;
assert(path);
assert(uid);
- e = path_startswith(path, "/user/");
- if (!e)
- return -ENOENT;
+ r = cg_path_get_slice(path, &slice);
+ if (r < 0)
+ return r;
- n = strchrnul(e, '/');
- if (n - e < 5)
+ e = startswith(slice, "user-");
+ if (!e)
return -ENOENT;
- if (memcmp(n - 5, ".user", 5) != 0)
+ if (!endswith(slice, ".slice"))
return -ENOENT;
- s = strndupa(e, n - e - 5);
+ s = strndupa(e, strlen(e) - 6);
if (!s)
return -ENOMEM;
@@ -1485,6 +1482,53 @@ int cg_pid_get_owner_uid(pid_t pid, uid_t *uid) {
return cg_path_get_owner_uid(cgroup, uid);
}
+int cg_path_get_slice(const char *p, char **slice) {
+ const char *e = NULL;
+ size_t m = 0;
+
+ assert(p);
+ assert(slice);
+
+ for (;;) {
+ size_t n;
+
+ p += strspn(p, "/");
+
+ n = strcspn(p, "/");
+ if (n <= 6 || memcmp(p + n - 6, ".slice", 6) != 0) {
+ char *s;
+
+ if (!e)
+ return -ENOENT;
+
+ s = strndup(e, m);
+ if (!s)
+ return -ENOMEM;
+
+ *slice = s;
+ return 0;
+ }
+
+ e = p;
+ m = n;
+
+ p += n;
+ }
+}
+
+int cg_pid_get_slice(pid_t pid, char **slice) {
+ _cleanup_free_ char *cgroup = NULL;
+ int r;
+
+ assert(slice);
+
+ r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
+ if (r < 0)
+ return r;
+
+ return cg_path_get_slice(cgroup, slice);
+}
+
int cg_controller_from_attr(const char *attr, char **controller) {
const char *dot;
char *c;
@@ -1572,9 +1616,7 @@ char *cg_unescape(const char *p) {
}
#define CONTROLLER_VALID \
- "0123456789" \
- "abcdefghijklmnopqrstuvwxyz" \
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
+ DIGITS LETTERS \
"_"
bool cg_controller_is_valid(const char *p, bool allow_named) {
@@ -1601,3 +1643,188 @@ bool cg_controller_is_valid(const char *p, bool allow_named) {
return true;
}
+
+int cg_slice_to_path(const char *unit, char **ret) {
+ _cleanup_free_ char *p = NULL, *s = NULL, *e = NULL;
+ const char *dash;
+
+ assert(unit);
+ assert(ret);
+
+ if (!unit_name_is_valid(unit, false))
+ return -EINVAL;
+
+ if (!endswith(unit, ".slice"))
+ return -EINVAL;
+
+ p = unit_name_to_prefix(unit);
+ if (!p)
+ return -ENOMEM;
+
+ dash = strchr(p, '-');
+ while (dash) {
+ _cleanup_free_ char *escaped = NULL;
+ char n[dash - p + sizeof(".slice")];
+
+ strcpy(stpncpy(n, p, dash - p), ".slice");
+
+ if (!unit_name_is_valid(n, false))
+ return -EINVAL;
+
+ escaped = cg_escape(n);
+ if (!escaped)
+ return -ENOMEM;
+
+ if (!strextend(&s, escaped, "/", NULL))
+ return -ENOMEM;
+
+ dash = strchr(dash+1, '-');
+ }
+
+ e = cg_escape(unit);
+ if (!e)
+ return -ENOMEM;
+
+ if (!strextend(&s, e, NULL))
+ return -ENOMEM;
+
+ *ret = s;
+ s = NULL;
+
+ return 0;
+}
+
+int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value) {
+ _cleanup_free_ char *p = NULL;
+ int r;
+
+ r = cg_get_path(controller, path, attribute, &p);
+ if (r < 0)
+ return r;
+
+ return write_string_file(p, value);
+}
+
+static const char mask_names[] =
+ "cpu\0"
+ "cpuacct\0"
+ "blkio\0"
+ "memory\0"
+ "devices\0";
+
+int cg_create_everywhere(CGroupControllerMask supported, CGroupControllerMask mask, const char *path) {
+ CGroupControllerMask bit = 1;
+ const char *n;
+ 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 */
+
+ /* First create the cgroup in our own hierarchy. */
+ r = cg_create(SYSTEMD_CGROUP_CONTROLLER, path);
+ if (r < 0)
+ return r;
+
+ /* Then, do the same in the other hierarchies */
+ NULSTR_FOREACH(n, mask_names) {
+ if (mask & bit)
+ cg_create(n, path);
+ else if (supported & bit)
+ cg_trim(n, path, true);
+
+ bit <<= 1;
+ }
+
+ return 0;
+}
+
+int cg_attach_everywhere(CGroupControllerMask supported, const char *path, pid_t pid) {
+ CGroupControllerMask bit = 1;
+ const char *n;
+ int r;
+
+ r = cg_attach(SYSTEMD_CGROUP_CONTROLLER, path, pid);
+ if (r < 0)
+ return r;
+
+ NULSTR_FOREACH(n, mask_names) {
+ if (supported & bit)
+ cg_attach_fallback(n, path, pid);
+
+ bit <<= 1;
+ }
+
+ return 0;
+}
+
+int cg_attach_many_everywhere(CGroupControllerMask supported, const char *path, Set* pids) {
+ Iterator i;
+ void *pidp;
+ int r = 0;
+
+ SET_FOREACH(pidp, pids, i) {
+ pid_t pid = PTR_TO_LONG(pidp);
+ int q;
+
+ q = cg_attach_everywhere(supported, path, pid);
+ if (q < 0)
+ r = q;
+ }
+
+ return r;
+}
+
+int cg_migrate_everywhere(CGroupControllerMask supported, const char *from, const char *to) {
+ CGroupControllerMask bit = 1;
+ const char *n;
+ int r;
+
+ if (!path_equal(from, to)) {
+ r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, false, true);
+ if (r < 0)
+ return r;
+ }
+
+ NULSTR_FOREACH(n, mask_names) {
+ if (supported & bit)
+ cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, n, to, false, false);
+
+ bit <<= 1;
+ }
+
+ return 0;
+}
+
+int cg_trim_everywhere(CGroupControllerMask supported, const char *path, bool delete_root) {
+ CGroupControllerMask bit = 1;
+ const char *n;
+ int r;
+
+ r = cg_trim(SYSTEMD_CGROUP_CONTROLLER, path, delete_root);
+ if (r < 0)
+ return r;
+
+ NULSTR_FOREACH(n, mask_names) {
+ if (supported & bit)
+ cg_trim(n, path, delete_root);
+
+ bit <<= 1;
+ }
+
+ return 0;
+}
+
+CGroupControllerMask cg_mask_supported(void) {
+ CGroupControllerMask bit = 1, mask = 0;
+ const char *n;
+
+ NULSTR_FOREACH(n, mask_names) {
+ if (check_hierarchy(n) >= 0)
+ mask |= bit;
+
+ bit <<= 1;
+ }
+
+ return mask;
+}
diff --git a/src/shared/cgroup-util.h b/src/shared/cgroup-util.h
index 25dd277ba5..0963450b08 100644
--- a/src/shared/cgroup-util.h
+++ b/src/shared/cgroup-util.h
@@ -28,6 +28,15 @@
#include "set.h"
#include "def.h"
+/* A bit mask of well known cgroup controllers */
+typedef enum CGroupControllerMask {
+ CGROUP_CPU = 1,
+ CGROUP_CPUACCT = 2,
+ CGROUP_BLKIO = 4,
+ CGROUP_MEMORY = 8,
+ CGROUP_DEVICE = 16
+} CGroupControllerMask;
+
/*
* General rules:
*
@@ -44,7 +53,6 @@
*/
int cg_enumerate_processes(const char *controller, const char *path, FILE **_f);
-int cg_enumerate_tasks(const char *controller, const char *path, FILE **_f);
int cg_read_pid(FILE *f, pid_t *_pid);
int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d);
@@ -56,6 +64,7 @@ int cg_kill_recursive_and_wait(const char *controller, const char *path, bool re
int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self);
int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool remove);
+int cg_migrate_recursive_fallback(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool rem);
int cg_split_spec(const char *spec, char **controller, char **path);
int cg_join_spec(const char *controller, const char *path, char **spec);
@@ -68,32 +77,34 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path);
int cg_trim(const char *controller, const char *path, bool delete_root);
-int cg_rmdir(const char *controller, const char *path, bool honour_sticky);
+int cg_rmdir(const char *controller, const char *path);
int cg_delete(const char *controller, const char *path);
-int cg_create(const char *controller, const char *path, const char *suffix);
+int cg_create(const char *controller, const char *path);
int cg_attach(const char *controller, const char *path, pid_t pid);
+int cg_attach_fallback(const char *controller, const char *path, pid_t pid);
int cg_create_and_attach(const char *controller, const char *path, pid_t pid);
+int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value);
+
int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid);
-int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid, int sticky);
+int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid);
int cg_install_release_agent(const char *controller, const char *agent);
+int cg_uninstall_release_agent(const char *controller);
int cg_is_empty(const char *controller, const char *path, bool ignore_self);
int cg_is_empty_by_spec(const char *spec, bool ignore_self);
int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self);
int cg_get_root_path(char **path);
-int cg_get_system_path(char **path);
-int cg_get_user_path(char **path);
-int cg_get_machine_path(const char *machine, char **path);
int cg_path_get_session(const char *path, char **session);
int cg_path_get_owner_uid(const char *path, uid_t *uid);
int cg_path_get_unit(const char *path, char **unit);
int cg_path_get_user_unit(const char *path, char **unit);
int cg_path_get_machine_name(const char *path, char **machine);
+int cg_path_get_slice(const char *path, char **slice);
int cg_pid_get_path_shifted(pid_t pid, char **root, char **cgroup);
@@ -102,6 +113,7 @@ int cg_pid_get_owner_uid(pid_t pid, uid_t *uid);
int cg_pid_get_unit(pid_t pid, char **unit);
int cg_pid_get_user_unit(pid_t pid, char **unit);
int cg_pid_get_machine_name(pid_t pid, char **machine);
+int cg_pid_get_slice(pid_t pid, char **slice);
int cg_path_decode_unit(const char *cgroup, char **unit);
@@ -113,3 +125,13 @@ char *cg_escape(const char *p);
char *cg_unescape(const char *p) _pure_;
bool cg_controller_is_valid(const char *p, bool allow_named);
+
+int cg_slice_to_path(const char *unit, char **ret);
+
+int cg_create_everywhere(CGroupControllerMask supported, CGroupControllerMask mask, const char *path);
+int cg_attach_everywhere(CGroupControllerMask supported, const char *path, pid_t pid);
+int cg_attach_many_everywhere(CGroupControllerMask supported, const char *path, Set* pids);
+int cg_migrate_everywhere(CGroupControllerMask supported, const char *from, const char *to);
+int cg_trim_everywhere(CGroupControllerMask supported, const char *path, bool delete_root);
+
+CGroupControllerMask cg_mask_supported(void);
diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c
index 2303d9a50b..6085d33391 100644
--- a/src/shared/conf-parser.c
+++ b/src/shared/conf-parser.c
@@ -599,6 +599,7 @@ int config_parse_path(const char *unit,
char **s = data;
char *n;
+ int offset;
assert(filename);
assert(lvalue);
@@ -611,7 +612,9 @@ int config_parse_path(const char *unit,
return 0;
}
- if (!path_is_absolute(rvalue)) {
+ offset = rvalue[0] == '-' && (streq(lvalue, "InaccessibleDirectories") ||
+ streq(lvalue, "ReadOnlyDirectories"));
+ if (!path_is_absolute(rvalue + offset)) {
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Not an absolute path, ignoring: %s", rvalue);
return 0;
@@ -713,6 +716,7 @@ int config_parse_path_strv(const char *unit,
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
_cleanup_free_ char *n;
+ int offset;
n = strndup(w, l);
if (!n)
@@ -724,7 +728,9 @@ int config_parse_path_strv(const char *unit,
continue;
}
- if (!path_is_absolute(n)) {
+ offset = n[0] == '-' && (streq(lvalue, "InaccessibleDirectories") ||
+ streq(lvalue, "ReadOnlyDirectories"));
+ if (!path_is_absolute(n + offset)) {
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Not an absolute path, ignoring: %s", rvalue);
continue;
diff --git a/src/shared/dbus-common.c b/src/shared/dbus-common.c
index b8c15cb9fc..c727cae7cd 100644
--- a/src/shared/dbus-common.c
+++ b/src/shared/dbus-common.c
@@ -178,9 +178,9 @@ int bus_connect_system_ssh(const char *user, const char *host, DBusConnection **
assert(user || host);
if (user && host)
- asprintf(&p, "unixexec:path=ssh,argv1=-xT,argv2=%s@%s,argv3=systemd-stdio-bridge", user, host);
+ asprintf(&p, "unixexec:path=ssh,argv1=-xT,argv2=%s%%40%s,argv3=systemd-stdio-bridge", user, host);
else if (user)
- asprintf(&p, "unixexec:path=ssh,argv1=-xT,argv2=%s@localhost,argv3=systemd-stdio-bridge", user);
+ asprintf(&p, "unixexec:path=ssh,argv1=-xT,argv2=%s%%40localhost,argv3=systemd-stdio-bridge", user);
else if (host)
asprintf(&p, "unixexec:path=ssh,argv1=-xT,argv2=%s,argv3=systemd-stdio-bridge", host);
@@ -1383,6 +1383,8 @@ int bus_method_call_with_reply(
r = -EACCES;
else if (dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY))
r = -ETIMEDOUT;
+ else if (dbus_error_has_name(&error, DBUS_ERROR_DISCONNECTED))
+ r = -ECONNRESET;
else
r = -EIO;
goto finish;
diff --git a/src/shared/def.h b/src/shared/def.h
index 5ba170f965..edd0bcf7a4 100644
--- a/src/shared/def.h
+++ b/src/shared/def.h
@@ -32,4 +32,9 @@
#define SYSTEMD_CGROUP_CONTROLLER "name=systemd"
#define SIGNALS_CRASH_HANDLER SIGSEGV,SIGILL,SIGFPE,SIGBUS,SIGQUIT,SIGABRT
-#define SIGNALS_IGNORE SIGKILL,SIGPIPE
+#define SIGNALS_IGNORE SIGPIPE
+
+#define DIGITS "0123456789"
+#define LOWERCASE_LETTERS "abcdefghijklmnopqrstuvwxyz"
+#define UPPERCASE_LETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+#define LETTERS LOWERCASE_LETTERS UPPERCASE_LETTERS
diff --git a/src/shared/dev-setup.c b/src/shared/dev-setup.c
index b0ac02d461..50a187fda9 100644
--- a/src/shared/dev-setup.c
+++ b/src/shared/dev-setup.c
@@ -54,13 +54,19 @@ void dev_setup(const char *prefix) {
const char *j, *k;
static const char symlinks[] =
- "/proc/kcore\0" "/dev/core\0"
+ "-/proc/kcore\0" "/dev/core\0"
"/proc/self/fd\0" "/dev/fd\0"
"/proc/self/fd/0\0" "/dev/stdin\0"
"/proc/self/fd/1\0" "/dev/stdout\0"
"/proc/self/fd/2\0" "/dev/stderr\0";
NULSTR_FOREACH_PAIR(j, k, symlinks) {
+ if (j[0] == '-') {
+ j++;
+
+ if (access(j, F_OK))
+ continue;
+ }
if (prefix) {
char *linkname;
diff --git a/src/shared/device-nodes.c b/src/shared/device-nodes.c
new file mode 100644
index 0000000000..9837375099
--- /dev/null
+++ b/src/shared/device-nodes.c
@@ -0,0 +1,74 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2008-2011 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 <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "device-nodes.h"
+#include "utf8.h"
+
+int whitelisted_char_for_devnode(char c, const char *white) {
+ if ((c >= '0' && c <= '9') ||
+ (c >= 'A' && c <= 'Z') ||
+ (c >= 'a' && c <= 'z') ||
+ strchr("#+-.:=@_", c) != NULL ||
+ (white != NULL && strchr(white, c) != NULL))
+ return 1;
+ return 0;
+}
+
+int encode_devnode_name(const char *str, char *str_enc, size_t len) {
+ size_t i, j;
+
+ if (str == NULL || str_enc == NULL)
+ return -1;
+
+ for (i = 0, j = 0; str[i] != '\0'; i++) {
+ int seqlen;
+
+ seqlen = utf8_encoded_valid_unichar(&str[i]);
+ if (seqlen > 1) {
+ if (len-j < (size_t)seqlen)
+ goto err;
+ memcpy(&str_enc[j], &str[i], seqlen);
+ j += seqlen;
+ i += (seqlen-1);
+ } else if (str[i] == '\\' || !whitelisted_char_for_devnode(str[i], NULL)) {
+ if (len-j < 4)
+ goto err;
+ sprintf(&str_enc[j], "\\x%02x", (unsigned char) str[i]);
+ j += 4;
+ } else {
+ if (len-j < 1)
+ goto err;
+ str_enc[j] = str[i];
+ j++;
+ }
+ }
+ if (len-j < 1)
+ goto err;
+ str_enc[j] = '\0';
+ return 0;
+err:
+ return -1;
+}
diff --git a/src/shared/device-nodes.h b/src/shared/device-nodes.h
new file mode 100644
index 0000000000..04ba4897e5
--- /dev/null
+++ b/src/shared/device-nodes.h
@@ -0,0 +1,25 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2012 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+int encode_devnode_name(const char *str, char *str_enc, size_t len);
+int whitelisted_char_for_devnode(char c, const char *additional);
diff --git a/src/shared/efivars.c b/src/shared/efivars.c
index 8d004bad33..1d5b6f9e72 100644
--- a/src/shared/efivars.c
+++ b/src/shared/efivars.c
@@ -24,6 +24,7 @@
#include <fcntl.h>
#include <ctype.h>
+#include "acpi-fpdt.h"
#include "util.h"
#include "utf8.h"
#include "efivars.h"
@@ -413,7 +414,7 @@ static int read_usec(sd_id128_t vendor, const char *name, usec_t *u) {
return 0;
}
-static int get_boot_usec(usec_t *firmware, usec_t *loader) {
+int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader) {
uint64_t x, y;
int r;
@@ -440,43 +441,7 @@ static int get_boot_usec(usec_t *firmware, usec_t *loader) {
return 0;
}
-int efi_get_boot_timestamps(const dual_timestamp *n, dual_timestamp *firmware, dual_timestamp *loader) {
- usec_t x, y, a;
- int r;
- dual_timestamp _n;
-
- assert(firmware);
- assert(loader);
-
- if (!n) {
- dual_timestamp_get(&_n);
- n = &_n;
- }
-
- r = get_boot_usec(&x, &y);
- if (r < 0)
- return r;
-
- /* Let's convert this to timestamps where the firmware
- * began/loader began working. To make this more confusing:
- * since usec_t is unsigned and the kernel's monotonic clock
- * begins at kernel initialization we'll actually initialize
- * the monotonic timestamps here as negative of the actual
- * value. */
-
- firmware->monotonic = y;
- loader->monotonic = y - x;
-
- a = n->monotonic + firmware->monotonic;
- firmware->realtime = n->realtime > a ? n->realtime - a : 0;
-
- a = n->monotonic + loader->monotonic;
- loader->realtime = n->realtime > a ? n->realtime - a : 0;
-
- return 0;
-}
-
-int efi_get_loader_device_part_uuid(sd_id128_t *u) {
+int efi_loader_get_device_part_uuid(sd_id128_t *u) {
_cleanup_free_ char *p = NULL;
int r, parsed[16];
unsigned i;
diff --git a/src/shared/efivars.h b/src/shared/efivars.h
index 2b88c6075c..7921bedc9f 100644
--- a/src/shared/efivars.h
+++ b/src/shared/efivars.h
@@ -42,6 +42,5 @@ int efi_get_boot_option(uint16_t nr, char **title, sd_id128_t *partuuid, char **
int efi_get_boot_order(uint16_t **order);
int efi_get_boot_options(uint16_t **options);
-int efi_get_boot_timestamps(const dual_timestamp *n, dual_timestamp *firmware, dual_timestamp *loader);
-
-int efi_get_loader_device_part_uuid(sd_id128_t *u);
+int efi_loader_get_device_part_uuid(sd_id128_t *u);
+int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader);
diff --git a/src/shared/env-util.c b/src/shared/env-util.c
index 6a52fb960d..5e29629efd 100644
--- a/src/shared/env-util.c
+++ b/src/shared/env-util.c
@@ -27,11 +27,10 @@
#include "utf8.h"
#include "util.h"
#include "env-util.h"
+#include "def.h"
#define VALID_CHARS_ENV_NAME \
- "0123456789" \
- "abcdefghijklmnopqrstuvwxyz" \
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
+ DIGITS LETTERS \
"_"
#ifndef ARG_MAX
diff --git a/src/shared/fileio.c b/src/shared/fileio.c
index ad068bf30d..603a1c7b38 100644
--- a/src/shared/fileio.c
+++ b/src/shared/fileio.c
@@ -23,7 +23,8 @@
#include "fileio.h"
#include "util.h"
#include "strv.h"
-
+#include "utf8.h"
+#include "ctype.h"
int write_string_to_file(FILE *f, const char *line) {
errno = 0;
@@ -178,13 +179,15 @@ int read_full_file(const char *fn, char **contents, size_t *size) {
static int parse_env_file_internal(
const char *fname,
const char *newline,
- int (*push) (const char *key, char *value, void *userdata),
+ int (*push) (const char *filename, unsigned line,
+ const char *key, char *value, void *userdata),
void *userdata) {
_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;
+ unsigned line = 1;
enum {
PRE_KEY,
@@ -231,6 +234,7 @@ static int parse_env_file_internal(
case KEY:
if (strchr(newline, c)) {
state = PRE_KEY;
+ line ++;
n_key = 0;
} else if (c == '=') {
state = PRE_VALUE;
@@ -254,6 +258,7 @@ static int parse_env_file_internal(
case PRE_VALUE:
if (strchr(newline, c)) {
state = PRE_KEY;
+ line ++;
key[n_key] = 0;
if (value)
@@ -263,7 +268,7 @@ static int parse_env_file_internal(
if (last_key_whitespace != (size_t) -1)
key[last_key_whitespace] = 0;
- r = push(key, value, userdata);
+ r = push(fname, line, key, value, userdata);
if (r < 0)
goto fail;
@@ -293,6 +298,7 @@ static int parse_env_file_internal(
case VALUE:
if (strchr(newline, c)) {
state = PRE_KEY;
+ line ++;
key[n_key] = 0;
@@ -307,7 +313,7 @@ static int parse_env_file_internal(
if (last_key_whitespace != (size_t) -1)
key[last_key_whitespace] = 0;
- r = push(key, value, userdata);
+ r = push(fname, line, key, value, userdata);
if (r < 0)
goto fail;
@@ -409,8 +415,10 @@ static int parse_env_file_internal(
case COMMENT:
if (c == '\\')
state = COMMENT_ESCAPE;
- else if (strchr(newline, c))
+ else if (strchr(newline, c)) {
state = PRE_KEY;
+ line ++;
+ }
break;
case COMMENT_ESCAPE:
@@ -440,7 +448,7 @@ static int parse_env_file_internal(
if (last_key_whitespace != (size_t) -1)
key[last_key_whitespace] = 0;
- r = push(key, value, userdata);
+ r = push(fname, line, key, value, userdata);
if (r < 0)
goto fail;
}
@@ -452,27 +460,36 @@ fail:
return r;
}
-static int parse_env_file_push(const char *key, char *value, void *userdata) {
- const char *k;
- va_list* ap = (va_list*) userdata;
- va_list aq;
+static int parse_env_file_push(const char *filename, unsigned line,
+ const char *key, char *value, void *userdata) {
+ assert(utf8_is_valid(key));
+
+ if (value && !utf8_is_valid(value))
+ /* FIXME: filter UTF-8 */
+ log_error("%s:%u: invalid UTF-8 for key %s: '%s', ignoring.",
+ filename, line, key, value);
+ else {
+ const char *k;
+ va_list* ap = (va_list*) userdata;
+ va_list aq;
- va_copy(aq, *ap);
+ va_copy(aq, *ap);
- while ((k = va_arg(aq, const char *))) {
- char **v;
+ while ((k = va_arg(aq, const char *))) {
+ char **v;
- v = va_arg(aq, char **);
+ v = va_arg(aq, char **);
- if (streq(key, k)) {
- va_end(aq);
- free(*v);
- *v = value;
- return 1;
+ if (streq(key, k)) {
+ va_end(aq);
+ free(*v);
+ *v = value;
+ return 1;
+ }
}
- }
- va_end(aq);
+ va_end(aq);
+ }
free(value);
return 0;
@@ -495,19 +512,28 @@ int parse_env_file(
return r;
}
-static int load_env_file_push(const char *key, char *value, void *userdata) {
- char ***m = userdata;
- char *p;
- int r;
+static int load_env_file_push(const char *filename, unsigned line,
+ const char *key, char *value, void *userdata) {
+ assert(utf8_is_valid(key));
- p = strjoin(key, "=", strempty(value), NULL);
- if (!p)
- return -ENOMEM;
+ if (value && !utf8_is_valid(value))
+ /* FIXME: filter UTF-8 */
+ log_error("%s:%u: invalid UTF-8 for key %s: '%s', ignoring.",
+ filename, line, key, value);
+ else {
+ char ***m = userdata;
+ char *p;
+ int r;
- r = strv_push(m, p);
- if (r < 0) {
- free(p);
- return r;
+ p = strjoin(key, "=", strempty(value), NULL);
+ if (!p)
+ return -ENOMEM;
+
+ r = strv_push(m, p);
+ if (r < 0) {
+ free(p);
+ return r;
+ }
}
free(value);
@@ -594,3 +620,79 @@ int write_env_file(const char *fname, char **l) {
return r;
}
+
+int executable_is_script(const char *path, char **interpreter) {
+ int r;
+ char _cleanup_free_ *line = NULL;
+ int len;
+ char *ans;
+
+ assert(path);
+
+ r = read_one_line_file(path, &line);
+ if (r < 0)
+ return r;
+
+ if (!startswith(line, "#!"))
+ return 0;
+
+ ans = strstrip(line + 2);
+ len = strcspn(ans, " \t");
+
+ if (len == 0)
+ return 0;
+
+ ans = strndup(ans, len);
+ if (!ans)
+ return -ENOMEM;
+
+ *interpreter = ans;
+ return 1;
+}
+
+/**
+ * Retrieve one field from a file like /proc/self/status. pattern
+ * should start with '\n' and end with a ':'. Whitespace and zeros
+ * after the ':' will be skipped. field must be freed afterwards.
+ */
+int get_status_field(const char *filename, const char *pattern, char **field) {
+ _cleanup_free_ char *status = NULL;
+ char *t;
+ size_t len;
+ int r;
+
+ assert(filename);
+ assert(field);
+
+ r = read_full_file(filename, &status, NULL);
+ if (r < 0)
+ return r;
+
+ t = strstr(status, pattern);
+ if (!t)
+ return -ENOENT;
+
+ t += strlen(pattern);
+ if (*t) {
+ t += strspn(t, " \t");
+
+ /* Also skip zeros, because when this is used for
+ * capabilities, we don't want the zeros. This way the
+ * same capability set always maps to the same string,
+ * irrespective of the total capability set size. For
+ * other numbers it shouldn't matter. */
+ t += strspn(t, "0");
+ /* Back off one char if there's nothing but whitespace
+ and zeros */
+ if (!*t || isspace(*t))
+ t --;
+ }
+
+ len = strcspn(t, WHITESPACE);
+
+ *field = strndup(t, len);
+ if (!*field)
+ return -ENOMEM;
+
+ return 0;
+}
diff --git a/src/shared/fileio.h b/src/shared/fileio.h
index 0ca6878ea4..59e41502b1 100644
--- a/src/shared/fileio.h
+++ b/src/shared/fileio.h
@@ -35,3 +35,7 @@ int read_full_file(const char *fn, char **contents, size_t *size);
int parse_env_file(const char *fname, const char *separator, ...) _sentinel_;
int load_env_file(const char *fname, const char *separator, char ***l);
int write_env_file(const char *fname, char **l);
+
+int executable_is_script(const char *path, char **interpreter);
+
+int get_status_field(const char *filename, const char *pattern, char **field);
diff --git a/src/shared/hashmap.c b/src/shared/hashmap.c
index 9f7db34397..f06fce6ef3 100644
--- a/src/shared/hashmap.c
+++ b/src/shared/hashmap.c
@@ -24,11 +24,15 @@
#include <string.h>
#include <errno.h>
+#ifdef HAVE_SYS_AUXV_H
+#include <sys/auxv.h>
+#endif
+
#include "util.h"
#include "hashmap.h"
#include "macro.h"
-#define NBUCKETS 127
+#define INITIAL_N_BUCKETS 31
struct hashmap_entry {
const void *key;
@@ -42,13 +46,14 @@ struct Hashmap {
compare_func_t compare_func;
struct hashmap_entry *iterate_list_head, *iterate_list_tail;
- unsigned n_entries;
+ struct hashmap_entry ** buckets;
+ unsigned n_buckets, n_entries;
+
+ unsigned random_xor;
bool from_pool;
};
-#define BY_HASH(h) ((struct hashmap_entry**) ((uint8_t*) (h) + ALIGN(sizeof(Hashmap))))
-
struct pool {
struct pool *next;
unsigned n_tiles;
@@ -64,6 +69,11 @@ static void *first_entry_tile = NULL;
static void* allocate_tile(struct pool **first_pool, void **first_tile, size_t tile_size) {
unsigned i;
+ /* When a tile is released we add it to the list and simply
+ * place the next pointer at its offset 0. */
+
+ assert(tile_size >= sizeof(void*));
+
if (*first_tile) {
void *r;
@@ -166,14 +176,19 @@ int uint64_compare_func(const void *_a, const void *_b) {
return a < b ? -1 : (a > b ? 1 : 0);
}
+static unsigned bucket_hash(Hashmap *h, const void *p) {
+ return (h->hash_func(p) ^ h->random_xor) % h->n_buckets;
+}
+
Hashmap *hashmap_new(hash_func_t hash_func, compare_func_t compare_func) {
bool b;
Hashmap *h;
size_t size;
+ void *auxv;
b = is_main_thread();
- size = ALIGN(sizeof(Hashmap)) + NBUCKETS * sizeof(struct hashmap_entry*);
+ size = ALIGN(sizeof(Hashmap)) + INITIAL_N_BUCKETS * sizeof(struct hashmap_entry*);
if (b) {
h = allocate_tile(&first_hashmap_pool, &first_hashmap_tile, size);
@@ -191,23 +206,43 @@ Hashmap *hashmap_new(hash_func_t hash_func, compare_func_t compare_func) {
h->hash_func = hash_func ? hash_func : trivial_hash_func;
h->compare_func = compare_func ? compare_func : trivial_compare_func;
+ h->n_buckets = INITIAL_N_BUCKETS;
h->n_entries = 0;
h->iterate_list_head = h->iterate_list_tail = NULL;
+ h->buckets = (struct hashmap_entry**) ((uint8_t*) h + ALIGN(sizeof(Hashmap)));
+
h->from_pool = b;
+ /* Let's randomize our hash functions a bit so that they are
+ * harder to guess for clients. For this, start out by cheaply
+ * using some bits the kernel passed into the process using
+ * the auxiliary vector. If the hashmap grows later on we will
+ * rehash everything using a new random XOR mask from
+ * /dev/random. */
+#ifdef HAVE_SYS_AUXV_H
+ auxv = (void*) getauxval(AT_RANDOM);
+ h->random_xor = auxv ? *(unsigned*) auxv : random_u();
+#else
+ h->random_xor = random_u();
+#endif
+
return h;
}
int hashmap_ensure_allocated(Hashmap **h, hash_func_t hash_func, compare_func_t compare_func) {
+ Hashmap *q;
+
assert(h);
if (*h)
return 0;
- if (!(*h = hashmap_new(hash_func, compare_func)))
+ q = hashmap_new(hash_func, compare_func);
+ if (!q)
return -ENOMEM;
+ *h = q;
return 0;
}
@@ -216,11 +251,11 @@ static void link_entry(Hashmap *h, struct hashmap_entry *e, unsigned hash) {
assert(e);
/* Insert into hash table */
- e->bucket_next = BY_HASH(h)[hash];
+ e->bucket_next = h->buckets[hash];
e->bucket_previous = NULL;
- if (BY_HASH(h)[hash])
- BY_HASH(h)[hash]->bucket_previous = e;
- BY_HASH(h)[hash] = e;
+ if (h->buckets[hash])
+ h->buckets[hash]->bucket_previous = e;
+ h->buckets[hash] = e;
/* Insert into iteration list */
e->iterate_previous = h->iterate_list_tail;
@@ -260,7 +295,7 @@ static void unlink_entry(Hashmap *h, struct hashmap_entry *e, unsigned hash) {
if (e->bucket_previous)
e->bucket_previous->bucket_next = e->bucket_next;
else
- BY_HASH(h)[hash] = e->bucket_next;
+ h->buckets[hash] = e->bucket_next;
assert(h->n_entries >= 1);
h->n_entries--;
@@ -272,8 +307,7 @@ static void remove_entry(Hashmap *h, struct hashmap_entry *e) {
assert(h);
assert(e);
- hash = h->hash_func(e->key) % NBUCKETS;
-
+ hash = bucket_hash(h, e->key);
unlink_entry(h, e, hash);
if (h->from_pool)
@@ -291,6 +325,9 @@ void hashmap_free(Hashmap*h) {
hashmap_clear(h);
+ if (h->buckets != (struct hashmap_entry**) ((uint8_t*) h + ALIGN(sizeof(Hashmap))))
+ free(h->buckets);
+
if (h->from_pool)
deallocate_tile(&first_hashmap_tile, h);
else
@@ -353,36 +390,91 @@ void hashmap_clear_free_free(Hashmap *h) {
}
}
-
static struct hashmap_entry *hash_scan(Hashmap *h, unsigned hash, const void *key) {
struct hashmap_entry *e;
assert(h);
- assert(hash < NBUCKETS);
+ assert(hash < h->n_buckets);
- for (e = BY_HASH(h)[hash]; e; e = e->bucket_next)
+ for (e = h->buckets[hash]; e; e = e->bucket_next)
if (h->compare_func(e->key, key) == 0)
return e;
return NULL;
}
+static bool resize_buckets(Hashmap *h) {
+ struct hashmap_entry **n, *i;
+ unsigned m, nxor;
+
+ assert(h);
+
+ if (_likely_(h->n_entries*4 < h->n_buckets*3))
+ return false;
+
+ /* Increase by four */
+ m = (h->n_entries+1)*4-1;
+
+ /* If we hit OOM we simply risk packed hashmaps... */
+ n = new0(struct hashmap_entry*, m);
+ if (!n)
+ return false;
+
+ /* Let's use a different randomized xor value for the
+ * extension, so that people cannot guess what we are using
+ * here forever */
+ nxor = random_u();
+
+ for (i = h->iterate_list_head; i; i = i->iterate_next) {
+ unsigned hash, x;
+
+ hash = h->hash_func(i->key);
+
+ /* First, drop from old bucket table */
+ if (i->bucket_next)
+ i->bucket_next->bucket_previous = i->bucket_previous;
+
+ if (i->bucket_previous)
+ i->bucket_previous->bucket_next = i->bucket_next;
+ else
+ h->buckets[(hash ^ h->random_xor) % h->n_buckets] = i->bucket_next;
+
+ /* Then, add to new backet table */
+ x = (hash ^ nxor) % m;
+
+ i->bucket_next = n[x];
+ i->bucket_previous = NULL;
+ if (n[x])
+ n[x]->bucket_previous = i;
+ n[x] = i;
+ }
+
+ if (h->buckets != (struct hashmap_entry**) ((uint8_t*) h + ALIGN(sizeof(Hashmap))))
+ free(h->buckets);
+
+ h->buckets = n;
+ h->n_buckets = m;
+ h->random_xor = nxor;
+
+ return true;
+}
+
int hashmap_put(Hashmap *h, const void *key, void *value) {
struct hashmap_entry *e;
unsigned hash;
assert(h);
- hash = h->hash_func(key) % NBUCKETS;
-
+ hash = bucket_hash(h, key);
e = hash_scan(h, hash, key);
if (e) {
-
if (e->value == value)
return 0;
-
return -EEXIST;
}
+ if (resize_buckets(h))
+ hash = bucket_hash(h, key);
+
if (h->from_pool)
e = allocate_tile(&first_entry_pool, &first_entry_tile, sizeof(struct hashmap_entry));
else
@@ -405,7 +497,7 @@ int hashmap_replace(Hashmap *h, const void *key, void *value) {
assert(h);
- hash = h->hash_func(key) % NBUCKETS;
+ hash = bucket_hash(h, key);
e = hash_scan(h, hash, key);
if (e) {
e->key = key;
@@ -422,7 +514,7 @@ int hashmap_update(Hashmap *h, const void *key, void *value) {
assert(h);
- hash = h->hash_func(key) % NBUCKETS;
+ hash = bucket_hash(h, key);
e = hash_scan(h, hash, key);
if (!e)
return -ENOENT;
@@ -438,7 +530,7 @@ void* hashmap_get(Hashmap *h, const void *key) {
if (!h)
return NULL;
- hash = h->hash_func(key) % NBUCKETS;
+ hash = bucket_hash(h, key);
e = hash_scan(h, hash, key);
if (!e)
return NULL;
@@ -453,7 +545,7 @@ void* hashmap_get2(Hashmap *h, const void *key, void **key2) {
if (!h)
return NULL;
- hash = h->hash_func(key) % NBUCKETS;
+ hash = bucket_hash(h, key);
e = hash_scan(h, hash, key);
if (!e)
return NULL;
@@ -470,12 +562,8 @@ bool hashmap_contains(Hashmap *h, const void *key) {
if (!h)
return false;
- hash = h->hash_func(key) % NBUCKETS;
-
- if (!hash_scan(h, hash, key))
- return false;
-
- return true;
+ hash = bucket_hash(h, key);
+ return !!hash_scan(h, hash, key);
}
void* hashmap_remove(Hashmap *h, const void *key) {
@@ -486,9 +574,9 @@ void* hashmap_remove(Hashmap *h, const void *key) {
if (!h)
return NULL;
- hash = h->hash_func(key) % NBUCKETS;
-
- if (!(e = hash_scan(h, hash, key)))
+ hash = bucket_hash(h, key);
+ e = hash_scan(h, hash, key);
+ if (!e)
return NULL;
data = e->value;
@@ -504,11 +592,12 @@ int hashmap_remove_and_put(Hashmap *h, const void *old_key, const void *new_key,
if (!h)
return -ENOENT;
- old_hash = h->hash_func(old_key) % NBUCKETS;
- if (!(e = hash_scan(h, old_hash, old_key)))
+ old_hash = bucket_hash(h, old_key);
+ e = hash_scan(h, old_hash, old_key);
+ if (!e)
return -ENOENT;
- new_hash = h->hash_func(new_key) % NBUCKETS;
+ new_hash = bucket_hash(h, new_key);
if (hash_scan(h, new_hash, new_key))
return -EEXIST;
@@ -529,13 +618,14 @@ int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_
if (!h)
return -ENOENT;
- old_hash = h->hash_func(old_key) % NBUCKETS;
- if (!(e = hash_scan(h, old_hash, old_key)))
+ old_hash = bucket_hash(h, old_key);
+ e = hash_scan(h, old_hash, old_key);
+ if (!e)
return -ENOENT;
- new_hash = h->hash_func(new_key) % NBUCKETS;
-
- if ((k = hash_scan(h, new_hash, new_key)))
+ new_hash = bucket_hash(h, new_key);
+ k = hash_scan(h, new_hash, new_key);
+ if (k)
if (e != k)
remove_entry(h, k);
@@ -556,9 +646,10 @@ void* hashmap_remove_value(Hashmap *h, const void *key, void *value) {
if (!h)
return NULL;
- hash = h->hash_func(key) % NBUCKETS;
+ hash = bucket_hash(h, key);
- if (!(e = hash_scan(h, hash, key)))
+ e = hash_scan(h, hash, key);
+ if (!e)
return NULL;
if (e->value != value)
@@ -646,9 +737,10 @@ void *hashmap_iterate_skip(Hashmap *h, const void *key, Iterator *i) {
if (!h)
return NULL;
- hash = h->hash_func(key) % NBUCKETS;
+ hash = bucket_hash(h, key);
- if (!(e = hash_scan(h, hash, key)))
+ e = hash_scan(h, hash, key);
+ if (!e)
return NULL;
*i = (Iterator) e;
@@ -727,6 +819,14 @@ unsigned hashmap_size(Hashmap *h) {
return h->n_entries;
}
+unsigned hashmap_buckets(Hashmap *h) {
+
+ if (!h)
+ return 0;
+
+ return h->n_buckets;
+}
+
bool hashmap_isempty(Hashmap *h) {
if (!h)
@@ -746,9 +846,9 @@ int hashmap_merge(Hashmap *h, Hashmap *other) {
for (e = other->iterate_list_head; e; e = e->iterate_next) {
int r;
- if ((r = hashmap_put(h, e->key, e->value)) < 0)
- if (r != -EEXIST)
- return r;
+ r = hashmap_put(h, e->key, e->value);
+ if (r < 0 && r != -EEXIST)
+ return r;
}
return 0;
@@ -770,13 +870,11 @@ void hashmap_move(Hashmap *h, Hashmap *other) {
n = e->iterate_next;
- h_hash = h->hash_func(e->key) % NBUCKETS;
-
+ h_hash = bucket_hash(h, e->key);
if (hash_scan(h, h_hash, e->key))
continue;
- other_hash = other->hash_func(e->key) % NBUCKETS;
-
+ other_hash = bucket_hash(other, e->key);
unlink_entry(other, e, other_hash);
link_entry(h, e, h_hash);
}
@@ -791,12 +889,13 @@ int hashmap_move_one(Hashmap *h, Hashmap *other, const void *key) {
assert(h);
- h_hash = h->hash_func(key) % NBUCKETS;
+ h_hash = bucket_hash(h, key);
if (hash_scan(h, h_hash, key))
return -EEXIST;
- other_hash = other->hash_func(key) % NBUCKETS;
- if (!(e = hash_scan(other, other_hash, key)))
+ other_hash = bucket_hash(other, key);
+ e = hash_scan(other, other_hash, key);
+ if (!e)
return -ENOENT;
unlink_entry(other, e, other_hash);
@@ -810,7 +909,8 @@ Hashmap *hashmap_copy(Hashmap *h) {
assert(h);
- if (!(copy = hashmap_new(h->hash_func, h->compare_func)))
+ copy = hashmap_new(h->hash_func, h->compare_func);
+ if (!copy)
return NULL;
if (hashmap_merge(copy, h) < 0) {
@@ -849,7 +949,7 @@ void *hashmap_next(Hashmap *h, const void *key) {
if (!h)
return NULL;
- hash = h->hash_func(key) % NBUCKETS;
+ hash = bucket_hash(h, key);
e = hash_scan(h, hash, key);
if (!e)
return NULL;
diff --git a/src/shared/hashmap.h b/src/shared/hashmap.h
index 15b7e27585..3d4f6721bc 100644
--- a/src/shared/hashmap.h
+++ b/src/shared/hashmap.h
@@ -76,6 +76,7 @@ int hashmap_move_one(Hashmap *h, Hashmap *other, const void *key);
unsigned hashmap_size(Hashmap *h) _pure_;
bool hashmap_isempty(Hashmap *h) _pure_;
+unsigned hashmap_buckets(Hashmap *h) _pure_;
void *hashmap_iterate(Hashmap *h, Iterator *i, const void **key);
void *hashmap_iterate_backwards(Hashmap *h, Iterator *i, const void **key);
diff --git a/src/shared/hwclock.c b/src/shared/hwclock.c
index cc11faa6c3..17f12de51f 100644
--- a/src/shared/hwclock.c
+++ b/src/shared/hwclock.c
@@ -151,7 +151,7 @@ int hwclock_reset_timezone(void) {
/*
* The very first time we set the kernel's timezone, it will warp
* the clock. Do a dummy call here, so the time warping is sealed
- * and we set only the time zone with next call.
+ * and we set only the timezone with next call.
*/
if (settimeofday(tv_null, &tz) < 0)
return -errno;
diff --git a/src/shared/install-printf.c b/src/shared/install-printf.c
index c44459b4e0..1ee1243f4d 100644
--- a/src/shared/install-printf.c
+++ b/src/shared/install-printf.c
@@ -27,21 +27,35 @@
#include "util.h"
#include "install-printf.h"
-static char *specifier_prefix_and_instance(char specifier, void *data, void *userdata) {
+static int specifier_prefix_and_instance(char specifier, void *data, void *userdata, char **ret) {
InstallInfo *i = userdata;
+ char *n;
+
assert(i);
- return unit_name_to_prefix_and_instance(i->name);
+ n = unit_name_to_prefix_and_instance(i->name);
+ if (!n)
+ return -ENOMEM;
+
+ *ret = n;
+ return 0;
}
-static char *specifier_prefix(char specifier, void *data, void *userdata) {
+static int specifier_prefix(char specifier, void *data, void *userdata, char **ret) {
InstallInfo *i = userdata;
+ char *n;
+
assert(i);
- return unit_name_to_prefix(i->name);
+ n = unit_name_to_prefix(i->name);
+ if (!n)
+ return -ENOMEM;
+
+ *ret = n;
+ return 0;
}
-static char *specifier_instance(char specifier, void *data, void *userdata) {
+static int specifier_instance(char specifier, void *data, void *userdata, char **ret) {
InstallInfo *i = userdata;
char *instance;
int r;
@@ -50,14 +64,19 @@ static char *specifier_instance(char specifier, void *data, void *userdata) {
r = unit_name_to_instance(i->name, &instance);
if (r < 0)
- return NULL;
- if (instance != NULL)
- return instance;
- else
- return strdup("");
+ return r;
+
+ if (!instance) {
+ instance = strdup("");
+ if (!instance)
+ return -ENOMEM;
+ }
+
+ *ret = instance;
+ return 0;
}
-static char *specifier_user_name(char specifier, void *data, void *userdata) {
+static int specifier_user_name(char specifier, void *data, void *userdata, char **ret) {
InstallInfo *i = userdata;
const char *username;
_cleanup_free_ char *tmp = NULL;
@@ -82,18 +101,20 @@ static char *specifier_user_name(char specifier, void *data, void *userdata) {
r = get_user_creds(&username, &uid, NULL, NULL, NULL);
if (r < 0)
- return NULL;
+ return r;
if (asprintf(&printed, "%d", uid) < 0)
- return NULL;
+ return -ENOMEM;
break;
}}
- return printed;
+
+ *ret = printed;
+ return 0;
}
-char *install_full_printf(InstallInfo *i, const char *format) {
+int install_full_printf(InstallInfo *i, const char *format, char **ret) {
/* This is similar to unit_full_printf() but does not support
* anything path-related.
@@ -108,6 +129,7 @@ char *install_full_printf(InstallInfo *i, const char *format) {
* %m the machine ID of the running system
* %H the host name of the running system
* %b the boot ID of the running system
+ * %v `uname -r` of the running system
*/
const Specifier table[] = {
@@ -122,11 +144,13 @@ char *install_full_printf(InstallInfo *i, const char *format) {
{ 'm', specifier_machine_id, NULL },
{ 'H', specifier_host_name, NULL },
{ 'b', specifier_boot_id, NULL },
- { 0, NULL, NULL }
+ { 'v', specifier_kernel_release, NULL },
+ {}
};
assert(i);
assert(format);
+ assert(ret);
- return specifier_printf(format, table, i);
+ return specifier_printf(format, table, i, ret);
}
diff --git a/src/shared/install-printf.h b/src/shared/install-printf.h
index 46f5294d21..6ffa488b1b 100644
--- a/src/shared/install-printf.h
+++ b/src/shared/install-printf.h
@@ -22,4 +22,4 @@
#pragma once
#include "install.h"
-char *install_full_printf(InstallInfo *i, const char *format);
+int install_full_printf(InstallInfo *i, const char *format, char **ret);
diff --git a/src/shared/install.c b/src/shared/install.c
index edf4d2a9fe..9722ed4e1c 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -506,7 +506,7 @@ static int find_symlinks_in_scope(
UnitFileState *state) {
int r;
- _cleanup_free_ char *path = NULL;
+ _cleanup_free_ char *path2 = NULL;
bool same_name_link_runtime = false, same_name_link = false;
assert(scope >= 0);
@@ -514,6 +514,7 @@ static int find_symlinks_in_scope(
assert(name);
if (scope == UNIT_FILE_SYSTEM || scope == UNIT_FILE_GLOBAL) {
+ _cleanup_free_ char *path = NULL;
/* First look in runtime config path */
r = get_config_path(scope, true, root_dir, &path);
@@ -530,11 +531,11 @@ static int find_symlinks_in_scope(
}
/* Then look in the normal config path */
- r = get_config_path(scope, false, root_dir, &path);
+ r = get_config_path(scope, false, root_dir, &path2);
if (r < 0)
return r;
- r = find_symlinks(name, path, &same_name_link);
+ r = find_symlinks(name, path2, &same_name_link);
if (r < 0)
return r;
else if (r > 0) {
@@ -966,14 +967,15 @@ static int config_parse_user(const char *unit,
InstallInfo *i = data;
char* printed;
+ int r;
assert(filename);
assert(lvalue);
assert(rvalue);
- printed = install_full_printf(i, rvalue);
- if (!printed)
- return -ENOMEM;
+ r = install_full_printf(i, rvalue, &printed);
+ if (r < 0)
+ return r;
free(i->user);
i->user = printed;
@@ -1061,8 +1063,8 @@ static int unit_file_search(
info->path = path;
else {
if (r == -ENOENT && unit_name_is_instance(info->name)) {
- /* unit file doesn't exist, however instance enablement was request */
- /* we will check if it is possible to load template unit file */
+ /* Unit file doesn't exist, however instance enablement was requested.
+ * We will check if it is possible to load template unit file. */
char *template = NULL,
*template_path = NULL,
*template_dir = NULL;
@@ -1073,7 +1075,7 @@ static int unit_file_search(
return -ENOMEM;
}
- /* we will reuse path variable since we don't need it anymore */
+ /* We will reuse path variable since we don't need it anymore. */
template_dir = path;
*(strrchr(path, '/') + 1) = '\0';
@@ -1084,7 +1086,7 @@ static int unit_file_search(
return -ENOMEM;
}
- /* let's try to load template unit */
+ /* Let's try to load template unit. */
r = unit_file_load(c, info, template_path, allow_symlink);
if (r >= 0) {
info->path = strdup(template_path);
@@ -1199,9 +1201,9 @@ static int install_info_symlink_alias(
STRV_FOREACH(s, i->aliases) {
_cleanup_free_ char *alias_path = NULL, *dst = NULL;
- dst = install_full_printf(i, *s);
- if (!dst)
- return -ENOMEM;
+ q = install_full_printf(i, *s, &dst);
+ if (q < 0)
+ return q;
alias_path = path_make_absolute(dst, config_path);
if (!alias_path)
@@ -1231,9 +1233,9 @@ static int install_info_symlink_wants(
STRV_FOREACH(s, i->wanted_by) {
_cleanup_free_ char *path = NULL, *dst = NULL;
- dst = install_full_printf(i, *s);
- if (!dst)
- return -ENOMEM;
+ q = install_full_printf(i, *s, &dst);
+ if (q < 0)
+ return q;
if (!unit_name_is_valid(dst, true)) {
r = -EINVAL;
@@ -1268,9 +1270,9 @@ static int install_info_symlink_requires(
STRV_FOREACH(s, i->required_by) {
_cleanup_free_ char *path = NULL, *dst = NULL;
- dst = install_full_printf(i, *s);
- if (!dst)
- return -ENOMEM;
+ q = install_full_printf(i, *s, &dst);
+ if (q < 0)
+ return q;
if (!unit_name_is_valid(dst, true)) {
r = -EINVAL;
@@ -1413,7 +1415,9 @@ static int install_context_mark_for_removal(
assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
q = unit_file_search(c, i, paths, root_dir, false);
- if (q < 0) {
+ if (q == -ENOENT) {
+ /* do nothing */
+ } else if (q < 0) {
if (r >= 0)
r = q;
@@ -1422,16 +1426,30 @@ static int install_context_mark_for_removal(
r += q;
if (unit_name_is_instance(i->name)) {
- char *unit_file = NULL;
+ char *unit_file;
+
+ if (i->path) {
+ unit_file = path_get_file_name(i->path);
+
+ if (unit_name_is_instance(unit_file))
+ /* unit file named as instance exists, thus all symlinks
+ * pointing to it will be removed */
+ q = mark_symlink_for_removal(remove_symlinks_to, i->name);
+ else
+ /* does not exist, thus we will mark for removal symlinks
+ * to template unit file */
+ q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
+ } else {
+ /* If i->path is not set, it means that we didn't actually find
+ * the unit file. But we can still remove symlinks to the
+ * nonexistent template. */
+ unit_file = unit_name_template(i->name);
+ if (!unit_file)
+ return log_oom();
- unit_file = path_get_file_name(i->path);
-
- if (unit_name_is_instance(unit_file))
- /* unit file named as instance exists, thus all symlinks pointing to it, will be removed */
- q = mark_symlink_for_removal(remove_symlinks_to, i->name);
- else
- /* does not exist, thus we will mark for removal symlinks to template unit file */
q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
+ free(unit_file);
+ }
} else
q = mark_symlink_for_removal(remove_symlinks_to, i->name);
@@ -1531,43 +1549,101 @@ int unit_file_reenable(
bool force,
UnitFileChange **changes,
unsigned *n_changes) {
+ int r;
+
+ r = unit_file_disable(scope, runtime, root_dir, files,
+ changes, n_changes);
+ if (r < 0)
+ return r;
+
+ return unit_file_enable(scope, runtime, root_dir, files, force,
+ changes, n_changes);
+}
+
+int unit_file_set_default(
+ UnitFileScope scope,
+ const char *root_dir,
+ char *file,
+ UnitFileChange **changes,
+ unsigned *n_changes) {
_cleanup_lookup_paths_free_ LookupPaths paths = {};
_cleanup_install_context_done_ InstallContext c = {};
- char **i;
_cleanup_free_ char *config_path = NULL;
- _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
- int r, q;
+ char *path;
+ int r;
+ InstallInfo *i = NULL;
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
+ if (unit_name_to_type(file) != UNIT_TARGET)
+ return -EINVAL;
+
r = lookup_paths_init_from_scope(&paths, scope);
if (r < 0)
return r;
- r = get_config_path(scope, runtime, root_dir, &config_path);
+ r = get_config_path(scope, false, root_dir, &config_path);
if (r < 0)
return r;
- STRV_FOREACH(i, files) {
- r = mark_symlink_for_removal(&remove_symlinks_to, *i);
- if (r < 0)
- return r;
+ r = install_info_add_auto(&c, file);
+ if (r < 0)
+ return r;
- r = install_info_add_auto(&c, *i);
- if (r < 0)
+ i = (InstallInfo*)hashmap_first(c.will_install);
+
+ r = unit_file_search(&c, i, &paths, root_dir, false);
+ if (r < 0)
+ return r;
+
+ path = strappenda(config_path, "/default.target");
+ r = create_symlink(i->path, path, true, changes, n_changes);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+int unit_file_get_default(
+ UnitFileScope scope,
+ const char *root_dir,
+ char **name) {
+
+ _cleanup_lookup_paths_free_ LookupPaths paths = {};
+ char **p;
+ int r;
+
+ r = lookup_paths_init_from_scope(&paths, scope);
+ if (r < 0)
+ return r;
+
+ STRV_FOREACH(p, paths.unit_path) {
+ _cleanup_free_ char *path = NULL, *tmp = NULL;
+
+ if (isempty(root_dir))
+ path = strappend(*p, "/default.target");
+ else
+ path = strjoin(root_dir, "/", *p, "/default.target", NULL);
+
+ if (!path)
+ return -ENOMEM;
+
+ r = readlink_malloc(path, &tmp);
+ if (r == -ENOENT)
+ continue;
+ else if (r < 0)
return r;
- }
- r = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
+ *name = strdup(path_get_file_name(tmp));
+ if (!*name)
+ return -ENOMEM;
- /* Returns number of symlinks that where supposed to be installed. */
- q = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
- if (r == 0)
- r = q;
+ return 0;
+ }
- return r;
+ return -ENOENT;
}
UnitFileState unit_file_get_state(
@@ -1609,24 +1685,29 @@ UnitFileState unit_file_get_state(
if (!path)
return -ENOMEM;
+ /*
+ * Search for a unit file in our default paths, to
+ * be sure, that there are no broken symlinks.
+ */
if (lstat(path, &st) < 0) {
r = -errno;
- if (errno == ENOENT)
- continue;
-
- return -errno;
- }
+ if (errno != ENOENT)
+ return r;
- if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
- return -ENOENT;
+ if (!unit_name_is_instance(name))
+ continue;
+ } else {
+ if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
+ return -ENOENT;
- r = null_or_empty_path(path);
- if (r < 0 && r != -ENOENT)
- return r;
- else if (r > 0) {
- state = path_startswith(*i, "/run") ?
- UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
- return state;
+ r = null_or_empty_path(path);
+ if (r < 0 && r != -ENOENT)
+ return r;
+ else if (r > 0) {
+ state = path_startswith(*i, "/run") ?
+ UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
+ return state;
+ }
}
r = find_symlinks_in_scope(scope, root_dir, name, &state);
diff --git a/src/shared/install.h b/src/shared/install.h
index 94516c9d05..5609d1e8df 100644
--- a/src/shared/install.h
+++ b/src/shared/install.h
@@ -80,6 +80,8 @@ int unit_file_link(UnitFileScope scope, bool runtime, const char *root_dir, char
int unit_file_preset(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);
int unit_file_mask(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);
int unit_file_unmask(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes);
+int unit_file_set_default(UnitFileScope scope, const char *root_dir, char *file, UnitFileChange **changes, unsigned *n_changes);
+int unit_file_get_default(UnitFileScope scope, const char *root_dir, char **name);
UnitFileState unit_file_get_state(UnitFileScope scope, const char *root_dir, const char *filename);
diff --git a/src/shared/label.c b/src/shared/label.c
index 1fe4574633..fde39f2259 100644
--- a/src/shared/label.c
+++ b/src/shared/label.c
@@ -257,14 +257,14 @@ void label_free(const char *label) {
#endif
}
-int label_mkdir(const char *path, mode_t mode, bool apply) {
+int label_mkdir(const char *path, mode_t mode) {
/* Creates a directory and labels it according to the SELinux policy */
#ifdef HAVE_SELINUX
int r;
security_context_t fcon = NULL;
- if (!apply || !use_selinux() || !label_hnd)
+ if (!use_selinux() || !label_hnd)
goto skipped;
if (path_is_absolute(path))
diff --git a/src/shared/label.h b/src/shared/label.h
index dda4d1c024..09e15e3c08 100644
--- a/src/shared/label.h
+++ b/src/shared/label.h
@@ -40,7 +40,7 @@ void label_free(const char *label);
int label_get_create_label_from_exe(const char *exe, char **label);
-int label_mkdir(const char *path, mode_t mode, bool apply);
+int label_mkdir(const char *path, mode_t mode);
void label_retest_selinux(void);
diff --git a/src/shared/list.h b/src/shared/list.h
index 47f275a019..476757460a 100644
--- a/src/shared/list.h
+++ b/src/shared/list.h
@@ -81,7 +81,7 @@
(head) = _item; \
} while (false)
-/* Find the head of the list */
+/* Find the tail of the list */
#define LIST_FIND_TAIL(t,name,item,tail) \
do { \
t *_item = (item); \
@@ -123,3 +123,10 @@
#define LIST_FOREACH_AFTER(name,i,p) \
for ((i) = (p)->name##_next; (i); (i) = (i)->name##_next)
+
+/* Loop starting from p->next until p->prev.
+ p can be adjusted meanwhile. */
+#define LIST_LOOP_BUT_ONE(name,i,head,p) \
+ for ((i) = (p)->name##_next ? (p)->name##_next : (head); \
+ (i) != (p); \
+ (i) = (i)->name##_next ? (i)->name##_next : (head))
diff --git a/src/shared/log.c b/src/shared/log.c
index 27317f7ed3..8f4995a0c8 100644
--- a/src/shared/log.c
+++ b/src/shared/log.c
@@ -115,16 +115,20 @@ void log_close_syslog(void) {
static int create_log_socket(int type) {
int fd;
+ struct timeval tv;
- /* All output to the syslog/journal fds we do asynchronously,
- * and if the buffers are full we just drop the messages */
-
- fd = socket(AF_UNIX, type|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ fd = socket(AF_UNIX, type|SOCK_CLOEXEC, 0);
if (fd < 0)
return -errno;
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. */
+ timeval_store(&tv, 1*USEC_PER_MINUTE);
+ setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
+
return fd;
}
diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c
index 116dc8a36c..7bb19b4006 100644
--- a/src/shared/logs-show.c
+++ b/src/shared/logs-show.c
@@ -32,7 +32,11 @@
#include "hashmap.h"
#include "journal-internal.h"
-#define PRINT_THRESHOLD 128
+/* up to three lines (each up to 100 characters),
+ or 300 characters, whichever is less */
+#define PRINT_LINE_THRESHOLD 3
+#define PRINT_CHAR_THRESHOLD 300
+
#define JSON_THRESHOLD 4096
static int print_catalog(FILE *f, sd_journal *j) {
@@ -92,15 +96,91 @@ static bool shall_print(const char *p, size_t l, OutputFlags flags) {
if (flags & OUTPUT_SHOW_ALL)
return true;
- if (l >= PRINT_THRESHOLD)
+ if (l >= PRINT_CHAR_THRESHOLD)
return false;
- if (!utf8_is_printable_n(p, l))
+ if (!utf8_is_printable(p, l))
return false;
return true;
}
+static bool print_multiline(FILE *f, unsigned prefix, unsigned n_columns, OutputFlags flags, int priority, const char* message, size_t message_len) {
+ const char *color_on = "", *color_off = "";
+ const char *pos, *end;
+ bool ellipsized = false;
+ int line = 0;
+
+ if (flags & OUTPUT_COLOR) {
+ if (priority <= LOG_ERR) {
+ color_on = ANSI_HIGHLIGHT_RED_ON;
+ color_off = ANSI_HIGHLIGHT_OFF;
+ } else if (priority <= LOG_NOTICE) {
+ color_on = ANSI_HIGHLIGHT_ON;
+ color_off = ANSI_HIGHLIGHT_OFF;
+ }
+ }
+
+ for (pos = message;
+ pos < message + message_len;
+ pos = end + 1, line++) {
+ bool continuation = line > 0;
+ bool tail_line;
+ int len;
+ for (end = pos; end < message + message_len && *end != '\n'; end++)
+ ;
+ len = end - pos;
+ assert(len >= 0);
+
+ /* We need to figure out when we are showing not-last line, *and*
+ * will skip subsequent lines. In that case, we will put the dots
+ * at the end of the line, instead of putting dots in the middle
+ * or not at all.
+ */
+ tail_line =
+ line + 1 == PRINT_LINE_THRESHOLD ||
+ end + 1 >= message + PRINT_CHAR_THRESHOLD;
+
+ if (flags & (OUTPUT_FULL_WIDTH | OUTPUT_SHOW_ALL) ||
+ (prefix + len + 1 < n_columns && !tail_line)) {
+ fprintf(f, "%*s%s%.*s%s\n",
+ continuation * prefix, "",
+ color_on, len, pos, color_off);
+ continue;
+ }
+
+ /* Beyond this point, ellipsization will happen. */
+ ellipsized = true;
+
+ if (prefix < n_columns && n_columns - prefix >= 3) {
+ if (n_columns - prefix > (unsigned) len + 3)
+ fprintf(f, "%*s%s%.*s...%s\n",
+ continuation * prefix, "",
+ color_on, len, pos, color_off);
+ else {
+ _cleanup_free_ char *e;
+
+ e = ellipsize_mem(pos, len, n_columns - prefix,
+ tail_line ? 100 : 90);
+ if (!e)
+ fprintf(f, "%*s%s%.*s%s\n",
+ continuation * prefix, "",
+ color_on, len, pos, color_off);
+ else
+ fprintf(f, "%*s%s%s%s\n",
+ continuation * prefix, "",
+ color_on, e, color_off);
+ }
+ } else
+ fputs("...\n", f);
+
+ if (tail_line)
+ break;
+ }
+
+ return ellipsized;
+}
+
static int output_short(
FILE *f,
sd_journal *j,
@@ -115,14 +195,20 @@ static int output_short(
_cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL;
size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, realtime_len = 0, monotonic_len = 0, priority_len = 0;
int p = LOG_INFO;
- const char *color_on = "", *color_off = "";
+ bool ellipsized = false;
assert(f);
assert(j);
- sd_journal_set_data_threshold(j, flags & OUTPUT_SHOW_ALL ? 0 : PRINT_THRESHOLD);
+ /* Set the threshold to one bigger than the actual print
+ * threshold, so that if the line is actually longer than what
+ * we're willing to print, ellipsization will occur. This way
+ * we won't output a misleading line without any indication of
+ * truncation.
+ */
+ sd_journal_set_data_threshold(j, flags & (OUTPUT_SHOW_ALL|OUTPUT_FULL_WIDTH) ? 0 : PRINT_CHAR_THRESHOLD + 1);
- SD_JOURNAL_FOREACH_DATA(j, data, length) {
+ JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
r = parse_field(data, length, "PRIORITY=", &priority, &priority_len);
if (r < 0)
@@ -177,6 +263,9 @@ static int output_short(
return r;
}
+ if (r < 0)
+ return r;
+
if (!message)
return 0;
@@ -199,7 +288,7 @@ static int output_short(
r = sd_journal_get_monotonic_usec(j, &t, &boot_id);
if (r < 0) {
- log_error("Failed to get monotonic: %s", strerror(-r));
+ log_error("Failed to get monotonic timestamp: %s", strerror(-r));
return r;
}
@@ -224,14 +313,30 @@ static int output_short(
r = sd_journal_get_realtime_usec(j, &x);
if (r < 0) {
- log_error("Failed to get realtime: %s", strerror(-r));
+ log_error("Failed to get realtime timestamp: %s", strerror(-r));
return r;
}
t = (time_t) (x / USEC_PER_SEC);
- if (strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm)) <= 0) {
+
+ switch(mode) {
+ case OUTPUT_SHORT_ISO:
+ r = strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", localtime_r(&t, &tm));
+ break;
+ case OUTPUT_SHORT_PRECISE:
+ r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm));
+ if (r > 0) {
+ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+ ".%06llu", x % USEC_PER_SEC);
+ }
+ break;
+ default:
+ r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm));
+ }
+
+ if (r <= 0) {
log_error("Failed to format time.");
- return r;
+ return -EINVAL;
}
fputs(buf, f);
@@ -260,39 +365,19 @@ static int output_short(
n += fake_pid_len + 2;
}
- if (flags & OUTPUT_COLOR) {
- if (p <= LOG_ERR) {
- color_on = ANSI_HIGHLIGHT_RED_ON;
- color_off = ANSI_HIGHLIGHT_OFF;
- } else if (p <= LOG_NOTICE) {
- color_on = ANSI_HIGHLIGHT_ON;
- color_off = ANSI_HIGHLIGHT_OFF;
- }
- }
-
- if (flags & OUTPUT_SHOW_ALL)
- fprintf(f, ": %s%.*s%s\n", color_on, (int) message_len, message, color_off);
- else if (!utf8_is_printable_n(message, message_len)) {
+ if (!(flags & OUTPUT_SHOW_ALL) && !utf8_is_printable(message, message_len)) {
char bytes[FORMAT_BYTES_MAX];
fprintf(f, ": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len));
- } else if ((flags & OUTPUT_FULL_WIDTH) || (message_len + n + 1 < n_columns))
- fprintf(f, ": %s%.*s%s\n", color_on, (int) message_len, message, color_off);
- else if (n < n_columns && n_columns - n - 2 >= 3) {
- _cleanup_free_ char *e;
-
- e = ellipsize_mem(message, message_len, n_columns - n - 2, 90);
-
- if (!e)
- fprintf(f, ": %s%.*s%s\n", color_on, (int) message_len, message, color_off);
- else
- fprintf(f, ": %s%s%s\n", color_on, e, color_off);
- } else
- fputs("\n", f);
+ } else {
+ fputs(": ", f);
+ ellipsized |=
+ print_multiline(f, n + 2, n_columns, flags, p, message, message_len);
+ }
if (flags & OUTPUT_CATALOG)
print_catalog(f, j);
- return 0;
+ return ellipsized;
}
static int output_verbose(
@@ -306,7 +391,7 @@ static int output_verbose(
size_t length;
_cleanup_free_ char *cursor = NULL;
uint64_t realtime;
- char ts[FORMAT_TIMESTAMP_MAX];
+ char ts[FORMAT_TIMESTAMP_MAX + 7];
int r;
assert(f);
@@ -314,10 +399,35 @@ static int output_verbose(
sd_journal_set_data_threshold(j, 0);
- r = sd_journal_get_realtime_usec(j, &realtime);
- if (r < 0) {
- log_error("Failed to get realtime timestamp: %s", strerror(-r));
+ r = sd_journal_get_data(j, "_SOURCE_REALTIME_TIMESTAMP", &data, &length);
+ if (r == -ENOENT)
+ log_debug("Source realtime timestamp not found");
+ else if (r < 0) {
+ log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR,
+ "Failed to get source realtime timestamp: %s", strerror(-r));
return r;
+ } else {
+ _cleanup_free_ char *value = NULL;
+ size_t size;
+
+ r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &value, &size);
+ if (r < 0)
+ log_debug("_SOURCE_REALTIME_TIMESTAMP invalid: %s", strerror(-r));
+ else {
+ r = safe_atou64(value, &realtime);
+ if (r < 0)
+ log_debug("Failed to parse realtime timestamp: %s",
+ strerror(-r));
+ }
+ }
+
+ if (r < 0) {
+ r = sd_journal_get_realtime_usec(j, &realtime);
+ if (r < 0) {
+ log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR,
+ "Failed to get realtime timestamp: %s", strerror(-r));
+ return r;
+ }
}
r = sd_journal_get_cursor(j, &cursor);
@@ -327,28 +437,47 @@ static int output_verbose(
}
fprintf(f, "%s [%s]\n",
- format_timestamp(ts, sizeof(ts), realtime),
+ format_timestamp_us(ts, sizeof(ts), realtime),
cursor);
- SD_JOURNAL_FOREACH_DATA(j, data, length) {
- if (!shall_print(data, length, flags)) {
- const char *c;
- char bytes[FORMAT_BYTES_MAX];
+ JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
+ const char *c;
+ int fieldlen;
+ const char *on = "", *off = "";
- c = memchr(data, '=', length);
- if (!c) {
- log_error("Invalid field.");
- return -EINVAL;
- }
+ c = memchr(data, '=', length);
+ if (!c) {
+ log_error("Invalid field.");
+ return -EINVAL;
+ }
+ fieldlen = c - (const char*) data;
- fprintf(f, "\t%.*s=[%s blob data]\n",
- (int) (c - (const char*) data),
- (const char*) data,
- format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1));
- } else
- fprintf(f, "\t%.*s\n", (int) length, (const char*) data);
+ if (flags & OUTPUT_COLOR && startswith(data, "MESSAGE=")) {
+ on = ANSI_HIGHLIGHT_ON;
+ off = ANSI_HIGHLIGHT_OFF;
+ }
+
+ if (flags & OUTPUT_SHOW_ALL ||
+ (((length < PRINT_CHAR_THRESHOLD) || flags & OUTPUT_FULL_WIDTH)
+ && utf8_is_printable(data, length))) {
+ fprintf(f, " %s%.*s=", on, fieldlen, (const char*)data);
+ print_multiline(f, 4 + fieldlen + 1, 0, OUTPUT_FULL_WIDTH, 0, c + 1, length - fieldlen - 1);
+ fputs(off, f);
+ } else {
+ char bytes[FORMAT_BYTES_MAX];
+
+ fprintf(f, " %s%.*s=[%s blob data]%s\n",
+ on,
+ (int) (c - (const char*) data),
+ (const char*) data,
+ format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1),
+ off);
+ }
}
+ if (r < 0)
+ return r;
+
if (flags & OUTPUT_CATALOG)
print_catalog(f, j);
@@ -402,15 +531,15 @@ static int output_export(
(unsigned long long) monotonic,
sd_id128_to_string(boot_id, sid));
- SD_JOURNAL_FOREACH_DATA(j, data, length) {
+ JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
/* We already printed the boot id, from the data in
* the header, hence let's suppress it here */
if (length >= 9 &&
- memcmp(data, "_BOOT_ID=", 9) == 0)
+ startswith(data, "_BOOT_ID="))
continue;
- if (!utf8_is_printable_n(data, length)) {
+ if (!utf8_is_printable(data, length)) {
const char *c;
uint64_t le64;
@@ -431,6 +560,9 @@ static int output_export(
fputc('\n', f);
}
+ if (r < 0)
+ return r;
+
fputc('\n', f);
return 0;
@@ -449,7 +581,7 @@ void json_escape(
fputs("null", f);
- else if (!utf8_is_printable_n(p, l)) {
+ else if (!utf8_is_printable(p, l)) {
bool not_first = false;
fputs("[ ", f);
@@ -474,7 +606,9 @@ void json_escape(
if (*p == '"' || *p == '\\') {
fputc('\\', f);
fputc(*p, f);
- } else if (*p < ' ')
+ } else if (*p == '\n')
+ fputs("\\n", f);
+ else if (*p < ' ')
fprintf(f, "\\u%04x", *p);
else
fputc(*p, f);
@@ -557,7 +691,7 @@ static int output_json(
return -ENOMEM;
/* First round, iterate through the entry and count how often each field appears */
- SD_JOURNAL_FOREACH_DATA(j, data, length) {
+ JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
const char *eq;
char *n;
unsigned u;
@@ -591,6 +725,9 @@ static int output_json(
}
}
+ if (r < 0)
+ return r;
+
separator = true;
do {
done = true;
@@ -747,6 +884,8 @@ static int (*output_funcs[_OUTPUT_MODE_MAX])(
OutputFlags flags) = {
[OUTPUT_SHORT] = output_short,
+ [OUTPUT_SHORT_ISO] = output_short,
+ [OUTPUT_SHORT_PRECISE] = output_short,
[OUTPUT_SHORT_MONOTONIC] = output_short,
[OUTPUT_VERBOSE] = output_verbose,
[OUTPUT_EXPORT] = output_export,
@@ -761,7 +900,8 @@ int output_journal(
sd_journal *j,
OutputMode mode,
unsigned n_columns,
- OutputFlags flags) {
+ OutputFlags flags,
+ bool *ellipsized) {
int ret;
assert(mode >= 0);
@@ -772,6 +912,10 @@ int output_journal(
ret = output_funcs[mode](f, j, mode, n_columns, flags);
fflush(stdout);
+
+ if (ellipsized && ret > 0)
+ *ellipsized = true;
+
return ret;
}
@@ -781,7 +925,8 @@ static int show_journal(FILE *f,
unsigned n_columns,
usec_t not_before,
unsigned how_many,
- OutputFlags flags) {
+ OutputFlags flags,
+ bool *ellipsized) {
int r;
unsigned line = 0;
@@ -832,7 +977,7 @@ static int show_journal(FILE *f,
line ++;
- r = output_journal(f, j, mode, n_columns, flags);
+ r = output_journal(f, j, mode, n_columns, flags, ellipsized);
if (r < 0)
goto finish;
}
@@ -872,15 +1017,15 @@ finish:
int add_matches_for_unit(sd_journal *j, const char *unit) {
int r;
- _cleanup_free_ char *m1 = NULL, *m2 = NULL, *m3 = NULL;
+ char *m1, *m2, *m3, *m4;
assert(j);
assert(unit);
- if (asprintf(&m1, "_SYSTEMD_UNIT=%s", unit) < 0 ||
- asprintf(&m2, "COREDUMP_UNIT=%s", unit) < 0 ||
- asprintf(&m3, "UNIT=%s", unit) < 0)
- return -ENOMEM;
+ m1 = strappenda("_SYSTEMD_UNIT=", unit);
+ m2 = strappenda("COREDUMP_UNIT=", unit);
+ m3 = strappenda("UNIT=", unit);
+ m4 = strappenda("OBJECT_SYSTEMD_UNIT=", unit);
(void)(
/* Look for messages from the service itself */
@@ -888,49 +1033,112 @@ int add_matches_for_unit(sd_journal *j, const char *unit) {
/* Look for coredumps of the service */
(r = sd_journal_add_disjunction(j)) ||
- (r = sd_journal_add_match(j,
- "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0)) ||
+ (r = sd_journal_add_match(j, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0)) ||
+ (r = sd_journal_add_match(j, "_UID=0", 0)) ||
(r = sd_journal_add_match(j, m2, 0)) ||
/* Look for messages from PID 1 about this service */
(r = sd_journal_add_disjunction(j)) ||
(r = sd_journal_add_match(j, "_PID=1", 0)) ||
- (r = sd_journal_add_match(j, m3, 0))
+ (r = sd_journal_add_match(j, m3, 0)) ||
+
+ /* Look for messages from authorized daemons about this service */
+ (r = sd_journal_add_disjunction(j)) ||
+ (r = sd_journal_add_match(j, "_UID=0", 0)) ||
+ (r = sd_journal_add_match(j, m4, 0))
);
+
+ if (r == 0 && endswith(unit, ".slice")) {
+ char *m5 = strappend("_SYSTEMD_SLICE=", unit);
+
+ /* Show all messages belonging to a slice */
+ (void)(
+ (r = sd_journal_add_disjunction(j)) ||
+ (r = sd_journal_add_match(j, m5, 0))
+ );
+ }
+
return r;
}
int add_matches_for_user_unit(sd_journal *j, const char *unit, uid_t uid) {
int r;
- _cleanup_free_ char *m1 = NULL, *m2 = NULL, *m3 = NULL, *m4 = NULL;
+ char *m1, *m2, *m3, *m4;
+ char muid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)];
assert(j);
assert(unit);
- if (asprintf(&m1, "_SYSTEMD_USER_UNIT=%s", unit) < 0 ||
- asprintf(&m2, "USER_UNIT=%s", unit) < 0 ||
- asprintf(&m3, "COREDUMP_USER_UNIT=%s", unit) < 0 ||
- asprintf(&m4, "_UID=%d", uid) < 0)
- return -ENOMEM;
+ m1 = strappenda("_SYSTEMD_USER_UNIT=", unit);
+ m2 = strappenda("USER_UNIT=", unit);
+ m3 = strappenda("COREDUMP_USER_UNIT=", unit);
+ m4 = strappenda("OBJECT_SYSTEMD_USER_UNIT=", unit);
+ sprintf(muid, "_UID=%lu", (unsigned long) uid);
(void) (
/* Look for messages from the user service itself */
(r = sd_journal_add_match(j, m1, 0)) ||
- (r = sd_journal_add_match(j, m4, 0)) ||
+ (r = sd_journal_add_match(j, muid, 0)) ||
/* Look for messages from systemd about this service */
(r = sd_journal_add_disjunction(j)) ||
(r = sd_journal_add_match(j, m2, 0)) ||
- (r = sd_journal_add_match(j, m4, 0)) ||
+ (r = sd_journal_add_match(j, muid, 0)) ||
/* Look for coredumps of the service */
(r = sd_journal_add_disjunction(j)) ||
(r = sd_journal_add_match(j, m3, 0)) ||
- (r = sd_journal_add_match(j, m4, 0))
+ (r = sd_journal_add_match(j, muid, 0)) ||
+ (r = sd_journal_add_match(j, "_UID=0", 0)) ||
+
+ /* Look for messages from authorized daemons about this service */
+ (r = sd_journal_add_disjunction(j)) ||
+ (r = sd_journal_add_match(j, m4, 0)) ||
+ (r = sd_journal_add_match(j, muid, 0)) ||
+ (r = sd_journal_add_match(j, "_UID=0", 0))
);
+
+ if (r == 0 && endswith(unit, ".slice")) {
+ char *m5 = strappend("_SYSTEMD_SLICE=", unit);
+
+ /* Show all messages belonging to a slice */
+ (void)(
+ (r = sd_journal_add_disjunction(j)) ||
+ (r = sd_journal_add_match(j, m5, 0)) ||
+ (r = sd_journal_add_match(j, muid, 0))
+ );
+ }
+
return r;
}
+int add_match_this_boot(sd_journal *j) {
+ char match[9+32+1] = "_BOOT_ID=";
+ sd_id128_t boot_id;
+ int r;
+
+ assert(j);
+
+ r = sd_id128_get_boot(&boot_id);
+ if (r < 0) {
+ log_error("Failed to get boot id: %s", strerror(-r));
+ return r;
+ }
+
+ sd_id128_to_string(boot_id, match + 9);
+ r = sd_journal_add_match(j, match, strlen(match));
+ if (r < 0) {
+ log_error("Failed to add match: %s", strerror(-r));
+ return r;
+ }
+
+ r = sd_journal_add_conjunction(j);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
int show_journal_by_unit(
FILE *f,
const char *unit,
@@ -940,11 +1148,12 @@ int show_journal_by_unit(
unsigned how_many,
uid_t uid,
OutputFlags flags,
- bool system) {
+ bool system,
+ bool *ellipsized) {
_cleanup_journal_close_ sd_journal*j = NULL;
int r;
- int jflags = SD_JOURNAL_LOCAL_ONLY | system * SD_JOURNAL_SYSTEM_ONLY;
+ int jflags = SD_JOURNAL_LOCAL_ONLY | system * SD_JOURNAL_SYSTEM;
assert(mode >= 0);
assert(mode < _OUTPUT_MODE_MAX);
@@ -957,6 +1166,10 @@ int show_journal_by_unit(
if (r < 0)
return r;
+ r = add_match_this_boot(j);
+ if (r < 0)
+ return r;
+
if (system)
r = add_matches_for_unit(j, unit);
else
@@ -964,15 +1177,20 @@ int show_journal_by_unit(
if (r < 0)
return r;
- r = show_journal(f, j, mode, n_columns, not_before, how_many, flags);
- if (r < 0)
- return r;
+ if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
+ _cleanup_free_ char *filter;
- return 0;
+ filter = journal_make_match_string(j);
+ log_debug("Journal filter: %s", filter);
+ }
+
+ return show_journal(f, j, mode, n_columns, not_before, how_many, flags, ellipsized);
}
static const char *const output_mode_table[_OUTPUT_MODE_MAX] = {
[OUTPUT_SHORT] = "short",
+ [OUTPUT_SHORT_ISO] = "short-iso",
+ [OUTPUT_SHORT_PRECISE] = "short-precise",
[OUTPUT_SHORT_MONOTONIC] = "short-monotonic",
[OUTPUT_VERBOSE] = "verbose",
[OUTPUT_EXPORT] = "export",
diff --git a/src/shared/logs-show.h b/src/shared/logs-show.h
index b0f93a661a..11b3b59b7b 100644
--- a/src/shared/logs-show.h
+++ b/src/shared/logs-show.h
@@ -35,7 +35,10 @@ int output_journal(
sd_journal *j,
OutputMode mode,
unsigned n_columns,
- OutputFlags flags);
+ OutputFlags flags,
+ bool *ellipsized);
+
+int add_match_this_boot(sd_journal *j);
int add_matches_for_unit(
sd_journal *j,
@@ -55,7 +58,8 @@ int show_journal_by_unit(
unsigned how_many,
uid_t uid,
OutputFlags flags,
- bool system);
+ bool system,
+ bool *ellipsized);
void json_escape(
FILE *f,
diff --git a/src/shared/macro.h b/src/shared/macro.h
index 0874102ece..d4f92b60ec 100644
--- a/src/shared/macro.h
+++ b/src/shared/macro.h
@@ -159,23 +159,25 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
} while (false)
#endif
+#define PTR_TO_INT(p) ((int) ((intptr_t) (p)))
+#define INT_TO_PTR(u) ((void *) ((intptr_t) (u)))
#define PTR_TO_UINT(p) ((unsigned int) ((uintptr_t) (p)))
-#define UINT_TO_PTR(u) ((void*) ((uintptr_t) (u)))
-
-#define PTR_TO_UINT32(p) ((uint32_t) ((uintptr_t) (p)))
-#define UINT32_TO_PTR(u) ((void*) ((uintptr_t) (u)))
+#define UINT_TO_PTR(u) ((void *) ((uintptr_t) (u)))
+#define PTR_TO_LONG(p) ((long) ((intptr_t) (p)))
+#define LONG_TO_PTR(u) ((void *) ((intptr_t) (u)))
#define PTR_TO_ULONG(p) ((unsigned long) ((uintptr_t) (p)))
-#define ULONG_TO_PTR(u) ((void*) ((uintptr_t) (u)))
+#define ULONG_TO_PTR(u) ((void *) ((uintptr_t) (u)))
-#define PTR_TO_INT(p) ((int) ((intptr_t) (p)))
-#define INT_TO_PTR(u) ((void*) ((intptr_t) (u)))
-
-#define TO_INT32(p) ((int32_t) ((intptr_t) (p)))
-#define INT32_TO_PTR(u) ((void*) ((intptr_t) (u)))
+#define PTR_TO_INT32(p) ((int32_t) ((intptr_t) (p)))
+#define INT32_TO_PTR(u) ((void *) ((intptr_t) (u)))
+#define PTR_TO_UINT32(p) ((uint32_t) ((uintptr_t) (p)))
+#define UINT32_TO_PTR(u) ((void *) ((uintptr_t) (u)))
-#define PTR_TO_LONG(p) ((long) ((intptr_t) (p)))
-#define LONG_TO_PTR(u) ((void*) ((intptr_t) (u)))
+#define PTR_TO_INT64(p) ((int64_t) ((intptr_t) (p)))
+#define INT64_TO_PTR(u) ((void *) ((intptr_t) (u)))
+#define PTR_TO_UINT64(p) ((uint64_t) ((uintptr_t) (p)))
+#define UINT64_TO_PTR(u) ((void *) ((uintptr_t) (u)))
#define memzero(x,l) (memset((x), 0, (l)))
#define zero(x) (memzero(&(x), sizeof(x)))
@@ -269,7 +271,7 @@ do { \
* the const magic to the type, otherwise the compiler warns about
* signed/unsigned comparison, because the magic can be 32 bit unsigned.
*/
-#define F_TYPE_CMP(a, b) (a == (typeof(a)) b)
+#define F_TYPE_EQUAL(a, b) (a == (typeof(a)) b)
/* Returns the number of chars needed to format variables of the
@@ -282,4 +284,7 @@ do { \
sizeof(type) <= 4 ? 10 : \
sizeof(type) <= 8 ? 20 : sizeof(int[-2*(sizeof(type) > 8)])))
+#define SET_FLAG(v, flag, b) \
+ (v) = (b) ? ((v) | (flag)) : ((v) & ~(flag))
+
#include "log.h"
diff --git a/src/shared/missing.h b/src/shared/missing.h
index d4ba0d3dcf..6c038d9f08 100644
--- a/src/shared/missing.h
+++ b/src/shared/missing.h
@@ -29,6 +29,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <linux/oom.h>
+#include <linux/input.h>
#ifdef HAVE_AUDIT
#include <libaudit.h>
@@ -138,7 +139,8 @@ static inline int fanotify_init(unsigned int flags, unsigned int event_f_flags)
#ifndef HAVE_FANOTIFY_MARK
static inline int fanotify_mark(int fanotify_fd, unsigned int flags, uint64_t mask,
int dfd, const char *pathname) {
-#if defined _MIPS_SIM && _MIPS_SIM == _MIPS_SIM_ABI32 || defined __powerpc__ && !defined __powerpc64__
+#if defined _MIPS_SIM && _MIPS_SIM == _MIPS_SIM_ABI32 || defined __powerpc__ && !defined __powerpc64__ \
+ || defined __arm__ && !defined __aarch64__
union {
uint64_t _64;
uint32_t _32[2];
@@ -161,15 +163,55 @@ static inline int fanotify_mark(int fanotify_fd, unsigned int flags, uint64_t ma
#define BTRFS_PATH_NAME_MAX 4087
#endif
+#ifndef BTRFS_DEVICE_PATH_NAME_MAX
+#define BTRFS_DEVICE_PATH_NAME_MAX 1024
+#endif
+
+#ifndef BTRFS_FSID_SIZE
+#define BTRFS_FSID_SIZE 16
+#endif
+
+#ifndef BTRFS_UUID_SIZE
+#define BTRFS_UUID_SIZE 16
+#endif
+
+#ifndef HAVE_LINUX_BTRFS_H
struct btrfs_ioctl_vol_args {
int64_t fd;
char name[BTRFS_PATH_NAME_MAX + 1];
};
+struct btrfs_ioctl_dev_info_args {
+ uint64_t devid; /* in/out */
+ uint8_t uuid[BTRFS_UUID_SIZE]; /* in/out */
+ uint64_t bytes_used; /* out */
+ uint64_t total_bytes; /* out */
+ uint64_t unused[379]; /* pad to 4k */
+ char path[BTRFS_DEVICE_PATH_NAME_MAX]; /* out */
+};
+
+struct btrfs_ioctl_fs_info_args {
+ uint64_t max_id; /* out */
+ uint64_t num_devices; /* out */
+ uint8_t fsid[BTRFS_FSID_SIZE]; /* out */
+ uint64_t reserved[124]; /* pad to 1k */
+};
+#endif
+
#ifndef BTRFS_IOC_DEFRAG
#define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, struct btrfs_ioctl_vol_args)
#endif
+#ifndef BTRFS_IOC_DEV_INFO
+#define BTRFS_IOC_DEV_INFO _IOWR(BTRFS_IOCTL_MAGIC, 30, \
+ struct btrfs_ioctl_dev_info_args)
+#endif
+
+#ifndef BTRFS_IOC_FS_INFO
+#define BTRFS_IOC_FS_INFO _IOR(BTRFS_IOCTL_MAGIC, 31, \
+ struct btrfs_ioctl_fs_info_args)
+#endif
+
#ifndef BTRFS_SUPER_MAGIC
#define BTRFS_SUPER_MAGIC 0x9123683E
#endif
@@ -265,3 +307,19 @@ static inline int name_to_handle_at(int fd, const char *name, struct file_handle
#ifndef TFD_TIMER_CANCEL_ON_SET
#define TFD_TIMER_CANCEL_ON_SET (1 << 1)
#endif
+
+#ifndef SO_REUSEPORT
+#define SO_REUSEPORT 15
+#endif
+
+#ifndef EVIOCREVOKE
+#define EVIOCREVOKE _IOW('E', 0x91, int)
+#endif
+
+#ifndef DRM_IOCTL_SET_MASTER
+#define DRM_IOCTL_SET_MASTER _IO('d', 0x1e)
+#endif
+
+#ifndef DRM_IOCTL_DROP_MASTER
+#define DRM_IOCTL_DROP_MASTER _IO('d', 0x1f)
+#endif
diff --git a/src/shared/mkdir-label.c b/src/shared/mkdir-label.c
new file mode 100644
index 0000000000..4ee6251bcd
--- /dev/null
+++ b/src/shared/mkdir-label.c
@@ -0,0 +1,53 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ 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 <assert.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "label.h"
+#include "util.h"
+#include "path-util.h"
+#include "mkdir.h"
+
+int mkdir_label(const char *path, mode_t mode) {
+ return label_mkdir(path, mode);
+}
+
+int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid) {
+ return mkdir_safe_internal(path, mode, uid, gid, label_mkdir);
+}
+
+int mkdir_parents_label(const char *path, mode_t mode) {
+ return mkdir_parents_internal(NULL, path, mode, label_mkdir);
+}
+
+int mkdir_parents_prefix_label(const char *prefix, const char *path, mode_t mode) {
+ return mkdir_parents_internal(prefix, path, mode, label_mkdir);
+}
+
+int mkdir_p_label(const char *path, mode_t mode) {
+ return mkdir_p_internal(NULL, path, mode, label_mkdir);
+}
diff --git a/src/shared/mkdir.c b/src/shared/mkdir.c
index 0e51b64f69..b7e5c6e67b 100644
--- a/src/shared/mkdir.c
+++ b/src/shared/mkdir.c
@@ -26,18 +26,15 @@
#include <stdlib.h>
#include <stdio.h>
-#include "mkdir.h"
#include "label.h"
#include "util.h"
+#include "path-util.h"
+#include "mkdir.h"
-int mkdir_label(const char *path, mode_t mode) {
- return label_mkdir(path, mode, true);
-}
-
-static int makedir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, bool apply) {
+int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, mkdir_func_t _mkdir) {
struct stat st;
- if (label_mkdir(path, mode, apply) >= 0)
+ if (_mkdir(path, mode) >= 0)
if (chmod_and_chown(path, mode, uid, gid) < 0)
return -errno;
@@ -56,36 +53,46 @@ static int makedir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, boo
}
int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid) {
- return makedir_safe(path, mode, uid, gid, false);
+ return mkdir_safe_internal(path, mode, uid, gid, false);
}
-int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid) {
- return makedir_safe(path, mode, uid, gid, true);
+static int is_dir(const char* path) {
+ struct stat st;
+
+ if (stat(path, &st) < 0)
+ return -errno;
+
+ return S_ISDIR(st.st_mode);
}
-static int makedir_parents(const char *path, mode_t mode, bool apply) {
- struct stat st;
+int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir) {
const char *p, *e;
+ int r;
assert(path);
+ if (prefix && !path_startswith(path, prefix))
+ return -ENOTDIR;
+
/* return immediately if directory exists */
e = strrchr(path, '/');
if (!e)
return -EINVAL;
+
+ if (e == path)
+ return 0;
+
p = strndupa(path, e - path);
- if (stat(p, &st) >= 0) {
- if ((st.st_mode & S_IFMT) == S_IFDIR)
- return 0;
- else
- return -ENOTDIR;
- }
+ r = is_dir(p);
+ if (r > 0)
+ return 0;
+ if (r == 0)
+ return -ENOTDIR;
/* create every parent directory in the path, except the last component */
p = path + strspn(path, "/");
for (;;) {
- int r;
- char *t;
+ char t[strlen(path) + 1];
e = p + strcspn(p, "/");
p = e + strspn(e, "/");
@@ -95,43 +102,32 @@ static int makedir_parents(const char *path, mode_t mode, bool apply) {
if (*p == 0)
return 0;
- t = strndup(path, e - path);
- if (!t)
- return -ENOMEM;
+ memcpy(t, path, e - path);
+ t[e-path] = 0;
- r = label_mkdir(t, mode, apply);
- free(t);
+ if (prefix && path_startswith(prefix, t))
+ continue;
+ r = _mkdir(t, mode);
if (r < 0 && errno != EEXIST)
return -errno;
}
}
int mkdir_parents(const char *path, mode_t mode) {
- return makedir_parents(path, mode, false);
-}
-
-int mkdir_parents_label(const char *path, mode_t mode) {
- return makedir_parents(path, mode, true);
-}
-
-static int is_dir(const char* path) {
- struct stat st;
- if (stat(path, &st) < 0)
- return -errno;
- return S_ISDIR(st.st_mode);
+ return mkdir_parents_internal(NULL, path, mode, mkdir);
}
-static int makedir_p(const char *path, mode_t mode, bool apply) {
+int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir) {
int r;
/* Like mkdir -p */
- r = makedir_parents(path, mode, apply);
+ r = mkdir_parents_internal(prefix, path, mode, _mkdir);
if (r < 0)
return r;
- r = label_mkdir(path, mode, apply);
+ r = _mkdir(path, mode);
if (r < 0 && (errno != EEXIST || is_dir(path) <= 0))
return -errno;
@@ -139,9 +135,9 @@ static int makedir_p(const char *path, mode_t mode, bool apply) {
}
int mkdir_p(const char *path, mode_t mode) {
- return makedir_p(path, mode, false);
+ return mkdir_p_internal(NULL, path, mode, mkdir);
}
-int mkdir_p_label(const char *path, mode_t mode) {
- return makedir_p(path, mode, true);
+int mkdir_p_prefix(const char *prefix, const char *path, mode_t mode) {
+ return mkdir_p_internal(prefix, path, mode, mkdir);
}
diff --git a/src/shared/mkdir.h b/src/shared/mkdir.h
index ce1c35e9ba..5b34db4229 100644
--- a/src/shared/mkdir.h
+++ b/src/shared/mkdir.h
@@ -7,6 +7,7 @@
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
@@ -22,11 +23,23 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-int mkdir_label(const char *path, mode_t mode);
+#include <sys/types.h>
+
int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid);
-int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid);
int mkdir_parents(const char *path, mode_t mode);
-int mkdir_parents_label(const char *path, mode_t mode);
int mkdir_p(const char *path, mode_t mode);
+int mkdir_p_prefix(const char *prefix, const char *path, mode_t mode);
+
+/* selinux versions */
+int mkdir_label(const char *path, mode_t mode);
+int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid);
+int mkdir_parents_label(const char *path, mode_t mode);
int mkdir_p_label(const char *path, mode_t mode);
+int mkdir_parents_prefix_label(const char *prefix, 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_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);
#endif
diff --git a/src/shared/output-mode.h b/src/shared/output-mode.h
index 0efd430c5d..9da789db76 100644
--- a/src/shared/output-mode.h
+++ b/src/shared/output-mode.h
@@ -23,6 +23,8 @@
typedef enum OutputMode {
OUTPUT_SHORT,
+ OUTPUT_SHORT_ISO,
+ OUTPUT_SHORT_PRECISE,
OUTPUT_SHORT_MONOTONIC,
OUTPUT_VERBOSE,
OUTPUT_EXPORT,
diff --git a/src/shared/path-util.c b/src/shared/path-util.c
index 0c1b6a0ab0..45099eeda8 100644
--- a/src/shared/path-util.c
+++ b/src/shared/path-util.c
@@ -102,7 +102,8 @@ char **path_split_and_make_absolute(const char *p) {
char **l;
assert(p);
- if (!(l = strv_split(p, ":")))
+ l = strv_split(p, ":");
+ if (!l)
return NULL;
if (!path_strv_make_absolute_cwd(l)) {
@@ -126,7 +127,7 @@ char *path_make_absolute(const char *p, const char *prefix) {
}
char *path_make_absolute_cwd(const char *p) {
- char *cwd, *r;
+ _cleanup_free_ char *cwd = NULL;
assert(p);
@@ -140,10 +141,7 @@ char *path_make_absolute_cwd(const char *p) {
if (!cwd)
return NULL;
- r = path_make_absolute(p, cwd);
- free(cwd);
-
- return r;
+ return path_make_absolute(p, cwd);
}
char **path_strv_make_absolute_cwd(char **l) {
@@ -156,7 +154,8 @@ char **path_strv_make_absolute_cwd(char **l) {
STRV_FOREACH(s, l) {
char *t;
- if (!(t = path_make_absolute_cwd(*s)))
+ t = path_make_absolute_cwd(*s);
+ if (!t)
return NULL;
free(*s);
@@ -426,3 +425,51 @@ int path_is_os_tree(const char *path) {
return r < 0 ? 0 : 1;
}
+
+int find_binary(const char *name, char **filename) {
+ assert(name);
+ if (strchr(name, '/')) {
+ char *p;
+
+ if (path_is_absolute(name))
+ p = strdup(name);
+ else
+ p = path_make_absolute_cwd(name);
+ if (!p)
+ return -ENOMEM;
+
+ *filename = p;
+ return 0;
+ } else {
+ const char *path;
+ char *state, *w;
+ size_t l;
+
+ /**
+ * Plain getenv, not secure_getenv, because we want
+ * to actually allow the user to pick the binary.
+ */
+ path = getenv("PATH");
+ if (!path)
+ path = DEFAULT_PATH;
+
+ FOREACH_WORD_SEPARATOR(w, l, path, ":", state) {
+ char *p;
+
+ if (asprintf(&p, "%.*s/%s", (int) l, w, name) < 0)
+ return -ENOMEM;
+
+ if (access(p, X_OK) < 0) {
+ free(p);
+ continue;
+ }
+
+ path_kill_slashes(p);
+ *filename = p;
+
+ return 0;
+ }
+
+ return -ENOENT;
+ }
+}
diff --git a/src/shared/path-util.h b/src/shared/path-util.h
index d187743769..0a42de7e27 100644
--- a/src/shared/path-util.h
+++ b/src/shared/path-util.h
@@ -25,6 +25,12 @@
#include "macro.h"
+#ifdef HAVE_SPLIT_USR
+# define DEFAULT_PATH "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+#else
+# define DEFAULT_PATH "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin"
+#endif
+
bool is_path(const char *p) _pure_;
char** path_split_and_make_absolute(const char *p);
char* path_get_file_name(const char *p) _pure_;
@@ -43,3 +49,15 @@ char** path_strv_canonicalize_uniq(char **l);
int path_is_mount_point(const char *path, bool allow_symlink);
int path_is_read_only_fs(const char *path);
int path_is_os_tree(const char *path);
+
+int find_binary(const char *name, char **filename);
+
+/* Iterates through the path prefixes of the specified path, going up
+ * 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); _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); _slash = strrchr((prefix), '/'))
diff --git a/src/shared/polkit.c b/src/shared/polkit.c
index cea7074ad3..1c5e9e3e0f 100644
--- a/src/shared/polkit.c
+++ b/src/shared/polkit.c
@@ -38,12 +38,8 @@ int verify_polkit(
#ifdef ENABLE_POLKIT
DBusMessage *m = NULL, *reply = NULL;
- const char *unix_process = "unix-process", *pid = "pid", *starttime = "start-time", *cancel_id = "";
+ const char *system_bus_name = "system-bus-name", *name = "name", *cancel_id = "";
uint32_t flags = interactive ? 1 : 0;
- pid_t pid_raw;
- uint32_t pid_u32;
- unsigned long long starttime_raw;
- uint64_t starttime_u64;
DBusMessageIter iter_msg, iter_struct, iter_array, iter_dict, iter_variant;
int r;
dbus_bool_t authorized = FALSE, challenge = FALSE;
@@ -68,14 +64,6 @@ int verify_polkit(
#ifdef ENABLE_POLKIT
- pid_raw = bus_get_unix_process_id(c, sender, error);
- if (pid_raw == 0)
- return -EINVAL;
-
- r = get_starttime_of_pid(pid_raw, &starttime_raw);
- if (r < 0)
- return r;
-
m = dbus_message_new_method_call(
"org.freedesktop.PolicyKit1",
"/org/freedesktop/PolicyKit1/Authority",
@@ -86,22 +74,13 @@ int verify_polkit(
dbus_message_iter_init_append(m, &iter_msg);
- pid_u32 = (uint32_t) pid_raw;
- starttime_u64 = (uint64_t) starttime_raw;
-
if (!dbus_message_iter_open_container(&iter_msg, DBUS_TYPE_STRUCT, NULL, &iter_struct) ||
- !dbus_message_iter_append_basic(&iter_struct, DBUS_TYPE_STRING, &unix_process) ||
+ !dbus_message_iter_append_basic(&iter_struct, DBUS_TYPE_STRING, &system_bus_name) ||
!dbus_message_iter_open_container(&iter_struct, DBUS_TYPE_ARRAY, "{sv}", &iter_array) ||
!dbus_message_iter_open_container(&iter_array, DBUS_TYPE_DICT_ENTRY, NULL, &iter_dict) ||
- !dbus_message_iter_append_basic(&iter_dict, DBUS_TYPE_STRING, &pid) ||
- !dbus_message_iter_open_container(&iter_dict, DBUS_TYPE_VARIANT, "u", &iter_variant) ||
- !dbus_message_iter_append_basic(&iter_variant, DBUS_TYPE_UINT32, &pid_u32) ||
- !dbus_message_iter_close_container(&iter_dict, &iter_variant) ||
- !dbus_message_iter_close_container(&iter_array, &iter_dict) ||
- !dbus_message_iter_open_container(&iter_array, DBUS_TYPE_DICT_ENTRY, NULL, &iter_dict) ||
- !dbus_message_iter_append_basic(&iter_dict, DBUS_TYPE_STRING, &starttime) ||
- !dbus_message_iter_open_container(&iter_dict, DBUS_TYPE_VARIANT, "t", &iter_variant) ||
- !dbus_message_iter_append_basic(&iter_variant, DBUS_TYPE_UINT64, &starttime_u64) ||
+ !dbus_message_iter_append_basic(&iter_dict, DBUS_TYPE_STRING, &name) ||
+ !dbus_message_iter_open_container(&iter_dict, DBUS_TYPE_VARIANT, "s", &iter_variant) ||
+ !dbus_message_iter_append_basic(&iter_variant, DBUS_TYPE_STRING, &sender) ||
!dbus_message_iter_close_container(&iter_dict, &iter_variant) ||
!dbus_message_iter_close_container(&iter_array, &iter_dict) ||
!dbus_message_iter_close_container(&iter_struct, &iter_array) ||
diff --git a/src/shared/refcnt.h b/src/shared/refcnt.h
new file mode 100644
index 0000000000..0502c20a2e
--- /dev/null
+++ b/src/shared/refcnt.h
@@ -0,0 +1,34 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#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 */
+
+typedef struct {
+ volatile unsigned _value;
+} RefCount;
+
+#define REFCNT_GET(r) ((r)._value)
+#define REFCNT_INC(r) (__sync_add_and_fetch(&(r)._value, 1))
+#define REFCNT_DEC(r) (__sync_sub_and_fetch(&(r)._value, 1))
+
+#define REFCNT_INIT ((RefCount) { ._value = 1 })
diff --git a/src/shared/replace-var.c b/src/shared/replace-var.c
index e11c57a43d..478fc43a38 100644
--- a/src/shared/replace-var.c
+++ b/src/shared/replace-var.c
@@ -24,6 +24,7 @@
#include "macro.h"
#include "util.h"
#include "replace-var.h"
+#include "def.h"
/*
* Generic infrastructure for replacing @FOO@ style variables in
@@ -40,7 +41,7 @@ static int get_variable(const char *b, char **r) {
if (*b != '@')
return 0;
- k = strspn(b + 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ_");
+ k = strspn(b + 1, UPPERCASE_LETTERS "_");
if (k <= 0 || b[k+1] != '@')
return 0;
diff --git a/src/shared/set.c b/src/shared/set.c
index c338dc3a44..5a4bf11bdf 100644
--- a/src/shared/set.c
+++ b/src/shared/set.c
@@ -50,9 +50,12 @@ int set_put(Set *s, void *value) {
}
int set_consume(Set *s, void *value) {
- int r = set_put(s, value);
+ int r;
+
+ r = set_put(s, value);
if (r < 0)
free(value);
+
return r;
}
diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c
index cd3238b405..d068bfce3c 100644
--- a/src/shared/sleep-config.c
+++ b/src/shared/sleep-config.c
@@ -163,6 +163,93 @@ int can_sleep_disk(char **types) {
return false;
}
+#define HIBERNATION_SWAP_THRESHOLD 0.98
+
+static int hibernation_partition_size(size_t *size, size_t *used) {
+ _cleanup_fclose_ FILE *f;
+ int i;
+
+ assert(size);
+ assert(used);
+
+ f = fopen("/proc/swaps", "r");
+ if (!f) {
+ log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
+ "Failed to retrieve open /proc/swaps: %m");
+ assert(errno > 0);
+ return -errno;
+ }
+
+ (void) fscanf(f, "%*s %*s %*s %*s %*s\n");
+
+ for (i = 1;; i++) {
+ _cleanup_free_ char *dev = NULL, *d = NULL, *type = NULL;
+ size_t size_field, used_field;
+ int k;
+
+ k = fscanf(f,
+ "%ms " /* device/file */
+ "%ms " /* type of swap */
+ "%zd " /* swap size */
+ "%zd " /* used */
+ "%*i\n", /* priority */
+ &dev, &type, &size_field, &used_field);
+ if (k != 4) {
+ if (k == EOF)
+ break;
+
+ log_warning("Failed to parse /proc/swaps:%u", i);
+ continue;
+ }
+
+ d = cunescape(dev);
+ if (!d)
+ return -ENOMEM;
+
+ if (!streq(type, "partition")) {
+ log_debug("Partition %s has type %s, ignoring.", d, type);
+ continue;
+ }
+
+ *size = size_field;
+ *used = used_field;
+ return 0;
+ }
+
+ log_debug("No swap partitions were found.");
+ return -ENOSYS;
+}
+
+static bool enough_memory_for_hibernation(void) {
+ _cleanup_free_ char *active = NULL;
+ unsigned long long act;
+ size_t size, used;
+ int r;
+
+ r = hibernation_partition_size(&size, &used);
+ if (r < 0)
+ return false;
+
+ r = get_status_field("/proc/meminfo", "\nActive(anon):", &active);
+ if (r < 0) {
+ log_error("Failed to retrieve Active(anon) from /proc/meminfo: %s", strerror(-r));
+ return false;
+ }
+
+ r = safe_atollu(active, &act);
+ if (r < 0) {
+ log_error("Failed to parse Active(anon) from /proc/meminfo: %s: %s",
+ active, strerror(-r));
+ return false;
+ }
+
+ r = act <= (size - used) * HIBERNATION_SWAP_THRESHOLD;
+ log_debug("Hibernation is %spossible, Active(anon)=%llu kB, size=%zu kB, used=%zu kB, threshold=%.2g%%",
+ r ? "" : "im", act, size, used, 100*HIBERNATION_SWAP_THRESHOLD);
+
+ return r;
+}
+
int can_sleep(const char *verb) {
_cleanup_strv_free_ char **modes = NULL, **states = NULL;
int r;
@@ -175,5 +262,8 @@ int can_sleep(const char *verb) {
if (r < 0)
return false;
- return can_sleep_state(states) && can_sleep_disk(modes);
+ if (!can_sleep_state(states) || !can_sleep_disk(modes))
+ return false;
+
+ return streq(verb, "suspend") || enough_memory_for_hibernation();
}
diff --git a/src/shared/socket-util.c b/src/shared/socket-util.c
index c583d3dfea..9224208244 100644
--- a/src/shared/socket-util.c
+++ b/src/shared/socket-util.c
@@ -486,16 +486,16 @@ bool socket_address_is_netlink(const SocketAddress *a, const char *s) {
return socket_address_equal(a, &b);
}
-bool socket_address_needs_mount(const SocketAddress *a, const char *prefix) {
+const char* socket_address_get_path(const SocketAddress *a) {
assert(a);
if (socket_address_family(a) != AF_UNIX)
- return false;
+ return NULL;
if (a->sockaddr.un.sun_path[0] == 0)
- return false;
+ return NULL;
- return path_startswith(a->sockaddr.un.sun_path, prefix);
+ return a->sockaddr.un.sun_path;
}
bool socket_ipv6_is_supported(void) {
diff --git a/src/shared/socket-util.h b/src/shared/socket-util.h
index 7829a337fc..e0b85adf9f 100644
--- a/src/shared/socket-util.h
+++ b/src/shared/socket-util.h
@@ -92,7 +92,7 @@ int make_socket_fd(const char* address, int flags);
bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) _pure_;
-bool socket_address_needs_mount(const SocketAddress *a, const char *prefix);
+const char* socket_address_get_path(const SocketAddress *a);
const char* socket_address_bind_ipv6_only_to_string(SocketAddressBindIPv6Only b) _const_;
SocketAddressBindIPv6Only socket_address_bind_ipv6_only_from_string(const char *s) _pure_;
diff --git a/src/shared/specifier.c b/src/shared/specifier.c
index 7577c91052..8fbf6db5df 100644
--- a/src/shared/specifier.c
+++ b/src/shared/specifier.c
@@ -20,6 +20,7 @@
***/
#include <string.h>
+#include <sys/utsname.h>
#include "macro.h"
#include "util.h"
@@ -31,21 +32,22 @@
*
*/
-char *specifier_printf(const char *text, const Specifier table[], void *userdata) {
- char *r, *t;
+int specifier_printf(const char *text, const Specifier table[], void *userdata, char **_ret) {
+ char *ret, *t;
const char *f;
bool percent = false;
size_t l;
+ int r;
assert(text);
assert(table);
l = strlen(text);
- r = new(char, l+1);
- if (!r)
- return NULL;
+ ret = new(char, l+1);
+ if (!ret)
+ return -ENOMEM;
- t = r;
+ t = ret;
for (f = text; *f; f++, l--) {
@@ -60,32 +62,31 @@ char *specifier_printf(const char *text, const Specifier table[], void *userdata
break;
if (i->lookup) {
- char *n, *w;
+ _cleanup_free_ char *w = NULL;
+ char *n;
size_t k, j;
- w = i->lookup(i->specifier, i->data, userdata);
- if (!w) {
- free(r);
- return NULL;
+ r = i->lookup(i->specifier, i->data, userdata, &w);
+ if (r < 0) {
+ free(ret);
+ return r;
}
- j = t - r;
+ j = t - ret;
k = strlen(w);
n = new(char, j + k + l + 1);
if (!n) {
- free(r);
- free(w);
- return NULL;
+ free(ret);
+ return -ENOMEM;
}
- memcpy(n, r, j);
+ memcpy(n, ret, j);
memcpy(n + j, w, k);
- free(r);
- free(w);
+ free(ret);
- r = n;
+ ret = n;
t = n + j + k;
} else {
*(t++) = '%';
@@ -101,47 +102,81 @@ char *specifier_printf(const char *text, const Specifier table[], void *userdata
}
*t = 0;
- return r;
+ *_ret = ret;
+ return 0;
}
/* Generic handler for simple string replacements */
-char* specifier_string(char specifier, void *data, void *userdata) {
- return strdup(strempty(data));
+int specifier_string(char specifier, void *data, void *userdata, char **ret) {
+ char *n;
+
+ n = strdup(strempty(data));
+ if (!n)
+ return -ENOMEM;
+
+ *ret = n;
+ return 0;
}
-char *specifier_machine_id(char specifier, void *data, void *userdata) {
+int specifier_machine_id(char specifier, void *data, void *userdata, char **ret) {
sd_id128_t id;
- char *buf;
+ char *n;
int r;
r = sd_id128_get_machine(&id);
if (r < 0)
- return NULL;
+ return r;
- buf = new(char, 33);
- if (!buf)
- return NULL;
+ n = new(char, 33);
+ if (!n)
+ return -ENOMEM;
- return sd_id128_to_string(id, buf);
+ *ret = sd_id128_to_string(id, n);
+ return 0;
}
-char *specifier_boot_id(char specifier, void *data, void *userdata) {
+int specifier_boot_id(char specifier, void *data, void *userdata, char **ret) {
sd_id128_t id;
- char *buf;
+ char *n;
int r;
r = sd_id128_get_boot(&id);
if (r < 0)
- return NULL;
+ return r;
+
+ n = new(char, 33);
+ if (!n)
+ return -ENOMEM;
+
+ *ret = sd_id128_to_string(id, n);
+ return 0;
+}
- buf = new(char, 33);
- if (!buf)
- return NULL;
+int specifier_host_name(char specifier, void *data, void *userdata, char **ret) {
+ char *n;
- return sd_id128_to_string(id, buf);
+ n = gethostname_malloc();
+ if (!n)
+ return -ENOMEM;
+
+ *ret = n;
+ return 0;
}
-char *specifier_host_name(char specifier, void *data, void *userdata) {
- return gethostname_malloc();
+int specifier_kernel_release(char specifier, void *data, void *userdata, char **ret) {
+ struct utsname uts;
+ char *n;
+ int r;
+
+ r = uname(&uts);
+ if (r < 0)
+ return -errno;
+
+ n = strdup(uts.release);
+ if (!n)
+ return -ENOMEM;
+
+ *ret = n;
+ return 0;
}
diff --git a/src/shared/specifier.h b/src/shared/specifier.h
index 0440dcac48..fca206f665 100644
--- a/src/shared/specifier.h
+++ b/src/shared/specifier.h
@@ -21,7 +21,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-typedef char* (*SpecifierCallback)(char specifier, void *data, void *userdata);
+typedef int (*SpecifierCallback)(char specifier, void *data, void *userdata, char **ret);
typedef struct Specifier {
const char specifier;
@@ -29,10 +29,11 @@ typedef struct Specifier {
void *data;
} Specifier;
-char *specifier_printf(const char *text, const Specifier table[], void *userdata);
+int specifier_printf(const char *text, const Specifier table[], void *userdata, char **ret);
-char *specifier_string(char specifier, void *data, void *userdata);
+int specifier_string(char specifier, void *data, void *userdata, char **ret);
-char *specifier_machine_id(char specifier, void *data, void *userdata);
-char *specifier_boot_id(char specifier, void *data, void *userdata);
-char *specifier_host_name(char specifier, void *data, void *userdata);
+int specifier_machine_id(char specifier, void *data, void *userdata, char **ret);
+int specifier_boot_id(char specifier, void *data, void *userdata, char **ret);
+int specifier_host_name(char specifier, void *data, void *userdata, char **ret);
+int specifier_kernel_release(char specifier, void *data, void *userdata, char **ret);
diff --git a/src/shared/strv.c b/src/shared/strv.c
index a5ce7e9593..adeee282b7 100644
--- a/src/shared/strv.c
+++ b/src/shared/strv.c
@@ -356,6 +356,43 @@ char *strv_join(char **l, const char *separator) {
return r;
}
+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:
+ free(buf);
+ return NULL;
+}
+
char **strv_append(char **l, const char *s) {
char **r, **k;
diff --git a/src/shared/strv.h b/src/shared/strv.h
index e35118752f..d1f2a0ef32 100644
--- a/src/shared/strv.h
+++ b/src/shared/strv.h
@@ -67,6 +67,7 @@ char **strv_split_quoted(const char *s);
char **strv_split_newlines(const char *s);
char *strv_join(char **l, const char *separator);
+char *strv_join_quoted(char **l);
char **strv_parse_nulstr(const char *s, size_t l);
char **strv_split_nulstr(const char *s);
diff --git a/src/shared/test-tables.h b/src/shared/test-tables.h
new file mode 100644
index 0000000000..3261302077
--- /dev/null
+++ b/src/shared/test-tables.h
@@ -0,0 +1,51 @@
+/***
+ 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 <stdio.h>
+#include <stdlib.h>
+
+typedef const char* (*lookup_t)(int);
+typedef int (*reverse_t)(const char*);
+
+static inline void _test_table(const char *name,
+ lookup_t lookup,
+ reverse_t reverse,
+ int size,
+ bool sparse) {
+ int i;
+
+ for (i = -1; i < size + 1; i++) {
+ const char* val = lookup(i);
+ int rev;
+
+ if (val)
+ rev = reverse(val);
+ else
+ rev = reverse("--no-such--value----");
+
+ printf("%s: %d → %s → %d\n", name, i, val, rev);
+ if (i >= 0 && i < size ?
+ sparse ? rev != i && rev != -1 : val == NULL || rev != i :
+ val != NULL || rev != -1)
+ exit(EXIT_FAILURE);
+ }
+}
+
+#define test_table(lower, upper) \
+ _test_table(STRINGIFY(lower), lower##_to_string, lower##_from_string, _##upper##_MAX, false)
diff --git a/src/shared/time-util.c b/src/shared/time-util.c
index 9ee711a49e..860be61e8b 100644
--- a/src/shared/time-util.c
+++ b/src/shared/time-util.c
@@ -168,6 +168,28 @@ char *format_timestamp(char *buf, size_t l, usec_t t) {
return buf;
}
+char *format_timestamp_us(char *buf, size_t l, usec_t t) {
+ struct tm tm;
+ time_t sec;
+
+ assert(buf);
+ assert(l > 0);
+
+ if (t <= 0)
+ return NULL;
+
+ sec = (time_t) (t / USEC_PER_SEC);
+ localtime_r(&sec, &tm);
+
+ if (strftime(buf, l, "%a %Y-%m-%d %H:%M:%S", &tm) <= 0)
+ return NULL;
+ snprintf(buf + strlen(buf), l - strlen(buf), ".%06llu", t % USEC_PER_SEC);
+ if (strftime(buf + strlen(buf), l - strlen(buf), " %Z", &tm) <= 0)
+ return NULL;
+
+ return buf;
+}
+
char *format_timestamp_relative(char *buf, size_t l, usec_t t) {
usec_t n, d;
diff --git a/src/shared/time-util.h b/src/shared/time-util.h
index f27a006891..7660fe1872 100644
--- a/src/shared/time-util.h
+++ b/src/shared/time-util.h
@@ -73,6 +73,7 @@ usec_t timeval_load(const struct timeval *tv) _pure_;
struct timeval *timeval_store(struct timeval *tv, usec_t u);
char *format_timestamp(char *buf, size_t l, usec_t t);
+char *format_timestamp_us(char *buf, size_t l, usec_t t);
char *format_timestamp_relative(char *buf, size_t l, usec_t t);
char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy);
diff --git a/src/shared/unit-name.c b/src/shared/unit-name.c
index a809713595..bc8094d112 100644
--- a/src/shared/unit-name.c
+++ b/src/shared/unit-name.c
@@ -26,11 +26,10 @@
#include "path-util.h"
#include "util.h"
#include "unit-name.h"
+#include "def.h"
#define VALID_CHARS \
- "0123456789" \
- "abcdefghijklmnopqrstuvwxyz" \
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
+ DIGITS LETTERS \
":-_.\\"
static const char* const unit_type_table[_UNIT_TYPE_MAX] = {
@@ -44,6 +43,8 @@ static const char* const unit_type_table[_UNIT_TYPE_MAX] = {
[UNIT_TIMER] = "timer",
[UNIT_SWAP] = "swap",
[UNIT_PATH] = "path",
+ [UNIT_SLICE] = "slice",
+ [UNIT_SCOPE] = "scope"
};
DEFINE_STRING_TABLE_LOOKUP(unit_type, UnitType);
@@ -51,6 +52,7 @@ 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_ERROR] = "error",
[UNIT_MERGED] = "merged",
[UNIT_MASKED] = "masked"
@@ -184,6 +186,7 @@ char *unit_name_change_suffix(const char *n, const char *suffix) {
assert(n);
assert(unit_name_is_valid(n, true));
assert(suffix);
+ assert(suffix[0] == '.');
assert_se(e = strrchr(n, '.'));
a = e - n;
@@ -298,7 +301,7 @@ char *unit_name_path_escape(const char *f) {
path_kill_slashes(p);
- if (streq(p, "/")) {
+ if (streq(p, "/") || streq(p, "")) {
free(p);
return strdup("-");
}
@@ -401,7 +404,6 @@ char *unit_name_template(const char *f) {
strcpy(mempcpy(r, f, a), e);
return r;
-
}
char *unit_name_from_path(const char *path, const char *suffix) {
@@ -453,7 +455,7 @@ char *unit_name_to_path(const char *name) {
}
char *unit_dbus_path_from_name(const char *name) {
- char *e, *p;
+ _cleanup_free_ char *e = NULL;
assert(name);
@@ -461,10 +463,23 @@ char *unit_dbus_path_from_name(const char *name) {
if (!e)
return NULL;
- p = strappend("/org/freedesktop/systemd1/unit/", e);
- free(e);
+ 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;
- return p;
+ n = bus_path_unescape(e);
+ if (!n)
+ return -ENOMEM;
+
+ *name = n;
+ return 0;
}
char *unit_name_mangle(const char *name) {
@@ -506,16 +521,18 @@ char *unit_name_mangle(const char *name) {
return r;
}
-char *snapshot_name_mangle(const char *name) {
+char *unit_name_mangle_with_suffix(const char *name, const char *suffix) {
char *r, *t;
const char *f;
assert(name);
+ assert(suffix);
+ assert(suffix[0] == '.');
/* Similar to unit_name_mangle(), but is called when we know
* that this is about snapshot units. */
- r = new(char, strlen(name) * 4 + 1 + sizeof(".snapshot")-1);
+ r = new(char, strlen(name) * 4 + strlen(suffix) + 1);
if (!r)
return NULL;
@@ -528,8 +545,8 @@ char *snapshot_name_mangle(const char *name) {
*(t++) = *f;
}
- if (!endswith(name, ".snapshot"))
- strcpy(t, ".snapshot");
+ if (!endswith(name, suffix))
+ strcpy(t, suffix);
else
*t = 0;
@@ -547,3 +564,30 @@ UnitType unit_name_to_type(const char *n) {
return unit_type_from_string(e + 1);
}
+
+int build_subslice(const char *slice, const char*name, char **subslice) {
+ char *ret;
+
+ assert(slice);
+ assert(name);
+ assert(subslice);
+
+ if (streq(slice, "-.slice"))
+ ret = strappend(name, ".slice");
+ else {
+ char *e;
+
+ e = endswith(slice, ".slice");
+ if (!e)
+ return -EINVAL;
+
+ ret = new(char, (e - slice) + 1 + strlen(name) + 6 + 1);
+ if (!ret)
+ return -ENOMEM;
+
+ stpcpy(stpcpy(stpcpy(mempcpy(ret, slice, e - slice), "-"), name), ".slice");
+ }
+
+ *subslice = ret;
+ return 0;
+}
diff --git a/src/shared/unit-name.h b/src/shared/unit-name.h
index 9eca8eb3c1..20138df089 100644
--- a/src/shared/unit-name.h
+++ b/src/shared/unit-name.h
@@ -41,6 +41,8 @@ enum UnitType {
UNIT_TIMER,
UNIT_SWAP,
UNIT_PATH,
+ UNIT_SLICE,
+ UNIT_SCOPE,
_UNIT_TYPE_MAX,
_UNIT_TYPE_INVALID = -1
};
@@ -48,6 +50,7 @@ enum UnitType {
enum UnitLoadState {
UNIT_STUB = 0,
UNIT_LOADED,
+ UNIT_NOT_FOUND,
UNIT_ERROR,
UNIT_MERGED,
UNIT_MASKED,
@@ -92,6 +95,9 @@ char *unit_name_from_path_instance(const char *prefix, const char *path, const c
char *unit_name_to_path(const char *name);
char *unit_dbus_path_from_name(const char *name);
+int unit_name_from_dbus_path(const char *path, char **name);
char *unit_name_mangle(const char *name);
-char *snapshot_name_mangle(const char *name);
+char *unit_name_mangle_with_suffix(const char *name, const char *suffix);
+
+int build_subslice(const char *slice, const char*name, char **subslice);
diff --git a/src/shared/utf8.c b/src/shared/utf8.c
index 3964e8b1ce..a8e28accd3 100644
--- a/src/shared/utf8.c
+++ b/src/shared/utf8.c
@@ -3,6 +3,7 @@
/***
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
@@ -19,7 +20,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-/* This file is based on the GLIB utf8 validation functions. The
+/* Parts of this file are based on the GLIB utf8 validation functions. The
* original license text follows. */
/* gutf8.c - Operations on UTF-8 strings.
@@ -51,8 +52,6 @@
#include "utf8.h"
#include "util.h"
-#define FILTER_CHAR '_'
-
static inline bool is_unicode_valid(uint32_t ch) {
if (ch >= 0x110000) /* End of unicode space */
@@ -67,17 +66,6 @@ static inline bool is_unicode_valid(uint32_t ch) {
return true;
}
-static inline bool is_continuation_char(uint8_t ch) {
- if ((ch & 0xc0) != 0x80) /* 10xxxxxx */
- return false;
- return true;
-}
-
-static inline void merge_continuation_char(uint32_t *u_ch, uint8_t ch) {
- *u_ch <<= 6;
- *u_ch |= ch & 0x3f;
-}
-
static bool is_unicode_control(uint32_t ch) {
/*
@@ -86,170 +74,101 @@ static bool is_unicode_control(uint32_t ch) {
'\t' is in C0 range, but more or less harmless and commonly used.
*/
- return (ch < ' ' && ch != '\t') ||
+ return (ch < ' ' && ch != '\t' && ch != '\n') ||
(0x7F <= ch && ch <= 0x9F);
}
-char* utf8_is_printable_n(const char* str, size_t length) {
- uint32_t val = 0;
- uint32_t min = 0;
- const uint8_t *p;
-
- assert(str);
-
- for (p = (const uint8_t*) str; length; p++, length--) {
- if (*p < 128) {
- val = *p;
- } else {
- if ((*p & 0xe0) == 0xc0) { /* 110xxxxx two-char seq. */
- min = 128;
- val = (uint32_t) (*p & 0x1e);
- goto ONE_REMAINING;
- } else if ((*p & 0xf0) == 0xe0) { /* 1110xxxx three-char seq.*/
- min = (1 << 11);
- val = (uint32_t) (*p & 0x0f);
- goto TWO_REMAINING;
- } else if ((*p & 0xf8) == 0xf0) { /* 11110xxx four-char seq */
- min = (1 << 16);
- val = (uint32_t) (*p & 0x07);
- } else
- goto error;
-
- p++;
- length--;
- if (!length || !is_continuation_char(*p))
- goto error;
- merge_continuation_char(&val, *p);
-
- TWO_REMAINING:
- p++;
- length--;
- if (!is_continuation_char(*p))
- goto error;
- merge_continuation_char(&val, *p);
-
- ONE_REMAINING:
- p++;
- length--;
- if (!is_continuation_char(*p))
- goto error;
- merge_continuation_char(&val, *p);
-
- if (val < min)
- goto error;
- }
+/* count of characters used to encode one unicode char */
+static int utf8_encoded_expected_len(const char *str) {
+ unsigned char c = (unsigned char)str[0];
+
+ if (c < 0x80)
+ return 1;
+ if ((c & 0xe0) == 0xc0)
+ return 2;
+ if ((c & 0xf0) == 0xe0)
+ return 3;
+ if ((c & 0xf8) == 0xf0)
+ return 4;
+ if ((c & 0xfc) == 0xf8)
+ return 5;
+ if ((c & 0xfe) == 0xfc)
+ return 6;
+ return 0;
+}
- if (is_unicode_control(val))
- goto error;
+/* decode one unicode char */
+static int utf8_encoded_to_unichar(const char *str) {
+ int unichar;
+ int len;
+ int i;
+
+ len = utf8_encoded_expected_len(str);
+ switch (len) {
+ case 1:
+ return (int)str[0];
+ case 2:
+ unichar = str[0] & 0x1f;
+ break;
+ case 3:
+ unichar = (int)str[0] & 0x0f;
+ break;
+ case 4:
+ unichar = (int)str[0] & 0x07;
+ break;
+ case 5:
+ unichar = (int)str[0] & 0x03;
+ break;
+ case 6:
+ unichar = (int)str[0] & 0x01;
+ break;
+ default:
+ return -1;
}
- return (char*) str;
+ for (i = 1; i < len; i++) {
+ if (((int)str[i] & 0xc0) != 0x80)
+ return -1;
+ unichar <<= 6;
+ unichar |= (int)str[i] & 0x3f;
+ }
-error:
- return NULL;
+ return unichar;
}
-static char* utf8_validate(const char *str, char *output) {
- uint32_t val = 0;
- uint32_t min = 0;
- const uint8_t *p, *last;
- int size;
- uint8_t *o;
+bool utf8_is_printable(const char* str, size_t length) {
+ const uint8_t *p;
assert(str);
- o = (uint8_t*) output;
- for (p = (const uint8_t*) str; *p; p++) {
- if (*p < 128) {
- if (o)
- *o = *p;
- } else {
- last = p;
-
- if ((*p & 0xe0) == 0xc0) { /* 110xxxxx two-char seq. */
- size = 2;
- min = 128;
- val = (uint32_t) (*p & 0x1e);
- goto ONE_REMAINING;
- } else if ((*p & 0xf0) == 0xe0) { /* 1110xxxx three-char seq.*/
- size = 3;
- min = (1 << 11);
- val = (uint32_t) (*p & 0x0f);
- goto TWO_REMAINING;
- } else if ((*p & 0xf8) == 0xf0) { /* 11110xxx four-char seq */
- size = 4;
- min = (1 << 16);
- val = (uint32_t) (*p & 0x07);
- } else
- goto error;
-
- p++;
- if (!is_continuation_char(*p))
- goto error;
- merge_continuation_char(&val, *p);
-
- TWO_REMAINING:
- p++;
- if (!is_continuation_char(*p))
- goto error;
- merge_continuation_char(&val, *p);
-
- ONE_REMAINING:
- p++;
- if (!is_continuation_char(*p))
- goto error;
- merge_continuation_char(&val, *p);
-
- if (val < min)
- goto error;
-
- if (!is_unicode_valid(val))
- goto error;
-
- if (o) {
- memcpy(o, last, (size_t) size);
- o += size;
- }
-
- continue;
-
- error:
- if (o) {
- *o = FILTER_CHAR;
- p = last; /* We retry at the next character */
- } else
- goto failure;
- }
+ for (p = (const uint8_t*) str; length; p++) {
+ int encoded_len = utf8_encoded_valid_unichar((const char *)p);
+ int32_t val = utf8_encoded_to_unichar((const char*)p);
- if (o)
- o++;
- }
+ if (encoded_len < 0 || val < 0 || is_unicode_control(val))
+ return false;
- if (o) {
- *o = '\0';
- return output;
+ length -= encoded_len;
}
- return (char*) str;
-
-failure:
- return NULL;
-}
-
-char* utf8_is_valid (const char *str) {
- return utf8_validate(str, NULL);
+ return true;
}
-char* utf8_filter (const char *str) {
- char *new_str;
+const char *utf8_is_valid(const char *str) {
+ const uint8_t *p;
assert(str);
- new_str = malloc(strlen(str) + 1);
- if (!new_str)
- return NULL;
+ for (p = (const uint8_t*) str; *p; ) {
+ int len = utf8_encoded_valid_unichar((const char *)p);
- return utf8_validate(str, new_str);
+ if (len < 0)
+ return NULL;
+
+ p += len;
+ }
+
+ return str;
}
char *ascii_is_valid(const char *str) {
@@ -320,3 +239,50 @@ char *utf16_to_utf8(const void *s, size_t length) {
return r;
}
+
+/* expected size used to encode one unicode char */
+static int utf8_unichar_to_encoded_len(int unichar) {
+ if (unichar < 0x80)
+ return 1;
+ if (unichar < 0x800)
+ return 2;
+ if (unichar < 0x10000)
+ return 3;
+ if (unichar < 0x200000)
+ return 4;
+ if (unichar < 0x4000000)
+ return 5;
+ return 6;
+}
+
+/* validate one encoded unicode char and return its length */
+int utf8_encoded_valid_unichar(const char *str) {
+ int len;
+ int unichar;
+ int i;
+
+ len = utf8_encoded_expected_len(str);
+ if (len == 0)
+ return -1;
+
+ /* ascii is valid */
+ if (len == 1)
+ return 1;
+
+ /* check if expected encoded chars are available */
+ for (i = 0; i < len; i++)
+ if ((str[i] & 0x80) != 0x80)
+ return -1;
+
+ unichar = utf8_encoded_to_unichar(str);
+
+ /* check if encoded length matches encoded value */
+ if (utf8_unichar_to_encoded_len(unichar) != len)
+ return -1;
+
+ /* check if value has valid range */
+ if (!is_unicode_valid(unichar))
+ return -1;
+
+ return len;
+}
diff --git a/src/shared/utf8.h b/src/shared/utf8.h
index 794ae15ab9..96a03ea7cb 100644
--- a/src/shared/utf8.h
+++ b/src/shared/utf8.h
@@ -21,14 +21,17 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stdbool.h>
+
#include "macro.h"
-char *utf8_is_valid(const char *s) _pure_;
+const char *utf8_is_valid(const char *s) _pure_;
char *ascii_is_valid(const char *s) _pure_;
-char *utf8_is_printable_n(const char* str, size_t length) _pure_;
+bool utf8_is_printable(const char* str, size_t length) _pure_;
-char *utf8_filter(const char *s);
char *ascii_filter(const char *s);
char *utf16_to_utf8(const void *s, size_t length);
+
+int utf8_encoded_valid_unichar(const char *str);
diff --git a/src/shared/util.c b/src/shared/util.c
index 673e0da6b6..9be6acfc8f 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -73,6 +73,7 @@
#include "hashmap.h"
#include "env-util.h"
#include "fileio.h"
+#include "device-nodes.h"
int saved_argc = 0;
char **saved_argv = NULL;
@@ -128,40 +129,6 @@ char* endswith(const char *s, const char *postfix) {
return (char*) s + sl - pl;
}
-char* startswith(const char *s, const char *prefix) {
- const char *a, *b;
-
- assert(s);
- assert(prefix);
-
- a = s, b = prefix;
- for (;;) {
- if (*b == 0)
- return (char*) a;
- if (*a != *b)
- return NULL;
-
- a++, b++;
- }
-}
-
-char* startswith_no_case(const char *s, const char *prefix) {
- const char *a, *b;
-
- assert(s);
- assert(prefix);
-
- a = s, b = prefix;
- for (;;) {
- if (*b == 0)
- return (char*) a;
- if (tolower(*a) != tolower(*b))
- return NULL;
-
- a++, b++;
- }
-}
-
bool first_word(const char *s, const char *word) {
size_t sl, wl;
@@ -367,7 +334,7 @@ int safe_atolli(const char *s, long long int *ret_lli) {
int safe_atod(const char *s, double *ret_d) {
char *x = NULL;
- double d;
+ double d = 0;
assert(s);
assert(ret_d);
@@ -726,9 +693,24 @@ int is_kernel_thread(pid_t pid) {
return 0;
}
+int get_process_capeff(pid_t pid, char **capeff) {
+ const char *p;
+
+ assert(capeff);
+ assert(pid >= 0);
+
+ if (pid == 0)
+ p = "/proc/self/status";
+ else
+ p = procfs_file_alloca(pid, "status");
+
+ return get_status_field(p, "\nCapEff:", capeff);
+}
int get_process_exe(pid_t pid, char **name) {
const char *p;
+ char *d;
+ int r;
assert(pid >= 0);
assert(name);
@@ -738,7 +720,15 @@ int get_process_exe(pid_t pid, char **name) {
else
p = procfs_file_alloca(pid, "exe");
- return readlink_malloc(p, name);
+ r = readlink_malloc(p, name);
+ if (r < 0)
+ return r;
+
+ d = endswith(*name, " (deleted)");
+ if (d)
+ *d = '\0';
+
+ return 0;
}
static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
@@ -850,18 +840,18 @@ int readlink_malloc(const char *p, char **r) {
}
int readlink_and_make_absolute(const char *p, char **r) {
- char *target, *k;
+ _cleanup_free_ char *target = NULL;
+ char *k;
int j;
assert(p);
assert(r);
- if ((j = readlink_malloc(p, &target)) < 0)
+ j = readlink_malloc(p, &target);
+ if (j < 0)
return j;
k = file_in_same_dir(p, target);
- free(target);
-
if (!k)
return -ENOMEM;
@@ -1600,6 +1590,7 @@ bool fstype_is_network(const char *fstype) {
"cifs\0"
"smbfs\0"
"ncpfs\0"
+ "ncp\0"
"nfs\0"
"nfs4\0"
"gfs\0"
@@ -1830,8 +1821,10 @@ int open_terminal(const char *name, int mode) {
* https://bugs.launchpad.net/ubuntu/+source/linux/+bug/554172/comments/245
*/
+ assert(!(mode & O_CREAT));
+
for (;;) {
- fd = open(name, mode);
+ fd = open(name, mode, 0);
if (fd >= 0)
break;
@@ -2193,8 +2186,10 @@ ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
return n > 0 ? n : -errno;
}
- if (pollfd.revents != POLLIN)
- return n > 0 ? n : -EIO;
+ /* We knowingly ignore the revents value here,
+ * and expect that any error/EOF is reported
+ * via read()/write()
+ */
continue;
}
@@ -2241,8 +2236,10 @@ ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
return n > 0 ? n : -errno;
}
- if (pollfd.revents != POLLOUT)
- return n > 0 ? n : -EIO;
+ /* We knowingly ignore the revents value here,
+ * and expect that any error/EOF is reported
+ * via read()/write()
+ */
continue;
}
@@ -2261,7 +2258,7 @@ ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
int parse_bytes(const char *t, off_t *bytes) {
static const struct {
const char *suffix;
- off_t factor;
+ unsigned long long factor;
} table[] = {
{ "B", 1 },
{ "K", 1024ULL },
@@ -2274,7 +2271,7 @@ int parse_bytes(const char *t, off_t *bytes) {
};
const char *p;
- off_t r = 0;
+ unsigned long long r = 0;
assert(t);
assert(bytes);
@@ -2301,7 +2298,17 @@ int parse_bytes(const char *t, off_t *bytes) {
for (i = 0; i < ELEMENTSOF(table); i++)
if (startswith(e, table[i].suffix)) {
- r += (off_t) l * table[i].factor;
+ unsigned long long tmp;
+ if ((unsigned long long) l > ULLONG_MAX / table[i].factor)
+ return -ERANGE;
+ tmp = l * table[i].factor;
+ if (tmp > ULLONG_MAX - r)
+ return -ERANGE;
+
+ r += tmp;
+ if ((unsigned long long) (off_t) r != r)
+ return -ERANGE;
+
p = e + strlen(table[i].suffix);
break;
}
@@ -2309,7 +2316,7 @@ int parse_bytes(const char *t, off_t *bytes) {
if (i >= ELEMENTSOF(table))
return -EINVAL;
- } while (*p != 0);
+ } while (*p);
*bytes = r;
@@ -2417,6 +2424,25 @@ fallback:
return random() * RAND_MAX + random();
}
+unsigned random_u(void) {
+ _cleanup_close_ int fd;
+ unsigned u;
+ ssize_t r;
+
+ fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
+ if (fd < 0)
+ goto fallback;
+
+ r = loop_read(fd, &u, sizeof(u), true);
+ if (r != sizeof(u))
+ goto fallback;
+
+ return u;
+
+fallback:
+ return random() * RAND_MAX + random();
+}
+
void rename_process(const char name[8]) {
assert(name);
@@ -2773,8 +2799,8 @@ int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct
_pure_ static int is_temporary_fs(struct statfs *s) {
assert(s);
return
- F_TYPE_CMP(s->f_type, TMPFS_MAGIC) ||
- F_TYPE_CMP(s->f_type, RAMFS_MAGIC);
+ F_TYPE_EQUAL(s->f_type, TMPFS_MAGIC) ||
+ F_TYPE_EQUAL(s->f_type, RAMFS_MAGIC);
}
int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
@@ -3275,7 +3301,7 @@ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne
r = new0(char, new_length+1);
if (!r)
- return r;
+ return NULL;
x = (new_length * percent) / 100;
@@ -3465,7 +3491,9 @@ DIR *xopendirat(int fd, const char *name, int flags) {
int nfd;
DIR *d;
- nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags);
+ assert(!(flags & O_CREAT));
+
+ nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags, 0);
if (nfd < 0)
return NULL;
@@ -3491,26 +3519,23 @@ int signal_from_string_try_harder(const char *s) {
}
static char *tag_to_udev_node(const char *tagvalue, const char *by) {
- char *dn, *t, *u;
- int r;
-
- /* FIXME: to follow udev's logic 100% we need to leave valid
- * UTF8 chars unescaped */
+ _cleanup_free_ char *t = NULL, *u = NULL;
+ char *dn;
+ size_t enc_len;
u = unquote(tagvalue, "\"\'");
if (u == NULL)
return NULL;
- t = xescape(u, "/ ");
- free(u);
-
+ enc_len = strlen(u) * 4;
+ t = new(char, enc_len);
if (t == NULL)
return NULL;
- r = asprintf(&dn, "/dev/disk/by-%s/%s", by, t);
- free(t);
+ if (encode_devnode_name(u, t, enc_len) < 0)
+ return NULL;
- if (r < 0)
+ if (asprintf(&dn, "/dev/disk/by-%s/%s", by, t) < 0)
return NULL;
return dn;
@@ -4343,7 +4368,7 @@ int in_group(const char *name) {
int glob_exists(const char *path) {
_cleanup_globfree_ glob_t g = {};
- int r, k;
+ int k;
assert(path);
@@ -4351,15 +4376,37 @@ int glob_exists(const char *path) {
k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
if (k == GLOB_NOMATCH)
- r = 0;
+ return 0;
else if (k == GLOB_NOSPACE)
- r = -ENOMEM;
+ return -ENOMEM;
else if (k == 0)
- r = !strv_isempty(g.gl_pathv);
+ return !strv_isempty(g.gl_pathv);
else
- r = errno ? -errno : -EIO;
+ return errno ? -errno : -EIO;
+}
- return r;
+int glob_extend(char ***strv, const char *path) {
+ _cleanup_globfree_ glob_t g = {};
+ int k;
+ char **p;
+
+ errno = 0;
+ k = glob(optarg, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
+
+ if (k == GLOB_NOMATCH)
+ return -ENOENT;
+ else if (k == GLOB_NOSPACE)
+ return -ENOMEM;
+ else if (k != 0 || strv_isempty(g.gl_pathv))
+ return errno ? -errno : -EIO;
+
+ STRV_FOREACH(p, g.gl_pathv) {
+ k = strv_extend(strv, *p);
+ if (k < 0)
+ break;
+ }
+
+ return k;
}
int dirent_ensure_type(DIR *d, struct dirent *de) {
@@ -4388,38 +4435,31 @@ int dirent_ensure_type(DIR *d, struct dirent *de) {
}
int in_search_path(const char *path, char **search) {
- char **i, *parent;
+ char **i;
+ _cleanup_free_ char *parent = NULL;
int r;
r = path_get_parent(path, &parent);
if (r < 0)
return r;
- r = 0;
-
- STRV_FOREACH(i, search) {
- if (path_equal(parent, *i)) {
- r = 1;
- break;
- }
- }
-
- free(parent);
+ STRV_FOREACH(i, search)
+ if (path_equal(parent, *i))
+ return 1;
- return r;
+ return 0;
}
int get_files_in_directory(const char *path, char ***list) {
- DIR *d;
- int r = 0;
- unsigned n = 0;
- char **l = NULL;
+ _cleanup_closedir_ DIR *d = NULL;
+ size_t bufsize = 0, n = 0;
+ _cleanup_strv_free_ char **l = NULL;
assert(path);
/* Returns all files in a directory in *list, and the number
* of files as return value. If list is NULL returns only the
- * number */
+ * number. */
d = opendir(path);
if (!d)
@@ -4431,11 +4471,9 @@ int get_files_in_directory(const char *path, char ***list) {
int k;
k = readdir_r(d, &buf.de, &de);
- if (k != 0) {
- r = -k;
- goto finish;
- }
-
+ assert(k >= 0);
+ if (k > 0)
+ return -k;
if (!de)
break;
@@ -4445,43 +4483,25 @@ int get_files_in_directory(const char *path, char ***list) {
continue;
if (list) {
- if ((unsigned) r >= n) {
- char **t;
-
- n = MAX(16, 2*r);
- t = realloc(l, sizeof(char*) * n);
- if (!t) {
- r = -ENOMEM;
- goto finish;
- }
-
- l = t;
- }
-
- assert((unsigned) r < n);
+ /* one extra slot is needed for the terminating NULL */
+ if (!GREEDY_REALLOC(l, bufsize, n + 2))
+ return -ENOMEM;
- l[r] = strdup(de->d_name);
- if (!l[r]) {
- r = -ENOMEM;
- goto finish;
- }
+ l[n] = strdup(de->d_name);
+ if (!l[n])
+ return -ENOMEM;
- l[++r] = NULL;
+ l[++n] = NULL;
} else
- r++;
+ n++;
}
-finish:
- if (d)
- closedir(d);
-
- if (r >= 0) {
- if (list)
- *list = l;
- } else
- strv_free(l);
+ if (list) {
+ *list = l;
+ l = NULL; /* avoid freeing */
+ }
- return r;
+ return n;
}
char *strjoin(const char *x, ...) {
@@ -5264,13 +5284,17 @@ bool string_is_safe(const char *p) {
return true;
}
+/**
+ * Check if a string contains control characters.
+ * Spaces and tabs are not considered control characters.
+ */
bool string_has_cc(const char *p) {
const char *t;
assert(p);
for (t = p; *t; t++)
- if (*t > 0 && *t < ' ')
+ if (*t > 0 && *t < ' ' && *t != '\t')
return true;
return false;
@@ -5343,20 +5367,24 @@ bool is_locale_utf8(void) {
goto out;
}
- /* For LC_CTYPE=="C" return true,
- * because CTYPE is effectly unset and
- * everything defaults to UTF-8 nowadays. */
-
+ /* For LC_CTYPE=="C" return true, because CTYPE is effectly
+ * unset and everything can do to UTF-8 nowadays. */
set = setlocale(LC_CTYPE, NULL);
if (!set) {
cached_answer = true;
goto out;
}
- cached_answer = streq(set, "C");
+ /* Check result, but ignore the result if C was set
+ * explicitly. */
+ cached_answer =
+ streq(set, "C") &&
+ !getenv("LC_ALL") &&
+ !getenv("LC_CTYPE") &&
+ !getenv("LANG");
out:
- return (bool)cached_answer;
+ return (bool) cached_answer;
}
const char *draw_special_char(DrawSpecialChar ch) {
@@ -5671,7 +5699,7 @@ int search_and_fopen_nulstr(const char *path, const char *mode, const char *sear
int create_tmp_dir(char template[], char** dir_name) {
int r = 0;
- char *d, *dt;
+ char *d = NULL, *dt;
assert(dir_name);
@@ -5847,3 +5875,48 @@ bool id128_is_valid(const char *s) {
return true;
}
+
+void parse_user_at_host(char *arg, char **user, char **host) {
+ assert(arg);
+ assert(user);
+ assert(host);
+
+ *host = strchr(arg, '@');
+ if (*host == NULL)
+ *host = arg;
+ else {
+ *host[0]++ = '\0';
+ *user = arg;
+ }
+}
+
+int split_pair(const char *s, const char *sep, char **l, char **r) {
+ char *x, *a, *b;
+
+ assert(s);
+ assert(sep);
+ assert(l);
+ assert(r);
+
+ if (isempty(sep))
+ return -EINVAL;
+
+ x = strstr(s, sep);
+ if (!x)
+ return -EINVAL;
+
+ a = strndup(s, x - s);
+ if (!a)
+ return -ENOMEM;
+
+ b = strdup(x + strlen(sep));
+ if (!b) {
+ free(a);
+ return -ENOMEM;
+ }
+
+ *l = a;
+ *r = b;
+
+ return 0;
+}
diff --git a/src/shared/util.h b/src/shared/util.h
index 64e63b8c07..1b845b3803 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -106,9 +106,19 @@ static inline bool isempty(const char *p) {
return !p || !p[0];
}
+static inline const char *startswith(const char *s, const char *prefix) {
+ if (strncmp(s, prefix, strlen(prefix)) == 0)
+ return s + strlen(prefix);
+ return NULL;
+}
+
+static inline const char *startswith_no_case(const char *s, const char *prefix) {
+ if (strncasecmp(s, prefix, strlen(prefix)) == 0)
+ return s + strlen(prefix);
+ return NULL;
+}
+
char *endswith(const char *s, const char *postfix) _pure_;
-char *startswith(const char *s, const char *prefix) _pure_;
-char *startswith_no_case(const char *s, const char *prefix) _pure_;
bool first_word(const char *s, const char *word) _pure_;
@@ -210,6 +220,7 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
int get_process_exe(pid_t pid, char **name);
int get_process_uid(pid_t pid, uid_t *uid);
int get_process_gid(pid_t pid, gid_t *gid);
+int get_process_capeff(pid_t pid, char **capeff);
char hexchar(int x) _const_;
int unhexchar(char c) _const_;
@@ -242,6 +253,7 @@ int make_null_stdio(void);
int make_console_stdio(void);
unsigned long long random_ull(void);
+unsigned random_u(void);
/* For basic lookup tables with strictly enumerated entries */
#define __DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \
@@ -373,6 +385,22 @@ void columns_lines_cache_reset(int _unused_ signum);
bool on_tty(void);
+static inline const char *ansi_highlight(void) {
+ return on_tty() ? ANSI_HIGHLIGHT_ON : "";
+}
+
+static inline const char *ansi_highlight_red(void) {
+ return on_tty() ? ANSI_HIGHLIGHT_RED_ON : "";
+}
+
+static inline const char *ansi_highlight_green(void) {
+ return on_tty() ? ANSI_HIGHLIGHT_GREEN_ON : "";
+}
+
+static inline const char *ansi_highlight_off(void) {
+ return on_tty() ? ANSI_HIGHLIGHT_OFF : "";
+}
+
int running_in_chroot(void);
char *ellipsize(const char *s, size_t length, unsigned percent);
@@ -439,6 +467,7 @@ char* uid_to_name(uid_t uid);
char* gid_to_name(gid_t gid);
int glob_exists(const char *path);
+int glob_extend(char ***strv, const char *path);
int dirent_ensure_type(DIR *d, struct dirent *de);
@@ -732,3 +761,6 @@ static inline void _reset_locale_(struct _locale_struct_ *s) {
_saved_locale_.quit = true)
bool id128_is_valid(const char *s) _pure_;
+void parse_user_at_host(char *arg, char **user, char **host);
+
+int split_pair(const char *s, const char *sep, char **l, char **r);
diff --git a/src/shared/virt.c b/src/shared/virt.c
index 1c86a3dd1e..4f8134a773 100644
--- a/src/shared/virt.c
+++ b/src/shared/virt.c
@@ -29,6 +29,8 @@
/* Returns a short identifier for the various VM implementations */
int detect_vm(const char **id) {
+ _cleanup_free_ char *cpuinfo_contents = NULL;
+ int r;
#if defined(__i386__) || defined(__x86_64__)
@@ -67,7 +69,6 @@ int detect_vm(const char **id) {
const char *j, *k;
bool hypervisor;
_cleanup_free_ char *hvtype = NULL;
- int r;
/* Try high-level hypervisor sysfs file first:
*
@@ -164,6 +165,16 @@ int detect_vm(const char **id) {
}
#endif
+
+ /* Detect User-Mode Linux by reading /proc/cpuinfo */
+ r = read_full_file("/proc/cpuinfo", &cpuinfo_contents, NULL);
+ if (r < 0)
+ return r;
+ if (strstr(cpuinfo_contents, "\nvendor_id\t: User Mode Linux\n")) {
+ *id = "uml";
+ return 1;
+ }
+
return 0;
}
diff --git a/src/stdio-bridge/stdio-bridge.c b/src/stdio-bridge/stdio-bridge.c
index a5bdb03416..ab1a43ab1a 100644
--- a/src/stdio-bridge/stdio-bridge.c
+++ b/src/stdio-bridge/stdio-bridge.c
@@ -68,7 +68,7 @@ int main(int argc, char *argv[]) {
goto finish;
}
- r = sd_bus_set_negotiate_fds(a, is_unix);
+ r = sd_bus_negotiate_fds(a, is_unix);
if (r < 0) {
log_error("Failed to set FD negotiation: %s", strerror(-r));
goto finish;
@@ -104,7 +104,7 @@ int main(int argc, char *argv[]) {
goto finish;
}
- r = sd_bus_set_negotiate_fds(b, is_unix);
+ r = sd_bus_negotiate_fds(b, is_unix);
if (r < 0) {
log_error("Failed to set FD negotiation: %s", strerror(-r));
goto finish;
diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c
index db18dd9f6e..b5670dbb86 100644
--- a/src/sysctl/sysctl.c
+++ b/src/sysctl/sysctl.c
@@ -135,6 +135,7 @@ static int parse_file(Hashmap *sysctl_options, const char *path, bool ignore_eno
log_debug("parse: %s\n", path);
while (!feof(f)) {
char l[LINE_MAX], *p, *value, *new_value, *property, *existing;
+ void *v;
int k;
if (!fgets(l, sizeof(l), f)) {
@@ -167,13 +168,14 @@ static int parse_file(Hashmap *sysctl_options, const char *path, bool ignore_eno
p = normalize_sysctl(strstrip(p));
value = strstrip(value);
- existing = hashmap_get(sysctl_options, p);
+ existing = hashmap_get2(sysctl_options, p, &v);
if (existing) {
- if (!streq(value, existing))
- log_warning("Duplicate assignment of %s in file '%s', ignoring.",
- p, path);
+ if (streq(value, existing))
+ continue;
- continue;
+ log_info("Overwriting earlier assignment of %s in file '%s'.", p, path);
+ free(hashmap_remove(sysctl_options, p));
+ free(v);
}
property = strdup(p);
@@ -188,7 +190,7 @@ static int parse_file(Hashmap *sysctl_options, const char *path, bool ignore_eno
k = hashmap_put(sysctl_options, property, new_value);
if (k < 0) {
- log_error("Failed to add sysctl variable %s to hashmap: %s", property, strerror(-r));
+ log_error("Failed to add sysctl variable %s to hashmap: %s", property, strerror(-k));
free(property);
free(new_value);
return k;
@@ -304,8 +306,6 @@ int main(int argc, char *argv[]) {
goto finish;
}
- r = parse_file(sysctl_options, "/etc/sysctl.conf", true);
-
STRV_FOREACH(f, files) {
k = parse_file(sysctl_options, *f, true);
if (k < 0 && r == 0)
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 3cca861cf6..bb7ada9f32 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -69,9 +69,10 @@
#include "fileio.h"
static char **arg_types = NULL;
-static char **arg_load_states = NULL;
+static char **arg_states = NULL;
static char **arg_properties = NULL;
static bool arg_all = false;
+static bool original_stdout_is_tty;
static enum dependency {
DEPENDENCY_FORWARD,
DEPENDENCY_REVERSE,
@@ -93,7 +94,6 @@ static bool arg_quiet = false;
static bool arg_full = false;
static int arg_force = 0;
static bool arg_ask_password = true;
-static bool arg_failed = false;
static bool arg_runtime = false;
static char **arg_wall = NULL;
static const char *arg_kill_who = NULL;
@@ -129,7 +129,8 @@ static enum transport {
TRANSPORT_SSH,
TRANSPORT_POLKIT
} arg_transport = TRANSPORT_NORMAL;
-static const char *arg_host = NULL;
+static char *arg_host = NULL;
+static char *arg_user = NULL;
static unsigned arg_lines = 10;
static OutputMode arg_output = OUTPUT_SHORT;
static bool arg_plain = false;
@@ -175,30 +176,6 @@ static void polkit_agent_open_if_enabled(void) {
}
#endif
-static const char *ansi_highlight(bool b) {
-
- if (!on_tty())
- return "";
-
- return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
-}
-
-static const char *ansi_highlight_red(bool b) {
-
- if (!on_tty())
- return "";
-
- return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
-}
-
-static const char *ansi_highlight_green(bool b) {
-
- if (!on_tty())
- return "";
-
- return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
-}
-
static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
assert(error);
@@ -300,12 +277,11 @@ static int compare_unit_info(const void *a, const void *b) {
static bool output_show_unit(const struct unit_info *u) {
const char *dot;
- if (arg_failed)
- return streq(u->active_state, "failed");
+ if (!strv_isempty(arg_states))
+ return strv_contains(arg_states, u->load_state) || strv_contains(arg_states, u->sub_state) || strv_contains(arg_states, u->active_state);
return (!arg_types || ((dot = strrchr(u->id, '.')) &&
strv_find(arg_types, dot+1))) &&
- (!arg_load_states || strv_find(arg_load_states, u->load_state)) &&
(arg_all || !(streq(u->active_state, "inactive")
|| u->following[0]) || u->job_id > 0);
}
@@ -334,7 +310,7 @@ static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
}
}
- if (!arg_full) {
+ if (!arg_full && original_stdout_is_tty) {
unsigned basic_len;
id_len = MIN(max_id_len, 25u);
basic_len = 5 + id_len + 5 + active_len + sub_len;
@@ -380,15 +356,16 @@ static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
n_shown++;
- if (streq(u->load_state, "error")) {
- on_loaded = on = ansi_highlight_red(true);
- off_loaded = off = ansi_highlight_red(false);
+ if (streq(u->load_state, "error") ||
+ streq(u->load_state, "not-found")) {
+ on_loaded = on = ansi_highlight_red();
+ off_loaded = off = ansi_highlight_off();
} else
on_loaded = off_loaded = "";
if (streq(u->active_state, "failed")) {
- on_active = on = ansi_highlight_red(true);
- off_active = off = ansi_highlight_red(false);
+ on_active = on = ansi_highlight_red();
+ off_active = off = ansi_highlight_off();
} else
on_active = off_active = "";
@@ -400,7 +377,7 @@ static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
on_active, active_len, u->active_state,
sub_len, u->sub_state, off_active,
job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
- if (!arg_full && arg_no_pager)
+ if (desc_len > 0)
printf("%.*s\n", desc_len, u->description);
else
printf("%s\n", u->description);
@@ -416,11 +393,11 @@ static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
if (job_count)
printf("JOB = Pending job for the unit.\n");
puts("");
- on = ansi_highlight(true);
- off = ansi_highlight(false);
+ on = ansi_highlight();
+ off = ansi_highlight_off();
} else {
- on = ansi_highlight_red(true);
- off = ansi_highlight_red(false);
+ on = ansi_highlight_red();
+ off = ansi_highlight_off();
}
if (arg_all)
@@ -434,8 +411,12 @@ static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
}
}
-static int get_unit_list(DBusConnection *bus, DBusMessage **reply,
- struct unit_info **unit_infos, unsigned *c) {
+static int get_unit_list(
+ DBusConnection *bus,
+ DBusMessage **reply,
+ struct unit_info **unit_infos,
+ unsigned *c) {
+
DBusMessageIter iter, sub;
size_t size = 0;
int r;
@@ -497,9 +478,11 @@ static int list_units(DBusConnection *bus, char **args) {
return 0;
}
-static int get_triggered_units(DBusConnection *bus, const char* unit_path,
- char*** triggered)
-{
+static int get_triggered_units(
+ DBusConnection *bus,
+ const char* unit_path,
+ char*** triggered) {
+
const char *interface = "org.freedesktop.systemd1.Unit",
*triggers_property = "Triggers";
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
@@ -655,11 +638,12 @@ static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
}
if (cs) {
- printf("%-*s %-*.*s%-*s %s\n",
- pathlen, "LISTEN",
- typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
- socklen, "UNIT",
- "ACTIVATES");
+ if (!arg_no_legend)
+ printf("%-*s %-*.*s%-*s %s\n",
+ pathlen, "LISTEN",
+ typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
+ socklen, "UNIT",
+ "ACTIVATES");
for (s = socket_infos; s < socket_infos + cs; s++) {
char **a;
@@ -676,17 +660,20 @@ static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
printf("\n");
}
- on = ansi_highlight(true);
- off = ansi_highlight(false);
- printf("\n");
+ on = ansi_highlight();
+ off = ansi_highlight_off();
+ if (!arg_no_legend)
+ printf("\n");
} else {
- on = ansi_highlight_red(true);
- off = ansi_highlight_red(false);
+ on = ansi_highlight_red();
+ off = ansi_highlight_off();
}
- printf("%s%u sockets listed.%s\n", on, cs, off);
- if (!arg_all)
- printf("Pass --all to see loaded but inactive sockets, too.\n");
+ if (!arg_no_legend) {
+ printf("%s%u sockets listed.%s\n", on, cs, off);
+ if (!arg_all)
+ printf("Pass --all to see loaded but inactive sockets, too.\n");
+ }
return 0;
}
@@ -828,11 +815,11 @@ static void output_unit_file_list(const UnitFileList *units, unsigned c) {
u->state == UNIT_FILE_MASKED_RUNTIME ||
u->state == UNIT_FILE_DISABLED ||
u->state == UNIT_FILE_INVALID) {
- on = ansi_highlight_red(true);
- off = ansi_highlight_red(false);
+ on = ansi_highlight_red();
+ off = ansi_highlight_off();
} else if (u->state == UNIT_FILE_ENABLED) {
- on = ansi_highlight_green(true);
- off = ansi_highlight_green(false);
+ on = ansi_highlight_green();
+ off = ansi_highlight_off();
} else
on = off = "";
@@ -1173,6 +1160,59 @@ static int list_dependencies(DBusConnection *bus, char **args) {
return list_dependencies_one(bus, u, 0, &units, 0);
}
+static int get_default(DBusConnection *bus, char **args) {
+ char *path = NULL;
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ int r;
+ _cleanup_dbus_error_free_ DBusError error;
+
+ dbus_error_init(&error);
+
+ if (!bus || avoid_bus()) {
+ r = unit_file_get_default(arg_scope, arg_root, &path);
+
+ if (r < 0) {
+ log_error("Operation failed: %s", strerror(-r));
+ goto finish;
+ }
+
+ r = 0;
+ } else {
+ r = bus_method_call_with_reply(
+ bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "GetDefaultTarget",
+ &reply,
+ NULL,
+ DBUS_TYPE_INVALID);
+
+ if (r < 0) {
+ log_error("Operation failed: %s", strerror(-r));
+ goto finish;
+ }
+
+ if (!dbus_message_get_args(reply, &error,
+ DBUS_TYPE_STRING, &path,
+ DBUS_TYPE_INVALID)) {
+ log_error("Failed to parse reply: %s", bus_error_message(&error));
+ dbus_error_free(&error);
+ return -EIO;
+ }
+ }
+
+ if (path)
+ printf("%s\n", path);
+
+finish:
+ if ((!bus || avoid_bus()) && path)
+ free(path);
+
+ return r;
+
+}
+
struct job_info {
uint32_t id;
char *name, *type, *state;
@@ -1187,8 +1227,8 @@ static void list_jobs_print(struct job_info* jobs, size_t n) {
assert(n == 0 || jobs);
if (n == 0) {
- on = ansi_highlight_green(true);
- off = ansi_highlight_green(false);
+ on = ansi_highlight_green();
+ off = ansi_highlight_off();
printf("%sNo jobs running.%s\n", on, off);
return;
@@ -1224,8 +1264,8 @@ static void list_jobs_print(struct job_info* jobs, size_t n) {
_cleanup_free_ char *e = NULL;
if (streq(j->state, "running")) {
- on = ansi_highlight(true);
- off = ansi_highlight(false);
+ on = ansi_highlight();
+ off = ansi_highlight_off();
} else
on = off = "";
@@ -1238,8 +1278,8 @@ static void list_jobs_print(struct job_info* jobs, size_t n) {
}
}
- on = ansi_highlight(true);
- off = ansi_highlight(false);
+ on = ansi_highlight();
+ off = ansi_highlight_off();
if (on_tty())
printf("\n%s%zu jobs listed%s.\n", on, n, off);
@@ -1325,36 +1365,6 @@ static int list_jobs(DBusConnection *bus, char **args) {
return 0;
}
-static int load_unit(DBusConnection *bus, char **args) {
- char **name;
-
- assert(args);
-
- STRV_FOREACH(name, args+1) {
- _cleanup_free_ char *n = NULL;
- int r;
-
- n = unit_name_mangle(*name);
- if (!n)
- return log_oom();
-
- r = bus_method_call_with_reply(
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "LoadUnit",
- NULL,
- NULL,
- DBUS_TYPE_STRING, &n,
- DBUS_TYPE_INVALID);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
static int cancel_job(DBusConnection *bus, char **args) {
char **name;
@@ -1390,8 +1400,9 @@ static int cancel_job(DBusConnection *bus, char **args) {
return 0;
}
-static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
+static int need_daemon_reload(DBusConnection *bus, const char *unit) {
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ _cleanup_dbus_error_free_ DBusError error;
dbus_bool_t b = FALSE;
DBusMessageIter iter, sub;
const char
@@ -1401,6 +1412,8 @@ static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
_cleanup_free_ char *n = NULL;
int r;
+ dbus_error_init(&error);
+
/* We ignore all errors here, since this is used to show a warning only */
n = unit_name_mangle(unit);
@@ -1414,7 +1427,7 @@ static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
"org.freedesktop.systemd1.Manager",
"GetUnit",
&reply,
- NULL,
+ &error,
DBUS_TYPE_STRING, &n,
DBUS_TYPE_INVALID);
if (r < 0)
@@ -1435,7 +1448,7 @@ static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
"org.freedesktop.DBus.Properties",
"Get",
&reply,
- NULL,
+ &error,
DBUS_TYPE_STRING, &interface,
DBUS_TYPE_STRING, &property,
DBUS_TYPE_INVALID);
@@ -1483,6 +1496,7 @@ static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *me
} else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
uint32_t id;
const char *path, *result, *unit;
+ char *r;
if (dbus_message_get_args(message, &error,
DBUS_TYPE_UINT32, &id,
@@ -1491,7 +1505,11 @@ static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *me
DBUS_TYPE_STRING, &result,
DBUS_TYPE_INVALID)) {
- free(set_remove(d->set, (char*) path));
+ r = set_remove(d->set, (char*) path);
+ if (!r)
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ free(r);
if (!isempty(result))
d->result = strdup(result);
@@ -1501,7 +1519,7 @@ static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *me
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
-#ifndef LEGACY
+#ifndef NOLEGACY
dbus_error_free(&error);
if (dbus_message_get_args(message, &error,
DBUS_TYPE_UINT32, &id,
@@ -1511,7 +1529,11 @@ static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *me
/* Compatibility with older systemd versions <
* 183 during upgrades. This should be dropped
* one day. */
- free(set_remove(d->set, (char*) path));
+ r = set_remove(d->set, (char*) path);
+ if (!r)
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ free(r);
if (*result)
d->result = strdup(result);
@@ -1855,9 +1877,9 @@ static int start_unit_one(
return -EIO;
}
- if (need_daemon_reload(bus, n))
- log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
- n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
+ if (need_daemon_reload(bus, n) > 0)
+ log_warning("Warning: Unit file of %s changed on disk, 'systemctl %sdaemon-reload' recommended.",
+ n, arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
if (s) {
char *p;
@@ -2320,150 +2342,6 @@ static int kill_unit(DBusConnection *bus, char **args) {
return 0;
}
-static int set_cgroup(DBusConnection *bus, char **args) {
- _cleanup_free_ char *n = NULL;
- const char *method, *runtime;
- char **argument;
- int r;
-
- assert(bus);
- assert(args);
-
- method =
- streq(args[0], "set-cgroup") ? "SetUnitControlGroup" :
- streq(args[0], "unset-cgroup") ? "UnsetUnitControlGroup"
- : "UnsetUnitControlGroupAttribute";
-
- runtime = arg_runtime ? "runtime" : "persistent";
-
- n = unit_name_mangle(args[1]);
- if (!n)
- return log_oom();
-
- STRV_FOREACH(argument, args + 2) {
-
- r = bus_method_call_with_reply(
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- method,
- NULL,
- NULL,
- DBUS_TYPE_STRING, &n,
- DBUS_TYPE_STRING, argument,
- DBUS_TYPE_STRING, &runtime,
- DBUS_TYPE_INVALID);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-static int set_cgroup_attr(DBusConnection *bus, char **args) {
- _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
- DBusError error;
- DBusMessageIter iter;
- _cleanup_free_ char *n = NULL;
- const char *runtime;
- int r;
-
- assert(bus);
- assert(args);
-
- dbus_error_init(&error);
-
- runtime = arg_runtime ? "runtime" : "persistent";
-
- n = unit_name_mangle(args[1]);
- if (!n)
- return log_oom();
-
- m = dbus_message_new_method_call(
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "SetUnitControlGroupAttribute");
- if (!m)
- return log_oom();
-
- dbus_message_iter_init_append(m, &iter);
- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
- !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[2]))
- return log_oom();
-
- r = bus_append_strv_iter(&iter, args + 3);
- if (r < 0)
- return log_oom();
-
- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
- return log_oom();
-
- reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
- if (!reply) {
- log_error("Failed to issue method call: %s", bus_error_message(&error));
- dbus_error_free(&error);
- return -EIO;
- }
-
- return 0;
-}
-
-static int get_cgroup_attr(DBusConnection *bus, char **args) {
- _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- _cleanup_free_ char *n = NULL;
- char **argument;
- int r;
-
- assert(bus);
- assert(args);
-
- n = unit_name_mangle(args[1]);
- if (!n)
- return log_oom();
-
- STRV_FOREACH(argument, args + 2) {
- _cleanup_strv_free_ char **list = NULL;
- DBusMessageIter iter;
- char **a;
-
- r = bus_method_call_with_reply(
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "GetUnitControlGroupAttribute",
- &reply,
- NULL,
- DBUS_TYPE_STRING, &n,
- DBUS_TYPE_STRING, argument,
- DBUS_TYPE_INVALID);
- if (r < 0)
- return r;
-
- if (!dbus_message_iter_init(reply, &iter)) {
- log_error("Failed to initialize iterator.");
- return -EIO;
- }
-
- r = bus_parse_strv_iter(&iter, &list);
- if (r < 0) {
- log_error("Failed to parse value list.");
- return r;
- }
-
- STRV_FOREACH(a, list) {
- if (endswith(*a, "\n"))
- fputs(*a, stdout);
- else
- puts(*a);
- }
- }
-
- return 0;
-}
-
typedef struct ExecStatusInfo {
char *name;
@@ -2581,7 +2459,7 @@ typedef struct UnitStatusInfo {
const char *fragment_path;
const char *source_path;
- const char *default_control_group;
+ const char *control_group;
char **dropin_paths;
@@ -2600,6 +2478,7 @@ typedef struct UnitStatusInfo {
pid_t main_pid;
pid_t control_pid;
const char *status_text;
+ const char *pid_file;
bool running:1;
usec_t start_timestamp;
@@ -2609,6 +2488,10 @@ typedef struct UnitStatusInfo {
usec_t condition_timestamp;
bool condition_result;
+ bool failed_condition_trigger;
+ bool failed_condition_negate;
+ const char *failed_condition;
+ const char *failed_condition_param;
/* Socket */
unsigned n_accepted;
@@ -2630,7 +2513,8 @@ typedef struct UnitStatusInfo {
LIST_HEAD(ExecStatusInfo, exec);
} UnitStatusInfo;
-static void print_status_info(UnitStatusInfo *i) {
+static void print_status_info(UnitStatusInfo *i,
+ bool *ellipsized) {
ExecStatusInfo *p;
const char *on, *off, *ss;
usec_t timestamp;
@@ -2643,20 +2527,10 @@ static void print_status_info(UnitStatusInfo *i) {
on_tty() * OUTPUT_COLOR |
!arg_quiet * OUTPUT_WARN_CUTOFF |
arg_full * OUTPUT_FULL_WIDTH;
- int maxlen = 8; /* a value that'll suffice most of the time */
char **t, **t2;
assert(i);
- STRV_FOREACH_PAIR(t, t2, i->listen)
- maxlen = MAX(maxlen, (int)(sizeof("Listen") - 1 + strlen(*t)));
- if (i->accept)
- maxlen = MAX(maxlen, (int)sizeof("Accept") - 1);
- if (i->main_pid > 0)
- maxlen = MAX(maxlen, (int)sizeof("Main PID") - 1);
- else if (i->control_pid > 0)
- maxlen = MAX(maxlen, (int)sizeof("Control") - 1);
-
/* This shows pretty information about a unit. See
* print_property() for a low-level property printer */
@@ -2668,28 +2542,28 @@ static void print_status_info(UnitStatusInfo *i) {
printf("\n");
if (i->following)
- printf(" %*s: unit currently follows state of %s\n", maxlen, "Follow", i->following);
+ printf(" Follow: unit currently follows state of %s\n", i->following);
if (streq_ptr(i->load_state, "error")) {
- on = ansi_highlight_red(true);
- off = ansi_highlight_red(false);
+ on = ansi_highlight_red();
+ off = ansi_highlight_off();
} else
on = off = "";
path = i->source_path ? i->source_path : i->fragment_path;
if (i->load_error)
- printf(" %*s: %s%s%s (Reason: %s)\n",
- maxlen, "Loaded", on, strna(i->load_state), off, i->load_error);
+ printf(" Loaded: %s%s%s (Reason: %s)\n",
+ on, strna(i->load_state), off, i->load_error);
else if (path && i->unit_file_state)
- printf(" %*s: %s%s%s (%s; %s)\n",
- maxlen, "Loaded", on, strna(i->load_state), off, path, i->unit_file_state);
+ printf(" Loaded: %s%s%s (%s; %s)\n",
+ on, strna(i->load_state), off, path, i->unit_file_state);
else if (path)
- printf(" %*s: %s%s%s (%s)\n",
- maxlen, "Loaded", on, strna(i->load_state), off, path);
+ printf(" Loaded: %s%s%s (%s)\n",
+ on, strna(i->load_state), off, path);
else
- printf(" %*s: %s%s%s\n",
- maxlen, "Loaded", on, strna(i->load_state), off);
+ printf(" Loaded: %s%s%s\n",
+ on, strna(i->load_state), off);
if (!strv_isempty(i->dropin_paths)) {
char ** dropin;
@@ -2698,7 +2572,7 @@ static void print_status_info(UnitStatusInfo *i) {
STRV_FOREACH(dropin, i->dropin_paths) {
if (! dir || last) {
- printf(" %*s ", maxlen, dir ? "" : "Drop-In:");
+ printf(dir ? " " : " Drop-In: ");
free(dir);
@@ -2707,7 +2581,7 @@ static void print_status_info(UnitStatusInfo *i) {
return;
}
- printf("%s\n %*s %s", dir, maxlen, "",
+ printf("%s\n %s", dir,
draw_special_char(DRAW_TREE_RIGHT));
}
@@ -2722,20 +2596,20 @@ static void print_status_info(UnitStatusInfo *i) {
ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
if (streq_ptr(i->active_state, "failed")) {
- on = ansi_highlight_red(true);
- off = ansi_highlight_red(false);
+ on = ansi_highlight_red();
+ off = ansi_highlight_off();
} else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
- on = ansi_highlight_green(true);
- off = ansi_highlight_green(false);
+ on = ansi_highlight_green();
+ off = ansi_highlight_off();
} else
on = off = "";
if (ss)
- printf(" %*s: %s%s (%s)%s",
- maxlen, "Active", on, strna(i->active_state), ss, off);
+ printf(" Active: %s%s (%s)%s",
+ on, strna(i->active_state), ss, off);
else
- printf(" %*s: %s%s%s",
- maxlen, "Active", on, strna(i->active_state), off);
+ printf(" Active: %s%s%s",
+ on, strna(i->active_state), off);
if (!isempty(i->result) && !streq(i->result, "success"))
printf(" (Result: %s)", i->result);
@@ -2761,27 +2635,32 @@ static void print_status_info(UnitStatusInfo *i) {
s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
- if (s1)
- printf(" %*s start condition failed at %s; %s\n", maxlen, "", s2, s1);
- else if (s2)
- printf(" %*s start condition failed at %s\n", maxlen, "", s2);
+ printf(" start condition failed at %s%s%s\n",
+ s2, s1 ? "; " : "", s1 ? s1 : "");
+ if (i->failed_condition_trigger)
+ printf(" none of the trigger conditions were met\n");
+ else if (i->failed_condition)
+ printf(" %s=%s%s was not met\n",
+ i->failed_condition,
+ i->failed_condition_negate ? "!" : "",
+ i->failed_condition_param);
}
if (i->sysfs_path)
- printf(" %*s: %s\n", maxlen, "Device", i->sysfs_path);
+ printf(" Device: %s\n", i->sysfs_path);
if (i->where)
- printf(" %*s: %s\n", maxlen, "Where", i->where);
+ printf(" Where: %s\n", i->where);
if (i->what)
- printf(" %*s: %s\n", maxlen, "What", i->what);
+ printf(" What: %s\n", i->what);
STRV_FOREACH(t, i->documentation)
- printf(" %*s %s\n", maxlen+1, t == i->documentation ? "Docs:" : "", *t);
+ printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
STRV_FOREACH_PAIR(t, t2, i->listen)
- printf(" %*s %s (%s)\n", maxlen+1, t == i->listen ? "Listen:" : "", *t2, *t);
+ printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
if (i->accept)
- printf(" %*s: %u; Connected: %u\n", maxlen, "Accepted", i->n_accepted, i->n_connections);
+ printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
LIST_FOREACH(exec, p, i->exec) {
_cleanup_free_ char *argv = NULL;
@@ -2792,12 +2671,12 @@ static void print_status_info(UnitStatusInfo *i) {
continue;
argv = strv_join(p->argv, " ");
- printf(" %*s: %u %s=%s ", maxlen, "Process", p->pid, p->name, strna(argv));
+ printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
good = is_clean_exit_lsb(p->code, p->status, NULL);
if (!good) {
- on = ansi_highlight_red(true);
- off = ansi_highlight_red(false);
+ on = ansi_highlight_red();
+ off = ansi_highlight_off();
} else
on = off = "";
@@ -2829,7 +2708,7 @@ static void print_status_info(UnitStatusInfo *i) {
if (i->main_pid > 0 || i->control_pid > 0) {
if (i->main_pid > 0) {
- printf(" %*s: %u", maxlen, "Main PID", (unsigned) i->main_pid);
+ printf(" Main PID: %u", (unsigned) i->main_pid);
if (i->running) {
_cleanup_free_ char *comm = NULL;
@@ -2860,7 +2739,7 @@ static void print_status_info(UnitStatusInfo *i) {
if (i->control_pid > 0) {
_cleanup_free_ char *c = NULL;
- printf(" %*s: %u", i->main_pid ? 0 : maxlen, "Control", (unsigned) i->control_pid);
+ printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
get_process_comm(i->control_pid, &c);
if (c)
@@ -2871,20 +2750,18 @@ static void print_status_info(UnitStatusInfo *i) {
}
if (i->status_text)
- printf(" %*s: \"%s\"\n", maxlen, "Status", i->status_text);
+ printf(" Status: \"%s\"\n", i->status_text);
- if (i->default_control_group &&
- (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
+ if (i->control_group &&
+ (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0)) {
unsigned c;
- printf(" %*s: %s\n", maxlen, "CGroup", i->default_control_group);
+ printf(" CGroup: %s\n", i->control_group);
if (arg_transport != TRANSPORT_SSH) {
unsigned k = 0;
pid_t extra[2];
- char prefix[maxlen + 4];
- memset(prefix, ' ', sizeof(prefix) - 1);
- prefix[sizeof(prefix) - 1] = '\0';
+ char prefix[] = " ";
c = columns();
if (c > sizeof(prefix) - 1)
@@ -2898,7 +2775,7 @@ static void print_status_info(UnitStatusInfo *i) {
if (i->control_pid > 0)
extra[k++] = i->control_pid;
- show_cgroup_and_extra_by_spec(i->default_control_group, prefix,
+ show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix,
c, false, extra, k, flags);
}
}
@@ -2913,14 +2790,15 @@ static void print_status_info(UnitStatusInfo *i) {
arg_lines,
getuid(),
flags,
- arg_scope == UNIT_FILE_SYSTEM);
+ arg_scope == UNIT_FILE_SYSTEM,
+ ellipsized);
}
if (i->need_daemon_reload)
- printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
- ansi_highlight_red(true),
- ansi_highlight_red(false),
- arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
+ printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
+ ansi_highlight_red(),
+ ansi_highlight_off(),
+ arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
}
static void show_unit_help(UnitStatusInfo *i) {
@@ -3007,10 +2885,20 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
i->fragment_path = s;
else if (streq(name, "SourcePath"))
i->source_path = s;
- else if (streq(name, "DefaultControlGroup"))
- i->default_control_group = s;
+#ifndef NOLEGACY
+ else if (streq(name, "DefaultControlGroup")) {
+ const char *e;
+ e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
+ if (e)
+ i->control_group = e;
+ }
+#endif
+ else if (streq(name, "ControlGroup"))
+ i->control_group = s;
else if (streq(name, "StatusText"))
i->status_text = s;
+ else if (streq(name, "PIDFile"))
+ i->pid_file = s;
else if (streq(name, "SysFSPath"))
i->sysfs_path = s;
else if (streq(name, "Where"))
@@ -3115,15 +3003,18 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
ExecStatusInfo *info;
int r;
- if (!(info = new0(ExecStatusInfo, 1)))
+ info = new0(ExecStatusInfo, 1);
+ if (!info)
return -ENOMEM;
- if (!(info->name = strdup(name))) {
+ info->name = strdup(name);
+ if (!info->name) {
free(info);
return -ENOMEM;
}
- if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
+ r = exec_status_info_deserialize(&sub, info);
+ if (r < 0) {
free(info);
return r;
}
@@ -3133,7 +3024,8 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
dbus_message_iter_next(&sub);
}
- } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
+ } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
+ streq(name, "Listen")) {
DBusMessageIter sub, sub2;
dbus_message_iter_recurse(iter, &sub);
@@ -3159,7 +3051,8 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
return 0;
- } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING && streq(name, "DropInPaths")) {
+ } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
+ streq(name, "DropInPaths")) {
int r = bus_parse_strv_iter(iter, &i->dropin_paths);
if (r < 0)
return r;
@@ -3182,6 +3075,36 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
dbus_message_iter_next(&sub);
}
+
+ } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
+ streq(name, "Conditions")) {
+ DBusMessageIter sub, sub2;
+
+ dbus_message_iter_recurse(iter, &sub);
+ while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
+ const char *cond, *param;
+ dbus_bool_t trigger, negate;
+ dbus_int32_t state;
+
+ dbus_message_iter_recurse(&sub, &sub2);
+ log_debug("here");
+
+ if(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &cond, true) >= 0 &&
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &trigger, true) >= 0 &&
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &negate, true) >= 0 &&
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &param, true) >= 0 &&
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &state, false) >= 0) {
+ log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
+ if (state < 0 && (!trigger || !i->failed_condition)) {
+ i->failed_condition = cond;
+ i->failed_condition_trigger = trigger;
+ i->failed_condition_negate = negate;
+ i->failed_condition_param = param;
+ }
+ }
+
+ dbus_message_iter_next(&sub);
+ }
}
break;
@@ -3350,30 +3273,6 @@ static int print_property(const char *name, DBusMessageIter *iter) {
return 0;
- } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
- DBusMessageIter sub, sub2;
-
- dbus_message_iter_recurse(iter, &sub);
- while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
- const char *controller, *attr, *value;
-
- dbus_message_iter_recurse(&sub, &sub2);
-
- if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
- bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
-
- printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
- controller,
- attr,
- value);
- }
-
- dbus_message_iter_next(&sub);
- }
-
- return 0;
-
} else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
DBusMessageIter sub;
@@ -3408,8 +3307,62 @@ static int print_property(const char *name, DBusMessageIter *iter) {
}
return 0;
+
+ } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "DeviceAllow")) {
+ DBusMessageIter sub, sub2;
+
+ dbus_message_iter_recurse(iter, &sub);
+ while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
+ const char *path, *rwm;
+
+ dbus_message_iter_recurse(&sub, &sub2);
+
+ if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &rwm, false) >= 0)
+ printf("%s=%s %s\n", name, strna(path), strna(rwm));
+
+ dbus_message_iter_next(&sub);
+ }
+ return 0;
+
+ } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "BlockIODeviceWeight")) {
+ DBusMessageIter sub, sub2;
+
+ dbus_message_iter_recurse(iter, &sub);
+ while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
+ const char *path;
+ uint64_t weight;
+
+ dbus_message_iter_recurse(&sub, &sub2);
+
+ if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &weight, false) >= 0)
+ printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
+
+ dbus_message_iter_next(&sub);
+ }
+ return 0;
+
+ } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
+ DBusMessageIter sub, sub2;
+
+ dbus_message_iter_recurse(iter, &sub);
+ while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
+ const char *path;
+ uint64_t bandwidth;
+
+ dbus_message_iter_recurse(&sub, &sub2);
+
+ if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &bandwidth, false) >= 0)
+ printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
+
+ dbus_message_iter_next(&sub);
+ }
+ return 0;
}
+
break;
}
@@ -3422,7 +3375,12 @@ static int print_property(const char *name, DBusMessageIter *iter) {
return 0;
}
-static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
+static int show_one(const char *verb,
+ DBusConnection *bus,
+ const char *path,
+ bool show_properties,
+ bool *new_line,
+ bool *ellipsized) {
_cleanup_free_ DBusMessage *reply = NULL;
const char *interface = "";
int r;
@@ -3492,7 +3450,7 @@ static int show_one(const char *verb, DBusConnection *bus, const char *path, boo
if (streq(verb, "help"))
show_unit_help(&info);
else
- print_status_info(&info);
+ print_status_info(&info, ellipsized);
}
strv_free(info.documentation);
@@ -3501,9 +3459,19 @@ static int show_one(const char *verb, DBusConnection *bus, const char *path, boo
if (!streq_ptr(info.active_state, "active") &&
!streq_ptr(info.active_state, "reloading") &&
- streq(verb, "status"))
+ streq(verb, "status")) {
/* According to LSB: "program not running" */
- r = 3;
+ /* 0: program is running or service is OK
+ * 1: program is dead and /var/run pid file exists
+ * 2: program is dead and /var/lock lock file exists
+ * 3: program is not running
+ * 4: program or service status is unknown
+ */
+ if (info.pid_file && access(info.pid_file, F_OK) == 0)
+ r = 1;
+ else
+ r = 3;
+ }
while ((p = info.exec)) {
LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
@@ -3513,7 +3481,11 @@ static int show_one(const char *verb, DBusConnection *bus, const char *path, boo
return r;
}
-static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
+static int show_one_by_pid(const char *verb,
+ DBusConnection *bus,
+ uint32_t pid,
+ bool *new_line,
+ bool *ellipsized) {
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
const char *path = NULL;
_cleanup_dbus_error_free_ DBusError error;
@@ -3541,11 +3513,15 @@ static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid,
return -EIO;
}
- r = show_one(verb, bus, path, false, new_line);
+ r = show_one(verb, bus, path, false, new_line, ellipsized);
return r;
}
-static int show_all(const char* verb, DBusConnection *bus, bool show_properties, bool *new_line) {
+static int show_all(const char* verb,
+ DBusConnection *bus,
+ bool show_properties,
+ bool *new_line,
+ bool *ellipsized) {
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
_cleanup_free_ struct unit_info *unit_infos = NULL;
unsigned c = 0;
@@ -3570,7 +3546,7 @@ static int show_all(const char* verb, DBusConnection *bus, bool show_properties,
printf("%s -> '%s'\n", u->id, p);
- r = show_one(verb, bus, p, show_properties, new_line);
+ r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
if (r != 0)
return r;
}
@@ -3582,6 +3558,7 @@ static int show(DBusConnection *bus, char **args) {
int r, ret = 0;
bool show_properties, show_status, new_line = false;
char **name;
+ bool ellipsized = false;
assert(bus);
assert(args);
@@ -3595,83 +3572,319 @@ static int show(DBusConnection *bus, char **args) {
/* If no argument is specified inspect the manager itself */
if (show_properties && strv_length(args) <= 1)
- return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
+ return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
if (show_status && strv_length(args) <= 1)
- return show_all(args[0], bus, false, &new_line);
+ ret = show_all(args[0], bus, false, &new_line, &ellipsized);
+ else
+ STRV_FOREACH(name, args+1) {
+ uint32_t id;
- STRV_FOREACH(name, args+1) {
- uint32_t id;
+ if (safe_atou32(*name, &id) < 0) {
+ _cleanup_free_ char *p = NULL, *n = NULL;
+ /* Interpret as unit name */
- if (safe_atou32(*name, &id) < 0) {
- _cleanup_free_ char *p = NULL, *n = NULL;
- /* Interpret as unit name */
+ n = unit_name_mangle(*name);
+ if (!n)
+ return log_oom();
- n = unit_name_mangle(*name);
- if (!n)
- return log_oom();
+ p = unit_dbus_path_from_name(n);
+ if (!p)
+ return log_oom();
+
+ r = show_one(args[0], bus, p, show_properties, &new_line, &ellipsized);
+ if (r != 0)
+ ret = r;
+
+ } else if (show_properties) {
+ _cleanup_free_ char *p = NULL;
+
+ /* Interpret as job id */
+ if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
+ return log_oom();
+
+ r = show_one(args[0], bus, p, show_properties, &new_line, &ellipsized);
+ if (r != 0)
+ ret = r;
+
+ } else {
+ /* Interpret as PID */
+ r = show_one_by_pid(args[0], bus, id, &new_line, &ellipsized);
+ if (r != 0)
+ ret = r;
+ }
+ }
+
+ if (ellipsized && !arg_quiet)
+ printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
+
+ return ret;
+}
+
+static int append_assignment(DBusMessageIter *iter, const char *assignment) {
+ const char *eq;
+ char *field;
+ DBusMessageIter sub;
+ int r;
+
+ assert(iter);
+ assert(assignment);
+
+ eq = strchr(assignment, '=');
+ if (!eq) {
+ log_error("Not an assignment: %s", assignment);
+ return -EINVAL;
+ }
+
+ field = strndupa(assignment, eq - assignment);
+ eq ++;
+
+ if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &field))
+ return log_oom();
+
+ if (streq(field, "CPUAccounting") ||
+ streq(field, "MemoryAccounting") ||
+ streq(field, "BlockIOAccounting")) {
+ dbus_bool_t b;
+
+ r = parse_boolean(eq);
+ if (r < 0) {
+ log_error("Failed to parse boolean assignment %s.", assignment);
+ return -EINVAL;
+ }
+
+ b = r;
+ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "b", &sub) ||
+ !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &b))
+ return log_oom();
+
+ } else if (streq(field, "MemoryLimit")) {
+ off_t bytes;
+ uint64_t u;
+
+ r = parse_bytes(eq, &bytes);
+ if (r < 0) {
+ log_error("Failed to parse bytes specification %s", assignment);
+ return -EINVAL;
+ }
+
+ u = bytes;
+ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
+ !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
+ return log_oom();
- p = unit_dbus_path_from_name(n);
- if (!p)
+ } else if (streq(field, "CPUShares") || streq(field, "BlockIOWeight")) {
+ uint64_t u;
+
+ r = safe_atou64(eq, &u);
+ if (r < 0) {
+ log_error("Failed to parse %s value %s.", field, eq);
+ return -EINVAL;
+ }
+
+ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
+ !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
+ return log_oom();
+
+ } else if (streq(field, "DevicePolicy")) {
+
+ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "s", &sub) ||
+ !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &eq))
+ return log_oom();
+
+ } else if (streq(field, "DeviceAllow")) {
+ DBusMessageIter sub2;
+
+ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(ss)", &sub) ||
+ !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(ss)", &sub2))
+ return log_oom();
+
+ if (!isempty(eq)) {
+ const char *path, *rwm;
+ DBusMessageIter sub3;
+ char *e;
+
+ e = strchr(eq, ' ');
+ if (e) {
+ path = strndupa(eq, e - eq);
+ rwm = e+1;
+ } else {
+ path = eq;
+ rwm = "";
+ }
+
+ if (!path_startswith(path, "/dev")) {
+ log_error("%s is not a device file in /dev.", path);
+ return -EINVAL;
+ }
+
+ if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
+ !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
+ !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &rwm) ||
+ !dbus_message_iter_close_container(&sub2, &sub3))
return log_oom();
+ }
+
+ if (!dbus_message_iter_close_container(&sub, &sub2))
+ return log_oom();
+
+ } else if (streq(field, "BlockIOReadBandwidth") || streq(field, "BlockIOWriteBandwidth")) {
+ DBusMessageIter sub2;
+
+ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(st)", &sub) ||
+ !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(st)", &sub2))
+ return log_oom();
+
+ if (!isempty(eq)) {
+ const char *path, *bandwidth;
+ DBusMessageIter sub3;
+ uint64_t u;
+ off_t bytes;
+ char *e;
+
+ e = strchr(eq, ' ');
+ if (e) {
+ path = strndupa(eq, e - eq);
+ bandwidth = e+1;
+ } else {
+ log_error("Failed to parse %s value %s.", field, eq);
+ return -EINVAL;
+ }
- r = show_one(args[0], bus, p, show_properties, &new_line);
- if (r != 0)
- ret = r;
+ if (!path_startswith(path, "/dev")) {
+ log_error("%s is not a device file in /dev.", path);
+ return -EINVAL;
+ }
- } else if (show_properties) {
- _cleanup_free_ char *p = NULL;
+ r = parse_bytes(bandwidth, &bytes);
+ if (r < 0) {
+ log_error("Failed to parse byte value %s.", bandwidth);
+ return -EINVAL;
+ }
- /* Interpret as job id */
- if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
+ u = (uint64_t) bytes;
+
+ if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
+ !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
+ !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_UINT64, &u) ||
+ !dbus_message_iter_close_container(&sub2, &sub3))
return log_oom();
+ }
- r = show_one(args[0], bus, p, show_properties, &new_line);
- if (r != 0)
- ret = r;
+ if (!dbus_message_iter_close_container(&sub, &sub2))
+ return log_oom();
- } else {
- /* Interpret as PID */
- r = show_one_by_pid(args[0], bus, id, &new_line);
- if (r != 0)
- ret = r;
+ } else if (streq(field, "BlockIODeviceWeight")) {
+ DBusMessageIter sub2;
+
+ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(st)", &sub) ||
+ !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(st)", &sub2))
+ return log_oom();
+
+ if (!isempty(eq)) {
+ const char *path, *weight;
+ DBusMessageIter sub3;
+ uint64_t u;
+ char *e;
+
+ e = strchr(eq, ' ');
+ if (e) {
+ path = strndupa(eq, e - eq);
+ weight = e+1;
+ } else {
+ log_error("Failed to parse %s value %s.", field, eq);
+ return -EINVAL;
+ }
+
+ if (!path_startswith(path, "/dev")) {
+ log_error("%s is not a device file in /dev.", path);
+ return -EINVAL;
+ }
+
+ r = safe_atou64(weight, &u);
+ if (r < 0) {
+ log_error("Failed to parse %s value %s.", field, weight);
+ return -EINVAL;
+ }
+ if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
+ !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
+ !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_UINT64, &u) ||
+ !dbus_message_iter_close_container(&sub2, &sub3))
+ return log_oom();
}
+
+ if (!dbus_message_iter_close_container(&sub, &sub2))
+ return log_oom();
+
+ } else {
+ log_error("Unknown assignment %s.", assignment);
+ return -EINVAL;
}
- return ret;
+ if (!dbus_message_iter_close_container(iter, &sub))
+ return log_oom();
+
+ return 0;
}
-static int dump(DBusConnection *bus, char **args) {
- _cleanup_free_ DBusMessage *reply = NULL;
+static int set_property(DBusConnection *bus, char **args) {
+
+ _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
+ _cleanup_free_ char *n = NULL;
+ DBusMessageIter iter, sub;
+ dbus_bool_t runtime;
DBusError error;
+ char **i;
int r;
- const char *text;
dbus_error_init(&error);
- pager_open_if_enabled();
-
- r = bus_method_call_with_reply(
- bus,
+ m = dbus_message_new_method_call(
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
- "Dump",
- &reply,
- NULL,
- DBUS_TYPE_INVALID);
- if (r < 0)
- return r;
+ "SetUnitProperties");
+ if (!m)
+ return log_oom();
- if (!dbus_message_get_args(reply, &error,
- DBUS_TYPE_STRING, &text,
- DBUS_TYPE_INVALID)) {
- log_error("Failed to parse reply: %s", bus_error_message(&error));
+ dbus_message_iter_init_append(m, &iter);
+
+ runtime = arg_runtime;
+
+ n = unit_name_mangle(args[1]);
+ if (!n)
+ return log_oom();
+
+ if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
+ !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &runtime) ||
+ !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sv)", &sub))
+ return log_oom();
+
+ STRV_FOREACH(i, args + 2) {
+ DBusMessageIter sub2;
+
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
+ return log_oom();
+
+ r = append_assignment(&sub2, *i);
+ if (r < 0)
+ return r;
+
+ if (!dbus_message_iter_close_container(&sub, &sub2))
+ return log_oom();
+
+ }
+
+ if (!dbus_message_iter_close_container(&iter, &sub))
+ return log_oom();
+
+ reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
+ if (!reply) {
+ log_error("Failed to issue method call: %s", bus_error_message(&error));
dbus_error_free(&error);
- return -EIO;
+ return -EIO;
}
- fputs(text, stdout);
return 0;
}
@@ -3690,13 +3903,13 @@ static int snapshot(DBusConnection *bus, char **args) {
dbus_error_init(&error);
if (strv_length(args) > 1)
- n = snapshot_name_mangle(args[1]);
+ n = unit_name_mangle_with_suffix(args[1], ".snapshot");
else
n = strdup("");
if (!n)
return log_oom();
- r = bus_method_call_with_reply (
+ r = bus_method_call_with_reply(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
@@ -3765,7 +3978,7 @@ static int delete_snapshot(DBusConnection *bus, char **args) {
_cleanup_free_ char *n = NULL;
int r;
- n = snapshot_name_mangle(*name);
+ n = unit_name_mangle_with_suffix(*name, ".snapshot");
if (!n)
return log_oom();
@@ -3825,9 +4038,9 @@ static int daemon_reload(DBusConnection *bus, char **args) {
/* There's always a fallback possible for
* legacy actions. */
r = -EADDRNOTAVAIL;
- else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
- /* On reexecution, we expect a disconnect, not
- * a reply */
+ else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
+ /* On reexecution, we expect a disconnect, not a
+ * reply */
r = 0;
else if (r < 0)
log_error("Failed to issue method call: %s", bus_error_message(&error));
@@ -4217,24 +4430,30 @@ static int enable_unit(DBusConnection *bus, char **args) {
if (!args[1])
return 0;
+ r = mangle_names(args+1, &mangled_names);
+ if (r < 0)
+ goto finish;
+
if (!bus || avoid_bus()) {
if (streq(verb, "enable")) {
- r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
+ r = unit_file_enable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
carries_install_info = r;
} else if (streq(verb, "disable"))
- r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
+ r = unit_file_disable(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
else if (streq(verb, "reenable")) {
- r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
+ r = unit_file_reenable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
carries_install_info = r;
} else if (streq(verb, "link"))
- r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
+ r = unit_file_link(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
else if (streq(verb, "preset")) {
- r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
+ r = unit_file_preset(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
carries_install_info = r;
} else if (streq(verb, "mask"))
- r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
+ r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
else if (streq(verb, "unmask"))
- r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
+ r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
+ else if (streq(verb, "set-default"))
+ r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes);
else
assert_not_reached("Unknown verb");
@@ -4278,6 +4497,8 @@ static int enable_unit(DBusConnection *bus, char **args) {
else if (streq(verb, "unmask")) {
method = "UnmaskUnitFiles";
send_force = false;
+ } else if (streq(verb, "set-default")) {
+ method = "SetDefaultTarget";
} else
assert_not_reached("Unknown verb");
@@ -4293,10 +4514,6 @@ static int enable_unit(DBusConnection *bus, char **args) {
dbus_message_iter_init_append(m, &iter);
- r = mangle_names(args+1, &mangled_names);
- if(r < 0)
- goto finish;
-
r = bus_append_strv_iter(&iter, mangled_names);
if (r < 0) {
log_error("Failed to append unit files.");
@@ -4498,19 +4715,20 @@ static int systemctl_help(void) {
" -h --help Show this help\n"
" --version Show package version\n"
" -t --type=TYPE List only units of a particular type\n"
+ " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
" -p --property=NAME Show only properties by this name\n"
" -a --all Show all loaded units/properties, including dead/empty\n"
" ones. To list all units installed on the system, use\n"
" the 'list-unit-files' command instead.\n"
" --reverse Show reverse dependencies with 'list-dependencies'\n"
- " --failed Show only failed units\n"
- " --full Don't ellipsize unit names on output\n"
+ " -l --full Don't ellipsize unit names on output\n"
" --fail When queueing a new job, fail if conflicting jobs are\n"
" pending\n"
- " --irreversible Create jobs which cannot be implicitly cancelled\n"
- " --show-types When showing sockets, explicitly show their type\n"
+ " --irreversible When queueing a new job, make sure it cannot be implicitly\n"
+ " cancelled\n"
" --ignore-dependencies\n"
" When queueing a new job, ignore all its dependencies\n"
+ " --show-types When showing sockets, explicitly show their type\n"
" -i --ignore-inhibitors\n"
" When shutting down or sleeping, ignore inhibitors\n"
" --kill-who=WHO Who to send signal to\n"
@@ -4530,15 +4748,16 @@ static int systemctl_help(void) {
" --system Connect to system manager\n"
" --user Connect to user service manager\n"
" --global Enable/disable unit files globally\n"
+ " --runtime Enable unit files only temporarily until next reboot\n"
" -f --force When enabling unit files, override existing symlinks\n"
" When shutting down, execute action immediately\n"
" --root=PATH Enable unit files in the specified root directory\n"
- " --runtime Enable unit files only temporarily until next reboot\n"
- " -n --lines=INTEGER Journal entries to show\n"
+ " -n --lines=INTEGER Numer of journal entries to show\n"
" -o --output=STRING Change journal output mode (short, short-monotonic,\n"
" verbose, export, json, json-pretty, json-sse, cat)\n\n"
"Unit Commands:\n"
" list-units List loaded units\n"
+ " list-sockets List loaded sockets ordered by address\n"
" start [NAME...] Start (activate) one or more units\n"
" stop [NAME...] Stop (deactivate) one or more units\n"
" reload [NAME...] Reload one or more units\n"
@@ -4555,18 +4774,11 @@ static int systemctl_help(void) {
" status [NAME...|PID...] Show runtime status of one or more units\n"
" show [NAME...|JOB...] Show properties of one or more\n"
" units/jobs or the manager\n"
+ " set-property [NAME] [ASSIGNMENT...]\n"
+ " Sets one or more properties of a unit\n"
" help [NAME...|PID...] Show manual for one or more units\n"
" reset-failed [NAME...] Reset failed state for all, one, or more\n"
" units\n"
- " get-cgroup-attr [NAME] [ATTR] ...\n"
- " Get control group attrubute\n"
- " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
- " Set control group attribute\n"
- " unset-cgroup-attr [NAME] [ATTR...]\n"
- " Unset control group attribute\n"
- " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
- " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
- " load [NAME...] Load one or more units\n"
" list-dependencies [NAME] Recursively show units which are required\n"
" or wanted by this unit or by which this\n"
" unit is required or wanted\n\n"
@@ -4577,16 +4789,16 @@ static int systemctl_help(void) {
" reenable [NAME...] Reenable one or more unit files\n"
" preset [NAME...] Enable/disable one or more unit files\n"
" based on preset configuration\n"
+ " is-enabled [NAME...] Check whether unit files are enabled\n\n"
" mask [NAME...] Mask one or more units\n"
" unmask [NAME...] Unmask one or more units\n"
" link [PATH...] Link one or more units files into\n"
" the search path\n"
- " is-enabled [NAME...] Check whether unit files are enabled\n\n"
+ " get-default Get the name of the default target\n"
+ " set-default NAME Set the default target\n\n"
"Job Commands:\n"
" list-jobs List jobs\n"
" cancel [JOB...] Cancel all, one, or more jobs\n\n"
- "Status Commands:\n"
- " dump Dump server status\n"
"Snapshot Commands:\n"
" snapshot [NAME] Create a snapshot\n"
" delete [NAME...] Remove one or more snapshots\n\n"
@@ -4691,13 +4903,6 @@ static int help_types(void) {
puts(t);
}
- puts("\nAvailable unit load states: ");
- for(i = 0; i < _UNIT_LOAD_STATE_MAX; i++) {
- t = unit_load_state_to_string(i);
- if (t)
- puts(t);
- }
-
return 0;
}
@@ -4720,53 +4925,54 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
ARG_NO_PAGER,
ARG_NO_WALL,
ARG_ROOT,
- ARG_FULL,
ARG_NO_RELOAD,
ARG_KILL_WHO,
ARG_NO_ASK_PASSWORD,
ARG_FAILED,
ARG_RUNTIME,
ARG_FORCE,
- ARG_PLAIN
+ ARG_PLAIN,
+ ARG_STATE
};
static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "type", required_argument, NULL, 't' },
- { "property", required_argument, NULL, 'p' },
- { "all", no_argument, NULL, 'a' },
- { "reverse", no_argument, NULL, ARG_REVERSE },
- { "after", no_argument, NULL, ARG_AFTER },
- { "before", no_argument, NULL, ARG_BEFORE },
- { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
- { "failed", no_argument, NULL, ARG_FAILED },
- { "full", no_argument, NULL, ARG_FULL },
- { "fail", no_argument, NULL, ARG_FAIL },
- { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
- { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
- { "ignore-inhibitors", no_argument, NULL, 'i' },
- { "user", no_argument, NULL, ARG_USER },
- { "system", no_argument, NULL, ARG_SYSTEM },
- { "global", no_argument, NULL, ARG_GLOBAL },
- { "no-block", no_argument, NULL, ARG_NO_BLOCK },
- { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
- { "no-pager", no_argument, NULL, ARG_NO_PAGER },
- { "no-wall", no_argument, NULL, ARG_NO_WALL },
- { "quiet", no_argument, NULL, 'q' },
- { "root", required_argument, NULL, ARG_ROOT },
- { "force", no_argument, NULL, ARG_FORCE },
- { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
- { "kill-who", required_argument, NULL, ARG_KILL_WHO },
- { "signal", required_argument, NULL, 's' },
- { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
- { "host", required_argument, NULL, 'H' },
- { "privileged",no_argument, NULL, 'P' },
- { "runtime", no_argument, NULL, ARG_RUNTIME },
- { "lines", required_argument, NULL, 'n' },
- { "output", required_argument, NULL, 'o' },
- { "plain", no_argument, NULL, ARG_PLAIN },
- { NULL, 0, NULL, 0 }
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "type", required_argument, NULL, 't' },
+ { "property", required_argument, NULL, 'p' },
+ { "all", no_argument, NULL, 'a' },
+ { "reverse", no_argument, NULL, ARG_REVERSE },
+ { "after", no_argument, NULL, ARG_AFTER },
+ { "before", no_argument, NULL, ARG_BEFORE },
+ { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
+ { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
+ { "full", no_argument, NULL, 'l' },
+ { "fail", no_argument, NULL, ARG_FAIL },
+ { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
+ { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
+ { "ignore-inhibitors", no_argument, NULL, 'i' },
+ { "user", no_argument, NULL, ARG_USER },
+ { "system", no_argument, NULL, ARG_SYSTEM },
+ { "global", no_argument, NULL, ARG_GLOBAL },
+ { "no-block", no_argument, NULL, ARG_NO_BLOCK },
+ { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
+ { "no-pager", no_argument, NULL, ARG_NO_PAGER },
+ { "no-wall", no_argument, NULL, ARG_NO_WALL },
+ { "quiet", no_argument, NULL, 'q' },
+ { "root", required_argument, NULL, ARG_ROOT },
+ { "force", no_argument, NULL, ARG_FORCE },
+ { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
+ { "kill-who", required_argument, NULL, ARG_KILL_WHO },
+ { "signal", required_argument, NULL, 's' },
+ { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
+ { "host", required_argument, NULL, 'H' },
+ { "privileged", no_argument, NULL, 'P' },
+ { "runtime", no_argument, NULL, ARG_RUNTIME },
+ { "lines", required_argument, NULL, 'n' },
+ { "output", required_argument, NULL, 'o' },
+ { "plain", no_argument, NULL, ARG_PLAIN },
+ { "state", required_argument, NULL, ARG_STATE },
+ { NULL, 0, NULL, 0 }
};
int c;
@@ -4774,7 +4980,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
+ while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:Pn:o:i", options, NULL)) >= 0) {
switch (c) {
@@ -4810,8 +5016,12 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
continue;
}
+ /* It's much nicer to use --state= for
+ * load states, but let's support this
+ * in --types= too for compatibility
+ * with old versions */
if (unit_load_state_from_string(optarg) >= 0) {
- if (strv_push(&arg_load_states, type))
+ if (strv_push(&arg_states, type) < 0)
return log_oom();
type = NULL;
continue;
@@ -4843,7 +5053,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
if (!prop)
return log_oom();
- if (strv_push(&arg_properties, prop)) {
+ if (strv_push(&arg_properties, prop) < 0) {
free(prop);
return log_oom();
}
@@ -4922,12 +5132,14 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
arg_root = optarg;
break;
- case ARG_FULL:
+ case 'l':
arg_full = true;
break;
case ARG_FAILED:
- arg_failed = true;
+ if (strv_extend(&arg_states, "failed") < 0)
+ return log_oom();
+
break;
case 'q':
@@ -4967,7 +5179,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
case 'H':
arg_transport = TRANSPORT_SSH;
- arg_host = optarg;
+ parse_user_at_host(optarg, &arg_user, &arg_host);
break;
case ARG_RUNTIME:
@@ -4997,6 +5209,25 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
arg_plain = true;
break;
+ case ARG_STATE: {
+ char *word, *state;
+ size_t size;
+
+ FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
+ char *s;
+
+ s = strndup(word, size);
+ if (!s)
+ return log_oom();
+
+ if (strv_push(&arg_states, s) < 0) {
+ free(s);
+ return log_oom();
+ }
+ }
+ break;
+ }
+
case '?':
return -EINVAL;
@@ -5447,94 +5678,6 @@ _pure_ static int action_to_runlevel(void) {
return table[arg_action];
}
-static int talk_upstart(void) {
- _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
- _cleanup_dbus_error_free_ DBusError error;
- int previous, rl, r;
- char
- env1_buf[] = "RUNLEVEL=X",
- env2_buf[] = "PREVLEVEL=X";
- char *env1 = env1_buf, *env2 = env2_buf;
- const char *emit = "runlevel";
- dbus_bool_t b_false = FALSE;
- DBusMessageIter iter, sub;
- DBusConnection *bus;
-
- dbus_error_init(&error);
-
- if (!(rl = action_to_runlevel()))
- return 0;
-
- if (utmp_get_runlevel(&previous, NULL) < 0)
- previous = 'N';
-
- if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
- if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
- r = 0;
- goto finish;
- }
-
- log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
- r = -EIO;
- goto finish;
- }
-
- if ((r = bus_check_peercred(bus)) < 0) {
- log_error("Failed to verify owner of bus.");
- goto finish;
- }
-
- if (!(m = dbus_message_new_method_call(
- "com.ubuntu.Upstart",
- "/com/ubuntu/Upstart",
- "com.ubuntu.Upstart0_6",
- "EmitEvent"))) {
-
- log_error("Could not allocate message.");
- r = -ENOMEM;
- goto finish;
- }
-
- dbus_message_iter_init_append(m, &iter);
-
- env1_buf[sizeof(env1_buf)-2] = rl;
- env2_buf[sizeof(env2_buf)-2] = previous;
-
- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
- !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
- !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
- !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
- !dbus_message_iter_close_container(&iter, &sub) ||
- !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
- log_error("Could not append arguments to message.");
- r = -ENOMEM;
- goto finish;
- }
-
- if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-
- if (bus_error_is_no_service(&error)) {
- r = -EADDRNOTAVAIL;
- goto finish;
- }
-
- log_error("Failed to issue method call: %s", bus_error_message(&error));
- r = -EIO;
- goto finish;
- }
-
- r = 1;
-
-finish:
- if (bus) {
- dbus_connection_flush(bus);
- dbus_connection_close(bus);
- dbus_connection_unref(bus);
- }
-
- return r;
-}
-
static int talk_initctl(void) {
struct init_request request = {};
int r;
@@ -5586,7 +5729,6 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
{ "list-sockets", LESS, 1, list_sockets },
{ "list-jobs", EQUAL, 1, list_jobs },
{ "clear-jobs", EQUAL, 1, daemon_reload },
- { "load", MORE, 2, load_unit },
{ "cancel", MORE, 2, cancel_job },
{ "start", MORE, 2, start_unit },
{ "stop", MORE, 2, start_unit },
@@ -5600,11 +5742,6 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
{ "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
{ "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
{ "isolate", EQUAL, 2, start_unit },
- { "set-cgroup", MORE, 3, set_cgroup },
- { "unset-cgroup", MORE, 3, set_cgroup },
- { "get-cgroup-attr", MORE, 3, get_cgroup_attr },
- { "set-cgroup-attr", MORE, 4, set_cgroup_attr },
- { "unset-cgroup-attr", MORE, 3, set_cgroup },
{ "kill", MORE, 2, kill_unit },
{ "is-active", MORE, 2, check_unit_active },
{ "check", MORE, 2, check_unit_active },
@@ -5612,7 +5749,6 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
{ "show", MORE, 1, show },
{ "status", MORE, 1, show },
{ "help", MORE, 2, show },
- { "dump", EQUAL, 1, dump },
{ "snapshot", LESS, 2, snapshot },
{ "delete", MORE, 2, delete_snapshot },
{ "daemon-reload", EQUAL, 1, daemon_reload },
@@ -5642,6 +5778,9 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
{ "link", MORE, 2, enable_unit },
{ "switch-root", MORE, 2, switch_root },
{ "list-dependencies", LESS, 2, list_dependencies },
+ { "set-default", EQUAL, 2, enable_unit },
+ { "get-default", LESS, 1, get_default },
+ { "set-property", MORE, 3, set_property },
};
int left;
@@ -5713,7 +5852,9 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
!streq(verbs[i].verb, "preset") &&
!streq(verbs[i].verb, "mask") &&
!streq(verbs[i].verb, "unmask") &&
- !streq(verbs[i].verb, "link")) {
+ !streq(verbs[i].verb, "link") &&
+ !streq(verbs[i].verb, "set-default") &&
+ !streq(verbs[i].verb, "get-default")) {
if (running_in_chroot() > 0) {
log_info("Running in chroot, ignoring request.");
@@ -5808,11 +5949,6 @@ static int start_with_fallback(DBusConnection *bus) {
goto done;
}
- /* Hmm, talking to systemd via D-Bus didn't work. Then
- * let's try to talk to Upstart via D-Bus. */
- if (talk_upstart() > 0)
- goto done;
-
/* Nothing else worked, so let's try
* /dev/initctl */
if (talk_initctl() > 0)
@@ -5954,6 +6090,11 @@ int main(int argc, char*argv[]) {
log_parse_environment();
log_open();
+ /* Explicitly not on_tty() to avoid setting cached value.
+ * This becomes relevant for piping output which might be
+ * ellipsized. */
+ original_stdout_is_tty = isatty(STDOUT_FILENO);
+
r = parse_argv(argc, argv);
if (r < 0)
goto finish;
@@ -5983,7 +6124,7 @@ int main(int argc, char*argv[]) {
bus_connect_system_polkit(&bus, &error);
private_bus = false;
} else if (arg_transport == TRANSPORT_SSH) {
- bus_connect_system_ssh(NULL, arg_host, &bus, &error);
+ bus_connect_system_ssh(arg_user, arg_host, &bus, &error);
private_bus = false;
} else
assert_not_reached("Uh, invalid transport...");
@@ -6052,7 +6193,7 @@ finish:
dbus_shutdown();
strv_free(arg_types);
- strv_free(arg_load_states);
+ strv_free(arg_states);
strv_free(arg_properties);
pager_close();
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index c1ec50871f..878001ccb5 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -27,6 +27,7 @@
#include <sd-id128.h>
#include "sd-bus-protocol.h"
+#include "sd-memfd.h"
#ifdef __cplusplus
extern "C" {
@@ -40,18 +41,6 @@ extern "C" {
# endif
#endif
-/* TODO:
- * - add page donation logic
- * - api for appending/reading fixed arrays
- * - merge busctl into systemctl or so?
- * - default policy (allow uid == 0 and our own uid)
- *
- * - enforce alignment of pointers passed in
- * - negotiation for attach attributes
- *
- * - for kernel and unix transports allow setting the unix user/access mode for the node
- */
-
typedef struct sd_bus sd_bus;
typedef struct sd_bus_message sd_bus_message;
@@ -61,7 +50,7 @@ typedef struct {
int need_free;
} sd_bus_error;
-typedef int (*sd_bus_message_handler_t)(sd_bus *bus, int ret, sd_bus_message *m, void *userdata);
+typedef int (*sd_bus_message_handler_t)(sd_bus *bus, sd_bus_message *m, void *userdata);
/* Connections */
@@ -75,7 +64,14 @@ int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[]);
int sd_bus_set_bus_client(sd_bus *bus, int b);
int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id);
int sd_bus_set_anonymous(sd_bus *bus, int b);
-int sd_bus_set_negotiate_fds(sd_bus *bus, int b);
+int sd_bus_negotiate_fds(sd_bus *bus, int b);
+int sd_bus_negotiate_attach_comm(sd_bus *bus, int b);
+int sd_bus_negotiate_attach_exe(sd_bus *bus, int b);
+int sd_bus_negotiate_attach_cmdline(sd_bus *bus, int b);
+int sd_bus_negotiate_attach_cgroup(sd_bus *bus, int b);
+int sd_bus_negotiate_attach_caps(sd_bus *bus, int b);
+int sd_bus_negotiate_attach_selinux_context(sd_bus *bus, int b);
+int sd_bus_negotiate_attach_audit(sd_bus *bus, int b);
int sd_bus_start(sd_bus *ret);
void sd_bus_close(sd_bus *bus);
@@ -163,11 +159,17 @@ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination);
int sd_bus_message_append(sd_bus_message *m, const char *types, ...);
int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p);
+int sd_bus_message_append_array(sd_bus_message *m, char type, const void *ptr, size_t size);
+int sd_bus_message_append_array_space(sd_bus_message *m, char type, size_t size, void **ptr);
+int sd_bus_message_append_array_memfd(sd_bus_message *m, char type, sd_memfd *memfd);
+int sd_bus_message_append_string_space(sd_bus_message *m, size_t size, char **s);
+int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd* memfd);
int sd_bus_message_open_container(sd_bus_message *m, char type, const char *contents);
int sd_bus_message_close_container(sd_bus_message *m);
int sd_bus_message_read(sd_bus_message *m, const char *types, ...);
int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p);
+int sd_bus_message_read_array(sd_bus_message *m, char type, const void **ptr, size_t *size);
int sd_bus_message_enter_container(sd_bus_message *m, char type, const char *contents);
int sd_bus_message_exit_container(sd_bus_message *m);
int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents);
@@ -203,6 +205,12 @@ int sd_bus_error_copy(sd_bus_error *dest, const sd_bus_error *e);
int sd_bus_error_is_set(const sd_bus_error *e);
int sd_bus_error_has_name(const sd_bus_error *e, const char *name);
+#define SD_BUS_APPEND_ID128(x) 16, \
+ (x).bytes[0], (x).bytes[1], (x).bytes[2], (x).bytes[3], \
+ (x).bytes[4], (x).bytes[5], (x).bytes[6], (x).bytes[7], \
+ (x).bytes[8], (x).bytes[9], (x).bytes[10], (x).bytes[11], \
+ (x).bytes[12], (x).bytes[13], (x).bytes[14], (x).bytes[15]
+
#ifdef __cplusplus
}
#endif
diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h
index 5375d49963..72ea328b28 100644
--- a/src/systemd/sd-journal.h
+++ b/src/systemd/sd-journal.h
@@ -86,7 +86,9 @@ typedef struct sd_journal sd_journal;
enum {
SD_JOURNAL_LOCAL_ONLY = 1,
SD_JOURNAL_RUNTIME_ONLY = 2,
- SD_JOURNAL_SYSTEM_ONLY = 4
+ SD_JOURNAL_SYSTEM = 4,
+ SD_JOURNAL_SYSTEM_ONLY = SD_JOURNAL_SYSTEM, /* deprecated */
+ SD_JOURNAL_CURRENT_USER = 8,
};
/* Wakeup event types */
@@ -98,6 +100,7 @@ enum {
int sd_journal_open(sd_journal **ret, int flags);
int sd_journal_open_directory(sd_journal **ret, const char *path, int flags);
+int sd_journal_open_files(sd_journal **ret, const char **paths, int flags);
void sd_journal_close(sd_journal *j);
int sd_journal_previous(sd_journal *j);
diff --git a/src/systemd/sd-login.h b/src/systemd/sd-login.h
index 4855e327a1..c5837f0ca0 100644
--- a/src/systemd/sd-login.h
+++ b/src/systemd/sd-login.h
@@ -72,9 +72,12 @@ int sd_pid_get_unit(pid_t pid, char **unit);
int sd_pid_get_user_unit(pid_t pid, char **unit);
/* Get machine name from PID, for processes assigned to VM or
- * container. This will return an error for non-service processes. */
+ * container. This will return an error for non-machine processes. */
int sd_pid_get_machine_name(pid_t pid, char **name);
+/* Get slice name from PID. */
+int sd_pid_get_slice(pid_t pid, char **name);
+
/* Get state from uid. Possible states: offline, lingering, online, active, closing */
int sd_uid_get_state(uid_t uid, char**state);
@@ -121,6 +124,9 @@ int sd_session_get_display(const char *session, char **display);
/* Determine the TTY of this session. */
int sd_session_get_tty(const char *session, char **display);
+/* Determine the VT number of this session. */
+int sd_session_get_vt(const char *session, unsigned *vtnr);
+
/* Return active session and user of seat */
int sd_seat_get_active(const char *seat, char **session, uid_t *uid);
diff --git a/src/systemd/sd-memfd.h b/src/systemd/sd-memfd.h
new file mode 100644
index 0000000000..ee140e48d3
--- /dev/null
+++ b/src/systemd/sd-memfd.h
@@ -0,0 +1,58 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#ifndef foosdmemfdhfoo
+#define foosdmemfdhfoo
+
+/***
+ 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 <sys/types.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct sd_memfd sd_memfd;
+
+int sd_memfd_new(sd_memfd **m);
+int sd_memfd_make(int fd, sd_memfd **m);
+
+int sd_memfd_new_and_map(sd_memfd **m, size_t sz, void **p);
+
+void sd_memfd_free(sd_memfd *m);
+
+int sd_memfd_get_fd(sd_memfd *m);
+int sd_memfd_get_file(sd_memfd *m, FILE **f);
+int sd_memfd_dup_fd(sd_memfd *n);
+
+int sd_memfd_map(sd_memfd *m, uint64_t offset, size_t size, void **p);
+
+int sd_memfd_set_sealed(sd_memfd *m, int b);
+int sd_memfd_get_sealed(sd_memfd *m);
+
+int sd_memfd_get_size(sd_memfd *m, uint64_t *sz);
+int sd_memfd_set_size(sd_memfd *m, uint64_t sz);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/systemd/sd-messages.h b/src/systemd/sd-messages.h
index c8de331691..c811a064e3 100644
--- a/src/systemd/sd-messages.h
+++ b/src/systemd/sd-messages.h
@@ -31,10 +31,15 @@ extern "C" {
/* Hey! If you add a new message here, you *must* also update the
* message catalog with an appropriate explanation */
+/* And if you add a new ID here, make sure to generate a random one
+ * with journalctl --new-id128. Do not use any other IDs, and do not
+ * count them up manually. */
+
#define SD_MESSAGE_JOURNAL_START SD_ID128_MAKE(f7,73,79,a8,49,0b,40,8b,be,5f,69,40,50,5a,77,7b)
#define SD_MESSAGE_JOURNAL_STOP SD_ID128_MAKE(d9,3f,b3,c9,c2,4d,45,1a,97,ce,a6,15,ce,59,c0,0b)
#define SD_MESSAGE_JOURNAL_DROPPED SD_ID128_MAKE(a5,96,d6,fe,7b,fa,49,94,82,8e,72,30,9e,95,d6,1e)
#define SD_MESSAGE_JOURNAL_MISSED SD_ID128_MAKE(e9,bf,28,e6,e8,34,48,1b,b6,f4,8f,54,8a,d1,36,06)
+#define SD_MESSAGE_JOURNAL_USAGE SD_ID128_MAKE(ec,38,7f,57,7b,84,4b,8f,a9,48,f3,3c,ad,9a,75,e6)
#define SD_MESSAGE_COREDUMP SD_ID128_MAKE(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1)
@@ -42,6 +47,8 @@ extern "C" {
#define SD_MESSAGE_SESSION_STOP SD_ID128_MAKE(33,54,93,94,24,b4,45,6d,98,02,ca,83,33,ed,42,4a)
#define SD_MESSAGE_SEAT_START SD_ID128_MAKE(fc,be,fc,5d,a2,3d,42,80,93,f9,7c,82,a9,29,0f,7b)
#define SD_MESSAGE_SEAT_STOP SD_ID128_MAKE(e7,85,2b,fe,46,78,4e,d0,ac,cd,e0,4b,c8,64,c2,d5)
+#define SD_MESSAGE_MACHINE_START SD_ID128_MAKE(24,d8,d4,45,25,73,40,24,96,06,83,81,a6,31,2d,f2)
+#define SD_MESSAGE_MACHINE_STOP SD_ID128_MAKE(58,43,2b,d3,ba,ce,47,7c,b5,14,b5,63,81,b8,a7,58)
#define SD_MESSAGE_TIME_CHANGE SD_ID128_MAKE(c7,a7,87,07,9b,35,4e,aa,a9,e7,7b,37,18,93,cd,27)
#define SD_MESSAGE_TIMEZONE_CHANGE SD_ID128_MAKE(45,f8,2f,4a,ef,7a,4b,bf,94,2c,e8,61,d1,f2,09,90)
diff --git a/src/test/test-boot-timestamps.c b/src/test/test-boot-timestamps.c
new file mode 100644
index 0000000000..4ede318e38
--- /dev/null
+++ b/src/test/test-boot-timestamps.c
@@ -0,0 +1,98 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2013 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 "util.h"
+#include "log.h"
+#include "boot-timestamps.h"
+#include "efivars.h"
+#include "acpi-fpdt.h"
+
+static int test_acpi_fpdt(void) {
+ usec_t loader_start;
+ usec_t loader_exit;
+ char ts_start[FORMAT_TIMESPAN_MAX];
+ char ts_exit[FORMAT_TIMESPAN_MAX];
+ char ts_span[FORMAT_TIMESPAN_MAX];
+ int r;
+
+ r = acpi_get_boot_usec(&loader_start, &loader_exit);
+ if (r < 0) {
+ if (r != -ENOENT)
+ log_error("Failed to read ACPI FPDT: %s", strerror(-r));
+ return r;
+ }
+
+ log_info("ACPI FPDT: loader start=%s exit=%s duration=%s",
+ format_timespan(ts_start, sizeof(ts_start), loader_start, USEC_PER_MSEC),
+ format_timespan(ts_exit, sizeof(ts_exit), loader_exit, USEC_PER_MSEC),
+ format_timespan(ts_span, sizeof(ts_span), loader_exit - loader_start, USEC_PER_MSEC));
+
+ return 0;
+}
+
+static int test_efi_loader(void) {
+ usec_t loader_start;
+ usec_t loader_exit;
+ char ts_start[FORMAT_TIMESPAN_MAX];
+ char ts_exit[FORMAT_TIMESPAN_MAX];
+ char ts_span[FORMAT_TIMESPAN_MAX];
+ int r;
+
+ r = efi_loader_get_boot_usec(&loader_start, &loader_exit);
+ if (r < 0) {
+ if (r != -ENOENT)
+ log_error("Failed to read EFI loader data: %s", strerror(-r));
+ return r;
+ }
+
+ log_info("EFI Loader: start=%s exit=%s duration=%s",
+ format_timespan(ts_start, sizeof(ts_start), loader_start, USEC_PER_MSEC),
+ format_timespan(ts_exit, sizeof(ts_exit), loader_exit, USEC_PER_MSEC),
+ format_timespan(ts_span, sizeof(ts_span), loader_exit - loader_start, USEC_PER_MSEC));
+
+ return 0;
+}
+
+int main(int argc, char* argv[]) {
+ char s[MAX(FORMAT_TIMESPAN_MAX, FORMAT_TIMESTAMP_MAX)];
+ int r;
+ dual_timestamp fw, l, k;
+
+ test_acpi_fpdt();
+ test_efi_loader();
+
+ dual_timestamp_from_monotonic(&k, 0);
+
+ r = boot_timestamps(NULL, &fw, &l);
+ if (r < 0) {
+ log_error("Failed to read variables: %s", strerror(-r));
+ return 1;
+ }
+
+ log_info("Firmware began %s before kernel.", format_timespan(s, sizeof(s), fw.monotonic, 0));
+ log_info("Loader began %s before kernel.", format_timespan(s, sizeof(s), l.monotonic, 0));
+ log_info("Firmware began %s.", format_timestamp(s, sizeof(s), fw.realtime));
+ log_info("Loader began %s.", format_timestamp(s, sizeof(s), l.realtime));
+ log_info("Kernel began %s.", format_timestamp(s, sizeof(s), k.realtime));
+
+ return 0;
+}
diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c
index c9634d42b0..16bf968340 100644
--- a/src/test/test-cgroup-util.c
+++ b/src/test/test-cgroup-util.c
@@ -23,6 +23,7 @@
#include "util.h"
#include "cgroup-util.h"
+#include "test-helper.h"
static void check_p_d_u(const char *path, int code, const char *result) {
_cleanup_free_ char *unit = NULL;
@@ -32,12 +33,15 @@ static void check_p_d_u(const char *path, int code, const char *result) {
}
static void test_path_decode_unit(void) {
- check_p_d_u("getty@.service/getty@tty2.service", 0, "getty@tty2.service");
- check_p_d_u("getty@.service/getty@tty2.service/xxx", 0, "getty@tty2.service");
+ check_p_d_u("getty@tty2.service", 0, "getty@tty2.service");
+ check_p_d_u("getty@tty2.service/", 0, "getty@tty2.service");
+ check_p_d_u("getty@tty2.service/xxx", 0, "getty@tty2.service");
check_p_d_u("getty@.service/", -EINVAL, NULL);
check_p_d_u("getty@.service", -EINVAL, NULL);
check_p_d_u("getty.service", 0, "getty.service");
check_p_d_u("getty", -EINVAL, NULL);
+ check_p_d_u("getty/waldo", -EINVAL, NULL);
+ check_p_d_u("_cpu.service", 0, "cpu.service");
}
static void check_p_g_u(const char *path, int code, const char *result) {
@@ -47,6 +51,18 @@ static void check_p_g_u(const char *path, int code, const char *result) {
assert_se(streq_ptr(unit, result));
}
+static void test_path_get_unit(void) {
+ check_p_g_u("/system.slice/foobar.service/sdfdsaf", 0, "foobar.service");
+ check_p_g_u("/system.slice/getty@tty5.service", 0, "getty@tty5.service");
+ check_p_g_u("/system.slice/getty@tty5.service/aaa/bbb", 0, "getty@tty5.service");
+ check_p_g_u("/system.slice/getty@tty5.service/", 0, "getty@tty5.service");
+ check_p_g_u("/system.slice/getty@tty6.service/tty5", 0, "getty@tty6.service");
+ check_p_g_u("sadfdsafsda", -EINVAL, NULL);
+ check_p_g_u("/system.slice/getty####@tty6.service/xxx", -EINVAL, NULL);
+ check_p_g_u("/system.slice/system-waldo.slice/foobar.service/sdfdsaf", 0, "foobar.service");
+ check_p_g_u("/system.slice/system-waldo.slice/_cpu.service/sdfdsaf", 0, "cpu.service");
+}
+
static void check_p_g_u_u(const char *path, int code, const char *result) {
_cleanup_free_ char *unit = NULL;
@@ -54,39 +70,65 @@ static void check_p_g_u_u(const char *path, int code, const char *result) {
assert_se(streq_ptr(unit, result));
}
-static void test_path_get_unit(void) {
- check_p_g_u("/system/foobar.service/sdfdsaf", 0, "foobar.service");
- check_p_g_u("/system/getty@.service/getty@tty5.service", 0, "getty@tty5.service");
- check_p_g_u("/system/getty@.service/getty@tty5.service/aaa/bbb", 0, "getty@tty5.service");
- check_p_g_u("/system/getty@.service/getty@tty5.service/", 0, "getty@tty5.service");
- check_p_g_u("/system/getty@tty6.service/tty5", 0, "getty@tty6.service");
- check_p_g_u("sadfdsafsda", -ENOENT, NULL);
- check_p_g_u("/system/getty####@tty6.service/tty5", -EINVAL, NULL);
+static void test_path_get_user_unit(void) {
+ check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/foobar.service", 0, "foobar.service");
+ check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/waldo.slice/foobar.service", 0, "foobar.service");
+ check_p_g_u_u("/user.slice/user-1002.slice/session-2.scope/foobar.service/waldo", 0, "foobar.service");
+ check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/foobar.service/waldo/uuuux", 0, "foobar.service");
+ check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/waldo/waldo/uuuux", -EINVAL, NULL);
+ check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/foobar@pie.service/pa/po", 0, "foobar@pie.service");
+ check_p_g_u_u("/session-2.scope/foobar@pie.service/pa/po", 0, "foobar@pie.service");
+ check_p_g_u_u("/xyz.slice/xyz-waldo.slice/session-77.scope/foobar@pie.service/pa/po", 0, "foobar@pie.service");
+ check_p_g_u_u("/meh.service", -ENOENT, NULL);
+ check_p_g_u_u("/session-3.scope/_cpu.service", 0, "cpu.service");
}
-static void test_path_get_user_unit(void) {
- check_p_g_u_u("/user/lennart/2/systemd-21548/foobar.service", 0, "foobar.service");
- check_p_g_u_u("/user/lennart/2/systemd-21548/foobar.service/waldo", 0, "foobar.service");
- check_p_g_u_u("/user/lennart/2/systemd-21548/foobar.service/waldo/uuuux", 0, "foobar.service");
- check_p_g_u_u("/user/lennart/2/systemd-21548/waldo/waldo/uuuux", -EINVAL, NULL);
- check_p_g_u_u("/user/lennart/2/foobar.service", -ENOENT, NULL);
- check_p_g_u_u("/user/lennart/2/systemd-21548/foobar@.service/foobar@pie.service/pa/po", 0, "foobar@pie.service");
+static void check_p_g_s(const char *path, int code, const char *result) {
+ _cleanup_free_ char *s = NULL;
+
+ assert_se(cg_path_get_session(path, &s) == code);
+ assert_se(streq_ptr(s, result));
}
-static void test_get_paths(void) {
- _cleanup_free_ char *a = NULL, *b = NULL, *c = NULL, *d = NULL;
+static void test_path_get_session(void) {
+ check_p_g_s("/user.slice/user-1000.slice/session-2.scope/foobar.service", 0, "2");
+ check_p_g_s("/session-3.scope", 0, "3");
+ check_p_g_s("", -ENOENT, 0);
+}
- assert_se(cg_get_root_path(&a) >= 0);
- log_info("Root = %s", a);
+static void check_p_g_o_u(const char *path, int code, uid_t result) {
+ uid_t uid = 0;
+
+ assert_se(cg_path_get_owner_uid(path, &uid) == code);
+ assert_se(uid == result);
+}
+
+static void test_path_get_owner_uid(void) {
+ check_p_g_o_u("/user.slice/user-1000.slice/session-2.scope/foobar.service", 0, 1000);
+ check_p_g_o_u("/user.slice/user-1006.slice", 0, 1006);
+ check_p_g_o_u("", -ENOENT, 0);
+}
+
+static void check_p_g_m_n(const char *path, int code, const char *result) {
+ _cleanup_free_ char *m = NULL;
- assert_se(cg_get_system_path(&b) >= 0);
- log_info("System = %s", b);
+ assert_se(cg_path_get_machine_name(path, &m) == code);
+ assert_se(streq_ptr(m, result));
+}
- assert_se(cg_get_user_path(&c) >= 0);
- log_info("User = %s", c);
+static void test_path_get_machine_name(void) {
+ check_p_g_m_n("/user.slice/machine-foobar.scope", 0, "foobar");
+ check_p_g_m_n("/machine-foobar.scope", 0, "foobar");
+ check_p_g_m_n("/user.slice/user-kuux.slice/machine-foobar.scope", 0, "foobar");
+ check_p_g_m_n("/user.slice/user-kuux.slice/machine-foobar.scope/asjhdkj", 0, "foobar");
+ check_p_g_m_n("", -ENOENT, NULL);
+}
- assert_se(cg_get_machine_path("harley", &d) >= 0);
- log_info("Machine = %s", d);
+static void test_get_paths(void) {
+ _cleanup_free_ char *a = NULL;
+
+ assert_se(cg_get_root_path(&a) >= 0);
+ log_info("Root = %s", a);
}
static void test_proc(void) {
@@ -98,7 +140,7 @@ static void test_proc(void) {
assert_se(d);
FOREACH_DIRENT(de, d, break) {
- _cleanup_free_ char *path = NULL, *path_shifted = NULL, *session = NULL, *unit = NULL, *user_unit = NULL, *machine = NULL, *prefix = NULL;
+ _cleanup_free_ char *path = NULL, *path_shifted = NULL, *session = NULL, *unit = NULL, *user_unit = NULL, *machine = NULL, *prefix = NULL, *slice = NULL;
pid_t pid;
uid_t uid = (uid_t) -1;
@@ -120,8 +162,9 @@ static void test_proc(void) {
cg_pid_get_unit(pid, &unit);
cg_pid_get_user_unit(pid, &user_unit);
cg_pid_get_machine_name(pid, &machine);
+ cg_pid_get_slice(pid, &slice);
- printf("%lu\t%s\t%s\t%s\t%lu\t%s\t%s\t%s\t%s\n",
+ printf("%lu\t%s\t%s\t%s\t%lu\t%s\t%s\t%s\t%s\t%s\n",
(unsigned long) pid,
path,
prefix,
@@ -130,7 +173,8 @@ static void test_proc(void) {
session,
unit,
user_unit,
- machine);
+ machine,
+ slice);
}
}
@@ -170,14 +214,37 @@ static void test_controller_is_valid(void) {
assert_se(!cg_controller_is_valid("tatü", false));
}
+static void test_slice_to_path_one(const char *unit, const char *path, int error) {
+ _cleanup_free_ char *ret = NULL;
+
+ assert_se(cg_slice_to_path(unit, &ret) == error);
+ assert_se(streq_ptr(ret, path));
+}
+
+static void test_slice_to_path(void) {
+
+ test_slice_to_path_one("foobar.slice", "foobar.slice", 0);
+ test_slice_to_path_one("foobar-waldo.slice", "foobar.slice/foobar-waldo.slice", 0);
+ test_slice_to_path_one("foobar-waldo.service", NULL, -EINVAL);
+ test_slice_to_path_one("-.slice", NULL, -EINVAL);
+ test_slice_to_path_one("-foo-.slice", NULL, -EINVAL);
+ test_slice_to_path_one("-foo.slice", NULL, -EINVAL);
+ test_slice_to_path_one("a-b.slice", "a.slice/a-b.slice", 0);
+ test_slice_to_path_one("a-b-c-d-e.slice", "a.slice/a-b.slice/a-b-c.slice/a-b-c-d.slice/a-b-c-d-e.slice", 0);
+}
+
int main(void) {
test_path_decode_unit();
test_path_get_unit();
test_path_get_user_unit();
- test_get_paths();
+ test_path_get_session();
+ test_path_get_owner_uid();
+ test_path_get_machine_name();
+ TEST_REQ_RUNNING_SYSTEMD(test_get_paths());
test_proc();
- test_escape();
+ TEST_REQ_RUNNING_SYSTEMD(test_escape());
test_controller_is_valid();
+ test_slice_to_path();
return 0;
}
diff --git a/src/test/test-cgroup.c b/src/test/test-cgroup.c
index 3a3489d6a2..2a0ce27206 100644
--- a/src/test/test-cgroup.c
+++ b/src/test/test-cgroup.c
@@ -31,10 +31,10 @@ int main(int argc, char*argv[]) {
char *path;
char *c, *p;
- assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-a", NULL) == 0);
- assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-a", NULL) == 0);
- assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-b", NULL) == 0);
- assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-b/test-c", NULL) == 0);
+ assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-a") == 0);
+ assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-a") == 0);
+ assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-b") == 0);
+ assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-b/test-c") == 0);
assert_se(cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0) == 0);
assert_se(cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, getpid(), &path) == 0);
diff --git a/src/test/test-device-nodes.c b/src/test/test-device-nodes.c
new file mode 100644
index 0000000000..2f3dedb90f
--- /dev/null
+++ b/src/test/test-device-nodes.c
@@ -0,0 +1,55 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ 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/>.
+***/
+
+#include <sys/types.h>
+
+#include "device-nodes.h"
+#include "util.h"
+
+/* helpers for test_encode_devnode_name */
+static char *do_encode_string(const char *in) {
+ size_t out_len = strlen(in) * 4;
+ char *out = malloc(out_len);
+
+ assert_se(out);
+ assert_se(encode_devnode_name(in, out, out_len) >= 0);
+ puts(out);
+
+ return out;
+}
+
+static bool expect_encoded_as(const char *in, const char *expected) {
+ _cleanup_free_ char *encoded = do_encode_string(in);
+ return streq(encoded, expected);
+}
+
+static void test_encode_devnode_name(void) {
+ assert_se(expect_encoded_as("systemd sucks", "systemd\\x20sucks"));
+ assert_se(expect_encoded_as("pinkiepie", "pinkiepie"));
+ assert_se(expect_encoded_as("valíd\\ųtf8", "valíd\\x5cųtf8"));
+ assert_se(expect_encoded_as("s/ash/ng", "s\\x2fash\\x2fng"));
+}
+
+int main(int argc, char *argv[]) {
+ test_encode_devnode_name();
+
+ return 0;
+}
diff --git a/src/test/test-efivars.c b/src/test/test-efivars.c
deleted file mode 100644
index 43ea5917b6..0000000000
--- a/src/test/test-efivars.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- 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 "log.h"
-#include "efivars.h"
-
-int main(int argc, char* argv[]) {
- char s[MAX(FORMAT_TIMESPAN_MAX, FORMAT_TIMESTAMP_MAX)];
- int r;
- dual_timestamp fw, l, k;
-
- dual_timestamp_from_monotonic(&k, 0);
-
- r = efi_get_boot_timestamps(NULL, &fw, &l);
- if (r < 0) {
- log_error("Failed to read variables: %s", strerror(-r));
- return 1;
- }
-
- log_info("Firmware began %s before kernel.", format_timespan(s, sizeof(s), fw.monotonic, 0));
- log_info("Loader began %s before kernel.", format_timespan(s, sizeof(s), l.monotonic, 0));
-
- log_info("Firmware began %s.", format_timestamp(s, sizeof(s), fw.realtime));
- log_info("Loader began %s.", format_timestamp(s, sizeof(s), l.realtime));
- log_info("Kernel began %s.", format_timestamp(s, sizeof(s), k.realtime));
-
- return 0;
-}
diff --git a/src/test/test-engine.c b/src/test/test-engine.c
index 0f3862226a..20ae103a19 100644
--- a/src/test/test-engine.c
+++ b/src/test/test-engine.c
@@ -33,7 +33,7 @@ int main(int argc, char *argv[]) {
assert_se(set_unit_path("test") >= 0);
- assert_se(manager_new(SYSTEMD_SYSTEM, &m) >= 0);
+ assert_se(manager_new(SYSTEMD_SYSTEM, false, &m) >= 0);
printf("Load1:\n");
assert_se(manager_load_unit(m, "a.service", NULL, NULL, &a) >= 0);
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
index d56f7cc856..06f3e28288 100644
--- a/src/test/test-fileio.c
+++ b/src/test/test-fileio.c
@@ -27,9 +27,12 @@
#include "fileio.h"
#include "strv.h"
#include "env-util.h"
+#include "def.h"
+#include "ctype.h"
static void test_parse_env_file(void) {
- char t[] = "/tmp/test-parse-env-file-XXXXXX";
+ char t[] = "/tmp/test-fileio-in-XXXXXX",
+ p[] = "/tmp/test-fileio-out-XXXXXX";
int fd, r;
FILE *f;
_cleanup_free_ char *one = NULL, *two = NULL, *three = NULL, *four = NULL, *five = NULL,
@@ -38,6 +41,8 @@ static void test_parse_env_file(void) {
char **i;
unsigned k;
+ assert_se(mktemp(p));
+
fd = mkostemp(t, O_CLOEXEC);
assert_se(fd >= 0);
@@ -83,7 +88,7 @@ static void test_parse_env_file(void) {
assert_se(streq(a[9], "ten="));
assert_se(a[10] == NULL);
- strv_env_clean_log(a, "/tmp/test-fileio");
+ strv_env_clean_log(a, "test");
k = 0;
STRV_FOREACH(i, b) {
@@ -129,17 +134,167 @@ static void test_parse_env_file(void) {
assert_se(streq(nine, "nineval"));
assert_se(ten == NULL);
- r = write_env_file("/tmp/test-fileio", a);
+ r = write_env_file(p, a);
assert_se(r >= 0);
- r = load_env_file("/tmp/test-fileio", NULL, &b);
+ r = load_env_file(p, NULL, &b);
assert_se(r >= 0);
unlink(t);
- unlink("/tmp/test-fileio");
+ unlink(p);
+}
+
+static void test_parse_multiline_env_file(void) {
+ char t[] = "/tmp/test-fileio-in-XXXXXX",
+ p[] = "/tmp/test-fileio-out-XXXXXX";
+ int fd, r;
+ FILE *f;
+ _cleanup_strv_free_ char **a = NULL, **b = NULL;
+ char **i;
+
+ assert_se(mktemp(p));
+
+ fd = mkostemp(t, O_CLOEXEC);
+ assert_se(fd >= 0);
+
+ f = fdopen(fd, "w");
+ assert_se(f);
+
+ fputs("one=BAR\\\n"
+ " VAR\\\n"
+ "\tGAR\n"
+ "#comment\n"
+ "two=\"bar\\\n"
+ " var\\\n"
+ "\tgar\"\n"
+ "#comment\n"
+ "tri=\"bar \\\n"
+ " var \\\n"
+ "\tgar \"\n", f);
+
+ fflush(f);
+ fclose(f);
+
+ r = load_env_file(t, NULL, &a);
+ assert_se(r >= 0);
+
+ STRV_FOREACH(i, a)
+ log_info("Got: <%s>", *i);
+
+ assert_se(streq(a[0], "one=BAR VAR\tGAR"));
+ assert_se(streq(a[1], "two=bar var\tgar"));
+ assert_se(streq(a[2], "tri=bar var \tgar "));
+ assert_se(a[3] == NULL);
+
+ r = write_env_file(p, a);
+ assert_se(r >= 0);
+
+ r = load_env_file(p, NULL, &b);
+ assert_se(r >= 0);
+
+ unlink(t);
+ unlink(p);
+}
+
+
+static void test_executable_is_script(void) {
+ char t[] = "/tmp/test-executable-XXXXXX";
+ int fd, r;
+ FILE *f;
+ char *command;
+
+ fd = mkostemp(t, O_CLOEXEC);
+ assert_se(fd >= 0);
+
+ f = fdopen(fd, "w");
+ assert_se(f);
+
+ fputs("#! /bin/script -a -b \ngoo goo", f);
+ fflush(f);
+
+ r = executable_is_script(t, &command);
+ assert_se(r > 0);
+ assert_se(streq(command, "/bin/script"));
+ free(command);
+
+ r = executable_is_script("/bin/sh", &command);
+ assert_se(r == 0);
+
+ r = executable_is_script("/usr/bin/yum", &command);
+ assert_se(r > 0 || r == -ENOENT);
+ if (r > 0) {
+ assert_se(startswith(command, "/"));
+ free(command);
+ }
+
+ fclose(f);
+ unlink(t);
+}
+
+static void test_status_field(void) {
+ _cleanup_free_ char *t = NULL, *p = NULL, *s = NULL, *z = NULL;
+ unsigned long long total = 0, buffers = 0;
+ int r;
+
+ assert_se(get_status_field("/proc/self/status", "\nThreads:", &t) == 0);
+ puts(t);
+ assert_se(streq(t, "1"));
+
+ r = get_status_field("/proc/meminfo", "MemTotal:", &p);
+ if (r != -ENOENT) {
+ assert(r == 0);
+ puts(p);
+ assert_se(safe_atollu(p, &total) == 0);
+ }
+
+ r = get_status_field("/proc/meminfo", "\nBuffers:", &s);
+ if (r != -ENOENT) {
+ assert(r == 0);
+ puts(s);
+ assert_se(safe_atollu(s, &buffers) == 0);
+ }
+
+ if (p && t)
+ assert(buffers < total);
+
+ /* Seccomp should be a good test for field full of zeros. */
+ r = get_status_field("/proc/meminfo", "\nSeccomp:", &z);
+ if (r != -ENOENT) {
+ assert(r == 0);
+ puts(z);
+ assert_se(safe_atollu(z, &buffers) == 0);
+ }
+}
+
+static void test_capeff(void) {
+ int pid, p;
+
+ for (pid = 0; pid < 2; pid++) {
+ _cleanup_free_ char *capeff = NULL;
+ int r;
+
+ r = get_process_capeff(0, &capeff);
+ log_info("capeff: '%s' (r=%d)", capeff, r);
+
+ if (r == -ENOENT || r == -EPERM)
+ return;
+
+ assert(r == 0);
+ assert(*capeff);
+ p = capeff[strspn(capeff, DIGITS "abcdefABCDEF")];
+ assert(!p || isspace(p));
+ }
}
int main(int argc, char *argv[]) {
+ log_parse_environment();
+ log_open();
+
test_parse_env_file();
+ test_parse_multiline_env_file();
+ test_executable_is_script();
+ test_status_field();
+ test_capeff();
+
return 0;
}
diff --git a/src/test/test-hashmap.c b/src/test/test-hashmap.c
index 2aead79bb1..56a9b58c24 100644
--- a/src/test/test-hashmap.c
+++ b/src/test/test-hashmap.c
@@ -467,10 +467,36 @@ static void test_hashmap_get(void) {
hashmap_free_free(m);
}
+static void test_hashmap_many(void) {
+ Hashmap *h;
+ unsigned i;
+
+#define N_ENTRIES 100000
+
+ assert_se(h = hashmap_new(NULL, NULL));
+
+ for (i = 1; i < N_ENTRIES*3; i+=3) {
+ assert_se(hashmap_put(h, UINT_TO_PTR(i), UINT_TO_PTR(i)) >= 0);
+ assert_se(PTR_TO_UINT(hashmap_get(h, UINT_TO_PTR(i))) == i);
+ }
+
+ for (i = 1; i < N_ENTRIES*3; i++)
+ assert_se(hashmap_contains(h, UINT_TO_PTR(i)) == (i % 3 == 1));
+
+ log_info("%u <= %u * 0.75 = %g", hashmap_size(h), hashmap_buckets(h), hashmap_buckets(h) * 0.75);
+
+ assert_se(hashmap_size(h) <= hashmap_buckets(h) * 0.75);
+ assert_se(hashmap_size(h) == N_ENTRIES);
+
+ hashmap_free(h);
+}
+
static void test_uint64_compare_func(void) {
- assert_se(uint64_compare_func("a", "a") == 0);
- assert_se(uint64_compare_func("a", "b") == -1);
- assert_se(uint64_compare_func("b", "a") == 1);
+ const uint64_t a = 0x100, b = 0x101;
+
+ assert_se(uint64_compare_func(&a, &a) == 0);
+ assert_se(uint64_compare_func(&a, &b) == -1);
+ assert_se(uint64_compare_func(&b, &a) == 1);
}
static void test_trivial_compare_func(void) {
@@ -484,8 +510,7 @@ static void test_string_compare_func(void) {
assert_se(string_compare_func("fred", "fred") == 0);
}
-int main(int argc, const char *argv[])
-{
+int main(int argc, const char *argv[]) {
test_hashmap_copy();
test_hashmap_get_strv();
test_hashmap_move_one();
@@ -502,6 +527,7 @@ int main(int argc, const char *argv[])
test_hashmap_isempty();
test_hashmap_get();
test_hashmap_size();
+ test_hashmap_many();
test_uint64_compare_func();
test_trivial_compare_func();
test_string_compare_func();
diff --git a/src/test/test-helper.h b/src/test/test-helper.h
new file mode 100644
index 0000000000..92864edb54
--- /dev/null
+++ b/src/test/test-helper.h
@@ -0,0 +1,31 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#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/>.
+***/
+
+#include "sd-daemon.h"
+
+#define TEST_REQ_RUNNING_SYSTEMD(x) \
+ if (sd_booted() > 0) { \
+ x; \
+ } else { \
+ printf("systemd not booted skipping '%s'\n", #x); \
+ }
diff --git a/src/test/test-id128.c b/src/test/test-id128.c
index 2ed8e292e6..7b92758174 100644
--- a/src/test/test-id128.c
+++ b/src/test/test-id128.c
@@ -25,6 +25,7 @@
#include "util.h"
#include "macro.h"
+#include "sd-daemon.h"
#define ID128_WALDI SD_ID128_MAKE(01, 02, 03, 04, 05, 06, 07, 08, 09, 0a, 0b, 0c, 0d, 0e, 0f, 10)
#define STR_WALDI "0102030405060708090a0b0c0d0e0f10"
@@ -41,11 +42,13 @@ int main(int argc, char *argv[]) {
assert_se(sd_id128_from_string(t, &id2) == 0);
assert_se(sd_id128_equal(id, id2));
- assert_se(sd_id128_get_machine(&id) == 0);
- printf("machine: %s\n", sd_id128_to_string(id, t));
+ if (sd_booted() > 0) {
+ assert_se(sd_id128_get_machine(&id) == 0);
+ printf("machine: %s\n", sd_id128_to_string(id, t));
- assert_se(sd_id128_get_boot(&id) == 0);
- printf("boot: %s\n", sd_id128_to_string(id, t));
+ assert_se(sd_id128_get_boot(&id) == 0);
+ printf("boot: %s\n", sd_id128_to_string(id, t));
+ }
printf("waldi: %s\n", sd_id128_to_string(ID128_WALDI, t));
assert_se(streq(t, STR_WALDI));
diff --git a/src/test/test-libudev.c b/src/test/test-libudev.c
index caa3b4d14c..716767ba5f 100644
--- a/src/test/test-libudev.c
+++ b/src/test/test-libudev.c
@@ -430,7 +430,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem)
}
static int test_hwdb(struct udev *udev, const char *modalias) {
- struct udev_hwdb * hwdb;
+ struct udev_hwdb *hwdb;
struct udev_list_entry *entry;
hwdb = udev_hwdb_new(udev);
diff --git a/src/test/test-list.c b/src/test/test-list.c
new file mode 100644
index 0000000000..2710504765
--- /dev/null
+++ b/src/test/test-list.c
@@ -0,0 +1,109 @@
+/***
+ 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/>.
+***/
+
+#include "list.h"
+#include "util.h"
+
+int main(int argc, const char *argv[]) {
+ size_t i;
+ typedef struct list_item {
+ LIST_FIELDS(struct list_item, item);
+ } list_item;
+ LIST_HEAD(list_item, head);
+ list_item items[4];
+ list_item *cursor;
+
+ LIST_HEAD_INIT(list_item, head);
+ assert_se(head == NULL);
+
+ for (i = 0; i < ELEMENTSOF(items); i++) {
+ LIST_INIT(list_item, item, &items[i]);
+ assert_se(LIST_JUST_US(item, &items[i]));
+ LIST_PREPEND(list_item, item, head, &items[i]);
+ }
+
+ assert_se(!LIST_JUST_US(item, head));
+
+ assert_se(items[0].item_next == NULL);
+ assert_se(items[1].item_next == &items[0]);
+ assert_se(items[2].item_next == &items[1]);
+ assert_se(items[3].item_next == &items[2]);
+
+ assert_se(items[0].item_prev == &items[1]);
+ assert_se(items[1].item_prev == &items[2]);
+ assert_se(items[2].item_prev == &items[3]);
+ assert_se(items[3].item_prev == NULL);
+
+ LIST_FIND_HEAD(list_item, item, &items[0], cursor);
+ assert_se(cursor == &items[3]);
+
+ LIST_FIND_TAIL(list_item, item, &items[3], cursor);
+ assert_se(cursor == &items[0]);
+
+ LIST_REMOVE(list_item, item, head, &items[1]);
+ assert_se(LIST_JUST_US(item, &items[1]));
+
+ assert_se(items[0].item_next == NULL);
+ assert_se(items[2].item_next == &items[0]);
+ assert_se(items[3].item_next == &items[2]);
+
+ assert_se(items[0].item_prev == &items[2]);
+ assert_se(items[2].item_prev == &items[3]);
+ assert_se(items[3].item_prev == NULL);
+
+ LIST_INSERT_AFTER(list_item, item, head, &items[3], &items[1]);
+ assert_se(items[0].item_next == NULL);
+ assert_se(items[2].item_next == &items[0]);
+ assert_se(items[1].item_next == &items[2]);
+ assert_se(items[3].item_next == &items[1]);
+
+ assert_se(items[0].item_prev == &items[2]);
+ assert_se(items[2].item_prev == &items[1]);
+ assert_se(items[1].item_prev == &items[3]);
+ assert_se(items[3].item_prev == NULL);
+
+ LIST_REMOVE(list_item, item, head, &items[0]);
+ assert_se(LIST_JUST_US(item, &items[0]));
+
+ assert_se(items[2].item_next == NULL);
+ assert_se(items[1].item_next == &items[2]);
+ assert_se(items[3].item_next == &items[1]);
+
+ assert_se(items[2].item_prev == &items[1]);
+ assert_se(items[1].item_prev == &items[3]);
+ assert_se(items[3].item_prev == NULL);
+
+ LIST_REMOVE(list_item, item, head, &items[1]);
+ assert_se(LIST_JUST_US(item, &items[1]));
+
+ assert_se(items[2].item_next == NULL);
+ assert_se(items[3].item_next == &items[2]);
+
+ assert_se(items[2].item_prev == &items[3]);
+ assert_se(items[3].item_prev == NULL);
+
+ LIST_REMOVE(list_item, item, head, &items[2]);
+ assert_se(LIST_JUST_US(item, &items[2]));
+ assert_se(LIST_JUST_US(item, head));
+
+ LIST_REMOVE(list_item, item, head, &items[3]);
+ assert_se(LIST_JUST_US(item, &items[3]));
+
+ return 0;
+}
diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
index 127e17803f..ed3b315a61 100644
--- a/src/test/test-path-util.c
+++ b/src/test/test-path-util.c
@@ -56,7 +56,7 @@ static void test_path(void) {
assert_se(streq(path_get_file_name("file.../"), ""));
#define test_parent(x, y) { \
- char *z; \
+ char _cleanup_free_ *z = NULL; \
int r = path_get_parent(x, &z); \
printf("expected: %s\n", y ? y : "error"); \
printf("actual: %s\n", r<0 ? "error" : z); \
@@ -83,7 +83,84 @@ static void test_path(void) {
}
}
+static void test_find_binary(void) {
+ char *p;
+
+ assert(find_binary("/bin/sh", &p) == 0);
+ puts(p);
+ assert(streq(p, "/bin/sh"));
+ free(p);
+
+ assert(find_binary("./test-path-util", &p) == 0);
+ puts(p);
+ assert(endswith(p, "/test-path-util"));
+ assert(path_is_absolute(p));
+ free(p);
+
+ assert(find_binary("sh", &p) == 0);
+ puts(p);
+ assert(endswith(p, "/sh"));
+ assert(path_is_absolute(p));
+ free(p);
+
+ assert(find_binary("xxxx-xxxx", &p) == -ENOENT);
+}
+
+static void test_prefixes(void) {
+ static const char* values[] = { "/a/b/c/d", "/a/b/c", "/a/b", "/a", "", NULL};
+ unsigned i;
+ char s[PATH_MAX];
+ bool b;
+
+ i = 0;
+ PATH_FOREACH_PREFIX_MORE(s, "/a/b/c/d") {
+ log_error("---%s---", s);
+ assert_se(streq(s, values[i++]));
+ }
+ assert_se(values[i] == NULL);
+
+ i = 1;
+ PATH_FOREACH_PREFIX(s, "/a/b/c/d") {
+ log_error("---%s---", s);
+ assert_se(streq(s, values[i++]));
+ }
+ assert_se(values[i] == NULL);
+
+ i = 0;
+ PATH_FOREACH_PREFIX_MORE(s, "////a////b////c///d///////")
+ assert_se(streq(s, values[i++]));
+ assert_se(values[i] == NULL);
+
+ i = 1;
+ PATH_FOREACH_PREFIX(s, "////a////b////c///d///////")
+ assert_se(streq(s, values[i++]));
+ assert_se(values[i] == NULL);
+
+ PATH_FOREACH_PREFIX(s, "////")
+ assert_not_reached("Wut?");
+
+ b = false;
+ PATH_FOREACH_PREFIX_MORE(s, "////") {
+ assert_se(!b);
+ assert_se(streq(s, ""));
+ b = true;
+ }
+ assert_se(b);
+
+ PATH_FOREACH_PREFIX(s, "")
+ assert_not_reached("wut?");
+
+ b = false;
+ PATH_FOREACH_PREFIX_MORE(s, "") {
+ assert(!b);
+ assert(streq(s, ""));
+ b = true;
+ }
+}
+
int main(void) {
test_path();
+ test_find_binary();
+ test_prefixes();
return 0;
}
diff --git a/src/test/test-sched-prio.c b/src/test/test-sched-prio.c
index ba0aacf79d..1bbe867317 100644
--- a/src/test/test-sched-prio.c
+++ b/src/test/test-sched-prio.c
@@ -34,8 +34,8 @@ int main(int argc, char *argv[]) {
/* prepare the test */
assert_se(set_unit_path(TEST_DIR) >= 0);
- r = manager_new(SYSTEMD_USER, &m);
- if (r == -EPERM) {
+ r = manager_new(SYSTEMD_USER, false, &m);
+ if (r == -EPERM || r == -EACCES) {
puts("manager_new: Permission denied. Skipping test.");
return EXIT_TEST_SKIP;
}
@@ -88,5 +88,7 @@ int main(int argc, char *argv[]) {
assert_se(ser->exec_context.cpu_sched_policy == SCHED_RR);
assert_se(ser->exec_context.cpu_sched_priority == 99);
+ manager_free(m);
+
return EXIT_SUCCESS;
}
diff --git a/src/test/test-sleep.c b/src/test/test-sleep.c
index c3cb9c531d..a1020ad14c 100644
--- a/src/test/test-sleep.c
+++ b/src/test/test-sleep.c
@@ -29,7 +29,7 @@
#include "sleep-config.h"
#include "strv.h"
-int main(int argc, char* argv[]) {
+static void test_sleep(void) {
_cleanup_strv_free_ char
**standby = strv_new("standby", NULL),
**mem = strv_new("mem", NULL),
@@ -40,18 +40,28 @@ int main(int argc, char* argv[]) {
**shutdown = strv_new("shutdown", NULL),
**freez = strv_new("freeze", NULL);
- log_info("Can Standby: %s", yes_no(can_sleep_state(standby) > 0));
- log_info("Can Suspend: %s", yes_no(can_sleep_state(mem) > 0));
- log_info("Can Hibernate: %s", yes_no(can_sleep_state(disk) > 0));
- log_info("Can Hibernate+Suspend (Hybrid-Sleep): %s", yes_no(can_sleep_disk(suspend) > 0));
- log_info("Can Hibernate+Reboot: %s", yes_no(can_sleep_disk(reboot) > 0));
- log_info("Can Hibernate+Platform: %s", yes_no(can_sleep_disk(platform) > 0));
- log_info("Can Hibernate+Shutdown: %s", yes_no(can_sleep_disk(shutdown) > 0));
- log_info("Can Freeze: %s", yes_no(can_sleep_disk(freez) > 0));
+ log_info("Standby configured: %s", yes_no(can_sleep_state(standby) > 0));
+ log_info("Suspend configured: %s", yes_no(can_sleep_state(mem) > 0));
+ log_info("Hibernate configured: %s", yes_no(can_sleep_state(disk) > 0));
+ log_info("Hibernate+Suspend (Hybrid-Sleep) configured: %s", yes_no(can_sleep_disk(suspend) > 0));
+ log_info("Hibernate+Reboot configured: %s", yes_no(can_sleep_disk(reboot) > 0));
+ log_info("Hibernate+Platform configured: %s", yes_no(can_sleep_disk(platform) > 0));
+ log_info("Hibernate+Shutdown configured: %s", yes_no(can_sleep_disk(shutdown) > 0));
+ log_info("Freeze configured: %s", yes_no(can_sleep_state(freez) > 0));
log_info("Suspend configured and possible: %s", yes_no(can_sleep("suspend") > 0));
log_info("Hibernation configured and possible: %s", yes_no(can_sleep("hibernate") > 0));
log_info("Hybrid-sleep configured and possible: %s", yes_no(can_sleep("hybrid-sleep") > 0));
+}
+
+int main(int argc, char* argv[]) {
+ log_parse_environment();
+ log_open();
+
+ if (getuid() != 0)
+ log_warning("This program is unlikely to work for unpriviledged users");
+
+ test_sleep();
return 0;
}
diff --git a/src/test/test-strv.c b/src/test/test-strv.c
index 074e1bb3d4..c3d536d057 100644
--- a/src/test/test-strv.c
+++ b/src/test/test-strv.c
@@ -27,65 +27,95 @@
#include "strv.h"
static void test_specifier_printf(void) {
- _cleanup_free_ char *w = NULL;
-
- const Specifier table[] = {
+ static const Specifier table[] = {
{ 'a', specifier_string, (char*) "AAAA" },
{ 'b', specifier_string, (char*) "BBBB" },
- { 0, NULL, NULL }
+ { 'm', specifier_machine_id, NULL },
+ { 'B', specifier_boot_id, NULL },
+ { 'H', specifier_host_name, NULL },
+ { 'v', specifier_kernel_release, NULL },
+ {}
};
- w = specifier_printf("xxx a=%a b=%b yyy", table, NULL);
- puts(w);
+ _cleanup_free_ char *w = NULL;
+ int r;
+ r = specifier_printf("xxx a=%a b=%b yyy", table, NULL, &w);
+ assert_se(r >= 0);
assert_se(w);
+
+ puts(w);
assert_se(streq(w, "xxx a=AAAA b=BBBB yyy"));
+
+ free(w);
+ r = specifier_printf("machine=%m, boot=%B, host=%H, version=%v", table, NULL, &w);
+ assert_se(r >= 0);
+ assert_se(w);
+ puts(w);
}
-static void test_strv_find(void) {
- const char * const input_table[] = {
- "one",
- "two",
- "three",
- NULL
- };
+static const char* const input_table_multiple[] = {
+ "one",
+ "two",
+ "three",
+ NULL,
+};
+
+static const char* const input_table_one[] = {
+ "one",
+ NULL,
+};
+
+static const char* const input_table_none[] = {
+ NULL,
+};
+
+static const char* const input_table_quotes[] = {
+ "\"",
+ "'",
+ "\"\"",
+ "\\",
+ "\\\\",
+ NULL,
+};
+#define QUOTES_STRING \
+ "\"\\\"\" " \
+ "\"\\\'\" " \
+ "\"\\\"\\\"\" " \
+ "\"\\\\\" " \
+ "\"\\\\\\\\\""
+
+static const char * const input_table_spaces[] = {
+ " ",
+ "' '",
+ "\" ",
+ " \"",
+ " \\\\ ",
+ NULL,
+};
+#define SPACES_STRING \
+ "\" \" " \
+ "\"\\' \\'\" " \
+ "\"\\\" \" " \
+ "\" \\\"\" " \
+ "\" \\\\\\\\ \""
- assert_se(strv_find((char **)input_table, "three"));
- assert_se(!strv_find((char **)input_table, "four"));
+static void test_strv_find(void) {
+ assert_se(strv_find((char **)input_table_multiple, "three"));
+ assert_se(!strv_find((char **)input_table_multiple, "four"));
}
static void test_strv_find_prefix(void) {
- const char * const input_table[] = {
- "one",
- "two",
- "three",
- NULL
- };
-
- assert_se(strv_find_prefix((char **)input_table, "o"));
- assert_se(strv_find_prefix((char **)input_table, "one"));
- assert_se(strv_find_prefix((char **)input_table, ""));
- assert_se(!strv_find_prefix((char **)input_table, "xxx"));
- assert_se(!strv_find_prefix((char **)input_table, "onee"));
+ assert_se(strv_find_prefix((char **)input_table_multiple, "o"));
+ assert_se(strv_find_prefix((char **)input_table_multiple, "one"));
+ assert_se(strv_find_prefix((char **)input_table_multiple, ""));
+ assert_se(!strv_find_prefix((char **)input_table_multiple, "xxx"));
+ assert_se(!strv_find_prefix((char **)input_table_multiple, "onee"));
}
static void test_strv_join(void) {
_cleanup_free_ char *p = NULL, *q = NULL, *r = NULL, *s = NULL, *t = NULL;
- const char * const input_table_multiple[] = {
- "one",
- "two",
- "three",
- NULL
- };
- const char * const input_table_one[] = {
- "one",
- NULL
- };
- const char * const input_table_none[] = {
- NULL
- };
-
p = strv_join((char **)input_table_multiple, ", ");
assert_se(p);
assert_se(streq(p, "one, two, three"));
@@ -107,6 +137,25 @@ static void test_strv_join(void) {
assert_se(streq(t, ""));
}
+static void test_strv_quote_unquote(const char* const *split, const char *quoted) {
+ _cleanup_free_ char *p;
+ _cleanup_strv_free_ char **s;
+ char **t;
+
+ p = strv_join_quoted((char **)split);
+ printf("-%s- --- -%s-\n", p, quoted); /* fprintf deals with NULL, puts does not */
+ assert_se(p);
+ assert_se(streq(p, quoted));
+
+ s = strv_split_quoted(quoted);
+ assert_se(s);
+ STRV_FOREACH(t, s) {
+ assert_se(*t);
+ assert_se(streq(*t, *split));
+ split++;
+ }
+}
+
static void test_strv_split_nulstr(void) {
_cleanup_strv_free_ char **l = NULL;
const char nulstr[] = "str0\0str1\0str2\0str3\0";
@@ -253,6 +302,13 @@ int main(int argc, char *argv[]) {
test_strv_find();
test_strv_find_prefix();
test_strv_join();
+
+ test_strv_quote_unquote(input_table_multiple, "\"one\" \"two\" \"three\"");
+ test_strv_quote_unquote(input_table_one, "\"one\"");
+ test_strv_quote_unquote(input_table_none, "");
+ test_strv_quote_unquote(input_table_quotes, QUOTES_STRING);
+ test_strv_quote_unquote(input_table_spaces, SPACES_STRING);
+
test_strv_split_nulstr();
test_strv_parse_nulstr();
test_strv_overlap();
diff --git a/src/test/test-tables.c b/src/test/test-tables.c
new file mode 100644
index 0000000000..3b7800cf37
--- /dev/null
+++ b/src/test/test-tables.c
@@ -0,0 +1,105 @@
+/***
+ 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 "automount.h"
+#include "cgroup.h"
+#include "condition.h"
+#include "device.h"
+#include "execute.h"
+#include "exit-status.h"
+#include "install.h"
+#include "job.h"
+#include "kill.h"
+#include "log.h"
+#include "logs-show.h"
+#include "mount.h"
+#include "path-lookup.h"
+#include "path.h"
+#include "scope.h"
+#include "service.h"
+#include "slice.h"
+#include "snapshot.h"
+#include "socket-util.h"
+#include "socket.h"
+#include "swap.h"
+#include "target.h"
+#include "timer.h"
+#include "unit-name.h"
+#include "unit.h"
+#include "util.h"
+#include "syscall-list.h"
+
+#include "test-tables.h"
+
+int main(int argc, char **argv) {
+ test_table(automount_result, AUTOMOUNT_RESULT);
+ test_table(automount_state, AUTOMOUNT_STATE);
+ test_table(cgroup_device_policy, CGROUP_DEVICE_POLICY);
+ test_table(condition_type, CONDITION_TYPE);
+ test_table(device_state, DEVICE_STATE);
+ test_table(exec_input, EXEC_INPUT);
+ test_table(exec_output, EXEC_OUTPUT);
+ test_table(job_mode, JOB_MODE);
+ test_table(job_result, JOB_RESULT);
+ test_table(job_state, JOB_STATE);
+ test_table(job_type, JOB_TYPE);
+ test_table(kill_mode, KILL_MODE);
+ test_table(kill_who, KILL_WHO);
+ test_table(log_target, LOG_TARGET);
+ test_table(mount_exec_command, MOUNT_EXEC_COMMAND);
+ test_table(mount_result, MOUNT_RESULT);
+ test_table(mount_state, MOUNT_STATE);
+ test_table(notify_access, NOTIFY_ACCESS);
+ test_table(output_mode, OUTPUT_MODE);
+ test_table(path_result, PATH_RESULT);
+ test_table(path_state, PATH_STATE);
+ test_table(path_type, PATH_TYPE);
+ test_table(scope_result, SCOPE_RESULT);
+ test_table(scope_state, SCOPE_STATE);
+ test_table(service_exec_command, SERVICE_EXEC_COMMAND);
+ test_table(service_restart, SERVICE_RESTART);
+ test_table(service_result, SERVICE_RESULT);
+ test_table(service_state, SERVICE_STATE);
+ test_table(service_type, SERVICE_TYPE);
+ test_table(slice_state, SLICE_STATE);
+ test_table(snapshot_state, SNAPSHOT_STATE);
+ test_table(socket_address_bind_ipv6_only, SOCKET_ADDRESS_BIND_IPV6_ONLY);
+ test_table(socket_exec_command, SOCKET_EXEC_COMMAND);
+ test_table(socket_result, SOCKET_RESULT);
+ test_table(socket_state, SOCKET_STATE);
+ test_table(start_limit_action, SERVICE_START_LIMIT);
+ test_table(swap_exec_command, SWAP_EXEC_COMMAND);
+ test_table(swap_result, SWAP_RESULT);
+ test_table(swap_state, SWAP_STATE);
+ test_table(systemd_running_as, SYSTEMD_RUNNING_AS);
+ test_table(target_state, TARGET_STATE);
+ test_table(timer_base, TIMER_BASE);
+ test_table(timer_result, TIMER_RESULT);
+ test_table(timer_state, TIMER_STATE);
+ test_table(unit_active_state, UNIT_ACTIVE_STATE);
+ test_table(unit_dependency, UNIT_DEPENDENCY);
+ test_table(unit_file_change_type, UNIT_FILE_CHANGE_TYPE);
+ test_table(unit_file_state, UNIT_FILE_STATE);
+ test_table(unit_load_state, UNIT_LOAD_STATE);
+ test_table(unit_type, UNIT_TYPE);
+
+ _test_table("syscall", syscall_to_name, syscall_from_name, syscall_max(), true);
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
index a7fe77af24..0413ae2117 100644
--- a/src/test/test-unit-file.c
+++ b/src/test/test-unit-file.c
@@ -35,8 +35,9 @@
#include "load-fragment.h"
#include "strv.h"
#include "fileio.h"
+#include "test-helper.h"
-static void test_unit_file_get_set(void) {
+static int test_unit_file_get_set(void) {
int r;
Hashmap *h;
Iterator i;
@@ -46,13 +47,17 @@ static void test_unit_file_get_set(void) {
assert(h);
r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h);
- log_info("unit_file_get_list: %s", strerror(-r));
- assert(r >= 0);
+ log_full(r == 0 ? LOG_INFO : LOG_ERR,
+ "unit_file_get_list: %s", strerror(-r));
+ if (r < 0)
+ return EXIT_FAILURE;
HASHMAP_FOREACH(p, h, i)
printf("%s = %s\n", p->path, unit_file_state_to_string(p->state));
unit_file_list_free(h);
+
+ return 0;
}
static void check_execcommand(ExecCommand *c,
@@ -297,17 +302,18 @@ static void test_install_printf(void) {
_cleanup_free_ char *mid, *bid, *host;
- assert_se((mid = specifier_machine_id('m', NULL, NULL)));
- assert_se((bid = specifier_boot_id('b', NULL, NULL)));
+ assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
+ assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
assert_se((host = gethostname_malloc()));
#define expect(src, pattern, result) \
do { \
- _cleanup_free_ char *t = install_full_printf(&src, pattern); \
+ _cleanup_free_ char *t = NULL; \
_cleanup_free_ char \
*d1 = strdup(i.name), \
*d2 = strdup(i.path), \
*d3 = strdup(i.user); \
+ assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
memzero(i.name, strlen(i.name)); \
memzero(i.path, strlen(i.path)); \
memzero(i.user, strlen(i.user)); \
@@ -351,17 +357,18 @@ static void test_install_printf(void) {
#pragma GCC diagnostic pop
int main(int argc, char *argv[]) {
+ int r;
log_parse_environment();
log_open();
- test_unit_file_get_set();
+ r = test_unit_file_get_set();
test_config_parse_exec();
test_load_env_file_1();
test_load_env_file_2();
test_load_env_file_3();
test_load_env_file_4();
- test_install_printf();
+ TEST_REQ_RUNNING_SYSTEMD(test_install_printf());
- return 0;
+ return r;
}
diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c
index 86cb2b8da6..67ccdd4228 100644
--- a/src/test/test-unit-name.c
+++ b/src/test/test-unit-name.c
@@ -34,6 +34,7 @@
#include "specifier.h"
#include "util.h"
#include "macro.h"
+#include "test-helper.h"
static void test_replacements(void) {
#define expect(pattern, repl, expected) \
@@ -116,15 +117,15 @@ static int test_unit_printf(void) {
_cleanup_free_ char *mid, *bid, *host, *root_uid;
struct passwd *root;
- assert_se((mid = specifier_machine_id('m', NULL, NULL)));
- assert_se((bid = specifier_boot_id('b', NULL, NULL)));
+ assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
+ assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
assert_se((host = gethostname_malloc()));
assert_se((root = getpwnam("root")));
assert_se(asprintf(&root_uid, "%d", (int) root->pw_uid) > 0);
- r = manager_new(SYSTEMD_USER, &m);
- if (r == -EPERM) {
+ r = manager_new(SYSTEMD_USER, false, &m);
+ if (r == -EPERM || r == -EACCES) {
puts("manager_new: Permission denied. Skipping test.");
return EXIT_TEST_SKIP;
}
@@ -133,8 +134,8 @@ static int test_unit_printf(void) {
#define expect(unit, pattern, expected) \
{ \
char *e; \
- _cleanup_free_ char *t = \
- unit_full_printf(unit, pattern); \
+ _cleanup_free_ char *t; \
+ assert_se(unit_full_printf(unit, pattern, &t) >= 0); \
printf("result: %s\nexpect: %s\n", t, expected); \
if ((e = endswith(expected, "*"))) \
assert(strncmp(t, e, e-expected)); \
@@ -190,10 +191,14 @@ static int test_unit_printf(void) {
expect(u2, "%H", host);
expect(u2, "%t", "/run/user/*");
+ manager_free(m);
+
return 0;
}
int main(int argc, char* argv[]) {
+ int rc = 0;
test_replacements();
- return test_unit_printf();
+ TEST_REQ_RUNNING_SYSTEMD(rc = test_unit_printf());
+ return rc;
}
diff --git a/src/test/test-utf8.c b/src/test/test-utf8.c
new file mode 100644
index 0000000000..7bd0db173a
--- /dev/null
+++ b/src/test/test-utf8.c
@@ -0,0 +1,76 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ 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/>.
+***/
+
+#include "utf8.h"
+#include "util.h"
+
+static void test_utf8_is_printable(void) {
+ assert_se(utf8_is_printable("ascii is valid\tunicode", 22));
+ assert_se(utf8_is_printable("\342\204\242", 3));
+ assert_se(!utf8_is_printable("\341\204", 2));
+}
+
+static void test_utf8_is_valid(void) {
+ assert_se(utf8_is_valid("ascii is valid unicode"));
+ assert_se(utf8_is_valid("\342\204\242"));
+ assert_se(!utf8_is_valid("\341\204"));
+}
+
+static void test_ascii_is_valid(void) {
+ 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_filter(void) {
+ char *f;
+
+ f = ascii_filter("alsdjf\t\vbarr\nba z");
+ assert_se(streq(f, "alsdjf\t\vbarr\nba z"));
+ free(f);
+
+ f = ascii_filter("\342\204\242");
+ assert_se(streq(f, ""));
+ free(f);
+
+ f = ascii_filter("foo\341\204bar");
+ assert_se(streq(f, "foobar"));
+ free(f);
+}
+
+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);
+ assert_se(utf8_encoded_valid_unichar("a") == 1);
+ assert_se(utf8_encoded_valid_unichar("\341\204") < 0);
+ assert_se(utf8_encoded_valid_unichar("\341\204\341\204") < 0);
+
+}
+
+int main(int argc, char *argv[]) {
+ test_utf8_is_valid();
+ test_utf8_is_printable();
+ test_ascii_is_valid();
+ test_ascii_filter();
+ test_utf8_encoded_valid_unichar();
+
+ return 0;
+}
diff --git a/src/test/test-util.c b/src/test/test-util.c
index 4c3a8a6b88..c5762ede4b 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -27,6 +27,7 @@
#include <errno.h>
#include "util.h"
+#include "strv.h"
static void test_streq_ptr(void) {
assert_se(streq_ptr(NULL, NULL));
@@ -192,41 +193,40 @@ static void test_safe_atod(void) {
}
static void test_strappend(void) {
- _cleanup_free_ char *t1, *t2, *t3, *t4;
+ _cleanup_free_ char *t1, *t2, *t3, *t4;
- t1 = strappend(NULL, NULL);
- assert_se(streq(t1, ""));
+ t1 = strappend(NULL, NULL);
+ assert_se(streq(t1, ""));
- t2 = strappend(NULL, "suf");
- assert_se(streq(t2, "suf"));
+ t2 = strappend(NULL, "suf");
+ assert_se(streq(t2, "suf"));
- t3 = strappend("pre", NULL);
- assert_se(streq(t3, "pre"));
+ t3 = strappend("pre", NULL);
+ assert_se(streq(t3, "pre"));
- t4 = strappend("pre", "suf");
- assert_se(streq(t4, "presuf"));
+ t4 = strappend("pre", "suf");
+ assert_se(streq(t4, "presuf"));
}
static void test_strstrip(void) {
- char *r;
- char input[] = " hello, waldo. ";
-
- r = strstrip(input);
- assert_se(streq(r, "hello, waldo."));
+ char *r;
+ char input[] = " hello, waldo. ";
+ r = strstrip(input);
+ assert_se(streq(r, "hello, waldo."));
}
static void test_delete_chars(void) {
- char *r;
- char input[] = " hello, waldo. abc";
+ char *r;
+ char input[] = " hello, waldo. abc";
- r = delete_chars(input, WHITESPACE);
- assert_se(streq(r, "hello,waldo.abc"));
+ r = delete_chars(input, WHITESPACE);
+ assert_se(streq(r, "hello,waldo.abc"));
}
static void test_in_charset(void) {
- assert_se(in_charset("dddaaabbbcccc", "abcd"));
- assert_se(!in_charset("dddaaabbbcccc", "abc f"));
+ assert_se(in_charset("dddaaabbbcccc", "abcd"));
+ assert_se(!in_charset("dddaaabbbcccc", "abc f"));
}
static void test_hexchar(void) {
@@ -260,6 +260,18 @@ static void test_undecchar(void) {
assert_se(undecchar('9') == 9);
}
+static void test_cescape(void) {
+ _cleanup_free_ char *escaped;
+ escaped = cescape("abc\\\"\b\f\n\r\t\v\003\177\234\313");
+ assert_se(streq(escaped, "abc\\\\\\\"\\b\\f\\n\\r\\t\\v\\003\\177\\234\\313"));
+}
+
+static void test_cunescape(void) {
+ _cleanup_free_ char *unescaped;
+ unescaped = cunescape("abc\\\\\\\"\\b\\f\\n\\r\\t\\v\\003\\177\\234\\313");
+ assert_se(streq(unescaped, "abc\\\"\b\f\n\r\t\v\003\177\234\313"));
+}
+
static void test_foreach_word(void) {
char *w, *state;
size_t l;
@@ -386,6 +398,7 @@ static void test_u64log2(void) {
}
static void test_get_process_comm(void) {
+ struct stat st;
_cleanup_free_ char *a = NULL, *c = NULL, *d = NULL, *f = NULL, *i = NULL;
unsigned long long b;
pid_t e;
@@ -394,8 +407,12 @@ static void test_get_process_comm(void) {
dev_t h;
int r;
- assert_se(get_process_comm(1, &a) >= 0);
- log_info("pid1 comm: '%s'", a);
+ if (stat("/proc/1/comm", &st) == 0) {
+ assert_se(get_process_comm(1, &a) >= 0);
+ log_info("pid1 comm: '%s'", a);
+ } else {
+ log_warning("/proc/1/comm does not exist.");
+ }
assert_se(get_starttime_of_pid(1, &b) >= 0);
log_info("pid1 starttime: '%llu'", b);
@@ -439,6 +456,141 @@ static void test_protect_errno(void) {
assert(errno == 12);
}
+static void test_parse_bytes(void) {
+ off_t bytes;
+
+ assert_se(parse_bytes("111", &bytes) == 0);
+ assert_se(bytes == 111);
+
+ assert_se(parse_bytes(" 112 B", &bytes) == 0);
+ assert_se(bytes == 112);
+
+ assert_se(parse_bytes("3 K", &bytes) == 0);
+ assert_se(bytes == 3*1024);
+
+ assert_se(parse_bytes(" 4 M 11K", &bytes) == 0);
+ assert_se(bytes == 4*1024*1024 + 11 * 1024);
+
+ assert_se(parse_bytes("3B3G", &bytes) == 0);
+ assert_se(bytes == 3ULL*1024*1024*1024 + 3);
+
+ assert_se(parse_bytes("3B3G4T", &bytes) == 0);
+ assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3);
+
+ assert_se(parse_bytes("12P", &bytes) == 0);
+ assert_se(bytes == 12ULL * 1024*1024*1024*1024*1024);
+
+ assert_se(parse_bytes("3E 2P", &bytes) == 0);
+ assert_se(bytes == (3 * 1024 + 2ULL) * 1024*1024*1024*1024*1024);
+
+ assert_se(parse_bytes("12X", &bytes) == -EINVAL);
+
+ assert_se(parse_bytes("1024E", &bytes) == -ERANGE);
+ assert_se(parse_bytes("-1", &bytes) == -ERANGE);
+ assert_se(parse_bytes("-1024E", &bytes) == -ERANGE);
+
+ assert_se(parse_bytes("-1024P", &bytes) == -ERANGE);
+
+ assert_se(parse_bytes("-10B 20K", &bytes) == -ERANGE);
+}
+
+static void test_strextend(void) {
+ _cleanup_free_ char *str = strdup("0123");
+ strextend(&str, "456", "78", "9", NULL);
+ assert_se(streq(str, "0123456789"));
+}
+
+static void test_strrep(void) {
+ _cleanup_free_ char *one, *three, *zero;
+ one = strrep("waldo", 1);
+ three = strrep("waldo", 3);
+ zero = strrep("waldo", 0);
+
+ assert_se(streq(one, "waldo"));
+ assert_se(streq(three, "waldowaldowaldo"));
+ assert_se(streq(zero, ""));
+}
+
+static void test_parse_user_at_host(void) {
+ _cleanup_free_ char *both = strdup("waldo@waldoscomputer");
+ _cleanup_free_ char *onlyhost = strdup("mikescomputer");
+ char *user = NULL, *host = NULL;
+
+ parse_user_at_host(both, &user, &host);
+ assert_se(streq(user, "waldo"));
+ assert_se(streq(host, "waldoscomputer"));
+
+ user = host = NULL;
+ parse_user_at_host(onlyhost, &user, &host);
+ assert_se(user == NULL);
+ assert_se(streq(host, "mikescomputer"));
+}
+
+static void test_split_pair(void) {
+ _cleanup_free_ char *a = NULL, *b = NULL;
+
+ assert_se(split_pair("", "", &a, &b) == -EINVAL);
+ assert_se(split_pair("foo=bar", "", &a, &b) == -EINVAL);
+ assert_se(split_pair("", "=", &a, &b) == -EINVAL);
+ assert_se(split_pair("foo=bar", "=", &a, &b) >= 0);
+ assert_se(streq(a, "foo"));
+ assert_se(streq(b, "bar"));
+ free(a);
+ free(b);
+ assert_se(split_pair("==", "==", &a, &b) >= 0);
+ assert_se(streq(a, ""));
+ assert_se(streq(b, ""));
+ free(a);
+ free(b);
+
+ assert_se(split_pair("===", "==", &a, &b) >= 0);
+ assert_se(streq(a, ""));
+ assert_se(streq(b, "="));
+}
+
+static void test_fstab_node_to_udev_node(void) {
+ char *n;
+
+ n = fstab_node_to_udev_node("LABEL=applé/jack");
+ puts(n);
+ assert_se(streq(n, "/dev/disk/by-label/applé\\x2fjack"));
+ free(n);
+
+ n = fstab_node_to_udev_node("PARTLABEL=pinkié pie");
+ puts(n);
+ assert_se(streq(n, "/dev/disk/by-partlabel/pinkié\\x20pie"));
+ free(n);
+
+ n = fstab_node_to_udev_node("UUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
+ puts(n);
+ assert_se(streq(n, "/dev/disk/by-uuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
+ free(n);
+
+ n = fstab_node_to_udev_node("PARTUUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
+ puts(n);
+ assert_se(streq(n, "/dev/disk/by-partuuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
+ free(n);
+
+
+ n = fstab_node_to_udev_node("PONIES=awesome");
+ puts(n);
+ assert_se(streq(n, "PONIES=awesome"));
+ free(n);
+
+ n = fstab_node_to_udev_node("/dev/xda1");
+ puts(n);
+ assert_se(streq(n, "/dev/xda1"));
+ free(n);
+}
+
+static void test_get_files_in_directory(void) {
+ _cleanup_strv_free_ char **l = NULL, **t = NULL;
+
+ assert_se(get_files_in_directory("/tmp", &l) >= 0);
+ assert_se(get_files_in_directory(".", &l) >= 0);
+ assert_se(get_files_in_directory(".", NULL) >= 0);
+}
+
int main(int argc, char *argv[]) {
test_streq_ptr();
test_first_word();
@@ -458,6 +610,8 @@ int main(int argc, char *argv[]) {
test_unoctchar();
test_decchar();
test_undecchar();
+ test_cescape();
+ test_cunescape();
test_foreach_word();
test_foreach_word_quoted();
test_default_term_for_tty();
@@ -467,6 +621,13 @@ int main(int argc, char *argv[]) {
test_u64log2();
test_get_process_comm();
test_protect_errno();
+ test_parse_bytes();
+ test_strextend();
+ test_strrep();
+ test_parse_user_at_host();
+ test_split_pair();
+ test_fstab_node_to_udev_node();
+ test_get_files_in_directory();
return 0;
}
diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c
index 8d4e560b93..141180c393 100644
--- a/src/timedate/timedatectl.c
+++ b/src/timedate/timedatectl.c
@@ -44,7 +44,8 @@ static enum transport {
TRANSPORT_POLKIT
} arg_transport = TRANSPORT_NORMAL;
static bool arg_ask_password = true;
-static const char *arg_host = NULL;
+static char *arg_host = NULL;
+static char *arg_user = NULL;
static void pager_open_if_enabled(void) {
@@ -197,7 +198,7 @@ static void print_status_info(StatusInfo *i) {
if (i->local_rtc)
fputs("\n" ANSI_HIGHLIGHT_ON
- "Warning: The RTC is configured to maintain time in the local time zone. This\n"
+ "Warning: The RTC is configured to maintain time in the local timezone. This\n"
" mode is not fully supported and will create various problems with time\n"
" zone changes and daylight saving adjustments. If at all possible use\n"
" RTC in UTC, by calling 'timedatectl set-local-rtc 0'" ANSI_HIGHLIGHT_OFF ".\n", stdout);
@@ -304,7 +305,7 @@ static int show_status(DBusConnection *bus, char **args, unsigned n) {
static int set_time(DBusConnection *bus, char **args, unsigned n) {
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- dbus_bool_t relative = false, interactive = true;
+ dbus_bool_t relative = false, interactive = arg_ask_password;
usec_t t;
dbus_int64_t u;
int r;
@@ -338,7 +339,7 @@ static int set_time(DBusConnection *bus, char **args, unsigned n) {
static int set_timezone(DBusConnection *bus, char **args, unsigned n) {
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- dbus_bool_t interactive = true;
+ dbus_bool_t interactive = arg_ask_password;
assert(args);
assert(n == 2);
@@ -360,7 +361,7 @@ static int set_timezone(DBusConnection *bus, char **args, unsigned n) {
static int set_local_rtc(DBusConnection *bus, char **args, unsigned n) {
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- dbus_bool_t interactive = true, b, q;
+ dbus_bool_t interactive = arg_ask_password, b, q;
int r;
assert(args);
@@ -393,7 +394,7 @@ static int set_local_rtc(DBusConnection *bus, char **args, unsigned n) {
static int set_ntp(DBusConnection *bus, char **args, unsigned n) {
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
- dbus_bool_t interactive = true, b;
+ dbus_bool_t interactive = arg_ask_password, b;
int r;
assert(args);
@@ -501,6 +502,7 @@ static int help(void) {
" --adjust-system-clock\n"
" Adjust system clock when changing local RTC mode\n"
" --no-pager Do not pipe output into a pager\n"
+ " -P --privileged Acquire privileges before execution\n"
" --no-ask-password Do not prompt for password\n"
" -H --host=[USER@]HOST Operate on remote host\n\n"
"Commands:\n"
@@ -540,7 +542,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "+hH:P", options, NULL)) >= 0) {
+ while ((c = getopt_long(argc, argv, "hH:P", options, NULL)) >= 0) {
switch (c) {
@@ -559,7 +561,11 @@ static int parse_argv(int argc, char *argv[]) {
case 'H':
arg_transport = TRANSPORT_SSH;
- arg_host = optarg;
+ parse_user_at_host(optarg, &arg_user, &arg_host);
+ break;
+
+ case ARG_NO_ASK_PASSWORD:
+ arg_ask_password = false;
break;
case ARG_ADJUST_SYSTEM_CLOCK:
diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
index cdb6e5b16c..525c72e497 100644
--- a/src/timedate/timedated.c
+++ b/src/timedate/timedated.c
@@ -662,7 +662,7 @@ static DBusHandlerResult timedate_message_handler(
return bus_send_error_reply(connection, message, NULL, r);
}
- /* 2. Tell the kernel our time zone */
+ /* 2. Tell the kernel our timezone */
hwclock_set_timezone(NULL);
if (tz.local_rtc) {
@@ -719,7 +719,7 @@ static DBusHandlerResult timedate_message_handler(
return bus_send_error_reply(connection, message, NULL, r);
}
- /* 2. Tell the kernel our time zone */
+ /* 2. Tell the kernel our timezone */
hwclock_set_timezone(NULL);
/* 3. Synchronize clocks */
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index f4885ec942..8122d6af6a 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -51,6 +51,7 @@
#include "set.h"
#include "conf-files.h"
#include "capability.h"
+#include "specifier.h"
/* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
* them in the file system. This is intended to be used to create
@@ -68,6 +69,7 @@ typedef enum ItemType {
CREATE_SYMLINK = 'L',
CREATE_CHAR_DEVICE = 'c',
CREATE_BLOCK_DEVICE = 'b',
+ ADJUST_MODE = 'm',
/* These ones take globs */
IGNORE_PATH = 'x',
@@ -105,7 +107,8 @@ static bool arg_create = false;
static bool arg_clean = false;
static bool arg_remove = false;
-static const char *arg_prefix = NULL;
+static char **include_prefixes = NULL;
+static char **exclude_prefixes = NULL;
static const char conf_file_dirs[] =
"/etc/tmpfiles.d\0"
@@ -255,8 +258,8 @@ static int dir_cleanup(
dev_t rootdev,
bool mountpoint,
int maxdepth,
- bool keep_this_level)
-{
+ bool keep_this_level) {
+
struct dirent *dent;
struct timespec times[2];
bool deleted = false;
@@ -427,12 +430,16 @@ finish:
return r;
}
-static int item_set_perms(Item *i, const char *path) {
+static int item_set_perms_full(Item *i, const char *path, bool ignore_enoent) {
+ int r;
+
/* not using i->path directly because it may be a glob */
if (i->mode_set)
if (chmod(path, i->mode) < 0) {
- log_error("chmod(%s) failed: %m", path);
- return -errno;
+ if (errno != ENOENT || !ignore_enoent) {
+ log_error("chmod(%s) failed: %m", path);
+ return -errno;
+ }
}
if (i->uid_set || i->gid_set)
@@ -440,11 +447,18 @@ static int item_set_perms(Item *i, const char *path) {
i->uid_set ? i->uid : (uid_t) -1,
i->gid_set ? i->gid : (gid_t) -1) < 0) {
- log_error("chown(%s) failed: %m", path);
- return -errno;
+ if (errno != ENOENT || !ignore_enoent) {
+ log_error("chown(%s) failed: %m", path);
+ return -errno;
+ }
}
- return label_fix(path, false, false);
+ r = label_fix(path, false, false);
+ return r == -ENOENT && ignore_enoent ? 0 : r;
+}
+
+static int item_set_perms(Item *i, const char *path) {
+ return item_set_perms_full(i, path, false);
}
static int write_one_file(Item *i, const char *path) {
@@ -640,6 +654,7 @@ static int create_item(Item *i) {
if (r < 0)
return r;
break;
+
case WRITE_FILE:
r = glob_item(i, write_one_file);
if (r < 0)
@@ -647,6 +662,13 @@ static int create_item(Item *i) {
break;
+ case ADJUST_MODE:
+ r = item_set_perms_full(i, i->path, true);
+ if (r < 0)
+ return r;
+
+ break;
+
case TRUNCATE_DIRECTORY:
case CREATE_DIRECTORY:
@@ -783,7 +805,7 @@ static int create_item(Item *i) {
r = glob_item(i, item_set_perms);
if (r < 0)
- return 0;
+ return r;
break;
case RECURSIVE_RELABEL_PATH:
@@ -817,6 +839,7 @@ static int remove_item_instance(Item *i, const char *instance) {
case RELABEL_PATH:
case RECURSIVE_RELABEL_PATH:
case WRITE_FILE:
+ case ADJUST_MODE:
break;
case REMOVE_PATH:
@@ -862,6 +885,7 @@ static int remove_item(Item *i) {
case RELABEL_PATH:
case RECURSIVE_RELABEL_PATH:
case WRITE_FILE:
+ case ADJUST_MODE:
break;
case REMOVE_PATH:
@@ -971,6 +995,12 @@ static void item_free(Item *i) {
free(i);
}
+static inline void item_freep(Item **i) {
+ if (*i)
+ item_free(*i);
+}
+#define _cleanup_item_free_ _cleanup_(item_freep)
+
static bool item_equal(Item *a, Item *b) {
assert(a);
assert(b);
@@ -1012,11 +1042,38 @@ static bool item_equal(Item *a, Item *b) {
return true;
}
+static bool should_include_path(const char *path) {
+ char **prefix;
+
+ STRV_FOREACH(prefix, exclude_prefixes) {
+ if (path_startswith(path, *prefix))
+ return false;
+ }
+
+ STRV_FOREACH(prefix, include_prefixes) {
+ if (path_startswith(path, *prefix))
+ return true;
+ }
+
+ /* no matches, so we should include this path only if we
+ * have no whitelist at all */
+ return strv_length(include_prefixes) == 0;
+}
+
static int parse_line(const char *fname, unsigned line, const char *buffer) {
- _cleanup_free_ Item *i = NULL;
+
+ static const Specifier specifier_table[] = {
+ { 'm', specifier_machine_id, NULL },
+ { 'b', specifier_boot_id, NULL },
+ { 'H', specifier_host_name, NULL },
+ { 'v', specifier_kernel_release, NULL },
+ {}
+ };
+
+ _cleanup_item_free_ Item *i = NULL;
Item *existing;
_cleanup_free_ char
- *mode = NULL, *user = NULL, *group = NULL, *age = NULL;
+ *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
char type;
Hashmap *h;
int r, n = -1;
@@ -1025,14 +1082,10 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
assert(line >= 1);
assert(buffer);
- i = new0(Item, 1);
- if (!i)
- return log_oom();
-
r = sscanf(buffer,
"%c %ms %ms %ms %ms %ms %n",
&type,
- &i->path,
+ &path,
&mode,
&user,
&group,
@@ -1043,6 +1096,16 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
return -EIO;
}
+ i = new0(Item, 1);
+ if (!i)
+ return log_oom();
+
+ r = specifier_printf(path, specifier_table, NULL, &i->path);
+ if (r < 0) {
+ log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
+ return r;
+ }
+
if (n >= 0) {
n += strspn(buffer+n, WHITESPACE);
if (buffer[n] != 0 && (buffer[n] != '-' || buffer[n+1] != 0)) {
@@ -1065,6 +1128,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
case RECURSIVE_REMOVE_PATH:
case RELABEL_PATH:
case RECURSIVE_RELABEL_PATH:
+ case ADJUST_MODE:
break;
case CREATE_SYMLINK:
@@ -1113,7 +1177,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
path_kill_slashes(i->path);
- if (arg_prefix && !path_startswith(i->path, arg_prefix))
+ if (!should_include_path(i->path))
return 0;
if (user && !streq(user, "-")) {
@@ -1198,11 +1262,12 @@ static int help(void) {
printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
"Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
- " -h --help Show this help\n"
- " --create Create marked files/directories\n"
- " --clean Clean up marked directories\n"
- " --remove Remove marked files/directories\n"
- " --prefix=PATH Only apply rules that apply to paths with the specified prefix\n",
+ " -h --help Show this help\n"
+ " --create Create marked files/directories\n"
+ " --clean Clean up marked directories\n"
+ " --remove Remove marked files/directories\n"
+ " --prefix=PATH Only apply rules that apply to paths with the specified prefix\n"
+ " --exclude-prefix=PATH Ignore rules that apply to paths with the specified prefix\n",
program_invocation_short_name);
return 0;
@@ -1214,16 +1279,18 @@ static int parse_argv(int argc, char *argv[]) {
ARG_CREATE,
ARG_CLEAN,
ARG_REMOVE,
- ARG_PREFIX
+ ARG_PREFIX,
+ ARG_EXCLUDE_PREFIX,
};
static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "create", no_argument, NULL, ARG_CREATE },
- { "clean", no_argument, NULL, ARG_CLEAN },
- { "remove", no_argument, NULL, ARG_REMOVE },
- { "prefix", required_argument, NULL, ARG_PREFIX },
- { NULL, 0, NULL, 0 }
+ { "help", no_argument, NULL, 'h' },
+ { "create", no_argument, NULL, ARG_CREATE },
+ { "clean", no_argument, NULL, ARG_CLEAN },
+ { "remove", no_argument, NULL, ARG_REMOVE },
+ { "prefix", required_argument, NULL, ARG_PREFIX },
+ { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
+ { NULL, 0, NULL, 0 }
};
int c;
@@ -1252,7 +1319,13 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_PREFIX:
- arg_prefix = optarg;
+ if (strv_extend(&include_prefixes, optarg) < 0)
+ return log_oom();
+ break;
+
+ case ARG_EXCLUDE_PREFIX:
+ if (strv_extend(&exclude_prefixes, optarg) < 0)
+ return log_oom();
break;
case '?':
@@ -1273,11 +1346,12 @@ static int parse_argv(int argc, char *argv[]) {
}
static int read_config_file(const char *fn, bool ignore_enoent) {
- FILE *f;
- unsigned v = 0;
- int r;
+ _cleanup_fclose_ FILE *f = NULL;
+ char line[LINE_MAX];
Iterator iterator;
+ unsigned v = 0;
Item *i;
+ int r;
assert(fn);
@@ -1290,23 +1364,19 @@ static int read_config_file(const char *fn, bool ignore_enoent) {
return r;
}
- log_debug("apply: %s\n", fn);
- for (;;) {
- char line[LINE_MAX], *l;
+ FOREACH_LINE(line, f, break) {
+ char *l;
int k;
- if (!(fgets(line, sizeof(line), f)))
- break;
-
v++;
l = strstrip(line);
if (*l == '#' || *l == 0)
continue;
- if ((k = parse_line(fn, v, l)) < 0)
- if (r == 0)
- r = k;
+ k = parse_line(fn, v, l);
+ if (k < 0 && r == 0)
+ r = k;
}
/* we have to determine age parameter for each entry of type X */
@@ -1343,8 +1413,6 @@ static int read_config_file(const char *fn, bool ignore_enoent) {
r = -EIO;
}
- fclose(f);
-
return r;
}
@@ -1417,6 +1485,8 @@ finish:
hashmap_free(items);
hashmap_free(globs);
+ strv_free(include_prefixes);
+
set_free_free(unix_sockets);
label_finish();
diff --git a/src/udev/.gitignore b/src/udev/.gitignore
index 3e375a7726..a229430e36 100644
--- a/src/udev/.gitignore
+++ b/src/udev/.gitignore
@@ -1 +1,5 @@
/udev.pc
+/keyboard-keys-from-name.gperf
+/keyboard-keys-from-name.h
+/keyboard-keys-to-name.h
+/keyboard-keys.txt
diff --git a/src/udev/collect/collect.c b/src/udev/collect/collect.c
index f95ee23b75..1346f27f91 100644
--- a/src/udev/collect/collect.c
+++ b/src/udev/collect/collect.c
@@ -442,19 +442,19 @@ int main(int argc, char **argv)
if (debug)
fprintf(stderr, "ID %s: not in database\n", argv[i]);
- him = malloc(sizeof (struct _mate));
+ him = new(struct _mate, 1);
if (!him) {
ret = ENOMEM;
goto out;
}
- him->name = malloc(strlen(argv[i]) + 1);
+ him->name = strdup(argv[i]);
if (!him->name) {
+ free(him);
ret = ENOMEM;
goto out;
}
- strcpy(him->name, argv[i]);
him->state = STATE_NONE;
udev_list_node_append(&him->node, &bunch);
} else {
diff --git a/src/udev/keymap/.gitignore b/src/udev/keymap/.gitignore
deleted file mode 100644
index 4567584f4e..0000000000
--- a/src/udev/keymap/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-keyboard-force-release.sh
-keys-from-name.gperf
-keys-from-name.h
-keys-to-name.h
-keys.txt
diff --git a/src/udev/keymap/95-keyboard-force-release.rules b/src/udev/keymap/95-keyboard-force-release.rules
deleted file mode 100644
index 3e33e85535..0000000000
--- a/src/udev/keymap/95-keyboard-force-release.rules
+++ /dev/null
@@ -1,57 +0,0 @@
-# Set model specific atkbd force_release quirk
-#
-# Several laptops have hotkeys which don't generate release events,
-# which can cause problems with software key repeat.
-# The atkbd driver has a quirk handler for generating synthetic
-# release events, which can be configured via sysfs since 2.6.32.
-# Simply add a file with a list of scancodes for your laptop model
-# in /usr/lib/udev/keymaps, and add a rule here.
-# If the hotkeys also need a keymap assignment you can copy the
-# scancodes from the keymap file, otherwise you can run
-# /usr/lib/udev/keymap -i /dev/input/eventX
-# on a Linux vt to find out.
-
-ACTION=="remove", GOTO="force_release_end"
-SUBSYSTEM!="serio", GOTO="force_release_end"
-KERNEL!="serio*", GOTO="force_release_end"
-DRIVER!="atkbd", GOTO="force_release_end"
-
-ENV{DMI_VENDOR}="$attr{[dmi/id]sys_vendor}"
-
-ENV{DMI_VENDOR}=="[sS][aA][mM][sS][uU][nN][gG]*", RUN+="keyboard-force-release.sh $devpath samsung-other"
-ENV{DMI_VENDOR}=="[sS][aA][mM][sS][uU][nN][gG]*", ATTR{[dmi/id]product_name}=="*90X3A*|*900X3*|*900X4*", RUN+="keyboard-force-release.sh $devpath samsung-series-9"
-
-ENV{DMI_VENDOR}=="Dell Inc.", ATTR{[dmi/id]product_name}=="Studio 1557|Studio 1558", RUN+="keyboard-force-release.sh $devpath common-volume-keys"
-ENV{DMI_VENDOR}=="Dell Inc.", ATTR{[dmi/id]product_name}=="Latitude E*|Latitude *U|Precision M*", RUN+="keyboard-force-release.sh $devpath dell-touchpad"
-ENV{DMI_VENDOR}=="Dell Inc.", ATTR{[dmi/id]product_name}=="XPS*", RUN+="keyboard-force-release.sh $devpath dell-xps"
-
-ENV{DMI_VENDOR}=="FUJITSU SIEMENS", ATTR{[dmi/id]product_name}=="AMILO*", RUN+="keyboard-force-release.sh $devpath common-volume-keys"
-
-ENV{DMI_VENDOR}=="FOXCONN", ATTR{[dmi/id]product_name}=="QBOOK", RUN+="keyboard-force-release.sh $devpath common-volume-keys"
-
-ENV{DMI_VENDOR}=="MTC", ATTR{[dmi/id]product_version}=="A0", RUN+="keyboard-force-release.sh $devpath common-volume-keys"
-
-ENV{DMI_VENDOR}=="Mio Technology", ATTR{[dmi/id]product_name}=="N890", RUN+="keyboard-force-release.sh $devpath common-volume-keys"
-
-ENV{DMI_VENDOR}=="PEGATRON CORP.", ATTR{[dmi/id]product_name}=="Spring Peak", RUN+="keyboard-force-release.sh $devpath common-volume-keys"
-
-ENV{DMI_VENDOR}=="TOSHIBA", ATTR{[dmi/id]product_name}=="Satellite [uU]300*|Satellite Pro [uU]300*|Satellite [uU]305*|SATELLITE [uU]500*", RUN+="keyboard-force-release.sh $devpath common-volume-keys"
-
-ENV{DMI_VENDOR}=="Viooo Corporation", ATTR{[dmi/id]product_name}=="PT17", RUN+="keyboard-force-release.sh $devpath common-volume-keys"
-
-# These are all the HP laptops that setup a touchpad toggle key
-ENV{DMI_VENDOR}=="Hewlett-Packard*", ATTR{[dmi/id]product_name}=="*[pP][aA][vV][iI][lL][iI][oO][nN]*", RUN+="keyboard-force-release.sh $devpath hp-other"
-ENV{DMI_VENDOR}=="Hewlett-Packard*", ATTR{[dmi/id]product_name}=="*[tT][xX]2*", RUN+="keyboard-force-release.sh $devpath hp-other"
-ENV{DMI_VENDOR}=="Hewlett-Packard*", ATTR{[dmi/id]product_name}=="*2510p*|*2530p*|HP G60 Notebook PC|HDX9494NR", RUN+="keyboard-force-release.sh $devpath hp-other"
-
-ENV{DMI_VENDOR}=="Zepto", ATTR{[dmi/id]product_name}=="Znote 6615WD", RUN+="keyboard-force-release.sh $devpath common-volume-keys"
-
-ENV{DMI_VENDOR}=="Zepto", ATTR{[dmi/id]product_name}=="Znote", ATTR{[dmi/id]product_version}=="6625WD", RUN+="keyboard-force-release.sh $devpath common-volume-keys"
-
-ENV{DMI_VENDOR}=="HANNspree", ATTR{[dmi/id]product_name}=="SN10E100", RUN+="keyboard-force-release.sh $devpath common-volume-keys"
-
-ENV{DMI_VENDOR}=="GIGABYTE", ATTR{[dmi/id]product_name}=="i1520M", RUN+="keyboard-force-release.sh $devpath common-volume-keys"
-
-ENV{DMI_VENDOR}=="BenQ", ATTR{[dmi/id]product_name}=="*nScreen*", RUN+="keyboard-force-release.sh $devpath common-volume-keys"
-
-LABEL="force_release_end"
diff --git a/src/udev/keymap/95-keymap.rules b/src/udev/keymap/95-keymap.rules
deleted file mode 100644
index 7956092030..0000000000
--- a/src/udev/keymap/95-keymap.rules
+++ /dev/null
@@ -1,183 +0,0 @@
-# Set model specific hotkey keycodes.
-#
-# Key map overrides can be specified by either giving scancode/keyname pairs
-# directly as keymap arguments (if there are just one or two to change), or as
-# a file name (in /usr/lib/udev/keymaps), which has to contain scancode/keyname
-# pairs.
-
-ACTION=="remove", GOTO="keyboard_end"
-KERNEL!="event*", GOTO="keyboard_end"
-ENV{ID_INPUT_KEY}=="", GOTO="keyboard_end"
-SUBSYSTEMS=="bluetooth", GOTO="keyboard_end"
-
-SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id"
-SUBSYSTEMS=="usb", GOTO="keyboard_usbcheck"
-GOTO="keyboard_modulecheck"
-
-#
-# The following are external USB keyboards
-#
-
-LABEL="keyboard_usbcheck"
-
-ENV{ID_VENDOR}=="Genius", ENV{ID_MODEL_ID}=="0708", ENV{ID_USB_INTERFACE_NUM}=="01", RUN+="keymap $name genius-slimstar-320"
-ENV{ID_VENDOR}=="Logitech*", ATTRS{name}=="Logitech USB Multimedia Keyboard", RUN+="keymap $name logitech-wave"
-ENV{ID_VENDOR}=="Logitech*", ATTRS{name}=="Logitech USB Receiver", RUN+="keymap $name logitech-wave-cordless"
-# Logitech Cordless Wave Pro looks slightly weird; some hotkeys are coming through the mouse interface
-ENV{ID_VENDOR_ID}=="046d", ENV{ID_MODEL_ID}=="c52[9b]", ATTRS{name}=="Logitech USB Receiver", RUN+="keymap $name logitech-wave-pro-cordless"
-
-ENV{ID_VENDOR}=="Lite-On_Technology_Corp*", ATTRS{name}=="Lite-On Technology Corp. ThinkPad USB Keyboard with TrackPoint", RUN+="keymap $name lenovo-thinkpad-usb-keyboard-trackpoint"
-ENV{ID_VENDOR_ID}=="04b3", ENV{ID_MODEL_ID}=="301[89]", RUN+="keymap $name ibm-thinkpad-usb-keyboard-trackpoint"
-
-ENV{ID_VENDOR}=="Microsoft", ENV{ID_MODEL_ID}=="00db", RUN+="keymap $name 0xc022d zoomin 0xc022e zoomout"
-
-GOTO="keyboard_end"
-
-#
-# The following are exposed as separate input devices with low key codes, thus
-# we need to check their input device product name
-#
-
-LABEL="keyboard_modulecheck"
-
-ENV{DMI_VENDOR}="$attr{[dmi/id]sys_vendor}"
-ENV{DMI_VENDOR}=="", GOTO="keyboard_end"
-
-ENV{DMI_VENDOR}=="LENOVO*", KERNELS=="input*", ATTRS{name}=="ThinkPad Extra Buttons", RUN+="keymap $name module-lenovo"
-ENV{DMI_VENDOR}=="LENOVO*", KERNELS=="input*", ATTRS{name}=="Lenovo ThinkPad SL Series extra buttons", RUN+="keymap $name 0x0E bluetooth"
-ENV{DMI_VENDOR}=="LENOVO*", KERNELS=="input*", ATTRS{name}=="Ideapad extra buttons", RUN+="keymap $name 0x42 f23 0x43 f22"
-
-ENV{DMI_VENDOR}=="ASUS*", KERNELS=="input*", ATTRS{name}=="Asus Extra Buttons", ATTR{[dmi/id]product_name}=="W3J", RUN+="keymap $name module-asus-w3j"
-ENV{DMI_VENDOR}=="ASUS*", KERNELS=="input*", ATTRS{name}=="Eee PC WMI hotkeys|Asus Laptop Support|Asus*WMI*", RUN+="keymap $name 0x6B f21"
-ENV{DMI_VENDOR}=="ASUS*", KERNELS=="input*", ATTRS{name}=="Eee PC Hotkey Driver", RUN+="keymap $name 0x37 f21"
-
-ENV{DMI_VENDOR}=="IBM*", KERNELS=="input*", ATTRS{name}=="ThinkPad Extra Buttons", RUN+="keymap $name module-ibm"
-ENV{DMI_VENDOR}=="Sony*", KERNELS=="input*", ATTRS{name}=="Sony Vaio Keys", RUN+="keymap $name module-sony"
-ENV{DMI_VENDOR}=="Acer*", KERNELS=="input*", ATTRS{name}=="Acer WMI hotkeys", RUN+="keymap $name 0x82 f21"
-ENV{DMI_VENDOR}=="MICRO-STAR*|Micro-Star*", KERNELS=="input*", ATTRS{name}=="MSI Laptop hotkeys", RUN+="keymap $name 0x213 f22 0x214 f23"
-
-# Older Vaios have some different keys
-ENV{DMI_VENDOR}=="Sony*", ATTR{[dmi/id]product_name}=="*PCG-C1*|*PCG-K25*|*PCG-F1*|*PCG-F2*|*PCG-F3*|*PCG-F4*|*PCG-F5*|*PCG-F6*|*PCG-FX*|*PCG-FRV*|*PCG-GR*|*PCG-TR*|*PCG-NV*|*PCG-Z*|*VGN-S360*", ATTRS{name}=="Sony Vaio Keys", RUN+="keymap $name module-sony-old"
-
-# Some Sony VGN/VPC models have yet another one
-ENV{DMI_VENDOR}=="Sony*", ATTR{[dmi/id]product_name}=="VGN-AR71*|VGN-FW*|VGN-Z21*", ATTRS{name}=="Sony Vaio Keys", RUN+="keymap $name module-sony-vgn"
-ENV{DMI_VENDOR}=="Sony*", ATTR{[dmi/id]product_name}=="VPC*", ATTRS{name}=="Sony Vaio Keys", RUN+="keymap $name module-sony-vpc"
-
-
-#
-# The following rules belong to standard i8042 AT keyboard with high key codes.
-#
-
-DRIVERS=="atkbd", GOTO="keyboard_vendorcheck"
-GOTO="keyboard_end"
-
-LABEL="keyboard_vendorcheck"
-
-ENV{DMI_VENDOR}=="Dell*", RUN+="keymap $name dell"
-ENV{DMI_VENDOR}=="Dell*", ATTR{[dmi/id]product_name}=="Inspiron 910|Inspiron 1010|Inspiron 1011|Inspiron 1012|Inspiron 1110|Inspiron 1210", RUN+="keymap $name 0x84 wlan"
-ENV{DMI_VENDOR}=="Dell*", ATTR{[dmi/id]product_name}=="Latitude XT2", RUN+="keymap $name dell-latitude-xt2"
-
-ENV{DMI_VENDOR}=="Compaq*", ATTR{[dmi/id]product_name}=="*E500*|*Evo N*", RUN+="keymap $name compaq-e_evo"
-
-ENV{DMI_VENDOR}=="LENOVO*", ATTR{[dmi/id]product_version}=="*3000*", RUN+="keymap $name lenovo-3000"
-ENV{DMI_VENDOR}=="LENOVO*", ATTR{[dmi/id]product_version}=="ThinkPad X6*", ATTR{[dmi/id]product_version}=="* Tablet", RUN+="keymap $name lenovo-thinkpad_x6_tablet"
-ENV{DMI_VENDOR}=="LENOVO*", ATTR{[dmi/id]product_version}=="ThinkPad X2* Tablet*", ATTR{[dmi/id]product_version}=="* Tablet", RUN+="keymap $name lenovo-thinkpad_x200_tablet"
-ENV{DMI_VENDOR}=="LENOVO*", ATTR{[dmi/id]product_version}=="*IdeaPad*", RUN+="keymap $name lenovo-ideapad"
-ENV{DMI_VENDOR}=="LENOVO*", ATTR{[dmi/id]product_name}=="S10-*", RUN+="keymap $name lenovo-ideapad"
-ENV{DMI_VENDOR}=="LENOVO", ATTR{[dmi/id]product_version}=="*IdeaPad Y550*", RUN+="keymap $name 0x95 media 0xA3 play"
-ENV{DMI_VENDOR}=="LENOVO", ATTR{[dmi/id]product_version}=="*Lenovo V480*", RUN+="keymap $name 0xf1 f21"
-# 0xf1 is touchpad toggle, 0xCE is microphone mute in Lenovo U300s
-ENV{DMI_VENDOR}=="LENOVO", ATTR{[dmi/id]product_version}=="*IdeaPad U300s*", RUN+="keymap $name 0xf1 f21 0xCE f20"
-
-ENV{DMI_VENDOR}=="Hewlett-Packard*", RUN+="keymap $name hewlett-packard"
-ENV{DMI_VENDOR}=="Hewlett-Packard*", ATTR{[dmi/id]product_name}=="*[tT][aA][bB][lL][eE][tT]*", RUN+="keymap $name hewlett-packard-tablet"
-ENV{DMI_VENDOR}=="Hewlett-Packard*", ATTR{[dmi/id]product_name}=="*[pP][aA][vV][iI][lL][iI][oO][nN]*", RUN+="keymap $name hewlett-packard-pavilion"
-ENV{DMI_VENDOR}=="Hewlett-Packard*", ATTR{[dmi/id]product_name}=="*Compaq*|*EliteBook*|*2230s*", RUN+="keymap $name hewlett-packard-compaq_elitebook"
-ENV{DMI_VENDOR}=="Hewlett-Packard*", ATTR{[dmi/id]product_name}=="*Presario*CQ*", RUN+="keymap $name 0xD8 f21 0xD9 f21"
-ENV{DMI_VENDOR}=="Hewlett-Packard*", ATTR{[dmi/id]product_name}=="*2510p*|*2530p*|HP G60 Notebook PC", RUN+="keymap $name hewlett-packard-2510p_2530p"
-ENV{DMI_VENDOR}=="Hewlett-Packard*", ATTR{[dmi/id]product_name}=="*[tT][xX]2*", RUN+="keymap $name hewlett-packard-tx2"
-ENV{DMI_VENDOR}=="Hewlett-Packard", ATTR{[dmi/id]product_name}=="Presario 2100*", RUN+="keymap $name hewlett-packard-presario-2100"
-ENV{DMI_VENDOR}=="Hewlett-Packard", ATTR{[dmi/id]product_name}=="HP G62 Notebook PC", RUN+="keymap $name 0xB2 www"
-ENV{DMI_VENDOR}=="Hewlett-Packard", ATTR{[dmi/id]product_name}=="HP ProBook*", RUN+="keymap $name 0xF8 rfkill 0xB2 www"
-ENV{DMI_VENDOR}=="Hewlett-Packard", ATTR{[dmi/id]product_name}=="HP EliteBook 8440p", RUN+="keymap $name hewlett-packard_elitebook-8440p"
-ENV{DMI_VENDOR}=="Hewlett-Packard", ATTR{[dmi/id]product_name}=="HP EliteBook 8460p", RUN+="keymap $name hewlett-packard_elitebook-8460p"
-ENV{DMI_VENDOR}=="Hewlett-Packard", ATTR{[dmi/id]product_name}=="HDX9494NR", RUN+="keymap $name hewlett-packard-hdx9494nr"
-# HP Pavilion dv6315ea has empty DMI_VENDOR
-ATTR{[dmi/id]board_vendor}=="Quanta", ATTR{[dmi/id]board_name}=="30B7", ATTR{[dmi/id]board_version}=="65.2B", RUN+="keymap $name 0x88 media" # "quick play
-
-# Gateway clone of Acer Aspire One AOA110/AOA150
-ENV{DMI_VENDOR}=="Gateway*", ATTR{[dmi/id]product_name}=="*AOA1*", RUN+="keymap $name acer"
-
-ENV{DMI_VENDOR}=="Acer*", RUN+="keymap $name acer"
-ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_name}=="Extensa*", ATTR{[dmi/id]product_name}=="*5210*|*5220*|*5610*|*5620*|*5720*", RUN+="keymap $name 0xEE screenlock"
-ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_name}=="TravelMate*C3[01]0*", RUN+="keymap $name acer-travelmate_c300"
-ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_name}=="TravelMate*6292*|TravelMate*8471*|TravelMate*4720*|TravelMate*7720*|Aspire 1810T*|AO751h|AO531h", RUN+="keymap $name 0xD9 bluetooth"
-ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_name}=="TravelMate*4720*", RUN+="keymap $name 0xB2 www 0xEE screenlock"
-ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_name}=="TravelMate 6593|Aspire 1640", RUN+="keymap $name 0xB2 www 0xEE screenlock"
-ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_name}=="Aspire 6920", RUN+="keymap $name acer-aspire_6920"
-ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_name}=="Aspire 5920G", RUN+="keymap $name acer-aspire_5920g"
-ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_name}=="Aspire 5720*", RUN+="keymap $name acer-aspire_5720"
-ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_name}=="Aspire 8930", RUN+="keymap $name acer-aspire_8930"
-ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_serial}=="ZG8*", RUN+="keymap $name acer-aspire_5720"
-
-ENV{DMI_VENDOR}=="*BenQ*", ATTR{[dmi/id]product_name}=="*Joybook R22*", RUN+="keymap $name 0x6E wlan"
-
-ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="*AMILO Pro V3205*", RUN+="keymap $name fujitsu-amilo_pro_v3205"
-ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="*AMILO Pa 2548*", RUN+="keymap $name fujitsu-amilo_pa_2548"
-ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="*ESPRIMO Mobile V5*", RUN+="keymap $name fujitsu-esprimo_mobile_v5"
-ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="*ESPRIMO Mobile V6*", RUN+="keymap $name fujitsu-esprimo_mobile_v6"
-ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="*AMILO Pro Edition V3505*", RUN+="keymap $name fujitsu-amilo_pro_edition_v3505"
-ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="*Amilo Si 1520*", RUN+="keymap $name fujitsu-amilo_si_1520"
-ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="AMILO*M*", RUN+="keymap $name 0x97 prog2 0x9F prog1"
-ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="Amilo Li 1718", RUN+="keymap $name 0xD6 wlan"
-ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="AMILO Li 2732", RUN+="keymap $name fujitsu-amilo_li_2732"
-
-ENV{DMI_VENDOR}=="LG*", ATTR{[dmi/id]product_name}=="*X110*", RUN+="keymap $name lg-x110"
-
-ENV{DMI_VENDOR}=="MEDION*", ATTR{[dmi/id]product_name}=="*FID2060*", RUN+="keymap $name medion-fid2060"
-ENV{DMI_VENDOR}=="MEDIONNB", ATTR{[dmi/id]product_name}=="A555*", RUN+="keymap $name medionnb-a555"
-
-ENV{DMI_VENDOR}=="MICRO-STAR*|Micro-Star*", RUN+="keymap $name micro-star"
-
-# some MSI models generate ACPI/input events on the LNXVIDEO input devices,
-# plus some extra synthesized ones on atkbd as an echo of actually changing the
-# brightness; so ignore those atkbd ones, to avoid loops
-ENV{DMI_VENDOR}=="MICRO-STAR*", ATTR{[dmi/id]product_name}=="*U-100*|*U100*|*N033", RUN+="keymap $name 0xF7 reserved 0xF8 reserved"
-
-# MSI Wind U90/U100 generates separate touchpad on/off keycodes so ignore touchpad toggle keycode
-ENV{DMI_VENDOR}=="MICRO-STAR*", ATTR{[dmi/id]product_name}=="U90/U100", RUN+="keymap $name 0xE4 reserved"
-
-ENV{DMI_VENDOR}=="INVENTEC", ATTR{[dmi/id]product_name}=="SYMPHONY 6.0/7.0", RUN+="keymap $name inventec-symphony_6.0_7.0"
-
-ENV{DMI_VENDOR}=="MAXDATA", ATTR{[dmi/id]product_name}=="Pro 7000*", RUN+="keymap $name maxdata-pro_7000"
-
-ENV{DMI_VENDOR}=="[sS][aA][mM][sS][uU][nN][gG]*", RUN+="keymap $name samsung-other"
-ENV{DMI_VENDOR}=="[sS][aA][mM][sS][uU][nN][gG]*", ATTR{[dmi/id]product_name}=="*SX20S*", RUN+="keymap $name samsung-sx20s"
-ENV{DMI_VENDOR}=="[sS][aA][mM][sS][uU][nN][gG]*", ATTR{[dmi/id]product_name}=="SQ1US", RUN+="keymap $name samsung-sq1us"
-ENV{DMI_VENDOR}=="[sS][aA][mM][sS][uU][nN][gG]*", ATTR{[dmi/id]product_name}=="*700Z*", RUN+="keymap $name 0xBA ejectcd 0x96 keyboardbrightnessup 0x97 keyboardbrightnessdown"
-ENV{DMI_VENDOR}=="[sS][aA][mM][sS][uU][nN][gG]*", ATTR{[dmi/id]product_name}=="*700T*", RUN+="keymap $name 0xAD leftmeta"
-ENV{DMI_VENDOR}=="[sS][aA][mM][sS][uU][nN][gG]*", ATTR{[dmi/id]product_name}=="*90X3A*|*900X3*|*900X4*", RUN+="keymap $name samsung-series-9"
-
-ENV{DMI_VENDOR}=="TOSHIBA", ATTR{[dmi/id]product_name}=="SATELLITE A100", RUN+="keymap $name toshiba-satellite_a100"
-ENV{DMI_VENDOR}=="TOSHIBA", ATTR{[dmi/id]product_name}=="Satellite A110", RUN+="keymap $name toshiba-satellite_a110"
-ENV{DMI_VENDOR}=="TOSHIBA", ATTR{[dmi/id]product_name}=="Satellite M30X", RUN+="keymap $name toshiba-satellite_m30x"
-
-ENV{DMI_VENDOR}=="OQO Inc.*", ATTR{[dmi/id]product_name}=="OQO Model 2*", RUN+="keymap $name oqo-model2"
-
-ENV{DMI_VENDOR}=="ONKYO CORPORATION", ATTR{[dmi/id]product_name}=="ONKYOPC", RUN+="keymap $name onkyo"
-
-ENV{DMI_VENDOR}=="ASUS", RUN+="keymap $name asus"
-
-ENV{DMI_VENDOR}=="VIA", ATTR{[dmi/id]product_name}=="K8N800", ATTR{[dmi/id]product_version}=="VT8204B", RUN+="keymap $name 0x81 prog1"
-
-ENV{DMI_VENDOR}=="Zepto", ATTR{[dmi/id]product_name}=="Znote", ATTR{[dmi/id]product_version}=="62*|63*", RUN+="keymap $name zepto-znote"
-
-ENV{DMI_VENDOR}=="Everex", ATTR{[dmi/id]product_name}=="XT5000*", RUN+="keymap $name everex-xt5000"
-
-ENV{DMI_VENDOR}=="COMPAL", ATTR{[dmi/id]product_name}=="HEL80I", RUN+="keymap $name 0x84 wlan"
-
-ENV{DMI_VENDOR}=="OLPC", ATTR{[dmi/id]product_name}=="XO", RUN+="keymap $name olpc-xo"
-
-ENV{DMI_VENDOR}=="Alienware*", ATTR{[dmi/id]product_name}=="M14xR1", RUN+="keymap $name 0x8A ejectcd"
-
-LABEL="keyboard_end"
diff --git a/src/udev/keymap/README.keymap.txt b/src/udev/keymap/README.keymap.txt
deleted file mode 100644
index 2cf2a4e88c..0000000000
--- a/src/udev/keymap/README.keymap.txt
+++ /dev/null
@@ -1,97 +0,0 @@
-= The udev keymap tool =
-
-== Introduction ==
-
-This udev extension configures computer model specific key mappings. This is
-particularly necessary for the non-standard extra keys found on many laptops,
-such as "brightness up", "next song", "www browser", or "suspend". Often these
-are accessed with the Fn key.
-
-Every key produces a "scan code", which is highly vendor/model specific for the
-nonstandard keys. This tool maintains mappings for these scan codes to standard
-"key codes", which denote the "meaning" of the key. The key codes are defined
-in /usr/include/linux/input.h.
-
-If some of your keys on your keyboard are not working at all, or produce the
-wrong effect, then a very likely cause of this is that the scan code -> key
-code mapping is incorrect on your computer.
-
-== Structure ==
-
-udev-keymap consists of the following parts:
-
- keymaps/*:: mappings of scan codes to key code names
-
- 95-keymap.rules:: udev rules for mapping system vendor/product names and
- input module names to one of the keymaps above
-
- keymap:: manipulate an evdev input device:
- * write a key map file into a device (used by udev rules)
- * dump current scan → key code mapping
- * interactively display scan and key codes of pressed keys
-
- findkeyboards:: display evdev input devices which belong to actual keyboards,
- i. e. those suitable for the keymap program
-
-== Fixing broken keys ==
-
-In order to make a broken key work on your system and send it back to upstream
-for inclusion you need to do the following steps:
-
- 1. Find the keyboard device.
-
- Run /usr/lib/udev/findkeyboards. This should always give you an "AT
- keyboard" and possibly a "module". Some laptops (notably Thinkpads, Sonys, and
- Acers) have multimedia/function keys on a separate input device instead of the
- primary keyboard. The keyboard device should have a name like "input/event3".
- In the following commands, the name will be written as "input/eventX" (replace
- X with the appropriate number).
-
- 2. Find broken scan codes:
-
- sudo /usr/lib/udev/keymap -i input/eventX
-
- Press all multimedia/function keys and check if the key name that gets printed
- out is plausible. If it is unknown or wrong, write down the scan code (looks
- like "0x1E") and the intended functionality of this key. Look in
- /usr/include/linux/input.h for an available KEY_XXXXX constant which most
- closely approximates this functionality and write it down as the new key code.
-
- For example, you might press a key labeled "web browser" which currently
- produces "unknown". Note down this:
-
- 0x1E www # Fn+F2 web browser
-
- Repeat that for all other keys. Write the resulting list into a file. Look at
- /usr/lib/udev/keymaps/ for existing key map files and make sure that you use the
- same structure.
-
- If the key only ever works once and then your keyboard (or the entire desktop)
- gets stuck for a long time, then it is likely that the BIOS fails to send a
- corresponding "key release" event after the key press event. Please note down
- this case as well, as it can be worked around in
- /usr/lib/udev/keymaps/95-keyboard-force-release.rules .
-
- 3. Find out your system vendor and product:
-
- cat /sys/class/dmi/id/sys_vendor
- cat /sys/class/dmi/id/product_name
-
- 4. Generate a device dump with "udevadm info --export-db > /tmp/udev-db.txt".
-
- 6. Send the system vendor/product names, the key mapping from step 2,
- and /tmp/udev-db.txt from step 4 to the linux-hotplug@vger.kernel.org mailing
- list, so that they can be included in the next release.
-
-For local testing, copy your map file to /usr/lib/udev/keymaps/ with an appropriate
-name, and add an appropriate udev rule to /usr/lib/udev/rules.d/95-keymap.rules:
-
- * If you selected an "AT keyboard", add the rule to the section after
- 'LABEL="keyboard_vendorcheck"'.
-
- * If you selected a "module", add the rule to the top section where the
- "ThinkPad Extra Buttons" are.
-
-== Author ==
-
-keymap is written and maintained by Martin Pitt <martin.pitt@ubuntu.com>.
diff --git a/src/udev/keymap/check-keymaps.sh b/src/udev/keymap/check-keymaps.sh
deleted file mode 100755
index c4572745e0..0000000000
--- a/src/udev/keymap/check-keymaps.sh
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/bash
-
-# check that all key names in keymaps/* are known in <linux/input.h>
-# and that all key maps listed in the rules are valid and present in
-# Makefile.am
-SRCDIR=${1:-.}
-KEYLIST=${2:-src/udev/keymap/keys.txt}
-KEYMAPS_DIR=$SRCDIR/keymaps
-RULES=$SRCDIR/src/udev/keymap/95-keymap.rules
-
-[ -e "$KEYLIST" ] || {
- echo "need $KEYLIST please build first" >&2
- exit 1
-}
-
-missing=$(join -v 2 <(awk '{print tolower(substr($1,5))}' $KEYLIST | sort -u) \
- <(grep -hv '^#' ${KEYMAPS_DIR}/*| awk '{print $2}' | sort -u))
-[ -z "$missing" ] || {
- echo "ERROR: unknown key names in keymaps/*:" >&2
- echo "$missing" >&2
- exit 1
-}
-
-# check that all maps referred to in $RULES exist
-maps=$(sed -rn '/keymap \$name/ { s/^.*\$name ([^"[:space:]]+).*$/\1/; p }' $RULES)
-for m in $maps; do
- # ignore inline mappings
- [ "$m" = "${m#0x}" ] || continue
-
- [ -e ${KEYMAPS_DIR}/$m ] || {
- echo "ERROR: unknown map name in $RULES: $m" >&2
- exit 1
- }
- grep -q "keymaps/$m\>" $SRCDIR/Makefile.am || {
- echo "ERROR: map file $m is not added to Makefile.am" >&2
- exit 1
- }
-done
diff --git a/src/udev/keymap/findkeyboards b/src/udev/keymap/findkeyboards
deleted file mode 100755
index c6b50d12d0..0000000000
--- a/src/udev/keymap/findkeyboards
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/bin/sh -e
-# Find "real" keyboard devices and print their device path.
-# Author: Martin Pitt <martin.pitt@ubuntu.com>
-#
-# Copyright (C) 2009, Canonical Ltd.
-#
-# 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.
-
-# returns OK if $1 contains $2
-strstr() {
- [ "${1#*$2*}" != "$1" ]
-}
-
-# returns OK if $1 contains $2 at the beginning
-str_starts() {
- [ "${1#$2*}" != "$1" ]
-}
-
-str_line_starts() {
- while read a; do str_starts "$a" "$1" && return 0;done
- return 1;
-}
-
-# print a list of input devices which are keyboard-like
-keyboard_devices() {
- # standard AT keyboard
- for dev in `udevadm trigger --dry-run --verbose --property-match=ID_INPUT_KEYBOARD=1`; do
- env=`udevadm info --query=env --path=$dev`
- # filter out non-event devices, such as the parent input devices which have no devnode
- if ! echo "$env" | str_line_starts 'DEVNAME='; then
- continue
- fi
- walk=`udevadm info --attribute-walk --path=$dev`
- if strstr "$walk" 'DRIVERS=="atkbd"'; then
- echo -n 'AT keyboard: '
- elif echo "$env" | str_line_starts 'ID_USB_DRIVER=usbhid'; then
- echo -n 'USB keyboard: '
- else
- echo -n 'Unknown type: '
- fi
- udevadm info --query=name --path=$dev
- done
-
- # modules
- module=$(udevadm trigger --verbose --dry-run --subsystem-match=input --attr-match=name='*Extra Buttons')
- module="$module
- $(udevadm trigger --verbose --dry-run --subsystem-match=input --attr-match=name='*extra buttons')"
- module="$module
- $(udevadm trigger --verbose --dry-run --subsystem-match=input --attr-match=name='Sony Vaio Keys')"
- for m in $module; do
- for evdev in $m/event*/dev; do
- if [ -e "$evdev" ]; then
- echo -n 'module: '
- udevadm info --query=name --path=${evdev%%/dev}
- fi
- done
- done
-}
-
-keyboard_devices
diff --git a/src/udev/keymap/keyboard-force-release.sh.in b/src/udev/keymap/keyboard-force-release.sh.in
deleted file mode 100755
index b82674840f..0000000000
--- a/src/udev/keymap/keyboard-force-release.sh.in
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/sh -e
-# read list of scancodes, convert hex to decimal and
-# append to the atkbd force_release sysfs attribute
-# $1 sysfs devpath for serioX
-# $2 file with scancode list (hex or dec)
-
-case "$2" in
- /*) scf="$2" ;;
- *) scf="@udevlibexecdir@/keymaps/force-release/$2" ;;
-esac
-
-read attr <"/sys/$1/force_release"
-while read scancode dummy; do
- case "$scancode" in
- \#*) ;;
- *)
- scancode=$(($scancode))
- attr="$attr${attr:+,}$scancode"
- ;;
- esac
-done <"$scf"
-echo "$attr" >"/sys/$1/force_release"
diff --git a/src/udev/keymap/keymap.c b/src/udev/keymap/keymap.c
deleted file mode 100644
index ae0a19d3a3..0000000000
--- a/src/udev/keymap/keymap.c
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- * keymap - dump keymap of an evdev device or set a new keymap from a file
- *
- * Based on keyfuzz by Lennart Poettering <mzqrovna@0pointer.net>
- * Adapted for udev-extras by Martin Pitt <martin.pitt@ubuntu.com>
- *
- * Copyright (C) 2006, Lennart Poettering
- * Copyright (C) 2009, Canonical Ltd.
- *
- * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <errno.h>
-#include <limits.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <sys/ioctl.h>
-#include <linux/limits.h>
-#include <linux/input.h>
-
-static const struct key* lookup_key (const char *str, unsigned int len);
-
-#include "keys-from-name.h"
-#include "keys-to-name.h"
-#include "macro.h"
-#include "util.h"
-
-#define MAX_SCANCODES 1024
-
-static int evdev_open(const char *dev)
-{
- int fd;
- char fn[PATH_MAX];
-
- if (!startswith(dev, "/dev")) {
- snprintf(fn, sizeof(fn), "/dev/%s", dev);
- dev = fn;
- }
-
- if ((fd = open(dev, O_RDWR)) < 0) {
- fprintf(stderr, "error open('%s'): %m\n", dev);
- return -1;
- }
- return fd;
-}
-
-static int evdev_get_keycode(int fd, unsigned scancode, int e)
-{
- unsigned codes[2];
-
- codes[0] = scancode;
- if (ioctl(fd, EVIOCGKEYCODE, codes) < 0) {
- if (e && errno == EINVAL) {
- return -2;
- } else {
- fprintf(stderr, "EVIOCGKEYCODE for scan code 0x%x: %m\n", scancode);
- return -1;
- }
- }
- return codes[1];
-}
-
-static int evdev_set_keycode(int fd, unsigned scancode, int keycode)
-{
- unsigned codes[2];
-
- codes[0] = scancode;
- codes[1] = (unsigned) keycode;
-
- if (ioctl(fd, EVIOCSKEYCODE, codes) < 0) {
- fprintf(stderr, "EVIOCSKEYCODE: %m\n");
- return -1;
- }
- return 0;
-}
-
-static int evdev_driver_version(int fd, char *v, size_t l)
-{
- int version;
-
- if (ioctl(fd, EVIOCGVERSION, &version)) {
- fprintf(stderr, "EVIOCGVERSION: %m\n");
- return -1;
- }
-
- snprintf(v, l, "%i.%i.%i.", version >> 16, (version >> 8) & 0xff, version & 0xff);
- return 0;
-}
-
-static int evdev_device_name(int fd, char *n, size_t l)
-{
- if (ioctl(fd, EVIOCGNAME(l), n) < 0) {
- fprintf(stderr, "EVIOCGNAME: %m\n");
- return -1;
- }
- return 0;
-}
-
-/* Return a lower-case string with KEY_ prefix removed */
-static const char* format_keyname(const char* key) {
- static char result[101];
- const char* s;
- int len;
-
- for (s = key+4, len = 0; *s && len < 100; ++len, ++s)
- result[len] = tolower(*s);
- result[len] = '\0';
- return result;
-}
-
-static int dump_table(int fd) {
- char version[256], name[256];
- unsigned scancode;
- int r = -1;
-
- if (evdev_driver_version(fd, version, sizeof(version)) < 0)
- goto fail;
-
- if (evdev_device_name(fd, name, sizeof(name)) < 0)
- goto fail;
-
- printf("### evdev %s, driver '%s'\n", version, name);
-
- r = 0;
- for (scancode = 0; scancode < MAX_SCANCODES; scancode++) {
- int keycode;
-
- if ((keycode = evdev_get_keycode(fd, scancode, 1)) < 0) {
- if (keycode == -2)
- continue;
- r = -1;
- break;
- }
-
- if (keycode < KEY_MAX && key_names[keycode])
- printf("0x%03x %s\n", scancode, format_keyname(key_names[keycode]));
- else
- printf("0x%03x 0x%03x\n", scancode, keycode);
- }
-fail:
- return r;
-}
-
-static void set_key(int fd, const char* scancode_str, const char* keyname)
-{
- unsigned scancode;
- char *endptr;
- char t[105] = "KEY_UNKNOWN";
- const struct key *k;
-
- scancode = (unsigned) strtol(scancode_str, &endptr, 0);
- if (*endptr != '\0') {
- fprintf(stderr, "ERROR: Invalid scancode\n");
- exit(1);
- }
-
- snprintf(t, sizeof(t), "KEY_%s", keyname);
-
- if (!(k = lookup_key(t, strlen(t)))) {
- fprintf(stderr, "ERROR: Unknown key name '%s'\n", keyname);
- exit(1);
- }
-
- if (evdev_set_keycode(fd, scancode, k->id) < 0)
- fprintf(stderr, "setting scancode 0x%2X to key code %i failed\n",
- scancode, k->id);
- else
- printf("setting scancode 0x%2X to key code %i\n",
- scancode, k->id);
-}
-
-static int merge_table(int fd, FILE *f) {
- int r = 0;
- int line = 0;
-
- while (!feof(f)) {
- char s[256], *p;
- unsigned scancode;
- int new_keycode, old_keycode;
-
- if (!fgets(s, sizeof(s), f))
- break;
-
- line++;
- p = s+strspn(s, "\t ");
- if (*p == '#' || *p == '\n')
- continue;
-
- if (sscanf(p, "%i %i", &scancode, &new_keycode) != 2) {
- char t[105] = "KEY_UNKNOWN";
- const struct key *k;
-
- if (sscanf(p, "%i %100s", &scancode, t+4) != 2) {
- fprintf(stderr, "WARNING: Parse failure at line %i, ignoring.\n", line);
- r = -1;
- continue;
- }
-
- if (!(k = lookup_key(t, strlen(t)))) {
- fprintf(stderr, "WARNING: Unknown key '%s' at line %i, ignoring.\n", t, line);
- r = -1;
- continue;
- }
-
- new_keycode = k->id;
- }
-
-
- if ((old_keycode = evdev_get_keycode(fd, scancode, 0)) < 0) {
- r = -1;
- continue;
- }
-
- if (evdev_set_keycode(fd, scancode, new_keycode) < 0) {
- r = -1;
- continue;
- }
-
- if (new_keycode != old_keycode)
- fprintf(stderr, "Remapped scancode 0x%02x to 0x%02x (prior: 0x%02x)\n",
- scancode, new_keycode, old_keycode);
- }
-
- fclose(f);
- return r;
-}
-
-
-/* read one event; return 1 if valid */
-static int read_event(int fd, struct input_event* ev)
-{
- int ret;
- ret = read(fd, ev, sizeof(struct input_event));
-
- if (ret < 0) {
- perror("read");
- return 0;
- }
- if (ret != sizeof(struct input_event)) {
- fprintf(stderr, "did not get enough data for event struct, aborting\n");
- return 0;
- }
-
- return 1;
-}
-
-static void print_key(unsigned scancode, uint16_t keycode, int has_scan, int has_key)
-{
- const char *keyname;
-
- /* ignore key release events */
- if (has_key == 1)
- return;
-
- if (has_key == 0 && has_scan != 0) {
- fprintf(stderr, "got scan code event 0x%02X without a key code event\n",
- scancode);
- return;
- }
-
- if (has_scan != 0)
- printf("scan code: 0x%02X ", scancode);
- else
- printf("(no scan code received) ");
-
- keyname = key_names[keycode];
- if (keyname != NULL)
- printf("key code: %s\n", format_keyname(keyname));
- else
- printf("key code: %03X\n", keycode);
-}
-
-static void interactive(int fd)
-{
- struct input_event ev;
- unsigned last_scan = 0;
- uint16_t last_key = 0;
- int has_scan; /* boolean */
- int has_key; /* 0: none, 1: release, 2: press */
-
- /* grab input device */
- ioctl(fd, EVIOCGRAB, 1);
- puts("Press ESC to finish, or Control-C if this device is not your primary keyboard");
-
- has_scan = has_key = 0;
- while (read_event(fd, &ev)) {
- /* Drivers usually send the scan code first, then the key code,
- * then a SYN. Some drivers (like thinkpad_acpi) send the key
- * code first, and some drivers might not send SYN events, so
- * keep a robust state machine which can deal with any of those
- */
-
- if (ev.type == EV_MSC && ev.code == MSC_SCAN) {
- if (has_scan) {
- fputs("driver did not send SYN event in between key events; previous event:\n",
- stderr);
- print_key(last_scan, last_key, has_scan, has_key);
- has_key = 0;
- }
-
- last_scan = ev.value;
- has_scan = 1;
- /*printf("--- got scan %u; has scan %i key %i\n", last_scan, has_scan, has_key); */
- }
- else if (ev.type == EV_KEY) {
- if (has_key) {
- fputs("driver did not send SYN event in between key events; previous event:\n",
- stderr);
- print_key(last_scan, last_key, has_scan, has_key);
- has_scan = 0;
- }
-
- last_key = ev.code;
- has_key = 1 + ev.value;
- /*printf("--- got key %hu; has scan %i key %i\n", last_key, has_scan, has_key);*/
-
- /* Stop on ESC */
- if (ev.code == KEY_ESC && ev.value == 0)
- break;
- }
- else if (ev.type == EV_SYN) {
- /*printf("--- got SYN; has scan %i key %i\n", has_scan, has_key);*/
- print_key(last_scan, last_key, has_scan, has_key);
-
- has_scan = has_key = 0;
- }
-
- }
-
- /* release input device */
- ioctl(fd, EVIOCGRAB, 0);
-}
-
-_noreturn_ static void help(int error)
-{
- const char* h = "Usage: keymap <event device> [<map file>]\n"
- " keymap <event device> scancode keyname [...]\n"
- " keymap -i <event device>\n";
- if (error) {
- fputs(h, stderr);
- exit(2);
- } else {
- fputs(h, stdout);
- exit(0);
- }
-}
-
-int main(int argc, char **argv)
-{
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "interactive", no_argument, NULL, 'i' },
- {}
- };
- int fd = -1;
- int opt_interactive = 0;
- int i;
-
- while (1) {
- int option;
-
- option = getopt_long(argc, argv, "hi", options, NULL);
- if (option == -1)
- break;
-
- switch (option) {
- case 'h':
- help(0);
-
- case 'i':
- opt_interactive = 1;
- break;
- default:
- return 1;
- }
- }
-
- if (argc < optind+1)
- help (1);
-
- if ((fd = evdev_open(argv[optind])) < 0)
- return 3;
-
- /* one argument (device): dump or interactive */
- if (argc == optind+1) {
- if (opt_interactive)
- interactive(fd);
- else
- dump_table(fd);
- return 0;
- }
-
- /* two arguments (device, mapfile): set map file */
- if (argc == optind+2) {
- const char *filearg = argv[optind+1];
- if (strchr(filearg, '/')) {
- /* Keymap file argument is a path */
- FILE *f = fopen(filearg, "re");
- if (f)
- merge_table(fd, f);
- else
- perror(filearg);
- } else {
- /* Keymap file argument is a filename */
- /* Open override file if present, otherwise default file */
- char keymap_path[PATH_MAX];
- FILE *f;
-
- snprintf(keymap_path, sizeof(keymap_path), "/etc/udev/keymaps/%s", filearg);
- f = fopen(keymap_path, "re");
- if (f) {
- merge_table(fd, f);
- } else {
- snprintf(keymap_path, sizeof(keymap_path), UDEVLIBEXECDIR "/keymaps/%s", filearg);
- f = fopen(keymap_path, "re");
- if (f)
- merge_table(fd, f);
- else
- perror(keymap_path);
- }
- }
- return 0;
- }
-
- /* more arguments (device, scancode/keyname pairs): set keys directly */
- if ((argc - optind - 1) % 2 == 0) {
- for (i = optind+1; i < argc; i += 2)
- set_key(fd, argv[i], argv[i+1]);
- return 0;
- }
-
- /* invalid number of arguments */
- help(1);
- return 1; /* not reached */
-}
diff --git a/src/udev/udev-builtin-blkid.c b/src/udev/udev-builtin-blkid.c
index bae429344f..b48dccc2fb 100644
--- a/src/udev/udev-builtin-blkid.c
+++ b/src/udev/udev-builtin-blkid.c
@@ -67,6 +67,9 @@ static void print_property(struct udev_device *dev, bool test, const char *name,
} else if (streq(name, "PTTYPE")) {
udev_builtin_add_property(dev, test, "ID_PART_TABLE_TYPE", value);
+ } else if (streq(name, "PTUUID")) {
+ udev_builtin_add_property(dev, test, "ID_PART_TABLE_UUID", value);
+
} else if (streq(name, "PART_ENTRY_NAME")) {
blkid_encode_string(value, s, sizeof(s));
udev_builtin_add_property(dev, test, "ID_PART_ENTRY_NAME", s);
diff --git a/src/udev/udev-builtin-hwdb.c b/src/udev/udev-builtin-hwdb.c
index 0b35d799fe..d6aa96bb3d 100644
--- a/src/udev/udev-builtin-hwdb.c
+++ b/src/udev/udev-builtin-hwdb.c
@@ -23,20 +23,37 @@
#include <inttypes.h>
#include <ctype.h>
#include <stdlib.h>
+#include <fnmatch.h>
#include <getopt.h>
#include "udev.h"
static struct udev_hwdb *hwdb;
-int udev_builtin_hwdb_lookup(struct udev_device *dev, const char *modalias, bool test) {
+int udev_builtin_hwdb_lookup(struct udev_device *dev,
+ const char *prefix, const char *modalias,
+ const char *filter, bool test) {
+ struct udev_list_entry *list;
struct udev_list_entry *entry;
int n = 0;
if (!hwdb)
return -ENOENT;
- udev_list_entry_foreach(entry, udev_hwdb_get_properties_list_entry(hwdb, modalias, 0)) {
+ if (prefix) {
+ _cleanup_free_ const char *lookup;
+
+ lookup = strjoin(prefix, modalias, NULL);
+ if (!lookup)
+ return -ENOMEM;
+ list = udev_hwdb_get_properties_list_entry(hwdb, lookup, 0);
+ } else
+ list = udev_hwdb_get_properties_list_entry(hwdb, modalias, 0);
+
+ udev_list_entry_foreach(entry, list) {
+ if (filter && fnmatch(filter, udev_list_entry_get_name(entry), FNM_NOESCAPE) != 0)
+ continue;
+
if (udev_builtin_add_property(dev, test,
udev_list_entry_get_name(entry),
udev_list_entry_get_value(entry)) < 0)
@@ -66,12 +83,14 @@ static const char *modalias_usb(struct udev_device *dev, char *s, size_t size) {
return s;
}
-static int udev_builtin_hwdb_search(struct udev_device *dev, const char *subsystem, bool test) {
+static int udev_builtin_hwdb_search(struct udev_device *dev, struct udev_device *srcdev,
+ const char *subsystem, const char *prefix,
+ const char *filter, bool test) {
struct udev_device *d;
char s[16];
int n = 0;
- for (d = dev; d; d = udev_device_get_parent(d)) {
+ for (d = srcdev; d; d = udev_device_get_parent(d)) {
const char *dsubsys;
const char *modalias = NULL;
@@ -83,16 +102,16 @@ static int udev_builtin_hwdb_search(struct udev_device *dev, const char *subsyst
if (subsystem && !streq(dsubsys, subsystem))
continue;
- /* the usb_device does not have a modalias, compose one */
- if (streq(dsubsys, "usb"))
- modalias = modalias_usb(dev, s, sizeof(s));
+ modalias = udev_device_get_property_value(d, "MODALIAS");
- if (!modalias)
- modalias = udev_device_get_property_value(d, "MODALIAS");
+ /* the usb_device does not have a modalias, compose one */
+ if (!modalias && streq(dsubsys, "usb"))
+ modalias = modalias_usb(d, s, sizeof(s));
if (!modalias)
continue;
- n = udev_builtin_hwdb_lookup(dev, modalias, test);
+
+ n = udev_builtin_hwdb_lookup(dev, prefix, modalias, filter, test);
if (n > 0)
break;
}
@@ -102,10 +121,17 @@ static int udev_builtin_hwdb_search(struct udev_device *dev, const char *subsyst
static int builtin_hwdb(struct udev_device *dev, int argc, char *argv[], bool test) {
static const struct option options[] = {
+ { "filter", required_argument, NULL, 'f' },
+ { "device", required_argument, NULL, 'd' },
{ "subsystem", required_argument, NULL, 's' },
+ { "lookup-prefix", required_argument, NULL, 'p' },
{}
};
+ const char *filter = NULL;
+ const char *device = NULL;
const char *subsystem = NULL;
+ const char *prefix = NULL;
+ struct udev_device *srcdev;
if (!hwdb)
return EXIT_FAILURE;
@@ -113,20 +139,47 @@ static int builtin_hwdb(struct udev_device *dev, int argc, char *argv[], bool te
for (;;) {
int option;
- option = getopt_long(argc, argv, "s", options, NULL);
+ option = getopt_long(argc, argv, "f:d:s:p:", options, NULL);
if (option == -1)
break;
switch (option) {
+ case 'f':
+ filter = optarg;
+ break;
+
+ case 'd':
+ device = optarg;
+ break;
+
case 's':
subsystem = optarg;
break;
+
+ case 'p':
+ prefix = optarg;
+ break;
}
}
- if (udev_builtin_hwdb_search(dev, subsystem, test) < 0)
+ /* query a specific key given as argument */
+ if (argv[optind]) {
+ if (udev_builtin_hwdb_lookup(dev, prefix, argv[optind], filter, test) > 0)
+ return EXIT_SUCCESS;
return EXIT_FAILURE;
- return EXIT_SUCCESS;
+ }
+
+ /* read data from another device than the device we will store the data */
+ if (device) {
+ srcdev = udev_device_new_from_device_id(udev_device_get_udev(dev), device);
+ if (!srcdev)
+ return EXIT_FAILURE;
+ } else
+ srcdev = dev;
+
+ if (udev_builtin_hwdb_search(dev, srcdev, subsystem, prefix, filter, test) > 0)
+ return EXIT_SUCCESS;
+ return EXIT_FAILURE;
}
/* called at udev startup and reload */
diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c
new file mode 100644
index 0000000000..ddd853594e
--- /dev/null
+++ b/src/udev/udev-builtin-keyboard.c
@@ -0,0 +1,163 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2013 Kay Sievers <kay@vrfy.org>
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/limits.h>
+#include <linux/input.h>
+
+#include "udev.h"
+
+static const struct key *keyboard_lookup_key(const char *str, unsigned int len);
+#include "keyboard-keys-from-name.h"
+#include "keyboard-keys-to-name.h"
+
+static int install_force_release(struct udev_device *dev, const unsigned int *release, unsigned int release_count) {
+ struct udev_device *atkbd;
+ const char *cur;
+ char codes[4096];
+ char *s;
+ size_t l;
+ unsigned int i;
+ int ret;
+
+ atkbd = udev_device_get_parent_with_subsystem_devtype(dev, "serio", NULL);
+ if (!atkbd)
+ return -ENODEV;
+
+ cur = udev_device_get_sysattr_value(atkbd, "force_release");
+ if (!cur)
+ return -ENODEV;
+
+ s = codes;
+ l = sizeof(codes);
+
+ /* copy current content */
+ l = strpcpy(&s, l, cur);
+
+ /* append new codes */
+ for (i = 0; i < release_count; i++)
+ l = strpcpyf(&s, l, ",%d", release[i]);
+
+ log_debug("keyboard: updating force-release list with '%s'\n", codes);
+ ret = udev_device_set_sysattr_value(atkbd, "force_release", codes);
+ if (ret < 0)
+ log_error("Error writing force-release attribute: %s", strerror(-ret));
+ return ret;
+}
+
+static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], bool test) {
+ struct udev_list_entry *entry;
+ struct {
+ unsigned int scan;
+ unsigned int key;
+ } map[1024];
+ unsigned int map_count = 0;
+ unsigned int release[1024];
+ unsigned int release_count = 0;
+
+ udev_list_entry_foreach(entry, udev_device_get_properties_list_entry(dev)) {
+ const char *key;
+ unsigned int scancode;
+ char *endptr;
+ const char *keycode;
+ const struct key *k;
+
+ key = udev_list_entry_get_name(entry);
+ if (!startswith(key, "KEYBOARD_KEY_"))
+ continue;
+
+ /* KEYBOARD_KEY_<hex scan code>=<key identifier string> */
+ scancode = strtol(key + 13, &endptr, 16);
+ if (endptr[0] != '\0') {
+ log_error("Error, unable to parse scan code from '%s'\n", key);
+ continue;
+ }
+
+ keycode = udev_list_entry_get_value(entry);
+
+ /* a leading '!' needs a force-release entry */
+ if (keycode[0] == '!') {
+ keycode++;
+
+ release[release_count] = scancode;
+ if (release_count < ELEMENTSOF(release)-1)
+ release_count++;
+
+ if (keycode[0] == '\0')
+ continue;
+ }
+
+ /* translate identifier to key code */
+ k = keyboard_lookup_key(keycode, strlen(keycode));
+ if (!k) {
+ log_error("Error, unknown key identifier '%s'\n", keycode);
+ continue;
+ }
+
+ map[map_count].scan = scancode;
+ map[map_count].key = k->id;
+ if (map_count < ELEMENTSOF(map)-1)
+ map_count++;
+ }
+
+ if (map_count > 0 || release_count > 0) {
+ const char *node;
+ int fd;
+ unsigned int i;
+
+ node = udev_device_get_devnode(dev);
+ if (!node) {
+ log_error("Error, no device node for '%s'\n", udev_device_get_syspath(dev));
+ return EXIT_FAILURE;
+ }
+
+ fd = open(udev_device_get_devnode(dev), O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
+ if (fd < 0) {
+ log_error("Error, opening device '%s': %m\n", node);
+ return EXIT_FAILURE;
+ }
+
+ /* install list of map codes */
+ for (i = 0; i < map_count; i++) {
+ log_debug("keyboard: mapping scan code %d (0x%x) to key code %d (0x%x)\n",
+ map[i].scan, map[i].scan, map[i].key, map[i].key);
+ if (ioctl(fd, EVIOCSKEYCODE, &map[i]) < 0)
+ log_error("Error calling EVIOCSKEYCODE: %m\n");
+ }
+
+ /* install list of force-release codes */
+ if (release_count > 0)
+ install_force_release(dev, release, release_count);
+
+ close(fd);
+ }
+
+ return EXIT_SUCCESS;
+}
+
+const struct udev_builtin udev_builtin_keyboard = {
+ .name = "keyboard",
+ .cmd = builtin_keyboard,
+ .help = "keyboard scan code to key mapping",
+};
diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
index 5719021e93..9ae8f08ccf 100644
--- a/src/udev/udev-builtin-net_id.c
+++ b/src/udev/udev-builtin-net_id.c
@@ -35,13 +35,16 @@
* o<index> -- on-board device index number
* s<slot>[f<function>][d<dev_id>] -- hotplug slot index number
* x<MAC> -- MAC address
- * p<bus>s<slot>[f<function>][d<dev_id>] -- PCI geographical location
- * p<bus>s<slot>[f<function>][u<port>][..][c<config>][i<interface>]
+ * [P<domain>]p<bus>s<slot>[f<function>][d<dev_id>]
+ * -- PCI geographical location
+ * [P<domain>]p<bus>s<slot>[f<function>][u<port>][..][c<config>][i<interface>]
* -- USB port number chain
*
* All multi-function PCI devices will carry the [f<function>] number in the
* device name, including the function 0 device.
*
+ * When using PCI geography, The PCI domain is only prepended when it is not 0.
+ *
* For USB devices the full chain of port numbers of hubs is composed. If the
* name gets longer than the maximum number of 15 characters, the name is not
* exported.
@@ -163,6 +166,7 @@ out:
static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
struct udev *udev = udev_device_get_udev(names->pcidev);
+ unsigned int domain;
unsigned int bus;
unsigned int slot;
unsigned int func;
@@ -178,7 +182,7 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
int hotplug_slot = 0;
int err = 0;
- if (sscanf(udev_device_get_sysname(names->pcidev), "0000:%x:%x.%d", &bus, &slot, &func) != 3)
+ if (sscanf(udev_device_get_sysname(names->pcidev), "%x:%x:%x.%d", &domain, &bus, &slot, &func) != 4)
return -ENOENT;
/* kernel provided multi-device index */
@@ -188,7 +192,10 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
/* compose a name based on the raw kernel's PCI bus, slot numbers */
s = names->pci_path;
- l = strpcpyf(&s, sizeof(names->pci_path), "p%ds%d", bus, slot);
+ l = sizeof(names->pci_path);
+ if (domain > 0)
+ l = strpcpyf(&s, l, "P%d", domain);
+ l = strpcpyf(&s, l, "p%ds%d", bus, slot);
if (func > 0 || is_pci_multifunction(names->pcidev))
l = strpcpyf(&s, l, "f%d", func);
if (dev_id > 0)
@@ -236,7 +243,10 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
if (hotplug_slot > 0) {
s = names->pci_slot;
- l = strpcpyf(&s, sizeof(names->pci_slot), "s%d", hotplug_slot);
+ l = sizeof(names->pci_slot);
+ if (domain > 0)
+ l = strpcpyf(&s, l, "P%d", domain);
+ l = strpcpyf(&s, l, "s%d", hotplug_slot);
if (func > 0 || is_pci_multifunction(names->pcidev))
l = strpcpyf(&s, l, "f%d", func);
if (dev_id > 0)
@@ -386,7 +396,7 @@ static int ieee_oui(struct udev_device *dev, struct netnames *names, bool test)
snprintf(str, sizeof(str), "OUI:%02X%02X%02X%02X%02X%02X",
names->mac[0], names->mac[1], names->mac[2],
names->mac[3], names->mac[4], names->mac[5]);
- udev_builtin_hwdb_lookup(dev, str, test);
+ udev_builtin_hwdb_lookup(dev, NULL, str, NULL, test);
return 0;
}
diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
index da0273197b..0659967c68 100644
--- a/src/udev/udev-builtin-path_id.c
+++ b/src/udev/udev-builtin-path_id.c
@@ -531,6 +531,7 @@ static int builtin_path_id(struct udev_device *dev, int argc, char *argv[], bool
} else if (streq(subsys, "scm")) {
path_prepend(&path, "scm-%s", udev_device_get_sysname(parent));
parent = skip_subsystem(parent, "scm");
+ some_transport = true;
}
parent = udev_device_get_parent(parent);
diff --git a/src/udev/udev-builtin.c b/src/udev/udev-builtin.c
index c7d431988d..6b3a518c2e 100644
--- a/src/udev/udev-builtin.c
+++ b/src/udev/udev-builtin.c
@@ -39,6 +39,7 @@ static const struct udev_builtin *builtins[] = {
#endif
[UDEV_BUILTIN_HWDB] = &udev_builtin_hwdb,
[UDEV_BUILTIN_INPUT_ID] = &udev_builtin_input_id,
+ [UDEV_BUILTIN_KEYBOARD] = &udev_builtin_keyboard,
#ifdef HAVE_KMOD
[UDEV_BUILTIN_KMOD] = &udev_builtin_kmod,
#endif
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
index 7a4fb70258..6f8b127872 100644
--- a/src/udev/udev-rules.c
+++ b/src/udev/udev-rules.c
@@ -33,6 +33,8 @@
#include "path-util.h"
#include "conf-files.h"
#include "strbuf.h"
+#include "strv.h"
+#include "util.h"
#define PREALLOC_TOKEN 2048
@@ -152,9 +154,9 @@ enum token_type {
TK_A_OWNER_ID, /* uid_t */
TK_A_GROUP_ID, /* gid_t */
TK_A_MODE_ID, /* mode_t */
+ TK_A_TAG, /* val */
TK_A_STATIC_NODE, /* val */
TK_A_ENV, /* val, attr */
- TK_A_TAG, /* val */
TK_A_NAME, /* val */
TK_A_DEVLINK, /* val */
TK_A_ATTR, /* val, attr */
@@ -1065,8 +1067,28 @@ static int add_rule(struct udev_rules *rules, char *line,
char *value;
enum operation_type op;
- if (get_key(rules->udev, &linepos, &key, &op, &value) != 0)
+ if (get_key(rules->udev, &linepos, &key, &op, &value) != 0) {
+ /* Avoid erroring on trailing whitespace. This is probably rare
+ * so save the work for the error case instead of always trying
+ * to strip the trailing whitespace with strstrip(). */
+ while (isblank(*linepos))
+ linepos++;
+
+ /* If we aren't at the end of the line, this is a parsing error.
+ * Make a best effort to describe where the problem is. */
+ if (*linepos != '\n') {
+ char buf[2] = {linepos[1]};
+ _cleanup_free_ char *tmp;
+
+ tmp = cescape(buf);
+ log_error("invalid key/value pair in file %s on line %u,"
+ "starting at character %tu ('%s')\n",
+ filename, lineno, linepos - line + 1, tmp);
+ if (linepos[1] == '#')
+ log_info("hint: comments can only start at beginning of line");
+ }
break;
+ }
if (streq(key, "ACTION")) {
if (op > OP_MATCH_MAX) {
@@ -1614,7 +1636,7 @@ struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names)
}
strv_uniq(rules->dirs);
- rules->dirs_ts_usec = calloc(strv_length(rules->dirs), sizeof(long long));
+ rules->dirs_ts_usec = calloc(strv_length(rules->dirs), sizeof(usec_t));
if(!rules->dirs_ts_usec)
return udev_rules_unref(rules);
udev_rules_check_timestamp(rules);
@@ -2496,16 +2518,21 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
}
}
-void udev_rules_apply_static_dev_perms(struct udev_rules *rules)
+int udev_rules_apply_static_dev_perms(struct udev_rules *rules)
{
struct token *cur;
struct token *rule;
uid_t uid = 0;
gid_t gid = 0;
mode_t mode = 0;
+ _cleanup_strv_free_ char **tags = NULL;
+ char **t;
+ FILE *f = NULL;
+ _cleanup_free_ char *path = NULL;
+ int r = 0;
if (rules->tokens == NULL)
- return;
+ return 0;
cur = &rules->tokens[0];
rule = cur;
@@ -2522,6 +2549,8 @@ void udev_rules_apply_static_dev_perms(struct udev_rules *rules)
uid = 0;
gid = 0;
mode = 0;
+ strv_free(tags);
+ tags = NULL;
break;
case TK_A_OWNER_ID:
uid = cur->key.uid;
@@ -2532,18 +2561,56 @@ void udev_rules_apply_static_dev_perms(struct udev_rules *rules)
case TK_A_MODE_ID:
mode = cur->key.mode;
break;
+ case TK_A_TAG:
+ r = strv_extend(&tags, rules_str(rules, cur->key.value_off));
+ if (r < 0)
+ goto finish;
+
+ break;
case TK_A_STATIC_NODE: {
- char filename[UTIL_PATH_SIZE];
+ char device_node[UTIL_PATH_SIZE];
+ char tags_dir[UTIL_PATH_SIZE];
+ char tag_symlink[UTIL_PATH_SIZE];
struct stat stats;
/* we assure, that the permissions tokens are sorted before the static token */
- if (mode == 0 && uid == 0 && gid == 0)
+ if (mode == 0 && uid == 0 && gid == 0 && tags == NULL)
goto next;
- strscpyl(filename, sizeof(filename), "/dev/", rules_str(rules, cur->key.value_off), NULL);
- if (stat(filename, &stats) != 0)
+ strscpyl(device_node, sizeof(device_node), "/dev/", rules_str(rules, cur->key.value_off), NULL);
+ if (stat(device_node, &stats) != 0)
goto next;
if (!S_ISBLK(stats.st_mode) && !S_ISCHR(stats.st_mode))
goto next;
+
+ if (tags) {
+ /* Export the tags to a directory as symlinks, allowing otherwise dead nodes to be tagged */
+
+ STRV_FOREACH(t, tags) {
+ _cleanup_free_ char *unescaped_filename = NULL;
+
+ strscpyl(tags_dir, sizeof(tags_dir), "/run/udev/static_node-tags/", *t, "/", NULL);
+ r = mkdir_p(tags_dir, 0755);
+ if (r < 0) {
+ log_error("failed to create %s: %s\n", tags_dir, strerror(-r));
+ return r;
+ }
+
+ unescaped_filename = xescape(rules_str(rules, cur->key.value_off), "/.");
+
+ strscpyl(tag_symlink, sizeof(tag_symlink), tags_dir, unescaped_filename, NULL);
+ r = symlink(device_node, tag_symlink);
+ if (r < 0 && errno != EEXIST) {
+ log_error("failed to create symlink %s -> %s: %s\n", tag_symlink, device_node, strerror(errno));
+ return -errno;
+ } else
+ r = 0;
+ }
+ }
+
+ /* don't touch the permissions if only the tags were set */
+ if (mode == 0 && uid == 0 && gid == 0)
+ goto next;
+
if (mode == 0) {
if (gid > 0)
mode = 0660;
@@ -2551,20 +2618,28 @@ void udev_rules_apply_static_dev_perms(struct udev_rules *rules)
mode = 0600;
}
if (mode != (stats.st_mode & 01777)) {
- chmod(filename, mode);
- log_debug("chmod '%s' %#o\n", filename, mode);
+ r = chmod(device_node, mode);
+ if (r < 0) {
+ log_error("failed to chmod '%s' %#o\n", device_node, mode);
+ return -errno;
+ } else
+ log_debug("chmod '%s' %#o\n", device_node, mode);
}
if ((uid != 0 && uid != stats.st_uid) || (gid != 0 && gid != stats.st_gid)) {
- chown(filename, uid, gid);
- log_debug("chown '%s' %u %u\n", filename, uid, gid);
+ r = chown(device_node, uid, gid);
+ if (r < 0) {
+ log_error("failed to chown '%s' %u %u \n", device_node, uid, gid);
+ return -errno;
+ } else
+ log_debug("chown '%s' %u %u\n", device_node, uid, gid);
}
- utimensat(AT_FDCWD, filename, NULL, 0);
+ utimensat(AT_FDCWD, device_node, NULL, 0);
break;
}
case TK_END:
- return;
+ goto finish;
}
cur++;
@@ -2574,4 +2649,18 @@ next:
cur = rule + rule->rule.token_count;
continue;
}
+
+finish:
+ if (f) {
+ fflush(f);
+ fchmod(fileno(f), 0644);
+ if (ferror(f) || rename(path, "/run/udev/static_node-tags") < 0) {
+ r = -errno;
+ unlink("/run/udev/static_node-tags");
+ unlink(path);
+ }
+ fclose(f);
+ }
+
+ return r;
}
diff --git a/src/udev/udev.h b/src/udev/udev.h
index caec5f0a5d..839592680b 100644
--- a/src/udev/udev.h
+++ b/src/udev/udev.h
@@ -72,7 +72,7 @@ struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names);
struct udev_rules *udev_rules_unref(struct udev_rules *rules);
bool udev_rules_check_timestamp(struct udev_rules *rules);
int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event, const sigset_t *sigmask);
-void udev_rules_apply_static_dev_perms(struct udev_rules *rules);
+int udev_rules_apply_static_dev_perms(struct udev_rules *rules);
/* udev-event.c */
struct udev_event *udev_event_new(struct udev_device *dev);
@@ -145,6 +145,7 @@ enum udev_builtin_cmd {
#endif
UDEV_BUILTIN_HWDB,
UDEV_BUILTIN_INPUT_ID,
+ UDEV_BUILTIN_KEYBOARD,
#ifdef HAVE_KMOD
UDEV_BUILTIN_KMOD,
#endif
@@ -174,6 +175,7 @@ extern const struct udev_builtin udev_builtin_firmware;
#endif
extern const struct udev_builtin udev_builtin_hwdb;
extern const struct udev_builtin udev_builtin_input_id;
+extern const struct udev_builtin udev_builtin_keyboard;
#ifdef HAVE_KMOD
extern const struct udev_builtin udev_builtin_kmod;
#endif
@@ -190,7 +192,8 @@ int udev_builtin_run(struct udev_device *dev, enum udev_builtin_cmd cmd, const c
void udev_builtin_list(struct udev *udev);
bool udev_builtin_validate(struct udev *udev);
int udev_builtin_add_property(struct udev_device *dev, bool test, const char *key, const char *val);
-int udev_builtin_hwdb_lookup(struct udev_device *dev, const char *modalias, bool test);
+int udev_builtin_hwdb_lookup(struct udev_device *dev, const char *prefix, const char *modalias,
+ const char *filter, bool test);
/* udev logging */
void udev_main_log(struct udev *udev, int priority,
diff --git a/src/udev/udevadm-hwdb.c b/src/udev/udevadm-hwdb.c
index 3e849aaed6..d9dc73bfc1 100644
--- a/src/udev/udevadm-hwdb.c
+++ b/src/udev/udevadm-hwdb.c
@@ -21,6 +21,7 @@
#include <unistd.h>
#include <getopt.h>
#include <string.h>
+#include <ctype.h>
#include "util.h"
#include "strbuf.h"
@@ -302,8 +303,10 @@ static int64_t trie_store_nodes(struct trie_f *trie, struct trie_node *node) {
int64_t child_off;
child_off = trie_store_nodes(trie, node->children[i].child);
- if (child_off < 0)
+ if (child_off < 0) {
+ free(children);
return child_off;
+ }
children[i].c = node->children[i].c;
children[i].child_off = htole64(child_off);
}
@@ -402,66 +405,122 @@ out:
return err;
}
-static int import_file(struct trie *trie, const char *filename) {
+static int insert_data(struct trie *trie, struct udev_list *match_list,
+ char *line, const char *filename) {
+ char *value;
+ struct udev_list_entry *entry;
+
+ value = strchr(line, '=');
+ if (!value) {
+ log_error("Error, key/value pair expected but got '%s' in '%s':\n", line, filename);
+ return -EINVAL;
+ }
+
+ value[0] = '\0';
+ value++;
+
+ if (line[0] == '\0' || value[0] == '\0') {
+ log_error("Error, empty key or value '%s' in '%s':\n", line, filename);
+ return -EINVAL;
+ }
+
+ udev_list_entry_foreach(entry, udev_list_get_entry(match_list))
+ trie_insert(trie, trie->root, udev_list_entry_get_name(entry), line, value);
+
+ return 0;
+}
+
+static int import_file(struct udev *udev, struct trie *trie, const char *filename) {
+ enum {
+ HW_MATCH,
+ HW_DATA,
+ HW_NONE,
+ } state = HW_NONE;
FILE *f;
char line[LINE_MAX];
- char match[LINE_MAX];
- char cond[LINE_MAX];
+ struct udev_list match_list;
+
+ udev_list_init(udev, &match_list, false);
f = fopen(filename, "re");
if (f == NULL)
return -errno;
- match[0] = '\0';
- cond[0] = '\0';
while (fgets(line, sizeof(line), f)) {
size_t len;
+ char *pos;
+ /* comment line */
if (line[0] == '#')
continue;
- /* new line, new record */
- if (line[0] == '\n') {
- match[0] = '\0';
- cond[0] = '\0';
- continue;
- }
+ /* strip trailing comment */
+ pos = strchr(line, '#');
+ if (pos)
+ pos[0] = '\0';
- /* remove newline */
+ /* strip trailing whitespace */
len = strlen(line);
- if (len < 2)
- continue;
- line[len-1] = '\0';
+ while (len > 0 && isspace(line[len-1]))
+ len--;
+ line[len] = '\0';
+
+ switch (state) {
+ case HW_NONE:
+ if (len == 0)
+ break;
+
+ if (line[0] == ' ') {
+ log_error("Error, MATCH expected but got '%s' in '%s':\n", line, filename);
+ break;
+ }
- /* start of new record */
- if (match[0] == '\0') {
- strcpy(match, line);
- cond[0] = '\0';
- continue;
- }
+ /* start of record, first match */
+ state = HW_MATCH;
+ udev_list_entry_add(&match_list, line, NULL);
+ break;
- if (line[0] == '+') {
- strcpy(cond, line);
- continue;
- }
+ case HW_MATCH:
+ if (len == 0) {
+ log_error("Error, DATA expected but got empty line in '%s':\n", filename);
+ state = HW_NONE;
+ udev_list_cleanup(&match_list);
+ break;
+ }
- /* TODO: support +; skip the entire record until we support it */
- if (cond[0] != '\0')
- continue;
+ /* another match */
+ if (line[0] != ' ') {
+ udev_list_entry_add(&match_list, line, NULL);
+ break;
+ }
- /* value lines */
- if (line[0] == ' ') {
- char *value;
+ /* first data */
+ state = HW_DATA;
+ insert_data(trie, &match_list, line, filename);
+ break;
- value = strchr(line, '=');
- if (!value)
- continue;
- value[0] = '\0';
- value++;
- trie_insert(trie, trie->root, match, line, value);
- }
+ case HW_DATA:
+ /* end of record */
+ if (len == 0) {
+ state = HW_NONE;
+ udev_list_cleanup(&match_list);
+ break;
+ }
+
+ if (line[0] != ' ') {
+ log_error("Error, DATA expected but got '%s' in '%s':\n", line, filename);
+ state = HW_NONE;
+ udev_list_cleanup(&match_list);
+ break;
+ }
+
+ insert_data(trie, &match_list, line, filename);
+ break;
+ };
}
+
fclose(f);
+ udev_list_cleanup(&match_list);
return 0;
}
@@ -549,7 +608,7 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) {
}
STRV_FOREACH(f, files) {
log_debug("reading file '%s'", *f);
- import_file(trie, *f);
+ import_file(udev, trie, *f);
}
strv_free(files);
diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c
index 002876594f..2ee59fe075 100644
--- a/src/udev/udevadm-info.c
+++ b/src/udev/udevadm-info.c
@@ -251,6 +251,12 @@ static void cleanup_db(struct udev *udev)
closedir(dir);
}
+ dir = opendir("/run/udev/static_node-tags");
+ if (dir != NULL) {
+ cleanup_dir(dir, 0, 2);
+ closedir(dir);
+ }
+
dir = opendir("/run/udev/watch");
if (dir != NULL) {
cleanup_dir(dir, 0, 1);
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index 7d13b4f532..7c6c5d6a87 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -812,77 +812,6 @@ static void handle_signal(struct udev *udev, int signo)
}
}
-static void static_dev_create_from_modules(struct udev *udev)
-{
- struct utsname kernel;
- char modules[UTIL_PATH_SIZE];
- char buf[4096];
- FILE *f;
-
- if (uname(&kernel) < 0) {
- log_error("uname failed: %m");
- return;
- }
-
- strscpyl(modules, sizeof(modules), ROOTPREFIX "/lib/modules/", kernel.release, "/modules.devname", NULL);
- f = fopen(modules, "re");
- if (f == NULL)
- return;
-
- while (fgets(buf, sizeof(buf), f) != NULL) {
- char *s;
- const char *modname;
- const char *devname;
- const char *devno;
- int maj, min;
- char type;
- mode_t mode;
- char filename[UTIL_PATH_SIZE];
-
- if (buf[0] == '#')
- continue;
-
- modname = buf;
- s = strchr(modname, ' ');
- if (s == NULL)
- continue;
- s[0] = '\0';
-
- devname = &s[1];
- s = strchr(devname, ' ');
- if (s == NULL)
- continue;
- s[0] = '\0';
-
- devno = &s[1];
- s = strchr(devno, ' ');
- if (s == NULL)
- s = strchr(devno, '\n');
- if (s != NULL)
- s[0] = '\0';
- if (sscanf(devno, "%c%u:%u", &type, &maj, &min) != 3)
- continue;
-
- mode = 0600;
- if (type == 'c')
- mode |= S_IFCHR;
- else if (type == 'b')
- mode |= S_IFBLK;
- else
- continue;
-
- strscpyl(filename, sizeof(filename), "/dev/", devname, NULL);
- mkdir_parents_label(filename, 0755);
- label_context_set(filename, mode);
- log_debug("mknod '%s' %c%u:%u\n", filename, type, maj, min);
- if (mknod(filename, mode, makedev(maj, min)) < 0 && errno == EEXIST)
- utimensat(AT_FDCWD, filename, NULL, 0);
- label_context_clear();
- }
-
- fclose(f);
-}
-
static int systemd_fds(struct udev *udev, int *rctrl, int *rnetlink)
{
int ctrl = -1, netlink = -1;
@@ -994,7 +923,10 @@ int main(int argc, char *argv[])
log_set_target(LOG_TARGET_AUTO);
log_parse_environment();
log_open();
+
udev_set_log_fn(udev, udev_main_log);
+ log_set_max_level(udev_get_log_priority(udev));
+
log_debug("version %s\n", VERSION);
label_init("/dev");
@@ -1067,7 +999,6 @@ int main(int argc, char *argv[])
mkdir("/run/udev", 0755);
dev_setup(NULL);
- static_dev_create_from_modules(udev);
/* before opening new files, make sure std{in,out,err} fds are in a sane state */
if (daemonize) {
@@ -1269,7 +1200,9 @@ int main(int argc, char *argv[])
}
log_debug("set children_max to %u\n", children_max);
- udev_rules_apply_static_dev_perms(rules);
+ rc = udev_rules_apply_static_dev_perms(rules);
+ if (rc < 0)
+ log_error("failed to apply permissions on static device nodes - %s\n", strerror(-rc));
udev_list_node_init(&event_list);
udev_list_node_init(&worker_list);
diff --git a/src/update-utmp/update-utmp.c b/src/update-utmp/update-utmp.c
index 9184025554..202aa98767 100644
--- a/src/update-utmp/update-utmp.c
+++ b/src/update-utmp/update-utmp.c
@@ -104,7 +104,7 @@ static int get_current_runlevel(Context *c) {
{ '3', SPECIAL_RUNLEVEL3_TARGET },
{ '4', SPECIAL_RUNLEVEL4_TARGET },
{ '2', SPECIAL_RUNLEVEL2_TARGET },
- { 'S', SPECIAL_RESCUE_TARGET },
+ { '1', SPECIAL_RESCUE_TARGET },
};
const char
*interface = "org.freedesktop.systemd1.Unit",
diff --git a/test/TEST-01-BASIC/test.sh b/test/TEST-01-BASIC/test.sh
index e41ed9dcfe..9b55a27a20 100755
--- a/test/TEST-01-BASIC/test.sh
+++ b/test/TEST-01-BASIC/test.sh
@@ -132,7 +132,7 @@ Description=Testsuite service
After=multi-user.target
[Service]
-ExecStart=/bin/bash -c 'set -x; systemctl --failed --no-legend --no-pager > /failed ; echo OK > /testok; while : ;do echo "testsuite service waiting for journal to move to /var/log/journal" > /dev/console ; for i in /var/log/journal/*;do [ -d "\$i" ] && echo "\$i" && break 2; done; sleep 1; done; sleep 1; exit 0;'
+ExecStart=/bin/bash -c 'set -x; ( systemctl --failed --no-legend --no-pager; systemctl status --failed ) > /failed ; echo OK > /testok; while : ;do echo "testsuite service waiting for journal to move to /var/log/journal" > /dev/console ; for i in /var/log/journal/*;do [ -d "\$i" ] && echo "\$i" && break 2; done; sleep 1; done; sleep 1; exit 0;'
Type=oneshot
EOF
@@ -190,7 +190,7 @@ EOF
# softlink mtab
ln -fs /proc/self/mounts $initdir/etc/mtab
- # install any Exec's from the service files
+ # install any Execs from the service files
egrep -ho '^Exec[^ ]*=[^ ]+' $initdir/lib/systemd/system/*.service \
| while read i; do
i=${i##Exec*=}; i=${i##-}
@@ -213,7 +213,7 @@ EOF
cp -a /etc/ld.so.conf* $initdir/etc
ldconfig -r "$initdir"
ddebug "Strip binaries"
- find "$initdir" -perm +111 -type f | xargs strip --strip-unneeded | ddebug
+ find "$initdir" -executable -not -path '*/lib/modules/*.ko' -type f | xargs strip --strip-unneeded | ddebug
# copy depmod files
inst /lib/modules/$KERNEL_VER/modules.order
diff --git a/test/TEST-02-CRYPTSETUP/test.sh b/test/TEST-02-CRYPTSETUP/test.sh
index ec714301c6..b98d23810a 100755
--- a/test/TEST-02-CRYPTSETUP/test.sh
+++ b/test/TEST-02-CRYPTSETUP/test.sh
@@ -131,7 +131,7 @@ Description=Testsuite service
After=multi-user.target
[Service]
-ExecStart=/bin/bash -c 'set -x; systemctl --failed --no-legend --no-pager > /failed ; echo OK > /testok; while : ;do systemd-cat echo "testsuite service waiting for /var/log/journal" ; echo "testsuite service waiting for journal to move to /var/log/journal" > /dev/console ; for i in /var/log/journal/*;do [ -d "\$i" ] && echo "\$i" && break 2; done; sleep 1; done; sleep 1; exit 0;'
+ExecStart=/bin/bash -c 'set -x; ( systemctl --failed --no-legend --no-pager; systemctl status --failed ) > /failed ; echo OK > /testok; while : ;do systemd-cat echo "testsuite service waiting for /var/log/journal" ; echo "testsuite service waiting for journal to move to /var/log/journal" > /dev/console ; for i in /var/log/journal/*;do [ -d "\$i" ] && echo "\$i" && break 2; done; sleep 1; done; sleep 1; exit 0;'
Type=oneshot
EOF
@@ -197,7 +197,7 @@ EOF
# softlink mtab
ln -fs /proc/self/mounts $initdir/etc/mtab
- # install any Exec's from the service files
+ # install any Execs from the service files
egrep -ho '^Exec[^ ]*=[^ ]+' $initdir/lib/systemd/system/*.service \
| while read i; do
i=${i##Exec*=}; i=${i##-}
@@ -220,7 +220,7 @@ EOF
cp -a /etc/ld.so.conf* $initdir/etc
ldconfig -r "$initdir"
ddebug "Strip binaeries"
- find "$initdir" -perm +111 -type f | xargs strip --strip-unneeded | ddebug
+ find "$initdir" -executable -not -path '*/lib/modules/*.ko' -type f | xargs strip --strip-unneeded | ddebug
# copy depmod files
inst /lib/modules/$KERNEL_VER/modules.order
diff --git a/test/TEST-03-JOBS/test.sh b/test/TEST-03-JOBS/test.sh
index 6440d1f54b..02fd8b9ce8 100755
--- a/test/TEST-03-JOBS/test.sh
+++ b/test/TEST-03-JOBS/test.sh
@@ -21,10 +21,10 @@ run_qemu() {
mkdir -p $TESTDIR/root
mount ${LOOPDEV}p1 $TESTDIR/root
[[ -e $TESTDIR/root/testok ]] && ret=0
- cp -a $TESTDIR/root/failed $TESTDIR
+ [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR
cp -a $TESTDIR/root/var/log/journal $TESTDIR
umount $TESTDIR/root
- cat $TESTDIR/failed
+ [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
ls -l $TESTDIR/journal/*/*.journal
test -s $TESTDIR/failed && ret=$(($ret+1))
return $ret
@@ -35,9 +35,9 @@ run_nspawn() {
../../systemd-nspawn -b -D $TESTDIR/nspawn-root /usr/lib/systemd/systemd
ret=1
[[ -e $TESTDIR/nspawn-root/testok ]] && ret=0
- cp -a $TESTDIR/nspawn-root/failed $TESTDIR
+ [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/nspawn-root/failed $TESTDIR
cp -a $TESTDIR/nspawn-root/var/log/journal $TESTDIR
- cat $TESTDIR/failed
+ [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
ls -l $TESTDIR/journal/*/*.journal
test -s $TESTDIR/failed && ret=$(($ret+1))
return $ret
diff --git a/test/rule-syntax-check.py b/test/rule-syntax-check.py
index b18f8780cb..ce4f5c75ad 100755
--- a/test/rule-syntax-check.py
+++ b/test/rule-syntax-check.py
@@ -4,19 +4,18 @@
# (C) 2010 Canonical Ltd.
# Author: Martin Pitt <martin.pitt@ubuntu.com>
#
-# 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
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
+
+# systemd is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
#
-# 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, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+# You should have received a copy of the GNU Lesser General Public License
+# along with systemd; If not, see <http://www.gnu.org/licenses/>.
import re
import sys
diff --git a/test/rules-test.sh b/test/rules-test.sh
index 1e224ff8b5..47d42cb3fa 100755
--- a/test/rules-test.sh
+++ b/test/rules-test.sh
@@ -3,6 +3,19 @@
#
# (C) 2010 Canonical Ltd.
# Author: Martin Pitt <martin.pitt@ubuntu.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/>.
[ -n "$srcdir" ] || srcdir=`dirname $0`/..
diff --git a/tmpfiles.d/systemd.conf b/tmpfiles.d/systemd.conf
index ee86f2ebce..b6304401fe 100644
--- a/tmpfiles.d/systemd.conf
+++ b/tmpfiles.d/systemd.conf
@@ -19,6 +19,10 @@ d /run/systemd/ask-password 0755 root root -
d /run/systemd/seats 0755 root root -
d /run/systemd/sessions 0755 root root -
d /run/systemd/users 0755 root root -
+d /run/systemd/machines 0755 root root -
d /run/systemd/shutdown 0755 root root -
-F /run/nologin 0644 - - - "System is booting up."
+F /run/nologin 0644 - - - "System is booting up. See pam_nologin(8)"
+
+m /var/log/journal 2755 root systemd-journal - -
+m /var/log/journal/%m 2755 root systemd-journal - -
diff --git a/units/.gitignore b/units/.gitignore
index 606d947634..9c65075c0a 100644
--- a/units/.gitignore
+++ b/units/.gitignore
@@ -1,3 +1,4 @@
+/systemd-backlight@.service
/halt-local.service
/rc-local.service
/systemd-hybrid-sleep.service
@@ -41,12 +42,11 @@
/systemd-remount-fs.service
/systemd-vconsole-setup.service
/systemd-shutdownd.service
-/systemd-random-seed-load.service
-/systemd-random-seed-save.service
+/systemd-random-seed.service
/systemd-initctl.service
/getty@.service
+/systemd-update-utmp.service
/systemd-update-utmp-runlevel.service
-/systemd-update-utmp-shutdown.service
/systemd-binfmt.service
/emergency.service
/systemd-udev-settle.service
@@ -58,3 +58,5 @@
/initrd-switch-root.service
/initrd-udevadm-cleanup-db.service
/systemd-nspawn@.service
+/systemd-machined.service
+/kmod-static-nodes.service
diff --git a/units/basic.target b/units/basic.target
index 6b9cfe4c97..d7c68f4e2c 100644
--- a/units/basic.target
+++ b/units/basic.target
@@ -9,6 +9,6 @@
Description=Basic System
Documentation=man:systemd.special(7)
Requires=sysinit.target
-Wants=sockets.target timers.target paths.target
-After=sysinit.target sockets.target timers.target paths.target
+Wants=sockets.target timers.target paths.target slices.target
+After=sysinit.target sockets.target timers.target paths.target slices.target
RefuseManualStart=yes
diff --git a/units/console-getty.service.m4.in b/units/console-getty.service.m4.in
index 0426050ee8..2fd9dd8478 100644
--- a/units/console-getty.service.m4.in
+++ b/units/console-getty.service.m4.in
@@ -25,10 +25,7 @@ TTYReset=yes
TTYVHangup=yes
KillMode=process
IgnoreSIGPIPE=no
-
-# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
-# terminates cleanly.
-KillSignal=SIGHUP
+SendSIGHUP=yes
[Install]
WantedBy=getty.target
diff --git a/units/console-shell.service.m4.in b/units/console-shell.service.m4.in
index dac2ac212b..3f4904a0ee 100644
--- a/units/console-shell.service.m4.in
+++ b/units/console-shell.service.m4.in
@@ -25,10 +25,7 @@ StandardOutput=inherit
StandardError=inherit
KillMode=process
IgnoreSIGPIPE=no
-
-# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
-# terminates cleanly.
-KillSignal=SIGHUP
+SendSIGHUP=yes
[Install]
WantedBy=getty.target
diff --git a/units/emergency.service.in b/units/emergency.service.in
index 442f0e0ee6..94c090f654 100644
--- a/units/emergency.service.in
+++ b/units/emergency.service.in
@@ -25,7 +25,4 @@ StandardOutput=inherit
StandardError=inherit
KillMode=process
IgnoreSIGPIPE=no
-
-# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
-# terminates cleanly.
-KillSignal=SIGHUP
+SendSIGHUP=yes
diff --git a/units/getty@.service.m4 b/units/getty@.service.m4
index 083eb97059..253da85f8e 100644
--- a/units/getty@.service.m4
+++ b/units/getty@.service.m4
@@ -20,14 +20,14 @@ After=rc-local.service
Before=getty.target
IgnoreOnIsolate=yes
-# On systems without virtual consoles, don't start any getty. (Note
+# On systems without virtual consoles, don't start any getty. Note
# that serial gettys are covered by serial-getty@.service, not this
-# unit
+# unit.
ConditionPathExists=/dev/tty0
[Service]
# the VT is cleared by TTYVTDisallocate
-ExecStart=-/sbin/agetty --noclear %I 38400 linux
+ExecStart=-/sbin/agetty --noclear %I
Type=idle
Restart=always
RestartSec=0
@@ -38,14 +38,11 @@ TTYVHangup=yes
TTYVTDisallocate=yes
KillMode=process
IgnoreSIGPIPE=no
+SendSIGHUP=yes
# Unset locale for the console getty since the console has problems
# displaying some internationalized messages.
Environment=LANG= LANGUAGE= LC_CTYPE= LC_NUMERIC= LC_TIME= LC_COLLATE= LC_MONETARY= LC_MESSAGES= LC_PAPER= LC_NAME= LC_ADDRESS= LC_TELEPHONE= LC_MEASUREMENT= LC_IDENTIFICATION=
-# Some login implementations ignore SIGTERM, so we send SIGHUP
-# instead, to ensure that login terminates cleanly.
-KillSignal=SIGHUP
-
[Install]
-Alias=getty.target.wants/getty@tty1.service
+WantedBy=getty.target
diff --git a/units/initrd-fs.target b/units/initrd-fs.target
index 7578b8824b..866f0d0257 100644
--- a/units/initrd-fs.target
+++ b/units/initrd-fs.target
@@ -12,3 +12,5 @@ OnFailure=emergency.target
OnFailureIsolate=yes
ConditionPathExists=/etc/initrd-release
After=initrd-parse-etc.service
+DefaultDependencies=no
+Conflicts=shutdown.target
diff --git a/units/initrd-root-fs.target b/units/initrd-root-fs.target
index cd189f0296..d0b9863000 100644
--- a/units/initrd-root-fs.target
+++ b/units/initrd-root-fs.target
@@ -11,3 +11,5 @@ Documentation=man:systemd.special(7)
ConditionPathExists=/etc/initrd-release
OnFailure=emergency.target
OnFailureIsolate=yes
+DefaultDependencies=no
+Conflicts=shutdown.target
diff --git a/units/kmod-static-nodes.service.in b/units/kmod-static-nodes.service.in
new file mode 100644
index 0000000000..ff4017bada
--- /dev/null
+++ b/units/kmod-static-nodes.service.in
@@ -0,0 +1,19 @@
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Create list of required static device nodes for the current kernel
+DefaultDependencies=no
+Before=sysinit.target systemd-tmpfiles-setup-dev.service
+ConditionCapability=CAP_MKNOD
+ConditionPathExists=/lib/modules/%v/modules.devname
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStartPre=@MKDIR_P@ /run/tmpfiles.d
+ExecStart=@KMOD@ static-nodes --format=tmpfiles --output=/run/tmpfiles.d/kmod.conf
diff --git a/units/local-fs.target b/units/local-fs.target
index 18c3d74f18..8f06ed6cab 100644
--- a/units/local-fs.target
+++ b/units/local-fs.target
@@ -9,5 +9,7 @@
Description=Local File Systems
Documentation=man:systemd.special(7)
After=local-fs-pre.target
+DefaultDependencies=no
+Conflicts=shutdown.target
OnFailure=emergency.target
OnFailureIsolate=no
diff --git a/units/machine.slice b/units/machine.slice
new file mode 100644
index 0000000000..3d40dfd73b
--- /dev/null
+++ b/units/machine.slice
@@ -0,0 +1,11 @@
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Virtual Machine and Container Slice
+Documentation=man:systemd.special(7)
+Before=slices.target
diff --git a/units/remote-fs.target b/units/remote-fs.target
index 09213e8fca..43ffa5c107 100644
--- a/units/remote-fs.target
+++ b/units/remote-fs.target
@@ -9,6 +9,8 @@
Description=Remote File Systems
Documentation=man:systemd.special(7)
After=remote-fs-pre.target
+DefaultDependencies=no
+Conflicts=shutdown.target
[Install]
WantedBy=multi-user.target
diff --git a/units/rescue.service.m4.in b/units/rescue.service.m4.in
index 269797a12e..552ef8981b 100644
--- a/units/rescue.service.m4.in
+++ b/units/rescue.service.m4.in
@@ -25,7 +25,5 @@ StandardInput=tty-force
StandardOutput=inherit
StandardError=inherit
KillMode=process
-
-# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
-# terminates cleanly.
-KillSignal=SIGHUP
+IgnoreSIGPIPE=no
+SendSIGHUP=yes
diff --git a/units/serial-getty@.service.m4 b/units/serial-getty@.service.m4
index 60d7737b74..e32c6b7aff 100644
--- a/units/serial-getty@.service.m4
+++ b/units/serial-getty@.service.m4
@@ -22,7 +22,7 @@ Before=getty.target
IgnoreOnIsolate=yes
[Service]
-ExecStart=-/sbin/agetty -s %I 115200,38400,9600 vt102
+ExecStart=-/sbin/agetty --keep-baud %I 115200,38400,9600
Type=idle
Restart=always
RestartSec=0
@@ -32,7 +32,4 @@ TTYReset=yes
TTYVHangup=yes
KillMode=process
IgnoreSIGPIPE=no
-
-# Some login implementations ignore SIGTERM, so we send SIGHUP
-# instead, to ensure that login terminates cleanly.
-KillSignal=SIGHUP
+SendSIGHUP=yes
diff --git a/units/slices.target b/units/slices.target
new file mode 100644
index 0000000000..a29310c047
--- /dev/null
+++ b/units/slices.target
@@ -0,0 +1,12 @@
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Slices
+Documentation=man:systemd.special(7)
+Wants=-.slice system.slice
+After=-.slice system.slice
diff --git a/units/systemd-random-seed-save.service.in b/units/system.slice
index 3444d4ce70..c0e3df9d0f 100644
--- a/units/systemd-random-seed-save.service.in
+++ b/units/system.slice
@@ -6,13 +6,9 @@
# (at your option) any later version.
[Unit]
-Description=Save Random Seed
-Documentation=man:systemd-random-seed-load.service(8) man:random(4)
+Description=System Slice
+Documentation=man:systemd.special(7)
DefaultDependencies=no
-RequiresMountsFor=@RANDOM_SEED@
-After=systemd-remount-fs.service systemd-random-seed-load.service
-Before=final.target
-
-[Service]
-Type=oneshot
-ExecStart=@rootlibexecdir@/systemd-random-seed save
+Before=slices.target
+Wants=-.slice
+After=-.slice
diff --git a/units/systemd-backlight@.service.in b/units/systemd-backlight@.service.in
new file mode 100644
index 0000000000..b0e75db39e
--- /dev/null
+++ b/units/systemd-backlight@.service.in
@@ -0,0 +1,21 @@
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Load/Save Screen Backlight Brightness of %I
+Documentation=man:systemd-backlight@.service(8)
+DefaultDependencies=no
+RequiresMountsFor=/var/lib/backlight
+Conflicts=shutdown.target
+After=systemd-readahead-collect.service systemd-readahead-replay.service systemd-remount-fs.service
+Before=sysinit.target shutdown.target
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=@rootlibexecdir@/systemd-backlight load %I
+ExecStop=@rootlibexecdir@/systemd-backlight save %I
diff --git a/units/systemd-fsck-root.service.in b/units/systemd-fsck-root.service.in
index ef5123feb8..4388314079 100644
--- a/units/systemd-fsck-root.service.in
+++ b/units/systemd-fsck-root.service.in
@@ -7,18 +7,16 @@
[Unit]
Description=File System Check on Root Device
-Documentation=man:systemd-fsck@.service(8)
+Documentation=man:systemd-fsck-root.service(8)
DefaultDependencies=no
After=systemd-readahead-collect.service systemd-readahead-replay.service
Before=local-fs.target shutdown.target
-# Dracut informs us with this flag file if the root fsck was already run
-ConditionPathExists=!/run/initramfs/root-fsck
ConditionPathIsReadWrite=!/
[Service]
Type=oneshot
-RemainAfterExit=no
+RemainAfterExit=yes
ExecStart=@rootlibexecdir@/systemd-fsck
StandardOutput=journal+console
FsckPassNo=1
diff --git a/units/systemd-fsck@.service.in b/units/systemd-fsck@.service.in
index b3c71eb250..e229cdcb83 100644
--- a/units/systemd-fsck@.service.in
+++ b/units/systemd-fsck@.service.in
@@ -15,7 +15,7 @@ Before=shutdown.target
[Service]
Type=oneshot
-RemainAfterExit=no
+RemainAfterExit=yes
ExecStart=@rootlibexecdir@/systemd-fsck %f
StandardOutput=journal+console
TimeoutSec=0
diff --git a/units/systemd-journald.socket b/units/systemd-journald.socket
index 4f0619d258..fbeb10baae 100644
--- a/units/systemd-journald.socket
+++ b/units/systemd-journald.socket
@@ -12,7 +12,7 @@ DefaultDependencies=no
Before=sockets.target
# Mount and swap units need this. If this socket unit is removed by an
-# isolate request the mount and and swap units would be removed too,
+# isolate request the mount and swap units would be removed too,
# hence let's exclude this from isolate requests.
IgnoreOnIsolate=yes
diff --git a/units/systemd-logind.service.in b/units/systemd-logind.service.in
index cf3c430b7f..31b5cd011f 100644
--- a/units/systemd-logind.service.in
+++ b/units/systemd-logind.service.in
@@ -8,15 +8,17 @@
[Unit]
Description=Login Service
Documentation=man:systemd-logind.service(8) man:logind.conf(5)
+Documentation=http://www.freedesktop.org/wiki/Software/systemd/logind
Documentation=http://www.freedesktop.org/wiki/Software/systemd/multiseat
-After=nss-user-lookup.target
+Wants=user.slice
+After=nss-user-lookup.target user.slice
[Service]
ExecStart=@rootlibexecdir@/systemd-logind
Restart=always
RestartSec=0
BusName=org.freedesktop.login1
-CapabilityBoundingSet=CAP_AUDIT_CONTROL CAP_CHOWN CAP_KILL CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_FOWNER CAP_SYS_TTY_CONFIG
+CapabilityBoundingSet=CAP_SYS_ADMIN CAP_AUDIT_CONTROL CAP_CHOWN CAP_KILL CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_FOWNER CAP_SYS_TTY_CONFIG
# Increase the default a bit in order to allow many simultaneous
# logins since we keep one fd open per session.
diff --git a/units/systemd-machined.service.in b/units/systemd-machined.service.in
new file mode 100644
index 0000000000..26bfe03537
--- /dev/null
+++ b/units/systemd-machined.service.in
@@ -0,0 +1,20 @@
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Virtual Machine and Container Registration Service
+Documentation=man:systemd-machined.service(8)
+Documentation=http://www.freedesktop.org/wiki/Software/systemd/machined
+Wants=machine.slice
+After=machine.slice
+
+[Service]
+ExecStart=@rootlibexecdir@/systemd-machined
+Restart=always
+RestartSec=0
+BusName=org.freedesktop.machine1
+CapabilityBoundingSet=CAP_KILL
diff --git a/units/systemd-nspawn@.service.in b/units/systemd-nspawn@.service.in
index c0d5886f88..eca62e3b17 100644
--- a/units/systemd-nspawn@.service.in
+++ b/units/systemd-nspawn@.service.in
@@ -11,7 +11,6 @@ Documentation=man:systemd-nspawn(1)
[Service]
ExecStart=@bindir@/systemd-nspawn -bjD /var/lib/container/%i
-ControlGroup=%R/machine/%i.nspawn cpu:/
Type=notify
[Install]
diff --git a/units/systemd-random-seed-load.service.in b/units/systemd-random-seed.service.in
index e9156ef086..1879b2f24c 100644
--- a/units/systemd-random-seed-load.service.in
+++ b/units/systemd-random-seed.service.in
@@ -6,13 +6,16 @@
# (at your option) any later version.
[Unit]
-Description=Load Random Seed
-Documentation=man:systemd-random-seed-load.service(8) man:random(4)
+Description=Load/Save Random Seed
+Documentation=man:systemd-random-seed.service(8) man:random(4)
DefaultDependencies=no
RequiresMountsFor=@RANDOM_SEED@
+Conflicts=shutdown.target
After=systemd-readahead-collect.service systemd-readahead-replay.service systemd-remount-fs.service
-Before=sysinit.target final.target
+Before=sysinit.target shutdown.target
[Service]
Type=oneshot
+RemainAfterExit=yes
ExecStart=@rootlibexecdir@/systemd-random-seed load
+ExecStop=@rootlibexecdir@/systemd-random-seed save
diff --git a/units/systemd-sysctl.service.in b/units/systemd-sysctl.service.in
index 45e1ceb25c..5baf22c183 100644
--- a/units/systemd-sysctl.service.in
+++ b/units/systemd-sysctl.service.in
@@ -13,7 +13,6 @@ Conflicts=shutdown.target
After=systemd-readahead-collect.service systemd-readahead-replay.service
Before=sysinit.target shutdown.target
ConditionPathIsReadWrite=/proc/sys/
-ConditionPathExists=|/etc/sysctl.conf
ConditionDirectoryNotEmpty=|/lib/sysctl.d
ConditionDirectoryNotEmpty=|/usr/lib/sysctl.d
ConditionDirectoryNotEmpty=|/usr/local/lib/sysctl.d
diff --git a/units/systemd-tmpfiles-setup-dev.service.in b/units/systemd-tmpfiles-setup-dev.service.in
index f029285bc0..579e7c6a4f 100644
--- a/units/systemd-tmpfiles-setup-dev.service.in
+++ b/units/systemd-tmpfiles-setup-dev.service.in
@@ -9,9 +9,10 @@
Description=Create static device nodes in /dev
Documentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8)
DefaultDependencies=no
-Before=sysinit.target systemd-udevd.service
+Before=sysinit.target local-fs-pre.target systemd-udevd.service
ConditionCapability=CAP_MKNOD
[Service]
Type=oneshot
+RemainAfterExit=yes
ExecStart=@rootbindir@/systemd-tmpfiles --prefix=/dev --create
diff --git a/units/systemd-tmpfiles-setup.service.in b/units/systemd-tmpfiles-setup.service.in
index 4a3441c3ac..6f98063744 100644
--- a/units/systemd-tmpfiles-setup.service.in
+++ b/units/systemd-tmpfiles-setup.service.in
@@ -10,6 +10,7 @@ Description=Recreate Volatile Files and Directories
Documentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8)
DefaultDependencies=no
Wants=local-fs.target
+Conflicts=shutdown.target
After=systemd-readahead-collect.service systemd-readahead-replay.service local-fs.target
Before=sysinit.target shutdown.target
ConditionDirectoryNotEmpty=|/usr/lib/tmpfiles.d
@@ -20,4 +21,4 @@ ConditionDirectoryNotEmpty=|/run/tmpfiles.d
[Service]
Type=oneshot
RemainAfterExit=yes
-ExecStart=@rootbindir@/systemd-tmpfiles --create --remove
+ExecStart=@rootbindir@/systemd-tmpfiles --create --remove --exclude-prefix=/dev
diff --git a/units/systemd-udev-settle.service.in b/units/systemd-udev-settle.service.in
index 037dd9a872..0817803a39 100644
--- a/units/systemd-udev-settle.service.in
+++ b/units/systemd-udev-settle.service.in
@@ -16,7 +16,7 @@ DefaultDependencies=no
Wants=systemd-udevd.service
After=systemd-udev-trigger.service
Before=sysinit.target
-ConditionCapability=CAP_MKNOD
+ConditionPathIsReadWrite=/sys
[Service]
Type=oneshot
diff --git a/units/systemd-udev-trigger.service.in b/units/systemd-udev-trigger.service.in
index 604c369a1b..0c33909cee 100644
--- a/units/systemd-udev-trigger.service.in
+++ b/units/systemd-udev-trigger.service.in
@@ -12,7 +12,7 @@ DefaultDependencies=no
Wants=systemd-udevd.service
After=systemd-udevd-kernel.socket systemd-udevd-control.socket
Before=sysinit.target
-ConditionCapability=CAP_MKNOD
+ConditionPathIsReadWrite=/sys
[Service]
Type=oneshot
diff --git a/units/systemd-udevd-control.socket b/units/systemd-udevd-control.socket
index ca17102dfa..8330a1c035 100644
--- a/units/systemd-udevd-control.socket
+++ b/units/systemd-udevd-control.socket
@@ -10,7 +10,7 @@ Description=udev Control Socket
Documentation=man:systemd-udevd.service(8) man:udev(7)
DefaultDependencies=no
Before=sockets.target
-ConditionCapability=CAP_MKNOD
+ConditionPathIsReadWrite=/sys
[Socket]
Service=systemd-udevd.service
diff --git a/units/systemd-udevd-kernel.socket b/units/systemd-udevd-kernel.socket
index 4b8a5b0fb5..39b7809204 100644
--- a/units/systemd-udevd-kernel.socket
+++ b/units/systemd-udevd-kernel.socket
@@ -10,7 +10,7 @@ Description=udev Kernel Socket
Documentation=man:systemd-udevd.service(8) man:udev(7)
DefaultDependencies=no
Before=sockets.target
-ConditionCapability=CAP_MKNOD
+ConditionPathIsReadWrite=/sys
[Socket]
Service=systemd-udevd.service
diff --git a/units/systemd-udevd.service.in b/units/systemd-udevd.service.in
index ddef423625..99f51304e4 100644
--- a/units/systemd-udevd.service.in
+++ b/units/systemd-udevd.service.in
@@ -11,8 +11,8 @@ Documentation=man:systemd-udevd.service(8) man:udev(7)
DefaultDependencies=no
Wants=systemd-udevd-control.socket systemd-udevd-kernel.socket
After=systemd-udevd-control.socket systemd-udevd-kernel.socket
-Before=sysinit.target local-fs-pre.target
-ConditionCapability=CAP_MKNOD
+Before=sysinit.target
+ConditionPathIsReadWrite=/sys
[Service]
Type=notify
diff --git a/units/systemd-update-utmp-runlevel.service.in b/units/systemd-update-utmp-runlevel.service.in
index 27fae2cd02..99783e2e69 100644
--- a/units/systemd-update-utmp-runlevel.service.in
+++ b/units/systemd-update-utmp-runlevel.service.in
@@ -7,12 +7,14 @@
[Unit]
Description=Update UTMP about System Runlevel Changes
-Documentation=man:systemd-update-utmp-runlevel.service(8) man:utmp(5)
+Documentation=man:systemd-update-utmp.service(8) man:utmp(5)
DefaultDependencies=no
RequiresMountsFor=/var/log/wtmp
-After=systemd-remount-fs.service systemd-tmpfiles-setup.service auditd.service
+Conflicts=shutdown.target
+Requisite=systemd-update-utmp.service
+After=systemd-update-utmp.service
After=runlevel1.target runlevel2.target runlevel3.target runlevel4.target runlevel5.target
-Before=final.target
+Before=shutdown.target
[Service]
Type=oneshot
diff --git a/units/systemd-update-utmp-shutdown.service.in b/units/systemd-update-utmp-shutdown.service.in
deleted file mode 100644
index aa93562f02..0000000000
--- a/units/systemd-update-utmp-shutdown.service.in
+++ /dev/null
@@ -1,19 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-
-[Unit]
-Description=Update UTMP about System Shutdown
-Documentation=man:systemd-update-utmp-runlevel.service(8) man:utmp(5)
-DefaultDependencies=no
-RequiresMountsFor=/var/log/wtmp
-After=systemd-remount-fs.service systemd-tmpfiles-setup.service auditd.service
-After=systemd-update-utmp-runlevel.service
-Before=final.target
-
-[Service]
-Type=oneshot
-ExecStart=@rootlibexecdir@/systemd-update-utmp shutdown
diff --git a/units/systemd-update-utmp.service.in b/units/systemd-update-utmp.service.in
new file mode 100644
index 0000000000..e7c20a5ead
--- /dev/null
+++ b/units/systemd-update-utmp.service.in
@@ -0,0 +1,21 @@
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Update UTMP about System Reboot/Shutdown
+Documentation=man:systemd-update-utmp.service(8) man:utmp(5)
+DefaultDependencies=no
+RequiresMountsFor=/var/log/wtmp
+Conflicts=shutdown.target
+After=systemd-readahead-collect.service systemd-readahead-replay.service systemd-remount-fs.service systemd-tmpfiles-setup.service auditd.service
+Before=sysinit.target shutdown.target
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=@rootlibexecdir@/systemd-update-utmp reboot
+ExecStop=@rootlibexecdir@/systemd-update-utmp shutdown
diff --git a/units/user.slice b/units/user.slice
new file mode 100644
index 0000000000..9fa6284c12
--- /dev/null
+++ b/units/user.slice
@@ -0,0 +1,11 @@
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=User and Session Slice
+Documentation=man:systemd.special(7)
+Before=slices.target
diff --git a/units/user@.service.in b/units/user@.service.in
index 3cf1347b16..3718a57087 100644
--- a/units/user@.service.in
+++ b/units/user@.service.in
@@ -6,18 +6,14 @@
# (at your option) any later version.
[Unit]
-Description=User Manager for %u
+Description=User Manager for %I
After=systemd-user-sessions.service
[Service]
User=%I
-PAMName=systemd-shared
-# in order to allow MEM_CG features to work, add "memory:/" here
-ControlGroup=%R/user/%U.user/shared cpu:/
-ControlGroupModify=yes
+PAMName=systemd-user
Type=notify
+Environment=SHELL=%s
ExecStart=-@rootlibexecdir@/systemd --user
-Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/%U/dbus/user_bus_socket
-
-[Install]
-Alias=user@%i.service
+Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/%I/dbus/user_bus_socket
+Slice=user-%i.slice
diff --git a/units/x-.slice b/units/x-.slice
new file mode 100644
index 0000000000..ac82c35874
--- /dev/null
+++ b/units/x-.slice
@@ -0,0 +1,12 @@
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Root Slice
+Documentation=man:systemd.special(7)
+DefaultDependencies=no
+Before=slices.target